8 from ...util.callback import callback, in_callback
9 from . import panel as panel
13 """A `Bind`able version of :class:`wx.Menu`.
15 From the `wxPython Style Guide`_, you can't do
16 wx.Menu().Bind(...), so we hack around it by bubbling the Bind up
17 to the closest parent :class:`wx.Frame`.
19 .. _wxPython Style Guide:
20 http://wiki.wxpython.org/wxPython%20Style%20Guide#line-101
22 def __init__(self, parent=None, **kwargs):
25 super(Menu, self).__init__(**kwargs)
27 def Bind(self, **kwargs):
28 assert 'id' in kwargs, kwargs
30 while not isinstance(obj, wx.Frame):
33 self._bindings.append(kwargs)
35 def Unbind(self, **kwargs):
36 assert 'id' in kwargs, kwargs
38 self._bindings.remove(kwargs)
41 kwargs.pop('handler', None)
43 while not isinstance(obj, wx.Frame):
47 def _unbind_all_items(self):
48 for kwargs in self._bindings:
53 class MenuBar (wx.MenuBar):
54 """A `Bind`able version of :class:`wx.MenuBar`.
56 See :class:`Menu` for the motivation.
58 def __init__(self, parent=None, **kwargs):
60 super(MenuBar, self).__init__(**kwargs)
62 def Append(self, menu, title):
64 super(MenuBar, self).Append(menu, title)
67 class FileMenu (Menu):
68 def __init__(self, callbacks=None, **kwargs):
69 super(FileMenu, self).__init__(**kwargs)
72 self._callbacks = callbacks
73 self._c = {'exit': self.Append(wx.ID_EXIT)}
74 self.Bind(event=wx.EVT_MENU, handler=self.close, id=wx.ID_EXIT)
77 def close(self, event):
81 class ViewMenu (Menu):
82 def __init__(self, callbacks=None, **kwargs):
83 super(ViewMenu, self).__init__(**kwargs)
86 self._callbacks = callbacks
88 for i,panelname in enumerate(sorted(panel.PANELS.keys())):
89 text = '%s\tF%d' % (panelname.capitalize(), i+5)
90 self._c[panelname] = self.AppendCheckItem(id=wx.ID_ANY, text=text)
91 for item in self._c.values():
93 self.Bind(event=wx.EVT_MENU, handler=self.view_panel, id=item.GetId())
95 def view_panel(self, event):
97 item = self.FindItemById(_id)
98 label = item.GetLabel()
99 selected = item.IsChecked()
100 in_callback(self, panel_name=label, visible=selected)
103 class PerspectiveMenu (Menu):
104 def __init__(self, callbacks=None, **kwargs):
105 super(PerspectiveMenu, self).__init__(**kwargs)
106 if callbacks == None:
108 self._callbacks = callbacks
111 def update(self, perspectives, selected):
112 """Rebuild the perspectives menu.
114 self._unbind_all_items()
115 for item in self.GetMenuItems():
116 self.DeleteItem(item)
118 'save': self.Append(id=wx.ID_ANY, text='Save Perspective'),
119 'delete': self.Append(id=wx.ID_ANY, text='Delete Perspective'),
121 self.Bind(event=wx.EVT_MENU, handler=self.save_perspective,
122 id=self._c['save'].GetId())
123 self.Bind(event=wx.EVT_MENU, handler=self.delete_perspective,
124 id=self._c['delete'].GetId())
125 self.AppendSeparator()
126 for label in perspectives:
127 self._c[label] = self.AppendRadioItem(id=wx.ID_ANY, text=label)
128 self.Bind(event=wx.EVT_MENU, handler=self.select_perspective,
129 id=self._c[label].GetId())
130 if label == selected:
131 self._c[label].Check(True)
134 def save_perspective(self, event):
138 def delete_perspective(self, event):
141 def select_perspective(self, event):
143 item = self.FindItemById(_id)
144 label = item.GetLabel()
145 selected = item.IsChecked()
146 assert selected == True, label
147 in_callback(self, name=label)
150 class HelpMenu (Menu):
151 def __init__(self, callbacks=None, **kwargs):
152 super(HelpMenu, self).__init__(**kwargs)
153 if callbacks == None:
155 self._callbacks = callbacks
156 self._c = {'about': self.Append(id=wx.ID_ABOUT)}
157 self.Bind(event=wx.EVT_MENU, handler=self.about, id=wx.ID_ABOUT)
160 def about(self, event):
164 class HookeMenuBar (MenuBar):
165 def __init__(self, callbacks=None, **kwargs):
166 super(HookeMenuBar, self).__init__(**kwargs)
167 if callbacks == None:
169 self._callbacks = callbacks
172 # Attach *Menu() instances
173 for key in ['file', 'view', 'perspective', 'help']:
174 cap_key = key.capitalize()
175 _class = globals()['%sMenu' % cap_key]
176 self._c[key] = _class(parent=self, callbacks=callbacks)
177 self.Append(self._c[key], cap_key)