list_view.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import logging
  2. from screen_objects import ScreenObjectsManager, ScrollBar, \
  3. TouchAndTextItem
  4. from ..input import InputManager
  5. logger = logging.getLogger(__name__)
  6. class ListView():
  7. def __init__(self, pos, size, base_size, font):
  8. self.size = size
  9. self.pos = pos
  10. self.base_size = base_size
  11. self.screen_objects = ScreenObjectsManager()
  12. self.max_rows = self.size[1] / font.size("TEXT SIZE")[1]
  13. self.current_item = 0
  14. self.font = font
  15. self.list_size = 0
  16. self.list = []
  17. self.scrollbar = False
  18. self.selected = None
  19. self.active = []
  20. self.set_list([])
  21. self.update_keys = []
  22. # Sets the list for the lisview.
  23. # It should be an iterable of strings
  24. def set_list(self, item_list):
  25. self.screen_objects.clear()
  26. self.list = item_list
  27. self.list_size = len(item_list)
  28. if self.max_rows < self.list_size:
  29. self.scrollbar = True
  30. scroll_bar = ScrollBar(
  31. (self.pos[0] + self.size[0] - self.base_size,
  32. self.pos[1]),
  33. (self.base_size, self.size[1]), self.list_size,
  34. self.max_rows)
  35. self.screen_objects.set_touch_object("scrollbar",
  36. scroll_bar)
  37. else:
  38. self.scrollbar = False
  39. if self.list_size > 0:
  40. self.selected = 0
  41. else:
  42. self.selected = None
  43. self.load_new_item_position(0)
  44. # Will load items currently displaying in item_pos
  45. def load_new_item_position(self, item_pos):
  46. self.update_keys = []
  47. self.current_item = item_pos
  48. if self.scrollbar:
  49. self.screen_objects.clear_touch(["scrollbar"])
  50. else:
  51. self.screen_objects.clear_touch(None)
  52. i = self.current_item
  53. z = 0
  54. if self.scrollbar:
  55. width = self.size[0] - self.base_size
  56. else:
  57. width = self.size[0]
  58. self.should_update_always = False
  59. current_y = self.pos[1]
  60. while i < self.list_size and current_y <= self.pos[1] + self.size[1]:
  61. item = TouchAndTextItem(self.font, self.list[i], (
  62. self.pos[0],
  63. current_y), (width, -1))
  64. current_y += item.size[1]
  65. if not item.fit_horizontal:
  66. self.update_keys.append(str(i))
  67. self.screen_objects.set_touch_object(str(i), item)
  68. i += 1
  69. z += 1
  70. self.reload_selected()
  71. def should_update(self):
  72. if len(self.update_keys) > 0:
  73. return True
  74. else:
  75. return False
  76. def find_update_rects(self, rects):
  77. for key in self.update_keys:
  78. object = self.screen_objects.get_touch_object(key)
  79. rects.append(object.rect_in_pos)
  80. def render(self, surface, update_all, rects):
  81. if update_all:
  82. self.screen_objects.render(surface)
  83. else:
  84. for key in self.update_keys:
  85. object = self.screen_objects.get_touch_object(key)
  86. object.update()
  87. object.render(surface)
  88. def touch_event(self, touch_event):
  89. self.must_update = True
  90. if touch_event.type == InputManager.click \
  91. or touch_event.type == InputManager.long_click:
  92. objects = self.screen_objects.get_touch_objects_in_pos(
  93. touch_event.current_pos)
  94. if objects is not None:
  95. for key in objects:
  96. if key == "scrollbar":
  97. direction = \
  98. self.screen_objects.get_touch_object(
  99. key).touch(touch_event.current_pos)
  100. if direction != 0:
  101. self.move_to(direction)
  102. else:
  103. return int(key)
  104. elif (touch_event.type == InputManager.key and
  105. self.selected is not None):
  106. if touch_event.direction == InputManager.enter:
  107. if self.selected is not None:
  108. return self.selected
  109. elif touch_event.direction == InputManager.up:
  110. self.set_selected(self.selected-1)
  111. elif touch_event.direction == InputManager.down:
  112. self.set_selected(self.selected+1)
  113. elif touch_event.type == InputManager.swipe:
  114. if touch_event.direction == InputManager.up:
  115. self.move_to(-1)
  116. elif touch_event.direction == InputManager.down:
  117. self.move_to(1)
  118. # Scroll to direction
  119. # direction == 1 will scroll down
  120. # direction == -1 will scroll up
  121. def move_to(self, direction):
  122. if self.scrollbar:
  123. if direction == 1:
  124. self.current_item += self.max_rows
  125. if self.current_item + self.max_rows > self.list_size:
  126. self.current_item = self.list_size - self.max_rows
  127. self.load_new_item_position(self.current_item)
  128. self.screen_objects.get_touch_object(
  129. "scrollbar").set_item(
  130. self.current_item)
  131. elif direction == -1:
  132. self.current_item -= self.max_rows
  133. if self.current_item < 0:
  134. self.current_item = 0
  135. self.load_new_item_position(self.current_item)
  136. self.screen_objects.get_touch_object(
  137. "scrollbar").set_item(
  138. self.current_item)
  139. self.set_active(self.active)
  140. # Set active items
  141. def set_active(self, active):
  142. self.must_update = True
  143. for number in self.active:
  144. try:
  145. self.screen_objects.get_touch_object(
  146. str(number)).set_active(
  147. False)
  148. except KeyError:
  149. pass
  150. for number in active:
  151. try:
  152. self.screen_objects.get_touch_object(
  153. str(number)).set_active(
  154. True)
  155. except KeyError:
  156. pass
  157. self.active = active
  158. def set_selected(self, selected):
  159. self.must_update = True
  160. if selected > -1 and selected < len(self.list):
  161. if self.selected is not None:
  162. try:
  163. self.screen_objects.get_touch_object(
  164. str(self.selected)).set_selected(
  165. False)
  166. except KeyError:
  167. pass
  168. if selected is not None:
  169. try:
  170. self.screen_objects.get_touch_object(
  171. str(selected)).set_selected(
  172. True)
  173. except KeyError:
  174. pass
  175. self.selected = selected
  176. self.set_selected_on_screen()
  177. def set_selected_on_screen(self):
  178. self.must_update = True
  179. if self.current_item + self.max_rows <= self.selected:
  180. self.move_to(1)
  181. self.set_selected_on_screen()
  182. elif self.current_item > self.selected:
  183. self.move_to(-1)
  184. self.set_selected_on_screen()
  185. def reload_selected(self):
  186. self.must_update = True
  187. if self.selected is not None:
  188. try:
  189. self.screen_objects.get_touch_object(
  190. str(self.selected)).set_selected(
  191. True)
  192. except KeyError:
  193. pass