Mercurial > libervia-web
comparison 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 |
comparison
equal
deleted
inserted
replaced
493:636b6c477a87 | 494:5d8632a7bfde |
---|---|
1 #!/usr/bin/python | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Libervia: a Salut à Toi frontend | |
5 # Copyright (C) 2011, 2012, 2013, 2014 Jérôme Poisson <goffi@goffi.org> | |
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 """Base classes for building a menu. | |
22 | |
23 These classes have been moved here from menu.py because they are also used | |
24 by base_widget.py, and the import sequence caused a JS runtime error.""" | |
25 | |
26 | |
27 import pyjd # this is dummy in pyjs | |
28 from sat.core.log import getLogger | |
29 log = getLogger(__name__) | |
30 | |
31 from pyjamas.ui.MenuBar import MenuBar | |
32 from pyjamas.ui.MenuItem import MenuItem | |
33 | |
34 | |
35 class MenuCmd: | |
36 """Return an object with an "execute" method that can be set to a menu item callback""" | |
37 | |
38 def __init__(self, object_, handler): | |
39 self._object = object_ | |
40 self._handler = handler | |
41 | |
42 def execute(self): | |
43 handler = getattr(self._object, self._handler) | |
44 handler() | |
45 | |
46 | |
47 class PluginMenuCmd: | |
48 """Like MenuCmd, but instead of executing a method, it will command the bridge to launch an action""" | |
49 | |
50 def __init__(self, host, action_id, menu_data=None): | |
51 self.host = host | |
52 self.action_id = action_id | |
53 self.menu_data = menu_data | |
54 | |
55 def execute(self): | |
56 self.host.launchAction(self.action_id, self.menu_data) | |
57 | |
58 | |
59 class CategoryMenuBar(MenuBar): | |
60 """A menu bar for a category (sub menu)""" | |
61 def __init__(self): | |
62 MenuBar.__init__(self, vertical=True) | |
63 | |
64 | |
65 class CategoryItem(MenuItem): | |
66 """A category item with a non-internationalized name""" | |
67 def __init__(self, name, *args, **kwargs): | |
68 MenuItem.__init__(self, *args, **kwargs) | |
69 self.name = name | |
70 | |
71 | |
72 class GenericMenuBar(MenuBar): | |
73 | |
74 def __init__(self, host, vertical=False, **kwargs): | |
75 MenuBar.__init__(self, vertical, **kwargs) | |
76 self.host = host | |
77 self.moved_popup_style = None | |
78 | |
79 @classmethod | |
80 def getCategoryHTML(cls, type_, menu_name_i18n): | |
81 """Build from the given parameters the html to be displayed for a category item. | |
82 | |
83 Inheriting classes may overwrite this method. | |
84 @param type_ (str): category type | |
85 @param menu_name_i18n (str): internationalized category name | |
86 @return: str | |
87 """ | |
88 return menu_name_i18n | |
89 | |
90 def doItemAction(self, item, fireCommand): | |
91 """Overwrites the default behavior for the popup menu to fit in the screen""" | |
92 MenuBar.doItemAction(self, item, fireCommand) | |
93 if not self.vertical and self.popup: | |
94 # we not only move the last popup, but any which would go over the menu right extremity | |
95 most_left = self.getAbsoluteLeft() + self.getOffsetWidth() - self.popup.getOffsetWidth() | |
96 if item.getAbsoluteLeft() > most_left: | |
97 self.popup.setPopupPosition(most_left, | |
98 self.getAbsoluteTop() + | |
99 self.getOffsetHeight() - 1) | |
100 # eventually smooth the popup edges to fit the menu own style | |
101 if self.moved_popup_style: | |
102 self.popup.addStyleName(self.moved_popup_style) | |
103 | |
104 def getCategories(self): | |
105 """Return the categories items. | |
106 | |
107 @return: list[CategoryItem] | |
108 """ | |
109 return [item for item in self.items if isinstance(item, CategoryItem)] | |
110 | |
111 def getSubMenu(self, category): | |
112 """Return the popup menu for the given category | |
113 | |
114 @param category (str): category name | |
115 @return: CategoryMenuBar instance or None | |
116 """ | |
117 try: | |
118 return [item for item in self.items if isinstance(item, CategoryItem) and item.name == category][0].getSubMenu() | |
119 except IndexError: | |
120 return None | |
121 | |
122 def addSeparator(self): | |
123 """Add a separator between the categories""" | |
124 self.addItem(CategoryItem(None, text='', asHTML=None, StyleName='menuSeparator')) | |
125 | |
126 def addCategory(self, menu_name, menu_name_i18n, type_, sub_menu): | |
127 """Add a category | |
128 | |
129 @param menu_name (str): category name | |
130 @param menu_name_i18n (str): internationalized category name | |
131 @param type_ (str): category type | |
132 @param sub_menu (CategoryMenuBar): category sub-menu | |
133 """ | |
134 html = self.getCategoryHTML(type_, menu_name_i18n) | |
135 self.addItem(CategoryItem(menu_name, text=html, asHTML=True, subMenu=sub_menu)) | |
136 | |
137 def addMenu(self, menu_name, menu_name_i18n, item_name_i18n, type_, menu_cmd): | |
138 """Add a new menu item | |
139 @param menu_name (str): category name | |
140 @param menu_name_i18n (str): internationalized menu name | |
141 @param item_name_i18n (str): internationalized item name | |
142 @param type_ (str): category type in ('games', 'help', 'home', 'photos', 'plugins', 'settings', 'social') | |
143 @param menu_cmd (MenuCmd or PluginMenuCmd): instance to execute as the item callback | |
144 """ | |
145 log.info("addMenu: %s %s %s %s %s" % (menu_name, menu_name_i18n, item_name_i18n, type_, menu_cmd)) | |
146 sub_menu = self.getSubMenu(menu_name) | |
147 if not sub_menu: | |
148 sub_menu = CategoryMenuBar() | |
149 self.addCategory(menu_name, menu_name_i18n, type_, sub_menu) | |
150 if item_name_i18n and menu_cmd: | |
151 sub_menu.addItem(item_name_i18n, menu_cmd) | |
152 | |
153 def addCachedMenus(self, type_, menu_data=None): | |
154 """Add cached menus to instance | |
155 @param type_: menu type like is sat.core.sat_main.importMenu | |
156 @param menu_data: data to send with these menus | |
157 """ | |
158 menus = self.host.menus.get(type_, []) | |
159 for action_id, path, path_i18n in menus: | |
160 if len(path) != 2: | |
161 raise NotImplementedError("Menu with a path != 2 are not implemented yet") | |
162 if len(path) != len(path_i18n): | |
163 log.error("inconsistency between menu paths") | |
164 continue | |
165 callback = PluginMenuCmd(self.host, action_id, menu_data) | |
166 self.addMenu(path[0], path_i18n[0], path_i18n[1], 'plugins', callback) |