Mercurial > fife-parpg
comparison tools/editor/scripts/gui/menubar.py @ 378:64738befdf3b
bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author | vtchill@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Mon, 11 Jan 2010 23:34:52 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
377:fe6fb0e0ed23 | 378:64738befdf3b |
---|---|
1 # -*- coding: utf-8 -*- | |
2 | |
3 # #################################################################### | |
4 # Copyright (C) 2005-2009 by the FIFE team | |
5 # http://www.fifengine.de | |
6 # This file is part of FIFE. | |
7 # | |
8 # FIFE is free software; you can redistribute it and/or | |
9 # modify it under the terms of the GNU Lesser General Public | |
10 # License as published by the Free Software Foundation; either | |
11 # version 2.1 of the License, or (at your option) any later version. | |
12 # | |
13 # This library is distributed in the hope that it will be useful, | |
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 # Lesser General Public License for more details. | |
17 # | |
18 # You should have received a copy of the GNU Lesser General Public | |
19 # License along with this library; if not, write to the | |
20 # Free Software Foundation, Inc., | |
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 # #################################################################### | |
23 | |
24 from fife.extensions.pychan import widgets | |
25 from fife.extensions.pychan.tools import callbackWithArguments as cbwa | |
26 | |
27 import scripts.events | |
28 import scripts.gui.action | |
29 from action import Action, ActionGroup | |
30 from fife.fife import Color | |
31 from fife.extensions import fife_timer | |
32 | |
33 MENU_ICON_SIZE = 24 | |
34 | |
35 class MenuBar(widgets.HBox): | |
36 def __init__(self, *args, **kwargs): | |
37 super(MenuBar, self).__init__(*args, **kwargs) | |
38 | |
39 self.menulist = [] | |
40 self._buttonlist = [] | |
41 self.gui = None | |
42 self._buildGui() | |
43 | |
44 self._timer = fife_timer.Timer(500, self._autoHideMenu) | |
45 self._timer.start() | |
46 | |
47 def _buildGui(self): | |
48 if self.gui is not None: | |
49 self.removeChild(self.gui) | |
50 self._buttonlist = [] | |
51 | |
52 self.gui = widgets.HBox() | |
53 for i, menu in enumerate(self.menulist): | |
54 button = widgets.Button(name=menu.name, text=menu.name) | |
55 button.hexpand = 0 | |
56 button.capture(cbwa(self._showMenu, i)) | |
57 self._buttonlist.append(button) | |
58 self.gui.addChild(button) | |
59 | |
60 self.gui.addSpacer(widgets.Spacer()) | |
61 | |
62 self.addChild(self.gui) | |
63 | |
64 def _showMenu(self, i): | |
65 if self.menulist[i].isVisible(): | |
66 self.menulist[i].hide() | |
67 return | |
68 | |
69 # Hide all menus | |
70 for m in self.menulist: | |
71 m.hide() | |
72 | |
73 menu = self.menulist[i] | |
74 button = self._buttonlist[i] | |
75 | |
76 menu.x = 0 | |
77 menu.y = button.height | |
78 | |
79 # Get absolute position of button | |
80 parent = button | |
81 while parent is not None: | |
82 menu.x += parent.x | |
83 menu.y += parent.y | |
84 parent = parent.parent | |
85 | |
86 menu.show() | |
87 | |
88 def _autoHideMenu(self): | |
89 for i, m in enumerate(self.menulist): | |
90 if not m.isVisible(): continue | |
91 if self._buttonlist[i].real_widget.isFocused(): continue | |
92 if self._isMenuFocused(m) is False: | |
93 m.hide() | |
94 | |
95 def _isMenuFocused(self, widget): | |
96 if widget.real_widget.isFocused(): return True | |
97 if hasattr(widget, "children"): | |
98 for c in widget.children: | |
99 if self._isMenuFocused(c): | |
100 return True | |
101 return False | |
102 | |
103 def addMenu(self, menu): | |
104 if menu is not None and self.menulist.count(menu) <= 0: | |
105 self.menulist.append(menu) | |
106 self._buildGui() | |
107 | |
108 def insertMenu(self, menu, beforeMenu): | |
109 try: | |
110 i = self.menulist.index(beforeMenu) | |
111 self.menulist.insert(i, menu) | |
112 self._buildGui() | |
113 | |
114 except ValueError: | |
115 print "MenuBar::insertMenu:", "MenuBar does not contain specified menu." | |
116 return | |
117 | |
118 def insertMenuAt(self, menu, index): | |
119 self.menulist.insert(index, menu) | |
120 self._buildGui() | |
121 | |
122 def removeMenu(self, menu): | |
123 self.menulist.remove(menu) | |
124 self._buildGui() | |
125 | |
126 def clear(self): | |
127 self.menulist = [] | |
128 self._buildGui() | |
129 | |
130 class Menu(widgets.VBox): | |
131 def __init__(self, name=u"", icon=u"", min_width=100, min_height=15, margins=(2,2), *args, **kwargs): | |
132 super(Menu, self).__init__(*args, **kwargs) | |
133 self.min_width=min_width | |
134 self.min_height=min_height | |
135 self.margins=margins | |
136 | |
137 self.name = name | |
138 self.icon = icon | |
139 | |
140 self._actions = [] | |
141 self._actionbuttons = [] | |
142 | |
143 self._update() | |
144 | |
145 def addSeparator(self, separator=None): | |
146 self.insertSeparator(separator, len(self._actions)) | |
147 | |
148 def addAction(self, action): | |
149 self.insertAction(action, len(self._actions)) | |
150 | |
151 def removeAction(self, action): | |
152 self._actions.remove(action) | |
153 | |
154 actions = [action] | |
155 if isinstance(action, ActionGroup): | |
156 actions = action.getActions() | |
157 scripts.gui.action.changed.disconnect(self._updateActionGroup, sender=action) | |
158 | |
159 for a in actions: | |
160 for b in self._actionbuttons[:]: | |
161 if a == b.action: | |
162 self.removeChild(b) | |
163 self._actionbuttons.remove(b) | |
164 | |
165 self.adaptLayout(False) | |
166 | |
167 def hasAction(self, action): | |
168 for a in self._actions: | |
169 if a == action: return True | |
170 return False | |
171 | |
172 def insertAction(self, action, position=0, before=None): | |
173 if self.hasAction(action): | |
174 print "Action already added to toolbar" | |
175 return | |
176 | |
177 if before is not None: | |
178 position = self._actions.index(before) | |
179 | |
180 self._actions.insert(position, action) | |
181 self._insertButton(action, position) | |
182 | |
183 def _updateActionGroup(self, sender): | |
184 position = self._actions.index(sender) | |
185 self.removeAction(sender) | |
186 self.insertAction(sender, position) | |
187 self.adaptLayout(False) | |
188 | |
189 def _insertButton(self, action, position): | |
190 actions = [action] | |
191 if isinstance(action, ActionGroup): | |
192 actions = action.getActions() | |
193 scripts.gui.action.changed.connect(self._updateActionGroup, sender=action) | |
194 | |
195 if position >= 0: | |
196 actions = reversed(actions) | |
197 | |
198 # Action groups are counted as one action, add the hidde number of actions to position | |
199 for i in range(position): | |
200 if isinstance(self._actions[i], ActionGroup): | |
201 position += len(self._actions[i].getActions()) - 1 | |
202 | |
203 for a in actions: | |
204 button = MenuButton(a, name=a.text) | |
205 self.insertChild(button, position) | |
206 self._actionbuttons.insert(position, button) | |
207 | |
208 def insertSeparator(self, separator=None, position=0, before=None): | |
209 if separator==None: | |
210 separator = Action(separator=True) | |
211 self.insertAction(separator, position, before) | |
212 | |
213 def clear(self): | |
214 self.removeAllChildren() | |
215 self._actions = [] | |
216 | |
217 for i in reversed(range(len(self._actionbuttons))): | |
218 self._actionbuttons[i].removeEvents() | |
219 self._actionbuttons = [] | |
220 | |
221 def _update(self): | |
222 actions = self._actions | |
223 | |
224 self.clear() | |
225 | |
226 for action in actions: | |
227 self.addAction(action) | |
228 | |
229 self.adaptLayout(False) | |
230 | |
231 def show(self): | |
232 self._update() | |
233 super(Menu, self).show() | |
234 | |
235 class MenuButton(widgets.HBox): | |
236 def __init__(self, action, **kwargs): | |
237 self._action = action | |
238 self._widget = None | |
239 | |
240 super(MenuButton, self).__init__(**kwargs) | |
241 | |
242 self.update() | |
243 | |
244 self.initEvents() | |
245 | |
246 def initEvents(self): | |
247 # Register eventlisteners | |
248 self.capture(self._showTooltip, "mouseEntered") | |
249 self.capture(self._hideTooltip, "mouseExited") | |
250 | |
251 scripts.gui.action.changed.connect(self._actionChanged, sender=self._action) | |
252 | |
253 def removeEvents(self): | |
254 # Remove eventlisteners | |
255 self.capture(None, "mouseEntered") | |
256 self.capture(None, "mouseExited") | |
257 | |
258 scripts.gui.action.changed.disconnect(self.update, sender=self._action) | |
259 | |
260 def setAction(self, action): | |
261 self.removeEvents() | |
262 | |
263 self._action = action | |
264 self.update() | |
265 self.adaptLayout(False) | |
266 | |
267 self.initEvents() | |
268 | |
269 def getAction(self): | |
270 return self._action | |
271 action = property(getAction, setAction) | |
272 | |
273 def _showTooltip(self): | |
274 if self._action is not None and self._action.helptext != "": | |
275 scripts.editor.getEditor().getStatusBar().showTooltip(self._action.helptext) | |
276 | |
277 def _hideTooltip(self): | |
278 scripts.editor.getEditor().getStatusBar().hideTooltip() | |
279 | |
280 def _actionChanged(self): | |
281 self.update() | |
282 self.adaptLayout(False) | |
283 | |
284 def update(self): | |
285 """ Sets up the button widget """ | |
286 if self._widget != None: | |
287 self.removeChild(self._widget) | |
288 self._widget = None | |
289 | |
290 if self._action is None: | |
291 return | |
292 | |
293 widget = None | |
294 icon = None | |
295 text = None | |
296 | |
297 if self._action.isSeparator(): | |
298 widget = widgets.HBox() | |
299 widget.base_color += Color(8, 8, 8) | |
300 widget.min_size = (2, 2) | |
301 else: | |
302 hasIcon = len(self._action.icon) > 0 | |
303 | |
304 if self._action.isCheckable(): | |
305 text = widgets.ToggleButton(text=self._action.text) | |
306 text.toggled = self._action.isChecked() | |
307 text.hexpand = 1 | |
308 else: | |
309 text = widgets.Button(text=self._action.text) | |
310 text.min_size = (1, MENU_ICON_SIZE) | |
311 text.max_size = (1000, MENU_ICON_SIZE) | |
312 text.capture(self._action.activate) | |
313 | |
314 if hasIcon: | |
315 if self._action.isCheckable(): | |
316 icon = widgets.ToggleButton(hexpand=0, up_image=self._action.icon,down_image=self._action.icon,hover_image=self._action.icon,offset=(1,1)) | |
317 icon.toggled = self._action.isChecked() | |
318 else: | |
319 icon = widgets.ImageButton(hexpand=0, up_image=self._action.icon,down_image=self._action.icon,hover_image=self._action.icon,offset=(1,1)) | |
320 | |
321 else: | |
322 if self._action.isCheckable(): | |
323 icon = widgets.ToggleButton(hexpand=0, offset=(1,1)) | |
324 icon.toggled = self._action.isChecked() | |
325 else: | |
326 icon = widgets.Button(text=u"", hexpand=0, offset=(1,1)) | |
327 | |
328 icon.min_size = icon.max_size = (MENU_ICON_SIZE, MENU_ICON_SIZE) | |
329 icon.capture(self._action.activate) | |
330 | |
331 widget = widgets.HBox() | |
332 widget.addChild(icon) | |
333 widget.addChild(text) | |
334 | |
335 widget.position_technique = "left:center" | |
336 widget.hexpand = 1 | |
337 widget.vexpand = 0 | |
338 | |
339 self._widget = widget | |
340 self.addChild(self._widget) | |
341 |