Mercurial > libervia-desktop-kivy
view src/libs/garden/garden.contextmenu/app_menu.py @ 97:5d2289127bb7
menu (upload): better menu using dedicated widget:
upload menu now use a decicated widget instead of context menu.
The menu take half the size of the main window, and show each upload option as an icon. Use can select upload or P2P sending, and a short text message explains how the file will be transmitted.
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 29 Dec 2016 23:47:07 +0100 |
parents | 741a7d6d8c28 |
children |
line wrap: on
line source
from kivy.uix.relativelayout import RelativeLayout from kivy.uix.stacklayout import StackLayout from kivy.uix.behaviors import ToggleButtonBehavior from kivy.uix.togglebutton import ToggleButton from kivy.lang import Builder import kivy.properties as kp import os from .context_menu import AbstractMenu, AbstractMenuItem, AbstractMenuItemHoverable class AppMenu(StackLayout, AbstractMenu): bounding_box = kp.ObjectProperty(None) def __init__(self, *args, **kwargs): super(AppMenu, self).__init__(*args, **kwargs) self.hovered_menu_item = None def update_height(self): max_height = 0 for widget in self.menu_item_widgets: if widget.height > max_height: max_height = widget.height return max_height def on_children(self, obj, new_children): for w in new_children: # bind events that update app menu height when any of its children resize w.bind(on_size=self.update_height) w.bind(on_height=self.update_height) def get_context_menu_root_parent(self): return self def self_or_submenu_collide_with_point(self, x, y): collide_widget = None # Iterate all siblings and all children for widget in self.menu_item_widgets: widget_pos = widget.to_window(0, 0) if widget.collide_point(x - widget_pos[0], y - widget_pos[1]) and not widget.disabled: if self.hovered_menu_item is None: self.hovered_menu_item = widget if self.hovered_menu_item != widget: self.hovered_menu_item = widget for sibling in widget.siblings: sibling.state = 'normal' if widget.state == 'normal': widget.state = 'down' widget.on_release() for sib in widget.siblings: sib.hovered = False elif widget.get_submenu() is not None and not widget.get_submenu().visible: widget.state = 'normal' return collide_widget def close_all(self): for submenu in [w.get_submenu() for w in self.menu_item_widgets if w.get_submenu() is not None]: submenu.hide() for w in self.menu_item_widgets: w.state = 'normal' def hide_app_menus(self, obj, pos): if not self.collide_point(pos.x, pos.y): for w in [w for w in self.menu_item_widgets if not w.disabled and w.get_submenu().visible]: submenu = w.get_submenu() if submenu.self_or_submenu_collide_with_point(pos.x, pos.y) is None: self.close_all() self._cancel_hover_timer() class AppMenuTextItem(ToggleButton, AbstractMenuItem): label = kp.ObjectProperty(None) text = kp.StringProperty('') font_size = kp.NumericProperty(14) color = kp.ListProperty([1, 1, 1, 1]) def on_release(self): submenu = self.get_submenu() if self.state == 'down': root = self._root_parent submenu.bounding_box_widget = root.bounding_box if root.bounding_box else root.parent submenu.bind(visible=self.on_visible) submenu.show(self.x, self.y - 1) for sibling in self.siblings: if sibling.get_submenu() is not None: sibling.state = 'normal' sibling.get_submenu().hide() self.parent._setup_hover_timer() else: self.parent._cancel_hover_timer() submenu.hide() def on_visible(self, *args): submenu = self.get_submenu() if self.width > submenu.get_max_width(): submenu.width = self.width def _check_submenu(self): super(AppMenuTextItem, self)._check_submenu() self.disabled = (self.get_submenu() is None) # def on_mouse_down(self): # print('on_mouse_down') # return True _path = os.path.dirname(os.path.realpath(__file__)) Builder.load_file(os.path.join(_path, 'app_menu.kv'))