Merge recent changes from 2.8 branch.
Make updates for recent changes on CVS HEAD. Remove or workaround deprecated items. Fix compile errors. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45088 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -1584,7 +1584,7 @@ class ButtonPanel(wx.PyPanel):
|
||||
|
||||
def OnPaint(self, event):
|
||||
""" Handles the wx.EVT_PAINT event for ButtonPanel. """
|
||||
|
||||
|
||||
dc = wx.BufferedPaintDC(self)
|
||||
rect = self.GetClientRect()
|
||||
|
||||
@@ -1744,7 +1744,7 @@ class ButtonPanel(wx.PyPanel):
|
||||
|
||||
def OnMouseMove(self, event):
|
||||
""" Handles the wx.EVT_MOTION event for ButtonPanel. """
|
||||
|
||||
|
||||
# Check to see if we are hovering a button
|
||||
tabId, flags = self.HitTest(event.GetPosition())
|
||||
|
||||
@@ -1765,7 +1765,8 @@ class ButtonPanel(wx.PyPanel):
|
||||
self.RepaintOldSelection()
|
||||
|
||||
if btn.GetRect().Contains(event.GetPosition()):
|
||||
btn.SetStatus("Hover")
|
||||
if btn.GetStatus() != "Pressed":
|
||||
btn.SetStatus("Hover")
|
||||
else:
|
||||
btn.SetStatus("Normal")
|
||||
|
||||
@@ -1808,21 +1809,21 @@ class ButtonPanel(wx.PyPanel):
|
||||
btn.SetFocus(False)
|
||||
|
||||
if hit.GetStatus() == "Pressed":
|
||||
# Fire a button click event
|
||||
btnEvent = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, hit.GetId())
|
||||
self.GetEventHandler().ProcessEvent(btnEvent)
|
||||
|
||||
hit.SetToggled(not hit.GetToggled())
|
||||
|
||||
# Update the button status to be hovered
|
||||
hit.SetStatus("Hover")
|
||||
hit.SetFocus()
|
||||
self._currentButton = tabId
|
||||
|
||||
# Fire a button click event
|
||||
btnEvent = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, hit.GetId())
|
||||
self.GetEventHandler().ProcessEvent(btnEvent)
|
||||
|
||||
|
||||
def OnMouseLeave(self, event):
|
||||
""" Handles the wx.EVT_LEAVE_WINDOW event for ButtonPanel. """
|
||||
|
||||
|
||||
# Reset all buttons statuses
|
||||
for btn in self._vButtons:
|
||||
if not btn.IsEnabled():
|
||||
|
@@ -589,6 +589,8 @@ class ThemedGenButton(GenButton):
|
||||
state = 0
|
||||
else:
|
||||
state = wx.CONTROL_PRESSED
|
||||
if not self.IsEnabled():
|
||||
state = wx.CONTROL_DISABLED
|
||||
wx.RendererNative.Get().DrawPushButton(self, dc, rect, state)
|
||||
|
||||
class ThemedGenBitmapButton(ThemedGenButton, GenBitmapButton):
|
||||
|
@@ -3,7 +3,7 @@
|
||||
# Inspired By And Heavily Based On wxGenericTreeCtrl.
|
||||
#
|
||||
# Andrea Gavana, @ 17 May 2006
|
||||
# Latest Revision: 26 May 2006, 22.30 CET
|
||||
# Latest Revision: 02 Mar 2007, 22.30 CET
|
||||
#
|
||||
#
|
||||
# TODO List
|
||||
@@ -134,8 +134,8 @@ CustomTreeCtrl has been tested on the following platforms:
|
||||
* Mac OS (Thanks to John Jackson).
|
||||
|
||||
|
||||
Latest Revision: Andrea Gavana @ 26 May 2006, 22.30 CET
|
||||
Version 0.8
|
||||
Latest Revision: Andrea Gavana @ 02 Mar 2007, 22.30 CET
|
||||
Version 0.9
|
||||
|
||||
"""
|
||||
|
||||
@@ -1736,7 +1736,7 @@ def EventFlagsToSelType(style, shiftDown=False, ctrlDown=False):
|
||||
class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
|
||||
def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
|
||||
style=0, ctstyle=TR_DEFAULT_STYLE, validator=wx.DefaultValidator,
|
||||
style=TR_DEFAULT_STYLE, ctstyle=0, validator=wx.DefaultValidator,
|
||||
name="CustomTreeCtrl"):
|
||||
"""
|
||||
Default class constructor.
|
||||
@@ -1749,9 +1749,8 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
|
||||
size: window size. If the default size (-1, -1) is specified then the window is sized appropriately.
|
||||
|
||||
style: the underlying wx.ScrolledWindow style
|
||||
style: the underlying wx.ScrolledWindow style + CustomTreeCtrl window style. This can be one of:
|
||||
|
||||
ctstyle: CustomTreeCtrl window style. This can be one of:
|
||||
TR_NO_BUTTONS
|
||||
TR_HAS_BUTTONS # draw collapsed/expanded btns
|
||||
TR_NO_LINES # don't draw lines at all
|
||||
@@ -1769,10 +1768,14 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
TR_AUTO_CHECK_PARENT # only meaningful for checkboxes
|
||||
TR_AUTO_TOGGLE_CHILD # only meaningful for checkboxes
|
||||
|
||||
ctstyle: kept for backward compatibility.
|
||||
|
||||
validator: window validator.
|
||||
|
||||
name: window name.
|
||||
"""
|
||||
|
||||
style = style | ctstyle
|
||||
|
||||
self._current = self._key_current = self._anchor = self._select_me = None
|
||||
self._hasFocus = False
|
||||
@@ -1873,14 +1876,14 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
self._itemWithWindow = []
|
||||
|
||||
if wx.Platform == "__WXMAC__":
|
||||
ctstyle &= ~TR_LINES_AT_ROOT
|
||||
ctstyle |= TR_NO_LINES
|
||||
style &= ~TR_LINES_AT_ROOT
|
||||
style |= TR_NO_LINES
|
||||
|
||||
platform, major, minor = wx.GetOsVersion()
|
||||
if major < 10:
|
||||
ctstyle |= TR_ROW_LINES
|
||||
style |= TR_ROW_LINES
|
||||
|
||||
self._windowStyle = ctstyle
|
||||
self._windowStyle = style
|
||||
|
||||
# Create the default check image list
|
||||
self.SetImageListCheck(13, 13)
|
||||
@@ -2370,7 +2373,7 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
return item.GetText()
|
||||
|
||||
|
||||
def GetItemImage(self, item, which):
|
||||
def GetItemImage(self, item, which=TreeItemIcon_Normal):
|
||||
"""Returns the item image."""
|
||||
|
||||
if not item:
|
||||
@@ -3467,8 +3470,8 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
self.ProcessEvent(event)
|
||||
|
||||
|
||||
def ExpandAll(self, item):
|
||||
"""Expands all the items."""
|
||||
def ExpandAllChildren(self, item):
|
||||
"""Expands all the items children of the input item."""
|
||||
|
||||
if not item:
|
||||
raise Exception("\nERROR: Invalid Tree Item. ")
|
||||
@@ -3481,10 +3484,17 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
child, cookie = self.GetFirstChild(item)
|
||||
|
||||
while child:
|
||||
self.ExpandAll(child)
|
||||
self.ExpandAllChildren(child)
|
||||
child, cookie = self.GetNextChild(item, cookie)
|
||||
|
||||
|
||||
def ExpandAll(self):
|
||||
"""Expands all CustomTreeCtrl items."""
|
||||
|
||||
if self._anchor:
|
||||
self.ExpandAllChildren(self._anchor)
|
||||
|
||||
|
||||
def Collapse(self, item):
|
||||
"""
|
||||
Collapse an item, sending a EVT_TREE_ITEM_COLLAPSING and
|
||||
@@ -3578,7 +3588,8 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
# the tree might not have the root item at all
|
||||
if rootItem:
|
||||
self.UnselectAllChildren(rootItem)
|
||||
|
||||
|
||||
self.Unselect()
|
||||
|
||||
# Recursive function !
|
||||
# To stop we must have crt_item<last_item
|
||||
@@ -3958,21 +3969,22 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
self._imageListNormal = imageList
|
||||
self._ownsImageListNormal = False
|
||||
self._dirty = True
|
||||
|
||||
# Don't do any drawing if we're setting the list to NULL,
|
||||
# since we may be in the process of deleting the tree control.
|
||||
if imageList:
|
||||
self.CalculateLineHeight()
|
||||
|
||||
# We gray out the image list to use the grayed icons with disabled items
|
||||
self._grayedImageList = wx.ImageList(16, 16, True, 0)
|
||||
|
||||
for ii in xrange(imageList.GetImageCount()):
|
||||
|
||||
bmp = imageList.GetBitmap(ii)
|
||||
image = wx.ImageFromBitmap(bmp)
|
||||
image = GrayOut(image)
|
||||
newbmp = wx.BitmapFromImage(image)
|
||||
self._grayedImageList.Add(newbmp)
|
||||
# We gray out the image list to use the grayed icons with disabled items
|
||||
sz = imageList.GetSize(0)
|
||||
self._grayedImageList = wx.ImageList(sz[0], sz[1], True, 0)
|
||||
|
||||
for ii in xrange(imageList.GetImageCount()):
|
||||
bmp = imageList.GetBitmap(ii)
|
||||
image = wx.ImageFromBitmap(bmp)
|
||||
image = GrayOut(image)
|
||||
newbmp = wx.BitmapFromImage(image)
|
||||
self._grayedImageList.Add(newbmp)
|
||||
|
||||
|
||||
def SetStateImageList(self, imageList):
|
||||
@@ -4402,6 +4414,7 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
if wnd:
|
||||
wndx = wcheck + image_w + item.GetX() + text_w + 4
|
||||
xa, ya = self.CalcScrolledPosition((0, item.GetY()))
|
||||
wndx += xa
|
||||
if not wnd.IsShown():
|
||||
wnd.Show()
|
||||
if wnd.GetPosition() != (wndx, ya):
|
||||
@@ -5733,4 +5746,6 @@ class CustomTreeCtrl(wx.PyScrolledWindow):
|
||||
attr.font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
||||
return attr
|
||||
|
||||
GetClassDefaultAttributes = classmethod(GetClassDefaultAttributes)
|
||||
|
||||
|
||||
|
@@ -34,8 +34,8 @@ class ScrolledMessageDialog(wx.Dialog):
|
||||
if x == -1 and y == -1:
|
||||
self.CenterOnScreen(wx.BOTH)
|
||||
|
||||
text = wx.TextCtrl(self, -1, msg,
|
||||
style=wx.TE_MULTILINE | wx.TE_READONLY)
|
||||
self.text = text = wx.TextCtrl(self, -1, msg,
|
||||
style=wx.TE_MULTILINE | wx.TE_READONLY)
|
||||
|
||||
ok = wx.Button(self, wx.ID_OK, "OK")
|
||||
ok.SetDefault()
|
||||
|
@@ -1920,8 +1920,8 @@ class DocManager(wx.EvtHandler):
|
||||
newDoc.SetDocumentName(temp.GetDocumentName())
|
||||
newDoc.SetDocumentTemplate(temp)
|
||||
if not newDoc.OnOpenDocument(path):
|
||||
newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews
|
||||
frame = newDoc.GetFirstView().GetFrame()
|
||||
newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews
|
||||
if frame:
|
||||
frame.Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it.
|
||||
return None
|
||||
|
@@ -351,8 +351,8 @@ class DirBrowseButton(FileBrowseButton):
|
||||
def OnBrowse(self, ev = None):
|
||||
style=0
|
||||
|
||||
if self.newDirectory:
|
||||
style|=wx.DD_NEW_DIR_BUTTON
|
||||
if not self.newDirectory:
|
||||
style |= wx.DD_DIR_MUST_EXIST
|
||||
|
||||
dialog = self.dialogClass(self,
|
||||
message = self.dialogTitle,
|
||||
|
@@ -198,8 +198,8 @@ FNB_DEFAULT_STYLE = FNB_MOUSE_MIDDLE_CLOSES_TABS | FNB_HIDE_ON_SINGLE_TAB
|
||||
# wxEVT_FLATNOTEBOOK_PAGE_CLOSED: Event Fired When A Page Is Closed.
|
||||
# wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU: Event Fired When A Menu Pops-up In A Tab.
|
||||
|
||||
wxEVT_FLATNOTEBOOK_PAGE_CHANGED = wx.NewEventType()
|
||||
wxEVT_FLATNOTEBOOK_PAGE_CHANGING = wx.NewEventType()
|
||||
wxEVT_FLATNOTEBOOK_PAGE_CHANGED = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
|
||||
wxEVT_FLATNOTEBOOK_PAGE_CHANGING = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
|
||||
wxEVT_FLATNOTEBOOK_PAGE_CLOSING = wx.NewEventType()
|
||||
wxEVT_FLATNOTEBOOK_PAGE_CLOSED = wx.NewEventType()
|
||||
wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.NewEventType()
|
||||
@@ -208,10 +208,10 @@ wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.NewEventType()
|
||||
# FlatNotebookEvent
|
||||
#-----------------------------------#
|
||||
|
||||
EVT_FLATNOTEBOOK_PAGE_CHANGED = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CHANGED, 1)
|
||||
EVT_FLATNOTEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED
|
||||
"""Notify client objects when the active page in L{FlatNotebook}
|
||||
has changed."""
|
||||
EVT_FLATNOTEBOOK_PAGE_CHANGING = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, 1)
|
||||
EVT_FLATNOTEBOOK_PAGE_CHANGING = wx.EVT_NOTEBOOK_PAGE_CHANGING
|
||||
"""Notify client objects when the active page in L{FlatNotebook}
|
||||
is about to change."""
|
||||
EVT_FLATNOTEBOOK_PAGE_CLOSING = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, 1)
|
||||
@@ -2955,14 +2955,17 @@ class FlatNotebook(wx.Panel):
|
||||
|
||||
|
||||
def SetImageList(self, imageList):
|
||||
"""
|
||||
Sets the image list for the page control. It does not take ownership
|
||||
of the image list, you must delete it yourself.
|
||||
"""
|
||||
""" Sets the image list for the page control. """
|
||||
|
||||
self._pages.SetImageList(imageList)
|
||||
|
||||
|
||||
def AssignImageList(self, imageList):
|
||||
""" Assigns the image list for the page control. """
|
||||
|
||||
self._pages.AssignImageList(imageList)
|
||||
|
||||
|
||||
def GetImageList(self):
|
||||
""" Returns the associated image list. """
|
||||
|
||||
@@ -4381,7 +4384,7 @@ class PageContainer(wx.Panel):
|
||||
|
||||
elif self.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND:
|
||||
|
||||
if wx.Platform in ["__WXMSW__", "__WXGTK__"]:
|
||||
if wx.Platform in ["__WXMSW__", "__WXGTK__", "__WXMAC__"]:
|
||||
if nTabPage >= 0:
|
||||
|
||||
window = oldNotebook.GetPage(nTabPage)
|
||||
@@ -4623,6 +4626,12 @@ class PageContainer(wx.Panel):
|
||||
self._ImageList = imglist
|
||||
|
||||
|
||||
def AssignImageList(self, imglist):
|
||||
""" Assigns the image list for the page control. """
|
||||
|
||||
self._ImageList = imglist
|
||||
|
||||
|
||||
def GetImageList(self):
|
||||
""" Returns the image list for the page control. """
|
||||
|
||||
|
901
wxPython/wx/lib/inspection.py
Normal file
901
wxPython/wx/lib/inspection.py
Normal file
@@ -0,0 +1,901 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: wx.lib.inspection
|
||||
# Purpose: A widget inspection tool that allows easy introspection of
|
||||
# all the live widgets and sizers in an application.
|
||||
#
|
||||
# Author: Robin Dunn
|
||||
#
|
||||
# Created: 26-Jan-2007
|
||||
# RCS-ID: $Id$
|
||||
# Copyright: (c) 2007 by Total Control Software
|
||||
# Licence: wxWindows license
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
# NOTE: This class was originally based on ideas sent to the
|
||||
# wxPython-users mail list by Dan Eloff. See also
|
||||
# wx.lib.mixins.inspect for a class that can be mixed-in with wx.App
|
||||
# to provide Hot-Key access to the inspection tool.
|
||||
|
||||
import wx
|
||||
import wx.py
|
||||
import wx.stc
|
||||
import wx.aui
|
||||
import sys
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
class InspectionTool:
|
||||
"""
|
||||
The InspectionTool is a singleton that manages creating and
|
||||
showing an InspectionFrame.
|
||||
"""
|
||||
|
||||
# Note: This is the Borg design pattern which ensures that all
|
||||
# instances of this class are actually using the same set of
|
||||
# instance data. See
|
||||
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531
|
||||
__shared_state = {}
|
||||
def __init__(self):
|
||||
self.__dict__ = self.__shared_state
|
||||
if not hasattr(self, 'initialized'):
|
||||
self.initialized = False
|
||||
|
||||
def Init(self, pos=wx.DefaultPosition, size=wx.Size(850,700),
|
||||
config=None, locals=None, app=None):
|
||||
"""
|
||||
Init is used to set some parameters that will be used later
|
||||
when the inspection tool is shown. Suitable defaults will be
|
||||
used for all of these parameters if they are not provided.
|
||||
|
||||
:param pos: The default position to show the frame at
|
||||
:param size: The default size of the frame
|
||||
:param config: A wx.Config object to be used to store layout
|
||||
and other info to when the inspection frame is closed.
|
||||
This info will be restored the next time the inspection
|
||||
frame is used.
|
||||
:param locals: A dictionary of names to be added to the PyCrust
|
||||
namespace.
|
||||
:param app: A reference to the wx.App object.
|
||||
"""
|
||||
self._frame = None
|
||||
self._pos = pos
|
||||
self._size = size
|
||||
self._config = config
|
||||
self._locals = locals
|
||||
self._app = app
|
||||
if not self._app:
|
||||
self._app = wx.GetApp()
|
||||
self.initialized = True
|
||||
|
||||
|
||||
def Show(self, selectObj=None, refreshTree=False):
|
||||
"""
|
||||
Creates the inspection frame if it hasn't been already, and
|
||||
raises it if neccessary. Pass a widget or sizer in selectObj
|
||||
to have that object be preselected in widget tree. If
|
||||
refreshTree is True then the widget tree will be rebuilt,
|
||||
otherwise if the tree has already been built it will be left
|
||||
alone.
|
||||
"""
|
||||
if not self.initialized:
|
||||
self.Init()
|
||||
|
||||
parent = self._app.GetTopWindow()
|
||||
if not selectObj:
|
||||
selectObj = parent
|
||||
if not self._frame:
|
||||
self._frame = InspectionFrame( parent=parent,
|
||||
pos=self._pos,
|
||||
size=self._size,
|
||||
config=self._config,
|
||||
locals=self._locals,
|
||||
app=self._app)
|
||||
if selectObj:
|
||||
self._frame.SetObj(selectObj)
|
||||
if refreshTree:
|
||||
self._frame.RefreshTree()
|
||||
self._frame.Show()
|
||||
if self._frame.IsIconized():
|
||||
self._frame.Iconize(False)
|
||||
self._frame.Raise()
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class InspectionFrame(wx.Frame):
|
||||
"""
|
||||
This class is the frame that holds the wxPython inspection tools.
|
||||
The toolbar and AUI splitters/floating panes are also managed
|
||||
here. The contents of the tool 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.SetIcon(getIconIcon())
|
||||
self.MacSetMetalAppearance(True)
|
||||
self.MakeToolBar()
|
||||
panel = wx.Panel(self, size=self.GetClientSize())
|
||||
|
||||
# tell FrameManager to manage this frame
|
||||
self.mgr = wx.aui.AuiManager(panel,
|
||||
wx.aui.AUI_MGR_DEFAULT
|
||||
| wx.aui.AUI_MGR_TRANSPARENT_DRAG
|
||||
| wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE)
|
||||
|
||||
# make the child tools
|
||||
self.tree = InspectionTree(panel)
|
||||
self.info = InspectionInfoPanel(panel,
|
||||
style=wx.NO_BORDER,
|
||||
)
|
||||
|
||||
if not locals:
|
||||
locals = {}
|
||||
myIntroText = (
|
||||
"Python %s on %s\nNOTE: The 'obj' variable refers to the object selected in the tree."
|
||||
% (sys.version.split()[0], sys.platform))
|
||||
self.crust = wx.py.crust.Crust(panel, locals=locals,
|
||||
intro=myIntroText,
|
||||
showInterpIntro=False,
|
||||
style=wx.NO_BORDER,
|
||||
)
|
||||
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)
|
||||
|
||||
# put the chlid tools in AUI panes
|
||||
self.mgr.AddPane(self.info,
|
||||
wx.aui.AuiPaneInfo().Name("info").Caption("Object Info").
|
||||
CenterPane().CaptionVisible(True).
|
||||
CloseButton(False).MaximizeButton(True)
|
||||
)
|
||||
self.mgr.AddPane(self.tree,
|
||||
wx.aui.AuiPaneInfo().Name("tree").Caption("Widget Tree").
|
||||
CaptionVisible(True).Left().Dockable(True).Floatable(True).
|
||||
BestSize((280,200)).CloseButton(False).MaximizeButton(True)
|
||||
)
|
||||
self.mgr.AddPane(self.crust,
|
||||
wx.aui.AuiPaneInfo().Name("crust").Caption("PyCrust").
|
||||
CaptionVisible(True).Bottom().Dockable(True).Floatable(True).
|
||||
BestSize((400,200)).CloseButton(False).MaximizeButton(True)
|
||||
)
|
||||
|
||||
self.mgr.Update()
|
||||
|
||||
if config is None:
|
||||
config = wx.Config('wxpyinspector')
|
||||
self.config = config
|
||||
self.Bind(wx.EVT_CLOSE, self.OnClose)
|
||||
self.LoadSettings(self.config)
|
||||
self.crust.shell.lineNumbers = False
|
||||
self.crust.shell.setDisplayLineNumbers(False)
|
||||
self.crust.shell.SetMarginWidth(1, 0)
|
||||
|
||||
|
||||
def MakeToolBar(self):
|
||||
tbar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.TB_FLAT | wx.TB_TEXT | wx.NO_BORDER )
|
||||
tbar.SetToolBitmapSize((24,24))
|
||||
|
||||
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 OnClose(self, evt):
|
||||
self.SaveSettings(self.config)
|
||||
evt.Skip()
|
||||
|
||||
|
||||
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()
|
||||
self.UpdateInfo()
|
||||
|
||||
|
||||
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())
|
||||
|
||||
|
||||
def LoadSettings(self, config):
|
||||
self.crust.LoadSettings(config)
|
||||
|
||||
pos = wx.Point(config.ReadInt('Window/PosX', -1),
|
||||
config.ReadInt('Window/PosY', -1))
|
||||
|
||||
size = wx.Size(config.ReadInt('Window/Width', -1),
|
||||
config.ReadInt('Window/Height', -1))
|
||||
self.SetSize(size)
|
||||
self.Move(pos)
|
||||
|
||||
perspective = config.Read('perspective', '')
|
||||
if perspective:
|
||||
self.mgr.LoadPerspective(perspective)
|
||||
self.includeSizers = config.ReadBool('includeSizers', False)
|
||||
|
||||
|
||||
def SaveSettings(self, config):
|
||||
self.crust.SaveSettings(config)
|
||||
|
||||
if not self.IsIconized() and not self.IsMaximized():
|
||||
w, h = self.GetSize()
|
||||
config.WriteInt('Window/Width', w)
|
||||
config.WriteInt('Window/Height', h)
|
||||
|
||||
px, py = self.GetPosition()
|
||||
config.WriteInt('Window/PosX', px)
|
||||
config.WriteInt('Window/PosY', py)
|
||||
|
||||
perspective = self.mgr.SavePerspective()
|
||||
config.Write('perspective', perspective)
|
||||
config.WriteBool('includeSizers', self.includeSizers)
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# 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)
|
||||
self.toolFrame = wx.GetTopLevelParent(self)
|
||||
if 'wxMac' in wx.PlatformInfo:
|
||||
self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL)
|
||||
|
||||
|
||||
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())
|
||||
self.toolFrame.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)
|
||||
self.SetMarginType(1, 0)
|
||||
self.SetMarginWidth(1, 0)
|
||||
self.SetSelForeground(True, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
|
||||
self.SetSelBackground(True, wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT))
|
||||
|
||||
|
||||
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.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
|
||||
from wx import EmptyIcon
|
||||
import cStringIO
|
||||
|
||||
|
||||
def getRefreshData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\x00\x00\x00\x18\x08\x06\
|
||||
\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
|
||||
\x05\xe8IDATH\x89\x9d\x96]h\x94\xd9\x19\xc7\x7f\xefG21\x93\x99Il\xcc&\x18w\
|
||||
\x1c?\xe2GK\xa5kb\x8d\xd3(+\xcb\xd2-\x0b-4A\xf1\xc6\xcb\x8a\xdaz\xa7\xd8\x9b\
|
||||
zQ\xe8\x85R\xd3\xd0\x1a\x97\x06w\xad\xa8\x14/z%\x85\xd2\x85\xe2\x17\xedEK\
|
||||
\x83\xd4\xc4X\x1b\x9bL\x98L\xdf\xc9d\xbe\'\x99\xc9{\xfe\xbd\xc8$\xc4e\xa1\
|
||||
\xd0\x07\x0e\x1c\x0e\xcf\xc7y\xfe\xe7\xff<\xcf\xb1\xf8\xdfr\x008\x03|\x0bp\
|
||||
\x00\x0b\xf0\x81\xa7\xc0\'\xc0\xdf\xbe\xccH\xabz\xb8\x1b\xce\x9c\xba!\xc0\
|
||||
\x07\xc0\xbf\x81\x92\xe38\xef\xf8\xbe\xff.\xf0\xb5\xae\xae\xae%\x80d2\xd9\
|
||||
\xd4\xd0\xd0\x90\xd9\xb9s\xe7\xf6\xc9\xc9\xc9y\xa0\x19\x88\x01\x9f\x03\x06p,\
|
||||
\xf0\x05\x96\xfb\x05\xe7[\x80\x9f\xb9\xae{d\xeb\xd6\xad%\xd7u\x7f\xf0\xfa\
|
||||
\xf5\xeb\xd7\xb6m[\x03\x03\x03\x0c\x0e\x0e6Y\x96\xc5\x83\x07\x0f\x98\x98\x98\
|
||||
h\xf4}?\x01\x84c\xb1\xd8\'\xb3\xb3\xb3\x1d+++\x7f\x06~\x0c$\xd7\x82l\xccj\
|
||||
\x8b\xe38\xf7W\xb3[_\x9f\x02W\x81\x7f\x0e\r\r)\x95J\xa9\\.\xeb\xf4\xe9\xd3\
|
||||
\x02fC\xa1\xd0\xcd\xb6\xb6\xb6\xcf6\xda\xd8\xb6\xfd\x00\xe8\xfc2\xd8\xc6\x00\
|
||||
\x85B!\xf5\xf6\xf6\x9aC\x87\x0e\x99\xd6\xd6V\x01joo\xd7\xcd\x9b7\xfdt:\xadR\
|
||||
\xa9\xa4\xb1\xb11?\x14\n\t\xd0\xbe}\xfb\xd4\xdb\xdb\xab\xde\xde^\x13\x0e\x87\
|
||||
\xd7\x02\xfd\xa6\x8e\xca\xba|\xe08\xce?\x00\x1d<x\xd0LMM\xc9\xf3<]\xbatI\xb6\
|
||||
m\xeb\xe2\xc5\x8b\x92\xa4B\xa1\xa0d2)I\xba|\xf9\xb2l\xdb\xd6\x85\x0b\x174??\
|
||||
\xaf\xe9\xe9i\xf5\xf7\xf7\x1b@\xae\xeb\xbe\x04>\xda\x18\xa0g\xfb\xf6\xed\xcf\
|
||||
\x00\xf5\xf5\xf5\xc9\xf3<%\x12\t%\x93I\xcd\xcc\xcc(\x95J\xa9T*)\x9f\xcf+\x97\
|
||||
\xcb\xa9X,*\x95JiffF\xc9dR\x89DB\x8b\x8b\x8b\x1a\x18\x180\x80\xa2\xd1\xe8\
|
||||
\xdf\x81\xfdlH\xa31\x9b\xcd~\xde\xd6\xd6\x16\t\x04\x02_\xf7<\x8fx<NGG\x07\
|
||||
\xa1P\x88\xc6\xc6Fj\xb5\x1a\x96eaY\x16\xc6\x18\x82\xc1 \x91H\x84`0H\xadVcxx\
|
||||
\x98\x87\x0f\x1fZ\x95J\xe5n{{\xfb\xe5\xc5\xc5\xc5\x0c\x90\x078\xd0\xd3\xd3\
|
||||
\xf3\xdd]\xbbv}#\x12\x89\xfc\xaa\xfeP\x9a\x99\x99\xd1\xca\xca\x8a\xb2\xd9\
|
||||
\xac\xca\xe5\xb2\xbe(\x95JE\xd9lV\xd5jU\x9e\xe7)\x18\x0c\xae\xe1\xff\x0b`\
|
||||
\xa7\xe38\x1f\x02\x07\x1c\xe0J\xa1P\xf8\xd8q\x9c\x8f3\x99L_0\x18\x8c\x9c?\
|
||||
\x7f\x9ec\xc7\x8e\xd1\xd8\xd8\x88m\xdb\x14\x8bE\xc6\xc7\xc7y\xf2\xe4\t\xcf\
|
||||
\x9f?\'\x9f\xcf\x13\n\x85\xd8\xb4i\x13\xc6\x18|\x7f\x95\x8d\x13\x13\x13\x94\
|
||||
\xcb\xe5\x0e\xdb\xb6\xfb\x8c1\xfd\xc0n\x80\xe7\x80\xe2\xf1\xb8N\x9e<\xa9\xd1\
|
||||
\xd1Q_\x92\x8a\xc5\xa2r\xb9\x9c$\xe9\xe9\xd3\xa7z\xff\xfd\xf7\xd5\xd0\xd0 \
|
||||
\xdb\xb6u\xf4\xe8Q=z\xf4H\x92\x94\xcb\xe5T(\x14$I\xb7n\xdd\xf2\x07\x07\x07u\
|
||||
\xfc\xf8q\xd9\xb6\xad\xbao^tuuUFFF\x94\xcb\xe5\x94\xcf\xe7\x95L&\xd7\xf7\x92\
|
||||
t\xef\xde=544l\xe4\xban\xdf\xbe-I\xca\xe7\xf3\xca\xe7\xf3*\x14\nJ\xa7\xd3J\
|
||||
\xa5R\x1a\x1d\x1dUww\xf72\xf0\xc2e\xadg\xb8.\xbe\xefcY\x16\xc1`\xf0\xad\x02\
|
||||
\x91\xb4\x0e\x03\x801\x06c\xcc[:\xc5b\x91p8\x8ceY\xd8\xb6\x8deY\x00\x96\x03\
|
||||
\xfc\xa8T*\xbd\xb3\xb4\xb4\xc4\xe3\xc7\x8fYZZ2\x87\x0f\x1f\xb6|\xdf\xc7\x18C\
|
||||
\x10 \x9f\xcf\xf3\xea\xd5+fgg\x91\xc4\x91#G\x18\x1a\x1a"\x1a\x8d\xb2\xbc\
|
||||
\xbc\x8cm\xdbl\xde\xbc\x99\xfb\xf7\xef\x9b\x91\x91\x11\xeb\xd9\xb3g\x8c\x8f\
|
||||
\x8f;@\xca\x02\xae\x00\xbd\xb6m7\x19cvttt\xc4\xce\x9c9\xc3\xb9s\xe7\x08\x87\
|
||||
\xc3\x00\x14\n\x05&\'\'\x99\x9e\x9e\xc6\x18\xc3\x8e\x1d;\xd8\xbbw/\xe1p\x18I\
|
||||
T*\x15FFF\x18\x1e\x1e&\x97\xcb\xcduvv\xcef2\x99\x95j\xb5\xfa\x02\xa0\xc3q\
|
||||
\x9c\xe3\xf5\xc2\xf8\xf9\xffK\xd3\xe6\xe6f\x01\n\x87\xc3\xb7zzz\xfa\xf6\xec\
|
||||
\xd9\xf3}\xe0=\x07(I\xaa\xc5b\xb1`6\x9b=\x1a\x89D\xde;{\xf6,\x03\x03\x03\x04\
|
||||
\x83A\\\xd7\xc5\x18C\xa5R\xa1Z\xadR\xadV\xd7a\t\x04\x02\x00,//S\xab\xd5X\\\\\
|
||||
\xa4T*M\xce\xcd\xcd\xfdqaa\xe1_\xc0\xcb\xb57\xda\xb5\xb1U\xcc\xcf\xcf+\x91H\
|
||||
\xc8\xf3<y\x9e\xa7\x85\x85\x05\x15\n\x85\xb7\x18\x93\xc9d\xe4y\x9e\xd2\xe9\
|
||||
\xb4\x12\x89\x84\xd2\xe9\xb4\xe2\xf1\xb8\x00\xc5b\xb1g\xc0>\x81e\xd7\x03lO\
|
||||
\xcc\xcdm^#M\xa5R!\x18\x0cr\xfd\xfau\xa2\xd1(W\xaf^\xa5\xa5\xa5\x85r\xb9\x0c\
|
||||
@KK\x0b7n\xdc \x1a\x8dr\xed\xda5\x9a\x9a\x9aXZZB\x92\x00\x12\x89\xc4\x16 f\
|
||||
\x81\x10XC\xab=\xe9\xd3:\x86\xea\xef\xef7\xf1x\xdc\xec\xdf\xbf_\x80ZZZ466\
|
||||
\xe6\xe7\xf3ye\xb3Y\xdd\xb9s\xc7\xef\xec\xec\x14\xa0\xd6\xd6V\xc5\xe3q\xc5\
|
||||
\xe3\xf1\xf5\xf6\x0e\xdc\x05\x1aW\xaf[\xaf\x03\xa0\xab>,\xd6\x0b\xaa\xb5\xb5\
|
||||
\xf5\xb7\xe1p\xf8\xd7\xc0\xec\x89\x13\'\x94\xcb\xe5\x94\xc9dt\xea\xd4)\x01o\
|
||||
\x80_\x02\x9fm\xb4q]\xf7w@\xf7\x9ao\x17\xe0 4\xfc\x15\x92\xc6\x98\x1f\x02\
|
||||
\x15\xd7u\xbf\xd9\xdd\xdd\x9d\x7f\xf3\xe6\xcdOw\xef\xde\xed477\xefK&\x93\xdd\
|
||||
w\xef\xde\xc5u]<\xcf\xc3\xb6\xed\x97\xc6\x98\x91X,\xd6$\xe9\xabsssm\xb5Z\xed\
|
||||
/+++\x97\x80\x04\xab\xa8\x18~\x02v=\x8b\x8d\xf3\xf9\xa3:m\xb7\xf6\xf4\xf4|/\
|
||||
\x10\x08\xfc\tPww\xf7\xf2\xb6m\xdb\x96\x1d\xc7\x11\xf0\x07\xc7q\xbe\r\xbc\
|
||||
\x0b\xec\x05\xbe\xb3\x0eK}\x0c\xacgp\x05,\xad\x0eh\x0b0\x16\xfc~\x8d^SSS\xed\
|
||||
\xc0\x04\xf0\x95D"\xb1\xf1\xdb2\xed\xfb\xfe\x7f\x80\x99\xba\xead\xfd\xa2\x16\
|
||||
\xab?\x0b\x0b\xe0\xbf\xf5\x19yJo\xfcW\xe3\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\x18\x00\x00\x00\x18\x08\x06\
|
||||
\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
|
||||
\x06\x04IDATH\x89\xb5\x95Mh\x1b\xdb\x15\xc7\xffs\xe7\x8e4\xfa@V%K\xc6\r\x91\
|
||||
\x12^\xeb$d\xf3\x08\xc1V\xa8\xc9\xb3i\xe2x\x97\x10(]$\xf0\xc0!i> i\xc0\x8bR(\
|
||||
\xcf\xdd\xb4\xf1\xaad\xd7E\x9cdS\x08\xdd\x98.\x82\xbc0\xe9\xc3q)\xc6\xa4v\
|
||||
\x82\xbf\x82\x15;\x93\x91,[c\xcb\x965\xdfsgn\x17\x0f\xf9\xb9\xa4o\xd7\x1e\
|
||||
\x18\xb8w8s\x7f\xf7\xf0\xff\x9f3\xc0\xff9\x84\xc3\x9b\xb1\xb1\xb1\xdf\xf8\
|
||||
\xbe\xff\xc7\xd7\xaf_C\x92$\x00\x80\xe388u\xea\x14\xb2\xd9\xec\xb7\xb7n\xdd\
|
||||
\xea\x07\x80\'O\x9e\x145M\x1b\\XX@8\x1c\x06\x00x\x9e\x87\xde\xde^PJ\x7f\x7f\
|
||||
\xe3\xc6\x8d\x91\xcfH\xe3\xe3\xe3\xc3\xf7\xee\xddc\xf9|\x9e\x038xB\xa1\x10/\
|
||||
\x14\n\xfc\xfa\xf5\xeb\x7fo\xe5^\xbbv\xad\xd8\xdb\xdb{\x90C\x08\xe1\xa2(\xf2\
|
||||
\\.\xc7o\xdf\xbe\xcd\xc6\xc7\xc7\x7f\xdb\xca\xa5\xad\x85\xef\xfb_\x11B\xc4\
|
||||
\xcd\xcdMv\xf5\xeaUZ(\x14P.\x97\xf1\xfc\xf9s\xcc\xcd\xcdA\x10\x04\xab\x95\
|
||||
\xbb\xb6\xb6f\xce\xcc\xcc\xe0\xf4\xe9\xd3\xb8s\xe7\x0e&\'\'Q\xab\xd50;;\xcb\
|
||||
\x04A\xa0\x8c\xb1~\x00\x7f\xf8\x0f\x00\xa5t\xbb^\xaf#\x91H\xd0\x0b\x17.\xe0\
|
||||
\xca\x95+X[[\xc3\xabW\xaf\xf0\xe9\xd3\'tuu}q\xe6\xcc\x99\xaf\t!\xac\xd9l\x9e\
|
||||
x\xf3\xe6\rN\x9e<\x89\x9b7o\x82R\nUUQ*\x95\xe8\xee\xee.(\xa5\xdb\x9fU \xcb2\
|
||||
\x18c\xd04\r333\xd8\xda\xda\x82\xef\xfb\xd8\xde\xde\x86,\xcb,\x9dNwy\x9e\xf7\
|
||||
\\\x10\x04\xa4R)$\x93Io~~^z\xfc\xf81\x16\x17\x17!\x08\x024M\x83m\xdb\x08\x85\
|
||||
B\xf8\x0c\xe0\xba.8\xe7 \x84@\x14E\xd4\xebuX\x96\x85 \x08\x10\x04\x01U\x14%0\
|
||||
M\xd3\x01\x80X,\x16\xe6\x9cK\xb6mcuu\x15\x9a\xa6!\x9dN\x1f\x18\x831v\x00 \
|
||||
\xad\xc5\x87\x0f\x1f\x9a\x8a\xa2@\x14Ed\xb3Yx\x9e\x87b\xb1\x08\xc7q\xd0\xd3\
|
||||
\xd3\x83l6\xfb\x8fb\xb1\x18-\x16\x8b\xd1l6\xfb\xea\xdc\xb9s0\x0c\x03\x13\x13\
|
||||
\x138v\xec\x18\x18cp]\x17\xd5j\x15+++\x07\x00\x11\x00\xee\xde\xbd\xfb\xbb\
|
||||
\xb7o\xdf\xde\x92e9\xd2\xdd\xdd\r]\xd7111\x81J\xa5\x02Y\x96q\xf6\xecY\xd8\
|
||||
\xb6M\xdf\xbd{w\x04\xc0\x85\xae\xae\xae\xaf\x92\xc9d\xdb\xd2\xd2\x12j\xb5\
|
||||
\x1a4MC>\x9fGGG\x07$I\x82\xaa\xaa\xd3\xa5R\xe9\xe5\x01\xa0\xbb\xbb\xfbo\xab\
|
||||
\xab\xab?\xda\xda\xdab\xc9d\x92\xcc\xce\xceBQ\x14\xc8\xb2\x8c\\.\xc7\xc2\xe1\
|
||||
0\xd1u=a\x9a\xe6\xb9x<\xfe\xb3x<\xde\xe6\xba.\x0c\xc3`\xf5z\x9d\xec\xed\xedA\
|
||||
\x14Ed2\x19\xa8\xaa\x8ar\xb9\xdcv\xff\xfe\xfd\xad\xa9\xa9\xa9E\n\x00\xe1p\
|
||||
\xf8c\xa5R\xf9\xd24MZ(\x14\xd0\xdf\xdf\x8fK\x97.AUU\xac\xaf\xaf\xd3\x85\x85\
|
||||
\x85R4\x1a-\xa7R\xa9>\x00(\x97\xcbS\x8dF\xa3#\x9f\xcf\x9f\x18\x18\x18\x80(\
|
||||
\x8a\xd0u\x1d\xd5j\x15\xef\xdf\xbf\xf7r\xb9\xdcO\x1b\x8d\xc6_\x00\xfc\x15\
|
||||
\x00\xf0\xf0\xe1\xc3\xb9T*\xc5\x07\x06\x06x\xadV\xe3\x86a\xf0\xf5\xf5u><<\
|
||||
\xcc\xdb\xda\xda8\x80a\x00\x91C\r\x98\x04p\xbb\xaf\xaf\x8f+\x8a\xc2\x9b\xcd&\
|
||||
\xd74\x8d\x8f\x8c\x8cpY\x96y.\x97\xe3\x0f\x1e<X>p\x11!\x04\x94R\xe8\xba\x0eU\
|
||||
U\x11\x89DP*\x95\xa0\xebz\xcb\x19\x0c\x80{\xa8\xf1=\x00\xbe\xe38PU\x15\x86a`\
|
||||
cc\x03{{{\x90$\t\x82 \x80\x10\xf2\xbdM\x1d\xc7qL\xd3\x84\xa6i\xd8\xdc\xdc\
|
||||
\x84,\xcbX^^\x86i\x9a\xadY\xf3+\x00\x83\x87\x00\xe3\x00~\xec8\x0e*\x95\n<\
|
||||
\xcf\xc3\xca\xca\nvvv`\x9a&$I\x82\xe38.\x00\x88ccc#/^\xbc\xf89\x80x\xa1P@gg\
|
||||
\'l\xdbF\xb5ZE\xbd^\xc7\xf2\xf2\xb2\xc79\xef\xe8\xe9\xe9\xf9\xc9\xf1\xe3\xc7\
|
||||
\x91\xcf\xe7q\xf4\xe8\xd1/\xca\xe5r6\x91Hx\xdd\xdd\xdd\xa2\xeb\xba(\x97\xcb\
|
||||
\x90$\t\xed\xed\xedh4\x1a\xa8T*\xe2\xa3G\x8fb\x941\xf6\xcd\xe2\xe2".^\xbc\
|
||||
\xe8\x9f?\x7f^\xacV\xabH&\x93p\x1c\x07\x9cs\xd8\xb6-\xe5r9\x0c\x0e\x0en\xeb\
|
||||
\xba\xfe-\x80 \x1e\x8f\xf7U\xab\xd5\xaca\x18\x92i\x9ap\x1c\x07\xba\xae#\x1a\
|
||||
\x8d\xe2\xf2\xe5\xcb`\x8c\xf9/_\xbelg\x8c}C\xa6\xa7\xa7\xc19G&\x93\x11=\xcf\
|
||||
\xc3\xce\xce\x0el\xdb\xc6\xce\xce\x0e\x18c\xa0\x94\x82\x10\x82\xfd\xfd\xfd\
|
||||
\x7f\x8d\x8e\x8e\xfebtt\xf4\x97\xcdf\xf3\x9f\x94R\xb8\xae\x8bz\xbd\x0e\xdb\
|
||||
\xb6\xd1h4\xa0(\n,\xcbB&\x93\x11\x01`zz\x1a\xa4%\x8aeY`\x8c\x81\x10\x02\xc7q\
|
||||
@\x08\x81 |\xf7\xbb\xe0\x9c\x83s\x1e:\xa4A\xb85V\x04A\x80\xe38\x10\x04\x01\
|
||||
\xa1P\x08\x9e\xe7\xc1\xb2\xbe\x1b\xbc\x92$\xa1\xd5\x07(\x95J\x90e\x19\xae\
|
||||
\xebbww\x17\x86a\xc0\xf7}\xfcPPJa\x18\x06VWW\x11\n\x85`\x9a&,\xcb\xc2\xdc\
|
||||
\xdc\x1cJ\xa5\xd2\xc1\\\xa2\xad\x1b\x8a\xa2\x88T*\x85X,\x86L&\x83\x8f\x1f?"\
|
||||
\x08\x02\xc8\xb2\xfc_AA\x10\x80R\x8a\xce\xceNttt@UUloo\x831\x06\xcb\xb2\xbe\
|
||||
\xb7i$\x12A\x10\x04PU5XZZ"\xd1h\x14\xf1x\x1c\x8a\xa2 \x08\x02\xd4j5?\x9dN\
|
||||
\x8b\x00\xda\x0f\x1d\xdeN)E\xbd^\xf7\xe7\xe7\xe7\xc5t:\rUU\xd1l6\xc19\x87\
|
||||
\xa2(\x81\xef\xfb$\x12\x89\x80Z\x965\x7f\xe4\xc8\x91\x13\x1b\x1b\x1b\x91\xa9\
|
||||
\xa9)p\xce\x11\x04\xc1A\x89\x92$\x89\xf1x\x1c\x00\xa6Z\x00B\xc8\xebX,vV\x92$\
|
||||
qrr\x12\xbe\xefC\x92\xa4\xc3\xba\x91\xce\xceN\xc7\xb2\xace\x01\x00\x86\x86\
|
||||
\x86\xe6"\x91\xc8\x97-q\x0eG"\x91@\xa3\xd1\xf8\xf3\xb3g\xcf\xee\x1c~?44\xf4\
|
||||
\xa7D"\xf1\xeb\xfd\xfd\xfd\xcf\xbe\x91e\x19\xb6m\xaf<}\xfa\xf4\xd4\x0f\x8a\
|
||||
\xf8\xbf\x8a\x7f\x03\x7f_\x17\xc3%\x00\xe7\xe4\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\x18\x00\x00\x00\x18\x08\x06\
|
||||
\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
|
||||
\x04(IDATH\x89\xb5\x95Mh\\U\x14\xc7\x7f\xf7\xdey\xf7\xcd\xbcy\x99\xc9\xb43\
|
||||
\x93\x99\xc4iM\x02~\x97R\xa9Q(\x82\x16*\xb5\xeaFP\x8b;\x0b\xe2\xb6\xba(\xa8\
|
||||
\xa0\xe0F\x17"\xaeD\xa9\x8a\x04\x84\n]\x16\x05\xadt\xe1B\xa8H\x8a\x0bK\xc4\
|
||||
\xd6\x966\xb553\x93\xc9L\xf3\xe6\xcd\xfb\xb8\xd7EZ\x9b\xa6%)-\x1e\xb8\xab\
|
||||
\xcb\xff\xfc\xce=\xfc\xcf\xb9\xf0?\x87X\xe7\xfe\xc1R\xa9\xf4\xaa\xeb\xba\xdb\
|
||||
\xad\xb5\x8b\xd7\t\x85(\xc6q<\xd3j\xb5\x0e\x02\xbf\xdd\x16}lll\xbf7\xe4\x9d\
|
||||
\x92\xc8(Cf\xe1\xdaaAB\x94\xf3\xbd\xd3\xf5z\xfd\xc0Z92k]*\xa5\xee2=\xb3\xd9\
|
||||
\xdcg\x94y\xc1\x0c\xb3\x04(`\xae\x08\xdf\x0f\xb0\xcdh\xb3\xde\xa8\x1b\xb7\r\
|
||||
\x00B\x81\xe8\xb3\x05\x9f7\x1c\x98-\x816\xf0g\x15~\xbf\x08\xcdN`\x8c\xe9\xdf\
|
||||
\t`9b\xe0\xaf\x1c\xfc4\t\x19\x0b\x84`\xe3[\x92\xde\x1a \x05Z1\x9ci\x82\xb2Pr\
|
||||
\xc0\xc2\xfa\x1eY\x07 \xa5\xcc\xd9\x8c\xcd\xf3\x03p\xa2\x0f\x97\xcf\x02X\xa4\
|
||||
\x15tbp\xdc\xbc\x94\xd2[+\x87Z\xb3\xf04U\xd2\x95%\xdf\xf8\xa1j\x89f\x14\x86U\
|
||||
\xc2Tx}\xe7\xe4\x90?4g\xb5:\x11\x06\xfdo\xa2(\x9a\xbd-@\x14E\xedJ\xb9RP\xae\
|
||||
\xba\xa7\x9f\x86\x15\xadu\xe48N`\x14*_\xf0\xdb^.\xf7m\xb3\xd9<\x02\x04W$7\
|
||||
\xf4l-@\xaeX,N%I\xb2\xa7\xd7\xeb\xedJ\xd3tP.\x97\xa7}\xdf\xff\xb5\xdb\xedn\
|
||||
\x1d\x0c\x06\xf7Zk\x17\xb4\xd6\x97\x06\x83\xc1E\x96\xadpS\xc8\xcd\xa2\xa8\
|
||||
\x94z\xaeV\xab\x1d\xd2Z[\xaduk\xd3\xa6M\xef\x00\xdb\x81m\x8dF\xe3m\xd7u\xe7\
|
||||
\x1d\xc7\xb1###\x87\x95R\xcf\x03\xa5\xf5\x92^%+\xa5\xd4\xee\xb1\xb1\xb1O\x94\
|
||||
RK\x9e\xe7\x85\xe5r\xf9K\xe0\xb1\x15/~\xa4R\xa9|\x9e\xcf\xe7\x97\xa4\x94\xc1\
|
||||
\xe8\xe8\xe8A\xa5\xd43\\3\xcd\x7f\xaf\xb8\xa1E\xf9|~g\xa1Px\xa5\xd9l\xee\xd5\
|
||||
Z\xf7]\xd7=\x94$\xc9g\x83\xc1\xe08W\xcc\t\\\x00\xe6\xb4\xd6J\x081\xd9\xedv\
|
||||
\xa7J\xa5\x92\'\x84h\xc7q|ze>\x05\x8c4\x1a\x8d\x1d\xb5Zm\x8b\xef\xfb\x0f\'I\
|
||||
\xf2b\xbf\xdf\x7fVJ9_.\x97g\x93$9\xd2\xe9t\x8e\xb2<\r\xe2juq\x1c7\xb3\xd9l\
|
||||
\xb1T*\xd5\xc20TI\x92l\xd5Z\xfb\xd5j5;222\xe1\xfb\xfe\xf8\xe2\xe2bOx\x9ew\
|
||||
\xc0q\x9c\x971\xe9\x03\x12\xd3\t\x07Q\xa1\x1f%\xee\xb0\xe2g<\xbf\x90\x085c\
|
||||
\x92\xf8\xa3 \x08fVV\xe6y\xde\xd6\x8c\x94\xfbQj\xaa/M\x10/\xf4\xb6\x93u\x02\
|
||||
\'\xe7-(c6d\x91\xa7\xa38\x9e\xa6^\xaf\x1f\x93B$\x08eqr-\x94\x9e\xc7\xcd\xcfS\
|
||||
\x1a\xb5 \xedP\xde\xebOLL\xbc\xb6\xba\x95\xe3\xe3\xe3\xfb\xfc\xc2P\x1f\xb0%T\
|
||||
\xb8\x91Lg\x18uy\x03*\xc8\x81E\x8a\xb4^\xaf\x1f\xcb\x18c\x02a\xad\xe2\xa1]_\
|
||||
\xf1\xe9w\xd3\xfc8\x93\xc5u\xef\xc6\xcd|\xc8\xc7/y\x9c=\x11\x00\xd1ML\x11-\
|
||||
\xd94\xad\x91\xe9\x9fdj\xda`\x92\x90T\x8cR\xe8\xbd\xc9\xc9G?\x10\x17\x9e0\
|
||||
\xc6\x04\xd7V\x85\x10\x97\xd8\x81\xcf?\xdb\x9e$%O\x7fI!\xd7\x9cC,\x08\t\xf10\
|
||||
C\x01dw\x82\xaat\t\x83K\xc8\n\x10\xc2\xca]\x94\xda9R&\xb1\xbc\x8e\xa4\xcdP^#\
|
||||
\xe4\x9a\x00@d\x10)x\xe1,K\x93\x92\x8c? %\x8b\x06\xe8\x01d\x84\x109\x0bp\xfa\
|
||||
\xf8n\xf6\xbe\xe7S\x19\x85\xe0\xf2\x06\x10\xd0\x9e\x83\x0c\x1e,+\xae\xcb,\
|
||||
\x84\xa3\x85t:\xc4\xb9\xb7\xf8\xe5\xf1S\xa4n\x04lD3K\x0f,Y!D.c\x8c9\xa7\xb4>\
|
||||
C\xd8\xde#\x0e\xbf\x0b\xb0\xc0\x95\xf9\xb0\x90\xb7\xc5\xe1\xb3I\x92\xb4V\x03\
|
||||
\xe28n\xe7\x90\x7f,Jq\xff\xfb\xe2\xfc\x0e`\x89\xe5\x9d$\xb0hW\xe9\xb61\xe6\
|
||||
\x9c\x00\x9e\xaeV\xab{\xa5\x94\rk\xedu\xbf\x93\x10\xa2\x10\x04\xc1\xd1n\xb7\
|
||||
\xfb\x05p~\x15c\xd4\xf7\xfd}\xbe\xef?e\xad\xed\xad\xd2e\xd34\xfd{~~\xfe\xeb\
|
||||
\xf5z|\xc7\xf1/Y%\x9eF\x90EP\xda\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\x18\x00\x00\x00\x18\x08\x06\
|
||||
\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
|
||||
\x01\x9eIDATH\x89\xed\x95\xcfJ\x02A\x1c\xc7?\xad\xbb\xb3\xb1-\x14\xae\x19E\
|
||||
\xed!\xf5)\xbaE\xbd@\x97\x0e\xdez\x84.\x82\xd7.\xbd\x81\xb7\x8e\xddD\x10*\
|
||||
\x83\x12z\x06\xa30<\x97\xb4\x14Ibh\xb3k\x17\x15u\xcdv\xadc\xdf\xd303\xdf\xef\
|
||||
g\x86\xdf\xfc\x81\x7f\xfd\xa0\xb9\xa1\xf6\x0e\xb0\x0b\xac\x00\xed\x19\xf3\
|
||||
\x04\xf0\x02\x94\x80+\x00uhp_U\xd5m)\xe52\xd0\x99\x11\xa0)\x8a\xfa\xeayrq\
|
||||
\x12`CJ\xb9~tt(67\xf78?\x7f\xc64\x83'\x9b\xe62\xb7\xb7g\\^\x1e/\x00\x1b\xfd\
|
||||
\xfea\xc0\x07\xf0a\x18I\xb1\xba\xba\x85m?b\x18\xc1\x01KKk<==\x0cr&\x01\x00\
|
||||
\xb8\xb9\xb9G\xd3\xae\xb1,\x07\xcf\x0b\x0e\xd0u\x0bM\xbb\x03\xe8~7\xa7\x00\
|
||||
\xbc\x15\n\xf9\xee\xac\xba\xb88\xeb\x02\xef\xbd,\x00\x94qJ\xbb\xfd\x19|\xd9\
|
||||
\x01\xbc>\x80\x10bf\xc0$\xaf\xaf\x06\x8dF\x03\x80f\xb3\x19*\xdc4\xcd\x81w* \
|
||||
\x97\xcbQ.\x97i\xb5Z\xa1\x00\x86aP\xab\xd5`\xac\xc8>@\xa5R\xa1Z\xad\xe2\x859\
|
||||
B\x80\xa2(t:\xfe\xfb\xe9\x03d2\x19\xd2\xe94\xf5z=\x14 \x1e\x8f\x93\xcf\xe7\
|
||||
\xc9f\xb3\xd3\x01\x89D\x82d2\x89m\xdb\xa1\x00B\x08R\xa9\x14\x8c\xbeo~\x80\
|
||||
\xae\xeb\x03CX\xf5\xbc#5\xf0\x1d\xd3h4\x1a:\xb8/\xcb\xb2`\xca\x0e\xe6\x81\
|
||||
\xf9b\xb1\x08\x80\xe38\xa1\xc2c\xb1\x18\xa5R\t@\xefe1N;\xf9\x8b\xe7:\x12\x89\
|
||||
\xbc\xba\xae{\x05\x1c\xc0\xe8\x0eN\xa5\x94\x0e\xbf\xfcp\\\xd7\xed\x7f8\xff\n\
|
||||
\xa6/8\xf7\xb7\xf5\xb4m\x07\xcd\x00\x00\x00\x00IEND\xaeB`\x82"
|
||||
|
||||
def getShowFillingBitmap():
|
||||
return BitmapFromImage(getShowFillingImage())
|
||||
|
||||
def getShowFillingImage():
|
||||
stream = cStringIO.StringIO(getShowFillingData())
|
||||
return ImageFromStream(stream)
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def getIconData():
|
||||
return \
|
||||
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
|
||||
\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\
|
||||
\xb8IDATX\x85\xed\x97\xcd\x12\x83 \x0c\x84w\x91\xf7\xd6>x\x9b\x1e,\x07Gl\x93\
|
||||
4N8\xb07gH\xf8\xc8\x1fB\x96\x05\x99*\xa9\xbbO\x80\x11\x00\xea\xaf\x05\xf2z\
|
||||
\x8a\xc71\xcb\xc2\x10\x80]\x9bq{\xfd\xfa\xf4\x14\xa8\x01DV\x88\xacy\x00w)\
|
||||
\x1d@Y\x84\x1am\x87/m\xf7\x04\x02\x00blX\x12\xa8\xde>\x8fR\x05\x80o\x04\xaai\
|
||||
rP\xf3\xa6\xb3\x1c\xa8\x08[\x02\xd9\'\'\x1f\xb7\x00\xa4G\x80hg\xbf\x88\x80\
|
||||
\xa5\x06>\x8e\xd4\x96\xa4\xe66\xec\x19\xe2|\xdby\xbb)=\x05\xe9\x00\xa1\x93p\
|
||||
\x97mr\x0c\x14\x81\x8b\xfe\xb7\xc8\xe3",\x05\xda\x7f\xc0.\xc0\xffg\xf7\x8b\
|
||||
\xf3i6\x01\xb2\x01\xde\x86\xde%]y\x9b\xef$\x00\x00\x00\x00IEND\xaeB`\x82'
|
||||
|
||||
def getIconBitmap():
|
||||
return BitmapFromImage(getIconImage())
|
||||
|
||||
def getIconImage():
|
||||
stream = cStringIO.StringIO(getIconData())
|
||||
return ImageFromStream(stream)
|
||||
|
||||
def getIconIcon():
|
||||
icon = EmptyIcon()
|
||||
icon.CopyFromBitmap(getIconBitmap())
|
||||
return icon
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
@@ -841,11 +841,15 @@ WXK_CTRL_Z = (ord('Z')+1) - ord('A')
|
||||
|
||||
nav = (
|
||||
wx.WXK_BACK, wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_UP, wx.WXK_DOWN, wx.WXK_TAB,
|
||||
wx.WXK_HOME, wx.WXK_END, wx.WXK_RETURN, wx.WXK_PRIOR, wx.WXK_NEXT
|
||||
wx.WXK_HOME, wx.WXK_END, wx.WXK_RETURN, wx.WXK_PRIOR, wx.WXK_NEXT,
|
||||
wx.WXK_NUMPAD_LEFT, wx.WXK_NUMPAD_RIGHT, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN,
|
||||
wx.WXK_NUMPAD_HOME, wx.WXK_NUMPAD_END, wx.WXK_NUMPAD_ENTER, wx.WXK_NUMPAD_PRIOR, wx.WXK_NUMPAD_NEXT
|
||||
)
|
||||
|
||||
control = (
|
||||
wx.WXK_BACK, wx.WXK_DELETE, wx.WXK_INSERT, WXK_CTRL_A, WXK_CTRL_C, WXK_CTRL_S, WXK_CTRL_V,
|
||||
wx.WXK_BACK, wx.WXK_DELETE, wx.WXK_INSERT,
|
||||
wx.WXK_NUMPAD_DELETE, wx.WXK_NUMPAD_INSERT,
|
||||
WXK_CTRL_A, WXK_CTRL_C, WXK_CTRL_S, WXK_CTRL_V,
|
||||
WXK_CTRL_X, WXK_CTRL_Z
|
||||
)
|
||||
|
||||
@@ -1761,27 +1765,39 @@ class MaskedEditMixin:
|
||||
## Initially populated with navigation and function control keys:
|
||||
self._keyhandlers = {
|
||||
# default navigation keys and handlers:
|
||||
wx.WXK_BACK: self._OnErase,
|
||||
wx.WXK_LEFT: self._OnArrow,
|
||||
wx.WXK_RIGHT: self._OnArrow,
|
||||
wx.WXK_UP: self._OnAutoCompleteField,
|
||||
wx.WXK_DOWN: self._OnAutoCompleteField,
|
||||
wx.WXK_TAB: self._OnChangeField,
|
||||
wx.WXK_HOME: self._OnHome,
|
||||
wx.WXK_END: self._OnEnd,
|
||||
wx.WXK_RETURN: self._OnReturn,
|
||||
wx.WXK_PRIOR: self._OnAutoCompleteField,
|
||||
wx.WXK_NEXT: self._OnAutoCompleteField,
|
||||
wx.WXK_BACK: self._OnErase,
|
||||
wx.WXK_LEFT: self._OnArrow,
|
||||
wx.WXK_NUMPAD_LEFT: self._OnArrow,
|
||||
wx.WXK_RIGHT: self._OnArrow,
|
||||
wx.WXK_NUMPAD_RIGHT: self._OnArrow,
|
||||
wx.WXK_UP: self._OnAutoCompleteField,
|
||||
wx.WXK_NUMPAD_UP: self._OnAutoCompleteField,
|
||||
wx.WXK_DOWN: self._OnAutoCompleteField,
|
||||
wx.WXK_NUMPAD_DOWN: self._OnAutoCompleteField,
|
||||
wx.WXK_TAB: self._OnChangeField,
|
||||
wx.WXK_HOME: self._OnHome,
|
||||
wx.WXK_NUMPAD_HOME: self._OnHome,
|
||||
wx.WXK_END: self._OnEnd,
|
||||
wx.WXK_NUMPAD_END: self._OnEnd,
|
||||
wx.WXK_RETURN: self._OnReturn,
|
||||
wx.WXK_NUMPAD_ENTER: self._OnReturn,
|
||||
wx.WXK_PRIOR: self._OnAutoCompleteField,
|
||||
wx.WXK_NUMPAD_PRIOR: self._OnAutoCompleteField,
|
||||
wx.WXK_NEXT: self._OnAutoCompleteField,
|
||||
wx.WXK_NUMPAD_NEXT: self._OnAutoCompleteField,
|
||||
|
||||
# default function control keys and handlers:
|
||||
wx.WXK_DELETE: self._OnDelete,
|
||||
wx.WXK_INSERT: self._OnInsert,
|
||||
WXK_CTRL_A: self._OnCtrl_A,
|
||||
WXK_CTRL_C: self._OnCtrl_C,
|
||||
WXK_CTRL_S: self._OnCtrl_S,
|
||||
WXK_CTRL_V: self._OnCtrl_V,
|
||||
WXK_CTRL_X: self._OnCtrl_X,
|
||||
WXK_CTRL_Z: self._OnCtrl_Z,
|
||||
wx.WXK_DELETE: self._OnDelete,
|
||||
wx.WXK_NUMPAD_DELETE: self._OnDelete,
|
||||
wx.WXK_INSERT: self._OnInsert,
|
||||
wx.WXK_NUMPAD_INSERT: self._OnInsert,
|
||||
|
||||
WXK_CTRL_A: self._OnCtrl_A,
|
||||
WXK_CTRL_C: self._OnCtrl_C,
|
||||
WXK_CTRL_S: self._OnCtrl_S,
|
||||
WXK_CTRL_V: self._OnCtrl_V,
|
||||
WXK_CTRL_X: self._OnCtrl_X,
|
||||
WXK_CTRL_Z: self._OnCtrl_Z,
|
||||
}
|
||||
|
||||
## bind standard navigational and control keycodes to this instance,
|
||||
@@ -2780,8 +2796,12 @@ class MaskedEditMixin:
|
||||
#### dbg('Registering numeric navigation and control handlers (if not already set)')
|
||||
if not self._keyhandlers.has_key(wx.WXK_DOWN):
|
||||
self._SetKeycodeHandler(wx.WXK_DOWN, self._OnChangeField)
|
||||
if not self._keyhandlers.has_key(wx.WXK_NUMPAD_DOWN):
|
||||
self._SetKeycodeHandler(wx.WXK_DOWN, self._OnChangeField)
|
||||
if not self._keyhandlers.has_key(wx.WXK_UP):
|
||||
self._SetKeycodeHandler(wx.WXK_UP, self._OnUpNumeric) # (adds "shift" to up arrow, and calls _OnChangeField)
|
||||
if not self._keyhandlers.has_key(wx.WXK_NUMPAD_UP):
|
||||
self._SetKeycodeHandler(wx.WXK_UP, self._OnUpNumeric) # (adds "shift" to up arrow, and calls _OnChangeField)
|
||||
|
||||
# On ., truncate contents right of cursor to decimal point (if any)
|
||||
# leaves cursor after decimal point if floating point, otherwise at 0.
|
||||
@@ -3205,25 +3225,25 @@ class MaskedEditMixin:
|
||||
keycode = event.GetKeyCode()
|
||||
sel_start, sel_to = self._GetSelection()
|
||||
entry_end = self._goEnd(getPosOnly=True)
|
||||
if keycode in (wx.WXK_RIGHT, wx.WXK_DOWN):
|
||||
if keycode in (wx.WXK_RIGHT, wx.WXK_DOWN, wx.WXK_NUMPAD_RIGHT, wx.WXK_NUMPAD_DOWN):
|
||||
if( ( not self._isTemplateChar(pos) and pos+1 > entry_end)
|
||||
or ( self._isTemplateChar(pos) and pos >= entry_end) ):
|
||||
## dbg("can't advance", indent=0)
|
||||
return False
|
||||
elif self._isTemplateChar(pos):
|
||||
self._AdjustField(pos)
|
||||
elif keycode in (wx.WXK_LEFT,wx.WXK_UP) and sel_start == sel_to and pos > 0 and self._isTemplateChar(pos-1):
|
||||
elif keycode in (wx.WXK_LEFT, wx.WXK_UP, wx.WXK_NUMPAD_LEFT, wx.WXK_NUMPAD_UP) and sel_start == sel_to and pos > 0 and self._isTemplateChar(pos-1):
|
||||
## dbg('adjusting field')
|
||||
self._AdjustField(pos)
|
||||
|
||||
# treat as shifted up/down arrows as tab/reverse tab:
|
||||
if event.ShiftDown() and keycode in (wx.WXK_UP, wx.WXK_DOWN):
|
||||
if event.ShiftDown() and keycode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN):
|
||||
# remove "shifting" and treat as (forward) tab:
|
||||
event.m_shiftDown = False
|
||||
keep_processing = self._OnChangeField(event)
|
||||
|
||||
elif self._FindField(pos)._selectOnFieldEntry:
|
||||
if( keycode in (wx.WXK_UP, wx.WXK_LEFT)
|
||||
if( keycode in (wx.WXK_UP, wx.WXK_LEFT, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_LEFT)
|
||||
and sel_start != 0
|
||||
and self._isTemplateChar(sel_start-1)
|
||||
and sel_start != self._masklength
|
||||
@@ -3234,7 +3254,7 @@ class MaskedEditMixin:
|
||||
event.m_shiftDown = True
|
||||
event.m_ControlDown = True
|
||||
keep_processing = self._OnChangeField(event)
|
||||
elif( keycode in (wx.WXK_DOWN, wx.WXK_RIGHT)
|
||||
elif( keycode in (wx.WXK_DOWN, wx.WXK_RIGHT, wx.WXK_NUMPAD_DOWN, wx.WXK_NUMPAD_RIGHT)
|
||||
and sel_to != self._masklength
|
||||
and self._isTemplateChar(sel_to)):
|
||||
|
||||
@@ -3247,8 +3267,8 @@ class MaskedEditMixin:
|
||||
## dbg('using base ctrl event processing')
|
||||
event.Skip()
|
||||
else:
|
||||
if( (sel_to == self._fields[0]._extent[0] and keycode == wx.WXK_LEFT)
|
||||
or (sel_to == self._masklength and keycode == wx.WXK_RIGHT) ):
|
||||
if( (sel_to == self._fields[0]._extent[0] and keycode in (wx.WXK_LEFT, wx.WXK_NUMPAD_LEFT) )
|
||||
or (sel_to == self._masklength and keycode in (wx.WXK_RIGHT, wx.WXK_NUMPAD_RIGHT) ) ):
|
||||
if not wx.Validator_IsSilent():
|
||||
wx.Bell()
|
||||
else:
|
||||
@@ -3358,11 +3378,11 @@ class MaskedEditMixin:
|
||||
# If trying to erase beyond "legal" bounds, disallow operation:
|
||||
if( (sel_to == 0 and key == wx.WXK_BACK)
|
||||
or (self._signOk and sel_to == 1 and value[0] == ' ' and key == wx.WXK_BACK)
|
||||
or (sel_to == self._masklength and sel_start == sel_to and key == wx.WXK_DELETE and not field._insertRight)
|
||||
or (sel_to == self._masklength and sel_start == sel_to and key in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and not field._insertRight)
|
||||
or (self._signOk and self._useParens
|
||||
and sel_start == sel_to
|
||||
and sel_to == self._masklength - 1
|
||||
and value[sel_to] == ' ' and key == wx.WXK_DELETE and not field._insertRight) ):
|
||||
and value[sel_to] == ' ' and key in (wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE) and not field._insertRight) ):
|
||||
if not wx.Validator_IsSilent():
|
||||
wx.Bell()
|
||||
## dbg(indent=0)
|
||||
@@ -3374,7 +3394,7 @@ class MaskedEditMixin:
|
||||
and sel_start >= start # and selection starts in field
|
||||
and ((sel_to == sel_start # and no selection
|
||||
and sel_to == end # and cursor at right edge
|
||||
and key in (wx.WXK_BACK, wx.WXK_DELETE)) # and either delete or backspace key
|
||||
and key in (wx.WXK_BACK, wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE)) # and either delete or backspace key
|
||||
or # or
|
||||
(key == wx.WXK_BACK # backspacing
|
||||
and (sel_to == end # and selection ends at right edge
|
||||
@@ -4050,21 +4070,21 @@ class MaskedEditMixin:
|
||||
## dbg('choices:', field._choices)
|
||||
## dbg('compareChoices:', field._compareChoices)
|
||||
choices, choice_required = field._compareChoices, field._choiceRequired
|
||||
if keycode in (wx.WXK_PRIOR, wx.WXK_UP):
|
||||
if keycode in (wx.WXK_PRIOR, wx.WXK_UP, wx.WXK_NUMPAD_PRIOR, wx.WXK_NUMPAD_UP):
|
||||
direction = -1
|
||||
else:
|
||||
direction = 1
|
||||
match_index, partial_match = self._autoComplete(direction, choices, text, compareNoCase=field._compareNoCase, current_index = field._autoCompleteIndex)
|
||||
if( match_index is None
|
||||
and (keycode in self._autoCompleteKeycodes + [wx.WXK_PRIOR, wx.WXK_NEXT]
|
||||
or (keycode in [wx.WXK_UP, wx.WXK_DOWN] and event.ShiftDown() ) ) ):
|
||||
and (keycode in self._autoCompleteKeycodes + [wx.WXK_PRIOR, wx.WXK_NEXT, wx.WXK_NUMPAD_PRIOR, wx.WXK_NUMPAD_NEXT]
|
||||
or (keycode in [wx.WXK_UP, wx.WXK_DOWN, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN] and event.ShiftDown() ) ) ):
|
||||
# Select the 1st thing from the list:
|
||||
match_index = 0
|
||||
|
||||
if( match_index is not None
|
||||
and ( keycode in self._autoCompleteKeycodes + [wx.WXK_PRIOR, wx.WXK_NEXT]
|
||||
or (keycode in [wx.WXK_UP, wx.WXK_DOWN] and event.ShiftDown())
|
||||
or (keycode == wx.WXK_DOWN and partial_match) ) ):
|
||||
and ( keycode in self._autoCompleteKeycodes + [wx.WXK_PRIOR, wx.WXK_NEXT, wx.WXK_NUMPAD_PRIOR, wx.WXK_NUMPAD_NEXT]
|
||||
or (keycode in [wx.WXK_UP, wx.WXK_DOWN, wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN] and event.ShiftDown())
|
||||
or (keycode in [wx.WXK_DOWN, wx.WXK_NUMPAD_DOWN] and partial_match) ) ):
|
||||
|
||||
# We're allowed to auto-complete:
|
||||
## dbg('match found')
|
||||
@@ -4077,10 +4097,11 @@ class MaskedEditMixin:
|
||||
self._CheckValid() # recolor as appopriate
|
||||
|
||||
|
||||
if keycode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT, wx.WXK_RIGHT):
|
||||
if keycode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT, wx.WXK_RIGHT,
|
||||
wx.WXK_NUMPAD_UP, wx.WXK_NUMPAD_DOWN, wx.WXK_NUMPAD_LEFT, wx.WXK_NUMPAD_RIGHT):
|
||||
# treat as left right arrow if unshifted, tab/shift tab if shifted.
|
||||
if event.ShiftDown():
|
||||
if keycode in (wx.WXK_DOWN, wx.WXK_RIGHT):
|
||||
if keycode in (wx.WXK_DOWN, wx.WXK_RIGHT, wx.WXK_NUMPAD_DOWN, wx.WXK_NUMPAD_RIGHT):
|
||||
# remove "shifting" and treat as (forward) tab:
|
||||
event.m_shiftDown = False
|
||||
keep_processing = self._OnChangeField(event)
|
||||
@@ -6702,6 +6723,9 @@ __i=0
|
||||
|
||||
## CHANGELOG:
|
||||
## ====================
|
||||
## Version 1.12
|
||||
## 1. Added proper support for NUMPAD keypad keycodes for navigation and control.
|
||||
##
|
||||
## Version 1.11
|
||||
## 1. Added value member to ValueError exceptions, so that people can catch them
|
||||
## and then display their own errors, and added attribute raiseOnInvalidPaste,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#----------------------------------------------------------------------------
|
||||
# Name: wx.lib.mixins.inspect
|
||||
# Name: wx.lib.mixins.inspection
|
||||
# Purpose: A mix-in class that can add PyCrust-based inspection of the
|
||||
# app's widgets and sizers.
|
||||
#
|
||||
@@ -15,7 +15,7 @@
|
||||
# wxPython-users mail list by Dan Eloff.
|
||||
|
||||
import wx
|
||||
from wx.lib.inspect import InspectionTool
|
||||
from wx.lib.inspection import InspectionTool
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
@@ -120,6 +120,15 @@ class ColumnSorterMixin:
|
||||
if wx.Platform != "__WXMAC__" or wx.SystemOptions.GetOptionInt("mac.listctrl.always_use_generic") == 1:
|
||||
self.__updateImages(oldCol)
|
||||
evt.Skip()
|
||||
self.OnSortOrderChanged()
|
||||
|
||||
|
||||
def OnSortOrderChanged(self):
|
||||
"""
|
||||
Callback called after sort order has changed (whenever user
|
||||
clicked column header).
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def __ColumnSorter(self, key1, key2):
|
||||
|
646
wxPython/wx/lib/mixins/treemixin.py
Normal file
646
wxPython/wx/lib/mixins/treemixin.py
Normal file
@@ -0,0 +1,646 @@
|
||||
'''
|
||||
treemixin.py
|
||||
|
||||
This module provides three mixin classes that can be used with tree
|
||||
controls:
|
||||
|
||||
- VirtualTree is a class that, when mixed in with a tree control,
|
||||
makes the tree control virtual, similar to a ListCtrl in virtual mode.
|
||||
A virtual tree control builds the tree itself by means of callbacks,
|
||||
so the programmer is freed from the burden of building the tree herself.
|
||||
|
||||
- DragAndDrop is a mixin class that helps with dragging and dropping of
|
||||
items. The graphical part of dragging and dropping tree items is done by
|
||||
this mixin class. You only need to implement the OnDrop method that is
|
||||
called when the drop happens.
|
||||
|
||||
- ExpansionState is a mixin that can be queried for the expansion state of
|
||||
all items in the tree to restore it later.
|
||||
|
||||
All mixin classes work with wx.TreeCtrl, wx.gizmos.TreeListCtrl,
|
||||
and wx.lib.customtree.CustomTreeCtrl. They can be used together or
|
||||
separately.
|
||||
|
||||
The VirtualTree and DragAndDrop mixins force the wx.TR_HIDE_ROOT style.
|
||||
|
||||
Author: Frank Niessink <frank@niessink.com>
|
||||
License: wxWidgets license
|
||||
Version: 0.9.1
|
||||
Date: 26 March 2007
|
||||
|
||||
ExpansionState is based on code and ideas from Karsten Hilbert.
|
||||
Andrea Gavana provided help with the CustomTreeCtrl integration.
|
||||
'''
|
||||
|
||||
|
||||
import wx, wx.lib.customtreectrl
|
||||
|
||||
|
||||
class TreeAPIHarmonizer(object):
|
||||
''' This class attempts to hide the differences in API between the
|
||||
different tree controls that are part of wxPython. '''
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# CustomTreeCtrl uses a different keyword for the window style
|
||||
# argument ('ctstyle'). To hide this, we replace the 'style' keyword
|
||||
# by 'ctstyle' if we're mixed in with CustomTreeCtrl.
|
||||
if isinstance(self, wx.lib.customtreectrl.CustomTreeCtrl):
|
||||
kwargs['ctstyle'] = kwargs.pop('style', wx.TR_DEFAULT_STYLE)
|
||||
super(TreeAPIHarmonizer, self).__init__(*args, **kwargs)
|
||||
|
||||
def __callSuper(self, methodName, default, *args, **kwargs):
|
||||
# If our super class has a method called methodName, call it,
|
||||
# otherwise return the default value.
|
||||
superClass = super(TreeAPIHarmonizer, self)
|
||||
if hasattr(superClass, methodName):
|
||||
return getattr(superClass, methodName)(*args, **kwargs)
|
||||
else:
|
||||
return default
|
||||
|
||||
def GetColumnCount(self, *args, **kwargs):
|
||||
# Only TreeListCtrl has columns, return 0 if we are mixed in
|
||||
# with another tree control.
|
||||
return self.__callSuper('GetColumnCount', 0, *args, **kwargs)
|
||||
|
||||
def GetItemType(self, *args, **kwargs):
|
||||
# Only CustomTreeCtrl has different item types, return the
|
||||
# default item type if we are mixed in with another tree control.
|
||||
return self.__callSuper('GetItemType', 0, *args, **kwargs)
|
||||
|
||||
def SetItemType(self, item, newType):
|
||||
# CustomTreeCtrl doesn't support changing the item type on the fly,
|
||||
# so we create a new item and delete the old one. We currently only
|
||||
# keep the item text, would be nicer to also retain other attributes.
|
||||
text = self.GetItemText(item)
|
||||
newItem = self.InsertItem(self.GetItemParent(item), item, text,
|
||||
ct_type=newType)
|
||||
self.Delete(item)
|
||||
return newItem
|
||||
|
||||
def IsItemChecked(self, *args, **kwargs):
|
||||
# Only CustomTreeCtrl supports checkable items, return False if
|
||||
# we are mixed in with another tree control.
|
||||
return self.__callSuper('IsItemChecked', False, *args, **kwargs)
|
||||
|
||||
def GetItemChecked(self, *args, **kwargs):
|
||||
# For consistency's sake, provide a 'Get' and 'Set' method for
|
||||
# checkable items.
|
||||
return self.IsItemChecked(*args, **kwargs)
|
||||
|
||||
def SetItemChecked(self, *args, **kwargs):
|
||||
# For consistency's sake, provide a 'Get' and 'Set' method for
|
||||
# checkable items.
|
||||
return self.CheckItem(*args, **kwargs)
|
||||
|
||||
def GetMainWindow(self, *args, **kwargs):
|
||||
# Only TreeListCtrl has a separate main window, return self if we are
|
||||
# mixed in with another tree control.
|
||||
return self.__callSuper('GetMainWindow', self, *args, **kwargs)
|
||||
|
||||
def GetItemImage(self, item, which=wx.TreeItemIcon_Normal, column=-1):
|
||||
# CustomTreeCtrl always wants the which argument, so provide it
|
||||
# TreeListCtr.GetItemImage has a different order of arguments than
|
||||
# the other tree controls. Hide the differenes.
|
||||
if self.GetColumnCount():
|
||||
args = (item, column, which)
|
||||
else:
|
||||
args = (item, which)
|
||||
return super(TreeAPIHarmonizer, self).GetItemImage(*args)
|
||||
|
||||
def SetItemImage(self, item, imageIndex, which=wx.TreeItemIcon_Normal,
|
||||
column=-1):
|
||||
# The SetItemImage signature is different for TreeListCtrl and
|
||||
# other tree controls. This adapter method hides the differences.
|
||||
if self.GetColumnCount():
|
||||
args = (item, imageIndex, column, which)
|
||||
else:
|
||||
args = (item, imageIndex, which)
|
||||
super(TreeAPIHarmonizer, self).SetItemImage(*args)
|
||||
|
||||
def UnselectAll(self):
|
||||
# Unselect all items, regardless of whether we are in multiple
|
||||
# selection mode or not.
|
||||
if self.HasFlag(wx.TR_MULTIPLE):
|
||||
super(TreeAPIHarmonizer, self).UnselectAll()
|
||||
else:
|
||||
# CustomTreeCtrl Unselect() doesn't seem to work in all cases,
|
||||
# also invoke UnselectAll just to be sure.
|
||||
self.Unselect()
|
||||
super(TreeAPIHarmonizer, self).UnselectAll()
|
||||
|
||||
def GetCount(self):
|
||||
# TreeListCtrl correctly ignores the root item when it is hidden,
|
||||
# but doesn't count the root item when it is visible
|
||||
itemCount = super(TreeAPIHarmonizer, self).GetCount()
|
||||
if self.GetColumnCount() and not self.HasFlag(wx.TR_HIDE_ROOT):
|
||||
itemCount += 1
|
||||
return itemCount
|
||||
|
||||
def GetSelections(self):
|
||||
# Always return a list of selected items, regardless of whether
|
||||
# we are in multiple selection mode or not.
|
||||
if self.HasFlag(wx.TR_MULTIPLE):
|
||||
selections = super(TreeAPIHarmonizer, self).GetSelections()
|
||||
else:
|
||||
selection = self.GetSelection()
|
||||
if selection:
|
||||
selections = [selection]
|
||||
else:
|
||||
selections = []
|
||||
# If the root item is hidden, it should never be selected,
|
||||
# unfortunately, CustomTreeCtrl and TreeCtrl allow it to be selected.
|
||||
if self.HasFlag(wx.TR_HIDE_ROOT):
|
||||
rootItem = self.GetRootItem()
|
||||
if rootItem and rootItem in selections:
|
||||
selections.remove(rootItem)
|
||||
return selections
|
||||
|
||||
def SelectItem(self, item, *args, **kwargs):
|
||||
# Prevent the hidden root from being selected, otherwise TreeCtrl
|
||||
# crashes
|
||||
if self.HasFlag(wx.TR_HIDE_ROOT) and item == self.GetRootItem():
|
||||
return
|
||||
else:
|
||||
return super(TreeAPIHarmonizer, self).SelectItem(item, *args,
|
||||
**kwargs)
|
||||
|
||||
def HitTest(self, *args, **kwargs):
|
||||
''' HitTest returns a two-tuple (item, flags) for tree controls
|
||||
without columns and a three-tuple (item, flags, column) for tree
|
||||
controls with columns. Our caller can indicate this method to
|
||||
always return a three-tuple no matter what tree control we're mixed
|
||||
in with by specifying the optional argument 'alwaysReturnColumn'
|
||||
to be True. '''
|
||||
alwaysReturnColumn = kwargs.pop('alwaysReturnColumn', False)
|
||||
hitTestResult = super(TreeAPIHarmonizer, self).HitTest(*args, **kwargs)
|
||||
if len(hitTestResult) == 2 and alwaysReturnColumn:
|
||||
hitTestResult += (0,)
|
||||
return hitTestResult
|
||||
|
||||
def ExpandAll(self, item=None):
|
||||
# TreeListCtrl wants an item as argument. That's an inconsistency with
|
||||
# the TreeCtrl API. Also, TreeCtrl doesn't allow invoking ExpandAll
|
||||
# on a tree with hidden root node, so prevent that.
|
||||
if self.HasFlag(wx.TR_HIDE_ROOT):
|
||||
rootItem = self.GetRootItem()
|
||||
if rootItem:
|
||||
child, cookie = self.GetFirstChild(rootItem)
|
||||
while child:
|
||||
self.ExpandAllChildren(child)
|
||||
child, cookie = self.GetNextChild(rootItem, cookie)
|
||||
else:
|
||||
try:
|
||||
super(TreeAPIHarmonizer, self).ExpandAll()
|
||||
except TypeError:
|
||||
if item is None:
|
||||
item = self.GetRootItem()
|
||||
super(TreeAPIHarmonizer, self).ExpandAll(item)
|
||||
|
||||
def ExpandAllChildren(self, item):
|
||||
# TreeListCtrl doesn't have ExpandallChildren
|
||||
try:
|
||||
super(TreeAPIHarmonizer, self).ExpandAllChildren(item)
|
||||
except AttributeError:
|
||||
self.Expand(item)
|
||||
child, cookie = self.GetFirstChild(item)
|
||||
while child:
|
||||
self.ExpandAllChildren(child)
|
||||
child, cookie = self.GetNextChild(item, cookie)
|
||||
|
||||
|
||||
class TreeHelper(object):
|
||||
''' This class provides methods that are not part of the API of any
|
||||
tree control, but are convenient to have available. '''
|
||||
|
||||
def GetItemChildren(self, item=None, recursively=False):
|
||||
''' Return the children of item as a list. '''
|
||||
if not item:
|
||||
item = self.GetRootItem()
|
||||
if not item:
|
||||
return []
|
||||
children = []
|
||||
child, cookie = self.GetFirstChild(item)
|
||||
while child:
|
||||
children.append(child)
|
||||
if recursively:
|
||||
children.extend(self.GetItemChildren(child, True))
|
||||
child, cookie = self.GetNextChild(item, cookie)
|
||||
return children
|
||||
|
||||
def GetIndexOfItem(self, item):
|
||||
''' Return the index of item. '''
|
||||
parent = self.GetItemParent(item)
|
||||
if parent:
|
||||
parentIndices = self.GetIndexOfItem(parent)
|
||||
ownIndex = self.GetItemChildren(parent).index(item)
|
||||
return parentIndices + (ownIndex,)
|
||||
else:
|
||||
return ()
|
||||
|
||||
def GetItemByIndex(self, index):
|
||||
''' Return the item specified by index. '''
|
||||
item = self.GetRootItem()
|
||||
for i in index:
|
||||
children = self.GetItemChildren(item)
|
||||
item = children[i]
|
||||
return item
|
||||
|
||||
|
||||
class VirtualTree(TreeAPIHarmonizer, TreeHelper):
|
||||
''' This is a mixin class that can be used to allow for virtual tree
|
||||
controls. It can be mixed in with wx.TreeCtrl, wx.gizmos.TreeListCtrl,
|
||||
wx.lib.customtree.CustomTreeCtrl.
|
||||
|
||||
To use it derive a new class from this class and one of the tree
|
||||
controls, e.g.:
|
||||
class MyTree(VirtualTree, wx.TreeCtrl):
|
||||
...
|
||||
|
||||
VirtualTree uses several callbacks (such as OnGetItemText) to
|
||||
retrieve information needed to construct the tree and render the
|
||||
items. To specify what item the callback needs information about,
|
||||
the callback passes an item index. Whereas for list controls a simple
|
||||
integer index can be used, for tree controls indicating a specific
|
||||
item is a little bit more complicated. See below for a more detailed
|
||||
explanation of the how index works.
|
||||
|
||||
Note that VirtualTree forces the wx.TR_HIDE_ROOT style.
|
||||
|
||||
In your subclass you *must* override OnGetItemText and
|
||||
OnGetChildrenCount. These two methods are the minimum needed to
|
||||
construct the tree and render the item labels. If you want to add
|
||||
images, change fonts our colours, etc., you need to override the
|
||||
appropriate OnGetXXX method as well.
|
||||
|
||||
About indices: your callbacks are passed a tuple of integers that
|
||||
identifies the item the VirtualTree wants information about. An
|
||||
empty tuple, i.e. (), represents the hidden root item. A tuple with
|
||||
one integer, e.g. (3,), represents a visible root item, in this case
|
||||
the fourth one. A tuple with two integers, e.g. (3,0), represents a
|
||||
child of a visible root item, in this case the first child of the
|
||||
fourth root item.
|
||||
'''
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['style'] = kwargs.get('style', wx.TR_DEFAULT_STYLE) | \
|
||||
wx.TR_HIDE_ROOT
|
||||
super(VirtualTree, self).__init__(*args, **kwargs)
|
||||
self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding)
|
||||
self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed)
|
||||
|
||||
def OnGetChildrenCount(self, index):
|
||||
''' This function *must* be overloaded in the derived class.
|
||||
It should return the number of child items of the item with the
|
||||
provided index. If index == () it should return the number of
|
||||
root items. '''
|
||||
raise NotImplementedError
|
||||
|
||||
def OnGetItemText(self, index, column=0):
|
||||
''' This function *must* be overloaded in the derived class. It
|
||||
should return the string containing the text of the specified
|
||||
item. '''
|
||||
raise NotImplementedError
|
||||
|
||||
def OnGetItemFont(self, index):
|
||||
''' This function may be overloaded in the derived class. It
|
||||
should return the wx.Font to be used for the specified item. '''
|
||||
return wx.NullFont
|
||||
|
||||
def OnGetItemTextColour(self, index):
|
||||
''' This function may be overloaded in the derived class. It
|
||||
should return the wx.Colour to be used as text colour for the
|
||||
specified item. '''
|
||||
return wx.NullColour
|
||||
|
||||
def OnGetItemBackgroundColour(self, index):
|
||||
''' This function may be overloaded in the derived class. It
|
||||
should return the wx.Colour to be used as background colour for
|
||||
the specified item. '''
|
||||
return wx.NullColour
|
||||
|
||||
def OnGetItemImage(self, index, which=wx.TreeItemIcon_Normal, column=0):
|
||||
''' This function may be overloaded in the derived class. It
|
||||
should return the index of the image to be used. Don't forget
|
||||
to associate an ImageList with the tree control. '''
|
||||
return -1
|
||||
|
||||
def OnGetItemType(self, index):
|
||||
''' This function may be overloaded in the derived class, but
|
||||
that only makes sense when this class is mixed in with a tree
|
||||
control that supports checkable items, i.e. CustomTreeCtrl.
|
||||
This method should return whether the item is to be normal (0,
|
||||
the default), a checkbox (1) or a radiobutton (2).
|
||||
Note that OnGetItemChecked needs to be implemented as well; it
|
||||
should return whether the item is actually checked. '''
|
||||
return 0
|
||||
|
||||
def OnGetItemChecked(self, index):
|
||||
''' This function may be overloaded in the derived class, but
|
||||
that only makes sense when this class is mixed in with a tree
|
||||
control that supports checkable items, i.e. CustomTreeCtrl.
|
||||
This method should return whether the item is to be checked.
|
||||
Note that OnGetItemType should return 1 (checkbox) or 2
|
||||
(radiobutton) for this item. '''
|
||||
return False
|
||||
|
||||
def RefreshItems(self):
|
||||
''' Redraws all visible items. '''
|
||||
rootItem = self.GetRootItem()
|
||||
if not rootItem:
|
||||
rootItem = self.AddRoot('Hidden root')
|
||||
self.RefreshChildrenRecursively(rootItem)
|
||||
|
||||
def RefreshItem(self, index):
|
||||
''' Redraws the item with the specified index. '''
|
||||
item = self.GetItemByIndex(index)
|
||||
hasChildren = bool(self.OnGetChildrenCount(index))
|
||||
self.DoRefreshItem(item, index, hasChildren)
|
||||
|
||||
def RefreshChildrenRecursively(self, item, itemIndex=None):
|
||||
''' Refresh the children of item, reusing as much of the
|
||||
existing items in the tree as possible. '''
|
||||
if itemIndex is None:
|
||||
itemIndex = self.GetIndexOfItem(item)
|
||||
reusableChildren = self.GetItemChildren(item)
|
||||
for childIndex in self.ChildIndices(itemIndex):
|
||||
if reusableChildren:
|
||||
child = reusableChildren.pop(0)
|
||||
else:
|
||||
child = self.AppendItem(item, '')
|
||||
self.RefreshItemRecursively(child, childIndex)
|
||||
for child in reusableChildren:
|
||||
self.Delete(child)
|
||||
|
||||
def RefreshItemRecursively(self, item, itemIndex):
|
||||
''' Refresh the item and its children recursively. '''
|
||||
hasChildren = bool(self.OnGetChildrenCount(itemIndex))
|
||||
item = self.DoRefreshItem(item, itemIndex, hasChildren)
|
||||
# We need to refresh the children when the item is expanded and
|
||||
# when the item has no children, because in the latter case we
|
||||
# might have to delete old children from the tree:
|
||||
if self.IsExpanded(item) or not hasChildren:
|
||||
self.RefreshChildrenRecursively(item, itemIndex)
|
||||
self.SetItemHasChildren(item, hasChildren)
|
||||
|
||||
def DoRefreshItem(self, item, index, hasChildren):
|
||||
''' Refresh one item. '''
|
||||
item = self.RefreshItemType(item, index)
|
||||
self.RefreshItemText(item, index)
|
||||
self.RefreshColumns(item, index)
|
||||
self.RefreshItemFont(item, index)
|
||||
self.RefreshTextColour(item, index)
|
||||
self.RefreshBackgroundColour(item, index)
|
||||
self.RefreshItemImage(item, index, hasChildren)
|
||||
self.RefreshCheckedState(item, index)
|
||||
return item
|
||||
|
||||
def RefreshItemText(self, item, index):
|
||||
self.__refreshAttribute(item, index, 'ItemText')
|
||||
|
||||
def RefreshColumns(self, item, index):
|
||||
for columnIndex in range(1, self.GetColumnCount()):
|
||||
self.__refreshAttribute(item, index, 'ItemText', columnIndex)
|
||||
|
||||
def RefreshItemFont(self, item, index):
|
||||
self.__refreshAttribute(item, index, 'ItemFont')
|
||||
|
||||
def RefreshTextColour(self, item, index):
|
||||
self.__refreshAttribute(item, index, 'ItemTextColour')
|
||||
|
||||
def RefreshBackgroundColour(self, item, index):
|
||||
self.__refreshAttribute(item, index, 'ItemBackgroundColour')
|
||||
|
||||
def RefreshItemImage(self, item, index, hasChildren):
|
||||
regularIcons = [wx.TreeItemIcon_Normal, wx.TreeItemIcon_Selected]
|
||||
expandedIcons = [wx.TreeItemIcon_Expanded,
|
||||
wx.TreeItemIcon_SelectedExpanded]
|
||||
# Refresh images in first column:
|
||||
for icon in regularIcons:
|
||||
self.__refreshAttribute(item, index, 'ItemImage', icon)
|
||||
for icon in expandedIcons:
|
||||
if hasChildren:
|
||||
imageIndex = self.OnGetItemImage(index, icon)
|
||||
else:
|
||||
imageIndex = -1
|
||||
if self.GetItemImage(item, icon) != imageIndex or imageIndex == -1:
|
||||
self.SetItemImage(item, imageIndex, icon)
|
||||
# Refresh images in remaining columns, if any:
|
||||
for columnIndex in range(1, self.GetColumnCount()):
|
||||
for icon in regularIcons:
|
||||
self.__refreshAttribute(item, index, 'ItemImage', icon,
|
||||
columnIndex)
|
||||
|
||||
def RefreshItemType(self, item, index):
|
||||
return self.__refreshAttribute(item, index, 'ItemType')
|
||||
|
||||
def RefreshCheckedState(self, item, index):
|
||||
self.__refreshAttribute(item, index, 'ItemChecked')
|
||||
|
||||
def ChildIndices(self, itemIndex):
|
||||
childrenCount = self.OnGetChildrenCount(itemIndex)
|
||||
return [itemIndex + (childNumber,) for childNumber \
|
||||
in range(childrenCount)]
|
||||
|
||||
def OnItemExpanding(self, event):
|
||||
self.RefreshChildrenRecursively(event.GetItem())
|
||||
event.Skip()
|
||||
|
||||
def OnItemCollapsed(self, event):
|
||||
parent = self.GetItemParent(event.GetItem())
|
||||
if not parent:
|
||||
parent = self.GetRootItem()
|
||||
self.RefreshChildrenRecursively(parent)
|
||||
event.Skip()
|
||||
|
||||
def __refreshAttribute(self, item, index, attribute, *args):
|
||||
''' Refresh the specified attribute if necessary. '''
|
||||
value = getattr(self, 'OnGet%s'%attribute)(index, *args)
|
||||
if getattr(self, 'Get%s'%attribute)(item, *args) != value:
|
||||
return getattr(self, 'Set%s'%attribute)(item, value, *args)
|
||||
else:
|
||||
return item
|
||||
|
||||
|
||||
class DragAndDrop(TreeAPIHarmonizer, TreeHelper):
|
||||
''' This is a mixin class that can be used to easily implement
|
||||
dragging and dropping of tree items. It can be mixed in with
|
||||
wx.TreeCtrl, wx.gizmos.TreeListCtrl, or wx.lib.customtree.CustomTreeCtrl.
|
||||
|
||||
To use it derive a new class from this class and one of the tree
|
||||
controls, e.g.:
|
||||
class MyTree(DragAndDrop, wx.TreeCtrl):
|
||||
...
|
||||
|
||||
You *must* implement OnDrop. OnDrop is called when the user has
|
||||
dropped an item on top of another item. It's up to you to decide how
|
||||
to handle the drop. If you are using this mixin together with the
|
||||
VirtualTree mixin, it makes sense to rearrange your underlying data
|
||||
and then call RefreshItems to let the virtual tree refresh itself. '''
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['style'] = kwargs.get('style', wx.TR_DEFAULT_STYLE) | \
|
||||
wx.TR_HIDE_ROOT
|
||||
super(DragAndDrop, self).__init__(*args, **kwargs)
|
||||
self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag)
|
||||
|
||||
def OnDrop(self, dropItem, dragItem):
|
||||
''' This function must be overloaded in the derived class.
|
||||
dragItem is the item being dragged by the user. dropItem is the
|
||||
item dragItem is dropped upon. If the user doesn't drop dragItem
|
||||
on another item, dropItem equals the (hidden) root item of the
|
||||
tree control. '''
|
||||
raise NotImplementedError
|
||||
|
||||
def OnBeginDrag(self, event):
|
||||
# We allow only one item to be dragged at a time, to keep it simple
|
||||
self._dragItem = event.GetItem()
|
||||
if self._dragItem and self._dragItem != self.GetRootItem():
|
||||
self.StartDragging()
|
||||
event.Allow()
|
||||
else:
|
||||
event.Veto()
|
||||
|
||||
def OnEndDrag(self, event):
|
||||
self.StopDragging()
|
||||
dropTarget = event.GetItem()
|
||||
if not dropTarget:
|
||||
dropTarget = self.GetRootItem()
|
||||
if self.IsValidDropTarget(dropTarget):
|
||||
self.UnselectAll()
|
||||
if dropTarget != self.GetRootItem():
|
||||
self.SelectItem(dropTarget)
|
||||
self.OnDrop(dropTarget, self._dragItem)
|
||||
|
||||
def OnDragging(self, event):
|
||||
if not event.Dragging():
|
||||
self.StopDragging()
|
||||
return
|
||||
item, flags, column = self.HitTest(wx.Point(event.GetX(), event.GetY()),
|
||||
alwaysReturnColumn=True)
|
||||
if not item:
|
||||
item = self.GetRootItem()
|
||||
if self.IsValidDropTarget(item):
|
||||
self.SetCursorToDragging()
|
||||
else:
|
||||
self.SetCursorToDroppingImpossible()
|
||||
if flags & wx.TREE_HITTEST_ONITEMBUTTON:
|
||||
self.Expand(item)
|
||||
if self.GetSelections() != [item]:
|
||||
self.UnselectAll()
|
||||
if item != self.GetRootItem():
|
||||
self.SelectItem(item)
|
||||
event.Skip()
|
||||
|
||||
def StartDragging(self):
|
||||
self.GetMainWindow().Bind(wx.EVT_MOTION, self.OnDragging)
|
||||
self.Bind(wx.EVT_TREE_END_DRAG, self.OnEndDrag)
|
||||
self.SetCursorToDragging()
|
||||
|
||||
def StopDragging(self):
|
||||
self.GetMainWindow().Unbind(wx.EVT_MOTION)
|
||||
self.Unbind(wx.EVT_TREE_END_DRAG)
|
||||
self.ResetCursor()
|
||||
self.UnselectAll()
|
||||
self.SelectItem(self._dragItem)
|
||||
|
||||
def SetCursorToDragging(self):
|
||||
self.GetMainWindow().SetCursor(wx.StockCursor(wx.CURSOR_HAND))
|
||||
|
||||
def SetCursorToDroppingImpossible(self):
|
||||
self.GetMainWindow().SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY))
|
||||
|
||||
def ResetCursor(self):
|
||||
self.GetMainWindow().SetCursor(wx.NullCursor)
|
||||
|
||||
def IsValidDropTarget(self, dropTarget):
|
||||
if dropTarget:
|
||||
allChildren = self.GetItemChildren(self._dragItem, recursively=True)
|
||||
parent = self.GetItemParent(self._dragItem)
|
||||
return dropTarget not in [self._dragItem, parent] + allChildren
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class ExpansionState(TreeAPIHarmonizer, TreeHelper):
|
||||
''' This is a mixin class that can be used to save and restore
|
||||
the expansion state (i.e. which items are expanded and which items
|
||||
are collapsed) of a tree. It can be mixed in with wx.TreeCtrl,
|
||||
wx.gizmos.TreeListCtrl, or wx.lib.customtree.CustomTreeCtrl.
|
||||
|
||||
To use it derive a new class from this class and one of the tree
|
||||
controls, e.g.:
|
||||
class MyTree(ExpansionState, wx.TreeCtrl):
|
||||
...
|
||||
|
||||
By default, ExpansionState uses the position of tree items in the tree
|
||||
to keep track of which items are expanded. This should be sufficient
|
||||
for the simple scenario where you save the expansion state of the tree
|
||||
when the user closes the application or file so that you can restore
|
||||
the expansion state when the user start the application or loads that
|
||||
file for the next session.
|
||||
|
||||
If you need to add or remove items between the moments of saving and
|
||||
restoring the expansion state (e.g. in case of a multi-user application)
|
||||
you must override GetItemIdentity so that saving and loading of the
|
||||
expansion doesn't depend on the position of items in the tree, but
|
||||
rather on some more stable characteristic of the underlying domain
|
||||
object, e.g. a social security number in case of persons or an isbn
|
||||
number in case of books. '''
|
||||
|
||||
def GetItemIdentity(self, item):
|
||||
''' Return a hashable object that represents the identity of the
|
||||
item. By default this returns the position of the item in the
|
||||
tree. You may want to override this to return the item label
|
||||
(if you know that labels are unique and don't change), or return
|
||||
something that represents the underlying domain object, e.g.
|
||||
a database key. '''
|
||||
return self.GetIndexOfItem(item)
|
||||
|
||||
def GetExpansionState(self):
|
||||
''' GetExpansionState() -> list of expanded items. Expanded items
|
||||
are coded as determined by the result of GetItemIdentity(item). '''
|
||||
root = self.GetRootItem()
|
||||
if not root:
|
||||
return []
|
||||
if self.HasFlag(wx.TR_HIDE_ROOT):
|
||||
return self.GetExpansionStateOfChildren(root)
|
||||
else:
|
||||
return self.GetExpansionStateOfItem(root)
|
||||
|
||||
def SetExpansionState(self, listOfExpandedItems):
|
||||
''' SetExpansionState(listOfExpandedItems). Expands all tree items
|
||||
whose identity, as determined by GetItemIdentity(item), is present
|
||||
in the list and collapses all other tree items. '''
|
||||
root = self.GetRootItem()
|
||||
if not root:
|
||||
return
|
||||
if self.HasFlag(wx.TR_HIDE_ROOT):
|
||||
self.SetExpansionStateOfChildren(listOfExpandedItems, root)
|
||||
else:
|
||||
self.SetExpansionStateOfItem(listOfExpandedItems, root)
|
||||
|
||||
ExpansionState = property(GetExpansionState, SetExpansionState)
|
||||
|
||||
def GetExpansionStateOfItem(self, item):
|
||||
listOfExpandedItems = []
|
||||
if self.IsExpanded(item):
|
||||
listOfExpandedItems.append(self.GetItemIdentity(item))
|
||||
listOfExpandedItems.extend(self.GetExpansionStateOfChildren(item))
|
||||
return listOfExpandedItems
|
||||
|
||||
def GetExpansionStateOfChildren(self, item):
|
||||
listOfExpandedItems = []
|
||||
for child in self.GetItemChildren(item):
|
||||
listOfExpandedItems.extend(self.GetExpansionStateOfItem(child))
|
||||
return listOfExpandedItems
|
||||
|
||||
def SetExpansionStateOfItem(self, listOfExpandedItems, item):
|
||||
if self.GetItemIdentity(item) in listOfExpandedItems:
|
||||
self.Expand(item)
|
||||
self.SetExpansionStateOfChildren(listOfExpandedItems, item)
|
||||
else:
|
||||
self.Collapse(item)
|
||||
|
||||
def SetExpansionStateOfChildren(self, listOfExpandedItems, item):
|
||||
for child in self.GetItemChildren(item):
|
||||
self.SetExpansionStateOfItem(listOfExpandedItems, child)
|
@@ -67,9 +67,6 @@ class ShapeEvtHandler(object):
|
||||
self._previousHandler = prev
|
||||
self._handlerShape = shape
|
||||
|
||||
def __del__(self):
|
||||
pass
|
||||
|
||||
def SetShape(self, sh):
|
||||
self._handlerShape = sh
|
||||
|
||||
@@ -311,9 +308,6 @@ class Shape(ShapeEvtHandler):
|
||||
self.GetEventHandler().OnDelete()
|
||||
self._eventHandler = None
|
||||
|
||||
def __del__(self):
|
||||
ShapeEvtHandler.__del__(self)
|
||||
|
||||
def Draggable(self):
|
||||
"""TRUE if the shape may be dragged by the user."""
|
||||
return True
|
||||
|
@@ -218,16 +218,6 @@ class LineShape(Shape):
|
||||
self._lineControlPoints = []
|
||||
self._arcArrows = []
|
||||
|
||||
def __del__(self):
|
||||
if self._lineControlPoints:
|
||||
self._lineControlPoints = []
|
||||
for i in range(3):
|
||||
if self._labelObjects[i]:
|
||||
self._labelObjects[i].Select(False)
|
||||
self._labelObjects[i].RemoveFromCanvas(self._canvas)
|
||||
self._labelObjects = []
|
||||
self.ClearArrowsAtPosition(-1)
|
||||
|
||||
def GetFrom(self):
|
||||
"""Return the 'from' object."""
|
||||
return self._from
|
||||
@@ -492,6 +482,11 @@ class LineShape(Shape):
|
||||
self._from.GetLines().remove(self)
|
||||
self._to = None
|
||||
self._from = None
|
||||
for i in range(3):
|
||||
if self._labelObjects[i]:
|
||||
self._labelObjects[i].Select(False)
|
||||
self._labelObjects[i].RemoveFromCanvas(self._canvas)
|
||||
self.ClearArrowsAtPosition(-1)
|
||||
|
||||
def SetEnds(self, x1, y1, x2, y2):
|
||||
"""Set the end positions of the line."""
|
||||
|
@@ -554,6 +554,7 @@ class PlotCanvas(wx.Panel):
|
||||
self._ySpec= 'auto'
|
||||
self._gridEnabled= False
|
||||
self._legendEnabled= False
|
||||
self._titleEnabled= True
|
||||
|
||||
# Fonts
|
||||
self._fontCache = {}
|
||||
@@ -567,6 +568,8 @@ class PlotCanvas(wx.Panel):
|
||||
self._pointLabelFunc= None
|
||||
self.canvas.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
|
||||
|
||||
self._useScientificNotation = False
|
||||
|
||||
self.canvas.Bind(wx.EVT_PAINT, self.OnPaint)
|
||||
self.canvas.Bind(wx.EVT_SIZE, self.OnSize)
|
||||
# OnSize called to make sure the buffer is initialized.
|
||||
@@ -746,6 +749,12 @@ class PlotCanvas(wx.Panel):
|
||||
"""Set True to show scrollbars"""
|
||||
return self.sb_vert.IsShown()
|
||||
|
||||
def SetUseScientificNotation(self, useScientificNotation):
|
||||
self._useScientificNotation = useScientificNotation
|
||||
|
||||
def GetUseScientificNotation(self):
|
||||
return self._useScientificNotation
|
||||
|
||||
def SetEnableDrag(self, value):
|
||||
"""Set True to enable drag."""
|
||||
if value not in [True,False]:
|
||||
@@ -799,6 +808,17 @@ class PlotCanvas(wx.Panel):
|
||||
"""True if Legend enabled."""
|
||||
return self._legendEnabled
|
||||
|
||||
def SetEnableTitle(self, value):
|
||||
"""Set True to enable title."""
|
||||
if value not in [True,False]:
|
||||
raise TypeError, "Value should be True or False"
|
||||
self._titleEnabled= value
|
||||
self.Redraw()
|
||||
|
||||
def GetEnableTitle(self):
|
||||
"""True if title enabled."""
|
||||
return self._titleEnabled
|
||||
|
||||
def SetEnablePointLabel(self, value):
|
||||
"""Set True to enable pointLabel."""
|
||||
if value not in [True,False]:
|
||||
@@ -1038,11 +1058,14 @@ class PlotCanvas(wx.Panel):
|
||||
textSize_scale= _Numeric.array([rhsW+lhsW,bottomH+topH]) # make plot area smaller by text size
|
||||
textSize_shift= _Numeric.array([lhsW, bottomH]) # shift plot area by this amount
|
||||
|
||||
# drawing title and labels text
|
||||
dc.SetFont(self._getFont(self._fontSizeTitle))
|
||||
titlePos= (self.plotbox_origin[0]+ lhsW + (self.plotbox_size[0]-lhsW-rhsW)/2.- titleWH[0]/2.,
|
||||
self.plotbox_origin[1]- self.plotbox_size[1])
|
||||
dc.DrawText(graphics.getTitle(),titlePos[0],titlePos[1])
|
||||
# draw title if requested
|
||||
if self._titleEnabled:
|
||||
dc.SetFont(self._getFont(self._fontSizeTitle))
|
||||
titlePos= (self.plotbox_origin[0]+ lhsW + (self.plotbox_size[0]-lhsW-rhsW)/2.- titleWH[0]/2.,
|
||||
self.plotbox_origin[1]- self.plotbox_size[1])
|
||||
dc.DrawText(graphics.getTitle(),titlePos[0],titlePos[1])
|
||||
|
||||
# draw label text
|
||||
dc.SetFont(self._getFont(self._fontSizeAxis))
|
||||
xLabelPos= (self.plotbox_origin[0]+ lhsW + (self.plotbox_size[0]-lhsW-rhsW)/2.- xLabelWH[0]/2.,
|
||||
self.plotbox_origin[1]- xLabelWH[1])
|
||||
@@ -1131,7 +1154,7 @@ class PlotCanvas(wx.Panel):
|
||||
l.append(cn)
|
||||
return l
|
||||
|
||||
def GetClosetPoint(self, pntXY, pointScaled= True):
|
||||
def GetClosestPoint(self, pntXY, pointScaled= True):
|
||||
"""Returns list with
|
||||
[curveNumber, legend, index of closest point, pointXY, scaledXY, distance]
|
||||
list for only the closest curve.
|
||||
@@ -1151,6 +1174,8 @@ class PlotCanvas(wx.Panel):
|
||||
mdist = min(dists) #Min dist
|
||||
i = dists.index(mdist) #index for min dist
|
||||
return closestPts[i] #this is the closest point on closest curve
|
||||
|
||||
GetClosetPoint = GetClosestPoint
|
||||
|
||||
def UpdatePointLabel(self, mDataDict):
|
||||
"""Updates the pointLabel point on screen with data contained in
|
||||
@@ -1355,8 +1380,11 @@ class PlotCanvas(wx.Panel):
|
||||
"""Draws Title and labels and returns width and height for each"""
|
||||
# TextExtents for Title and Axis Labels
|
||||
dc.SetFont(self._getFont(self._fontSizeTitle))
|
||||
title= graphics.getTitle()
|
||||
titleWH= dc.GetTextExtent(title)
|
||||
if self._titleEnabled:
|
||||
title= graphics.getTitle()
|
||||
titleWH= dc.GetTextExtent(title)
|
||||
else:
|
||||
titleWH= (0,0)
|
||||
dc.SetFont(self._getFont(self._fontSizeAxis))
|
||||
xLabel, yLabel= graphics.getXLabel(),graphics.getYLabel()
|
||||
xLabelWH= dc.GetTextExtent(xLabel)
|
||||
@@ -1565,7 +1593,7 @@ class PlotCanvas(wx.Panel):
|
||||
error = e
|
||||
factor = f
|
||||
grid = factor * 10.**power
|
||||
if power > 4 or power < -4:
|
||||
if self._useScientificNotation and (power > 4 or power < -4):
|
||||
format = '%+7.1e'
|
||||
elif power >= 0:
|
||||
digits = max(1, int(power))
|
||||
@@ -2021,7 +2049,7 @@ class TestFrame(wx.Frame):
|
||||
if self.client.GetEnablePointLabel() == True:
|
||||
#make up dict with info for the pointLabel
|
||||
#I've decided to mark the closest point on the closest curve
|
||||
dlst= self.client.GetClosetPoint( self.client._getXY(event), pointScaled= True)
|
||||
dlst= self.client.GetClosestPoint( self.client._getXY(event), pointScaled= True)
|
||||
if dlst != []: #returns [] if none
|
||||
curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst
|
||||
#make up dictionary to pass to my user function (see DrawPointLabel)
|
||||
|
@@ -163,16 +163,13 @@ class wxpTagHandler(wx.html.HtmlWinTagHandler):
|
||||
# create the object
|
||||
parent = self.GetParser().GetWindowInterface().GetHTMLWindow()
|
||||
if parent:
|
||||
obj = apply(self.ctx.classObj,
|
||||
(parent,),
|
||||
self.ctx.kwargs)
|
||||
obj = self.ctx.classObj(parent, **self.ctx.kwargs)
|
||||
obj.Show(True)
|
||||
|
||||
# add it to the HtmlWindow
|
||||
self.GetParser().GetContainer().InsertCell(
|
||||
wx.html.HtmlWidgetCell(obj, self.ctx.floatWidth))
|
||||
self.ctx = None
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user