1 # Copyright (C) 2010-2012 W. Trevor King <wking@tremily.us>
3 # This file is part of Hooke.
5 # Hooke is free software: you can redistribute it and/or modify it under the
6 # terms of the GNU Lesser General Public License as published by the Free
7 # Software Foundation, either version 3 of the License, or (at your option) any
10 # Hooke is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with Hooke. If not, see <http://www.gnu.org/licenses/>.
18 """Menu bar for Hooke.
23 from ...util.callback import callback, in_callback
27 """A `Bind`able version of :class:`wx.Menu`.
29 From the `wxPython Style Guide`_, you can't do
30 wx.Menu().Bind(...), so we hack around it by bubbling the Bind up
31 to the closest parent :class:`wx.Frame`.
33 .. _wxPython Style Guide:
34 http://wiki.wxpython.org/wxPython%20Style%20Guide#line-101
36 def __init__(self, parent=None, **kwargs):
39 super(Menu, self).__init__(**kwargs)
41 def Bind(self, **kwargs):
42 assert 'id' in kwargs, kwargs
44 while not isinstance(obj, wx.Frame):
47 self._bindings.append(kwargs)
49 def Unbind(self, **kwargs):
50 assert 'id' in kwargs, kwargs
52 self._bindings.remove(kwargs)
55 kwargs.pop('handler', None)
57 while not isinstance(obj, wx.Frame):
61 def _unbind_all_items(self):
62 for kwargs in self._bindings:
67 class MenuBar (wx.MenuBar):
68 """A `Bind`able version of :class:`wx.MenuBar`.
70 See :class:`Menu` for the motivation.
72 def __init__(self, parent=None, **kwargs):
74 super(MenuBar, self).__init__(**kwargs)
76 def Append(self, menu, title):
78 super(MenuBar, self).Append(menu, title)
81 class FileMenu (Menu):
82 def __init__(self, callbacks=None, **kwargs):
83 super(FileMenu, self).__init__(**kwargs)
86 self._callbacks = callbacks
87 self._c = {'exit': self.Append(wx.ID_EXIT)}
88 self.Bind(event=wx.EVT_MENU, handler=self.close, id=wx.ID_EXIT)
91 def close(self, event):
95 class ViewMenu (Menu):
96 def __init__(self, panels, callbacks=None, **kwargs):
97 super(ViewMenu, self).__init__(**kwargs)
100 self._callbacks = callbacks
102 for i,panelname in enumerate(sorted([p.managed_name for p in panels])):
103 text = '%s\tF%d' % (panelname, i+4)
104 self._c[panelname] = self.AppendCheckItem(id=wx.ID_ANY, text=text)
105 for item in self._c.values():
107 self.Bind(event=wx.EVT_MENU, handler=self.view_panel, id=item.GetId())
109 def view_panel(self, event):
111 item = self.FindItemById(_id)
112 label = item.GetLabel()
113 selected = item.IsChecked()
114 in_callback(self, panel_name=label, visible=selected)
117 class PerspectiveMenu (Menu):
118 def __init__(self, callbacks=None, **kwargs):
119 super(PerspectiveMenu, self).__init__(**kwargs)
120 if callbacks == None:
122 self._callbacks = callbacks
125 def update(self, perspectives, selected):
126 """Rebuild the perspectives menu.
128 self._unbind_all_items()
129 for item in self.GetMenuItems():
130 self.DeleteItem(item)
132 'save': self.Append(id=wx.ID_ANY, text='Save Perspective'),
133 'delete': self.Append(id=wx.ID_ANY, text='Delete Perspective'),
135 self.Bind(event=wx.EVT_MENU, handler=self.save_perspective,
136 id=self._c['save'].GetId())
137 self.Bind(event=wx.EVT_MENU, handler=self.delete_perspective,
138 id=self._c['delete'].GetId())
139 self.AppendSeparator()
140 for label in perspectives:
141 self._c[label] = self.AppendRadioItem(id=wx.ID_ANY, text=label)
142 self.Bind(event=wx.EVT_MENU, handler=self.select_perspective,
143 id=self._c[label].GetId())
144 if label == selected:
145 self._c[label].Check(True)
148 def save_perspective(self, event):
152 def delete_perspective(self, event):
155 def select_perspective(self, event):
157 item = self.FindItemById(_id)
158 label = item.GetLabel()
159 selected = item.IsChecked()
160 assert selected == True, label
161 in_callback(self, name=label)
164 class HelpMenu (Menu):
165 def __init__(self, callbacks=None, **kwargs):
166 super(HelpMenu, self).__init__(**kwargs)
167 if callbacks == None:
169 self._callbacks = callbacks
170 self._c = {'about': self.Append(id=wx.ID_ABOUT)}
171 self.Bind(event=wx.EVT_MENU, handler=self.about, id=wx.ID_ABOUT)
174 def about(self, event):
178 class HookeMenuBar (MenuBar):
179 def __init__(self, panels, callbacks=None, **kwargs):
180 super(HookeMenuBar, self).__init__(**kwargs)
181 if callbacks == None:
183 self._callbacks = callbacks
186 # Attach *Menu() instances
187 for key in ['file', 'view', 'perspective', 'help']:
188 cap_key = key.capitalize()
189 hot_key = '&' + cap_key
190 _class = globals()['%sMenu' % cap_key]
193 kwargs['panels'] = panels
194 self._c[key] = _class(parent=self, callbacks=callbacks, **kwargs)
195 self.Append(self._c[key], hot_key)