Mercurial > libervia-desktop-kivy
annotate cagou/core/widgets_handler.py @ 154:a5e8833184c6
widget handler: refactoring:
- replaced proof of concept implementation with cleaner one based on custom layout
- removed proof of concept big bars in favor of thin line to separate widgets, with a 3 dots area in the center where user can touch/click more easily
- when in delete zone, the line + half circle become red, so user knows that she's about to delete a widget
- carousel is now created in kv
- ignore perpendicular swipes. This was not working before but is know working well, and the swipe is far more easy to do on desktop or mobile
- each new widget of the handler has an id (its creation number), which is displayed in debug logs on touch
- handler's widgets keep track of which widgets are on sides (left, top, right, bottom)
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 27 Apr 2018 16:45:09 +0200 |
parents | cd99f70ea592 |
children | a0e486074d91 |
rev | line source |
---|---|
13 | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Cagou: desktop/mobile frontend for Salut à Toi XMPP client | |
126 | 5 # Copyright (C) 2016-2018 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 |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
28 from kivy.metrics import dp |
13 | 29 from kivy import properties |
16
ba14b596b90e
host can now be get as a global value:
Goffi <goffi@goffi.org>
parents:
15
diff
changeset
|
30 from cagou import G |
13 | 31 |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
32 CAROUSEL_SCROLL_DISTANCE = dp(50) |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
33 CAROUSEL_SCROLL_TIMEOUT = 80 |
154 | 34 REMOVE_WID_LIMIT = dp(10) |
35 MIN_WIDTH = MIN_HEIGHT = dp(50) | |
13 | 36 |
37 | |
154 | 38 class WHWrapper(BoxLayout): |
39 carousel = properties.ObjectProperty(None) | |
40 split_size = properties.NumericProperty(dp(1)) | |
41 split_margin = properties.NumericProperty(dp(2)) | |
42 split_color = properties.ListProperty([0.8, 0.8, 0.8, 1]) | |
43 split_color_move = properties.ListProperty([0.0, 0.8, 0.8, 1]) | |
44 split_color_del = properties.ListProperty([0.8, 0.0, 0.0, 1]) | |
45 # sp stands for "split point" | |
46 sp_size = properties.NumericProperty(dp(1)) | |
47 sp_space = properties.NumericProperty(dp(4)) | |
48 sp_zone = properties.NumericProperty(dp(30)) | |
49 _split = properties.OptionProperty('None', options=['None', 'left', 'top']) | |
50 _split_del = properties.BooleanProperty(False) | |
51 | |
52 def __init__(self, **kwargs): | |
53 idx = kwargs.pop('_wid_idx') | |
54 self._wid_idx = idx | |
55 super(WHWrapper, self).__init__(**kwargs) | |
56 self._former_slide = None | |
57 self.carousel.bind(current_slide=self.onSlideChange) | |
58 self._slides_update_lock = False | |
59 self._left_wids = set() | |
60 self._top_wids = set() | |
61 self._right_wids = set() | |
62 self._bottom_wids = set() | |
63 | |
64 def __repr__(self): | |
65 return "WHWrapper_{idx}".format(idx=self._wid_idx) | |
66 | |
67 def _main_wid(self, wid_list): | |
68 """return main widget of a side list | |
69 | |
70 main widget is either the widget currently splitter | |
71 or any widget if none is split | |
72 @return (WHWrapper, None): main widget or None | |
73 if there is not widget | |
74 """ | |
75 if not wid_list: | |
76 return None | |
77 for wid in wid_list: | |
78 if wid._split != 'None': | |
79 return wid | |
80 return next(iter(wid_list)) | |
81 | |
82 @property | |
83 def _left_wid(self): | |
84 return self._main_wid(self._left_wids) | |
85 | |
86 @property | |
87 def _top_wid(self): | |
88 return self._main_wid(self._top_wids) | |
89 | |
90 @property | |
91 def _right_wid(self): | |
92 return self._main_wid(self._right_wids) | |
93 | |
94 @property | |
95 def _bottom_wid(self): | |
96 return self._main_wid(self._bottom_wids) | |
13 | 97 |
154 | 98 @property |
99 def current_slide(self): | |
100 return self.carousel.current_slide | |
101 | |
102 def _draw_ellipse(self): | |
103 """draw split ellipse""" | |
104 color = self.split_color_del if self._split_del else self.split_color_move | |
105 try: | |
106 self.canvas.after.remove(self.ellipse) | |
107 except AttributeError: | |
108 pass | |
109 if self._split == "top": | |
110 with self.canvas.after: | |
111 Color(*color) | |
112 self.ellipse = Ellipse(angle_start=90, angle_end=270, | |
113 pos=(self.x + self.width/2 - self.sp_zone/2, | |
114 self.y + self.height - self.sp_zone/2), | |
115 size=(self.sp_zone, self.sp_zone)) | |
116 elif self._split == "left": | |
117 with self.canvas.after: | |
118 Color(*color) | |
119 self.ellipse = Ellipse(angle_end=180, | |
120 pos=(self.x + -self.sp_zone/2, | |
121 self.y + self.height/2 - self.sp_zone/2), | |
122 size = (self.sp_zone, self.sp_zone)) | |
123 else: | |
124 raise exceptions.InternalError('unexpected split value') | |
13 | 125 |
154 | 126 def on_touch_down(self, touch): |
127 """activate split if touch is on a split zone""" | |
128 if not self.collide_point(*touch.pos): | |
129 return | |
130 log.debug("WIDGET IDX: {} (left: {}, top: {}, right: {}, bottom: {}), pos: {}, size: {}".format( | |
131 self._wid_idx, | |
132 'None' if not self._left_wids else [w._wid_idx for w in self._left_wids], | |
133 'None' if not self._top_wids else [w._wid_idx for w in self._top_wids], | |
134 'None' if not self._right_wids else [w._wid_idx for w in self._right_wids], | |
135 'None' if not self._bottom_wids else [w._wid_idx for w in self._bottom_wids], | |
136 self.pos, | |
137 self.size, | |
138 )) | |
139 touch_rx, touch_ry = self.to_widget(*touch.pos, relative=True) | |
140 if (touch_ry <= self.height and | |
141 touch_ry >= self.height - self.split_size - self.split_margin or | |
142 touch_ry <= self.height and | |
143 touch_ry >= self.height - self.sp_zone and | |
144 touch_rx >= self.width/2 - self.sp_zone/2 and | |
145 touch_rx <= self.width/2 + self.sp_zone/2): | |
146 # split area is touched, we activate top split mode | |
147 self._split = "top" | |
148 self._draw_ellipse() | |
149 elif (touch_rx >= 0 and | |
150 touch_rx <= self.split_size + self.split_margin or | |
151 touch_rx >= 0 and | |
152 touch_rx <= self.sp_zone and | |
153 touch_ry >= self.height/2 - self.sp_zone/2 and | |
154 touch_ry <= self.height/2 + self.sp_zone/2): | |
155 # split area is touched, we activate left split mode | |
156 self._split = "left" | |
157 touch.ud['ori_width'] = self.width | |
158 self._draw_ellipse() | |
13 | 159 else: |
154 | 160 return super(WHWrapper, self).on_touch_down(touch) |
13 | 161 |
162 def on_touch_move(self, touch): | |
154 | 163 """handle size change and widget creation on split""" |
164 if self._split == 'None': | |
165 return super(WHWrapper, self).on_touch_move(touch) | |
166 | |
167 elif self._split == 'top': | |
168 new_height = touch.y - self.y | |
169 | |
170 if new_height < MIN_HEIGHT: | |
171 return | |
172 | |
173 # we must not pass the top widget/border | |
174 if self._top_wids: | |
175 top = next(iter(self._top_wids)) | |
176 y_limit = top.y + top.height | |
177 | |
178 if top.height <= REMOVE_WID_LIMIT: | |
179 # we are in remove zone, we add visual hint for that | |
180 if not self._split_del: | |
181 self._split_del = True | |
182 self._draw_ellipse() | |
183 else: | |
184 if self._split_del: | |
185 self._split_del = False | |
186 self._draw_ellipse() | |
187 else: | |
188 y_limit = self.y + self.height | |
189 | |
190 if touch.y >= y_limit: | |
191 return | |
192 | |
193 # all right, we can change size | |
194 self.height = new_height | |
195 self.ellipse.pos = (self.ellipse.pos[0], touch.y - self.sp_zone/2) | |
196 | |
197 if not self._top_wids: | |
198 # we are the last widget on the top | |
199 # so we create a new widget | |
200 new_wid = self.parent.add_widget() | |
201 self._top_wids.add(new_wid) | |
202 new_wid._bottom_wids.add(self) | |
203 for w in self._right_wids: | |
204 new_wid._right_wids.add(w) | |
205 w._left_wids.add(new_wid) | |
206 for w in self._left_wids: | |
207 new_wid._left_wids.add(w) | |
208 w._right_wids.add(new_wid) | |
13 | 209 |
154 | 210 elif self._split == 'left': |
211 ori_width = touch.ud['ori_width'] | |
212 new_x = touch.x | |
213 new_width = ori_width - (touch.x - touch.ox) | |
214 | |
215 if new_width < MIN_WIDTH: | |
216 return | |
217 | |
218 # we must not pass the left widget/border | |
219 if self._left_wids: | |
220 left = next(iter(self._left_wids)) | |
221 x_limit = left.x | |
222 | |
223 if left.width <= REMOVE_WID_LIMIT: | |
224 # we are in remove zone, we add visual hint for that | |
225 if not self._split_del: | |
226 self._split_del = True | |
227 self._draw_ellipse() | |
228 else: | |
229 if self._split_del: | |
230 self._split_del = False | |
231 self._draw_ellipse() | |
232 else: | |
233 x_limit = self.x | |
234 | |
235 if new_x <= x_limit: | |
236 return | |
237 | |
238 # all right, we can change position/size | |
239 self.x = new_x | |
240 self.width = new_width | |
241 self.ellipse.pos = (touch.x - self.sp_zone/2, self.ellipse.pos[1]) | |
242 | |
243 if not self._left_wids: | |
244 # we are the last widget on the left | |
245 # so we create a new widget | |
246 new_wid = self.parent.add_widget() | |
247 self._left_wids.add(new_wid) | |
248 new_wid._right_wids.add(self) | |
249 for w in self._top_wids: | |
250 new_wid._top_wids.add(w) | |
251 w._bottom_wids.add(new_wid) | |
252 for w in self._bottom_wids: | |
253 new_wid._bottom_wids.add(w) | |
254 w._top_wids.add(new_wid) | |
255 | |
256 else: | |
257 raise Exception.InternalError('invalid _split value') | |
13 | 258 |
259 def on_touch_up(self, touch): | |
154 | 260 if self._split == 'None': |
261 return super(WHWrapper, self).on_touch_up(touch) | |
262 if self._split == 'top': | |
263 # we remove all top widgets in delete zone, | |
264 # and update there side widgets list | |
265 for top in self._top_wids.copy(): | |
266 if top.height <= REMOVE_WID_LIMIT: | |
267 for w in top._top_wids: | |
268 w._bottom_wids.remove(top) | |
269 w._bottom_wids.update(top._bottom_wids) | |
270 for w in top._bottom_wids: | |
271 w._top_wids.remove(top) | |
272 w._top_wids.update(top._top_wids) | |
273 for w in top._left_wids: | |
274 w._right_wids.remove(top) | |
275 for w in top._right_wids: | |
276 w._left_wids.remove(top) | |
277 self.parent.remove_widget(top) | |
278 elif self._split == 'left': | |
279 # we remove all left widgets in delete zone, | |
280 # and update there side widgets list | |
281 for left in self._left_wids.copy(): | |
282 if left.width <= REMOVE_WID_LIMIT: | |
283 for w in left._left_wids: | |
284 w._right_wids.remove(left) | |
285 w._right_wids.update(left._right_wids) | |
286 for w in left._right_wids: | |
287 w._left_wids.remove(left) | |
288 w._left_wids.update(left._left_wids) | |
289 for w in left._top_wids: | |
290 w._bottom_wids.remove(left) | |
291 for w in left._bottom_wids: | |
292 w._top_wids.remove(left) | |
293 self.parent.remove_widget(left) | |
294 self._split = 'None' | |
295 self.canvas.after.remove(self.ellipse) | |
296 del self.ellipse | |
13 | 297 |
154 | 298 def set_widget(self, wid, index=0): |
299 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
|
300 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
301 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
|
302 """Change currently displayed widget |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
303 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
304 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
|
305 """ |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
306 # 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
|
307 # 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
|
308 self._slides_update_lock = True |
154 | 309 current = self.carousel.current_slide |
310 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
|
311 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
|
312 continue |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
313 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
|
314 G.host.widgets.deleteWidget(w) |
154 | 315 self.carousel.clear_widgets() |
316 self.carousel.add_widget(new_widget) | |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
317 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
|
318 self.updateHiddenSlides() |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
319 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
320 def onSlideChange(self, handler, new_slide): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
321 if isinstance(self._former_slide, quick_widgets.QuickWidget): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
322 G.host.removeVisibleWidget(self._former_slide) |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
323 self._former_slide = new_slide |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
324 if isinstance(new_slide, quick_widgets.QuickWidget): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
325 G.host.addVisibleWidget(new_slide) |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
326 self.updateHiddenSlides() |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
327 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
328 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
|
329 """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
|
330 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
331 @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
|
332 @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
|
333 """ |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
334 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
|
335 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
|
336 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
|
337 continue |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
338 yield w |
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 widgets_sort(self, widget): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
341 """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
|
342 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
343 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
|
344 @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
|
345 @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
|
346 """ |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
347 try: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
348 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
|
349 except AttributeError: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
350 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
|
351 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
352 def updateHiddenSlides(self): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
353 """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
|
354 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
|
355 return |
154 | 356 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
|
357 return |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
358 # 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
|
359 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
|
360 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
|
361 hidden = list(self.hiddenList(visible_list)) |
154 | 362 slides_sorted = sorted(hidden + [self.carousel.current_slide], key=self.widgets_sort) |
363 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
|
364 for w in to_remove: |
154 | 365 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
|
366 if hidden: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
367 # 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
|
368 # 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
|
369 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
|
370 try: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
371 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
|
372 except IndexError: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
373 next_slide = slides_sorted[0] |
154 | 374 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
|
375 if len(hidden)>1: |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
376 previous_slide = slides_sorted[current_idx-1] |
154 | 377 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
|
378 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
379 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
|
380 |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
381 |
154 | 382 class WidgetsHandlerLayout(Layout): |
383 count = 0 | |
13 | 384 |
154 | 385 def __init__(self, **kwargs): |
386 super(WidgetsHandlerLayout, self).__init__(**kwargs) | |
387 fbind = self.fbind | |
388 update = self._trigger_layout | |
389 fbind('children', update) | |
390 fbind('parent', update) | |
391 fbind('size', update) | |
392 fbind('pos', update) | |
13 | 393 |
14 | 394 @property |
395 def default_widget(self): | |
16
ba14b596b90e
host can now be get as a global value:
Goffi <goffi@goffi.org>
parents:
15
diff
changeset
|
396 return G.host.default_wid['factory'](G.host.default_wid, None, None) |
14 | 397 |
154 | 398 def do_layout(self, *args): |
399 x, y = self.pos | |
400 width, height = self.width, self.height | |
401 end_x, end_y = x + width, y + height | |
402 for child in self.children: | |
403 # XXX: left must be calculated before right and bottom before top | |
404 # because they are the pos, and are used to caculate size (right and top) | |
405 # left | |
406 left = child._left_wid | |
407 left_end_x = x-1 if left is None else left.x + left.width | |
408 if child.x != left_end_x + 1 and child._split == "None": | |
409 child.x = left_end_x + 1 | |
410 # right | |
411 right = child._right_wid | |
412 right_x = end_x + 1 if right is None else right.x | |
413 if child.x + child.width != right_x - 1: | |
414 child.width = right_x - child.x - 1 | |
415 # bottom | |
416 bottom = child._bottom_wid | |
417 if bottom is None: | |
418 if child.y != y: | |
419 child.y = y | |
420 else: | |
421 bottom_end_y = bottom.y + bottom.height | |
422 if child.y != bottom_end_y + 1: | |
423 child.y = bottom_end_y + 1 | |
424 # top | |
425 top = child._top_wid | |
426 top_y = end_y+1 if top is None else top.y | |
427 if child.y + child.height != top_y - 1: | |
428 if child._split == "None": | |
429 child.height = top_y - child.y - 1 | |
430 | |
431 def remove_widget(self, wid): | |
432 super(WidgetsHandlerLayout, self).remove_widget(wid) | |
433 log.debug("widget deleted ({})".format(wid._wid_idx)) | |
434 | |
435 def add_widget(self, wid=None, index=0): | |
436 WidgetsHandlerLayout.count += 1 | |
437 if wid is None: | |
438 wid = self.default_widget | |
439 wrapper = WHWrapper(_wid_idx=WidgetsHandlerLayout.count) | |
440 log.debug("WHWrapper created ({})".format(wrapper._wid_idx)) | |
441 wrapper.set_widget(wid) | |
442 super(WidgetsHandlerLayout, self).add_widget(wrapper, index) | |
443 return wrapper | |
444 | |
445 | |
446 class WidgetsHandler(WidgetsHandlerLayout): | |
447 | |
448 def __init__(self, **kw): | |
449 super(WidgetsHandler, self).__init__(**kw) | |
450 self.wrapper = self.add_widget() | |
451 | |
38
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
452 @property |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
453 def cagou_widget(self): |
9f45098289cc
widgets handler, core: hidden widgets can now be shown with swipes:
Goffi <goffi@goffi.org>
parents:
34
diff
changeset
|
454 """get holded CagouWidget""" |
154 | 455 return self.wrapper.current_slide |