Mercurial > libervia-desktop-kivy
annotate cagou/core/widgets_handler.py @ 282:1b835bcfa663
date update
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 25 Mar 2019 07:11:09 +0100 |
parents | 23d4358803c7 |
children | efd3fbc85aaf |
rev | line source |
---|---|
13 | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client | |
282 | 5 # Copyright (C) 2016-2019 Jérôme Poisson (goffi@goffi.org) |
13 | 6 |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 | |
21 from sat.core import log as logging | |
22 log = logging.getLogger(__name__) | |
154 | 23 from sat.core import exceptions |
34
02acbb297a61
handler, widget: deleteWidget is now properly called when a QuickWidget is deleted
Goffi <goffi@goffi.org>
parents:
16
diff
changeset
|
24 from sat_frontends.quick_frontend import quick_widgets |
154 | 25 from kivy.graphics import Color, Ellipse |
26 from kivy.uix.layout import Layout | |
13 | 27 from kivy.uix.boxlayout import BoxLayout |
155
a0e486074d91
widget handler: block carousel swiping when there is only one slide
Goffi <goffi@goffi.org>
parents:
154
diff
changeset
|
28 from kivy.uix.stencilview import StencilView |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
29 from kivy.metrics import dp |
13 | 30 from kivy import properties |
16
ba14b596b90e
host can now be get as a global value:
Goffi <goffi@goffi.org>
parents:
15
diff
changeset
|
31 from cagou import G |
177
9835cafbd909
widgets handler: use dark secondary color for split
Goffi <goffi@goffi.org>
parents:
171
diff
changeset
|
32 from cagou.core.constants import Const as C |
13 | 33 |
163
ef09dce878c7
widgets handler: removed constants which are not used anymore
Goffi <goffi@goffi.org>
parents:
160
diff
changeset
|
34 |
269
a5dfc789eeaf
widgets_handler: increased remove limit and min height/width:
Goffi <goffi@goffi.org>
parents:
263
diff
changeset
|
35 REMOVE_WID_LIMIT = dp(50) |
a5dfc789eeaf
widgets_handler: increased remove limit and min height/width:
Goffi <goffi@goffi.org>
parents:
263
diff
changeset
|
36 MIN_WIDTH = MIN_HEIGHT = dp(70) |
13 | 37 |
38 | |
154 | 39 class WHWrapper(BoxLayout): |
40 carousel = properties.ObjectProperty(None) | |
41 split_size = properties.NumericProperty(dp(1)) | |
42 split_margin = properties.NumericProperty(dp(2)) | |
43 split_color = properties.ListProperty([0.8, 0.8, 0.8, 1]) | |
177
9835cafbd909
widgets handler: use dark secondary color for split
Goffi <goffi@goffi.org>
parents:
171
diff
changeset
|
44 split_color_move = C.COLOR_SEC_DARK |
154 | 45 split_color_del = properties.ListProperty([0.8, 0.0, 0.0, 1]) |
46 # sp stands for "split point" | |
47 sp_size = properties.NumericProperty(dp(1)) | |
48 sp_space = properties.NumericProperty(dp(4)) | |
49 sp_zone = properties.NumericProperty(dp(30)) | |
50 _split = properties.OptionProperty('None', options=['None', 'left', 'top']) | |
51 _split_del = properties.BooleanProperty(False) | |
52 | |
53 def __init__(self, **kwargs): | |
54 idx = kwargs.pop('_wid_idx') | |
55 self._wid_idx = idx | |
56 super(WHWrapper, self).__init__(**kwargs) | |
57 self._former_slide = None | |
58 self.carousel.bind(current_slide=self.onSlideChange) | |
59 self._slides_update_lock = False | |
60 self._left_wids = set() | |
61 self._top_wids = set() | |
62 self._right_wids = set() | |
63 self._bottom_wids = set() | |
64 | |
65 def __repr__(self): | |
66 return "WHWrapper_{idx}".format(idx=self._wid_idx) | |
67 | |
68 def _main_wid(self, wid_list): | |
69 """return main widget of a side list | |
70 | |
263
fe540a6dc14d
widgets handler: call host._removeVisibleWidget when a widget is deleted (using split)
Goffi <goffi@goffi.org>
parents:
260
diff
changeset
|
71 main widget is either the widget currently splitted |
154 | 72 or any widget if none is split |
73 @return (WHWrapper, None): main widget or None | |
74 if there is not widget | |
75 """ | |
76 if not wid_list: | |
77 return None | |
78 for wid in wid_list: | |
79 if wid._split != 'None': | |
80 return wid | |
81 return next(iter(wid_list)) | |
82 | |
83 @property | |
84 def _left_wid(self): | |
85 return self._main_wid(self._left_wids) | |
86 | |
87 @property | |
88 def _top_wid(self): | |
89 return self._main_wid(self._top_wids) | |
90 | |
91 @property | |
92 def _right_wid(self): | |
93 return self._main_wid(self._right_wids) | |
94 | |
95 @property | |
96 def _bottom_wid(self): | |
97 return self._main_wid(self._bottom_wids) | |
13 | 98 |
154 | 99 @property |
100 def current_slide(self): | |
101 return self.carousel.current_slide | |
102 | |
103 def _draw_ellipse(self): | |
104 """draw split ellipse""" | |
105 color = self.split_color_del if self._split_del else self.split_color_move | |
106 try: | |
107 self.canvas.after.remove(self.ellipse) | |
108 except AttributeError: | |
109 pass | |
110 if self._split == "top": | |
111 with self.canvas.after: | |
112 Color(*color) | |
113 self.ellipse = Ellipse(angle_start=90, angle_end=270, | |
114 pos=(self.x + self.width/2 - self.sp_zone/2, | |
115 self.y + self.height - self.sp_zone/2), | |
116 size=(self.sp_zone, self.sp_zone)) | |
117 elif self._split == "left": | |
118 with self.canvas.after: | |
119 Color(*color) | |
120 self.ellipse = Ellipse(angle_end=180, | |
121 pos=(self.x + -self.sp_zone/2, | |
122 self.y + self.height/2 - self.sp_zone/2), | |
123 size = (self.sp_zone, self.sp_zone)) | |
124 else: | |
125 raise exceptions.InternalError('unexpected split value') | |
13 | 126 |
154 | 127 def on_touch_down(self, touch): |
128 """activate split if touch is on a split zone""" | |
129 if not self.collide_point(*touch.pos): | |
130 return | |
131 log.debug("WIDGET IDX: {} (left: {}, top: {}, right: {}, bottom: {}), pos: {}, size: {}".format( | |
132 self._wid_idx, | |
133 'None' if not self._left_wids else [w._wid_idx for w in self._left_wids], | |
134 'None' if not self._top_wids else [w._wid_idx for w in self._top_wids], | |
135 'None' if not self._right_wids else [w._wid_idx for w in self._right_wids], | |
136 'None' if not self._bottom_wids else [w._wid_idx for w in self._bottom_wids], | |
137 self.pos, | |
138 self.size, | |
139 )) | |
140 touch_rx, touch_ry = self.to_widget(*touch.pos, relative=True) | |
141 if (touch_ry <= self.height and | |
142 touch_ry >= self.height - self.split_size - self.split_margin or | |
143 touch_ry <= self.height and | |
144 touch_ry >= self.height - self.sp_zone and | |
145 touch_rx >= self.width/2 - self.sp_zone/2 and | |
146 touch_rx <= self.width/2 + self.sp_zone/2): | |
147 # split area is touched, we activate top split mode | |
148 self._split = "top" | |
149 self._draw_ellipse() | |
150 elif (touch_rx >= 0 and | |
151 touch_rx <= self.split_size + self.split_margin or | |
152 touch_rx >= 0 and | |
153 touch_rx <= self.sp_zone and | |
154 touch_ry >= self.height/2 - self.sp_zone/2 and | |
155 touch_ry <= self.height/2 + self.sp_zone/2): | |
156 # split area is touched, we activate left split mode | |
157 self._split = "left" | |
158 touch.ud['ori_width'] = self.width | |
159 self._draw_ellipse() | |
13 | 160 else: |
155
a0e486074d91
widget handler: block carousel swiping when there is only one slide
Goffi <goffi@goffi.org>
parents:
154
diff
changeset
|
161 if len(self.carousel.slides) == 1: |
a0e486074d91
widget handler: block carousel swiping when there is only one slide
Goffi <goffi@goffi.org>
parents:
154
diff
changeset
|
162 # we don't want swipe if there is only one slide |
a0e486074d91
widget handler: block carousel swiping when there is only one slide
Goffi <goffi@goffi.org>
parents:
154
diff
changeset
|
163 return StencilView.on_touch_down(self.carousel, touch) |
a0e486074d91
widget handler: block carousel swiping when there is only one slide
Goffi <goffi@goffi.org>
parents:
154
diff
changeset
|
164 else: |
a0e486074d91
widget handler: block carousel swiping when there is only one slide
Goffi <goffi@goffi.org>
parents:
154
diff
changeset
|
165 return super(WHWrapper, self).on_touch_down(touch) |
13 | 166 |
167 def on_touch_move(self, touch): | |
154 | 168 """handle size change and widget creation on split""" |
169 if self._split == 'None': | |
170 return super(WHWrapper, self).on_touch_move(touch) | |
171 | |
172 elif self._split == 'top': | |
173 new_height = touch.y - self.y | |
174 | |
175 if new_height < MIN_HEIGHT: | |
176 return | |
177 | |
178 # we must not pass the top widget/border | |
179 if self._top_wids: | |
180 top = next(iter(self._top_wids)) | |
181 y_limit = top.y + top.height | |
182 | |
183 if top.height <= REMOVE_WID_LIMIT: | |
184 # we are in remove zone, we add visual hint for that | |
160
916af9c1cb9b
widget handler: don't set split delete mode if there is not top/left widget
Goffi <goffi@goffi.org>
parents:
155
diff
changeset
|
185 if not self._split_del and self._top_wids: |
154 | 186 self._split_del = True |
187 self._draw_ellipse() | |
188 else: | |
189 if self._split_del: | |
190 self._split_del = False | |
191 self._draw_ellipse() | |
192 else: | |
193 y_limit = self.y + self.height | |
194 | |
195 if touch.y >= y_limit: | |
196 return | |
197 | |
198 # all right, we can change size | |
199 self.height = new_height | |
200 self.ellipse.pos = (self.ellipse.pos[0], touch.y - self.sp_zone/2) | |
201 | |
202 if not self._top_wids: | |
203 # we are the last widget on the top | |
204 # so we create a new widget | |
205 new_wid = self.parent.add_widget() | |
206 self._top_wids.add(new_wid) | |
207 new_wid._bottom_wids.add(self) | |
208 for w in self._right_wids: | |
209 new_wid._right_wids.add(w) | |
210 w._left_wids.add(new_wid) | |
211 for w in self._left_wids: | |
212 new_wid._left_wids.add(w) | |
213 w._right_wids.add(new_wid) | |
13 | 214 |
154 | 215 elif self._split == 'left': |
216 ori_width = touch.ud['ori_width'] | |
217 new_x = touch.x | |
218 new_width = ori_width - (touch.x - touch.ox) | |
219 | |
220 if new_width < MIN_WIDTH: | |
221 return | |
222 | |
223 # we must not pass the left widget/border | |
224 if self._left_wids: | |
225 left = next(iter(self._left_wids)) | |
226 x_limit = left.x | |
227 | |
228 if left.width <= REMOVE_WID_LIMIT: | |
229 # we are in remove zone, we add visual hint for that | |
160
916af9c1cb9b
widget handler: don't set split delete mode if there is not top/left widget
Goffi <goffi@goffi.org>
parents:
155
diff
changeset
|
230 if not self._split_del and self._left_wids: |
154 | 231 self._split_del = True |
232 self._draw_ellipse() | |
233 else: | |
234 if self._split_del: | |
235 self._split_del = False | |
236 self._draw_ellipse() | |
237 else: | |
238 x_limit = self.x | |
239 | |
240 if new_x <= x_limit: | |
241 return | |
242 | |
243 # all right, we can change position/size | |
244 self.x = new_x | |
245 self.width = new_width | |
246 self.ellipse.pos = (touch.x - self.sp_zone/2, self.ellipse.pos[1]) | |
247 | |
248 if not self._left_wids: | |
249 # we are the last widget on the left | |
250 # so we create a new widget | |
251 new_wid = self.parent.add_widget() | |
252 self._left_wids.add(new_wid) | |
253 new_wid._right_wids.add(self) | |
254 for w in self._top_wids: | |
255 new_wid._top_wids.add(w) | |
256 w._bottom_wids.add(new_wid) | |
257 for w in self._bottom_wids: | |
258 new_wid._bottom_wids.add(w) | |
259 w._top_wids.add(new_wid) | |
260 | |
261 else: | |
262 raise Exception.InternalError('invalid _split value') | |
13 | 263 |
264 def on_touch_up(self, touch): | |
154 | 265 if self._split == 'None': |
266 return super(WHWrapper, self).on_touch_up(touch) | |
267 if self._split == 'top': | |
268 # we remove all top widgets in delete zone, | |
269 # and update there side widgets list | |
270 for top in self._top_wids.copy(): | |
271 if top.height <= REMOVE_WID_LIMIT: | |
263
fe540a6dc14d
widgets handler: call host._removeVisibleWidget when a widget is deleted (using split)
Goffi <goffi@goffi.org>
parents:
260
diff
changeset
|
272 G.host._removeVisibleWidget(top.current_slide) |
154 | 273 for w in top._top_wids: |
274 w._bottom_wids.remove(top) | |
275 w._bottom_wids.update(top._bottom_wids) | |
276 for w in top._bottom_wids: | |
277 w._top_wids.remove(top) | |
278 w._top_wids.update(top._top_wids) | |
279 for w in top._left_wids: | |
280 w._right_wids.remove(top) | |
281 for w in top._right_wids: | |
282 w._left_wids.remove(top) | |
283 self.parent.remove_widget(top) | |
284 elif self._split == 'left': | |
285 # we remove all left widgets in delete zone, | |
286 # and update there side widgets list | |
287 for left in self._left_wids.copy(): | |
288 if left.width <= REMOVE_WID_LIMIT: | |
263
fe540a6dc14d
widgets handler: call host._removeVisibleWidget when a widget is deleted (using split)
Goffi <goffi@goffi.org>
parents:
260
diff
changeset
|
289 G.host._removeVisibleWidget(left.current_slide) |
154 | 290 for w in left._left_wids: |
291 w._right_wids.remove(left) | |
292 w._right_wids.update(left._right_wids) | |
293 for w in left._right_wids: | |
294 w._left_wids.remove(left) | |
295 w._left_wids.update(left._left_wids) | |
296 for w in left._top_wids: | |
297 w._bottom_wids.remove(left) | |
298 for w in left._bottom_wids: | |
299 w._top_wids.remove(left) | |
300 self.parent.remove_widget(left) | |
301 self._split = 'None' | |
302 self.canvas.after.remove(self.ellipse) | |
303 del self.ellipse | |
13 | 304 |
154 | 305 def set_widget(self, wid, index=0): |
306 self.carousel.add_widget(wid, index) | |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
307 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
308 def changeWidget(self, new_widget): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
309 """Change currently displayed widget |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
310 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
311 slides widgets will be updated |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
312 """ |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
313 # slides update need to be blocked to avoid the update in onSlideChange |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
314 # which would mess the removal of current widgets |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
315 self._slides_update_lock = True |
154 | 316 current = self.carousel.current_slide |
317 for w in self.carousel.slides: | |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
318 if w == current or w == new_widget: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
319 continue |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
320 if isinstance(w, quick_widgets.QuickWidget): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
321 G.host.widgets.deleteWidget(w) |
154 | 322 self.carousel.clear_widgets() |
260
145c29b5f2b5
core: improved getOrClone + use in chat and widgets_handler:
Goffi <goffi@goffi.org>
parents:
248
diff
changeset
|
323 self.carousel.add_widget(G.host.getOrClone(new_widget)) |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
324 self._slides_update_lock = False |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
325 self.updateHiddenSlides() |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
326 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
327 def onSlideChange(self, handler, new_slide): |
248
b6e33b35538b
core, widgets handler: visible_widgets now keep all CagouWidgets, not only QuickWidgets. visible_quick_widgets can be used if only QuickWidgets are desired.
Goffi <goffi@goffi.org>
parents:
177
diff
changeset
|
328 if self._former_slide is not None: |
271
23d4358803c7
widgets_handler: work around the double call of onSlideChange:
Goffi <goffi@goffi.org>
parents:
269
diff
changeset
|
329 if self._former_slide is new_slide: |
23d4358803c7
widgets_handler: work around the double call of onSlideChange:
Goffi <goffi@goffi.org>
parents:
269
diff
changeset
|
330 # FIXME: workaround for Kivy a95d67f (and above?), Carousel.current_slide |
23d4358803c7
widgets_handler: work around the double call of onSlideChange:
Goffi <goffi@goffi.org>
parents:
269
diff
changeset
|
331 # binding now calls onSlideChange twice with the same widget (here |
23d4358803c7
widgets_handler: work around the double call of onSlideChange:
Goffi <goffi@goffi.org>
parents:
269
diff
changeset
|
332 # "new_slide"). To be checked with Kivy team. |
23d4358803c7
widgets_handler: work around the double call of onSlideChange:
Goffi <goffi@goffi.org>
parents:
269
diff
changeset
|
333 return |
248
b6e33b35538b
core, widgets handler: visible_widgets now keep all CagouWidgets, not only QuickWidgets. visible_quick_widgets can be used if only QuickWidgets are desired.
Goffi <goffi@goffi.org>
parents:
177
diff
changeset
|
334 G.host._removeVisibleWidget(self._former_slide) |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
335 self._former_slide = new_slide |
248
b6e33b35538b
core, widgets handler: visible_widgets now keep all CagouWidgets, not only QuickWidgets. visible_quick_widgets can be used if only QuickWidgets are desired.
Goffi <goffi@goffi.org>
parents:
177
diff
changeset
|
336 if new_slide is not None: |
b6e33b35538b
core, widgets handler: visible_widgets now keep all CagouWidgets, not only QuickWidgets. visible_quick_widgets can be used if only QuickWidgets are desired.
Goffi <goffi@goffi.org>
parents:
177
diff
changeset
|
337 G.host._addVisibleWidget(new_slide) |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
338 self.updateHiddenSlides() |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
339 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
340 def hiddenList(self, visible_list): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
341 """return widgets of same class as holded one which are hidden |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
342 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
343 @param visible_list(list[QuickWidget]): widgets visible |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
344 @return (iter[QuickWidget]): widgets hidden |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
345 """ |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
346 added = [(w.targets, w.profiles) for w in visible_list] # we want to avoid recreated widgets |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
347 for w in G.host.widgets.getWidgets(self.current_slide.__class__, profiles=self.current_slide.profiles): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
348 if w in visible_list or (w.targets, w.profiles) in added: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
349 continue |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
350 yield w |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
351 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
352 def widgets_sort(self, widget): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
353 """method used as key to sort the widgets |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
354 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
355 order of the widgets when changing slide is affected |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
356 @param widget(QuickWidget): widget to sort |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
357 @return: a value which will be used for sorting |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
358 """ |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
359 try: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
360 return unicode(widget.target).lower() |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
361 except AttributeError: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
362 return unicode(list(widget.targets)[0]).lower() |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
363 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
364 def updateHiddenSlides(self): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
365 """adjust carousel slides according to visible widgets""" |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
366 if self._slides_update_lock: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
367 return |
154 | 368 if not isinstance(self.carousel.current_slide, quick_widgets.QuickWidget): |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
369 return |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
370 # lock must be used here to avoid recursions |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
371 self._slides_update_lock = True |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
372 visible_list = G.host.getVisibleList(self.current_slide.__class__) |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
373 hidden = list(self.hiddenList(visible_list)) |
154 | 374 slides_sorted = sorted(hidden + [self.carousel.current_slide], key=self.widgets_sort) |
375 to_remove = set(self.carousel.slides).difference({self.carousel.current_slide}) | |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
376 for w in to_remove: |
154 | 377 self.carousel.remove_widget(w) |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
378 if hidden: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
379 # no need to add more than two widgets (next and previous), |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
380 # as the list will be updated on each new visible widget |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
381 current_idx = slides_sorted.index(self.current_slide) |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
382 try: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
383 next_slide = slides_sorted[current_idx+1] |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
384 except IndexError: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
385 next_slide = slides_sorted[0] |
154 | 386 self.carousel.add_widget(G.host.getOrClone(next_slide)) |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
387 if len(hidden)>1: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
388 previous_slide = slides_sorted[current_idx-1] |
154 | 389 self.carousel.add_widget(G.host.getOrClone(previous_slide)) |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
390 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
391 self._slides_update_lock = False |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
392 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
393 |
154 | 394 class WidgetsHandlerLayout(Layout): |
395 count = 0 | |
13 | 396 |
154 | 397 def __init__(self, **kwargs): |
398 super(WidgetsHandlerLayout, self).__init__(**kwargs) | |
171
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
399 self._layout_size = None # size used for the last layout |
154 | 400 fbind = self.fbind |
401 update = self._trigger_layout | |
402 fbind('children', update) | |
403 fbind('parent', update) | |
171
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
404 fbind('size', self.adjust_prop) |
154 | 405 fbind('pos', update) |
13 | 406 |
14 | 407 @property |
408 def default_widget(self): | |
16
ba14b596b90e
host can now be get as a global value:
Goffi <goffi@goffi.org>
parents:
15
diff
changeset
|
409 return G.host.default_wid['factory'](G.host.default_wid, None, None) |
14 | 410 |
171
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
411 def adjust_prop(self, handler, new_size): |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
412 """Adjust children proportion |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
413 |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
414 useful when this widget is resized (e.g. when going to fullscreen) |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
415 """ |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
416 if len(self.children) > 1: |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
417 old_width, old_height = self._layout_size |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
418 if not old_width or not old_height: |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
419 # we don't want division by zero |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
420 return self._trigger_layout(handler, new_size) |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
421 width_factor = float(self.width) / old_width |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
422 height_factor = float(self.height) / old_height |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
423 for child in self.children: |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
424 child.width *= width_factor |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
425 child.height *= height_factor |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
426 child.x *= width_factor |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
427 child.y *= height_factor |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
428 self._trigger_layout(handler, new_size) |
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
429 |
154 | 430 def do_layout(self, *args): |
171
27b4ceb977c7
widgets handler: keep proportion on resize
Goffi <goffi@goffi.org>
parents:
170
diff
changeset
|
431 self._layout_size = self.size[:] |
154 | 432 for child in self.children: |
433 # XXX: left must be calculated before right and bottom before top | |
434 # because they are the pos, and are used to caculate size (right and top) | |
435 # left | |
436 left = child._left_wid | |
170
f4522b7c3318
widgets handler: use widget's top and right
Goffi <goffi@goffi.org>
parents:
163
diff
changeset
|
437 left_end_x = self.x-1 if left is None else left.right |
154 | 438 if child.x != left_end_x + 1 and child._split == "None": |
439 child.x = left_end_x + 1 | |
440 # right | |
441 right = child._right_wid | |
170
f4522b7c3318
widgets handler: use widget's top and right
Goffi <goffi@goffi.org>
parents:
163
diff
changeset
|
442 right_x = self.right + 1 if right is None else right.x |
f4522b7c3318
widgets handler: use widget's top and right
Goffi <goffi@goffi.org>
parents:
163
diff
changeset
|
443 if child.right != right_x - 1: |
154 | 444 child.width = right_x - child.x - 1 |
445 # bottom | |
446 bottom = child._bottom_wid | |
447 if bottom is None: | |
170
f4522b7c3318
widgets handler: use widget's top and right
Goffi <goffi@goffi.org>
parents:
163
diff
changeset
|
448 if child.y != self.y: |
f4522b7c3318
widgets handler: use widget's top and right
Goffi <goffi@goffi.org>
parents:
163
diff
changeset
|
449 child.y = self.y |
154 | 450 else: |
170
f4522b7c3318
widgets handler: use widget's top and right
Goffi <goffi@goffi.org>
parents:
163
diff
changeset
|
451 if child.y != bottom.top + 1: |
f4522b7c3318
widgets handler: use widget's top and right
Goffi <goffi@goffi.org>
parents:
163
diff
changeset
|
452 child.y = bottom.top + 1 |
154 | 453 # top |
454 top = child._top_wid | |
170
f4522b7c3318
widgets handler: use widget's top and right
Goffi <goffi@goffi.org>
parents:
163
diff
changeset
|
455 top_y = self.top+1 if top is None else top.y |
f4522b7c3318
widgets handler: use widget's top and right
Goffi <goffi@goffi.org>
parents:
163
diff
changeset
|
456 if child.top != top_y - 1: |
154 | 457 if child._split == "None": |
458 child.height = top_y - child.y - 1 | |
459 | |
460 def remove_widget(self, wid): | |
461 super(WidgetsHandlerLayout, self).remove_widget(wid) | |
462 log.debug("widget deleted ({})".format(wid._wid_idx)) | |
463 | |
464 def add_widget(self, wid=None, index=0): | |
465 WidgetsHandlerLayout.count += 1 | |
466 if wid is None: | |
467 wid = self.default_widget | |
468 wrapper = WHWrapper(_wid_idx=WidgetsHandlerLayout.count) | |
469 log.debug("WHWrapper created ({})".format(wrapper._wid_idx)) | |
470 wrapper.set_widget(wid) | |
471 super(WidgetsHandlerLayout, self).add_widget(wrapper, index) | |
472 return wrapper | |
473 | |
474 | |
475 class WidgetsHandler(WidgetsHandlerLayout): | |
476 | |
477 def __init__(self, **kw): | |
478 super(WidgetsHandler, self).__init__(**kw) | |
479 self.wrapper = self.add_widget() | |
480 | |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
481 @property |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
482 def cagou_widget(self): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
483 """get holded CagouWidget""" |
154 | 484 return self.wrapper.current_slide |