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

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. from gui.toolbox import Monitor
  6. import wx
  7. import sys
  8. import math
  9. import traceback
  10. from wx import Bitmap, Rect, RectS, RectPS, GetMousePosition, MenuEvent, Point, VERTICAL, HORIZONTAL, Pen, Brush, Size
  11. from gui.skin.skinobjects import SkinColor, Margins
  12. from gui.windowfx import fadein
  13. from gui import skin
  14. from util.primitives.funcs import do, Delegate
  15. from common import pref
  16. from gui.uberwidgets import UberWidget
  17. from gui.textutil import GetTextWidth, default_font
  18. from gui.windowfx import DrawSubMenuArrow, ApplySmokeAndMirrors
  19. from logging import getLogger
  20. log = getLogger('simplemenu')
  21.  
  22. class SMDTimer(wx.Timer):
  23.     
  24.     def __init__(self, menu):
  25.         self.menu = menu
  26.         wx.Timer.__init__(self)
  27.  
  28.     
  29.     def Start(self, hitrect, *args, **kwargs):
  30.         self.hitrect = hitrect
  31.         self.args = args
  32.         self.kwargs = kwargs
  33.         wx.Timer.Start(self, 500, True)
  34.  
  35.     
  36.     def Notify(self):
  37.         if not (self.menu.Shown) and self.hitrect.Contains(wx.GetMousePosition()):
  38.             self.menu.Display(*self.args, **self.kwargs)
  39.         
  40.  
  41.  
  42.  
  43. class RecapTimer(wx.Timer):
  44.     
  45.     def __init__(self, target):
  46.         wx.Timer.__init__(self)
  47.         self.target = target
  48.         self.Start(10)
  49.  
  50.     
  51.     def Notify(self):
  52.         target = self.target
  53.         mp = target.Parent.ScreenToClient(wx.GetMousePosition())
  54.         if (not target.Rect.Contains(mp) or target.ClientRect.Contains(mp)) and not wx.GetMouseState().LeftDown():
  55.             self.Stop(target)
  56.         
  57.  
  58.     
  59.     def Stop(self, target):
  60.         wx.Timer.Stop(self)
  61.         target.Parent.CascadeCapture()
  62.         del target.recaptimer
  63.  
  64.  
  65.  
  66. class SimpleMenuSpine(wx.VListBox, UberWidget):
  67.     
  68.     def __init__(self, parent, skin):
  69.         wx.VListBox.__init__(self, parent)
  70.         UberWidget.__init__(self, 'LISTBOX')
  71.         self.MinSize = wx.Size(1, 1)
  72.         events = [
  73.             (wx.EVT_PAINT, self.OnPaint),
  74.             (wx.EVT_MOUSEWHEEL, self.OnMouseWheel),
  75.             (wx.EVT_MOTION, self.OnMouseMove),
  76.             (wx.EVT_LEFT_UP, self.OnLUp),
  77.             (wx.EVT_LEFT_DOWN, self.OnLDown),
  78.             (wx.EVT_RIGHT_DOWN, self.OnLDown),
  79.             (wx.EVT_MIDDLE_DOWN, self.OnLDown),
  80.             (wx.EVT_LEFT_DCLICK, (lambda e: pass)),
  81.             (wx.EVT_SCROLLWIN, self.OnScroll),
  82.             (wx.EVT_MOUSE_CAPTURE_LOST, self.OnMouseCaptureLost)]
  83.         (do,)((lambda .0: for event, method in .0:
  84. self.Bind(event, method))(events))
  85.         self.itemheight = 20
  86.         self.items = []
  87.         self.ItemCount = len(self.items)
  88.         self.SetSkinKey(skin, True)
  89.  
  90.     
  91.     def OnMouseCaptureLost(self, e):
  92.         self.Parent.CloseRoot()
  93.  
  94.     
  95.     def UpdateSkin(self):
  96.         key = self.skinkey
  97.         self.native = native = not key
  98.         if native:
  99.             self.OpenNativeTheme()
  100.             self.padding = wx.Point(2, 2)
  101.             self.framesize = Margins([
  102.                 1,
  103.                 1,
  104.                 1,
  105.                 1])
  106.             sz = self.Parent.Sizer
  107.             if sz:
  108.                 sz.Detach(1)
  109.                 sz.Detach(1)
  110.                 sz.Add(wx.Size(self.framesize.left, self.framesize.top), (0, 0))
  111.                 sz.Add(wx.Size(self.framesize.right, self.framesize.bottom), (2, 2))
  112.             
  113.             self.framebg = None
  114.             self.menubg = None
  115.             self.itembg = None
  116.             self.selbg = None
  117.             self.Font = default_font()
  118.             self.normalfc = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)
  119.             self.selfc = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
  120.             self.MakeNativeSubmenuIcons()
  121.             self.separator = None
  122.         else:
  123.             self.CloseNativeTheme()
  124.             
  125.             s = lambda k, default: skin.get('%s.%s' % (key, k), default)
  126.             self.padding = s('padding', wx.Point(2, 2))
  127.             self.framesize = s('framesize', Margins([
  128.                 0,
  129.                 0,
  130.                 0,
  131.                 0]))
  132.             sz = self.Parent.Sizer
  133.             if sz:
  134.                 sz.Detach(1)
  135.                 sz.Detach(1)
  136.                 sz.Add(wx.Size(self.framesize.left, self.framesize.top), (0, 0))
  137.                 sz.Add(wx.Size(self.framesize.right, self.framesize.bottom), (2, 2))
  138.             
  139.             self.framebg = s('frame', (lambda : SkinColor(wx.BLACK)))
  140.             self.menubg = s('backgrounds.menu', None)
  141.             self.itembg = s('backgrounds.item', None)
  142.             self.selbg = s('backgrounds.selection', None)
  143.             self.Font = s('font', default_font())
  144.             self.normalfc = s('fontcolors.normal', (lambda : wx.BLACK))
  145.             self.selfc = s('fontcolors.selection', (lambda : wx.BLACK))
  146.             submenuicon = self.submenuicon = s('submenuicon', None)
  147.             if submenuicon is None:
  148.                 self.MakeNativeSubmenuIcons()
  149.             else:
  150.                 self.submenuiconhot = s('submenuiconhover', submenuicon)
  151.             self.separator = s('separatorimage', None)
  152.         for item in self.items:
  153.             if item.menu:
  154.                 item.menu.spine.SetSkinKey(key)
  155.                 continue
  156.         
  157.  
  158.     
  159.     def MakeNativeSubmenuIcons(self):
  160.         arrowmask = wx.EmptyBitmap(10, 10)
  161.         mdc = wx.MemoryDC()
  162.         mdc.SelectObject(arrowmask)
  163.         controls = controls
  164.         import gui.windowfx
  165.         arect = wx.Rect(0, 0, 10, 10)
  166.         DrawSubMenuArrow(mdc, arect)
  167.         mdc.SelectObject(wx.NullBitmap)
  168.         mdc2 = wx.MemoryDC()
  169.         for s in xrange(2):
  170.             acolor = None if s else self.normalfc
  171.             arrow = wx.EmptyBitmap(10, 10)
  172.             arrow.SetMask(wx.Mask(arrowmask, wx.WHITE))
  173.             mdc2.SelectObject(arrow)
  174.             mdc2.Brush = wx.Brush(acolor)
  175.             mdc2.FloodFill(0, 0, wx.BLACK)
  176.             mdc2.SelectObject(wx.NullBitmap)
  177.             if s:
  178.                 self.submenuiconhot = arrow
  179.                 continue
  180.             self.submenuicon = arrow
  181.         
  182.  
  183.     
  184.     def DrawNativeBackgroundFallback(self, dc, part, state, unusedrect):
  185.         rect = wx.RectS(self.Size)
  186.         dc.Brush = Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
  187.         dc.Pen = wx.TRANSPARENT_PEN
  188.         dc.DrawRectangleRect(rect)
  189.  
  190.     
  191.     def OnPaint(self, event):
  192.         dc = wx.AutoBufferedPaintDC(self)
  193.         rect = wx.RectS(self.ClientSize)
  194.         if self.menubg:
  195.             self.menubg.Draw(dc, rect)
  196.         else:
  197.             dc.SetClippingRect(rect)
  198.             nrect = wx.Rect(*rect)
  199.             nrect.Inflate(1, 1)
  200.             self.DrawNativeLike(dc, 0, 0, nrect, self.DrawNativeBackgroundFallback)
  201.             dc.DestroyClippingRegion()
  202.         rect.Height = self.itemheight
  203.         i = self.FirstVisibleLine
  204.         j = self.LastVisibleLine
  205.         if j >= 0 and j != sys.maxint * 2 + 1:
  206.             bg = self.OnDrawBackground
  207.             draw = self.OnDrawItem
  208.             measure = self.OnMeasureItem
  209.             for n in xrange(i, j + 1):
  210.                 bg(dc, rect, n)
  211.                 draw(dc, rect, n)
  212.                 rect.SetY(rect.GetY() + measure(n))
  213.             
  214.         
  215.  
  216.     
  217.     def OnDrawBackground(self, dc, rect, n):
  218.         if self.native:
  219.             if self.GetSelection() == n:
  220.                 dc.Brush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
  221.                 dc.Pen = wx.TRANSPARENT_PEN
  222.                 dc.DrawRectangleRect(rect)
  223.             
  224.         elif self.GetSelection() == n and self.selbg:
  225.             self.selbg.Draw(dc, rect)
  226.         elif self.itembg:
  227.             self.itembg.Draw(dc, rect)
  228.         
  229.  
  230.     
  231.     def OnDrawItem(self, dc, rect, n):
  232.         curser = Point(rect.x, rect.y) + (self.padding.x, 0)
  233.         if self.items[n].id == -1:
  234.             return self.DrawSeparator(dc, rect, n)
  235.         if self.items[n].font:
  236.             font = self.items[n].font
  237.         else:
  238.             font = self.Font
  239.         dc.Font = font
  240.         dc.TextForeground = None if self.Selection == n else self.normalfc
  241.         if self.items[n].menu:
  242.             dc.Brush = wx.BLACK_BRUSH
  243.             dc.Pen = wx.TRANSPARENT_PEN
  244.             smi = None if self.Selection == n else self.submenuicon
  245.             dc.DrawBitmap(smi, rect.Width - self.padding.x - smi.Width, rect.Y + rect.Height / 2 - smi.Height / 2, True)
  246.             endcap = smi.Width + self.padding.x
  247.         else:
  248.             endcap = 0
  249.         padx = self.padding.x
  250.         txtext = dc.Font.Height
  251.         txtext_pad = Point(txtext + padx, 0)
  252.         for i in self.items[n].content:
  253.             if type(i) is Bitmap:
  254.                 curser.y = rect.Y + (rect.height / 2 - i.Height / 2)
  255.                 imgpad = None if self.bitmapwidth else 0
  256.                 
  257.                 try:
  258.                     dc.DrawBitmapPoint(i, (curser.x + imgpad, curser.y), True)
  259.                 except Exception:
  260.                     traceback.print_exc_once()
  261.                     
  262.                     try:
  263.                         log.error('Failed drawing bitmap: %r', getattr(i, 'path', None))
  264.                     except Exception:
  265.                         pass
  266.                     except:
  267.                         None<EXCEPTION MATCH>Exception
  268.                     
  269.  
  270.                     None<EXCEPTION MATCH>Exception
  271.  
  272.                 curser += Point(max(self.bitmapwidth, i.Width) + padx, 0)
  273.                 continue
  274.             if isinstance(i, basestring):
  275.                 curser.y = rect.Y + (rect.height / 2 - txtext / 2)
  276.                 text_rect = RectPS(curser, Size(rect.width - curser.x - padx - endcap, txtext))
  277.                 dc.DrawTruncatedText(i, text_rect, alignment = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
  278.                 curser += txtext_pad
  279.                 continue
  280.         
  281.  
  282.     
  283.     def DrawSeparator(self, dc, rect, n):
  284.         sepwidth = rect.width - self.padding.x * 2
  285.         if self.separator:
  286.             sepheight = self.separator.Size.height
  287.             seppos = (self.padding.x, rect.y + rect.height // 2 - sepheight // 2)
  288.             self.separator.Draw(dc, RectPS(seppos, (sepwidth, sepheight)))
  289.         else:
  290.             dc.Pen = Pen(self.normalfc, 1)
  291.             seppos = Point(self.padding.x, rect.y + rect.height // 2)
  292.             endpos = seppos + Point(sepwidth, 0)
  293.             dc.DrawLinePoint(seppos, endpos)
  294.  
  295.     
  296.     def OnMouseWheel(self, e):
  297.         self.ScrollLines(-math.copysign(1, e.WheelRotation))
  298.  
  299.     
  300.     def OnMouseMove(self, event):
  301.         mp = self.ScreenToClient(GetMousePosition())
  302.         items = self.items
  303.         if self.ClientRect.Contains(mp):
  304.             n = self.HitTest(mp)
  305.             if self.Selection != n:
  306.                 do((lambda .0: for item in .0:
  307. if item.menu and item.menu.IsShown():
  308. item.menu.Show(False)continue)(self.items))
  309.                 if items[n].id != -1:
  310.                     self.SetSelection(n)
  311.                     if items[n].menu:
  312.                         items[n].menu.DelayedDisplay(self.GetItemRect(n), self)
  313.                     
  314.                 else:
  315.                     self.SetSelection(-1)
  316.             
  317.         elif self.Rect.Contains(mp):
  318.             self.Parent.CascadeRelease()
  319.             self.recaptimer = RecapTimer(self)
  320.         else:
  321.             self.SetSelection(-1)
  322.             gp = self.GrandParent
  323.             if isinstance(gp, SimpleMenu) and gp.CheckParentalContact(GetMousePosition()):
  324.                 gp.spine.AddPendingEvent(event)
  325.             
  326.  
  327.     
  328.     def OnLUp(self, event):
  329.         if self.GetClientRect().Contains(event.Position):
  330.             n = self.HitTest(event.Position)
  331.             if self.items[n].id != -1:
  332.                 item = self.items[n]
  333.                 if not item.menu:
  334.                     self.TriggerItem(item)
  335.                 
  336.             
  337.         
  338.  
  339.     
  340.     def TriggerItem(self, item):
  341.         if item.method is not None:
  342.             wx.CallAfter(item.method, item)
  343.         elif self.Parent.callback:
  344.             wx.CallAfter(self.Parent.callback, item)
  345.         else:
  346.             menuevent = MenuEvent(wx.wxEVT_COMMAND_MENU_SELECTED, item.id)
  347.             self.Parent.AddPendingEvent(menuevent)
  348.         self.Parent.CloseRoot()
  349.  
  350.     
  351.     def OnLDown(self, event):
  352.         if not self.Rect.Contains(event.Position) and not self.Parent.CheckParentalContact(wx.GetMousePosition(), True):
  353.             self.Parent.CloseRoot()
  354.         
  355.  
  356.     
  357.     def OnScroll(self, event):
  358.         self.Refresh()
  359.         event.Skip()
  360.  
  361.     
  362.     def CalcSize(self):
  363.         self.CalcItemHeight()
  364.         if self.Parent.staticwidth:
  365.             width = self.Parent.width
  366.         else:
  367.             self.CalcItemWidth()
  368.             width = self.calcedwidth
  369.         if not (self.Parent.maxheight) or self.ItemCount < self.Parent.maxheight:
  370.             height = self.itemheight * self.ItemCount
  371.         else:
  372.             height = self.itemheight * self.Parent.maxheight
  373.         maxwidth = self.Parent.maxwidth
  374.         if maxwidth and width > maxwidth:
  375.             width = maxwidth
  376.         
  377.         minwidth = self.Parent.minwidth
  378.         if minwidth and width < minwidth:
  379.             width = minwidth
  380.         
  381.         p = self.Parent.ScreenRect[:2]
  382.         self.Parent.Rect = RectPS(p, wx.Size(width, height + self.framesize.y))
  383.  
  384.     
  385.     def CalcItemHeight(self):
  386.         hset = list((lambda .0: for item in .0:
  387. if item.font:
  388. item.font.Heightcontinue)(self.items))
  389.         hset.append(self.Font.Height)
  390.         if max(hset) - min(hset) > 10:
  391.             hset = sorted(hset)
  392.             lhset = len(hset)
  393.             
  394.             def Median(set):
  395.                 lset = len(set)
  396.                 if lset % 2:
  397.                     m1 = lset // 2
  398.                     m2 = m1 + 1
  399.                     return set[m1] + (set[m2] - set[m1]) // 2
  400.                 return set[lset // 2 + 1]
  401.  
  402.             q1 = Median(hset[:lhset // 2])
  403.             q3 = Median(hset[lhset // 2 + 1:])
  404.             iqr = q3 - q1
  405.             hi = q3 + 1.5 * iqr
  406.             hset = (set,)((lambda .0: for h in .0:
  407. if h < hi:
  408. hcontinue)(hset))
  409.         
  410.         self.bitmapwidth = bitmapwidth = 0
  411.         for item in self.items:
  412.             if item.id == -1:
  413.                 pass
  414.             elif item.content and isinstance(item.content[0], Bitmap):
  415.                 bitmapwidth = max(bitmapwidth, item.content[0].Width)
  416.             
  417.             for object in item.content:
  418.                 if type(object) is Bitmap:
  419.                     hset.append(object.Height)
  420.                     continue
  421.             
  422.         
  423.         if bitmapwidth:
  424.             empty_bitmap = wx.EmptyBitmap(bitmapwidth, 1)
  425.             for item in self.items:
  426.                 if item.id == -1:
  427.                     continue
  428.                 if item.content and isinstance(item.content[0], basestring):
  429.                     item.content.insert(0, empty_bitmap)
  430.                     continue
  431.             
  432.             self.bitmapwidth = bitmapwidth
  433.         
  434.         h = max(hset)
  435.         for item in self.items:
  436.             if item.font and item.font.Height > h:
  437.                 self.items.remove(item)
  438.                 continue
  439.         
  440.         self.ItemCount = len(self.items)
  441.         self.itemheight = h + 2 * self.padding.y
  442.  
  443.     
  444.     def CalcItemWidth(self):
  445.         if not self.items:
  446.             self.calcedwidth = 0
  447.         else:
  448.             wset = (set,)((lambda .0: for item in .0:
  449. item.GetContentWidth(self.Parent))(self.items))
  450.             w = max(wset)
  451.             w += self.framesize.x
  452.             self.calcedwidth = w
  453.  
  454.     
  455.     def OnMeasureItem(self, n):
  456.         return self.itemheight
  457.  
  458.     
  459.     def GetSelectionRect(self):
  460.         return self.GetItemRect(self.Selection)
  461.  
  462.     
  463.     def GetItemRect(self, n):
  464.         pos = self.ScreenRect.Position
  465.         x = pos.x
  466.         width = self.Size.x
  467.         y = pos.y + (sum,)((lambda .0: for i in .0:
  468. self.OnMeasureItem(i))(xrange(n)))
  469.         height = self.OnMeasureItem(n)
  470.         return Rect(x, y, width, height)
  471.  
  472.  
  473.  
  474. class SimpleMenu(wx.PopupTransientWindow, UberWidget):
  475.     
  476.     def __init__(self, parent, skinkey = 'simplemenu', maxheight = None, width = 0, minwidth = 0, maxwidth = 0, callback = None):
  477.         wx.PopupTransientWindow.__init__(self, parent)
  478.         self.BeforeDisplay = Delegate()
  479.         Bind = self.Bind
  480.         Bind(wx.EVT_PAINT, self.OnPaint)
  481.         Bind(wx.EVT_SIZE, self.OnSize)
  482.         Bind(wx.EVT_SHOW, self.OnClose)
  483.         Bind(wx.EVT_MENU, self.PassEvent)
  484.         self.maxheight = maxheight
  485.         self.staticwidth = bool(width)
  486.         self.width = width
  487.         self.maxwidth = maxwidth
  488.         self.minwidth = minwidth
  489.         self.spine = SimpleMenuSpine(self, skinkey)
  490.         self.displaytimer = SMDTimer(self)
  491.         s = self.Sizer = wx.GridBagSizer()
  492.         s.SetEmptyCellSize(wx.Size(0, 0))
  493.         s.Add(self.spine, (1, 1), flag = wx.EXPAND)
  494.         s.Add(wx.Size(self.spine.framesize.left, self.spine.framesize.top), (0, 0))
  495.         s.Add(wx.Size(self.spine.framesize.right, self.spine.framesize.bottom), (2, 2))
  496.         s.AddGrowableCol(1, 1)
  497.         s.AddGrowableRow(1, 1)
  498.         self.callback = callback
  499.         self.connected = None
  500.  
  501.     
  502.     def SetSkinKey(self, key):
  503.         self.spine.SetSkinKey(key)
  504.  
  505.     
  506.     def SetWidth(self, width):
  507.         self.staticwidth = True
  508.         w = width
  509.         if self.minwidth:
  510.             w = max(w, self.minwidth)
  511.         
  512.         if self.maxwidth:
  513.             w = min(w, self.maxwidth)
  514.         
  515.         self.width = w
  516.         self.Size = wx.Size(w, -1)
  517.  
  518.     
  519.     def OnSize(self, event):
  520.         event.Skip()
  521.         background = self.spine.framebg
  522.         SplitImage4 = SplitImage4
  523.         import cgui
  524.         if isinstance(background, SplitImage4):
  525.             ApplySmokeAndMirrors(self, background.GetBitmap(self.Size))
  526.         else:
  527.             ApplySmokeAndMirrors(self)
  528.         self.Layout()
  529.  
  530.     
  531.     def OnPaint(self, event):
  532.         dc = wx.PaintDC(self)
  533.         rect = wx.RectS(self.Size)
  534.         bg = self.spine.framebg
  535.         if bg:
  536.             bg.Draw(dc, rect)
  537.         elif self.spine.native:
  538.             dc.Brush = wx.TRANSPARENT_BRUSH
  539.             dc.Pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWFRAME))
  540.             dc.DrawRectangleRect(rect)
  541.         
  542.  
  543.     
  544.     def GetIndex(self, item):
  545.         
  546.         try:
  547.             return self.spine.items.index(item)
  548.         except ValueError:
  549.             return -1
  550.  
  551.  
  552.     
  553.     def Insert(self, index, *args, **kwargs):
  554.         self.InsertItem(index, SimpleMenuItem(*args, **kwargs))
  555.  
  556.     
  557.     def Append(self, *args, **kwargs):
  558.         self.AppendItem(SimpleMenuItem(*args, **kwargs))
  559.  
  560.     
  561.     def InsertItem(self, index, item):
  562.         self.spine.items.insert(index, item)
  563.         self.spine.ItemCount = len(self.spine.items)
  564.  
  565.     
  566.     def AppendItem(self, item):
  567.         self.spine.items.append(item)
  568.         self.spine.ItemCount = len(self.spine.items)
  569.  
  570.     
  571.     def RemoveItem(self, item):
  572.         sp = self.spine
  573.         if isinstance(item, int):
  574.             item = sp.items[item]
  575.         
  576.         sp.Selection = -1
  577.         sp.items.remove(item)
  578.         sp.ItemCount = len(self.spine.items)
  579.  
  580.     
  581.     def RemoveAll(self):
  582.         self.spine.items = []
  583.         self.spine.ItemCount = len(self.spine.items)
  584.  
  585.     
  586.     def GetCount(self):
  587.         return len(self.spine.items)
  588.  
  589.     Count = property(GetCount)
  590.     __len__ = GetCount
  591.     
  592.     def SetSelection(self, selection):
  593.         self.spine.Selection = selection
  594.  
  595.     
  596.     def GetSelection(self):
  597.         return self.spine.Selection
  598.  
  599.     Selection = property(GetSelection, SetSelection)
  600.     
  601.     def SetItems(self, items):
  602.         if wx.IsDestroyed(self):
  603.             print >>sys.stderr, 'WARNING: %r is destroyed' % self
  604.             return None
  605.         self.Frozen().__enter__()
  606.         
  607.         try:
  608.             sp = self.spine
  609.             sp.items = items
  610.             sp.ItemCount = len(items)
  611.             if sp.IsShownOnScreen():
  612.                 sp.RefreshAll()
  613.         finally:
  614.             pass
  615.  
  616.  
  617.     
  618.     def GetItem(self, index):
  619.         return self.spine.items[index]
  620.  
  621.     
  622.     def GetItems(self):
  623.         return self.spine.items
  624.  
  625.     
  626.     def GetItemIndex(self, item):
  627.         return self.spine.items.index(item)
  628.  
  629.     
  630.     def FindItemById(self, id):
  631.         for item in self.spine.items:
  632.             if item.id == id:
  633.                 return item
  634.         
  635.  
  636.     
  637.     def PassEvent(self, event):
  638.         self.Parent.AddPendingEvent(event)
  639.  
  640.     
  641.     def DelayedDisplay(self, rect, *args, **kwargs):
  642.         if not self.displaytimer.IsRunning():
  643.             self.displaytimer.Start(rect, *args, **kwargs)
  644.         
  645.  
  646.     
  647.     def Display(self, caller = None, funnle = True, funnlefullscreen = False):
  648.         self.BeforeDisplay()
  649.         if not self.IsShown() and len(self):
  650.             self.spine.CalcSize()
  651.             if caller and isinstance(caller, SimpleMenuSpine):
  652.                 self.caller = None
  653.                 rect = caller.GetSelectionRect()
  654.                 position = Point(rect.x + rect.width, rect.y - self.spine.framesize.top)
  655.                 newrect = RectPS(position, self.ScreenRect.Size)
  656.                 screenrect = Monitor.GetFromRect(newrect).Geometry
  657.                 if newrect.bottom > screenrect.bottom:
  658.                     position.y = rect.y + rect.height - self.Size.height
  659.                 
  660.                 if newrect.right > screenrect.right:
  661.                     position.x = rect.x - self.Size.width
  662.                 
  663.             elif caller:
  664.                 self.caller = caller
  665.                 caller_rect = caller.ScreenRect
  666.                 position = caller_rect.BottomLeft
  667.                 newrect = RectPS(position, self.ScreenRect.Size)
  668.                 screenrect = Monitor.GetFromWindow(caller).Geometry
  669.                 if newrect.bottom > screenrect.bottom:
  670.                     position.y -= caller_rect.Height + self.spine.Size.height
  671.                 
  672.                 if newrect.right > screenrect.right:
  673.                     position.x += caller_rect.Width - self.spine.Size.width
  674.                 
  675.             else:
  676.                 self.caller = None
  677.                 position = wx.GetMousePosition()
  678.                 newrect = RectPS(position, self.ScreenRect.Size)
  679.                 screenrect = Monitor.GetFromPoint(position).Geometry
  680.                 if newrect.bottom > screenrect.bottom:
  681.                     position.y -= self.spine.Size.height
  682.                 
  683.                 if newrect.right > screenrect.right and pref('menus.shift_mode', False):
  684.                     position.x -= self.spine.Size.width
  685.                 
  686.             newrect = wx.RectPS(position, self.Size)
  687.             screenrect = Monitor.GetFromRect(newrect).Geometry
  688.             pos = None if funnle else position
  689.             self.SetRect(RectPS(pos, self.Size))
  690.             self.spine.SetSelection(-1)
  691.             fadein(self, 'xfast')
  692.             self.spine.RefreshAll()
  693.             if not self.spine.HasCapture():
  694.                 self.spine.CaptureMouse()
  695.             
  696.             wx.CallLater(10, self.Refresh)
  697.             if not isinstance(caller, SimpleMenuSpine):
  698.                 self.TopConnect()
  699.             
  700.         
  701.  
  702.     
  703.     def TopConnect(self):
  704.         t = self.Top
  705.         while not isinstance(t, wx.TopLevelWindow):
  706.             t = t.Parent.Top
  707.         id = t.Id
  708.         t.Connect(id, id, wx.wxEVT_ACTIVATE, self.OnActiveChange)
  709.         self.connected = (t, id)
  710.  
  711.     
  712.     def OnActiveChange(self, event):
  713.         self.CloseRoot()
  714.  
  715.     
  716.     def OnClose(self, event):
  717.         if not self.IsShown():
  718.             do((lambda .0: for item in .0:
  719. if item.menu and item.menu.IsShown():
  720. item.menu.Show(False)continue)(self.spine.items))
  721.             while self.spine.HasCapture():
  722.                 self.spine.ReleaseMouse()
  723.             if self.caller:
  724.                 event = wx.MenuEvent(wx.wxEVT_MENU_CLOSE, self.Id)
  725.                 self.caller.AddPendingEvent(event)
  726.                 self.caller = None
  727.             
  728.             if self.connected:
  729.                 (window, id) = self.connected
  730.                 window.Disconnect(id, id, wx.wxEVT_ACTIVATE)
  731.                 self.connected = None
  732.             
  733.         
  734.  
  735.     
  736.     def CloseRoot(self):
  737.         if isinstance(self.Parent, SimpleMenu):
  738.             self.Parent.CloseRoot()
  739.         else:
  740.             self.Show(False)
  741.  
  742.     
  743.     def __repr__(self):
  744.         return '<SimpleMenu %r>' % self.spine.items
  745.  
  746.     
  747.     def CheckParentalContact(self, pos, ignoresubmenu = False):
  748.         rect = RectS(self.spine.Size)
  749.         mp = self.spine.ScreenToClient(pos)
  750.         if rect.Contains(mp):
  751.             if ignoresubmenu and not (self.spine.items[self.spine.HitTest(mp)].menu) or not self.spine.items[self.spine.HitTest(mp)].menu.IsShown():
  752.                 return True
  753.             if isinstance(self.Parent, SimpleMenu):
  754.                 return self.Parent.CheckParentalContact(pos, ignoresubmenu)
  755.             return False
  756.  
  757.     
  758.     def CascadeRelease(self):
  759.         while self.spine.HasCapture():
  760.             self.spine.ReleaseMouse()
  761.         if isinstance(self.Parent, SimpleMenu):
  762.             self.Parent.CascadeRelease()
  763.         
  764.  
  765.     
  766.     def CascadeCapture(self):
  767.         if isinstance(self.Parent, SimpleMenu):
  768.             self.Parent.CascadeCapture()
  769.         
  770.         if not self.spine.HasCapture():
  771.             self.spine.CaptureMouse()
  772.         
  773.  
  774.  
  775.  
  776. class SimpleMenuItem(object):
  777.     
  778.     def __init__(self, content = '', method = None, font = None, id = None, menu = None):
  779.         if content is not None:
  780.             if isinstance(content, basestring):
  781.                 self.content = [
  782.                     content]
  783.             elif isinstance(content, list):
  784.                 self.content = content
  785.             else:
  786.                 raise TypeError
  787.         isinstance(content, basestring)
  788.         self.content = []
  789.         self.method = method
  790.         self.menu = menu
  791.         self.font = font
  792.         self.id = id
  793.  
  794.     
  795.     def __repr__(self):
  796.         return '<SMItem %s>' % self.GetContentAsString()
  797.  
  798.     
  799.     def __str__(self):
  800.         return self.GetContentAsString()
  801.  
  802.     
  803.     def __eq__(self, o):
  804.         if isinstance(o, self.__class__):
  805.             pass
  806.         return self.content == o.content
  807.  
  808.     
  809.     def __ne__(self, other):
  810.         return not self.__eq__(other)
  811.  
  812.     
  813.     def __hash__(self):
  814.         return hash(id(self))
  815.  
  816.     
  817.     def GetContentAsString(self):
  818.         for thing in self.content:
  819.             if isinstance(thing, basestring):
  820.                 return thing
  821.         
  822.         return ''
  823.  
  824.     
  825.     def GetContentWidth(self, menu):
  826.         if not menu:
  827.             return None
  828.         pad = menu.spine.padding
  829.         if not self.font:
  830.             pass
  831.         font = menu.spine.Font
  832.         cont = self.content
  833.         count = len(cont)
  834.         w = (sum,)((lambda .0: for s in .0:
  835. if isinstance(s, basestring):
  836. GetTextWidth(s, font)continue)(cont))
  837.         w += sum((lambda .0: for b in .0:
  838. if type(b) is Bitmap:
  839. b.Widthcontinue)(cont))
  840.         w += (count + 1) * pad.x + 1
  841.         return w
  842.  
  843.     
  844.     def SetLabel(self, label):
  845.         for i, item in enumerate(self.content):
  846.             if isinstance(item, basestring):
  847.                 self.content[i] = label
  848.                 return None
  849.         
  850.  
  851.  
  852.