home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 October / maximum-cd-2011-10.iso / DiscContents / digsby_setup.exe / lib / gui / uberwidgets / umenu.pyo (.txt) < prev   
Encoding:
Python Compiled Bytecode  |  2011-06-22  |  44.7 KB  |  1,378 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. from gui.skin.skinobjects import SkinColor
  6. import wx
  7. from wx import RectPS, Rect, ITEM_NORMAL, ITEM_SEPARATOR, ITEM_CHECK, ITEM_RADIO, Point, ALIGN_CENTER_VERTICAL, FindWindowAtPoint, MenuItem, CallLater, FindWindowAtPointer, GetMousePosition, wxEVT_MOTION, StockCursor, CURSOR_DEFAULT, GetMouseState, Window
  8. from wx import PyCommandEvent, wxEVT_MENU_OPEN
  9. from gui import skin
  10. from traceback import print_exc
  11. from gui.textutil import default_font
  12. from gui.windowfx import fadein
  13. from gui.vlist.skinvlist import SkinVListBox
  14. from gui.uberwidgets.UberButton import UberButton
  15. from gui.skin.skinobjects import Margins
  16. from gui.uberwidgets.skinnedpanel import SkinnedPanel
  17. from gui.uberwidgets.keycatcher import KeyCatcher
  18. from cgui import SplitImage4
  19. from gui.toolbox import Monitor
  20. import config
  21. from util import traceguard, memoize, Storage as S, InstanceTracker
  22. from util.primitives.funcs import Delegate
  23. from common import prefprop
  24. from weakref import ref
  25. from logging import getLogger
  26. log = getLogger('umenu')
  27. wxMSW = 'wxMSW' in wx.PlatformInfo
  28. WM_INITMENUPOPUP = 279
  29.  
  30. def MenuItem_repr(item):
  31.     text = None if item.IsSeparator() else item.Label
  32.     return '<%s %s>' % (item.__class__.__name__, text)
  33.  
  34. MenuItem.__repr__ = MenuItem_repr
  35. del MenuItem_repr
  36.  
  37. MenuItem.SetCallback = lambda item, callback: item.Menu.SetCallback(item.Id, callback)
  38. if wxMSW:
  39.     from ctypes import windll
  40.     ReleaseCapture_win32 = windll.user32.ReleaseCapture
  41.  
  42.  
  43. class UMenuTrayTimer(wx.Timer):
  44.     
  45.     def __init__(self, umenu):
  46.         wx.Timer.__init__(self)
  47.         self.umenu = umenu
  48.  
  49.     
  50.     def Notify(self):
  51.         
  52.         try:
  53.             mp = GetMousePosition()
  54.             ms = GetMouseState()
  55.         except Exception:
  56.             return None
  57.  
  58.         if not ms.LeftDown() and ms.RightDown() or ms.MiddleDown():
  59.             return None
  60.         menu = self.umenu
  61.         while menu != None:
  62.             if menu.ScreenRect.Contains(mp):
  63.                 return None
  64.             submenu = menu.menu._childmenu
  65.             menu = menu.ScreenRect.Contains(mp) if submenu is not None else None
  66.             continue
  67.             ms.MiddleDown()
  68.         self.Stop()
  69.         self.umenu.Dismiss()
  70.  
  71.  
  72.  
  73. class UMenu(wx.Menu, InstanceTracker):
  74.     last_menu = None
  75.     
  76.     def __init__(self, parent, label = '', id = None, onshow = None, windowless = None):
  77.         if not isinstance(parent, wx.WindowClass):
  78.             raise TypeError('UMenu parent must be a wx.Window')
  79.         isinstance(parent, wx.WindowClass)
  80.         wx.Menu.__init__(self, label)
  81.         InstanceTracker.track(self)
  82.         if not isinstance(id, (int, type(None))):
  83.             raise TypeError
  84.         isinstance(id, (int, type(None)))
  85.         self._parentmenu = None
  86.         self._childmenu = None
  87.         self.Id = None if id is None else id
  88.         self._window = ref(parent)
  89.         self.OnDismiss = Delegate()
  90.         self.cbs = { }
  91.         if onshow is not None:
  92.             self.Handler.AddShowCallback(self.Id, (lambda menu = (ref(self),): onshow(menu())))
  93.         
  94.         if wxMSW:
  95.             self.Handler.hwndMap[self.HMenu] = self
  96.         
  97.         self.Windowless = windowless
  98.         self.UpdateSkin()
  99.  
  100.     
  101.     def Window(self):
  102.         return self._window()
  103.  
  104.     Window = property(Window)
  105.     
  106.     def SetWindowless(self, val):
  107.         self._windowless = val
  108.  
  109.     
  110.     def GetWindowless(self):
  111.         if self._parentmenu:
  112.             return self._parentmenu.Windowless
  113.         return self._windowless
  114.  
  115.     Windowless = property(GetWindowless, SetWindowless)
  116.     
  117.     def IsShown(self):
  118.         if not (self.popup) or wx.IsDestroyed(self.popup):
  119.             return False
  120.         
  121.         try:
  122.             return self.popup.IsShown()
  123.         except AttributeError:
  124.             wx.IsDestroyed(self.popup)
  125.             wx.IsDestroyed(self.popup)
  126.             return False
  127.  
  128.  
  129.     
  130.     def UpdateSkin(self):
  131.         mbskin = skin.get('MenuBar', None)
  132.         if 'wxMac' in wx.PlatformInfo and not mbskin and mbskin.get('menuskin', None) is None or mbskin.get('mode', 'skin').lower() == 'native':
  133.             self.skin = S(native = True)
  134.             native = True
  135.         else:
  136.             self.skin = skin.get(mbskin.menuskin)
  137.             native = False
  138.             self.skin.native = False
  139.         if not native and not hasattr(self, 'popup'):
  140.             self.popup = MenuPopupWindow(self.Window, self)
  141.         elif not native:
  142.             self.popup.UpdateSkin()
  143.             self.popup.vlist.UpdateSkin()
  144.         elif native:
  145.             if hasattr(self, 'popup'):
  146.                 self.popup.Destroy()
  147.                 del self.popup
  148.             
  149.         
  150.  
  151.     
  152.     def Display(self, caller = None):
  153.         self.PopupMenu(caller.ScreenRect)
  154.  
  155.     
  156.     def dismiss_old(self):
  157.         menuref = UMenu.last_menu
  158.         if menuref is None:
  159.             return None
  160.         menu = menuref()
  161.         if menu is not None and not wx.IsDestroyed(menu):
  162.             menu.Dismiss()
  163.         
  164.         UMenu.last_menu = None
  165.  
  166.     
  167.     def PopupMenu(self, pos = None, submenu = False, event = None):
  168.         if not submenu:
  169.             self.dismiss_old()
  170.         
  171.         if event is not None:
  172.             event.Skip(False)
  173.             self._set_menu_event(event)
  174.         
  175.         if 'wxMSW' in wx.PlatformInfo and self.Windowless:
  176.             _smokeFrame = _smokeFrame
  177.             import gui.native.win.wineffects
  178.             if _smokeFrame:
  179.                 _smokeFrame.SetFocus()
  180.             
  181.         
  182.         self._menuevent = event
  183.         
  184.         try:
  185.             onshow = self._onshow
  186.         except AttributeError:
  187.             pass
  188.         else:
  189.             onshow(self)
  190.         finally:
  191.             del self._menuevent
  192.  
  193.         traceguard.__enter__()
  194.         
  195.         try:
  196.             return popup(pos)
  197.         finally:
  198.             pass
  199.  
  200.  
  201.     
  202.     def Dismiss(self):
  203.         if not self.skin.get('native', False) and not wx.IsDestroyed(self.popup):
  204.             return self.popup.vlist.Dismiss()
  205.  
  206.     if wxMSW:
  207.         if hasattr(wx.Menu, 'GetHMenu'):
  208.             GetHMenu = wx.Menu.GetHMenu
  209.         else:
  210.             
  211.             def GetHMenu(self):
  212.                 cast = cast
  213.                 POINTER = POINTER
  214.                 c_long = c_long
  215.                 import ctypes
  216.                 p = cast(int(self.this), POINTER(c_long))
  217.                 return p[25]
  218.  
  219.         HMenu = property(GetHMenu)
  220.     
  221.     
  222.     def AddItem(self, text = '', bitmap = None, callback = None, id = -1):
  223.         return self._additem(text, bitmap, callback, id = id)
  224.  
  225.     
  226.     def AddItemAt(self, position, text = '', bitmap = None, callback = None, id = -1):
  227.         return self._additem(text, bitmap, callback, id = id, position = position)
  228.  
  229.     
  230.     def Append(self, id, text, bitmap = None, callback = None):
  231.         return self._additem(text, bitmap, callback, id = id)
  232.  
  233.     
  234.     def AddCheckItem(self, text, callback = None, id = -1):
  235.         return self._additem(text, callback = callback, kind = ITEM_CHECK, id = id)
  236.  
  237.     
  238.     def AddRadioItem(self, text, callback = None):
  239.         return self._additem(text, callback = callback, kind = ITEM_RADIO)
  240.  
  241.     
  242.     def AddPrefCheck(self, pref, text, help = '', updatenow = True):
  243.         profile = profile
  244.         import common
  245.         prefs = profile.prefs
  246.         
  247.         def callback():
  248.             prefs[pref] = not prefs[pref]
  249.  
  250.         item = self._additem(text, callback = callback, kind = ITEM_CHECK)
  251.         prefs.link((pref,), (lambda val: item.Check(val)), obj = self)
  252.         return item
  253.  
  254.     
  255.     def AppendLazyMenu(self, name, callback, bitmap = None):
  256.         if not callable(callback):
  257.             raise TypeError, repr(callback)
  258.         callable(callback)
  259.         menu = UMenu(self.Window)
  260.         return self.AddSubMenu(menu, name, bitmap = bitmap, onshow = (lambda menu = (menu,): callback(menu)))
  261.  
  262.     
  263.     def _additem(self, text, bitmap = None, callback = None, kind = ITEM_NORMAL, id = -1, position = None):
  264.         item = MenuItem(self, id, text, kind = kind)
  265.         id = item.Id
  266.         if bitmap is not None:
  267.             self.SetItemBitmap(item, bitmap)
  268.         
  269.         if callback is not None:
  270.             self.SetCallback(id, callback)
  271.         
  272.         if position is None:
  273.             return self.AppendItem(item)
  274.         return self.InsertItem(position, item)
  275.  
  276.     
  277.     def SetCallback(self, id, callback):
  278.         
  279.         callback = lambda cb = (callback,): self._refresh_callback(cb)
  280.         self.cbs[id] = callback
  281.         self.Handler.AddCallback(id, callback)
  282.  
  283.     
  284.     def _refresh_callback(self, cb):
  285.         m = self._parentmenu
  286.         if m is None:
  287.             m = self
  288.         else:
  289.             while m._parentmenu:
  290.                 m = m._parentmenu
  291.         if hasattr(m, '_button'):
  292.             if wx.IsDestroyed(m._button):
  293.                 del m._button
  294.             else:
  295.                 m._button.Refresh()
  296.                 m._button.Update()
  297.         
  298.         self.Window.Refresh()
  299.         self.Window.Update()
  300.         return cb()
  301.  
  302.     
  303.     def AddSubMenu(self, submenu, label, bitmap = None, onshow = None):
  304.         submenu._parentmenu = self
  305.         if onshow is not None:
  306.             self.Handler.AddShowCallback(submenu.Id, onshow)
  307.         
  308.         item = self.AppendSubMenu(submenu, label)
  309.         if bitmap is not None:
  310.             self.SetItemBitmap(item, bitmap)
  311.         
  312.         return item
  313.  
  314.     
  315.     def SetItemBitmap(self, item, bitmap):
  316.         if self.skin.native and bitmap.Ok():
  317.             bitmap = bitmap.ResizedSmaller(16)
  318.         
  319.         item.SetBitmap(bitmap)
  320.  
  321.     
  322.     def AddSep(self):
  323.         return self.AppendItem(MenuItem(self))
  324.  
  325.     
  326.     def AddSepAt(self, i):
  327.         return self.InsertItem(i, MenuItem(self))
  328.  
  329.     
  330.     def RemoveItems(self, items):
  331.         return [ self.RemoveItem(item) for item in items ]
  332.  
  333.     
  334.     def RemoveAll(self):
  335.         return self.RemoveItems(list(self))
  336.  
  337.     
  338.     def DestroyAll(self):
  339.         for item in self.RemoveAll():
  340.             item.Destroy()
  341.         
  342.  
  343.     
  344.     def GetItemById(self, id):
  345.         for i, myitem in enumerate(self):
  346.             if myitem.Id == id:
  347.                 return myitem
  348.         
  349.  
  350.     
  351.     def IndexOf(self, item):
  352.         id = item.Id
  353.         for i, myitem in enumerate(self):
  354.             if myitem.Id == id:
  355.                 return i
  356.         
  357.         return -1
  358.  
  359.     
  360.     def Break(self):
  361.         raise NotImplementedError('skinned menus cannot break')
  362.  
  363.     
  364.     def Top(self):
  365.         w = self.Window
  366.         while not isinstance(w, wx.TopLevelWindow):
  367.             
  368.             try:
  369.                 w = getattr(w, 'Window', getattr(w, 'ParentWindow', w.Parent))
  370.             continue
  371.             except AttributeError:
  372.                 print '***', w, '***'
  373.                 raise 
  374.                 continue
  375.             
  376.  
  377.             None<EXCEPTION MATCH>AttributeError
  378.         return w
  379.  
  380.     Top = property(Top)
  381.     
  382.     def Handler(self):
  383.         return menuEventHandler(self.Top)
  384.  
  385.     Handler = property(Handler)
  386.     
  387.     def _activate_item(self, item):
  388.         return self.popup.vlist._activate_item(item)
  389.  
  390.     
  391.     def __iter__(self):
  392.         return iter(self.GetMenuItems())
  393.  
  394.     
  395.     def __getitem__(self, n):
  396.         return self.GetMenuItems()[n % len(self)]
  397.  
  398.     
  399.     def __len__(self):
  400.         return self.GetMenuItemCount()
  401.  
  402.     
  403.     def __contains__(self, item):
  404.         return (any,)((lambda .0: for i in .0:
  405. i.Id == item.Id)(self))
  406.  
  407.     
  408.     def __repr__(self):
  409.         return '<%s %r>' % (self.__class__.__name__, self.Title)
  410.  
  411.     
  412.     def __enter__(self):
  413.         self.RemoveAll()
  414.         return self
  415.  
  416.     
  417.     def __exit__(self, exc, value, tb):
  418.         if exc is None:
  419.             self.PopupMenu()
  420.         
  421.  
  422.     
  423.     def _set_menu_event(self, e):
  424.         self._menu_event = ref(e)
  425.  
  426.     
  427.     def Reuse(parent, attr = 'menu', event = None):
  428.         
  429.         try:
  430.             menu = getattr(parent, attr)
  431.         except AttributeError:
  432.             menu = UMenu(parent)
  433.             setattr(parent, attr, menu)
  434.  
  435.         menu._set_menu_event(event)
  436.         return menu
  437.  
  438.     Reuse = staticmethod(Reuse)
  439.  
  440.  
  441. class UMenuBar(wx.MenuBar):
  442.     
  443.     def __init__(self, parent, skinkey = 'MenuBar'):
  444.         wx.MenuBar.__init__(self)
  445.         self.toptitles = { }
  446.         self.skinkey = skinkey
  447.         self.accelremoves = Delegate()
  448.         self.panel = SkinnedPanel(parent, 'MenuBar')
  449.         self.panel.UpdateSkin = self.UpdateSkin
  450.         self.panel.Hide()
  451.         self.UpdateSkin()
  452.  
  453.     
  454.     def UpdateSkin(self):
  455.         s = self.skin = skin.get(self.skinkey)
  456.         if not s.get('mode', 'skin').lower() == 'native':
  457.             pass
  458.         self.native = 'wxMac' in wx.PlatformInfo
  459.         if not hasattr(self, 'panel'):
  460.             return None
  461.  
  462.     
  463.     def Append(self, menu, title, onshow = None):
  464.         self.toptitles[menu] = title
  465.         i = wx.MenuBar.Append(self, menu, title)
  466.         if not self.native:
  467.             self._constructSkinElements()
  468.         
  469.         if onshow is not None:
  470.             self.Handler.AddShowCallback(menu.Id, (lambda menu = (menu,): onshow(menu)))
  471.         
  472.         return i
  473.  
  474.     
  475.     def _constructSkinElements(self):
  476.         s = self.skin
  477.         p = self.panel
  478.         p.bg = s.get('background', SkinColor(wx.WHITE))
  479.         pad = p.padding = s.get('padding', wx.Point(0, 0))
  480.         for child in list(p.Children):
  481.             child.Hide()
  482.             child.Destroy()
  483.         
  484.         v = wx.BoxSizer(wx.VERTICAL)
  485.         h = wx.BoxSizer(wx.HORIZONTAL)
  486.         v.Add(h, 1, wx.EXPAND | wx.TOP | wx.BOTTOM, pad.y)
  487.         p.Sizer = s.get('margins', Margins()).Sizer(v)
  488.         self.buttons = []
  489.         addb = self.buttons.append
  490.         menus = self.Menus
  491.         nummenus = len(self.Menus)
  492.         for menu, label in enumerate(menus):
  493.             del menu.OnDismiss[:]
  494.             label = self.toptitles.get(menu, label)
  495.             button = UberButton(p, -1, skin = s.itemskin, label = label, type = 'menu', menu = menu, menubarmode = True)
  496.             addb(button)
  497.             menu._next = menus[(i + 1) % nummenus][0]
  498.             menu._prev = menus[i - 1][0]
  499.             menu._button = button
  500.         
  501.         (h.AddMany,)((lambda .0: for b in .0:
  502. (b, 0, wx.EXPAND | wx.LEFT, pad.x))(self.buttons))
  503.         self._bindAccelerators()
  504.  
  505.     
  506.     def Show(self, val):
  507.         native = self.native
  508.         if native:
  509.             win = self.ParentWindow.Top
  510.             self.panel.Hide()
  511.             if val and win.MenuBar is not self:
  512.                 win.MenuBar = self
  513.             elif not val and win.MenuBar is self:
  514.                 win.MenuBar = None
  515.             
  516.         else:
  517.             self.panel.Show(val)
  518.  
  519.     
  520.     def _bindAccelerators(self):
  521.         accelrems = self.accelremoves
  522.         parentproc = self.ParentWindow.ProcessEvent
  523.         keybind = self.KeyCatcher.OnDown
  524.         accelrems()
  525.         del accelrems[:]
  526.         for menu in self:
  527.             for item in menu:
  528.                 accel = GetAccelText(item)
  529.                 if accel:
  530.                     
  531.                     cb = lambda e, item = item, menu = (menu,): parentproc(menuevt(item))
  532.                     accelrems.append(keybind(accel, cb))
  533.                     continue
  534.             
  535.         
  536.  
  537.     
  538.     def KeyCatcher(self):
  539.         
  540.         try:
  541.             return self.ParentWindow._keycatcher
  542.         except AttributeError:
  543.             k = self.ParentWindow._keycatcher = KeyCatcher(self.ParentWindow)
  544.             return k
  545.  
  546.  
  547.     KeyCatcher = property(KeyCatcher)
  548.     
  549.     def __len__(self):
  550.         return self.GetMenuCount()
  551.  
  552.     
  553.     def __iter__(self):
  554.         return []([ self.GetMenu(i) for i in xrange(self.GetMenuCount()) ])
  555.  
  556.     
  557.     def SizableWindow(self):
  558.         return self.panel
  559.  
  560.     SizableWindow = property(SizableWindow)
  561.     
  562.     def ParentWindow(self):
  563.         return self.panel.Parent
  564.  
  565.     ParentWindow = property(ParentWindow)
  566.     
  567.     def Handler(self):
  568.         return menuEventHandler(self.panel.Top)
  569.  
  570.     Handler = property(Handler)
  571.  
  572. from wx.lib.pubsub import Publisher
  573.  
  574. def _activateapp(message):
  575.     is_active = message.data
  576.     vlist = None
  577.     if '_lastvlist' in dir(MenuListBox):
  578.         vlist = MenuListBox._lastvlist()
  579.     
  580.     if vlist is not None and not wx.IsDestroyed(vlist) and not wx.IsDestroyed(vlist.menu):
  581.         if vlist.menu and vlist.menu.Windowless and not is_active:
  582.             vlist.DismissRoot()
  583.         
  584.     
  585.  
  586. Publisher().subscribe(_activateapp, 'app.activestate.changed')
  587.  
  588. class MenuListBox(SkinVListBox):
  589.     
  590.     def __init__(self, parent, menu):
  591.         SkinVListBox.__init__(self, parent, style = wx.NO_BORDER | wx.FULL_REPAINT_ON_RESIZE | wx.WANTS_CHARS)
  592.         self.menu = menu
  593.         self.UpdateSkin()
  594.         self.timer = wx.PyTimer(self._on_submenu_timer)
  595.         Bind = self.Bind
  596.         Bind(wx.EVT_MOUSE_EVENTS, self._mouseevents)
  597.         Bind(wx.EVT_MOUSE_CAPTURE_CHANGED, self._capturechanged)
  598.         Bind(wx.EVT_LISTBOX, self._listbox)
  599.         Bind(wx.EVT_KEY_DOWN, self._keydown)
  600.         self.mouseCallbacks = {
  601.             wx.wxEVT_MOTION: self._motion,
  602.             wx.wxEVT_RIGHT_DOWN: self._rdown,
  603.             wx.wxEVT_LEFT_DOWN: self._ldown,
  604.             wx.wxEVT_LEFT_UP: self._lup }
  605.         MenuListBox._lastvlist = ref(self)
  606.  
  607.     
  608.     def reassign(self, menu):
  609.         self.menu = menu
  610.  
  611.     menuOpenDelayMs = prefprop('menus.submenu_delay', 250)
  612.     
  613.     def __repr__(self):
  614.         return '<%s for %r>' % (self.__class__.__name__, self.menu)
  615.  
  616.     
  617.     def ParentPopup(self):
  618.         pmenu = self.menu._parentmenu
  619.         if pmenu is None:
  620.             return None
  621.         return pmenu.popup.vlist
  622.  
  623.     ParentPopup = property(ParentPopup)
  624.     
  625.     def CalcSize(self):
  626.         self.SetItemCount(len(self.menu))
  627.         height = 0
  628.         dc = wx.MemoryDC()
  629.         dc.Font = self.font
  630.         s = self.skin
  631.         padx = self.padding[0]
  632.         iconsize = s.iconsize
  633.         subw = s.submenuicon.Width
  634.         sepheight = s.separatorimage.Size.height
  635.         itemheight = self.itemheight
  636.         textExtent = dc.GetTextExtent
  637.         labelw = accelw = 0
  638.         for item in self.menu:
  639.             if item.Kind == ITEM_SEPARATOR:
  640.                 height += sepheight
  641.                 continue
  642.             height += itemheight
  643.             labelw = max(labelw, textExtent(item.Label)[0])
  644.             accelw = max(accelw, textExtent(item.AccelText)[0])
  645.         
  646.         self.accelColumnX = padx + iconsize + padx + padx + labelw + padx
  647.         width = self.accelColumnX + padx + max(accelw, subw) + padx
  648.         self.MinSize = self.Size = wx.Size(width, height)
  649.  
  650.     
  651.     def OnDrawItem(self, dc, rect, n):
  652.         item = self.menu[n]
  653.         kind = item.Kind
  654.         s = self.skin
  655.         iconsize = s.iconsize
  656.         submenuicon = s.submenuicon
  657.         padx = self.padding.x
  658.         selected = self.IsSelected(n)
  659.         drawbitmap = dc.DrawBitmap
  660.         drawlabel = dc.DrawLabel
  661.         if kind == ITEM_SEPARATOR:
  662.             s.separatorimage.Draw(dc, rect, n)
  663.         else:
  664.             dc.Font = self.font
  665.             if not item.IsEnabled():
  666.                 fg = 'disabled'
  667.             elif selected:
  668.                 fg = 'selection'
  669.             else:
  670.                 fg = 'normal'
  671.             dc.TextForeground = getattr(s.fontcolors, fg)
  672.             grect = Rect(*rect)
  673.             grect.width = padx + iconsize + padx
  674.             bmap = item.Bitmap
  675.             if bmap and bmap.Ok():
  676.                 bmap = bmap.ResizedSmaller(iconsize)
  677.                 drawbitmap(bmap, grect.HCenter(bmap), rect.VCenter(bmap), True)
  678.             
  679.             if item.IsCheckable() and item.IsChecked():
  680.                 if bmap:
  681.                     checkx = grect.Right - s.checkedicon.Width
  682.                 else:
  683.                     checkx = grect.HCenter(s.checkedicon)
  684.                 if kind == ITEM_CHECK:
  685.                     drawbitmap(s.checkedicon, checkx, rect.VCenter(s.checkedicon), True)
  686.                 elif kind == ITEM_RADIO:
  687.                     drawbitmap(s.checkedicon, checkx, rect.VCenter(s.checkedicon), True)
  688.                 
  689.             
  690.             rect.Subtract(left = iconsize + 3 * padx)
  691.             drawlabel(item.Label, rect, indexAccel = item.Text.split('\t')[0].find('&'), alignment = ALIGN_CENTER_VERTICAL)
  692.             rect.Subtract(right = submenuicon.Width + padx)
  693.             if item.SubMenu is not None:
  694.                 drawbitmap(submenuicon, rect.Right, rect.VCenter(submenuicon), True)
  695.             
  696.             acceltext = item.AccelText
  697.             if acceltext:
  698.                 rect.x = self.accelColumnX + padx
  699.                 drawlabel(acceltext, rect, alignment = ALIGN_CENTER_VERTICAL)
  700.             
  701.  
  702.     
  703.     def OnDrawBackground(self, dc, rect, n):
  704.         s = self.skin
  705.         bgs = s.backgrounds
  706.         bgname = None if self.menu[n].Kind != ITEM_SEPARATOR and self.IsSelected(n) else 'item'
  707.         bg = getattr(bgs, bgname, None)
  708.         if bg:
  709.             bg.Draw(dc, rect, n)
  710.         
  711.  
  712.     
  713.     def PaintMoreBackground(self, dc, rect):
  714.         g = self.skin.backgrounds.gutter
  715.         if g:
  716.             g.Draw(dc, Rect(rect.x, rect.y, self.skin.iconsize + self.padding.x * 2, rect.height))
  717.         
  718.  
  719.     
  720.     def OnMeasureItem(self, n):
  721.         item = self.menu[n]
  722.         kind = item.Kind
  723.         if kind == ITEM_SEPARATOR:
  724.             return self.sepheight
  725.         return self.itemheight
  726.  
  727.     
  728.     def OnPopup(self):
  729.         parentless = self.TopMenu == self.menu
  730.         if parentless:
  731.             if wxMSW:
  732.                 ReleaseCapture_win32()
  733.             
  734.             if self.menu.Windowless:
  735.                 if not hasattr(self, 'traytimer'):
  736.                     self.traytimer = UMenuTrayTimer(self)
  737.                 
  738.                 self.traytimer.Start(50)
  739.             
  740.         
  741.         if not self.menu._parentmenu:
  742.             self._grabkeyboard()
  743.         
  744.         if wx.LeftDown():
  745.             self._leftbuttondown = True
  746.         
  747.         if not self.HasCapture():
  748.             self.CaptureMouse()
  749.         
  750.         self.SetCursor(StockCursor(CURSOR_DEFAULT))
  751.         self.SetFocus()
  752.  
  753.     
  754.     def Dismiss(self):
  755.         if hasattr(self, 'traytimer'):
  756.             self.traytimer.Stop()
  757.         
  758.         if self.menu._childmenu:
  759.             self.menu._childmenu.Dismiss()
  760.             self.menu._childmenu = None
  761.         
  762.         while self.HasCapture():
  763.             self.ReleaseMouse()
  764.         self.Parent.Hide()
  765.         m = self.menu
  766.         if m._parentmenu is None:
  767.             if hasattr(self, 'focusHandler'):
  768.                 self.focusHandler.close()
  769.                 del self.focusHandler
  770.             
  771.             wx.CallAfter(self.menu.OnDismiss)
  772.         else:
  773.             m._parentmenu._childmenu = None
  774.  
  775.     
  776.     def DismissRoot(self):
  777.         self.TopMenu.Dismiss()
  778.  
  779.     
  780.     def TopMenu(self):
  781.         m = self.menu
  782.         while m._parentmenu is not None:
  783.             m = m._parentmenu
  784.         return m
  785.  
  786.     TopMenu = property(TopMenu)
  787.     
  788.     def UpdateSkin(self):
  789.         self.SetMargins(wx.Point(0, 0))
  790.         s = self.skin = self.menu.skin
  791.         self.sepheight = s.separatorimage.Size.height
  792.         
  793.         try:
  794.             self.font = s.font
  795.         except KeyError:
  796.             self.font = default_font()
  797.  
  798.         self.fontheight = s.font.Height
  799.         
  800.         try:
  801.             self.padding = s.padding
  802.         except Exception:
  803.             self.padding = wx.Point(3, 3)
  804.  
  805.         self.itemheight = int(self.fontheight + self.padding.y * 2)
  806.         self.Background = s.backgrounds.menu
  807.  
  808.     
  809.     def Window(self):
  810.         return self.menu.Window
  811.  
  812.     Window = property(Window)
  813.     
  814.     def _grabkeyboard(self):
  815.         if 'wxMSW' in wx.PlatformInfo:
  816.             f = wx.Window.FindFocus()
  817.         elif 'wxGTK' in wx.Platform:
  818.             f = self
  819.         else:
  820.             f = None
  821.         if f:
  822.             self.focusHandler = FocusHandler(self, f)
  823.         
  824.  
  825.     
  826.     def _showsubmenu(self, i, highlight = False):
  827.         item = self.menu[i]
  828.         submenu = item.SubMenu
  829.         child = self.menu._childmenu
  830.         if child is submenu:
  831.             return None
  832.         if i != -1 and submenu is not None:
  833.             r = self.ClientRect
  834.             r.Y = self.GetItemY(i)
  835.             r.Height = self.OnMeasureItem(i)
  836.             self.menu._childmenu = submenu
  837.             submenu._parentmenu = self.menu
  838.             submenu._parentindex = i
  839.             submenu.PopupMenu(r.ToScreen(self), submenu = True)
  840.             if highlight:
  841.                 submenu.popup.vlist.Selection = 0
  842.             
  843.         
  844.  
  845.     
  846.     def _on_submenu_timer(self):
  847.         i = self.Selection
  848.         if i != -1 and self.IsShown() and FindWindowAtPointer() is self:
  849.             self._showsubmenu(i)
  850.         
  851.  
  852.     
  853.     def _listbox(self, e):
  854.         self.timer.Start(self.menuOpenDelayMs, True)
  855.  
  856.     
  857.     def _emit_menuevent(self, id, type = wx.wxEVT_COMMAND_MENU_SELECTED):
  858.         event = wx.CommandEvent(type, id)
  859.         self.menu.Handler.AddPendingEvent(event)
  860.  
  861.     
  862.     def _mouseevents(self, e, wxEVT_MOTION = wxEVT_MOTION, FindWindowAtPoint = FindWindowAtPoint, UberButton = UberButton):
  863.         rect = self.ClientRect
  864.         pt_original = pt = e.Position
  865.         if not rect.Contains(pt):
  866.             menu = self.ParentPopup
  867.             oldmenu = self
  868.             while menu:
  869.                 pt = menu.ScreenToClient(oldmenu.ClientToScreen(pt))
  870.                 if menu.ClientRect.Contains(pt):
  871.                     (e.m_x, e.m_y) = pt
  872.                     return menu._mouseevents(e)
  873.                 oldmenu = menu
  874.                 menu = menu.ParentPopup
  875.                 continue
  876.                 menu.ClientRect.Contains(pt)
  877.             
  878.             try:
  879.                 button = self.TopMenu._button
  880.             except AttributeError:
  881.                 pass
  882.  
  883.             if e.GetEventType() == wxEVT_MOTION:
  884.                 ctrl = FindWindowAtPoint(self.ClientToScreen(e.Position))
  885.                 if ctrl is not None:
  886.                     if getattr(self, '_motionswitch', -1) is ctrl:
  887.                         self._motionswitch = None
  888.                         self.DismissRoot()
  889.                         ctrl.menu._showquick = True
  890.                         ctrl.OnLeftDown()
  891.                     elif isinstance(ctrl, UberButton) and ctrl.menubarmode and hasattr(ctrl, 'menu'):
  892.                         if ctrl.Parent is button.Parent and ctrl is not button:
  893.                             self._motionswitch = ctrl
  894.                         
  895.                     
  896.                 
  897.             
  898.         
  899.         (e.m_x, e.m_y) = pt_original
  900.         
  901.         try:
  902.             cb = self.mouseCallbacks[e.EventType]
  903.         except KeyError:
  904.             pass
  905.  
  906.         cb(e)
  907.  
  908.     
  909.     def _motion(self, e):
  910.         p = e.Position
  911.         i = None if self.ClientRect.Contains(p) else -1
  912.         s = self.Selection
  913.         if i != s:
  914.             p = self.ParentPopup
  915.             if p is not None:
  916.                 pi = getattr(self.menu, '_parentindex', None)
  917.                 if pi is not None and p.Selection != pi:
  918.                     p.Selection = pi
  919.                 
  920.             
  921.             self.SetSelection(i)
  922.             self._emit_lbox_selection(i)
  923.         
  924.  
  925.     
  926.     def LeafMenu(self):
  927.         s = self.menu
  928.         while s._childmenu:
  929.             s = s._childmenu
  930.         return s
  931.  
  932.     LeafMenu = property(LeafMenu)
  933.     
  934.     def _keydown(self, e):
  935.         self = self.LeafMenu.popup.vlist
  936.         code = e.KeyCode
  937.         i = self.Selection
  938.         j = -1
  939.         m = self.menu
  940.         if code == wx.WXK_DOWN:
  941.             j = (i + 1) % len(m)
  942.             while j != i and m[j].Kind == wx.ITEM_SEPARATOR:
  943.                 j = (j + 1) % len(m)
  944.         elif code == wx.WXK_UP:
  945.             if i == -1:
  946.                 i = len(m)
  947.             
  948.             j = (i - 1) % len(m)
  949.             while j != i and m[j].Kind == wx.ITEM_SEPARATOR:
  950.                 j = (j - 1) % len(m)
  951.         elif code == wx.WXK_RETURN:
  952.             return self._activate_item(i, submenu = True, highlight = True)
  953.         if code == wx.WXK_RIGHT:
  954.             if i == -1:
  955.                 pass
  956.             elif m[i].SubMenu is not None:
  957.                 self.timer.Stop()
  958.                 return self._showsubmenu(i, highlight = True)
  959.             while m._parentmenu:
  960.                 m = m._parentmenu
  961.             next = getattr(m, '_next', None)
  962.             if next is not None:
  963.                 wx.CallAfter(self.DismissRoot)
  964.                 next._showquick = True
  965.                 wx.CallAfter(next._button.OnLeftDown)
  966.             
  967.         elif code == wx.WXK_ESCAPE:
  968.             self.Dismiss()
  969.         elif code == wx.WXK_LEFT:
  970.             if m._parentmenu:
  971.                 self.Dismiss()
  972.             else:
  973.                 prev = getattr(self.menu, '_prev', None)
  974.                 if prev is not None:
  975.                     wx.CallAfter(self.DismissRoot)
  976.                     prev._showquick = True
  977.                     wx.CallAfter(prev._button.OnLeftDown)
  978.                 
  979.         elif code < 256:
  980.             self._on_char(unichr(e.UnicodeKey))
  981.         
  982.         if j != -1:
  983.             self.SetSelection(j)
  984.         
  985.  
  986.     
  987.     def _on_char(self, char):
  988.         char = char.lower()
  989.         items = []
  990.         for item in self.menu:
  991.             amp_char = GetAmpChar(item)
  992.             if amp_char is not None and char == amp_char.lower():
  993.                 return self._activate_item(item, submenu = True, highlight = True)
  994.         
  995.         items = []
  996.         for i in rotated(range(0, len(self.menu)), -(self.Selection) - 1):
  997.             item = self.menu[i]
  998.             label_text = item.GetItemLabelText()
  999.             if label_text and label_text[0].lower() == char:
  1000.                 items.append(i)
  1001.                 continue
  1002.             char == amp_char.lower()
  1003.         
  1004.         if len(items) == 1:
  1005.             self._activate_item(items[0], submenu = True, highlight = True)
  1006.         elif len(items) > 1:
  1007.             self.SetSelection(items[0])
  1008.         
  1009.  
  1010.     
  1011.     def _rdown(self, e):
  1012.         p = e.Position
  1013.         rect = self.ClientRect
  1014.         if not rect.Contains(p):
  1015.             return self.DismissRoot()
  1016.  
  1017.     
  1018.     def _ldown(self, e):
  1019.         p = e.Position
  1020.         rect = self.ClientRect
  1021.         if not rect.Contains(p):
  1022.             return self.DismissRoot()
  1023.         i = self.HitTest(p)
  1024.  
  1025.     
  1026.     def _lup(self, e):
  1027.         p = e.Position
  1028.         i = self.HitTest(e.Position)
  1029.         if self.ClientRect.Contains(p):
  1030.             self._activate_item(i)
  1031.         else:
  1032.             ctrl = FindWindowAtPointer()
  1033.             if not isinstance(ctrl, UberButton) or not (ctrl.type == 'menu'):
  1034.                 self.DismissRoot()
  1035.             
  1036.  
  1037.     
  1038.     def _activate_item(self, i, submenu = False, highlight = False):
  1039.         if isinstance(i, int):
  1040.             if i == -1:
  1041.                 return None
  1042.             item = self.menu[i]
  1043.         else:
  1044.             item = i
  1045.             i = self.menu.IndexOf(item)
  1046.         if submenu:
  1047.             if item.SubMenu is not None:
  1048.                 self.timer.Stop()
  1049.                 if not self.Selection == i:
  1050.                     self.SetSelection(i)
  1051.                 
  1052.                 return self._showsubmenu(i, highlight = highlight)
  1053.         
  1054.         if item.Kind != ITEM_SEPARATOR and item.IsEnabled() and item.SubMenu is None:
  1055.             if item.IsCheckable():
  1056.                 item.Check(not item.IsChecked())
  1057.             
  1058.             self._emit_menuevent(item.Id)
  1059.             self.DismissRoot()
  1060.         
  1061.  
  1062.     
  1063.     def _capturechanged(self, e):
  1064.         
  1065.         def active():
  1066.             
  1067.             try:
  1068.                 if self.menu.Windowless or not hasattr(self.menu.Window.Top, 'IsActive'):
  1069.                     return True
  1070.                 return self.menu.Window.Top.IsActive()
  1071.             except Exception:
  1072.                 print_exc()
  1073.                 return True
  1074.  
  1075.  
  1076.         if not active():
  1077.             (wx.CallAfter,)((lambda : self.DismissRoot()))
  1078.         
  1079.  
  1080.  
  1081.  
  1082. class MenuWindowBase(object):
  1083.     
  1084.     def __init__(self, parent, menu):
  1085.         self.vlist = MenuListBox(self, menu)
  1086.         self.UpdateSkin()
  1087.         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
  1088.         self.Bind(wx.EVT_PAINT, self._paint)
  1089.  
  1090.     
  1091.     def reassign(self, parent, menu):
  1092.         self.Reparent(parent)
  1093.         self.vlist.reassign(menu)
  1094.  
  1095.     
  1096.     def _paint(self, e):
  1097.         dc = wx.AutoBufferedPaintDC(self)
  1098.         self.bg.Draw(dc, self.ClientRect)
  1099.  
  1100.     
  1101.     def UpdateSkin(self):
  1102.         s = self.skin = self.vlist.menu.skin
  1103.         
  1104.         try:
  1105.             if self.Sizer and not wx.IsDestroyed(self.Sizer):
  1106.                 self.Sizer.Clear()
  1107.         except wx.PyDeadObjectError:
  1108.             return None
  1109.  
  1110.         self.framesize = s.get('framesize', skin.ZeroMargins)
  1111.         self.Sizer = self.framesize.Sizer(self.vlist)
  1112.         self.bg = s.frame
  1113.  
  1114.     
  1115.     def _guess_position(self):
  1116.         return wx.GetMousePosition()
  1117.  
  1118.     
  1119.     def _was_spawned_via_keyboard(self):
  1120.         menu_event = getattr(self.vlist.menu, '_menu_event', None)
  1121.         self.vlist.menu._menu_event = None
  1122.         if menu_event is not None:
  1123.             menu_event = menu_event()
  1124.             if menu_event is not None:
  1125.                 return menu_event.Position == wx.DefaultPosition
  1126.         
  1127.         return False
  1128.  
  1129.     
  1130.     def PopupMenu(self, pos = None, submenu = False):
  1131.         v = self.vlist
  1132.         v.menu.Handler._menu_open(menu = v.menu)
  1133.         v.SetSelection(-1)
  1134.         v.CalcSize()
  1135.         self.Fit()
  1136.         self.Sizer.Layout()
  1137.         if isinstance(self.bg, SplitImage4):
  1138.             self.Cut(self.bg.GetBitmap(self.Size))
  1139.         else:
  1140.             self.Cut()
  1141.         pos = None if pos is None else pos
  1142.         
  1143.         try:
  1144.             
  1145.             try:
  1146.                 disp = Monitor.GetFromPoint(pos[:2]).Geometry
  1147.             except Exception:
  1148.                 disp = Monitor.GetFromPoint(pos.BottomRight, find_near = True).Geometry
  1149.  
  1150.         except Exception:
  1151.             print_exc()
  1152.             log.critical('could not find display for %s, falling back to zero', pos)
  1153.             disp = Monitor.All()[0].Geometry
  1154.  
  1155.         size = self.Size
  1156.         rects = []
  1157.         
  1158.         add = lambda *seq: []([ RectPS(p, size) for p in seq ])
  1159.         singlepoint = len(pos) == 2
  1160.         offset = (None, None) if singlepoint else 0
  1161.         if singlepoint:
  1162.             pos = wx.RectPS(pos, (0, 0))
  1163.         
  1164.         w = Point(size.width - offset, 0)
  1165.         h = Point(0, size.height - offset)
  1166.         wh = Point(size.width - offset, size.height - offset)
  1167.         difftop = Point(0, self.framesize.top)
  1168.         diffbottom = Point(0, self.framesize.bottom)
  1169.         if submenu:
  1170.             add(pos.TopRight - difftop, pos.TopLeft - w - difftop, (pos.BottomRight - h) + diffbottom, (pos.BottomLeft - wh) + diffbottom)
  1171.         else:
  1172.             add(pos.BottomLeft, pos.TopLeft - h, pos.BottomRight - w, pos.TopRight - h, pos.TopRight - wh, pos.BottomLeft - h)
  1173.         for rect in rects:
  1174.             if disp.ContainsRect(rect):
  1175.                 self._showat(rect)
  1176.                 return None
  1177.         
  1178.         rect = rects[0]
  1179.         if hasattr(v.menu, '_button'):
  1180.             brect = v.menu._button.ScreenRect
  1181.             if rect.Intersects(brect):
  1182.                 rect.Offset((brect.Width, 0))
  1183.             
  1184.         
  1185.         self._showat(rect)
  1186.  
  1187.     
  1188.     def _showat(self, rect, nofade = False):
  1189.         self.SetRect(rect)
  1190.         self.EnsureInScreen(client_area = False)
  1191.         if nofade:
  1192.             self.Show()
  1193.         elif getattr(self.vlist.menu, '_showquick', False):
  1194.             self.vlist.menu._showquick = False
  1195.             self.Show()
  1196.         else:
  1197.             fadein(self, 'xfast')
  1198.         if wxMSW:
  1199.             CallLater((1,), (lambda : if self:
  1200. self.Refresh()))
  1201.         
  1202.         self.vlist.OnPopup()
  1203.  
  1204.  
  1205.  
  1206. class MenuPopupWindow(MenuWindowBase, wx.PopupWindow):
  1207.     
  1208.     def __init__(self, parent, menu):
  1209.         wx.PopupWindow.__init__(self, parent)
  1210.         MenuWindowBase.__init__(self, parent, menu)
  1211.  
  1212.  
  1213.  
  1214. class MenuFrameWindow(MenuWindowBase, wx.Frame):
  1215.     
  1216.     def __init__(self, parent, menu):
  1217.         wx.Frame.__init__(self, parent)
  1218.         MenuWindowBase.__init__(self, parent, menu)
  1219.  
  1220.  
  1221. from weakref import WeakValueDictionary
  1222.  
  1223. class MenuEventHandler(wx.EvtHandler):
  1224.     
  1225.     def __init__(self, parentFrame):
  1226.         wx.EvtHandler.__init__(self)
  1227.         parentFrame.PushEventHandler(self)
  1228.         self.Bind(wx.EVT_MENU, self._MenuEventHandler__menu)
  1229.         if 'wxMac' not in wx.PlatformInfo:
  1230.             self.Bind(wx.EVT_MENU_OPEN, self._menu_open)
  1231.         
  1232.         if 'wxMSW' in wx.PlatformInfo and hasattr(parentFrame, 'BindWin32'):
  1233.             parentFrame.BindWin32(WM_INITMENUPOPUP, self._initmenupopup)
  1234.         
  1235.         self.cbs = WeakValueDictionary()
  1236.         self.showcbs = { }
  1237.         if wxMSW:
  1238.             self.hwndMap = WeakValueDictionary()
  1239.         
  1240.  
  1241.     
  1242.     def AddCallback(self, id, callback):
  1243.         self.cbs[id] = callback
  1244.  
  1245.     
  1246.     def AddShowCallback(self, id, callback):
  1247.         self.showcbs[id] = callback
  1248.  
  1249.     
  1250.     def __menu(self, e):
  1251.         id = e.Id
  1252.         
  1253.         try:
  1254.             cb = self.cbs[id]
  1255.         except KeyError:
  1256.             e.Skip()
  1257.  
  1258.         cb()
  1259.  
  1260.     
  1261.     def _menu_open(self, e = None, menu = None):
  1262.         if e is not None:
  1263.             e.Skip()
  1264.             menu = e.Menu
  1265.         
  1266.         if menu is None:
  1267.             return None
  1268.         
  1269.         try:
  1270.             cb = self.showcbs[menu.Id]
  1271.         except KeyError:
  1272.             menu is None
  1273.             menu is None
  1274.         except:
  1275.             menu is None
  1276.  
  1277.         cb()
  1278.  
  1279.     if wxMSW:
  1280.         
  1281.         def _initmenupopup(self, hWnd, msg, wParam, lParam):
  1282.             
  1283.             try:
  1284.                 menu = self.hwndMap[wParam]
  1285.             except KeyError:
  1286.                 return None
  1287.  
  1288.             if menu._parentmenu:
  1289.                 evt = PyCommandEvent(wxEVT_MENU_OPEN, menu.Id)
  1290.                 evt.Menu = menu
  1291.                 menu.Handler.ProcessEvent(evt)
  1292.             
  1293.  
  1294.     
  1295.  
  1296.  
  1297. class FocusHandler(wx.EvtHandler):
  1298.     
  1299.     def __init__(self, menu, ctrl):
  1300.         wx.EvtHandler.__init__(self)
  1301.         self._menu = menu
  1302.         self._ctrl = ctrl
  1303.         self.Bind(wx.EVT_KEY_DOWN, self._menu._keydown)
  1304.         self.Bind(wx.EVT_NAVIGATION_KEY, self._menu._keydown)
  1305.         self.wantschars = bool(ctrl.WindowStyleFlag & wx.WANTS_CHARS)
  1306.         if not self.wantschars:
  1307.             ctrl.SetWindowStyleFlag(ctrl.WindowStyleFlag | wx.WANTS_CHARS)
  1308.         
  1309.         ctrl.PushEventHandler(self)
  1310.  
  1311.     
  1312.     def close(self):
  1313.         ctrl = self._ctrl
  1314.         self._ctrl = None
  1315.         ctrl.RemoveEventHandler(self)
  1316.         f = ctrl.WindowStyleFlag
  1317.         if not self.wantschars:
  1318.             f = f & ~(wx.WANTS_CHARS)
  1319.             ctrl.SetWindowStyleFlag(f)
  1320.         
  1321.         del self._menu
  1322.  
  1323.     
  1324.     def SetMenu(self, menu):
  1325.         self._menu = menu
  1326.  
  1327.     
  1328.     def OnKeyDown(self, event):
  1329.         self._menu.OnKeyDown(event)
  1330.  
  1331.  
  1332.  
  1333. def menuEventHandler(f):
  1334.     
  1335.     try:
  1336.         return f._menuevthandler
  1337.     except AttributeError:
  1338.         h = f._menuevthandler = MenuEventHandler(f)
  1339.  
  1340.     return h
  1341.  
  1342. from gui.toolbox.keynames import keynames, modifiernames
  1343.  
  1344. def menuevt(item):
  1345.     return wx.CommandEvent(wx.wxEVT_COMMAND_MENU_SELECTED, item.Id)
  1346.  
  1347.  
  1348. def GetAccelText(item):
  1349.     a = item.Accel
  1350.     if not a:
  1351.         return ''
  1352.     return _getacceltext(a.Flags, a.KeyCode)
  1353.  
  1354. if not hasattr(wx, '_MenuItem'):
  1355.     wx._MenuItem = wx.MenuItem
  1356.  
  1357. wx._MenuItem.AccelText = property(GetAccelText)
  1358.  
  1359. def GetAmpChar(item):
  1360.     text = item.Text
  1361.     amp_index = text.find('&')
  1362.     if amp_index != -1 and amp_index < len(text) - 1:
  1363.         return text[amp_index + 1]
  1364.  
  1365.  
  1366. def _getacceltext(modifiers, key, joinstr = '+'):
  1367.     return [](_[1] + [
  1368.         keynames.get(key, chr(key).upper())])
  1369.  
  1370. _getacceltext = memoize(_getacceltext)
  1371. from collections import deque
  1372.  
  1373. def rotated(iter, n):
  1374.     d = deque(iter)
  1375.     d.rotate(n)
  1376.     return d
  1377.  
  1378.