From 27587c251c4c500a20af0c3fbab9a849a28e4456 Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Wed, 17 Jan 2007 23:37:12 +0000 Subject: [PATCH] The inspect module is now a widget browser plus a shell. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44239 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- wxPython/docs/CHANGES.txt | 11 + wxPython/wx/lib/mixins/inspect.py | 649 ++++++++++++++++++++++++++++-- 2 files changed, 635 insertions(+), 25 deletions(-) diff --git a/wxPython/docs/CHANGES.txt b/wxPython/docs/CHANGES.txt index d881573a29..7b4183ae8c 100644 --- a/wxPython/docs/CHANGES.txt +++ b/wxPython/docs/CHANGES.txt @@ -19,6 +19,17 @@ these cases. PyCrust now has an option for showing/hiding the notebook. +wxMSW: Corrected drawing of bitmaps for disabled menu items. + +Enhanced the wx.lib.mixins.inspect module. In addition to showing a +PyCrust window it is now a widget browser, which provides a tree +loaded up with all the widgets in the app, optionally with the sizers +too, and also a panel displaying the properties of the selected +window. Run the demo and type Ctrl-Alt-I keystroke (or Cmd-Alt-I on +the Mac) to see how it works. You can add this to your own apps with +just a few lines of code. + + diff --git a/wxPython/wx/lib/mixins/inspect.py b/wxPython/wx/lib/mixins/inspect.py index fc114c597a..a7bdd3a6f0 100644 --- a/wxPython/wx/lib/mixins/inspect.py +++ b/wxPython/wx/lib/mixins/inspect.py @@ -1,6 +1,7 @@ #---------------------------------------------------------------------------- # Name: wx.lib.mixins.inspect -# Purpose: A mix-in class that can add PyCrust-based inspection of the app +# Purpose: A mix-in class that can add PyCrust-based inspection of the +# app's widgets and sizers. # # Author: Robin Dunn # @@ -10,52 +11,650 @@ # Licence: wxWindows license #---------------------------------------------------------------------------- -# NOTE: This class is based on ideas sent to the wxPython-users -# mail-list by Dan Eloff. +# NOTE: This class was originally based on ideas sent to the +# wxPython-users mail list by Dan Eloff. import wx import wx.py +import wx.stc +import sys + class InspectionMixin(object): """ This class is intended to be used as a mix-in with the wx.App - object. When used it will add the ability to popup a PyCrust - window where the widget under the mouse cursor will be loaded into - the shell's namespace as 'win'. + class. When used it will add the ability to popup a + InspectionFrame window where the widget under the mouse cursor + will be selected in the tree and loaded into the shell's namespace + as 'obj'. The default key sequence to activate the inspector is + Ctrl-Alt-I (or Cmd-Alt-I on Mac) but this can be changed via + parameters to the `Init` method, or the application can call + `ShowInspectionTool` from other event handlers if desired. To use this class simply derive a class from wx.App and - InspectionMixin and then call the Init() method from the app's + InspectionMixin and then call the `Init` method from the app's OnInit. """ - def Init(self, pos=(-1, -1), size=(-1, -1)): + def Init(self, pos=(-1, -1), size=(850,700), config=None, locals=None, + alt=True, cmd=True, shift=False, keyCode=ord('I')): """ - Make the event binding that will activate the PyCrust window. + Make the event binding that will activate the InspectionFrame window. """ - self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPress) - self._crust = None + self.Bind(wx.EVT_KEY_DOWN, self._OnKeyPress) + self._tool = None self._pos = pos self._size = size + self._config = config + self._locals = locals + self._alt = alt + self._cmd = cmd + self._shift = shift + self._keyCode = keyCode - def OnKeyPress(self, evt): + def _OnKeyPress(self, evt): """ - Event handler + Event handler, check for our hot-key. Normally it is + Ctrl-Alt-I but that can be changed by what is passed to the + Init method. """ - if evt.AltDown() and evt.CmdDown() and evt.KeyCode == ord('I'): - self.ShowShell() + if evt.AltDown() == self._alt and \ + evt.CmdDown() == self._cmd and \ + evt.ShiftDown() == self._shift and \ + evt.GetKeyCode() == self._keyCode: + self.ShowInspectionTool() else: evt.Skip() - def ShowShell(self): + def ShowInspectionTool(self): """ - Show the PyCrust window. + Show the Inspection tool, creating it if neccesary. """ - if not self._crust: - self._crust = wx.py.crust.CrustFrame(self.GetTopWindow(), - pos = self._pos, size = self._size) - self._crust.shell.interp.locals['app'] = self - self._crust.shell.interp.locals['wx'] = wx - win = wx.FindWindowAtPointer() - self._crust.shell.interp.locals['win'] = win - self._crust.Show() + if not self._tool: + self._tool = InspectionFrame(parent=self.GetTopWindow(), + pos=self._pos, + size=self._size, + config=self._config, + locals=self._locals, + app=self) + # get the current widget under the mouse + wnd = wx.FindWindowAtPointer() + self._tool.SetObj(wnd) + + self._tool.Show() + self._tool.Raise() + + +#--------------------------------------------------------------------------- + +class InspectionFrame(wx.Frame): + """ + This class is the frame that holds the wxPython inspection tools. + The toolbar and splitter windows are also managed here. The + contents of the splitter windows are handled by other classes. + """ + def __init__(self, wnd=None, locals=None, config=None, + app=None, title="wxPython Widget Inspection Tool", + *args, **kw): + kw['title'] = title + wx.Frame.__init__(self, *args, **kw) + + self.includeSizers = False + self.started = False + + self.MakeToolBar() + + self.outerSplitter = wx.SplitterWindow(self,style=wx.SP_3D|wx.SP_LIVE_UPDATE) + self.innerSplitter = wx.SplitterWindow(self.outerSplitter,style=wx.SP_3D|wx.SP_LIVE_UPDATE) + self.tree = InspectionTree(self.outerSplitter) + self.info = InspectionInfoPanel(self.innerSplitter) + + if not locals: + locals = {} + myIntroText = ( + "Python %s on %s\nNOTE: The 'obj' variable refers to the selected object." + % (sys.version.split()[0], sys.platform)) + self.crust = wx.py.crust.Crust(self.innerSplitter, locals=locals, + intro=myIntroText, + showInterpIntro=False, + ) + self.locals = self.crust.shell.interp.locals + self.crust.shell.interp.introText = '' + self.locals['obj'] = self.obj = wnd + self.locals['app'] = app + self.locals['wx'] = wx + wx.CallAfter(self._postStartup) + + self.innerSplitter.SplitHorizontally(self.info, self.crust, -225) + self.outerSplitter.SplitVertically(self.tree, self.innerSplitter, 280) + self.outerSplitter.SetMinimumPaneSize(20) + self.innerSplitter.SetMinimumPaneSize(20) + + + def MakeToolBar(self): + tbar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.TB_FLAT | wx.TB_TEXT | wx.NO_BORDER ) + tbar.SetToolBitmapSize((20,20)) + + refreshBmp = getRefreshBitmap() + findWidgetBmp = getFindBitmap() + showSizersBmp = getShowSizersBitmap() + toggleFillingBmp = getShowFillingBitmap() + + refreshTool = tbar.AddLabelTool(-1, 'Refresh', refreshBmp, + shortHelp = 'Refresh widget tree') + findWidgetTool = tbar.AddLabelTool(-1, 'Find', findWidgetBmp, + shortHelp='Find new target widget. Click here and\nthen on another widget in the app.') + showSizersTool = tbar.AddLabelTool(-1, 'Sizers', showSizersBmp, + shortHelp='Include sizers in widget tree', + kind=wx.ITEM_CHECK) + toggleFillingTool = tbar.AddLabelTool(-1, 'Filling', toggleFillingBmp, + shortHelp='Show PyCrust \'filling\'', + kind=wx.ITEM_CHECK) + tbar.Realize() + + self.Bind(wx.EVT_TOOL, self.OnRefreshTree, refreshTool) + self.Bind(wx.EVT_TOOL, self.OnFindWidget, findWidgetTool) + self.Bind(wx.EVT_TOOL, self.OnShowSizers, showSizersTool) + self.Bind(wx.EVT_TOOL, self.OnToggleFilling, toggleFillingTool) + self.Bind(wx.EVT_UPDATE_UI, self.OnShowSizersUI, showSizersTool) + self.Bind(wx.EVT_UPDATE_UI, self.OnToggleFillingUI, toggleFillingTool) + + + + def _postStartup(self): + if self.crust.ToolsShown(): + self.crust.ToggleTools() + self.UpdateInfo() + self.started = True + + def UpdateInfo(self): + self.info.Update(self.obj) + + def SetObj(self, obj): + if self.obj is obj: + return + self.locals['obj'] = self.obj = obj + self.UpdateInfo() + if not self.tree.built: + self.tree.BuildTree(obj, includeSizers=self.includeSizers) + else: + self.tree.SelectObj(obj) + + + def RefreshTree(self): + self.tree.BuildTree(self.obj, includeSizers=self.includeSizers) + + + def OnRefreshTree(self, evt): + self.RefreshTree() + + + def OnFindWidget(self, evt): + self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) + self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnCaptureLost) + self.CaptureMouse() + self.finding = wx.BusyInfo("Click on any widget in the app...") + + def OnCaptureLost(self, evt): + self.Unbind(wx.EVT_LEFT_DOWN) + self.Unbind(wx.EVT_MOUSE_CAPTURE_LOST) + del self.finding + + def OnLeftDown(self, evt): + self.ReleaseMouse() + wnd = wx.FindWindowAtPointer() + if wnd is not None: + self.SetObj(wnd) + else: + wx.Bell() + self.OnCaptureLost(evt) + + + def OnShowSizers(self, evt): + self.includeSizers = not self.includeSizers + self.RefreshTree() + + + def OnToggleFilling(self, evt): + self.crust.ToggleTools() + + + def OnShowSizersUI(self, evt): + evt.Check(self.includeSizers) + + + def OnToggleFillingUI(self, evt): + if self.started: + evt.Check(self.crust.ToolsShown()) + + + +#--------------------------------------------------------------------------- + +# should inspection frame (and children) be includeed in the tree? +INCLUDE_INSPECTOR = True + +class InspectionTree(wx.TreeCtrl): + """ + All of the widgets in the app, and optionally their sizers, are + loaded into this tree. + """ + def __init__(self, *args, **kw): + #s = kw.get('style', 0) + #kw['style'] = s | wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT + wx.TreeCtrl.__init__(self, *args, **kw) + self.roots = [] + self.built = False + self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectionChanged) + + + def BuildTree(self, startWidget, includeSizers=False): + if self.GetCount(): + self.DeleteAllItems() + self.roots = [] + self.built = False + + realRoot = self.AddRoot('Top-level Windows') + + for w in wx.GetTopLevelWindows(): + if w is wx.GetTopLevelParent(self) and not INCLUDE_INSPECTOR: + continue + root = self._AddWidget(realRoot, w, includeSizers) + self.roots.append(root) + + # Expand the subtree containing the startWidget, and select it. + if not startWidget or not isinstance(startWidget, wx.Window): + startWidget = wx.GetApp().GetTopWindow() + top = wx.GetTopLevelParent(startWidget) + topItem = self.FindWidgetItem(top) + if topItem: + self.ExpandAllChildren(topItem) + self.SelectObj(startWidget) + self.built = True + + + def _AddWidget(self, parentItem, widget, includeSizers): + text = self.GetTextForWidget(widget) + item = self.AppendItem(parentItem, text) + self.SetItemPyData(item, widget) + + # Add the sizer and widgets in the sizer, if we're showing them + widgetsInSizer = [] + if includeSizers and widget.GetSizer() is not None: + widgetsInSizer = self._AddSizer(item, widget.GetSizer()) + + # Add any children not in the sizer, or all children if we're + # not showing the sizers + for child in widget.GetChildren(): + if not child in widgetsInSizer and not child.IsTopLevel(): + self._AddWidget(item, child, includeSizers) + + return item + + + def _AddSizer(self, parentItem, sizer): + widgets = [] + text = self.GetTextForSizer(sizer) + item = self.AppendItem(parentItem, text) + self.SetItemPyData(item, sizer) + self.SetItemTextColour(item, "blue") + + for si in sizer.GetChildren(): + if si.IsWindow(): + w = si.GetWindow() + self._AddWidget(item, w, True) + widgets.append(w) + elif si.IsSizer(): + widgets += self._AddSizer(item, si.GetSizer()) + else: + i = self.AppendItem(item, "Spacer") + self.SetItemPyData(i, si) + self.SetItemTextColour(i, "blue") + return widgets + + + def FindWidgetItem(self, widget): + """ + Find the tree item for a widget. + """ + for item in self.roots: + found = self._FindWidgetItem(widget, item) + if found: + return found + return None + + def _FindWidgetItem(self, widget, item): + if self.GetItemPyData(item) is widget: + return item + child, cookie = self.GetFirstChild(item) + while child: + found = self._FindWidgetItem(widget, child) + if found: + return found + child, cookie = self.GetNextChild(item, cookie) + return None + + + def GetTextForWidget(self, widget): + """ + Returns the string to be used in the tree for a widget + """ + return "%s (\"%s\")" % (widget.__class__.__name__, widget.GetName()) + + def GetTextForSizer(self, sizer): + """ + Returns the string to be used in the tree for a sizer + """ + return "%s" % sizer.__class__.__name__ + + + def SelectObj(self, obj): + item = self.FindWidgetItem(obj) + if item: + self.EnsureVisible(item) + self.SelectItem(item) + + + def OnSelectionChanged(self, evt): + obj = self.GetItemPyData(evt.GetItem()) + toolFrm = wx.GetTopLevelParent(self) + toolFrm.SetObj(obj) + + +#--------------------------------------------------------------------------- + +class InspectionInfoPanel(wx.stc.StyledTextCtrl): + """ + Used to display information about the currently selected items. + Currently just a read-only wx.stc.StyledTextCtrl with some plain + text. Should probably add some styles to make things easier to + read. + """ + def __init__(self, *args, **kw): + wx.stc.StyledTextCtrl.__init__(self, *args, **kw) + + from wx.py.editwindow import FACES + self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, + "face:%(mono)s,size:%(size)d,back:%(backcol)s" % FACES) + self.StyleClearAll() + self.SetReadOnly(True) + + + def Update(self, obj): + st = [] + if not obj: + st.append("Item is None or has been destroyed.") + + elif isinstance(obj, wx.Window): + st += self.FmtWidget(obj) + + elif isinstance(obj, wx.Sizer): + st += self.FmtSizer(obj) + + elif isinstance(obj, wx.SizerItem): + st += self.FmtSizerItem(obj) + + #self.SetValue('\n'.join(st)) + self.SetReadOnly(False) + self.SetText('\n'.join(st)) + self.SetReadOnly(True) + + + def Fmt(self, name, value): + if isinstance(value, (str, unicode)): + return " %s = '%s'" % (name, value) + else: + return " %s = %s" % (name, value) + + + def FmtWidget(self, obj): + st = ["Widget:"] + st.append(self.Fmt('name', obj.GetName())) + st.append(self.Fmt('class', obj.__class__)) + st.append(self.Fmt('bases', obj.__class__.__bases__)) + st.append(self.Fmt('id', obj.GetId())) + st.append(self.Fmt('style', obj.GetWindowStyle())) + st.append(self.Fmt('pos', obj.GetPosition())) + st.append(self.Fmt('size', obj.GetSize())) + st.append(self.Fmt('minsize', obj.GetMinSize())) + st.append(self.Fmt('bestsize', obj.GetBestSize())) + st.append(self.Fmt('client size',obj.GetClientSize())) + st.append(self.Fmt('IsEnabled', obj.IsEnabled())) + st.append(self.Fmt('IsShown', obj.IsShown())) + st.append(self.Fmt('fg color', obj.GetForegroundColour())) + st.append(self.Fmt('bg color', obj.GetBackgroundColour())) + st.append(self.Fmt('label', obj.GetLabel())) + if hasattr(obj, 'GetTitle'): + st.append(self.Fmt('title', obj.GetTitle())) + if hasattr(obj, 'GetValue'): + st.append(self.Fmt('value', obj.GetValue())) + if obj.GetContainingSizer() is not None: + st.append('') + sizer = obj.GetContainingSizer() + st += self.FmtSizerItem(sizer.GetItem(obj)) + return st + + + def FmtSizerItem(self, obj): + st = ['SizerItem:'] + st.append(self.Fmt('proportion', obj.GetProportion())) + st.append(self.Fmt('flag', + FlagsFormatter(itemFlags, obj.GetFlag()))) + st.append(self.Fmt('border', obj.GetBorder())) + st.append(self.Fmt('pos', obj.GetPosition())) + st.append(self.Fmt('size', obj.GetSize())) + st.append(self.Fmt('minsize', obj.GetMinSize())) + st.append(self.Fmt('ratio', obj.GetRatio())) + st.append(self.Fmt('IsWindow', obj.IsWindow())) + st.append(self.Fmt('IsSizer', obj.IsSizer())) + st.append(self.Fmt('IsSpacer', obj.IsSpacer())) + st.append(self.Fmt('IsShown', obj.IsShown())) + if isinstance(obj, wx.GBSizerItem): + st.append(self.Fmt('cellpos', obj.GetPos())) + st.append(self.Fmt('cellspan', obj.GetSpan())) + st.append(self.Fmt('endpos', obj.GetEndPos())) + return st + + + def FmtSizer(self, obj): + st = ['Sizer:'] + st.append(self.Fmt('class', obj.__class__)) + st.append(self.Fmt('pos', obj.GetPosition())) + st.append(self.Fmt('size', obj.GetSize())) + st.append(self.Fmt('minsize', obj.GetMinSize())) + if isinstance(obj, wx.BoxSizer): + st.append(self.Fmt('orientation', + FlagsFormatter(orientFlags, obj.GetOrientation()))) + if isinstance(obj, wx.GridSizer): + st.append(self.Fmt('cols', obj.GetCols())) + st.append(self.Fmt('rows', obj.GetRows())) + st.append(self.Fmt('vgap', obj.GetVGap())) + st.append(self.Fmt('hgap', obj.GetHGap())) + if isinstance(obj, wx.FlexGridSizer): + st.append(self.Fmt('rowheights', obj.GetRowHeights())) + st.append(self.Fmt('colwidths', obj.GetColWidths())) + st.append(self.Fmt('flexdir', + FlagsFormatter(orientFlags, obj.GetFlexibleDirection()))) + st.append(self.Fmt('nonflexmode', + FlagsFormatter(flexmodeFlags, obj.GetNonFlexibleGrowMode()))) + if isinstance(obj, wx.GridBagSizer): + st.append(self.Fmt('emptycell', obj.GetEmptyCellSize())) + + if obj.GetContainingWindow(): + si = obj.GetContainingWindow().GetSizer().GetItem(obj) + if si: + st.append('') + st += self.FmtSizerItem(si) + return st + + +class FlagsFormatter(object): + def __init__(self, d, val): + self.d = d + self.val = val + + def __str__(self): + st = [] + for k in self.d.keys(): + if self.val & k: + st.append(self.d[k]) + if st: + return '|'.join(st) + else: + return '0' + +orientFlags = { + wx.HORIZONTAL : 'wx.HORIZONTAL', + wx.VERTICAL : 'wx.VERTICAL', + } + +itemFlags = { + wx.TOP : 'wx.TOP', + wx.BOTTOM : 'wx.BOTTOM', + wx.LEFT : 'wx.LEFT', + wx.RIGHT : 'wx.RIGHT', +# wx.ALL : 'wx.ALL', + wx.EXPAND : 'wx.EXPAND', +# wx.GROW : 'wx.GROW', + wx.SHAPED : 'wx.SHAPED', + wx.STRETCH_NOT : 'wx.STRETCH_NOT', + wx.ALIGN_CENTER : 'wx.ALIGN_CENTER', + wx.ALIGN_LEFT : 'wx.ALIGN_LEFT', + wx.ALIGN_RIGHT : 'wx.ALIGN_RIGHT', + wx.ALIGN_TOP : 'wx.ALIGN_TOP', + wx.ALIGN_BOTTOM : 'wx.ALIGN_BOTTOM', + wx.ALIGN_CENTER_VERTICAL : 'wx.ALIGN_CENTER_VERTICAL', + wx.ALIGN_CENTER_HORIZONTAL : 'wx.ALIGN_CENTER_HORIZONTAL', + wx.ADJUST_MINSIZE : 'wx.ADJUST_MINSIZE', + wx.FIXED_MINSIZE : 'wx.FIXED_MINSIZE', + } + +flexmodeFlags = { + wx.FLEX_GROWMODE_NONE : 'wx.FLEX_GROWMODE_NONE', + wx.FLEX_GROWMODE_SPECIFIED : 'wx.FLEX_GROWMODE_SPECIFIED', + wx.FLEX_GROWMODE_ALL : 'wx.FLEX_GROWMODE_ALL', + } + +#--------------------------------------------------------------------------- +from wx import ImageFromStream, BitmapFromImage +import cStringIO + + +def getRefreshData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x14\x00\x00\x00\x14\x08\x06\ +\x00\x00\x00\x8d\x89\x1d\r\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x02TIDAT8\x8d\x9d\x95\xbfk\xdbP\x10\xc7?\xaaC\'\xa3%\x85d\n\x1c\x04\xba\ +\x96[:\x14\x8aK;\xe6O\xc8\x90\xc1\xde\r\x9d\x0b\xfa\x13\x84\x97\x0c\xf5\x98\ +\xc9c\xe9\xd0%i\xe2\xad\x14D\x97\x0c\x15\x86\x83\x0c\xc2\x01\x17\xc3CK\x83\ +\xcd\xeb\xa0\x1f\x95\x9c\x1f\r=\x10z\xe8\xee\xbe\xef\xbd\xef\xdd}\x15D\xdco\ +\x11\x0c\x80C\xe0Y\xf9i\x01\x9cD\xf0\xf1\x8e\xf0\x00`\xeb\x1e\x90+\xe0\x1a\ +\xd8\x01^\xab*\x00I\x92 "\xdf#\xb3\x17\xa5o\xaf\x01\xee\x81\xe0\xc9\x06\xd8)\ +p,"_\xaao\xaaJ\x1c\xc7\xc4qL\x05\x0c "\x9f\x80\xe32\xa72OT\x00A\xe1\xf0\x8dg\ +\x01\xacT\xd5\xa7i\xea\xb3,\xf3\xaa\xea\x81\x95\x88\xfc\xde\x88=\xadqJ\xb0\ +\x01\xb0\x02\xfcd2\xf1I\x92T\xc9\xde9\xe7\x9ds>\xcb2\x9fe\x99\x07\xbc\xaa\ +\xfa$I\xfcd2\xa9\x00W\xc0 jpx%"k3\xeb\xec\xef\xef\xb3\xbb\xbb\xcb\xf9\xf9y\ +\x8b\xdbn\xb7\x0b\x80s\x0e\x80<\xcf\x9b\xd7\xef\x98\xd9\x15@\xc5\xe1\xb5\x99\ +\xbd\x14\x91\x9b~\xbf_\'?d\xddn\x97~\xbf\x0f\xf0\xcb\xcc\x94\xa2\x88\x04\xc0\ +@D\x9e\x03\x98\xd9\x10\xe8T\xa7\xf8\x97\x85a\x08\xb0\xa6f\xae\x00\xbd\xa0\ +\xe4EU}\x96e5o\xce9?\x1a\x8dj\xdfh4j\xf9\x9cs\xb5\x8f\x82\xcb\x0b\x80KU\xf5\ +\xd3\xe9\xb4&~3\xa1\x0c\xf6\xaaz\x0b0MS?\x9dN\xab\xb8\xcbV\x1f\xe6y\xfe(\xfe\ +\x1e\x8a\xdf\x02\x16I\x920\x1c\x0e\x01nU\xf7\xe8\xe8\xe8\xceue\x07\x07\x07@1\ +E\xc0"\x00\xde\x00\xafJ\x7f\xc4\x7f\x14EDb\x003\xfb\xb9\x15\xc1\xd7\x08\x96\ +\x14\x15\x1f\xaa\xea\xf6\xa3\xd0(\xc6r\xb9\\\xae\xcd\xec\xa4<\xcd\x8f\x8a\ +\xc3\x1d\x11I\x80\xed\xf1x\xdcj\xda\xfb,\xcfs\xc6\xe31f\xf6TD\xbeQ\x88E-\x0e\ +{f\xb6\x06\x98\xcdf\xcc\xe7sz\xbd\x1ea\x18\x92\xe7yk\x830\x0c\xe9\xf5z\xcc\ +\xe7sf\xb3\x19\xe5U;\xc0\x1e\xa58\x04Qq\xdd\x968\x94\x02\xb0\xaaz3M\xd3Z\x1c\ +(\x84\xe3Nq\xa8\xdb&\x82\xb7\xc0\x19\x05\xc97\xe5(\xc6\xcdS\xff\r\xe5\x9d\ +\x88@1%ge.@\x10D\x05h\xb5SK`E\xe4\xd0\xcc\xde7\x05\x16\xf8\x00|\xe6\xb6\xc0\ +\xb6\x00\xa9\x00\x1b\xef\xc7\xfe\x02\x82\xc6\x9a?\xea\xc8x\xd8\xb0\t\xb9\xf6\ +\x00\x00\x00\x00IEND\xaeB`\x82' + +def getRefreshBitmap(): + return BitmapFromImage(getRefreshImage()) + +def getRefreshImage(): + stream = cStringIO.StringIO(getRefreshData()) + return ImageFromStream(stream) + +#---------------------------------------------------------------------- +def getFindData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x14\x00\x00\x00\x14\x08\x06\ +\x00\x00\x00\x8d\x89\x1d\r\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01\xe6IDAT8\x8d\xa5\xd3\xbdk\x13q\x1c\xc7\xf1W\x9a\x12t\xe8\x18\xcd\ +\xd6\xa1\x17\x10\x8a\xa8\x8b\x83C\x0c\x9d\xae\x07R\x1d|@\x9d\x02\xa2 \xde\ +\x1f\xe0t\x93\x7f@\xbb(\x82\xb8\xa4\xb8i;\xa47\xd6\x08\x0e\x1d\xdaB\xc7\\)\ +\x05\x1fJ\x07\xff\x80\n\xe2pi\x9a\xda\xa6O~\xe0\x0b?\x8e\xef\xef}\xef\xdfS!\ +\xb1\x97\x84\xeb\xb8\x81\xcb\xf6g\r_\x13\x96\x1c\x93b}\x0f\xf6\x08wq\x05\xf7\ +p\xad\xaf\xfe\xe0\xd2"#\xf5\x1c>0\xc3}\xb0\x87\x88\xe28\x16\x86\xa1 \x08@\ +\x96e\xd24\x8d\xa6\xa7\xa7\xa1\x92\xe4\xfd\xcdA\xc0\x82|\x99O\xd1h\xb5Z\x82 \ +\xb0\xb3S\xdd\xd7T*udY&\x8a"x\x877\x83\x96?$\xdf\xb3J\x1c\xc7=\xd8\xf88\xeb\ +\xeby\xc1\xceNU\x10\x04\xe28\x86Jw\xce\xa1\x19\x92\x1f@\x14\x86a\x0f\x06\x17\ +\xba\xd5\x0f\r\xc3\x10"\x07\x0f\xad\x97\xe1\xddAn\xc7\xfc|\x0e\xda\xcd.tlLo_\ +\x8f\xca\xd0\xb1\x1d\xa7L\x0f\x98e\x19r\x93\xed\xbe\x86\xed\xee\xb7\xfe\x1e\ +\xfc<\n\xb8\x86V\x9a\xa6J\xa5\xce>h?\xacT\xeaH\xd3T\xadV\x83\xd5A\xc0\xb3\\\ +\x1bh\'\xdc<\x0cXL\xf8\xbe\xc8\x08\xce5\x9b\xcdj\xa1PP.S.S,\xfe\xb2\xb1\xb1d\ +vvV\x1c\xc7\xa2(R\xadvt:F\x17\x99\xa8\xf3\xfe\x80a\xd2\x1d$\xf9k\x99\x90\xdf\ +\xb3\xa8\xbf\xa9V\xabi\xb7\xdb\x1a\rn]\xe5\xdb\x16/^\x1dn\xda{\xcbu\xd6\x16\ +\xd9\xc2o\xfc\xc0J\xb7Z\x9b\x9b\x9b3\xa8\xac\xac\x18}0\xc9\xfd\xc7s.\x9e\xff\ +`\xe1\xcbA\xd3\x9e\xe1I\x92\xf0\x19\xb5\x8f\xd3L\xde\x9e\xf3\xf6\xf5\xd4\x01\ +\xd3S\xdd\xc3\xee\xa4\xf6\x9d\x98\x85OS\x9e<\x9b3\xf3\x12\xd4\xba?;\x9d\xe1I\ +L\xcf\xf4R\x0e3m4r\xd33\x19\xfek\xdah\xb0\xba\xca\xf2\xb2\xf6\x7f\x01\xfb\ +\xa1h\xe3\xf9_3n\xb4\xee\xba\xaf\xf1\xb8\x00\x00\x00\x00IEND\xaeB`\x82' + +def getFindBitmap(): + return BitmapFromImage(getFindImage()) + +def getFindImage(): + stream = cStringIO.StringIO(getFindData()) + return ImageFromStream(stream) + +#---------------------------------------------------------------------- +def getShowSizersData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x14\x00\x00\x00\x14\x08\x06\ +\x00\x00\x00\x8d\x89\x1d\r\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01-IDAT8\x8d\xad\x931N\xc3@\x10E\x9f!\x1dU\xba\x7f\x008\x00\x17@\xe9\ +\x007\\\x81\x16\xc5\xe2\x0c{\x01\xba Qr\x85H\x89#Rr\r\xe2~\xbaH\xc8\xa2B2\ +\x05^\xb3$v\xd6\x962\xd2Jc\xff\xd9\xb73;;\x89\xe3\xb86\xea\x12\x1c\xdcJ\xca\ +\xda43\x9b9X\r\x02J\xca\xcc,\xed\xd0\xc0l\x18\xb0\xb1\xb7\xc0__\xc0\xd3\xc7\ +\xc1\xf08\x10\xa0\xb8\xac\x9d2\x1a\xda\x13\x18\x07\xf5\x07^\x03\x1c.\xb3\x17\ +\xd0\xccf\x92\xbc\x9f\x02H\xca\xbd\xd6\xb5\xef$v\xa2\x99\xa5\x92rIyW\xd7\xa3\ +\x19\xba\xfa\rz\x98\xcfH\x92?\x00g\x86ky\x8b\xa7\x93\x1e0\x07\xab\tl\x16e\ +\xb9\x954\xae\xb5\xf1\xa2,\xb7\x13\xd8t\x02\xbb`^\xef\x03\x1d\xb9`\xc4\x14\ +\xdcY\xec\xae\xfc\x9dJ\xe2\x052\xa8\x9b%i\tTmK\xd2\xd2\xfdf\xde\xacX\xfc_S^\ +\xab\xbb\xc6\xff,\xe6<\x9e\x1f\xcc\xb0\xe2\xea9\xfcNx\x9f\xc2n\x97\xbfy\x88\ +\x95\x1aZ\xc1\xd9\x14`\x8d5\xff\xfe\x03\xbf\x8a\x9b!\xc0\x10\xb4\x0f\xbcO\ +\xe6C`\xbe\xc4=`8b\xbb\xd66b\xb1\xf8\xc4\rI\xab\x87\xfd\x00>\xff\xa7/3u\xdc\ +\xf3\x00\x00\x00\x00IEND\xaeB`\x82' + +def getShowSizersBitmap(): + return BitmapFromImage(getShowSizersImage()) + +def getShowSizersImage(): + stream = cStringIO.StringIO(getShowSizersData()) + return ImageFromStream(stream) + +#---------------------------------------------------------------------- +def getShowFillingData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x14\x00\x00\x00\x14\x08\x06\ +\x00\x00\x00\x8d\x89\x1d\r\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x00\x99IDAT8\x8d\xd5\xd2\xb1\r\xc3 \x10\x85\xe1\xff"\xcf\x90\x89\xa0O\ +\xe3\x19\\d\x89["\x8dWp\xe1\x01`"/q)\x12G\xc2r\n\xccEr^\x03\x08\xf4\xe9I\x87\ +(\xbe\xb98{t\x00\n\x01\xe8\x1b\x9cI!\x7f@\xe0\x0e\xdc\x1a\xc0+\x1b\x10\x003c\ +\x1c\xeb\xa4a\x90\xe2\xdc\x95\x97\x95\xda^\xf4\xb5\xcc\x80\x1d\t`\xc0\xaco\ +\xcb}\xca\xbf\xf96kr\xce\xbe`\x8c\xd1\x17L)U\x03\xdb\x12\x05\x18B8R\xaa\xc8\ +\x9fMYD\xbe\xbd\xab\x06\x1f\xc0\xd2\xe0L\xebF\xb4\xa5\xceN\xce?\x94\'\x9egM\ +\xd2gvb\xb2\x00\x00\x00\x00IEND\xaeB`\x82' + +def getShowFillingBitmap(): + return BitmapFromImage(getShowFillingImage()) + +def getShowFillingImage(): + stream = cStringIO.StringIO(getShowFillingData()) + return ImageFromStream(stream) + +#----------------------------------------------------------------------