comparison cagou/core/menu.py @ 404:f7476818f9fb

core (common): JidSelector + behaviors various improvments: - renamed *Behaviour => *Behavior to be consistent with Kivy + moved to new "core.behaviors" modules - use a dedicated property in ContactItem for notification counter (which is now named "badge") - in JidSelector, well-known strings now create use a dedicated layout, add separator (except if new `add_separators` property is set to False), and are added to attribute of the same name - a new `item_class` property is now used to indicate the class to instanciate for items (by default it's a ContactItem) - FilterBahavior.do_filter now expect the parent layout instead of directly the children, this is to allow a FilterBahavior to manage several children layout at once (used with JidSelector) - core.utils has been removed, as the behavior there has been moved to core.behaviors
author Goffi <goffi@goffi.org>
date Wed, 12 Feb 2020 20:02:58 +0100
parents 71f51198478c
children 5761b5f03c0c
comparison
equal deleted inserted replaced
403:b0af45a92055 404:f7476818f9fb
24 from cagou.core.common import JidToggle 24 from cagou.core.common import JidToggle
25 from kivy.uix.boxlayout import BoxLayout 25 from kivy.uix.boxlayout import BoxLayout
26 from kivy.uix.label import Label 26 from kivy.uix.label import Label
27 from kivy.uix.button import Button 27 from kivy.uix.button import Button
28 from kivy.uix.popup import Popup 28 from kivy.uix.popup import Popup
29 from cagou.core.utils import FilterBehavior 29 from .behaviors import FilterBehavior
30 from kivy import properties 30 from kivy import properties
31 from kivy_garden import modernmenu
32 from kivy.core.window import Window 31 from kivy.core.window import Window
33 from kivy.animation import Animation 32 from kivy.animation import Animation
34 from kivy.metrics import dp 33 from kivy.metrics import dp
35 from kivy.clock import Clock
36 from cagou import G 34 from cagou import G
37 from functools import partial 35 from functools import partial
38 import webbrowser 36 import webbrowser
39 37
40 log = logging.getLogger(__name__) 38 log = logging.getLogger(__name__)
293 jids = [c.jid for c in self.layout.children if c.state == 'down'] 291 jids = [c.jid for c in self.layout.children if c.state == 'down']
294 self.callback(jids) 292 self.callback(jids)
295 293
296 def do_filter_input(self, filter_input, text): 294 def do_filter_input(self, filter_input, text):
297 self.layout.spacing = 0 if text else dp(5) 295 self.layout.spacing = 0 if text else dp(5)
298 self.do_filter(self.layout.children, 296 self.do_filter(self.layout,
299 text, 297 text,
300 lambda c: c.jid, 298 lambda c: c.jid,
301 width_cb=lambda c: c.width, 299 width_cb=lambda c: c.width,
302 height_cb=lambda c: dp(70)) 300 height_cb=lambda c: dp(70))
303
304
305 class TouchMenu(modernmenu.ModernMenu):
306 pass
307
308
309 class TouchMenuItemBehaviour(object):
310 """Class to use on every item where a menu may appear
311
312 main_wid attribute must be set to the class inheriting from TouchMenuBehaviour
313 do_item_action is the method called on simple click
314 getMenuChoices must return a list of menus for long press
315 menus there are dict as expected by ModernMenu
316 (translated text, index and callback)
317 """
318 main_wid = properties.ObjectProperty()
319 click_timeout = properties.NumericProperty(0.4)
320
321 def on_touch_down(self, touch):
322 if not self.collide_point(*touch.pos):
323 return
324 t = partial(self.open_menu, touch)
325 touch.ud['menu_timeout'] = t
326 Clock.schedule_once(t, self.click_timeout)
327 return super(TouchMenuItemBehaviour, self).on_touch_down(touch)
328
329 def do_item_action(self, touch):
330 pass
331
332 def on_touch_up(self, touch):
333 if touch.ud.get('menu_timeout'):
334 Clock.unschedule(touch.ud['menu_timeout'])
335 if self.collide_point(*touch.pos) and self.main_wid.menu is None:
336 self.do_item_action(touch)
337 return super(TouchMenuItemBehaviour, self).on_touch_up(touch)
338
339 def open_menu(self, touch, dt):
340 self.main_wid.open_menu(self, touch)
341 del touch.ud['menu_timeout']
342
343 def getMenuChoices(self):
344 """return choice adapted to selected item
345
346 @return (list[dict]): choices ad expected by ModernMenu
347 """
348 return []
349
350
351 class TouchMenuBehaviour(object):
352 """Class to handle a menu appearing on long press on items
353
354 classes using this behaviour need to have a float_layout property
355 pointing the main FloatLayout.
356 """
357 float_layout = properties.ObjectProperty()
358
359 def __init__(self, *args, **kwargs):
360 super(TouchMenuBehaviour, self).__init__(*args, **kwargs)
361 self.menu = None
362 self.menu_item = None
363
364 ## menu methods ##
365
366 def clean_fl_children(self, layout, children):
367 """insure that self.menu and self.menu_item are None when menu is dimissed"""
368 if self.menu is not None and self.menu not in children:
369 self.menu = self.menu_item = None
370
371 def clear_menu(self):
372 """remove menu if there is one"""
373 if self.menu is not None:
374 self.menu.dismiss()
375 self.menu = None
376 self.menu_item = None
377
378 def open_menu(self, item, touch):
379 """open menu for item
380
381 @param item(PathWidget): item when the menu has been requested
382 @param touch(kivy.input.MotionEvent): touch data
383 """
384 if self.menu_item == item:
385 return
386 self.clear_menu()
387 pos = self.to_widget(*touch.pos)
388 choices = item.getMenuChoices()
389 if not choices:
390 return
391 self.menu = TouchMenu(choices=choices,
392 center=pos,
393 size_hint=(None, None))
394 self.float_layout.add_widget(self.menu)
395 self.menu.start_display(touch)
396 self.menu_item = item
397
398 def on_float_layout(self, wid, float_layout):
399 float_layout.bind(children=self.clean_fl_children)