ViewMenu now works with new gui layout
[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             self.Bind(event=wx.EVT_MENU, handler=self.view_panel, id=item.GetId())
75
76     def view_panel(self, event):
77         _id = event.GetId()
78         item = self.FindItemById(_id)
79         label = item.GetLabel()
80         selected = item.IsChecked()
81         in_callback(self, panel_name=label, visible=selected)
82
83
84 class PerspectiveMenu (Menu):
85     def __init__(self, callbacks=None, **kwargs):
86         super(PerspectiveMenu, self).__init__(**kwargs)
87         if callbacks == None:
88             callbacks = {}
89         self._callbacks = callbacks
90         self._c = {}
91
92     def update(self, perspectives, selected, callback):
93         """Rebuild the perspectives menu.
94         """
95         for item in self.GetMenuItems():
96             self.UnBind(item.GetId)
97             self.DeleteItem(item)
98         self._c = {
99             'save': self.Append(id=wx.ID_ANY, text='Save Perspective'),
100             'delete': self.Append(id=wx.ID_ANY, text='Delete Perspective'),
101             }
102         self.AppendSeparator()
103         for label in perspectives:
104             self._c[label] = self.AppendRadioItem(id=wx.ID_ANY, text=label)
105             self.Bind(event=wx.EVT_MENU, handler=callback,
106                       id=self._c[label].GetId())
107             if label == selected:
108                 self._c[label].Check(True)
109
110
111 class HelpMenu (Menu):
112     def __init__(self, callbacks=None, **kwargs):
113         super(HelpMenu, self).__init__(**kwargs)
114         if callbacks == None:
115             callbacks = {}
116         self._callbacks = callbacks
117         self._c = {'about': self.Append(id=wx.ID_ABOUT)}
118         self.Bind(event=wx.EVT_MENU, handler=self.about, id=wx.ID_ABOUT)
119
120     @callback
121     def about(self, event):
122         pass
123
124
125 class HookeMenuBar (MenuBar):
126     def __init__(self, callbacks=None, **kwargs):
127         super(HookeMenuBar, self).__init__(**kwargs)
128         if callbacks == None:
129             callbacks = {}
130         self._callbacks = callbacks
131         self._c = {}
132
133         # Attach *Menu() instances
134         for key in ['file', 'view', 'perspective', 'help']:
135             cap_key = key.capitalize()
136             _class = globals()['%sMenu' % cap_key]
137             self._c[key] = _class(parent=self, callbacks=callbacks)
138             self.Append(self._c[key], cap_key)