|
1 from tuikit.core.container import Container |
|
2 from tuikit.layouts.offset import OffsetLayout |
|
3 |
|
4 #from tuikit.layout import AnchorLayout, OffsetLayout |
|
5 #from tuikit.scrollbar import VScrollbar, HScrollbar |
|
6 #from tuikit.common import Borders |
|
7 |
|
8 |
|
9 class Viewport(Container): |
|
10 |
|
11 """Viewport for partial view on widgets. |
|
12 |
|
13 Viewport is special type of Container, which shows partial view |
|
14 on its managed widgets. This view can be moved to show different part |
|
15 and thus allow "scrolling" over the content. Complete view with scrollbars |
|
16 is implemented in ScrollView. |
|
17 |
|
18 """ |
|
19 |
|
20 def __init__(self): |
|
21 Container.__init__(self, OffsetLayout) |
|
22 |
|
23 |
|
24 class Scrollview(Container): |
|
25 |
|
26 def __init__(self): |
|
27 Container.__init__(self) |
|
28 |
|
29 |
|
30 class Scrolling: |
|
31 def __init__(self): |
|
32 self.vscroll = VScrollbar() |
|
33 self.vscroll.add_handler('change', self._on_vscroll_change) |
|
34 AnchorLayout.add(self, self.vscroll, halign='right', valign='fill') |
|
35 |
|
36 self.hscroll = HScrollbar() |
|
37 self.hscroll.add_handler('change', self._on_hscroll_change) |
|
38 AnchorLayout.add(self, self.hscroll, halign='fill', valign='bottom') |
|
39 |
|
40 def on_resize(self, ev): |
|
41 self._update_scroll_max() |
|
42 |
|
43 def _connect_child(self, widget): |
|
44 widget.add_handler('sizereq', self._on_child_sizereq) |
|
45 widget.add_handler('spotmove', self._on_child_spotmove) |
|
46 widget.add_handler('scrollreq', self._on_child_scrollreq) |
|
47 |
|
48 def _on_child_sizereq(self, ev): |
|
49 self._update_scroll_max() |
|
50 |
|
51 def _on_child_spotmove(self, ev): |
|
52 child = ev.originator |
|
53 # x |
|
54 spot_x = child.x - self._inner.offset.x + child.spot.x |
|
55 if spot_x < self.hscroll.scroll_pos: |
|
56 self.hscroll.scroll_pos = spot_x |
|
57 if spot_x > (self._inner.width - 1) + self.hscroll.scroll_pos: |
|
58 self.hscroll.scroll_pos = spot_x - (self._inner.width - 1) |
|
59 # y |
|
60 spot_y = child.y - self._inner.offset.y + child.spot.y |
|
61 if spot_y < self.vscroll.scroll_pos: |
|
62 self.vscroll.scroll_pos = spot_y |
|
63 if spot_y > (self._inner.height - 1) + self.vscroll.scroll_pos: |
|
64 self.vscroll.scroll_pos = spot_y - (self._inner.height - 1) |
|
65 |
|
66 def _on_child_scrollreq(self, ev): |
|
67 new_scroll_pos = self.vscroll.scroll_pos + ev.data |
|
68 if new_scroll_pos > self.vscroll.scroll_max: |
|
69 self.vscroll.scroll_pos = self.vscroll.scroll_max |
|
70 elif new_scroll_pos < 0: |
|
71 self.vscroll.scroll_pos = 0 |
|
72 else: |
|
73 self.vscroll.scroll_pos = new_scroll_pos |
|
74 |
|
75 def _on_vscroll_change(self, ev): |
|
76 self._inner.offset.y = - self.vscroll.scroll_pos |
|
77 |
|
78 def _on_hscroll_change(self, ev): |
|
79 self._inner.offset.x = - self.hscroll.scroll_pos |
|
80 |
|
81 def _update_scroll_max(self): |
|
82 max_width = 0 |
|
83 max_height = 0 |
|
84 for child in self._inner.children: |
|
85 posx, posy = child.hint_value('position') |
|
86 child_width = posx + child.sizereq.w |
|
87 if child_width > max_width: |
|
88 max_width = child_width |
|
89 child_height = posy + child.sizereq.h |
|
90 if child_height > max_height: |
|
91 max_height = child_height |
|
92 max_width += 1 |
|
93 self.hscroll.scroll_max = max_width - self._inner.width |
|
94 self.vscroll.scroll_max = max_height - self._inner.height |
|
95 hscroll_hide = max_width < self._inner.width |
|
96 vscroll_hide = max_height < self._inner.height |
|
97 self._toggle_scrollers(hscroll_hide, vscroll_hide) |
|
98 |
|
99 def _toggle_scrollers(self, hscroll_hide, vscroll_hide): |
|
100 if hscroll_hide: |
|
101 self.hscroll.hide() |
|
102 else: |
|
103 self.hscroll.show() |
|
104 if vscroll_hide: |
|
105 self.vscroll.hide() |
|
106 else: |
|
107 self.vscroll.show() |
|
108 # self._inner.need_resize() |
|
109 |
|
110 |
|
111 class ScrollView(OffsetView, Scrolling): |
|
112 """Scrolling view |
|
113 |
|
114 Shows scrollbars when needed. |
|
115 Scrolling area is determined according to child widget's size request. |
|
116 |
|
117 """ |
|
118 |
|
119 def __init__(self): |
|
120 OffsetView.__init__(self) |
|
121 Scrolling.__init__(self) |
|
122 |
|
123 def add(self, widget, **kwargs): |
|
124 OffsetView.add(self, widget, **kwargs) |
|
125 self._connect_child(widget) |
|
126 |
|
127 def _toggle_scrollers(self, hscroll_hide, vscroll_hide): |
|
128 bpad = int(not hscroll_hide) |
|
129 self.vscroll.update_hint('margin', b=bpad) |
|
130 rpad = int(not vscroll_hide) |
|
131 self.hscroll.update_hint('margin', r=rpad) |
|
132 self._inner.update_hint('margin', b=bpad, r=rpad) |
|
133 Scrolling._toggle_scrollers(self, hscroll_hide, vscroll_hide) |
|
134 |