hooke.ui.gui was getting complicated, so I stripped it down for a moment.
[hooke.git] / hooke / ui / gui / menu.py
1 # Copyright
2
3 """Menu bar for Hooke.
4 """
5
6 import wx
7
8 from ...util.callback import callback, in_callback
9 from . import panel as panel
10
11
12 class Menu (wx.Menu):
13     """A `Bind`able version of :class:`wx.Menu`.
14
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`.
18
19     .. _wxPython Style Guide:
20       http://wiki.wxpython.org/wxPython%20Style%20Guide#line-101
21     """
22     def __init__(self, parent=None, **kwargs):
23         self._parent = parent
24         super(Menu, self).__init__(**kwargs)
25
26     def Bind(self, **kwargs):
27         assert 'id' in kwargs, kwargs
28         obj = self
29         while not isinstance(obj, wx.Frame):
30             obj = obj._parent
31         obj.Bind(**kwargs)
32
33
34 class MenuBar (wx.MenuBar):
35     """A `Bind`able version of :class:`wx.MenuBar`.
36
37     See :class:`Menu` for the motivation.
38     """
39     def __init__(self, parent=None, **kwargs):
40         self._parent = parent
41         super(MenuBar, self).__init__(**kwargs)
42
43     def Append(self, menu, title):
44         menu._parent = self
45         super(MenuBar, self).Append(menu, title)
46
47
48 class FileMenu (Menu):
49     def __init__(self, callbacks=None, **kwargs):
50         super(FileMenu, self).__init__(**kwargs)
51         if callbacks == None:
52             callbacks = {}
53         self._callbacks = callbacks
54         self._c = {'exit': self.Append(wx.ID_EXIT)}
55         self.Bind(event=wx.EVT_MENU, handler=self.close, id=wx.ID_EXIT)
56
57     @callback
58     def close(self, event):
59         pass
60
61
62 class ViewMenu (Menu):
63     def __init__(self, callbacks=None, **kwargs):
64         super(ViewMenu, self).__init__(**kwargs)
65         if callbacks == None:
66             callbacks = {}
67         self._callbacks = callbacks
68         self._c = {}
69         for i,panelname in enumerate(sorted(panel.PANELS.keys())):
70             text = '%s\tF%d' % (panelname.capitalize, i+5)
71             self._c[panelname] = self.AppendCheckItem(id=wx.ID_ANY, text=text)
72         for item in self._c.values():
73             item.Check()
74
75
76 class PerspectiveMenu (Menu):
77     def __init__(self, callbacks=None, **kwargs):
78         super(PerspectiveMenu, self).__init__(**kwargs)
79         if callbacks == None:
80             callbacks = {}
81         self._callbacks = callbacks
82         self._c = {}
83
84     def update(self, perspectives, selected, callback):
85         """Rebuild the perspectives menu.
86         """
87         for item in self.GetMenuItems():
88             self.UnBind(item.GetId)
89             self.DeleteItem(item)
90         self._c = {
91             'save': self.Append(id=wx.ID_ANY, text='Save Perspective'),
92             'delete': self.Append(id=wx.ID_ANY, text='Delete Perspective'),
93             }
94         self.AppendSeparator()
95         for label in perspectives:
96             self._c[label] = self.AppendRadioItem(id=wx.ID_ANY, text=label)
97             self.Bind(event=wx.EVT_MENU, handler=callback,
98                       id=self._c[label].GetId())
99             if label == selected:
100                 self._c[label].Check(True)
101
102
103 class HelpMenu (Menu):
104     def __init__(self, callbacks=None, **kwargs):
105         super(HelpMenu, self).__init__(**kwargs)
106         if callbacks == None:
107             callbacks = {}
108         self._callbacks = callbacks
109         self._c = {'about': self.Append(id=wx.ID_ABOUT)}
110         self.Bind(event=wx.EVT_MENU, handler=self.about, id=wx.ID_ABOUT)
111
112     @callback
113     def about(self, event):
114         pass
115
116
117 class HookeMenuBar (MenuBar):
118     def __init__(self, callbacks=None, **kwargs):
119         super(HookeMenuBar, self).__init__(**kwargs)
120         if callbacks == None:
121             callbacks = {}
122         self._callbacks = callbacks
123         self._c = {}
124
125         # Attach *Menu() instances
126         for key in ['file', 'view', 'perspective', 'help']:
127             cap_key = key.capitalize()
128             _class = globals()['%sMenu' % cap_key]
129             self._c[key] = _class(parent=self, callbacks=callbacks)
130             self.Append(self._c[key], cap_key)