1 # Copyright (C) 2010-2012 W. Trevor King <wking@drexel.edu>
3 # This file is part of Hooke.
5 # Hooke is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU Lesser General Public License as
7 # published by the Free Software Foundation, either version 3 of the
8 # License, or (at your option) any later version.
10 # Hooke is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
13 # Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with Hooke. If not, see
17 # <http://www.gnu.org/licenses/>.
19 """Menu bar for Hooke.
24 from ...util.callback import callback, in_callback
28 """A `Bind`able version of :class:`wx.Menu`.
30 From the `wxPython Style Guide`_, you can't do
31 wx.Menu().Bind(...), so we hack around it by bubbling the Bind up
32 to the closest parent :class:`wx.Frame`.
34 .. _wxPython Style Guide:
35 http://wiki.wxpython.org/wxPython%20Style%20Guide#line-101
37 def __init__(self, parent=None, **kwargs):
40 super(Menu, self).__init__(**kwargs)
42 def Bind(self, **kwargs):
43 assert 'id' in kwargs, kwargs
45 while not isinstance(obj, wx.Frame):
48 self._bindings.append(kwargs)
50 def Unbind(self, **kwargs):
51 assert 'id' in kwargs, kwargs
53 self._bindings.remove(kwargs)
56 kwargs.pop('handler', None)
58 while not isinstance(obj, wx.Frame):
62 def _unbind_all_items(self):
63 for kwargs in self._bindings:
68 class MenuBar (wx.MenuBar):
69 """A `Bind`able version of :class:`wx.MenuBar`.
71 See :class:`Menu` for the motivation.
73 def __init__(self, parent=None, **kwargs):
75 super(MenuBar, self).__init__(**kwargs)
77 def Append(self, menu, title):
79 super(MenuBar, self).Append(menu, title)
82 class FileMenu (Menu):
83 def __init__(self, callbacks=None, **kwargs):
84 super(FileMenu, self).__init__(**kwargs)
87 self._callbacks = callbacks
88 self._c = {'exit': self.Append(wx.ID_EXIT)}
89 self.Bind(event=wx.EVT_MENU, handler=self.close, id=wx.ID_EXIT)
92 def close(self, event):
96 class ViewMenu (Menu):
97 def __init__(self, panels, callbacks=None, **kwargs):
98 super(ViewMenu, self).__init__(**kwargs)
101 self._callbacks = callbacks
103 for i,panelname in enumerate(sorted([p.managed_name for p in panels])):
104 text = '%s\tF%d' % (panelname, i+4)
105 self._c[panelname] = self.AppendCheckItem(id=wx.ID_ANY, text=text)
106 for item in self._c.values():
108 self.Bind(event=wx.EVT_MENU, handler=self.view_panel, id=item.GetId())
110 def view_panel(self, event):
112 item = self.FindItemById(_id)
113 label = item.GetLabel()
114 selected = item.IsChecked()
115 in_callback(self, panel_name=label, visible=selected)
118 class PerspectiveMenu (Menu):
119 def __init__(self, callbacks=None, **kwargs):
120 super(PerspectiveMenu, self).__init__(**kwargs)
121 if callbacks == None:
123 self._callbacks = callbacks
126 def update(self, perspectives, selected):
127 """Rebuild the perspectives menu.
129 self._unbind_all_items()
130 for item in self.GetMenuItems():
131 self.DeleteItem(item)
133 'save': self.Append(id=wx.ID_ANY, text='Save Perspective'),
134 'delete': self.Append(id=wx.ID_ANY, text='Delete Perspective'),
136 self.Bind(event=wx.EVT_MENU, handler=self.save_perspective,
137 id=self._c['save'].GetId())
138 self.Bind(event=wx.EVT_MENU, handler=self.delete_perspective,
139 id=self._c['delete'].GetId())
140 self.AppendSeparator()
141 for label in perspectives:
142 self._c[label] = self.AppendRadioItem(id=wx.ID_ANY, text=label)
143 self.Bind(event=wx.EVT_MENU, handler=self.select_perspective,
144 id=self._c[label].GetId())
145 if label == selected:
146 self._c[label].Check(True)
149 def save_perspective(self, event):
153 def delete_perspective(self, event):
156 def select_perspective(self, event):
158 item = self.FindItemById(_id)
159 label = item.GetLabel()
160 selected = item.IsChecked()
161 assert selected == True, label
162 in_callback(self, name=label)
165 class HelpMenu (Menu):
166 def __init__(self, callbacks=None, **kwargs):
167 super(HelpMenu, self).__init__(**kwargs)
168 if callbacks == None:
170 self._callbacks = callbacks
171 self._c = {'about': self.Append(id=wx.ID_ABOUT)}
172 self.Bind(event=wx.EVT_MENU, handler=self.about, id=wx.ID_ABOUT)
175 def about(self, event):
179 class HookeMenuBar (MenuBar):
180 def __init__(self, panels, callbacks=None, **kwargs):
181 super(HookeMenuBar, self).__init__(**kwargs)
182 if callbacks == None:
184 self._callbacks = callbacks
187 # Attach *Menu() instances
188 for key in ['file', 'view', 'perspective', 'help']:
189 cap_key = key.capitalize()
190 hot_key = '&' + cap_key
191 _class = globals()['%sMenu' % cap_key]
194 kwargs['panels'] = panels
195 self._c[key] = _class(parent=self, callbacks=callbacks, **kwargs)
196 self.Append(self._c[key], hot_key)