Mercurial > libervia-web
view src/browser/sat_browser/base_menu.py @ 494:5d8632a7bfde
browser_side: refactorisation of menus and LiberviaWidget's header
author | souliane <souliane@mailoo.org> |
---|---|
date | Tue, 15 Jul 2014 18:43:55 +0200 |
parents | |
children | 60be99de3808 |
line wrap: on
line source
#!/usr/bin/python # -*- coding: utf-8 -*- # Libervia: a Salut à Toi frontend # Copyright (C) 2011, 2012, 2013, 2014 Jérôme Poisson <goffi@goffi.org> # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. """Base classes for building a menu. These classes have been moved here from menu.py because they are also used by base_widget.py, and the import sequence caused a JS runtime error.""" import pyjd # this is dummy in pyjs from sat.core.log import getLogger log = getLogger(__name__) from pyjamas.ui.MenuBar import MenuBar from pyjamas.ui.MenuItem import MenuItem class MenuCmd: """Return an object with an "execute" method that can be set to a menu item callback""" def __init__(self, object_, handler): self._object = object_ self._handler = handler def execute(self): handler = getattr(self._object, self._handler) handler() class PluginMenuCmd: """Like MenuCmd, but instead of executing a method, it will command the bridge to launch an action""" def __init__(self, host, action_id, menu_data=None): self.host = host self.action_id = action_id self.menu_data = menu_data def execute(self): self.host.launchAction(self.action_id, self.menu_data) class CategoryMenuBar(MenuBar): """A menu bar for a category (sub menu)""" def __init__(self): MenuBar.__init__(self, vertical=True) class CategoryItem(MenuItem): """A category item with a non-internationalized name""" def __init__(self, name, *args, **kwargs): MenuItem.__init__(self, *args, **kwargs) self.name = name class GenericMenuBar(MenuBar): def __init__(self, host, vertical=False, **kwargs): MenuBar.__init__(self, vertical, **kwargs) self.host = host self.moved_popup_style = None @classmethod def getCategoryHTML(cls, type_, menu_name_i18n): """Build from the given parameters the html to be displayed for a category item. Inheriting classes may overwrite this method. @param type_ (str): category type @param menu_name_i18n (str): internationalized category name @return: str """ return menu_name_i18n def doItemAction(self, item, fireCommand): """Overwrites the default behavior for the popup menu to fit in the screen""" MenuBar.doItemAction(self, item, fireCommand) if not self.vertical and self.popup: # we not only move the last popup, but any which would go over the menu right extremity most_left = self.getAbsoluteLeft() + self.getOffsetWidth() - self.popup.getOffsetWidth() if item.getAbsoluteLeft() > most_left: self.popup.setPopupPosition(most_left, self.getAbsoluteTop() + self.getOffsetHeight() - 1) # eventually smooth the popup edges to fit the menu own style if self.moved_popup_style: self.popup.addStyleName(self.moved_popup_style) def getCategories(self): """Return the categories items. @return: list[CategoryItem] """ return [item for item in self.items if isinstance(item, CategoryItem)] def getSubMenu(self, category): """Return the popup menu for the given category @param category (str): category name @return: CategoryMenuBar instance or None """ try: return [item for item in self.items if isinstance(item, CategoryItem) and item.name == category][0].getSubMenu() except IndexError: return None def addSeparator(self): """Add a separator between the categories""" self.addItem(CategoryItem(None, text='', asHTML=None, StyleName='menuSeparator')) def addCategory(self, menu_name, menu_name_i18n, type_, sub_menu): """Add a category @param menu_name (str): category name @param menu_name_i18n (str): internationalized category name @param type_ (str): category type @param sub_menu (CategoryMenuBar): category sub-menu """ html = self.getCategoryHTML(type_, menu_name_i18n) self.addItem(CategoryItem(menu_name, text=html, asHTML=True, subMenu=sub_menu)) def addMenu(self, menu_name, menu_name_i18n, item_name_i18n, type_, menu_cmd): """Add a new menu item @param menu_name (str): category name @param menu_name_i18n (str): internationalized menu name @param item_name_i18n (str): internationalized item name @param type_ (str): category type in ('games', 'help', 'home', 'photos', 'plugins', 'settings', 'social') @param menu_cmd (MenuCmd or PluginMenuCmd): instance to execute as the item callback """ log.info("addMenu: %s %s %s %s %s" % (menu_name, menu_name_i18n, item_name_i18n, type_, menu_cmd)) sub_menu = self.getSubMenu(menu_name) if not sub_menu: sub_menu = CategoryMenuBar() self.addCategory(menu_name, menu_name_i18n, type_, sub_menu) if item_name_i18n and menu_cmd: sub_menu.addItem(item_name_i18n, menu_cmd) def addCachedMenus(self, type_, menu_data=None): """Add cached menus to instance @param type_: menu type like is sat.core.sat_main.importMenu @param menu_data: data to send with these menus """ menus = self.host.menus.get(type_, []) for action_id, path, path_i18n in menus: if len(path) != 2: raise NotImplementedError("Menu with a path != 2 are not implemented yet") if len(path) != len(path_i18n): log.error("inconsistency between menu paths") continue callback = PluginMenuCmd(self.host, action_id, menu_data) self.addMenu(path[0], path_i18n[0], path_i18n[1], 'plugins', callback)