1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 __maintainer__ = 'Florian Boucault <florian@fluendo.com>'
19
20
21 from elisa.core import plugin_registry, common
22
23 import pgm
24 from pgm.timing import implicit
25 from pgm.graph.group import Group
26 from pgm.graph.text import Text
27 from pgm.graph.image import Image
28
29 from poblenou_widgets.top_level_menu import *
30
31 from twisted.internet import reactor
32
33 from elisa.extern.translation import Translatable
34
35 BaseTreeView = plugin_registry.get_component_class('base:tree_view')
36
38
39 supported_controllers = ('poblenou:tree_controller',)
40
42 super(TreeView, self).__init__()
43 self.context_path = 'pigment:pigment_context'
44
45
46 self._description = None
47 self._description_string = ""
48
49
50 self._description_delay = 0.100
51 self._description_delayed = None
52
53
54 self._menu = None
55
56
57 self._arrow = None
58 self._arrow_delay = 0.100
59 self._arrow_delayed = None
60
61
62
63 self._previous_menu_zone = None
64
65
66 self._drag_level_zone = None
67 self._drag_started = False
68 self._drag_start_position = None
69 self._drag_start_index = 0
70
71
72 self._back_button = None
73
74
75 self._loading = None
76
77
78
79
80 self.icons_cache = {}
81
83 if self.icons_cache.has_key(icon_theme_name):
84 return self.icons_cache[icon_theme_name]
85
86 self.debug("drawable for icon %s not in cache; creating it" \
87 % icon_theme_name)
88
89 img = pgm.Image()
90 image_path = self.frontend.theme.get_media(icon_theme_name)
91 img.set_from_file(image_path)
92 img.set_name(icon_theme_name)
93 self.icons_cache[icon_theme_name] = img
94
95 self.debug("drawables cache now containing %s drawables" \
96 % len(self.icons_cache))
97
98
99
100 canvas = self.frontend.context.canvas
101 canvas.add(pgm.DRAWABLE_MIDDLE, img)
102
103 return img
104
125
138
143
145 canvas = self.frontend.context.canvas
146
147
148 size = canvas.width/3.0
149 menu_selected_size = (size, size)
150 padding = size/4.0
151 menu_selected_position = (padding, padding*3.0/4.0, 0.0)
152 menu_selected_position = ((canvas.width-size)/2.0, 0.0, 0.0)
153
154 self._menu = TopLevelMenu(canvas, pgm.DRAWABLE_MIDDLE,
155 width = canvas.width,
156 height = canvas.height,
157 font_family = "Nimbus Sans L",
158 selected_position = menu_selected_position,
159 selected_size = menu_selected_size,
160 selected_opacity = 20,
161 mode = CAROUSEL,
162 path_steps = 1,
163 duration = 500,
164 transformation = implicit.DECELERATE)
165
166 self._menu.bg_color = (0, 0, 0, 0)
167 self._menu.opacity = 255
168 self.root_group.add(self._menu)
169
170 self._animated_menu = implicit.AnimatedObject(self._menu)
171 self._animated_menu.mode = implicit.REPLACE
172 self._animated_menu.setup_next_animations(duration = 550,
173 transformation = implicit.DECELERATE)
174 self._menu.visible = True
175
176
198
200
201 self._description = Text()
202 self._description.label = ""
203 self._description.set_name('(empty)')
204 self._description.font_family = "Nimbus Sans L"
205 self._description.bg_color = (0, 0, 0, 0)
206 self._description.alignment = pgm.TEXT_ALIGN_CENTER
207 self._description.ellipsize = pgm.TEXT_ELLIPSIZE_END
208 self._description.opacity = 255
209
210 self._description.connect("clicked", self._description_clicked)
211
212 self._animated_description = implicit.AnimatedObject(self._description)
213 self._animated_description.mode = implicit.REPLACE
214 self._animated_description.setup_next_animations(duration=200,
215 transformation=implicit.DECELERATE)
216
217 self._scale_description()
218 self._description.visible = True
219
220 self.root_group.add(self._description)
221
232
258
260
261 self._description_delayed = None
262 self._description.label = self._description_string
263 self._description.set_name(self._description_string)
264 self._animated_description.opacity = 255
265
267
268 self._arrow = Image()
269 self._arrow.bg_color = (0, 0, 0, 0)
270 self._arrow.layout = pgm.IMAGE_SCALED
271 self._arrow.alignment = pgm.IMAGE_CENTER
272 self._arrow.opacity = 0
273
274 self._arrow.connect("clicked", self._description_clicked)
275
276 arrow_path = self.frontend.theme.get_media("down_arrow_icon")
277 self._arrow.set_from_file(arrow_path)
278 self._arrow.set_name('down_arrow_icon')
279
280 self._animated_arrow = implicit.AnimatedObject(self._arrow)
281 self._animated_arrow.mode = implicit.REPLACE
282 self._animated_arrow.setup_next_animations(duration=200,
283 transformation=implicit.DECELERATE)
284 self._animated_arrow.setup_next_animations(attribute="y",
285 duration=350,
286 repeat_count=implicit.INFINITE,
287 repeat_behavior=implicit.REVERSE,
288 transformation=implicit.SMOOTH)
289 self._scale_arrow()
290 self._arrow.visible = True
291 self.root_group.add(self._arrow)
292
301
303
304 if self._arrow.opacity != 0:
305 self._animated_arrow.stop_animations()
306 self._arrow.opacity = 0
307 self._scale_arrow()
308
309
310 if self._arrow_delayed != None and self._arrow_delayed.active():
311 if visible:
312 self._arrow_delayed.reset(self._arrow_delay)
313 else:
314 self._arrow_delayed.cancel()
315 elif visible:
316 self._arrow_delayed = reactor.callLater(self._arrow_delay, self._show_arrow)
317
319 self._animated_arrow.opacity = 255
320 self._animated_arrow.y += 0.01
321
322
344
353
359
361 self._loading = Image()
362
363 loading_icon = self.frontend.theme.get_media("loading_icon")
364 self._loading.set_from_file(loading_icon)
365 self._loading.set_name("loading_icon")
366
367 self._loading.bg_color = (0, 0, 0, 0)
368 self._loading.opacity = 1
369 self._loading.layout = pgm.IMAGE_SCALED
370 self._loading.alignment = pgm.IMAGE_CENTER
371
372 self._animated_loading = implicit.AnimatedObject(self._loading)
373 self._animated_loading.mode = implicit.REPLACE
374 self._animated_loading.setup_next_animations(attribute="opacity",
375 duration = 200)
376 params = {"duration": 350, \
377 "repeat_count": implicit.INFINITE, \
378 "repeat_behavior": implicit.REVERSE, \
379 "transformation": implicit.SMOOTH}
380 self._animated_loading.setup_next_animations(attribute="width",
381 **params)
382 self._animated_loading.setup_next_animations(attribute="height",
383 **params)
384 self._animated_loading.setup_next_animations(attribute="x",
385 **params)
386 self._animated_loading.setup_next_animations(attribute="y",
387 **params)
388
389 self._scale_loading()
390 self._loading.visible = True
391
392 self.root_group.add(self._loading)
393
401
403 if value:
404 loading_icon = self.frontend.theme.get_media("loading_icon")
405 self._loading.set_from_file(loading_icon)
406 self._loading.set_name("loading_icon")
407
408 self._animated_loading.opacity = 255
409 delta = 0.05
410 self._animated_loading.x -= delta/2.0
411 self._animated_loading.y -= delta/2.0
412 self._animated_loading.width += delta
413 self._animated_loading.height += delta
414 else:
415 self._animated_loading.stop_animations()
416 self._animated_loading.opacity = 1
417 self._scale_loading()
418
420 if value:
421 empty_icon = self.frontend.theme.get_media("empty_icon")
422 self._loading.set_from_file(empty_icon)
423 self._loading.set_name("empty_icon")
424 self._animated_loading.stop_animations()
425 self._animated_loading.opacity = 255
426 else:
427 self._animated_loading.stop_animations()
428 self._animated_loading.opacity = 1
429 self._scale_loading()
430
431
451
455
456
471
478
480
481 if self.controller.selected_controller is not self.controller.backend.focused_controller:
482 return False
483
484 if button == pgm.BUTTON_LEFT:
485 self._drag_started = True
486 self._drag_start_position = (x, y)
487 level_controller = self.controller.selected_controller
488 self._drag_start_index = level_controller.current_index
489 return True
490
492 if button == pgm.BUTTON_LEFT and self._drag_started:
493 self._drag_started = False
494
495 dx = self._drag_start_position[0] - x
496 dy = self._drag_start_position[1] - y
497
498 level_controller = self.controller.selected_controller
499 if self._drag_start_index == level_controller.current_index:
500 if dy > 0.05:
501
502 if self.controller.selected_controller != self.controller:
503 self.controller.selected_controller.exit_node()
504 return True
505
506 elif dy < -0.05:
507
508 self.controller.selected_controller.enter_node()
509 return True
510
511 return False
512
514 if self._drag_started == True:
515 dx = self._drag_start_position[0] - x
516
517
518 level_controller = self.controller.selected_controller
519
520 if level_controller == self.controller:
521
522 visible_items = 4
523 increment = int(dx/float(self._drag_level_zone.width)*visible_items)
524 level_controller.current_index = (self._drag_start_index + \
525 increment) % len(level_controller)
526 else:
527
528 visible_items = 11
529 increment = int(dx/float(self._drag_level_zone.width)*visible_items)
530 level_controller.current_index = self._drag_start_index+increment
531
532 return True
533
568
582
584 super(TreeView, self).child_view_creating(view, controller, position)
585
586
587 icon, blurred, reflected = self._get_child_icons(controller)
588 if isinstance(controller.model.text, Translatable):
589 trans = common.application.translator
590 text = trans.translateTranslatable(controller.model.text,
591 self.frontend.languages)
592 else:
593 text = controller.model.text
594 self._menu.insert(position, icon, blurred, reflected, text)
595
596
597
598 for widget in self._menu._item_handles[position]:
599 widget.connect('clicked', self._entry_clicked, controller)
600
601 self._menu.layout()
602 self._menu.update()
603
604 - def _entry_clicked(self, drawable, x, y, z, button, time, controller):
605 self.debug("%s clicked" % controller.model.text)
606
607 if self.controller.selected_controller == self.controller:
608
609 current_index = self.controller.current_index
610 clicked_index = self.controller.index(controller)
611 if current_index != clicked_index:
612
613 self.controller.current_index = clicked_index
614 else:
615
616 self.controller.enter_node()
617
618 return True
619
620 return False
621
635
637 if not self._animated_description.visible or self._animated_description.opacity == 0 or \
638 not self.root_group.visible or self.root_group.opacity == 0 or \
639 self._description_string =="":
640 return False
641
642 self.controller.root.selected_controller.activate_node()
643
644 return True
645