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