/usr/share/pyshared/PythonCard/menu.py is in python-pythoncard 0.8.2-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 | """
__version__ = "$Revision: 1.40 $"
__date__ = "$Date: 2004/12/31 20:44:09 $"
"""
import wx
import event
import component
"""
KEA 2003-08-02
Need to test adding, renaming, deleting, a menuitem or menu
once the application is running. In particular, I'm curious about
doing dynamic menus for adding Scriptlets or allowing the user
to override accelerator key bindings.
Also, probably need to refactor so that we just use wxPython methods
when possible and get rid of the extra lists and duplicate method
calls.
The exception are any name related utility routines that make it
simpler to modify menu items and menus based on name rather than
a fixed id.
Also need to make sure a wxMenu can be created for use as a popup menu
and then have it be destroyed correctly. See fpop sample.
Can debug.py have its menu handled via the new menu classes? That is
can we add the Debug menu dynamically. Maybe not because of the event
binding.
"""
class MenuSelectEvent(event.SelectEvent):
binding = wx.EVT_MENU
id = wx.wxEVT_COMMAND_MENU_SELECTED
def decorate(self, aWxEvent, source):
aWxEvent = event.Event.decorate(self, aWxEvent, source)
aWxEvent.checked = aWxEvent.IsChecked()
return aWxEvent
class MenuItem(wx.MenuItem, component.Component):
"""
A MenuItem represents one selectable item in a Menu.
A MenuItem with the name '-' is interpreted as
a separator.
"""
def __init__(self, aScriptable, aParent, aResource):
self.label = aResource.label
self.command = aResource.command
self.checkable = aResource.checkable
self.enabled = aResource.enabled
self.checked = aResource.checked
id = wx.NewId()
if aResource.label == '-':
wx.MenuItem.__init__(self, aParent, wx.ID_SEPARATOR, kind=wx.ITEM_SEPARATOR)
elif aResource.checkable:
#print aResource.label, aResource.checked, aResource.checked==True
wx.MenuItem.__init__(self, aParent, id, aResource.label, "", kind=wx.ITEM_CHECK)
# must use wxCallAfter to avoid init problems
# if this ends up causing another conflict with openBackground...
# then I guess we could drop the wxMenuItem sub-class and
# just use wxMenu.Append like we used to
if aResource.checked:
wx.CallAfter(self.Check, aResource.checked)
if not aResource.enabled:
wx.CallAfter(self.Enable, aResource.enabled)
else:
#print aResource.label
wx.MenuItem.__init__(self, aParent, id, aResource.label, "")
if not aResource.enabled:
wx.CallAfter(self.Enable, aResource.enabled)
component.Component.__init__(self, aResource)
self._bindEvents((MenuSelectEvent,), aScriptable, id)
# KEA 2004-05-06
# since the only use of id2itemMap
# is enableCommand and disableCommand
# it might make more sense to just store
# a mapping of command names to ids
aParent.parent.id2itemMap[id] = self
def _bindEvents(self, eventList, aScriptable, menuId):
## background = wx.GetTopLevelParent(self)
background = aScriptable
if wx.GetApp()._showDebugMenu:
bindUnusedEvents = True
else:
bindUnusedEvents = False
# helper variable to simplify test for whether to bind InsteadOfTypeEvents
# there is a good chance we will need to know
# which events are bound, if we want to dynamically add or remove
# events later, so go ahead and keep a reference to the list
self.boundEvents = {}
self.eventIdToHandler = {}
self.wxEventIdMap = {}
if 0:
print "\nBINDING...", self.name
for eventClass in eventList:
self.wxEventIdMap[eventClass.id] = eventClass
if issubclass(eventClass, event.CommandTypeEvent) and self.command:
handler = background.findHandler('on_' + self.command + '_command')
if not handler:
handler = background.findHandler('on_' + self.name + '_' + eventClass.name)
else:
handler = background.findHandler('on_' + self.name + '_' + eventClass.name)
if not handler:
handler = background.findHandler('on_' + eventClass.name)
if handler or bindUnusedEvents:
if not self.boundEvents.get(eventClass.binding, None):
## self.Bind(eventClass.binding, self._dispatch)
# KEA 2004-05-04
# not sure yet if there is a different way to handle the bind
# apparently we have to bind the event to the parent frame
# and I think we also need the id, need to check with Robin
background.Bind(eventClass.binding, self._dispatch, id=menuId)
self.boundEvents[eventClass.binding] = eventClass.name
if handler:
if 0:
print " binding", self.name, eventClass.name, handler.__name__, eventClass.id
#self.eventIdToHandler[eventClass.id] = handler.getFunction()
self.eventIdToHandler[eventClass.id] = handler
if 0:
print "\n boundEvents:"
for name in self.boundEvents.values():
print " ", name
print "\n\n"
print "\n self.eventIdToHandler:"
for id in self.eventIdToHandler:
# KEA 2004-05-02
# change to just using the method directly, Handler class not needed
#print " ", id, self.eventIdToHandler[id]._function
print " ", id, self.eventIdToHandler[id]
print "\n\n"
def _dispatch(self, aWxEvent):
eventType = aWxEvent.GetEventType()
# KEA 2004-05-04
# for a menu item this event will always be the same
# so this is redundant unless there is some binding other than
# EVT_MENU that we're going to support?!
eventClass = self.wxEventIdMap[eventType]
eventClassInstance = eventClass()
# decorate will add the relevant event attributes
aWxEvent = eventClassInstance.decorate(aWxEvent, self)
if self.command and isinstance(eventClassInstance, event.CommandTypeEvent):
# need to report the name for the handler if it exists
eventName = 'command ' + self.command
else:
if isinstance(eventClassInstance, event.InsteadOfTypeEvent):
# changes eventType if needed
# e.g. mouseDrag instead of mouseMove
eventType = eventClassInstance.translateEventType(aWxEvent)
eventName = self.wxEventIdMap[eventType].name
# cleanup
eventClass = None
eventClassInstance = None
handler = self.eventIdToHandler.get(eventType, None)
if handler:
event.EventLog.getInstance().log(eventName, self.name, True)
if 0:
print "dispatching", handler.__name__
# make a lowercase alias
aWxEvent.skip = aWxEvent.Skip
# KEA 2004-05-04
# the menu events are always bound to the parent frame
# so the target of the event will be the "background"
# KEA 2004-05-05
# it looks like WXMAC might be broken since GetEventObject
# is returning the menu item, not the frame the event was
# bound to
if wx.Platform in ('__WXGTK__', '__WXMAC__'):
background = aWxEvent.GetEventObject().parent.parent
else:
# KEA 2004-05-05
# it looks like Windows is actually the busted platform
# this time
# if we end up caching the handlers as bound methods
# then I guess this kind of problem would go away because
# we won't have to supply the first arg "self"
background = aWxEvent.GetEventObject()
## background = wx.GetTopLevelParent(self)
handler(background, aWxEvent)
# do we have to clean up this alias?
aWxEvent.skip = None
# how about this local reference to handler?
handler = None
background = None
else:
event.EventLog.getInstance().log(eventName, self.name, False)
# hopefully this is all we need to do for "unused events"
aWxEvent.Skip()
# cleanup
aWxEvent.target = aWxEvent.eventObject = None
def _getName( self ) :
return self.name
def getLabel( self ) :
return self.label
def getCommand( self ) :
return self.command
def getCheckable( self ) :
return self.checkable
def getEnabled( self ) :
return self.enabled
def getChecked( self ) :
return self.checked
def setName( self, aString ) :
self.name = aString
def setLabel( self, aString ) :
self.label = aString
def setCommand( self, aString ) :
self.command = aString
def __repr__( self ) :
return 'MenuItem=' + str( self.__dict__ )
class Menu(wx.Menu):
"""
A Menu contains 0..n MenuItem objects.
"""
def __init__(self, aParent, aResource):
wx.Menu.__init__(self)
self.parent = aParent
self.name = aResource.name
self.label = aResource.label
self.enabled = aResource.enabled
self.items = []
for itemRsrc in aResource.items:
menuItem = MenuItem(aParent.parent, self, itemRsrc)
self.appendMenuItem(menuItem)
def _getName( self ) :
return self.name
def getLabel( self ) :
return self.label
def getEnabled( self ) :
return self.enabled
def appendMenuItem(self, aMenuItem):
# self.items is for backwards compatability
self.items.append(aMenuItem)
self.AppendItem(aMenuItem)
def insertMenuItem( self, aMenuItem, aIndex ) :
pass
def deleteMenuItem( self, aName ) :
pass
def getMenuItem( self, aName ) :
pass
def getMenuItemByIndex( self, aIndex ) :
pass
def enable( self ) :
pass
def disable( self ) :
pass
def getMenuItems( self ) :
return self.items
def __repr__( self ) :
return 'Menu=' + str( self.__dict__ )
class MenuBar(wx.MenuBar):
def __init__(self, aParent, aMenuBarRsrc):
wx.MenuBar.__init__(self)
self.parent = aParent
self.menus = []
#self.parseMenus(aParent, aMenuBarRsrc.menus)
self.id2itemMap = {}
enabledMenus = []
#menus = self.getMenus()
# KEA 2003-08-02
# menus probably needs to be a UserList subclass
# so that menus can be treated as a Python list, but
# automatically do wxMenuBar.Append... as needed
# alternatively, the helper methods
# would just get ids and such dynamically from the menubar
# using wxPython methods
for menuRsrc in aMenuBarRsrc.menus:
menu = Menu(self, menuRsrc)
self.menus.append(menu)
self.Append(menu, menu.getLabel())
enabledMenus.append(menu.getEnabled())
aParent.SetMenuBar(self)
# this is a complete hack because we don't have the id of the Menu
for i in range(0, len(enabledMenus)):
if not enabledMenus[i]:
self.EnableTop(i, 0)
def __repr__(self):
return 'MenuBar=' + str(self.__dict__)
def appendMenu( self, aMenu ) :
pass
def insertMenu( self, aMenu, aIndex ) :
pass
def deleteMenu( self, aName ) :
pass
def getMenu( self, aName ) :
pass
def getMenuByIndex( self, aIndex ) :
pass
def getMenuId(self, aString):
id = -1
for m in self.menus:
menuLabel = m.label.replace('&', '')
if m.name == aString:
id = self.FindMenu(menuLabel)
break
for mi in m.items:
if mi.name == aString:
menuItemLabel = mi.label.split('\t')[0].replace('&', '')
if menuItemLabel == 'Exit' and wx.Platform == '__WXMAC__':
# KEA 2004-09-14
# I think this is the only label WXMAC changes
# but I wonder if this won't work for other languages?!
# maybe the Quit menu item would always have the same id?
menuItemLabel = 'Quit'
id = self.FindMenuItem(menuLabel, menuItemLabel)
break
return id
# KEA 2004-04-07
# Rowland suggests that the methods below be separated for release 0.8
# so that separate methods are used for menus and menu items
def getChecked( self, aString):
id = self.getMenuId(aString)
if id == -1:
# KEA 2004-04-07
# should we throw an exception here to indicate the menu/menu item wasn't found?
return -1
else:
return self.IsChecked(id)
def getEnabled( self, aString):
id = self.getMenuId(aString)
if id == -1:
# KEA 2004-04-07
# should we throw an exception here to indicate the menu/menu item wasn't found?
return -1
else:
return self.IsEnabled(id)
def setChecked( self, aString, aBoolean=True):
# KEA 2004-04-07
# if aString is a menu name instead of a menuItem name
# and there is a match then an exception will be thrown below
# when Check is called
id = self.getMenuId(aString)
if id == -1:
# KEA 2004-04-07
# should we throw an exception here to indicate the
# menu/menu item wasn't found instead of failing silently?
pass
else:
self.Check(id, aBoolean)
def setEnabled( self, aString, aBoolean=1) :
i = 0
for m in self.menus:
menuLabel = m.label.strip('&')
if m.name == aString:
self.EnableTop(i, aBoolean)
break
for mi in m.items:
if mi.name == aString:
menuItemLabel = mi.label.split('\t')[0].strip('&')
id = self.FindMenuItem(menuLabel, menuItemLabel)
self.Enable(id, aBoolean)
break
i += 1
def getMenus( self ) :
return self.menus
def enableCommand(self, aString, aBoolean=True):
for item in self.id2itemMap.itervalues():
if item.command == aString :
self.Enable(item.GetId(), aBoolean)
def disableCommand(self, aString):
self.enableCommand(aString, False)
# Unit Test
if __name__ == '__main__' :
import sys
import resource
r = resource.ResourceFile(sys.argv[1]).getResource()
|