X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=pcremote-client-n8x0%2Fkineticlist.py;fp=pcremote-client-n8x0%2Fkineticlist.py;h=4234176113c39f3cd4a1493c7628f655a4467b7c;hb=8eeea3225c010dea378cdc71c4e91294e04a6e9c;hp=0000000000000000000000000000000000000000;hpb=e8447209e336f2a6845027f50b84cc914fa2c796;p=remotepc diff --git a/pcremote-client-n8x0/kineticlist.py b/pcremote-client-n8x0/kineticlist.py new file mode 100755 index 0000000..4234176 --- /dev/null +++ b/pcremote-client-n8x0/kineticlist.py @@ -0,0 +1,400 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# **************************************************************************** +# Copyright (c) 2008 INdT/Fucapi. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +# ============================================================================ +# Project Name :PC Remote +# Author :Gustavo Sverzut Barbieri ; André Luiz do Canto Portela +# Email :barbieri@gmail.com ; andre_portela_@hotmail.com +# Version :1.0 +# Module :main +# Class :This class are an adaptation of barbieri's demo 03 of edje +# :python-bindings +# ============================================================================ + +import evas +import edje +import ecore +import time + +class KineticList(evas.ClippedSmartObject): + ( + SCROLL_PAGE_FORWARD, + SCROLL_PAGE_BACKWARD, + SCROLL_STEP_FORWARD, + SCROLL_STEP_BACKWARD, + SCROLL_PIXELS_DOWN, + SCROLL_PIXELS_UP + ) = range(6) + + + def __init__(self, ecanvas, file, item_width=-1, item_height=-1, father=None): + ''' + if item_width or item_height is left out the width (resp. height) + of the List element is used. + ''' + self.father = father + evas.ClippedSmartObject.__init__(self, ecanvas) + self.elements = [] + self.objects = [] + self.w = 32 + self.h = 32 + + self.realized = False + + self.top_pos = 0 + self.last_top_pos = 0 + self.last_start_row = -1 + + self.canvas = ecanvas + self.edje_file = file + + self.row_width = item_width + self.row_height = item_height + + self.__manage_objects() + + self.mouse_down = False + self.last_y_pos = 0 + self.start_pos = 0 + self.mouse_moved = False + self.continue_scrolling = False + self.is_scrolling = False + self.do_freeze = False + + def freeze(self): + self.do_freeze = True + + def thaw(self): + self.do_freeze = False + if self.realized: + self.__update_variables_after_new_elements() + self.__update_screen() + + def scroll(self, scroll_type, amount=1): + self.continue_scrolling = False + + if scroll_type == self.SCROLL_PAGE_FORWARD: + self.top_pos += amount * self.row_height * self.max_visible_rows + elif scroll_type == self.SCROLL_PAGE_BACKWARD: + self.top_pos -= amount * self.row_height * self.max_visible_rows + elif scroll_type == self.SCROLL_STEP_FORWARD: + self.top_pos += amount * self.row_height + elif scroll_type == self.SCROLL_STEP_BACKWARD: + self.top_pos -= amount * self.row_height + elif scroll_type == self.SCROLL_PIXELS_DOWN: + self.top_pos += amount + elif scroll_type == self.SCROLL_PIXELS_UP: + self.top_pos -= amount + else: + return + + self.__update_screen() + + def __on_mouse_clicked(self, edje_obj, emission, source, data=None): + #for obj in self.objects: + # if obj != edje_obj: + # obj.signal_emit("fadeout", "") + + #edje_obj.signal_emit("open", "") + #TODO:portela - it works! :D + edje_obj.signal_emit("program,start","label") + #we are setting up the choice's text on the main edje object + self.parent_get().part_text_set("choice",edje_obj.part_text_get("label")) + + def __on_mouse_move(self, edje_obj, emission, source, data=None): + if self.mouse_down: + x_pos, y_pos = self.canvas.pointer_canvas_xy + diff = int(self.last_y_pos - y_pos) + + if diff == 0: + return + + self.mouse_moved = True + + # Reset the data if the direction of the mouse move is changed + if self.last_diff != -1 and (diff < 0) != (self.last_diff < 0): + self.last_y_pos = y_pos + self.start_pos = y_pos + self.start_time = time.time() + + self.last_diff = diff + self.top_pos += diff + + self.last_y_pos = y_pos + self.__update_screen() + self.last_update_time = time.time() + + #TODO: portela mod + def __on_blink_ended(self, edje_obj, emission, source, data=None): + for obj in self.objects: + obj.signal_emit("program,start,fade,out","label") + #we are sending a signal for the application connect the target + self.parent_get().signal_emit("connect_to","choice") + + #TODO: portela mod + + def show_list(self): + for obj in self.objects: + obj.signal_emit("program,start,fade,in","label") + + def __on_mouse_down(self, edje_obj, emission, source, data=None): + if not self.is_scrolling: + self.mouse_moved = False + + self.continue_scrolling = False + self.mouse_down = True + + x_pos, y_pos = self.canvas.pointer_canvas_xy + + self.last_diff = -1 + self.last_y_pos = y_pos + self.start_pos = y_pos + self.start_time = time.time() + self.last_update_time = time.time() + + def __on_mouse_up(self, edje_obj, emission, source, data=None): + if self.mouse_down: + self.mouse_down = False + + x_pos, end_pos = self.canvas.pointer_canvas_xy + + if not self.mouse_moved and not self.is_scrolling: + #self.__on_mouse_clicked(edje_obj, emission, source) + return + + self.mouse_moved = False + self.is_scrolling = False + + # do not scroll automatically if the finger was paused + if time.time() - self.last_update_time > 0.1: + return + + end_time = time.time() + + pos_diff = end_pos - self.start_pos + time_diff = end_time - self.start_time + + self.pixel_per_sec = pos_diff / time_diff + self.continue_scrolling = True + self.__do_scroll() + + def __do_scroll(self): + self.is_scrolling = True + + if self.continue_scrolling == False: + return + + diff = int(self.pixel_per_sec / 10) + + if abs(self.pixel_per_sec) - diff <= self.row_height: + offset = self.top_pos % self.row_height + + if offset >= self.row_height / 2: + self.sign = 1 + offset = self.row_height - offset + else: + self.sign = -1 + + self.pixels_left = offset + self.__do_magnetic_scroll() + + return + + if diff != 0: + self.top_pos -= diff + self.pixel_per_sec -= self.pixel_per_sec / 10 + self.__update_screen() + + ecore.timer_add(0.02, self.__do_scroll) + + def __do_magnetic_scroll(self): + if self.pixels_left <= 0 or abs(self.pixel_per_sec) < 1: + self.mouse_moved = False + self.is_scrolling = False + return + + self.pixel_per_sec -= (self.pixel_per_sec / 10) + + pixels_to_substract = int(abs(self.pixel_per_sec / 10)) + if abs(pixels_to_substract) < 1: + pixels_to_substract = 1 + + if self.pixels_left - pixels_to_substract > 0: + self.pixels_left -= pixels_to_substract + self.top_pos += self.sign * pixels_to_substract + else: + self.top_pos += self.sign * self.pixels_left + self.pixels_left = 0 + + self.__update_screen() + ecore.timer_add(0.1, self.__do_magnetic_scroll) + + def row_add(self, label): + self.elements.append(label) + + if not self.do_freeze: + self.__update_variables_after_new_elements() + self.__update_screen() + + def __manage_objects(self): + remain = (self.h % self.row_height) > 1 + needed_objects = ((self.h / self.row_height) + 1 + remain) * (self.w / self.row_width) + current_objects = len(self.objects) + + if current_objects < needed_objects: + for i in range(current_objects, needed_objects): + obj = edje.Edje(self.canvas); + obj.file_set(self.edje_file, "list_item"); + + obj.signal_callback_add("mouse,move", "*", + self.__on_mouse_move) + obj.signal_callback_add("mouse,down,*", "*", + self.__on_mouse_down) + obj.signal_callback_add("mouse,up,*", "*", + self.__on_mouse_up) + #TODO: portela mod + obj.signal_callback_add("animation_blink_ended", "label", + self.__on_blink_ended) + obj.signal_callback_add("mouse,clicked,*", "label", + self.__on_mouse_clicked) + obj.size = (self.row_width, self.row_height) + obj.clip = self + self.objects.append(obj) + + elif needed_objects < current_objects: + for i in range(needed_objects, current_objects): + pass # Make this work, it throws exception that makes + # things stop working properly + #del self.objects[i] + + def __update_variables_after_resize(self): + self.max_visible_rows = (self.h / self.row_height) + 1 + self.max_horiz_elements = (self.w / self.row_width) + self.max_visible_elements = self.max_visible_rows * \ + self.max_horiz_elements + + # Invalidate variable in order to repaint all rows + # Some might not have been painted before (Didn't + # fit on the screen + self.last_start_row = -1 + + self.__update_variables_after_new_elements() + + def __update_variables_after_new_elements(self): + if not self.realized: + return + + self.min_pos = 0 + remainer1 = (len(self.elements) % self.max_horiz_elements) > 0 + remainer2 = (self.h % self.row_height) > 0 + self.row_amount = (len(self.elements) / self.max_horiz_elements) + \ + remainer1 + remainer2 + self.max_pos = self.row_height * \ + (self.row_amount - self.max_visible_rows + 1) + + def __update_screen(self): + remainer = (self.h % self.row_height) > 0 + row_offset = (self.top_pos / self.row_height) + pixel_offset = - (self.top_pos % self.row_height) + start_row = row_offset + end_row = self.max_visible_rows + row_offset + remainer + + SCROLL_DOWN = self.top_pos > self.last_top_pos + SCROLL_UP = self.top_pos < self.last_top_pos + + # Let's not move over the last element + if SCROLL_DOWN and self.last_top_pos >= self.max_pos: + self.top_pos = self.max_pos + self.last_top_pos = self.top_pos + self.continue_scrolling = False + return + + # Let's not move over the first element + if SCROLL_UP and self.last_top_pos <= self.min_pos: + self.top_pos = self.min_pos + self.last_top_pos = self.top_pos + self.continue_scrolling = False + return + + # Overflow scrolling down + if SCROLL_DOWN and end_row > self.row_amount: + offset = end_row - self.row_amount + end_row -= offset + start_row -= offset + row_offset -= offset - 1 + self.top_pos = self.max_pos + pixel_offset = 0 + + # Overflow scrolling up + if SCROLL_UP and start_row < 0: + self.top_pos = self.min_pos + end_row -= start_row + start_row = 0 + row_offset = 0 + pixel_offset = 0 + + self.last_top_pos = self.top_pos + + if start_row != self.last_start_row: + for i in range(0, len(self.objects)): + self.objects[i].hide() + + for i in range(start_row, end_row): + row_iter = i - start_row + + for k in range(self.max_horiz_elements): + obj_iter = row_iter * self.max_horiz_elements + k + data_iter = i * self.max_horiz_elements + k + + try: + label = self.elements[data_iter] + except Exception, e: + break; + + offset = (self.w % + (self.row_width * self.max_horiz_elements)) / 2 + x = self.row_width * k + self.top_left[0] + offset + y = self.top_left[1] + self.row_height * (i - row_offset) - \ + 5 + pixel_offset + + self.objects[obj_iter].move(x, y) + + if start_row != self.last_start_row: + self.objects[obj_iter].part_text_set("label", label) + self.objects[obj_iter].show() + + self.last_start_row = start_row + + def resize(self, w, h): + if self.row_width == -1 or self.row_width == self.w: + self.row_width = w + + if self.row_height == -1 or self.row_height == self.h: + self.row_height = h + + self.w = w + self.h = h + + self.__manage_objects() + + for obj in self.objects: + obj.size = (self.row_width, self.row_height) + + self.realized = True + self.__update_variables_after_resize() + self.__update_screen()