1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
# menu.py
import wx
import waxyobject
import string
class Menu(wx.Menu, waxyobject.WaxyObject):
def __init__(self, parent, autoevents=1):
wx.Menu.__init__(self)
self.parent = parent # necessary for hooking up events
self.autoevents = autoevents
def Append(self, title, event=None, tooltip="", type="", hotkey=""):
# Note: the order is different from wx.Menu.Append!
style = 0
style |= {
"r": wx.ITEM_RADIO,
"c": wx.ITEM_CHECK,
}.get(type.lower()[:1], wx.ITEM_NORMAL)
if hotkey:
title = title + "\t" + hotkey
id = wx.NewId()
item = wx.Menu.Append(self, id, title, tooltip, style)
if event:
# you *can* choose to specify no event, but that doesn't seem very
# useful
wx.EVT_MENU(self.parent, id, event)
elif self.autoevents:
wx.EVT_MENU(self.parent, id, self.HandleAutoEvent)
return item
def AppendMenu(self, title, menu):
id = wx.NewId()
return wx.Menu.AppendMenu(self, id, title, menu)
# I suppose there's room for an event here, but why bother...?
def GetItem(self, title):
""" Find item by title, bypassing the internal id. """
id = self.FindItem(title)
item = self.FindItemById(id)
return item
def Delete(self, obj):
# according to the wxWindows reference, wx.Menu.Delete() also accepts
# MenuItems... but apparently that isn't true, at least not in wxPython.
# So let's fix it:
if isinstance(obj, wx.MenuItem):
id = obj.GetId()
return wx.Menu.Delete(self, id)
else:
# assume it's a number
return wx.Menu.Delete(self, obj)
def HandleAutoEvent(self, event):
id = event.GetId()
menuitem = self.FindItemById(id)
def GetFullTitle(id):
menubar = self.parent.GetMenuBar()
if menubar:
for mwitem in menubar.Walk():
if mwitem.items and mwitem.items[-1].GetId() == id:
title = mwitem.name
for menuitem in mwitem.items:
title = title + " " + menuitem.GetLabel()
return title
return None
title = GetFullTitle(id)
if title:
methodname = "Menu_" + genmethodname(title)
#print "Looking for:", methodname
if hasattr(self.parent, methodname):
f = getattr(self.parent, methodname)
f(event)
# these aliases make sense...
Add = Append
AddMenu = AppendMenu
def Walk(self):
for menuitem in self.GetMenuItems():
yield [menuitem]
submenu = menuitem.GetSubMenu()
if submenu:
for subitem in submenu.Walk():
yield [menuitem] + subitem
# TODO: Is it possible to write a better GetTitle() or GetRealTitle()
# or something, that gives us the actual label of the menu?
class MenuBar(wx.MenuBar, waxobject.WaxObject):
def __init__(self, parent=None, *args, **kwargs):
wx.MenuBar.__init__(self, *args, **kwargs)
if parent: parent.SetMenuBar(self)
def Append(self, menu, text):
wx.MenuBar.Append(self, menu, text)
def Walk(self):
for i in range(self.GetMenuCount()):
menu = self.GetMenu(i)
for items in menu.Walk():
menuwalkitem = _MenuWalkItem()
menuwalkitem.name = self.GetLabelTop(i)
menuwalkitem.menu = menu
menuwalkitem.items = items
yield menuwalkitem
class _MenuWalkItem:
pass
#
# auxiliary methods
def genmethodname(title):
allowed = string.letters + string.digits + "_"
name = ""
for char in title:
if char in allowed:
name = name + char
elif char == ' ':
name = name + '_'
return name
|