--- /dev/null
+#!/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 <http://www.gnu.org/licenses/>.
+
+# ============================================================================
+# 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()