From 02b800ce7c2bb1c1f08075f22be2e7412124b47f Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Fri, 30 Dec 2005 23:02:03 +0000 Subject: [PATCH] Merged modifications from the 2.6 branch git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@36607 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- wxPython/config.py | 18 +- wxPython/demo/BitmapButton.py | 8 +- wxPython/demo/FileBrowseButton.py | 5 +- wxPython/demo/FoldPanelBar.py | 48 +- wxPython/demo/GLCanvas.py | 60 +- wxPython/demo/HyperLinkCtrl.py | 2 +- wxPython/demo/LayoutConstraints.py | 8 +- wxPython/demo/MDIWindows.py | 15 +- wxPython/demo/Main.py | 26 +- wxPython/demo/Process.py | 3 +- wxPython/demo/StyledTextCtrl_2.py | 46 +- wxPython/demo/TablePrint.py | 13 +- wxPython/demo/Throbber.py | 90 +- wxPython/demo/XmlResourceHandler.py | 10 +- wxPython/demo/data/proclamation.txt | 115 + wxPython/distrib/mac/wxPythonOSX/build | 4 +- wxPython/distrib/make_installer_inno4.py | 40 +- wxPython/distrib/makedemo | 2 +- wxPython/distrib/makedocs | 4 +- wxPython/distrib/viewdocs.py | 1 - wxPython/distrib/wxPythonFull.spec.in | 2 +- wxPython/docs/CHANGES.txt | 199 +- wxPython/docs/xml/wxPython-metadata.xml | 41655 ---------------- wxPython/include/wx/wxPython/wxPython_int.h | 33 + .../ide/activegrid/tool/AboutDialog.py | 63 +- .../ide/activegrid/tool/AbstractEditor.py | 167 +- .../samples/ide/activegrid/tool/CodeEditor.py | 18 +- .../ide/activegrid/tool/DebuggerService.py | 319 +- .../ide/activegrid/tool/ExtensionService.py | 198 +- .../ide/activegrid/tool/FindInDirService.py | 40 +- .../ide/activegrid/tool/FindService.py | 43 +- .../samples/ide/activegrid/tool/HtmlEditor.py | 37 +- wxPython/samples/ide/activegrid/tool/IDE.py | 6235 ++- .../ide/activegrid/tool/ImageEditor.py | 34 +- .../ide/activegrid/tool/MessageService.py | 117 +- .../ide/activegrid/tool/OutlineService.py | 19 +- .../samples/ide/activegrid/tool/PHPEditor.py | 26 +- .../samples/ide/activegrid/tool/PerlEditor.py | 36 +- .../ide/activegrid/tool/ProjectEditor.py | 3288 +- .../ide/activegrid/tool/PythonEditor.py | 155 +- .../ide/activegrid/tool/STCTextEditor.py | 166 +- .../samples/ide/activegrid/tool/SVNService.py | 130 +- .../samples/ide/activegrid/tool/Service.py | 40 +- .../samples/ide/activegrid/tool/UICommon.py | 405 +- .../samples/ide/activegrid/tool/Wizard.py | 706 +- .../samples/ide/activegrid/tool/XmlEditor.py | 31 +- .../samples/ide/activegrid/tool/project.py | 549 + .../samples/ide/activegrid/util/__init__.py | 48 - .../samples/ide/activegrid/util/aglogging.py | 299 +- .../samples/ide/activegrid/util/appdirs.py | 59 + .../samples/ide/activegrid/util/fileutils.py | 348 + wxPython/samples/ide/activegrid/util/lang.py | 6 + .../samples/ide/activegrid/util/objutils.py | 343 +- .../samples/ide/activegrid/util/strutils.py | 23 + .../samples/ide/activegrid/util/sysutils.py | 87 + .../ide/activegrid/util/xmlmarshaller.py | 1004 +- .../ide/activegrid/util/xmlprettyprinter.py | 4 +- .../samples/ide/activegrid/util/xmlutils.py | 379 +- wxPython/samples/pydocview/PyDocViewDemo.py | 4 +- wxPython/setup.py | 5 +- wxPython/src/__core_rename.i | 7 + wxPython/src/_bitmap.i | 3 + wxPython/src/_choice.i | 9 + wxPython/src/_clipbrd.i | 3 +- wxPython/src/_combobox.i | 9 + wxPython/src/_core_api.i | 27 + wxPython/src/_dataobj.i | 3 +- wxPython/src/_datetime.i | 16 +- wxPython/src/_defs.i | 2 + wxPython/src/_event.i | 21 +- wxPython/src/_font.i | 12 +- wxPython/src/_functions.i | 2 + wxPython/src/_image.i | 71 +- wxPython/src/_listctrl.i | 3 + wxPython/src/_sizers.i | 8 +- wxPython/src/_statctrls.i | 8 + wxPython/src/_window.i | 11 +- wxPython/src/_xmlres.i | 3 + wxPython/src/helpers.cpp | 154 +- wxPython/src/media.i | 40 +- wxPython/wx/lib/calendar.py | 1 + wxPython/wx/lib/docview.py | 98 +- wxPython/wx/lib/filebrowsebutton.py | 4 +- wxPython/wx/lib/foldpanelbar.py | 82 +- wxPython/wx/lib/hyperlink.py | 27 +- wxPython/wx/lib/masked/maskededit.py | 70 +- wxPython/wx/lib/masked/numctrl.py | 17 +- wxPython/wx/lib/mixins/grid.py | 15 +- wxPython/wx/lib/ogl/_basic.py | 6 +- wxPython/wx/lib/printout.py | 111 +- wxPython/wx/lib/pydocview.py | 397 +- wxPython/wx/lib/throbber.py | 90 +- wxPython/wx/py/CHANGES.txt | 78 + wxPython/wx/py/PyCrust.py | 19 +- wxPython/wx/py/PyShell.py | 15 +- wxPython/wx/py/crust.py | 158 +- wxPython/wx/py/editor.py | 20 +- wxPython/wx/py/editwindow.py | 82 +- wxPython/wx/py/filling.py | 39 +- wxPython/wx/py/frame.py | 613 +- wxPython/wx/py/interpreter.py | 3 +- wxPython/wx/py/shell.py | 405 +- wxPython/wx/py/version.py | 2 +- wxPython/wxPython/_core.py | 8 + 104 files changed, 14076 insertions(+), 46534 deletions(-) create mode 100644 wxPython/demo/data/proclamation.txt delete mode 100644 wxPython/docs/xml/wxPython-metadata.xml create mode 100644 wxPython/samples/ide/activegrid/tool/project.py create mode 100644 wxPython/samples/ide/activegrid/util/appdirs.py create mode 100644 wxPython/samples/ide/activegrid/util/fileutils.py create mode 100644 wxPython/samples/ide/activegrid/util/strutils.py create mode 100644 wxPython/samples/ide/activegrid/util/sysutils.py diff --git a/wxPython/config.py b/wxPython/config.py index 27ce149bf6..aaa18d4928 100644 --- a/wxPython/config.py +++ b/wxPython/config.py @@ -147,6 +147,15 @@ WX_CONFIG = None # Usually you shouldn't need to touch this, but you can set # version, port, etc. and it will be looked for on the # default $PATH. +SYS_WX_CONFIG = None # When installing an in tree build, setup.py uses wx-config + # for two different purposes. First, to determine the prefix + # where files will be installed, and secondly, to initialise + # build_options.py with the correct options for it. + # WX_CONFIG is used for the first task. SYS_WX_CONFIG may + # be set independently, to the value that should appear in + # build_options.py, if it is different to that. The default + # is to use the value of WX_CONFIG. + WXPORT = 'gtk2' # On Linux/Unix there are several ports of wxWidgets available. # Setting this value lets you select which will be used for # the wxPython build. Possibilites are 'gtk', 'gtk2' and @@ -255,8 +264,8 @@ for flag in [ 'BUILD_ACTIVEX', 'BUILD_ANIMATE', 'BUILD_DLLWIDGET', sys.argv[x] = '' # String options -for option in ['WX_CONFIG', 'WXDLLVER', 'BUILD_BASE', 'WXPORT', 'SWIG', - 'CONTRIBS_INC', 'WXPY_SRC', 'FLAVOUR', +for option in ['WX_CONFIG', 'SYS_WX_CONFIG', 'WXDLLVER', 'BUILD_BASE', + 'WXPORT', 'SWIG', 'CONTRIBS_INC', 'WXPY_SRC', 'FLAVOUR', ]: for x in range(len(sys.argv)): if sys.argv[x].find(option) == 0: @@ -272,6 +281,9 @@ sys.argv = filter(None, sys.argv) # build options file #---------------------------------------------------------------------- +if SYS_WX_CONFIG is None: + SYS_WX_CONFIG = WX_CONFIG + build_options_template = """ UNICODE=%d UNDEF_NDEBUG=%d @@ -284,7 +296,7 @@ MONOLITHIC=%d FINAL=%d HYBRID=%d """ % (UNICODE, UNDEF_NDEBUG, INSTALL_MULTIVERSION, FLAVOUR, EP_ADD_OPTS, - WX_CONFIG, WXPORT, MONOLITHIC, FINAL, HYBRID) + SYS_WX_CONFIG, WXPORT, MONOLITHIC, FINAL, HYBRID) try: from build_options import * diff --git a/wxPython/demo/BitmapButton.py b/wxPython/demo/BitmapButton.py index 8edea6b5ee..f1d526fbc8 100644 --- a/wxPython/demo/BitmapButton.py +++ b/wxPython/demo/BitmapButton.py @@ -29,10 +29,16 @@ class TestPanel(wx.Panel): mask = wx.Mask(bmp, wx.BLUE) bmp.SetMask(mask) - b = wx.BitmapButton(self, 30, bmp, (20, 20), + b = wx.BitmapButton(self, -1, bmp, (20, 20), (bmp.GetWidth()+10, bmp.GetHeight()+10)) b.SetToolTipString("This is a bitmap button.") self.Bind(wx.EVT_BUTTON, self.OnClick, b) + + b = wx.BitmapButton(self, -1, bmp, (20, 120), + (bmp.GetWidth()+10, bmp.GetHeight()+10), + style = wx.NO_BORDER) + b.SetToolTipString("This is a bitmap button with \nwx.NO_BORDER style.") + self.Bind(wx.EVT_BUTTON, self.OnClick, b) def OnClick(self, event): diff --git a/wxPython/demo/FileBrowseButton.py b/wxPython/demo/FileBrowseButton.py index 369c245769..2af110a9f8 100644 --- a/wxPython/demo/FileBrowseButton.py +++ b/wxPython/demo/FileBrowseButton.py @@ -27,7 +27,8 @@ class TestPanel(wx.Panel): self, -1, size=(450, -1), changeCallback = self.dbbCallback ) - self.fbbh.SetHistory(['You', 'can', 'put', 'some', 'filenames', 'here']) + self.fbbh.callCallback = False + self.fbbh.SetHistory(['You', 'can', 'put', 'some', 'filenames', 'here'], 4) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.fbb, 0, wx.ALL, 5) @@ -45,6 +46,8 @@ class TestPanel(wx.Panel): def fbbhCallback(self, evt): if hasattr(self, 'fbbh'): value = evt.GetString() + if not value: + return self.log.write('FileBrowseButtonWithHistory: %s\n' % value) history = self.fbbh.GetHistory() if value not in history: diff --git a/wxPython/demo/FoldPanelBar.py b/wxPython/demo/FoldPanelBar.py index 9664b06084..cb4725d650 100644 --- a/wxPython/demo/FoldPanelBar.py +++ b/wxPython/demo/FoldPanelBar.py @@ -344,6 +344,10 @@ class Extended(wx.Frame): # or normal if event.IsChecked(): + self.GetMenuBar().Check(self._singlestyle, False) + self.GetMenuBar().Check(self._exclusivestyle, False) + self._flags = self._flags & ~fpb.FPB_SINGLE_FOLD + self._flags = self._flags & ~fpb.FPB_EXCLUSIVE_FOLD self._flags = self._flags | fpb.FPB_COLLAPSE_TO_BOTTOM else: self._flags = self._flags & ~fpb.FPB_COLLAPSE_TO_BOTTOM @@ -352,13 +356,15 @@ class Extended(wx.Frame): def OnCreateNormalStyle(self, event): - + # recreate with style where only one panel at the time is # allowed to be opened - - # TODO: Not yet implemented even in the C++ class!!!! if event.IsChecked(): + self.GetMenuBar().Check(self._bottomstyle, False) + self.GetMenuBar().Check(self._exclusivestyle, False) + self._flags = self._flags & ~fpb.FPB_EXCLUSIVE_FOLD + self._flags = self._flags & ~fpb.FPB_COLLAPSE_TO_BOTTOM self._flags = self._flags | fpb.FPB_SINGLE_FOLD else: self._flags = self._flags & ~fpb.FPB_SINGLE_FOLD @@ -366,6 +372,23 @@ class Extended(wx.Frame): self.ReCreateFoldPanel(self._flags) + def OnCreateExclusiveStyle(self, event): + + # recreate with style where only one panel at the time is + # allowed to be opened and the others are collapsed to bottom + + if event.IsChecked(): + self.GetMenuBar().Check(self._singlestyle, False) + self.GetMenuBar().Check(self._bottomstyle, False) + self._flags = self._flags & ~fpb.FPB_SINGLE_FOLD + self._flags = self._flags & ~fpb.FPB_COLLAPSE_TO_BOTTOM + self._flags = self._flags | fpb.FPB_EXCLUSIVE_FOLD + else: + self._flags = self._flags & ~fpb.FPB_EXCLUSIVE_FOLD + + self.ReCreateFoldPanel(self._flags) + + def OnCollapseMe(self, event): for i in range(0, self._pnl.GetCount()): @@ -487,8 +510,9 @@ class Extended(wx.Frame): FPBTEST_QUIT = wx.NewId() FPBTEST_REFRESH = wx.NewId() - FPB_BOTTOM_STICK = wx.NewId() + FPB_BOTTOM_FOLD = wx.NewId() FPB_SINGLE_FOLD = wx.NewId() + FPB_EXCLUSIVE_FOLD = wx.NewId() FPBTEST_TOGGLE_WINDOW = wx.NewId() FPBTEST_ABOUT = wx.NewId() @@ -504,10 +528,13 @@ class Extended(wx.Frame): # make fold panel menu fpb_menu = wx.Menu() - fpb_menu.AppendCheckItem(FPB_BOTTOM_STICK, "Create with &fpb.FPB_COLLAPSE_TO_BOTTOM") + fpb_menu.AppendCheckItem(FPB_BOTTOM_FOLD, "Create with &fpb.FPB_COLLAPSE_TO_BOTTOM") - # Not Yet Implemented In The C++ class!!! - # fpb_menu.AppendCheckItem(FPB_SINGLE_FOLD, _T("Create with &FPB_SINGLE_FOLD")) + # Now Implemented! + fpb_menu.AppendCheckItem(FPB_SINGLE_FOLD, "Create with &fpb.FPB_SINGLE_FOLD") + + # Now Implemented! + fpb_menu.AppendCheckItem(FPB_EXCLUSIVE_FOLD, "Create with &fpb.FPB_EXCLUSIVE_FOLD") fpb_menu.AppendSeparator() fpb_menu.Append(FPBTEST_TOGGLE_WINDOW, "&Toggle FoldPanelBar") @@ -528,8 +555,13 @@ class Extended(wx.Frame): self.Bind(wx.EVT_MENU, self.OnAbout, id=FPBTEST_ABOUT) self.Bind(wx.EVT_MENU, self.OnQuit, id=FPBTEST_QUIT) self.Bind(wx.EVT_MENU, self.OnToggleWindow, id=FPBTEST_TOGGLE_WINDOW) - self.Bind(wx.EVT_MENU, self.OnCreateBottomStyle, id=FPB_BOTTOM_STICK) + self.Bind(wx.EVT_MENU, self.OnCreateBottomStyle, id=FPB_BOTTOM_FOLD) self.Bind(wx.EVT_MENU, self.OnCreateNormalStyle, id=FPB_SINGLE_FOLD) + self.Bind(wx.EVT_MENU, self.OnCreateExclusiveStyle, id=FPB_EXCLUSIVE_FOLD) + + self._bottomstyle = FPB_BOTTOM_FOLD + self._singlestyle = FPB_SINGLE_FOLD + self._exclusivestyle = FPB_EXCLUSIVE_FOLD return menu_bar diff --git a/wxPython/demo/GLCanvas.py b/wxPython/demo/GLCanvas.py index 5601305da8..89b984df69 100644 --- a/wxPython/demo/GLCanvas.py +++ b/wxPython/demo/GLCanvas.py @@ -80,6 +80,7 @@ class MyCanvasBase(glcanvas.GLCanvas): # initial mouse position self.lastx = self.x = 30 self.lasty = self.y = 30 + self.size = None self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_PAINT, self.OnPaint) @@ -93,7 +94,7 @@ class MyCanvasBase(glcanvas.GLCanvas): def OnSize(self, event): - size = self.GetClientSize() + size = self.size = self.GetClientSize() if self.GetContext(): self.SetCurrent() glViewport(0, 0, size.width, size.height) @@ -111,6 +112,7 @@ class MyCanvasBase(glcanvas.GLCanvas): def OnMouseDown(self, evt): self.CaptureMouse() + self.x, self.y = self.lastx, self.lasty = evt.GetPosition() def OnMouseUp(self, evt): @@ -119,7 +121,7 @@ class MyCanvasBase(glcanvas.GLCanvas): def OnMouseMotion(self, evt): if evt.Dragging() and evt.LeftIsDown(): - self.x, self.y = self.lastx, self.lasty + self.lastx, self.lasty = self.x, self.y self.x, self.y = evt.GetPosition() self.Refresh(False) @@ -129,25 +131,25 @@ class MyCanvasBase(glcanvas.GLCanvas): class CubeCanvas(MyCanvasBase): def InitGL(self): # set viewing projection - glMatrixMode(GL_PROJECTION); - glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0); + glMatrixMode(GL_PROJECTION) + glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0) # position viewer - glMatrixMode(GL_MODELVIEW); - glTranslatef(0.0, 0.0, -2.0); + glMatrixMode(GL_MODELVIEW) + glTranslatef(0.0, 0.0, -2.0) # position object - glRotatef(self.y, 1.0, 0.0, 0.0); - glRotatef(self.x, 0.0, 1.0, 0.0); + glRotatef(self.y, 1.0, 0.0, 0.0) + glRotatef(self.x, 0.0, 1.0, 0.0) - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST) + glEnable(GL_LIGHTING) + glEnable(GL_LIGHT0) def OnDraw(self): # clear color and depth buffers - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # draw six faces of a cube glBegin(GL_QUADS) @@ -188,8 +190,15 @@ class CubeCanvas(MyCanvasBase): glVertex3f(-0.5, 0.5,-0.5) glEnd() - glRotatef((self.lasty - self.y)/100., 1.0, 0.0, 0.0); - glRotatef((self.lastx - self.x)/100., 0.0, 1.0, 0.0); + if self.size is None: + self.size = self.GetClientSize() + w, h = self.size + w = max(w, 1.0) + h = max(h, 1.0) + xScale = 180.0 / w + yScale = 180.0 / h + glRotatef((self.y - self.lasty) * yScale, 1.0, 0.0, 0.0); + glRotatef((self.x - self.lastx) * xScale, 0.0, 1.0, 0.0); self.SwapBuffers() @@ -199,9 +208,9 @@ class CubeCanvas(MyCanvasBase): class ConeCanvas(MyCanvasBase): def InitGL( self ): - glMatrixMode(GL_PROJECTION); + glMatrixMode(GL_PROJECTION) # camera frustrum setup - glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0); + glFrustum(-0.5, 0.5, -0.5, 0.5, 1.0, 3.0) glMaterial(GL_FRONT, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0]) glMaterial(GL_FRONT, GL_DIFFUSE, [0.8, 0.8, 0.8, 1.0]) glMaterial(GL_FRONT, GL_SPECULAR, [1.0, 0.0, 1.0, 1.0]) @@ -209,7 +218,7 @@ class ConeCanvas(MyCanvasBase): glLight(GL_LIGHT0, GL_AMBIENT, [0.0, 1.0, 0.0, 1.0]) glLight(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0]) glLight(GL_LIGHT0, GL_SPECULAR, [1.0, 1.0, 1.0, 1.0]) - glLight(GL_LIGHT0, GL_POSITION, [1.0, 1.0, 1.0, 0.0]); + glLight(GL_LIGHT0, GL_POSITION, [1.0, 1.0, 1.0, 0.0]) glLightModel(GL_LIGHT_MODEL_AMBIENT, [0.2, 0.2, 0.2, 1.0]) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) @@ -217,25 +226,28 @@ class ConeCanvas(MyCanvasBase): glEnable(GL_DEPTH_TEST) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # position viewer - glMatrixMode(GL_MODELVIEW); + glMatrixMode(GL_MODELVIEW) + # position viewer + glTranslatef(0.0, 0.0, -2.0); + def OnDraw(self): # clear color and depth buffers - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # use a fresh transformation matrix glPushMatrix() # position object - glTranslate(0.0, 0.0, -2.0); - glRotate(30.0, 1.0, 0.0, 0.0); - glRotate(30.0, 0.0, 1.0, 0.0); + #glTranslate(0.0, 0.0, -2.0) + glRotate(30.0, 1.0, 0.0, 0.0) + glRotate(30.0, 0.0, 1.0, 0.0) glTranslate(0, -1, 0) glRotate(250, 1, 0, 0) glutSolidCone(0.5, 1, 30, 5) glPopMatrix() - glRotatef((self.lasty - self.y)/100., 0.0, 0.0, 1.0); - glRotatef(0.0, (self.lastx - self.x)/100., 1.0, 0.0); + glRotatef((self.y - self.lasty), 0.0, 0.0, 1.0); + glRotatef((self.x - self.lastx), 1.0, 0.0, 0.0); # push into visible buffer self.SwapBuffers() diff --git a/wxPython/demo/HyperLinkCtrl.py b/wxPython/demo/HyperLinkCtrl.py index 3986620960..601409eaf3 100644 --- a/wxPython/demo/HyperLinkCtrl.py +++ b/wxPython/demo/HyperLinkCtrl.py @@ -89,7 +89,7 @@ class TestPanel(wx.Panel): def OnRightLink(self, event): - pos = event.GetPosition() + pos = self._hyper3.GetPosition() + event.GetPosition() menuPopUp = wx.Menu("Having a nice day?") ID_MENU_YES = wx.NewId() ID_MENU_NO = wx.NewId() diff --git a/wxPython/demo/LayoutConstraints.py b/wxPython/demo/LayoutConstraints.py index abd5e1a8b2..3484fe5dc7 100644 --- a/wxPython/demo/LayoutConstraints.py +++ b/wxPython/demo/LayoutConstraints.py @@ -56,7 +56,7 @@ class TestLayoutConstraints(wx.Panel): lc.centreY.SameAs (self.panelA, wx.CentreY) lc.height.AsIs () lc.width.PercentOf (self.panelA, wx.Width, 50) - b.SetConstraints(lc); + b.SetConstraints(lc) b = wx.Button(self.panelB, 100, ' Panel B ') lc = wx.LayoutConstraints() @@ -64,7 +64,7 @@ class TestLayoutConstraints(wx.Panel): lc.right.SameAs (self.panelB, wx.Right, 4) lc.height.AsIs () lc.width.AsIs () - b.SetConstraints(lc); + b.SetConstraints(lc) self.panelD = wx.Window(self.panelC, -1, style=wx.SIMPLE_BORDER) self.panelD.SetBackgroundColour(wx.GREEN) @@ -78,14 +78,14 @@ class TestLayoutConstraints(wx.Panel): lc.left.RightOf (self.panelD) lc.height.AsIs () lc.width.AsIs () - b.SetConstraints(lc); + b.SetConstraints(lc) lc = wx.LayoutConstraints() lc.bottom.PercentOf (self.panelC, wx.Height, 50) lc.right.PercentOf (self.panelC, wx.Width, 50) lc.height.SameAs (b, wx.Height) lc.width.SameAs (b, wx.Width) - self.panelD.SetConstraints(lc); + self.panelD.SetConstraints(lc) def OnButton(self, event): diff --git a/wxPython/demo/MDIWindows.py b/wxPython/demo/MDIWindows.py index 8e47f24c02..521c14cc66 100644 --- a/wxPython/demo/MDIWindows.py +++ b/wxPython/demo/MDIWindows.py @@ -1,8 +1,7 @@ import wx - -import MDIDemo -import MDISashDemo +import os +import sys #---------------------------------------------------------------------- @@ -25,14 +24,14 @@ class TestPanel(wx.Panel): self.SetSizer(box) + # These are spawned as new processes because on Mac there can be + # some problems related to having regular frames and MDI frames in + # the same app. def ShowMDIDemo(self, evt): - frame = MDIDemo.MyParentFrame() - frame.Show() + os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, "MDIDemo.py") def ShowMDISashDemo(self, evt): - frame = MDISashDemo.MyParentFrame() - frame.Show() - + os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, "MDISashDemo.py") #---------------------------------------------------------------------- diff --git a/wxPython/demo/Main.py b/wxPython/demo/Main.py index 152a858a44..6e7e0f3cb3 100644 --- a/wxPython/demo/Main.py +++ b/wxPython/demo/Main.py @@ -51,6 +51,7 @@ _treeList = [ 'GIFAnimationCtrl', 'HyperLinkCtrl', 'MultiSplitterWindow', + 'Throbber', ]), # managed windows == things with a (optional) caption you can close @@ -803,7 +804,8 @@ class DemoModules: def LoadDict(self, modID): if self.name != __name__: source = self.modules[modID][1] - description = self.modules[modID][3] + #description = self.modules[modID][3] + description = self.modules[modID][2] try: self.modules[modID][0] = {} @@ -1211,6 +1213,7 @@ class wxPythonDemo(wx.Frame): self.SetMenuBar(self.mainmenu) self.finddata = wx.FindReplaceData() + self.finddata.SetFlags(wx.FR_DOWN) if 0: # This is another way to set Accelerators, in addition to @@ -1528,9 +1531,7 @@ class wxPythonDemo(wx.Frame): self.nb.SetSelection(1) self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find", - wx.FR_NOUPDOWN | - wx.FR_NOMATCHCASE | - wx.FR_NOWHOLEWORD) + wx.FR_NOMATCHCASE | wx.FR_NOWHOLEWORD) self.finddlg.Show(True) @@ -1543,13 +1544,22 @@ class wxPythonDemo(wx.Frame): self.nb.SetSelection(1) end = editor.GetLastPosition() textstring = editor.GetRange(0, end).lower() - start = editor.GetSelection()[1] findstring = self.finddata.GetFindString().lower() - loc = textstring.find(findstring, start) + backward = not (self.finddata.GetFlags() & wx.FR_DOWN) + if backward: + start = editor.GetSelection()[0] + loc = textstring.rfind(findstring, 0, start) + else: + start = editor.GetSelection()[1] + loc = textstring.find(findstring, start) if loc == -1 and start != 0: # string not found, start at beginning - start = 0 - loc = textstring.find(findstring, start) + if backward: + start = end + loc = textstring.rfind(findstring, 0, start) + else: + start = 0 + loc = textstring.find(findstring, start) if loc == -1: dlg = wx.MessageDialog(self, 'Find String Not Found', 'Find String Not Found in Demo File', diff --git a/wxPython/demo/Process.py b/wxPython/demo/Process.py index beea93893c..ad6827cc31 100644 --- a/wxPython/demo/Process.py +++ b/wxPython/demo/Process.py @@ -22,7 +22,8 @@ class TestPanel(wx.Panel): self.cmd = wx.TextCtrl(self, -1, 'python -u data/echo.py') self.exBtn = wx.Button(self, -1, 'Execute') - self.out = wx.TextCtrl(self, -1, '', style=wx.TE_MULTILINE|wx.TE_READONLY) + self.out = wx.TextCtrl(self, -1, '', + style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_RICH2) self.inp = wx.TextCtrl(self, -1, '', style=wx.TE_PROCESS_ENTER) self.sndBtn = wx.Button(self, -1, 'Send') diff --git a/wxPython/demo/StyledTextCtrl_2.py b/wxPython/demo/StyledTextCtrl_2.py index 589407b7cc..788f815a34 100644 --- a/wxPython/demo/StyledTextCtrl_2.py +++ b/wxPython/demo/StyledTextCtrl_2.py @@ -75,33 +75,33 @@ class PythonSTC(stc.StyledTextCtrl): if self.fold_symbols == 0: # Arrow pointing right for contracted folders, arrow pointing down for expanded - self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black"); + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_ARROWDOWN, "black", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_ARROW, "black", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "black", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "black", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") elif self.fold_symbols == 1: # Plus for contracted folders, minus for expanded - self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black"); + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_MINUS, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_PLUS, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_EMPTY, "white", "black") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_EMPTY, "white", "black") elif self.fold_symbols == 2: # Like a flattened tree control using circular headers and curved joins - self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040"); - self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040"); + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_CIRCLEMINUS, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_CIRCLEPLUS, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNERCURVE, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040") + self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNERCURVE, "white", "#404040") elif self.fold_symbols == 3: # Like a flattened tree control using square headers @@ -286,7 +286,7 @@ class PythonSTC(stc.StyledTextCtrl): for lineNum in range(lineCount): if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG: expanding = not self.GetFoldExpanded(lineNum) - break; + break lineNum = 0 @@ -342,7 +342,7 @@ class PythonSTC(stc.StyledTextCtrl): else: line = self.Expand(line, False, force, visLevels-1) else: - line = line + 1; + line = line + 1 return line diff --git a/wxPython/demo/TablePrint.py b/wxPython/demo/TablePrint.py index ce40f69a51..73818dda8a 100644 --- a/wxPython/demo/TablePrint.py +++ b/wxPython/demo/TablePrint.py @@ -1,6 +1,5 @@ import os - import wx import wx.lib.printout as printout @@ -9,6 +8,7 @@ import wx.lib.printout as printout buttonDefs = { 814 : ('PreviewWide', 'Preview print of a wide table'), 815 : ('PreviewNarrow', 'Preview print of a narrow table with color highlights'), + 816 : ('PreviewText', 'Preview print of a text file'), 818 : ('OnPreviewMatrix', 'Preview print of a narrow column grid without a table header'), 817 : ('PreviewLine', 'Preview print to demonstrate the use of line breaks'), 819 : ('PrintWide', 'Direct print (no preview) of a wide table'), @@ -150,6 +150,17 @@ class TablePanel(wx.Panel): prt.SetFooter() prt.Preview() + def PreviewText(self): + prt = printout.PrintTable(self.frame) + prt.SetHeader("PROCLAMATION") + file = open('data/proclamation.txt') + data = [] + for txt in file: + data.append(txt.strip()) + file.close() + prt.data = data + prt.Preview() + def PrintWide(self): self.ReadData() prt = printout.PrintTable(self.frame) diff --git a/wxPython/demo/Throbber.py b/wxPython/demo/Throbber.py index 10b91c667e..45fa4a3638 100644 --- a/wxPython/demo/Throbber.py +++ b/wxPython/demo/Throbber.py @@ -69,6 +69,13 @@ class TestPanel(wx.Panel): pointSize = 8, family = wx.DEFAULT, style = wx.NORMAL, weight = wx.BOLD )) + self.customThrobber = \ + throb.Throbber(self, -1, images, size=(36, 36), + frameDelay = 0.1, + rest = 4, + sequence = [ 1, 5, 2, 7, 3, 6, 4, 4, 4, 4, 7, 2, 2, 0 ] + ) + box = wx.BoxSizer(wx.VERTICAL) sizer = wx.GridBagSizer() box.Add(sizer, 1, wx.EXPAND|wx.ALL, 5) @@ -90,6 +97,18 @@ class TestPanel(wx.Panel): row += 1 + # Add custom throbber to sizer. + row += 2 + sizer.Add( + self.customThrobber, (row, 0), (1, 1), + flag = wx.ALIGN_CENTER|wx.ALL, border=2 + ) + + sizer.Add( + wx.StaticText(self, -1, 'with custom & manual sequences'), + (row, 1), flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT + ) + # start and stop buttons startButton = wx.Button(self, -1, "Start") self.Bind(wx.EVT_BUTTON, self.OnStartAnimation, startButton) @@ -104,9 +123,54 @@ class TestPanel(wx.Panel): ]) sizer.Add( - buttonBox, (len(self.throbbers) + 3, 0), (1, 3), flag = wx.ALIGN_CENTER + buttonBox, (len(self.throbbers) + 2, 0), (1, 3), flag = wx.ALIGN_CENTER ) + # Buttoms for the custom throbber. + nextButton = wx.Button(self, -1, "Next") + self.Bind(wx.EVT_BUTTON, self.OnNext, nextButton) + + prevButton = wx.Button(self, -1, "Previous") + self.Bind(wx.EVT_BUTTON, self.OnPrevious, prevButton) + + incButton = wx.Button(self, -1, "Increment") + self.Bind(wx.EVT_BUTTON, self.OnIncrement, incButton) + + decButton = wx.Button(self, -1, "Decrement") + self.Bind(wx.EVT_BUTTON, self.OnDecrement, decButton) + + revButton = wx.Button(self, -1, "Reverse") + self.Bind(wx.EVT_BUTTON, self.OnReverse, revButton) + + restButton = wx.Button(self, -1, "Rest") + self.Bind(wx.EVT_BUTTON, self.OnRest, restButton) + + startButton = wx.Button(self, -1, "Start") + self.Bind(wx.EVT_BUTTON, self.OnStart, startButton) + + stopButton = wx.Button(self, -1, "Stop") + self.Bind(wx.EVT_BUTTON, self.OnStop, stopButton) + + customBox1 = wx.BoxSizer(wx.HORIZONTAL) + customBox1.AddMany([ + (nextButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5), + (prevButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5), + (incButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5), + (decButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5), + (revButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5), + ]) + + customBox2 = wx.BoxSizer(wx.HORIZONTAL) + customBox2.AddMany([ + (restButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5), + (startButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5), + (stopButton, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5), + ]) + + sizer.Add( customBox1, (len(self.throbbers) + 5, 0), (1, 3), flag = wx.ALIGN_CENTER ) + sizer.Add( customBox2, (len(self.throbbers) + 6, 0), (1, 3), flag = wx.ALIGN_CENTER ) + + # Layout. self.SetSizer(box) self.SetAutoLayout(True) self.Layout() @@ -130,6 +194,30 @@ class TestPanel(wx.Panel): for t in self.throbbers.keys(): self.throbbers[t]['throbber'].Rest() + def OnNext(self, event): + self.customThrobber.Next() + + def OnPrevious(self, event): + self.customThrobber.Previous() + + def OnIncrement(self, event): + self.customThrobber.Increment() + + def OnDecrement(self, event): + self.customThrobber.Decrement() + + def OnReverse(self, event): + self.customThrobber.Reverse() + + def OnRest(self, event): + self.customThrobber.Rest() + + def OnStart(self, event): + self.customThrobber.Start() + + def OnStop(self, event): + self.customThrobber.Stop() + def ShutdownDemo(self): for t in self.throbbers.keys(): self.throbbers[t]['throbber'].Rest() diff --git a/wxPython/demo/XmlResourceHandler.py b/wxPython/demo/XmlResourceHandler.py index 201d06d850..15770de475 100644 --- a/wxPython/demo/XmlResourceHandler.py +++ b/wxPython/demo/XmlResourceHandler.py @@ -71,11 +71,11 @@ class MyCustomPanelXmlHandler(xrc.XmlResourceHandler): def __init__(self): xrc.XmlResourceHandler.__init__(self) # Specify the styles recognized by objects of this type - self.AddStyle("wxNO_3D", wx.NO_3D); - self.AddStyle("wxTAB_TRAVERSAL", wx.TAB_TRAVERSAL); - self.AddStyle("wxWS_EX_VALIDATE_RECURSIVELY", wx.WS_EX_VALIDATE_RECURSIVELY); - self.AddStyle("wxCLIP_CHILDREN", wx.CLIP_CHILDREN); - self.AddWindowStyles(); + self.AddStyle("wxNO_3D", wx.NO_3D) + self.AddStyle("wxTAB_TRAVERSAL", wx.TAB_TRAVERSAL) + self.AddStyle("wxWS_EX_VALIDATE_RECURSIVELY", wx.WS_EX_VALIDATE_RECURSIVELY) + self.AddStyle("wxCLIP_CHILDREN", wx.CLIP_CHILDREN) + self.AddWindowStyles() # This method and the next one are required for XmlResourceHandlers def CanHandle(self, node): diff --git a/wxPython/demo/data/proclamation.txt b/wxPython/demo/data/proclamation.txt new file mode 100644 index 0000000000..5d305e49d8 --- /dev/null +++ b/wxPython/demo/data/proclamation.txt @@ -0,0 +1,115 @@ +EMANCIPATION PROCLAMATION: +By the President of the United States of America: +A PROCLAMATION + + Whereas on the 22nd day of September, A.D. 1862, a proclamation +was issued by the President of the United States, containing, +among other things, the following, to wit: + + "That on the 1st day of January, A.D. 1863, all persons held as +slaves within any State or designated part of a State the people +whereof shall then be in rebellion against the United States shall +be then, thenceforward, and forever free; and the executive +government of the United States, including the military and naval +authority thereof, will recognize and maintain the freedom of such +persons and will do no act or acts to repress such persons, or any +of them, in any efforts they may make for their actual freedom. + + "That the executive will on the 1st day of January aforesaid, +by proclamation, designate the States and parts of States, if any, +in which the people thereof, respectively, shall then be in +rebellion against the United States; and the fact that any State +or the people thereof shall on that day be in good faith +represented in the Congress of the United States by members +chosen thereto at elections wherein a majority of the qualified +voters of such States shall have participated shall, in the +absence of strong countervailing testimony, be deemed conclusive +evidence that such State and the people thereof are not then +in rebellion against the United States." + + Now, therefore, I, Abraham Lincoln, President of the United +States, by virtue of the power in me vested as Commander-In-Chief +of the Army and Navy of the United States in time of actual armed +rebellion against the authority and government of the United States, +and as a fit and necessary war measure for supressing said +rebellion, do, on this 1st day of January, A.D. 1863, and in +accordance with my purpose so to do, publicly proclaimed for the +full period of one hundred days from the first day above mentioned, +order and designate as the States and parts of States wherein the +people thereof, respectively, are this day in rebellion against +the United States the following, to wit: + + Arkansas, Texas, Louisiana (except the parishes of St. Bernard, +Palquemines, Jefferson, St. John, St. Charles, St. James, Ascension, +Assumption, Terrebone, Lafourche, St. Mary, St. Martin, and Orleans, +including the city of New Orleans), Mississippi, Alabama, Florida, +Georgia, South Carolina, North Carolina, and Virginia (except the +forty-eight counties designated as West Virginia, and also the +counties of Berkeley, Accomac, Morthhampton, Elizabeth City, York, +Princess Anne, and Norfolk, including the cities of Norfolk and +Portsmouth), and which excepted parts are for the present left +precisely as if this proclamation were not issued. + + And by virtue of the power and for the purpose aforesaid, I do +order and declare that all persons held as slaves within said +designated States and parts of States are, and henceforward shall +be, free; and that the Executive Government of the United States, +including the military and naval authorities thereof, will +recognize and maintain the freedom of said persons. + + And I hereby enjoin upon the people so declared to be free to +abstain from all violence, unless in necessary self-defence; and +I recommend to them that, in all case when allowed, they labor +faithfully for reasonable wages. + + And I further declare and make known that such persons of +suitable condition will be received into the armed service of +the United States to garrison forts, positions, stations, and +other places, and to man vessels of all sorts in said service. + + And upon this act, sincerely believed to be an act of justice, +warranted by the Constitution upon military necessity, I invoke +the considerate judgment of mankind and the gracious favor +of Almighty God. + +(signed) +ABRAHAM LINCOLN +------------------------------------- + +On Jan. 1, 1863, U.S. President Abraham Lincoln declared free +all slaves residing in territory in rebellion against the federal +government. This Emancipation Proclamation actually freed few +people. It did not apply to slaves in border states fighting on +the Union side; nor did it affect slaves in southern areas already +under Union control. Naturally, the states in rebellion did not +act on Lincoln's order. But the proclamation did show Americans-- +and the world--that the civil war was now being fought to end slavery. + +Lincoln had been reluctant to come to this position. A believer +in white supremacy, he initially viewed the war only in terms of +preserving the Union. As pressure for abolition mounted in +Congress and the country, however, Lincoln became more sympathetic +to the idea. On Sept. 22, 1862, he issued a preliminary proclamation +announcing that emancipation would become effective on Jan. 1, 1863, +in those states still in rebellion. Although the Emancipation +Proclamation did not end slavery in America--this was achieved +by the passage of the 13TH Amendment to the Constitution on Dec. +18, 1865--it did make that accomplishment a basic war goal and +a virtual certainty. + +DOUGLAS T. MILLER + +Bibliography: Commager, Henry Steele, The Great Proclamation +(1960); Donovan, Frank, Mr. Lincoln's Proclamation (1964); +Franklin, John Hope, ed., The Emancipation Proclamation (1964). + +------------------------------------- + +Prepared by Gerald Murphy (The Cleveland Free-Net - aa300) +Distributed by the Cybercasting Services Division of the + National Public Telecomputing Network (NPTN). + +Permission is hereby granted to download, reprint, and/or otherwise + redistribute this file, provided appropriate point of origin + credit is given to the preparer(s) and the National Public + Telecomputing Network. diff --git a/wxPython/distrib/mac/wxPythonOSX/build b/wxPython/distrib/mac/wxPythonOSX/build index 0d7a8153a5..9f71573171 100755 --- a/wxPython/distrib/mac/wxPythonOSX/build +++ b/wxPython/distrib/mac/wxPythonOSX/build @@ -419,7 +419,7 @@ EOF $INSTALLROOT \ $RESOURCEDIR - mv $PKGNAME.pkg $DMGROOT + mv $PKGNAME.pkg $DMGROOT/$PKGNAME.pkg rm $RESOURCEDIR/postflight rm $RESOURCEDIR/preflight @@ -569,7 +569,7 @@ EOF if [ ! -e $TARBALLDIR/wxPython-demo-$VERSION.tar.gz ]; then cat > "$DMGAPPS/Samples/Build ERROR.txt" < - - - -#// Give a reference to the dictionary of this module to the C++ extension -#// code. -_core_._wxPySetDictionary(vars()) - -#// A little trick to make 'wx' be a reference to this module so wx.Names can -#// be used here. -import sys as _sys -wx = _sys.modules[__name__] - - - -#---------------------------------------------------------------------------- - -def _deprecated(callable, msg=None): - """ - Create a wrapper function that will raise a DeprecationWarning - before calling the callable. - """ - if msg is None: - msg = "%s is deprecated" % callable - def deprecatedWrapper(*args, **kwargs): - import warnings - warnings.warn(msg, DeprecationWarning, stacklevel=2) - return callable(*args, **kwargs) - deprecatedWrapper.__doc__ = msg - return deprecatedWrapper - - -#---------------------------------------------------------------------------- - - -#--------------------------------------------------------------------------- - - - The base class for most wx objects, although in wxPython not -much functionality is needed nor exposed. - - GetClassName(self) -> String - Returns the class name of the C++ class using wxRTTI. - - - Destroy(self) - Deletes the C++ object this Python object is a proxy for. - - - -#--------------------------------------------------------------------------- - - -#--------------------------------------------------------------------------- - - - wx.Size is a useful data structure used to represent the size of -something. It simply contians integer width and height proprtites. -In most places in wxPython where a wx.Size is expected a -(width,height) tuple can be used instead. - - __init__(self, int w=0, int h=0) -> Size - Creates a size object. - - - - - - - __del__(self) - - - - - __eq__(self, Size sz) -> bool - Test for equality of wx.Size objects. - - - - - - __ne__(self, Size sz) -> bool - Test for inequality. - - - - - - __add__(self, Size sz) -> Size - Add sz's proprties to this and return the result. - - - - - - __sub__(self, Size sz) -> Size - Subtract sz's properties from this and return the result. - - - - - - IncTo(self, Size sz) - Increments this object so that both of its dimensions are not less -than the corresponding dimensions of the size. - - - - - - DecTo(self, Size sz) - Decrements this object so that both of its dimensions are not greater -than the corresponding dimensions of the size. - - - - - - Set(self, int w, int h) - Set both width and height. - - - - - - - SetWidth(self, int w) - - - - - - SetHeight(self, int h) - - - - - - GetWidth(self) -> int - - - GetHeight(self) -> int - - - IsFullySpecified(self) -> bool - Returns True if both components of the size are non-default values. - - - SetDefaults(self, Size size) - Combine this size with the other one replacing the default components -of this object (i.e. equal to -1) with those of the other. - - - - - - Get() -> (width,height) - Returns the width and height properties as a tuple. - - - -#--------------------------------------------------------------------------- - - - A data structure for representing a point or position with floating -point x and y properties. In wxPython most places that expect a -wx.RealPoint can also accept a (x,y) tuple. - - __init__(self, double x=0.0, double y=0.0) -> RealPoint - Create a wx.RealPoint object - - - - - - - __del__(self) - - - - - __eq__(self, RealPoint pt) -> bool - Test for equality of wx.RealPoint objects. - - - - - - __ne__(self, RealPoint pt) -> bool - Test for inequality of wx.RealPoint objects. - - - - - - __add__(self, RealPoint pt) -> RealPoint - Add pt's proprties to this and return the result. - - - - - - __sub__(self, RealPoint pt) -> RealPoint - Subtract pt's proprties from this and return the result - - - - - - Set(self, double x, double y) - Set both the x and y properties - - - - - - - Get() -> (x,y) - Return the x and y properties as a tuple. - - - -#--------------------------------------------------------------------------- - - - A data structure for representing a point or position with integer x -and y properties. Most places in wxPython that expect a wx.Point can -also accept a (x,y) tuple. - - __init__(self, int x=0, int y=0) -> Point - Create a wx.Point object - - - - - - - __del__(self) - - - - - __eq__(self, Point pt) -> bool - Test for equality of wx.Point objects. - - - - - - __ne__(self, Point pt) -> bool - Test for inequality of wx.Point objects. - - - - - - __add__(self, Point pt) -> Point - Add pt's proprties to this and return the result. - - - - - - __sub__(self, Point pt) -> Point - Subtract pt's proprties from this and return the result - - - - - - __iadd__(self, Point pt) -> Point - Add pt to this object. - - - - - - __isub__(self, Point pt) -> Point - Subtract pt from this object. - - - - - - Set(self, long x, long y) - Set both the x and y properties - - - - - - - Get() -> (x,y) - Return the x and y properties as a tuple. - - - -#--------------------------------------------------------------------------- - - - A class for representing and manipulating rectangles. It has x, y, -width and height properties. In wxPython most palces that expect a -wx.Rect can also accept a (x,y,width,height) tuple. - - __init__(self, int x=0, int y=0, int width=0, int height=0) -> Rect - Create a new Rect object. - - - - - - - - - RectPP(Point topLeft, Point bottomRight) -> Rect - Create a new Rect object from Points representing two corners. - - - - - - - RectPS(Point pos, Size size) -> Rect - Create a new Rect from a position and size. - - - - - - - __del__(self) - - - GetX(self) -> int - - - SetX(self, int x) - - - - - - GetY(self) -> int - - - SetY(self, int y) - - - - - - GetWidth(self) -> int - - - SetWidth(self, int w) - - - - - - GetHeight(self) -> int - - - SetHeight(self, int h) - - - - - - GetPosition(self) -> Point - - - SetPosition(self, Point p) - - - - - - GetSize(self) -> Size - - - SetSize(self, Size s) - - - - - - GetTopLeft(self) -> Point - - - SetTopLeft(self, Point p) - - - - - - GetBottomRight(self) -> Point - - - SetBottomRight(self, Point p) - - - - - - GetLeft(self) -> int - - - GetTop(self) -> int - - - GetBottom(self) -> int - - - GetRight(self) -> int - - - SetLeft(self, int left) - - - - - - SetRight(self, int right) - - - - - - SetTop(self, int top) - - - - - - SetBottom(self, int bottom) - - - - - - Inflate(self, int dx, int dy) -> Rect - Increase the rectangle size by dx in x direction and dy in y -direction. Both or one of) parameters may be negative to decrease the -rectangle size. - - - - - - - Deflate(self, int dx, int dy) -> Rect - Decrease the rectangle size by dx in x direction and dy in y -direction. Both or one of) parameters may be negative to increase the -rectngle size. This method is the opposite of Inflate. - - - - - - - OffsetXY(self, int dx, int dy) - Moves the rectangle by the specified offset. If dx is positive, the -rectangle is moved to the right, if dy is positive, it is moved to the -bottom, otherwise it is moved to the left or top respectively. - - - - - - - Offset(self, Point pt) - Same as OffsetXY but uses dx,dy from Point - - - - - - Intersect(self, Rect rect) -> Rect - Return the intersectsion of this rectangle and rect. - - - - - - __add__(self, Rect rect) -> Rect - Add the properties of rect to this rectangle and return the result. - - - - - - __iadd__(self, Rect rect) -> Rect - Add the properties of rect to this rectangle, updating this rectangle. - - - - - - __eq__(self, Rect rect) -> bool - Test for equality. - - - - - - __ne__(self, Rect rect) -> bool - Test for inequality. - - - - - - InsideXY(self, int x, int y) -> bool - Return True if the point is (not strcitly) inside the rect. - - - - - - - Inside(self, Point pt) -> bool - Return True if the point is (not strcitly) inside the rect. - - - - - - Intersects(self, Rect rect) -> bool - Returns True if the rectangles have a non empty intersection. - - - - - - - - - - Set(self, int x=0, int y=0, int width=0, int height=0) - Set all rectangle properties. - - - - - - - - - Get() -> (x,y,width,height) - Return the rectangle properties as a tuple. - - - - IntersectRect(Rect r1, Rect r2) -> Rect - Calculate and return the intersection of r1 and r2. - - - - - - -#--------------------------------------------------------------------------- - - - wx.Point2Ds represent a point or a vector in a 2d coordinate system -with floating point values. - - __init__(self, double x=0.0, double y=0.0) -> Point2D - Create a w.Point2D object. - - - - - - - Point2DCopy(Point2D pt) -> Point2D - Create a w.Point2D object. - - - - - - Point2DFromPoint(Point pt) -> Point2D - Create a w.Point2D object. - - - - - - GetFloor() -> (x,y) - Convert to integer - - - - - - - GetRounded() -> (x,y) - Convert to integer - - - - - - - GetVectorLength(self) -> double - - - GetVectorAngle(self) -> double - - - SetVectorLength(self, double length) - - - - - - SetVectorAngle(self, double degrees) - - - - - - GetDistance(self, Point2D pt) -> double - - - - - - GetDistanceSquare(self, Point2D pt) -> double - - - - - - GetDotProduct(self, Point2D vec) -> double - - - - - - GetCrossProduct(self, Point2D vec) -> double - - - - - - __neg__(self) -> Point2D - the reflection of this point - - - __iadd__(self, Point2D pt) -> Point2D - - - - - - __isub__(self, Point2D pt) -> Point2D - - - - - - __imul__(self, Point2D pt) -> Point2D - - - - - - __idiv__(self, Point2D pt) -> Point2D - - - - - - __eq__(self, Point2D pt) -> bool - Test for equality - - - - - - __ne__(self, Point2D pt) -> bool - Test for inequality - - - - - - - - Set(self, double x=0, double y=0) - - - - - - - Get() -> (x,y) - Return x and y properties as a tuple. - - - -#--------------------------------------------------------------------------- - - - - __init__(self, PyObject p) -> InputStream - - - - - - close(self) - - - flush(self) - - - eof(self) -> bool - - - read(self, int size=-1) -> PyObject - - - - - - readline(self, int size=-1) -> PyObject - - - - - - readlines(self, int sizehint=-1) -> PyObject - - - - - - seek(self, int offset, int whence=0) - - - - - - - tell(self) -> int - - - Peek(self) -> char - - - GetC(self) -> char - - - LastRead(self) -> size_t - - - CanRead(self) -> bool - - - Eof(self) -> bool - - - Ungetch(self, char c) -> bool - - - - - - SeekI(self, long pos, int mode=FromStart) -> long - - - - - - - TellI(self) -> long - - - - - write(self, PyObject obj) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, InputStream stream, String loc, String mimetype, String anchor, - DateTime modif) -> FSFile - - - - - - - - - - __del__(self) - - - GetStream(self) -> InputStream - - - GetMimeType(self) -> String - - - GetLocation(self) -> String - - - GetAnchor(self) -> String - - - GetModificationTime(self) -> DateTime - - - - - - - __init__(self) -> FileSystemHandler - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - CanOpen(self, String location) -> bool - - - - - - OpenFile(self, FileSystem fs, String location) -> FSFile - - - - - - - FindFirst(self, String spec, int flags=0) -> String - - - - - - - FindNext(self) -> String - - - GetProtocol(self, String location) -> String - - - - - - GetLeftLocation(self, String location) -> String - - - - - - GetAnchor(self, String location) -> String - - - - - - GetRightLocation(self, String location) -> String - - - - - - GetMimeTypeFromExt(self, String location) -> String - - - - - - - - - __init__(self) -> FileSystem - - - __del__(self) - - - ChangePathTo(self, String location, bool is_dir=False) - - - - - - - GetPath(self) -> String - - - OpenFile(self, String location) -> FSFile - - - - - - FindFirst(self, String spec, int flags=0) -> String - - - - - - - FindNext(self) -> String - - - AddHandler(CPPFileSystemHandler handler) - - - - - - CleanUpHandlers() - - - FileNameToURL(String filename) -> String - - - - - - - FileSystem_URLToFileName(String url) -> String - - - - - - - - __init__(self) -> InternetFSHandler - - - CanOpen(self, String location) -> bool - - - - - - OpenFile(self, FileSystem fs, String location) -> FSFile - - - - - - - - - - __init__(self) -> ZipFSHandler - - - CanOpen(self, String location) -> bool - - - - - - OpenFile(self, FileSystem fs, String location) -> FSFile - - - - - - - FindFirst(self, String spec, int flags=0) -> String - - - - - - - FindNext(self) -> String - - - - __wxMemoryFSHandler_AddFile_wxImage(String filename, Image image, long type) - - - - - - - - __wxMemoryFSHandler_AddFile_wxBitmap(String filename, Bitmap bitmap, long type) - - - - - - - - __wxMemoryFSHandler_AddFile_Data(String filename, PyObject data) - - - - - - -def MemoryFSHandler_AddFile(filename, a, b=''): - if isinstance(a, wx.Image): - __wxMemoryFSHandler_AddFile_wxImage(filename, a, b) - elif isinstance(a, wx.Bitmap): - __wxMemoryFSHandler_AddFile_wxBitmap(filename, a, b) - elif type(a) == str: - __wxMemoryFSHandler_AddFile_Data(filename, a) - else: raise TypeError, 'wx.Image, wx.Bitmap or string expected' - - - - - __init__(self) -> MemoryFSHandler - - - RemoveFile(String filename) - - - - - - CanOpen(self, String location) -> bool - - - - - - OpenFile(self, FileSystem fs, String location) -> FSFile - - - - - - - FindFirst(self, String spec, int flags=0) -> String - - - - - - - FindNext(self) -> String - - - -#--------------------------------------------------------------------------- - - - - - GetName(self) -> String - - - GetExtension(self) -> String - - - GetType(self) -> long - - - GetMimeType(self) -> String - - - CanRead(self, String name) -> bool - - - - - - SetName(self, String name) - - - - - - SetExtension(self, String extension) - - - - - - SetType(self, long type) - - - - - - SetMimeType(self, String mimetype) - - - - - - - - __init__(self) -> ImageHistogram - - - MakeKey(unsigned char r, unsigned char g, unsigned char b) -> unsigned long - Get the key in the histogram for the given RGB values - - - - - - - - FindFirstUnusedColour(int startR=1, int startG=0, int startB=0) -> (success, r, g, b) - Find first colour that is not used in the image and has higher RGB -values than startR, startG, startB. Returns a tuple consisting of a -success flag and rgb values. - - - - - - - - - - - - - - __init__(self, String name, long type=BITMAP_TYPE_ANY, int index=-1) -> Image - - - - - - - - ImageFromMime(String name, String mimetype, int index=-1) -> Image - - - - - - - - ImageFromStream(InputStream stream, long type=BITMAP_TYPE_ANY, int index=-1) -> Image - - - - - - - - ImageFromStreamMime(InputStream stream, String mimetype, int index=-1) -> Image - - - - - - - - EmptyImage(int width=0, int height=0, bool clear=True) -> Image - - - - - - - - ImageFromBitmap(Bitmap bitmap) -> Image - - - - - - ImageFromData(int width, int height, unsigned char data) -> Image - - - - - - - - __del__(self) - - - Create(self, int width, int height) - - - - - - - Destroy(self) - Deletes the C++ object this Python object is a proxy for. - - - Scale(self, int width, int height) -> Image - - - - - - - ShrinkBy(self, int xFactor, int yFactor) -> Image - - - - - - - Rescale(self, int width, int height) -> Image - - - - - - - SetRGB(self, int x, int y, unsigned char r, unsigned char g, unsigned char b) - - - - - - - - - - GetRed(self, int x, int y) -> unsigned char - - - - - - - GetGreen(self, int x, int y) -> unsigned char - - - - - - - GetBlue(self, int x, int y) -> unsigned char - - - - - - - SetAlpha(self, int x, int y, unsigned char alpha) - - - - - - - - GetAlpha(self, int x, int y) -> unsigned char - - - - - - - HasAlpha(self) -> bool - - - FindFirstUnusedColour(int startR=1, int startG=0, int startB=0) -> (success, r, g, b) - Find first colour that is not used in the image and has higher RGB -values than startR, startG, startB. Returns a tuple consisting of a -success flag and rgb values. - - - - - - - - - - - ConvertAlphaToMask(self, byte threshold=128) -> bool - If the image has alpha channel, this method converts it to mask. All pixels -with alpha value less than ``threshold`` are replaced with mask colour and the -alpha channel is removed. Mask colour is chosen automatically using -`FindFirstUnusedColour`. - -If the image image doesn't have alpha channel, ConvertAlphaToMask does -nothing. - - - - - - SetMaskFromImage(self, Image mask, byte mr, byte mg, byte mb) -> bool - - - - - - - - - CanRead(String name) -> bool - - - - - - GetImageCount(String name, long type=BITMAP_TYPE_ANY) -> int - - - - - - - LoadFile(self, String name, long type=BITMAP_TYPE_ANY, int index=-1) -> bool - - - - - - - - LoadMimeFile(self, String name, String mimetype, int index=-1) -> bool - - - - - - - - SaveFile(self, String name, int type) -> bool - - - - - - - SaveMimeFile(self, String name, String mimetype) -> bool - - - - - - - CanReadStream(InputStream stream) -> bool - - - - - - LoadStream(self, InputStream stream, long type=BITMAP_TYPE_ANY, int index=-1) -> bool - - - - - - - - LoadMimeStream(self, InputStream stream, String mimetype, int index=-1) -> bool - - - - - - - - Ok(self) -> bool - - - GetWidth(self) -> int - - - GetHeight(self) -> int - - - GetSize(self) -> Size - - - GetSubImage(self, Rect rect) -> Image - - - - - - Copy(self) -> Image - - - Paste(self, Image image, int x, int y) - - - - - - - - GetData(self) -> PyObject - - - SetData(self, PyObject data) - - - - - - GetDataBuffer(self) -> PyObject - - - SetDataBuffer(self, PyObject data) - - - - - - GetAlphaData(self) -> PyObject - - - SetAlphaData(self, PyObject data) - - - - - - GetAlphaBuffer(self) -> PyObject - - - SetAlphaBuffer(self, PyObject data) - - - - - - SetMaskColour(self, unsigned char r, unsigned char g, unsigned char b) - - - - - - - - GetMaskRed(self) -> unsigned char - - - GetMaskGreen(self) -> unsigned char - - - GetMaskBlue(self) -> unsigned char - - - SetMask(self, bool mask=True) - - - - - - HasMask(self) -> bool - - - Rotate(self, double angle, Point centre_of_rotation, bool interpolating=True, - Point offset_after_rotation=None) -> Image - - - - - - - - - Rotate90(self, bool clockwise=True) -> Image - - - - - - Mirror(self, bool horizontally=True) -> Image - - - - - - Replace(self, unsigned char r1, unsigned char g1, unsigned char b1, - unsigned char r2, unsigned char g2, unsigned char b2) - - - - - - - - - - - ConvertToMono(self, unsigned char r, unsigned char g, unsigned char b) -> Image - - - - - - - - SetOption(self, String name, String value) - - - - - - - SetOptionInt(self, String name, int value) - - - - - - - GetOption(self, String name) -> String - - - - - - GetOptionInt(self, String name) -> int - - - - - - HasOption(self, String name) -> bool - - - - - - CountColours(self, unsigned long stopafter=(unsigned long) -1) -> unsigned long - - - - - - ComputeHistogram(self, ImageHistogram h) -> unsigned long - - - - - - AddHandler(ImageHandler handler) - - - - - - InsertHandler(ImageHandler handler) - - - - - - RemoveHandler(String name) -> bool - - - - - - GetImageExtWildcard() -> String - - - ConvertToBitmap(self) -> Bitmap - - - ConvertToMonoBitmap(self, unsigned char red, unsigned char green, unsigned char blue) -> Bitmap - - - - - - - - - def InitAllImageHandlers(): - """ - The former functionality of InitAllImageHanders is now done internal to - the _core_ extension module and so this function has become a simple NOP. - """ - pass - - - - - __init__(self) -> BMPHandler - - - - - - __init__(self) -> ICOHandler - - - - - - __init__(self) -> CURHandler - - - - - - __init__(self) -> ANIHandler - - - - - - __init__(self) -> PNGHandler - - - - - - __init__(self) -> GIFHandler - - - - - - __init__(self) -> PCXHandler - - - - - - __init__(self) -> JPEGHandler - - - - - - __init__(self) -> PNMHandler - - - - - - __init__(self) -> XPMHandler - - - - - - __init__(self) -> TIFFHandler - - - - Performs quantization, or colour reduction, on a wxImage. - - Quantize(Image src, Image dest, int desiredNoColours=236, int flags=wxQUANTIZE_INCLUDE_WINDOWS_COLOURS|wxQUANTIZE_FILL_DESTINATION_IMAGE) -> bool - Reduce the colours in the source image and put the result into the -destination image, setting the palette in the destination if -needed. Both images may be the same, to overwrite the source image. -:todo: Create a version that returns the wx.Palette used. - - - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> EvtHandler - - - GetNextHandler(self) -> EvtHandler - - - GetPreviousHandler(self) -> EvtHandler - - - SetNextHandler(self, EvtHandler handler) - - - - - - SetPreviousHandler(self, EvtHandler handler) - - - - - - GetEvtHandlerEnabled(self) -> bool - - - SetEvtHandlerEnabled(self, bool enabled) - - - - - - ProcessEvent(self, Event event) -> bool - - - - - - AddPendingEvent(self, Event event) - - - - - - ProcessPendingEvents(self) - - - Connect(self, int id, int lastId, int eventType, PyObject func) - - - - - - - - - Disconnect(self, int id, int lastId=-1, wxEventType eventType=wxEVT_NULL) -> bool - - - - - - - - _setOORInfo(self, PyObject _self) - - - - - - - -#--------------------------------------------------------------------------- - -class PyEventBinder(object): - """ - Instances of this class are used to bind specific events to event - handlers. - """ - def __init__(self, evtType, expectedIDs=0): - if expectedIDs not in [0, 1, 2]: - raise ValueError, "Invalid number of expectedIDs" - self.expectedIDs = expectedIDs - - if type(evtType) == list or type(evtType) == tuple: - self.evtType = evtType - else: - self.evtType = [evtType] - - - def Bind(self, target, id1, id2, function): - """Bind this set of event types to target.""" - for et in self.evtType: - target.Connect(id1, id2, et, function) - - - def Unbind(self, target, id1, id2): - """Remove an event binding.""" - success = 0 - for et in self.evtType: - success += target.Disconnect(id1, id2, et) - return success != 0 - - - def __call__(self, *args): - """ - For backwards compatibility with the old EVT_* functions. - Should be called with either (window, func), (window, ID, - func) or (window, ID1, ID2, func) parameters depending on the - type of the event. - """ - assert len(args) == 2 + self.expectedIDs - id1 = wx.ID_ANY - id2 = wx.ID_ANY - target = args[0] - if self.expectedIDs == 0: - func = args[1] - elif self.expectedIDs == 1: - id1 = args[1] - func = args[2] - elif self.expectedIDs == 2: - id1 = args[1] - id2 = args[2] - func = args[3] - else: - raise ValueError, "Unexpected number of IDs" - - self.Bind(target, id1, id2, func) - - -# These two are square pegs that don't fit the PyEventBinder hole... -def EVT_COMMAND(win, id, cmd, func): - win.Connect(id, -1, cmd, func) -def EVT_COMMAND_RANGE(win, id1, id2, cmd, func): - win.Connect(id1, id2, cmd, func) - - -#--------------------------------------------------------------------------- - - -#--------------------------------------------------------------------------- - - - NewEventType() -> wxEventType - - -# -# Create some event binders -EVT_SIZE = wx.PyEventBinder( wxEVT_SIZE ) -EVT_SIZING = wx.PyEventBinder( wxEVT_SIZING ) -EVT_MOVE = wx.PyEventBinder( wxEVT_MOVE ) -EVT_MOVING = wx.PyEventBinder( wxEVT_MOVING ) -EVT_CLOSE = wx.PyEventBinder( wxEVT_CLOSE_WINDOW ) -EVT_END_SESSION = wx.PyEventBinder( wxEVT_END_SESSION ) -EVT_QUERY_END_SESSION = wx.PyEventBinder( wxEVT_QUERY_END_SESSION ) -EVT_PAINT = wx.PyEventBinder( wxEVT_PAINT ) -EVT_NC_PAINT = wx.PyEventBinder( wxEVT_NC_PAINT ) -EVT_ERASE_BACKGROUND = wx.PyEventBinder( wxEVT_ERASE_BACKGROUND ) -EVT_CHAR = wx.PyEventBinder( wxEVT_CHAR ) -EVT_KEY_DOWN = wx.PyEventBinder( wxEVT_KEY_DOWN ) -EVT_KEY_UP = wx.PyEventBinder( wxEVT_KEY_UP ) -EVT_HOTKEY = wx.PyEventBinder( wxEVT_HOTKEY, 1) -EVT_CHAR_HOOK = wx.PyEventBinder( wxEVT_CHAR_HOOK ) -EVT_MENU_OPEN = wx.PyEventBinder( wxEVT_MENU_OPEN ) -EVT_MENU_CLOSE = wx.PyEventBinder( wxEVT_MENU_CLOSE ) -EVT_MENU_HIGHLIGHT = wx.PyEventBinder( wxEVT_MENU_HIGHLIGHT, 1) -EVT_MENU_HIGHLIGHT_ALL = wx.PyEventBinder( wxEVT_MENU_HIGHLIGHT ) -EVT_SET_FOCUS = wx.PyEventBinder( wxEVT_SET_FOCUS ) -EVT_KILL_FOCUS = wx.PyEventBinder( wxEVT_KILL_FOCUS ) -EVT_CHILD_FOCUS = wx.PyEventBinder( wxEVT_CHILD_FOCUS ) -EVT_ACTIVATE = wx.PyEventBinder( wxEVT_ACTIVATE ) -EVT_ACTIVATE_APP = wx.PyEventBinder( wxEVT_ACTIVATE_APP ) -EVT_END_SESSION = wx.PyEventBinder( wxEVT_END_SESSION ) -EVT_QUERY_END_SESSION = wx.PyEventBinder( wxEVT_QUERY_END_SESSION ) -EVT_DROP_FILES = wx.PyEventBinder( wxEVT_DROP_FILES ) -EVT_INIT_DIALOG = wx.PyEventBinder( wxEVT_INIT_DIALOG ) -EVT_SYS_COLOUR_CHANGED = wx.PyEventBinder( wxEVT_SYS_COLOUR_CHANGED ) -EVT_DISPLAY_CHANGED = wx.PyEventBinder( wxEVT_DISPLAY_CHANGED ) -EVT_SHOW = wx.PyEventBinder( wxEVT_SHOW ) -EVT_MAXIMIZE = wx.PyEventBinder( wxEVT_MAXIMIZE ) -EVT_ICONIZE = wx.PyEventBinder( wxEVT_ICONIZE ) -EVT_NAVIGATION_KEY = wx.PyEventBinder( wxEVT_NAVIGATION_KEY ) -EVT_PALETTE_CHANGED = wx.PyEventBinder( wxEVT_PALETTE_CHANGED ) -EVT_QUERY_NEW_PALETTE = wx.PyEventBinder( wxEVT_QUERY_NEW_PALETTE ) -EVT_WINDOW_CREATE = wx.PyEventBinder( wxEVT_CREATE ) -EVT_WINDOW_DESTROY = wx.PyEventBinder( wxEVT_DESTROY ) -EVT_SET_CURSOR = wx.PyEventBinder( wxEVT_SET_CURSOR ) -EVT_MOUSE_CAPTURE_CHANGED = wx.PyEventBinder( wxEVT_MOUSE_CAPTURE_CHANGED ) - -EVT_LEFT_DOWN = wx.PyEventBinder( wxEVT_LEFT_DOWN ) -EVT_LEFT_UP = wx.PyEventBinder( wxEVT_LEFT_UP ) -EVT_MIDDLE_DOWN = wx.PyEventBinder( wxEVT_MIDDLE_DOWN ) -EVT_MIDDLE_UP = wx.PyEventBinder( wxEVT_MIDDLE_UP ) -EVT_RIGHT_DOWN = wx.PyEventBinder( wxEVT_RIGHT_DOWN ) -EVT_RIGHT_UP = wx.PyEventBinder( wxEVT_RIGHT_UP ) -EVT_MOTION = wx.PyEventBinder( wxEVT_MOTION ) -EVT_LEFT_DCLICK = wx.PyEventBinder( wxEVT_LEFT_DCLICK ) -EVT_MIDDLE_DCLICK = wx.PyEventBinder( wxEVT_MIDDLE_DCLICK ) -EVT_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_RIGHT_DCLICK ) -EVT_LEAVE_WINDOW = wx.PyEventBinder( wxEVT_LEAVE_WINDOW ) -EVT_ENTER_WINDOW = wx.PyEventBinder( wxEVT_ENTER_WINDOW ) -EVT_MOUSEWHEEL = wx.PyEventBinder( wxEVT_MOUSEWHEEL ) - -EVT_MOUSE_EVENTS = wx.PyEventBinder([ wxEVT_LEFT_DOWN, - wxEVT_LEFT_UP, - wxEVT_MIDDLE_DOWN, - wxEVT_MIDDLE_UP, - wxEVT_RIGHT_DOWN, - wxEVT_RIGHT_UP, - wxEVT_MOTION, - wxEVT_LEFT_DCLICK, - wxEVT_MIDDLE_DCLICK, - wxEVT_RIGHT_DCLICK, - wxEVT_ENTER_WINDOW, - wxEVT_LEAVE_WINDOW, - wxEVT_MOUSEWHEEL - ]) - - -# Scrolling from wxWindow (sent to wxScrolledWindow) -EVT_SCROLLWIN = wx.PyEventBinder([ wxEVT_SCROLLWIN_TOP, - wxEVT_SCROLLWIN_BOTTOM, - wxEVT_SCROLLWIN_LINEUP, - wxEVT_SCROLLWIN_LINEDOWN, - wxEVT_SCROLLWIN_PAGEUP, - wxEVT_SCROLLWIN_PAGEDOWN, - wxEVT_SCROLLWIN_THUMBTRACK, - wxEVT_SCROLLWIN_THUMBRELEASE, - ]) - -EVT_SCROLLWIN_TOP = wx.PyEventBinder( wxEVT_SCROLLWIN_TOP ) -EVT_SCROLLWIN_BOTTOM = wx.PyEventBinder( wxEVT_SCROLLWIN_BOTTOM ) -EVT_SCROLLWIN_LINEUP = wx.PyEventBinder( wxEVT_SCROLLWIN_LINEUP ) -EVT_SCROLLWIN_LINEDOWN = wx.PyEventBinder( wxEVT_SCROLLWIN_LINEDOWN ) -EVT_SCROLLWIN_PAGEUP = wx.PyEventBinder( wxEVT_SCROLLWIN_PAGEUP ) -EVT_SCROLLWIN_PAGEDOWN = wx.PyEventBinder( wxEVT_SCROLLWIN_PAGEDOWN ) -EVT_SCROLLWIN_THUMBTRACK = wx.PyEventBinder( wxEVT_SCROLLWIN_THUMBTRACK ) -EVT_SCROLLWIN_THUMBRELEASE = wx.PyEventBinder( wxEVT_SCROLLWIN_THUMBRELEASE ) - -# Scrolling from wxSlider and wxScrollBar -EVT_SCROLL = wx.PyEventBinder([ wxEVT_SCROLL_TOP, - wxEVT_SCROLL_BOTTOM, - wxEVT_SCROLL_LINEUP, - wxEVT_SCROLL_LINEDOWN, - wxEVT_SCROLL_PAGEUP, - wxEVT_SCROLL_PAGEDOWN, - wxEVT_SCROLL_THUMBTRACK, - wxEVT_SCROLL_THUMBRELEASE, - wxEVT_SCROLL_ENDSCROLL, - ]) - -EVT_SCROLL_TOP = wx.PyEventBinder( wxEVT_SCROLL_TOP ) -EVT_SCROLL_BOTTOM = wx.PyEventBinder( wxEVT_SCROLL_BOTTOM ) -EVT_SCROLL_LINEUP = wx.PyEventBinder( wxEVT_SCROLL_LINEUP ) -EVT_SCROLL_LINEDOWN = wx.PyEventBinder( wxEVT_SCROLL_LINEDOWN ) -EVT_SCROLL_PAGEUP = wx.PyEventBinder( wxEVT_SCROLL_PAGEUP ) -EVT_SCROLL_PAGEDOWN = wx.PyEventBinder( wxEVT_SCROLL_PAGEDOWN ) -EVT_SCROLL_THUMBTRACK = wx.PyEventBinder( wxEVT_SCROLL_THUMBTRACK ) -EVT_SCROLL_THUMBRELEASE = wx.PyEventBinder( wxEVT_SCROLL_THUMBRELEASE ) -EVT_SCROLL_ENDSCROLL = wx.PyEventBinder( wxEVT_SCROLL_ENDSCROLL ) - -# Scrolling from wxSlider and wxScrollBar, with an id -EVT_COMMAND_SCROLL = wx.PyEventBinder([ wxEVT_SCROLL_TOP, - wxEVT_SCROLL_BOTTOM, - wxEVT_SCROLL_LINEUP, - wxEVT_SCROLL_LINEDOWN, - wxEVT_SCROLL_PAGEUP, - wxEVT_SCROLL_PAGEDOWN, - wxEVT_SCROLL_THUMBTRACK, - wxEVT_SCROLL_THUMBRELEASE, - wxEVT_SCROLL_ENDSCROLL, - ], 1) - -EVT_COMMAND_SCROLL_TOP = wx.PyEventBinder( wxEVT_SCROLL_TOP, 1) -EVT_COMMAND_SCROLL_BOTTOM = wx.PyEventBinder( wxEVT_SCROLL_BOTTOM, 1) -EVT_COMMAND_SCROLL_LINEUP = wx.PyEventBinder( wxEVT_SCROLL_LINEUP, 1) -EVT_COMMAND_SCROLL_LINEDOWN = wx.PyEventBinder( wxEVT_SCROLL_LINEDOWN, 1) -EVT_COMMAND_SCROLL_PAGEUP = wx.PyEventBinder( wxEVT_SCROLL_PAGEUP, 1) -EVT_COMMAND_SCROLL_PAGEDOWN = wx.PyEventBinder( wxEVT_SCROLL_PAGEDOWN, 1) -EVT_COMMAND_SCROLL_THUMBTRACK = wx.PyEventBinder( wxEVT_SCROLL_THUMBTRACK, 1) -EVT_COMMAND_SCROLL_THUMBRELEASE = wx.PyEventBinder( wxEVT_SCROLL_THUMBRELEASE, 1) -EVT_COMMAND_SCROLL_ENDSCROLL = wx.PyEventBinder( wxEVT_SCROLL_ENDSCROLL, 1) - -EVT_BUTTON = wx.PyEventBinder( wxEVT_COMMAND_BUTTON_CLICKED, 1) -EVT_CHECKBOX = wx.PyEventBinder( wxEVT_COMMAND_CHECKBOX_CLICKED, 1) -EVT_CHOICE = wx.PyEventBinder( wxEVT_COMMAND_CHOICE_SELECTED, 1) -EVT_LISTBOX = wx.PyEventBinder( wxEVT_COMMAND_LISTBOX_SELECTED, 1) -EVT_LISTBOX_DCLICK = wx.PyEventBinder( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, 1) -EVT_MENU = wx.PyEventBinder( wxEVT_COMMAND_MENU_SELECTED, 1) -EVT_MENU_RANGE = wx.PyEventBinder( wxEVT_COMMAND_MENU_SELECTED, 2) -EVT_SLIDER = wx.PyEventBinder( wxEVT_COMMAND_SLIDER_UPDATED, 1) -EVT_RADIOBOX = wx.PyEventBinder( wxEVT_COMMAND_RADIOBOX_SELECTED, 1) -EVT_RADIOBUTTON = wx.PyEventBinder( wxEVT_COMMAND_RADIOBUTTON_SELECTED, 1) - -EVT_SCROLLBAR = wx.PyEventBinder( wxEVT_COMMAND_SCROLLBAR_UPDATED, 1) -EVT_VLBOX = wx.PyEventBinder( wxEVT_COMMAND_VLBOX_SELECTED, 1) -EVT_COMBOBOX = wx.PyEventBinder( wxEVT_COMMAND_COMBOBOX_SELECTED, 1) -EVT_TOOL = wx.PyEventBinder( wxEVT_COMMAND_TOOL_CLICKED, 1) -EVT_TOOL_RANGE = wx.PyEventBinder( wxEVT_COMMAND_TOOL_CLICKED, 2) -EVT_TOOL_RCLICKED = wx.PyEventBinder( wxEVT_COMMAND_TOOL_RCLICKED, 1) -EVT_TOOL_RCLICKED_RANGE = wx.PyEventBinder( wxEVT_COMMAND_TOOL_RCLICKED, 2) -EVT_TOOL_ENTER = wx.PyEventBinder( wxEVT_COMMAND_TOOL_ENTER, 1) -EVT_CHECKLISTBOX = wx.PyEventBinder( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, 1) - - -EVT_COMMAND_LEFT_CLICK = wx.PyEventBinder( wxEVT_COMMAND_LEFT_CLICK, 1) -EVT_COMMAND_LEFT_DCLICK = wx.PyEventBinder( wxEVT_COMMAND_LEFT_DCLICK, 1) -EVT_COMMAND_RIGHT_CLICK = wx.PyEventBinder( wxEVT_COMMAND_RIGHT_CLICK, 1) -EVT_COMMAND_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_COMMAND_RIGHT_DCLICK, 1) -EVT_COMMAND_SET_FOCUS = wx.PyEventBinder( wxEVT_COMMAND_SET_FOCUS, 1) -EVT_COMMAND_KILL_FOCUS = wx.PyEventBinder( wxEVT_COMMAND_KILL_FOCUS, 1) -EVT_COMMAND_ENTER = wx.PyEventBinder( wxEVT_COMMAND_ENTER, 1) - -EVT_IDLE = wx.PyEventBinder( wxEVT_IDLE ) - -EVT_UPDATE_UI = wx.PyEventBinder( wxEVT_UPDATE_UI, 1) -EVT_UPDATE_UI_RANGE = wx.PyEventBinder( wxEVT_UPDATE_UI, 2) - -EVT_CONTEXT_MENU = wx.PyEventBinder( wxEVT_CONTEXT_MENU ) - - - - -#--------------------------------------------------------------------------- - - - - - __del__(self) - - - SetEventType(self, wxEventType typ) - - - - - - GetEventType(self) -> wxEventType - - - GetEventObject(self) -> Object - - - SetEventObject(self, Object obj) - - - - - - GetTimestamp(self) -> long - - - SetTimestamp(self, long ts=0) - - - - - - GetId(self) -> int - - - SetId(self, int Id) - - - - - - IsCommandEvent(self) -> bool - - - Skip(self, bool skip=True) - - - - - - GetSkipped(self) -> bool - - - ShouldPropagate(self) -> bool - - - StopPropagation(self) -> int - - - ResumePropagation(self, int propagationLevel) - - - - - - Clone(self) -> Event - - - -#--------------------------------------------------------------------------- - - - - __init__(self, Event event) -> PropagationDisabler - - - - - - __del__(self) - - - - - __init__(self, Event event) -> PropagateOnce - - - - - - __del__(self) - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int winid=0) -> CommandEvent - - - - - - - GetSelection(self) -> int - - - SetString(self, String s) - - - - - - GetString(self) -> String - - - IsChecked(self) -> bool - - - IsSelection(self) -> bool - - - SetExtraLong(self, long extraLong) - - - - - - GetExtraLong(self) -> long - - - SetInt(self, int i) - - - - - - GetInt(self) -> long - - - Clone(self) -> Event - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int winid=0) -> NotifyEvent - - - - - - - Veto(self) - - - Allow(self) - - - IsAllowed(self) -> bool - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int winid=0, int pos=0, - int orient=0) -> ScrollEvent - - - - - - - - - GetOrientation(self) -> int - - - GetPosition(self) -> int - - - SetOrientation(self, int orient) - - - - - - SetPosition(self, int pos) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int pos=0, int orient=0) -> ScrollWinEvent - - - - - - - - GetOrientation(self) -> int - - - GetPosition(self) -> int - - - SetOrientation(self, int orient) - - - - - - SetPosition(self, int pos) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType mouseType=wxEVT_NULL) -> MouseEvent - - - - - - IsButton(self) -> bool - - - ButtonDown(self, int but=MOUSE_BTN_ANY) -> bool - - - - - - ButtonDClick(self, int but=MOUSE_BTN_ANY) -> bool - - - - - - ButtonUp(self, int but=MOUSE_BTN_ANY) -> bool - - - - - - Button(self, int but) -> bool - - - - - - ButtonIsDown(self, int but) -> bool - - - - - - GetButton(self) -> int - - - ControlDown(self) -> bool - - - MetaDown(self) -> bool - - - AltDown(self) -> bool - - - ShiftDown(self) -> bool - - - CmdDown(self) -> bool - "Cmd" is a pseudo key which is the same as Control for PC and Unix -platforms but the special "Apple" (a.k.a as "Command") key on -Macs: it makes often sense to use it instead of, say, `ControlDown` -because Cmd key is used for the same thing under Mac as Ctrl -elsewhere. The Ctrl still exists, it's just not used for this -purpose. So for non-Mac platforms this is the same as `ControlDown` -and Macs this is the same as `MetaDown`. - - - LeftDown(self) -> bool - - - MiddleDown(self) -> bool - - - RightDown(self) -> bool - - - LeftUp(self) -> bool - - - MiddleUp(self) -> bool - - - RightUp(self) -> bool - - - LeftDClick(self) -> bool - - - MiddleDClick(self) -> bool - - - RightDClick(self) -> bool - - - LeftIsDown(self) -> bool - - - MiddleIsDown(self) -> bool - - - RightIsDown(self) -> bool - - - Dragging(self) -> bool - - - Moving(self) -> bool - - - Entering(self) -> bool - - - Leaving(self) -> bool - - - GetPosition(self) -> Point - Returns the position of the mouse in window coordinates when the event -happened. - - - GetPositionTuple() -> (x,y) - Returns the position of the mouse in window coordinates when the event -happened. - - - - - - - GetLogicalPosition(self, DC dc) -> Point - - - - - - GetX(self) -> int - - - GetY(self) -> int - - - GetWheelRotation(self) -> int - - - GetWheelDelta(self) -> int - - - GetLinesPerAction(self) -> int - - - IsPageScroll(self) -> bool - - - - - - - - - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int x=0, int y=0) -> SetCursorEvent - - - - - - - GetX(self) -> int - - - GetY(self) -> int - - - SetCursor(self, Cursor cursor) - - - - - - GetCursor(self) -> Cursor - - - HasCursor(self) -> bool - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType keyType=wxEVT_NULL) -> KeyEvent - - - - - - ControlDown(self) -> bool - - - MetaDown(self) -> bool - - - AltDown(self) -> bool - - - ShiftDown(self) -> bool - - - CmdDown(self) -> bool - "Cmd" is a pseudo key which is the same as Control for PC and Unix -platforms but the special "Apple" (a.k.a as "Command") key on -Macs: it makes often sense to use it instead of, say, `ControlDown` -because Cmd key is used for the same thing under Mac as Ctrl -elsewhere. The Ctrl still exists, it's just not used for this -purpose. So for non-Mac platforms this is the same as `ControlDown` -and Macs this is the same as `MetaDown`. - - - HasModifiers(self) -> bool - - - GetKeyCode(self) -> int - - - GetUnicodeKey(self) -> int - - - GetRawKeyCode(self) -> unsigned int - - - GetRawKeyFlags(self) -> unsigned int - - - GetPosition(self) -> Point - Find the position of the event. - - - GetPositionTuple() -> (x,y) - Find the position of the event. - - - - - - - GetX(self) -> int - - - GetY(self) -> int - - - - - - - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Size sz=DefaultSize, int winid=0) -> SizeEvent - - - - - - - GetSize(self) -> Size - - - GetRect(self) -> Rect - - - SetRect(self, Rect rect) - - - - - - SetSize(self, Size size) - - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Point pos=DefaultPosition, int winid=0) -> MoveEvent - - - - - - - GetPosition(self) -> Point - - - GetRect(self) -> Rect - - - SetRect(self, Rect rect) - - - - - - SetPosition(self, Point pos) - - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int Id=0) -> PaintEvent - - - - - - - - - __init__(self, int winid=0) -> NcPaintEvent - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int Id=0, DC dc=(wxDC *) NULL) -> EraseEvent - - - - - - - GetDC(self) -> DC - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType type=wxEVT_NULL, int winid=0) -> FocusEvent - - - - - - - GetWindow(self) -> Window - - - SetWindow(self, Window win) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window win=None) -> ChildFocusEvent - - - - - - GetWindow(self) -> Window - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType type=wxEVT_NULL, bool active=True, int Id=0) -> ActivateEvent - - - - - - - - GetActive(self) -> bool - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int Id=0) -> InitDialogEvent - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType type=wxEVT_NULL, int winid=0, Menu menu=None) -> MenuEvent - - - - - - - - GetMenuId(self) -> int - - - IsPopup(self) -> bool - - - GetMenu(self) -> Menu - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType type=wxEVT_NULL, int winid=0) -> CloseEvent - - - - - - - SetLoggingOff(self, bool logOff) - - - - - - GetLoggingOff(self) -> bool - - - Veto(self, bool veto=True) - - - - - - SetCanVeto(self, bool canVeto) - - - - - - CanVeto(self) -> bool - - - GetVeto(self) -> bool - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int winid=0, bool show=False) -> ShowEvent - - - - - - - SetShow(self, bool show) - - - - - - GetShow(self) -> bool - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int id=0, bool iconized=True) -> IconizeEvent - - - - - - - Iconized(self) -> bool - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int id=0) -> MaximizeEvent - - - - - - -#--------------------------------------------------------------------------- - - - - - GetPosition(self) -> Point - - - GetNumberOfFiles(self) -> int - - - GetFiles(self) -> PyObject - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int commandId=0) -> UpdateUIEvent - - - - - - GetChecked(self) -> bool - - - GetEnabled(self) -> bool - - - GetText(self) -> String - - - GetSetText(self) -> bool - - - GetSetChecked(self) -> bool - - - GetSetEnabled(self) -> bool - - - Check(self, bool check) - - - - - - Enable(self, bool enable) - - - - - - SetText(self, String text) - - - - - - SetUpdateInterval(long updateInterval) - - - - - - GetUpdateInterval() -> long - - - CanUpdate(Window win) -> bool - - - - - - ResetUpdateTime() - - - SetMode(int mode) - - - - - - GetMode() -> int - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> SysColourChangedEvent - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int winid=0, Window gainedCapture=None) -> MouseCaptureChangedEvent - - - - - - - GetCapturedWindow(self) -> Window - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> DisplayChangedEvent - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int id=0) -> PaletteChangedEvent - - - - - - SetChangedWindow(self, Window win) - - - - - - GetChangedWindow(self) -> Window - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int winid=0) -> QueryNewPaletteEvent - - - - - - SetPaletteRealized(self, bool realized) - - - - - - GetPaletteRealized(self) -> bool - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> NavigationKeyEvent - - - GetDirection(self) -> bool - - - SetDirection(self, bool forward) - - - - - - IsWindowChange(self) -> bool - - - SetWindowChange(self, bool ischange) - - - - - - SetFlags(self, long flags) - - - - - - GetCurrentFocus(self) -> Window - - - SetCurrentFocus(self, Window win) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window win=None) -> WindowCreateEvent - - - - - - GetWindow(self) -> Window - - - - - - __init__(self, Window win=None) -> WindowDestroyEvent - - - - - - GetWindow(self) -> Window - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType type=wxEVT_NULL, int winid=0, Point pt=DefaultPosition) -> ContextMenuEvent - - - - - - - - GetPosition(self) -> Point - - - SetPosition(self, Point pos) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> IdleEvent - - - RequestMore(self, bool needMore=True) - - - - - - MoreRequested(self) -> bool - - - SetMode(int mode) - - - - - - GetMode() -> int - - - CanSend(Window win) -> bool - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int winid=0, wxEventType commandType=wxEVT_NULL) -> PyEvent - - - - - - - __del__(self) - - - SetSelf(self, PyObject self) - - - - - - GetSelf(self) -> PyObject - - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int id=0) -> PyCommandEvent - - - - - - - __del__(self) - - - SetSelf(self, PyObject self) - - - - - - GetSelf(self) -> PyObject - - - -#--------------------------------------------------------------------------- - - - The ``wx.PyApp`` class is an *implementation detail*, please use the -`wx.App` class (or some other derived class) instead. - - - __init__(self) -> PyApp - Create a new application object, starting the bootstrap process. - - - __del__(self) - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - GetAppName(self) -> String - Get the application name. - - - SetAppName(self, String name) - Set the application name. This value may be used automatically by -`wx.Config` and such. - - - - - - GetClassName(self) -> String - Get the application's class name. - - - SetClassName(self, String name) - Set the application's class name. This value may be used for -X-resources if applicable for the platform - - - - - - GetVendorName(self) -> String - Get the application's vendor name. - - - SetVendorName(self, String name) - Set the application's vendor name. This value may be used -automatically by `wx.Config` and such. - - - - - - GetTraits(self) -> wxAppTraits - Return (and create if necessary) the app traits object to which we -delegate for everything which either should be configurable by the -user (then he can change the default behaviour simply by overriding -CreateTraits() and returning his own traits object) or which is -GUI/console dependent as then wx.AppTraits allows us to abstract the -differences behind the common facade. - -:todo: Add support for overriding CreateAppTraits in wxPython. - - - ProcessPendingEvents(self) - Process all events in the Pending Events list -- it is necessary to -call this function to process posted events. This normally happens -during each event loop iteration. - - - Yield(self, bool onlyIfNeeded=False) -> bool - Process all currently pending events right now, instead of waiting -until return to the event loop. It is an error to call ``Yield`` -recursively unless the value of ``onlyIfNeeded`` is True. - -:warning: This function is dangerous as it can lead to unexpected - reentrancies (i.e. when called from an event handler it may - result in calling the same event handler again), use with - extreme care or, better, don't use at all! - -:see: `wx.Yield`, `wx.YieldIfNeeded`, `wx.SafeYield` - - - - - - - WakeUpIdle(self) - Make sure that idle events are sent again. -:see: `wx.WakeUpIdle` - - - MainLoop(self) -> int - Execute the main GUI loop, the function doesn't normally return until -all top level windows have been closed and destroyed. - - - Exit(self) - Exit the main loop thus terminating the application. -:see: `wx.Exit` - - - ExitMainLoop(self) - Exit the main GUI loop during the next iteration of the main -loop, (i.e. it does not stop the program immediately!) - - - Pending(self) -> bool - Returns True if there are unprocessed events in the event queue. - - - Dispatch(self) -> bool - Process the first event in the event queue (blocks until an event -appears if there are none currently) - - - ProcessIdle(self) -> bool - Called from the MainLoop when the application becomes idle (there are -no pending events) and sends a `wx.IdleEvent` to all interested -parties. Returns True if more idle events are needed, False if not. - - - SendIdleEvents(self, Window win, IdleEvent event) -> bool - Send idle event to window and all subwindows. Returns True if more -idle time is requested. - - - - - - - IsActive(self) -> bool - Return True if our app has focus. - - - SetTopWindow(self, Window win) - Set the *main* top level window - - - - - - GetTopWindow(self) -> Window - Return the *main* top level window (if it hadn't been set previously -with SetTopWindow(), will return just some top level window and, if -there not any, will return None) - - - SetExitOnFrameDelete(self, bool flag) - Control the exit behaviour: by default, the program will exit the main -loop (and so, usually, terminate) when the last top-level program -window is deleted. Beware that if you disable this behaviour (with -SetExitOnFrameDelete(False)), you'll have to call ExitMainLoop() -explicitly from somewhere. - - - - - - GetExitOnFrameDelete(self) -> bool - Get the current exit behaviour setting. - - - SetUseBestVisual(self, bool flag) - Set whether the app should try to use the best available visual on -systems where more than one is available, (Sun, SGI, XFree86 4, etc.) - - - - - - GetUseBestVisual(self) -> bool - Get current UseBestVisual setting. - - - SetPrintMode(self, int mode) - - - - - - GetPrintMode(self) -> int - - - SetAssertMode(self, int mode) - Set the OnAssert behaviour for debug and hybrid builds.The following flags may be or'd together: - - ========================= ======================================= - wx.PYAPP_ASSERT_SUPPRESS Don't do anything - wx.PYAPP_ASSERT_EXCEPTION Turn it into a Python exception if possible - (default) - wx.PYAPP_ASSERT_DIALOG Display a message dialog - wx.PYAPP_ASSERT_LOG Write the assertion info to the wx.Log - ========================= ======================================= - - - - - - - - GetAssertMode(self) -> int - Get the current OnAssert behaviour setting. - - - GetMacSupportPCMenuShortcuts() -> bool - - - GetMacAboutMenuItemId() -> long - - - GetMacPreferencesMenuItemId() -> long - - - GetMacExitMenuItemId() -> long - - - GetMacHelpMenuTitleName() -> String - - - SetMacSupportPCMenuShortcuts(bool val) - - - - - - SetMacAboutMenuItemId(long val) - - - - - - SetMacPreferencesMenuItemId(long val) - - - - - - SetMacExitMenuItemId(long val) - - - - - - SetMacHelpMenuTitleName(String val) - - - - - - _BootstrapApp(self) - For internal use only - - - GetComCtl32Version() -> int - Returns 400, 470, 471, etc. for comctl32.dll 4.00, 4.70, 4.71 or 0 if -it wasn't found at all. Raises an exception on non-Windows platforms. - - - -#--------------------------------------------------------------------------- - - - Exit() - Force an exit of the application. Convenience for wx.GetApp().Exit() - - - Yield() -> bool - Yield to other apps/messages. Convenience for wx.GetApp().Yield() - - - YieldIfNeeded() -> bool - Yield to other apps/messages. Convenience for wx.GetApp().Yield(True) - - - SafeYield(Window win=None, bool onlyIfNeeded=False) -> bool - This function is similar to `wx.Yield`, except that it disables the -user input to all program windows before calling `wx.Yield` and -re-enables it again afterwards. If ``win`` is not None, this window -will remain enabled, allowing the implementation of some limited user -interaction. - -:Returns: the result of the call to `wx.Yield`. - - - - - - - WakeUpIdle() - Cause the message queue to become empty again, so idle events will be -sent. - - - PostEvent(EvtHandler dest, Event event) - Send an event to a window or other wx.EvtHandler to be processed -later. - - - - - - - App_CleanUp() - For internal use only, it is used to cleanup after wxWidgets when -Python shuts down. - - - GetApp() -> PyApp - Return a reference to the current wx.App object. - - -#---------------------------------------------------------------------- - -class PyOnDemandOutputWindow: - """ - A class that can be used for redirecting Python's stdout and - stderr streams. It will do nothing until something is wrriten to - the stream at which point it will create a Frame with a text area - and write the text there. - """ - def __init__(self, title = "wxPython: stdout/stderr"): - self.frame = None - self.title = title - self.pos = wx.DefaultPosition - self.size = (450, 300) - self.parent = None - - def SetParent(self, parent): - """Set the window to be used as the popup Frame's parent.""" - self.parent = parent - - - def CreateOutputWindow(self, st): - self.frame = wx.Frame(self.parent, -1, self.title, self.pos, self.size, - style=wx.DEFAULT_FRAME_STYLE) - self.text = wx.TextCtrl(self.frame, -1, "", - style=wx.TE_MULTILINE|wx.TE_READONLY) - self.text.AppendText(st) - self.frame.Show(True) - EVT_CLOSE(self.frame, self.OnCloseWindow) - - - def OnCloseWindow(self, event): - if self.frame is not None: - self.frame.Destroy() - self.frame = None - self.text = None - - - # These methods provide the file-like output behaviour. - def write(self, text): - """ - Create the output window if needed and write the string to it. - If not called in the context of the gui thread then uses - CallAfter to do the work there. - """ - if self.frame is None: - if not wx.Thread_IsMain(): - wx.CallAfter(self.CreateOutputWindow, text) - else: - self.CreateOutputWindow(text) - else: - if not wx.Thread_IsMain(): - wx.CallAfter(self.text.AppendText, text) - else: - self.text.AppendText(text) - - - def close(self): - if self.frame is not None: - wx.CallAfter(self.frame.Close) - - - def flush(self): - pass - - - -#---------------------------------------------------------------------- - -_defRedirect = (wx.Platform == '__WXMSW__' or wx.Platform == '__WXMAC__') - -class App(wx.PyApp): - """ - The ``wx.App`` class represents the application and is used to: - - * bootstrap the wxPython system and initialize the underlying - gui toolkit - * set and get application-wide properties - * implement the windowing system main message or event loop, - and to dispatch events to window instances - * etc. - - Every application must have a ``wx.App`` instance, and all - creation of UI objects should be delayed until after the - ``wx.App`` object has been created in order to ensure that the gui - platform and wxWidgets have been fully initialized. - - Normally you would derive from this class and implement an - ``OnInit`` method that creates a frame and then calls - ``self.SetTopWindow(frame)``. - - :see: `wx.PySimpleApp` for a simpler app class that can be used - directly. - """ - - outputWindowClass = PyOnDemandOutputWindow - - def __init__(self, redirect=_defRedirect, filename=None, - useBestVisual=False, clearSigInt=True): - """ - Construct a ``wx.App`` object. - - :param redirect: Should ``sys.stdout`` and ``sys.stderr`` be - redirected? Defaults to True on Windows and Mac, False - otherwise. If `filename` is None then output will be - redirected to a window that pops up as needed. (You can - control what kind of window is created for the output by - resetting the class variable ``outputWindowClass`` to a - class of your choosing.) - - :param filename: The name of a file to redirect output to, if - redirect is True. - - :param useBestVisual: Should the app try to use the best - available visual provided by the system (only relevant on - systems that have more than one visual.) This parameter - must be used instead of calling `SetUseBestVisual` later - on because it must be set before the underlying GUI - toolkit is initialized. - - :param clearSigInt: Should SIGINT be cleared? This allows the - app to terminate upon a Ctrl-C in the console like other - GUI apps will. - - :note: You should override OnInit to do applicaition - initialization to ensure that the system, toolkit and - wxWidgets are fully initialized. - """ - wx.PyApp.__init__(self) - - if wx.Platform == "__WXMAC__": - try: - import MacOS - if not MacOS.WMAvailable(): - print """\\ -This program needs access to the screen. Please run with 'pythonw', -not 'python', and only when you are logged in on the main display of -your Mac.""" - _sys.exit(1) - except SystemExit: - raise - except: - pass - - # This has to be done before OnInit - self.SetUseBestVisual(useBestVisual) - - # Set the default handler for SIGINT. This fixes a problem - # where if Ctrl-C is pressed in the console that started this - # app then it will not appear to do anything, (not even send - # KeyboardInterrupt???) but will later segfault on exit. By - # setting the default handler then the app will exit, as - # expected (depending on platform.) - if clearSigInt: - try: - import signal - signal.signal(signal.SIGINT, signal.SIG_DFL) - except: - pass - - # Save and redirect the stdio to a window? - self.stdioWin = None - self.saveStdio = (_sys.stdout, _sys.stderr) - if redirect: - self.RedirectStdio(filename) - - # This finishes the initialization of wxWindows and then calls - # the OnInit that should be present in the derived class - self._BootstrapApp() - - - def __del__(self): - try: - self.RestoreStdio() # Just in case the MainLoop was overridden - except: - pass - - - def SetTopWindow(self, frame): - """Set the \\"main\\" top level window""" - if self.stdioWin: - self.stdioWin.SetParent(frame) - wx.PyApp.SetTopWindow(self, frame) - - - def MainLoop(self): - """Execute the main GUI event loop""" - wx.PyApp.MainLoop(self) - self.RestoreStdio() - - - def RedirectStdio(self, filename=None): - """Redirect sys.stdout and sys.stderr to a file or a popup window.""" - if filename: - _sys.stdout = _sys.stderr = open(filename, 'a') - else: - self.stdioWin = self.outputWindowClass() - _sys.stdout = _sys.stderr = self.stdioWin - - - def RestoreStdio(self): - _sys.stdout, _sys.stderr = self.saveStdio - - - def SetOutputWindowAttributes(self, title=None, pos=None, size=None): - """ - Set the title, position and/or size of the output window if - the stdio has been redirected. This should be called before - any output would cause the output window to be created. - """ - if self.stdioWin: - if title is not None: - self.stdioWin.title = title - if pos is not None: - self.stdioWin.pos = pos - if size is not None: - self.stdioWin.size = size - - - - -# change from wx.PyApp_XX to wx.App_XX -App_GetMacSupportPCMenuShortcuts = _core_.PyApp_GetMacSupportPCMenuShortcuts -App_GetMacAboutMenuItemId = _core_.PyApp_GetMacAboutMenuItemId -App_GetMacPreferencesMenuItemId = _core_.PyApp_GetMacPreferencesMenuItemId -App_GetMacExitMenuItemId = _core_.PyApp_GetMacExitMenuItemId -App_GetMacHelpMenuTitleName = _core_.PyApp_GetMacHelpMenuTitleName -App_SetMacSupportPCMenuShortcuts = _core_.PyApp_SetMacSupportPCMenuShortcuts -App_SetMacAboutMenuItemId = _core_.PyApp_SetMacAboutMenuItemId -App_SetMacPreferencesMenuItemId = _core_.PyApp_SetMacPreferencesMenuItemId -App_SetMacExitMenuItemId = _core_.PyApp_SetMacExitMenuItemId -App_SetMacHelpMenuTitleName = _core_.PyApp_SetMacHelpMenuTitleName -App_GetComCtl32Version = _core_.PyApp_GetComCtl32Version - -#---------------------------------------------------------------------------- - -class PySimpleApp(wx.App): - """ - A simple application class. You can just create one of these and - then then make your top level windows later, and not have to worry - about OnInit. For example:: - - app = wx.PySimpleApp() - frame = wx.Frame(None, title='Hello World') - frame.Show() - app.MainLoop() - - :see: `wx.App` - """ - - def __init__(self, redirect=False, filename=None, - useBestVisual=False, clearSigInt=True): - """ - :see: `wx.App.__init__` - """ - wx.App.__init__(self, redirect, filename, useBestVisual, clearSigInt) - - def OnInit(self): - return True - - - -# Is anybody using this one? -class PyWidgetTester(wx.App): - def __init__(self, size = (250, 100)): - self.size = size - wx.App.__init__(self, 0) - - def OnInit(self): - self.frame = wx.Frame(None, -1, "Widget Tester", pos=(0,0), size=self.size) - self.SetTopWindow(self.frame) - return True - - def SetWidget(self, widgetClass, *args, **kwargs): - w = widgetClass(self.frame, *args, **kwargs) - self.frame.Show(True) - -#---------------------------------------------------------------------------- -# DO NOT hold any other references to this object. This is how we -# know when to cleanup system resources that wxWidgets is holding. When -# the sys module is unloaded, the refcount on sys.__wxPythonCleanup -# goes to zero and it calls the wx.App_CleanUp function. - -class __wxPyCleanup: - def __init__(self): - self.cleanup = _core_.App_CleanUp - def __del__(self): - self.cleanup() - -_sys.__wxPythonCleanup = __wxPyCleanup() - -## # another possible solution, but it gets called too early... -## import atexit -## atexit.register(_core_.wxApp_CleanUp) - - -#---------------------------------------------------------------------------- - - -#--------------------------------------------------------------------------- - - - A class used to define items in an `wx.AcceleratorTable`. wxPython -programs can choose to use wx.AcceleratorEntry objects, but using a -list of 3-tuple of integers (flags, keyCode, cmdID) usually works just -as well. See `__init__` for of the tuple values. - -:see: `wx.AcceleratorTable` - - __init__(self, int flags=0, int keyCode=0, int cmdID=0) -> AcceleratorEntry - Construct a wx.AcceleratorEntry. - :param flags: A bitmask of wx.ACCEL_ALT, wx.ACCEL_SHIFT, - wx.ACCEL_CTRL or wx.ACCEL_NORMAL used to specify - which modifier keys are held down. - :param keyCode: The keycode to be detected - :param cmdID: The menu or control command ID to use for the - accellerator event. - - - - - - - - - __del__(self) - - - Set(self, int flags, int keyCode, int cmd) - (Re)set the attributes of a wx.AcceleratorEntry. -:see `__init__` - - - - - - - - GetFlags(self) -> int - Get the AcceleratorEntry's flags. - - - GetKeyCode(self) -> int - Get the AcceleratorEntry's keycode. - - - GetCommand(self) -> int - Get the AcceleratorEntry's command ID. - - - - An accelerator table allows the application to specify a table of -keyboard shortcuts for menus or other commands. On Windows, menu or -button commands are supported; on GTK, only menu commands are -supported. - -The object ``wx.NullAcceleratorTable`` is defined to be a table with -no data, and is the initial accelerator table for a window. - -An accelerator takes precedence over normal processing and can be a -convenient way to program some event handling. For example, you can -use an accelerator table to make a hotkey generate an event no matter -which window within a frame has the focus. - -Foe example:: - - aTable = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), exitID), - (wx.ACCEL_CTRL, ord('H'), helpID), - (wx.ACCEL_CTRL, ord('F'), findID), - (wx.ACCEL_NORMAL, wx.WXK_F3, findnextID) - ]) - self.SetAcceleratorTable(aTable) - - -:see: `wx.AcceleratorEntry`, `wx.Window.SetAcceleratorTable` - - - - __init__(entries) -> AcceleratorTable - Construct an AcceleratorTable from a list of `wx.AcceleratorEntry` -items or or of 3-tuples (flags, keyCode, cmdID) - -:see: `wx.AcceleratorEntry` - - - - - - - __del__(self) - - - Ok(self) -> bool - - - - GetAccelFromString(String label) -> AcceleratorEntry - - - - - -#--------------------------------------------------------------------------- - - - struct containing all the visual attributes of a control - - __init__(self) -> VisualAttributes - struct containing all the visual attributes of a control - - - __del__(self) - - - - - - - wx.Window is the base class for all windows and represents any visible -object on the screen. All controls, top level windows and so on are -wx.Windows. Sizers and device contexts are not however, as they don't -appear on screen themselves. - -Styles -------- - ============================= ===================================== - wx.SIMPLE_BORDER Displays a thin border around the window. - - wx.DOUBLE_BORDER Displays a double border. Windows and Mac only. - - wx.SUNKEN_BORDER Displays a sunken border. - - wx.RAISED_BORDER Displays a raised border. - - wx.STATIC_BORDER Displays a border suitable for a static - control. Windows only. - - wx.NO_BORDER Displays no border, overriding the default - border style for the window. - - wx.TRANSPARENT_WINDOW The window is transparent, that is, it - will not receive paint events. Windows only. - - wx.TAB_TRAVERSAL Use this to enable tab traversal for - non-dialog windows. - - wx.WANTS_CHARS Use this to indicate that the window - wants to get all char/key events for - all keys - even for keys like TAB or - ENTER which are usually used for - dialog navigation and which wouldn't - be generated without this style. If - you need to use this style in order to - get the arrows or etc., but would - still like to have normal keyboard - navigation take place, you should - create and send a wxNavigationKeyEvent - in response to the key events for Tab - and Shift-Tab. - - wx.NO_FULL_REPAINT_ON_RESIZE Disables repainting the window - completely when its size is changed. - You will have to repaint the new - window area manually if you use this - style. As of version 2.5.1 this - style is on by default. Use - wx.FULL_REPAINT_ON_RESIZE to - deactivate it. - - wx.VSCROLL Use this style to enable a vertical scrollbar. - - wx.HSCROLL Use this style to enable a horizontal scrollbar. - - wx.ALWAYS_SHOW_SB If a window has scrollbars, disable them - instead of hiding them when they are - not needed (i.e. when the size of the - window is big enough to not require - the scrollbars to navigate it). This - style is currently only implemented - for wxMSW and wxUniversal and does - nothing on the other platforms. - - wx.CLIP_CHILDREN Use this style to eliminate flicker caused by - the background being repainted, then - children being painted over - them. Windows only. - - wx.FULL_REPAINT_ON_RESIZE Use this style to force a complete - redraw of the window whenever it is - resized instead of redrawing just the - part of the window affected by - resizing. Note that this was the - behaviour by default before 2.5.1 - release and that if you experience - redraw problems with the code which - previously used to work you may want - to try this. - ============================= ===================================== - - -Extra Styles ------------- - ============================= ===================================== - wx.WS_EX_VALIDATE_RECURSIVELY By default, - Validate/TransferDataTo/FromWindow() - only work on direct children of - the window (compatible - behaviour). Set this flag to make - them recursively descend into all - subwindows. - - wx.WS_EX_BLOCK_EVENTS wx.CommandEvents and the objects of the - derived classes are forwarded to - the parent window and so on - recursively by default. Using this - flag for the given window allows - to block this propagation at this - window, i.e. prevent the events - from being propagated further - upwards. Dialogs have this flag on - by default. - - wx.WS_EX_TRANSIENT Don't use this window as an implicit parent for - the other windows: this must be - used with transient windows as - otherwise there is the risk of - creating a dialog/frame with this - window as a parent which would - lead to a crash if the parent is - destroyed before the child. - - wx.WS_EX_PROCESS_IDLE This window should always process idle - events, even if the mode set by - wx.IdleEvent.SetMode is - wx.IDLE_PROCESS_SPECIFIED. - - wx.WS_EX_PROCESS_UI_UPDATES This window should always process UI - update events, even if the mode - set by wxUpdateUIEvent::SetMode is - wxUPDATE_UI_PROCESS_SPECIFIED. - ============================= ===================================== - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=PanelNameStr) -> Window - Construct and show a generic Window. - - - - - - - - - - - PreWindow() -> Window - Precreate a Window for 2-phase creation. - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=PanelNameStr) -> bool - Create the GUI part of the Window for 2-phase creation mode. - - - - - - - - - - - Close(self, bool force=False) -> bool - This function simply generates a EVT_CLOSE event whose handler usually -tries to close the window. It doesn't close the window itself, -however. If force is False (the default) then the window's close -handler will be allowed to veto the destruction of the window. -Usually Close is only used with the top level windows (wx.Frame and -wx.Dialog classes) as the others are not supposed to have any special -EVT_CLOSE logic. - -The close handler should check whether the window is being deleted -forcibly, using wx.CloseEvent.GetForce, in which case it should -destroy the window using wx.Window.Destroy. - -Note that calling Close does not guarantee that the window will be -destroyed; but it provides a way to simulate a manual close of a -window, which may or may not be implemented by destroying the -window. The default EVT_CLOSE handler for wx.Dialog does not -necessarily delete the dialog, since it will simply simulate an -wxID_CANCEL event which is handled by the appropriate button event -handler and may do anything at all. - -To guarantee that the window will be destroyed, call wx.Window.Destroy -instead. - - - - - - Destroy(self) -> bool - Destroys the window safely. Frames and dialogs are not destroyed -immediately when this function is called -- they are added to a list -of windows to be deleted on idle time, when all the window's events -have been processed. This prevents problems with events being sent to -non-existent windows. - -Returns True if the window has either been successfully deleted, or it -has been added to the list of windows pending real deletion. - - - DestroyChildren(self) -> bool - Destroys all children of a window. Called automatically by the -destructor. - - - IsBeingDeleted(self) -> bool - Is the window in the process of being deleted? - - - SetTitle(self, String title) - Sets the window's title. Applicable only to frames and dialogs. - - - - - - GetTitle(self) -> String - Gets the window's title. Applicable only to frames and dialogs. - - - SetLabel(self, String label) - Set the text which the window shows in its label if applicable. - - - - - - GetLabel(self) -> String - Generic way of getting a label from any window, for identification -purposes. The interpretation of this function differs from class to -class. For frames and dialogs, the value returned is the title. For -buttons or static text controls, it is the button text. This function -can be useful for meta-programs such as testing tools or special-needs -access programs)which need to identify windows by name. - - - SetName(self, String name) - Sets the window's name. The window name is used for ressource setting -in X, it is not the same as the window title/label - - - - - - GetName(self) -> String - Returns the windows name. This name is not guaranteed to be unique; -it is up to the programmer to supply an appropriate name in the window -constructor or via wx.Window.SetName. - - - SetWindowVariant(self, int variant) - Sets the variant of the window/font size to use for this window, if -the platform supports variants, for example, wxMac. -Variant values are: - - ======================== ======================================= - wx.WINDOW_VARIANT_NORMAL Normal size - wx.WINDOW_VARIANT_SMALL Smaller size (about 25 % smaller than normal) - wx.WINDOW_VARIANT_MINI Mini size (about 33 % smaller than normal) - wx.WINDOW_VARIANT_LARGE Large size (about 25 % larger than normal) - ======================== ======================================= - - - - - - - GetWindowVariant(self) -> int - - - SetId(self, int winid) - Sets the identifier of the window. Each window has an integer -identifier. If the application has not provided one, an identifier -will be generated. Normally, the identifier should be provided on -creation and should not be modified subsequently. - - - - - - GetId(self) -> int - Returns the identifier of the window. Each window has an integer -identifier. If the application has not provided one (or the default Id --1 is used) then an unique identifier with a negative value will be -generated. - - - NewControlId() -> int - Generate a control id for the controls which were not given one. - - - NextControlId(int winid) -> int - Get the id of the control following the one with the given -autogenerated) id - - - - - - PrevControlId(int winid) -> int - Get the id of the control preceding the one with the given -autogenerated) id - - - - - - SetSize(self, Size size) - Sets the size of the window in pixels. - - - - - - SetDimensions(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO) - Sets the position and size of the window in pixels. The sizeFlags -parameter indicates the interpretation of the other params if they are --1. wx.SIZE_AUTO*: a -1 indicates that a class-specific default -shoudl be used. wx.SIZE_USE_EXISTING: existing dimensions should be -used if -1 values are supplied. wxSIZE_ALLOW_MINUS_ONE: allow -dimensions of -1 and less to be interpreted as real dimensions, not -default values. - - - - - - - - - - SetRect(self, Rect rect, int sizeFlags=SIZE_AUTO) - Sets the position and size of the window in pixels using a wx.Rect. - - - - - - - SetSizeWH(self, int width, int height) - Sets the size of the window in pixels. - - - - - - - Move(self, Point pt, int flags=SIZE_USE_EXISTING) - Moves the window to the given position. - - - - - - - MoveXY(self, int x, int y, int flags=SIZE_USE_EXISTING) - Moves the window to the given position. - - - - - - - - SetBestFittingSize(self, Size size=DefaultSize) - A 'Smart' SetSize that will fill in default size components with the -window's *best size* values. Also set's the minsize for use with sizers. - - - - - - Raise(self) - Raises the window to the top of the window hierarchy if it is a -managed window (dialog or frame). - - - Lower(self) - Lowers the window to the bottom of the window hierarchy if it is a -managed window (dialog or frame). - - - SetClientSize(self, Size size) - This sets the size of the window client area in pixels. Using this -function to size a window tends to be more device-independent than -wx.Window.SetSize, since the application need not worry about what -dimensions the border or title bar have when trying to fit the window -around panel items, for example. - - - - - - SetClientSizeWH(self, int width, int height) - This sets the size of the window client area in pixels. Using this -function to size a window tends to be more device-independent than -wx.Window.SetSize, since the application need not worry about what -dimensions the border or title bar have when trying to fit the window -around panel items, for example. - - - - - - - SetClientRect(self, Rect rect) - This sets the size of the window client area in pixels. Using this -function to size a window tends to be more device-independent than -wx.Window.SetSize, since the application need not worry about what -dimensions the border or title bar have when trying to fit the window -around panel items, for example. - - - - - - GetPosition(self) -> Point - Get the window's position. - - - GetPositionTuple() -> (x,y) - Get the window's position. - - - - - - - GetSize(self) -> Size - Get the window size. - - - GetSizeTuple() -> (width, height) - Get the window size. - - - - - - - GetRect(self) -> Rect - Returns the size and position of the window as a wx.Rect object. - - - GetClientSize(self) -> Size - This gets the size of the window's 'client area' in pixels. The client -area is the area which may be drawn on by the programmer, excluding -title bar, border, scrollbars, etc. - - - GetClientSizeTuple() -> (width, height) - This gets the size of the window's 'client area' in pixels. The client -area is the area which may be drawn on by the programmer, excluding -title bar, border, scrollbars, etc. - - - - - - - GetClientAreaOrigin(self) -> Point - Get the origin of the client area of the window relative to the -window's top left corner (the client area may be shifted because of -the borders, scrollbars, other decorations...) - - - GetClientRect(self) -> Rect - Get the client area position and size as a `wx.Rect` object. - - - GetBestSize(self) -> Size - This function returns the best acceptable minimal size for the -window, if applicable. For example, for a static text control, it will -be the minimal size such that the control label is not truncated. For -windows containing subwindows (suzh aswx.Panel), the size returned by -this function will be the same as the size the window would have had -after calling Fit. - - - GetBestSizeTuple() -> (width, height) - This function returns the best acceptable minimal size for the -window, if applicable. For example, for a static text control, it will -be the minimal size such that the control label is not truncated. For -windows containing subwindows (suzh aswx.Panel), the size returned by -this function will be the same as the size the window would have had -after calling Fit. - - - - - - - InvalidateBestSize(self) - Reset the cached best size value so it will be recalculated the next -time it is needed. - - - GetBestFittingSize(self) -> Size - This function will merge the window's best size into the window's -minimum size, giving priority to the min size components, and returns -the results. - - - - GetAdjustedBestSize(self) -> Size - This method is similar to GetBestSize, except in one -thing. GetBestSize should return the minimum untruncated size of the -window, while this method will return the largest of BestSize and any -user specified minimum size. ie. it is the minimum size the window -should currently be drawn at, not the minimal size it can possibly -tolerate. - - - Center(self, int direction=BOTH) - Centers the window. The parameter specifies the direction for -cetering, and may be wx.HORIZONTAL, wx.VERTICAL or wx.BOTH. It may -also include wx.CENTER_ON_SCREEN flag if you want to center the window -on the entire screen and not on its parent window. If it is a -top-level window and has no parent then it will always be centered -relative to the screen. - - - - - - CenterOnScreen(self, int dir=BOTH) - Center on screen (only works for top level windows) - - - - - - CenterOnParent(self, int dir=BOTH) - Center with respect to the the parent window - - - - - - Fit(self) - Sizes the window so that it fits around its subwindows. This function -won't do anything if there are no subwindows and will only really work -correctly if sizers are used for the subwindows layout. Also, if the -window has exactly one subwindow it is better (faster and the result -is more precise as Fit adds some margin to account for fuzziness of -its calculations) to call window.SetClientSize(child.GetSize()) -instead of calling Fit. - - - FitInside(self) - Similar to Fit, but sizes the interior (virtual) size of a -window. Mainly useful with scrolled windows to reset scrollbars after -sizing changes that do not trigger a size event, and/or scrolled -windows without an interior sizer. This function similarly won't do -anything if there are no subwindows. - - - SetSizeHints(self, int minW, int minH, int maxW=-1, int maxH=-1, int incW=-1, - int incH=-1) - Allows specification of minimum and maximum window sizes, and window -size increments. If a pair of values is not set (or set to -1), the -default values will be used. If this function is called, the user -will not be able to size the window outside the given bounds (if it is -a top-level window.) Sizers will also inspect the minimum window size -and will use that value if set when calculating layout. - -The resizing increments are only significant under Motif or Xt. - -:see: `GetMinSize`, `GetMaxSize`, `SetMinSize`, `SetMaxSize` - - - - - - - - - - - - SetSizeHintsSz(self, Size minSize, Size maxSize=DefaultSize, Size incSize=DefaultSize) - Allows specification of minimum and maximum window sizes, and window -size increments. If a pair of values is not set (or set to -1), the -default values will be used. If this function is called, the user -will not be able to size the window outside the given bounds (if it is -a top-level window.) Sizers will also inspect the minimum window size -and will use that value if set when calculating layout. - -The resizing increments are only significant under Motif or Xt. - -:see: `GetMinSize`, `GetMaxSize`, `SetMinSize`, `SetMaxSize` - - - - - - - - - SetVirtualSizeHints(self, int minW, int minH, int maxW=-1, int maxH=-1) - Allows specification of minimum and maximum virtual window sizes. If a -pair of values is not set (or set to -1), the default values will be -used. If this function is called, the user will not be able to size -the virtual area of the window outside the given bounds. - - - - - - - - - SetVirtualSizeHintsSz(self, Size minSize, Size maxSize=DefaultSize) - Allows specification of minimum and maximum virtual window sizes. If a -pair of values is not set (or set to -1), the default values will be -used. If this function is called, the user will not be able to size -the virtual area of the window outside the given bounds. - - - - - - - GetMaxSize(self) -> Size - - - GetMinSize(self) -> Size - - - SetMinSize(self, Size minSize) - A more convenient method than `SetSizeHints` for setting just the -min size. - - - - - - SetMaxSize(self, Size maxSize) - A more convenient method than `SetSizeHints` for setting just the -max size. - - - - - - GetMinWidth(self) -> int - - - GetMinHeight(self) -> int - - - GetMaxWidth(self) -> int - - - GetMaxHeight(self) -> int - - - SetVirtualSize(self, Size size) - Set the the virtual size of a window in pixels. For most windows this -is just the client area of the window, but for some like scrolled -windows it is more or less independent of the screen window size. - - - - - - SetVirtualSizeWH(self, int w, int h) - Set the the virtual size of a window in pixels. For most windows this -is just the client area of the window, but for some like scrolled -windows it is more or less independent of the screen window size. - - - - - - - GetVirtualSize(self) -> Size - Get the the virtual size of the window in pixels. For most windows -this is just the client area of the window, but for some like scrolled -windows it is more or less independent of the screen window size. - - - GetVirtualSizeTuple() -> (width, height) - Get the the virtual size of the window in pixels. For most windows -this is just the client area of the window, but for some like scrolled -windows it is more or less independent of the screen window size. - - - - - - - GetBestVirtualSize(self) -> Size - Return the largest of ClientSize and BestSize (as determined by a -sizer, interior children, or other means) - - - Show(self, bool show=True) -> bool - Shows or hides the window. You may need to call Raise for a top level -window if you want to bring it to top, although this is not needed if -Show is called immediately after the frame creation. Returns True if -the window has been shown or hidden or False if nothing was done -because it already was in the requested state. - - - - - - Hide(self) -> bool - Equivalent to calling Show(False). - - - Enable(self, bool enable=True) -> bool - Enable or disable the window for user input. Note that when a parent -window is disabled, all of its children are disabled as well and they -are reenabled again when the parent is. Returns true if the window -has been enabled or disabled, false if nothing was done, i.e. if the -window had already been in the specified state. - - - - - - Disable(self) -> bool - Disables the window, same as Enable(false). - - - IsShown(self) -> bool - Returns true if the window is shown, false if it has been hidden. - - - IsEnabled(self) -> bool - Returns true if the window is enabled for input, false otherwise. - - - SetWindowStyleFlag(self, long style) - Sets the style of the window. Please note that some styles cannot be -changed after the window creation and that Refresh() might need to be -called after changing the others for the change to take place -immediately. - - - - - - GetWindowStyleFlag(self) -> long - Gets the window style that was passed to the constructor or Create -method. - - - HasFlag(self, int flag) -> bool - Test if the given style is set for this window. - - - - - - IsRetained(self) -> bool - Returns true if the window is retained, false otherwise. Retained -windows are only available on X platforms. - - - SetExtraStyle(self, long exStyle) - Sets the extra style bits for the window. Extra styles are the less -often used style bits which can't be set with the constructor or with -SetWindowStyleFlag() - - - - - - GetExtraStyle(self) -> long - Returns the extra style bits for the window. - - - MakeModal(self, bool modal=True) - Disables all other windows in the application so that the user can -only interact with this window. Passing False will reverse this -effect. - - - - - - SetThemeEnabled(self, bool enableTheme) - This function tells a window if it should use the system's "theme" - code to draw the windows' background instead if its own background - drawing code. This will only have an effect on platforms that support - the notion of themes in user defined windows. One such platform is - GTK+ where windows can have (very colourful) backgrounds defined by a - user's selected theme. - -Dialogs, notebook pages and the status bar have this flag set to true -by default so that the default look and feel is simulated best. - - - - - - GetThemeEnabled(self) -> bool - Return the themeEnabled flag. - - - SetFocus(self) - Set's the focus to this window, allowing it to receive keyboard input. - - - SetFocusFromKbd(self) - Set focus to this window as the result of a keyboard action. Normally -only called internally. - - - FindFocus() -> Window - Returns the window or control that currently has the keyboard focus, -or None. - - - AcceptsFocus(self) -> bool - Can this window have focus? - - - AcceptsFocusFromKeyboard(self) -> bool - Can this window be given focus by keyboard navigation? if not, the -only way to give it focus (provided it accepts it at all) is to click -it. - - - GetDefaultItem(self) -> Window - Get the default child of this parent, i.e. the one which is activated -by pressing <Enter> such as the OK button on a wx.Dialog. - - - SetDefaultItem(self, Window child) -> Window - Set this child as default, return the old default. - - - - - - SetTmpDefaultItem(self, Window win) - Set this child as temporary default - - - - - - Navigate(self, int flags=NavigationKeyEvent.IsForward) -> bool - Does keyboard navigation from this window to another, by sending a -`wx.NavigationKeyEvent`. - - :param flags: A combination of the ``IsForward`` or ``IsBackward`` - and the ``WinChange`` values in the `wx.NavigationKeyEvent` - class, which determine if the navigation should be in forward - or reverse order, and if it should be able to cross parent - window boundaries, such as between notebook pages or MDI child - frames. Typically the status of the Shift key (for forward or - backward) or the Control key (for WinChange) would be used to - determine how to set the flags. - -One situation in which you may wish to call this method is from a text -control custom keypress handler to do the default navigation behaviour -for the tab key, since the standard default behaviour for a multiline -text control with the wx.TE_PROCESS_TAB style is to insert a tab and -not navigate to the next control. - - - - - - MoveAfterInTabOrder(self, Window win) - Moves this window in the tab navigation order after the specified -sibling window. This means that when the user presses the TAB key on -that other window, the focus switches to this window. - -The default tab order is the same as creation order. This function -and `MoveBeforeInTabOrder` allow to change it after creating all the -windows. - - - - - - - MoveBeforeInTabOrder(self, Window win) - Same as `MoveAfterInTabOrder` except that it inserts this window just -before win instead of putting it right after it. - - - - - - GetChildren(self) -> PyObject - Returns a list of the window's children. NOTE: Currently this is a -copy of the child window list maintained by the window, so the return -value of this function is only valid as long as the window's children -do not change. - - - GetParent(self) -> Window - Returns the parent window of this window, or None if there isn't one. - - - GetGrandParent(self) -> Window - Returns the parent of the parent of this window, or None if there -isn't one. - - - IsTopLevel(self) -> bool - Returns true if the given window is a top-level one. Currently all -frames and dialogs are always considered to be top-level windows (even -if they have a parent window). - - - Reparent(self, Window newParent) -> bool - Reparents the window, i.e the window will be removed from its current -parent window (e.g. a non-standard toolbar in a wxFrame) and then -re-inserted into another. Available on Windows and GTK. Returns True -if the parent was changed, False otherwise (error or newParent == -oldParent) - - - - - - AddChild(self, Window child) - Adds a child window. This is called automatically by window creation -functions so should not be required by the application programmer. - - - - - - RemoveChild(self, Window child) - Removes a child window. This is called automatically by window -deletion functions so should not be required by the application -programmer. - - - - - - FindWindowById(self, long winid) -> Window - Find a chld of this window by window ID - - - - - - FindWindowByName(self, String name) -> Window - Find a child of this window by name - - - - - - GetEventHandler(self) -> EvtHandler - Returns the event handler for this window. By default, the window is -its own event handler. - - - SetEventHandler(self, EvtHandler handler) - Sets the event handler for this window. An event handler is an object -that is capable of processing the events sent to a window. By default, -the window is its own event handler, but an application may wish to -substitute another, for example to allow central implementation of -event-handling for a variety of different window classes. - -It is usually better to use `wx.Window.PushEventHandler` since this sets -up a chain of event handlers, where an event not handled by one event -handler is handed to the next one in the chain. - - - - - - PushEventHandler(self, EvtHandler handler) - Pushes this event handler onto the event handler stack for the window. -An event handler is an object that is capable of processing the events -sent to a window. By default, the window is its own event handler, but -an application may wish to substitute another, for example to allow -central implementation of event-handling for a variety of different -window classes. - -wx.Window.PushEventHandler allows an application to set up a chain of -event handlers, where an event not handled by one event handler is -handed to the next one in the chain. Use `wx.Window.PopEventHandler` to -remove the event handler. - - - - - - PopEventHandler(self, bool deleteHandler=False) -> EvtHandler - Removes and returns the top-most event handler on the event handler -stack. If deleteHandler is True then the wx.EvtHandler object will be -destroyed after it is popped. - - - - - - RemoveEventHandler(self, EvtHandler handler) -> bool - Find the given handler in the event handler chain and remove (but not -delete) it from the event handler chain, return True if it was found -and False otherwise (this also results in an assert failure so this -function should only be called when the handler is supposed to be -there.) - - - - - - SetValidator(self, Validator validator) - Deletes the current validator (if any) and sets the window validator, -having called wx.Validator.Clone to create a new validator of this -type. - - - - - - GetValidator(self) -> Validator - Returns a pointer to the current validator for the window, or None if -there is none. - - - Validate(self) -> bool - Validates the current values of the child controls using their -validators. If the window has wx.WS_EX_VALIDATE_RECURSIVELY extra -style flag set, the method will also call Validate() of all child -windows. Returns false if any of the validations failed. - - - TransferDataToWindow(self) -> bool - Transfers values to child controls from data areas specified by their -validators. If the window has wx.WS_EX_VALIDATE_RECURSIVELY extra -style flag set, the method will also call TransferDataToWindow() of -all child windows. - - - TransferDataFromWindow(self) -> bool - Transfers values from child controls to data areas specified by their -validators. Returns false if a transfer failed. If the window has -wx.WS_EX_VALIDATE_RECURSIVELY extra style flag set, the method will -also call TransferDataFromWindow() of all child windows. - - - InitDialog(self) - Sends an EVT_INIT_DIALOG event, whose handler usually transfers data -to the dialog via validators. - - - SetAcceleratorTable(self, AcceleratorTable accel) - Sets the accelerator table for this window. - - - - - - GetAcceleratorTable(self) -> AcceleratorTable - Gets the accelerator table for this window. - - - RegisterHotKey(self, int hotkeyId, int modifiers, int keycode) -> bool - Registers a system wide hotkey. Every time the user presses the hotkey -registered here, this window will receive a hotkey event. It will -receive the event even if the application is in the background and -does not have the input focus because the user is working with some -other application. To bind an event handler function to this hotkey -use EVT_HOTKEY with an id equal to hotkeyId. Returns True if the -hotkey was registered successfully. - - - - - - - - UnregisterHotKey(self, int hotkeyId) -> bool - Unregisters a system wide hotkey. - - - - - - ConvertDialogPointToPixels(self, Point pt) -> Point - Converts a point or size from dialog units to pixels. Dialog units -are used for maintaining a dialog's proportions even if the font -changes. For the x dimension, the dialog units are multiplied by the -average character width and then divided by 4. For the y dimension, -the dialog units are multiplied by the average character height and -then divided by 8. - - - - - - ConvertDialogSizeToPixels(self, Size sz) -> Size - Converts a point or size from dialog units to pixels. Dialog units -are used for maintaining a dialog's proportions even if the font -changes. For the x dimension, the dialog units are multiplied by the -average character width and then divided by 4. For the y dimension, -the dialog units are multiplied by the average character height and -then divided by 8. - - - - - - DLG_PNT(self, Point pt) -> Point - Converts a point or size from dialog units to pixels. Dialog units -are used for maintaining a dialog's proportions even if the font -changes. For the x dimension, the dialog units are multiplied by the -average character width and then divided by 4. For the y dimension, -the dialog units are multiplied by the average character height and -then divided by 8. - - - - - - DLG_SZE(self, Size sz) -> Size - Converts a point or size from dialog units to pixels. Dialog units -are used for maintaining a dialog's proportions even if the font -changes. For the x dimension, the dialog units are multiplied by the -average character width and then divided by 4. For the y dimension, -the dialog units are multiplied by the average character height and -then divided by 8. - - - - - - ConvertPixelPointToDialog(self, Point pt) -> Point - - - - - - ConvertPixelSizeToDialog(self, Size sz) -> Size - - - - - - WarpPointer(self, int x, int y) - Moves the pointer to the given position on the window. - -NOTE: This function is not supported under Mac because Apple Human -Interface Guidelines forbid moving the mouse cursor programmatically. - - - - - - - CaptureMouse(self) - Directs all mouse input to this window. Call wx.Window.ReleaseMouse to -release the capture. - -Note that wxWindows maintains the stack of windows having captured the -mouse and when the mouse is released the capture returns to the window -which had had captured it previously and it is only really released if -there were no previous window. In particular, this means that you must -release the mouse as many times as you capture it. - - - ReleaseMouse(self) - Releases mouse input captured with wx.Window.CaptureMouse. - - - GetCapture() -> Window - Returns the window which currently captures the mouse or None - - - HasCapture(self) -> bool - Returns true if this window has the current mouse capture. - - - Refresh(self, bool eraseBackground=True, Rect rect=None) - Mark the specified rectangle (or the whole window) as "dirty" so it -will be repainted. Causes an EVT_PAINT event to be generated and sent -to the window. - - - - - - - RefreshRect(self, Rect rect) - Redraws the contents of the given rectangle: the area inside it will -be repainted. This is the same as Refresh but has a nicer syntax. - - - - - - Update(self) - Calling this method immediately repaints the invalidated area of the -window instead of waiting for the EVT_PAINT event to happen, (normally -this would usually only happen when the flow of control returns to the -event loop.) Notice that this function doesn't refresh the window and -does nothing if the window has been already repainted. Use Refresh -first if you want to immediately redraw the window (or some portion of -it) unconditionally. - - - ClearBackground(self) - Clears the window by filling it with the current background -colour. Does not cause an erase background event to be generated. - - - Freeze(self) - Freezes the window or, in other words, prevents any updates from -taking place on screen, the window is not redrawn at all. Thaw must be -called to reenable window redrawing. Calls to Freeze/Thaw may be -nested, with the actual Thaw being delayed until all the nesting has -been undone. - -This method is useful for visual appearance optimization (for example, -it is a good idea to use it before inserting large amount of text into -a wxTextCtrl under wxGTK) but is not implemented on all platforms nor -for all controls so it is mostly just a hint to wxWindows and not a -mandatory directive. - - - Thaw(self) - Reenables window updating after a previous call to Freeze. Calls to -Freeze/Thaw may be nested, so Thaw must be called the same number of -times that Freeze was before the window will be updated. - - - PrepareDC(self, DC dc) - Call this function to prepare the device context for drawing a -scrolled image. It sets the device origin according to the current -scroll position. - - - - - - GetUpdateRegion(self) -> Region - Returns the region specifying which parts of the window have been -damaged. Should only be called within an EVT_PAINT handler. - - - GetUpdateClientRect(self) -> Rect - Get the update rectangle region bounding box in client coords. - - - IsExposed(self, int x, int y, int w=1, int h=1) -> bool - Returns true if the given point or rectangle area has been exposed -since the last repaint. Call this in an paint event handler to -optimize redrawing by only redrawing those areas, which have been -exposed. - - - - - - - - - IsExposedPoint(self, Point pt) -> bool - Returns true if the given point or rectangle area has been exposed -since the last repaint. Call this in an paint event handler to -optimize redrawing by only redrawing those areas, which have been -exposed. - - - - - - IsExposedRect(self, Rect rect) -> bool - Returns true if the given point or rectangle area has been exposed -since the last repaint. Call this in an paint event handler to -optimize redrawing by only redrawing those areas, which have been -exposed. - - - - - - GetDefaultAttributes(self) -> VisualAttributes - Get the default attributes for an instance of this class. This is -useful if you want to use the same font or colour in your own control -as in a standard control -- which is a much better idea than hard -coding specific colours or fonts which might look completely out of -place on the user's system, especially if it uses themes. - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - SetBackgroundColour(self, Colour colour) -> bool - Sets the background colour of the window. Returns True if the colour -was changed. The background colour is usually painted by the default -EVT_ERASE_BACKGROUND event handler function under Windows and -automatically under GTK. Using `wx.NullColour` will reset the window -to the default background colour. - -Note that setting the background colour may not cause an immediate -refresh, so you may wish to call `ClearBackground` or `Refresh` after -calling this function. - -Using this function will disable attempts to use themes for this -window, if the system supports them. Use with care since usually the -themes represent the appearance chosen by the user to be used for all -applications on the system. - - - - - - SetOwnBackgroundColour(self, Colour colour) - - - - - - SetForegroundColour(self, Colour colour) -> bool - Sets the foreground colour of the window. Returns True is the colour -was changed. The interpretation of foreground colour is dependent on -the window class; it may be the text colour or other colour, or it may -not be used at all. - - - - - - SetOwnForegroundColour(self, Colour colour) - - - - - - GetBackgroundColour(self) -> Colour - Returns the background colour of the window. - - - GetForegroundColour(self) -> Colour - Returns the foreground colour of the window. The interpretation of -foreground colour is dependent on the window class; it may be the text -colour or other colour, or it may not be used at all. - - - SetBackgroundStyle(self, int style) -> bool - Returns the background style of the window. The background style -indicates how the background of the window is drawn. - - ====================== ======================================== - wx.BG_STYLE_SYSTEM The background colour or pattern should - be determined by the system - wx.BG_STYLE_COLOUR The background should be a solid colour - wx.BG_STYLE_CUSTOM The background will be implemented by the - application. - ====================== ======================================== - -On GTK+, use of wx.BG_STYLE_CUSTOM allows the flicker-free drawing of -a custom background, such as a tiled bitmap. Currently the style has -no effect on other platforms. - -:see: `GetBackgroundStyle`, `SetBackgroundColour` - - - - - - GetBackgroundStyle(self) -> int - Returns the background style of the window. - -:see: `SetBackgroundStyle` - - - SetCursor(self, Cursor cursor) -> bool - Sets the window's cursor. Notice that the window cursor also sets it -for the children of the window implicitly. - -The cursor may be wx.NullCursor in which case the window cursor will -be reset back to default. - - - - - - GetCursor(self) -> Cursor - Return the cursor associated with this window. - - - SetFont(self, Font font) -> bool - Sets the font for this window. - - - - - - SetOwnFont(self, Font font) - - - - - - GetFont(self) -> Font - Returns the default font used for this window. - - - SetCaret(self, Caret caret) - Sets the caret associated with the window. - - - - - - GetCaret(self) -> Caret - Returns the caret associated with the window. - - - GetCharHeight(self) -> int - Get the (average) character size for the current font. - - - GetCharWidth(self) -> int - Get the (average) character size for the current font. - - - GetTextExtent(String string) -> (width, height) - Get the width and height of the text using the current font. - - - - - - - - GetFullTextExtent(String string, Font font=None) -> - (width, height, descent, externalLeading) - Get the width, height, decent and leading of the text using the -current or specified font. - - - - - - - - - - - ClientToScreenXY(int x, int y) -> (x,y) - Converts to screen coordinates from coordinates relative to this window. - - - - - - - ScreenToClientXY(int x, int y) -> (x,y) - Converts from screen to client window coordinates. - - - - - - - ClientToScreen(self, Point pt) -> Point - Converts to screen coordinates from coordinates relative to this window. - - - - - - ScreenToClient(self, Point pt) -> Point - Converts from screen to client window coordinates. - - - - - - HitTestXY(self, int x, int y) -> int - Test where the given (in client coords) point lies - - - - - - - HitTest(self, Point pt) -> int - Test where the given (in client coords) point lies - - - - - - Get the window border style from the given flags: this is different -from simply doing flags & wxBORDER_MASK because it uses -GetDefaultBorder() to translate wxBORDER_DEFAULT to something -reasonable. - - - - - - - GetBorder(self, long flags) -> int -GetBorder(self) -> int - Get border for the flags of this window - - - UpdateWindowUI(self, long flags=UPDATE_UI_NONE) - This function sends EVT_UPDATE_UI events to the window. The particular -implementation depends on the window; for example a wx.ToolBar will -send an update UI event for each toolbar button, and a wx.Frame will -send an update UI event for each menubar menu item. You can call this -function from your application to ensure that your UI is up-to-date at -a particular point in time (as far as your EVT_UPDATE_UI handlers are -concerned). This may be necessary if you have called -wx.UpdateUIEvent.SetMode or wx.UpdateUIEvent.SetUpdateInterval to -limit the overhead that wxWindows incurs by sending update UI events -in idle time. -The flags should be a bitlist of one or more of the following values: - - ===================== ============================== - wx.UPDATE_UI_NONE No particular value - wx.UPDATE_UI_RECURSE Call the function for descendants - wx.UPDATE_UI_FROMIDLE Invoked from OnIdle - ===================== ============================== - -If you are calling this function from an OnIdle function, make sure -you pass the wx.UPDATE_UI_FROMIDLE flag, since this tells the window -to only update the UI elements that need to be updated in idle -time. Some windows update their elements only when necessary, for -example when a menu is about to be shown. The following is an example -of how to call UpdateWindowUI from an idle function:: - - def OnIdle(self, evt): - if wx.UpdateUIEvent.CanUpdate(self): - self.UpdateWindowUI(wx.UPDATE_UI_FROMIDLE); - - - - - - - PopupMenuXY(self, Menu menu, int x=-1, int y=-1) -> bool - Pops up the given menu at the specified coordinates, relative to this window, -and returns control when the user has dismissed the menu. If a menu item is -selected, the corresponding menu event is generated and will be processed as -usual. If the default position is given then the current position of the -mouse cursor will be used. - - - - - - - - PopupMenu(self, Menu menu, Point pos=DefaultPosition) -> bool - Pops up the given menu at the specified coordinates, relative to this window, -and returns control when the user has dismissed the menu. If a menu item is -selected, the corresponding menu event is generated and will be processed as -usual. If the default position is given then the current position of the -mouse cursor will be used. - - - - - - - GetHandle(self) -> long - Returns the platform-specific handle (as a long integer) of the -physical window. Currently on wxMac it returns the handle of the -toplevel parent of the window. - - - HasScrollbar(self, int orient) -> bool - Does the window have the scrollbar for this orientation? - - - - - - SetScrollbar(self, int orientation, int position, int thumbSize, int range, - bool refresh=True) - Sets the scrollbar properties of a built-in scrollbar. - :param orientation: Determines the scrollbar whose page size is to - be set. May be wx.HORIZONTAL or wx.VERTICAL. - - :param position: The position of the scrollbar in scroll units. - - :param thumbSize: The size of the thumb, or visible portion of the - scrollbar, in scroll units. - - :param range: The maximum position of the scrollbar. - - :param refresh: True to redraw the scrollbar, false otherwise. - - - - - - - - - - - SetScrollPos(self, int orientation, int pos, bool refresh=True) - Sets the position of one of the built-in scrollbars. - - - - - - - - GetScrollPos(self, int orientation) -> int - Returns the built-in scrollbar position. - - - - - - GetScrollThumb(self, int orientation) -> int - Returns the built-in scrollbar thumb size. - - - - - - GetScrollRange(self, int orientation) -> int - Returns the built-in scrollbar range. - - - - - - ScrollWindow(self, int dx, int dy, Rect rect=None) - Physically scrolls the pixels in the window and move child windows -accordingly. Use this function to optimise your scrolling -implementations, to minimise the area that must be redrawn. Note that -it is rarely required to call this function from a user program. - :param dx: Amount to scroll horizontally. - - :param dy: Amount to scroll vertically. - - :param rect: Rectangle to invalidate. If this is None, the whole - window is invalidated. If you pass a rectangle corresponding - to the area of the window exposed by the scroll, your - painting handler can optimize painting by checking for the - invalidated region. - - - - - - - - ScrollLines(self, int lines) -> bool - If the platform and window class supports it, scrolls the window by -the given number of lines down, if lines is positive, or up if lines -is negative. Returns True if the window was scrolled, False if it was -already on top/bottom and nothing was done. - - - - - - ScrollPages(self, int pages) -> bool - If the platform and window class supports it, scrolls the window by -the given number of pages down, if pages is positive, or up if pages -is negative. Returns True if the window was scrolled, False if it was -already on top/bottom and nothing was done. - - - - - - LineUp(self) -> bool - This is just a wrapper for ScrollLines(-1). - - - LineDown(self) -> bool - This is just a wrapper for ScrollLines(1). - - - PageUp(self) -> bool - This is just a wrapper for ScrollPages(-1). - - - PageDown(self) -> bool - This is just a wrapper for ScrollPages(1). - - - SetHelpText(self, String text) - Sets the help text to be used as context-sensitive help for this -window. Note that the text is actually stored by the current -wxHelpProvider implementation, and not in the window object itself. - - - - - - SetHelpTextForId(self, String text) - Associate this help text with all windows with the same id as this -one. - - - - - - GetHelpText(self) -> String - Gets the help text to be used as context-sensitive help for this -window. Note that the text is actually stored by the current -wxHelpProvider implementation, and not in the window object itself. - - - SetToolTipString(self, String tip) - Attach a tooltip to the window. - - - - - - SetToolTip(self, ToolTip tip) - Attach a tooltip to the window. - - - - - - GetToolTip(self) -> ToolTip - get the associated tooltip or None if none - - - SetDropTarget(self, DropTarget dropTarget) - Associates a drop target with this window. If the window already has -a drop target, it is deleted. - - - - - - GetDropTarget(self) -> DropTarget - Returns the associated drop target, which may be None. - - - SetConstraints(self, LayoutConstraints constraints) - Sets the window to have the given layout constraints. If an existing -layout constraints object is already owned by the window, it will be -deleted. Pass None to disassociate and delete the window's current -constraints. - -You must call SetAutoLayout to tell a window to use the constraints -automatically in its default EVT_SIZE handler; otherwise, you must -handle EVT_SIZE yourself and call Layout() explicitly. When setting -both a wx.LayoutConstraints and a wx.Sizer, only the sizer will have -effect. - - - - - - GetConstraints(self) -> LayoutConstraints - Returns a pointer to the window's layout constraints, or None if there -are none. - - - SetAutoLayout(self, bool autoLayout) - Determines whether the Layout function will be called automatically -when the window is resized. It is called implicitly by SetSizer but -if you use SetConstraints you should call it manually or otherwise the -window layout won't be correctly updated when its size changes. - - - - - - GetAutoLayout(self) -> bool - Returns the current autoLayout setting - - - Layout(self) -> bool - Invokes the constraint-based layout algorithm or the sizer-based -algorithm for this window. See SetAutoLayout: when auto layout is on, -this function gets called automatically by the default EVT_SIZE -handler when the window is resized. - - - SetSizer(self, Sizer sizer, bool deleteOld=True) - Sets the window to have the given layout sizer. The window will then -own the object, and will take care of its deletion. If an existing -layout sizer object is already owned by the window, it will be deleted -if the deleteOld parameter is true. Note that this function will also -call SetAutoLayout implicitly with a True parameter if the sizer is -non-NoneL and False otherwise. - - - - - - - SetSizerAndFit(self, Sizer sizer, bool deleteOld=True) - The same as SetSizer, except it also sets the size hints for the -window based on the sizer's minimum size. - - - - - - - GetSizer(self) -> Sizer - Return the sizer associated with the window by a previous call to -SetSizer or None if there isn't one. - - - SetContainingSizer(self, Sizer sizer) - This normally does not need to be called by application code. It is -called internally when a window is added to a sizer, and is used so -the window can remove itself from the sizer when it is destroyed. - - - - - - GetContainingSizer(self) -> Sizer - Return the sizer that this window is a member of, if any, otherwise None. - - - InheritAttributes(self) - This function is (or should be, in case of custom controls) called -during window creation to intelligently set up the window visual -attributes, that is the font and the foreground and background -colours. - -By 'intelligently' the following is meant: by default, all windows use -their own default attributes. However if some of the parent's -attributes are explicitly changed (that is, using SetFont and not -SetOwnFont) and if the corresponding attribute hadn't been -explicitly set for this window itself, then this window takes the same -value as used by the parent. In addition, if the window overrides -ShouldInheritColours to return false, the colours will not be changed -no matter what and only the font might. - -This rather complicated logic is necessary in order to accommodate the -different usage scenarius. The most common one is when all default -attributes are used and in this case, nothing should be inherited as -in modern GUIs different controls use different fonts (and colours) -than their siblings so they can't inherit the same value from the -parent. However it was also deemed desirable to allow to simply change -the attributes of all children at once by just changing the font or -colour of their common parent, hence in this case we do inherit the -parents attributes. - - - - ShouldInheritColours(self) -> bool - Return true from here to allow the colours of this window to be -changed by InheritAttributes, returning false forbids inheriting them -from the parent window. - -The base class version returns false, but this method is overridden in -wxControl where it returns true. - - - -def DLG_PNT(win, point_or_x, y=None): - """ - Convenience function for converting a Point or (x,y) in - dialog units to pixel units. - """ - if y is None: - return win.ConvertDialogPointToPixels(point_or_x) - else: - return win.ConvertDialogPointToPixels(wx.Point(point_or_x, y)) - -def DLG_SZE(win, size_width, height=None): - """ - Convenience function for converting a Size or (w,h) in - dialog units to pixel units. - """ - if height is None: - return win.ConvertDialogSizeToPixels(size_width) - else: - return win.ConvertDialogSizeToPixels(wx.Size(size_width, height)) - - - FindWindowById(long id, Window parent=None) -> Window - Find the first window in the application with the given id. If parent -is None, the search will start from all top-level frames and dialog -boxes; if non-None, the search will be limited to the given window -hierarchy. The search is recursive in both cases. - - - - - - - FindWindowByName(String name, Window parent=None) -> Window - Find a window by its name (as given in a window constructor or Create -function call). If parent is None, the search will start from all -top-level frames and dialog boxes; if non-None, the search will be -limited to the given window hierarchy. The search is recursive in both -cases. - -If no window with such name is found, wx.FindWindowByLabel is called. - - - - - - - FindWindowByLabel(String label, Window parent=None) -> Window - Find a window by its label. Depending on the type of window, the label -may be a window title or panel item label. If parent is None, the -search will start from all top-level frames and dialog boxes; if -non-None, the search will be limited to the given window -hierarchy. The search is recursive in both cases. - - - - - - - Window_FromHWND(Window parent, unsigned long _hWnd) -> Window - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> Validator - - - Clone(self) -> Validator - - - Validate(self, Window parent) -> bool - - - - - - TransferToWindow(self) -> bool - - - TransferFromWindow(self) -> bool - - - GetWindow(self) -> Window - - - SetWindow(self, Window window) - - - - - - IsSilent() -> bool - - - SetBellOnError(int doIt=True) - - - - - - - - - __init__(self) -> PyValidator - - - _setCallbackInfo(self, PyObject self, PyObject _class, int incref=True) - - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, String title=EmptyString, long style=0) -> Menu - - - - - - - Append(self, int id, String text, String help=EmptyString, int kind=ITEM_NORMAL) -> MenuItem - - - - - - - - - AppendSeparator(self) -> MenuItem - - - AppendCheckItem(self, int id, String text, String help=EmptyString) -> MenuItem - - - - - - - - AppendRadioItem(self, int id, String text, String help=EmptyString) -> MenuItem - - - - - - - - AppendMenu(self, int id, String text, Menu submenu, String help=EmptyString) -> MenuItem - - - - - - - - - AppendItem(self, MenuItem item) -> MenuItem - - - - - - Break(self) - - - InsertItem(self, size_t pos, MenuItem item) -> MenuItem - - - - - - - Insert(self, size_t pos, int id, String text, String help=EmptyString, - int kind=ITEM_NORMAL) -> MenuItem - - - - - - - - - - InsertSeparator(self, size_t pos) -> MenuItem - - - - - - InsertCheckItem(self, size_t pos, int id, String text, String help=EmptyString) -> MenuItem - - - - - - - - - InsertRadioItem(self, size_t pos, int id, String text, String help=EmptyString) -> MenuItem - - - - - - - - - InsertMenu(self, size_t pos, int id, String text, Menu submenu, String help=EmptyString) -> MenuItem - - - - - - - - - - PrependItem(self, MenuItem item) -> MenuItem - - - - - - Prepend(self, int id, String text, String help=EmptyString, int kind=ITEM_NORMAL) -> MenuItem - - - - - - - - - PrependSeparator(self) -> MenuItem - - - PrependCheckItem(self, int id, String text, String help=EmptyString) -> MenuItem - - - - - - - - PrependRadioItem(self, int id, String text, String help=EmptyString) -> MenuItem - - - - - - - - PrependMenu(self, int id, String text, Menu submenu, String help=EmptyString) -> MenuItem - - - - - - - - - Remove(self, int id) -> MenuItem - - - - - - RemoveItem(self, MenuItem item) -> MenuItem - - - - - - Delete(self, int id) -> bool - - - - - - DeleteItem(self, MenuItem item) -> bool - - - - - - Destroy(self) - Deletes the C++ object this Python object is a proxy for. - - - DestroyId(self, int id) -> bool - Deletes the C++ object this Python object is a proxy for. - - - - - - DestroyItem(self, MenuItem item) -> bool - Deletes the C++ object this Python object is a proxy for. - - - - - - GetMenuItemCount(self) -> size_t - - - GetMenuItems(self) -> PyObject - - - FindItem(self, String item) -> int - - - - - - FindItemById(self, int id) -> MenuItem - - - - - - FindItemByPosition(self, size_t position) -> MenuItem - - - - - - Enable(self, int id, bool enable) - - - - - - - IsEnabled(self, int id) -> bool - - - - - - Check(self, int id, bool check) - - - - - - - IsChecked(self, int id) -> bool - - - - - - SetLabel(self, int id, String label) - - - - - - - GetLabel(self, int id) -> String - - - - - - SetHelpString(self, int id, String helpString) - - - - - - - GetHelpString(self, int id) -> String - - - - - - SetTitle(self, String title) - - - - - - GetTitle(self) -> String - - - SetEventHandler(self, EvtHandler handler) - - - - - - GetEventHandler(self) -> EvtHandler - - - SetInvokingWindow(self, Window win) - - - - - - GetInvokingWindow(self) -> Window - - - GetStyle(self) -> long - - - UpdateUI(self, EvtHandler source=None) - - - - - - GetMenuBar(self) -> MenuBar - - - Attach(self, wxMenuBarBase menubar) - - - - - - Detach(self) - - - IsAttached(self) -> bool - - - SetParent(self, Menu parent) - - - - - - GetParent(self) -> Menu - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, long style=0) -> MenuBar - - - - - - Append(self, Menu menu, String title) -> bool - - - - - - - Insert(self, size_t pos, Menu menu, String title) -> bool - - - - - - - - GetMenuCount(self) -> size_t - - - GetMenu(self, size_t pos) -> Menu - - - - - - Replace(self, size_t pos, Menu menu, String title) -> Menu - - - - - - - - Remove(self, size_t pos) -> Menu - - - - - - EnableTop(self, size_t pos, bool enable) - - - - - - - IsEnabledTop(self, size_t pos) -> bool - - - - - - SetLabelTop(self, size_t pos, String label) - - - - - - - GetLabelTop(self, size_t pos) -> String - - - - - - FindMenuItem(self, String menu, String item) -> int - - - - - - - FindItemById(self, int id) -> MenuItem - - - - - - FindMenu(self, String title) -> int - - - - - - Enable(self, int id, bool enable) - - - - - - - Check(self, int id, bool check) - - - - - - - IsChecked(self, int id) -> bool - - - - - - IsEnabled(self, int id) -> bool - - - - - - SetLabel(self, int id, String label) - - - - - - - GetLabel(self, int id) -> String - - - - - - SetHelpString(self, int id, String helpString) - - - - - - - GetHelpString(self, int id) -> String - - - - - - GetFrame(self) -> wxFrame - - - IsAttached(self) -> bool - - - Attach(self, wxFrame frame) - - - - - - Detach(self) - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Menu parentMenu=None, int id=ID_ANY, String text=EmptyString, - String help=EmptyString, int kind=ITEM_NORMAL, - Menu subMenu=None) -> MenuItem - - - - - - - - - - - GetMenu(self) -> Menu - - - SetMenu(self, Menu menu) - - - - - - SetId(self, int id) - - - - - - GetId(self) -> int - - - IsSeparator(self) -> bool - - - SetText(self, String str) - - - - - - GetLabel(self) -> String - - - GetText(self) -> String - - - GetLabelFromText(String text) -> String - - - - - - GetKind(self) -> int - - - SetKind(self, int kind) - - - - - - SetCheckable(self, bool checkable) - - - - - - IsCheckable(self) -> bool - - - IsSubMenu(self) -> bool - - - SetSubMenu(self, Menu menu) - - - - - - GetSubMenu(self) -> Menu - - - Enable(self, bool enable=True) - - - - - - IsEnabled(self) -> bool - - - Check(self, bool check=True) - - - - - - IsChecked(self) -> bool - - - Toggle(self) - - - SetHelp(self, String str) - - - - - - GetHelp(self) -> String - - - GetAccel(self) -> AcceleratorEntry - - - SetAccel(self, AcceleratorEntry accel) - - - - - - GetDefaultMarginWidth() -> int - - - SetBitmap(self, Bitmap bitmap) - - - - - - GetBitmap(self) -> Bitmap - - - -#--------------------------------------------------------------------------- - - - This is the base class for a control or 'widget'. - -A control is generally a small window which processes user input -and/or displays one or more item of data. - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, Validator validator=DefaultValidator, - String name=ControlNameStr) -> Control - Create a Control. Normally you should only call this from a subclass' -__init__ as a plain old wx.Control is not very useful. - - - - - - - - - - - - PreControl() -> Control - Precreate a Control control for 2-phase creation - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, Validator validator=DefaultValidator, - String name=ControlNameStr) -> bool - Do the 2nd phase and create the GUI control. - - - - - - - - - - - - Command(self, CommandEvent event) - Simulates the effect of the user issuing a command to the item. - -:see: `wx.CommandEvent` - - - - - - - GetLabel(self) -> String - Return a control's text. - - - SetLabel(self, String label) - Sets the item's text. - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - wx.ItemContainer defines an interface which is implemented by all -controls which have string subitems, each of which may be selected, -such as `wx.ListBox`, `wx.CheckListBox`, `wx.Choice` as well as -`wx.ComboBox` which implements an extended interface deriving from -this one. - -It defines the methods for accessing the control's items and although -each of the derived classes implements them differently, they still -all conform to the same interface. - -The items in a wx.ItemContainer have (non empty) string labels and, -optionally, client data associated with them. - - - Append(self, String item, PyObject clientData=None) -> int - Adds the item to the control, associating the given data with the item -if not None. The return value is the index of the newly added item -which may be different from the last one if the control is sorted (e.g. -has wx.LB_SORT or wx.CB_SORT style). - - - - - - - AppendItems(self, List strings) - Apend several items at once to the control. Notice that calling this -method may be much faster than appending the items one by one if you -need to add a lot of items. - - - - - - Insert(self, String item, int pos, PyObject clientData=None) -> int - Insert an item into the control before the item at the ``pos`` index, -optionally associating some data object with the item. - - - - - - - - Clear(self) - Removes all items from the control. - - - Delete(self, int n) - Deletes the item at the zero-based index 'n' from the control. Note -that it is an error (signalled by a `wx.PyAssertionError` exception if -enabled) to remove an item with the index negative or greater or equal -than the number of items in the control. - - - - - - GetCount(self) -> int - Returns the number of items in the control. - - - IsEmpty(self) -> bool - Returns True if the control is empty or False if it has some items. - - - GetString(self, int n) -> String - Returns the label of the item with the given index. - - - - - - GetStrings(self) -> wxArrayString - - - SetString(self, int n, String s) - Sets the label for the given item. - - - - - - - FindString(self, String s) -> int - Finds an item whose label matches the given string. Returns the -zero-based position of the item, or ``wx.NOT_FOUND`` if the string was not -found. - - - - - - Select(self, int n) - Sets the item at index 'n' to be the selected item. - - - - - - GetSelection(self) -> int - Returns the index of the selected item or ``wx.NOT_FOUND`` if no item -is selected. - - - GetStringSelection(self) -> String - Returns the label of the selected item or an empty string if no item -is selected. - - - GetClientData(self, int n) -> PyObject - Returns the client data associated with the given item, (if any.) - - - - - - SetClientData(self, int n, PyObject clientData) - Associate the given client data with the item at position n. - - - - - - - -#--------------------------------------------------------------------------- - - - wx.ControlWithItems combines the ``wx.ItemContainer`` class with the -wx.Control class, and is used for the base class of various controls -that have items. - - - - -#--------------------------------------------------------------------------- - - - The wx.SizerItem class is used to track the position, size and other -attributes of each item managed by a `wx.Sizer`. In normal usage user -code should never need to deal directly with a wx.SizerItem, but -custom classes derived from `wx.PySizer` will probably need to use the -collection of wx.SizerItems held by wx.Sizer when calculating layout. - -:see: `wx.Sizer`, `wx.GBSizerItem` - - - __init__(self) -> SizerItem - Constructs an empty wx.SizerItem. Either a window, sizer or spacer -size will need to be set before this item can be used in a Sizer. - -You will probably never need to create a wx.SizerItem directly as they -are created automatically when the sizer's Add, Insert or Prepend -methods are called. - -:see: `wx.SizerItemSpacer`, `wx.SizerItemWindow`, `wx.SizerItemSizer` - - - SizerItemWindow(Window window, int proportion, int flag, int border, - PyObject userData=None) -> SizerItem - Constructs a `wx.SizerItem` for tracking a window. - - - - - - - - - - SizerItemSpacer(int width, int height, int proportion, int flag, int border, - PyObject userData=None) -> SizerItem - Constructs a `wx.SizerItem` for tracking a spacer. - - - - - - - - - - - SizerItemSizer(Sizer sizer, int proportion, int flag, int border, - PyObject userData=None) -> SizerItem - Constructs a `wx.SizerItem` for tracking a subsizer - - - - - - - - - - DeleteWindows(self) - Destroy the window or the windows in a subsizer, depending on the type -of item. - - - DetachSizer(self) - Enable deleting the SizerItem without destroying the contained sizer. - - - GetSize(self) -> Size - Get the current size of the item, as set in the last Layout. - - - CalcMin(self) -> Size - Calculates the minimum desired size for the item, including any space -needed by borders. - - - SetDimension(self, Point pos, Size size) - Set the position and size of the space allocated for this item by the -sizer, and adjust the position and size of the item (window or -subsizer) to be within that space taking alignment and borders into -account. - - - - - - - GetMinSize(self) -> Size - Get the minimum size needed for the item. - - - GetMinSizeWithBorder(self) -> Size - Get the minimum size needed for the item with space for the borders -added, if needed. - - - SetInitSize(self, int x, int y) - - - - - - - SetRatioWH(self, int width, int height) - Set the ratio item attribute. - - - - - - - SetRatioSize(self, Size size) - Set the ratio item attribute. - - - - - - SetRatio(self, float ratio) - Set the ratio item attribute. - - - - - - GetRatio(self) -> float - Set the ratio item attribute. - - - IsWindow(self) -> bool - Is this sizer item a window? - - - IsSizer(self) -> bool - Is this sizer item a subsizer? - - - IsSpacer(self) -> bool - Is this sizer item a spacer? - - - SetProportion(self, int proportion) - Set the proportion value for this item. - - - - - - GetProportion(self) -> int - Get the proportion value for this item. - - - SetFlag(self, int flag) - Set the flag value for this item. - - - - - - GetFlag(self) -> int - Get the flag value for this item. - - - SetBorder(self, int border) - Set the border value for this item. - - - - - - GetBorder(self) -> int - Get the border value for this item. - - - GetWindow(self) -> Window - Get the window (if any) that is managed by this sizer item. - - - SetWindow(self, Window window) - Set the window to be managed by this sizer item. - - - - - - GetSizer(self) -> Sizer - Get the subsizer (if any) that is managed by this sizer item. - - - SetSizer(self, Sizer sizer) - Set the subsizer to be managed by this sizer item. - - - - - - GetSpacer(self) -> Size - Get the size of the spacer managed by this sizer item. - - - SetSpacer(self, Size size) - Set the size of the spacer to be managed by this sizer item. - - - - - - Show(self, bool show) - Set the show item attribute, which sizers use to determine if the item -is to be made part of the layout or not. If the item is tracking a -window then it is shown or hidden as needed. - - - - - - IsShown(self) -> bool - Is the item to be shown in the layout? - - - GetPosition(self) -> Point - Returns the current position of the item, as set in the last Layout. - - - GetUserData(self) -> PyObject - Returns the userData associated with this sizer item, or None if there -isn't any. - - - - wx.Sizer is the abstract base class used for laying out subwindows in -a window. You cannot use wx.Sizer directly; instead, you will have to -use one of the sizer classes derived from it such as `wx.BoxSizer`, -`wx.StaticBoxSizer`, `wx.NotebookSizer`, `wx.GridSizer`, `wx.FlexGridSizer` -and `wx.GridBagSizer`. - -The concept implemented by sizers in wxWidgets is closely related to -layout tools in other GUI toolkits, such as Java's AWT, the GTK -toolkit or the Qt toolkit. It is based upon the idea of the individual -subwindows reporting their minimal required size and their ability to -get stretched if the size of the parent window has changed. This will -most often mean that the programmer does not set the original size of -a dialog in the beginning, rather the dialog will assigned a sizer and -this sizer will be queried about the recommended size. The sizer in -turn will query its children, which can be normal windows or contorls, -empty space or other sizers, so that a hierarchy of sizers can be -constructed. Note that wxSizer does not derive from wxWindow and thus -do not interfere with tab ordering and requires very little resources -compared to a real window on screen. - -What makes sizers so well fitted for use in wxWidgets is the fact that -every control reports its own minimal size and the algorithm can -handle differences in font sizes or different window (dialog item) -sizes on different platforms without problems. If for example the -standard font as well as the overall design of Mac widgets requires -more space than on Windows, then the initial size of a dialog using a -sizer will automatically be bigger on Mac than on Windows. - -:note: If you wish to create a custom sizer class in wxPython you - should derive the class from `wx.PySizer` in order to get - Python-aware capabilities for the various virtual methods. - -:see: `wx.SizerItem` - -:todo: More dscriptive text here along with some pictures... - - - - - _setOORInfo(self, PyObject _self) - - - - - - Add(self, item, int proportion=0, int flag=0, int border=0, - PyObject userData=None) - Appends a child item to the sizer. - - :param item: The item can be one of three kinds of objects: - - - **window**: A `wx.Window` to be managed by the sizer. Its - minimal size (either set explicitly by the user or - calculated internally when constructed with wx.DefaultSize) - is interpreted as the minimal size to use when laying out - item in the sizer. This is particularly useful in - connection with `wx.Window.SetSizeHints`. - - - **sizer**: The (child-)sizer to be added to the sizer. This - allows placing a child sizer in a sizer and thus to create - hierarchies of sizers (typically a vertical box as the top - sizer and several horizontal boxes on the level beneath). - - - **size**: A `wx.Size` or a 2-element sequence of integers - that represents the width and height of a spacer to be added - to the sizer. Adding spacers to sizers gives more - flexibility in the design of dialogs; imagine for example a - horizontal box with two buttons at the bottom of a dialog: - you might want to insert a space between the two buttons and - make that space stretchable using the *proportion* value and - the result will be that the left button will be aligned with - the left side of the dialog and the right button with the - right side - the space in between will shrink and grow with - the dialog. - - :param proportion: Although the meaning of this parameter is - undefined in wx.Sizer, it is used in `wx.BoxSizer` to indicate - if a child of a sizer can change its size in the main - orientation of the wx.BoxSizer - where 0 stands for not - changeable and a value of more than zero is interpreted - relative (a proportion of the total) to the value of other - children of the same wx.BoxSizer. For example, you might have - a horizontal wx.BoxSizer with three children, two of which are - supposed to change their size with the sizer. Then the two - stretchable windows should each be given *proportion* value of - 1 to make them grow and shrink equally with the sizer's - horizontal dimension. But if one of them had a *proportion* - value of 2 then it would get a double share of the space - available after the fixed size items are positioned. - - :param flag: This parameter can be used to set a number of flags - which can be combined using the binary OR operator ``|``. Two - main behaviours are defined using these flags. One is the - border around a window: the *border* parameter determines the - border width whereas the flags given here determine which - side(s) of the item that the border will be added. The other - flags determine how the sizer item behaves when the space - allotted to the sizer changes, and is somewhat dependent on - the specific kind of sizer used. - - +----------------------------+------------------------------------------+ - |- wx.TOP |These flags are used to specify | - |- wx.BOTTOM |which side(s) of the sizer item that | - |- wx.LEFT |the *border* width will apply to. | - |- wx.RIGHT | | - |- wx.ALL | | - | | | - +----------------------------+------------------------------------------+ - |- wx.EXAPAND |The item will be expanded to fill | - | |the space allotted to the item. | - +----------------------------+------------------------------------------+ - |- wx.SHAPED |The item will be expanded as much as | - | |possible while also maintaining its | - | |aspect ratio | - +----------------------------+------------------------------------------+ - |- wx.FIXED_MINSIZE |Normally wx.Sizers will use | - | |`wx.Window.GetMinSize` or | - | |`wx.Window.GetBestSize` to determine what | - | |the minimal size of window items should | - | |be, and will use that size to calculate | - | |the layout. This allows layouts to adjust | - | |when an item changes and it's best size | - | |becomes different. If you would rather | - | |have a window item stay the size it | - | |started with then use wx.FIXED_MINSIZE. | - +----------------------------+------------------------------------------+ - |- wx.ALIGN_CENTER |The wx.ALIGN flags allow you to specify | - |- wx.ALIGN_LEFT |the alignment of the item within the space| - |- wx.ALIGN_RIGHT |allotted to it by the sizer, ajusted for | - |- wx.ALIGN_TOP |the border if any. | - |- wx.ALIGN_BOTTOM | | - |- wx.ALIGN_CENTER_VERTICAL | | - |- wx.ALIGN_CENTER_HORIZONTAL| | - +----------------------------+------------------------------------------+ - - - :param border: Determines the border width, if the *flag* - parameter is set to include any border flag. - - :param userData: Allows an extra object to be attached to the - sizer item, for use in derived classes when sizing information - is more complex than the *proportion* and *flag* will allow for. - - - - - - - - - - - Insert(self, int before, item, int proportion=0, int flag=0, int border=0, - PyObject userData=None) - Inserts a new item into the list of items managed by this sizer before -the item at index *before*. See `Add` for a description of the parameters. - - - - - - - - - - - Prepend(self, item, int proportion=0, int flag=0, int border=0, - PyObject userData=None) - Adds a new item to the begining of the list of sizer items managed by -this sizer. See `Add` for a description of the parameters. - - - - - - - - - - Remove(self, item) -> bool - Removes an item from the sizer and destroys it. This method does not -cause any layout or resizing to take place, call `Layout` to update -the layout on screen after removing a child from the sizer. The -*item* parameter can be either a window, a sizer, or the zero-based -index of an item to remove. Returns True if the child item was found -and removed. - -:note: For historical reasons calling this method with a `wx.Window` - parameter is depreacted, as it will not be able to destroy the - window since it is owned by its parent. You should use `Detach` - instead. - - - - - - - Detach(self, item) -> bool - Detaches an item from the sizer without destroying it. This method -does not cause any layout or resizing to take place, call `Layout` to -do so. The *item* parameter can be either a window, a sizer, or the -zero-based index of the item to be detached. Returns True if the child item -was found and detached. - - - - - - _SetItemMinSize(self, PyObject item, Size size) - - - - - - - AddItem(self, SizerItem item) - Adds a `wx.SizerItem` to the sizer. - - - - - - InsertItem(self, int index, SizerItem item) - Inserts a `wx.SizerItem` to the sizer at the position given by *index*. - - - - - - - PrependItem(self, SizerItem item) - Prepends a `wx.SizerItem` to the sizer. - - - - - - SetDimension(self, int x, int y, int width, int height) - Call this to force the sizer to take the given dimension and thus -force the items owned by the sizer to resize themselves according to -the rules defined by the parameter in the `Add`, `Insert` or `Prepend` -methods. - - - - - - - - - SetMinSize(self, Size size) - Call this to give the sizer a minimal size. Normally, the sizer will -calculate its minimal size based purely on how much space its children -need. After calling this method `GetMinSize` will return either the -minimal size as requested by its children or the minimal size set -here, depending on which is bigger. - - - - - - GetSize(self) -> Size - Returns the current size of the space managed by the sizer. - - - GetPosition(self) -> Point - Returns the current position of the sizer's managed space. - - - GetMinSize(self) -> Size - Returns the minimal size of the sizer. This is either the combined -minimal size of all the children and their borders or the minimal size -set by SetMinSize, depending on which is bigger. - - - RecalcSizes(self) - Using the sizes calculated by `CalcMin` reposition and resize all the -items managed by this sizer. You should not need to call this directly as -it is called by `Layout`. - - - CalcMin(self) -> Size - This method is where the sizer will do the actual calculation of its -children's minimal sizes. You should not need to call this directly as -it is called by `Layout`. - - - Layout(self) - This method will force the recalculation and layout of the items -controlled by the sizer using the current space allocated to the -sizer. Normally this is called automatically from the owning window's -EVT_SIZE handler, but it is also useful to call it from user code when -one of the items in a sizer change size, or items are added or -removed. - - - Fit(self, Window window) -> Size - Tell the sizer to resize the *window* to match the sizer's minimal -size. This is commonly done in the constructor of the window itself in -order to set its initial size to match the needs of the children as -determined by the sizer. Returns the new size. - -For a top level window this is the total window size, not the client size. - - - - - - FitInside(self, Window window) - Tell the sizer to resize the *virtual size* of the *window* to match the -sizer's minimal size. This will not alter the on screen size of the -window, but may cause the addition/removal/alteration of scrollbars -required to view the virtual area in windows which manage it. - -:see: `wx.ScrolledWindow.SetScrollbars`, `SetVirtualSizeHints` - - - - - - - SetSizeHints(self, Window window) - Tell the sizer to set (and `Fit`) the minimal size of the *window* to -match the sizer's minimal size. This is commonly done in the -constructor of the window itself if the window is resizable (as are -many dialogs under Unix and frames on probably all platforms) in order -to prevent the window from being sized smaller than the minimal size -required by the sizer. - - - - - - SetVirtualSizeHints(self, Window window) - Tell the sizer to set the minimal size of the window virtual area to -match the sizer's minimal size. For windows with managed scrollbars -this will set them appropriately. - -:see: `wx.ScrolledWindow.SetScrollbars` - - - - - - - Clear(self, bool deleteWindows=False) - Clear all items from the sizer, optionally destroying the window items -as well. - - - - - - DeleteWindows(self) - Destroy all windows managed by the sizer. - - - GetChildren(sefl) -> list - Returns a list of all the `wx.SizerItem` objects managed by the sizer. - - - Show(self, item, bool show=True) - Shows or hides an item managed by the sizer. To make a sizer item -disappear or reappear, use Show followed by `Layout`. The *item* -parameter can be either a window, a sizer, or the zero-based index of -the item. - - - - - - - IsShown(self, item) - Determines if the item is currently shown. sizer. To make a sizer -item disappear or reappear, use Show followed by `Layout`. The *item* -parameter can be either a window, a sizer, or the zero-based index of -the item. - - - - - - ShowItems(self, bool show) - Recursively call `wx.Window.Show` on all sizer items. - - - - - - - wx.PySizer is a special version of `wx.Sizer` that has been -instrumented to allow the C++ virtual methods to be overloaded in -Python derived classes. You would derive from this class if you are -wanting to implement a custom sizer in Python code. Simply implement -`CalcMin` and `RecalcSizes` in the derived class and you're all set. -For example:: - - class MySizer(wx.PySizer): - def __init__(self): - wx.PySizer.__init__(self) - - def CalcMin(self): - for item in self.GetChildren(): - # calculate the total minimum width and height needed - # by all items in the sizer according to this sizer's - # layout algorithm. - ... - return wx.Size(width, height) - - def RecalcSizes(self): - # find the space allotted to this sizer - pos = self.GetPosition() - size = self.GetSize() - for item in self.GetChildren(): - # Recalculate (if necessary) the position and size of - # each item and then call item.SetDimension to do the - # actual positioning and sizing of the items within the - # space alloted to this sizer. - ... - item.SetDimension(itemPos, itemSize) - - -When `Layout` is called it first calls `CalcMin` followed by -`RecalcSizes` so you can optimize a bit by saving the results of -`CalcMin` and resuing them in `RecalcSizes`. - -:see: `wx.SizerItem`, `wx.Sizer.GetChildren` - - - - - __init__(self) -> PySizer - Creates a wx.PySizer. Must be called from the __init__ in the derived -class. - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - -#--------------------------------------------------------------------------- - - - The basic idea behind a box sizer is that windows will most often be -laid out in rather simple basic geometry, typically in a row or a -column or nested hierarchies of either. A wx.BoxSizer will lay out -its items in a simple row or column, depending on the orientation -parameter passed to the constructor. - -It is the unique feature of a box sizer, that it can grow in both -directions (height and width) but can distribute its growth in the -main direction (horizontal for a row) *unevenly* among its children. -This is determined by the proportion parameter give to items when they -are added to the sizer. It is interpreted as a weight factor, i.e. it -can be zero, indicating that the window may not be resized at all, or -above zero. If several windows have a value above zero, the value is -interpreted relative to the sum of all weight factors of the sizer, so -when adding two windows with a value of 1, they will both get resized -equally and each will receive half of the available space after the -fixed size items have been sized. If the items have unequal -proportion settings then they will receive a coresondingly unequal -allotment of the free space. - -:see: `wx.StaticBoxSizer` - - - - __init__(self, int orient=HORIZONTAL) -> BoxSizer - Constructor for a wx.BoxSizer. *orient* may be one of ``wx.VERTICAL`` -or ``wx.HORIZONTAL`` for creating either a column sizer or a row -sizer. - - - - - - GetOrientation(self) -> int - Returns the current orientation of the sizer. - - - SetOrientation(self, int orient) - Resets the orientation of the sizer. - - - - - - -#--------------------------------------------------------------------------- - - - wx.StaticBoxSizer derives from and functions identically to the -`wx.BoxSizer` and adds a `wx.StaticBox` around the items that the sizer -manages. Note that this static box must be created separately and -passed to the sizer constructor. - - - __init__(self, StaticBox box, int orient=HORIZONTAL) -> StaticBoxSizer - Constructor. It takes an associated static box and the orientation -*orient* as parameters - orient can be either of ``wx.VERTICAL`` or -``wx.HORIZONTAL``. - - - - - - - GetStaticBox(self) -> StaticBox - Returns the static box associated with this sizer. - - - -#--------------------------------------------------------------------------- - - - A grid sizer is a sizer which lays out its children in a -two-dimensional table with all cells having the same size. In other -words, the width of each cell within the grid is the width of the -widest item added to the sizer and the height of each grid cell is the -height of the tallest item. An optional vertical and/or horizontal -gap between items can also be specified (in pixels.) - -Items are placed in the cells of the grid in the order they are added, -in row-major order. In other words, the first row is filled first, -then the second, and so on until all items have been added. (If -neccessary, additional rows will be added as items are added.) If you -need to have greater control over the cells that items are placed in -then use the `wx.GridBagSizer`. - - - - __init__(self, int rows=1, int cols=0, int vgap=0, int hgap=0) -> GridSizer - Constructor for a wx.GridSizer. *rows* and *cols* determine the number -of columns and rows in the sizer - if either of the parameters is -zero, it will be calculated to from the total number of children in -the sizer, thus making the sizer grow dynamically. *vgap* and *hgap* -define extra space between all children. - - - - - - - - - SetCols(self, int cols) - Sets the number of columns in the sizer. - - - - - - SetRows(self, int rows) - Sets the number of rows in the sizer. - - - - - - SetVGap(self, int gap) - Sets the vertical gap (in pixels) between the cells in the sizer. - - - - - - SetHGap(self, int gap) - Sets the horizontal gap (in pixels) between cells in the sizer - - - - - - GetCols(self) -> int - Returns the number of columns in the sizer. - - - GetRows(self) -> int - Returns the number of rows in the sizer. - - - GetVGap(self) -> int - Returns the vertical gap (in pixels) between the cells in the sizer. - - - GetHGap(self) -> int - Returns the horizontal gap (in pixels) between cells in the sizer. - - - -#--------------------------------------------------------------------------- - - - A flex grid sizer is a sizer which lays out its children in a -two-dimensional table with all table cells in one row having the same -height and all cells in one column having the same width, but all -rows or all columns are not necessarily the same height or width as in -the `wx.GridSizer`. - -wx.FlexGridSizer can also size items equally in one direction but -unequally ("flexibly") in the other. If the sizer is only flexible -in one direction (this can be changed using `SetFlexibleDirection`), it -needs to be decided how the sizer should grow in the other ("non -flexible") direction in order to fill the available space. The -`SetNonFlexibleGrowMode` method serves this purpose. - - - - - __init__(self, int rows=1, int cols=0, int vgap=0, int hgap=0) -> FlexGridSizer - Constructor for a wx.FlexGridSizer. *rows* and *cols* determine the -number of columns and rows in the sizer - if either of the parameters -is zero, it will be calculated to from the total number of children in -the sizer, thus making the sizer grow dynamically. *vgap* and *hgap* -define extra space between all children. - - - - - - - - - AddGrowableRow(self, size_t idx, int proportion=0) - Specifies that row *idx* (starting from zero) should be grown if there -is extra space available to the sizer. - -The *proportion* parameter has the same meaning as the stretch factor -for the box sizers except that if all proportions are 0, then all -columns are resized equally (instead of not being resized at all). - - - - - - - RemoveGrowableRow(self, size_t idx) - Specifies that row *idx* is no longer growable. - - - - - - AddGrowableCol(self, size_t idx, int proportion=0) - Specifies that column *idx* (starting from zero) should be grown if -there is extra space available to the sizer. - -The *proportion* parameter has the same meaning as the stretch factor -for the box sizers except that if all proportions are 0, then all -columns are resized equally (instead of not being resized at all). - - - - - - - RemoveGrowableCol(self, size_t idx) - Specifies that column *idx* is no longer growable. - - - - - - SetFlexibleDirection(self, int direction) - Specifies whether the sizer should flexibly resize its columns, rows, -or both. Argument *direction* can be one of the following values. Any -other value is ignored. - - ============== ======================================= - wx.VERTICAL Rows are flexibly sized. - wx.HORIZONTAL Columns are flexibly sized. - wx.BOTH Both rows and columns are flexibly sized - (this is the default value). - ============== ======================================= - -Note that this method does not trigger relayout. - - - - - - - GetFlexibleDirection(self) -> int - Returns a value that specifies whether the sizer -flexibly resizes its columns, rows, or both (default). - -:see: `SetFlexibleDirection` - - - SetNonFlexibleGrowMode(self, int mode) - Specifies how the sizer should grow in the non-flexible direction if -there is one (so `SetFlexibleDirection` must have been called -previously). Argument *mode* can be one of the following values: - - ========================== ================================================= - wx.FLEX_GROWMODE_NONE Sizer doesn't grow in the non flexible direction. - wx.FLEX_GROWMODE_SPECIFIED Sizer honors growable columns/rows set with - `AddGrowableCol` and `AddGrowableRow`. In this - case equal sizing applies to minimum sizes of - columns or rows (this is the default value). - wx.FLEX_GROWMODE_ALL Sizer equally stretches all columns or rows in - the non flexible direction, whether they are - growable or not in the flexbile direction. - ========================== ================================================= - -Note that this method does not trigger relayout. - - - - - - - - GetNonFlexibleGrowMode(self) -> int - Returns the value that specifies how the sizer grows in the -non-flexible direction if there is one. - -:see: `SetNonFlexibleGrowMode` - - - GetRowHeights(self) -> list - Returns a list of integers representing the heights of each of the -rows in the sizer. - - - GetColWidths(self) -> list - Returns a list of integers representing the widths of each of the -columns in the sizer. - - - -#--------------------------------------------------------------------------- - - - This class represents the position of an item in a virtual grid of -rows and columns managed by a `wx.GridBagSizer`. wxPython has -typemaps that will automatically convert from a 2-element sequence of -integers to a wx.GBPosition, so you can use the more pythonic -representation of the position nearly transparently in Python code. - - __init__(self, int row=0, int col=0) -> GBPosition - This class represents the position of an item in a virtual grid of -rows and columns managed by a `wx.GridBagSizer`. wxPython has -typemaps that will automatically convert from a 2-element sequence of -integers to a wx.GBPosition, so you can use the more pythonic -representation of the position nearly transparently in Python code. - - - - - - - GetRow(self) -> int - - - GetCol(self) -> int - - - SetRow(self, int row) - - - - - - SetCol(self, int col) - - - - - - __eq__(self, GBPosition other) -> bool - - - - - - __ne__(self, GBPosition other) -> bool - - - - - - Set(self, int row=0, int col=0) - - - - - - - Get(self) -> PyObject - - - - This class is used to hold the row and column spanning attributes of -items in a `wx.GridBagSizer`. wxPython has typemaps that will -automatically convert from a 2-element sequence of integers to a -wx.GBSpan, so you can use the more pythonic representation of the span -nearly transparently in Python code. - - - __init__(self, int rowspan=1, int colspan=1) -> GBSpan - Construct a new wxGBSpan, optionally setting the rowspan and -colspan. The default is (1,1). (Meaning that the item occupies one -cell in each direction. - - - - - - - GetRowspan(self) -> int - - - GetColspan(self) -> int - - - SetRowspan(self, int rowspan) - - - - - - SetColspan(self, int colspan) - - - - - - __eq__(self, GBSpan other) -> bool - - - - - - __ne__(self, GBSpan other) -> bool - - - - - - Set(self, int rowspan=1, int colspan=1) - - - - - - - Get(self) -> PyObject - - - - The wx.GBSizerItem class is used to track the additional data about -items in a `wx.GridBagSizer` such as the item's position in the grid -and how many rows or columns it spans. - - - - __init__(self) -> GBSizerItem - Constructs an empty wx.GBSizerItem. Either a window, sizer or spacer -size will need to be set, as well as a position and span before this -item can be used in a Sizer. - -You will probably never need to create a wx.GBSizerItem directly as they -are created automatically when the sizer's Add method is called. - - - GBSizerItemWindow(Window window, GBPosition pos, GBSpan span, int flag, - int border, PyObject userData=None) -> GBSizerItem - Construct a `wx.GBSizerItem` for a window. - - - - - - - - - - - GBSizerItemSizer(Sizer sizer, GBPosition pos, GBSpan span, int flag, - int border, PyObject userData=None) -> GBSizerItem - Construct a `wx.GBSizerItem` for a sizer - - - - - - - - - - - GBSizerItemSpacer(int width, int height, GBPosition pos, GBSpan span, - int flag, int border, PyObject userData=None) -> GBSizerItem - Construct a `wx.GBSizerItem` for a spacer. - - - - - - - - - - - - GetPos(self) -> GBPosition - Get the grid position of the item - - - GetSpan(self) -> GBSpan - Get the row and column spanning of the item - - - SetPos(self, GBPosition pos) -> bool - If the item is already a member of a sizer then first ensure that -there is no other item that would intersect with this one at the new -position, then set the new position. Returns True if the change is -successful and after the next Layout() the item will be moved. - - - - - - SetSpan(self, GBSpan span) -> bool - If the item is already a member of a sizer then first ensure that -there is no other item that would intersect with this one with its new -spanning size, then set the new spanning. Returns True if the change -is successful and after the next Layout() the item will be resized. - - - - - - - Intersects(self, GBSizerItem other) -> bool - Returns True if this item and the other item instersect. - - - - - - IntersectsPos(self, GBPosition pos, GBSpan span) -> bool - Returns True if the given pos/span would intersect with this item. - - - - - - - GetEndPos(self) -> GBPosition - Get the row and column of the endpoint of this item. - - - GetGBSizer(self) -> GridBagSizer - Get the sizer this item is a member of. - - - SetGBSizer(self, GridBagSizer sizer) - Set the sizer this item is a member of. - - - - - - - A `wx.Sizer` that can lay out items in a virtual grid like a -`wx.FlexGridSizer` but in this case explicit positioning of the items -is allowed using `wx.GBPosition`, and items can optionally span more -than one row and/or column using `wx.GBSpan`. The total size of the -virtual grid is determined by the largest row and column that items are -positioned at, adjusted for spanning. - - - - __init__(self, int vgap=0, int hgap=0) -> GridBagSizer - Constructor, with optional parameters to specify the gap between the -rows and columns. - - - - - - - Add(self, item, GBPosition pos, GBSpan span=DefaultSpan, int flag=0, -int border=0, userData=None) - Adds an item to the sizer at the grid cell *pos*, optionally spanning -more than one row or column as specified with *span*. The remaining -args behave similarly to `wx.Sizer.Add`. - -Returns True if the item was successfully placed at the given cell -position, False if something was already there. - - - - - - - - - - - - Add(self, GBSizerItem item) -> bool - Add an item to the sizer using a `wx.GBSizerItem`. Returns True if -the item was successfully placed at its given cell position, False if -something was already there. - - - - - - GetEmptyCellSize(self) -> Size - Get the size used for cells in the grid with no item. - - - SetEmptyCellSize(self, Size sz) - Set the size used for cells in the grid with no item. - - - - - - GetItemPosition(self, item) -> GBPosition - -Get the grid position of the specified *item* where *item* is either a -window or subsizer that is a member of this sizer, or a zero-based -index of an item. - - - - - - GetItemPosition(self, item) -> GBPosition - -Get the grid position of the specified *item* where *item* is either a -window or subsizer that is a member of this sizer, or a zero-based -index of an item. - - - - - - GetItemPosition(self, item) -> GBPosition - -Get the grid position of the specified *item* where *item* is either a -window or subsizer that is a member of this sizer, or a zero-based -index of an item. - - - - - - SetItemPosition(self, item, GBPosition pos) -> bool - -Set the grid position of the specified *item* where *item* is either a -window or subsizer that is a member of this sizer, or a zero-based -index of an item. Returns True on success. If the move is not -allowed (because an item is already there) then False is returned. - - - - - - - - SetItemPosition(self, item, GBPosition pos) -> bool - -Set the grid position of the specified *item* where *item* is either a -window or subsizer that is a member of this sizer, or a zero-based -index of an item. Returns True on success. If the move is not -allowed (because an item is already there) then False is returned. - - - - - - - - SetItemPosition(self, item, GBPosition pos) -> bool - -Set the grid position of the specified *item* where *item* is either a -window or subsizer that is a member of this sizer, or a zero-based -index of an item. Returns True on success. If the move is not -allowed (because an item is already there) then False is returned. - - - - - - - - GetItemSpan(self, item) -> GBSpan - -Get the row/col spanning of the specified *item* where *item* is -either a window or subsizer that is a member of this sizer, or a -zero-based index of an item. - - - - - - GetItemSpan(self, item) -> GBSpan - -Get the row/col spanning of the specified *item* where *item* is -either a window or subsizer that is a member of this sizer, or a -zero-based index of an item. - - - - - - GetItemSpan(self, item) -> GBSpan - -Get the row/col spanning of the specified *item* where *item* is -either a window or subsizer that is a member of this sizer, or a -zero-based index of an item. - - - - - - SetItemSpan(self, item, GBSpan span) -> bool - -Set the row/col spanning of the specified *item* where *item* is -either a window or subsizer that is a member of this sizer, or a -zero-based index of an item. Returns True on success. If the move is -not allowed (because an item is already there) then False is returned. - - - - - - - SetItemSpan(self, item, GBSpan span) -> bool - -Set the row/col spanning of the specified *item* where *item* is -either a window or subsizer that is a member of this sizer, or a -zero-based index of an item. Returns True on success. If the move is -not allowed (because an item is already there) then False is returned. - - - - - - - SetItemSpan(self, item, GBSpan span) -> bool - -Set the row/col spanning of the specified *item* where *item* is -either a window or subsizer that is a member of this sizer, or a -zero-based index of an item. Returns True on success. If the move is -not allowed (because an item is already there) then False is returned. - - - - - - - FindItem(self, item) -> GBSizerItem - -Find the sizer item for the given window or subsizer, returns None if -not found. (non-recursive) - - - - - - FindItem(self, item) -> GBSizerItem - -Find the sizer item for the given window or subsizer, returns None if -not found. (non-recursive) - - - - - - FindItemAtPosition(self, GBPosition pos) -> GBSizerItem - Return the sizer item for the given grid cell, or None if there is no -item at that position. (non-recursive) - - - - - - FindItemAtPoint(self, Point pt) -> GBSizerItem - Return the sizer item located at the point given in *pt*, or None if -there is no item at that point. The (x,y) coordinates in pt correspond -to the client coordinates of the window using the sizer for -layout. (non-recursive) - - - - - - CheckForIntersection(self, GBSizerItem item, GBSizerItem excludeItem=None) -> bool - Look at all items and see if any intersect (or would overlap) the -given *item*. Returns True if so, False if there would be no overlap. -If an *excludeItem* is given then it will not be checked for -intersection, for example it may be the item we are checking the -position of. - - - - - - - - CheckForIntersectionPos(self, GBPosition pos, GBSpan span, GBSizerItem excludeItem=None) -> bool - Look at all items and see if any intersect (or would overlap) the -given position and span. Returns True if so, False if there would be -no overlap. If an *excludeItem* is given then it will not be checked -for intersection, for example it may be the item we are checking the -position of. - - - - - - - - -#--------------------------------------------------------------------------- - - - Objects of this class are stored in the `wx.LayoutConstraints` class as -one of eight possible constraints that a window can be involved in. -You will never need to create an instance of -wx.IndividualLayoutConstraint, rather you should create a -`wx.LayoutConstraints` instance and use the individual contstraints -that it contains. - -Constraints are initially set to have the relationship -wx.Unconstrained, which means that their values should be calculated -by looking at known constraints. - -The Edge specifies the type of edge or dimension of a window. - -Edges ------- - ================== ============================================== - wx.Left The left edge. - wx.Top The top edge. - wx.Right The right edge. - wx.Bottom The bottom edge. - wx.CentreX The x-coordinate of the centre of the window. - wx.CentreY The y-coordinate of the centre of the window. - ================== ============================================== - - -The Relationship specifies the relationship that this edge or -dimension has with another specified edge or dimension. Normally, the -user doesn't use these directly because functions such as Below and -RightOf are a convenience for using the more general Set function. - -Relationships -------------- - ================== ============================================== - wx.Unconstrained The edge or dimension is unconstrained - (the default for edges.) - wx.AsIs The edge or dimension is to be taken from the current - window position or size (the default for dimensions.) - wx.Above The edge should be above another edge. - wx.Below The edge should be below another edge. - wx.LeftOf The edge should be to the left of another edge. - wx.RightOf The edge should be to the right of another edge. - wx.SameAs The edge or dimension should be the same as another edge - or dimension. - wx.PercentOf The edge or dimension should be a percentage of another - edge or dimension. - wx.Absolute The edge or dimension should be a given absolute value. - ================== ============================================== - -:see: `wx.LayoutConstraints`, `wx.Window.SetConstraints` - - - - Set(self, int rel, Window otherW, int otherE, int val=0, int marg=wxLAYOUT_DEFAULT_MARGIN) - Sets the properties of the constraint. Normally called by one of the -convenience functions such as Above, RightOf, SameAs. - - - - - - - - - - LeftOf(self, Window sibling, int marg=0) - Constrains this edge to be to the left of the given window, with an -optional margin. Implicitly, this is relative to the left edge of the -other window. - - - - - - - RightOf(self, Window sibling, int marg=0) - Constrains this edge to be to the right of the given window, with an -optional margin. Implicitly, this is relative to the right edge of the -other window. - - - - - - - Above(self, Window sibling, int marg=0) - Constrains this edge to be above the given window, with an optional -margin. Implicitly, this is relative to the top edge of the other -window. - - - - - - - Below(self, Window sibling, int marg=0) - Constrains this edge to be below the given window, with an optional -margin. Implicitly, this is relative to the bottom edge of the other -window. - - - - - - - SameAs(self, Window otherW, int edge, int marg=0) - Constrains this edge or dimension to be to the same as the edge of the -given window, with an optional margin. - - - - - - - - PercentOf(self, Window otherW, int wh, int per) - Constrains this edge or dimension to be to a percentage of the given -window, with an optional margin. - - - - - - - - Absolute(self, int val) - Constrains this edge or dimension to be the given absolute value. - - - - - - Unconstrained(self) - Sets this edge or dimension to be unconstrained, that is, dependent on -other edges and dimensions from which this value can be deduced. - - - AsIs(self) - Sets this edge or constraint to be whatever the window's value is at -the moment. If either of the width and height constraints are *as is*, -the window will not be resized, but moved instead. This is important -when considering panel items which are intended to have a default -size, such as a button, which may take its size from the size of the -button label. - - - GetOtherWindow(self) -> Window - - - GetMyEdge(self) -> int - - - SetEdge(self, int which) - - - - - - SetValue(self, int v) - - - - - - GetMargin(self) -> int - - - SetMargin(self, int m) - - - - - - GetValue(self) -> int - - - GetPercent(self) -> int - - - GetOtherEdge(self) -> int - - - GetDone(self) -> bool - - - SetDone(self, bool d) - - - - - - GetRelationship(self) -> int - - - SetRelationship(self, int r) - - - - - - ResetIfWin(self, Window otherW) -> bool - Reset constraint if it mentions otherWin - - - - - - SatisfyConstraint(self, LayoutConstraints constraints, Window win) -> bool - Try to satisfy constraint - - - - - - - GetEdge(self, int which, Window thisWin, Window other) -> int - Get the value of this edge or dimension, or if this -is not determinable, -1. - - - - - - - - - **Note:** constraints are now deprecated and you should use sizers -instead. - -Objects of this class can be associated with a window to define its -layout constraints, with respect to siblings or its parent. - -The class consists of the following eight constraints of class -wx.IndividualLayoutConstraint, some or all of which should be accessed -directly to set the appropriate constraints. - - * left: represents the left hand edge of the window - * right: represents the right hand edge of the window - * top: represents the top edge of the window - * bottom: represents the bottom edge of the window - * width: represents the width of the window - * height: represents the height of the window - * centreX: represents the horizontal centre point of the window - * centreY: represents the vertical centre point of the window - -Most constraints are initially set to have the relationship -wxUnconstrained, which means that their values should be calculated by -looking at known constraints. The exceptions are width and height, -which are set to wxAsIs to ensure that if the user does not specify a -constraint, the existing width and height will be used, to be -compatible with panel items which often have take a default size. If -the constraint is ``wx.AsIs``, the dimension will not be changed. - -:see: `wx.IndividualLayoutConstraint`, `wx.Window.SetConstraints` - - - - __init__(self) -> LayoutConstraints - - - - - - - - - - - SatisfyConstraints(Window win) -> (areSatisfied, noChanges) - - - - - - - AreSatisfied(self) -> bool - - - #---------------------------------------------------------------------------- - -# Use Python's bool constants if available, make some if not -try: - True -except NameError: - __builtins__.True = 1==1 - __builtins__.False = 1==0 - def bool(value): return not not value - __builtins__.bool = bool - - - -# workarounds for bad wxRTTI names -__wxPyPtrTypeMap['wxGauge95'] = 'wxGauge' -__wxPyPtrTypeMap['wxSlider95'] = 'wxSlider' -__wxPyPtrTypeMap['wxStatusBar95'] = 'wxStatusBar' - - -#---------------------------------------------------------------------------- -# Load version numbers from __version__... Ensure that major and minor -# versions are the same for both wxPython and wxWidgets. - -from __version__ import * -__version__ = VERSION_STRING - -assert MAJOR_VERSION == _core_.MAJOR_VERSION, "wxPython/wxWidgets version mismatch" -assert MINOR_VERSION == _core_.MINOR_VERSION, "wxPython/wxWidgets version mismatch" -if RELEASE_VERSION != _core_.RELEASE_VERSION: - import warnings - warnings.warn("wxPython/wxWidgets release number mismatch") - -#---------------------------------------------------------------------------- - -class PyDeadObjectError(AttributeError): - pass - -class _wxPyDeadObject(object): - """ - Instances of wx objects that are OOR capable will have their __class__ - changed to this class when the C++ object is deleted. This should help - prevent crashes due to referencing a bogus C++ pointer. - """ - reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)" - attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed." - - def __repr__(self): - if not hasattr(self, "_name"): - self._name = "[unknown]" - return self.reprStr % self._name - - def __getattr__(self, *args): - if not hasattr(self, "_name"): - self._name = "[unknown]" - raise PyDeadObjectError(self.attrStr % self._name) - - def __nonzero__(self): - return 0 - - - -class PyUnbornObjectError(AttributeError): - pass - -class _wxPyUnbornObject(object): - """ - Some stock objects are created when the wx._core module is - imported, but their C++ instance is not created until the wx.App - object is created and initialized. These object instances will - temporarily have their __class__ changed to this class so an - exception will be raised if they are used before the C++ instance - is ready. - """ - - reprStr = "wxPython wrapper for UNBORN object! (The C++ object is not initialized yet.)" - attrStr = "The C++ part of this object has not been initialized, attribute access not allowed." - - def __repr__(self): - #if not hasattr(self, "_name"): - # self._name = "[unknown]" - return self.reprStr #% self._name - - def __getattr__(self, *args): - #if not hasattr(self, "_name"): - # self._name = "[unknown]" - raise PyUnbornObjectError(self.attrStr) # % self._name ) - - def __nonzero__(self): - return 0 - - -#---------------------------------------------------------------------------- -_wxPyCallAfterId = None - -def CallAfter(callable, *args, **kw): - """ - Call the specified function after the current and pending event - handlers have been completed. This is also good for making GUI - method calls from non-GUI threads. Any extra positional or - keyword args are passed on to the callable when it is called. - - :see: `wx.FutureCall` - """ - app = wx.GetApp() - assert app is not None, 'No wx.App created yet' - - global _wxPyCallAfterId - if _wxPyCallAfterId is None: - _wxPyCallAfterId = wx.NewEventType() - app.Connect(-1, -1, _wxPyCallAfterId, - lambda event: event.callable(*event.args, **event.kw) ) - evt = wx.PyEvent() - evt.SetEventType(_wxPyCallAfterId) - evt.callable = callable - evt.args = args - evt.kw = kw - wx.PostEvent(app, evt) - - -#---------------------------------------------------------------------------- - - -class FutureCall: - """ - A convenience class for wx.Timer, that calls the given callable - object once after the given amount of milliseconds, passing any - positional or keyword args. The return value of the callable is - availbale after it has been run with the `GetResult` method. - - If you don't need to get the return value or restart the timer - then there is no need to hold a reference to this object. It will - hold a reference to itself while the timer is running (the timer - has a reference to self.Notify) but the cycle will be broken when - the timer completes, automatically cleaning up the wx.FutureCall - object. - - :see: `wx.CallAfter` - """ - def __init__(self, millis, callable, *args, **kwargs): - self.millis = millis - self.callable = callable - self.SetArgs(*args, **kwargs) - self.runCount = 0 - self.running = False - self.hasRun = False - self.result = None - self.timer = None - self.Start() - - def __del__(self): - self.Stop() - - - def Start(self, millis=None, *args, **kwargs): - """ - (Re)start the timer - """ - self.hasRun = False - if millis is not None: - self.millis = millis - if args or kwargs: - self.SetArgs(*args, **kwargs) - self.Stop() - self.timer = wx.PyTimer(self.Notify) - self.timer.Start(self.millis, wx.TIMER_ONE_SHOT) - self.running = True - Restart = Start - - - def Stop(self): - """ - Stop and destroy the timer. - """ - if self.timer is not None: - self.timer.Stop() - self.timer = None - - - def GetInterval(self): - if self.timer is not None: - return self.timer.GetInterval() - else: - return 0 - - - def IsRunning(self): - return self.timer is not None and self.timer.IsRunning() - - - def SetArgs(self, *args, **kwargs): - """ - (Re)set the args passed to the callable object. This is - useful in conjunction with Restart if you want to schedule a - new call to the same callable object but with different - parameters. - """ - self.args = args - self.kwargs = kwargs - - - def HasRun(self): - return self.hasRun - - def GetResult(self): - return self.result - - def Notify(self): - """ - The timer has expired so call the callable. - """ - if self.callable and getattr(self.callable, 'im_self', True): - self.runCount += 1 - self.running = False - self.result = self.callable(*self.args, **self.kwargs) - self.hasRun = True - if not self.running: - # if it wasn't restarted, then cleanup - wx.CallAfter(self.Stop) - - - -#---------------------------------------------------------------------------- -# Control which items in this module should be documented by epydoc. -# We allow only classes and functions, which will help reduce the size -# of the docs by filtering out the zillions of constants, EVT objects, -# and etc that don't make much sense by themselves, but are instead -# documented (or will be) as part of the classes/functions/methods -# where they should be used. - -class __DocFilter: - """ - A filter for epydoc that only allows non-Ptr classes and - fucntions, in order to reduce the clutter in the API docs. - """ - def __init__(self, globals): - self._globals = globals - - def __call__(self, name): - import types - obj = self._globals.get(name, None) - if type(obj) not in [type, types.ClassType, types.FunctionType, types.BuiltinFunctionType]: - return False - if name.startswith('_') or name.endswith('Ptr') or name.startswith('EVT'): - return False - return True - -#---------------------------------------------------------------------------- -#---------------------------------------------------------------------------- - -# Import other modules in this package that should show up in the -# "core" wx namespace -from _gdi import * -from _windows import * -from _controls import * -from _misc import * - - -# Fixup the stock objects since they can't be used yet. (They will be -# restored in wx.PyApp.OnInit.) -_core_._wxPyFixStockObjects() - -#---------------------------------------------------------------------------- -#---------------------------------------------------------------------------- - - - - - wx = _core - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> GDIObject - - - __del__(self) - - - GetVisible(self) -> bool - - - SetVisible(self, bool visible) - - - - - - IsNull(self) -> bool - - - -#--------------------------------------------------------------------------- - - - A colour is an object representing a combination of Red, Green, and -Blue (RGB) intensity values, and is used to determine drawing colours, -window colours, etc. Valid RGB values are in the range 0 to 255. - -In wxPython there are typemaps that will automatically convert from a -colour name, or from a '#RRGGBB' colour hex value string to a -wx.Colour object when calling C++ methods that expect a wxColour. -This means that the following are all equivallent:: - - win.SetBackgroundColour(wxColour(0,0,255)) - win.SetBackgroundColour('BLUE') - win.SetBackgroundColour('#0000FF') - -Additional colour names and their coresponding values can be added -using `wx.ColourDatabase`. Various system colours (as set in the -user's system preferences) can be retrieved with -`wx.SystemSettings.GetColour`. - - - - __init__(self, byte red=0, byte green=0, byte blue=0) -> Colour - Constructs a colour from red, green and blue values. - -:see: Alternate constructors `wx.NamedColour` and `wx.ColourRGB`. - - - - - - - - - NamedColour(String colorName) -> Colour - Constructs a colour object using a colour name listed in -``wx.TheColourDatabase``. - - - - - - ColourRGB(unsigned long colRGB) -> Colour - Constructs a colour from a packed RGB value. - - - - - - __del__(self) - - - Red(self) -> byte - Returns the red intensity. - - - Green(self) -> byte - Returns the green intensity. - - - Blue(self) -> byte - Returns the blue intensity. - - - Ok(self) -> bool - Returns True if the colour object is valid (the colour has been -initialised with RGB values). - - - Set(self, byte red, byte green, byte blue) - Sets the RGB intensity values. - - - - - - - - SetRGB(self, unsigned long colRGB) - Sets the RGB intensity values from a packed RGB value. - - - - - - SetFromName(self, String colourName) - Sets the RGB intensity values using a colour name listed in -``wx.TheColourDatabase``. - - - - - - GetPixel(self) -> long - Returns a pixel value which is platform-dependent. On Windows, a -COLORREF is returned. On X, an allocated pixel value is returned. -1 -is returned if the pixel is invalid (on X, unallocated). - - - __eq__(self, Colour colour) -> bool - Compare colours for equality - - - - - - __ne__(self, Colour colour) -> bool - Compare colours for inequality - - - - - - Get() -> (r, g, b) - Returns the RGB intensity values as a tuple. - - - GetRGB(self) -> unsigned long - Return the colour as a packed RGB value - - - - Color = Colour - NamedColor = NamedColour - ColorRGB = ColourRGB - - - - - __init__(self, int n, unsigned char red, unsigned char green, unsigned char blue) -> Palette - - - - - - - - - __del__(self) - - - GetPixel(self, byte red, byte green, byte blue) -> int - - - - - - - - GetRGB(int pixel) -> (R,G,B) - - - - - - - - - Ok(self) -> bool - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Colour colour, int width=1, int style=SOLID) -> Pen - - - - - - - - __del__(self) - - - GetCap(self) -> int - - - GetColour(self) -> Colour - - - GetJoin(self) -> int - - - GetStyle(self) -> int - - - GetWidth(self) -> int - - - Ok(self) -> bool - - - SetCap(self, int cap_style) - - - - - - SetColour(self, Colour colour) - - - - - - SetJoin(self, int join_style) - - - - - - SetStyle(self, int style) - - - - - - SetWidth(self, int width) - - - - - - SetDashes(self, int dashes, wxDash dashes_array) - - - - - - - GetDashes(self) -> PyObject - - - _SetDashes(self, PyObject _self, PyObject pyDashes) - - - - - - - GetDashCount(self) -> int - - - __eq__(self, Pen other) -> bool - - - - - - __ne__(self, Pen other) -> bool - - - - - - -#--------------------------------------------------------------------------- - - - A brush is a drawing tool for filling in areas. It is used for -painting the background of rectangles, ellipses, etc. when drawing on -a `wx.DC`. It has a colour and a style. - -:warning: Do not create instances of wx.Brush before the `wx.App` - object has been created because, depending on the platform, - required internal data structures may not have been initialized - yet. Instead create your brushes in the app's OnInit or as they - are needed for drawing. - -:note: On monochrome displays all brushes are white, unless the colour - really is black. - -:see: `wx.BrushList`, `wx.DC`, `wx.DC.SetBrush` - - - - __init__(self, Colour colour, int style=SOLID) -> Brush - Constructs a brush from a `wx.Colour` object and a style.The style parameter may be one of the following: - - =================== ============================= - Style Meaning - =================== ============================= - wx.TRANSPARENT Transparent (no fill). - wx.SOLID Solid. - wx.STIPPLE Uses a bitmap as a stipple. - wx.BDIAGONAL_HATCH Backward diagonal hatch. - wx.CROSSDIAG_HATCH Cross-diagonal hatch. - wx.FDIAGONAL_HATCH Forward diagonal hatch. - wx.CROSS_HATCH Cross hatch. - wx.HORIZONTAL_HATCH Horizontal hatch. - wx.VERTICAL_HATCH Vertical hatch. - =================== ============================= - - - - - - - - - __del__(self) - - - SetColour(self, Colour col) - Set the brush's `wx.Colour`. - - - - - - SetStyle(self, int style) - Sets the style of the brush. See `__init__` for a listing of styles. - - - - - - SetStipple(self, Bitmap stipple) - Sets the stipple `wx.Bitmap`. - - - - - - GetColour(self) -> Colour - Returns the `wx.Colour` of the brush. - - - GetStyle(self) -> int - Returns the style of the brush. See `__init__` for a listing of -styles. - - - GetStipple(self) -> Bitmap - Returns the stiple `wx.Bitmap` of the brush. If the brush does not -have a wx.STIPPLE style, then the return value may be non-None but an -uninitialised bitmap (`wx.Bitmap.Ok` returns False). - - - Ok(self) -> bool - Returns True if the brush is initialised and valid. - - - - The wx.Bitmap class encapsulates the concept of a platform-dependent -bitmap. It can be either monochrome or colour, and either loaded from -a file or created dynamically. A bitmap can be selected into a memory -device context (instance of `wx.MemoryDC`). This enables the bitmap to -be copied to a window or memory device context using `wx.DC.Blit`, or -to be used as a drawing surface. - -The BMP and XMP image file formats are supported on all platforms by -wx.Bitmap. Other formats are automatically loaded by `wx.Image` and -converted to a wx.Bitmap, so any image file format supported by -`wx.Image` can be used. - -:todo: Add wrappers and support for raw bitmap data access. Can this - be be put into Python without losing the speed benefits of the - teplates and iterators in rawbmp.h? - -:todo: Find a way to do very efficient PIL Image <--> wx.Bitmap - converstions. - - - - __init__(self, String name, int type=BITMAP_TYPE_ANY) -> Bitmap - Loads a bitmap from a file. - :param name: Name of the file to load the bitmap from. - :param type: The type of image to expect. Can be one of the following - constants (assuming that the neccessary `wx.Image` handlers are - loaded): - - * wx.BITMAP_TYPE_ANY - * wx.BITMAP_TYPE_BMP - * wx.BITMAP_TYPE_ICO - * wx.BITMAP_TYPE_CUR - * wx.BITMAP_TYPE_XBM - * wx.BITMAP_TYPE_XPM - * wx.BITMAP_TYPE_TIF - * wx.BITMAP_TYPE_GIF - * wx.BITMAP_TYPE_PNG - * wx.BITMAP_TYPE_JPEG - * wx.BITMAP_TYPE_PNM - * wx.BITMAP_TYPE_PCX - * wx.BITMAP_TYPE_PICT - * wx.BITMAP_TYPE_ICON - * wx.BITMAP_TYPE_ANI - * wx.BITMAP_TYPE_IFF - -:see: Alternate constructors `wx.EmptyBitmap`, `wx.BitmapFromIcon`, - `wx.BitmapFromImage`, `wx.BitmapFromXPMData`, - `wx.BitmapFromBits` - - - - - - - - EmptyBitmap(int width, int height, int depth=-1) -> Bitmap - Creates a new bitmap of the given size. A depth of -1 indicates the -depth of the current screen or visual. Some platforms only support 1 -for monochrome and -1 for the current colour setting. - - - - - - - - BitmapFromIcon(Icon icon) -> Bitmap - Create a new bitmap from a `wx.Icon` object. - - - - - - BitmapFromImage(Image image, int depth=-1) -> Bitmap - Creates bitmap object from a `wx.Image`. This has to be done to -actually display a `wx.Image` as you cannot draw an image directly on -a window. The resulting bitmap will use the provided colour depth (or -that of the current screen colour depth if depth is -1) which entails -that a colour reduction may have to take place. - - - - - - - BitmapFromXPMData(PyObject listOfStrings) -> Bitmap - Construct a Bitmap from a list of strings formatted as XPM data. - - - - - - BitmapFromBits(PyObject bits, int width, int height, int depth=1) -> Bitmap - Creates a bitmap from an array of bits. You should only use this -function for monochrome bitmaps (depth 1) in portable programs: in -this case the bits parameter should contain an XBM image. For other -bit depths, the behaviour is platform dependent. - - - - - - - - - __del__(self) - - - Ok(self) -> bool - - - GetWidth(self) -> int - Gets the width of the bitmap in pixels. - - - GetHeight(self) -> int - Gets the height of the bitmap in pixels. - - - GetDepth(self) -> int - Gets the colour depth of the bitmap. A value of 1 indicates a -monochrome bitmap. - - - GetSize(self) -> Size - Get the size of the bitmap. - - - ConvertToImage(self) -> Image - Creates a platform-independent image from a platform-dependent -bitmap. This preserves mask information so that bitmaps and images can -be converted back and forth without loss in that respect. - - - GetMask(self) -> Mask - Gets the associated mask (if any) which may have been loaded from a -file or explpicitly set for the bitmap. - -:see: `SetMask`, `wx.Mask` - - - - SetMask(self, Mask mask) - Sets the mask for this bitmap. - -:see: `GetMask`, `wx.Mask` - - - - - - - SetMaskColour(self, Colour colour) - Create a Mask based on a specified colour in the Bitmap. - - - - - - GetSubBitmap(self, Rect rect) -> Bitmap - Returns a sub-bitmap of the current one as long as the rect belongs -entirely to the bitmap. This function preserves bit depth and mask -information. - - - - - - SaveFile(self, String name, int type, Palette palette=None) -> bool - Saves a bitmap in the named file. See `__init__` for a description of -the ``type`` parameter. - - - - - - - - LoadFile(self, String name, int type) -> bool - Loads a bitmap from a file. See `__init__` for a description of the -``type`` parameter. - - - - - - - CopyFromIcon(self, Icon icon) -> bool - - - - - - SetHeight(self, int height) - Set the height property (does not affect the existing bitmap data). - - - - - - SetWidth(self, int width) - Set the width property (does not affect the existing bitmap data). - - - - - - SetDepth(self, int depth) - Set the depth property (does not affect the existing bitmap data). - - - - - - SetSize(self, Size size) - Set the bitmap size (does not affect the existing bitmap data). - - - - - - __eq__(self, Bitmap other) -> bool - - - - - - __ne__(self, Bitmap other) -> bool - - - - - - - This class encapsulates a monochrome mask bitmap, where the masked -area is black and the unmasked area is white. When associated with a -bitmap and drawn in a device context, the unmasked area of the bitmap -will be drawn, and the masked area will not be drawn. - -A mask may be associated with a `wx.Bitmap`. It is used in -`wx.DC.DrawBitmap` or `wx.DC.Blit` when the source device context is a -`wx.MemoryDC` with a `wx.Bitmap` selected into it that contains a -mask. - - - __init__(self, Bitmap bitmap, Colour colour=NullColour) -> Mask - Constructs a mask from a `wx.Bitmap` and a `wx.Colour` in that bitmap -that indicates the transparent portions of the mask. In other words, -the pixels in ``bitmap`` that match ``colour`` will be the transparent -portions of the mask. If no ``colour`` or an invalid ``colour`` is -passed then BLACK is used. - -:see: `wx.Bitmap`, `wx.Colour` - - - - - - - MaskColour = wx._deprecated(Mask, "wx.MaskColour is deprecated, use `wx.Mask` instead.") - - - - __init__(self, String name, int type, int desiredWidth=-1, int desiredHeight=-1) -> Icon - - - - - - - - - EmptyIcon() -> Icon - - - IconFromLocation(IconLocation loc) -> Icon - - - - - - IconFromBitmap(Bitmap bmp) -> Icon - - - - - - IconFromXPMData(PyObject listOfStrings) -> Icon - - - - - - __del__(self) - - - LoadFile(self, String name, int type) -> bool - - - - - - - Ok(self) -> bool - - - GetWidth(self) -> int - - - GetHeight(self) -> int - - - GetDepth(self) -> int - - - SetWidth(self, int w) - - - - - - SetHeight(self, int h) - - - - - - SetDepth(self, int d) - - - - - - CopyFromBitmap(self, Bitmap bmp) - - - - - - - - __init__(self, String filename=&wxPyEmptyString, int num=0) -> IconLocation - - - - - - - __del__(self) - - - IsOk(self) -> bool - - - SetFileName(self, String filename) - - - - - - GetFileName(self) -> String - - - SetIndex(self, int num) - - - - - - GetIndex(self) -> int - - - - - __init__(self) -> IconBundle - - - IconBundleFromFile(String file, long type) -> IconBundle - - - - - - - IconBundleFromIcon(Icon icon) -> IconBundle - - - - - - __del__(self) - - - AddIcon(self, Icon icon) - - - - - - AddIconFromFile(self, String file, long type) - - - - - - - GetIcon(self, Size size) -> Icon - - - - - - - A cursor is a small bitmap usually used for denoting where the mouse -pointer is, with a picture that might indicate the interpretation of a -mouse click. - -A single cursor object may be used in many windows (any subwindow -type). The wxWindows convention is to set the cursor for a window, as -in X, rather than to set it globally as in MS Windows, although a -global `wx.SetCursor` function is also available for use on MS Windows. - - -Stock Cursor IDs ------------------ - ======================== ====================================== - wx.CURSOR_ARROW A standard arrow cursor. - wx.CURSOR_RIGHT_ARROW A standard arrow cursor pointing to the right. - wx.CURSOR_BLANK Transparent cursor. - wx.CURSOR_BULLSEYE Bullseye cursor. - wx.CURSOR_CHAR Rectangular character cursor. - wx.CURSOR_CROSS A cross cursor. - wx.CURSOR_HAND A hand cursor. - wx.CURSOR_IBEAM An I-beam cursor (vertical line). - wx.CURSOR_LEFT_BUTTON Represents a mouse with the left button depressed. - wx.CURSOR_MAGNIFIER A magnifier icon. - wx.CURSOR_MIDDLE_BUTTON Represents a mouse with the middle button depressed. - wx.CURSOR_NO_ENTRY A no-entry sign cursor. - wx.CURSOR_PAINT_BRUSH A paintbrush cursor. - wx.CURSOR_PENCIL A pencil cursor. - wx.CURSOR_POINT_LEFT A cursor that points left. - wx.CURSOR_POINT_RIGHT A cursor that points right. - wx.CURSOR_QUESTION_ARROW An arrow and question mark. - wx.CURSOR_RIGHT_BUTTON Represents a mouse with the right button depressed. - wx.CURSOR_SIZENESW A sizing cursor pointing NE-SW. - wx.CURSOR_SIZENS A sizing cursor pointing N-S. - wx.CURSOR_SIZENWSE A sizing cursor pointing NW-SE. - wx.CURSOR_SIZEWE A sizing cursor pointing W-E. - wx.CURSOR_SIZING A general sizing cursor. - wx.CURSOR_SPRAYCAN A spraycan cursor. - wx.CURSOR_WAIT A wait cursor. - wx.CURSOR_WATCH A watch cursor. - wx.CURSOR_ARROWWAIT A cursor with both an arrow and an hourglass, (windows.) - ======================== ====================================== - - - - - __init__(self, String cursorName, long type, int hotSpotX=0, int hotSpotY=0) -> Cursor - Construct a Cursor from a file. Specify the type of file using -wx.BITAMP_TYPE* constants, and specify the hotspot if not using a cur -file. - -This constructor is not available on wxGTK, use ``wx.StockCursor``, -``wx.CursorFromImage``, or ``wx.CursorFromBits`` instead. - - - - - - - - - StockCursor(int id) -> Cursor - Create a cursor using one of the stock cursors. Note that not all -cursors are available on all platforms. - - - - - - CursorFromImage(Image image) -> Cursor - Constructs a cursor from a wxImage. The cursor is monochrome, colors -with the RGB elements all greater than 127 will be foreground, colors -less than this background. The mask (if any) will be used as -transparent. -In MSW the foreground will be white and the background -black. The cursor is resized to 32x32. - -In GTK, the two most frequent colors will be used for foreground and -background. The cursor will be displayed at the size of the image. - -On MacOS the cursor is resized to 16x16 and currently only shown as -black/white (mask respected). - - - - - - __del__(self) - - - Ok(self) -> bool - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int x=0, int y=0, int width=0, int height=0) -> Region - - - - - - - - - RegionFromBitmap(Bitmap bmp) -> Region - - - - - - RegionFromBitmapColour(Bitmap bmp, Colour transColour, int tolerance=0) -> Region - - - - - - - - RegionFromPoints(int points, Point points_array, int fillStyle=WINDING_RULE) -> Region - - - - - - - - __del__(self) - - - Clear(self) - - - Offset(self, int x, int y) -> bool - - - - - - - Contains(self, int x, int y) -> int - - - - - - - ContainsPoint(self, Point pt) -> int - - - - - - ContainsRect(self, Rect rect) -> int - - - - - - ContainsRectDim(self, int x, int y, int w, int h) -> int - - - - - - - - - GetBox(self) -> Rect - - - Intersect(self, int x, int y, int width, int height) -> bool - - - - - - - - - IntersectRect(self, Rect rect) -> bool - - - - - - IntersectRegion(self, Region region) -> bool - - - - - - IsEmpty(self) -> bool - - - Union(self, int x, int y, int width, int height) -> bool - - - - - - - - - UnionRect(self, Rect rect) -> bool - - - - - - UnionRegion(self, Region region) -> bool - - - - - - Subtract(self, int x, int y, int width, int height) -> bool - - - - - - - - - SubtractRect(self, Rect rect) -> bool - - - - - - SubtractRegion(self, Region region) -> bool - - - - - - Xor(self, int x, int y, int width, int height) -> bool - - - - - - - - - XorRect(self, Rect rect) -> bool - - - - - - XorRegion(self, Region region) -> bool - - - - - - ConvertToBitmap(self) -> Bitmap - - - UnionBitmap(self, Bitmap bmp) -> bool - - - - - - UnionBitmapColour(self, Bitmap bmp, Colour transColour, int tolerance=0) -> bool - - - - - - - - - - - __init__(self, Region region) -> RegionIterator - - - - - - __del__(self) - - - GetX(self) -> int - - - GetY(self) -> int - - - GetW(self) -> int - - - GetWidth(self) -> int - - - GetH(self) -> int - - - GetHeight(self) -> int - - - GetRect(self) -> Rect - - - HaveRects(self) -> bool - - - Reset(self) - - - Next(self) - - - __nonzero__(self) -> bool - - - -#--------------------------------------------------------------------------- - - -#--------------------------------------------------------------------------- - - - - __init__(self) -> NativeFontInfo - - - __del__(self) - - - Init(self) - - - InitFromFont(self, Font font) - - - - - - GetPointSize(self) -> int - - - GetStyle(self) -> int - - - GetWeight(self) -> int - - - GetUnderlined(self) -> bool - - - GetFaceName(self) -> String - - - GetFamily(self) -> int - - - GetEncoding(self) -> int - - - SetPointSize(self, int pointsize) - - - - - - SetStyle(self, int style) - - - - - - SetWeight(self, int weight) - - - - - - SetUnderlined(self, bool underlined) - - - - - - SetFaceName(self, String facename) - - - - - - SetFamily(self, int family) - - - - - - SetEncoding(self, int encoding) - - - - - - FromString(self, String s) -> bool - - - - - - ToString(self) -> String - - - __str__(self) -> String - - - FromUserString(self, String s) -> bool - - - - - - ToUserString(self) -> String - - - - - __init__(self) -> NativeEncodingInfo - - - __del__(self) - - - - - FromString(self, String s) -> bool - - - - - - ToString(self) -> String - - - - GetNativeFontEncoding(int encoding) -> NativeEncodingInfo - - - - - - TestFontEncoding(NativeEncodingInfo info) -> bool - - - - - -#--------------------------------------------------------------------------- - - - - __init__(self) -> FontMapper - - - __del__(self) - - - Get() -> FontMapper - - - Set(FontMapper mapper) -> FontMapper - - - - - - CharsetToEncoding(self, String charset, bool interactive=True) -> int - - - - - - - GetSupportedEncodingsCount() -> size_t - - - GetEncoding(size_t n) -> int - - - - - - GetEncodingName(int encoding) -> String - - - - - - GetEncodingDescription(int encoding) -> String - - - - - - GetEncodingFromName(String name) -> int - - - - - - SetConfig(self, ConfigBase config) - - - - - - SetConfigPath(self, String prefix) - - - - - - GetDefaultConfigPath() -> String - - - GetAltForEncoding(self, int encoding, String facename=EmptyString, bool interactive=True) -> PyObject - - - - - - - - IsEncodingAvailable(self, int encoding, String facename=EmptyString) -> bool - - - - - - - SetDialogParent(self, Window parent) - - - - - - SetDialogTitle(self, String title) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int pointSize, int family, int style, int weight, bool underline=False, - String face=EmptyString, - int encoding=FONTENCODING_DEFAULT) -> Font - - - - - - - - - - - - FontFromNativeInfo(NativeFontInfo info) -> Font - - - - - - FontFromNativeInfoString(String info) -> Font - - - - - - Font2(int pointSize, int family, int flags=FONTFLAG_DEFAULT, - String face=EmptyString, int encoding=FONTENCODING_DEFAULT) -> Font - - - - - - - - - - __del__(self) - - - Ok(self) -> bool - - - __eq__(self, Font other) -> bool - - - - - - __ne__(self, Font other) -> bool - - - - - - GetPointSize(self) -> int - - - GetFamily(self) -> int - - - GetStyle(self) -> int - - - GetWeight(self) -> int - - - GetUnderlined(self) -> bool - - - GetFaceName(self) -> String - - - GetEncoding(self) -> int - - - GetNativeFontInfo(self) -> NativeFontInfo - - - IsFixedWidth(self) -> bool - - - GetNativeFontInfoDesc(self) -> String - - - GetNativeFontInfoUserDesc(self) -> String - - - SetPointSize(self, int pointSize) - - - - - - SetFamily(self, int family) - - - - - - SetStyle(self, int style) - - - - - - SetWeight(self, int weight) - - - - - - SetFaceName(self, String faceName) - - - - - - SetUnderlined(self, bool underlined) - - - - - - SetEncoding(self, int encoding) - - - - - - SetNativeFontInfo(self, NativeFontInfo info) - - - - - - SetNativeFontInfoFromString(self, String info) - - - - - - SetNativeFontInfoUserDesc(self, String info) - - - - - - GetFamilyString(self) -> String - - - GetStyleString(self) -> String - - - GetWeightString(self) -> String - - - SetNoAntiAliasing(self, bool no=True) - - - - - - GetNoAntiAliasing(self) -> bool - - - GetDefaultEncoding() -> int - - - SetDefaultEncoding(int encoding) - - - - - - -#--------------------------------------------------------------------------- - - - - __init__(self) -> FontEnumerator - - - __del__(self) - - - _setCallbackInfo(self, PyObject self, PyObject _class, bool incref) - - - - - - - - EnumerateFacenames(self, int encoding=FONTENCODING_SYSTEM, bool fixedWidthOnly=False) -> bool - - - - - - - EnumerateEncodings(self, String facename=EmptyString) -> bool - - - - - - GetEncodings(self) -> PyObject - - - GetFacenames(self) -> PyObject - - - -#--------------------------------------------------------------------------- - - - - - - - - - __init__(self, int language=-1, int flags=wxLOCALE_LOAD_DEFAULT|wxLOCALE_CONV_ENCODING) -> Locale - - - - - - - __del__(self) - - - Init1(self, String szName, String szShort=EmptyString, String szLocale=EmptyString, - bool bLoadDefault=True, - bool bConvertEncoding=False) -> bool - - - - - - - - - - Init2(self, int language=LANGUAGE_DEFAULT, int flags=wxLOCALE_LOAD_DEFAULT|wxLOCALE_CONV_ENCODING) -> bool - - - - - - - GetSystemLanguage() -> int - - - GetSystemEncoding() -> int - - - GetSystemEncodingName() -> String - - - IsOk(self) -> bool - - - GetLocale(self) -> String - - - GetLanguage(self) -> int - - - GetSysName(self) -> String - - - GetCanonicalName(self) -> String - - - AddCatalogLookupPathPrefix(String prefix) - - - - - - AddCatalog(self, String szDomain) -> bool - - - - - - IsLoaded(self, String szDomain) -> bool - - - - - - GetLanguageInfo(int lang) -> LanguageInfo - - - - - - GetLanguageName(int lang) -> String - - - - - - FindLanguageInfo(String locale) -> LanguageInfo - - - - - - AddLanguage(LanguageInfo info) - - - - - - GetString(self, String szOrigString, String szDomain=EmptyString) -> String - - - - - - - GetName(self) -> String - - - - GetLocale() -> Locale - - - - - - - - GetTranslation(String str) -> String -GetTranslation(String str, String strPlural, size_t n) -> String - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> EncodingConverter - - - __del__(self) - - - Init(self, int input_enc, int output_enc, int method=CONVERT_STRICT) -> bool - - - - - - - - Convert(self, String input) -> String - - - - - - GetPlatformEquivalents(int enc, int platform=PLATFORM_CURRENT) -> wxFontEncodingArray - - - - - - - GetAllEquivalents(int enc) -> wxFontEncodingArray - - - - - - CanConvert(int encIn, int encOut) -> bool - - - - - - - #---------------------------------------------------------------------------- -# On MSW add the directory where the wxWidgets catalogs were installed -# to the default catalog path. -if wx.Platform == "__WXMSW__": - import os - localedir = os.path.join(os.path.split(__file__)[0], "locale") - Locale_AddCatalogLookupPathPrefix(localedir) - del os - -#---------------------------------------------------------------------------- - - -#--------------------------------------------------------------------------- - - - A wx.DC is a device context onto which graphics and text can be -drawn. It is intended to represent a number of output devices in a -generic way, so a window can have a device context associated with it, -and a printer also has a device context. In this way, the same piece -of code may write to a number of different devices, if the device -context is used as a parameter. - -Derived types of wxDC have documentation for specific features only, -so refer to this section for most device context information. - -The wx.DC class is abstract and can not be instantiated, you must use -one of the derived classes instead. Which one will depend on the -situation in which it is used. - - - __del__(self) - - - BeginDrawing(self) - Allows for optimization of drawing code on platforms that need it. On -other platforms this is just an empty function and is harmless. To -take advantage of this postential optimization simply enclose each -group of calls to the drawing primitives within calls to -`BeginDrawing` and `EndDrawing`. - - - EndDrawing(self) - Ends the group of drawing primitives started with `BeginDrawing`, and -invokes whatever optimization is available for this DC type on the -current platform. - - - FloodFill(self, int x, int y, Colour col, int style=FLOOD_SURFACE) -> bool - Flood fills the device context starting from the given point, using -the current brush colour, and using a style: - - - **wxFLOOD_SURFACE**: the flooding occurs until a colour other than - the given colour is encountered. - - - **wxFLOOD_BORDER**: the area to be flooded is bounded by the given - colour. - -Returns False if the operation failed. - -Note: The present implementation for non-Windows platforms may fail to -find colour borders if the pixels do not match the colour -exactly. However the function will still return true. - - - - - - - - - FloodFillPoint(self, Point pt, Colour col, int style=FLOOD_SURFACE) -> bool - Flood fills the device context starting from the given point, using -the current brush colour, and using a style: - - - **wxFLOOD_SURFACE**: the flooding occurs until a colour other than - the given colour is encountered. - - - **wxFLOOD_BORDER**: the area to be flooded is bounded by the given - colour. - -Returns False if the operation failed. - -Note: The present implementation for non-Windows platforms may fail to -find colour borders if the pixels do not match the colour -exactly. However the function will still return true. - - - - - - - - GetPixel(self, int x, int y) -> Colour - Gets the colour at the specified location on the DC. - - - - - - - GetPixelPoint(self, Point pt) -> Colour - - - - - - DrawLine(self, int x1, int y1, int x2, int y2) - Draws a line from the first point to the second. The current pen is -used for drawing the line. Note that the second point is *not* part of -the line and is not drawn by this function (this is consistent with -the behaviour of many other toolkits). - - - - - - - - - DrawLinePoint(self, Point pt1, Point pt2) - Draws a line from the first point to the second. The current pen is -used for drawing the line. Note that the second point is *not* part of -the line and is not drawn by this function (this is consistent with -the behaviour of many other toolkits). - - - - - - - CrossHair(self, int x, int y) - Displays a cross hair using the current pen. This is a vertical and -horizontal line the height and width of the window, centred on the -given point. - - - - - - - CrossHairPoint(self, Point pt) - Displays a cross hair using the current pen. This is a vertical and -horizontal line the height and width of the window, centred on the -given point. - - - - - - DrawArc(self, int x1, int y1, int x2, int y2, int xc, int yc) - Draws an arc of a circle, centred on the *center* point (xc, yc), from -the first point to the second. The current pen is used for the outline -and the current brush for filling the shape. - -The arc is drawn in an anticlockwise direction from the start point to -the end point. - - - - - - - - - - - DrawArcPoint(self, Point pt1, Point pt2, Point center) - Draws an arc of a circle, centred on the *center* point (xc, yc), from -the first point to the second. The current pen is used for the outline -and the current brush for filling the shape. - -The arc is drawn in an anticlockwise direction from the start point to -the end point. - - - - - - - - DrawCheckMark(self, int x, int y, int width, int height) - Draws a check mark inside the given rectangle. - - - - - - - - - DrawCheckMarkRect(self, Rect rect) - Draws a check mark inside the given rectangle. - - - - - - DrawEllipticArc(self, int x, int y, int w, int h, double start, double end) - Draws an arc of an ellipse, with the given rectangle defining the -bounds of the ellipse. The current pen is used for drawing the arc and -the current brush is used for drawing the pie. - -The *start* and *end* parameters specify the start and end of the arc -relative to the three-o'clock position from the center of the -rectangle. Angles are specified in degrees (360 is a complete -circle). Positive values mean counter-clockwise motion. If start is -equal to end, a complete ellipse will be drawn. - - - - - - - - - - - DrawEllipticArcPointSize(self, Point pt, Size sz, double start, double end) - Draws an arc of an ellipse, with the given rectangle defining the -bounds of the ellipse. The current pen is used for drawing the arc and -the current brush is used for drawing the pie. - -The *start* and *end* parameters specify the start and end of the arc -relative to the three-o'clock position from the center of the -rectangle. Angles are specified in degrees (360 is a complete -circle). Positive values mean counter-clockwise motion. If start is -equal to end, a complete ellipse will be drawn. - - - - - - - - - DrawPoint(self, int x, int y) - Draws a point using the current pen. - - - - - - - DrawPointPoint(self, Point pt) - Draws a point using the current pen. - - - - - - DrawRectangle(self, int x, int y, int width, int height) - Draws a rectangle with the given top left corner, and with the given -size. The current pen is used for the outline and the current brush -for filling the shape. - - - - - - - - - DrawRectangleRect(self, Rect rect) - Draws a rectangle with the given top left corner, and with the given -size. The current pen is used for the outline and the current brush -for filling the shape. - - - - - - DrawRectanglePointSize(self, Point pt, Size sz) - Draws a rectangle with the given top left corner, and with the given -size. The current pen is used for the outline and the current brush -for filling the shape. - - - - - - - DrawRoundedRectangle(self, int x, int y, int width, int height, double radius) - Draws a rectangle with the given top left corner, and with the given -size. The corners are quarter-circles using the given radius. The -current pen is used for the outline and the current brush for filling -the shape. - -If radius is positive, the value is assumed to be the radius of the -rounded corner. If radius is negative, the absolute value is assumed -to be the proportion of the smallest dimension of the rectangle. This -means that the corner can be a sensible size relative to the size of -the rectangle, and also avoids the strange effects X produces when the -corners are too big for the rectangle. - - - - - - - - - - DrawRoundedRectangleRect(self, Rect r, double radius) - Draws a rectangle with the given top left corner, and with the given -size. The corners are quarter-circles using the given radius. The -current pen is used for the outline and the current brush for filling -the shape. - -If radius is positive, the value is assumed to be the radius of the -rounded corner. If radius is negative, the absolute value is assumed -to be the proportion of the smallest dimension of the rectangle. This -means that the corner can be a sensible size relative to the size of -the rectangle, and also avoids the strange effects X produces when the -corners are too big for the rectangle. - - - - - - - DrawRoundedRectanglePointSize(self, Point pt, Size sz, double radius) - Draws a rectangle with the given top left corner, and with the given -size. The corners are quarter-circles using the given radius. The -current pen is used for the outline and the current brush for filling -the shape. - -If radius is positive, the value is assumed to be the radius of the -rounded corner. If radius is negative, the absolute value is assumed -to be the proportion of the smallest dimension of the rectangle. This -means that the corner can be a sensible size relative to the size of -the rectangle, and also avoids the strange effects X produces when the -corners are too big for the rectangle. - - - - - - - - DrawCircle(self, int x, int y, int radius) - Draws a circle with the given center point and radius. The current -pen is used for the outline and the current brush for filling the -shape. - -:see: `DrawEllipse` - - - - - - - - DrawCirclePoint(self, Point pt, int radius) - Draws a circle with the given center point and radius. The current -pen is used for the outline and the current brush for filling the -shape. - -:see: `DrawEllipse` - - - - - - - DrawEllipse(self, int x, int y, int width, int height) - Draws an ellipse contained in the specified rectangle. The current pen -is used for the outline and the current brush for filling the shape. - -:see: `DrawCircle` - - - - - - - - - DrawEllipseRect(self, Rect rect) - Draws an ellipse contained in the specified rectangle. The current pen -is used for the outline and the current brush for filling the shape. - -:see: `DrawCircle` - - - - - - DrawEllipsePointSize(self, Point pt, Size sz) - Draws an ellipse contained in the specified rectangle. The current pen -is used for the outline and the current brush for filling the shape. - -:see: `DrawCircle` - - - - - - - DrawIcon(self, Icon icon, int x, int y) - Draw an icon on the display (does nothing if the device context is -PostScript). This can be the simplest way of drawing bitmaps on a -window. - - - - - - - - DrawIconPoint(self, Icon icon, Point pt) - Draw an icon on the display (does nothing if the device context is -PostScript). This can be the simplest way of drawing bitmaps on a -window. - - - - - - - DrawBitmap(self, Bitmap bmp, int x, int y, bool useMask=False) - Draw a bitmap on the device context at the specified point. If -*transparent* is true and the bitmap has a transparency mask, (or -alpha channel on the platforms that support it) then the bitmap will -be drawn transparently. - -When drawing a mono-bitmap, the current text foreground colour will be -used to draw the foreground of the bitmap (all bits set to 1), and the -current text background colour to draw the background (all bits set to -0). - -:see: `SetTextForeground`, `SetTextBackground` and `wx.MemoryDC` - - - - - - - - - DrawBitmapPoint(self, Bitmap bmp, Point pt, bool useMask=False) - Draw a bitmap on the device context at the specified point. If -*transparent* is true and the bitmap has a transparency mask, (or -alpha channel on the platforms that support it) then the bitmap will -be drawn transparently. - -When drawing a mono-bitmap, the current text foreground colour will be -used to draw the foreground of the bitmap (all bits set to 1), and the -current text background colour to draw the background (all bits set to -0). - -:see: `SetTextForeground`, `SetTextBackground` and `wx.MemoryDC` - - - - - - - - DrawText(self, String text, int x, int y) - Draws a text string at the specified point, using the current text -font, and the current text foreground and background colours. - -The coordinates refer to the top-left corner of the rectangle bounding -the string. See `GetTextExtent` for how to get the dimensions of a -text string, which can be used to position the text more precisely. - -**NOTE**: under wxGTK the current logical function is used by this -function but it is ignored by wxMSW. Thus, you should avoid using -logical functions with this function in portable programs. - -:see: `DrawRotatedText` - - - - - - - - DrawTextPoint(self, String text, Point pt) - Draws a text string at the specified point, using the current text -font, and the current text foreground and background colours. - -The coordinates refer to the top-left corner of the rectangle bounding -the string. See `GetTextExtent` for how to get the dimensions of a -text string, which can be used to position the text more precisely. - -**NOTE**: under wxGTK the current logical function is used by this -function but it is ignored by wxMSW. Thus, you should avoid using -logical functions with this function in portable programs. - -:see: `DrawRotatedText` - - - - - - - DrawRotatedText(self, String text, int x, int y, double angle) - Draws the text rotated by *angle* degrees, if supported by the platform. - -**NOTE**: Under Win9x only TrueType fonts can be drawn by this -function. In particular, a font different from ``wx.NORMAL_FONT`` -should be used as the it is not normally a TrueType -font. ``wx.SWISS_FONT`` is an example of a font which is. - -:see: `DrawText` - - - - - - - - - DrawRotatedTextPoint(self, String text, Point pt, double angle) - Draws the text rotated by *angle* degrees, if supported by the platform. - -**NOTE**: Under Win9x only TrueType fonts can be drawn by this -function. In particular, a font different from ``wx.NORMAL_FONT`` -should be used as the it is not normally a TrueType -font. ``wx.SWISS_FONT`` is an example of a font which is. - -:see: `DrawText` - - - - - - - - Blit(self, int xdest, int ydest, int width, int height, DC source, - int xsrc, int ysrc, int rop=COPY, bool useMask=False, - int xsrcMask=-1, int ysrcMask=-1) -> bool - Copy from a source DC to this DC. Parameters specify the destination -coordinates, size of area to copy, source DC, source coordinates, -logical function, whether to use a bitmap mask, and mask source -position. - - :param xdest: Destination device context x position. - :param ydest: Destination device context y position. - :param width: Width of source area to be copied. - :param height: Height of source area to be copied. - :param source: Source device context. - :param xsrc: Source device context x position. - :param ysrc: Source device context y position. - :param rop: Logical function to use: see `SetLogicalFunction`. - :param useMask: If true, Blit does a transparent blit using the mask - that is associated with the bitmap selected into the - source device context. - :param xsrcMask: Source x position on the mask. If both xsrcMask and - ysrcMask are -1, xsrc and ysrc will be assumed for - the mask source position. - :param ysrcMask: Source y position on the mask. - - - - - - - - - - - - - - - - - BlitPointSize(self, Point destPt, Size sz, DC source, Point srcPt, int rop=COPY, - bool useMask=False, Point srcPtMask=DefaultPosition) -> bool - Copy from a source DC to this DC. Parameters specify the destination -coordinates, size of area to copy, source DC, source coordinates, -logical function, whether to use a bitmap mask, and mask source -position. - - :param destPt: Destination device context position. - :param sz: Size of source area to be copied. - :param source: Source device context. - :param srcPt: Source device context position. - :param rop: Logical function to use: see `SetLogicalFunction`. - :param useMask: If true, Blit does a transparent blit using the mask - that is associated with the bitmap selected into the - source device context. - :param srcPtMask: Source position on the mask. - - - - - - - - - - - - - SetClippingRegion(self, int x, int y, int width, int height) - Sets the clipping region for this device context to the intersection -of the given region described by the parameters of this method and the -previously set clipping region. You should call `DestroyClippingRegion` -if you want to set the clipping region exactly to the region -specified. - -The clipping region is an area to which drawing is -restricted. Possible uses for the clipping region are for clipping -text or for speeding up window redraws when only a known area of the -screen is damaged. - -:see: `DestroyClippingRegion`, `wx.Region` - - - - - - - - - SetClippingRegionPointSize(self, Point pt, Size sz) - Sets the clipping region for this device context to the intersection -of the given region described by the parameters of this method and the -previously set clipping region. You should call `DestroyClippingRegion` -if you want to set the clipping region exactly to the region -specified. - -The clipping region is an area to which drawing is -restricted. Possible uses for the clipping region are for clipping -text or for speeding up window redraws when only a known area of the -screen is damaged. - -:see: `DestroyClippingRegion`, `wx.Region` - - - - - - - SetClippingRegionAsRegion(self, Region region) - Sets the clipping region for this device context to the intersection -of the given region described by the parameters of this method and the -previously set clipping region. You should call `DestroyClippingRegion` -if you want to set the clipping region exactly to the region -specified. - -The clipping region is an area to which drawing is -restricted. Possible uses for the clipping region are for clipping -text or for speeding up window redraws when only a known area of the -screen is damaged. - -:see: `DestroyClippingRegion`, `wx.Region` - - - - - - SetClippingRect(self, Rect rect) - Sets the clipping region for this device context to the intersection -of the given region described by the parameters of this method and the -previously set clipping region. You should call `DestroyClippingRegion` -if you want to set the clipping region exactly to the region -specified. - -The clipping region is an area to which drawing is -restricted. Possible uses for the clipping region are for clipping -text or for speeding up window redraws when only a known area of the -screen is damaged. - -:see: `DestroyClippingRegion`, `wx.Region` - - - - - - DrawLines(self, List points, int xoffset=0, int yoffset=0) - Draws lines using a sequence of `wx.Point` objects, adding the -optional offset coordinate. The current pen is used for drawing the -lines. - - - - - - - - - DrawPolygon(self, List points, int xoffset=0, int yoffset=0, - int fillStyle=ODDEVEN_RULE) - Draws a filled polygon using a sequence of `wx.Point` objects, adding -the optional offset coordinate. The last argument specifies the fill -rule: ``wx.ODDEVEN_RULE`` (the default) or ``wx.WINDING_RULE``. - -The current pen is used for drawing the outline, and the current brush -for filling the shape. Using a transparent brush suppresses -filling. Note that wxWidgets automatically closes the first and last -points. - - - - - - - - - - DrawLabel(self, String text, Rect rect, int alignment=wxALIGN_LEFT|wxALIGN_TOP, - int indexAccel=-1) - Draw *text* within the specified rectangle, abiding by the alignment -flags. Will additionally emphasize the character at *indexAccel* if -it is not -1. - -:see: `DrawImageLabel` - - - - - - - - - DrawImageLabel(self, String text, Bitmap image, Rect rect, int alignment=wxALIGN_LEFT|wxALIGN_TOP, - int indexAccel=-1) -> Rect - Draw *text* and an image (which may be ``wx.NullBitmap`` to skip -drawing it) within the specified rectangle, abiding by the alignment -flags. Will additionally emphasize the character at *indexAccel* if -it is not -1. Returns the bounding rectangle. - - - - - - - - - - DrawSpline(self, List points) - Draws a spline between all given control points, (a list of `wx.Point` -objects) using the current pen. The spline is drawn using a series of -lines, using an algorithm taken from the X drawing program 'XFIG'. - - - - - - - Clear(self) - Clears the device context using the current background brush. - - - StartDoc(self, String message) -> bool - Starts a document (only relevant when outputting to a -printer). *Message* is a message to show whilst printing. - - - - - - EndDoc(self) - Ends a document (only relevant when outputting to a printer). - - - StartPage(self) - Starts a document page (only relevant when outputting to a printer). - - - EndPage(self) - Ends a document page (only relevant when outputting to a printer). - - - SetFont(self, Font font) - Sets the current font for the DC. It must be a valid font, in -particular you should not pass ``wx.NullFont`` to this method. - -:see: `wx.Font` - - - - - - SetPen(self, Pen pen) - Sets the current pen for the DC. - -If the argument is ``wx.NullPen``, the current pen is selected out of the -device context, and the original pen restored. - -:see: `wx.Pen` - - - - - - SetBrush(self, Brush brush) - Sets the current brush for the DC. - -If the argument is ``wx.NullBrush``, the current brush is selected out -of the device context, and the original brush restored, allowing the -current brush to be destroyed safely. - -:see: `wx.Brush` - - - - - - SetBackground(self, Brush brush) - Sets the current background brush for the DC. - - - - - - SetBackgroundMode(self, int mode) - *mode* may be one of ``wx.SOLID`` and ``wx.TRANSPARENT``. This setting -determines whether text will be drawn with a background colour or -not. - - - - - - SetPalette(self, Palette palette) - If this is a window DC or memory DC, assigns the given palette to the -window or bitmap associated with the DC. If the argument is -``wx.NullPalette``, the current palette is selected out of the device -context, and the original palette restored. - -:see: `wx.Palette` - - - - - - DestroyClippingRegion(self) - Destroys the current clipping region so that none of the DC is -clipped. - -:see: `SetClippingRegion` - - - GetClippingBox() -> (x, y, width, height) - Gets the rectangle surrounding the current clipping region. - - - - - - - - - GetClippingRect(self) -> Rect - Gets the rectangle surrounding the current clipping region. - - - GetCharHeight(self) -> int - Gets the character height of the currently set font. - - - GetCharWidth(self) -> int - Gets the average character width of the currently set font. - - - GetTextExtent(wxString string) -> (width, height) - Get the width and height of the text using the current font. Only -works for single line strings. - - - - - - - - GetFullTextExtent(wxString string, Font font=None) -> - (width, height, descent, externalLeading) - Get the width, height, decent and leading of the text using the -current or specified font. Only works for single line strings. - - - - - - - - - - - GetMultiLineTextExtent(wxString string, Font font=None) -> - (width, height, descent, externalLeading) - Get the width, height, decent and leading of the text using the -current or specified font. Works for single as well as multi-line -strings. - - - - - - - - - - GetPartialTextExtents(self, text) -> [widths] - Returns a list of integers such that each value is the distance in -pixels from the begining of text to the coresponding character of -*text*. The generic version simply builds a running total of the widths -of each character using GetTextExtent, however if the various -platforms have a native API function that is faster or more accurate -than the generic implementation then it will be used instead. - - - - - - GetSize(self) -> Size - This gets the horizontal and vertical resolution in device units. It -can be used to scale graphics to fit the page. For example, if *maxX* -and *maxY* represent the maximum horizontal and vertical 'pixel' values -used in your application, the following code will scale the graphic to -fit on the printer page:: - - w, h = dc.GetSize() - scaleX = maxX*1.0 / w - scaleY = maxY*1.0 / h - dc.SetUserScale(min(scaleX,scaleY),min(scaleX,scaleY)) - - - - GetSizeTuple() -> (width, height) - This gets the horizontal and vertical resolution in device units. It -can be used to scale graphics to fit the page. For example, if *maxX* -and *maxY* represent the maximum horizontal and vertical 'pixel' values -used in your application, the following code will scale the graphic to -fit on the printer page:: - - w, h = dc.GetSize() - scaleX = maxX*1.0 / w - scaleY = maxY*1.0 / h - dc.SetUserScale(min(scaleX,scaleY),min(scaleX,scaleY)) - - - - - - - - GetSizeMM(self) -> Size - Get the DC size in milimeters. - - - GetSizeMMTuple() -> (width, height) - Get the DC size in milimeters. - - - - - - - DeviceToLogicalX(self, int x) -> int - Convert device X coordinate to logical coordinate, using the current -mapping mode. - - - - - - DeviceToLogicalY(self, int y) -> int - Converts device Y coordinate to logical coordinate, using the current -mapping mode. - - - - - - DeviceToLogicalXRel(self, int x) -> int - Convert device X coordinate to relative logical coordinate, using the -current mapping mode but ignoring the x axis orientation. Use this -function for converting a width, for example. - - - - - - DeviceToLogicalYRel(self, int y) -> int - Convert device Y coordinate to relative logical coordinate, using the -current mapping mode but ignoring the y axis orientation. Use this -function for converting a height, for example. - - - - - - LogicalToDeviceX(self, int x) -> int - Converts logical X coordinate to device coordinate, using the current -mapping mode. - - - - - - LogicalToDeviceY(self, int y) -> int - Converts logical Y coordinate to device coordinate, using the current -mapping mode. - - - - - - LogicalToDeviceXRel(self, int x) -> int - Converts logical X coordinate to relative device coordinate, using the -current mapping mode but ignoring the x axis orientation. Use this for -converting a width, for example. - - - - - - LogicalToDeviceYRel(self, int y) -> int - Converts logical Y coordinate to relative device coordinate, using the -current mapping mode but ignoring the y axis orientation. Use this for -converting a height, for example. - - - - - - CanDrawBitmap(self) -> bool - - - CanGetTextExtent(self) -> bool - - - GetDepth(self) -> int - Returns the colour depth of the DC. - - - GetPPI(self) -> Size - Resolution in Pixels per inch - - - Ok(self) -> bool - Returns true if the DC is ok to use. - - - GetBackgroundMode(self) -> int - Returns the current background mode, either ``wx.SOLID`` or -``wx.TRANSPARENT``. - -:see: `SetBackgroundMode` - - - GetBackground(self) -> Brush - Gets the brush used for painting the background. - -:see: `SetBackground` - - - GetBrush(self) -> Brush - Gets the current brush - - - GetFont(self) -> Font - Gets the current font - - - GetPen(self) -> Pen - Gets the current pen - - - GetTextBackground(self) -> Colour - Gets the current text background colour - - - GetTextForeground(self) -> Colour - Gets the current text foreground colour - - - SetTextForeground(self, Colour colour) - Sets the current text foreground colour for the DC. - - - - - - SetTextBackground(self, Colour colour) - Sets the current text background colour for the DC. - - - - - - GetMapMode(self) -> int - Gets the current *mapping mode* for the device context - - - SetMapMode(self, int mode) - The *mapping mode* of the device context defines the unit of -measurement used to convert logical units to device units. The -mapping mode can be one of the following: - - ================ ============================================= - wx.MM_TWIPS Each logical unit is 1/20 of a point, or 1/1440 - of an inch. - wx.MM_POINTS Each logical unit is a point, or 1/72 of an inch. - wx.MM_METRIC Each logical unit is 1 mm. - wx.MM_LOMETRIC Each logical unit is 1/10 of a mm. - wx.MM_TEXT Each logical unit is 1 pixel. - ================ ============================================= - -Note that in X, text drawing isn't handled consistently with the -mapping mode; a font is always specified in point size. However, -setting the user scale (see `SetUserScale`) scales the text -appropriately. In Windows, scalable TrueType fonts are always used; in -X, results depend on availability of fonts, but usually a reasonable -match is found. - -The coordinate origin is always at the top left of the screen/printer. - -Drawing to a Windows printer device context uses the current mapping -mode, but mapping mode is currently ignored for PostScript output. - - - - - - - GetUserScale(self) -> (xScale, yScale) - Gets the current user scale factor (set by `SetUserScale`). - - - - - - - SetUserScale(self, double x, double y) - Sets the user scaling factor, useful for applications which require -'zooming'. - - - - - - - GetLogicalScale() -> (xScale, yScale) - - - - - - - SetLogicalScale(self, double x, double y) - - - - - - - GetLogicalOrigin(self) -> Point - - - GetLogicalOriginTuple() -> (x,y) - - - - - - - SetLogicalOrigin(self, int x, int y) - - - - - - - SetLogicalOriginPoint(self, Point point) - - - - - - GetDeviceOrigin(self) -> Point - - - GetDeviceOriginTuple() -> (x,y) - - - - - - - SetDeviceOrigin(self, int x, int y) - - - - - - - SetDeviceOriginPoint(self, Point point) - - - - - - SetAxisOrientation(self, bool xLeftRight, bool yBottomUp) - Sets the x and y axis orientation (i.e., the direction from lowest to -highest values on the axis). The default orientation is the natural -orientation, e.g. x axis from left to right and y axis from bottom up. - - - - - - - GetLogicalFunction(self) -> int - Gets the current logical function (set by `SetLogicalFunction`). - - - SetLogicalFunction(self, int function) - Sets the current logical function for the device context. This -determines how a source pixel (from a pen or brush colour, or source -device context if using `Blit`) combines with a destination pixel in -the current device context. - -The possible values and their meaning in terms of source and -destination pixel values are as follows: - - ================ ========================== - wx.AND src AND dst - wx.AND_INVERT (NOT src) AND dst - wx.AND_REVERSE src AND (NOT dst) - wx.CLEAR 0 - wx.COPY src - wx.EQUIV (NOT src) XOR dst - wx.INVERT NOT dst - wx.NAND (NOT src) OR (NOT dst) - wx.NOR (NOT src) AND (NOT dst) - wx.NO_OP dst - wx.OR src OR dst - wx.OR_INVERT (NOT src) OR dst - wx.OR_REVERSE src OR (NOT dst) - wx.SET 1 - wx.SRC_INVERT NOT src - wx.XOR src XOR dst - ================ ========================== - -The default is wx.COPY, which simply draws with the current -colour. The others combine the current colour and the background using -a logical operation. wx.INVERT is commonly used for drawing rubber -bands or moving outlines, since drawing twice reverts to the original -colour. - - - - - - - SetOptimization(self, bool optimize) - If *optimize* is true this function sets optimization mode on. This -currently means that under X, the device context will not try to set a -pen or brush property if it is known to be set already. This approach -can fall down if non-wxWidgets code is using the same device context -or window, for example when the window is a panel on which the -windowing system draws panel items. The wxWidgets device context -'memory' will now be out of step with reality. - -Setting optimization off, drawing, then setting it back on again, is a -trick that must occasionally be employed. - - - - - - GetOptimization(self) -> bool - Returns true if device context optimization is on. See -`SetOptimization` for . - - - CalcBoundingBox(self, int x, int y) - Adds the specified point to the bounding box which can be retrieved -with `MinX`, `MaxX` and `MinY`, `MaxY` or `GetBoundingBox` functions. - - - - - - - CalcBoundingBoxPoint(self, Point point) - Adds the specified point to the bounding box which can be retrieved -with `MinX`, `MaxX` and `MinY`, `MaxY` or `GetBoundingBox` functions. - - - - - - ResetBoundingBox(self) - Resets the bounding box: after a call to this function, the bounding -box doesn't contain anything. - - - MinX(self) -> int - Gets the minimum horizontal extent used in drawing commands so far. - - - MaxX(self) -> int - Gets the maximum horizontal extent used in drawing commands so far. - - - MinY(self) -> int - Gets the minimum vertical extent used in drawing commands so far. - - - MaxY(self) -> int - Gets the maximum vertical extent used in drawing commands so far. - - - GetBoundingBox() -> (x1,y1, x2,y2) - Returns the min and max points used in drawing commands so far. - - - - - - - - - _DrawPointList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject - - - - - - - - _DrawLineList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject - - - - - - - - _DrawRectangleList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject - - - - - - - - _DrawEllipseList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject - - - - - - - - _DrawPolygonList(self, PyObject pyCoords, PyObject pyPens, PyObject pyBrushes) -> PyObject - - - - - - - - _DrawTextList(self, PyObject textList, PyObject pyPoints, PyObject foregroundList, - PyObject backgroundList) -> PyObject - - - - - - - - - -#--------------------------------------------------------------------------- - - - A memory device context provides a means to draw graphics onto a -bitmap. A bitmap must be selected into the new memory DC before it may -be used for anything. Typical usage is as follows:: - - dc = wx.MemoryDC() - dc.SelectObject(bitmap) - # draw on the dc usign any of the Draw methods - dc.SelectObject(wx.NullBitmap) - # the bitmap now contains wahtever was drawn upon it - -Note that the memory DC *must* be deleted (or the bitmap selected out -of it) before a bitmap can be reselected into another memory DC. - - - - __init__(self) -> MemoryDC - Constructs a new memory device context. - -Use the Ok member to test whether the constructor was successful in -creating a usable device context. Don't forget to select a bitmap into -the DC before drawing on it. - -:see: `MemoryDCFromDC` - - - MemoryDCFromDC(DC oldDC) -> MemoryDC - Creates a DC that is compatible with the oldDC. - - - - - - SelectObject(self, Bitmap bitmap) - Selects the bitmap into the device context, to use as the memory -bitmap. Selecting the bitmap into a memory DC allows you to draw into -the DC, and therefore the bitmap, and also to use Blit to copy the -bitmap to a window. - -If the argument is wx.NullBitmap (or some other uninitialised -`wx.Bitmap`) the current bitmap is selected out of the device context, -and the original bitmap restored, allowing the current bitmap to be -destroyed safely. - - - - - - -#--------------------------------------------------------------------------- - - - This simple class provides a simple way to avoid flicker: when drawing -on it, everything is in fact first drawn on an in-memory buffer (a -`wx.Bitmap`) and then copied to the screen only once, when this object -is destroyed. - -It can be used in the same way as any other device -context. wx.BufferedDC itself typically replaces `wx.ClientDC`, if you -want to use it in your EVT_PAINT handler, you should look at -`wx.BufferedPaintDC`. - - - - Constructs a buffered DC. - - :param dc: The underlying DC: everything drawn to this object will - be flushed to this DC when this object is destroyed. You may - pass ``None`` in order to just initialize the buffer, and not - flush it. - - :param buffer: If a `wx.Size` object is passed as the 2nd arg then - it is the size of the bitmap that will be created internally - and used for an implicit buffer. If the 2nd arg is a - `wx.Bitmap` then it is the explicit buffer that will be - used. Using an explicit buffer is the most efficient solution - as the bitmap doesn't have to be recreated each time but it - also requires more memory as the bitmap is never freed. The - bitmap should have appropriate size, anything drawn outside of - its bounds is clipped. - - - - - - - - __init__(self, DC dc, Bitmap buffer) -> BufferedDC -__init__(self, DC dc, Size area) -> BufferedDC - Constructs a buffered DC. - - :param dc: The underlying DC: everything drawn to this object will - be flushed to this DC when this object is destroyed. You may - pass ``None`` in order to just initialize the buffer, and not - flush it. - - :param buffer: If a `wx.Size` object is passed as the 2nd arg then - it is the size of the bitmap that will be created internally - and used for an implicit buffer. If the 2nd arg is a - `wx.Bitmap` then it is the explicit buffer that will be - used. Using an explicit buffer is the most efficient solution - as the bitmap doesn't have to be recreated each time but it - also requires more memory as the bitmap is never freed. The - bitmap should have appropriate size, anything drawn outside of - its bounds is clipped. - - - - - - - - __del__(self) - Copies everything drawn on the DC so far to the underlying DC -associated with this object, if any. - - - UnMask(self) - Blits the buffer to the dc, and detaches the dc from the buffer (so it -can be effectively used once only). This is usually only called in -the destructor. - - - - This is a subclass of `wx.BufferedDC` which can be used inside of an -EVT_PAINT event handler. Just create an object of this class instead -of `wx.PaintDC` and that's all you have to do to (mostly) avoid -flicker. The only thing to watch out for is that if you are using this -class together with `wx.ScrolledWindow`, you probably do **not** want -to call `wx.Window.PrepareDC` on it as it already does this internally -for the real underlying `wx.PaintDC`. - -If your window is already fully buffered in a `wx.Bitmap` then your -EVT_PAINT handler can be as simple as just creating a -``wx.BufferedPaintDC`` as it will `Blit` the buffer to the window -automatically when it is destroyed. For example:: - - def OnPaint(self, event): - dc = wx.BufferedPaintDC(self, self.buffer) - - - - - - __init__(self, Window window, Bitmap buffer=NullBitmap) -> BufferedPaintDC - Create a buffered paint DC. As with `wx.BufferedDC`, you may either -provide the bitmap to be used for buffering or let this object create -one internally (in the latter case, the size of the client part of the -window is automatically used). - - - - - - - - - -#--------------------------------------------------------------------------- - - - A wxScreenDC can be used to paint anywhere on the screen. This should -normally be constructed as a temporary stack object; don't store a -wxScreenDC object. - - - - __init__(self) -> ScreenDC - A wxScreenDC can be used to paint anywhere on the screen. This should -normally be constructed as a temporary stack object; don't store a -wxScreenDC object. - - - - StartDrawingOnTopWin(self, Window window) -> bool - Specify that the area of the screen to be drawn upon coincides with -the given window. - -:see: `EndDrawingOnTop` - - - - - - StartDrawingOnTop(self, Rect rect=None) -> bool - Specify that the area is the given rectangle, or the whole screen if -``None`` is passed. - -:see: `EndDrawingOnTop` - - - - - - EndDrawingOnTop(self) -> bool - Use this in conjunction with `StartDrawingOnTop` or -`StartDrawingOnTopWin` to ensure that drawing to the screen occurs on -top of existing windows. Without this, some window systems (such as X) -only allow drawing to take place underneath other windows. - -You might use this pair of functions when implementing a drag feature, -for example as in the `wx.SplitterWindow` implementation. - -These functions are probably obsolete since the X implementations -allow drawing directly on the screen now. However, the fact that this -function allows the screen to be refreshed afterwards may be useful -to some applications. - - - -#--------------------------------------------------------------------------- - - - A wx.ClientDC must be constructed if an application wishes to paint on -the client area of a window from outside an EVT_PAINT event. This should -normally be constructed as a temporary stack object; don't store a -wx.ClientDC object long term. - -To draw on a window from within an EVT_PAINT handler, construct a -`wx.PaintDC` object. - -To draw on the whole window including decorations, construct a -`wx.WindowDC` object (Windows only). - - - - __init__(self, Window win) -> ClientDC - Constructor. Pass the window on which you wish to paint. - - - - - - -#--------------------------------------------------------------------------- - - - A wx.PaintDC must be constructed if an application wishes to paint on -the client area of a window from within an EVT_PAINT event -handler. This should normally be constructed as a temporary stack -object; don't store a wx.PaintDC object. If you have an EVT_PAINT -handler, you **must** create a wx.PaintDC object within it even if you -don't actually use it. - -Using wx.PaintDC within EVT_PAINT handlers is important because it -automatically sets the clipping area to the damaged area of the -window. Attempts to draw outside this area do not appear. - -To draw on a window from outside EVT_PAINT handlers, construct a -`wx.ClientDC` object. - - - - __init__(self, Window win) -> PaintDC - Constructor. Pass the window on which you wish to paint. - - - - - - -#--------------------------------------------------------------------------- - - - A wx.WindowDC must be constructed if an application wishes to paint on -the whole area of a window (client and decorations). This should -normally be constructed as a temporary stack object; don't store a -wx.WindowDC object. - - - __init__(self, Window win) -> WindowDC - Constructor. Pass the window on which you wish to paint. - - - - - - -#--------------------------------------------------------------------------- - - - wx.MirrorDC is a simple wrapper class which is always associated with a -real `wx.DC` object and either forwards all of its operations to it -without changes (no mirroring takes place) or exchanges x and y -coordinates which makes it possible to reuse the same code to draw a -figure and its mirror -- i.e. reflection related to the diagonal line -x == y. - - - __init__(self, DC dc, bool mirror) -> MirrorDC - Creates a mirrored DC associated with the real *dc*. Everything drawn -on the wx.MirrorDC will appear on the *dc*, and will be mirrored if -*mirror* is True. - - - - - - - -#--------------------------------------------------------------------------- - - - This is a `wx.DC` that can write to PostScript files on any platform. - - - __init__(self, wxPrintData printData) -> PostScriptDC - Constructs a PostScript printer device context from a `wx.PrintData` -object. - - - - - - GetPrintData(self) -> wxPrintData - - - SetPrintData(self, wxPrintData data) - - - - - - SetResolution(int ppi) - Set resolution (in pixels per inch) that will be used in PostScript -output. Default is 720ppi. - - - - - - GetResolution() -> int - Return resolution used in PostScript output. - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, String filename=EmptyString) -> MetaFile - - - - - - - - - __init__(self, String filename=EmptyString, int width=0, int height=0, - String description=EmptyString) -> MetaFileDC - - - - - - - - - - - - __init__(self, wxPrintData printData) -> PrinterDC - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int width, int height, int mask=True, int initialCount=1) -> ImageList - - - - - - - - - __del__(self) - - - Add(self, Bitmap bitmap, Bitmap mask=NullBitmap) -> int - - - - - - - AddWithColourMask(self, Bitmap bitmap, Colour maskColour) -> int - - - - - - - AddIcon(self, Icon icon) -> int - - - - - - Replace(self, int index, Bitmap bitmap) -> bool - - - - - - - Draw(self, int index, DC dc, int x, int x, int flags=IMAGELIST_DRAW_NORMAL, - bool solidBackground=False) -> bool - - - - - - - - - - - GetImageCount(self) -> int - - - Remove(self, int index) -> bool - - - - - - RemoveAll(self) -> bool - - - GetSize() -> (width,height) - - - - - - - - -#--------------------------------------------------------------------------- - - - - - AddPen(self, Pen pen) - - - - - - FindOrCreatePen(self, Colour colour, int width, int style) -> Pen - - - - - - - - RemovePen(self, Pen pen) - - - - - - GetCount(self) -> int - - - - - - AddBrush(self, Brush brush) - - - - - - FindOrCreateBrush(self, Colour colour, int style) -> Brush - - - - - - - RemoveBrush(self, Brush brush) - - - - - - GetCount(self) -> int - - - - - - __init__(self) -> ColourDatabase - - - __del__(self) - - - Find(self, String name) -> Colour - - - - - - FindName(self, Colour colour) -> String - - - - - - AddColour(self, String name, Colour colour) - - - - - - - Append(self, String name, int red, int green, int blue) - - - - - - - - - - - - AddFont(self, Font font) - - - - - - FindOrCreateFont(self, int point_size, int family, int style, int weight, - bool underline=False, String facename=EmptyString, - int encoding=FONTENCODING_DEFAULT) -> Font - - - - - - - - - - - - RemoveFont(self, Font font) - - - - - - GetCount(self) -> int - - - -#--------------------------------------------------------------------------- - - NullColor = NullColour - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> Effects - - - GetHighlightColour(self) -> Colour - - - GetLightShadow(self) -> Colour - - - GetFaceColour(self) -> Colour - - - GetMediumShadow(self) -> Colour - - - GetDarkShadow(self) -> Colour - - - SetHighlightColour(self, Colour c) - - - - - - SetLightShadow(self, Colour c) - - - - - - SetFaceColour(self, Colour c) - - - - - - SetMediumShadow(self, Colour c) - - - - - - SetDarkShadow(self, Colour c) - - - - - - Set(self, Colour highlightColour, Colour lightShadow, Colour faceColour, - Colour mediumShadow, Colour darkShadow) - - - - - - - - - - DrawSunkenEdge(self, DC dc, Rect rect, int borderSize=1) - - - - - - - - TileBitmap(self, Rect rect, DC dc, Bitmap bitmap) -> bool - - - - - - - - - - - wx = _core - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxTAB_TRAVERSAL|wxNO_BORDER, - String name=PanelNameStr) -> Panel - - - - - - - - - - - PrePanel() -> Panel - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxTAB_TRAVERSAL|wxNO_BORDER, - String name=PanelNameStr) -> bool - Create the GUI part of the Window for 2-phase creation mode. - - - - - - - - - - - InitDialog(self) - Sends an EVT_INIT_DIALOG event, whose handler usually transfers data -to the dialog via validators. - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxHSCROLL|wxVSCROLL, - String name=PanelNameStr) -> ScrolledWindow - - - - - - - - - - - PreScrolledWindow() -> ScrolledWindow - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxHSCROLL|wxVSCROLL, - String name=PanelNameStr) -> bool - Create the GUI part of the Window for 2-phase creation mode. - - - - - - - - - - - SetScrollbars(self, int pixelsPerUnitX, int pixelsPerUnitY, int noUnitsX, - int noUnitsY, int xPos=0, int yPos=0, bool noRefresh=False) - - - - - - - - - - - - Scroll(self, int x, int y) - - - - - - - GetScrollPageSize(self, int orient) -> int - - - - - - SetScrollPageSize(self, int orient, int pageSize) - - - - - - - SetScrollRate(self, int xstep, int ystep) - - - - - - - GetScrollPixelsPerUnit() -> (xUnit, yUnit) - Get the size of one logical unit in physical units. - - - - - - - EnableScrolling(self, bool x_scrolling, bool y_scrolling) - - - - - - - GetViewStart() -> (x,y) - Get the view start - - - - - - - SetScale(self, double xs, double ys) - - - - - - - GetScaleX(self) -> double - - - GetScaleY(self) -> double - - - Translate between scrolled and unscrolled coordinates. - - - - - - CalcScrolledPosition(self, Point pt) -> Point -CalcScrolledPosition(int x, int y) -> (sx, sy) - Translate between scrolled and unscrolled coordinates. - - - - - - - - - Translate between scrolled and unscrolled coordinates. - - - - - - CalcUnscrolledPosition(self, Point pt) -> Point -CalcUnscrolledPosition(int x, int y) -> (ux, uy) - Translate between scrolled and unscrolled coordinates. - - - - - - - - - AdjustScrollbars(self) - - - CalcScrollInc(self, ScrollWinEvent event) -> int - - - - - - SetTargetWindow(self, Window target) - - - - - - GetTargetWindow(self) -> Window - - - DoPrepareDC(self, DC dc) - Normally what is called by `PrepareDC`. - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - Maximize(self, bool maximize=True) - - - - - - Restore(self) - - - Iconize(self, bool iconize=True) - - - - - - IsMaximized(self) -> bool - - - IsIconized(self) -> bool - - - GetIcon(self) -> Icon - - - SetIcon(self, Icon icon) - - - - - - SetIcons(self, wxIconBundle icons) - - - - - - ShowFullScreen(self, bool show, long style=FULLSCREEN_ALL) -> bool - - - - - - - IsFullScreen(self) -> bool - - - SetTitle(self, String title) - Sets the window's title. Applicable only to frames and dialogs. - - - - - - GetTitle(self) -> String - Gets the window's title. Applicable only to frames and dialogs. - - - SetShape(self, Region region) -> bool - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> Frame - - - - - - - - - - - - PreFrame() -> Frame - - - Create(self, Window parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> bool - - - - - - - - - - - - GetClientAreaOrigin(self) -> Point - Get the origin of the client area of the window relative to the -window's top left corner (the client area may be shifted because of -the borders, scrollbars, other decorations...) - - - SendSizeEvent(self) - - - SetMenuBar(self, MenuBar menubar) - - - - - - GetMenuBar(self) -> MenuBar - - - ProcessCommand(self, int winid) -> bool - - - - - - CreateStatusBar(self, int number=1, long style=wxST_SIZEGRIP|wxFULL_REPAINT_ON_RESIZE, - int winid=0, String name=StatusLineNameStr) -> StatusBar - - - - - - - - - GetStatusBar(self) -> StatusBar - - - SetStatusBar(self, StatusBar statBar) - - - - - - SetStatusText(self, String text, int number=0) - - - - - - - SetStatusWidths(self, int widths, int widths_field) - - - - - - - PushStatusText(self, String text, int number=0) - - - - - - - PopStatusText(self, int number=0) - - - - - - SetStatusBarPane(self, int n) - - - - - - GetStatusBarPane(self) -> int - - - CreateToolBar(self, long style=-1, int winid=-1, String name=ToolBarNameStr) -> wxToolBar - - - - - - - - GetToolBar(self) -> wxToolBar - - - SetToolBar(self, wxToolBar toolbar) - - - - - - DoGiveHelp(self, String text, bool show) - - - - - - - DoMenuUpdates(self, Menu menu=None) - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=DEFAULT_DIALOG_STYLE, String name=DialogNameStr) -> Dialog - - - - - - - - - - - - PreDialog() -> Dialog - - - Create(self, Window parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=DEFAULT_DIALOG_STYLE, String name=DialogNameStr) -> bool - - - - - - - - - - - - SetReturnCode(self, int returnCode) - - - - - - GetReturnCode(self) -> int - - - CreateTextSizer(self, String message) -> Sizer - - - - - - CreateButtonSizer(self, long flags) -> Sizer - - - - - - IsModal(self) -> bool - - - ShowModal(self) -> int - - - EndModal(self, int retCode) - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> MiniFrame - - - - - - - - - - - - PreMiniFrame() -> MiniFrame - - - Create(self, Window parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> bool - - - - - - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Bitmap bitmap, Window parent, int id, Point pos=DefaultPosition, - Size size=DefaultSize, long style=NO_BORDER) -> SplashScreenWindow - - - - - - - - - - - SetBitmap(self, Bitmap bitmap) - - - - - - GetBitmap(self) -> Bitmap - - - - - - __init__(self, Bitmap bitmap, long splashStyle, int milliseconds, - Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP) -> SplashScreen - - - - - - - - - - - - - GetSplashStyle(self) -> long - - - GetSplashWindow(self) -> SplashScreenWindow - - - GetTimeout(self) -> int - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, long style=wxST_SIZEGRIP|wxFULL_REPAINT_ON_RESIZE, - String name=StatusLineNameStr) -> StatusBar - - - - - - - - - PreStatusBar() -> StatusBar - - - Create(self, Window parent, int id=-1, long style=ST_SIZEGRIP, String name=StatusLineNameStr) -> bool - - - - - - - - - SetFieldsCount(self, int number=1) - - - - - - GetFieldsCount(self) -> int - - - SetStatusText(self, String text, int number=0) - - - - - - - GetStatusText(self, int number=0) -> String - - - - - - PushStatusText(self, String text, int number=0) - - - - - - - PopStatusText(self, int number=0) - - - - - - SetStatusWidths(self, int widths, int widths_field) - - - - - - - SetStatusStyles(self, int styles, int styles_field) - - - - - - - GetFieldRect(self, int i) -> Rect - - - - - - SetMinHeight(self, int height) - - - - - - GetBorderX(self) -> int - - - GetBorderY(self) -> int - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - wx.SplitterWindow manages up to two subwindows or panes, with an -optional vertical or horizontal split which can be used with the mouse -or programmatically. - -Styles -------- - ==================== ====================================== - wx.SP_3D Draws a 3D effect border and sash. - wx.SP_3DSASH Draws a 3D effect sash. - wx.SP_3DBORDER Synonym for wxSP_BORDER. - wx.SP_BORDER Draws a standard border. - wx.SP_NOBORDER No border (default). - wx.SP_NO_XP_THEME Under Windows XP, switches off the - attempt to draw the splitter - using Windows XP theming, so the - borders and sash will take on the - pre-XP look. - wx.SP_PERMIT_UNSPLIT Always allow to unsplit, even with - the minimum pane size other than zero. - wx.SP_LIVE_UPDATE Don't draw XOR line but resize the - child windows immediately. - ==================== ====================================== - -Events ------- - ============================== ======================================= - EVT_SPLITTER_SASH_POS_CHANGING The sash position is in the - process of being changed. May be - used to modify the position of - the tracking bar to properly - reflect the position that would - be set if the drag were to be - completed at this point. - - EVT_SPLITTER_SASH_POS_CHANGED - The sash position was - changed. May be used to modify - the sash position before it is - set, or to prevent the change - from taking place. - - EVT_SPLITTER_UNSPLIT The splitter has been just unsplit. - - EVT_SPLITTER_DCLICK The sash was double clicked. The - default behaviour is to unsplit - the window when this happens - (unless the minimum pane size has - been set to a value greater than - zero.) - ============================== ======================================= - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=SP_3D, String name=SplitterNameStr) -> SplitterWindow - Constructor. Creates and shows a SplitterWindow. - - - - - - - - - - - PreSplitterWindow() -> SplitterWindow - Precreate a SplitterWindow for 2-phase creation. - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=SP_3D, String name=SplitterNameStr) -> bool - Create the GUI part of the SplitterWindow for the 2-phase create. - - - - - - - - - - - GetWindow1(self) -> Window - Gets the only or left/top pane. - - - GetWindow2(self) -> Window - Gets the right/bottom pane. - - - SetSplitMode(self, int mode) - Sets the split mode. The mode can be wx.SPLIT_VERTICAL or -wx.SPLIT_HORIZONTAL. This only sets the internal variable; does not -update the display. - - - - - - GetSplitMode(self) -> int - Gets the split mode - - - Initialize(self, Window window) - Initializes the splitter window to have one pane. This should be -called if you wish to initially view only a single pane in the -splitter window. - - - - - - SplitVertically(self, Window window1, Window window2, int sashPosition=0) -> bool - Initializes the left and right panes of the splitter window. - :param window1: The left pane. - :param window2: The right pane. - :param sashPosition: The initial position of the sash. If this - value is positive, it specifies the size of the left - pane. If it is negative, it is absolute value gives - the size of the right pane. Finally, specify 0 - (default) to choose the default position (half of - the total window width). - -Returns True if successful, False otherwise (the window was already -split). - -SplitVertically should be called if you wish to initially view two -panes. It can also be called at any subsequent time, but the -application should check that the window is not currently split using -IsSplit. - - - - - - - - - SplitHorizontally(self, Window window1, Window window2, int sashPosition=0) -> bool - Initializes the top and bottom panes of the splitter window. - :param window1: The top pane. - :param window2: The bottom pane. - :param sashPosition: The initial position of the sash. If this - value is positive, it specifies the size of the - upper pane. If it is negative, it is absolute value - gives the size of the lower pane. Finally, specify 0 - (default) to choose the default position (half of - the total window height). - -Returns True if successful, False otherwise (the window was already -split). - -SplitHorizontally should be called if you wish to initially view two -panes. It can also be called at any subsequent time, but the -application should check that the window is not currently split using -IsSplit. - - - - - - - - - Unsplit(self, Window toRemove=None) -> bool - Unsplits the window. Pass the pane to remove, or None to remove the -right or bottom pane. Returns True if successful, False otherwise (the -window was not split). - -This function will not actually delete the pane being -removed; it sends EVT_SPLITTER_UNSPLIT which can be handled -for the desired behaviour. By default, the pane being -removed is only hidden. - - - - - - ReplaceWindow(self, Window winOld, Window winNew) -> bool - This function replaces one of the windows managed by the -SplitterWindow with another one. It is in general better to use it -instead of calling Unsplit() and then resplitting the window back -because it will provoke much less flicker. It is valid to call this -function whether the splitter has two windows or only one. - -Both parameters should be non-None and winOld must specify one of the -windows managed by the splitter. If the parameters are incorrect or -the window couldn't be replaced, False is returned. Otherwise the -function will return True, but please notice that it will not Destroy -the replaced window and you may wish to do it yourself. - - - - - - - UpdateSize(self) - Causes any pending sizing of the sash and child panes to take place -immediately. - -Such resizing normally takes place in idle time, in order to wait for -layout to be completed. However, this can cause unacceptable flicker -as the panes are resized after the window has been shown. To work -around this, you can perform window layout (for example by sending a -size event to the parent window), and then call this function, before -showing the top-level window. - - - IsSplit(self) -> bool - Is the window split? - - - SetSashSize(self, int width) - Sets the sash size - - - - - - SetBorderSize(self, int width) - Sets the border size - - - - - - GetSashSize(self) -> int - Gets the sash size - - - GetBorderSize(self) -> int - Gets the border size - - - SetSashPosition(self, int position, bool redraw=True) - Sets the sash position, in pixels. If redraw is Ttrue then the panes -are resized and the sash and border are redrawn. - - - - - - - GetSashPosition(self) -> int - Returns the surrent sash position. - - - SetMinimumPaneSize(self, int min) - Sets the minimum pane size in pixels. - -The default minimum pane size is zero, which means that either pane -can be reduced to zero by dragging the sash, thus removing one of the -panes. To prevent this behaviour (and veto out-of-range sash -dragging), set a minimum size, for example 20 pixels. If the -wx.SP_PERMIT_UNSPLIT style is used when a splitter window is created, -the window may be unsplit even if minimum size is non-zero. - - - - - - GetMinimumPaneSize(self) -> int - Gets the minimum pane size in pixels. - - - SashHitTest(self, int x, int y, int tolerance=5) -> bool - Tests for x, y over the sash - - - - - - - - SizeWindows(self) - Resizes subwindows - - - SetNeedUpdating(self, bool needUpdating) - - - - - - GetNeedUpdating(self) -> bool - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - - This class represents the events generated by a splitter control. - - - __init__(self, wxEventType type=wxEVT_NULL, SplitterWindow splitter=(wxSplitterWindow *) NULL) -> SplitterEvent - This class represents the events generated by a splitter control. - - - - - - - SetSashPosition(self, int pos) - This funciton is only meaningful during EVT_SPLITTER_SASH_POS_CHANGING -and EVT_SPLITTER_SASH_POS_CHANGED events. In the case of _CHANGED -events, sets the the new sash position. In the case of _CHANGING -events, sets the new tracking bar position so visual feedback during -dragging will represent that change that will actually take place. Set -to -1 from the event handler code to prevent repositioning. - - - - - - GetSashPosition(self) -> int - Returns the new sash position while in EVT_SPLITTER_SASH_POS_CHANGING -and EVT_SPLITTER_SASH_POS_CHANGED events. - - - GetWindowBeingRemoved(self) -> Window - Returns a pointer to the window being removed when a splitter window -is unsplit. - - - GetX(self) -> int - Returns the x coordinate of the double-click point in a -EVT_SPLITTER_DCLICK event. - - - GetY(self) -> int - Returns the y coordinate of the double-click point in a -EVT_SPLITTER_DCLICK event. - - - -EVT_SPLITTER_SASH_POS_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, 1 ) -EVT_SPLITTER_SASH_POS_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, 1 ) -EVT_SPLITTER_DOUBLECLICKED = wx.PyEventBinder( wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, 1 ) -EVT_SPLITTER_UNSPLIT = wx.PyEventBinder( wxEVT_COMMAND_SPLITTER_UNSPLIT, 1 ) -EVT_SPLITTER_DCLICK = EVT_SPLITTER_DOUBLECLICKED - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxSW_3D, - String name=SashNameStr) -> SashWindow - - - - - - - - - - - PreSashWindow() -> SashWindow - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxSW_3D, - String name=SashNameStr) -> bool - - - - - - - - - - - SetSashVisible(self, int edge, bool sash) - - - - - - - GetSashVisible(self, int edge) -> bool - - - - - - SetSashBorder(self, int edge, bool border) - - - - - - - HasBorder(self, int edge) -> bool - - - - - - GetEdgeMargin(self, int edge) -> int - - - - - - SetDefaultBorderSize(self, int width) - - - - - - GetDefaultBorderSize(self) -> int - - - SetExtraBorderSize(self, int width) - - - - - - GetExtraBorderSize(self) -> int - - - SetMinimumSizeX(self, int min) - - - - - - SetMinimumSizeY(self, int min) - - - - - - GetMinimumSizeX(self) -> int - - - GetMinimumSizeY(self) -> int - - - SetMaximumSizeX(self, int max) - - - - - - SetMaximumSizeY(self, int max) - - - - - - GetMaximumSizeX(self) -> int - - - GetMaximumSizeY(self) -> int - - - SashHitTest(self, int x, int y, int tolerance=2) -> int - - - - - - - - SizeWindows(self) - - - - - - __init__(self, int id=0, int edge=SASH_NONE) -> SashEvent - - - - - - - SetEdge(self, int edge) - - - - - - GetEdge(self) -> int - - - SetDragRect(self, Rect rect) - - - - - - GetDragRect(self) -> Rect - - - SetDragStatus(self, int status) - - - - - - GetDragStatus(self) -> int - - - - EVT_SASH_DRAGGED = wx.PyEventBinder( wxEVT_SASH_DRAGGED, 1 ) - EVT_SASH_DRAGGED_RANGE = wx.PyEventBinder( wxEVT_SASH_DRAGGED, 2 ) - - -#--------------------------------------------------------------------------- - - - - - __init__(self, int id=0) -> QueryLayoutInfoEvent - - - - - - SetRequestedLength(self, int length) - - - - - - GetRequestedLength(self) -> int - - - SetFlags(self, int flags) - - - - - - GetFlags(self) -> int - - - SetSize(self, Size size) - - - - - - GetSize(self) -> Size - - - SetOrientation(self, int orient) - - - - - - GetOrientation(self) -> int - - - SetAlignment(self, int align) - - - - - - GetAlignment(self) -> int - - - - - - __init__(self, int id=0) -> CalculateLayoutEvent - - - - - - SetFlags(self, int flags) - - - - - - GetFlags(self) -> int - - - SetRect(self, Rect rect) - - - - - - GetRect(self) -> Rect - - - - EVT_QUERY_LAYOUT_INFO = wx.PyEventBinder( wxEVT_QUERY_LAYOUT_INFO ) - EVT_CALCULATE_LAYOUT = wx.PyEventBinder( wxEVT_CALCULATE_LAYOUT ) - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxSW_3D, - String name=SashLayoutNameStr) -> SashLayoutWindow - - - - - - - - - - - PreSashLayoutWindow() -> SashLayoutWindow - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxSW_3D, - String name=SashLayoutNameStr) -> bool - - - - - - - - - - - GetAlignment(self) -> int - - - GetOrientation(self) -> int - - - SetAlignment(self, int alignment) - - - - - - SetDefaultSize(self, Size size) - - - - - - SetOrientation(self, int orientation) - - - - - - - - - __init__(self) -> LayoutAlgorithm - - - __del__(self) - - - LayoutMDIFrame(self, MDIParentFrame frame, Rect rect=None) -> bool - - - - - - - LayoutFrame(self, Frame frame, Window mainWindow=None) -> bool - - - - - - - LayoutWindow(self, Window parent, Window mainWindow=None) -> bool - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int flags=BORDER_NONE) -> PopupWindow - - - - - - - PrePopupWindow() -> PopupWindow - - - Create(self, Window parent, int flags=BORDER_NONE) -> bool - - - - - - - Position(self, Point ptOrigin, Size size) - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int style=BORDER_NONE) -> PopupTransientWindow - - - - - - - PrePopupTransientWindow() -> PopupTransientWindow - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - Popup(self, Window focus=None) - - - - - - Dismiss(self) - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, String text, int maxLength=100, Rect rectBound=None) -> TipWindow - - - - - - - - - SetBoundingRect(self, Rect rectBound) - - - - - - Close(self) - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=PanelNameStr) -> VScrolledWindow - - - - - - - - - - - PreVScrolledWindow() -> VScrolledWindow - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=PanelNameStr) -> bool - - - - - - - - - - - SetLineCount(self, size_t count) - - - - - - ScrollToLine(self, size_t line) -> bool - - - - - - ScrollLines(self, int lines) -> bool - If the platform and window class supports it, scrolls the window by -the given number of lines down, if lines is positive, or up if lines -is negative. Returns True if the window was scrolled, False if it was -already on top/bottom and nothing was done. - - - - - - ScrollPages(self, int pages) -> bool - If the platform and window class supports it, scrolls the window by -the given number of pages down, if pages is positive, or up if pages -is negative. Returns True if the window was scrolled, False if it was -already on top/bottom and nothing was done. - - - - - - RefreshLine(self, size_t line) - - - - - - RefreshLines(self, size_t from, size_t to) - - - - - - - HitTestXY(self, int x, int y) -> int - Test where the given (in client coords) point lies - - - - - - - HitTest(self, Point pt) -> int - Test where the given (in client coords) point lies - - - - - - RefreshAll(self) - - - GetLineCount(self) -> size_t - - - GetFirstVisibleLine(self) -> size_t - - - GetLastVisibleLine(self) -> size_t - - - IsVisible(self, size_t line) -> bool - - - - - - - - - __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=VListBoxNameStr) -> VListBox - - - - - - - - - - - PreVListBox() -> VListBox - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=VListBoxNameStr) -> bool - - - - - - - - - - - GetItemCount(self) -> size_t - - - HasMultipleSelection(self) -> bool - - - GetSelection(self) -> int - - - IsCurrent(self, size_t item) -> bool - - - - - - IsSelected(self, size_t item) -> bool - - - - - - GetSelectedCount(self) -> size_t - - - GetFirstSelected(self) -> PyObject - - - GetNextSelected(self, unsigned long cookie) -> PyObject - - - - - - GetMargins(self) -> Point - - - GetSelectionBackground(self) -> Colour - - - SetItemCount(self, size_t count) - - - - - - Clear(self) - - - SetSelection(self, int selection) - - - - - - Select(self, size_t item, bool select=True) -> bool - - - - - - - SelectRange(self, size_t from, size_t to) -> bool - - - - - - - Toggle(self, size_t item) - - - - - - SelectAll(self) -> bool - - - DeselectAll(self) -> bool - - - SetMargins(self, Point pt) - - - - - - SetMarginsXY(self, int x, int y) - - - - - - - SetSelectionBackground(self, Colour col) - - - - - - - - - __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=VListBoxNameStr) -> HtmlListBox - - - - - - - - - - - PreHtmlListBox() -> HtmlListBox - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=VListBoxNameStr) -> bool - - - - - - - - - - - RefreshAll(self) - - - SetItemCount(self, size_t count) - - - - - - GetFileSystem(self) -> FileSystem - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> TaskBarIcon - - - __del__(self) - - - Destroy(self) - Deletes the C++ object this Python object is a proxy for. - - - IsOk(self) -> bool - - - IsIconInstalled(self) -> bool - - - SetIcon(self, Icon icon, String tooltip=EmptyString) -> bool - - - - - - - RemoveIcon(self) -> bool - - - PopupMenu(self, Menu menu) -> bool - - - - - - - - - __init__(self, wxEventType evtType, TaskBarIcon tbIcon) -> TaskBarIconEvent - - - - - - - -EVT_TASKBAR_MOVE = wx.PyEventBinder ( wxEVT_TASKBAR_MOVE ) -EVT_TASKBAR_LEFT_DOWN = wx.PyEventBinder ( wxEVT_TASKBAR_LEFT_DOWN ) -EVT_TASKBAR_LEFT_UP = wx.PyEventBinder ( wxEVT_TASKBAR_LEFT_UP ) -EVT_TASKBAR_RIGHT_DOWN = wx.PyEventBinder ( wxEVT_TASKBAR_RIGHT_DOWN ) -EVT_TASKBAR_RIGHT_UP = wx.PyEventBinder ( wxEVT_TASKBAR_RIGHT_UP ) -EVT_TASKBAR_LEFT_DCLICK = wx.PyEventBinder ( wxEVT_TASKBAR_LEFT_DCLICK ) -EVT_TASKBAR_RIGHT_DCLICK = wx.PyEventBinder ( wxEVT_TASKBAR_RIGHT_DCLICK ) - - -#--------------------------------------------------------------------------- - - - This class holds a variety of information related to the colour -chooser dialog, used to transfer settings and results to and from the -`wx.ColourDialog`. - - - __init__(self) -> ColourData - Constructor, sets default values. - - - __del__(self) - - - GetChooseFull(self) -> bool - Under Windows, determines whether the Windows colour dialog will -display the full dialog with custom colour selection controls. Has no -meaning under other platforms. The default value is true. - - - GetColour(self) -> Colour - Gets the colour (pre)selected by the dialog. - - - GetCustomColour(self, int i) -> Colour - Gets the i'th custom colour associated with the colour dialog. i -should be an integer between 0 and 15. The default custom colours are -all invalid colours. - - - - - - SetChooseFull(self, int flag) - Under Windows, tells the Windows colour dialog to display the full -dialog with custom colour selection controls. Under other platforms, -has no effect. The default value is true. - - - - - - SetColour(self, Colour colour) - Sets the default colour for the colour dialog. The default colour is -black. - - - - - - SetCustomColour(self, int i, Colour colour) - Sets the i'th custom colour for the colour dialog. i should be an -integer between 0 and 15. The default custom colours are all invalid colours. - - - - - - - - This class represents the colour chooser dialog. - - - __init__(self, Window parent, ColourData data=None) -> ColourDialog - Constructor. Pass a parent window, and optionally a `wx.ColourData`, -which will be copied to the colour dialog's internal ColourData -instance. - - - - - - - GetColourData(self) -> ColourData - Returns a reference to the `wx.ColourData` used by the dialog. - - - - wx.DirDialog allows the user to select a directory by browising the -file system. - -Window Styles --------------- - ==================== ========================================== - wx.DD_NEW_DIR_BUTTON Add 'Create new directory' button and allow - directory names to be editable. On Windows - the new directory button is only available - with recent versions of the common dialogs. - ==================== ========================================== - - - - __init__(self, Window parent, String message=DirSelectorPromptStr, - String defaultPath=EmptyString, long style=0, - Point pos=DefaultPosition, Size size=DefaultSize, - String name=DirDialogNameStr) -> DirDialog - Constructor. Use ShowModal method to show the dialog. - - - - - - - - - - - - GetPath(self) -> String - Returns the default or user-selected path. - - - GetMessage(self) -> String - Returns the message that will be displayed on the dialog. - - - GetStyle(self) -> long - Returns the dialog style. - - - SetMessage(self, String message) - Sets the message that will be displayed on the dialog. - - - - - - SetPath(self, String path) - Sets the default path. - - - - - - - wx.FileDialog allows the user to select one or more files from the -filesystem. - -In Windows, this is the common file selector dialog. On X based -platforms a generic alternative is used. The path and filename are -distinct elements of a full file pathname. If path is "", the -current directory will be used. If filename is "", no default -filename will be supplied. The wildcard determines what files are -displayed in the file selector, and file extension supplies a type -extension for the required filename. - -Both the X and Windows versions implement a wildcard filter. Typing a -filename containing wildcards (\\*, ?) in the filename text item, and -clicking on Ok, will result in only those files matching the pattern -being displayed. The wildcard may be a specification for multiple -types of file with a description for each, such as:: - - "BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif" - - -Window Styles --------------- - =================== ========================================== - wx.OPEN This is an open dialog. - - wx.SAVE This is a save dialog. - - wx.HIDE_READONLY For open dialog only: hide the checkbox - allowing to open the file in read-only mode. - - wx.OVERWRITE_PROMPT For save dialog only: prompt for a confirmation - if a file will be overwritten. - - wx.MULTIPLE For open dialog only: allows selecting multiple - files. - - wx.CHANGE_DIR Change the current working directory to the - directory where the file(s) chosen by the user - are. - =================== ========================================== - - - - __init__(self, Window parent, String message=FileSelectorPromptStr, - String defaultDir=EmptyString, String defaultFile=EmptyString, - String wildcard=FileSelectorDefaultWildcardStr, - long style=0, Point pos=DefaultPosition) -> FileDialog - Constructor. Use ShowModal method to show the dialog. - - - - - - - - - - - - SetMessage(self, String message) - Sets the message that will be displayed on the dialog. - - - - - - SetPath(self, String path) - Sets the path (the combined directory and filename that will be -returned when the dialog is dismissed). - - - - - - SetDirectory(self, String dir) - Sets the default directory. - - - - - - SetFilename(self, String name) - Sets the default filename. - - - - - - SetWildcard(self, String wildCard) - Sets the wildcard, which can contain multiple file types, for -example:: - - "BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif" - - - - - - - SetStyle(self, long style) - Sets the dialog style. - - - - - - SetFilterIndex(self, int filterIndex) - Sets the default filter index, starting from zero. - - - - - - GetMessage(self) -> String - Returns the message that will be displayed on the dialog. - - - GetPath(self) -> String - Returns the full path (directory and filename) of the selected file. - - - GetDirectory(self) -> String - Returns the default directory. - - - GetFilename(self) -> String - Returns the default filename. - - - GetWildcard(self) -> String - Returns the file dialog wildcard. - - - GetStyle(self) -> long - Returns the dialog style. - - - GetFilterIndex(self) -> int - Returns the index into the list of filters supplied, optionally, in -the wildcard parameter. Before the dialog is shown, this is the index -which will be used when the dialog is first displayed. After the -dialog is shown, this is the index selected by the user. - - - GetFilenames(self) -> PyObject - Returns a list of filenames chosen in the dialog. This function -should only be used with the dialogs which have wx.MULTIPLE style, use -GetFilename for the others. - - - GetPaths(self) -> PyObject - Fills the array paths with the full paths of the files chosen. This -function should only be used with the dialogs which have wx.MULTIPLE -style, use GetPath for the others. - - - - A simple dialog with a multi selection listbox. - - - __init__(Window parent, String message, String caption, - List choices=[], long style=CHOICEDLG_STYLE, - Point pos=DefaultPosition) -> MultiChoiceDialog - Constructor. Use ShowModal method to show the dialog. - - - - - - - - - - - - SetSelections(List selections) - Specify the items in the list that should be selected, using a list of -integers. - - - - - - GetSelections() -> [selections] - Returns a list of integers representing the items that are selected. - - - - A simple dialog with a single selection listbox. - - - __init__(Window parent, String message, String caption, - List choices=[], long style=CHOICEDLG_STYLE, - Point pos=DefaultPosition) -> SingleChoiceDialog - Constructor. Use ShowModal method to show the dialog. - - - - - - - - - - - - GetSelection(self) -> int - Get the index of teh currently selected item. - - - GetStringSelection(self) -> String - Returns the string value of the currently selected item - - - SetSelection(self, int sel) - Set the current selected item to sel - - - - - - - A dialog with text control, [ok] and [cancel] buttons - - - __init__(self, Window parent, String message, String caption=GetTextFromUserPromptStr, - String defaultValue=EmptyString, - long style=wxOK|wxCANCEL|wxCENTRE, Point pos=DefaultPosition) -> TextEntryDialog - Constructor. Use ShowModal method to show the dialog. - - - - - - - - - - - GetValue(self) -> String - Returns the text that the user has entered if the user has pressed OK, -or the original value if the user has pressed Cancel. - - - SetValue(self, String value) - Sets the default text value. - - - - - - - This class holds a variety of information related to font dialogs and -is used to transfer settings to and results from a `wx.FontDialog`. - - - __init__(self) -> FontData - This class holds a variety of information related to font dialogs and -is used to transfer settings to and results from a `wx.FontDialog`. - - - __del__(self) - - - EnableEffects(self, bool enable) - Enables or disables 'effects' under MS Windows only. This refers to -the controls for manipulating colour, strikeout and underline -properties. The default value is true. - - - - - - GetAllowSymbols(self) -> bool - Under MS Windows, returns a flag determining whether symbol fonts can -be selected. Has no effect on other platforms. The default value is -true. - - - GetColour(self) -> Colour - Gets the colour associated with the font dialog. The default value is -black. - - - GetChosenFont(self) -> Font - Gets the font chosen by the user. - - - GetEnableEffects(self) -> bool - Determines whether 'effects' are enabled under Windows. - - - GetInitialFont(self) -> Font - Gets the font that will be initially used by the font dialog. This -should have previously been set by the application. - - - GetShowHelp(self) -> bool - Returns true if the Help button will be shown (Windows only). The -default value is false. - - - SetAllowSymbols(self, bool allowSymbols) - Under MS Windows, determines whether symbol fonts can be selected. Has -no effect on other platforms. The default value is true. - - - - - - SetChosenFont(self, Font font) - Sets the font that will be returned to the user (normally for internal -use only). - - - - - - SetColour(self, Colour colour) - Sets the colour that will be used for the font foreground colour. The -default colour is black. - - - - - - SetInitialFont(self, Font font) - Sets the font that will be initially used by the font dialog. - - - - - - SetRange(self, int min, int max) - Sets the valid range for the font point size (Windows only). The -default is 0, 0 (unrestricted range). - - - - - - - SetShowHelp(self, bool showHelp) - Determines whether the Help button will be displayed in the font -dialog (Windows only). The default value is false. - - - - - - - wx.FontDialog allows the user to select a system font and its attributes. - -:see: `wx.FontData` - - - - __init__(self, Window parent, FontData data) -> FontDialog - Constructor. Pass a parent window and the `wx.FontData` object to be -used to initialize the dialog controls. Call `ShowModal` to display -the dialog. If ShowModal returns ``wx.ID_OK`` then you can fetch the -results with via the `wx.FontData` returned by `GetFontData`. - - - - - - - GetFontData(self) -> FontData - Returns a reference to the internal `wx.FontData` used by the -wx.FontDialog. - - - - This class provides a simple dialog that shows a single or multi-line -message, with a choice of OK, Yes, No and/or Cancel buttons. - -Window Styles --------------- - =================== ============================================= - wx.OK Show an OK button. - wx.CANCEL Show a Cancel button. - wx.YES_NO Show Yes and No buttons. - wx.YES_DEFAULT Used with wxYES_NO, makes Yes button the - default - which is the default behaviour. - wx.NO_DEFAULT Used with wxYES_NO, makes No button the default. - wx.ICON_EXCLAMATION Shows an exclamation mark icon. - wx.ICON_HAND Shows an error icon. - wx.ICON_ERROR Shows an error icon - the same as wxICON_HAND. - wx.ICON_QUESTION Shows a question mark icon. - wx.ICON_INFORMATION Shows an information (i) icon. - wx.STAY_ON_TOP The message box stays on top of all other - window, even those of the other applications - (Windows only). - =================== ============================================= - - - - __init__(self, Window parent, String message, String caption=MessageBoxCaptionStr, - long style=wxOK|wxCANCEL|wxCENTRE, - Point pos=DefaultPosition) -> MessageDialog - Constructor, use `ShowModal` to display the dialog. - - - - - - - - - - - A dialog that shows a short message and a progress bar. Optionally, it -can display an ABORT button. - -Window Styles --------------- - ==================== ============================================= - wx.PD_APP_MODAL Make the progress dialog modal. If this flag is - not given, it is only "locally" modal - - that is the input to the parent window is - disabled, but not to the other ones. - - wx.PD_AUTO_HIDE Causes the progress dialog to disappear from - screen as soon as the maximum value of the - progress meter has been reached. - - wx.PD_CAN_ABORT This flag tells the dialog that it should have - a "Cancel" button which the user may press. If - this happens, the next call to Update() will - return false. - - wx.PD_ELAPSED_TIME This flag tells the dialog that it should show - elapsed time (since creating the dialog). - - wx.PD_ESTIMATED_TIME This flag tells the dialog that it should show - estimated time. - - wx.PD_REMAINING_TIME This flag tells the dialog that it should show - remaining time. - ==================== ============================================= - - - - __init__(self, String title, String message, int maximum=100, Window parent=None, - int style=wxPD_AUTO_HIDE|wxPD_APP_MODAL) -> ProgressDialog - Constructor. Creates the dialog, displays it and disables user input -for other windows, or, if wx.PD_APP_MODAL flag is not given, for its -parent window only. - - - - - - - - - - Update(self, int value, String newmsg=EmptyString) -> bool - Updates the dialog, setting the progress bar to the new value and, if -given changes the message above it. The value given should be less -than or equal to the maximum value given to the constructor and the -dialog is closed if it is equal to the maximum. Returns true unless -the Cancel button has been pressed. - -If false is returned, the application can either immediately destroy -the dialog or ask the user for the confirmation and if the abort is -not confirmed the dialog may be resumed with Resume function. - - - - - - - Resume(self) - Can be used to continue with the dialog, after the user had chosen to -abort. - - - -EVT_FIND = wx.PyEventBinder( wxEVT_COMMAND_FIND, 1 ) -EVT_FIND_NEXT = wx.PyEventBinder( wxEVT_COMMAND_FIND_NEXT, 1 ) -EVT_FIND_REPLACE = wx.PyEventBinder( wxEVT_COMMAND_FIND_REPLACE, 1 ) -EVT_FIND_REPLACE_ALL = wx.PyEventBinder( wxEVT_COMMAND_FIND_REPLACE_ALL, 1 ) -EVT_FIND_CLOSE = wx.PyEventBinder( wxEVT_COMMAND_FIND_CLOSE, 1 ) - -# For backwards compatibility. Should they be removed? -EVT_COMMAND_FIND = EVT_FIND -EVT_COMMAND_FIND_NEXT = EVT_FIND_NEXT -EVT_COMMAND_FIND_REPLACE = EVT_FIND_REPLACE -EVT_COMMAND_FIND_REPLACE_ALL = EVT_FIND_REPLACE_ALL -EVT_COMMAND_FIND_CLOSE = EVT_FIND_CLOSE - - - Events for the FindReplaceDialog - - - __init__(self, wxEventType commandType=wxEVT_NULL, int id=0) -> FindDialogEvent - Events for the FindReplaceDialog - - - - - - - GetFlags(self) -> int - Get the currently selected flags: this is the combination of -wx.FR_DOWN, wx.FR_WHOLEWORD and wx.FR_MATCHCASE flags. - - - GetFindString(self) -> String - Return the string to find (never empty). - - - GetReplaceString(self) -> String - Return the string to replace the search string with (only for replace -and replace all events). - - - GetDialog(self) -> FindReplaceDialog - Return the pointer to the dialog which generated this event. - - - SetFlags(self, int flags) - - - - - - SetFindString(self, String str) - - - - - - SetReplaceString(self, String str) - - - - - - - wx.FindReplaceData holds the data for wx.FindReplaceDialog. It is used -to initialize the dialog with the default values and will keep the -last values from the dialog when it is closed. It is also updated each -time a `wx.FindDialogEvent` is generated so instead of using the -`wx.FindDialogEvent` methods you can also directly query this object. - -Note that all SetXXX() methods may only be called before showing the -dialog and calling them has no effect later. - -Flags ------ - ================ =============================================== - wx.FR_DOWN Downward search/replace selected (otherwise, - upwards) - - wx.FR_WHOLEWORD Whole word search/replace selected - - wx.FR_MATCHCASE Case sensitive search/replace selected - (otherwise, case insensitive) - ================ =============================================== - - - - __init__(self, int flags=0) -> FindReplaceData - Constuctor initializes the flags to default value (0). - - - - - - __del__(self) - - - GetFindString(self) -> String - Get the string to find. - - - GetReplaceString(self) -> String - Get the replacement string. - - - GetFlags(self) -> int - Get the combination of flag values. - - - SetFlags(self, int flags) - Set the flags to use to initialize the controls of the dialog. - - - - - - SetFindString(self, String str) - Set the string to find (used as initial value by the dialog). - - - - - - SetReplaceString(self, String str) - Set the replacement string (used as initial value by the dialog). - - - - - - - wx.FindReplaceDialog is a standard modeless dialog which is used to -allow the user to search for some text (and possibly replace it with -something else). The actual searching is supposed to be done in the -owner window which is the parent of this dialog. Note that it means -that unlike for the other standard dialogs this one must have a parent -window. Also note that there is no way to use this dialog in a modal -way; it is always, by design and implementation, modeless. - - -Window Styles -------------- - - ===================== ========================================= - wx.FR_REPLACEDIALOG replace dialog (otherwise find dialog) - - wx.FR_NOUPDOWN don't allow changing the search direction - - wx.FR_NOMATCHCASE don't allow case sensitive searching - - wx.FR_NOWHOLEWORD don't allow whole word searching - ===================== ========================================= - - - - __init__(self, Window parent, FindReplaceData data, String title, - int style=0) -> FindReplaceDialog - Create a FindReplaceDialog. The parent and data parameters must be -non-None. Use Show to display the dialog. - - - - - - - - - PreFindReplaceDialog() -> FindReplaceDialog - Precreate a FindReplaceDialog for 2-phase creation - - - Create(self, Window parent, FindReplaceData data, String title, - int style=0) -> bool - Create the dialog, for 2-phase create. - - - - - - - - - GetData(self) -> FindReplaceData - Get the FindReplaceData object used by this dialog. - - - SetData(self, FindReplaceData data) - Set the FindReplaceData object used by this dialog. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=wxDEFAULT_FRAME_STYLE|wxVSCROLL|wxHSCROLL, - String name=FrameNameStr) -> MDIParentFrame - - - - - - - - - - - - PreMDIParentFrame() -> MDIParentFrame - - - Create(self, Window parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=wxDEFAULT_FRAME_STYLE|wxVSCROLL|wxHSCROLL, - String name=FrameNameStr) -> bool - - - - - - - - - - - - ActivateNext(self) - - - ActivatePrevious(self) - - - ArrangeIcons(self) - - - Cascade(self) - - - GetActiveChild(self) -> MDIChildFrame - - - GetClientWindow(self) -> MDIClientWindow - - - GetToolBar(self) -> Window - - - Tile(self) - - - - - - __init__(self, MDIParentFrame parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=DEFAULT_FRAME_STYLE, - String name=FrameNameStr) -> MDIChildFrame - - - - - - - - - - - - PreMDIChildFrame() -> MDIChildFrame - - - Create(self, MDIParentFrame parent, int id=-1, String title=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=DEFAULT_FRAME_STYLE, - String name=FrameNameStr) -> bool - - - - - - - - - - - - Activate(self) - - - Maximize(self, bool maximize) - - - - - - Restore(self) - - - - - - __init__(self, MDIParentFrame parent, long style=0) -> MDIClientWindow - - - - - - - PreMDIClientWindow() -> MDIClientWindow - - - Create(self, MDIParentFrame parent, long style=0) -> bool - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=PanelNameStr) -> PyWindow - - - - - - - - - - - PrePyWindow() -> PyWindow - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetBestSize(self, Size size) - - - - - - base_DoMoveWindow(self, int x, int y, int width, int height) - - - - - - - - - base_DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO) - - - - - - - - - - base_DoSetClientSize(self, int width, int height) - - - - - - - base_DoSetVirtualSize(self, int x, int y) - - - - - - - base_DoGetSize() -> (width, height) - - - - - - - base_DoGetClientSize() -> (width, height) - - - - - - - base_DoGetPosition() -> (x,y) - - - - - - - base_DoGetVirtualSize(self) -> Size - - - base_DoGetBestSize(self) -> Size - - - base_InitDialog(self) - - - base_TransferDataToWindow(self) -> bool - - - base_TransferDataFromWindow(self) -> bool - - - base_Validate(self) -> bool - - - base_AcceptsFocus(self) -> bool - - - base_AcceptsFocusFromKeyboard(self) -> bool - - - base_GetMaxSize(self) -> Size - - - base_AddChild(self, Window child) - - - - - - base_RemoveChild(self, Window child) - - - - - - base_ShouldInheritColours(self) -> bool - - - base_ApplyParentThemeBackground(self, Colour c) - - - - - - base_GetDefaultAttributes(self) -> VisualAttributes - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=PanelNameStr) -> PyPanel - - - - - - - - - - - PrePyPanel() -> PyPanel - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetBestSize(self, Size size) - - - - - - base_DoMoveWindow(self, int x, int y, int width, int height) - - - - - - - - - base_DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO) - - - - - - - - - - base_DoSetClientSize(self, int width, int height) - - - - - - - base_DoSetVirtualSize(self, int x, int y) - - - - - - - base_DoGetSize() -> (width, height) - - - - - - - base_DoGetClientSize() -> (width, height) - - - - - - - base_DoGetPosition() -> (x,y) - - - - - - - base_DoGetVirtualSize(self) -> Size - - - base_DoGetBestSize(self) -> Size - - - base_InitDialog(self) - - - base_TransferDataToWindow(self) -> bool - - - base_TransferDataFromWindow(self) -> bool - - - base_Validate(self) -> bool - - - base_AcceptsFocus(self) -> bool - - - base_AcceptsFocusFromKeyboard(self) -> bool - - - base_GetMaxSize(self) -> Size - - - base_AddChild(self, Window child) - - - - - - base_RemoveChild(self, Window child) - - - - - - base_ShouldInheritColours(self) -> bool - - - base_ApplyParentThemeBackground(self, Colour c) - - - - - - base_GetDefaultAttributes(self) -> VisualAttributes - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=PanelNameStr) -> PyScrolledWindow - - - - - - - - - - - PrePyScrolledWindow() -> PyScrolledWindow - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetBestSize(self, Size size) - - - - - - base_DoMoveWindow(self, int x, int y, int width, int height) - - - - - - - - - base_DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO) - - - - - - - - - - base_DoSetClientSize(self, int width, int height) - - - - - - - base_DoSetVirtualSize(self, int x, int y) - - - - - - - base_DoGetSize() -> (width, height) - - - - - - - base_DoGetClientSize() -> (width, height) - - - - - - - base_DoGetPosition() -> (x,y) - - - - - - - base_DoGetVirtualSize(self) -> Size - - - base_DoGetBestSize(self) -> Size - - - base_InitDialog(self) - - - base_TransferDataToWindow(self) -> bool - - - base_TransferDataFromWindow(self) -> bool - - - base_Validate(self) -> bool - - - base_AcceptsFocus(self) -> bool - - - base_AcceptsFocusFromKeyboard(self) -> bool - - - base_GetMaxSize(self) -> Size - - - base_AddChild(self, Window child) - - - - - - base_RemoveChild(self, Window child) - - - - - - base_ShouldInheritColours(self) -> bool - - - base_ApplyParentThemeBackground(self, Colour c) - - - - - - base_GetDefaultAttributes(self) -> VisualAttributes - - - -#--------------------------------------------------------------------------- - - - - - - __init__(self) -> PrintData -__init__(self, PrintData data) -> PrintData - - - - - - __del__(self) - - - GetNoCopies(self) -> int - - - GetCollate(self) -> bool - - - GetOrientation(self) -> int - - - Ok(self) -> bool - - - GetPrinterName(self) -> String - - - GetColour(self) -> bool - - - GetDuplex(self) -> int - - - GetPaperId(self) -> int - - - GetPaperSize(self) -> Size - - - GetQuality(self) -> int - - - SetNoCopies(self, int v) - - - - - - SetCollate(self, bool flag) - - - - - - SetOrientation(self, int orient) - - - - - - SetPrinterName(self, String name) - - - - - - SetColour(self, bool colour) - - - - - - SetDuplex(self, int duplex) - - - - - - SetPaperId(self, int sizeId) - - - - - - SetPaperSize(self, Size sz) - - - - - - SetQuality(self, int quality) - - - - - - GetPrinterCommand(self) -> String - - - GetPrinterOptions(self) -> String - - - GetPreviewCommand(self) -> String - - - GetFilename(self) -> String - - - GetFontMetricPath(self) -> String - - - GetPrinterScaleX(self) -> double - - - GetPrinterScaleY(self) -> double - - - GetPrinterTranslateX(self) -> long - - - GetPrinterTranslateY(self) -> long - - - GetPrintMode(self) -> int - - - SetPrinterCommand(self, String command) - - - - - - SetPrinterOptions(self, String options) - - - - - - SetPreviewCommand(self, String command) - - - - - - SetFilename(self, String filename) - - - - - - SetFontMetricPath(self, String path) - - - - - - SetPrinterScaleX(self, double x) - - - - - - SetPrinterScaleY(self, double y) - - - - - - SetPrinterScaling(self, double x, double y) - - - - - - - SetPrinterTranslateX(self, long x) - - - - - - SetPrinterTranslateY(self, long y) - - - - - - SetPrinterTranslation(self, long x, long y) - - - - - - - SetPrintMode(self, int printMode) - - - - - - GetOutputStream(self) -> OutputStream - - - SetOutputStream(self, OutputStream outputstream) - - - - - - - - - - __init__(self) -> PageSetupDialogData -__init__(self, PageSetupDialogData data) -> PageSetupDialogData - - - - - - __del__(self) - - - EnableHelp(self, bool flag) - - - - - - EnableMargins(self, bool flag) - - - - - - EnableOrientation(self, bool flag) - - - - - - EnablePaper(self, bool flag) - - - - - - EnablePrinter(self, bool flag) - - - - - - GetDefaultMinMargins(self) -> bool - - - GetEnableMargins(self) -> bool - - - GetEnableOrientation(self) -> bool - - - GetEnablePaper(self) -> bool - - - GetEnablePrinter(self) -> bool - - - GetEnableHelp(self) -> bool - - - GetDefaultInfo(self) -> bool - - - GetMarginTopLeft(self) -> Point - - - GetMarginBottomRight(self) -> Point - - - GetMinMarginTopLeft(self) -> Point - - - GetMinMarginBottomRight(self) -> Point - - - GetPaperId(self) -> int - - - GetPaperSize(self) -> Size - - - GetPrintData(self) -> PrintData - - - Ok(self) -> bool - - - SetDefaultInfo(self, bool flag) - - - - - - SetDefaultMinMargins(self, bool flag) - - - - - - SetMarginTopLeft(self, Point pt) - - - - - - SetMarginBottomRight(self, Point pt) - - - - - - SetMinMarginTopLeft(self, Point pt) - - - - - - SetMinMarginBottomRight(self, Point pt) - - - - - - SetPaperId(self, int id) - - - - - - SetPaperSize(self, Size size) - - - - - - SetPrintData(self, PrintData printData) - - - - - - - - - __init__(self, Window parent, PageSetupDialogData data=None) -> PageSetupDialog - - - - - - - GetPageSetupData(self) -> PageSetupDialogData - - - ShowModal(self) -> int - - - - - - - __init__(self) -> PrintDialogData -__init__(self, PrintData printData) -> PrintDialogData - - - - - - __del__(self) - - - GetFromPage(self) -> int - - - GetToPage(self) -> int - - - GetMinPage(self) -> int - - - GetMaxPage(self) -> int - - - GetNoCopies(self) -> int - - - GetAllPages(self) -> bool - - - GetSelection(self) -> bool - - - GetCollate(self) -> bool - - - GetPrintToFile(self) -> bool - - - GetSetupDialog(self) -> bool - - - SetFromPage(self, int v) - - - - - - SetToPage(self, int v) - - - - - - SetMinPage(self, int v) - - - - - - SetMaxPage(self, int v) - - - - - - SetNoCopies(self, int v) - - - - - - SetAllPages(self, bool flag) - - - - - - SetSelection(self, bool flag) - - - - - - SetCollate(self, bool flag) - - - - - - SetPrintToFile(self, bool flag) - - - - - - SetSetupDialog(self, bool flag) - - - - - - EnablePrintToFile(self, bool flag) - - - - - - EnableSelection(self, bool flag) - - - - - - EnablePageNumbers(self, bool flag) - - - - - - EnableHelp(self, bool flag) - - - - - - GetEnablePrintToFile(self) -> bool - - - GetEnableSelection(self) -> bool - - - GetEnablePageNumbers(self) -> bool - - - GetEnableHelp(self) -> bool - - - Ok(self) -> bool - - - GetPrintData(self) -> PrintData - - - SetPrintData(self, PrintData printData) - - - - - - - - - __init__(self, Window parent, PrintDialogData data=None) -> PrintDialog - - - - - - - GetPrintDialogData(self) -> PrintDialogData - - - GetPrintDC(self) -> DC - - - ShowModal(self) -> int - - - - - - __init__(self, PrintDialogData data=None) -> Printer - - - - - - __del__(self) - - - CreateAbortWindow(self, Window parent, Printout printout) - - - - - - - GetPrintDialogData(self) -> PrintDialogData - - - Print(self, Window parent, Printout printout, int prompt=True) -> bool - - - - - - - - PrintDialog(self, Window parent) -> DC - - - - - - ReportError(self, Window parent, Printout printout, String message) - - - - - - - - Setup(self, Window parent) -> bool - - - - - - GetAbort(self) -> bool - - - GetLastError() -> int - - - - - - __init__(self, String title=PrintoutTitleStr) -> Printout - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - GetTitle(self) -> String - - - GetDC(self) -> DC - - - SetDC(self, DC dc) - - - - - - SetPageSizePixels(self, int w, int h) - - - - - - - GetPageSizePixels() -> (w, h) - - - - - - - SetPageSizeMM(self, int w, int h) - - - - - - - GetPageSizeMM() -> (w, h) - - - - - - - SetPPIScreen(self, int x, int y) - - - - - - - GetPPIScreen() -> (x,y) - - - - - - - SetPPIPrinter(self, int x, int y) - - - - - - - GetPPIPrinter() -> (x,y) - - - - - - - IsPreview(self) -> bool - - - SetIsPreview(self, bool p) - - - - - - base_OnBeginDocument(self, int startPage, int endPage) -> bool - - - - - - - base_OnEndDocument(self) - - - base_OnBeginPrinting(self) - - - base_OnEndPrinting(self) - - - base_OnPreparePrinting(self) - - - base_HasPage(self, int page) -> bool - - - - - - base_GetPageInfo() -> (minPage, maxPage, pageFrom, pageTo) - - - - - - - - - - - - __init__(self, PrintPreview preview, Window parent, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, - String name=PreviewCanvasNameStr) -> PreviewCanvas - - - - - - - - - - - - - - __init__(self, PrintPreview preview, Frame parent, String title, Point pos=DefaultPosition, - Size size=DefaultSize, - long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> PreviewFrame - - - - - - - - - - - - Initialize(self) - - - CreateControlBar(self) - - - CreateCanvas(self) - - - GetControlBar(self) -> PreviewControlBar - - - - - - __init__(self, PrintPreview preview, long buttons, Window parent, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=TAB_TRAVERSAL, String name=PanelNameStr) -> PreviewControlBar - - - - - - - - - - - - GetZoomControl(self) -> int - - - SetZoomControl(self, int zoom) - - - - - - GetPrintPreview(self) -> PrintPreview - - - OnNext(self) - - - OnPrevious(self) - - - OnFirst(self) - - - OnLast(self) - - - OnGoto(self) - - - - - - - - - - - - - __init__(self, Printout printout, Printout printoutForPrinting, PrintDialogData data=None) -> PrintPreview -__init__(self, Printout printout, Printout printoutForPrinting, PrintData data) -> PrintPreview - - - - - - - - SetCurrentPage(self, int pageNum) -> bool - - - - - - GetCurrentPage(self) -> int - - - SetPrintout(self, Printout printout) - - - - - - GetPrintout(self) -> Printout - - - GetPrintoutForPrinting(self) -> Printout - - - SetFrame(self, Frame frame) - - - - - - SetCanvas(self, PreviewCanvas canvas) - - - - - - GetFrame(self) -> Frame - - - GetCanvas(self) -> PreviewCanvas - - - PaintPage(self, PreviewCanvas canvas, DC dc) -> bool - - - - - - - DrawBlankPage(self, PreviewCanvas canvas, DC dc) -> bool - - - - - - - RenderPage(self, int pageNum) -> bool - - - - - - AdjustScrollbars(self, PreviewCanvas canvas) - - - - - - GetPrintDialogData(self) -> PrintDialogData - - - SetZoom(self, int percent) - - - - - - GetZoom(self) -> int - - - GetMaxPage(self) -> int - - - GetMinPage(self) -> int - - - Ok(self) -> bool - - - SetOk(self, bool ok) - - - - - - Print(self, bool interactive) -> bool - - - - - - DetermineScaling(self) - - - - - - - - - - - - - __init__(self, Printout printout, Printout printoutForPrinting, PrintDialogData data=None) -> PyPrintPreview -__init__(self, Printout printout, Printout printoutForPrinting, PrintData data) -> PyPrintPreview - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_SetCurrentPage(self, int pageNum) -> bool - - - - - - base_PaintPage(self, PreviewCanvas canvas, DC dc) -> bool - - - - - - - base_DrawBlankPage(self, PreviewCanvas canvas, DC dc) -> bool - - - - - - - base_RenderPage(self, int pageNum) -> bool - - - - - - base_SetZoom(self, int percent) - - - - - - base_Print(self, bool interactive) -> bool - - - - - - base_DetermineScaling(self) - - - - - - __init__(self, PrintPreview preview, Frame parent, String title, Point pos=DefaultPosition, - Size size=DefaultSize, - long style=DEFAULT_FRAME_STYLE, String name=FrameNameStr) -> PyPreviewFrame - - - - - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetPreviewCanvas(self, PreviewCanvas canvas) - - - - - - SetControlBar(self, PreviewControlBar bar) - - - - - - base_Initialize(self) - - - base_CreateCanvas(self) - - - base_CreateControlBar(self) - - - - - - __init__(self, PrintPreview preview, long buttons, Window parent, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, String name=PanelNameStr) -> PyPreviewControlBar - - - - - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetPrintPreview(self, PrintPreview preview) - - - - - - base_CreateButtons(self) - - - base_SetZoomControl(self, int zoom) - - - - - - - - - wx = _core - -#--------------------------------------------------------------------------- - - - A button is a control that contains a text string, and is one of the most -common elements of a GUI. It may be placed on a dialog box or panel, or -indeed almost any other window. - -Window Styles -------------- - ============== ========================================== - wx.BU_LEFT Left-justifies the label. Windows and GTK+ only. - wx.BU_TOP Aligns the label to the top of the button. - Windows and GTK+ only. - wx.BU_RIGHT Right-justifies the bitmap label. Windows and GTK+ only. - wx.BU_BOTTOM Aligns the label to the bottom of the button. - Windows and GTK+ only. - wx.BU_EXACTFIT Creates the button as small as possible - instead of making it of the standard size - (which is the default behaviour.) - ============== ========================================== - -Events ------- - ============ ========================================== - EVT_BUTTON Sent when the button is clicked. - ============ ========================================== - -:see: `wx.BitmapButton` - - - - __init__(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=ButtonNameStr) -> Button - Create and show a button. The preferred way to create standard -buttons is to use a standard ID and an empty label. In this case -wxWigets will automatically use a stock label that coresponds to the -ID given. In additon, the button will be decorated with stock icons -under GTK+ 2. - -The stock IDs and coresponding labels are - - ================== ==================== - wx.ID_ADD 'Add' - wx.ID_APPLY '\\&Apply' - wx.ID_BOLD '\\&Bold' - wx.ID_CANCEL '\\&Cancel' - wx.ID_CLEAR '\\&Clear' - wx.ID_CLOSE '\\&Close' - wx.ID_COPY '\\&Copy' - wx.ID_CUT 'Cu\\&t' - wx.ID_DELETE '\\&Delete' - wx.ID_FIND '\\&Find' - wx.ID_REPLACE 'Find and rep\\&lace' - wx.ID_BACKWARD '\\&Back' - wx.ID_DOWN '\\&Down' - wx.ID_FORWARD '\\&Forward' - wx.ID_UP '\\&Up' - wx.ID_HELP '\\&Help' - wx.ID_HOME '\\&Home' - wx.ID_INDENT 'Indent' - wx.ID_INDEX '\\&Index' - wx.ID_ITALIC '\\&Italic' - wx.ID_JUSTIFY_CENTER 'Centered' - wx.ID_JUSTIFY_FILL 'Justified' - wx.ID_JUSTIFY_LEFT 'Align Left' - wx.ID_JUSTIFY_RIGHT 'Align Right' - wx.ID_NEW '\\&New' - wx.ID_NO '\\&No' - wx.ID_OK '\\&OK' - wx.ID_OPEN '\\&Open' - wx.ID_PASTE '\\&Paste' - wx.ID_PREFERENCES '\\&Preferences' - wx.ID_PRINT '\\&Print' - wx.ID_PREVIEW 'Print previe\\&w' - wx.ID_PROPERTIES '\\&Properties' - wx.ID_EXIT '\\&Quit' - wx.ID_REDO '\\&Redo' - wx.ID_REFRESH 'Refresh' - wx.ID_REMOVE 'Remove' - wx.ID_REVERT_TO_SAVED 'Revert to Saved' - wx.ID_SAVE '\\&Save' - wx.ID_SAVEAS 'Save \\&As...' - wx.ID_STOP '\\&Stop' - wx.ID_UNDELETE 'Undelete' - wx.ID_UNDERLINE '\\&Underline' - wx.ID_UNDO '\\&Undo' - wx.ID_UNINDENT '\\&Unindent' - wx.ID_YES '\\&Yes' - wx.ID_ZOOM_100 '\\&Actual Size' - wx.ID_ZOOM_FIT 'Zoom to \\&Fit' - wx.ID_ZOOM_IN 'Zoom \\&In' - wx.ID_ZOOM_OUT 'Zoom \\&Out' - ================== ==================== - - - - - - - - - - - - - - PreButton() -> Button - Precreate a Button for 2-phase creation. - - - Create(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=ButtonNameStr) -> bool - Acutally create the GUI Button for 2-phase creation. - - - - - - - - - - - - - SetDefault(self) - This sets the button to be the default item for the panel or dialog box. - - - GetDefaultSize() -> Size - Returns the default button size for this platform. - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - - A Button that contains a bitmap. A bitmap button can be supplied with a -single bitmap, and wxWidgets will draw all button states using this bitmap. If -the application needs more control, additional bitmaps for the selected state, -unpressed focused state, and greyed-out state may be supplied. - -Window Styles -------------- - ============== ============================================= - wx.BU_AUTODRAW If this is specified, the button will be drawn - automatically using the label bitmap only, - providing a 3D-look border. If this style is - not specified, the button will be drawn - without borders and using all provided - bitmaps. WIN32 only. - wx.BU_LEFT Left-justifies the label. WIN32 only. - wx.BU_TOP Aligns the label to the top of the button. WIN32 - only. - wx.BU_RIGHT Right-justifies the bitmap label. WIN32 only. - wx.BU_BOTTOM Aligns the label to the bottom of the - button. WIN32 only. - wx.BU_EXACTFIT Creates the button as small as possible - instead of making it of the standard size - (which is the default behaviour.) - ============== ============================================= - -Events ------- - =========== ================================== - EVT_BUTTON Sent when the button is clicked. - =========== ================================== - -:see: `wx.Button`, `wx.Bitmap` - - - - __init__(self, Window parent, int id=-1, Bitmap bitmap=wxNullBitmap, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=BU_AUTODRAW, Validator validator=DefaultValidator, - String name=ButtonNameStr) -> BitmapButton - Create and show a button with a bitmap for the label. - - - - - - - - - - - - - PreBitmapButton() -> BitmapButton - Precreate a BitmapButton for 2-phase creation. - - - Create(self, Window parent, int id=-1, Bitmap bitmap=wxNullBitmap, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=BU_AUTODRAW, Validator validator=DefaultValidator, - String name=ButtonNameStr) -> bool - Acutally create the GUI BitmapButton for 2-phase creation. - - - - - - - - - - - - - GetBitmapLabel(self) -> Bitmap - Returns the label bitmap (the one passed to the constructor). - - - GetBitmapDisabled(self) -> Bitmap - Returns the bitmap for the disabled state. - - - GetBitmapFocus(self) -> Bitmap - Returns the bitmap for the focused state. - - - GetBitmapSelected(self) -> Bitmap - Returns the bitmap for the selected state. - - - SetBitmapDisabled(self, Bitmap bitmap) - Sets the bitmap for the disabled button appearance. - - - - - - SetBitmapFocus(self, Bitmap bitmap) - Sets the bitmap for the button appearance when it has the keyboard focus. - - - - - - SetBitmapSelected(self, Bitmap bitmap) - Sets the bitmap for the selected (depressed) button appearance. - - - - - - SetBitmapLabel(self, Bitmap bitmap) - Sets the bitmap label for the button. This is the bitmap used for the -unselected state, and for all other states if no other bitmaps are provided. - - - - - - SetMargins(self, int x, int y) - - - - - - - GetMarginX(self) -> int - - - GetMarginY(self) -> int - - - -#--------------------------------------------------------------------------- - - - A checkbox is a labelled box which by default is either on (the -checkmark is visible) or off (no checkmark). Optionally (When the -wx.CHK_3STATE style flag is set) it can have a third state, called the -mixed or undetermined state. Often this is used as a "Does Not -Apply" state. - -Window Styles -------------- - ================================= =============================== - wx.CHK_2STATE Create a 2-state checkbox. - This is the default. - wx.CHK_3STATE Create a 3-state checkbox. - wx.CHK_ALLOW_3RD_STATE_FOR_USER By default a user can't set a - 3-state checkbox to the - third state. It can only be - done from code. Using this - flags allows the user to set - the checkbox to the third - state by clicking. - wx.ALIGN_RIGHT Makes the - text appear on the left of - the checkbox. - ================================= =============================== - -Events ------- - =============================== =============================== - EVT_CHECKBOX Sent when checkbox is clicked. - =============================== =============================== - - - - __init__(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=CheckBoxNameStr) -> CheckBox - Creates and shows a CheckBox control - - - - - - - - - - - - - PreCheckBox() -> CheckBox - Precreate a CheckBox for 2-phase creation. - - - Create(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=CheckBoxNameStr) -> bool - Actually create the GUI CheckBox for 2-phase creation. - - - - - - - - - - - - - GetValue(self) -> bool - Gets the state of a 2-state CheckBox. Returns True if it is checked, -False otherwise. - - - IsChecked(self) -> bool - Similar to GetValue, but raises an exception if it is not a 2-state -CheckBox. - - - SetValue(self, bool state) - Set the state of a 2-state CheckBox. Pass True for checked, False for -unchecked. - - - - - - Get3StateValue(self) -> int - Returns wx.CHK_UNCHECKED when the CheckBox is unchecked, -wx.CHK_CHECKED when it is checked and wx.CHK_UNDETERMINED when it's in -the undetermined state. Raises an exceptiion when the function is -used with a 2-state CheckBox. - - - Set3StateValue(self, int state) - Sets the CheckBox to the given state. The state parameter can be one -of the following: wx.CHK_UNCHECKED (Check is off), wx.CHK_CHECKED (the -Check is on) or wx.CHK_UNDETERMINED (Check is mixed). Raises an -exception when the CheckBox is a 2-state checkbox and setting the -state to wx.CHK_UNDETERMINED. - - - - - - Is3State(self) -> bool - Returns whether or not the CheckBox is a 3-state CheckBox. - - - Is3rdStateAllowedForUser(self) -> bool - Returns whether or not the user can set the CheckBox to the third -state. - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - A Choice control is used to select one of a list of strings. -Unlike a `wx.ListBox`, only the selection is visible until the -user pulls down the menu of choices. - -Events ------- - ================ ========================================== - EVT_CHOICE Sent when an item in the list is selected. - ================ ========================================== - - - - __init__(Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize, - List choices=[], long style=0, Validator validator=DefaultValidator, - String name=ChoiceNameStr) -> Choice - Create and show a Choice control - - - - - - - - - - - - - PreChoice() -> Choice - Precreate a Choice control for 2-phase creation. - - - Create(Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize, - List choices=[], long style=0, Validator validator=DefaultValidator, - String name=ChoiceNameStr) -> bool - Actually create the GUI Choice control for 2-phase creation - - - - - - - - - - - - - SetSelection(self, int n) - Select the n'th item (zero based) in the list. - - - - - - SetStringSelection(self, String string) -> bool - Select the item with the specifed string - - - - - - SetString(self, int n, String string) - Set the label for the n'th item (zero based) in the list. - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - A combobox is like a combination of an edit control and a -listbox. It can be displayed as static list with editable or -read-only text field; or a drop-down list with text field. - -A combobox permits a single selection only. Combobox items are -numbered from zero. - -Styles ------- - ================ =============================================== - wx.CB_SIMPLE Creates a combobox with a permanently - displayed list. Windows only. - - wx.CB_DROPDOWN Creates a combobox with a drop-down list. - - wx.CB_READONLY Same as wxCB_DROPDOWN but only the strings - specified as the combobox choices can be - selected, it is impossible to select - (even from a program) a string which is - not in the choices list. - - wx.CB_SORT Sorts the entries in the list alphabetically. - ================ =============================================== - -Events -------- - ================ =============================================== - EVT_COMBOBOX Sent when an item on the list is selected. - EVT_TEXT Sent when the combobox text changes. - ================ =============================================== - - - - - __init__(Window parent, int id, String value=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - List choices=[], long style=0, Validator validator=DefaultValidator, - String name=ComboBoxNameStr) -> ComboBox - Constructor, creates and shows a ComboBox control. - - - - - - - - - - - - - - PreComboBox() -> ComboBox - Precreate a ComboBox control for 2-phase creation. - - - Create(Window parent, int id, String value=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - List choices=[], long style=0, Validator validator=DefaultValidator, - String name=ChoiceNameStr) -> bool - Actually create the GUI wxComboBox control for 2-phase creation - - - - - - - - - - - - - - GetValue(self) -> String - Returns the current value in the combobox text field. - - - SetValue(self, String value) - - - - - - Copy(self) - Copies the selected text to the clipboard. - - - Cut(self) - Copies the selected text to the clipboard and removes the selection. - - - Paste(self) - Pastes text from the clipboard to the text field. - - - SetInsertionPoint(self, long pos) - Sets the insertion point in the combobox text field. - - - - - - GetInsertionPoint(self) -> long - Returns the insertion point for the combobox's text field. - - - GetLastPosition(self) -> long - Returns the last position in the combobox text field. - - - Replace(self, long from, long to, String value) - Replaces the text between two positions with the given text, in the -combobox text field. - - - - - - - - SetSelection(self, int n) - Sets the item at index 'n' to be the selected item. - - - - - - SetMark(self, long from, long to) - Selects the text between the two positions in the combobox text field. - - - - - - - SetStringSelection(self, String string) -> bool - Select the item with the specifed string - - - - - - SetString(self, int n, String string) - Set the label for the n'th item (zero based) in the list. - - - - - - - SetEditable(self, bool editable) - - - - - - SetInsertionPointEnd(self) - Sets the insertion point at the end of the combobox text field. - - - Remove(self, long from, long to) - Removes the text between the two positions in the combobox text field. - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, int range=100, Point pos=DefaultPosition, - Size size=DefaultSize, long style=GA_HORIZONTAL, - Validator validator=DefaultValidator, - String name=GaugeNameStr) -> Gauge - - - - - - - - - - - - - PreGauge() -> Gauge - - - Create(self, Window parent, int id=-1, int range=100, Point pos=DefaultPosition, - Size size=DefaultSize, long style=GA_HORIZONTAL, - Validator validator=DefaultValidator, - String name=GaugeNameStr) -> bool - - - - - - - - - - - - - SetRange(self, int range) - - - - - - GetRange(self) -> int - - - SetValue(self, int pos) - - - - - - GetValue(self) -> int - - - IsVertical(self) -> bool - - - SetShadowWidth(self, int w) - - - - - - GetShadowWidth(self) -> int - - - SetBezelFace(self, int w) - - - - - - GetBezelFace(self) -> int - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, String name=StaticBoxNameStr) -> StaticBox - - - - - - - - - - - - PreStaticBox() -> StaticBox - - - Create(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, String name=StaticBoxNameStr) -> bool - - - - - - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=LI_HORIZONTAL, - String name=StaticTextNameStr) -> StaticLine - - - - - - - - - - - PreStaticLine() -> StaticLine - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=LI_HORIZONTAL, - String name=StaticTextNameStr) -> bool - - - - - - - - - - - IsVertical(self) -> bool - - - GetDefaultSize() -> int - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, String name=StaticTextNameStr) -> StaticText - - - - - - - - - - - - PreStaticText() -> StaticText - - - Create(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, String name=StaticTextNameStr) -> bool - - - - - - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Bitmap bitmap=wxNullBitmap, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, String name=StaticBitmapNameStr) -> StaticBitmap - - - - - - - - - - - - PreStaticBitmap() -> StaticBitmap - - - Create(self, Window parent, int id=-1, Bitmap bitmap=wxNullBitmap, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, String name=StaticBitmapNameStr) -> bool - - - - - - - - - - - - GetBitmap(self) -> Bitmap - - - SetBitmap(self, Bitmap bitmap) - - - - - - SetIcon(self, Icon icon) - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray, - long style=0, Validator validator=DefaultValidator, - String name=ListBoxNameStr) -> ListBox - - - - - - - - - - - - - PreListBox() -> ListBox - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray, - long style=0, Validator validator=DefaultValidator, - String name=ListBoxNameStr) -> bool - - - - - - - - - - - - - Insert(self, String item, int pos, PyObject clientData=None) - Insert an item into the control before the item at the ``pos`` index, -optionally associating some data object with the item. - - - - - - - - InsertItems(self, wxArrayString items, int pos) - - - - - - - Set(self, wxArrayString items) - - - - - - IsSelected(self, int n) -> bool - - - - - - SetSelection(self, int n, bool select=True) - - - - - - - Select(self, int n) - Sets the item at index 'n' to be the selected item. - - - - - - Deselect(self, int n) - - - - - - DeselectAll(self, int itemToLeaveSelected=-1) - - - - - - SetStringSelection(self, String s, bool select=True) -> bool - - - - - - - GetSelections(self) -> PyObject - - - SetFirstItem(self, int n) - - - - - - SetFirstItemStr(self, String s) - - - - - - EnsureVisible(self, int n) - - - - - - AppendAndEnsureVisible(self, String s) - - - - - - IsSorted(self) -> bool - - - SetItemForegroundColour(self, int item, Colour c) - - - - - - - SetItemBackgroundColour(self, int item, Colour c) - - - - - - - SetItemFont(self, int item, Font f) - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray, - long style=0, Validator validator=DefaultValidator, - String name=ListBoxNameStr) -> CheckListBox - - - - - - - - - - - - - PreCheckListBox() -> CheckListBox - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, wxArrayString choices=wxPyEmptyStringArray, - long style=0, Validator validator=DefaultValidator, - String name=ListBoxNameStr) -> bool - - - - - - - - - - - - - IsChecked(self, int index) -> bool - - - - - - Check(self, int index, int check=True) - - - - - - - GetItemHeight(self) -> int - - - HitTest(self, Point pt) -> int - Test where the given (in client coords) point lies - - - - - - HitTestXY(self, int x, int y) -> int - Test where the given (in client coords) point lies - - - - - - - -#--------------------------------------------------------------------------- - - - - __init__(self, Colour colText=wxNullColour, Colour colBack=wxNullColour, - Font font=wxNullFont, int alignment=TEXT_ALIGNMENT_DEFAULT) -> TextAttr - - - - - - - - - __del__(self) - - - Init(self) - - - SetTextColour(self, Colour colText) - - - - - - SetBackgroundColour(self, Colour colBack) - - - - - - SetFont(self, Font font, long flags=TEXT_ATTR_FONT) - - - - - - - SetAlignment(self, int alignment) - - - - - - SetTabs(self, wxArrayInt tabs) - - - - - - SetLeftIndent(self, int indent, int subIndent=0) - - - - - - - SetRightIndent(self, int indent) - - - - - - SetFlags(self, long flags) - - - - - - HasTextColour(self) -> bool - - - HasBackgroundColour(self) -> bool - - - HasFont(self) -> bool - - - HasAlignment(self) -> bool - - - HasTabs(self) -> bool - - - HasLeftIndent(self) -> bool - - - HasRightIndent(self) -> bool - - - HasFlag(self, long flag) -> bool - - - - - - GetTextColour(self) -> Colour - - - GetBackgroundColour(self) -> Colour - - - GetFont(self) -> Font - - - GetAlignment(self) -> int - - - GetTabs(self) -> wxArrayInt - - - GetLeftIndent(self) -> long - - - GetLeftSubIndent(self) -> long - - - GetRightIndent(self) -> long - - - GetFlags(self) -> long - - - IsDefault(self) -> bool - - - Combine(TextAttr attr, TextAttr attrDef, TextCtrl text) -> TextAttr - - - - - - - - - - - __init__(self, Window parent, int id=-1, String value=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=TextCtrlNameStr) -> TextCtrl - - - - - - - - - - - - - PreTextCtrl() -> TextCtrl - - - Create(self, Window parent, int id=-1, String value=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=TextCtrlNameStr) -> bool - - - - - - - - - - - - - GetValue(self) -> String - - - SetValue(self, String value) - - - - - - GetRange(self, long from, long to) -> String - - - - - - - GetLineLength(self, long lineNo) -> int - - - - - - GetLineText(self, long lineNo) -> String - - - - - - GetNumberOfLines(self) -> int - - - IsModified(self) -> bool - - - IsEditable(self) -> bool - - - IsSingleLine(self) -> bool - - - IsMultiLine(self) -> bool - - - GetSelection() -> (from, to) - If the return values from and to are the same, there is no selection. - - - - - - - GetStringSelection(self) -> String - - - Clear(self) - - - Replace(self, long from, long to, String value) - - - - - - - - Remove(self, long from, long to) - - - - - - - LoadFile(self, String file) -> bool - - - - - - SaveFile(self, String file=EmptyString) -> bool - - - - - - MarkDirty(self) - - - DiscardEdits(self) - - - SetMaxLength(self, unsigned long len) - - - - - - WriteText(self, String text) - - - - - - AppendText(self, String text) - - - - - - EmulateKeyPress(self, KeyEvent event) -> bool - - - - - - SetStyle(self, long start, long end, TextAttr style) -> bool - - - - - - - - GetStyle(self, long position, TextAttr style) -> bool - - - - - - - SetDefaultStyle(self, TextAttr style) -> bool - - - - - - GetDefaultStyle(self) -> TextAttr - - - XYToPosition(self, long x, long y) -> long - - - - - - - PositionToXY(long pos) -> (x, y) - - - - - - - - ShowPosition(self, long pos) - - - - - - HitTest(Point pt) -> (result, row, col) - Find the row, col coresponding to the character at the point given in -pixels. NB: pt is in device coords but is not adjusted for the client -area origin nor scrolling. - - - - - - - - HitTestPos(Point pt) -> (result, position) - Find the character position in the text coresponding to the point -given in pixels. NB: pt is in device coords but is not adjusted for -the client area origin nor scrolling. - - - - - - - Copy(self) - - - Cut(self) - - - Paste(self) - - - CanCopy(self) -> bool - - - CanCut(self) -> bool - - - CanPaste(self) -> bool - - - Undo(self) - - - Redo(self) - - - CanUndo(self) -> bool - - - CanRedo(self) -> bool - - - SetInsertionPoint(self, long pos) - - - - - - SetInsertionPointEnd(self) - - - GetInsertionPoint(self) -> long - - - GetLastPosition(self) -> long - - - SetSelection(self, long from, long to) - - - - - - - SelectAll(self) - - - SetEditable(self, bool editable) - - - - - - write(self, String text) - - - - - - GetString(self, long from, long to) -> String - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - - - - __init__(self, int winid, MouseEvent evtMouse, long start, long end) -> TextUrlEvent - - - - - - - - - GetMouseEvent(self) -> MouseEvent - - - GetURLStart(self) -> long - - - GetURLEnd(self) -> long - - - -EVT_TEXT = wx.PyEventBinder( wxEVT_COMMAND_TEXT_UPDATED, 1) -EVT_TEXT_ENTER = wx.PyEventBinder( wxEVT_COMMAND_TEXT_ENTER, 1) -EVT_TEXT_URL = wx.PyEventBinder( wxEVT_COMMAND_TEXT_URL, 1) -EVT_TEXT_MAXLEN = wx.PyEventBinder( wxEVT_COMMAND_TEXT_MAXLEN, 1) - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=SB_HORIZONTAL, - Validator validator=DefaultValidator, String name=ScrollBarNameStr) -> ScrollBar - - - - - - - - - - - - PreScrollBar() -> ScrollBar - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=SB_HORIZONTAL, - Validator validator=DefaultValidator, String name=ScrollBarNameStr) -> bool - Do the 2nd phase and create the GUI control. - - - - - - - - - - - - GetThumbPosition(self) -> int - - - GetThumbSize(self) -> int - - - GetPageSize(self) -> int - - - GetRange(self) -> int - - - IsVertical(self) -> bool - - - SetThumbPosition(self, int viewStart) - - - - - - SetScrollbar(self, int position, int thumbSize, int range, int pageSize, - bool refresh=True) - Sets the scrollbar properties of a built-in scrollbar. - :param orientation: Determines the scrollbar whose page size is to - be set. May be wx.HORIZONTAL or wx.VERTICAL. - - :param position: The position of the scrollbar in scroll units. - - :param thumbSize: The size of the thumb, or visible portion of the - scrollbar, in scroll units. - - :param range: The maximum position of the scrollbar. - - :param refresh: True to redraw the scrollbar, false otherwise. - - - - - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=SP_HORIZONTAL, - String name=SPIN_BUTTON_NAME) -> SpinButton - - - - - - - - - - - PreSpinButton() -> SpinButton - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=SP_HORIZONTAL, - String name=SPIN_BUTTON_NAME) -> bool - - - - - - - - - - - GetValue(self) -> int - - - GetMin(self) -> int - - - GetMax(self) -> int - - - SetValue(self, int val) - - - - - - SetMin(self, int minVal) - - - - - - SetMax(self, int maxVal) - - - - - - SetRange(self, int minVal, int maxVal) - - - - - - - IsVertical(self) -> bool - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - - - - __init__(self, Window parent, int id=-1, String value=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=SP_ARROW_KEYS, int min=0, int max=100, - int initial=0, String name=SpinCtrlNameStr) -> SpinCtrl - - - - - - - - - - - - - - - PreSpinCtrl() -> SpinCtrl - - - Create(self, Window parent, int id=-1, String value=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=SP_ARROW_KEYS, int min=0, int max=100, - int initial=0, String name=SpinCtrlNameStr) -> bool - - - - - - - - - - - - - - - GetValue(self) -> int - - - SetValue(self, int value) - - - - - - SetValueString(self, String text) - - - - - - SetRange(self, int minVal, int maxVal) - - - - - - - GetMin(self) -> int - - - GetMax(self) -> int - - - SetSelection(self, long from, long to) - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int winid=0) -> SpinEvent - - - - - - - GetPosition(self) -> int - - - SetPosition(self, int pos) - - - - - - -EVT_SPIN_UP = wx.PyEventBinder( wx.wxEVT_SCROLL_LINEUP, 1) -EVT_SPIN_DOWN = wx.PyEventBinder( wx.wxEVT_SCROLL_LINEDOWN, 1) -EVT_SPIN = wx.PyEventBinder( wx.wxEVT_SCROLL_THUMBTRACK, 1) -EVT_SPINCTRL = wx.PyEventBinder( wxEVT_COMMAND_SPINCTRL_UPDATED, 1) - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - wxArrayString choices=wxPyEmptyStringArray, - int majorDimension=0, long style=RA_HORIZONTAL, - Validator validator=DefaultValidator, - String name=RadioBoxNameStr) -> RadioBox - - - - - - - - - - - - - - - PreRadioBox() -> RadioBox - - - Create(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - wxArrayString choices=wxPyEmptyStringArray, - int majorDimension=0, long style=RA_HORIZONTAL, - Validator validator=DefaultValidator, - String name=RadioBoxNameStr) -> bool - - - - - - - - - - - - - - - SetSelection(self, int n) - - - - - - GetSelection(self) -> int - - - GetStringSelection(self) -> String - - - SetStringSelection(self, String s) -> bool - - - - - - GetCount(self) -> int - - - FindString(self, String s) -> int - - - - - - GetString(self, int n) -> String - - - - - - SetString(self, int n, String label) - - - - - - - EnableItem(self, int n, bool enable=True) - - - - - - - ShowItem(self, int n, bool show=True) - - - - - - - GetColumnCount(self) -> int - - - GetRowCount(self) -> int - - - GetNextItem(self, int item, int dir, long style) -> int - - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=RadioButtonNameStr) -> RadioButton - - - - - - - - - - - - - PreRadioButton() -> RadioButton - - - Create(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=RadioButtonNameStr) -> bool - - - - - - - - - - - - - GetValue(self) -> bool - - - SetValue(self, bool value) - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, int value=0, int minValue=0, - int maxValue=100, Point pos=DefaultPosition, - Size size=DefaultSize, long style=SL_HORIZONTAL, - Validator validator=DefaultValidator, - String name=SliderNameStr) -> Slider - - - - - - - - - - - - - - - PreSlider() -> Slider - - - Create(self, Window parent, int id=-1, int value=0, int minValue=0, - int maxValue=100, Point pos=DefaultPosition, - Size size=DefaultSize, long style=SL_HORIZONTAL, - Validator validator=DefaultValidator, - String name=SliderNameStr) -> bool - - - - - - - - - - - - - - - GetValue(self) -> int - - - SetValue(self, int value) - - - - - - SetRange(self, int minValue, int maxValue) - - - - - - - GetMin(self) -> int - - - GetMax(self) -> int - - - SetMin(self, int minValue) - - - - - - SetMax(self, int maxValue) - - - - - - SetLineSize(self, int lineSize) - - - - - - SetPageSize(self, int pageSize) - - - - - - GetLineSize(self) -> int - - - GetPageSize(self) -> int - - - SetThumbLength(self, int lenPixels) - - - - - - GetThumbLength(self) -> int - - - SetTickFreq(self, int n, int pos=1) - - - - - - - GetTickFreq(self) -> int - - - ClearTicks(self) - - - SetTick(self, int tickPos) - - - - - - ClearSel(self) - - - GetSelEnd(self) -> int - - - GetSelStart(self) -> int - - - SetSelection(self, int min, int max) - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - EVT_TOGGLEBUTTON = wx.PyEventBinder( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, 1) - - - - - __init__(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=ToggleButtonNameStr) -> ToggleButton - - - - - - - - - - - - - PreToggleButton() -> ToggleButton - - - Create(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=0, Validator validator=DefaultValidator, - String name=ToggleButtonNameStr) -> bool - - - - - - - - - - - - - SetValue(self, bool value) - - - - - - GetValue(self) -> bool - - - SetLabel(self, String label) - Sets the item's text. - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - GetPageCount(self) -> size_t - - - GetPage(self, size_t n) -> Window - - - - - - GetSelection(self) -> int - - - SetPageText(self, size_t n, String strText) -> bool - - - - - - - GetPageText(self, size_t n) -> String - - - - - - SetImageList(self, ImageList imageList) - - - - - - AssignImageList(self, ImageList imageList) - - - - - - GetImageList(self) -> ImageList - - - GetPageImage(self, size_t n) -> int - - - - - - SetPageImage(self, size_t n, int imageId) -> bool - - - - - - - SetPageSize(self, Size size) - - - - - - CalcSizeFromPage(self, Size sizePage) -> Size - - - - - - DeletePage(self, size_t n) -> bool - - - - - - RemovePage(self, size_t n) -> bool - - - - - - DeleteAllPages(self) -> bool - - - AddPage(self, Window page, String text, bool select=False, int imageId=-1) -> bool - - - - - - - - - InsertPage(self, size_t n, Window page, String text, bool select=False, - int imageId=-1) -> bool - - - - - - - - - - SetSelection(self, size_t n) -> int - - - - - - AdvanceSelection(self, bool forward=True) - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int id=0, int nSel=-1, - int nOldSel=-1) -> BookCtrlEvent - - - - - - - - - GetSelection(self) -> int - - - SetSelection(self, int nSel) - - - - - - GetOldSelection(self) -> int - - - SetOldSelection(self, int nOldSel) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=NOTEBOOK_NAME) -> Notebook - - - - - - - - - - - PreNotebook() -> Notebook - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=NOTEBOOK_NAME) -> bool - - - - - - - - - - - GetRowCount(self) -> int - - - SetPadding(self, Size padding) - - - - - - SetTabSize(self, Size sz) - - - - - - HitTest(Point pt) -> (tab, where) - Returns the tab which is hit, and flags indicating where using -wx.NB_HITTEST flags. - - - - - - - CalcSizeFromPage(self, Size sizePage) -> Size - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int id=0, int nSel=-1, - int nOldSel=-1) -> NotebookEvent - - - - - - - - - - # wxNotebook events - EVT_NOTEBOOK_PAGE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, 1 ) - EVT_NOTEBOOK_PAGE_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, 1 ) - - -#---------------------------------------------------------------------------- - -class NotebookPage(wx.Panel): - """ - There is an old (and apparently unsolvable) bug when placing a - window with a nonstandard background colour in a wxNotebook on - wxGTK, as the notbooks's background colour would always be used - when the window is refreshed. The solution is to place a panel in - the notbook and the coloured window on the panel, sized to cover - the panel. This simple class does that for you, just put an - instance of this in the notebook and make your regular window a - child of this one and it will handle the resize for you. - """ - def __init__(self, parent, id=-1, - pos=wx.DefaultPosition, size=wx.DefaultSize, - style=wx.TAB_TRAVERSAL, name="panel"): - wx.Panel.__init__(self, parent, id, pos, size, style, name) - self.child = None - EVT_SIZE(self, self.OnSize) - - def OnSize(self, evt): - if self.child is None: - children = self.GetChildren() - if len(children): - self.child = children[0] - if self.child: - self.child.SetPosition((0,0)) - self.child.SetSize(self.GetSize()) - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=EmptyString) -> Listbook - - - - - - - - - - - PreListbook() -> Listbook - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=EmptyString) -> bool - - - - - - - - - - - IsVertical(self) -> bool - - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int id=0, int nSel=-1, - int nOldSel=-1) -> ListbookEvent - - - - - - - - - - EVT_LISTBOOK_PAGE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED, 1 ) - EVT_LISTBOOK_PAGE_CHANGING = wx.PyEventBinder( wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING, 1 ) - - -#--------------------------------------------------------------------------- - - - - - __init__(self, BookCtrl nb) -> BookCtrlSizer - - - - - - RecalcSizes(self) - Using the sizes calculated by `CalcMin` reposition and resize all the -items managed by this sizer. You should not need to call this directly as -it is called by `Layout`. - - - CalcMin(self) -> Size - This method is where the sizer will do the actual calculation of its -children's minimal sizes. You should not need to call this directly as -it is called by `Layout`. - - - GetControl(self) -> BookCtrl - - - - - - __init__(self, Notebook nb) -> NotebookSizer - - - - - - RecalcSizes(self) - Using the sizes calculated by `CalcMin` reposition and resize all the -items managed by this sizer. You should not need to call this directly as -it is called by `Layout`. - - - CalcMin(self) -> Size - This method is where the sizer will do the actual calculation of its -children's minimal sizes. You should not need to call this directly as -it is called by `Layout`. - - - GetNotebook(self) -> Notebook - - - -#--------------------------------------------------------------------------- - - - - - GetId(self) -> int - - - GetControl(self) -> Control - - - GetToolBar(self) -> ToolBarBase - - - IsButton(self) -> int - - - IsControl(self) -> int - - - IsSeparator(self) -> int - - - GetStyle(self) -> int - - - GetKind(self) -> int - - - IsEnabled(self) -> bool - - - IsToggled(self) -> bool - - - CanBeToggled(self) -> bool - - - GetNormalBitmap(self) -> Bitmap - - - GetDisabledBitmap(self) -> Bitmap - - - GetBitmap(self) -> Bitmap - - - GetLabel(self) -> String - - - GetShortHelp(self) -> String - - - GetLongHelp(self) -> String - - - Enable(self, bool enable) -> bool - - - - - - Toggle(self) - - - SetToggle(self, bool toggle) -> bool - - - - - - SetShortHelp(self, String help) -> bool - - - - - - SetLongHelp(self, String help) -> bool - - - - - - SetNormalBitmap(self, Bitmap bmp) - - - - - - SetDisabledBitmap(self, Bitmap bmp) - - - - - - SetLabel(self, String label) - - - - - - Detach(self) - - - Attach(self, ToolBarBase tbar) - - - - - - GetClientData(self) -> PyObject - - - SetClientData(self, PyObject clientData) - - - - - - - - - DoAddTool(self, int id, String label, Bitmap bitmap, Bitmap bmpDisabled=wxNullBitmap, - int kind=ITEM_NORMAL, String shortHelp=EmptyString, - String longHelp=EmptyString, - PyObject clientData=None) -> ToolBarToolBase - - - - - - - - - - - - - DoInsertTool(self, size_t pos, int id, String label, Bitmap bitmap, Bitmap bmpDisabled=wxNullBitmap, - int kind=ITEM_NORMAL, - String shortHelp=EmptyString, String longHelp=EmptyString, - PyObject clientData=None) -> ToolBarToolBase - - - - - - - - - - - - - - AddToolItem(self, ToolBarToolBase tool) -> ToolBarToolBase - - - - - - InsertToolItem(self, size_t pos, ToolBarToolBase tool) -> ToolBarToolBase - - - - - - - AddControl(self, Control control) -> ToolBarToolBase - - - - - - InsertControl(self, size_t pos, Control control) -> ToolBarToolBase - - - - - - - FindControl(self, int id) -> Control - - - - - - AddSeparator(self) -> ToolBarToolBase - - - InsertSeparator(self, size_t pos) -> ToolBarToolBase - - - - - - RemoveTool(self, int id) -> ToolBarToolBase - - - - - - DeleteToolByPos(self, size_t pos) -> bool - - - - - - DeleteTool(self, int id) -> bool - - - - - - ClearTools(self) - - - Realize(self) -> bool - - - EnableTool(self, int id, bool enable) - - - - - - - ToggleTool(self, int id, bool toggle) - - - - - - - SetToggle(self, int id, bool toggle) - - - - - - - GetToolClientData(self, int id) -> PyObject - - - - - - SetToolClientData(self, int id, PyObject clientData) - - - - - - - GetToolPos(self, int id) -> int - - - - - - GetToolState(self, int id) -> bool - - - - - - GetToolEnabled(self, int id) -> bool - - - - - - SetToolShortHelp(self, int id, String helpString) - - - - - - - GetToolShortHelp(self, int id) -> String - - - - - - SetToolLongHelp(self, int id, String helpString) - - - - - - - GetToolLongHelp(self, int id) -> String - - - - - - SetMarginsXY(self, int x, int y) - - - - - - - SetMargins(self, Size size) - - - - - - SetToolPacking(self, int packing) - - - - - - SetToolSeparation(self, int separation) - - - - - - GetToolMargins(self) -> Size - - - GetMargins(self) -> Size - - - GetToolPacking(self) -> int - - - GetToolSeparation(self) -> int - - - SetRows(self, int nRows) - - - - - - SetMaxRowsCols(self, int rows, int cols) - - - - - - - GetMaxRows(self) -> int - - - GetMaxCols(self) -> int - - - SetToolBitmapSize(self, Size size) - - - - - - GetToolBitmapSize(self) -> Size - - - GetToolSize(self) -> Size - - - FindToolForPosition(self, int x, int y) -> ToolBarToolBase - - - - - - - FindById(self, int toolid) -> ToolBarToolBase - - - - - - IsVertical(self) -> bool - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxNO_BORDER|wxTB_HORIZONTAL, - String name=wxPyToolBarNameStr) -> ToolBar - - - - - - - - - - - PreToolBar() -> ToolBar - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxNO_BORDER|wxTB_HORIZONTAL, - String name=wxPyToolBarNameStr) -> bool - - - - - - - - - - - FindToolForPosition(self, int x, int y) -> ToolBarToolBase - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - -#--------------------------------------------------------------------------- - - - - __init__(self, Colour colText=wxNullColour, Colour colBack=wxNullColour, - Font font=wxNullFont) -> ListItemAttr - - - - - - - - SetTextColour(self, Colour colText) - - - - - - SetBackgroundColour(self, Colour colBack) - - - - - - SetFont(self, Font font) - - - - - - HasTextColour(self) -> bool - - - HasBackgroundColour(self) -> bool - - - HasFont(self) -> bool - - - GetTextColour(self) -> Colour - - - GetBackgroundColour(self) -> Colour - - - GetFont(self) -> Font - - - Destroy(self) - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> ListItem - - - __del__(self) - - - Clear(self) - - - ClearAttributes(self) - - - SetMask(self, long mask) - - - - - - SetId(self, long id) - - - - - - SetColumn(self, int col) - - - - - - SetState(self, long state) - - - - - - SetStateMask(self, long stateMask) - - - - - - SetText(self, String text) - - - - - - SetImage(self, int image) - - - - - - SetData(self, long data) - - - - - - SetWidth(self, int width) - - - - - - SetAlign(self, int align) - - - - - - SetTextColour(self, Colour colText) - - - - - - SetBackgroundColour(self, Colour colBack) - - - - - - SetFont(self, Font font) - - - - - - GetMask(self) -> long - - - GetId(self) -> long - - - GetColumn(self) -> int - - - GetState(self) -> long - - - GetText(self) -> String - - - GetImage(self) -> int - - - GetData(self) -> long - - - GetWidth(self) -> int - - - GetAlign(self) -> int - - - GetAttributes(self) -> ListItemAttr - - - HasAttributes(self) -> bool - - - GetTextColour(self) -> Colour - - - GetBackgroundColour(self) -> Colour - - - GetFont(self) -> Font - - - - - - - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int id=0) -> ListEvent - - - - - - - - - - - - - GetKeyCode(self) -> int - - - GetIndex(self) -> long - - - GetColumn(self) -> int - - - GetPoint(self) -> Point - - - GetLabel(self) -> String - - - GetText(self) -> String - - - GetImage(self) -> int - - - GetData(self) -> long - - - GetMask(self) -> long - - - GetItem(self) -> ListItem - - - GetCacheFrom(self) -> long - - - GetCacheTo(self) -> long - - - IsEditCancelled(self) -> bool - - - SetEditCanceled(self, bool editCancelled) - - - - - - - -EVT_LIST_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_LIST_BEGIN_DRAG , 1) -EVT_LIST_BEGIN_RDRAG = wx.PyEventBinder(wxEVT_COMMAND_LIST_BEGIN_RDRAG , 1) -EVT_LIST_BEGIN_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT , 1) -EVT_LIST_END_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_LIST_END_LABEL_EDIT , 1) -EVT_LIST_DELETE_ITEM = wx.PyEventBinder(wxEVT_COMMAND_LIST_DELETE_ITEM , 1) -EVT_LIST_DELETE_ALL_ITEMS = wx.PyEventBinder(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS , 1) -EVT_LIST_GET_INFO = wx.PyEventBinder(wxEVT_COMMAND_LIST_GET_INFO , 1) -EVT_LIST_SET_INFO = wx.PyEventBinder(wxEVT_COMMAND_LIST_SET_INFO , 1) -EVT_LIST_ITEM_SELECTED = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_SELECTED , 1) -EVT_LIST_ITEM_DESELECTED = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_DESELECTED , 1) -EVT_LIST_KEY_DOWN = wx.PyEventBinder(wxEVT_COMMAND_LIST_KEY_DOWN , 1) -EVT_LIST_INSERT_ITEM = wx.PyEventBinder(wxEVT_COMMAND_LIST_INSERT_ITEM , 1) -EVT_LIST_COL_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_CLICK , 1) -EVT_LIST_ITEM_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK , 1) -EVT_LIST_ITEM_MIDDLE_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 1) -EVT_LIST_ITEM_ACTIVATED = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_ACTIVATED , 1) -EVT_LIST_CACHE_HINT = wx.PyEventBinder(wxEVT_COMMAND_LIST_CACHE_HINT , 1) -EVT_LIST_COL_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK , 1) -EVT_LIST_COL_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG , 1) -EVT_LIST_COL_DRAGGING = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_DRAGGING , 1) -EVT_LIST_COL_END_DRAG = wx.PyEventBinder(wxEVT_COMMAND_LIST_COL_END_DRAG , 1) -EVT_LIST_ITEM_FOCUSED = wx.PyEventBinder(wxEVT_COMMAND_LIST_ITEM_FOCUSED , 1) - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=LC_ICON, - Validator validator=DefaultValidator, String name=ListCtrlNameStr) -> ListCtrl - - - - - - - - - - - - PreListCtrl() -> ListCtrl - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=LC_ICON, - Validator validator=DefaultValidator, String name=ListCtrlNameStr) -> bool - Do the 2nd phase and create the GUI control. - - - - - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetForegroundColour(self, Colour col) -> bool - - - - - - SetBackgroundColour(self, Colour col) -> bool - - - - - - GetColumn(self, int col) -> ListItem - - - - - - SetColumn(self, int col, ListItem item) -> bool - - - - - - - GetColumnWidth(self, int col) -> int - - - - - - SetColumnWidth(self, int col, int width) -> bool - - - - - - - GetCountPerPage(self) -> int - - - GetViewRect(self) -> Rect - - - GetItem(self, long itemId, int col=0) -> ListItem - - - - - - - SetItem(self, ListItem info) -> bool - - - - - - SetStringItem(self, long index, int col, String label, int imageId=-1) -> long - - - - - - - - - GetItemState(self, long item, long stateMask) -> int - - - - - - - SetItemState(self, long item, long state, long stateMask) -> bool - - - - - - - - SetItemImage(self, long item, int image, int selImage) -> bool - - - - - - - - GetItemText(self, long item) -> String - - - - - - SetItemText(self, long item, String str) - - - - - - - GetItemData(self, long item) -> long - - - - - - SetItemData(self, long item, long data) -> bool - - - - - - - GetItemPosition(self, long item) -> Point - - - - - - GetItemRect(self, long item, int code=LIST_RECT_BOUNDS) -> Rect - - - - - - - SetItemPosition(self, long item, Point pos) -> bool - - - - - - - GetItemCount(self) -> int - - - GetColumnCount(self) -> int - - - GetItemSpacing(self) -> Size - - - SetItemSpacing(self, int spacing, bool isSmall=False) - - - - - - - GetSelectedItemCount(self) -> int - - - GetTextColour(self) -> Colour - - - SetTextColour(self, Colour col) - - - - - - GetTopItem(self) -> long - - - SetSingleStyle(self, long style, bool add=True) - - - - - - - SetWindowStyleFlag(self, long style) - Sets the style of the window. Please note that some styles cannot be -changed after the window creation and that Refresh() might need to be -called after changing the others for the change to take place -immediately. - - - - - - GetNextItem(self, long item, int geometry=LIST_NEXT_ALL, int state=LIST_STATE_DONTCARE) -> long - - - - - - - - GetImageList(self, int which) -> ImageList - - - - - - SetImageList(self, ImageList imageList, int which) - - - - - - - AssignImageList(self, ImageList imageList, int which) - - - - - - - InReportView(self) -> bool - - - IsVirtual(self) -> bool - - - RefreshItem(self, long item) - - - - - - RefreshItems(self, long itemFrom, long itemTo) - - - - - - - Arrange(self, int flag=LIST_ALIGN_DEFAULT) -> bool - - - - - - DeleteItem(self, long item) -> bool - - - - - - DeleteAllItems(self) -> bool - - - DeleteColumn(self, int col) -> bool - - - - - - DeleteAllColumns(self) -> bool - - - ClearAll(self) - - - EditLabel(self, long item) - - - - - - EnsureVisible(self, long item) -> bool - - - - - - FindItem(self, long start, String str, bool partial=False) -> long - - - - - - - - FindItemData(self, long start, long data) -> long - - - - - - - FindItemAtPos(self, long start, Point pt, int direction) -> long - - - - - - - - HitTest(Point point) -> (item, where) - Determines which item (if any) is at the specified point, giving - in the second return value (see wxLIST_HITTEST_... flags.) - - - - - - - InsertItem(self, ListItem info) -> long - - - - - - InsertStringItem(self, long index, String label) -> long - - - - - - - InsertImageItem(self, long index, int imageIndex) -> long - - - - - - - InsertImageStringItem(self, long index, String label, int imageIndex) -> long - - - - - - - - InsertColumnInfo(self, long col, ListItem info) -> long - - - - - - - InsertColumn(self, long col, String heading, int format=LIST_FORMAT_LEFT, - int width=-1) -> long - - - - - - - - - SetItemCount(self, long count) - - - - - - ScrollList(self, int dx, int dy) -> bool - - - - - - - SetItemTextColour(self, long item, Colour col) - - - - - - - GetItemTextColour(self, long item) -> Colour - - - - - - SetItemBackgroundColour(self, long item, Colour col) - - - - - - - GetItemBackgroundColour(self, long item) -> Colour - - - - - - SortItems(self, PyObject func) -> bool - - - - - - GetMainWindow(self) -> Window - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=LC_REPORT, - Validator validator=DefaultValidator, String name=ListCtrlNameStr) -> ListView - - - - - - - - - - - - PreListView() -> ListView - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=LC_REPORT, - Validator validator=DefaultValidator, String name=ListCtrlNameStr) -> bool - Do the 2nd phase and create the GUI control. - - - - - - - - - - - - Select(self, long n, bool on=True) - - - - - - - Focus(self, long index) - - - - - - GetFocusedItem(self) -> long - - - GetNextSelected(self, long item) -> long - - - - - - GetFirstSelected(self) -> long - - - IsSelected(self, long index) -> bool - - - - - - SetColumnImage(self, int col, int image) - - - - - - - ClearColumnImage(self, int col) - - - - - - -#--------------------------------------------------------------------------- - - -#--------------------------------------------------------------------------- - - - - __init__(self) -> TreeItemId - - - __del__(self) - - - IsOk(self) -> bool - - - __eq__(self, TreeItemId other) -> bool - - - - - - __ne__(self, TreeItemId other) -> bool - - - - - - - - - __init__(self, PyObject obj=None) -> TreeItemData - - - - - - GetData(self) -> PyObject - - - SetData(self, PyObject obj) - - - - - - GetId(self) -> TreeItemId - - - SetId(self, TreeItemId id) - - - - - - Destroy(self) - - - -#--------------------------------------------------------------------------- - - - -EVT_TREE_BEGIN_DRAG = wx.PyEventBinder(wxEVT_COMMAND_TREE_BEGIN_DRAG , 1) -EVT_TREE_BEGIN_RDRAG = wx.PyEventBinder(wxEVT_COMMAND_TREE_BEGIN_RDRAG , 1) -EVT_TREE_BEGIN_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT , 1) -EVT_TREE_END_LABEL_EDIT = wx.PyEventBinder(wxEVT_COMMAND_TREE_END_LABEL_EDIT , 1) -EVT_TREE_DELETE_ITEM = wx.PyEventBinder(wxEVT_COMMAND_TREE_DELETE_ITEM , 1) -EVT_TREE_GET_INFO = wx.PyEventBinder(wxEVT_COMMAND_TREE_GET_INFO , 1) -EVT_TREE_SET_INFO = wx.PyEventBinder(wxEVT_COMMAND_TREE_SET_INFO , 1) -EVT_TREE_ITEM_EXPANDED = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_EXPANDED , 1) -EVT_TREE_ITEM_EXPANDING = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_EXPANDING , 1) -EVT_TREE_ITEM_COLLAPSED = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_COLLAPSED , 1) -EVT_TREE_ITEM_COLLAPSING = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_COLLAPSING , 1) -EVT_TREE_SEL_CHANGED = wx.PyEventBinder(wxEVT_COMMAND_TREE_SEL_CHANGED , 1) -EVT_TREE_SEL_CHANGING = wx.PyEventBinder(wxEVT_COMMAND_TREE_SEL_CHANGING , 1) -EVT_TREE_KEY_DOWN = wx.PyEventBinder(wxEVT_COMMAND_TREE_KEY_DOWN , 1) -EVT_TREE_ITEM_ACTIVATED = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_ACTIVATED , 1) -EVT_TREE_ITEM_RIGHT_CLICK = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK , 1) -EVT_TREE_ITEM_MIDDLE_CLICK = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, 1) -EVT_TREE_END_DRAG = wx.PyEventBinder(wxEVT_COMMAND_TREE_END_DRAG , 1) -EVT_TREE_STATE_IMAGE_CLICK = wx.PyEventBinder(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, 1) -EVT_TREE_ITEM_GETTOOLTIP = wx.PyEventBinder(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, 1) - - - - - __init__(self, wxEventType commandType=wxEVT_NULL, int id=0) -> TreeEvent - - - - - - - GetItem(self) -> TreeItemId - - - SetItem(self, TreeItemId item) - - - - - - GetOldItem(self) -> TreeItemId - - - SetOldItem(self, TreeItemId item) - - - - - - GetPoint(self) -> Point - - - SetPoint(self, Point pt) - - - - - - GetKeyEvent(self) -> KeyEvent - - - GetKeyCode(self) -> int - - - SetKeyEvent(self, KeyEvent evt) - - - - - - GetLabel(self) -> String - - - SetLabel(self, String label) - - - - - - IsEditCancelled(self) -> bool - - - SetEditCanceled(self, bool editCancelled) - - - - - - SetToolTip(self, String toolTip) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=TR_DEFAULT_STYLE, - Validator validator=DefaultValidator, - String name=TreeCtrlNameStr) -> TreeCtrl - - - - - - - - - - - - PreTreeCtrl() -> TreeCtrl - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=TR_DEFAULT_STYLE, - Validator validator=DefaultValidator, - String name=TreeCtrlNameStr) -> bool - Do the 2nd phase and create the GUI control. - - - - - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - GetCount(self) -> size_t - - - GetIndent(self) -> unsigned int - - - SetIndent(self, unsigned int indent) - - - - - - GetSpacing(self) -> unsigned int - - - SetSpacing(self, unsigned int spacing) - - - - - - GetImageList(self) -> ImageList - - - GetStateImageList(self) -> ImageList - - - SetImageList(self, ImageList imageList) - - - - - - SetStateImageList(self, ImageList imageList) - - - - - - AssignImageList(self, ImageList imageList) - - - - - - AssignStateImageList(self, ImageList imageList) - - - - - - GetItemText(self, TreeItemId item) -> String - - - - - - GetItemImage(self, TreeItemId item, int which=TreeItemIcon_Normal) -> int - - - - - - - GetItemData(self, TreeItemId item) -> TreeItemData - - - - - - GetItemPyData(self, TreeItemId item) -> PyObject - - - - - - GetItemTextColour(self, TreeItemId item) -> Colour - - - - - - GetItemBackgroundColour(self, TreeItemId item) -> Colour - - - - - - GetItemFont(self, TreeItemId item) -> Font - - - - - - SetItemText(self, TreeItemId item, String text) - - - - - - - SetItemImage(self, TreeItemId item, int image, int which=TreeItemIcon_Normal) - - - - - - - - SetItemData(self, TreeItemId item, TreeItemData data) - - - - - - - SetItemPyData(self, TreeItemId item, PyObject obj) - - - - - - - SetItemHasChildren(self, TreeItemId item, bool has=True) - - - - - - - SetItemBold(self, TreeItemId item, bool bold=True) - - - - - - - SetItemTextColour(self, TreeItemId item, Colour col) - - - - - - - SetItemBackgroundColour(self, TreeItemId item, Colour col) - - - - - - - SetItemFont(self, TreeItemId item, Font font) - - - - - - - IsVisible(self, TreeItemId item) -> bool - - - - - - ItemHasChildren(self, TreeItemId item) -> bool - - - - - - IsExpanded(self, TreeItemId item) -> bool - - - - - - IsSelected(self, TreeItemId item) -> bool - - - - - - IsBold(self, TreeItemId item) -> bool - - - - - - GetChildrenCount(self, TreeItemId item, bool recursively=True) -> size_t - - - - - - - GetRootItem(self) -> TreeItemId - - - GetSelection(self) -> TreeItemId - - - GetSelections(self) -> PyObject - - - GetItemParent(self, TreeItemId item) -> TreeItemId - - - - - - GetFirstChild(self, TreeItemId item) -> PyObject - - - - - - GetNextChild(self, TreeItemId item, void cookie) -> PyObject - - - - - - - GetLastChild(self, TreeItemId item) -> TreeItemId - - - - - - GetNextSibling(self, TreeItemId item) -> TreeItemId - - - - - - GetPrevSibling(self, TreeItemId item) -> TreeItemId - - - - - - GetFirstVisibleItem(self) -> TreeItemId - - - GetNextVisible(self, TreeItemId item) -> TreeItemId - - - - - - GetPrevVisible(self, TreeItemId item) -> TreeItemId - - - - - - AddRoot(self, String text, int image=-1, int selectedImage=-1, TreeItemData data=None) -> TreeItemId - - - - - - - - - PrependItem(self, TreeItemId parent, String text, int image=-1, int selectedImage=-1, - TreeItemData data=None) -> TreeItemId - - - - - - - - - - InsertItem(self, TreeItemId parent, TreeItemId idPrevious, String text, - int image=-1, int selectedImage=-1, TreeItemData data=None) -> TreeItemId - - - - - - - - - - - InsertItemBefore(self, TreeItemId parent, size_t index, String text, int image=-1, - int selectedImage=-1, TreeItemData data=None) -> TreeItemId - - - - - - - - - - - AppendItem(self, TreeItemId parent, String text, int image=-1, int selectedImage=-1, - TreeItemData data=None) -> TreeItemId - - - - - - - - - - Delete(self, TreeItemId item) - - - - - - DeleteChildren(self, TreeItemId item) - - - - - - DeleteAllItems(self) - - - Expand(self, TreeItemId item) - - - - - - Collapse(self, TreeItemId item) - - - - - - CollapseAndReset(self, TreeItemId item) - - - - - - Toggle(self, TreeItemId item) - - - - - - Unselect(self) - - - UnselectItem(self, TreeItemId item) - - - - - - UnselectAll(self) - - - SelectItem(self, TreeItemId item, bool select=True) - - - - - - - ToggleItemSelection(self, TreeItemId item) - - - - - - EnsureVisible(self, TreeItemId item) - - - - - - ScrollTo(self, TreeItemId item) - - - - - - EditLabel(self, TreeItemId item) - - - - - - GetEditControl(self) -> TextCtrl - - - SortChildren(self, TreeItemId item) - - - - - - HitTest(Point point) -> (item, where) - Determine which item (if any) belongs the given point. The coordinates -specified are relative to the client area of tree ctrl and the where return -value is set to a bitmask of wxTREE_HITTEST_xxx constants. - - - - - - - - GetBoundingRect(self, TreeItemId item, bool textOnly=False) -> PyObject - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, String dir=DirDialogDefaultFolderStr, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=wxDIRCTRL_3D_INTERNAL|wxSUNKEN_BORDER, - String filter=EmptyString, - int defaultFilter=0, String name=TreeCtrlNameStr) -> GenericDirCtrl - - - - - - - - - - - - - - PreGenericDirCtrl() -> GenericDirCtrl - - - Create(self, Window parent, int id=-1, String dir=DirDialogDefaultFolderStr, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=wxDIRCTRL_3D_INTERNAL|wxSUNKEN_BORDER, - String filter=EmptyString, - int defaultFilter=0, String name=TreeCtrlNameStr) -> bool - - - - - - - - - - - - - - ExpandPath(self, String path) -> bool - - - - - - GetDefaultPath(self) -> String - - - SetDefaultPath(self, String path) - - - - - - GetPath(self) -> String - - - GetFilePath(self) -> String - - - SetPath(self, String path) - - - - - - ShowHidden(self, bool show) - - - - - - GetShowHidden(self) -> bool - - - GetFilter(self) -> String - - - SetFilter(self, String filter) - - - - - - GetFilterIndex(self) -> int - - - SetFilterIndex(self, int n) - - - - - - GetRootId(self) -> TreeItemId - - - GetTreeCtrl(self) -> TreeCtrl - - - GetFilterListCtrl(self) -> DirFilterListCtrl - - - FindChild(wxTreeItemId parentId, wxString path) -> (item, done) - Find the child that matches the first part of 'path'. E.g. if a child -path is "/usr" and 'path' is "/usr/include" then the child for -/usr is returned. If the path string has been used (we're at the -leaf), done is set to True. - - - - - - - - - DoResize(self) - - - ReCreateTree(self) - - - - - - __init__(self, GenericDirCtrl parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0) -> DirFilterListCtrl - - - - - - - - - - PreDirFilterListCtrl() -> DirFilterListCtrl - - - Create(self, GenericDirCtrl parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0) -> bool - - - - - - - - - - FillFilterList(self, String filter, int defaultFilter) - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, Validator validator=DefaultValidator, - String name=ControlNameStr) -> PyControl - - - - - - - - - - - - PrePyControl() -> PyControl - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetBestSize(self, Size size) - - - - - - base_DoMoveWindow(self, int x, int y, int width, int height) - - - - - - - - - base_DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO) - - - - - - - - - - base_DoSetClientSize(self, int width, int height) - - - - - - - base_DoSetVirtualSize(self, int x, int y) - - - - - - - base_DoGetSize() -> (width, height) - - - - - - - base_DoGetClientSize() -> (width, height) - - - - - - - base_DoGetPosition() -> (x,y) - - - - - - - base_DoGetVirtualSize(self) -> Size - - - base_DoGetBestSize(self) -> Size - - - base_InitDialog(self) - - - base_TransferDataToWindow(self) -> bool - - - base_TransferDataFromWindow(self) -> bool - - - base_Validate(self) -> bool - - - base_AcceptsFocus(self) -> bool - - - base_AcceptsFocusFromKeyboard(self) -> bool - - - base_GetMaxSize(self) -> Size - - - base_AddChild(self, Window child) - - - - - - base_RemoveChild(self, Window child) - - - - - - base_ShouldInheritColours(self) -> bool - - - base_ApplyParentThemeBackground(self, Colour c) - - - - - - base_GetDefaultAttributes(self) -> VisualAttributes - - - -#--------------------------------------------------------------------------- - - -EVT_HELP = wx.PyEventBinder( wxEVT_HELP, 1) -EVT_HELP_RANGE = wx.PyEventBinder( wxEVT_HELP, 2) -EVT_DETAILED_HELP = wx.PyEventBinder( wxEVT_DETAILED_HELP, 1) -EVT_DETAILED_HELP_RANGE = wx.PyEventBinder( wxEVT_DETAILED_HELP, 2) - - - A help event is sent when the user has requested context-sensitive -help. This can either be caused by the application requesting -context-sensitive help mode via wx.ContextHelp, or (on MS Windows) by -the system generating a WM_HELP message when the user pressed F1 or -clicked on the query button in a dialog caption. - -A help event is sent to the window that the user clicked on, and is -propagated up the window hierarchy until the event is processed or -there are no more event handlers. The application should call -event.GetId to check the identity of the clicked-on window, and then -either show some suitable help or call event.Skip if the identifier is -unrecognised. Calling Skip is important because it allows wxWindows to -generate further events for ancestors of the clicked-on -window. Otherwise it would be impossible to show help for container -windows, since processing would stop after the first window found. - -Events -------- - ============== ========================================= - EVT_HELP Sent when the user has requested context- - sensitive help. - EVT_HELP_RANGE Allows to catch EVT_HELP for a range of IDs - ============== ========================================= - -:see: `wx.ContextHelp`, `wx.ContextHelpButton` - - - - __init__(self, wxEventType type=wxEVT_NULL, int winid=0, Point pt=DefaultPosition) -> HelpEvent - - - - - - - - GetPosition(self) -> Point - Returns the left-click position of the mouse, in screen -coordinates. This allows the application to position the help -appropriately. - - - SetPosition(self, Point pos) - Sets the left-click position of the mouse, in screen coordinates. - - - - - - GetLink(self) -> String - Get an optional link to further help - - - SetLink(self, String link) - Set an optional link to further help - - - - - - GetTarget(self) -> String - Get an optional target to display help in. E.g. a window specification - - - SetTarget(self, String target) - Set an optional target to display help in. E.g. a window specification - - - - - - - This class changes the cursor to a query and puts the application into -a 'context-sensitive help mode'. When the user left-clicks on a window -within the specified window, a ``EVT_HELP`` event is sent to that -control, and the application may respond to it by popping up some -help. - -There are a couple of ways to invoke this behaviour implicitly: - - * Use the wx.DIALOG_EX_CONTEXTHELP extended style for a dialog - (Windows only). This will put a question mark in the titlebar, - and Windows will put the application into context-sensitive help - mode automatically, with further programming. - - * Create a `wx.ContextHelpButton`, whose predefined behaviour is - to create a context help object. Normally you will write your - application so that this button is only added to a dialog for - non-Windows platforms (use ``wx.DIALOG_EX_CONTEXTHELP`` on - Windows). - -:see: `wx.ContextHelpButton` - - - - __init__(self, Window window=None, bool doNow=True) -> ContextHelp - Constructs a context help object, calling BeginContextHelp if doNow is -true (the default). - -If window is None, the top window is used. - - - - - - - __del__(self) - - - BeginContextHelp(self, Window window=None) -> bool - Puts the application into context-sensitive help mode. window is the -window which will be used to catch events; if NULL, the top window -will be used. - -Returns true if the application was successfully put into -context-sensitive help mode. This function only returns when the event -loop has finished. - - - - - - EndContextHelp(self) -> bool - Ends context-sensitive help mode. Not normally called by the -application. - - - - Instances of this class may be used to add a question mark button that -when pressed, puts the application into context-help mode. It does -this by creating a wx.ContextHelp object which itself generates a -``EVT_HELP`` event when the user clicks on a window. - -On Windows, you may add a question-mark icon to a dialog by use of the -``wx.DIALOG_EX_CONTEXTHELP`` extra style, but on other platforms you -will have to add a button explicitly, usually next to OK, Cancel or -similar buttons. - -:see: `wx.ContextHelp`, `wx.ContextHelpButton` - - - - __init__(self, Window parent, int id=ID_CONTEXT_HELP, Point pos=DefaultPosition, - Size size=DefaultSize, long style=BU_AUTODRAW) -> ContextHelpButton - Constructor, creating and showing a context help button. - - - - - - - - - - - wx.HelpProvider is an abstract class used by a program -implementing context-sensitive help to show the help text for the -given window. - -The current help provider must be explicitly set by the -application using wx.HelpProvider.Set(). - - Set(HelpProvider helpProvider) -> HelpProvider - Sset the current, application-wide help provider. Returns the previous -one. Unlike some other classes, the help provider is not created on -demand. This must be explicitly done by the application. - - - - - - Get() -> HelpProvider - Return the current application-wide help provider. - - - GetHelp(self, Window window) -> String - Gets the help string for this window. Its interpretation is dependent -on the help provider except that empty string always means that no -help is associated with the window. - - - - - - ShowHelp(self, Window window) -> bool - Shows help for the given window. Uses GetHelp internally if -applicable. Returns True if it was done, or False if no help was -available for this window. - - - - - - AddHelp(self, Window window, String text) - Associates the text with the given window. - - - - - - - AddHelpById(self, int id, String text) - This version associates the given text with all windows with this -id. May be used to set the same help string for all Cancel buttons in -the application, for example. - - - - - - - RemoveHelp(self, Window window) - Removes the association between the window pointer and the help -text. This is called by the wx.Window destructor. Without this, the -table of help strings will fill up and when window pointers are -reused, the wrong help string will be found. - - - - - - Destroy(self) - - - - wx.SimpleHelpProvider is an implementation of `wx.HelpProvider` which -supports only plain text help strings, and shows the string associated -with the control (if any) in a tooltip. - - - __init__(self) -> SimpleHelpProvider - wx.SimpleHelpProvider is an implementation of `wx.HelpProvider` which -supports only plain text help strings, and shows the string associated -with the control (if any) in a tooltip. - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Bitmap image, Cursor cursor=wxNullCursor) -> DragImage - - - - - - - DragIcon(Icon image, Cursor cursor=wxNullCursor) -> DragImage - - - - - - - DragString(String str, Cursor cursor=wxNullCursor) -> DragImage - - - - - - - DragTreeItem(TreeCtrl treeCtrl, TreeItemId id) -> DragImage - - - - - - - DragListItem(ListCtrl listCtrl, long id) -> DragImage - - - - - - - __del__(self) - - - SetBackingBitmap(self, Bitmap bitmap) - - - - - - BeginDrag(self, Point hotspot, Window window, bool fullScreen=False, - Rect rect=None) -> bool - - - - - - - - - BeginDragBounded(self, Point hotspot, Window window, Window boundingWindow) -> bool - - - - - - - - EndDrag(self) -> bool - - - Move(self, Point pt) -> bool - - - - - - Show(self) -> bool - - - Hide(self) -> bool - - - GetImageRect(self, Point pos) -> Rect - - - - - - DoDrawImage(self, DC dc, Point pos) -> bool - - - - - - - UpdateBackingFromWindow(self, DC windowDC, MemoryDC destDC, Rect sourceRect, Rect destRect) -> bool - - - - - - - - - RedrawImage(self, Point oldPos, Point newPos, bool eraseOld, bool drawNew) -> bool - - - - - - - - - - - - wx = _core - -#--------------------------------------------------------------------------- - - - - GetColour(int index) -> Colour - - - - - - GetFont(int index) -> Font - - - - - - GetMetric(int index) -> int - - - - - - HasFeature(int index) -> bool - - - - - - GetScreenType() -> int - - - SetScreenType(int screen) - - - - - - - - - __init__(self) -> SystemOptions - - - SetOption(String name, String value) - - - - - - - SetOptionInt(String name, int value) - - - - - - - GetOption(String name) -> String - - - - - - GetOptionInt(String name) -> int - - - - - - HasOption(String name) -> bool - - - - - - -#--------------------------------------------------------------------------- - - - NewId() -> long - - - RegisterId(long id) - - - - - - GetCurrentId() -> long - - - Bell() - - - EndBusyCursor() - - - GetElapsedTime(bool resetTimer=True) -> long - - - - - - GetMousePosition() -> (x,y) - - - - - - - IsBusy() -> bool - - - Now() -> String - - - Shell(String command=EmptyString) -> bool - - - - - - StartTimer() - - - GetOsVersion() -> (platform, major, minor) - - - - - - - GetOsDescription() -> String - - - GetFreeMemory() -> long - - - Shutdown(int wFlags) -> bool - - - - - - Sleep(int secs) - - - - - - MilliSleep(unsigned long milliseconds) - - - - - - MicroSleep(unsigned long microseconds) - - - - - Usleep = MilliSleep - - EnableTopLevelWindows(bool enable) - - - - - - StripMenuCodes(String in) -> String - - - - - - GetEmailAddress() -> String - - - GetHostName() -> String - - - GetFullHostName() -> String - - - GetUserId() -> String - - - GetUserName() -> String - - - GetHomeDir() -> String - - - GetUserHome(String user=EmptyString) -> String - - - - - - GetProcessId() -> unsigned long - - - Trap() - - - FileSelector(String message=FileSelectorPromptStr, String default_path=EmptyString, - String default_filename=EmptyString, - String default_extension=EmptyString, - String wildcard=FileSelectorDefaultWildcardStr, - int flags=0, Window parent=None, int x=-1, - int y=-1) -> String - - - - - - - - - - - - - - LoadFileSelector(String what, String extension, String default_name=EmptyString, - Window parent=None) -> String - - - - - - - - - SaveFileSelector(String what, String extension, String default_name=EmptyString, - Window parent=None) -> String - - - - - - - - - DirSelector(String message=DirSelectorPromptStr, String defaultPath=EmptyString, - long style=DD_DEFAULT_STYLE, - Point pos=DefaultPosition, Window parent=None) -> String - - - - - - - - - - GetTextFromUser(String message, String caption=EmptyString, String default_value=EmptyString, - Window parent=None, - int x=-1, int y=-1, bool centre=True) -> String - - - - - - - - - - - - GetPasswordFromUser(String message, String caption=EmptyString, String default_value=EmptyString, - Window parent=None) -> String - - - - - - - - - GetSingleChoice(String message, String caption, int choices, String choices_array, - Window parent=None, int x=-1, - int y=-1, bool centre=True, int width=150, int height=200) -> String - - - - - - - - - - - - - - - GetSingleChoiceIndex(String message, String caption, int choices, String choices_array, - Window parent=None, int x=-1, - int y=-1, bool centre=True, int width=150, int height=200) -> int - - - - - - - - - - - - - - - MessageBox(String message, String caption=EmptyString, int style=wxOK|wxCENTRE, - Window parent=None, int x=-1, - int y=-1) -> int - - - - - - - - - - - GetNumberFromUser(String message, String prompt, String caption, long value, - long min=0, long max=100, Window parent=None, - Point pos=DefaultPosition) -> long - - - - - - - - - - - - - ColourDisplay() -> bool - - - DisplayDepth() -> int - - - GetDisplayDepth() -> int - - - DisplaySize() -> (width, height) - - - - - - - GetDisplaySize() -> Size - - - DisplaySizeMM() -> (width, height) - - - - - - - GetDisplaySizeMM() -> Size - - - ClientDisplayRect() -> (x, y, width, height) - - - - - - - - - GetClientDisplayRect() -> Rect - - - SetCursor(Cursor cursor) - - - - - - BeginBusyCursor(Cursor cursor=wxHOURGLASS_CURSOR) - - - - - - GetActiveWindow() -> Window - - - GenericFindWindowAtPoint(Point pt) -> Window - - - - - - FindWindowAtPoint(Point pt) -> Window - - - - - - GetTopLevelParent(Window win) -> Window - - - - - - GetKeyState(int key) -> bool - Get the state of a key (true if pressed or toggled on, false if not.) -This is generally most useful getting the state of the modifier or -toggle keys. On some platforms those may be the only keys that work. - - - - - - - WakeUpMainThread() - - - MutexGuiEnter() - - - MutexGuiLeave() - - - - __init__(self) -> MutexGuiLocker - - - __del__(self) - - - - Thread_IsMain() -> bool - - -#--------------------------------------------------------------------------- - - - - - __init__(self, String tip) -> ToolTip - - - - - - SetTip(self, String tip) - - - - - - GetTip(self) -> String - - - GetWindow(self) -> Window - - - Enable(bool flag) - - - - - - SetDelay(long milliseconds) - - - - - - - - __init__(self, Window window, Size size) -> Caret - - - - - - - __del__(self) - - - IsOk(self) -> bool - - - IsVisible(self) -> bool - - - GetPosition(self) -> Point - - - GetPositionTuple() -> (x,y) - - - - - - - GetSize(self) -> Size - - - GetSizeTuple() -> (width, height) - - - - - - - GetWindow(self) -> Window - - - MoveXY(self, int x, int y) - - - - - - - Move(self, Point pt) - - - - - - SetSizeWH(self, int width, int height) - - - - - - - SetSize(self, Size size) - - - - - - Show(self, int show=True) - - - - - - Hide(self) - - - - Caret_GetBlinkTime() -> int - - - Caret_SetBlinkTime(int milliseconds) - - - - - - - __init__(self, Cursor cursor=wxHOURGLASS_CURSOR) -> BusyCursor - - - - - - __del__(self) - - - - - __init__(self, Window winToSkip=None) -> WindowDisabler - - - - - - __del__(self) - - - - - - __init__(self, String message) -> BusyInfo - - - - - - __del__(self) - - - - - __init__(self) -> StopWatch - - - Start(self, long t0=0) - - - - - - Pause(self) - - - Resume(self) - - - Time(self) -> long - - - - - - __init__(self, int maxFiles=9, int idBase=ID_FILE1) -> FileHistory - - - - - - - __del__(self) - - - AddFileToHistory(self, String file) - - - - - - RemoveFileFromHistory(self, int i) - - - - - - GetMaxFiles(self) -> int - - - UseMenu(self, Menu menu) - - - - - - RemoveMenu(self, Menu menu) - - - - - - Load(self, ConfigBase config) - - - - - - Save(self, ConfigBase config) - - - - - - AddFilesToMenu(self) - - - AddFilesToThisMenu(self, Menu menu) - - - - - - GetHistoryFile(self, int i) -> String - - - - - - GetCount(self) -> int - - - - - __init__(self, String name, String path=EmptyString) -> SingleInstanceChecker - - - - - - - PreSingleInstanceChecker() -> SingleInstanceChecker - - - __del__(self) - - - Create(self, String name, String path=EmptyString) -> bool - - - - - - - IsAnotherRunning(self) -> bool - - - - DrawWindowOnDC(Window window, DC dc, int method) - - - - - - - -#--------------------------------------------------------------------------- - - - - __del__(self) - - - GetTip(self) -> String - - - GetCurrentTip(self) -> size_t - - - PreprocessTip(self, String tip) -> String - - - - - - - - - __init__(self, size_t currentTip) -> PyTipProvider - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - - ShowTip(Window parent, TipProvider tipProvider, bool showAtStartup=True) -> bool - - - - - - - - CreateFileTipProvider(String filename, size_t currentTip) -> TipProvider - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, EvtHandler owner=None, int id=-1) -> Timer - - - - - - - __del__(self) - - - _setCallbackInfo(self, PyObject self, PyObject _class, int incref=1) - - - - - - - - SetOwner(self, EvtHandler owner, int id=-1) - - - - - - - GetOwner(self) -> EvtHandler - - - Start(self, int milliseconds=-1, bool oneShot=False) -> bool - - - - - - - Stop(self) - - - IsRunning(self) -> bool - - - GetInterval(self) -> int - - - IsOneShot(self) -> bool - - - GetId(self) -> int - - - -# For backwards compatibility with 2.4 -class PyTimer(Timer): - def __init__(self, notify): - Timer.__init__(self) - self.notify = notify - - def Notify(self): - if self.notify: - self.notify() - - -EVT_TIMER = wx.PyEventBinder( wxEVT_TIMER, 1 ) - - - - - - __init__(self, int timerid=0, int interval=0) -> TimerEvent - - - - - - - GetInterval(self) -> int - - - - - - - - - - __init__(self, wxTimer timer) -> TimerRunner -__init__(self, wxTimer timer, int milli, bool oneShot=False) -> TimerRunner - - - - - - - - __del__(self) - - - Start(self, int milli, bool oneShot=False) - - - - - - - -#--------------------------------------------------------------------------- - - - - __init__(self) -> Log - - - IsEnabled() -> bool - - - EnableLogging(bool doIt=True) -> bool - - - - - - OnLog(wxLogLevel level, wxChar szString, time_t t) - - - - - - - - Flush(self) - - - FlushActive() - - - GetActiveTarget() -> Log - - - SetActiveTarget(Log pLogger) -> Log - - - - - - Suspend() - - - Resume() - - - SetVerbose(bool bVerbose=True) - - - - - - SetLogLevel(wxLogLevel logLevel) - - - - - - DontCreateOnDemand() - - - SetTraceMask(wxTraceMask ulMask) - - - - - - AddTraceMask(String str) - - - - - - RemoveTraceMask(String str) - - - - - - ClearTraceMasks() - - - GetTraceMasks() -> wxArrayString - - - SetTimestamp(wxChar ts) - - - - - - GetVerbose() -> bool - - - GetTraceMask() -> wxTraceMask - - - IsAllowedTraceMask(wxChar mask) -> bool - - - - - - GetLogLevel() -> wxLogLevel - - - GetTimestamp() -> wxChar - - - TimeStamp() -> String - - - Destroy(self) - - - - - - __init__(self) -> LogStderr - - - - - - __init__(self, wxTextCtrl pTextCtrl) -> LogTextCtrl - - - - - - - - - __init__(self) -> LogGui - - - - - - __init__(self, wxFrame pParent, String szTitle, bool bShow=True, bool bPassToOld=True) -> LogWindow - - - - - - - - - Show(self, bool bShow=True) - - - - - - GetFrame(self) -> wxFrame - - - GetOldLog(self) -> Log - - - IsPassingMessages(self) -> bool - - - PassMessages(self, bool bDoPass) - - - - - - - - - __init__(self, Log logger) -> LogChain - - - - - - SetLog(self, Log logger) - - - - - - PassMessages(self, bool bDoPass) - - - - - - IsPassingMessages(self) -> bool - - - GetOldLog(self) -> Log - - - - SysErrorCode() -> unsigned long - - - SysErrorMsg(unsigned long nErrCode=0) -> String - - - - - - LogFatalError(String msg) - - - - - - LogError(String msg) - - - - - - LogWarning(String msg) - - - - - - LogMessage(String msg) - - - - - - LogInfo(String msg) - - - - - - LogDebug(String msg) - - - - - - LogVerbose(String msg) - - - - - - LogStatus(String msg) - - - - - - LogStatusFrame(wxFrame pFrame, String msg) - - - - - - - LogSysError(String msg) - - - - - - - - - - - - LogTrace(unsigned long mask, String msg) -LogTrace(String mask, String msg) - - - - - - - LogGeneric(unsigned long level, String msg) - - - - - - - SafeShowMessage(String title, String text) - - - - - - - - __init__(self) -> LogNull - - - __del__(self) - - - - - - __init__(self) -> PyLog - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, EvtHandler parent=None, int id=-1) -> Process - - - - - - - Kill(int pid, int sig=SIGTERM) -> int - - - - - - - Exists(int pid) -> bool - - - - - - Open(String cmd, int flags=EXEC_ASYNC) -> Process - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_OnTerminate(self, int pid, int status) - - - - - - - Redirect(self) - - - IsRedirected(self) -> bool - - - Detach(self) - - - GetInputStream(self) -> InputStream - - - GetErrorStream(self) -> InputStream - - - GetOutputStream(self) -> OutputStream - - - CloseOutput(self) - - - IsInputOpened(self) -> bool - - - IsInputAvailable(self) -> bool - - - IsErrorAvailable(self) -> bool - - - - - - __init__(self, int id=0, int pid=0, int exitcode=0) -> ProcessEvent - - - - - - - - GetPid(self) -> int - - - GetExitCode(self) -> int - - - - - -EVT_END_PROCESS = wx.PyEventBinder( wxEVT_END_PROCESS, 1 ) - - - Execute(String command, int flags=EXEC_ASYNC, Process process=None) -> long - - - - - - - -#--------------------------------------------------------------------------- - - - - __init__(self, int joystick=JOYSTICK1) -> Joystick - - - - - - __del__(self) - - - GetPosition(self) -> Point - - - GetZPosition(self) -> int - - - GetButtonState(self) -> int - - - GetPOVPosition(self) -> int - - - GetPOVCTSPosition(self) -> int - - - GetRudderPosition(self) -> int - - - GetUPosition(self) -> int - - - GetVPosition(self) -> int - - - GetMovementThreshold(self) -> int - - - SetMovementThreshold(self, int threshold) - - - - - - IsOk(self) -> bool - - - GetNumberJoysticks(self) -> int - - - GetManufacturerId(self) -> int - - - GetProductId(self) -> int - - - GetProductName(self) -> String - - - GetXMin(self) -> int - - - GetYMin(self) -> int - - - GetZMin(self) -> int - - - GetXMax(self) -> int - - - GetYMax(self) -> int - - - GetZMax(self) -> int - - - GetNumberButtons(self) -> int - - - GetNumberAxes(self) -> int - - - GetMaxButtons(self) -> int - - - GetMaxAxes(self) -> int - - - GetPollingMin(self) -> int - - - GetPollingMax(self) -> int - - - GetRudderMin(self) -> int - - - GetRudderMax(self) -> int - - - GetUMin(self) -> int - - - GetUMax(self) -> int - - - GetVMin(self) -> int - - - GetVMax(self) -> int - - - HasRudder(self) -> bool - - - HasZ(self) -> bool - - - HasU(self) -> bool - - - HasV(self) -> bool - - - HasPOV(self) -> bool - - - HasPOV4Dir(self) -> bool - - - HasPOVCTS(self) -> bool - - - SetCapture(self, Window win, int pollingFreq=0) -> bool - - - - - - - ReleaseCapture(self) -> bool - - - - - - __init__(self, wxEventType type=wxEVT_NULL, int state=0, int joystick=JOYSTICK1, - int change=0) -> JoystickEvent - - - - - - - - - - - - - - GetPosition(self) -> Point - - - GetZPosition(self) -> int - - - GetButtonState(self) -> int - - - GetButtonChange(self) -> int - - - GetJoystick(self) -> int - - - SetJoystick(self, int stick) - - - - - - SetButtonState(self, int state) - - - - - - SetButtonChange(self, int change) - - - - - - SetPosition(self, Point pos) - - - - - - SetZPosition(self, int zPos) - - - - - - IsButton(self) -> bool - - - IsMove(self) -> bool - - - IsZMove(self) -> bool - - - ButtonDown(self, int but=JOY_BUTTON_ANY) -> bool - - - - - - ButtonUp(self, int but=JOY_BUTTON_ANY) -> bool - - - - - - ButtonIsDown(self, int but=JOY_BUTTON_ANY) -> bool - - - - - - -EVT_JOY_BUTTON_DOWN = wx.PyEventBinder( wxEVT_JOY_BUTTON_DOWN ) -EVT_JOY_BUTTON_UP = wx.PyEventBinder( wxEVT_JOY_BUTTON_UP ) -EVT_JOY_MOVE = wx.PyEventBinder( wxEVT_JOY_MOVE ) -EVT_JOY_ZMOVE = wx.PyEventBinder( wxEVT_JOY_ZMOVE ) - -EVT_JOYSTICK_EVENTS = wx.PyEventBinder([ wxEVT_JOY_BUTTON_DOWN, - wxEVT_JOY_BUTTON_UP, - wxEVT_JOY_MOVE, - wxEVT_JOY_ZMOVE, - ]) - - - -#--------------------------------------------------------------------------- - - - - __init__(self, String fileName=EmptyString) -> Sound - - - - - - SoundFromData(PyObject data) -> Sound - - - - - - __del__(self) - - - Create(self, String fileName) -> bool - - - - - - CreateFromData(self, PyObject data) -> bool - - - - - - IsOk(self) -> bool - - - Play(self, unsigned int flags=SOUND_ASYNC) -> bool - - - - - - PlaySound(String filename, unsigned int flags=SOUND_ASYNC) -> bool - - - - - - - Stop() - - - -#--------------------------------------------------------------------------- - - - - __init__(self, String mimeType, String openCmd, String printCmd, String desc) -> FileTypeInfo - - - - - - - - - FileTypeInfoSequence(wxArrayString sArray) -> FileTypeInfo - - - - - - NullFileTypeInfo() -> FileTypeInfo - - - IsValid(self) -> bool - - - SetIcon(self, String iconFile, int iconIndex=0) - - - - - - - SetShortDesc(self, String shortDesc) - - - - - - GetMimeType(self) -> String - - - GetOpenCommand(self) -> String - - - GetPrintCommand(self) -> String - - - GetShortDesc(self) -> String - - - GetDescription(self) -> String - - - GetExtensions(self) -> wxArrayString - - - GetExtensionsCount(self) -> int - - - GetIconFile(self) -> String - - - GetIconIndex(self) -> int - - - - - __init__(self, FileTypeInfo ftInfo) -> FileType - - - - - - __del__(self) - - - GetMimeType(self) -> PyObject - - - GetMimeTypes(self) -> PyObject - - - GetExtensions(self) -> PyObject - - - GetIcon(self) -> Icon - - - GetIconInfo(self) -> PyObject - - - GetDescription(self) -> PyObject - - - GetOpenCommand(self, String filename, String mimetype=EmptyString) -> PyObject - - - - - - - GetPrintCommand(self, String filename, String mimetype=EmptyString) -> PyObject - - - - - - - GetAllCommands(self, String filename, String mimetype=EmptyString) -> PyObject - - - - - - - SetCommand(self, String cmd, String verb, bool overwriteprompt=True) -> bool - - - - - - - - SetDefaultIcon(self, String cmd=EmptyString, int index=0) -> bool - - - - - - - Unassociate(self) -> bool - - - ExpandCommand(String command, String filename, String mimetype=EmptyString) -> String - - - - - - - - - - __init__(self) -> MimeTypesManager - - - __del__(self) - - - IsOfType(String mimeType, String wildcard) -> bool - - - - - - - Initialize(self, int mailcapStyle=MAILCAP_ALL, String extraDir=EmptyString) - - - - - - - ClearData(self) - - - GetFileTypeFromExtension(self, String ext) -> FileType - - - - - - GetFileTypeFromMimeType(self, String mimeType) -> FileType - - - - - - ReadMailcap(self, String filename, bool fallback=False) -> bool - - - - - - - ReadMimeTypes(self, String filename) -> bool - - - - - - EnumAllFileTypes(self) -> PyObject - - - AddFallback(self, FileTypeInfo ft) - - - - - - Associate(self, FileTypeInfo ftInfo) -> FileType - - - - - - Unassociate(self, FileType ft) -> bool - - - - - - -#--------------------------------------------------------------------------- - - - The wx.ArtProvider class is used to customize the look of wxWidgets -application. When wxWidgets needs to display an icon or a bitmap (e.g. -in the standard file dialog), it does not use hard-coded resource but -asks wx.ArtProvider for it instead. This way the users can plug in -their own wx.ArtProvider class and easily replace standard art with -his/her own version. It is easy thing to do: all that is needed is -to derive a class from wx.ArtProvider, override it's CreateBitmap -method and register the provider with wx.ArtProvider.PushProvider:: - - class MyArtProvider(wx.ArtProvider): - def __init__(self): - wx.ArtProvider.__init__(self) - - def CreateBitmap(self, artid, client, size): - ... - return bmp - - -Identifying art resources -------------------------- - -Every bitmap is known to wx.ArtProvider under an unique ID that is -used when requesting a resource from it. The IDs can have one of the -following predefined values. Additionally, any string recognized by -custom art providers registered using `PushProvider` may be used. - -GTK+ Note ---------- - -When running under GTK+ 2, GTK+ stock item IDs (e.g. 'gtk-cdrom') may be used -as well. Additionally, if wxGTK was compiled against GTK+ >= 2.4, then it is -also possible to load icons from current icon theme by specifying their name -without the extension and directory components. Icon themes recognized by GTK+ -follow the freedesktop.org Icon Themes specification. Note that themes are -not guaranteed to contain all icons, so wx.ArtProvider may return wx.NullBitmap -or wx.NullIcon. The default theme is typically installed in /usr/share/icons/hicolor. - - - * wx.ART_ADD_BOOKMARK - * wx.ART_DEL_BOOKMARK - * wx.ART_HELP_SIDE_PANEL - * wx.ART_HELP_SETTINGS - * wx.ART_HELP_BOOK - * wx.ART_HELP_FOLDER - * wx.ART_HELP_PAGE - * wx.ART_GO_BACK - * wx.ART_GO_FORWARD - * wx.ART_GO_UP - * wx.ART_GO_DOWN - * wx.ART_GO_TO_PARENT - * wx.ART_GO_HOME - * wx.ART_FILE_OPEN - * wx.ART_PRINT - * wx.ART_HELP - * wx.ART_TIP - * wx.ART_REPORT_VIEW - * wx.ART_LIST_VIEW - * wx.ART_NEW_DIR - * wx.ART_FOLDER - * wx.ART_GO_DIR_UP - * wx.ART_EXECUTABLE_FILE - * wx.ART_NORMAL_FILE - * wx.ART_TICK_MARK - * wx.ART_CROSS_MARK - * wx.ART_ERROR - * wx.ART_QUESTION - * wx.ART_WARNING - * wx.ART_INFORMATION - * wx.ART_MISSING_IMAGE - - -Clients -------- - -The Client is the entity that calls wx.ArtProvider's `GetBitmap` or -`GetIcon` function. Client IDs serve as a hint to wx.ArtProvider -that is supposed to help it to choose the best looking bitmap. For -example it is often desirable to use slightly different icons in menus -and toolbars even though they represent the same action (e.g. -wx.ART_FILE_OPEN). Remember that this is really only a hint for -wx.ArtProvider -- it is common that `wx.ArtProvider.GetBitmap` returns -identical bitmap for different client values! - - * wx.ART_TOOLBAR - * wx.ART_MENU - * wx.ART_FRAME_ICON - * wx.ART_CMN_DIALOG - * wx.ART_HELP_BROWSER - * wx.ART_MESSAGE_BOX - * wx.ART_BUTTON - * wx.ART_OTHER (used for all requests that don't fit into any - of the categories above) - - - __init__(self) -> ArtProvider - The wx.ArtProvider class is used to customize the look of wxWidgets -application. When wxWidgets needs to display an icon or a bitmap (e.g. -in the standard file dialog), it does not use hard-coded resource but -asks wx.ArtProvider for it instead. This way the users can plug in -their own wx.ArtProvider class and easily replace standard art with -his/her own version. It is easy thing to do: all that is needed is -to derive a class from wx.ArtProvider, override it's CreateBitmap -method and register the provider with wx.ArtProvider.PushProvider:: - - class MyArtProvider(wx.ArtProvider): - def __init__(self): - wx.ArtProvider.__init__(self) - - def CreateBitmap(self, artid, client, size): - ... - return bmp - - -Identifying art resources -------------------------- - -Every bitmap is known to wx.ArtProvider under an unique ID that is -used when requesting a resource from it. The IDs can have one of the -following predefined values. Additionally, any string recognized by -custom art providers registered using `PushProvider` may be used. - -GTK+ Note ---------- - -When running under GTK+ 2, GTK+ stock item IDs (e.g. 'gtk-cdrom') may be used -as well. Additionally, if wxGTK was compiled against GTK+ >= 2.4, then it is -also possible to load icons from current icon theme by specifying their name -without the extension and directory components. Icon themes recognized by GTK+ -follow the freedesktop.org Icon Themes specification. Note that themes are -not guaranteed to contain all icons, so wx.ArtProvider may return wx.NullBitmap -or wx.NullIcon. The default theme is typically installed in /usr/share/icons/hicolor. - - - * wx.ART_ADD_BOOKMARK - * wx.ART_DEL_BOOKMARK - * wx.ART_HELP_SIDE_PANEL - * wx.ART_HELP_SETTINGS - * wx.ART_HELP_BOOK - * wx.ART_HELP_FOLDER - * wx.ART_HELP_PAGE - * wx.ART_GO_BACK - * wx.ART_GO_FORWARD - * wx.ART_GO_UP - * wx.ART_GO_DOWN - * wx.ART_GO_TO_PARENT - * wx.ART_GO_HOME - * wx.ART_FILE_OPEN - * wx.ART_PRINT - * wx.ART_HELP - * wx.ART_TIP - * wx.ART_REPORT_VIEW - * wx.ART_LIST_VIEW - * wx.ART_NEW_DIR - * wx.ART_FOLDER - * wx.ART_GO_DIR_UP - * wx.ART_EXECUTABLE_FILE - * wx.ART_NORMAL_FILE - * wx.ART_TICK_MARK - * wx.ART_CROSS_MARK - * wx.ART_ERROR - * wx.ART_QUESTION - * wx.ART_WARNING - * wx.ART_INFORMATION - * wx.ART_MISSING_IMAGE - - -Clients -------- - -The Client is the entity that calls wx.ArtProvider's `GetBitmap` or -`GetIcon` function. Client IDs serve as a hint to wx.ArtProvider -that is supposed to help it to choose the best looking bitmap. For -example it is often desirable to use slightly different icons in menus -and toolbars even though they represent the same action (e.g. -wx.ART_FILE_OPEN). Remember that this is really only a hint for -wx.ArtProvider -- it is common that `wx.ArtProvider.GetBitmap` returns -identical bitmap for different client values! - - * wx.ART_TOOLBAR - * wx.ART_MENU - * wx.ART_FRAME_ICON - * wx.ART_CMN_DIALOG - * wx.ART_HELP_BROWSER - * wx.ART_MESSAGE_BOX - * wx.ART_BUTTON - * wx.ART_OTHER (used for all requests that don't fit into any - of the categories above) - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - PushProvider(ArtProvider provider) - Add new provider to the top of providers stack. - - - - - - PopProvider() -> bool - Remove latest added provider and delete it. - - - RemoveProvider(ArtProvider provider) -> bool - Remove provider. The provider must have been added previously! The -provider is _not_ deleted. - - - - - - GetBitmap(String id, String client=ART_OTHER, Size size=DefaultSize) -> Bitmap - Query the providers for bitmap with given ID and return it. Return -wx.NullBitmap if no provider provides it. - - - - - - - - GetIcon(String id, String client=ART_OTHER, Size size=DefaultSize) -> Icon - Query the providers for icon with given ID and return it. Return -wx.NullIcon if no provider provides it. - - - - - - - - Destroy(self) - - - -#--------------------------------------------------------------------------- - - - wx.ConfigBase class defines the basic interface of all config -classes. It can not be used by itself (it is an abstract base class) -and you will always use one of its derivations: wx.Config or -wx.FileConfig. - -wx.ConfigBase organizes the items in a tree-like structure, modeled -after the Unix/Dos filesystem. There are groups that act like -directories and entries, key/value pairs that act like files. There -is always one current group given by the current path. As in the file -system case, to specify a key in the config class you must use a path -to it. Config classes also support the notion of the current group, -which makes it possible to use relative paths. - -Keys are pairs "key_name = value" where value may be of string, -integer floating point or boolean, you can not store binary data -without first encoding it as a string. For performance reasons items -should be kept small, no more than a couple kilobytes. - - - __del__(self) - - - Set(ConfigBase config) -> ConfigBase - Sets the global config object (the one returned by Get) and returns a -reference to the previous global config object. - - - - - - Get(bool createOnDemand=True) -> ConfigBase - Returns the current global config object, creating one if neccessary. - - - - - - Create() -> ConfigBase - Create and return a new global config object. This function will -create the "best" implementation of wx.Config available for the -current platform. - - - DontCreateOnDemand() - Should Get() try to create a new log object if there isn't a current -one? - - - SetPath(self, String path) - Set current path: if the first character is '/', it's the absolute -path, otherwise it's a relative path. '..' is supported. If the -strPath doesn't exist it is created. - - - - - - GetPath(self) -> String - Retrieve the current path (always as absolute path) - - - GetFirstGroup() -> (more, value, index) - Allows enumerating the subgroups in a config object. Returns a tuple -containing a flag indicating there are more items, the name of the -current item, and an index to pass to GetNextGroup to fetch the next -item. - - - GetNextGroup(long index) -> (more, value, index) - Allows enumerating the subgroups in a config object. Returns a tuple -containing a flag indicating there are more items, the name of the -current item, and an index to pass to GetNextGroup to fetch the next -item. - - - - - - GetFirstEntry() -> (more, value, index) - Allows enumerating the entries in the current group in a config -object. Returns a tuple containing a flag indicating there are more -items, the name of the current item, and an index to pass to -GetNextGroup to fetch the next item. - - - GetNextEntry(long index) -> (more, value, index) - Allows enumerating the entries in the current group in a config -object. Returns a tuple containing a flag indicating there are more -items, the name of the current item, and an index to pass to -GetNextGroup to fetch the next item. - - - - - - GetNumberOfEntries(self, bool recursive=False) -> size_t - Get the number of entries in the current group, with or without its -subgroups. - - - - - - GetNumberOfGroups(self, bool recursive=False) -> size_t - Get the number of subgroups in the current group, with or without its -subgroups. - - - - - - HasGroup(self, String name) -> bool - Returns True if the group by this name exists - - - - - - HasEntry(self, String name) -> bool - Returns True if the entry by this name exists - - - - - - Exists(self, String name) -> bool - Returns True if either a group or an entry with a given name exists - - - - - - GetEntryType(self, String name) -> int - Get the type of the entry. Returns one of the wx.Config.Type_XXX values. - - - - - - Read(self, String key, String defaultVal=EmptyString) -> String - Returns the value of key if it exists, defaultVal otherwise. - - - - - - - ReadInt(self, String key, long defaultVal=0) -> long - Returns the value of key if it exists, defaultVal otherwise. - - - - - - - ReadFloat(self, String key, double defaultVal=0.0) -> double - Returns the value of key if it exists, defaultVal otherwise. - - - - - - - ReadBool(self, String key, bool defaultVal=False) -> bool - Returns the value of key if it exists, defaultVal otherwise. - - - - - - - Write(self, String key, String value) -> bool - write the value (return True on success) - - - - - - - WriteInt(self, String key, long value) -> bool - write the value (return True on success) - - - - - - - WriteFloat(self, String key, double value) -> bool - write the value (return True on success) - - - - - - - WriteBool(self, String key, bool value) -> bool - write the value (return True on success) - - - - - - - Flush(self, bool currentOnly=False) -> bool - permanently writes all changes - - - - - - RenameEntry(self, String oldName, String newName) -> bool - Rename an entry. Returns False on failure (probably because the new -name is already taken by an existing entry) - - - - - - - RenameGroup(self, String oldName, String newName) -> bool - Rename a group. Returns False on failure (probably because the new -name is already taken by an existing entry) - - - - - - - DeleteEntry(self, String key, bool deleteGroupIfEmpty=True) -> bool - Deletes the specified entry and the group it belongs to if it was the -last key in it and the second parameter is True - - - - - - - DeleteGroup(self, String key) -> bool - Delete the group (with all subgroups) - - - - - - DeleteAll(self) -> bool - Delete the whole underlying object (disk file, registry key, ...) -primarly intended for use by deinstallation routine. - - - SetExpandEnvVars(self, bool doIt=True) - We can automatically expand environment variables in the config -entries this option is on by default, you can turn it on/off at any -time) - - - - - - IsExpandingEnvVars(self) -> bool - Are we currently expanding environment variables? - - - SetRecordDefaults(self, bool doIt=True) - Set whether the config objec should record default values. - - - - - - IsRecordingDefaults(self) -> bool - Are we currently recording default values? - - - ExpandEnvVars(self, String str) -> String - Expand any environment variables in str and return the result - - - - - - GetAppName(self) -> String - - - GetVendorName(self) -> String - - - SetAppName(self, String appName) - - - - - - SetVendorName(self, String vendorName) - - - - - - SetStyle(self, long style) - - - - - - GetStyle(self) -> long - - - - This ConfigBase-derived class will use the registry on Windows, -and will be a wx.FileConfig on other platforms. - - - __init__(self, String appName=EmptyString, String vendorName=EmptyString, - String localFilename=EmptyString, String globalFilename=EmptyString, - long style=wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_GLOBAL_FILE) -> Config - - - - - - - - - - __del__(self) - - - - This config class will use a file for storage on all platforms. - - - __init__(self, String appName=EmptyString, String vendorName=EmptyString, - String localFilename=EmptyString, String globalFilename=EmptyString, - long style=wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_GLOBAL_FILE) -> FileConfig - - - - - - - - - - __del__(self) - - - - A handy little class which changes current path to the path of given -entry and restores it in the destructoir: so if you declare a local -variable of this type, you work in the entry directory and the path is -automatically restored when the function returns. - - __init__(self, ConfigBase config, String entry) -> ConfigPathChanger - - - - - - - __del__(self) - - - Name(self) -> String - Get the key name - - - - ExpandEnvVars(String sz) -> String - Replace environment variables ($SOMETHING) with their values. The -format is $VARNAME or ${VARNAME} where VARNAME contains alphanumeric -characters and '_' only. '$' must be escaped ('\\$') in order to be -taken literally. - - - - - -#--------------------------------------------------------------------------- - - - - __init__(self) -> DateTime - - - DateTimeFromTimeT(time_t timet) -> DateTime - - - - - - DateTimeFromJDN(double jdn) -> DateTime - - - - - - DateTimeFromHMS(int hour, int minute=0, int second=0, int millisec=0) -> DateTime - - - - - - - - - DateTimeFromDMY(int day, int month=Inv_Month, int year=Inv_Year, int hour=0, - int minute=0, int second=0, int millisec=0) -> DateTime - - - - - - - - - - - - __del__(self) - - - SetCountry(int country) - - - - - - GetCountry() -> int - - - IsWestEuropeanCountry(int country=Country_Default) -> bool - - - - - - GetCurrentYear(int cal=Gregorian) -> int - - - - - - ConvertYearToBC(int year) -> int - - - - - - GetCurrentMonth(int cal=Gregorian) -> int - - - - - - IsLeapYear(int year=Inv_Year, int cal=Gregorian) -> bool - - - - - - - GetCentury(int year=Inv_Year) -> int - - - - - - GetNumberOfDaysinYear(int year, int cal=Gregorian) -> int - - - - - - - GetNumberOfDaysInMonth(int month, int year=Inv_Year, int cal=Gregorian) -> int - - - - - - - - GetMonthName(int month, int flags=Name_Full) -> String - - - - - - - GetWeekDayName(int weekday, int flags=Name_Full) -> String - - - - - - - GetAmPmStrings() -> (am, pm) - Get the AM and PM strings in the current locale (may be empty) - - - - - - - IsDSTApplicable(int year=Inv_Year, int country=Country_Default) -> bool - - - - - - - GetBeginDST(int year=Inv_Year, int country=Country_Default) -> DateTime - - - - - - - GetEndDST(int year=Inv_Year, int country=Country_Default) -> DateTime - - - - - - - Now() -> DateTime - - - UNow() -> DateTime - - - Today() -> DateTime - - - SetToCurrent(self) -> DateTime - - - SetTimeT(self, time_t timet) -> DateTime - - - - - - SetJDN(self, double jdn) -> DateTime - - - - - - SetHMS(self, int hour, int minute=0, int second=0, int millisec=0) -> DateTime - - - - - - - - - Set(self, int day, int month=Inv_Month, int year=Inv_Year, int hour=0, - int minute=0, int second=0, int millisec=0) -> DateTime - - - - - - - - - - - - ResetTime(self) -> DateTime - - - SetYear(self, int year) -> DateTime - - - - - - SetMonth(self, int month) -> DateTime - - - - - - SetDay(self, int day) -> DateTime - - - - - - SetHour(self, int hour) -> DateTime - - - - - - SetMinute(self, int minute) -> DateTime - - - - - - SetSecond(self, int second) -> DateTime - - - - - - SetMillisecond(self, int millisecond) -> DateTime - - - - - - SetToWeekDayInSameWeek(self, int weekday, int flags=Monday_First) -> DateTime - - - - - - - GetWeekDayInSameWeek(self, int weekday, int flags=Monday_First) -> DateTime - - - - - - - SetToNextWeekDay(self, int weekday) -> DateTime - - - - - - GetNextWeekDay(self, int weekday) -> DateTime - - - - - - SetToPrevWeekDay(self, int weekday) -> DateTime - - - - - - GetPrevWeekDay(self, int weekday) -> DateTime - - - - - - SetToWeekDay(self, int weekday, int n=1, int month=Inv_Month, int year=Inv_Year) -> bool - - - - - - - - - SetToLastWeekDay(self, int weekday, int month=Inv_Month, int year=Inv_Year) -> bool - - - - - - - - GetLastWeekDay(self, int weekday, int month=Inv_Month, int year=Inv_Year) -> DateTime - - - - - - - - SetToTheWeek(self, int numWeek, int weekday=Mon, int flags=Monday_First) -> bool - - - - - - - - GetWeek(self, int numWeek, int weekday=Mon, int flags=Monday_First) -> DateTime - - - - - - - - SetToLastMonthDay(self, int month=Inv_Month, int year=Inv_Year) -> DateTime - - - - - - - GetLastMonthDay(self, int month=Inv_Month, int year=Inv_Year) -> DateTime - - - - - - - SetToYearDay(self, int yday) -> DateTime - - - - - - GetYearDay(self, int yday) -> DateTime - - - - - - GetJulianDayNumber(self) -> double - - - GetJDN(self) -> double - - - GetModifiedJulianDayNumber(self) -> double - - - GetMJD(self) -> double - - - GetRataDie(self) -> double - - - ToTimezone(self, wxDateTime::TimeZone tz, bool noDST=False) -> DateTime - - - - - - - MakeTimezone(self, wxDateTime::TimeZone tz, bool noDST=False) -> DateTime - - - - - - - ToGMT(self, bool noDST=False) -> DateTime - - - - - - MakeGMT(self, bool noDST=False) -> DateTime - - - - - - IsDST(self, int country=Country_Default) -> int - - - - - - IsValid(self) -> bool - - - GetTicks(self) -> time_t - - - GetYear(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - GetMonth(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - GetDay(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - GetWeekDay(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - GetHour(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - GetMinute(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - GetSecond(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - GetMillisecond(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - GetDayOfYear(self, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - GetWeekOfYear(self, int flags=Monday_First, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - - GetWeekOfMonth(self, int flags=Monday_First, wxDateTime::TimeZone tz=LOCAL_TZ) -> int - - - - - - - IsWorkDay(self, int country=Country_Default) -> bool - - - - - - IsEqualTo(self, DateTime datetime) -> bool - - - - - - IsEarlierThan(self, DateTime datetime) -> bool - - - - - - IsLaterThan(self, DateTime datetime) -> bool - - - - - - IsStrictlyBetween(self, DateTime t1, DateTime t2) -> bool - - - - - - - IsBetween(self, DateTime t1, DateTime t2) -> bool - - - - - - - IsSameDate(self, DateTime dt) -> bool - - - - - - IsSameTime(self, DateTime dt) -> bool - - - - - - IsEqualUpTo(self, DateTime dt, TimeSpan ts) -> bool - - - - - - - AddTS(self, TimeSpan diff) -> DateTime - - - - - - AddDS(self, DateSpan diff) -> DateTime - - - - - - SubtractTS(self, TimeSpan diff) -> DateTime - - - - - - SubtractDS(self, DateSpan diff) -> DateTime - - - - - - Subtract(self, DateTime dt) -> TimeSpan - - - - - - - - - - - __iadd__(self, TimeSpan diff) -> DateTime -__iadd__(self, DateSpan diff) -> DateTime - - - - - - - - - - - __isub__(self, TimeSpan diff) -> DateTime -__isub__(self, DateSpan diff) -> DateTime - - - - - - - - - - - __add__(self, TimeSpan other) -> DateTime -__add__(self, DateSpan other) -> DateTime - - - - - - - - - - - - - - - - __sub__(self, DateTime other) -> TimeSpan -__sub__(self, TimeSpan other) -> DateTime -__sub__(self, DateSpan other) -> DateTime - - - - - - __lt__(self, DateTime other) -> bool - - - - - - __le__(self, DateTime other) -> bool - - - - - - __gt__(self, DateTime other) -> bool - - - - - - __ge__(self, DateTime other) -> bool - - - - - - __eq__(self, DateTime other) -> bool - - - - - - __ne__(self, DateTime other) -> bool - - - - - - ParseRfc822Date(self, String date) -> int - - - - - - ParseFormat(self, String date, String format=DateFormatStr, DateTime dateDef=DefaultDateTime) -> int - - - - - - - - ParseDateTime(self, String datetime) -> int - - - - - - ParseDate(self, String date) -> int - - - - - - ParseTime(self, String time) -> int - - - - - - Format(self, String format=DateFormatStr, wxDateTime::TimeZone tz=LOCAL_TZ) -> String - - - - - - - FormatDate(self) -> String - - - FormatTime(self) -> String - - - FormatISODate(self) -> String - - - FormatISOTime(self) -> String - - - - - __init__(self, long hours=0, long minutes=0, long seconds=0, long milliseconds=0) -> TimeSpan - - - - - - - - - __del__(self) - - - Seconds(long sec) -> TimeSpan - - - - - - Second() -> TimeSpan - - - Minutes(long min) -> TimeSpan - - - - - - Minute() -> TimeSpan - - - Hours(long hours) -> TimeSpan - - - - - - Hour() -> TimeSpan - - - Days(long days) -> TimeSpan - - - - - - Day() -> TimeSpan - - - Weeks(long days) -> TimeSpan - - - - - - Week() -> TimeSpan - - - Add(self, TimeSpan diff) -> TimeSpan - - - - - - Subtract(self, TimeSpan diff) -> TimeSpan - - - - - - Multiply(self, int n) -> TimeSpan - - - - - - Neg(self) -> TimeSpan - - - Abs(self) -> TimeSpan - - - __iadd__(self, TimeSpan diff) -> TimeSpan - - - - - - __isub__(self, TimeSpan diff) -> TimeSpan - - - - - - __imul__(self, int n) -> TimeSpan - - - - - - __neg__(self) -> TimeSpan - - - __add__(self, TimeSpan other) -> TimeSpan - - - - - - __sub__(self, TimeSpan other) -> TimeSpan - - - - - - __mul__(self, int n) -> TimeSpan - - - - - - __rmul__(self, int n) -> TimeSpan - - - - - - __lt__(self, TimeSpan other) -> bool - - - - - - __le__(self, TimeSpan other) -> bool - - - - - - __gt__(self, TimeSpan other) -> bool - - - - - - __ge__(self, TimeSpan other) -> bool - - - - - - __eq__(self, TimeSpan other) -> bool - - - - - - __ne__(self, TimeSpan other) -> bool - - - - - - IsNull(self) -> bool - - - IsPositive(self) -> bool - - - IsNegative(self) -> bool - - - IsEqualTo(self, TimeSpan ts) -> bool - - - - - - IsLongerThan(self, TimeSpan ts) -> bool - - - - - - IsShorterThan(self, TimeSpan t) -> bool - - - - - - GetWeeks(self) -> int - - - GetDays(self) -> int - - - GetHours(self) -> int - - - GetMinutes(self) -> int - - - GetSeconds(self) -> wxLongLong - - - GetMilliseconds(self) -> wxLongLong - - - Format(self, String format=TimeSpanFormatStr) -> String - - - - - - - - __init__(self, int years=0, int months=0, int weeks=0, int days=0) -> DateSpan - - - - - - - - - __del__(self) - - - Days(int days) -> DateSpan - - - - - - Day() -> DateSpan - - - Weeks(int weeks) -> DateSpan - - - - - - Week() -> DateSpan - - - Months(int mon) -> DateSpan - - - - - - Month() -> DateSpan - - - Years(int years) -> DateSpan - - - - - - Year() -> DateSpan - - - SetYears(self, int n) -> DateSpan - - - - - - SetMonths(self, int n) -> DateSpan - - - - - - SetWeeks(self, int n) -> DateSpan - - - - - - SetDays(self, int n) -> DateSpan - - - - - - GetYears(self) -> int - - - GetMonths(self) -> int - - - GetWeeks(self) -> int - - - GetDays(self) -> int - - - GetTotalDays(self) -> int - - - Add(self, DateSpan other) -> DateSpan - - - - - - Subtract(self, DateSpan other) -> DateSpan - - - - - - Neg(self) -> DateSpan - - - Multiply(self, int factor) -> DateSpan - - - - - - __iadd__(self, DateSpan other) -> DateSpan - - - - - - __isub__(self, DateSpan other) -> DateSpan - - - - - - __neg__(self) -> DateSpan - - - __imul__(self, int factor) -> DateSpan - - - - - - __add__(self, DateSpan other) -> DateSpan - - - - - - __sub__(self, DateSpan other) -> DateSpan - - - - - - __mul__(self, int n) -> DateSpan - - - - - - __rmul__(self, int n) -> DateSpan - - - - - - __eq__(self, DateSpan other) -> bool - - - - - - __ne__(self, DateSpan other) -> bool - - - - - - - GetLocalTime() -> long - - - GetUTCTime() -> long - - - GetCurrentTime() -> long - - - GetLocalTimeMillis() -> wxLongLong - - -#--------------------------------------------------------------------------- - - - A wx.DataFormat is an encapsulation of a platform-specific format -handle which is used by the system for the clipboard and drag and drop -operations. The applications are usually only interested in, for -example, pasting data from the clipboard only if the data is in a -format the program understands. A data format is is used to uniquely -identify this format. -On the system level, a data format is usually just a number, (which -may be the CLIPFORMAT under Windows or Atom under X11, for example.) - -The standard format IDs are: - - ================ ===================================== - wx.DF_INVALID An invalid format - wx.DF_TEXT Text format - wx.DF_BITMAP A bitmap (wx.Bitmap) - wx.DF_METAFILE A metafile (wx.Metafile, Windows only) - wx.DF_FILENAME A list of filenames - wx.DF_HTML An HTML string. This is only valid on - Windows and non-unicode builds - ================ ===================================== - -Aside the standard formats, the application may also use custom -formats which are identified by their names (strings) and not numeric -identifiers. Although internally custom format must be created (or -registered) first, you shouldn't care about it because it is done -automatically the first time the wxDataFormat object corresponding to -a given format name is created. - - - - __init__(self, int type) -> DataFormat - Constructs a data format object for one of the standard data formats -or an empty data object (use SetType or SetId later in this case) - - - - - - CustomDataFormat(String format) -> DataFormat - Constructs a data format object for a custom format identified by its -name. - - - - - - __del__(self) - - - - - - - - - - - - - __eq__(self, int format) -> bool -__eq__(self, DataFormat format) -> bool - - - - - - __ne__(self, int format) -> bool -__ne__(self, DataFormat format) -> bool - - - - - - SetType(self, int format) - Sets the format to the given value, which should be one of wx.DF_XXX -constants. - - - - - - GetType(self) -> int - Returns the platform-specific number identifying the format. - - - GetId(self) -> String - Returns the name of a custom format (this function will fail for a -standard format). - - - SetId(self, String format) - Sets the format to be the custom format identified by the given name. - - - - - - - A wx.DataObject represents data that can be copied to or from the -clipboard, or dragged and dropped. The important thing about -wx.DataObject is that this is a 'smart' piece of data unlike usual -'dumb' data containers such as memory buffers or files. Being 'smart' -here means that the data object itself should know what data formats -it supports and how to render itself in each of supported formats. - -**NOTE**: This class is an abstract base class and can not be used -directly from Python. If you need a custom type of data object then -you should instead derive from `wx.PyDataObjectSimple` or use -`wx.CustomDataObject`. - -Not surprisingly, being 'smart' comes at a price of added -complexity. This is reasonable for the situations when you really need -to support multiple formats, but may be annoying if you only want to -do something simple like cut and paste text. - -To provide a solution for both cases, wxWidgets has two predefined -classes which derive from wx.DataObject: `wx.DataObjectSimple` and -`wx.DataObjectComposite`. `wx.DataObjectSimple` is the simplest -wx.DataObject possible and only holds data in a single format (such as -text or bitmap) and `wx.DataObjectComposite` is the simplest way to -implement a wx.DataObject which supports multiple simultaneous formats -because it achievs this by simply holding several -`wx.DataObjectSimple` objects. - -Please note that the easiest way to use drag and drop and the -clipboard with multiple formats is by using `wx.DataObjectComposite`, -but it is not the most efficient one as each `wx.DataObjectSimple` -would contain the whole data in its respective formats. Now imagine -that you want to paste 200 pages of text in your proprietary format, -as well as Word, RTF, HTML, Unicode and plain text to the clipboard -and even today's computers are in trouble. For this case, you will -have to derive from wx.DataObject directly and make it enumerate its -formats and provide the data in the requested format on -demand. (**TODO**: This is currently not possible from Python. Make -it so.) - -Note that the platform transfer mechanisms for the clipboard and drag -and drop, do not copy any data out of the source application until -another application actually requests the data. This is in contrast to -the 'feel' offered to the user of a program who would normally think -that the data resides in the clipboard after having pressed 'Copy' - -in reality it is only declared to be available. - - - __del__(self) - - - GetPreferredFormat(self, int dir=Get) -> DataFormat - Returns the preferred format for either rendering the data (if dir is -Get, its default value) or for setting it. Usually this will be the -native format of the wx.DataObject. - - - - - - GetFormatCount(self, int dir=Get) -> size_t - Returns the number of available formats for rendering or setting the -data. - - - - - - IsSupported(self, DataFormat format, int dir=Get) -> bool - Returns True if this format is supported. - - - - - - - GetDataSize(self, DataFormat format) -> size_t - Get the (total) size of data for the given format - - - - - - GetAllFormats(self, int dir=Get) -> [formats] - Returns a list of all the wx.DataFormats that this dataobject supports -in the given direction. - - - - - - GetDataHere(self, DataFormat format) -> String - Get the data bytes in the specified format, returns None on failure. - -:todo: This should use the python buffer interface isntead... - - - - - - SetData(self, DataFormat format, String data) -> bool - Set the data in the specified format from the bytes in the the data string. - -:todo: This should use the python buffer interface isntead... - - - - - - - - wx.DataObjectSimple is a `wx.DataObject` which only supports one -format. This is the simplest possible `wx.DataObject` implementation. - -This is still an "abstract base class" meaning that you can't use it -directly. You either need to use one of the predefined base classes, -or derive your own class from `wx.PyDataObjectSimple`. - - - - __init__(self, DataFormat format=FormatInvalid) -> DataObjectSimple - Constructor accepts the supported format (none by default) which may -also be set later with `SetFormat`. - - - - - - GetFormat(self) -> DataFormat - Returns the (one and only one) format supported by this object. It is -assumed that the format is supported in both directions. - - - SetFormat(self, DataFormat format) - Sets the supported format. - - - - - - GetDataSize(self) -> size_t - Get the size of our data. - - - GetDataHere(self) -> String - Returns the data bytes from the data object as a string, returns None -on failure. Must be implemented in the derived class if the object -supports rendering its data. - - - SetData(self, String data) -> bool - Copy the data value to the data object. Must be implemented in the -derived class if the object supports setting its data. - - - - - - - - wx.PyDataObjectSimple is a version of `wx.DataObjectSimple` that is -Python-aware and knows how to reflect calls to its C++ virtual methods -to methods in the Python derived class. You should derive from this -class and overload `GetDataSize`, `GetDataHere` and `SetData` when you -need to create your own simple single-format type of `wx.DataObject`. - -Here is a simple example:: - - class MyDataObject(wx.PyDataObjectSimple): - def __init__(self): - wx.PyDataObjectSimple.__init__( - self, wx.CustomDataFormat('MyDOFormat')) - self.data = '' - - def GetDataSize(self): - return len(self.data) - def GetDataHere(self): - return self.data # returns a string - def SetData(self, data): - self.data = data - return True - -Note that there is already a `wx.CustomDataObject` class that behaves -very similarly to this example. The value of creating your own -derived class like this is to be able to do additional things when the -data is requested or given via the clipboard or drag and drop -operation, such as generate the data value or decode it into needed -data structures. - - - - __init__(self, DataFormat format=FormatInvalid) -> PyDataObjectSimple - wx.PyDataObjectSimple is a version of `wx.DataObjectSimple` that is -Python-aware and knows how to reflect calls to its C++ virtual methods -to methods in the Python derived class. You should derive from this -class and overload `GetDataSize`, `GetDataHere` and `SetData` when you -need to create your own simple single-format type of `wx.DataObject`. - -Here is a simple example:: - - class MyDataObject(wx.PyDataObjectSimple): - def __init__(self): - wx.PyDataObjectSimple.__init__( - self, wx.CustomDataFormat('MyDOFormat')) - self.data = '' - - def GetDataSize(self): - return len(self.data) - def GetDataHere(self): - return self.data # returns a string - def SetData(self, data): - self.data = data - return True - -Note that there is already a `wx.CustomDataObject` class that behaves -very similarly to this example. The value of creating your own -derived class like this is to be able to do additional things when the -data is requested or given via the clipboard or drag and drop -operation, such as generate the data value or decode it into needed -data structures. - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - - wx.DataObjectComposite is the simplest `wx.DataObject` derivation -which may be sued to support multiple formats. It contains several -'wx.DataObjectSimple` objects and supports any format supported by at -least one of them. Only one of these data objects is *preferred* (the -first one if not explicitly changed by using the second parameter of -`Add`) and its format determines the preferred format of the composite -data object as well. - -See `wx.DataObject` documentation for the reasons why you might prefer -to use wx.DataObject directly instead of wx.DataObjectComposite for -efficiency reasons. - - - - __init__(self) -> DataObjectComposite - wx.DataObjectComposite is the simplest `wx.DataObject` derivation -which may be sued to support multiple formats. It contains several -'wx.DataObjectSimple` objects and supports any format supported by at -least one of them. Only one of these data objects is *preferred* (the -first one if not explicitly changed by using the second parameter of -`Add`) and its format determines the preferred format of the composite -data object as well. - -See `wx.DataObject` documentation for the reasons why you might prefer -to use wx.DataObject directly instead of wx.DataObjectComposite for -efficiency reasons. - - - - Add(self, DataObjectSimple dataObject, bool preferred=False) - Adds the dataObject to the list of supported objects and it becomes -the preferred object if preferred is True. - - - - - - - - wx.TextDataObject is a specialization of `wx.DataObject` for text -data. It can be used without change to paste data into the `wx.Clipboard` -or a `wx.DropSource`. - -Alternativly, you may wish to derive a new class from the -`wx.PyTextDataObject` class for providing text on-demand in order to -minimize memory consumption when offering data in several formats, -such as plain text and RTF, because by default the text is stored in a -string in this class, but it might as well be generated on demand when -requested. For this, `GetTextLength` and `GetText` will have to be -overridden. - - - __init__(self, String text=EmptyString) -> TextDataObject - Constructor, may be used to initialise the text (otherwise `SetText` -should be used later). - - - - - - GetTextLength(self) -> size_t - Returns the data size. By default, returns the size of the text data -set in the constructor or using `SetText`. This can be overridden (via -`wx.PyTextDataObject`) to provide text size data on-demand. It is -recommended to return the text length plus 1 for a trailing zero, but -this is not strictly required. - - - GetText(self) -> String - Returns the text associated with the data object. - - - SetText(self, String text) - Sets the text associated with the data object. This method is called -when the data object receives the data and, by default, copies the -text into the member variable. If you want to process the text on the -fly you may wish to override this function (via -`wx.PyTextDataObject`.) - - - - - - - wx.PyTextDataObject is a version of `wx.TextDataObject` that is -Python-aware and knows how to reflect calls to its C++ virtual methods -to methods in the Python derived class. You should derive from this -class and overload `GetTextLength`, `GetText`, and `SetText` when you -want to be able to provide text on demand instead of preloading it -into the data object. - - - __init__(self, String text=EmptyString) -> PyTextDataObject - wx.PyTextDataObject is a version of `wx.TextDataObject` that is -Python-aware and knows how to reflect calls to its C++ virtual methods -to methods in the Python derived class. You should derive from this -class and overload `GetTextLength`, `GetText`, and `SetText` when you -want to be able to provide text on demand instead of preloading it -into the data object. - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - - wx.BitmapDataObject is a specialization of wxDataObject for bitmap -data. It can be used without change to paste data into the `wx.Clipboard` -or a `wx.DropSource`. - -:see: `wx.PyBitmapDataObject` if you wish to override `GetBitmap` to increase efficiency. - - - __init__(self, Bitmap bitmap=wxNullBitmap) -> BitmapDataObject - Constructor, optionally passing a bitmap (otherwise use `SetBitmap` -later). - - - - - - GetBitmap(self) -> Bitmap - Returns the bitmap associated with the data object. You may wish to -override this method (by deriving from `wx.PyBitmapDataObject`) when -offering data on-demand, but this is not required by wxWidgets' -internals. Use this method to get data in bitmap form from the -`wx.Clipboard`. - - - SetBitmap(self, Bitmap bitmap) - Sets the bitmap associated with the data object. This method is called -when the data object receives data. Usually there will be no reason to -override this function. - - - - - - - wx.PyBitmapDataObject is a version of `wx.BitmapDataObject` that is -Python-aware and knows how to reflect calls to its C++ virtual methods -to methods in the Python derived class. To be able to provide bitmap -data on demand derive from this class and overload `GetBitmap`. - - - __init__(self, Bitmap bitmap=wxNullBitmap) -> PyBitmapDataObject - wx.PyBitmapDataObject is a version of `wx.BitmapDataObject` that is -Python-aware and knows how to reflect calls to its C++ virtual methods -to methods in the Python derived class. To be able to provide bitmap -data on demand derive from this class and overload `GetBitmap`. - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - - wx.FileDataObject is a specialization of `wx.DataObjectSimple` for -file names. The program works with it just as if it were a list of -absolute file names, but internally it uses the same format as -Explorer and other compatible programs under Windows or GNOME/KDE -filemanager under Unix which makes it possible to receive files from -them using this class. - -:Warning: Under all non-Windows platforms this class is currently - "input-only", i.e. you can receive the files from another - application, but copying (or dragging) file(s) from a wxWidgets - application is not currently supported. - - - - __init__(self) -> FileDataObject - - - GetFilenames(self) -> [names] - Returns a list of file names. - - - AddFile(self, String filename) - Adds a file to the list of files represented by this data object. - - - - - - - wx.CustomDataObject is a specialization of `wx.DataObjectSimple` for -some application-specific data in arbitrary format. Python strings -are used for getting and setting data, but any picklable object can -easily be transfered via strings. A copy of the data is stored in the -data object. - - - __init__(self, DataFormat format=FormatInvalid) -> CustomDataObject - wx.CustomDataObject is a specialization of `wx.DataObjectSimple` for -some application-specific data in arbitrary format. Python strings -are used for getting and setting data, but any picklable object can -easily be transfered via strings. A copy of the data is stored in the -data object. - - - - - - SetData(self, String data) -> bool - Copy the data value to the data object. - - - - - - GetSize(self) -> size_t - Get the size of the data. - - - GetData(self) -> String - Returns the data bytes from the data object as a string. - - - - This data object holds a URL in a format that is compatible with some -browsers such that it is able to be dragged to or from them. - - - __init__(self) -> URLDataObject - This data object holds a URL in a format that is compatible with some -browsers such that it is able to be dragged to or from them. - - - GetURL(self) -> String - Returns a string containing the current URL. - - - SetURL(self, String url) - Set the URL. - - - - - - - - - __init__(self) -> MetafileDataObject - - - -#--------------------------------------------------------------------------- - - - IsDragResultOk(int res) -> bool - - - - - - - __init__(self, Window win, Icon copy=wxNullIcon, Icon move=wxNullIcon, - Icon none=wxNullIcon) -> DropSource - - - - - - - - - __del__(self) - - - _setCallbackInfo(self, PyObject self, PyObject _class, int incref) - - - - - - - - SetData(self, DataObject data) - - - - - - GetDataObject(self) -> DataObject - - - SetCursor(self, int res, Cursor cursor) - - - - - - - DoDragDrop(self, int flags=Drag_CopyOnly) -> int - - - - - - base_GiveFeedback(self, int effect) -> bool - - - - - - - - __init__(self, DataObject dataObject=None) -> DropTarget - - - - - - __del__(self) - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - GetDataObject(self) -> DataObject - - - SetDataObject(self, DataObject dataObject) - - - - - - base_OnEnter(self, int x, int y, int def) -> int - - - - - - - - base_OnDragOver(self, int x, int y, int def) -> int - - - - - - - - base_OnLeave(self) - - - base_OnDrop(self, int x, int y) -> bool - - - - - - - GetData(self) -> bool - - - PyDropTarget = DropTarget - - - - __init__(self) -> TextDropTarget - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_OnEnter(self, int x, int y, int def) -> int - - - - - - - - base_OnDragOver(self, int x, int y, int def) -> int - - - - - - - - base_OnLeave(self) - - - base_OnDrop(self, int x, int y) -> bool - - - - - - - base_OnData(self, int x, int y, int def) -> int - - - - - - - - - - - __init__(self) -> FileDropTarget - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_OnEnter(self, int x, int y, int def) -> int - - - - - - - - base_OnDragOver(self, int x, int y, int def) -> int - - - - - - - - base_OnLeave(self) - - - base_OnDrop(self, int x, int y) -> bool - - - - - - - base_OnData(self, int x, int y, int def) -> int - - - - - - - - -#--------------------------------------------------------------------------- - - - wx.Clipboard represents the system clipboard and provides methods to -copy data to it or paste data from it. Normally, you should only use -``wx.TheClipboard`` which is a reference to a global wx.Clipboard -instance. - -Call ``wx.TheClipboard``'s `Open` method to get ownership of the -clipboard. If this operation returns True, you now own the -clipboard. Call `SetData` to put data on the clipboard, or `GetData` -to retrieve data from the clipboard. Call `Close` to close the -clipboard and relinquish ownership. You should keep the clipboard open -only momentarily. - -:see: `wx.DataObject` - - - - __init__(self) -> Clipboard - - - __del__(self) - - - Open(self) -> bool - Call this function to open the clipboard before calling SetData and -GetData. Call Close when you have finished with the clipboard. You -should keep the clipboard open for only a very short time. Returns -True on success. - - - Close(self) - Closes the clipboard. - - - IsOpened(self) -> bool - Query whether the clipboard is opened - - - AddData(self, DataObject data) -> bool - Call this function to add the data object to the clipboard. You may -call this function repeatedly after having cleared the clipboard. -After this function has been called, the clipboard owns the data, so -do not delete the data explicitly. - -:see: `wx.DataObject` - - - - - - SetData(self, DataObject data) -> bool - Set the clipboard data, this is the same as `Clear` followed by -`AddData`. - -:see: `wx.DataObject` - - - - - - IsSupported(self, DataFormat format) -> bool - Returns True if the given format is available in the data object(s) on -the clipboard. - - - - - - GetData(self, DataObject data) -> bool - Call this function to fill data with data on the clipboard, if -available in the required format. Returns true on success. - - - - - - Clear(self) - Clears data from the clipboard object and also the system's clipboard -if possible. - - - Flush(self) -> bool - Flushes the clipboard: this means that the data which is currently on -clipboard will stay available even after the application exits, -possibly eating memory, otherwise the clipboard will be emptied on -exit. Returns False if the operation is unsuccesful for any reason. - - - UsePrimarySelection(self, bool primary=True) - On platforms supporting it (the X11 based platforms), selects the -so called PRIMARY SELECTION as the clipboard as opposed to the -normal clipboard, if primary is True. - - - - - - Get() -> Clipboard - Returns global instance (wxTheClipboard) of the object. - - - - class _wxPyDelayedInitWrapper(object): - def __init__(self, initfunc, *args, **kwargs): - self._initfunc = initfunc - self._args = args - self._kwargs = kwargs - self._instance = None - def _checkInstance(self): - if self._instance is None: - self._instance = self._initfunc(*self._args, **self._kwargs) - def __getattr__(self, name): - self._checkInstance() - return getattr(self._instance, name) - def __repr__(self): - self._checkInstance() - return repr(self._instance) - TheClipboard = _wxPyDelayedInitWrapper(Clipboard.Get) - - - A helpful class for opening the clipboard and automatically -closing it when the locker is destroyed. - - __init__(self, Clipboard clipboard=None) -> ClipboardLocker - A helpful class for opening the clipboard and automatically -closing it when the locker is destroyed. - - - - - - __del__(self) - - - __nonzero__(self) -> bool - A ClipboardLocker instance evaluates to True if the clipboard was -successfully opened. - - - -#--------------------------------------------------------------------------- - - - A simple struct containing video mode parameters for a display - - __init__(self, int width=0, int height=0, int depth=0, int freq=0) -> VideoMode - A simple struct containing video mode parameters for a display - - - - - - - - - __del__(self) - - - Matches(self, VideoMode other) -> bool - Returns true if this mode matches the other one in the sense that all -non zero fields of the other mode have the same value in this -one (except for refresh which is allowed to have a greater value) - - - - - - GetWidth(self) -> int - Returns the screen width in pixels (e.g. 640*480), 0 means unspecified - - - GetHeight(self) -> int - Returns the screen width in pixels (e.g. 640*480), 0 means -unspecified - - - GetDepth(self) -> int - Returns the screen's bits per pixel (e.g. 32), 1 is monochrome and 0 -means unspecified/known - - - IsOk(self) -> bool - returns true if the object has been initialized - - - __eq__(self, VideoMode other) -> bool - - - - - - __ne__(self, VideoMode other) -> bool - - - - - - - - - - - Represents a display/monitor attached to the system - - __init__(self, size_t index=0) -> Display - Set up a Display instance with the specified display. The displays -are numbered from 0 to GetCount() - 1, 0 is always the primary display -and the only one which is always supported - - - - - - __del__(self) - - - GetCount() -> size_t - Return the number of available displays. - - - GetFromPoint(Point pt) -> int - Find the display where the given point lies, return wx.NOT_FOUND if it -doesn't belong to any display - - - - - - GetFromWindow(Window window) -> int - Find the display where the given window lies, return wx.NOT_FOUND if -it is not shown at all. - - - - - - IsOk(self) -> bool - Return true if the object was initialized successfully - - - GetGeometry(self) -> Rect - Returns the bounding rectangle of the display whose index was passed -to the constructor. - - - GetName(self) -> String - Returns the display's name. A name is not available on all platforms. - - - IsPrimary(self) -> bool - Returns true if the display is the primary display. The primary -display is the one whose index is 0. - - - GetModes(VideoMode mode=DefaultVideoMode) -> [videoMode...] - Enumerate all video modes supported by this display matching the given -one (in the sense of VideoMode.Match()). - -As any mode matches the default value of the argument and there is -always at least one video mode supported by display, the returned -array is only empty for the default value of the argument if this -function is not supported at all on this platform. - - - - - - GetCurrentMode(self) -> VideoMode - Get the current video mode. - - - ChangeMode(self, VideoMode mode=DefaultVideoMode) -> bool - Changes the video mode of this display to the mode specified in the -mode parameter. - -If wx.DefaultVideoMode is passed in as the mode parameter, the defined -behaviour is that wx.Display will reset the video mode to the default -mode used by the display. On Windows, the behavior is normal. -However, there are differences on other platforms. On Unix variations -using X11 extensions it should behave as defined, but some -irregularities may occur. - -On wxMac passing in wx.DefaultVideoMode as the mode parameter does -nothing. This happens because Carbon no longer has access to -DMUseScreenPrefs, an undocumented function that changed the video mode -to the system default by using the system's 'scrn' resource. - -Returns True if succeeded, False otherwise - - - - - - ResetMode(self) - Restore the default video mode (just a more readable synonym) - - - - - - wx = _core - __docfilter__ = wx.__DocFilter(globals()) - - A set of customization attributes for a calendar date, which can be -used to control the look of the Calendar object. - - __init__(self, Colour colText=wxNullColour, Colour colBack=wxNullColour, - Colour colBorder=wxNullColour, Font font=wxNullFont, - int border=CAL_BORDER_NONE) -> CalendarDateAttr - Create a CalendarDateAttr. - - - - - - - - - - SetTextColour(self, Colour colText) - - - - - - SetBackgroundColour(self, Colour colBack) - - - - - - SetBorderColour(self, Colour col) - - - - - - SetFont(self, Font font) - - - - - - SetBorder(self, int border) - - - - - - SetHoliday(self, bool holiday) - - - - - - HasTextColour(self) -> bool - - - HasBackgroundColour(self) -> bool - - - HasBorderColour(self) -> bool - - - HasFont(self) -> bool - - - HasBorder(self) -> bool - - - IsHoliday(self) -> bool - - - GetTextColour(self) -> Colour - - - GetBackgroundColour(self) -> Colour - - - GetBorderColour(self) -> Colour - - - GetFont(self) -> Font - - - GetBorder(self) -> int - - - - - - __init__(self, CalendarCtrl cal, wxEventType type) -> CalendarEvent - - - - - - - GetDate(self) -> DateTime - - - SetDate(self, DateTime date) - - - - - - SetWeekDay(self, int wd) - - - - - - GetWeekDay(self) -> int - - - -EVT_CALENDAR = wx.PyEventBinder( wxEVT_CALENDAR_DOUBLECLICKED, 1) -EVT_CALENDAR_SEL_CHANGED = wx.PyEventBinder( wxEVT_CALENDAR_SEL_CHANGED, 1) -EVT_CALENDAR_DAY = wx.PyEventBinder( wxEVT_CALENDAR_DAY_CHANGED, 1) -EVT_CALENDAR_MONTH = wx.PyEventBinder( wxEVT_CALENDAR_MONTH_CHANGED, 1) -EVT_CALENDAR_YEAR = wx.PyEventBinder( wxEVT_CALENDAR_YEAR_CHANGED, 1) -EVT_CALENDAR_WEEKDAY_CLICKED = wx.PyEventBinder( wxEVT_CALENDAR_WEEKDAY_CLICKED, 1) - - - The calendar control allows the user to pick a date interactively. - -The CalendarCtrl displays a window containing several parts: the -control to pick the month and the year at the top (either or both of -them may be disabled) and a month area below them which shows all the -days in the month. The user can move the current selection using the -keyboard and select the date (generating EVT_CALENDAR event) by -pressing <Return> or double clicking it. - -It has advanced possibilities for the customization of its -display. All global settings (such as colours and fonts used) can, of -course, be changed. But also, the display style for each day in the -month can be set independently using CalendarDateAttr class. - -An item without custom attributes is drawn with the default colours -and font and without border, but setting custom attributes with -SetAttr allows to modify its appearance. Just create a custom -attribute object and set it for the day you want to be displayed -specially A day may be marked as being a holiday, (even if it is not -recognized as one by wx.DateTime) by using the SetHoliday method. - -As the attributes are specified for each day, they may change when the -month is changed, so you will often want to update them in an -EVT_CALENDAR_MONTH event handler. - -Window Styles -------------- - ============================== ============================ - CAL_SUNDAY_FIRST Show Sunday as the first day - in the week - CAL_MONDAY_FIRST Show Monday as the first day - in the week - CAL_SHOW_HOLIDAYS Highlight holidays in the - calendar - CAL_NO_YEAR_CHANGE Disable the year changing - CAL_NO_MONTH_CHANGE Disable the month (and, - implicitly, the year) changing - CAL_SHOW_SURROUNDING_WEEKS Show the neighbouring weeks in - the previous and next months - CAL_SEQUENTIAL_MONTH_SELECTION Use alternative, more compact, - style for the month and year - selection controls. - ============================== ============================ - -The default calendar style is CAL_SHOW_HOLIDAYS. - -Events -------- - ============================= ============================== - EVT_CALENDAR A day was double clicked in the - calendar. - EVT_CALENDAR_SEL_CHANGED The selected date changed. - EVT_CALENDAR_DAY The selected day changed. - EVT_CALENDAR_MONTH The selected month changed. - EVT_CALENDAR_YEAR The selected year changed. - EVT_CALENDAR_WEEKDAY_CLICKED User clicked on the week day - header - ============================= ============================== - -Note that changing the selected date will result in one of -EVT_CALENDAR_DAY, MONTH or YEAR events and an EVT_CALENDAR_SEL_CHANGED -event. - - - - - __init__(self, Window parent, int id=-1, DateTime date=DefaultDateTime, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=wxCAL_SHOW_HOLIDAYS|wxWANTS_CHARS, - String name=CalendarNameStr) -> CalendarCtrl - Create and show a calendar control. - - - - - - - - - - - - PreCalendarCtrl() -> CalendarCtrl - Precreate a CalendarCtrl for 2-phase creation. - - - Create(self, Window parent, int id, DateTime date=DefaultDateTime, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=wxCAL_SHOW_HOLIDAYS|wxWANTS_CHARS, - String name=CalendarNameStr) -> bool - Acutally create the GUI portion of the CalendarCtrl for 2-phase -creation. - - - - - - - - - - - - SetDate(self, DateTime date) - Sets the current date. - - - - - - GetDate(self) -> DateTime - Gets the currently selected date. - - - SetLowerDateLimit(self, DateTime date=DefaultDateTime) -> bool - set the range in which selection can occur - - - - - - SetUpperDateLimit(self, DateTime date=DefaultDateTime) -> bool - set the range in which selection can occur - - - - - - GetLowerDateLimit(self) -> DateTime - get the range in which selection can occur - - - GetUpperDateLimit(self) -> DateTime - get the range in which selection can occur - - - SetDateRange(self, DateTime lowerdate=DefaultDateTime, DateTime upperdate=DefaultDateTime) -> bool - set the range in which selection can occur - - - - - - - EnableYearChange(self, bool enable=True) - This function should be used instead of changing CAL_NO_YEAR_CHANGE -style bit directly. It allows or disallows the user to change the year -interactively. - - - - - - EnableMonthChange(self, bool enable=True) - This function should be used instead of changing CAL_NO_MONTH_CHANGE -style bit. It allows or disallows the user to change the month -interactively. Note that if the month can not be changed, the year can -not be changed either. - - - - - - EnableHolidayDisplay(self, bool display=True) - This function should be used instead of changing CAL_SHOW_HOLIDAYS -style bit directly. It enables or disables the special highlighting of -the holidays. - - - - - - SetHeaderColours(self, Colour colFg, Colour colBg) - Header colours are used for painting the weekdays at the top. - - - - - - - GetHeaderColourFg(self) -> Colour - Header colours are used for painting the weekdays at the top. - - - GetHeaderColourBg(self) -> Colour - Header colours are used for painting the weekdays at the top. - - - SetHighlightColours(self, Colour colFg, Colour colBg) - Highlight colour is used for the currently selected date. - - - - - - - GetHighlightColourFg(self) -> Colour - Highlight colour is used for the currently selected date. - - - GetHighlightColourBg(self) -> Colour - Highlight colour is used for the currently selected date. - - - SetHolidayColours(self, Colour colFg, Colour colBg) - Holiday colour is used for the holidays (if CAL_SHOW_HOLIDAYS style is -used). - - - - - - - GetHolidayColourFg(self) -> Colour - Holiday colour is used for the holidays (if CAL_SHOW_HOLIDAYS style is -used). - - - GetHolidayColourBg(self) -> Colour - Holiday colour is used for the holidays (if CAL_SHOW_HOLIDAYS style is -used). - - - GetAttr(self, size_t day) -> CalendarDateAttr - Returns the attribute for the given date (should be in the range -1...31). The returned value may be None - - - - - - SetAttr(self, size_t day, CalendarDateAttr attr) - Associates the attribute with the specified date (in the range -1...31). If the attribute passed is None, the items attribute is -cleared. - - - - - - - SetHoliday(self, size_t day) - Marks the specified day as being a holiday in the current month. - - - - - - ResetAttr(self, size_t day) - Clears any attributes associated with the given day (in the range -1...31). - - - - - - HitTest(Point pos) -> (result, date, weekday) - Returns 3-tuple with information about the given position on the -calendar control. The first value of the tuple is a result code and -determines the validity of the remaining two values. -The result codes are: - - =================== ============================================ - CAL_HITTEST_NOWHERE hit outside of anything - CAL_HITTEST_HEADER hit on the header, weekday is valid - CAL_HITTEST_DAY hit on a day in the calendar, date is set. - =================== ============================================ - - - - - - - GetMonthControl(self) -> Control - Get the currently shown control for month. - - - GetYearControl(self) -> Control - Get the currently shown control for year. - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - - - - wx = _core - __docfilter__ = wx.__DocFilter(globals()) - - - _setOORInfo(self, PyObject _self) - - - - - - SetParameters(self, String params) - - - - - - IncRef(self) - - - DecRef(self) - - - Draw(self, Grid grid, GridCellAttr attr, DC dc, Rect rect, int row, - int col, bool isSelected) - - - - - - - - - - - - GetBestSize(self, Grid grid, GridCellAttr attr, DC dc, int row, int col) -> Size - - - - - - - - - - Clone(self) -> GridCellRenderer - - - - - - __init__(self) -> PyGridCellRenderer - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_SetParameters(self, String params) - - - - - - - - - __init__(self) -> GridCellStringRenderer - - - - - - __init__(self) -> GridCellNumberRenderer - - - - - - __init__(self, int width=-1, int precision=-1) -> GridCellFloatRenderer - - - - - - - GetWidth(self) -> int - - - SetWidth(self, int width) - - - - - - GetPrecision(self) -> int - - - SetPrecision(self, int precision) - - - - - - - - - __init__(self) -> GridCellBoolRenderer - - - - - - __init__(self, String outformat=DateTimeFormatStr, String informat=DateTimeFormatStr) -> GridCellDateTimeRenderer - - - - - - - - - - __init__(self, String choices=EmptyString) -> GridCellEnumRenderer - - - - - - - - - __init__(self) -> GridCellAutoWrapStringRenderer - - - - - _setOORInfo(self, PyObject _self) - - - - - - IsCreated(self) -> bool - - - GetControl(self) -> Control - - - SetControl(self, Control control) - - - - - - GetCellAttr(self) -> GridCellAttr - - - SetCellAttr(self, GridCellAttr attr) - - - - - - SetParameters(self, String params) - - - - - - IncRef(self) - - - DecRef(self) - - - Create(self, Window parent, int id, EvtHandler evtHandler) - - - - - - - - BeginEdit(self, int row, int col, Grid grid) - - - - - - - - EndEdit(self, int row, int col, Grid grid) -> bool - - - - - - - - Reset(self) - - - Clone(self) -> GridCellEditor - - - SetSize(self, Rect rect) - - - - - - Show(self, bool show, GridCellAttr attr=None) - - - - - - - PaintBackground(self, Rect rectCell, GridCellAttr attr) - - - - - - - IsAcceptedKey(self, KeyEvent event) -> bool - - - - - - StartingKey(self, KeyEvent event) - - - - - - StartingClick(self) - - - HandleReturn(self, KeyEvent event) - - - - - - Destroy(self) - - - - - - __init__(self) -> PyGridCellEditor - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_SetSize(self, Rect rect) - - - - - - base_Show(self, bool show, GridCellAttr attr=None) - - - - - - - base_PaintBackground(self, Rect rectCell, GridCellAttr attr) - - - - - - - base_IsAcceptedKey(self, KeyEvent event) -> bool - - - - - - base_StartingKey(self, KeyEvent event) - - - - - - base_StartingClick(self) - - - base_HandleReturn(self, KeyEvent event) - - - - - - base_Destroy(self) - - - base_SetParameters(self, String params) - - - - - - - - - __init__(self) -> GridCellTextEditor - - - GetValue(self) -> String - - - - - - __init__(self, int min=-1, int max=-1) -> GridCellNumberEditor - - - - - - - GetValue(self) -> String - - - - - - __init__(self, int width=-1, int precision=-1) -> GridCellFloatEditor - - - - - - - GetValue(self) -> String - - - - - - __init__(self) -> GridCellBoolEditor - - - GetValue(self) -> String - - - - - - __init__(self, int choices=0, String choices_array=None, bool allowOthers=False) -> GridCellChoiceEditor - - - - - - - - GetValue(self) -> String - - - - - - __init__(self, String choices=EmptyString) -> GridCellEnumEditor - - - - - - GetValue(self) -> String - - - - - - __init__(self) -> GridCellAutoWrapStringEditor - - - GetValue(self) -> String - - - - - __init__(self, GridCellAttr attrDefault=None) -> GridCellAttr - - - - - - _setOORInfo(self, PyObject _self) - - - - - - Clone(self) -> GridCellAttr - - - MergeWith(self, GridCellAttr mergefrom) - - - - - - IncRef(self) - - - DecRef(self) - - - SetTextColour(self, Colour colText) - - - - - - SetBackgroundColour(self, Colour colBack) - - - - - - SetFont(self, Font font) - - - - - - SetAlignment(self, int hAlign, int vAlign) - - - - - - - SetSize(self, int num_rows, int num_cols) - - - - - - - SetOverflow(self, bool allow=True) - - - - - - SetReadOnly(self, bool isReadOnly=True) - - - - - - SetRenderer(self, GridCellRenderer renderer) - - - - - - SetEditor(self, GridCellEditor editor) - - - - - - SetKind(self, int kind) - - - - - - HasTextColour(self) -> bool - - - HasBackgroundColour(self) -> bool - - - HasFont(self) -> bool - - - HasAlignment(self) -> bool - - - HasRenderer(self) -> bool - - - HasEditor(self) -> bool - - - HasReadWriteMode(self) -> bool - - - HasOverflowMode(self) -> bool - - - GetTextColour(self) -> Colour - - - GetBackgroundColour(self) -> Colour - - - GetFont(self) -> Font - - - GetAlignment() -> (hAlign, vAlign) - - - - - - - GetSize() -> (num_rows, num_cols) - - - - - - - GetOverflow(self) -> bool - - - GetRenderer(self, Grid grid, int row, int col) -> GridCellRenderer - - - - - - - - GetEditor(self, Grid grid, int row, int col) -> GridCellEditor - - - - - - - - IsReadOnly(self) -> bool - - - GetKind(self) -> int - - - SetDefAttr(self, GridCellAttr defAttr) - - - - - - - - __init__(self) -> GridCellAttrProvider - - - _setOORInfo(self, PyObject _self) - - - - - - GetAttr(self, int row, int col, int kind) -> GridCellAttr - - - - - - - - SetAttr(self, GridCellAttr attr, int row, int col) - - - - - - - - SetRowAttr(self, GridCellAttr attr, int row) - - - - - - - SetColAttr(self, GridCellAttr attr, int col) - - - - - - - UpdateAttrRows(self, size_t pos, int numRows) - - - - - - - UpdateAttrCols(self, size_t pos, int numCols) - - - - - - - - - - __init__(self) -> PyGridCellAttrProvider - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_GetAttr(self, int row, int col, int kind) -> GridCellAttr - - - - - - - - base_SetAttr(self, GridCellAttr attr, int row, int col) - - - - - - - - base_SetRowAttr(self, GridCellAttr attr, int row) - - - - - - - base_SetColAttr(self, GridCellAttr attr, int col) - - - - - - - - - - _setOORInfo(self, PyObject _self) - - - - - - SetAttrProvider(self, GridCellAttrProvider attrProvider) - - - - - - GetAttrProvider(self) -> GridCellAttrProvider - - - SetView(self, Grid grid) - - - - - - GetView(self) -> Grid - - - GetNumberRows(self) -> int - - - GetNumberCols(self) -> int - - - IsEmptyCell(self, int row, int col) -> bool - - - - - - - GetValue(self, int row, int col) -> String - - - - - - - SetValue(self, int row, int col, String value) - - - - - - - - GetTypeName(self, int row, int col) -> String - - - - - - - CanGetValueAs(self, int row, int col, String typeName) -> bool - - - - - - - - CanSetValueAs(self, int row, int col, String typeName) -> bool - - - - - - - - GetValueAsLong(self, int row, int col) -> long - - - - - - - GetValueAsDouble(self, int row, int col) -> double - - - - - - - GetValueAsBool(self, int row, int col) -> bool - - - - - - - SetValueAsLong(self, int row, int col, long value) - - - - - - - - SetValueAsDouble(self, int row, int col, double value) - - - - - - - - SetValueAsBool(self, int row, int col, bool value) - - - - - - - - Clear(self) - - - InsertRows(self, size_t pos=0, size_t numRows=1) -> bool - - - - - - - AppendRows(self, size_t numRows=1) -> bool - - - - - - DeleteRows(self, size_t pos=0, size_t numRows=1) -> bool - - - - - - - InsertCols(self, size_t pos=0, size_t numCols=1) -> bool - - - - - - - AppendCols(self, size_t numCols=1) -> bool - - - - - - DeleteCols(self, size_t pos=0, size_t numCols=1) -> bool - - - - - - - GetRowLabelValue(self, int row) -> String - - - - - - GetColLabelValue(self, int col) -> String - - - - - - SetRowLabelValue(self, int row, String value) - - - - - - - SetColLabelValue(self, int col, String value) - - - - - - - CanHaveAttributes(self) -> bool - - - GetAttr(self, int row, int col, int kind) -> GridCellAttr - - - - - - - - SetAttr(self, GridCellAttr attr, int row, int col) - - - - - - - - SetRowAttr(self, GridCellAttr attr, int row) - - - - - - - SetColAttr(self, GridCellAttr attr, int col) - - - - - - - - - - __init__(self) -> PyGridTableBase - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - Destroy(self) - Deletes the C++ object this Python object is a proxy for. - - - base_GetTypeName(self, int row, int col) -> String - - - - - - - base_CanGetValueAs(self, int row, int col, String typeName) -> bool - - - - - - - - base_CanSetValueAs(self, int row, int col, String typeName) -> bool - - - - - - - - base_Clear(self) - - - base_InsertRows(self, size_t pos=0, size_t numRows=1) -> bool - - - - - - - base_AppendRows(self, size_t numRows=1) -> bool - - - - - - base_DeleteRows(self, size_t pos=0, size_t numRows=1) -> bool - - - - - - - base_InsertCols(self, size_t pos=0, size_t numCols=1) -> bool - - - - - - - base_AppendCols(self, size_t numCols=1) -> bool - - - - - - base_DeleteCols(self, size_t pos=0, size_t numCols=1) -> bool - - - - - - - base_GetRowLabelValue(self, int row) -> String - - - - - - base_GetColLabelValue(self, int col) -> String - - - - - - base_SetRowLabelValue(self, int row, String value) - - - - - - - base_SetColLabelValue(self, int col, String value) - - - - - - - base_CanHaveAttributes(self) -> bool - - - base_GetAttr(self, int row, int col, int kind) -> GridCellAttr - - - - - - - - base_SetAttr(self, GridCellAttr attr, int row, int col) - - - - - - - - base_SetRowAttr(self, GridCellAttr attr, int row) - - - - - - - base_SetColAttr(self, GridCellAttr attr, int col) - - - - - - - - - - __init__(self, int numRows=0, int numCols=0) -> GridStringTable - - - - - - - - - __init__(self, GridTableBase table, int id, int comInt1=-1, int comInt2=-1) -> GridTableMessage - - - - - - - - - __del__(self) - - - SetTableObject(self, GridTableBase table) - - - - - - GetTableObject(self) -> GridTableBase - - - SetId(self, int id) - - - - - - GetId(self) -> int - - - SetCommandInt(self, int comInt1) - - - - - - GetCommandInt(self) -> int - - - SetCommandInt2(self, int comInt2) - - - - - - GetCommandInt2(self) -> int - - - - - __init__(self, int r=-1, int c=-1) -> GridCellCoords - - - - - - - __del__(self) - - - GetRow(self) -> int - - - SetRow(self, int n) - - - - - - GetCol(self) -> int - - - SetCol(self, int n) - - - - - - Set(self, int row, int col) - - - - - - - __eq__(self, GridCellCoords other) -> bool - - - - - - __ne__(self, GridCellCoords other) -> bool - - - - - - Get(self) -> PyObject - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=WANTS_CHARS, - String name=PanelNameStr) -> Grid - - - - - - - - - - - PreGrid() -> Grid - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=WANTS_CHARS, - String name=PanelNameStr) -> bool - - - - - - - - - - - CreateGrid(self, int numRows, int numCols, WXGRIDSELECTIONMODES selmode=wxGridSelectCells) -> bool - - - - - - - - SetSelectionMode(self, WXGRIDSELECTIONMODES selmode) - - - - - - GetSelectionMode(self) -> WXGRIDSELECTIONMODES - - - GetNumberRows(self) -> int - - - GetNumberCols(self) -> int - - - ProcessTableMessage(self, GridTableMessage ??) -> bool - - - - - - GetTable(self) -> GridTableBase - - - SetTable(self, GridTableBase table, bool takeOwnership=False, WXGRIDSELECTIONMODES selmode=wxGridSelectCells) -> bool - - - - - - - - ClearGrid(self) - - - InsertRows(self, int pos=0, int numRows=1, bool updateLabels=True) -> bool - - - - - - - - AppendRows(self, int numRows=1, bool updateLabels=True) -> bool - - - - - - - DeleteRows(self, int pos=0, int numRows=1, bool updateLabels=True) -> bool - - - - - - - - InsertCols(self, int pos=0, int numCols=1, bool updateLabels=True) -> bool - - - - - - - - AppendCols(self, int numCols=1, bool updateLabels=True) -> bool - - - - - - - DeleteCols(self, int pos=0, int numCols=1, bool updateLabels=True) -> bool - - - - - - - - DrawCellHighlight(self, DC dc, GridCellAttr attr) - - - - - - - DrawTextRectangle(self, DC dc, String ??, Rect ??, int horizontalAlignment=LEFT, - int verticalAlignment=TOP, int textOrientation=HORIZONTAL) - - - - - - - - - - - GetTextBoxSize(DC dc, list lines) -> (width, height) - - - - - - - - - BeginBatch(self) - - - EndBatch(self) - - - GetBatchCount(self) -> int - - - ForceRefresh(self) - - - IsEditable(self) -> bool - - - EnableEditing(self, bool edit) - - - - - - EnableCellEditControl(self, bool enable=True) - - - - - - DisableCellEditControl(self) - - - CanEnableCellControl(self) -> bool - - - IsCellEditControlEnabled(self) -> bool - - - IsCellEditControlShown(self) -> bool - - - IsCurrentCellReadOnly(self) -> bool - - - ShowCellEditControl(self) - - - HideCellEditControl(self) - - - SaveEditControlValue(self) - - - XYToCell(self, int x, int y) -> GridCellCoords - - - - - - - YToRow(self, int y) -> int - - - - - - XToCol(self, int x) -> int - - - - - - YToEdgeOfRow(self, int y) -> int - - - - - - XToEdgeOfCol(self, int x) -> int - - - - - - CellToRect(self, int row, int col) -> Rect - - - - - - - GetGridCursorRow(self) -> int - - - GetGridCursorCol(self) -> int - - - IsVisible(self, int row, int col, bool wholeCellVisible=True) -> bool - - - - - - - - MakeCellVisible(self, int row, int col) - - - - - - - SetGridCursor(self, int row, int col) - - - - - - - MoveCursorUp(self, bool expandSelection) -> bool - - - - - - MoveCursorDown(self, bool expandSelection) -> bool - - - - - - MoveCursorLeft(self, bool expandSelection) -> bool - - - - - - MoveCursorRight(self, bool expandSelection) -> bool - - - - - - MovePageDown(self) -> bool - - - MovePageUp(self) -> bool - - - MoveCursorUpBlock(self, bool expandSelection) -> bool - - - - - - MoveCursorDownBlock(self, bool expandSelection) -> bool - - - - - - MoveCursorLeftBlock(self, bool expandSelection) -> bool - - - - - - MoveCursorRightBlock(self, bool expandSelection) -> bool - - - - - - GetDefaultRowLabelSize(self) -> int - - - GetRowLabelSize(self) -> int - - - GetDefaultColLabelSize(self) -> int - - - GetColLabelSize(self) -> int - - - GetLabelBackgroundColour(self) -> Colour - - - GetLabelTextColour(self) -> Colour - - - GetLabelFont(self) -> Font - - - GetRowLabelAlignment() -> (horiz, vert) - - - - - - - GetColLabelAlignment() -> (horiz, vert) - - - - - - - GetColLabelTextOrientation(self) -> int - - - GetRowLabelValue(self, int row) -> String - - - - - - GetColLabelValue(self, int col) -> String - - - - - - GetGridLineColour(self) -> Colour - - - GetCellHighlightColour(self) -> Colour - - - GetCellHighlightPenWidth(self) -> int - - - GetCellHighlightROPenWidth(self) -> int - - - SetRowLabelSize(self, int width) - - - - - - SetColLabelSize(self, int height) - - - - - - SetLabelBackgroundColour(self, Colour ??) - - - - - - SetLabelTextColour(self, Colour ??) - - - - - - SetLabelFont(self, Font ??) - - - - - - SetRowLabelAlignment(self, int horiz, int vert) - - - - - - - SetColLabelAlignment(self, int horiz, int vert) - - - - - - - SetColLabelTextOrientation(self, int textOrientation) - - - - - - SetRowLabelValue(self, int row, String ??) - - - - - - - SetColLabelValue(self, int col, String ??) - - - - - - - SetGridLineColour(self, Colour ??) - - - - - - SetCellHighlightColour(self, Colour ??) - - - - - - SetCellHighlightPenWidth(self, int width) - - - - - - SetCellHighlightROPenWidth(self, int width) - - - - - - EnableDragRowSize(self, bool enable=True) - - - - - - DisableDragRowSize(self) - - - CanDragRowSize(self) -> bool - - - EnableDragColSize(self, bool enable=True) - - - - - - DisableDragColSize(self) - - - CanDragColSize(self) -> bool - - - EnableDragGridSize(self, bool enable=True) - - - - - - DisableDragGridSize(self) - - - CanDragGridSize(self) -> bool - - - EnableDragCell(self, bool enable=True) - - - - - - DisableDragCell(self) - - - CanDragCell(self) -> bool - - - SetAttr(self, int row, int col, GridCellAttr attr) - - - - - - - - SetRowAttr(self, int row, GridCellAttr attr) - - - - - - - SetColAttr(self, int col, GridCellAttr attr) - - - - - - - SetColFormatBool(self, int col) - - - - - - SetColFormatNumber(self, int col) - - - - - - SetColFormatFloat(self, int col, int width=-1, int precision=-1) - - - - - - - - SetColFormatCustom(self, int col, String typeName) - - - - - - - EnableGridLines(self, bool enable=True) - - - - - - GridLinesEnabled(self) -> bool - - - GetDefaultRowSize(self) -> int - - - GetRowSize(self, int row) -> int - - - - - - GetDefaultColSize(self) -> int - - - GetColSize(self, int col) -> int - - - - - - GetDefaultCellBackgroundColour(self) -> Colour - - - GetCellBackgroundColour(self, int row, int col) -> Colour - - - - - - - GetDefaultCellTextColour(self) -> Colour - - - GetCellTextColour(self, int row, int col) -> Colour - - - - - - - GetDefaultCellFont(self) -> Font - - - GetCellFont(self, int row, int col) -> Font - - - - - - - GetDefaultCellAlignment() -> (horiz, vert) - - - - - - - GetCellAlignment() -> (horiz, vert) - - - - - - - - - GetDefaultCellOverflow(self) -> bool - - - GetCellOverflow(self, int row, int col) -> bool - - - - - - - GetCellSize(int row, int col) -> (num_rows, num_cols) - - - - - - - - - SetDefaultRowSize(self, int height, bool resizeExistingRows=False) - - - - - - - SetRowSize(self, int row, int height) - - - - - - - SetDefaultColSize(self, int width, bool resizeExistingCols=False) - - - - - - - SetColSize(self, int col, int width) - - - - - - - AutoSizeColumn(self, int col, bool setAsMin=True) - - - - - - - AutoSizeRow(self, int row, bool setAsMin=True) - - - - - - - AutoSizeColumns(self, bool setAsMin=True) - - - - - - AutoSizeRows(self, bool setAsMin=True) - - - - - - AutoSize(self) - - - AutoSizeRowLabelSize(self, int row) - - - - - - AutoSizeColLabelSize(self, int col) - - - - - - SetColMinimalWidth(self, int col, int width) - - - - - - - SetRowMinimalHeight(self, int row, int width) - - - - - - - SetColMinimalAcceptableWidth(self, int width) - - - - - - SetRowMinimalAcceptableHeight(self, int width) - - - - - - GetColMinimalAcceptableWidth(self) -> int - - - GetRowMinimalAcceptableHeight(self) -> int - - - SetDefaultCellBackgroundColour(self, Colour ??) - - - - - - SetCellBackgroundColour(self, int row, int col, Colour ??) - - - - - - - - SetDefaultCellTextColour(self, Colour ??) - - - - - - SetCellTextColour(self, int row, int col, Colour ??) - - - - - - - - SetDefaultCellFont(self, Font ??) - - - - - - SetCellFont(self, int row, int col, Font ??) - - - - - - - - SetDefaultCellAlignment(self, int horiz, int vert) - - - - - - - SetCellAlignment(self, int row, int col, int horiz, int vert) - - - - - - - - - SetDefaultCellOverflow(self, bool allow) - - - - - - SetCellOverflow(self, int row, int col, bool allow) - - - - - - - - SetCellSize(self, int row, int col, int num_rows, int num_cols) - - - - - - - - - SetDefaultRenderer(self, GridCellRenderer renderer) - - - - - - SetCellRenderer(self, int row, int col, GridCellRenderer renderer) - - - - - - - - GetDefaultRenderer(self) -> GridCellRenderer - - - GetCellRenderer(self, int row, int col) -> GridCellRenderer - - - - - - - SetDefaultEditor(self, GridCellEditor editor) - - - - - - SetCellEditor(self, int row, int col, GridCellEditor editor) - - - - - - - - GetDefaultEditor(self) -> GridCellEditor - - - GetCellEditor(self, int row, int col) -> GridCellEditor - - - - - - - GetCellValue(self, int row, int col) -> String - - - - - - - SetCellValue(self, int row, int col, String s) - - - - - - - - IsReadOnly(self, int row, int col) -> bool - - - - - - - SetReadOnly(self, int row, int col, bool isReadOnly=True) - - - - - - - - SelectRow(self, int row, bool addToSelected=False) - - - - - - - SelectCol(self, int col, bool addToSelected=False) - - - - - - - SelectBlock(self, int topRow, int leftCol, int bottomRow, int rightCol, - bool addToSelected=False) - - - - - - - - - - SelectAll(self) - - - IsSelection(self) -> bool - - - ClearSelection(self) - - - IsInSelection(self, int row, int col) -> bool - - - - - - - GetSelectedCells(self) -> wxGridCellCoordsArray - - - GetSelectionBlockTopLeft(self) -> wxGridCellCoordsArray - - - GetSelectionBlockBottomRight(self) -> wxGridCellCoordsArray - - - GetSelectedRows(self) -> wxArrayInt - - - GetSelectedCols(self) -> wxArrayInt - - - DeselectRow(self, int row) - - - - - - DeselectCol(self, int col) - - - - - - DeselectCell(self, int row, int col) - - - - - - - BlockToDeviceRect(self, GridCellCoords topLeft, GridCellCoords bottomRight) -> Rect - - - - - - - GetSelectionBackground(self) -> Colour - - - GetSelectionForeground(self) -> Colour - - - SetSelectionBackground(self, Colour c) - - - - - - SetSelectionForeground(self, Colour c) - - - - - - RegisterDataType(self, String typeName, GridCellRenderer renderer, GridCellEditor editor) - - - - - - - - GetDefaultEditorForCell(self, int row, int col) -> GridCellEditor - - - - - - - GetDefaultRendererForCell(self, int row, int col) -> GridCellRenderer - - - - - - - GetDefaultEditorForType(self, String typeName) -> GridCellEditor - - - - - - GetDefaultRendererForType(self, String typeName) -> GridCellRenderer - - - - - - SetMargins(self, int extraWidth, int extraHeight) - - - - - - - GetGridWindow(self) -> Window - - - GetGridRowLabelWindow(self) -> Window - - - GetGridColLabelWindow(self) -> Window - - - GetGridCornerLabelWindow(self) -> Window - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - - - - __init__(self, int id, wxEventType type, Grid obj, int row=-1, int col=-1, - int x=-1, int y=-1, bool sel=True, bool control=False, - bool shift=False, bool alt=False, - bool meta=False) -> GridEvent - - - - - - - - - - - - - - - - - GetRow(self) -> int - - - GetCol(self) -> int - - - GetPosition(self) -> Point - - - Selecting(self) -> bool - - - ControlDown(self) -> bool - - - MetaDown(self) -> bool - - - ShiftDown(self) -> bool - - - AltDown(self) -> bool - - - - - - __init__(self, int id, wxEventType type, Grid obj, int rowOrCol=-1, - int x=-1, int y=-1, bool control=False, bool shift=False, - bool alt=False, bool meta=False) -> GridSizeEvent - - - - - - - - - - - - - - - GetRowOrCol(self) -> int - - - GetPosition(self) -> Point - - - ControlDown(self) -> bool - - - MetaDown(self) -> bool - - - ShiftDown(self) -> bool - - - AltDown(self) -> bool - - - - - - __init__(self, int id, wxEventType type, Grid obj, GridCellCoords topLeft, - GridCellCoords bottomRight, bool sel=True, - bool control=False, bool shift=False, - bool alt=False, bool meta=False) -> GridRangeSelectEvent - - - - - - - - - - - - - - - GetTopLeftCoords(self) -> GridCellCoords - - - GetBottomRightCoords(self) -> GridCellCoords - - - GetTopRow(self) -> int - - - GetBottomRow(self) -> int - - - GetLeftCol(self) -> int - - - GetRightCol(self) -> int - - - Selecting(self) -> bool - - - ControlDown(self) -> bool - - - MetaDown(self) -> bool - - - ShiftDown(self) -> bool - - - AltDown(self) -> bool - - - - - - __init__(self, int id, wxEventType type, Object obj, int row, int col, - Control ctrl) -> GridEditorCreatedEvent - - - - - - - - - - - GetRow(self) -> int - - - GetCol(self) -> int - - - GetControl(self) -> Control - - - SetRow(self, int row) - - - - - - SetCol(self, int col) - - - - - - SetControl(self, Control ctrl) - - - - - - -EVT_GRID_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK ) -EVT_GRID_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK ) -EVT_GRID_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK ) -EVT_GRID_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK ) -EVT_GRID_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK ) -EVT_GRID_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK ) -EVT_GRID_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK ) -EVT_GRID_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK ) -EVT_GRID_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE ) -EVT_GRID_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE ) -EVT_GRID_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT ) -EVT_GRID_CELL_CHANGE = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGE ) -EVT_GRID_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL ) -EVT_GRID_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN ) -EVT_GRID_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN ) -EVT_GRID_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED ) -EVT_GRID_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG ) - - -# The same as above but with the ability to specify an identifier -EVT_GRID_CMD_CELL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_CLICK, 1 ) -EVT_GRID_CMD_CELL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_CLICK, 1 ) -EVT_GRID_CMD_CELL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_LEFT_DCLICK, 1 ) -EVT_GRID_CMD_CELL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_CELL_RIGHT_DCLICK, 1 ) -EVT_GRID_CMD_LABEL_LEFT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_CLICK, 1 ) -EVT_GRID_CMD_LABEL_RIGHT_CLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_CLICK, 1 ) -EVT_GRID_CMD_LABEL_LEFT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_LEFT_DCLICK, 1 ) -EVT_GRID_CMD_LABEL_RIGHT_DCLICK = wx.PyEventBinder( wxEVT_GRID_LABEL_RIGHT_DCLICK, 1 ) -EVT_GRID_CMD_ROW_SIZE = wx.PyEventBinder( wxEVT_GRID_ROW_SIZE, 1 ) -EVT_GRID_CMD_COL_SIZE = wx.PyEventBinder( wxEVT_GRID_COL_SIZE, 1 ) -EVT_GRID_CMD_RANGE_SELECT = wx.PyEventBinder( wxEVT_GRID_RANGE_SELECT, 1 ) -EVT_GRID_CMD_CELL_CHANGE = wx.PyEventBinder( wxEVT_GRID_CELL_CHANGE, 1 ) -EVT_GRID_CMD_SELECT_CELL = wx.PyEventBinder( wxEVT_GRID_SELECT_CELL, 1 ) -EVT_GRID_CMD_EDITOR_SHOWN = wx.PyEventBinder( wxEVT_GRID_EDITOR_SHOWN, 1 ) -EVT_GRID_CMD_EDITOR_HIDDEN = wx.PyEventBinder( wxEVT_GRID_EDITOR_HIDDEN, 1 ) -EVT_GRID_CMD_EDITOR_CREATED = wx.PyEventBinder( wxEVT_GRID_EDITOR_CREATED, 1 ) -EVT_GRID_CMD_CELL_BEGIN_DRAG = wx.PyEventBinder( wxEVT_GRID_CELL_BEGIN_DRAG, 1 ) - - - - - - wx = _core - __docfilter__ = wx.__DocFilter(globals()) - -#--------------------------------------------------------------------------- - - - - - __init__(self, String href, String target=EmptyString) -> HtmlLinkInfo - - - - - - - GetHref(self) -> String - - - GetTarget(self) -> String - - - GetEvent(self) -> MouseEvent - - - GetHtmlCell(self) -> HtmlCell - - - SetEvent(self, MouseEvent e) - - - - - - SetHtmlCell(self, HtmlCell e) - - - - - - - - - GetName(self) -> String - - - HasParam(self, String par) -> bool - - - - - - GetParam(self, String par, int with_commas=False) -> String - - - - - - - GetAllParams(self) -> String - - - HasEnding(self) -> bool - - - GetBeginPos(self) -> int - - - GetEndPos1(self) -> int - - - GetEndPos2(self) -> int - - - - - - SetFS(self, FileSystem fs) - - - - - - GetFS(self) -> FileSystem - - - Parse(self, String source) -> Object - - - - - - InitParser(self, String source) - - - - - - DoneParser(self) - - - DoParsing(self, int begin_pos, int end_pos) - - - - - - - StopParsing(self) - - - AddTagHandler(self, HtmlTagHandler handler) - - - - - - GetSource(self) -> String - - - PushTagHandler(self, HtmlTagHandler handler, String tags) - - - - - - - PopTagHandler(self) - - - - - - __init__(self, HtmlWindow wnd=None) -> HtmlWinParser - - - - - - SetDC(self, DC dc) - - - - - - GetDC(self) -> DC - - - GetCharHeight(self) -> int - - - GetCharWidth(self) -> int - - - GetWindow(self) -> HtmlWindow - - - SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None) - - - - - - - - NormalizeFontSizes(self, int size=-1) - - - - - - GetContainer(self) -> HtmlContainerCell - - - OpenContainer(self) -> HtmlContainerCell - - - SetContainer(self, HtmlContainerCell c) -> HtmlContainerCell - - - - - - CloseContainer(self) -> HtmlContainerCell - - - GetFontSize(self) -> int - - - SetFontSize(self, int s) - - - - - - GetFontBold(self) -> int - - - SetFontBold(self, int x) - - - - - - GetFontItalic(self) -> int - - - SetFontItalic(self, int x) - - - - - - GetFontUnderlined(self) -> int - - - SetFontUnderlined(self, int x) - - - - - - GetFontFixed(self) -> int - - - SetFontFixed(self, int x) - - - - - - GetAlign(self) -> int - - - SetAlign(self, int a) - - - - - - GetLinkColor(self) -> Colour - - - SetLinkColor(self, Colour clr) - - - - - - GetActualColor(self) -> Colour - - - SetActualColor(self, Colour clr) - - - - - - SetLink(self, String link) - - - - - - CreateCurrentFont(self) -> Font - - - GetLink(self) -> HtmlLinkInfo - - - - - - __init__(self) -> HtmlTagHandler - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetParser(self, HtmlParser parser) - - - - - - GetParser(self) -> HtmlParser - - - ParseInner(self, HtmlTag tag) - - - - - - - - - __init__(self) -> HtmlWinTagHandler - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetParser(self, HtmlParser parser) - - - - - - GetParser(self) -> HtmlWinParser - - - ParseInner(self, HtmlTag tag) - - - - - - - HtmlWinParser_AddTagHandler(PyObject tagHandlerClass) - - - - - -#--------------------------------------------------------------------------- - - - - __init__(self) -> HtmlSelection - - - __del__(self) - - - Set(self, Point fromPos, HtmlCell fromCell, Point toPos, HtmlCell toCell) - - - - - - - - - SetCells(self, HtmlCell fromCell, HtmlCell toCell) - - - - - - - GetFromCell(self) -> HtmlCell - - - GetToCell(self) -> HtmlCell - - - GetFromPos(self) -> Point - - - GetToPos(self) -> Point - - - GetFromPrivPos(self) -> Point - - - GetToPrivPos(self) -> Point - - - SetFromPrivPos(self, Point pos) - - - - - - SetToPrivPos(self, Point pos) - - - - - - ClearPrivPos(self) - - - IsEmpty(self) -> bool - - - - - __init__(self) -> HtmlRenderingState - - - __del__(self) - - - SetSelectionState(self, int s) - - - - - - GetSelectionState(self) -> int - - - SetFgColour(self, Colour c) - - - - - - GetFgColour(self) -> Colour - - - SetBgColour(self, Colour c) - - - - - - GetBgColour(self) -> Colour - - - - - GetSelectedTextColour(self, Colour clr) -> Colour - - - - - - GetSelectedTextBgColour(self, Colour clr) -> Colour - - - - - - - - - GetSelectedTextColour(self, Colour clr) -> Colour - - - - - - GetSelectedTextBgColour(self, Colour clr) -> Colour - - - - - - - - __init__(self) -> HtmlRenderingInfo - - - __del__(self) - - - SetSelection(self, HtmlSelection s) - - - - - - GetSelection(self) -> HtmlSelection - - - SetStyle(self, HtmlRenderingStyle style) - - - - - - GetStyle(self) -> HtmlRenderingStyle - - - GetState(self) -> HtmlRenderingState - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> HtmlCell - - - GetPosX(self) -> int - - - GetPosY(self) -> int - - - GetWidth(self) -> int - - - GetHeight(self) -> int - - - GetDescent(self) -> int - - - GetMaxTotalWidth(self) -> int - - - GetId(self) -> String - - - SetId(self, String id) - - - - - - GetLink(self, int x=0, int y=0) -> HtmlLinkInfo - - - - - - - GetNext(self) -> HtmlCell - - - GetParent(self) -> HtmlContainerCell - - - GetFirstChild(self) -> HtmlCell - - - GetCursor(self) -> Cursor - - - IsFormattingCell(self) -> bool - - - SetLink(self, HtmlLinkInfo link) - - - - - - SetNext(self, HtmlCell cell) - - - - - - SetParent(self, HtmlContainerCell p) - - - - - - SetPos(self, int x, int y) - - - - - - - Layout(self, int w) - - - - - - Draw(self, DC dc, int x, int y, int view_y1, int view_y2, HtmlRenderingInfo info) - - - - - - - - - - - DrawInvisible(self, DC dc, int x, int y, HtmlRenderingInfo info) - - - - - - - - - Find(self, int condition, void param) -> HtmlCell - - - - - - - AdjustPagebreak(self, int INOUT) -> bool - - - - - - SetCanLiveOnPagebreak(self, bool can) - - - - - - IsLinebreakAllowed(self) -> bool - - - IsTerminalCell(self) -> bool - - - FindCellByPos(self, int x, int y, unsigned int flags=HTML_FIND_EXACT) -> HtmlCell - - - - - - - - GetAbsPos(self) -> Point - - - GetFirstTerminal(self) -> HtmlCell - - - GetLastTerminal(self) -> HtmlCell - - - GetDepth(self) -> unsigned int - - - IsBefore(self, HtmlCell cell) -> bool - - - - - - ConvertToText(self, HtmlSelection sel) -> String - - - - - - - - - __init__(self, String word, DC dc) -> HtmlWordCell - - - - - - - - - - __init__(self, HtmlContainerCell parent) -> HtmlContainerCell - - - - - - InsertCell(self, HtmlCell cell) - - - - - - SetAlignHor(self, int al) - - - - - - GetAlignHor(self) -> int - - - SetAlignVer(self, int al) - - - - - - GetAlignVer(self) -> int - - - SetIndent(self, int i, int what, int units=HTML_UNITS_PIXELS) - - - - - - - - GetIndent(self, int ind) -> int - - - - - - GetIndentUnits(self, int ind) -> int - - - - - - SetAlign(self, HtmlTag tag) - - - - - - SetWidthFloat(self, int w, int units) - - - - - - - SetWidthFloatFromTag(self, HtmlTag tag) - - - - - - SetMinHeight(self, int h, int align=HTML_ALIGN_TOP) - - - - - - - SetBackgroundColour(self, Colour clr) - - - - - - GetBackgroundColour(self) -> Colour - - - SetBorder(self, Colour clr1, Colour clr2) - - - - - - - GetFirstChild(self) -> HtmlCell - - - - - - __init__(self, Colour clr, int flags=HTML_CLR_FOREGROUND) -> HtmlColourCell - - - - - - - - - - __init__(self, Font font) -> HtmlFontCell - - - - - - - - - __init__(self, Window wnd, int w=0) -> HtmlWidgetCell - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> HtmlFilter - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, int style=HW_DEFAULT_STYLE, - String name=HtmlWindowNameStr) -> HtmlWindow - - - - - - - - - - - PreHtmlWindow() -> HtmlWindow - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, int style=HW_SCROLLBAR_AUTO, - String name=HtmlWindowNameStr) -> bool - - - - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetPage(self, String source) -> bool - - - - - - LoadPage(self, String location) -> bool - - - - - - LoadFile(self, String filename) -> bool - - - - - - AppendToPage(self, String source) -> bool - - - - - - GetOpenedPage(self) -> String - - - GetOpenedAnchor(self) -> String - - - GetOpenedPageTitle(self) -> String - - - SetRelatedFrame(self, Frame frame, String format) - - - - - - - GetRelatedFrame(self) -> Frame - - - SetRelatedStatusBar(self, int bar) - - - - - - SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None) - - - - - - - - NormalizeFontSizes(self, int size=-1) - - - - - - SetTitle(self, String title) - - - - - - SetBorders(self, int b) - - - - - - ReadCustomization(self, ConfigBase cfg, String path=EmptyString) - - - - - - - WriteCustomization(self, ConfigBase cfg, String path=EmptyString) - - - - - - - HistoryBack(self) -> bool - - - HistoryForward(self) -> bool - - - HistoryCanBack(self) -> bool - - - HistoryCanForward(self) -> bool - - - HistoryClear(self) - - - GetInternalRepresentation(self) -> HtmlContainerCell - - - GetParser(self) -> HtmlWinParser - - - ScrollToAnchor(self, String anchor) -> bool - - - - - - HasAnchor(self, String anchor) -> bool - - - - - - AddFilter(HtmlFilter filter) - - - - - - SelectWord(self, Point pos) - - - - - - SelectLine(self, Point pos) - - - - - - SelectAll(self) - - - SelectionToText(self) -> String - - - ToText(self) -> String - - - base_OnLinkClicked(self, HtmlLinkInfo link) - - - - - - base_OnSetTitle(self, String title) - - - - - - base_OnCellMouseHover(self, HtmlCell cell, int x, int y) - - - - - - - - base_OnCellClicked(self, HtmlCell cell, int x, int y, MouseEvent event) - - - - - - - - - GetClassDefaultAttributes(int variant=WINDOW_VARIANT_NORMAL) -> VisualAttributes - Get the default attributes for this class. This is useful if you want -to use the same font or colour in your own control as in a standard -control -- which is a much better idea than hard coding specific -colours or fonts which might look completely out of place on the -user's system, especially if it uses themes. - -The variant parameter is only relevant under Mac currently and is -ignore under other platforms. Under Mac, it will change the size of -the returned font. See `wx.Window.SetWindowVariant` for more about -this. - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> HtmlDCRenderer - - - __del__(self) - - - SetDC(self, DC dc, int maxwidth) - - - - - - - SetSize(self, int width, int height) - - - - - - - SetHtmlText(self, String html, String basepath=EmptyString, bool isdir=True) - - - - - - - - SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None) - - - - - - - - NormalizeFontSizes(self, int size=-1) - - - - - - Render(self, int x, int y, int from=0, int dont_render=False, int to=INT_MAX, - int choices=None, int LCOUNT=0) -> int - - - - - - - - - - - - GetTotalHeight(self) -> int - - - - - - __init__(self, String title=HtmlPrintoutTitleStr) -> HtmlPrintout - - - - - - SetHtmlText(self, String html, String basepath=EmptyString, bool isdir=True) - - - - - - - - SetHtmlFile(self, String htmlfile) - - - - - - SetHeader(self, String header, int pg=PAGE_ALL) - - - - - - - SetFooter(self, String footer, int pg=PAGE_ALL) - - - - - - - SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None) - - - - - - - - NormalizeFontSizes(self, int size=-1) - - - - - - SetMargins(self, float top=25.2, float bottom=25.2, float left=25.2, - float right=25.2, float spaces=5) - - - - - - - - - - AddFilter(wxHtmlFilter filter) - - - - - - CleanUpStatics() - - - - - - __init__(self, String name=HtmlPrintingTitleStr, Window parentWindow=None) -> HtmlEasyPrinting - - - - - - - __del__(self) - - - PreviewFile(self, String htmlfile) - - - - - - PreviewText(self, String htmltext, String basepath=EmptyString) - - - - - - - PrintFile(self, String htmlfile) - - - - - - PrintText(self, String htmltext, String basepath=EmptyString) - - - - - - - PrinterSetup(self) - - - PageSetup(self) - - - SetHeader(self, String header, int pg=PAGE_ALL) - - - - - - - SetFooter(self, String footer, int pg=PAGE_ALL) - - - - - - - SetFonts(self, String normal_face, String fixed_face, PyObject sizes=None) - - - - - - - - NormalizeFontSizes(self, int size=-1) - - - - - - GetPrintData(self) -> PrintData - - - GetPageSetupData(self) -> PageSetupDialogData - - - -#--------------------------------------------------------------------------- - - - - __init__(self, String bookfile, String basepath, String title, String start) -> HtmlBookRecord - - - - - - - - - GetBookFile(self) -> String - - - GetTitle(self) -> String - - - GetStart(self) -> String - - - GetBasePath(self) -> String - - - SetContentsRange(self, int start, int end) - - - - - - - GetContentsStart(self) -> int - - - GetContentsEnd(self) -> int - - - SetTitle(self, String title) - - - - - - SetBasePath(self, String path) - - - - - - SetStart(self, String start) - - - - - - GetFullPath(self, String page) -> String - - - - - - - - GetLevel(self) -> int - - - GetID(self) -> int - - - GetName(self) -> String - - - GetPage(self) -> String - - - GetBook(self) -> HtmlBookRecord - - - - - Search(self) -> bool - - - IsActive(self) -> bool - - - GetCurIndex(self) -> int - - - GetMaxIndex(self) -> int - - - GetName(self) -> String - - - GetContentsItem(self) -> HtmlContentsItem - - - - - __init__(self) -> HtmlHelpData - - - __del__(self) - - - SetTempDir(self, String path) - - - - - - AddBook(self, String book) -> bool - - - - - - FindPageByName(self, String page) -> String - - - - - - FindPageById(self, int id) -> String - - - - - - GetBookRecArray(self) -> wxHtmlBookRecArray - - - GetContents(self) -> HtmlContentsItem - - - GetContentsCnt(self) -> int - - - GetIndex(self) -> HtmlContentsItem - - - GetIndexCnt(self) -> int - - - - - - __init__(self, Window parent, int ??, String title=EmptyString, int style=HF_DEFAULTSTYLE, - HtmlHelpData data=None) -> HtmlHelpFrame - - - - - - - - - - GetData(self) -> HtmlHelpData - - - SetTitleFormat(self, String format) - - - - - - Display(self, String x) - - - - - - DisplayID(self, int id) - - - - - - DisplayContents(self) - - - DisplayIndex(self) - - - KeywordSearch(self, String keyword) -> bool - - - - - - UseConfig(self, ConfigBase config, String rootpath=EmptyString) - - - - - - - ReadCustomization(self, ConfigBase cfg, String path=EmptyString) - - - - - - - WriteCustomization(self, ConfigBase cfg, String path=EmptyString) - - - - - - - - - - __init__(self, int style=HF_DEFAULTSTYLE) -> HtmlHelpController - - - - - - __del__(self) - - - SetTitleFormat(self, String format) - - - - - - SetTempDir(self, String path) - - - - - - AddBook(self, String book, int show_wait_msg=False) -> bool - - - - - - - Display(self, String x) - - - - - - DisplayID(self, int id) - - - - - - DisplayContents(self) - - - DisplayIndex(self) - - - KeywordSearch(self, String keyword) -> bool - - - - - - UseConfig(self, ConfigBase config, String rootpath=EmptyString) - - - - - - - ReadCustomization(self, ConfigBase cfg, String path=EmptyString) - - - - - - - WriteCustomization(self, ConfigBase cfg, String path=EmptyString) - - - - - - - GetFrame(self) -> HtmlHelpFrame - - - - - - wx = _core - __docfilter__ = wx.__DocFilter(globals()) - -EVT_WIZARD_PAGE_CHANGED = wx.PyEventBinder( wxEVT_WIZARD_PAGE_CHANGED, 1) -EVT_WIZARD_PAGE_CHANGING = wx.PyEventBinder( wxEVT_WIZARD_PAGE_CHANGING, 1) -EVT_WIZARD_CANCEL = wx.PyEventBinder( wxEVT_WIZARD_CANCEL, 1) -EVT_WIZARD_HELP = wx.PyEventBinder( wxEVT_WIZARD_HELP, 1) -EVT_WIZARD_FINISHED = wx.PyEventBinder( wxEVT_WIZARD_FINISHED, 1) - - - - - __init__(self, wxEventType type=wxEVT_NULL, int id=-1, bool direction=True, - WizardPage page=None) -> WizardEvent - - - - - - - - - GetDirection(self) -> bool - - - GetPage(self) -> WizardPage - - - - - - Create(self, Wizard parent, Bitmap bitmap=wxNullBitmap, String resource=EmptyString) -> bool - - - - - - - - GetPrev(self) -> WizardPage - - - GetNext(self) -> WizardPage - - - GetBitmap(self) -> Bitmap - - - - - - __init__(self, Wizard parent, Bitmap bitmap=&wxNullBitmap, String resource=&wxPyEmptyString) -> PyWizardPage - - - - - - - - PrePyWizardPage() -> PyWizardPage - - - Create(self, Wizard parent, Bitmap bitmap=wxNullBitmap, String resource=EmptyString) -> bool - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_DoMoveWindow(self, int x, int y, int width, int height) - - - - - - - - - base_DoSetSize(self, int x, int y, int width, int height, int sizeFlags=SIZE_AUTO) - - - - - - - - - - base_DoSetClientSize(self, int width, int height) - - - - - - - base_DoSetVirtualSize(self, int x, int y) - - - - - - - base_DoGetSize() -> (width, height) - - - - - - - base_DoGetClientSize() -> (width, height) - - - - - - - base_DoGetPosition() -> (x,y) - - - - - - - base_DoGetVirtualSize(self) -> Size - - - base_DoGetBestSize(self) -> Size - - - base_InitDialog(self) - - - base_TransferDataToWindow(self) -> bool - - - base_TransferDataFromWindow(self) -> bool - - - base_Validate(self) -> bool - - - base_AcceptsFocus(self) -> bool - - - base_AcceptsFocusFromKeyboard(self) -> bool - - - base_GetMaxSize(self) -> Size - - - base_AddChild(self, Window child) - - - - - - base_RemoveChild(self, Window child) - - - - - - - - - __init__(self, Wizard parent, WizardPage prev=None, WizardPage next=None, - Bitmap bitmap=wxNullBitmap, wxChar resource=None) -> WizardPageSimple - - - - - - - - - - PreWizardPageSimple() -> WizardPageSimple - - - Create(self, Wizard parent=None, WizardPage prev=None, WizardPage next=None, - Bitmap bitmap=wxNullBitmap, wxChar resource=None) -> bool - - - - - - - - - - SetPrev(self, WizardPage prev) - - - - - - SetNext(self, WizardPage next) - - - - - - Chain(WizardPageSimple first, WizardPageSimple second) - - - - - - - - - - __init__(self, Window parent, int id=-1, String title=EmptyString, - Bitmap bitmap=wxNullBitmap, Point pos=DefaultPosition, - long style=DEFAULT_DIALOG_STYLE) -> Wizard - - - - - - - - - - - PreWizard() -> Wizard - - - Create(self, Window parent, int id=-1, String title=EmptyString, - Bitmap bitmap=wxNullBitmap, Point pos=DefaultPosition) -> bool - - - - - - - - - - Init(self) - - - RunWizard(self, WizardPage firstPage) -> bool - - - - - - GetCurrentPage(self) -> WizardPage - - - SetPageSize(self, Size size) - - - - - - GetPageSize(self) -> Size - - - FitToPage(self, WizardPage firstPage) - - - - - - GetPageAreaSizer(self) -> Sizer - - - SetBorder(self, int border) - - - - - - IsRunning(self) -> bool - - - ShowPage(self, WizardPage page, bool goingForward=True) -> bool - - - - - - - HasNextPage(self, WizardPage page) -> bool - - - - - - HasPrevPage(self, WizardPage page) -> bool - - - - - - - - - wx = _core - __docfilter__ = wx.__DocFilter(globals()) - - - - __init__(self, bool isRGB, GLCanvas win, wxPalette palette=wxNullPalette, - GLContext other=None) -> GLContext - - - - - - - - - __del__(self) - - - SetCurrent(self) - - - SetColour(self, String colour) - - - - - - SwapBuffers(self) - - - SetupPixelFormat(self) - - - SetupPalette(self, wxPalette palette) - - - - - - CreateDefaultPalette(self) -> wxPalette - - - GetPalette(self) -> wxPalette - - - GetWindow(self) -> Window - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=GLCanvasNameStr, - int attribList=None, wxPalette palette=wxNullPalette) -> GLCanvas - - - - - - - - - - - - - GLCanvasWithContext(Window parent, GLContext shared=None, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, - long style=0, String name=GLCanvasNameStr, - int attribList=None, wxPalette palette=wxNullPalette) -> GLCanvas - - - - - - - - - - - - - - SetCurrent(self) - - - SetColour(self, String colour) - - - - - - SwapBuffers(self) - - - GetContext(self) -> GLContext - - - - - - wx = _core - __docfilter__ = wx.__DocFilter(globals()) - - import warnings - warnings.warn("This module is deprecated. Please use the wx.lib.ogl package instead.", - DeprecationWarning, stacklevel=2) - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> ShapeRegion - - - SetText(self, String s) - - - - - - SetFont(self, Font f) - - - - - - SetMinSize(self, double w, double h) - - - - - - - SetSize(self, double w, double h) - - - - - - - SetPosition(self, double x, double y) - - - - - - - SetProportions(self, double x, double y) - - - - - - - SetFormatMode(self, int mode) - - - - - - SetName(self, String s) - - - - - - SetColour(self, String col) - - - - - - GetText(self) -> String - - - GetFont(self) -> Font - - - GetMinSize(self, double OUTPUT, double OUTPUT) - - - - - - - GetProportion(self, double OUTPUT, double OUTPUT) - - - - - - - GetSize(self, double OUTPUT, double OUTPUT) - - - - - - - GetPosition(self, double OUTPUT, double OUTPUT) - - - - - - - GetFormatMode(self) -> int - - - GetName(self) -> String - - - GetColour(self) -> String - - - GetActualColourObject(self) -> Colour - - - GetFormattedText(self) -> wxList - - - GetPenColour(self) -> String - - - GetPenStyle(self) -> int - - - SetPenStyle(self, int style) - - - - - - SetPenColour(self, String col) - - - - - - GetActualPen(self) -> wxPen - - - GetWidth(self) -> double - - - GetHeight(self) -> double - - - ClearText(self) - - - - - - __init__(self, int id=0, double x=0.0, double y=0.0) -> AttachmentPoint - - - - - - - - - - - - - - __init__(self, PyShapeEvtHandler prev=None, PyShape shape=None) -> PyShapeEvtHandler - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - _setOORInfo(self, PyObject _self) - - - - - - SetShape(self, PyShape sh) - - - - - - GetShape(self) -> PyShape - - - SetPreviousHandler(self, PyShapeEvtHandler handler) - - - - - - GetPreviousHandler(self) -> PyShapeEvtHandler - - - CreateNewCopy(self) -> PyShapeEvtHandler - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=False) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self, PyShapeCanvas can=None) -> PyShape - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - GetBoundingBoxMax(self, double OUTPUT, double OUTPUT) - - - - - - - GetBoundingBoxMin(self, double OUTPUT, double OUTPUT) - - - - - - - GetPerimeterPoint(self, double x1, double y1, double x2, double y2, double OUTPUT, - double OUTPUT) -> bool - - - - - - - - - - - GetCanvas(self) -> PyShapeCanvas - - - SetCanvas(self, PyShapeCanvas the_canvas) - - - - - - AddToCanvas(self, PyShapeCanvas the_canvas, PyShape addAfter=None) - - - - - - - InsertInCanvas(self, PyShapeCanvas the_canvas) - - - - - - RemoveFromCanvas(self, PyShapeCanvas the_canvas) - - - - - - GetX(self) -> double - - - GetY(self) -> double - - - SetX(self, double x) - - - - - - SetY(self, double y) - - - - - - GetParent(self) -> PyShape - - - SetParent(self, PyShape p) - - - - - - GetTopAncestor(self) -> PyShape - - - GetChildren(self) -> PyObject - - - Unlink(self) - - - SetDrawHandles(self, bool drawH) - - - - - - GetDrawHandles(self) -> bool - - - MakeControlPoints(self) - - - DeleteControlPoints(self, DC dc=None) - - - - - - ResetControlPoints(self) - - - GetEventHandler(self) -> PyShapeEvtHandler - - - SetEventHandler(self, PyShapeEvtHandler handler) - - - - - - MakeMandatoryControlPoints(self) - - - ResetMandatoryControlPoints(self) - - - Recompute(self) -> bool - - - CalculateSize(self) - - - Select(self, bool select=True, DC dc=None) - - - - - - - SetHighlight(self, bool hi=True, bool recurse=False) - - - - - - - IsHighlighted(self) -> bool - - - Selected(self) -> bool - - - AncestorSelected(self) -> bool - - - SetSensitivityFilter(self, int sens=OP_ALL, bool recursive=False) - - - - - - - GetSensitivityFilter(self) -> int - - - SetDraggable(self, bool drag, bool recursive=False) - - - - - - - SetFixedSize(self, bool x, bool y) - - - - - - - GetFixedSize(self, bool OUTPUT, bool OUTPUT) - - - - - - - GetFixedWidth(self) -> bool - - - GetFixedHeight(self) -> bool - - - SetSpaceAttachments(self, bool sp) - - - - - - GetSpaceAttachments(self) -> bool - - - SetShadowMode(self, int mode, bool redraw=False) - - - - - - - GetShadowMode(self) -> int - - - HitTest(self, double x, double y, int OUTPUT, double OUTPUT) -> bool - - - - - - - - - SetCentreResize(self, bool cr) - - - - - - GetCentreResize(self) -> bool - - - SetMaintainAspectRatio(self, bool ar) - - - - - - GetMaintainAspectRatio(self) -> bool - - - GetLines(self) -> PyObject - - - SetDisableLabel(self, bool flag) - - - - - - GetDisableLabel(self) -> bool - - - SetAttachmentMode(self, int mode) - - - - - - GetAttachmentMode(self) -> int - - - SetId(self, long i) - - - - - - GetId(self) -> long - - - SetPen(self, wxPen pen) - - - - - - SetBrush(self, wxBrush brush) - - - - - - Show(self, bool show) - - - - - - IsShown(self) -> bool - - - Move(self, DC dc, double x1, double y1, bool display=True) - - - - - - - - - Erase(self, DC dc) - - - - - - EraseContents(self, DC dc) - - - - - - Draw(self, DC dc) - - - - - - Flash(self) - - - MoveLinks(self, DC dc) - - - - - - DrawContents(self, DC dc) - - - - - - SetSize(self, double x, double y, bool recursive=True) - - - - - - - - SetAttachmentSize(self, double x, double y) - - - - - - - Attach(self, PyShapeCanvas can) - - - - - - Detach(self) - - - Constrain(self) -> bool - - - AddLine(self, PyLineShape line, PyShape other, int attachFrom=0, - int attachTo=0, int positionFrom=-1, int positionTo=-1) - - - - - - - - - - - GetLinePosition(self, PyLineShape line) -> int - - - - - - AddText(self, String string) - - - - - - GetPen(self) -> wxPen - - - GetBrush(self) -> wxBrush - - - SetDefaultRegionSize(self) - - - FormatText(self, DC dc, String s, int regionId=0) - - - - - - - - SetFormatMode(self, int mode, int regionId=0) - - - - - - - GetFormatMode(self, int regionId=0) -> int - - - - - - SetFont(self, Font font, int regionId=0) - - - - - - - GetFont(self, int regionId=0) -> Font - - - - - - SetTextColour(self, String colour, int regionId=0) - - - - - - - GetTextColour(self, int regionId=0) -> String - - - - - - GetNumberOfTextRegions(self) -> int - - - SetRegionName(self, String name, int regionId=0) - - - - - - - GetRegionName(self, int regionId) -> String - - - - - - GetRegionId(self, String name) -> int - - - - - - NameRegions(self, String parentName=EmptyString) - - - - - - GetRegions(self) -> PyObject - - - AddRegion(self, ShapeRegion region) - - - - - - ClearRegions(self) - - - AssignNewIds(self) - - - FindRegion(self, String regionName, int OUTPUT) -> PyShape - - - - - - - FindRegionNames(self, wxStringList list) - - - - - - ClearText(self, int regionId=0) - - - - - - RemoveLine(self, PyLineShape line) - - - - - - GetAttachmentPosition(self, int attachment, double OUTPUT, double OUTPUT, int nth=0, - int no_arcs=1, PyLineShape line=None) -> bool - - - - - - - - - - - GetNumberOfAttachments(self) -> int - - - AttachmentIsValid(self, int attachment) -> bool - - - - - - GetAttachments(self) -> PyObject - - - GetAttachmentPositionEdge(self, int attachment, double OUTPUT, double OUTPUT, int nth=0, - int no_arcs=1, PyLineShape line=None) -> bool - - - - - - - - - - - CalcSimpleAttachment(self, RealPoint pt1, RealPoint pt2, int nth, int noArcs, - PyLineShape line) -> RealPoint - - - - - - - - - - AttachmentSortTest(self, int attachmentPoint, RealPoint pt1, RealPoint pt2) -> bool - - - - - - - - EraseLinks(self, DC dc, int attachment=-1, bool recurse=False) - - - - - - - - DrawLinks(self, DC dc, int attachment=-1, bool recurse=False) - - - - - - - - MoveLineToNewAttachment(self, DC dc, PyLineShape to_move, double x, double y) -> bool - - - - - - - - - ApplyAttachmentOrdering(self, PyObject linesToSort) - - - - - - GetBranchingAttachmentRoot(self, int attachment) -> RealPoint - - - - - - GetBranchingAttachmentInfo(self, int attachment, RealPoint root, RealPoint neck, RealPoint shoulder1, - RealPoint shoulder2) -> bool - - - - - - - - - - GetBranchingAttachmentPoint(self, int attachment, int n, RealPoint attachmentPoint, RealPoint stemPoint) -> bool - - - - - - - - - GetAttachmentLineCount(self, int attachment) -> int - - - - - - SetBranchNeckLength(self, int len) - - - - - - GetBranchNeckLength(self) -> int - - - SetBranchStemLength(self, int len) - - - - - - GetBranchStemLength(self) -> int - - - SetBranchSpacing(self, int len) - - - - - - GetBranchSpacing(self) -> int - - - SetBranchStyle(self, long style) - - - - - - GetBranchStyle(self) -> long - - - PhysicalToLogicalAttachment(self, int physicalAttachment) -> int - - - - - - LogicalToPhysicalAttachment(self, int logicalAttachment) -> int - - - - - - Draggable(self) -> bool - - - HasDescendant(self, PyShape image) -> bool - - - - - - CreateNewCopy(self, bool resetMapping=True, bool recompute=True) -> PyShape - - - - - - - Copy(self, PyShape copy) - - - - - - CopyWithHandler(self, PyShape copy) - - - - - - Rotate(self, double x, double y, double theta) - - - - - - - - GetRotation(self) -> double - - - SetRotation(self, double rotation) - - - - - - ClearAttachments(self) - - - Recentre(self, DC dc) - - - - - - ClearPointList(self, wxList list) - - - - - - GetBackgroundPen(self) -> wxPen - - - GetBackgroundBrush(self) -> wxBrush - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=False) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self) -> PseudoMetaFile - - - __del__(self) - - - Draw(self, DC dc, double xoffset, double yoffset) - - - - - - - - Clear(self) - - - Copy(self, PseudoMetaFile copy) - - - - - - Scale(self, double sx, double sy) - - - - - - - ScaleTo(self, double w, double h) - - - - - - - Translate(self, double x, double y) - - - - - - - Rotate(self, double x, double y, double theta) - - - - - - - - LoadFromMetaFile(self, String filename, double width, double height) -> bool - - - - - - - - GetBounds(self, double minX, double minY, double maxX, double maxY) - - - - - - - - - CalculateSize(self, PyDrawnShape shape) - - - - - - SetRotateable(self, bool rot) - - - - - - GetRotateable(self) -> bool - - - SetSize(self, double w, double h) - - - - - - - SetFillBrush(self, wxBrush brush) - - - - - - GetFillBrush(self) -> wxBrush - - - SetOutlinePen(self, wxPen pen) - - - - - - GetOutlinePen(self) -> wxPen - - - SetOutlineOp(self, int op) - - - - - - GetOutlineOp(self) -> int - - - IsValid(self) -> bool - - - DrawLine(self, Point pt1, Point pt2) - - - - - - - DrawRectangle(self, Rect rect) - - - - - - DrawRoundedRectangle(self, Rect rect, double radius) - - - - - - - DrawArc(self, Point centrePt, Point startPt, Point endPt) - - - - - - - - DrawEllipticArc(self, Rect rect, double startAngle, double endAngle) - - - - - - - - DrawEllipse(self, Rect rect) - - - - - - DrawPoint(self, Point pt) - - - - - - DrawText(self, String text, Point pt) - - - - - - - DrawLines(self, int points, Point points_array) - - - - - - - DrawPolygon(self, int points, Point points_array, int flags=0) - - - - - - - - DrawSpline(self, int points, Point points_array) - - - - - - - SetClippingRect(self, Rect rect) - - - - - - DestroyClippingRect(self) - - - SetPen(self, wxPen pen, bool isOutline=FALSE) - - - - - - - SetBrush(self, wxBrush brush, bool isFill=FALSE) - - - - - - - SetFont(self, Font font) - - - - - - SetTextColour(self, Colour colour) - - - - - - SetBackgroundColour(self, Colour colour) - - - - - - SetBackgroundMode(self, int mode) - - - - - - - - - __init__(self, double width=0.0, double height=0.0) -> PyRectangleShape - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetCornerRadius(self, double radius) - - - - - - GetCornerRadius(self) -> double - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self, PyShapeCanvas the_canvas=None, PyShape object=None, - double size=0.0, double the_xoffset=0.0, double the_yoffset=0.0, - int the_type=0) -> PyControlPoint - - - - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - SetCornerRadius(self, double radius) - - - - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self) -> PyBitmapShape - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - GetBitmap(self) -> Bitmap - - - GetFilename(self) -> String - - - SetBitmap(self, Bitmap bitmap) - - - - - - SetFilename(self, String filename) - - - - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self) -> PyDrawnShape - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - CalculateSize(self) - - - DestroyClippingRect(self) - - - DrawArc(self, Point centrePoint, Point startPoint, Point endPoint) - - - - - - - - DrawAtAngle(self, int angle) - - - - - - DrawEllipticArc(self, Rect rect, double startAngle, double endAngle) - - - - - - - - DrawLine(self, Point point1, Point point2) - - - - - - - DrawLines(self, int points, Point points_array) - - - - - - - DrawPoint(self, Point point) - - - - - - DrawPolygon(self, int points, Point points_array, int flags=0) - - - - - - - - DrawRectangle(self, Rect rect) - - - - - - DrawRoundedRectangle(self, Rect rect, double radius) - - - - - - - DrawSpline(self, int points, Point points_array) - - - - - - - DrawText(self, String text, Point point) - - - - - - - GetAngle(self) -> int - - - GetMetaFile(self) -> PseudoMetaFile - - - GetRotation(self) -> double - - - LoadFromMetaFile(self, String filename) -> bool - - - - - - Rotate(self, double x, double y, double theta) - - - - - - - - SetClippingRect(self, Rect rect) - - - - - - SetDrawnBackgroundColour(self, Colour colour) - - - - - - SetDrawnBackgroundMode(self, int mode) - - - - - - SetDrawnBrush(self, wxBrush pen, bool isOutline=FALSE) - - - - - - - SetDrawnFont(self, Font font) - - - - - - SetDrawnPen(self, wxPen pen, bool isOutline=FALSE) - - - - - - - SetDrawnTextColour(self, Colour colour) - - - - - - Scale(self, double sx, double sy) - - - - - - - SetSaveToFile(self, bool save) - - - - - - Translate(self, double x, double y) - - - - - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self, int type, PyShape constraining, PyObject constrained) -> OGLConstraint - - - - - - - - Evaluate(self) -> bool - - - SetSpacing(self, double x, double y) - - - - - - - Equals(self, double a, double b) -> bool - - - - - - - - - - __init__(self) -> PyCompositeShape - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - AddChild(self, PyShape child, PyShape addAfter=None) - - - - - - - AddConstraint(self, OGLConstraint constraint) -> OGLConstraint - - - - - - AddConstrainedShapes(self, int type, PyShape constraining, PyObject constrained) -> OGLConstraint - - - - - - - - AddSimpleConstraint(self, int type, PyShape constraining, PyShape constrained) -> OGLConstraint - - - - - - - - CalculateSize(self) - - - ContainsDivision(self, PyDivisionShape division) -> bool - - - - - - DeleteConstraint(self, OGLConstraint constraint) - - - - - - DeleteConstraintsInvolvingChild(self, PyShape child) - - - - - - FindContainerImage(self) -> PyShape - - - GetConstraints(self) -> PyObject - - - GetDivisions(self) -> PyObject - - - MakeContainer(self) - - - Recompute(self) -> bool - - - RemoveChild(self, PyShape child) - - - - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self, double width=0.0, double height=0.0) -> PyDividedShape - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - EditRegions(self) - - - SetRegionSizes(self) - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self) -> PyDivisionShape - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - AdjustBottom(self, double bottom, bool test) - - - - - - - AdjustLeft(self, double left, bool test) - - - - - - - AdjustRight(self, double right, bool test) - - - - - - - AdjustTop(self, double top, bool test) - - - - - - - Divide(self, int direction) - - - - - - EditEdge(self, int side) - - - - - - GetBottomSide(self) -> PyDivisionShape - - - GetHandleSide(self) -> int - - - GetLeftSide(self) -> PyDivisionShape - - - GetLeftSideColour(self) -> String - - - GetLeftSidePen(self) -> wxPen - - - GetRightSide(self) -> PyDivisionShape - - - GetTopSide(self) -> PyDivisionShape - - - GetTopSidePen(self) -> wxPen - - - ResizeAdjoining(self, int side, double newPos, bool test) - - - - - - - - PopupMenu(self, double x, double y) - - - - - - - SetBottomSide(self, PyDivisionShape shape) - - - - - - SetHandleSide(self, int side) - - - - - - SetLeftSide(self, PyDivisionShape shape) - - - - - - SetLeftSideColour(self, String colour) - - - - - - SetLeftSidePen(self, wxPen pen) - - - - - - SetRightSide(self, PyDivisionShape shape) - - - - - - SetTopSide(self, PyDivisionShape shape) - - - - - - SetTopSideColour(self, String colour) - - - - - - SetTopSidePen(self, wxPen pen) - - - - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self, double width=0.0, double height=0.0) -> PyEllipseShape - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self, double width=0.0) -> PyCircleShape - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self, int type=0, int end=0, double size=0.0, double dist=0.0, - String name=EmptyString, PseudoMetaFile mf=None, - long arrowId=-1) -> ArrowHead - - - - - - - - - - - - __del__(self) - - - _GetType(self) -> int - - - GetPosition(self) -> int - - - SetPosition(self, int pos) - - - - - - GetXOffset(self) -> double - - - GetYOffset(self) -> double - - - GetSpacing(self) -> double - - - GetSize(self) -> double - - - GetName(self) -> String - - - SetXOffset(self, double x) - - - - - - SetYOffset(self, double y) - - - - - - GetMetaFile(self) -> PseudoMetaFile - - - GetId(self) -> long - - - GetArrowEnd(self) -> int - - - GetArrowSize(self) -> double - - - SetSize(self, double size) - - - - - - SetSpacing(self, double sp) - - - - - - - - - __init__(self) -> PyLineShape - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - AddArrow(self, int type, int end=ARROW_POSITION_END, double arrowSize=10.0, - double xOffset=0.0, String name=EmptyString, - PseudoMetaFile mf=None, long arrowId=-1) - - - - - - - - - - - - AddArrowOrdered(self, ArrowHead arrow, PyObject referenceList, int end) - - - - - - - - ClearArrow(self, String name) -> bool - - - - - - ClearArrowsAtPosition(self, int position=-1) - - - - - - DrawArrow(self, DC dc, ArrowHead arrow, double xOffset, bool proportionalOffset) - - - - - - - - - DeleteArrowHeadId(self, long arrowId) -> bool - - - - - - DeleteArrowHead(self, int position, String name) -> bool - - - - - - - DeleteLineControlPoint(self) -> bool - - - DrawArrows(self, DC dc) - - - - - - DrawRegion(self, DC dc, ShapeRegion region, double x, double y) - - - - - - - - - EraseRegion(self, DC dc, ShapeRegion region, double x, double y) - - - - - - - - - FindArrowHeadId(self, long arrowId) -> ArrowHead - - - - - - FindArrowHead(self, int position, String name) -> ArrowHead - - - - - - - FindLineEndPoints(self, double OUTPUT, double OUTPUT, double OUTPUT, double OUTPUT) - - - - - - - - - FindLinePosition(self, double x, double y) -> int - - - - - - - FindMinimumWidth(self) -> double - - - FindNth(self, PyShape image, int OUTPUT, int OUTPUT, bool incoming) - - - - - - - - - GetAttachmentFrom(self) -> int - - - GetAttachmentTo(self) -> int - - - GetEnds(self, double OUTPUT, double OUTPUT, double OUTPUT, double OUTPUT) - - - - - - - - - GetFrom(self) -> PyShape - - - GetLabelPosition(self, int position, double OUTPUT, double OUTPUT) - - - - - - - - GetNextControlPoint(self, PyShape shape) -> RealPoint - - - - - - GetTo(self) -> PyShape - - - Initialise(self) - - - InsertLineControlPoint(self, DC dc) - - - - - - IsEnd(self, PyShape shape) -> bool - - - - - - IsSpline(self) -> bool - - - MakeLineControlPoints(self, int n) - - - - - - GetLineControlPoints(self) -> PyObject - - - SetLineControlPoints(self, PyObject list) - - - - - - SetAttachmentFrom(self, int fromAttach) - - - - - - SetAttachments(self, int fromAttach, int toAttach) - - - - - - - SetAttachmentTo(self, int toAttach) - - - - - - SetEnds(self, double x1, double y1, double x2, double y2) - - - - - - - - - SetFrom(self, PyShape object) - - - - - - SetIgnoreOffsets(self, bool ignore) - - - - - - SetSpline(self, bool spline) - - - - - - SetTo(self, PyShape object) - - - - - - Straighten(self, DC dc=None) - - - - - - Unlink(self) - - - SetAlignmentOrientation(self, bool isEnd, bool isHoriz) - - - - - - - SetAlignmentType(self, bool isEnd, int alignType) - - - - - - - GetAlignmentOrientation(self, bool isEnd) -> bool - - - - - - GetAlignmentType(self, bool isEnd) -> int - - - - - - GetAlignmentStart(self) -> int - - - GetAlignmentEnd(self) -> int - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self) -> PyPolygonShape - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - Create(self, PyObject points) -> PyObject - - - - - - AddPolygonPoint(self, int pos=0) - - - - - - CalculatePolygonCentre(self) - - - DeletePolygonPoint(self, int pos=0) - - - - - - GetPoints(self) -> PyObject - - - GetOriginalPoints(self) -> PyObject - - - GetOriginalWidth(self) -> double - - - GetOriginalHeight(self) -> double - - - SetOriginalWidth(self, double w) - - - - - - SetOriginalHeight(self, double h) - - - - - - UpdateOriginalPoints(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self, double width=0.0, double height=0.0) -> PyTextShape - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - base_OnDelete(self) - - - base_OnDraw(self, DC dc) - - - - - - base_OnDrawContents(self, DC dc) - - - - - - base_OnDrawBranches(self, DC dc, bool erase=FALSE) - - - - - - - base_OnMoveLinks(self, DC dc) - - - - - - base_OnErase(self, DC dc) - - - - - - base_OnEraseContents(self, DC dc) - - - - - - base_OnHighlight(self, DC dc) - - - - - - base_OnLeftClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnLeftDoubleClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnSize(self, double x, double y) - - - - - - - base_OnMovePre(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) -> bool - - - - - - - - - - - base_OnMovePost(self, DC dc, double x, double y, double old_x, double old_y, - bool display=True) - - - - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0, int attachment=0) - - - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0, int attachment=0) - - - - - - - - - base_OnDrawOutline(self, DC dc, double x, double y, double w, double h) - - - - - - - - - - base_OnDrawControlPoints(self, DC dc) - - - - - - base_OnEraseControlPoints(self, DC dc) - - - - - - base_OnMoveLink(self, DC dc, bool moveControlPoints=True) - - - - - - - base_OnSizingDragLeft(self, PyControlPoint pt, bool draw, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - - base_OnSizingBeginDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnSizingEndDragLeft(self, PyControlPoint pt, double x, double y, int keys=0, - int attachment=0) - - - - - - - - - - base_OnBeginSize(self, double w, double h) - - - - - - - base_OnEndSize(self, double w, double h) - - - - - - - - - - __init__(self) -> Diagram - - - AddShape(self, PyShape shape, PyShape addAfter=None) - - - - - - - Clear(self, DC dc) - - - - - - DeleteAllShapes(self) - - - DrawOutline(self, DC dc, double x1, double y1, double x2, double y2) - - - - - - - - - - FindShape(self, long id) -> PyShape - - - - - - GetCanvas(self) -> PyShapeCanvas - - - GetCount(self) -> int - - - GetGridSpacing(self) -> double - - - GetMouseTolerance(self) -> int - - - GetShapeList(self) -> PyObject - - - GetQuickEditMode(self) -> bool - - - GetSnapToGrid(self) -> bool - - - InsertShape(self, PyShape shape) - - - - - - RecentreAll(self, DC dc) - - - - - - Redraw(self, DC dc) - - - - - - RemoveAllShapes(self) - - - RemoveShape(self, PyShape shape) - - - - - - SetCanvas(self, PyShapeCanvas canvas) - - - - - - SetGridSpacing(self, double spacing) - - - - - - SetMouseTolerance(self, int tolerance) - - - - - - SetQuickEditMode(self, bool mode) - - - - - - SetSnapToGrid(self, bool snap) - - - - - - ShowAll(self, bool show) - - - - - - Snap(self, double INOUT, double INOUT) - - - - - - - - - - __init__(self, Window parent=None, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=BORDER, - String name=wxPyShapeCanvasNameStr) -> PyShapeCanvas - - - - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - AddShape(self, PyShape shape, PyShape addAfter=None) - - - - - - - FindShape(self, double x1, double y, int OUTPUT, wxClassInfo info=None, - PyShape notImage=None) -> PyShape - - - - - - - - - - FindFirstSensitiveShape(self, double x1, double y, int OUTPUT, int op) -> PyShape - - - - - - - - - GetDiagram(self) -> Diagram - - - GetQuickEditMode(self) -> bool - - - InsertShape(self, PyShape shape) - - - - - - base_OnBeginDragLeft(self, double x, double y, int keys=0) - - - - - - - - base_OnBeginDragRight(self, double x, double y, int keys=0) - - - - - - - - base_OnEndDragLeft(self, double x, double y, int keys=0) - - - - - - - - base_OnEndDragRight(self, double x, double y, int keys=0) - - - - - - - - base_OnDragLeft(self, bool draw, double x, double y, int keys=0) - - - - - - - - - base_OnDragRight(self, bool draw, double x, double y, int keys=0) - - - - - - - - - base_OnLeftClick(self, double x, double y, int keys=0) - - - - - - - - base_OnRightClick(self, double x, double y, int keys=0) - - - - - - - - Redraw(self, DC dc) - - - - - - RemoveShape(self, PyShape shape) - - - - - - SetDiagram(self, Diagram diagram) - - - - - - Snap(self, double INOUT, double INOUT) - - - - - - - -# Aliases -ShapeCanvas = PyShapeCanvas -ShapeEvtHandler = PyShapeEvtHandler -Shape = PyShape -RectangleShape = PyRectangleShape -BitmapShape = PyBitmapShape -DrawnShape = PyDrawnShape -CompositeShape = PyCompositeShape -DividedShape = PyDividedShape -DivisionShape = PyDivisionShape -EllipseShape = PyEllipseShape -CircleShape = PyCircleShape -LineShape = PyLineShape -PolygonShape = PyPolygonShape -TextShape = PyTextShape -ControlPoint = PyControlPoint - - - OGLInitialize() - - - OGLCleanUp() - - - - - - wx = _core - __docfilter__ = wx.__DocFilter(globals()) - - - - __init__(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=STCNameStr) -> StyledTextCtrl - - - - - - - - - - - PreStyledTextCtrl() -> StyledTextCtrl - - - Create(self, Window parent, int id=ID_ANY, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0, String name=wxSTCNameStr) - - - - - - - - - - - AddText(self, String text) - - - - - - AddStyledText(self, wxMemoryBuffer data) - - - - - - InsertText(self, int pos, String text) - - - - - - - ClearAll(self) - - - ClearDocumentStyle(self) - - - GetLength(self) -> int - - - GetCharAt(self, int pos) -> int - - - - - - GetCurrentPos(self) -> int - - - GetAnchor(self) -> int - - - GetStyleAt(self, int pos) -> int - - - - - - Redo(self) - - - SetUndoCollection(self, bool collectUndo) - - - - - - SelectAll(self) - - - SetSavePoint(self) - - - GetStyledText(self, int startPos, int endPos) -> wxMemoryBuffer - - - - - - - CanRedo(self) -> bool - - - MarkerLineFromHandle(self, int handle) -> int - - - - - - MarkerDeleteHandle(self, int handle) - - - - - - GetUndoCollection(self) -> bool - - - GetViewWhiteSpace(self) -> int - - - SetViewWhiteSpace(self, int viewWS) - - - - - - PositionFromPoint(self, Point pt) -> int - - - - - - PositionFromPointClose(self, int x, int y) -> int - - - - - - - GotoLine(self, int line) - - - - - - GotoPos(self, int pos) - - - - - - SetAnchor(self, int posAnchor) - - - - - - GetCurLine(self, int OUTPUT) -> String - - - - - - GetEndStyled(self) -> int - - - ConvertEOLs(self, int eolMode) - - - - - - GetEOLMode(self) -> int - - - SetEOLMode(self, int eolMode) - - - - - - StartStyling(self, int pos, int mask) - - - - - - - SetStyling(self, int length, int style) - - - - - - - GetBufferedDraw(self) -> bool - - - SetBufferedDraw(self, bool buffered) - - - - - - SetTabWidth(self, int tabWidth) - - - - - - GetTabWidth(self) -> int - - - SetCodePage(self, int codePage) - - - - - - MarkerDefine(self, int markerNumber, int markerSymbol, Colour foreground=wxNullColour, - Colour background=wxNullColour) - - - - - - - - - MarkerSetForeground(self, int markerNumber, Colour fore) - - - - - - - MarkerSetBackground(self, int markerNumber, Colour back) - - - - - - - MarkerAdd(self, int line, int markerNumber) -> int - - - - - - - MarkerDelete(self, int line, int markerNumber) - - - - - - - MarkerDeleteAll(self, int markerNumber) - - - - - - MarkerGet(self, int line) -> int - - - - - - MarkerNext(self, int lineStart, int markerMask) -> int - - - - - - - MarkerPrevious(self, int lineStart, int markerMask) -> int - - - - - - - MarkerDefineBitmap(self, int markerNumber, Bitmap bmp) - - - - - - - SetMarginType(self, int margin, int marginType) - - - - - - - GetMarginType(self, int margin) -> int - - - - - - SetMarginWidth(self, int margin, int pixelWidth) - - - - - - - GetMarginWidth(self, int margin) -> int - - - - - - SetMarginMask(self, int margin, int mask) - - - - - - - GetMarginMask(self, int margin) -> int - - - - - - SetMarginSensitive(self, int margin, bool sensitive) - - - - - - - GetMarginSensitive(self, int margin) -> bool - - - - - - StyleClearAll(self) - - - StyleSetForeground(self, int style, Colour fore) - - - - - - - StyleSetBackground(self, int style, Colour back) - - - - - - - StyleSetBold(self, int style, bool bold) - - - - - - - StyleSetItalic(self, int style, bool italic) - - - - - - - StyleSetSize(self, int style, int sizePoints) - - - - - - - StyleSetFaceName(self, int style, String fontName) - - - - - - - StyleSetEOLFilled(self, int style, bool filled) - - - - - - - StyleResetDefault(self) - - - StyleSetUnderline(self, int style, bool underline) - - - - - - - StyleSetCase(self, int style, int caseForce) - - - - - - - StyleSetCharacterSet(self, int style, int characterSet) - - - - - - - StyleSetHotSpot(self, int style, bool hotspot) - - - - - - - SetSelForeground(self, bool useSetting, Colour fore) - - - - - - - SetSelBackground(self, bool useSetting, Colour back) - - - - - - - SetCaretForeground(self, Colour fore) - - - - - - CmdKeyAssign(self, int key, int modifiers, int cmd) - - - - - - - - CmdKeyClear(self, int key, int modifiers) - - - - - - - CmdKeyClearAll(self) - - - SetStyleBytes(self, int length, char styleBytes) - - - - - - - StyleSetVisible(self, int style, bool visible) - - - - - - - GetCaretPeriod(self) -> int - - - SetCaretPeriod(self, int periodMilliseconds) - - - - - - SetWordChars(self, String characters) - - - - - - BeginUndoAction(self) - - - EndUndoAction(self) - - - IndicatorSetStyle(self, int indic, int style) - - - - - - - IndicatorGetStyle(self, int indic) -> int - - - - - - IndicatorSetForeground(self, int indic, Colour fore) - - - - - - - IndicatorGetForeground(self, int indic) -> Colour - - - - - - SetWhitespaceForeground(self, bool useSetting, Colour fore) - - - - - - - SetWhitespaceBackground(self, bool useSetting, Colour back) - - - - - - - SetStyleBits(self, int bits) - - - - - - GetStyleBits(self) -> int - - - SetLineState(self, int line, int state) - - - - - - - GetLineState(self, int line) -> int - - - - - - GetMaxLineState(self) -> int - - - GetCaretLineVisible(self) -> bool - - - SetCaretLineVisible(self, bool show) - - - - - - GetCaretLineBack(self) -> Colour - - - SetCaretLineBack(self, Colour back) - - - - - - StyleSetChangeable(self, int style, bool changeable) - - - - - - - AutoCompShow(self, int lenEntered, String itemList) - - - - - - - AutoCompCancel(self) - - - AutoCompActive(self) -> bool - - - AutoCompPosStart(self) -> int - - - AutoCompComplete(self) - - - AutoCompStops(self, String characterSet) - - - - - - AutoCompSetSeparator(self, int separatorCharacter) - - - - - - AutoCompGetSeparator(self) -> int - - - AutoCompSelect(self, String text) - - - - - - AutoCompSetCancelAtStart(self, bool cancel) - - - - - - AutoCompGetCancelAtStart(self) -> bool - - - AutoCompSetFillUps(self, String characterSet) - - - - - - AutoCompSetChooseSingle(self, bool chooseSingle) - - - - - - AutoCompGetChooseSingle(self) -> bool - - - AutoCompSetIgnoreCase(self, bool ignoreCase) - - - - - - AutoCompGetIgnoreCase(self) -> bool - - - UserListShow(self, int listType, String itemList) - - - - - - - AutoCompSetAutoHide(self, bool autoHide) - - - - - - AutoCompGetAutoHide(self) -> bool - - - AutoCompSetDropRestOfWord(self, bool dropRestOfWord) - - - - - - AutoCompGetDropRestOfWord(self) -> bool - - - RegisterImage(self, int type, Bitmap bmp) - - - - - - - ClearRegisteredImages(self) - - - AutoCompGetTypeSeparator(self) -> int - - - AutoCompSetTypeSeparator(self, int separatorCharacter) - - - - - - SetIndent(self, int indentSize) - - - - - - GetIndent(self) -> int - - - SetUseTabs(self, bool useTabs) - - - - - - GetUseTabs(self) -> bool - - - SetLineIndentation(self, int line, int indentSize) - - - - - - - GetLineIndentation(self, int line) -> int - - - - - - GetLineIndentPosition(self, int line) -> int - - - - - - GetColumn(self, int pos) -> int - - - - - - SetUseHorizontalScrollBar(self, bool show) - - - - - - GetUseHorizontalScrollBar(self) -> bool - - - SetIndentationGuides(self, bool show) - - - - - - GetIndentationGuides(self) -> bool - - - SetHighlightGuide(self, int column) - - - - - - GetHighlightGuide(self) -> int - - - GetLineEndPosition(self, int line) -> int - - - - - - GetCodePage(self) -> int - - - GetCaretForeground(self) -> Colour - - - GetReadOnly(self) -> bool - - - SetCurrentPos(self, int pos) - - - - - - SetSelectionStart(self, int pos) - - - - - - GetSelectionStart(self) -> int - - - SetSelectionEnd(self, int pos) - - - - - - GetSelectionEnd(self) -> int - - - SetPrintMagnification(self, int magnification) - - - - - - GetPrintMagnification(self) -> int - - - SetPrintColourMode(self, int mode) - - - - - - GetPrintColourMode(self) -> int - - - FindText(self, int minPos, int maxPos, String text, int flags=0) -> int - - - - - - - - - FormatRange(self, bool doDraw, int startPos, int endPos, DC draw, DC target, - Rect renderRect, Rect pageRect) -> int - - - - - - - - - - - - GetFirstVisibleLine(self) -> int - - - GetLine(self, int line) -> String - - - - - - GetLineCount(self) -> int - - - SetMarginLeft(self, int pixelWidth) - - - - - - GetMarginLeft(self) -> int - - - SetMarginRight(self, int pixelWidth) - - - - - - GetMarginRight(self) -> int - - - GetModify(self) -> bool - - - SetSelection(self, int start, int end) - - - - - - - GetSelectedText(self) -> String - - - GetTextRange(self, int startPos, int endPos) -> String - - - - - - - HideSelection(self, bool normal) - - - - - - LineFromPosition(self, int pos) -> int - - - - - - PositionFromLine(self, int line) -> int - - - - - - LineScroll(self, int columns, int lines) - - - - - - - EnsureCaretVisible(self) - - - ReplaceSelection(self, String text) - - - - - - SetReadOnly(self, bool readOnly) - - - - - - CanPaste(self) -> bool - - - CanUndo(self) -> bool - - - EmptyUndoBuffer(self) - - - Undo(self) - - - Cut(self) - - - Copy(self) - - - Paste(self) - - - Clear(self) - - - SetText(self, String text) - - - - - - GetText(self) -> String - - - GetTextLength(self) -> int - - - SetOvertype(self, bool overtype) - - - - - - GetOvertype(self) -> bool - - - SetCaretWidth(self, int pixelWidth) - - - - - - GetCaretWidth(self) -> int - - - SetTargetStart(self, int pos) - - - - - - GetTargetStart(self) -> int - - - SetTargetEnd(self, int pos) - - - - - - GetTargetEnd(self) -> int - - - ReplaceTarget(self, String text) -> int - - - - - - ReplaceTargetRE(self, String text) -> int - - - - - - SearchInTarget(self, String text) -> int - - - - - - SetSearchFlags(self, int flags) - - - - - - GetSearchFlags(self) -> int - - - CallTipShow(self, int pos, String definition) - - - - - - - CallTipCancel(self) - - - CallTipActive(self) -> bool - - - CallTipPosAtStart(self) -> int - - - CallTipSetHighlight(self, int start, int end) - - - - - - - CallTipSetBackground(self, Colour back) - - - - - - CallTipSetForeground(self, Colour fore) - - - - - - CallTipSetForegroundHighlight(self, Colour fore) - - - - - - VisibleFromDocLine(self, int line) -> int - - - - - - DocLineFromVisible(self, int lineDisplay) -> int - - - - - - SetFoldLevel(self, int line, int level) - - - - - - - GetFoldLevel(self, int line) -> int - - - - - - GetLastChild(self, int line, int level) -> int - - - - - - - GetFoldParent(self, int line) -> int - - - - - - ShowLines(self, int lineStart, int lineEnd) - - - - - - - HideLines(self, int lineStart, int lineEnd) - - - - - - - GetLineVisible(self, int line) -> bool - - - - - - SetFoldExpanded(self, int line, bool expanded) - - - - - - - GetFoldExpanded(self, int line) -> bool - - - - - - ToggleFold(self, int line) - - - - - - EnsureVisible(self, int line) - - - - - - SetFoldFlags(self, int flags) - - - - - - EnsureVisibleEnforcePolicy(self, int line) - - - - - - SetTabIndents(self, bool tabIndents) - - - - - - GetTabIndents(self) -> bool - - - SetBackSpaceUnIndents(self, bool bsUnIndents) - - - - - - GetBackSpaceUnIndents(self) -> bool - - - SetMouseDwellTime(self, int periodMilliseconds) - - - - - - GetMouseDwellTime(self) -> int - - - WordStartPosition(self, int pos, bool onlyWordCharacters) -> int - - - - - - - WordEndPosition(self, int pos, bool onlyWordCharacters) -> int - - - - - - - SetWrapMode(self, int mode) - - - - - - GetWrapMode(self) -> int - - - SetLayoutCache(self, int mode) - - - - - - GetLayoutCache(self) -> int - - - SetScrollWidth(self, int pixelWidth) - - - - - - GetScrollWidth(self) -> int - - - TextWidth(self, int style, String text) -> int - - - - - - - SetEndAtLastLine(self, bool endAtLastLine) - - - - - - GetEndAtLastLine(self) -> int - - - TextHeight(self, int line) -> int - - - - - - SetUseVerticalScrollBar(self, bool show) - - - - - - GetUseVerticalScrollBar(self) -> bool - - - AppendText(self, int length, String text) - - - - - - - GetTwoPhaseDraw(self) -> bool - - - SetTwoPhaseDraw(self, bool twoPhase) - - - - - - TargetFromSelection(self) - - - LinesJoin(self) - - - LinesSplit(self, int pixelWidth) - - - - - - SetFoldMarginColour(self, bool useSetting, Colour back) - - - - - - - SetFoldMarginHiColour(self, bool useSetting, Colour fore) - - - - - - - LineDown(self) - This is just a wrapper for ScrollLines(1). - - - LineDownExtend(self) - - - LineUp(self) - This is just a wrapper for ScrollLines(-1). - - - LineUpExtend(self) - - - CharLeft(self) - - - CharLeftExtend(self) - - - CharRight(self) - - - CharRightExtend(self) - - - WordLeft(self) - - - WordLeftExtend(self) - - - WordRight(self) - - - WordRightExtend(self) - - - Home(self) - - - HomeExtend(self) - - - LineEnd(self) - - - LineEndExtend(self) - - - DocumentStart(self) - - - DocumentStartExtend(self) - - - DocumentEnd(self) - - - DocumentEndExtend(self) - - - PageUp(self) - This is just a wrapper for ScrollPages(-1). - - - PageUpExtend(self) - - - PageDown(self) - This is just a wrapper for ScrollPages(1). - - - PageDownExtend(self) - - - EditToggleOvertype(self) - - - Cancel(self) - - - DeleteBack(self) - - - Tab(self) - - - BackTab(self) - - - NewLine(self) - - - FormFeed(self) - - - VCHome(self) - - - VCHomeExtend(self) - - - ZoomIn(self) - - - ZoomOut(self) - - - DelWordLeft(self) - - - DelWordRight(self) - - - LineCut(self) - - - LineDelete(self) - - - LineTranspose(self) - - - LineDuplicate(self) - - - LowerCase(self) - - - UpperCase(self) - - - LineScrollDown(self) - - - LineScrollUp(self) - - - DeleteBackNotLine(self) - - - HomeDisplay(self) - - - HomeDisplayExtend(self) - - - LineEndDisplay(self) - - - LineEndDisplayExtend(self) - - - HomeWrap(self) - - - HomeWrapExtend(self) - - - LineEndWrap(self) - - - LineEndWrapExtend(self) - - - VCHomeWrap(self) - - - VCHomeWrapExtend(self) - - - LineCopy(self) - - - MoveCaretInsideView(self) - - - LineLength(self, int line) -> int - - - - - - BraceHighlight(self, int pos1, int pos2) - - - - - - - BraceBadLight(self, int pos) - - - - - - BraceMatch(self, int pos) -> int - - - - - - GetViewEOL(self) -> bool - - - SetViewEOL(self, bool visible) - - - - - - GetDocPointer(self) -> void - - - SetDocPointer(self, void docPointer) - - - - - - SetModEventMask(self, int mask) - - - - - - GetEdgeColumn(self) -> int - - - SetEdgeColumn(self, int column) - - - - - - GetEdgeMode(self) -> int - - - SetEdgeMode(self, int mode) - - - - - - GetEdgeColour(self) -> Colour - - - SetEdgeColour(self, Colour edgeColour) - - - - - - SearchAnchor(self) - - - SearchNext(self, int flags, String text) -> int - - - - - - - SearchPrev(self, int flags, String text) -> int - - - - - - - LinesOnScreen(self) -> int - - - UsePopUp(self, bool allowPopUp) - - - - - - SelectionIsRectangle(self) -> bool - - - SetZoom(self, int zoom) - - - - - - GetZoom(self) -> int - - - CreateDocument(self) -> void - - - AddRefDocument(self, void docPointer) - - - - - - ReleaseDocument(self, void docPointer) - - - - - - GetModEventMask(self) -> int - - - SetSTCFocus(self, bool focus) - - - - - - GetSTCFocus(self) -> bool - - - SetStatus(self, int statusCode) - - - - - - GetStatus(self) -> int - - - SetMouseDownCaptures(self, bool captures) - - - - - - GetMouseDownCaptures(self) -> bool - - - SetSTCCursor(self, int cursorType) - - - - - - GetSTCCursor(self) -> int - - - SetControlCharSymbol(self, int symbol) - - - - - - GetControlCharSymbol(self) -> int - - - WordPartLeft(self) - - - WordPartLeftExtend(self) - - - WordPartRight(self) - - - WordPartRightExtend(self) - - - SetVisiblePolicy(self, int visiblePolicy, int visibleSlop) - - - - - - - DelLineLeft(self) - - - DelLineRight(self) - - - SetXOffset(self, int newOffset) - - - - - - GetXOffset(self) -> int - - - ChooseCaretX(self) - - - SetXCaretPolicy(self, int caretPolicy, int caretSlop) - - - - - - - SetYCaretPolicy(self, int caretPolicy, int caretSlop) - - - - - - - SetPrintWrapMode(self, int mode) - - - - - - GetPrintWrapMode(self) -> int - - - SetHotspotActiveForeground(self, bool useSetting, Colour fore) - - - - - - - SetHotspotActiveBackground(self, bool useSetting, Colour back) - - - - - - - SetHotspotActiveUnderline(self, bool underline) - - - - - - SetHotspotSingleLine(self, bool singleLine) - - - - - - ParaDown(self) - - - ParaDownExtend(self) - - - ParaUp(self) - - - ParaUpExtend(self) - - - PositionBefore(self, int pos) -> int - - - - - - PositionAfter(self, int pos) -> int - - - - - - CopyRange(self, int start, int end) - - - - - - - CopyText(self, int length, String text) - - - - - - - SetSelectionMode(self, int mode) - - - - - - GetSelectionMode(self) -> int - - - GetLineSelStartPosition(self, int line) -> int - - - - - - GetLineSelEndPosition(self, int line) -> int - - - - - - LineDownRectExtend(self) - - - LineUpRectExtend(self) - - - CharLeftRectExtend(self) - - - CharRightRectExtend(self) - - - HomeRectExtend(self) - - - VCHomeRectExtend(self) - - - LineEndRectExtend(self) - - - PageUpRectExtend(self) - - - PageDownRectExtend(self) - - - StutteredPageUp(self) - - - StutteredPageUpExtend(self) - - - StutteredPageDown(self) - - - StutteredPageDownExtend(self) - - - WordLeftEnd(self) - - - WordLeftEndExtend(self) - - - WordRightEnd(self) - - - WordRightEndExtend(self) - - - SetWhitespaceChars(self, String characters) - - - - - - SetCharsDefault(self) - - - AutoCompGetCurrent(self) -> int - - - StartRecord(self) - - - StopRecord(self) - - - SetLexer(self, int lexer) - - - - - - GetLexer(self) -> int - - - Colourise(self, int start, int end) - - - - - - - SetProperty(self, String key, String value) - - - - - - - SetKeyWords(self, int keywordSet, String keyWords) - - - - - - - SetLexerLanguage(self, String language) - - - - - - GetCurrentLine(self) -> int - - - StyleSetSpec(self, int styleNum, String spec) - - - - - - - StyleSetFont(self, int styleNum, Font font) - - - - - - - StyleSetFontAttr(self, int styleNum, int size, String faceName, bool bold, - bool italic, bool underline) - - - - - - - - - - - CmdKeyExecute(self, int cmd) - - - - - - SetMargins(self, int left, int right) - - - - - - - GetSelection(self, int OUTPUT, int OUTPUT) - - - - - - - PointFromPosition(self, int pos) -> Point - - - - - - ScrollToLine(self, int line) - - - - - - ScrollToColumn(self, int column) - - - - - - SendMsg(self, int msg, long wp=0, long lp=0) -> long - - - - - - - - SetVScrollBar(self, wxScrollBar bar) - - - - - - SetHScrollBar(self, wxScrollBar bar) - - - - - - GetLastKeydownProcessed(self) -> bool - - - SetLastKeydownProcessed(self, bool val) - - - - - - SaveFile(self, String filename) -> bool - - - - - - LoadFile(self, String filename) -> bool - - - - - - DoDragOver(self, int x, int y, int def) -> int - - - - - - - - DoDropText(self, long x, long y, String data) -> bool - - - - - - - - SetUseAntiAliasing(self, bool useAA) - - - - - - GetUseAntiAliasing(self) -> bool - - - - - - __init__(self, wxEventType commandType=0, int id=0) -> StyledTextEvent - - - - - - - __del__(self) - - - SetPosition(self, int pos) - - - - - - SetKey(self, int k) - - - - - - SetModifiers(self, int m) - - - - - - SetModificationType(self, int t) - - - - - - SetText(self, String t) - - - - - - SetLength(self, int len) - - - - - - SetLinesAdded(self, int num) - - - - - - SetLine(self, int val) - - - - - - SetFoldLevelNow(self, int val) - - - - - - SetFoldLevelPrev(self, int val) - - - - - - SetMargin(self, int val) - - - - - - SetMessage(self, int val) - - - - - - SetWParam(self, int val) - - - - - - SetLParam(self, int val) - - - - - - SetListType(self, int val) - - - - - - SetX(self, int val) - - - - - - SetY(self, int val) - - - - - - SetDragText(self, String val) - - - - - - SetDragAllowMove(self, bool val) - - - - - - SetDragResult(self, int val) - - - - - - GetPosition(self) -> int - - - GetKey(self) -> int - - - GetModifiers(self) -> int - - - GetModificationType(self) -> int - - - GetText(self) -> String - - - GetLength(self) -> int - - - GetLinesAdded(self) -> int - - - GetLine(self) -> int - - - GetFoldLevelNow(self) -> int - - - GetFoldLevelPrev(self) -> int - - - GetMargin(self) -> int - - - GetMessage(self) -> int - - - GetWParam(self) -> int - - - GetLParam(self) -> int - - - GetListType(self) -> int - - - GetX(self) -> int - - - GetY(self) -> int - - - GetDragText(self) -> String - - - GetDragAllowMove(self) -> bool - - - GetDragResult(self) -> int - - - GetShift(self) -> bool - - - GetControl(self) -> bool - - - GetAlt(self) -> bool - - - Clone(self) -> Event - - - -EVT_STC_CHANGE = wx.PyEventBinder( wxEVT_STC_CHANGE, 1 ) -EVT_STC_STYLENEEDED = wx.PyEventBinder( wxEVT_STC_STYLENEEDED, 1 ) -EVT_STC_CHARADDED = wx.PyEventBinder( wxEVT_STC_CHARADDED, 1 ) -EVT_STC_SAVEPOINTREACHED = wx.PyEventBinder( wxEVT_STC_SAVEPOINTREACHED, 1 ) -EVT_STC_SAVEPOINTLEFT = wx.PyEventBinder( wxEVT_STC_SAVEPOINTLEFT, 1 ) -EVT_STC_ROMODIFYATTEMPT = wx.PyEventBinder( wxEVT_STC_ROMODIFYATTEMPT, 1 ) -EVT_STC_KEY = wx.PyEventBinder( wxEVT_STC_KEY, 1 ) -EVT_STC_DOUBLECLICK = wx.PyEventBinder( wxEVT_STC_DOUBLECLICK, 1 ) -EVT_STC_UPDATEUI = wx.PyEventBinder( wxEVT_STC_UPDATEUI, 1 ) -EVT_STC_MODIFIED = wx.PyEventBinder( wxEVT_STC_MODIFIED, 1 ) -EVT_STC_MACRORECORD = wx.PyEventBinder( wxEVT_STC_MACRORECORD, 1 ) -EVT_STC_MARGINCLICK = wx.PyEventBinder( wxEVT_STC_MARGINCLICK, 1 ) -EVT_STC_NEEDSHOWN = wx.PyEventBinder( wxEVT_STC_NEEDSHOWN, 1 ) -EVT_STC_PAINTED = wx.PyEventBinder( wxEVT_STC_PAINTED, 1 ) -EVT_STC_USERLISTSELECTION = wx.PyEventBinder( wxEVT_STC_USERLISTSELECTION, 1 ) -EVT_STC_URIDROPPED = wx.PyEventBinder( wxEVT_STC_URIDROPPED, 1 ) -EVT_STC_DWELLSTART = wx.PyEventBinder( wxEVT_STC_DWELLSTART, 1 ) -EVT_STC_DWELLEND = wx.PyEventBinder( wxEVT_STC_DWELLEND, 1 ) -EVT_STC_START_DRAG = wx.PyEventBinder( wxEVT_STC_START_DRAG, 1 ) -EVT_STC_DRAG_OVER = wx.PyEventBinder( wxEVT_STC_DRAG_OVER, 1 ) -EVT_STC_DO_DROP = wx.PyEventBinder( wxEVT_STC_DO_DROP, 1 ) -EVT_STC_ZOOM = wx.PyEventBinder( wxEVT_STC_ZOOM, 1 ) -EVT_STC_HOTSPOT_CLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_CLICK, 1 ) -EVT_STC_HOTSPOT_DCLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_DCLICK, 1 ) -EVT_STC_CALLTIP_CLICK = wx.PyEventBinder( wxEVT_STC_CALLTIP_CLICK, 1 ) - - - - - wx = _core - __docfilter__ = wx.__DocFilter(globals()) - -#--------------------------------------------------------------------------- - - - - - __init__(self, String filemask, int flags=XRC_USE_LOCALE) -> XmlResource - - - - - - - EmptyXmlResource(int flags=XRC_USE_LOCALE) -> XmlResource - - - - - - __del__(self) - - - Load(self, String filemask) -> bool - - - - - - LoadFromString(self, String data) -> bool - - - - - - InitAllHandlers(self) - - - AddHandler(self, XmlResourceHandler handler) - - - - - - InsertHandler(self, XmlResourceHandler handler) - - - - - - ClearHandlers(self) - - - AddSubclassFactory(XmlSubclassFactory factory) - - - - - - LoadMenu(self, String name) -> Menu - - - - - - LoadMenuBar(self, String name) -> MenuBar - - - - - - LoadMenuBarOnFrame(self, Window parent, String name) -> MenuBar - - - - - - - LoadToolBar(self, Window parent, String name) -> wxToolBar - - - - - - - LoadDialog(self, Window parent, String name) -> wxDialog - - - - - - - LoadOnDialog(self, wxDialog dlg, Window parent, String name) -> bool - - - - - - - - LoadPanel(self, Window parent, String name) -> wxPanel - - - - - - - LoadOnPanel(self, wxPanel panel, Window parent, String name) -> bool - - - - - - - - LoadFrame(self, Window parent, String name) -> wxFrame - - - - - - - LoadOnFrame(self, wxFrame frame, Window parent, String name) -> bool - - - - - - - - LoadObject(self, Window parent, String name, String classname) -> Object - - - - - - - - LoadOnObject(self, Object instance, Window parent, String name, String classname) -> bool - - - - - - - - - LoadBitmap(self, String name) -> Bitmap - - - - - - LoadIcon(self, String name) -> Icon - - - - - - AttachUnknownControl(self, String name, Window control, Window parent=None) -> bool - - - - - - - - GetXRCID(String str_id) -> int - - - - - - GetVersion(self) -> long - - - CompareVersion(self, int major, int minor, int release, int revision) -> int - - - - - - - - - Get() -> XmlResource - - - Set(XmlResource res) -> XmlResource - - - - - - GetFlags(self) -> int - - - SetFlags(self, int flags) - - - - - - -def XRCID(str_id): - return XmlResource_GetXRCID(str_id) - -def XRCCTRL(window, str_id, *ignoreargs): - return window.FindWindowById(XRCID(str_id)) - - -#--------------------------------------------------------------------------- - - - - __init__(self) -> XmlSubclassFactory - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - -#--------------------------------------------------------------------------- - - - - __init__(self, String name=EmptyString, String value=EmptyString, - XmlProperty next=None) -> XmlProperty - - - - - - - - GetName(self) -> String - - - GetValue(self) -> String - - - GetNext(self) -> XmlProperty - - - SetName(self, String name) - - - - - - SetValue(self, String value) - - - - - - SetNext(self, XmlProperty next) - - - - - - - - __init__(self, XmlNode parent=None, int type=0, String name=EmptyString, - String content=EmptyString, XmlProperty props=None, - XmlNode next=None) -> XmlNode - - - - - - - - - - - XmlNodeEasy(int type, String name, String content=EmptyString) -> XmlNode - - - - - - - - __del__(self) - - - AddChild(self, XmlNode child) - - - - - - InsertChild(self, XmlNode child, XmlNode before_node) - - - - - - - RemoveChild(self, XmlNode child) -> bool - - - - - - AddProperty(self, XmlProperty prop) - - - - - - AddPropertyName(self, String name, String value) - - - - - - - DeleteProperty(self, String name) -> bool - - - - - - GetType(self) -> int - - - GetName(self) -> String - - - GetContent(self) -> String - - - GetParent(self) -> XmlNode - - - GetNext(self) -> XmlNode - - - GetChildren(self) -> XmlNode - - - GetProperties(self) -> XmlProperty - - - GetPropVal(self, String propName, String defaultVal) -> String - - - - - - - HasProp(self, String propName) -> bool - - - - - - SetType(self, int type) - - - - - - SetName(self, String name) - - - - - - SetContent(self, String con) - - - - - - SetParent(self, XmlNode parent) - - - - - - SetNext(self, XmlNode next) - - - - - - SetChildren(self, XmlNode child) - - - - - - SetProperties(self, XmlProperty prop) - - - - - - - - - __init__(self, String filename, String encoding=UTF8String) -> XmlDocument - - - - - - - XmlDocumentFromStream(InputStream stream, String encoding=UTF8String) -> XmlDocument - - - - - - - EmptyXmlDocument() -> XmlDocument - - - __del__(self) - - - Load(self, String filename, String encoding=UTF8String) -> bool - - - - - - - LoadFromStream(self, InputStream stream, String encoding=UTF8String) -> bool - - - - - - - Save(self, String filename) -> bool - - - - - - SaveToStream(self, OutputStream stream) -> bool - - - - - - IsOk(self) -> bool - - - GetRoot(self) -> XmlNode - - - GetVersion(self) -> String - - - GetFileEncoding(self) -> String - - - SetRoot(self, XmlNode node) - - - - - - SetVersion(self, String version) - - - - - - SetFileEncoding(self, String encoding) - - - - - - -#--------------------------------------------------------------------------- - - - - - __init__(self) -> XmlResourceHandler - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - CreateResource(self, XmlNode node, Object parent, Object instance) -> Object - - - - - - - - SetParentResource(self, XmlResource res) - - - - - - GetResource(self) -> XmlResource - - - GetNode(self) -> XmlNode - - - GetClass(self) -> String - - - GetParent(self) -> Object - - - GetInstance(self) -> Object - - - GetParentAsWindow(self) -> Window - - - GetInstanceAsWindow(self) -> Window - - - IsOfClass(self, XmlNode node, String classname) -> bool - - - - - - - GetNodeContent(self, XmlNode node) -> String - - - - - - HasParam(self, String param) -> bool - - - - - - GetParamNode(self, String param) -> XmlNode - - - - - - GetParamValue(self, String param) -> String - - - - - - AddStyle(self, String name, int value) - - - - - - - AddWindowStyles(self) - - - GetStyle(self, String param=StyleString, int defaults=0) -> int - - - - - - - GetText(self, String param, bool translate=True) -> String - - - - - - - GetID(self) -> int - - - GetName(self) -> String - - - GetBool(self, String param, bool defaultv=False) -> bool - - - - - - - GetLong(self, String param, long defaultv=0) -> long - - - - - - - GetColour(self, String param) -> Colour - - - - - - GetSize(self, String param=SizeString) -> Size - - - - - - GetPosition(self, String param=PosString) -> Point - - - - - - GetDimension(self, String param, int defaultv=0) -> int - - - - - - - GetBitmap(self, String param=BitmapString, wxArtClient defaultArtClient=wxART_OTHER, - Size size=DefaultSize) -> Bitmap - - - - - - - - GetIcon(self, String param=IconString, wxArtClient defaultArtClient=wxART_OTHER, - Size size=DefaultSize) -> Icon - - - - - - - - GetFont(self, String param=FontString) -> Font - - - - - - SetupWindow(self, Window wnd) - - - - - - CreateChildren(self, Object parent, bool this_hnd_only=False) - - - - - - - CreateChildrenPrivately(self, Object parent, XmlNode rootnode=None) - - - - - - - CreateResFromNode(self, XmlNode node, Object parent, Object instance=None) -> Object - - - - - - - - GetCurFileSystem(self) -> FileSystem - - - #---------------------------------------------------------------------------- -# The global was removed in favor of static accessor functions. This is for -# backwards compatibility: - -TheXmlResource = XmlResource_Get() - - -#---------------------------------------------------------------------------- -# Create a factory for handling the subclass property of the object tag. - - -def _my_import(name): - mod = __import__(name) - components = name.split('.') - for comp in components[1:]: - mod = getattr(mod, comp) - return mod - - -class XmlSubclassFactory_Python(XmlSubclassFactory): - def __init__(self): - XmlSubclassFactory.__init__(self) - - def Create(self, className): - assert className.find('.') != -1, "Module name must be specified!" - mname = className[:className.rfind('.')] - cname = className[className.rfind('.')+1:] - module = _my_import(mname) - klass = getattr(module, cname) - inst = klass() - return inst - - -XmlResource_AddSubclassFactory(XmlSubclassFactory_Python()) - -#---------------------------------------------------------------------------- - - - - - - import wx - __docfilter__ = wx._core.__DocFilter(globals()) - - - - __init__(self, Object target) -> DynamicSashSplitEvent - - - - - - - - - __init__(self, Object target) -> DynamicSashUnifyEvent - - - - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxDS_MANAGE_SCROLLBARS|wxDS_DRAG_CORNER, - String name=DynamicSashNameStr) -> DynamicSashWindow - - - - - - - - - - - PreDynamicSashWindow() -> DynamicSashWindow - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxCLIP_CHILDREN|wxDS_MANAGE_SCROLLBARS|wxDS_DRAG_CORNER, - String name=DynamicSashNameStr) -> bool - - - - - - - - - - - GetHScrollBar(self, Window child) -> ScrollBar - - - - - - GetVScrollBar(self, Window child) -> ScrollBar - - - - - - -EVT_DYNAMIC_SASH_SPLIT = wx.PyEventBinder( wxEVT_DYNAMIC_SASH_SPLIT, 1 ) -EVT_DYNAMIC_SASH_UNIFY = wx.PyEventBinder( wxEVT_DYNAMIC_SASH_UNIFY, 1 ) - - - - - __init__(self, Window parent, int id=-1, String label=EmptyString, - Point pos=DefaultPosition, Size size=DefaultSize, - long style=wxEL_ALLOW_NEW|wxEL_ALLOW_EDIT|wxEL_ALLOW_DELETE, - String name=EditableListBoxNameStr) -> EditableListBox - - - - - - - - - - - - SetStrings(self, wxArrayString strings) - - - - - - GetStrings(self) -> PyObject - - - GetListCtrl(self) -> ListCtrl - - - GetDelButton(self) -> BitmapButton - - - GetNewButton(self) -> BitmapButton - - - GetUpButton(self) -> BitmapButton - - - GetDownButton(self) -> BitmapButton - - - GetEditButton(self) -> BitmapButton - - - - - - __init__(self, Window parent, int id, Point pos=DefaultPosition, Size size=DefaultSize, - long style=TR_HAS_BUTTONS) -> RemotelyScrolledTreeCtrl - - - - - - - - - - HideVScrollbar(self) - - - AdjustRemoteScrollbars(self) - - - GetScrolledWindow(self) -> ScrolledWindow - - - ScrollToLine(self, int posHoriz, int posVert) - - - - - - - SetCompanionWindow(self, Window companion) - - - - - - GetCompanionWindow(self) -> Window - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0) -> TreeCompanionWindow - - - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - GetTreeCtrl(self) -> RemotelyScrolledTreeCtrl - - - SetTreeCtrl(self, RemotelyScrolledTreeCtrl treeCtrl) - - - - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxSP_3D|wxCLIP_CHILDREN) -> ThinSplitterWindow - - - - - - - - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=0) -> SplitterScrolledWindow - - - - - - - - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxLED_ALIGN_LEFT|wxLED_DRAW_FADED) -> LEDNumberCtrl - - - - - - - - - - PreLEDNumberCtrl() -> LEDNumberCtrl - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=wxLED_ALIGN_LEFT|wxLED_DRAW_FADED) -> bool - - - - - - - - - - GetAlignment(self) -> int - - - GetDrawFaded(self) -> bool - - - GetValue(self) -> String - - - SetAlignment(self, int Alignment, bool Redraw=true) - - - - - - - SetDrawFaded(self, bool DrawFaded, bool Redraw=true) - - - - - - - SetValue(self, String Value, bool Redraw=true) - - - - - - - wx.TR_DONT_ADJUST_MAC = TR_DONT_ADJUST_MAC - - - - __init__(self, String text=EmptyString, int image=-1, size_t width=100, - bool shown=True, int alignment=TL_ALIGN_LEFT) -> TreeListColumnInfo - - - - - - - - - - GetShown(self) -> bool - - - GetAlignment(self) -> int - - - GetText(self) -> String - - - GetImage(self) -> int - - - GetSelectedImage(self) -> int - - - GetWidth(self) -> size_t - - - SetShown(self, bool shown) - - - - - - SetAlignment(self, int alignment) - - - - - - SetText(self, String text) - - - - - - SetImage(self, int image) - - - - - - SetSelectedImage(self, int image) - - - - - - SetWidth(self, size_t with) - - - - - - - - - __init__(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=TR_DEFAULT_STYLE, - Validator validator=DefaultValidator, - String name=TreeListCtrlNameStr) -> TreeListCtrl - - - - - - - - - - - - PreTreeListCtrl() -> TreeListCtrl - - - Create(self, Window parent, int id=-1, Point pos=DefaultPosition, - Size size=DefaultSize, long style=TR_DEFAULT_STYLE, - Validator validator=DefaultValidator, - String name=TreeListCtrlNameStr) -> bool - Do the 2nd phase and create the GUI control. - - - - - - - - - - - - _setCallbackInfo(self, PyObject self, PyObject _class) - - - - - - - GetCount(self) -> size_t - - - GetIndent(self) -> unsigned int - - - SetIndent(self, unsigned int indent) - - - - - - GetLineSpacing(self) -> unsigned int - - - SetLineSpacing(self, unsigned int spacing) - - - - - - GetImageList(self) -> ImageList - - - GetStateImageList(self) -> ImageList - - - GetButtonsImageList(self) -> ImageList - - - SetImageList(self, ImageList imageList) - - - - - - SetStateImageList(self, ImageList imageList) - - - - - - SetButtonsImageList(self, ImageList imageList) - - - - - - AssignImageList(self, ImageList imageList) - - - - - - AssignStateImageList(self, ImageList imageList) - - - - - - AssignButtonsImageList(self, ImageList imageList) - - - - - - AddColumn(self, String text) - - - - - - AddColumnInfo(self, TreeListColumnInfo col) - - - - - - InsertColumn(self, size_t before, String text) - - - - - - - InsertColumnInfo(self, size_t before, TreeListColumnInfo col) - - - - - - - RemoveColumn(self, size_t column) - - - - - - GetColumnCount(self) -> size_t - - - SetColumnWidth(self, size_t column, size_t width) - - - - - - - GetColumnWidth(self, size_t column) -> int - - - - - - SetMainColumn(self, size_t column) - - - - - - GetMainColumn(self) -> size_t - - - SetColumnText(self, size_t column, String text) - - - - - - - GetColumnText(self, size_t column) -> String - - - - - - SetColumn(self, size_t column, TreeListColumnInfo info) - - - - - - - GetColumn(self, size_t column) -> TreeListColumnInfo - - - - - - SetColumnAlignment(self, size_t column, int align) - - - - - - - GetColumnAlignment(self, size_t column) -> int - - - - - - SetColumnImage(self, size_t column, int image) - - - - - - - GetColumnImage(self, size_t column) -> int - - - - - - ShowColumn(self, size_t column, bool shown) - - - - - - - IsColumnShown(self, size_t column) -> bool - - - - - - GetItemText(self, TreeItemId item, int column=-1) -> String - - - - - - - GetItemImage(self, TreeItemId item, int column=-1, int which=TreeItemIcon_Normal) -> int - - - - - - - - SetItemText(self, TreeItemId item, String text, int column=-1) - - - - - - - - SetItemImage(self, TreeItemId item, int image, int column=-1, int which=TreeItemIcon_Normal) - - - - - - - - - GetItemData(self, TreeItemId item) -> TreeItemData - - - - - - SetItemData(self, TreeItemId item, TreeItemData data) - - - - - - - GetItemPyData(self, TreeItemId item) -> PyObject - - - - - - SetItemPyData(self, TreeItemId item, PyObject obj) - - - - - - - SetItemHasChildren(self, TreeItemId item, bool has=True) - - - - - - - SetItemBold(self, TreeItemId item, bool bold=True) - - - - - - - SetItemTextColour(self, TreeItemId item, Colour colour) - - - - - - - SetItemBackgroundColour(self, TreeItemId item, Colour colour) - - - - - - - SetItemFont(self, TreeItemId item, Font font) - - - - - - - GetItemBold(self, TreeItemId item) -> bool - - - - - - GetItemTextColour(self, TreeItemId item) -> Colour - - - - - - GetItemBackgroundColour(self, TreeItemId item) -> Colour - - - - - - GetItemFont(self, TreeItemId item) -> Font - - - - - - IsVisible(self, TreeItemId item) -> bool - - - - - - ItemHasChildren(self, TreeItemId item) -> bool - - - - - - IsExpanded(self, TreeItemId item) -> bool - - - - - - IsSelected(self, TreeItemId item) -> bool - - - - - - IsBold(self, TreeItemId item) -> bool - - - - - - GetChildrenCount(self, TreeItemId item, bool recursively=True) -> size_t - - - - - - - GetRootItem(self) -> TreeItemId - - - GetSelection(self) -> TreeItemId - - - GetSelections(self) -> PyObject - - - GetItemParent(self, TreeItemId item) -> TreeItemId - - - - - - GetFirstChild(self, TreeItemId item) -> PyObject - - - - - - GetNextChild(self, TreeItemId item, void cookie) -> PyObject - - - - - - - GetLastChild(self, TreeItemId item) -> TreeItemId - - - - - - GetNextSibling(self, TreeItemId item) -> TreeItemId - - - - - - GetPrevSibling(self, TreeItemId item) -> TreeItemId - - - - - - GetFirstVisibleItem(self) -> TreeItemId - - - GetNextVisible(self, TreeItemId item) -> TreeItemId - - - - - - GetPrevVisible(self, TreeItemId item) -> TreeItemId - - - - - - GetNext(self, TreeItemId item) -> TreeItemId - - - - - - AddRoot(self, String text, int image=-1, int selectedImage=-1, TreeItemData data=None) -> TreeItemId - - - - - - - - - PrependItem(self, TreeItemId parent, String text, int image=-1, int selectedImage=-1, - TreeItemData data=None) -> TreeItemId - - - - - - - - - - InsertItem(self, TreeItemId parent, TreeItemId idPrevious, String text, - int image=-1, int selectedImage=-1, TreeItemData data=None) -> TreeItemId - - - - - - - - - - - InsertItemBefore(self, TreeItemId parent, size_t index, String text, int image=-1, - int selectedImage=-1, TreeItemData data=None) -> TreeItemId - - - - - - - - - - - AppendItem(self, TreeItemId parent, String text, int image=-1, int selectedImage=-1, - TreeItemData data=None) -> TreeItemId - - - - - - - - - - Delete(self, TreeItemId item) - - - - - - DeleteChildren(self, TreeItemId item) - - - - - - DeleteAllItems(self) - - - Expand(self, TreeItemId item) - - - - - - ExpandAll(self, TreeItemId item) - - - - - - Collapse(self, TreeItemId item) - - - - - - CollapseAndReset(self, TreeItemId item) - - - - - - Toggle(self, TreeItemId item) - - - - - - Unselect(self) - - - UnselectAll(self) - - - SelectItem(self, TreeItemId item, bool unselect_others=True, bool extended_select=False) - - - - - - - - SelectAll(self, bool extended_select=False) - - - - - - EnsureVisible(self, TreeItemId item) - - - - - - ScrollTo(self, TreeItemId item) - - - - - - HitTest(self, Point point, int OUTPUT, int OUTPUT) -> TreeItemId - - - - - - - - GetBoundingRect(self, TreeItemId item, bool textOnly=False) -> PyObject - - - - - - - EditLabel(self, TreeItemId item) - - - - - - Edit(self, TreeItemId item) - - - - - - SortChildren(self, TreeItemId item) - - - - - - FindItem(self, TreeItemId item, String str, int flags=0) -> TreeItemId - - - - - - - - GetHeaderWindow(self) -> Window - - - GetMainWindow(self) -> ScrolledWindow - - - - diff --git a/wxPython/include/wx/wxPython/wxPython_int.h b/wxPython/include/wx/wxPython/wxPython_int.h index 44886701d5..199b5fa7ef 100644 --- a/wxPython/include/wx/wxPython/wxPython_int.h +++ b/wxPython/include/wx/wxPython/wxPython_int.h @@ -497,6 +497,39 @@ public: }; +//--------------------------------------------------------------------------- +// A wxImageHandler that can be derived from in Python. +// + +class wxPyImageHandler: public wxImageHandler { +protected: + PyObject *m_self; + + // used for interning method names as PyStrings + static PyObject* m_DoCanRead_Name; + static PyObject* m_GetImageCount_Name; + static PyObject* m_LoadFile_Name; + static PyObject* m_SaveFile_Name; + + // converstion helpers + PyObject* py_InputStream(wxInputStream* stream); + PyObject* py_Image(wxImage* image); + PyObject* py_OutputStream(wxOutputStream* stream); + +public: + wxPyImageHandler(); + ~wxPyImageHandler(); + void _SetSelf(PyObject *self); + + virtual bool LoadFile(wxImage* image, wxInputStream& stream, + bool verbose=true, int index=-1 ); + virtual bool SaveFile(wxImage* image, wxOutputStream& stream, + bool verbose=true ); + virtual int GetImageCount(wxInputStream& stream ); + virtual bool DoCanRead(wxInputStream &stream); +}; + + //--------------------------------------------------------------------------- // This class holds an instance of a Python Shadow Class object and assists // with looking up and invoking Python callback methods from C++ virtual diff --git a/wxPython/samples/ide/activegrid/tool/AboutDialog.py b/wxPython/samples/ide/activegrid/tool/AboutDialog.py index b43e5244ca..53a00402ca 100644 --- a/wxPython/samples/ide/activegrid/tool/AboutDialog.py +++ b/wxPython/samples/ide/activegrid/tool/AboutDialog.py @@ -11,37 +11,45 @@ #---------------------------------------------------------------------------- import wx -from IDE import ACTIVEGRID_BASE_IDE, getSplashBitmap +import os.path +from IDE import ACTIVEGRID_BASE_IDE, getSplashBitmap, getIDESplashBitmap +import activegrid.util.sysutils as sysutilslib _ = wx.GetTranslation #---------------------------------------------------------------------------- # Package License Data for AboutDialog # Package, License, URL # If no information is available, put a None as a place holder. +# +# NO GPL Allowed. Only LGPL, BSD, and Public Domain Based Licenses! #---------------------------------------------------------------------------- -licenseData = [ - ("ActiveGrid", "ASL 2.0", "http://apache.org/licenses/LICENSE-2.0"), - ("Python 2.3", "Python Software Foundation License", "http://www.python.org/2.3/license.html"), - ("wxPython 2.5", "wxWidgets 2 - LGPL", "http://wxwidgets.org/newlicen.htm"), - ("wxWidgets", "wxWindows Library License 3", "http://www.wxwidgets.org/manuals/2.5.4/wx_wxlicense.html"), +licenseData = [ # add licenses for base IDE features + ("ActiveGrid", "Apache License, Version 2.0", "http://apache.org/licenses/LICENSE-2.0"), + ("Python 2.4", "Python Software Foundation License", "http://www.python.org/2.4/license.html"), + ("wxPython 2.6", "wxWidgets 2 - LGPL", "http://wxwidgets.org/newlicen.htm"), + ("wxWidgets", "wxWindows Library License 3", "http://www.wxwidgets.org/manuals/2.6.1/wx_wxlicense.html"), ("pychecker", "MetaSlash - BSD", "http://pychecker.sourceforge.net/COPYRIGHT"), ("process.py", "See file", "http://starship.python.net/~tmick/"), - ("pysvn", "Apache License", "http://pysvn.tigris.org/"), + ("pysvn", "Apache License, Version 2.0", "http://pysvn.tigris.org/"), ] -if not ACTIVEGRID_BASE_IDE: # add licenses for database connections only if not the base IDE +if not ACTIVEGRID_BASE_IDE: # add licenses for non-base IDE features such as database connections licenseData += [ ("pydb2", "LGPL", "http://sourceforge.net/projects/pydb2"), ("pysqlite", "Python License (CNRI)", "http://sourceforge.net/projects/pysqlite"), ("mysql-python", "GPL, Python License (CNRI), Zope Public License", "http://sourceforge.net/projects/mysql-python"), - ("cx_Oracle", "Computronix", "http://http://www.computronix.com/download/License(cxOracle).txt"), + ("cx_Oracle", "Computronix", "http://www.computronix.com/download/License(cxOracle).txt"), ("SQLite", "Public Domain", "http://www.sqlite.org/copyright.html"), ("PyGreSQL", "BSD", "http://www.pygresql.org"), + ("pyXML", "CNRI Python License", "http://sourceforge.net/softwaremap/trove_list.php?form_cat=194"), + ("Zolera Soap Infrastructure", "Zope Public License 2.0", "http://www.zope.org/Resources/License/"), + ("Sarissa", "LGPL", "http://sourceforge.net/projects/sarissa/"), + ("Dynarch DHTML Calendar", "LGPL", "http://www.dynarch.com/projects/calendar/"), ] -if wx.Platform == '__WXMSW__': +if wx.Platform == '__WXMSW__': # add Windows only licenses licenseData += [("pywin32", "Python Software Foundation License", "http://sourceforge.net/projects/pywin32/")] class AboutDialog(wx.Dialog): @@ -56,10 +64,25 @@ class AboutDialog(wx.Dialog): aboutPage = wx.Panel(nb, -1) sizer = wx.BoxSizer(wx.VERTICAL) - splash_bmp = getSplashBitmap() + + if not ACTIVEGRID_BASE_IDE: + splash_bmp = getSplashBitmap() + else: + splash_bmp = getIDESplashBitmap() + + # find version number from + versionFilepath = os.path.join(sysutilslib.mainModuleDir, "version.txt") + if os.path.exists(versionFilepath): + versionfile = open(versionFilepath, 'r') + versionLines = versionfile.readlines() + versionfile.close() + version = "".join(versionLines) + else: + version = _("Version Unknown - %s not found" % versionFilepath) + image = wx.StaticBitmap(aboutPage, -1, splash_bmp, (0,0), (splash_bmp.GetWidth(), splash_bmp.GetHeight())) sizer.Add(image, 0, wx.ALIGN_CENTER|wx.ALL, 0) - sizer.Add(wx.StaticText(aboutPage, -1, wx.GetApp().GetAppName() + _("\nVersion 0.7 Early Access\n\nCopyright (c) 2003-2005 ActiveGrid Incorporated and Contributors. All rights reserved.")), 0, wx.ALIGN_LEFT|wx.ALL, 10) + sizer.Add(wx.StaticText(aboutPage, -1, wx.GetApp().GetAppName() + _("\n%s\n\nCopyright (c) 2003-2005 ActiveGrid Incorporated and Contributors. All rights reserved.") % version), 0, wx.ALIGN_LEFT|wx.ALL, 10) sizer.Add(wx.StaticText(aboutPage, -1, _("http://www.activegrid.com")), 0, wx.ALIGN_LEFT|wx.LEFT|wx.BOTTOM, 10) aboutPage.SetSizer(sizer) nb.AddPage(aboutPage, _("Copyright")) @@ -78,12 +101,16 @@ class AboutDialog(wx.Dialog): maxHeight = h grid.SetColLabelSize(maxHeight + 6) # add a 6 pixel margin + maxW = 0 for row, data in enumerate(licenseData): package = data[0] license = data[1] url = data[2] if package: grid.SetRowLabelValue(row, package) + w, h = dc.GetTextExtent(package) + if w > maxW: + maxW = w if license: grid.SetCellValue(row, 0, license) if url: @@ -95,8 +122,9 @@ class AboutDialog(wx.Dialog): grid.EnableDragRowSize(False) grid.SetRowLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE) grid.SetLabelBackgroundColour(wx.WHITE) - grid.AutoSizeColumn(0, 100) - grid.AutoSizeColumn(1, 100) + grid.AutoSizeColumn(0) + grid.AutoSizeColumn(1) + grid.SetRowLabelSize(maxW + 10) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(grid, 1, wx.EXPAND|wx.ALL, 10) licensePage.SetSizer(sizer) @@ -104,7 +132,7 @@ class AboutDialog(wx.Dialog): creditsPage = wx.Panel(nb, -1) sizer = wx.BoxSizer(wx.VERTICAL) - sizer.Add(wx.StaticText(creditsPage, -1, _("ActiveGrid Development Team:\n\nLawrence Bruhmuller\nEric Chu\nMatt Fryer\nJoel Hare\nMorgan Hua\nAlan Mullendore\nJeff Norton\nKevin Wang\nPeter Yared")), 0, wx.ALIGN_LEFT|wx.ALL, 10) + sizer.Add(wx.StaticText(creditsPage, -1, _("ActiveGrid Development Team:\n\nLarry Abrahams\nLawrence Bruhmuller\nEric Chu\nBeth Fryer\nMatt Fryer\nJoel Hare\nMorgan Hua\nMatt McNulty\nPratik Mehta\nAlan Mullendore\nJeff Norton\nSimon Toens\nKevin Wang\nPeter Yared")), 0, wx.ALIGN_LEFT|wx.ALL, 10) creditsPage.SetSizer(sizer) nb.AddPage(creditsPage, _("Credits")) @@ -114,7 +142,8 @@ class AboutDialog(wx.Dialog): sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) self.SetSizer(sizer) - self.SetAutoLayout(True) - sizer.Fit(self) + self.Layout() + self.Fit() + grid.ForceRefresh() # wxBug: Get rid of unnecessary scrollbars diff --git a/wxPython/samples/ide/activegrid/tool/AbstractEditor.py b/wxPython/samples/ide/activegrid/tool/AbstractEditor.py index f8e9d16e4e..f795ecd6f8 100644 --- a/wxPython/samples/ide/activegrid/tool/AbstractEditor.py +++ b/wxPython/samples/ide/activegrid/tool/AbstractEditor.py @@ -23,6 +23,19 @@ SHAPE_BRUSH = wx.Brush("WHEAT", wx.SOLID) LINE_BRUSH = wx.BLACK_BRUSH INACTIVE_SELECT_BRUSH = wx.Brush("LIGHT BLUE", wx.SOLID) +NORMALFONT = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) +SLANTFONT = wx.Font(NORMALFONT.GetPointSize(), NORMALFONT.GetFamily(), wx.SLANT, NORMALFONT.GetWeight()) +BOLDFONT = wx.Font(NORMALFONT.GetPointSize(), NORMALFONT.GetFamily(), NORMALFONT.GetStyle(), wx.BOLD) + +DEFAULT_BACKGROUND_COLOR = wx.Colour(0xEE, 0xEE, 0xEE) +HEADER_BRUSH = wx.Brush(wx.Colour(0xDB, 0xEB, 0xFF), wx.SOLID) +BODY_BRUSH = wx.Brush(wx.WHITE, wx.SOLID) + + +PARKING_VERTICAL = 1 +PARKING_HORIZONTAL = 2 +PARKING_OFFSET = 30 # space between shapes + def GetRawModel(model): if hasattr(model, "GetRawModel"): @@ -32,6 +45,27 @@ def GetRawModel(model): return rawModel +def GetLabel(model): + model = GetRawModel(model) + if hasattr(model, "__xmlname__"): + label = model.__xmlname__ + try: + if (len(label) > 0): + label = label[0].upper() + label[1:] + if (hasattr(model, "complexType")): + label += ': %s/%s' % (model.complexType.name, model.name) + else: + if model.name: + label += ': %s' % model.name + elif model.ref: + label += ': %s' % model.ref + except AttributeError: + pass + else: + label = str(model) + return label + + class CanvasView(wx.lib.docview.View): @@ -40,9 +74,10 @@ class CanvasView(wx.lib.docview.View): #---------------------------------------------------------------------------- - def __init__(self, brush = SHAPE_BRUSH): + def __init__(self, brush=SHAPE_BRUSH, background=DEFAULT_BACKGROUND_COLOR): wx.lib.docview.View.__init__(self) self._brush = brush + self._backgroundColor = background self._canvas = None self._pt1 = None self._pt2 = None @@ -68,6 +103,7 @@ class CanvasView(wx.lib.docview.View): frame.SetSizer(sizer) frame.Layout() self.Activate() + wx.EVT_RIGHT_DOWN(self._canvas, self.OnRightClick) return True @@ -145,12 +181,20 @@ class CanvasView(wx.lib.docview.View): self._canvas.SetScrollbars(20, 20, self._maxWidth / 20, self._maxHeight / 20) - self._canvas.SetBackgroundColour(wx.WHITE) + self._canvas.SetBackgroundColour(self._backgroundColor) self._diagram = ogl.Diagram() self._canvas.SetDiagram(self._diagram) self._diagram.SetCanvas(self._canvas) + self._canvas.SetFont(NORMALFONT) + def OnClear(self, event): + """ Deletion of selected objects from view. + *Must Override* + """ + self.SetPropertyModel(None) + + def OnKeyPressed(self, event): key = event.KeyCode() if key == wx.WXK_DELETE: @@ -159,7 +203,42 @@ class CanvasView(wx.lib.docview.View): event.Skip() + def OnRightClick(self, event): + """ force selection underneath right click position. """ + self.Activate() + self._canvas.SetFocus() + + dc = wx.ClientDC(self._canvas) + self._canvas.PrepareDC(dc) + x, y = event.GetLogicalPosition(dc) # this takes into account scrollbar offset + shape = self._canvas.FindShape(x, y)[0] + + model = None + if not shape: + self.SetSelection(None) + self.SetPropertyShape(None) + elif hasattr(shape, "GetModel"): + self.BringToFront(shape) + self.SetPropertyShape(shape) + self.SetSelection(shape) + shape.Select(True, dc) + model = shape.GetModel() + elif shape.GetParent() and isinstance(shape.GetParent(), ogl.CompositeShape): # ComplexTypeHeader for ComplexTypeShape + self.BringToFront(shape) + self.SetPropertyShape(shape.GetParent()) + self.SetSelection(shape.GetParent()) + shape.GetParent().Select(True, dc) + model = shape.GetParent().GetModel() + + self.SetPropertyModel(model) + + return (shape, model) + + def OnLeftClick(self, event): + self.Activate() + self._canvas.SetFocus() + self.EraseRubberBand() dc = wx.ClientDC(self._canvas) @@ -322,21 +401,24 @@ class CanvasView(wx.lib.docview.View): dc.EndDrawing() - def FindParkingSpot(self, width, height): + def FindParkingSpot(self, width, height, parking=PARKING_HORIZONTAL, x=PARKING_OFFSET, y=PARKING_OFFSET): """ given a width and height, find a upper left corner where shape can be parked without overlapping other shape """ - offset = 30 # space between shapes - x = offset - y = offset - maxX = 700 # max distance to the right where we'll place tables + max = 700 # max distance to the right where we'll place tables noParkingSpot = True while noParkingSpot: point = self.isSpotOccupied(x, y, width, height) if point: - x = point[0] + offset - if x > maxX: - x = offset - y = point[1] + offset + if parking == PARKING_HORIZONTAL: + x = point[0] + PARKING_OFFSET + if x > max: + x = PARKING_OFFSET + y = point[1] + PARKING_OFFSET + else: # parking == PARKING_VERTICAL: + y = point[1] + PARKING_OFFSET + if y > max: + y = PARKING_OFFSET + x = point[0] + PARKING_OFFSET else: noParkingSpot = False @@ -351,7 +433,7 @@ class CanvasView(wx.lib.docview.View): y2 = y + height for shape in self._diagram.GetShapeList(): - if isinstance(shape, ogl.RectangleShape) or isinstance(shape, ogl.EllipseShape): + if isinstance(shape, ogl.RectangleShape) or isinstance(shape, ogl.EllipseShape) or isinstance(shape, ogl.PolygonShape): if shape.GetParent() and isinstance(shape.GetParent(), ogl.CompositeShape): # skip, part of a composite shape continue @@ -381,7 +463,7 @@ class CanvasView(wx.lib.docview.View): # Canvas methods #---------------------------------------------------------------------------- - def AddShape(self, shape, x = None, y = None, pen = None, brush = None, text = None, eventHandler = None): + def AddShape(self, shape, x = None, y = None, pen = None, brush = None, text = None, eventHandler = None, shown=True): if isinstance(shape, ogl.CompositeShape): dc = wx.ClientDC(self._canvas) self._canvas.PrepareDC(dc) @@ -403,7 +485,7 @@ class CanvasView(wx.lib.docview.View): shape.AddText(text) shape.SetShadowMode(ogl.SHADOW_NONE) self._diagram.AddShape(shape) - shape.Show(True) + shape.Show(shown) if not eventHandler: eventHandler = EditorCanvasShapeEvtHandler(self) eventHandler.SetShape(shape) @@ -424,16 +506,21 @@ class CanvasView(wx.lib.docview.View): for line in shape.GetLines(): shape.RemoveLine(line) self._diagram.RemoveShape(line) + line.Delete() for obj in self._diagram.GetShapeList(): for line in obj.GetLines(): if self.IsShapeContained(shape, line.GetTo()) or self.IsShapeContained(shape, line.GetFrom()): obj.RemoveLine(line) self._diagram.RemoveShape(line) + line.Delete() if line == shape: obj.RemoveLine(line) + self._diagram.RemoveShape(line) + line.Delete() shape.RemoveFromCanvas(self._canvas) self._diagram.RemoveShape(shape) + shape.Delete() def IsShapeContained(self, parent, shape): @@ -448,29 +535,22 @@ class CanvasView(wx.lib.docview.View): def UpdateShape(self, model): for shape in self._diagram.GetShapeList(): if hasattr(shape, "GetModel") and shape.GetModel() == model: + oldw, oldh = shape.GetBoundingBoxMax() + oldx = shape.GetX() + oldy = shape.GetY() + x, y, w, h = model.getEditorBounds() newX = x + w / 2 newY = y + h / 2 - changed = False - if isinstance(shape, ogl.CompositeShape): - if shape.GetX() != newX or shape.GetY() != newY: - dc = wx.ClientDC(self._canvas) - self._canvas.PrepareDC(dc) - shape.SetSize(w, h, True) # wxBug: SetSize must be before Move because links won't go to the right place - shape.Move(dc, newX, newY) # wxBug: Move must be before SetSize because links won't go to the right place - changed = True - else: - oldw, oldh = shape.GetBoundingBoxMax() - oldx = shape.GetX() - oldy = shape.GetY() - if oldw != w or oldh != h or oldx != newX or oldy != newY: - shape.SetSize(w, h) - shape.SetX(newX) - shape.SetY(newY) - changed = True - if changed: + + if oldw != w or oldh != h or oldx != newX or oldy != newY: + dc = wx.ClientDC(self._canvas) + self._canvas.PrepareDC(dc) + shape.SetSize(w, h, True) # wxBug: SetSize must be before Move because links won't go to the right place + shape.Move(dc, newX, newY) # wxBug: Move must be after SetSize because links won't go to the right place shape.ResetControlPoints() self._canvas.Refresh() + break @@ -481,6 +561,10 @@ class CanvasView(wx.lib.docview.View): return None + def GetShapeCount(self): + return self._diagram.GetCount() + + def GetSelection(self): return filter(lambda shape: shape.Selected(), self._diagram.GetShapeList()) @@ -526,7 +610,10 @@ class CanvasView(wx.lib.docview.View): def ScrollVisible(self, shape): - xUnit, yUnit = shape._canvas.GetScrollPixelsPerUnit() + if not shape: + return + + xUnit, yUnit = self._canvas.GetScrollPixelsPerUnit() scrollX, scrollY = self._canvas.GetViewStart() # in scroll units scrollW, scrollH = self._canvas.GetSize() # in pixels w, h = shape.GetBoundingBoxMax() # in pixels @@ -564,7 +651,10 @@ class CanvasView(wx.lib.docview.View): # erase old selection if it still exists if self._propShape and self._propShape in self._diagram.GetShapeList(): - self._propShape.SetBrush(self._brush) + if hasattr(self._propShape, "DEFAULT_BRUSH"): + self._propShape.SetBrush(self._propShape.DEFAULT_BRUSH) + else: + self._propShape.SetBrush(self._brush) if (self._propShape._textColourName in ["BLACK", "WHITE"]): # Would use GetTextColour() but it is broken self._propShape.SetTextColour("BLACK", 0) self._propShape.Draw(dc) @@ -667,9 +757,10 @@ class EditorCanvasShapeEvtHandler(ogl.ShapeEvtHandler): if shape: model = shape.GetModel() - self._view.SetSelection(model, keys == self.SHIFT_KEY or keys == self.CONTROL_KEY) - self._view.SetPropertyShape(shape) - self._view.SetPropertyModel(model) + if model: + self._view.SetSelection(model, keys == self.SHIFT_KEY or keys == self.CONTROL_KEY) + self._view.SetPropertyShape(shape) + self._view.SetPropertyModel(model) def OnEndDragLeft(self, x, y, keys = 0, attachment = 0): @@ -686,7 +777,7 @@ class EditorCanvasShapeEvtHandler(ogl.ShapeEvtHandler): def OnMovePre(self, dc, x, y, oldX, oldY, display): """ Prevent objects from being dragged outside of viewable area """ - if (x > self._view._maxWidth) or (y > self._view._maxHeight): + if (x < 0) or (y < 0) or (x > self._view._maxWidth) or (y > self._view._maxHeight): return False return ogl.ShapeEvtHandler.OnMovePre(self, dc, x, y, oldX, oldY, display) diff --git a/wxPython/samples/ide/activegrid/tool/CodeEditor.py b/wxPython/samples/ide/activegrid/tool/CodeEditor.py index de0fbaf86e..7e245bcd1f 100644 --- a/wxPython/samples/ide/activegrid/tool/CodeEditor.py +++ b/wxPython/samples/ide/activegrid/tool/CodeEditor.py @@ -21,6 +21,7 @@ import string import sys import DebuggerService import MarkerService +from UICommon import CaseInsensitiveCompare _ = wx.GetTranslation if wx.Platform == '__WXMSW__': _WINDOWS = True @@ -354,18 +355,6 @@ class CodeView(STCTextEditor.TextView): return ['Put', 'Editor Specific', 'Keywords', 'Here'] - def CaseInsensitiveCompare(self, s1, s2): - """ GetAutoCompleteKeywordList() method used to show keywords in case insensitive order """ - s1L = s1.lower() - s2L = s2.lower() - if s1L == s2L: - return 0 - elif s1L < s2L: - return -1 - else: - return 1 - - def GetAutoCompleteKeywordList(self, context, hint): """ Replace this method with Editor specific keywords """ kw = self.GetAutoCompleteDefaultKeywords() @@ -380,7 +369,7 @@ class CodeView(STCTextEditor.TextView): else: replaceLen = 0 - kw.sort(self.CaseInsensitiveCompare) + kw.sort(CaseInsensitiveCompare) return " ".join(kw), replaceLen @@ -410,6 +399,7 @@ class CodeView(STCTextEditor.TextView): def OnSetIndentWidth(self): dialog = wx.TextEntryDialog(self._GetParentFrame(), _("Enter new indent width (2-10):"), _("Set Indent Width"), "%i" % self.GetCtrl().GetIndent()) + dialog.CenterOnParent() if dialog.ShowModal() == wx.ID_OK: try: indent = int(dialog.GetValue()) @@ -480,7 +470,7 @@ class CodeView(STCTextEditor.TextView): if hint == "ViewStuff": self.GetCtrl().SetViewDefaults() elif hint == "Font": - font, color = self.GetFontAndColorFromConfig() + font, color = self.GetCtrl().GetFontAndColorFromConfig() self.GetCtrl().SetFont(font) self.GetCtrl().SetFontColor(color) else: diff --git a/wxPython/samples/ide/activegrid/tool/DebuggerService.py b/wxPython/samples/ide/activegrid/tool/DebuggerService.py index 547d8c9912..485853611b 100644 --- a/wxPython/samples/ide/activegrid/tool/DebuggerService.py +++ b/wxPython/samples/ide/activegrid/tool/DebuggerService.py @@ -310,6 +310,13 @@ class RunCommandUI(wx.Panel): self._textCtrl.SetFontColor(wx.BLACK) self._textCtrl.StyleClearAll() self._textCtrl.SetReadOnly(True) + + def StopAndRemoveUI(self, event): + self.StopExecution() + self.StopExecution() + index = self._noteBook.GetSelection() + self._noteBook.GetPage(index).Show(False) + self._noteBook.RemovePage(index) #------------------------------------------------------------------------------ # Event handling @@ -322,10 +329,7 @@ class RunCommandUI(wx.Panel): self.StopExecution() elif id == self.CLOSE_TAB_ID: - self.StopExecution() - index = self._noteBook.GetSelection() - self._noteBook.GetPage(index).Show(False) - self._noteBook.RemovePage(index) + self.StopAndRemoveUI(event) def OnDoubleClick(self, event): # Looking for a stack trace line. @@ -368,7 +372,7 @@ class RunCommandUI(wx.Panel): # FACTOR THIS INTO DocManager openDocs = wx.GetApp().GetDocumentManager().GetDocuments() for openDoc in openDocs: - if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): + if(isinstance(openDoc, CodeEditor.CodeDocument)): openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() foundView.GetCtrl().MarkerAdd(lineNum -1, CodeEditor.CodeCtrl.CURRENT_LINE_MARKER_NUM) @@ -419,8 +423,9 @@ class DebugCommandUI(wx.Panel): def ReturnPortToPool(port): config = wx.ConfigBase_Get() startingPort = config.ReadInt("DebuggerStartingPort", DEFAULT_PORT) - if port in range(startingPort, startingPort + PORT_COUNT): - DebugCommandUI.debuggerPortList.append(port) + val = int(startingPort) + int(PORT_COUNT) + if int(port) >= startingPort and (int(port) <= val): + DebugCommandUI.debuggerPortList.append(int(port)) ReturnPortToPool = staticmethod(ReturnPortToPool) @@ -588,7 +593,7 @@ class DebugCommandUI(wx.Panel): self._tb.EnableTool(self.ADD_WATCH_ID, False) openDocs = wx.GetApp().GetDocumentManager().GetDocuments() for openDoc in openDocs: - if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): + if(isinstance(openDoc, CodeEditor.CodeDocument)): openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() if self.framesTab: self.framesTab.ClearWhileRunning() @@ -662,7 +667,7 @@ class DebugCommandUI(wx.Panel): def DeleteCurrentLineMarkers(self): openDocs = wx.GetApp().GetDocumentManager().GetDocuments() for openDoc in openDocs: - if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): + if(isinstance(openDoc, CodeEditor.CodeDocument)): openDoc.GetFirstView().GetCtrl().ClearCurrentLineMarkers() def LoadFramesListXML(self, framesXML): @@ -848,7 +853,7 @@ class WatchDialog(wx.Dialog): self.label_4 = wx.StaticText(self, -1, ",frame.f_globals, frame.f_locals)") self.radio_box_1 = wx.RadioBox(self, -1, "Watch Information", choices=[WatchDialog.WATCH_ALL_FRAMES, WatchDialog.WATCH_THIS_FRAME, WatchDialog.WATCH_ONCE], majorDimension=0, style=wx.RA_SPECIFY_ROWS) - self._okButton = wx.Button(self, wx.ID_OK, "OK", size=(75,-1)) + self._okButton = wx.Button(self, wx.ID_OK, "OK") self._okButton.SetDefault() self._okButton.SetHelpText(_("The OK button completes the dialog")) def OnOkClick(event): @@ -861,7 +866,7 @@ class WatchDialog(wx.Dialog): self.EndModal(wx.ID_OK) self.Bind(wx.EVT_BUTTON, OnOkClick, self._okButton) - self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel"), size=(75,-1)) + self._cancelButton = wx.Button(self, wx.ID_CANCEL, _("Cancel")) self._cancelButton.SetHelpText(_("The Cancel button cancels the dialog.")) self.__set_properties() @@ -900,7 +905,6 @@ class WatchDialog(wx.Dialog): box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5) box.Add(self._cancelButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5) sizer_1.Add(box, 1, wx.EXPAND, 0) - self.SetAutoLayout(True) self.SetSizer(sizer_1) self.Layout() @@ -979,30 +983,31 @@ class FramesUI(wx.SplitterWindow): #sizer.Fit(panel) return panel + + def ReplaceLastLine(self, command): + line = self._interCtrl.GetLineCount() - 1 + self._interCtrl.GotoLine(line) + start = self._interCtrl.GetCurrentPos() + self._interCtrl.SetTargetStart(start) + end = self._interCtrl.GetLineEndPosition(line) + self._interCtrl.SetTargetEnd(end) + self._interCtrl.ReplaceTarget(">>> " + command) + self._interCtrl.GotoLine(line) + self._interCtrl.SetSelectionStart(self._interCtrl.GetLineEndPosition(line)) + + def ExecuteCommand(self, command): + if not len(self.command_list) or not command == self.command_list[len(self.command_list) -1]: + self.command_list.append(command) + self.command_index = len(self.command_list) - 1 + retval = self._ui._callback._debuggerServer.execute_in_frame(self._framesChoiceCtrl.GetStringSelection(), command) + self._interCtrl.AddText("\n" + str(retval)) + self._interCtrl.ScrollToLine(self._interCtrl.GetLineCount()) + # Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items. + self.PopulateTreeFromFrameMessage(self._framesChoiceCtrl.GetStringSelection()) def MakeInspectConsoleTab(self, parent, id): self.command_list = [] self.command_index = 0 - def ExecuteCommand(command): - if not len(self.command_list) or not command == self.command_list[len(self.command_list) -1]: - self.command_list.append(command) - self.command_index = len(self.command_list) - 1 - retval = self._ui._callback._debuggerServer.execute_in_frame(self._framesChoiceCtrl.GetStringSelection(), command) - self._interCtrl.AddText("\n" + str(retval)) - self._interCtrl.ScrollToLine(self._interCtrl.GetLineCount()) - # Refresh the tree view in case this command resulted in changes there. TODO: Need to reopen tree items. - self.PopulateTreeFromFrameMessage(self._framesChoiceCtrl.GetStringSelection()) - - def ReplaceLastLine(command): - line = self._interCtrl.GetLineCount() - 1 - self._interCtrl.GotoLine(line) - start = self._interCtrl.GetCurrentPos() - self._interCtrl.SetTargetStart(start) - end = self._interCtrl.GetLineEndPosition(line) - self._interCtrl.SetTargetEnd(end) - self._interCtrl.ReplaceTarget(">>> " + command) - self._interCtrl.GotoLine(line) - self._interCtrl.SetSelectionStart(self._interCtrl.GetLineEndPosition(line)) def OnKeyPressed(event): key = event.KeyCode() @@ -1011,13 +1016,13 @@ class FramesUI(wx.SplitterWindow): return elif key == wx.WXK_RETURN: command = self._interCtrl.GetLine(self._interCtrl.GetCurrentLine())[4:] - ExecuteCommand(command) + self.ExecuteCommand(command) self._interCtrl.AddText("\n>>> ") return elif key == wx.WXK_UP: if not len(self.command_list): return - ReplaceLastLine(self.command_list[self.command_index]) + self.ReplaceLastLine(self.command_list[self.command_index]) if self.command_index == 0: self.command_index = len(self.command_list) - 1 else: @@ -1030,7 +1035,7 @@ class FramesUI(wx.SplitterWindow): self.command_index = self.command_index + 1 else: self.command_index = 0 - ReplaceLastLine(self.command_list[self.command_index]) + self.ReplaceLastLine(self.command_list[self.command_index]) return event.Skip() @@ -1081,6 +1086,12 @@ class FramesUI(wx.SplitterWindow): self.Bind(wx.EVT_MENU, self.OnView, id=self.viewID) item = wx.MenuItem(menu, self.viewID, "View in Dialog") menu.AppendItem(item) + if not hasattr(self, "toInteractID"): + self.toInteractID = wx.NewId() + self.Bind(wx.EVT_MENU, self.OnSendToInteract, id=self.toInteractID) + item = wx.MenuItem(menu, self.toInteractID, "Send to Interact") + menu.AppendItem(item) + offset = wx.Point(x=0, y=20) menuSpot = event.GetPoint() + offset self._treeCtrl.PopupMenu(menu, menuSpot) @@ -1105,13 +1116,33 @@ class FramesUI(wx.SplitterWindow): value = self._treeCtrl.GetItemText(self._introspectItem,1) dlg = wx.lib.dialogs.ScrolledMessageDialog(self, value, title, style=wx.DD_DEFAULT_STYLE | wx.RESIZE_BORDER) dlg.Show() - + + def OnSendToInteract(self, event): + value = "" + prevItem = "" + for item in self._parentChain: + + if item.find(prevItem + '[') != -1: + value += item[item.find('['):] + continue + if value != "": + value = value + '.' + if item == 'globals': + item = 'globals()' + if item != 'locals': + value += item + prevItem = item + print value + self.ReplaceLastLine(value) + self.ExecuteCommand(value) + def OnWatch(self, event): try: if hasattr(self, '_parentChain'): wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", self._parentChain) else: wd = WatchDialog(wx.GetApp().GetTopWindow(), "Add a Watch", None) + wd.CenterOnParent() if wd.ShowModal() == wx.ID_OK: name, text, send_frame, run_once = wd.GetSettings() if send_frame: @@ -1125,6 +1156,7 @@ class FramesUI(wx.SplitterWindow): nodeList = domDoc.getElementsByTagName('watch') if len(nodeList) == 1: watchValue = nodeList.item(0).getAttribute("message") + wd.Destroy() except: tp, val, tb = sys.exc_info() traceback.print_exception(tp, val, tb) @@ -1147,6 +1179,8 @@ class FramesUI(wx.SplitterWindow): tree = self._treeCtrl parent = tree.GetItemParent(self._introspectItem) treeNode = self.AppendSubTreeFromNode(thingToWalk, thingToWalk.getAttribute('name'), parent, insertBefore=self._introspectItem) + if thingToWalk.getAttribute('name').find('[') == -1: + self._treeCtrl.SortChildren(treeNode) self._treeCtrl.Expand(treeNode) tree.Delete(self._introspectItem) except: @@ -1297,7 +1331,8 @@ class FramesUI(wx.SplitterWindow): if intro == "True": tree.SetItemHasChildren(n, True) tree.SetPyData(n, "Introspect") - + if name.find('[') == -1: + self._treeCtrl.SortChildren(treeNode) return treeNode def StripOuterSingleQuotes(self, string): @@ -1613,7 +1648,7 @@ class DebuggerService(Service.Service): RUN_ID = wx.NewId() DEBUG_ID = wx.NewId() DEBUG_WEBSERVER_ID = wx.NewId() - + RUN_WEBSERVER_ID = wx.NewId() def ComparePaths(first, second): one = DebuggerService.ExpandPath(first) @@ -1695,6 +1730,9 @@ class DebuggerService(Service.Service): debuggerMenu.Append(DebuggerService.DEBUG_WEBSERVER_ID, _("Debug Internal Web Server"), _("Debugs the internal webservier")) wx.EVT_MENU(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessEvent) wx.EVT_UPDATE_UI(frame, DebuggerService.DEBUG_WEBSERVER_ID, frame.ProcessUpdateUIEvent) + debuggerMenu.Append(DebuggerService.RUN_WEBSERVER_ID, _("Restart Internal Web Server"), _("Restarts the internal webservier")) + wx.EVT_MENU(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessEvent) + wx.EVT_UPDATE_UI(frame, DebuggerService.RUN_WEBSERVER_ID, frame.ProcessUpdateUIEvent) debuggerMenu.AppendSeparator() @@ -1709,6 +1747,11 @@ class DebuggerService(Service.Service): viewMenuIndex = menuBar.FindMenu(_("&Project")) menuBar.Insert(viewMenuIndex + 1, debuggerMenu, _("&Run")) + + toolBar.AddSeparator() + toolBar.AddTool(DebuggerService.RUN_ID, getRunningManBitmap(), shortHelpString = _("Run"), longHelpString = _("Run")) + toolBar.AddTool(DebuggerService.DEBUG_ID, getDebuggingManBitmap(), shortHelpString = _("Debug"), longHelpString = _("Debug")) + toolBar.Realize() return True @@ -1742,6 +1785,9 @@ class DebuggerService(Service.Service): elif an_id == DebuggerService.DEBUG_WEBSERVER_ID: self.OnDebugWebServer(event) return True + elif an_id == DebuggerService.RUN_WEBSERVER_ID: + self.OnRunWebServer(event) + return True return False def ProcessUpdateUIEvent(self, event): @@ -1778,13 +1824,13 @@ class DebuggerService(Service.Service): return self.ShowWindow(True) projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) - project = projectService.GetView().GetDocument() try: dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Debug Python File', projectService, None, pythonOnly=True, okButtonName="Debug", debugging=True) except: return + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: - fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings() + projectPath, fileToDebug, initialArgs, startIn, isPython, environment = dlg.GetSettings() dlg.Destroy() else: dlg.Destroy() @@ -1822,7 +1868,13 @@ class DebuggerService(Service.Service): page.Execute(args, startIn=os.getcwd(), environment=os.environ) except: pass - + + def OnRunWebServer(self, event): + if not Executor.GetPythonExecutablePath(): + return + import WebServerService + wsService = wx.GetApp().GetService(WebServerService.WebServerService) + wsService.ShutDownAndRestart() def HasAnyFiles(self): docs = wx.GetApp().GetDocumentManager().GetDocuments() @@ -1849,10 +1901,12 @@ class DebuggerService(Service.Service): _("Debug"), wx.YES_NO|wx.ICON_QUESTION ) + yesNoMsg.CenterOnParent() if yesNoMsg.ShowModal() == wx.ID_YES: docs = wx.GetApp().GetDocumentManager().GetDocuments() for doc in docs: doc.Save() + yesNoMsg.Destroy() def OnExit(self): DebugCommandUI.ShutdownAllDebuggers() @@ -1865,15 +1919,13 @@ class DebuggerService(Service.Service): if not Executor.GetPythonExecutablePath(): return projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) - project = projectService.GetView().GetDocument() try: dlg = CommandPropertiesDialog(self.GetView().GetFrame(), 'Run', projectService, None) except: return + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: - fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings() - - + projectPath, fileToRun, initialArgs, startIn, isPython, environment = dlg.GetSettings() dlg.Destroy() else: dlg.Destroy() @@ -1881,7 +1933,12 @@ class DebuggerService(Service.Service): self.PromptToSaveFiles() # This will need to change when we can run more than .py and .bpel files. if not isPython: - projectService.RunProcessModel(fileToRun) + projects = projectService.FindProjectByFile(projectPath) + if not projects: + return + project = projects[0] + deployFilePath = project.GenerateDeployment() + projectService.RunProcessModel(fileToRun, project.GetAppInfo().language, deployFilePath) return self.ShowWindow(True) @@ -1901,10 +1958,16 @@ class DebuggerService(Service.Service): fileName = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename() if line < 0: line = view.GetCtrl().GetCurrentLine() + else: + view = None if self.BreakpointSet(fileName, line + 1): self.ClearBreak(fileName, line + 1) + if view: + view.GetCtrl().Refresh() else: self.SetBreak(fileName, line + 1) + if view: + view.GetCtrl().Refresh() # Now refresh all the markers icons in all the open views. self.ClearAllBreakpointMarkers() self.SetAllBreakpointMarkers() @@ -1939,6 +2002,10 @@ class DebuggerService(Service.Service): else: return self._masterBPDict[expandedName] + def SetBreakpointList(self, fileName, bplist): + expandedName = DebuggerService.ExpandPath(fileName) + self._masterBPDict[expandedName] = bplist + def BreakpointSet(self, fileName, line): expandedName = DebuggerService.ExpandPath(fileName) if not self._masterBPDict.has_key(expandedName): @@ -1977,16 +2044,20 @@ class DebuggerService(Service.Service): def ClearAllBreakpointMarkers(self): openDocs = wx.GetApp().GetDocumentManager().GetDocuments() for openDoc in openDocs: - if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): + if isinstance(openDoc, CodeEditor.CodeDocument): openDoc.GetFirstView().MarkerDeleteAll(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM) - + + def UpdateBreakpointsFromMarkers(self, view, fileName): + newbpLines = view.GetMarkerLines(CodeEditor.CodeCtrl.BREAKPOINT_MARKER_NUM) + self.SetBreakpointList(fileName, newbpLines) + def GetMasterBreakpointDict(self): return self._masterBPDict def SetAllBreakpointMarkers(self): openDocs = wx.GetApp().GetDocumentManager().GetDocuments() for openDoc in openDocs: - if(isinstance(openDoc.GetFirstView(), CodeEditor.CodeView)): + if(isinstance(openDoc, CodeEditor.CodeDocument)): self.SetCurrentBreakpointMarkers(openDoc.GetFirstView()) def SetCurrentBreakpointMarkers(self, view): @@ -2052,6 +2123,11 @@ class DebuggerOptionsPanel(wx.Panel): config.Write("DebuggerHostName", self._LocalHostTextCtrl.GetValue()) if self._PortNumberTextCtrl.IsInBounds(): config.WriteInt("DebuggerStartingPort", self._PortNumberTextCtrl.GetValue()) + + + def GetIcon(self): + return getContinueIcon() + class CommandPropertiesDialog(wx.Dialog): @@ -2070,10 +2146,8 @@ class CommandPropertiesDialog(wx.Dialog): if not self._projectNameList: wx.MessageBox(_("To run or debug you must have an open runnable file or project containing runnable files. Use File->Open to open the file you wish to run or debug."), _("Nothing to Run")) raise BadBadBad - if _WINDOWS: - wx.Dialog.__init__(self, parent, -1, title) - else: - wx.Dialog.__init__(self, parent, -1, title, size=(390,270)) + + wx.Dialog.__init__(self, parent, -1, title) projStaticText = wx.StaticText(self, -1, _("Project:")) fileStaticText = wx.StaticText(self, -1, _("File:")) @@ -2082,43 +2156,43 @@ class CommandPropertiesDialog(wx.Dialog): pythonPathStaticText = wx.StaticText(self, -1, _("PYTHONPATH:")) postpendStaticText = _("Postpend win32api path") cpPanelBorderSizer = wx.BoxSizer(wx.VERTICAL) - self._projList = wx.Choice(self, -1, (200,-1), choices=self._projectNameList) + self._projList = wx.Choice(self, -1, choices=self._projectNameList) self.Bind(wx.EVT_CHOICE, self.EvtListBox, self._projList) HALF_SPACE = 5 - flexGridSizer = wx.FlexGridSizer(cols = 3, vgap = 10, hgap = 10) + GAP = HALF_SPACE + if wx.Platform == "__WXMAC__": + GAP = 10 + flexGridSizer = wx.GridBagSizer(GAP, GAP) - flexGridSizer.Add(projStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) - flexGridSizer.Add(self._projList, 1, flag=wx.EXPAND) - flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) + flexGridSizer.Add(projStaticText, (0,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + flexGridSizer.Add(self._projList, (0,1), (1,2), flag=wx.EXPAND) - flexGridSizer.Add(fileStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) - self._fileList = wx.Choice(self, -1, (200,-1)) + flexGridSizer.Add(fileStaticText, (1,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + self._fileList = wx.Choice(self, -1) self.Bind(wx.EVT_CHOICE, self.OnFileSelected, self._fileList) - flexGridSizer.Add(self._fileList, 1, flag=wx.EXPAND) - flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) + flexGridSizer.Add(self._fileList, (1,1), (1,2), flag=wx.EXPAND) config = wx.ConfigBase_Get() self._lastArguments = config.Read("LastRunArguments") self._argsEntry = wx.TextCtrl(self, -1, str(self._lastArguments)) self._argsEntry.SetToolTipString(str(self._lastArguments)) - flexGridSizer.Add(argsStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) - flexGridSizer.Add(self._argsEntry, 1, flag=wx.EXPAND) - flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) + flexGridSizer.Add(argsStaticText, (2,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + flexGridSizer.Add(self._argsEntry, (2,1), (1,2), flag=wx.EXPAND) - flexGridSizer.Add(startInStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + flexGridSizer.Add(startInStaticText, (3,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) self._lastStartIn = config.Read("LastRunStartIn") if not self._lastStartIn: self._lastStartIn = str(os.getcwd()) self._startEntry = wx.TextCtrl(self, -1, self._lastStartIn) self._startEntry.SetToolTipString(self._lastStartIn) - flexGridSizer.Add(self._startEntry, 1, wx.EXPAND) + flexGridSizer.Add(self._startEntry, (3,1), flag=wx.EXPAND) self._findDir = wx.Button(self, -1, _("Browse...")) self.Bind(wx.EVT_BUTTON, self.OnFindDirClick, self._findDir) - flexGridSizer.Add(self._findDir, 0, wx.RIGHT, 10) + flexGridSizer.Add(self._findDir, (3,2)) - flexGridSizer.Add(pythonPathStaticText, 0, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + flexGridSizer.Add(pythonPathStaticText, (4,0), flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) if os.environ.has_key('PYTHONPATH'): startval = os.environ['PYTHONPATH'] else: @@ -2126,34 +2200,29 @@ class CommandPropertiesDialog(wx.Dialog): self._lastPythonPath = config.Read("LastPythonPath", startval) self._pythonPathEntry = wx.TextCtrl(self, -1, self._lastPythonPath) self._pythonPathEntry.SetToolTipString(self._lastPythonPath) - flexGridSizer.Add(self._pythonPathEntry, 1, wx.EXPAND) - flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) - flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) + flexGridSizer.Add(self._pythonPathEntry, (4,1), (1,2), flag=wx.EXPAND) + if debugging and _WINDOWS: self._postpendCheckBox = wx.CheckBox(self, -1, postpendStaticText) checked = bool(config.ReadInt("PythonPathPostpend", 1)) self._postpendCheckBox.SetValue(checked) - flexGridSizer.Add(self._postpendCheckBox, 1, wx.EXPAND) - flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) - cpPanelBorderSizer.Add(flexGridSizer, 0, wx.ALL, 10) + flexGridSizer.Add(self._postpendCheckBox, (5,1), flag=wx.EXPAND) + cpPanelBorderSizer.Add(flexGridSizer, 0, flag=wx.ALL, border=10) - box = wx.BoxSizer(wx.HORIZONTAL) + box = wx.StdDialogButtonSizer() self._okButton = wx.Button(self, wx.ID_OK, okButtonName) self._okButton.SetDefault() self._okButton.SetHelpText(_("The ") + okButtonName + _(" button completes the dialog")) - box.Add(self._okButton, 0, wx.ALIGN_RIGHT|wx.ALL, 5) + box.AddButton(self._okButton) self.Bind(wx.EVT_BUTTON, self.OnOKClick, self._okButton) btn = wx.Button(self, wx.ID_CANCEL, _("Cancel")) btn.SetHelpText(_("The Cancel button cancels the dialog.")) - box.Add(btn, 0, wx.ALIGN_RIGHT|wx.ALL, 5) - cpPanelBorderSizer.Add(box, 0, wx.ALIGN_RIGHT|wx.BOTTOM, 5) + box.AddButton(btn) + box.Realize() + cpPanelBorderSizer.Add(box, 0, flag=wx.ALIGN_RIGHT|wx.ALL, border=5) self.SetSizer(cpPanelBorderSizer) - if _WINDOWS: - self.GetSizer().Fit(self) - - self.Layout() - + # Set up selections based on last values used. self._fileNameList = None self._selectedFileIndex = 0 @@ -2168,6 +2237,9 @@ class CommandPropertiesDialog(wx.Dialog): self._selectedProjectIndex = selectedIndex self._selectedProjectDocument = self._projectDocumentList[selectedIndex] self.PopulateFileList(self._selectedProjectDocument, lastFile) + + cpPanelBorderSizer.Fit(self) + def OnOKClick(self, event): startIn = self._startEntry.GetValue() @@ -2193,6 +2265,7 @@ class CommandPropertiesDialog(wx.Dialog): self.EndModal(wx.ID_OK) def GetSettings(self): + projectPath = self._selectedProjectDocument.GetFilename() filename = self._fileNameList[self._selectedFileIndex] args = self._argsEntry.GetValue() startIn = self._startEntry.GetValue() @@ -2207,7 +2280,7 @@ class CommandPropertiesDialog(wx.Dialog): else: env['PYTHONPATH'] = self._pythonPathEntry.GetValue() - return filename, args, startIn, isPython, env + return projectPath, filename, args, startIn, isPython, env def OnFileSelected(self, event): self._selectedFileIndex = self._fileList.GetSelection() @@ -2229,16 +2302,17 @@ class CommandPropertiesDialog(wx.Dialog): self._argsEntry.SetValue(self._lastArguments) - def OnFindDirClick(self, event): dlg = wx.DirDialog(self, "Choose a starting directory:", self._startEntry.GetValue(), style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON) + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: self._startEntry.SetValue(dlg.GetPath()) dlg.Destroy() + def EvtListBox(self, event): if event.GetString(): index = self._projectNameList.index(event.GetString()) @@ -2524,3 +2598,76 @@ def getAddWatchImage(): def getAddWatchIcon(): return wx.IconFromBitmap(getAddWatchBitmap()) + +#---------------------------------------------------------------------- +def getRunningManData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01\x86IDAT8\x8d\xa5\x93\xb1K\x02Q\x1c\xc7\xbf\xcf\x9a\x1bZl\x88\xb4\ +\x04\x83\x10\xa2\x96\xc0A\xa8\x96\x96\xf4h\xe9\xf0\x1f\xd0\xcd(Bpi\x13nH\xb2\ +%\x9d\x1a"\xb9)\xb4\x16i\x10\n\x13MA\x84\xa3&\xa1\xa1A\xa1E\xbdw\x97\xa2\xbd\ +\x06\xf1(\xef,\xac\xef\xf6x\xdf\xf7}\x9f\xdf\x97\xf7\x081M\xe0?\x9a\xfc\xcd \ +\\\xdc2\x99\xb6A[\x14\x91C\x9e\x8c\x1d\x00\x00\xd5\xa7*\x9a\x8a\xfa7\x82u\ +\xfb\x14dj\x03mQ\xc3}\xf2\xb5\x83\xc7B\x9e\x89\xf7/\xda\xba\xd1\x94\x01\x00j\ +CF\xe2t\xef\x1b>\x1f\x8c3Q\xf0\x11\xd3p\xa2yf\x1a\xbc\xcb\n\xdee\x85\xdd>\ +\x07\xb5!C\xe9\xb4\xb1\xe9=b\x03\x8fc\xc3\xcf\xbcN\xb3\x9e`@\x11\xb9\xaa`\ +\x7fg\x19\'\x97y\xd8\x96\xfa\xf8\x95\xf23d\xa5O4\xbfh\x87(\xf8\x88a\xc0 $|~\ +\x87n\xf7\x03\xaa\xf2\x8e\xc0\xee\n\x00 \x91\xab\xc3\xeb4\xc3\xed\xe1\xb4qF\ +\x96\xb8`\xb3h\xb7\xa6Jo\xa0\x9d\x1eD\xc1G\xc4!\x9f\xae\x03\x00\xa8\xd5jh4e\ +\r\xb9\xf0P\x82T,\x83\xf3\x0bl\xd8k\x18\xe0\xf6p\x84vz\xa0M\x8aB\xf2\x98\x84\ +\x03[\xb0.XP\xcafu^m\x04>\x18\xd7\x9aM\xe4\xea\xba\xc0x\xec\x8c\xa9\xca*^\ +\xa5\x1b}\xc0u*\xc9B\xd14\x12\xe8\x97%\x15\xcbF`\xdaH\xba\x80P4\r)\x13#R\xc6\ +\xf0\xdc\x8f2\x01\x80\x94\x89\xe9>\xc9(\xcd:\xb6\xd9\x1aw\xa0\x95i\xf8\x0e\ +\xc6\xd1\'\'\x86\xa2\xd5\x8d \xbe@\x00\x00\x00\x00IEND\xaeB`\x82' + +def getRunningManBitmap(): + return BitmapFromImage(getRunningManImage()) + +def getRunningManImage(): + stream = cStringIO.StringIO(getRunningManData()) + return ImageFromStream(stream) + +def getRunningManIcon(): + icon = EmptyIcon() + icon.CopyFromBitmap(getRunningManBitmap()) + return icon + +#---------------------------------------------------------------------- +def getDebuggingManData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01\xafIDAT8\x8d\x8d\x93\xbfK[Q\x14\xc7?7\n:\t\xb5SA\xc1?@\xc1A\x9c,%\ +\xd0\xa9\x83\xb5\x98!(b\t\xbc\xa7q("m\x1c\n5V]D\xd4-\xf8\x83\xa7\xa2\t\xa1\ +\xa6\xed$8\x08\x92\xa1\x8b\x14A\xd0YB"\xa4\xf4\x87\x90\x97K\xa8\xcb\xed\xf0\ +\xc8m\xae\xfa\xd4\x03\x07.\xe7\x9e\xf3\xfd\x9e\x9f\x88@\x1d\xb5\xba\x94\xca\ +\xaa\xeb\xb6\xbb4\xc0\x03d&\xb1\xa7\xfc\xfe\x0c\x80L\xdaQ\xd2\xad\x90I;F\x80\ +++\xbe\xe0bve\xdf\xd7y\xfemH\xc4\x162\xaa\xbb\xa5D(\x1c\x11\xb7\x02\x88@\x9d\ +f?*4\xd1\xf6\xa2\x0f\x80\x93\xf4\x8e\xe1\xb8\xf2\xf1\xb5\x18\x9cH(\x80\xe4bT\ +\x83\xd5W\x1f\xa1pD\x8c|\xd8T\x00\xdf\xd6\xd7\xe8\x1f\xb3tp\xf1\n^\xfe\xf8\ +\xa5^u7\x00P\x1eYP\xd2\x95\x1c\xa4\xa6\x84\x18\x8do\xab*C&\xed\xa8\xafG\x7f\ +\xe9\x1f\xb3x\xdc\x08\xad\x8f \x7f\tg%\xf8Y\x82\xe3\x8de\x86\x82\xcdF9\xba\ +\x84\xc1\x89\x84*K\t\xc0\xf0\xbbq:\x9f\xfcO\x7f?\xe7\x01\x9c\xff\x86Br\x8e\ +\x83\xd4\x94\x06\xd0SH.F\xc5P\xb0\x19\xe9z \xf9KOmkN\x07\x03\x14/r\xb4?\x8b\ +\xe8\xc6\xeb\x1e\x00l\x1f\xfe\xd15\x17\xaf<\xdb\xd37\xef\xd9\x9d\xb4\xe9\x8a\ +\xadj\xbfx\xb4\x878(#\x03\x00\xe9JF{[\xf92\xeb\xb1V\x99\xbbb\xab|\x9f\xb7\ +\x8d\xa9\x9cf\x1dq\x9au\xc4\x8dM\x0c\x85#\xa2x\x91cw\xd2\xd6i\x83\trk\x13\ +\x9f\x0fL\xab\xda\xe6\xd4\xd6Y+\xf1h\x8f\xb9T~G\xd2\x11\xb4\xd4\xe7O[\xf7\ +\x1e\xd6\x9d\xc7\xe4\xb7\xbe\x86\xf8\xb1?\xf4\x9c\xff\x01\xbe\xe9\xaf\x96\ +\xf0\x7fPA\x00\x00\x00\x00IEND\xaeB`\x82' + +def getDebuggingManBitmap(): + return BitmapFromImage(getDebuggingManImage()) + +def getDebuggingManImage(): + stream = cStringIO.StringIO(getDebuggingManData()) + return ImageFromStream(stream) + +def getDebuggingManIcon(): + icon = EmptyIcon() + icon.CopyFromBitmap(getDebuggingManBitmap()) + return icon + +#---------------------------------------------------------------------- + diff --git a/wxPython/samples/ide/activegrid/tool/ExtensionService.py b/wxPython/samples/ide/activegrid/tool/ExtensionService.py index b75e544585..32e4fcffeb 100644 --- a/wxPython/samples/ide/activegrid/tool/ExtensionService.py +++ b/wxPython/samples/ide/activegrid/tool/ExtensionService.py @@ -13,9 +13,10 @@ import wx import wx.lib.pydocview import MessageService +import ProjectEditor import os import os.path -import pickle +import activegrid.util.xmlutils as xmlutils _ = wx.GetTranslation @@ -38,7 +39,7 @@ EXTENSIONS_CONFIG_STRING = "Extensions" class Extension: - def __init__(self, menuItemName): + def __init__(self, menuItemName=None): self.menuItemName = menuItemName self.id = 0 self.menuItemDesc = '' @@ -46,32 +47,51 @@ class Extension: self.commandPreArgs = '' self.commandPostArgs = '' self.fileExt = None - + self.opOnSelectedFile = True + class ExtensionService(wx.lib.pydocview.DocService): + EXTENSIONS_KEY = "/AG_Extensions" def __init__(self): self.LoadExtensions() + def __getExtensionKeyName(extensionName): + return "%s/%s" % (ExtensionService.EXTENSIONS_KEY, extensionName) + + + __getExtensionKeyName = staticmethod(__getExtensionKeyName) + + def LoadExtensions(self): + self._extensions = [] + + extensionNames = [] config = wx.ConfigBase_Get() - pickledExtensions = config.Read(EXTENSIONS_CONFIG_STRING) - if pickledExtensions: - try: - self._extensions = pickle.loads(pickledExtensions.encode('ascii')) - except: - tp, val, tb = sys.exc_info() - traceback.print_exception(tp,val,tb) - self._extensions = [] - else: - self._extensions = [] - + path = config.GetPath() + try: + config.SetPath(ExtensionService.EXTENSIONS_KEY) + cont, value, index = config.GetFirstEntry() + while cont: + extensionNames.append(value) + cont, value, index = config.GetNextEntry(index) + finally: + config.SetPath(path) + + for extensionName in extensionNames: + extensionData = config.Read(self.__getExtensionKeyName(extensionName)) + if extensionData: + extension = xmlutils.unmarshal(extensionData.encode('utf-8')) + self._extensions.append(extension) + def SaveExtensions(self): config = wx.ConfigBase_Get() - config.Write(EXTENSIONS_CONFIG_STRING, pickle.dumps(self._extensions)) + config.DeleteGroup(ExtensionService.EXTENSIONS_KEY) + for extension in self._extensions: + config.Write(self.__getExtensionKeyName(extension.menuItemName), xmlutils.marshal(extension)) def GetExtensions(self): @@ -82,6 +102,10 @@ class ExtensionService(wx.lib.pydocview.DocService): self._extensions = extensions + def CheckSumExtensions(self): + return xmlutils.marshal(self._extensions) + + def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None): toolsMenuIndex = menuBar.FindMenu(_("&Tools")) if toolsMenuIndex > -1: @@ -100,8 +124,15 @@ class ExtensionService(wx.lib.pydocview.DocService): wx.EVT_UPDATE_UI(frame, ext.id, frame.ProcessUpdateUIEvent) if toolsMenuIndex == -1: - formatMenuIndex = menuBar.FindMenu(_("&Format")) - menuBar.Insert(formatMenuIndex + 1, toolsMenu, _("&Tools")) + index = menuBar.FindMenu(_("&Run")) + if index == -1: + index = menuBar.FindMenu(_("&Project")) + if index == -1: + index = menuBar.FindMenu(_("&Format")) + if index == -1: + index = menuBar.FindMenu(_("&View")) + menuBar.Insert(index + 1, toolsMenu, _("&Tools")) + def ProcessEvent(self, event): id = event.GetId() @@ -126,6 +157,14 @@ class ExtensionService(wx.lib.pydocview.DocService): if fileExt in doc.GetDocumentTemplate().GetFileFilter(): event.Enable(True) return True + if extension.opOnSelectedFile and isinstance(doc, ProjectEditor.ProjectDocument): + filename = doc.GetFirstView().GetSelectedFile() + if filename: + template = wx.GetApp().GetDocumentManager().FindTemplateForPath(filename) + for fileExt in extension.fileExt: + if fileExt in template.GetFileFilter(): + event.Enable(True) + return True event.Enable(False) return False return False @@ -136,7 +175,12 @@ class ExtensionService(wx.lib.pydocview.DocService): doc = wx.GetApp().GetDocumentManager().GetCurrentDocument() if not doc: return - filename = doc.GetFilename() + if extension.opOnSelectedFile and isinstance(doc, ProjectEditor.ProjectDocument): + filename = doc.GetFirstView().GetSelectedFile() + if not filename: + filename = doc.GetFilename() + else: + filename = doc.GetFilename() ext = os.path.splitext(filename)[1] if not '*' in extension.fileExt: if not ext or ext[1:] not in extension.fileExt: @@ -171,99 +215,107 @@ class ExtensionOptionsPanel(wx.Panel): def __init__(self, parent, id): wx.Panel.__init__(self, parent, id) - extOptionsPanelBorderSizer = wx.BoxSizer(wx.HORIZONTAL) + extOptionsPanelBorderSizer = wx.BoxSizer(wx.VERTICAL) - extOptionsPanelSizer = wx.FlexGridSizer(cols=2, hgap=SPACE, vgap=HALF_SPACE) + extOptionsPanelSizer = wx.BoxSizer(wx.HORIZONTAL) extCtrlSizer = wx.BoxSizer(wx.VERTICAL) - extCtrlSizer.Add(wx.StaticText(self, -1, _("Extensions:")), 0) - self._extListBox = wx.ListBox(self, -1, size=(-1,185), style=wx.LB_SINGLE) + extCtrlSizer.Add(wx.StaticText(self, -1, _("External Tools:")), 0, wx.BOTTOM, HALF_SPACE) + self._extListBox = wx.ListBox(self, -1, size=(-1,160), style=wx.LB_SINGLE) self.Bind(wx.EVT_LISTBOX, self.OnListBoxSelect, self._extListBox) - extCtrlSizer.Add(self._extListBox, 1, wx.TOP | wx.BOTTOM | wx.EXPAND, SPACE) - buttonSizer = wx.GridSizer(rows=1, hgap=10, vgap=5) + extCtrlSizer.Add(self._extListBox, 1, wx.BOTTOM | wx.EXPAND, SPACE) + buttonSizer = wx.GridSizer(cols=2, vgap=5, hgap=10) self._moveUpButton = wx.Button(self, -1, _("Move Up")) self.Bind(wx.EVT_BUTTON, self.OnMoveUp, self._moveUpButton) - buttonSizer.Add(self._moveUpButton, 0) + buttonSizer.Add(self._moveUpButton, 1, wx.EXPAND) self._moveDownButton = wx.Button(self, -1, _("Move Down")) self.Bind(wx.EVT_BUTTON, self.OnMoveDown, self._moveDownButton) - buttonSizer.Add(self._moveDownButton, 0) - extCtrlSizer.Add(buttonSizer, 0, wx.ALIGN_CENTER | wx.BOTTOM, HALF_SPACE) - buttonSizer = wx.GridSizer(rows=1, hgap=10, vgap=5) - self._addButton = wx.Button(self, -1, _("Add")) + buttonSizer.Add(self._moveDownButton, 1, wx.EXPAND) + self._addButton = wx.Button(self, wx.ID_ADD) self.Bind(wx.EVT_BUTTON, self.OnAdd, self._addButton) - buttonSizer.Add(self._addButton, 0) - self._deleteButton = wx.Button(self, wx.ID_DELETE) + buttonSizer.Add(self._addButton, 1, wx.EXPAND) + self._deleteButton = wx.Button(self, wx.ID_DELETE, label=_("Delete")) # get rid of accelerator for letter d in "&Delete" self.Bind(wx.EVT_BUTTON, self.OnDelete, self._deleteButton) - buttonSizer.Add(self._deleteButton, 0) + buttonSizer.Add(self._deleteButton, 1, wx.EXPAND) extCtrlSizer.Add(buttonSizer, 0, wx.ALIGN_CENTER) - extOptionsPanelSizer.Add(extCtrlSizer, 0) + extOptionsPanelSizer.Add(extCtrlSizer, 0, wx.EXPAND) self._extDetailPanel = wx.Panel(self) - staticBox = wx.StaticBox(self._extDetailPanel, label=_("Selected Extension")) - staticBoxSizer = wx.StaticBoxSizer(staticBox) - self._extDetailPanel.SetSizer(staticBoxSizer) - extDetailSizer = wx.FlexGridSizer(cols=1, hgap=5, vgap=3) - staticBoxSizer.AddSizer(extDetailSizer, 0, wx.ALL, 5) + staticBox = wx.StaticBox(self, label=_("Selected External Tool")) + staticBoxSizer = wx.StaticBoxSizer(staticBox, wx.VERTICAL) + + extDetailSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=3) + extDetailSizer.AddGrowableCol(1,1) extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Name:"))) self._menuItemNameTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) - extDetailSizer.Add(self._menuItemNameTextCtrl, 1, wx.EXPAND) + extDetailSizer.Add(self._menuItemNameTextCtrl, 0, wx.EXPAND) self.Bind(wx.EVT_TEXT, self.SaveCurrentItem, self._menuItemNameTextCtrl) extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Menu Item Description:"))) self._menuItemDescTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) - extDetailSizer.Add(self._menuItemDescTextCtrl, 1, wx.EXPAND) + extDetailSizer.Add(self._menuItemDescTextCtrl, 0, wx.EXPAND) extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Path:"))) self._commandTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) findFileButton = wx.Button(self._extDetailPanel, -1, _("Browse...")) def OnBrowseButton(event): - fileDlg = wx.FileDialog(self, _("Choose an Executable:"), style=wx.OPEN | wx.HIDE_READONLY) + fileDlg = wx.FileDialog(self, _("Choose an Executable:"), style=wx.OPEN|wx.FILE_MUST_EXIST|wx.HIDE_READONLY|wx.CHANGE_DIR) path = self._commandTextCtrl.GetValue() if path: fileDlg.SetPath(path) + # fileDlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog if fileDlg.ShowModal() == wx.ID_OK: self._commandTextCtrl.SetValue(fileDlg.GetPath()) self._commandTextCtrl.SetInsertionPointEnd() + self._commandTextCtrl.SetToolTipString(fileDlg.GetPath()) fileDlg.Destroy() wx.EVT_BUTTON(findFileButton, -1, OnBrowseButton) hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.Add(self._commandTextCtrl, 1, wx.EXPAND) hsizer.Add(findFileButton, 0, wx.LEFT, HALF_SPACE) - extDetailSizer.Add(hsizer, 0) + extDetailSizer.Add(hsizer, 0, wx.EXPAND) - extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Pre Arguments:"))) + extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Pre Args:"))) self._commandPreArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) - extDetailSizer.Add(self._commandPreArgsTextCtrl, 1, wx.EXPAND) + extDetailSizer.Add(self._commandPreArgsTextCtrl, 0, wx.EXPAND) - extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Post Arguments:"))) + extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("Command Post Args:"))) self._commandPostArgsTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) - extDetailSizer.Add(self._commandPostArgsTextCtrl, 1, wx.EXPAND) + extDetailSizer.Add(self._commandPostArgsTextCtrl, 0, wx.EXPAND) - extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("File Extensions (Comma Separated):"))) + extDetailSizer.Add(wx.StaticText(self._extDetailPanel, -1, _("File Extensions:"))) self._fileExtTextCtrl = wx.TextCtrl(self._extDetailPanel, -1, size = (-1, -1)) - self._fileExtTextCtrl.SetToolTipString(_("""For example: "txt, text" or "*" for all files""")) - extDetailSizer.Add(self._fileExtTextCtrl, 1, wx.EXPAND) + self._fileExtTextCtrl.SetToolTipString(_("""For example: "txt, text" (comma separated) or "*" for all files""")) + extDetailSizer.Add(self._fileExtTextCtrl, 0, wx.EXPAND) - extOptionsPanelSizer.Add(self._extDetailPanel, 0) + self._selFileCtrl = wx.CheckBox(self._extDetailPanel, -1, _("Operate on Selected File")) + extDetailSizer.Add(self._selFileCtrl) + self._selFileCtrl.SetToolTipString(_("If focus is in the project, instead of operating on the project file, operate on the selected file.")) - extOptionsPanelBorderSizer.Add(extOptionsPanelSizer, 0, wx.ALL | wx.EXPAND, SPACE) - self.SetSizer(extOptionsPanelBorderSizer) - self.Layout() - parent.AddPage(self, _("Extensions")) + self._extDetailPanel.SetSizer(extDetailSizer) + staticBoxSizer.Add(self._extDetailPanel, 1, wx.ALL|wx.EXPAND, SPACE) + extOptionsPanelSizer.Add(staticBoxSizer, 1, wx.LEFT|wx.EXPAND, SPACE) + + extOptionsPanelBorderSizer.Add(extOptionsPanelSizer, 1, wx.ALL|wx.EXPAND, SPACE) + self.SetSizer(extOptionsPanelBorderSizer) + if self.PopulateItems(): self._extListBox.SetSelection(0) - self.OnListBoxSelect(None) + self.OnListBoxSelect() + + self.Layout() + + parent.AddPage(self, _("External Tools")) def OnOK(self, optionsDialog): self.SaveCurrentItem() extensionsService = wx.GetApp().GetService(ExtensionService) - oldExtensions = extensionsService.GetExtensions() extensionsService.SetExtensions(self._extensions) extensionsService.SaveExtensions() - if oldExtensions.__repr__() != self._extensions.__repr__(): + if extensionsService.CheckSumExtensions() != self._oldExtensions: # see PopulateItems() note about self._oldExtensions msgTitle = wx.GetApp().GetAppName() if not msgTitle: msgTitle = _("Document Options") @@ -277,6 +329,7 @@ class ExtensionOptionsPanel(wx.Panel): extensionsService = wx.GetApp().GetService(ExtensionService) import copy self._extensions = copy.deepcopy(extensionsService.GetExtensions()) + self._oldExtensions = extensionsService.CheckSumExtensions() # wxBug: need to make a copy now since the deepcopy reorders fields, so we must compare the prestine copy with the modified copy for extension in self._extensions: self._extListBox.Append(extension.menuItemName, extension) self._currentItem = None @@ -284,9 +337,9 @@ class ExtensionOptionsPanel(wx.Panel): return len(self._extensions) - def OnListBoxSelect(self, event): + def OnListBoxSelect(self, event=None): self.SaveCurrentItem() - if not self._extListBox.GetSelections(): + if self._extListBox.GetSelection() == wx.NOT_FOUND: self._currentItemIndex = -1 self._currentItem = None self._deleteButton.Enable(False) @@ -316,43 +369,52 @@ class ExtensionOptionsPanel(wx.Panel): extension.fileExt = None else: extension.fileExt = fileExt.split(',') + extension.opOnSelectedFile = self._selFileCtrl.GetValue() def LoadItem(self, extension): if extension: self._menuItemDescTextCtrl.SetValue(extension.menuItemDesc or '') self._commandTextCtrl.SetValue(extension.command or '') + self._commandTextCtrl.SetToolTipString(extension.command or '') self._commandPreArgsTextCtrl.SetValue(extension.commandPreArgs or '') self._commandPostArgsTextCtrl.SetValue(extension.commandPostArgs or '') if extension.fileExt: - self._fileExtTextCtrl.SetValue(extension.fileExt.__repr__()[1:-1].replace("'","")) # Make the list a string, strip the brakcet on either side + list = "" + for ext in extension.fileExt: + if list: + list = list + ", " + list = list + ext + self._fileExtTextCtrl.SetValue(list) else: self._fileExtTextCtrl.SetValue('') + self._selFileCtrl.SetValue(extension.opOnSelectedFile) self._menuItemNameTextCtrl.SetValue(extension.menuItemName or '') # Do the name last since it triggers the write event that updates the entire item self._extDetailPanel.Enable() else: self._menuItemNameTextCtrl.SetValue('') self._menuItemDescTextCtrl.SetValue('') self._commandTextCtrl.SetValue('') + self._commandTextCtrl.SetToolTipString(_("Path to executable")) self._commandPreArgsTextCtrl.SetValue('') self._commandPostArgsTextCtrl.SetValue('') self._fileExtTextCtrl.SetValue('') + self._selFileCtrl.SetValue(True) self._extDetailPanel.Enable(False) def OnAdd(self, event): self.SaveCurrentItem() - extensionNames = map(lambda extension: extension.menuItemName, self._extensions) name = _("Untitled") count = 1 - while name in extensionNames: + while self._extListBox.FindString(name) != wx.NOT_FOUND: count = count + 1 - name = _("Untitled %s") % count + name = _("Untitled%s") % count extension = Extension(name) self._extensions.append(extension) self._extListBox.Append(extension.menuItemName, extension) - self._extListBox.SetSelection(self._extListBox.GetCount() - 1) - self.OnListBoxSelect(None) + self._extListBox.SetStringSelection(extension.menuItemName) + self.OnListBoxSelect() self._menuItemNameTextCtrl.SetFocus() self._menuItemNameTextCtrl.SetSelection(-1, -1) @@ -364,7 +426,7 @@ class ExtensionOptionsPanel(wx.Panel): if self._currentItemIndex > -1: self._extListBox.SetSelection(self._currentItemIndex) self._currentItem = None # Don't update it since it no longer exists - self.OnListBoxSelect(None) + self.OnListBoxSelect() def OnMoveUp(self, event): @@ -374,7 +436,7 @@ class ExtensionOptionsPanel(wx.Panel): self._extListBox.Insert(itemAboveString, self._currentItemIndex) self._extListBox.SetClientData(self._currentItemIndex, itemAboveData) self._currentItemIndex = self._currentItemIndex - 1 - self.OnListBoxSelect(None) # Reset buttons + self.OnListBoxSelect() # Reset buttons def OnMoveDown(self, event): @@ -384,4 +446,4 @@ class ExtensionOptionsPanel(wx.Panel): self._extListBox.Insert(itemBelowString, self._currentItemIndex) self._extListBox.SetClientData(self._currentItemIndex, itemBelowData) self._currentItemIndex = self._currentItemIndex + 1 - self.OnListBoxSelect(None) # Reset buttons + self.OnListBoxSelect() # Reset buttons diff --git a/wxPython/samples/ide/activegrid/tool/FindInDirService.py b/wxPython/samples/ide/activegrid/tool/FindInDirService.py index 63eea49a13..1fd557b002 100644 --- a/wxPython/samples/ide/activegrid/tool/FindInDirService.py +++ b/wxPython/samples/ide/activegrid/tool/FindInDirService.py @@ -79,8 +79,7 @@ class FindInDirService(FindService.FindService): id = event.GetId() if id == FindInDirService.FINDALL_ID: projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) - view = projectService.GetView() - if view and view.GetDocument() and view.GetDocument().GetFiles(): + if projectService.GetFilesFromCurrentProject(): event.Enable(True) else: event.Enable(False) @@ -94,7 +93,7 @@ class FindInDirService(FindService.FindService): def ShowFindDirDialog(self, findString=None): config = wx.ConfigBase_Get() - frame = wx.Dialog(None, -1, _("Find in Directory"), size= (320,200)) + frame = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("Find in Directory"), size= (320,200)) borderSizer = wx.BoxSizer(wx.HORIZONTAL) contentSizer = wx.BoxSizer(wx.VERTICAL) @@ -112,11 +111,11 @@ class FindInDirService(FindService.FindService): dir = dirCtrl.GetValue() if len(dir): dlg.SetPath(dir) + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: dirCtrl.SetValue(dlg.GetPath()) dirCtrl.SetToolTipString(dirCtrl.GetValue()) dirCtrl.SetInsertionPointEnd() - dlg.Destroy() wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton) @@ -128,6 +127,9 @@ class FindInDirService(FindService.FindService): lineSizer.Add(wx.StaticLine(frame, -1, size = (10,-1)), 0, flag=wx.EXPAND) contentSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.BOTTOM, border=HALF_SPACE) + if wx.Platform == "__WXMAC__": + contentSizer.Add((-1, 10), 0, wx.EXPAND) + lineSizer = wx.BoxSizer(wx.HORIZONTAL) lineSizer.Add(wx.StaticText(frame, -1, _("Find what:")), 0, wx.ALIGN_CENTER | wx.RIGHT, HALF_SPACE) if not findString: @@ -151,13 +153,17 @@ class FindInDirService(FindService.FindService): buttonSizer = wx.BoxSizer(wx.VERTICAL) findBtn = wx.Button(frame, wx.ID_OK, _("Find")) findBtn.SetDefault() - buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) + BTM_SPACE = HALF_SPACE + if wx.Platform == "__WXMAC__": + BTM_SPACE = SPACE + buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE) buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL), 0) borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE) frame.SetSizer(borderSizer) frame.Fit() + frame.CenterOnParent() status = frame.ShowModal() passedCheck = False @@ -168,6 +174,7 @@ class FindInDirService(FindService.FindService): _("Find in Directory"), wx.OK | wx.ICON_EXCLAMATION ) + dlg.CenterOnParent() dlg.ShowModal() dlg.Destroy() @@ -178,6 +185,7 @@ class FindInDirService(FindService.FindService): _("Find in Directory"), wx.OK | wx.ICON_EXCLAMATION ) + dlg.CenterOnParent() dlg.ShowModal() dlg.Destroy() @@ -197,10 +205,8 @@ class FindInDirService(FindService.FindService): regExpr = regExprCtrl.IsChecked() self.SaveFindConfig(findString, wholeWord, matchCase, regExpr) - + frame.Destroy() if status == wx.ID_OK: - frame.Destroy() - messageService = wx.GetApp().GetService(MessageService.MessageService) messageService.ShowWindow() @@ -267,7 +273,6 @@ class FindInDirService(FindService.FindService): return True else: - frame.Destroy() return False @@ -285,7 +290,7 @@ class FindInDirService(FindService.FindService): def ShowFindAllDialog(self, findString=None): config = wx.ConfigBase_Get() - frame = wx.Dialog(None, -1, _("Find in Project"), size= (320,200)) + frame = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("Find in Project"), size= (320,200)) borderSizer = wx.BoxSizer(wx.HORIZONTAL) contentSizer = wx.BoxSizer(wx.VERTICAL) @@ -310,13 +315,17 @@ class FindInDirService(FindService.FindService): buttonSizer = wx.BoxSizer(wx.VERTICAL) findBtn = wx.Button(frame, wx.ID_OK, _("Find")) findBtn.SetDefault() - buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) + BTM_SPACE = HALF_SPACE + if wx.Platform == "__WXMAC__": + BTM_SPACE = SPACE + buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE) buttonSizer.Add(wx.Button(frame, wx.ID_CANCEL), 0) borderSizer.Add(buttonSizer, 0, wx.ALL, SPACE) frame.SetSizer(borderSizer) frame.Fit() + frame.CenterOnParent() status = frame.ShowModal() # save user choice state for this and other Find Dialog Boxes @@ -326,9 +335,8 @@ class FindInDirService(FindService.FindService): regExpr = regExprCtrl.IsChecked() self.SaveFindConfig(findString, wholeWord, matchCase, regExpr) + frame.Destroy() if status == wx.ID_OK: - frame.Destroy() - messageService = wx.GetApp().GetService(MessageService.MessageService) messageService.ShowWindow() @@ -412,7 +420,6 @@ class FindInDirService(FindService.FindService): return True else: - frame.Destroy() return False @@ -442,8 +449,9 @@ class FindInDirService(FindService.FindService): break if not foundView: - doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT) - foundView = doc.GetFirstView() + doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE) + if doc: + foundView = doc.GetFirstView() if foundView: foundView.GetFrame().SetFocus() diff --git a/wxPython/samples/ide/activegrid/tool/FindService.py b/wxPython/samples/ide/activegrid/tool/FindService.py index 2fac20da23..3d5e2e4083 100644 --- a/wxPython/samples/ide/activegrid/tool/FindService.py +++ b/wxPython/samples/ide/activegrid/tool/FindService.py @@ -121,6 +121,7 @@ class FindService(wx.lib.pydocview.DocService): self._findDialog = None self._replaceDialog = FindReplaceDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Replace"), size=(320,200), findString=findString) + self._replaceDialog.CenterOnParent() self._replaceDialog.Show(True) else: if self._replaceDialog != None: @@ -129,6 +130,7 @@ class FindService(wx.lib.pydocview.DocService): self._replaceDialog = None self._findDialog = FindDialog(self.GetDocumentManager().FindSuitableParent(), -1, _("Find"), size=(320,200), findString=findString) + self._findDialog.CenterOnParent() self._findDialog.Show(True) @@ -152,6 +154,7 @@ class FindService(wx.lib.pydocview.DocService): """ Display Goto Line Number dialog box """ line = -1 dialog = wx.TextEntryDialog(parent, _("Enter line number to go to:"), _("Go to Line")) + dialog.CenterOnParent() if dialog.ShowModal() == wx.ID_OK: try: line = int(dialog.GetValue()) @@ -356,7 +359,10 @@ class FindDialog(wx.Dialog): wx.EVT_BUTTON(self, FindService.FINDONE_ID, self.OnActionEvent) cancelBtn = wx.Button(self, wx.ID_CANCEL) wx.EVT_BUTTON(self, wx.ID_CANCEL, self.OnClose) - buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) + BTM_SPACE = HALF_SPACE + if wx.Platform == "__WXMAC__": + BTM_SPACE = SPACE + buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE) buttonSizer.Add(cancelBtn, 0) gridSizer.Add(buttonSizer, pos=(0,2), span=(3,1)) @@ -455,9 +461,14 @@ class FindReplaceDialog(FindDialog): wx.EVT_BUTTON(self, FindService.REPLACEONE_ID, self.OnActionEvent) replaceAllBtn = wx.Button(self, FindService.REPLACEALL_ID, _("Replace All")) wx.EVT_BUTTON(self, FindService.REPLACEALL_ID, self.OnActionEvent) - buttonSizer.Add(findBtn, 0, wx.BOTTOM, HALF_SPACE) - buttonSizer.Add(replaceBtn, 0, wx.BOTTOM, HALF_SPACE) - buttonSizer.Add(replaceAllBtn, 0, wx.BOTTOM, HALF_SPACE) + + BTM_SPACE = HALF_SPACE + if wx.Platform == "__WXMAC__": + BTM_SPACE = SPACE + + buttonSizer.Add(findBtn, 0, wx.BOTTOM, BTM_SPACE) + buttonSizer.Add(replaceBtn, 0, wx.BOTTOM, BTM_SPACE) + buttonSizer.Add(replaceAllBtn, 0, wx.BOTTOM, BTM_SPACE) buttonSizer.Add(cancelBtn, 0) gridSizer.Add(buttonSizer, pos=(0,2), span=(3,1)) @@ -495,12 +506,24 @@ def getFindData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00\x81IDAT8\x8d\xa5S\xc1\x16\xc0\x10\x0ckk\xff\xff\xc7d\x87\xad^U\r\ -\x93S\xe5U$\n\xb3$:\xc1e\x17(\x19Z\xb3$\x9e\xf1DD\xe2\x15\x01x\xea\x93\xef\ -\x04\x989\xea\x1b\xf2U\xc0\xda\xb4\xeb\x11\x1f:\xd8\xb5\xff8\x93\xd4\xa9\xae\ -@/S\xaaUwJ3\x85\xc0\x81\xee\xeb.q\x17C\x81\xd5XU \x1a\x93\xc6\x18\x8d\x90\ -\xe8}\x89\x00\x9a&\x9b_k\x94\x0c\xdf\xd78\xf8\x0b\x99Y\xb4\x08c\x9e\xfe\xc6\ -\xe3\x087\xf9\xd0D\x180\xf1#\x8e\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x01\xb1IDAT8\x8d\xa5\x93=o\xd3P\x14\x86\x1f\xa7\x11\x95<\xdc\xc6\xecN+5\ +[\x86B\x99\xacLQ2Zr[\x89\xa1\xfd\x0b%\x95\x90\x00\xf1\x03\x80\x01\x98\x80\ +\x19G\xac\x0cm\xff@Y\xd9:\xd9Ck\x94\xd6\xddb\x94\x9b\x98\xc8\xd2e1C\xe5\x8b\ +\xdd\x14\x96\xbe\xdb=\x1f\xefy\xef\xf90\x8c\xda\x12wA\xbd\xfc\x18\xfa\x9fs\ +\x80\xf9|\x0e\xc0\x93\xc1\x81\x01\xf0\xe6\xf5\xab\x1c`:\x9d\x02\xf0\xf6\xdd{\ +\xa3\xc8\xa9\xddd\xec\xf5z\xb4Z\xeb\x00\x1c\x1f\x1d\xe6\x85\xdd\xf3<\x06\x83\ +\xc1\x82\xbd\xa2 \x0cCL\xd3d<\x1e\x13\xc71\xb6m\x030\x1a\x8d\x08\x82\x00\x80\ +\xb3\xb3s:\x9d\x8e\xce\xa9(h6\x9b8\x8e\x83m\xdb4\x1a\r\x82 \xe0\xc5\xf3g\xb9\ +eY\xb4\xdbm\x1c\xc7Y\xe8\x81&\xf8\xf4\xf1C\xde\xedv+\xce\x97Owx\xfc\xe8k\xc5\ +\xb6\xb7\xb7\x8b\xef\x0foW \x84\xe0\xea\xea\x02\xa5\x94n\x18\x80\x94\x92\xd9\ +l\x02@\x96e\x95>\xd4nVO\xd3\xb9\x0e\xba\r\xa6i\xd2\xef\xf7\xf0\xfd!\xc7G\x87\ +y\xed:)\xd5\x01J\xfd\xd6c\xfc~\x9a\xfc\x93\xe8\xf2\xf2\x02(Ma6\x9b \x84@)\ +\xa5\t}\xff\x0b\xd0\'I~R\x14\xca\xb2L\xfb\x97\x97\xef-\xeeA!_J\x89\xeb\xba\ +\xb8\xae\xab\xbf\x06\x7f\x97\xacP[\x87\xeb9\x0b!H\x92\ta\x18"\xa5\xd4U\xbd\ +\xadm\xe3\xe1\x83\x8d<\x8a~\x90\xa6\xbf\x88\xe3\x18)\xa5&\xa9\x03X\x96E\xab\ +\xb5\x8em7\xf5\xc2\x94\xb1\xba\xba\xc6\xe6\xe6\x06++\xf7\x89\xa2\xa8\xe2\xd3\ +=89\xf9Va.\x14\x14\xd8\xdf?X VJa\x14\xd7X\xde\xef2\xbc\xadm\xe3\x7f~\xe3\xae\ +\xe7\xfc\x07\x84;\xc5\x82\xa1m&\x95\x00\x00\x00\x00IEND\xaeB`\x82' def getFindBitmap(): diff --git a/wxPython/samples/ide/activegrid/tool/HtmlEditor.py b/wxPython/samples/ide/activegrid/tool/HtmlEditor.py index 21001efc6b..bcdbe7ed7b 100644 --- a/wxPython/samples/ide/activegrid/tool/HtmlEditor.py +++ b/wxPython/samples/ide/activegrid/tool/HtmlEditor.py @@ -76,7 +76,6 @@ class HtmlView(CodeEditor.CodeView): ## sizer = wx.BoxSizer(wx.HORIZONTAL) ## sizer.Add(self._notebook, 1, wx.EXPAND) ## frame.SetSizer(sizer) -## frame.SetAutoLayout(True) ## ## ## def OnNotebookChanging(self, event): @@ -120,7 +119,7 @@ class HtmlCtrl(CodeEditor.CodeCtrl): def SetViewDefaults(self): - CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Html", hasWordWrap = False, hasTabs = True) + CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Html", hasWordWrap = True, hasTabs = True) def GetFontAndColorFromConfig(self): @@ -160,6 +159,10 @@ class HtmlOptionsPanel(STCTextEditor.TextOptionsPanel): STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Html", label = "HTML", hasWordWrap = True, hasTabs = True) + def GetIcon(self): + return getHTMLIcon() + + HTMLKEYWORDS = [ "A", "ABBR", "ACRONYM", "ADDRESS", "APPLET", "AREA", "B", "BASE", "BASEFONT", "BDO", "BIG", "BLOCKQUOTE", "BODY", "BR", "BUTTON", "CAPTION", "CENTER", "CITE", "CODE", "COL", "COLGROUP", "DD", "DEL", "DFN", "DIR", @@ -199,16 +202,26 @@ def getHTMLData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00\xd3IDAT8\x8dcddbf\xa0\x040\xfe\xbf\xd1\xf3\x9f\x12\x03X\xfe}\xbeI\ -\x91\x0b\x98(\xd2=(\x0c`\x90W\xd2\xfc\x0f\x030\xb6\xbc\x92\xe6\x7f\x1d\x03\ -\xf3\xffN\xae\xde\xff\xff\xff\xff\xff\xdf\xc0\xd8\xfa\xff\xb5;O\xfe_\xbb\xf3\ -\xe4\xbf\x8e\x819\\\xcd\xd7_\xff\xff\xb3<|x\x9dAAY\x0b\xc5\xd0\x07w\xaf1\xd8\ -\xdbZ0\xec\xdd\xb5\x85\x81\x81\x81\x81\xe1\xdd\xf3\x1b\x0c\xab\x97\xcef\xe0`\ -ca\xf8\xfa\xf1\x19\\\x1d\x17+\x03\x03\x0b\x03\x03\x03Cqq>\xc3\xd3\x17o\x18V,\ -]\n\x97de\xe7\x81\xb3\x199\xc4\x18\x0e\x1d:\xc2 "*\xce\xf0\x8f\x11!\x8e\xd3\ -\x0b\xd8\xd8\xa7\x8e\xed\xf9\x7f\xf1\xcca\x14o\xca+i\xfeg\xfc{:\x95\xa2\x844\ -\xf0\xd1H\xb1\x01\x8c\x94\xe6F\x8a]\x00\x00YXz\xf0\x97\x87\'\x1a\x00\x00\x00\ -\x00IEND\xaeB`\x82' +\x00\x01\xeeIDAT8\x8d}\x92?h\x13a\x18\xc6\x7fw=\x8d\xb4\x98\xa9-uP\x1a\xc9p$\ +\xdc`\xd0C\x8d\x8b)\xc5!Z\x11\xcc\xd0A\xd0*\xa8\x93\x8b8\x18\x11\x14RD\x07\t\ +N\xfe\xc1\x0cRAtS\x1c,\xcd\x10\x8c\xd8S\xba$9"\x11L\r\x96\x92\xa4.\xda#i\xa5\ +\xe7p^r\x97?\xbe\xd3\xf1~\xdf\xf3{\x9f\xe7\xbbW\xf8T(\x998j\xb9V\x07 _\xde\ +\x0e\xc0\xad\x19U\xe0?%\x01\x0c\xef\x19owv\xf9\xff\x01\x96\x88N\x850\x92)\ +\xf3\xde\x95s}!Rgcx\xdb\x9f\xd6\xf7Z\x13"\xa7\xcf\x00\xf4\x85t\x01\xea\x9b\ +\xedV\xfa\xd53\x00\xb2z\xb3\x7f\x84\xe5Z\xbd\x15\xc1)>x,\x04\x84,\xc0\xed\'\ +\xfd\x01\x9dB\xdb:\xc0\x8a\xb1E\xa3\xb2A8\xe0!\x9cL\x99\x00\x83;\x83D\x0fxQ\ +\x15Y\xe8\x19\xc1\x16\xff\xfe\xf2\x11V\xaf\xb1\x03\x90G\xe0\xf5\xe7\n\xd5\ +\xf58\xb0\xc4\xfc"\xbcL\xbf7c\x91#\x82h\xff\xae\xb5\xa6{\xf2\xdc\x9bi\x17\ +\xf8\xc6\x85\xaf\x9c\xbf:\x03\xc0\xe8P\x82\x8bwN\xa2\xe5\x8a\xa6\xe8\x9cjW\ +\xf1\xed\x1c`M\x05P\x94\xa7=\xf3\xcf\xa6&\x91\x8c_\x85\xd6c\xad\x18[\xae\x0b\ +\'\xf6\xef\xe6h4\r\xc0\xcf\x1f\xd0\xa8l0:\x94 \x937\x00\xc8\xe4\r\xeb\r:\x85\ +\xe3J\x0cy\xe41\xde\xb1\xbb\xd4\xbf\x97\x11\x07|\x00T\xcbz\x97\x0b\xb1\x97\ +\xb5jY\xa71\xf6\x0e-Wb65\xc9\x8b\xf9\xe7,\xaenZg\xebq\xd7])\xab7\xc9\xea\xee\ +\x8c\xdaB\x90\xf8u\xbde\x13n\xb6\x96I[\x08\xa2N$(~\x8b#\xfb\x12H\x1f\x1e^\ +\xeaZQ-W4\x0f\x9f\xaa\x01~\x8eO\r\x92\xc9\x1b\xc8>KlC\xbc{!\x1c\xf0\xf4\x8e\ +\xa0*\xb2\x90|\xb4\xcf\xe1\xa0-v\xd6\xe5\xb3\xd3\x08\x828\xd0\x8b\x01X\xcb\ +\xa2\xe5J\xdc\x7f\xe0o\xc3\'\n\x84\x03\x1eb\x91C\xa8\x8a,\xfc\x05\xf6\x0e\ +\xbfa\x1f\xe7Z\xfb\x00\x00\x00\x00IEND\xaeB`\x82' def getHTMLBitmap(): diff --git a/wxPython/samples/ide/activegrid/tool/IDE.py b/wxPython/samples/ide/activegrid/tool/IDE.py index 4a9a5a45c8..a9c6dcc77b 100644 --- a/wxPython/samples/ide/activegrid/tool/IDE.py +++ b/wxPython/samples/ide/activegrid/tool/IDE.py @@ -16,10 +16,33 @@ import wx.lib.pydocview import sys import wx.grid import os.path -import activegrid.util +import activegrid.util.sysutils as sysutilslib +import activegrid.util.appdirs as appdirs _ = wx.GetTranslation ACTIVEGRID_BASE_IDE = False +#---------------------------------------------------------------------------- +# Helper functions for command line args +#---------------------------------------------------------------------------- + +# Since Windows accept command line options with '/', but this character +# is used to denote absolute path names on other platforms, we need to +# conditionally handle '/' style arguments on Windows only. +def printArg(argname): + output = "'-" + argname + "'" + if wx.Platform == "__WXMSW__": + output = output + " or '/" + argname + "'" + + return output + +def isInArgs(argname, argv): + result = False + if ("-" + argname) in argv: + result = True + if wx.Platform == "__WXMSW__" and ("/" + argname) in argv: + result = True + + return result #---------------------------------------------------------------------------- # Classes @@ -34,38 +57,53 @@ class IDEApplication(wx.lib.pydocview.DocApp): global ACTIVEGRID_BASE_IDE args = sys.argv - if "-h" in args or "-help" in args or "/help" in args: + + if "-h" in args or "-help" in args or "--help" in args\ + or (wx.Platform == "__WXMSW__" and "/help" in args): print "Usage: ActiveGridAppBuilder.py [options] [filenames]\n" - print " option '-multiple' or '/multiple' to allow multiple instances of application." - print " option '-debug' or '/debug' for debug mode." - print " option '-h' or '-help' or '/help' to show usage information for command." - print " option '-baseide' or '/baseide' for base IDE mode." + # Mac doesn't really support multiple instances for GUI apps + # and since we haven't got time to test this thoroughly I'm + # disabling it for now. + if wx.Platform != "__WXMAC__": + print " option " + printArg("multiple") + " to allow multiple instances of application." + print " option " + printArg("debug") + " for debug mode." + print " option '-h' or " + printArg("help") + " to show usage information for command." + print " option " + printArg("baseide") + " for base IDE mode." print " [filenames] is an optional list of files you want to open when application starts." return False - elif "-dev" in args or "/dev" in args: + elif isInArgs("dev", args): self.SetAppName(_("ActiveGrid Application Builder Dev")) self.SetDebug(False) - elif "-debug" in args or "/debug" in args: + elif isInArgs("debug", args): self.SetAppName(_("ActiveGrid Application Builder Debug")) self.SetDebug(True) self.SetSingleInstance(False) - elif "-baseide" in args or "/baseide" in args: + elif isInArgs("baseide", args): self.SetAppName(_("ActiveGrid IDE")) ACTIVEGRID_BASE_IDE = True else: self.SetAppName(_("ActiveGrid Application Builder")) self.SetDebug(False) - if "-multiple" in args or "/multiple" in args: + if isInArgs("multiple", args) and wx.Platform != "__WXMAC__": self.SetSingleInstance(False) + + if not ACTIVEGRID_BASE_IDE: + import CmdlineOptions + if isInArgs(CmdlineOptions.DEPLOY_TO_SERVE_PATH_ARG, args): + CmdlineOptions.enableDeployToServePath() if not wx.lib.pydocview.DocApp.OnInit(self): return False - self.ShowSplash(getSplashBitmap()) + if not ACTIVEGRID_BASE_IDE: + self.ShowSplash(getSplashBitmap()) + else: + self.ShowSplash(getIDESplashBitmap()) import STCTextEditor import FindInDirService import MarkerService + import project as projectlib import ProjectEditor import PythonEditor import OutlineService @@ -82,16 +120,31 @@ class IDEApplication(wx.lib.pydocview.DocApp): import AboutDialog import SVNService import ExtensionService - + if not ACTIVEGRID_BASE_IDE: + import activegrid.model.basedocmgr as basedocmgr + import UpdateService as updater import DataModelEditor import ProcessModelEditor import DeploymentService import WebServerService - import WebBrowserService import WelcomeService import ViewEditor import PropertyService + import WSDLEditor + import WsdlAgEditor + import XPathEditor + import ImportServiceWizard + import RoleEditor + import HelpService + import WebBrowserService + import SQLEditor + _EDIT_LAYOUTS = True + if not ACTIVEGRID_BASE_IDE: + import BPELEditor + if _EDIT_LAYOUTS: + import LayoutEditor + import SkinEditor # This creates some pens and brushes that the OGL library uses. @@ -131,7 +184,7 @@ class IDEApplication(wx.lib.pydocview.DocApp): _("Deployment View"), XmlEditor.XmlDocument, XmlEditor.XmlView, - icon = getDPLIcon()) + icon = DeploymentService.getDPLIcon()) docManager.AssociateTemplate(dplTemplate) htmlTemplate = wx.lib.docview.DocTemplate(docManager, @@ -148,15 +201,32 @@ class IDEApplication(wx.lib.pydocview.DocApp): imageTemplate = wx.lib.docview.DocTemplate(docManager, _("Image"), - "*.gif;*.jpg;*.jpeg", + "*.bmp;*.ico;*.gif;*.jpg;*.jpeg;*.png", _("Image"), - _(".gif"), + _(".png"), _("Image Document"), _("Image View"), ImageEditor.ImageDocument, ImageEditor.ImageView, + wx.lib.docview.TEMPLATE_NO_CREATE, icon = ImageEditor.getImageIcon()) docManager.AssociateTemplate(imageTemplate) + + if not ACTIVEGRID_BASE_IDE and _EDIT_LAYOUTS: + layoutTemplate = wx.lib.docview.DocTemplate(docManager, + _("Layout"), + "*.lyt", + _("Layout"), + _(".lyt"), + _("Renderer Layouts Document"), + _("Layout View"), + # Fix the fonts for CDATA XmlEditor.XmlDocument, + # XmlEditor.XmlView, + LayoutEditor.LayoutEditorDocument, + LayoutEditor.LayoutEditorView, + wx.lib.docview.TEMPLATE_NO_CREATE, + icon = LayoutEditor.getLytIcon()) + docManager.AssociateTemplate(layoutTemplate) perlTemplate = wx.lib.docview.DocTemplate(docManager, _("Perl"), @@ -231,6 +301,34 @@ class IDEApplication(wx.lib.pydocview.DocApp): DataModelEditor.DataModelView, icon = DataModelEditor.getDataModelIcon()) docManager.AssociateTemplate(dataModelTemplate) + + if not ACTIVEGRID_BASE_IDE and _EDIT_LAYOUTS: + layoutTemplate = wx.lib.docview.DocTemplate(docManager, + _("Skin"), + "*.skn", + _("Skin"), + _(".skn"), + _("Application Skin"), + _("Skin View"), + SkinEditor.SkinDocument, + SkinEditor.SkinView, + wx.lib.docview.TEMPLATE_NO_CREATE, + icon = getSkinIcon()) + docManager.AssociateTemplate(layoutTemplate) + + if not ACTIVEGRID_BASE_IDE: + identityTemplate = wx.lib.docview.DocTemplate(docManager, + _("Identity"), + "*.xacml", + _("Identity"), + _(".xacml"), + _("Identity Configuration"), + _("Identity View"), + RoleEditor.RoleEditorDocument, + RoleEditor.RoleEditorView, + wx.lib.docview.TEMPLATE_NO_CREATE, + icon = XmlEditor.getXMLIcon()) + docManager.AssociateTemplate(identityTemplate) textTemplate = wx.lib.docview.DocTemplate(docManager, _("Text"), @@ -244,6 +342,59 @@ class IDEApplication(wx.lib.pydocview.DocApp): icon = STCTextEditor.getTextIcon()) docManager.AssociateTemplate(textTemplate) + if not ACTIVEGRID_BASE_IDE: + sqlTemplate = wx.lib.docview.DocTemplate(docManager, + _("SQL"), + "*.sql", + _("SQL"), + _(".sql"), + _("SQL Document"), + _("SQL View"), + SQLEditor.SQLDocument, + SQLEditor.SQLView, + wx.lib.docview.TEMPLATE_NO_CREATE, + icon = SQLEditor.getSQLIcon()) + docManager.AssociateTemplate(sqlTemplate) + + + wsdlagTemplate = wx.lib.docview.DocTemplate(docManager, + _("Service Reference"), + "*.wsdlag", + _("Project"), + _(".wsdlag"), + _("Service Reference Document"), + _("Service Reference View"), + WsdlAgEditor.WsdlAgDocument, + WsdlAgEditor.WsdlAgView, + wx.lib.docview.TEMPLATE_NO_CREATE, + icon = WSDLEditor.getWSDLIcon()) + docManager.AssociateTemplate(wsdlagTemplate) + + wsdlTemplate = WSDLEditor.WSDLTemplate(docManager, + _("WSDL"), + "*.wsdl", + _("WSDL"), + _(".wsdl"), + _("WSDL Document"), + _("WSDL View"), + WSDLEditor.WSDLDocument, + WSDLEditor.WSDLView, + icon = WSDLEditor.getWSDLIcon()) + docManager.AssociateTemplate(wsdlTemplate) + + xformTemplate = wx.lib.docview.DocTemplate(docManager, + _("XForm"), + "*.xform", + _("XForm"), + _(".xform"), + _("XForm Document"), + _("XForm View"), + ViewEditor.ViewEditorDocument, + ViewEditor.ViewEditorView, + wx.lib.docview.TEMPLATE_NO_CREATE, + icon = ViewEditor.getXFORMIcon()) + docManager.AssociateTemplate(xformTemplate) + xmlTemplate = wx.lib.docview.DocTemplate(docManager, _("XML"), "*.xml", @@ -256,7 +407,6 @@ class IDEApplication(wx.lib.pydocview.DocApp): icon = XmlEditor.getXMLIcon()) docManager.AssociateTemplate(xmlTemplate) - if not ACTIVEGRID_BASE_IDE: viewTemplate = wx.lib.pydocview.ChildDocTemplate(docManager, _("View"), @@ -267,9 +417,21 @@ class IDEApplication(wx.lib.pydocview.DocApp): _("ViewEditor View"), ViewEditor.ViewEditorDocument, ViewEditor.ViewEditorView, - icon = ProcessModelEditor.getProcessModelIcon()) + icon = ProcessModelEditor.getXFORMIcon()) docManager.AssociateTemplate(viewTemplate) + bpelTemplate = wx.lib.pydocview.ChildDocTemplate(docManager, + _("BPEL"), + "*.none", + _("BPEL"), + _(".bpel"), + _("BPELEditor Document"), + _("BPELEditor View"), + BPELEditor.BPELDocument, + BPELEditor.BPELView, + icon = ProcessModelEditor.getProcessModelIcon()) + docManager.AssociateTemplate(bpelTemplate) + dataModelChildTemplate = wx.lib.pydocview.ChildDocTemplate(docManager, _("Schema"), "*.none", @@ -282,14 +444,13 @@ class IDEApplication(wx.lib.pydocview.DocApp): icon = DataModelEditor.getDataModelIcon()) docManager.AssociateTemplate(dataModelChildTemplate) - textService = self.InstallService(STCTextEditor.TextService()) pythonService = self.InstallService(PythonEditor.PythonService()) perlService = self.InstallService(PerlEditor.PerlService()) phpService = self.InstallService(PHPEditor.PHPService()) if not ACTIVEGRID_BASE_IDE: - propertyService = self.InstallService(PropertyService.PropertyService("Property", embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_RIGHT)) - projectService = self.InstallService(ProjectEditor.ProjectService("Project", embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_TOPLEFT)) + propertyService = self.InstallService(PropertyService.PropertyService("Properties", embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_RIGHT)) + projectService = self.InstallService(ProjectEditor.ProjectService("Projects", embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_TOPLEFT)) findService = self.InstallService(FindInDirService.FindInDirService()) if not ACTIVEGRID_BASE_IDE: webServerService = self.InstallService(WebServerService.WebServerService()) @@ -297,66 +458,134 @@ class IDEApplication(wx.lib.pydocview.DocApp): outlineService = self.InstallService(OutlineService.OutlineService("Outline", embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOMLEFT)) filePropertiesService = self.InstallService(wx.lib.pydocview.FilePropertiesService()) markerService = self.InstallService(MarkerService.MarkerService()) - messageService = self.InstallService(MessageService.MessageService("Message", embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM)) + messageService = self.InstallService(MessageService.MessageService("Messages", embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM)) debuggerService = self.InstallService(DebuggerService.DebuggerService("Debugger", embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM)) if not ACTIVEGRID_BASE_IDE: processModelService = self.InstallService(ProcessModelEditor.ProcessModelService()) viewEditorService = self.InstallService(ViewEditor.ViewEditorService()) deploymentService = self.InstallService(DeploymentService.DeploymentService()) dataModelService = self.InstallService(DataModelEditor.DataModelService()) + dataSourceService = self.InstallService(DataModelEditor.DataSourceService()) + wsdlService = self.InstallService(WSDLEditor.WSDLService()) welcomeService = self.InstallService(WelcomeService.WelcomeService()) + if not ACTIVEGRID_BASE_IDE and _EDIT_LAYOUTS: + layoutService = self.InstallService(LayoutEditor.LayoutEditorService()) extensionService = self.InstallService(ExtensionService.ExtensionService()) optionsService = self.InstallService(wx.lib.pydocview.DocOptionsService(supportedModes=wx.lib.docview.DOC_MDI)) aboutService = self.InstallService(wx.lib.pydocview.AboutService(AboutDialog.AboutDialog)) svnService = self.InstallService(SVNService.SVNService()) + if not ACTIVEGRID_BASE_IDE: + helpPath = os.path.join(sysutilslib.mainModuleDir, "activegrid", "tool", "data", "AGDeveloperGuideWebHelp", "AGDeveloperGuideWebHelp.hhp") + helpService = self.InstallService(HelpService.HelpService(helpPath)) + if not ACTIVEGRID_BASE_IDE: projectService.AddRunHandler(processModelService) + # order of these added determines display order of Options Panels optionsService.AddOptionsPanel(ProjectEditor.ProjectOptionsPanel) + optionsService.AddOptionsPanel(DebuggerService.DebuggerOptionsPanel) if not ACTIVEGRID_BASE_IDE: optionsService.AddOptionsPanel(WebServerService.WebServerOptionsPanel) - optionsService.AddOptionsPanel(DataModelEditor.SchemaOptionsPanel) optionsService.AddOptionsPanel(DataModelEditor.DataSourceOptionsPanel) - optionsService.AddOptionsPanel(DebuggerService.DebuggerOptionsPanel) - if not ACTIVEGRID_BASE_IDE: + optionsService.AddOptionsPanel(DataModelEditor.SchemaOptionsPanel) optionsService.AddOptionsPanel(WebBrowserService.WebBrowserOptionsPanel) + optionsService.AddOptionsPanel(ImportServiceWizard.ServiceOptionsPanel) optionsService.AddOptionsPanel(PythonEditor.PythonOptionsPanel) - optionsService.AddOptionsPanel(XmlEditor.XmlOptionsPanel) - optionsService.AddOptionsPanel(PerlEditor.PerlOptionsPanel) optionsService.AddOptionsPanel(PHPEditor.PHPOptionsPanel) - optionsService.AddOptionsPanel(STCTextEditor.TextOptionsPanel) + optionsService.AddOptionsPanel(PerlEditor.PerlOptionsPanel) + optionsService.AddOptionsPanel(XmlEditor.XmlOptionsPanel) optionsService.AddOptionsPanel(HtmlEditor.HtmlOptionsPanel) + optionsService.AddOptionsPanel(STCTextEditor.TextOptionsPanel) optionsService.AddOptionsPanel(SVNService.SVNOptionsPanel) optionsService.AddOptionsPanel(ExtensionService.ExtensionOptionsPanel) filePropertiesService.AddCustomEventHandler(projectService) - outlineService.AddTemplateForBackgroundHandler(pythonTemplate) - outlineService.AddTemplateForBackgroundHandler(phpTemplate) - outlineService.AddTemplateForBackgroundHandler(projectTemplate) # special case, don't clear outline if in project + outlineService.AddViewTypeForBackgroundHandler(PythonEditor.PythonView) + outlineService.AddViewTypeForBackgroundHandler(PHPEditor.PHPView) + outlineService.AddViewTypeForBackgroundHandler(ProjectEditor.ProjectView) # special case, don't clear outline if in project + outlineService.AddViewTypeForBackgroundHandler(MessageService.MessageView) # special case, don't clear outline if in message window if not ACTIVEGRID_BASE_IDE: - outlineService.AddTemplateForBackgroundHandler(dataModelTemplate) - outlineService.AddTemplateForBackgroundHandler(processModelTemplate) + outlineService.AddViewTypeForBackgroundHandler(DataModelEditor.DataModelView) + outlineService.AddViewTypeForBackgroundHandler(ProcessModelEditor.ProcessModelView) + outlineService.AddViewTypeForBackgroundHandler(PropertyService.PropertyView) # special case, don't clear outline if in property window outlineService.StartBackgroundTimer() if not ACTIVEGRID_BASE_IDE: - propertyService.AddTemplateForBackgroundHandler(dataModelTemplate) - propertyService.AddTemplateForBackgroundHandler(processModelTemplate) - propertyService.AddTemplateForBackgroundHandler(viewTemplate) - propertyService.AddTemplateForBackgroundHandler(dataModelChildTemplate) + propertyService.AddViewTypeForBackgroundHandler(DataModelEditor.DataModelView) + propertyService.AddViewTypeForBackgroundHandler(ProcessModelEditor.ProcessModelView) + propertyService.AddViewTypeForBackgroundHandler(ViewEditor.ViewEditorView) + propertyService.AddViewTypeForBackgroundHandler(BPELEditor.BPELView) + propertyService.AddViewTypeForBackgroundHandler(WSDLEditor.WSDLView) propertyService.StartBackgroundTimer() + + propertyService.AddCustomCellRenderers(DataModelEditor.GetCustomGridCellRendererDict()) + propertyService.AddCustomCellRenderers(BPELEditor.GetCustomGridCellRendererDict()) + propertyService.AddCustomCellRenderers(WsdlAgEditor.GetCustomGridCellRendererDict()) + propertyService.AddCustomCellRenderers(XPathEditor.GetCustomGridCellRendererDict()) + propertyService.AddCustomCellRenderers(ViewEditor.GetCustomGridCellRendererDict()) + propertyService.AddCustomCellRenderers(WSDLEditor.GetCustomGridCellRendererDict()) + + propertyService.AddCustomCellEditors(DataModelEditor.GetCustomGridCellEditorDict()) + propertyService.AddCustomCellEditors(BPELEditor.GetCustomGridCellEditorDict()) + propertyService.AddCustomCellEditors(ViewEditor.GetCustomGridCellEditorDict()) + propertyService.AddCustomCellEditors(WsdlAgEditor.GetCustomGridCellEditorDict()) + propertyService.AddCustomCellEditors(XPathEditor.GetCustomGridCellEditorDict()) + propertyService.AddCustomCellEditors(WSDLEditor.GetCustomGridCellEditorDict()) + + if not ACTIVEGRID_BASE_IDE: + projectService.AddNameDefault(".bpel", projectService.GetDefaultNameCallback) + projectService.AddNameDefault(".xsd", dataModelService.GetDefaultNameCallback) + projectService.AddNameDefault(".xform", projectService.GetDefaultNameCallback) + projectService.AddNameDefault(".wsdl", projectService.GetDefaultNameCallback) + projectService.AddNameDefault(".wsdlag", projectService.GetDefaultNameCallback) + projectService.AddNameDefault(".skn", projectService.GetDefaultNameCallback) + projectService.AddNameDefault(".xacml", projectService.GetDefaultNameCallback) + projectService.AddFileTypeDefault(".lyt", basedocmgr.FILE_TYPE_LAYOUT) + projectService.AddFileTypeDefault(".bpel", basedocmgr.FILE_TYPE_PROCESS) + projectService.AddFileTypeDefault(".xsd", basedocmgr.FILE_TYPE_SCHEMA) + projectService.AddFileTypeDefault(".wsdlag", basedocmgr.FILE_TYPE_SERVICE) + projectService.AddFileTypeDefault(".skn", basedocmgr.FILE_TYPE_SKIN) + projectService.AddFileTypeDefault(".xacml", basedocmgr.FILE_TYPE_IDENTITY) + projectService.AddFileTypeDefault(".css", basedocmgr.FILE_TYPE_STATIC) + projectService.AddFileTypeDefault(".js", basedocmgr.FILE_TYPE_STATIC) + projectService.AddFileTypeDefault(".gif", basedocmgr.FILE_TYPE_STATIC) + projectService.AddFileTypeDefault(".jpg", basedocmgr.FILE_TYPE_STATIC) + projectService.AddFileTypeDefault(".jpeg", basedocmgr.FILE_TYPE_STATIC) + # projectService.AddFileTypeDefault(".xform", basedocmgr.FILE_TYPE_XFORM) # don't register xform as a default, must be explicitly added + + projectService.AddLogicalViewFolderDefault(".wsdlag", _("Services")) + projectService.AddLogicalViewFolderDefault(".wsdl", _("Services")) + projectService.AddLogicalViewFolderDefault("wsdl.php", _("Services")) + projectService.AddLogicalViewFolderDefault("wsdl.py", _("Services")) + projectService.AddLogicalViewFolderDefault(".xsd", _("Schemas")) + projectService.AddLogicalViewFolderDefault("xsd.php", _("Schemas")) + projectService.AddLogicalViewFolderDefault("xsd.py", _("Schemas")) + projectService.AddLogicalViewFolderDefault(".bpel", _("Processes")) + projectService.AddLogicalViewFolderDefault(".xform", _("XForms")) + projectService.AddLogicalViewFolderDefault(".lyt", _("XForms/Skins_and_Layouts")) + projectService.AddLogicalViewFolderDefault(".skn", _("XForms/Skins_and_Layouts")) + projectService.AddLogicalViewFolderDefault(".xacml", _("Security")) + projectService.AddLogicalViewFolderDefault(".css", _("XForms/Static")) + projectService.AddLogicalViewFolderDefault(".js", _("XForms/Static")) + projectService.AddLogicalViewFolderDefault(".gif", _("Images")) + projectService.AddLogicalViewFolderDefault(".jpeg", _("Images")) + projectService.AddLogicalViewFolderDefault(".jpg", _("Images")) + projectService.AddLogicalViewFolderDefault(".py", None) + + self.SetDefaultIcon(getActiveGridIcon()) if not ACTIVEGRID_BASE_IDE: embeddedWindows = wx.lib.pydocview.EMBEDDED_WINDOW_TOPLEFT | wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOMLEFT |wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM | wx.lib.pydocview.EMBEDDED_WINDOW_RIGHT else: embeddedWindows = wx.lib.pydocview.EMBEDDED_WINDOW_TOPLEFT | wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOMLEFT |wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM if self.GetUseTabbedMDI(): - frame = IDEDocTabbedParentFrame(docManager, None, -1, wx.GetApp().GetAppName(), embeddedWindows=embeddedWindows) + self.frame = IDEDocTabbedParentFrame(docManager, None, -1, wx.GetApp().GetAppName(), embeddedWindows=embeddedWindows) else: - frame = IDEMDIParentFrame(docManager, None, -1, wx.GetApp().GetAppName(), embeddedWindows=embeddedWindows) - frame.Show(True) + self.frame = IDEMDIParentFrame(docManager, None, -1, wx.GetApp().GetAppName(), embeddedWindows=embeddedWindows) + self.frame.Show(True) wx.lib.pydocview.DocApp.CloseSplash(self) @@ -365,19 +594,38 @@ class IDEApplication(wx.lib.pydocview.DocApp): if not projectService.OpenSavedProjects() and not docManager.GetDocuments() and self.IsSDI(): # Have to open something if it's SDI and there are no projects... projectTemplate.CreateDocument('', wx.lib.docview.DOC_NEW).OnNewDocument() - TIPS_FILE_PARTS = ("activegrid", "tool", "data", "tips.txt") - tips_path = activegrid.util.mainModuleDir - for segment in TIPS_FILE_PARTS: - tips_path = os.path.join(tips_path, segment) + tips_path = os.path.join(sysutilslib.mainModuleDir, "activegrid", "tool", "data", "tips.txt") + + # wxBug: On Mac, having the updates fire while the tip dialog is at front + # for some reason messes up menu updates. This seems a low-level wxWidgets bug, + # so until I track this down, turn off UI updates while the tip dialog is showing. + #wx.UpdateUIEvent.SetUpdateInterval(-1) + #appUpdater = updater.AppUpdateService(self) + #appUpdater.RunUpdateIfNewer() if not ACTIVEGRID_BASE_IDE: + wx.UpdateUIEvent.SetUpdateInterval(-1) + appUpdater = updater.AppUpdateService(self) + appUpdater.RunUpdateIfNewer() if not welcomeService.RunWelcomeIfFirstTime(): - if os.path.exists(tips_path): - wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider(tips_path, 0)) + if os.path.isfile(tips_path): + self.ShowTip(docManager.FindSuitableParent(), wx.CreateFileTipProvider(tips_path, 0)) else: - if os.path.exists(tips_path): - wx.CallAfter(self.ShowTip, docManager.FindSuitableParent(), wx.CreateFileTipProvider(tips_path, 0)) + if os.path.isfile(tips_path): + self.ShowTip(docManager.FindSuitableParent(), wx.CreateFileTipProvider(tips_path, 0)) + + wx.UpdateUIEvent.SetUpdateInterval(1000) # Overhead of updating menus was too much. Change to update every n milliseconds. + + # we need this for a while due to the Mac 1.0 release which put things + # in ~/Documents/ActiveGrid Projects/demos. + # Now it should be ~/Documents/ActiveGrid Demos/ + base_path = appdirs.documents_folder + if os.path.isdir(os.path.join(base_path, "ActiveGrid Projects", "demos")): + message = _("The location where demo files are stored has changed between the 1.0 and 1.1 release as a result of improved multi-user support across platforms. In order for ActiveGrid Application Builder to find these files, they need to be moved from '%s/ActiveGrid Projects/demos' to '%s/ActiveGrid Demos'. Click OK to move the files.") % (base_path, base_path) + wx.MessageBox(message, _("Demo Files Location Update")) + import shutil + shutil.copytree(os.path.join(base_path, "ActiveGrid Projects", "demos"), os.path.join(base_path, "ActiveGrid Demos")) + shutil.rmtree(os.path.join(base_path, "ActiveGrid Projects")) - wx.UpdateUIEvent.SetUpdateInterval(400) # Overhead of updating menus was too much. Change to update every 400 milliseconds. return True @@ -408,1585 +656,2196 @@ import cStringIO def getSplashData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01\x90\x00\x00\x00\xb4\x08\x06\ -\x00\x00\x00\xba\xf5zX\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\ - \x00IDATx\x9c\xec\xbdy\xb8eU}\xf7\xf9Yk\xed\xf1\x0c\xf7\xd6\xbduk.f(\xa0\ -\x98\x14\x84B\xa4\x04J\x01\x99\x14\xa3\xa2\xf8\x9a\xe45\t&\xfd\xb6\x99\xda<\ -\x1d\xcd\x9b\xf4\x9bt\x92N:\x1d\x9f7\xe9\xc4\x98\x8ei}}\xd4\xa45J\x82\x88A\ -\x01E\x19\x15\x19\xa4(\xa6\x82\x9a\xe7\xba\xe3\x99\xf7\xb4V\xff\xb1\xf6>\xe7\ -\xdc[\x05\xea5\xa6$\xec\xcf\xf3\xc0\xbdu\xee\x9e\xce>\xfb\xac\xef\xfa\x8dK\ -\x18c\x0c%%%%%%?"\xf2X_@IIII\xc9+\x93R@JJJJJ\x16E) %%%%%\x8b\xa2\x14\x90\x92\ -\x92\x92\x92\x92EQ\nHIIII\xc9\xa2(\x05\xa4\xa4\xa4\xa4\xa4dQ\x94\x02RRRRR\ -\xb2(J\x01)))))Y\x14\xa5\x80\x94\x94\x94\x94\x94,\x8aR@JJJJJ\x16E) %%%%%\x8b\ -\xa2\x14\x90\x92\x92\x92\x92\x92EQ\nHIIII\xc9\xa2(\x05\xa4\xa4\xa4\xa4\xa4dQ\ -\x94\x02RRRRR\xb2(J\x01)))))Y\x14\xa5\x80\x94\x94\x94\x94\x94,\x8aR@JJJJJ\ -\x16E) %%%%%\x8b\xa2\x14\x90\x92\x92\x92\x92\x92EQ\nHIIII\xc9\xa2(\x05\xa4\ -\xa4\xa4\xa4\xa4dQ\x94\x02RRRRR\xb2(J\x01)))))Y\x14\xa5\x80\x94\x94\x94\x94\ -\x94,\x8aR@JJJJJ\x16E) %%%%%\x8b\xa2\x14\x90\x92\x92\x92\x92\x92EQ\nHIIII\ -\xc9\xa2(\x05\xa4\xa4\xa4\xa4\xa4dQ\x94\x02RRRRR\xb2(J\x01)))))Y\x14\xa5\x80\ -\x94\x94\x94\x94\x94,\x8aR@JJJJJ\x16E) %%%%%\x8b\xa2\x14\x90\x92\x92\x92\x92\ -\x92EQ\nHIIII\xc9\xa2(\x05\xa4\xa4\xa4\xa4\xa4dQ\x94\x02RRRRR\xb2(J\x01)))))\ -Y\x14\xa5\x80\x94\x94\x94\x94\x94,\x8aR@JJJJJ\x16E) %%%%%\x8b\xa2\x14\x90\ -\x92\x92\x92\x92\x92EQ\nHIIII\xc9\xa2(\x05\xa4\xa4\xa4\xa4\xa4dQ8\xc7\xfa\ -\x02~|\xf4\x82\x7f\x1f\xa9\x89\xe6%\xf6\x14\xe8\xa1\xfde\xff\xa7\xe9\xff\xfd\ -h\xc7\x1f>\x8f\x06\xa3\xf33\x88|\'9\xff\x1a\x86O.\x8er1bh\xef\xa3]\xe8\xd0\ -\xa1\x8b\x9f\xf3\x0f\xa9\xe7o\x93\x9f{\xe1i\xfb\xef\xa3\x7f\xbd\xdan+\x14\ -\xe5<\xa2\xa4\xa4d1\xbc\xc2\x05D\x03\xd9\xd0\xbf\x8bQT\xce\x1b@\x8f.\x01\x1a\ -\x89F\x90\xe4[8\x80\xca\x87V\x99\x1fE\xe7"c\xf2\x81W\xe6\xa7\x10\x0c\x04\xa4\ -7\xf47\x95\x1f\xe7(\x83\xb8\x19z\xa1\xf8]\x82\x11\xfd\xa1\xdcn\xa3\x17\xec\ -\x18\x1bP\x02\xdc\xc1\xf6Y\xbe\x99\x02\x94\xc9\xec\xf9S\x03B\x80\xf402\xbf\ -\xea\xfc\xa58\xea!M\x8a\xef\xbb`\x12\x88\xbb`R\xf0B\x90\xd5\\\xf4JJJJ~4^\xe1\ -\x02\x02GZ\x10G\xff+\x0c&\xea\x06\x9dK\x8d\x99\xb7E!\x1e\x83\t\xbd\\p\x04\rF\ -\r\r\xb8\x12Pv\x94F\x82p@(\x8e\xa6\x03B\xd8\x01\xdf\x1e<\xb5\xa3\xbb\x04\x10\ -\x98\x85\x1fC!0\x02p\x8a\x1d\x0bkIb\x10\xc4\x1aD\x92P\x95\x1a\xa4\x01\xe9\ -\x80\x14\xfd+7\x80\x16\xd0\x8b\x0c\xbe\x1b\xe0JC\x96F()\xadp\x98\xd4n+()))Y\ -\x14\xc2\x18\xf3R\x1e\x9eW\x00\x85\x05\xd2\x9f\xc3\xe7?\xe5Q\xbdA\xc5V:\xb7>\ -\xc0\xe4\xe3\xa7\x1d\xc4\x178w\x10\x14\x83\xfe\xb0\xabk0\xd8\x1b18\xee\xb0h\ -\x1c\xe9\xa5J\x11$H2\x04q\xfe\xd3Z=\x86\x00\xf0\x10(0\xf2\xc8\x83\x88\x14D\ -\x06:A\x9b\x0c-\x15\xca\xf1\xd1\xa8\\Wr\x0b\xc4@\x92d\xc4Z`\xa4\x8b\x138 \ -\x16\xc8\x9f\x01\x93\x81o\xffD\x1c\xc5T|\xaf\xd4\x90\x92\x92\x92E\xf1\x1fD@`\ -X<\xe0\xa8\xa1\x86\xa1}\x06q\x8bb\xf6\xbf\xd0b(\xf6Q\xc3/.\x08,\x18 \x16\xf3\ -\x9dh\xc3\xc8\xfc\xc8\x82\x0cA\x9a\x8b\x96\x15\x0f\x99\xcb\x94\xc8]g\xe0X\ -\xeb\xc6\xc8!\x0b$E\xf7ZH\xa9\xc1S\xa0\x1c\nW[f$i\xa2\xf1\xbc\xf9\xd7\xaf\ -\x99\xff\x0e5\xd0\xcb\xac\x05\xe4-0\xd2\x14\xe0\xf3\x1f\xc2\x0c-))9\x06\xbc\ -\xe2\xc7\x8e\x81\r1\x9f#f\xd5\x06\x10\xc3C\xab\xe5h\xc2Q\xec/\x8f&\x1eC\xaf\ -\t1\xdf\xdb\x04\xb9\xc5\xc2@\xceD.j\x12\xf7\x88\x13\xd9pJ\x04$C/h\xeb"\xcb\ -\x0f*\xab!\x85$X+\xc9\x8a\x8d\x11\x90\xba\x92F\n\x99\x04%\xf3\x98\xc8\xd0\ -\xf15\xd0\xee\xc0\xae\xdd\xfb\x99\x9d\x9de||\x9c5\xc7\xaf\xa0\xea\xdb3\xea\ -\x08\x96\xf9Gy\xf3%%%%?\x04\xafp\x01\xf9!\x82\xbf\x85p\x14\x83s\x7f\x14\xb7a\ -\xe8a\x97\x15\x0c\r\xfc/cy\x0c\x8eko\xa0\x18\xdaO\x15\x9b,\xf4e-\x10\x0fS\ -\x1cka\x00[H\x0c\x12-\xb0?q\x88Im\x8c\x1c\x85\x12\x02\x91_s"\xa0\xe3X1\x90@\ -\n\xec\xde\x9e\xf0\xec\x93\x8f\xb1\xe5\xc9\xc78\xb0w;\xad\xd9in|\xdb\r\xdcx\ -\xc3\xf5\x8c\xd6\x14\x196\xde\x1e\np\xfc2\x04RRR\xb2x^\xe1.\xac\xa1P\xc1\x11\ -\x7f\xd1\xf37\xe8\xbf6$ B\x91\xe6\xb1\x8f"\x99\xd5\n\xc7\xf0\xber\xfe\xc1\ry\ -L$\xff\xdbB\x91\xe8_\xd0 \xe8\xdd\xdfv\x90$6@$6\xce\x81\x83\xc1\xed\xe7\x84\ -\x15?\xa3\xa3\\y+\x82\x83\x07`\xdf\x1c\xdc\xff\xfc~\xf6\xce\xcc\xb0k\xeb\xb3\ -\xecyq\x0b\xf1\xec\x01V\x8ez\x9cw\xeaq\xac;n\x82[~\xfefFC\x17Gd\xa4q\x8f \ -\x08P\xd2^H\xb7\x17Q\t\xc2#\xee\\III\xc9\x0f\xc3\xabH@\x86\xc2\xc9\xc2\xe4\ -\x16\x84\xe8\x0b\x88\x8b\rvS\xa4\xc5\xc2PM\xc7p\xadD.\x0c\xda\xd8(\xbaq\x8e\ -\xe2\x03K\xed\x89\xc5P\xea\xafP \xed1\xb2\x97_\xb0\x9ew]s)\xaf9\xb9\x86\x8f\ -\x8ds@b3\xafLF\xda\xed\xe2\xb8.x\xc5_\xcb4\xde\x92\x92\x92\x1f\x9dW\xb8\x0b\ -\xeb\x87p\xc1,(\xb0\xb3\x0c,\x88^\x1c\x13x\x1eQ\xd4$\xf0\xa4\xad\x93\xd0)h\r\ -N\x00\xd2JK\x91\xf8\xdb?\x8a\xd4\x90i;(K\x99\xa7\xf2\x0eek\x89<\x96!\xa0\xdd\ -\xe9\xe2WF\x98j\xb7\xa9U\xab\xc4@\xd7@M@\x15I\x16C36\x04u\xc1\xde\x06<\xf4\ -\xfd\x03\xdc\xfd\xc0w\xd9\xfc\xe2v\xa6\xda=R\xe1\x10\xa5\x828\x01GU\x08\xbd\ -\x11\x8c\xe3\xd0\xc9b\x94\xe3\x91\xc6M\\\x93q\xe6\xbaS\xf8O7l\xe2\xc6K\'\xa8\ -\x00\xbd.\xd4C\xec{21E\xb8\xdf\t\x8b\xa2\x92\xfcz\xcb:\x90\x92\x92\x92E\xf0\ -\x8a\xb7@^\x9a\x81\xc5\xa15h\xad)\xde\xaa\xe38\x08!l\x16\x15\xa0\xd0d\xd1\ -\x1c\xbe/@\'\xd6\n\xc9\x0c\xb8!h\x8fD\x06h!\x07\xb2c\x0c\x0e\x19jH\xbdL?\xe7\ -\xca\xa6\x10\xa7\xd8\xe1:\xce\x7f\x17C\xaf\x1d\xea\xc1\xae\xdd-\xb6~\xffQ\ -\xe4\xe4n~\xedW\xde\xd7\xb7:\xa6Rx\xef\x07\xfe\x8a]\xd3\x1d2\xbf\xcaL\x14\ -\x93\xe1\xe2\x04!aPG\'\x82n+B\x18\x87Z(\xe9\xb5\xf7P\x0fR\xdet\xe9E\xfc\xd2\ -\xfb\xae\xe0\x8c\x89\xbc,\xa4\x0b\x13\x95\xc2\xc2\xc9\xad\x0fL^\x08S\xd4\x7f\ -8 r1))))\xf9\x11y\xc5[ /\xe5\xc32C\x83\xa2\x90\xd8\x02:\x86R\\\x8d\xd5\x08$\ -\xc4FS\xf1\x03\xfa\x11\x07Q\xb4%q\x88\xf0\xc8\x84\xec\xc7$\x00\x94\x10d\xf9\ -\xadK\x19\x88D\x11\x02\xc9\x18\xb8\xa2\x9e{\x11\xb6\xef\x99d\xcb\xb3\xdb\xd9\ -\xbe\xeb\x00\xcfo\xdd\x81\xf4\x02\xb4QLm\x7f\x92\x8f\xfd\xce\xcf\xd2\xe8B#\ -\x86\xa6\x86\xcf\xfc\xf3\x93\xec\x9a\x8c\xf0\x96\x1e\xcf\\l\xa8T|zi\x861\x82\ -\x04\x07%\xc1\xf5\r"\x13\xf8t9\xf7\xf8\x1a7]\xf7\x06\xder\xe5\xd9\x8c{\xf6\ -\x03\xf5\x04\xb8\x15Hz=\x1c?\xaf\x8c\x97\x1eE\xa8?\x13\x83:\x99~\xd0\xbf\xa4\ -\xa4\xa4\xe4G\xe4\x95/ \x05\xf3\xfaAY46P\x8cP(\xe5\xe0\x0c\x87+\xc4\xa0-H\ -\x92*B\x17\x84N\x07{*\x87,\xf3I\x95C\x04\xf4\xb0\xa2P\x9c\xc6\xcf\x7f6\x80\ -\x833\xb0ko\x8fm;\xf7\xb2}\xd7A^\xdc\xbd\x8f\x9d{\x0e39\xd3B\xb8\x01q*P\xd2g\ -dl\x9cf\xb6\x84\x8a\xa8\x10\xc5\t\xe7m\xd8\xc4u\xd7_\x80\x0b\xd4Bxq\x1b\xdc\ -\xfa\x95\xbb\xc0\xad\xd3M\x14\x8d\xb9\x16T\x05(\x05YD\xda\x9eeI%\xe4\xac\xd3\ -\x8e\xe7\xac\xd3O\xe7\xd4e\x01W\x9f7\xcaI\x13P\xf5\xec\xf5$\xbd\x0ccRT\xe8\ -\xa2\xfc\xfc\xe3\xcd+\xe53d\xbf\xec\xf2\x88b\xc9\x92\x92\x92\x92\x1f\x91\xff\ -8\x02\x02G\x15\x91 \xf0\xfb\xe5\x86QF?\xdfV\xe6\x9b\xa7\x00\xae\x9d\xdd\xbb\ -\xa2B\xd6i\xe0T\xaa }:\x99\x15\x8e\x060\x1d\xc3T\x03\x0e\x1c\x80m/nc\xc7\xb3\ -[\xd8\xb3\x7f\x86\xad;{t\xb3\x80\xc4\x80Q.\xd2\xaf\xa0\x9d\x90X\x1fO\x1c\xa4\ -\x04\x95\x90\xa8=\x87\x14\x9a\xac\x97\x11e1Q+"\xf0$7\xff\xdc{hjp$\xbc\xb0\ -\x1b\xfe\xf0O\xfeo\x12#\xe8\xf4b2\x13\xb3t\xf9\nzI\xc4\xd8h\xc8\x05\xe7\x9d\ -\xceY\xa7\x1dG\xe7\xd0\x1e\x0e\xecz\x81ucmnz\xf3\n\xd6\xb8\xe0kC\xdc\xe9\xe1\ -\x85>\x9eo\x88\xda=\xd2n\x82\x13\x04\xf9\xfd\x18\x88\xc7p\xc5\xfcK\xb5\x89,)\ -))\xf9ax\xe5\x0b\xc8Q\\X\x0b\x07\xc9BW\xa4\x9a_\x9d\xddK\xc0\r \xd107\xabY3\ -\xae\x88M\x05\xc7\xf8\xc4\x02\x9a\t\xfc\xf1_\xdc\xce\x8b\x87;<\xb3{\x9a\xfd3\ --\xb4\xd6T<\x97\x9a\xaf\x902 \xf5\x97\x93j\x9fD\x0bR\xa1\xc8\xa4\x836\x8e=\ -\xabL\xe9\xa6\x80\xe3\xa3<\x85\xa7b*^\x05\x99v8s\xdd\x89lz\xad\x15\xb2\x0c\ -\xb8\xe3\xee\xbb\xd8\xfc\xcc\xb3T&N#\x0cC&\xd6\xaee\xed)\xa7p\xc9\xeb\x8fc\ -\xf2`\x87\xc7\x1e\xfc:\x9f\xfb\xfa\xa7\xd9t\xd1z~\xfb\x97\xde\xcd\tc\xe0\x01\ -\xa6\x17\x83/\xf1B\x97,\xea\xa2\x94\xc2\xafV\x01\xe8v;\x84\x95Z\xdf\x9dWt\ -\xf6R\x1cUkKJJJ~$^\xf9A\xf4b\x1a=\xd4\xf2|X8\xba)6\xe1H\x16\x8d\x14\xad`4\ -\x9a\xd0\xec\xc0\xf7\xb6\xec \xea\xf6h\x1f\xda\xce\x07\x7f\xf1\x1ad\x1e\xf1N\ -\x14\xecm\xc0\xe5\xef\xf80mo\x9c4X\x86SYB\x10\xd8F\x84I\xa7A\xd4m"=\x97TJ2\\\ -\x12Y\x04\xa5\xddAf\x93\xd0H\x99\xa1\x1b\xb3\xf8D\xb8i\x9b\x89\x11\x8f\xdf\ -\xf8\x95[\xb8\xfeR\x9f\n\xf0\x9d\xc7\x9e\xe3\x0f\xfe\xe4oX~\xdc\xb9\x9cy\xfe\ -\x9b8\xfbu\'\xf2\xdcvx\xfc\x89-<\xf1\xc4\x83,\x1f\x91l\xba\xf8\x0c\xdey\xf5\ -\x06\xceY\xeb z]B\xd3!\x0c\x03t\xe6apPC\x11\xfd,3\x08!\x8a\xac\xe1\x057\xeah\ -\xed\xef\xcb zII\xc9\x8f\x8e3\xbf\xf0\xad\x98\xd0\x0f\x05\xa0\x8b\x17E\xca\ -\xbc\xe9\xbe\xf91\x8c\x17\xa1\xed\x88>8a^+q\xb4A\xce\xe9oV\xb8\xa2\xcc\xd0\ -\xbf\xa5\x1cl\xbd\xb0\x17T\x06\xbc\xb0/\xe2\xc0\xe4\x0c/\xee\xd8\xcb\xf6\x1d\ -{\xd8\xb7\xff\x10\x87\xa7\xe6h4\xda\xb4\xba\t\xc2\xa9\x90%1\xa67\xcb;\xdf{\r\ -\xabB\xfa\x95\xde\xc6\x85`l%]1J\xa4}:\x9d\x84F\xc7v\xbfU\x08\x94\x1b \x84\ -\xc6\x08\x8d\x91\x9a\xdc!f\x7f\x8a|\x9e\x9f\xf6\x18\x19\xa9\xd2m\xb6\x98\xa8\ -(\xc2Xs\xea\xf2\x1a\xef\xbc\xd4\xefg\x815\xc5\x18\x7f\xf8\xd1\xbf\xe4\x89\'w\ -\xf1\xf0\xf7\x9e\xe1K\xb7}\x99V\xb3\xc3\xca\x95c\xfc\xec\xf5o\xe0\xcd\x97\ -\x9e\xcd\xf9\'A\x05\xf00\x84\x81\xce[\xed\xb6\x90\xc122\xc4\xbc\x8az\xa9\x06\ -\x1dy\xe7Y\x19F\xd3\xef\x19o\xf8\xb7I\xdf\x9dW\xa5\xaf\x87\xfe)\x07\xe7>Z%\ -\xffK\xbf\xfc\xf2\xa7\xe8\xfff?\xf5l\xc8\xba\x1at\x0f\xc8?\xfd\xa2\x0e\xc7\ -\xb65\x063h\x80Y<%\xa2\x14\xd0W//\xd5\xc3\xe8\xa8,\xec\xdam\x9f-\xf5*\x7fv\ -\x1c2\xec\x17M\xd9~L\x19\n\x8d\xec\x7f!\x15\xa0\x93\x04\xe9Et\x1b\x87\tG\xc6\ -\xec\xc8\x9ah\x90\x1eI\xd4\xc5u]prA)>\x94,\xb1\xf9\xb3\xae;\xff\x8c\xc6\x0c\ -\x84\xc2\x00ZB\xaa\xc1DPq\xe9E-\x82\xc0\xa7\x18\x0e\xa3^\x8c\xefW\x98\x9eM\ -\xa9\x8e\xd9\x80v\'\xffk\x0c$\x06\x0eO\xc2\xae\xbd\x9a\xdd{\xf6\xb1\xe7\xc0A\ -v\xee\xdd\xcb\xae\xbd\x87889C\xa6\\2\\2\xe1a\x8cK&\x0245\x1bX\x0f\xc11\x19A\ -\x00=g\x96]\x1dX\x16\x82\x9b\xd9\xb8u\xbb\x03M\x1d\xd3s\x05\xd2Ud\xe4\xef[\ -\x1b2%p\xbd:\x15\x15\xd0\xea\xf4H\xa3\x0c<\xc7V$\x9a\x14H\x11\xae\xa1VQ\xcc\ -\xee\xdc\xcc\xa9k\x96\xe1vg\x18\xa5\xcb\xef\xfe\xe2\x7faI\n-\x03\x7f\xff\xd5\ -\x83\xdc\xfd\xc8\xf7y\xfe\xe9\xa7qH\x08]\xcd\xea1\x9f\xab\xdf~\x05\xef\xb8v\ -\x03k\x96XW\x95\x87=\xb42\x06\x8cg\x05\xdc\xb5\xa6\x95\x14\xc3\xbd\xb7^\x8a\ -\xe1\x8az\xf5\x12\xf51?"f\xe8?i\x07d\x8d\xc1 \xf2\xeb\x91\x83uP\x86\xd5L\x80\ -A\xf7\x07\x7f\xb0M+\x8f\xb8\xf6\x05\xd6\xe4\xbc\xf7hl{\x9a\x1e\x1a\x81\x83\ -\x07\x90\x80\xa3\xb1\xff\x13]\x90\x89\x15\xf2\xcc!\x8a\x03\x1c\xcf\x01U\xc4\ -\xbe"$).a."%\xafJ\xb4\x86$\xb5\xfem\xd7\xa6\x93$\xa9F)\x89\xe8\xafv\x90?\xdb\ -&\xa3\x1b\xf5\xf0\x83\x80\x0cM;\xee2\xe6-\xf9\x89>?i\x9a\xe28\x0eY\x96\x91$\ -\tA\x10\x10E\x11RJ\\\xd7%\x8ec<\xcf#\xcb2\x94\xb2\xd7_\xbc\x06\x90e\x19q\x1c\ -\x13\x86Gv\x9c0\xc6`\x8c\xf5V\x00\x08!\xfa\xfb\xce\xcd\xcd1::\xfa\x03\xaf\ -\xcf\x19|\xb15f\xa8\xf5F\xe1+\xef\xb44\xa1\x07\x18M8R\x032\xb2^\x82TKA\x83\ -\x1b\x86\xfd\xb6\x1dY\x9c\xa2\xb5FJ\x89t\x1c\xc4B\xf1\xa08\x97\xc2\x18;\xce&\ -\x1d\xf0\xab\x928\x0bQ\x022\xe5\x93"\xf3\xcc \x07\'pi%\xe0\x8e9l\xd9\x07\xdf\ -}\xfa /\xee;\xc4\xa1\xd9\x19\x9ex\xfaY\xa6g\xbaD\xa9!N\r\x08\x17\xe9\x06h\ -\xe9\x12e\x1eQ\xb6\x1c\xd7\xab\xa2q0\xb90\xdaF\x85y\x9bC\x93\xe1\xeb\x88Tdte\ -\x85\xc9\xc8Z-\x1e1\x12\xcf\xc6L\x94$\xca\x0c&\x8e\xc1s\x90\x95\x11\xa4\x94\ -\x88\xb4C\x1a\xa7L\xcf\xb5\x11\xca\xc3\x0b}\x942\xa4Y\x97$\x9a\x83\xb4\x8d$\ -\xc2\t$\xe7\x9d\xb6\x86\xb3N>\x8ek/\xdb\xc8\xe5\xaf\r\xf1\xb0\xedH\xfe\xe8\ -\xbf\xdf\xc1?=\xf0\xb3\xe9\xda \x94\xc6\xef\xcb\x96\xf9\ -\xa9\xb9\x8d%\xc7\x06\x93&\x08\xafX\x14\x0e\x92,\xc5Q\xb6\xdeJ\xf9\n2\x05\ -\xb8\x10%\xf4\x92\x087\xacPqjt\xb4\x9d,\xbb\xceO\xd6z\x15Bp\xf8\xf0a\x96-[\ -\xd6\xb7"\x92$\xc1u]\x84\x10}\x01\xa8T*dYF\xaf\xd7\xa3Z\xad\xe2\xe4\x1e\xa1\ -\xe9\xe9i\xc6\xc7\xc7\x19\x19\x19\xe9\x1f\xb3\xd3\xe9\xa0\x94\xc2q\x9c\xbe\ -\x90t\xbb\xddy\xc7\xf7<\x8fv\xbbM5O\xc8y)\x9c\x85\xdf\xa0\xc2d\x93F\x0e\xc5?\ -\x00m\x90^H\x8cC\x86\x87\x16\xb0\xe7 \xac]Q\x07l\t^\x9bAzl\x11\x11\xe8\xbb \ -\x04\xa4\x02Z\x1a\xf6\x1d\xd4\xec\xdc\xb1\x8b}\x87\xdalyf\x9a\xfd\x07&\t\x02\ -M=\xe8\xf2\xd1\xdf\x7f\x1fu \xc4\xc5s\xe1\xacsN`\xc9\xda\xd3y\xe0\xbb\xbb\ -\xa8\x1dw\x12\xd1\xa8C,\x04\xed\xb9Y\x94\xf2\x11^\x05-=\x8cV$FBZ\xac\xa7\x91\ -w\x9br<{%\xc6\xdaW\xca\xd8\xf59\x94\xb6"b\x84&5\x1a\x1c\xc5\xcc\\\x07M\xc5V\ -\xac\x0bH\xa2\x8c\xc0\xf3\xe8F]\xa6\xe6\xba\xe8\xd4\xc5\rjT\xaa!\xbeL\xc9t\ -\x8f\xcck\xd3j\xce\xe0\xbb\x8a+/}-7^}!\xebO\x81\xc3\xbb\xe1\xe9\'\xb7\xf1w\ -\x1f\xff\x0c\xbb\xf6\xec&\x13\x92\x8f\x7f\xea\xc3T\xaa\xf0\x7f}\xfc\xbb\xdcv\ -\xc7\xbf2Q\xafp\xd3\x9b\xaf\xe0\xdd\xd7\xbc\x9e\x93V\xdb{\x17u\xa1\x12\xda\ -\xd4\xde\xc9\x83\xd3\xac^1N\xbf\xa9#\xcc\x8f[\xfc\xb4\x8c~\xf9u\xe8#Vp\\\xb0\ -M_\x08\ -\x9d\xe1\nc]\xa0\xe8\xdc\x15\x11\xda\x02Q\x01\x9d\xc4\xbe$\xb0\x8b6\xaa<\xef\ -M H\xa3\x0c\xc7/\xddW\xafZ\x04\x08\xdf\xcd\xc7(Id4Ij M\t]\x07OH\x9a\xb3s\xd4\ -\x97\x8c\x82\xe3\x10\xb8a\xdf\xad\x9a\xc5\x82J\x10\xfc\xc4\x9d\x9fi\x9a\xf2\ -\xe7\x7f\xfe\xe7\x1c8p\x808\x8e\xc9\xb2\x8c \x08\xf8\xec\xe7\xfeAdib\x80y\ -\xee\xa6j\xb5\x8a1\x86V\xabE\xbd^g||\xbc\x7f\xac\xc2\x82q\x1c\x07\xcf\xf3\ -\x88\xa2\xa8o\xcd\x14\x96I\xbb\xdd&\x08\x82\xfe\xb1~\x10N\xf1\xc5\x1e8\x1d\ -\x86\x83\x8bX\x15p\x01\xe5\xda\xf5%\xb4DJ+\x18#+`*\xb3\x16\xa0,n,0\xd5\x86\ -\xfd\x87aj6f\xcb\xb3/\xb0\xff\xf0\x14/\xee\xde\xcb\xbe\x03\x87h\xb4\xbbdF\ -\x80Ph\x110\xb6j\x1d;wL3R5\xf8\xd9$\x0f|\x7f\x9a\xab\xce\x1b\'5v5\xd7\xb96l\ -\xba\xfa\x06\xee\xdd\xfdU\xba\xee8Y"\xf0Fj\xc43\x99m\x0c\xd8vA\x056\x06\xe3\ -\xc8|\xda.\xc0q\xed\x01:]{U\x99\xf5]\x98\xcc\xb1\x83\x93q\x11Z\x83\x12\x98,\ -\xc2\xf5\x04\xb3\xd3\x11\x92\n\xca\x04\xb6\xb1a/\xa2\xd7\x9e#\x18\x19c\xacZ!\ -\x89\r\xdd\xa4I\x96\xcc\xa0IpE\x93k/y-\x97]\xf16.:\xcb\xa3\x0b\xdc\xf3m\xf8\ -\xbd?{\x98m\xdb\xf7\x11G)q\x94\xa1\x98\xe0\xa3\x7f\xf6\x01\x96V\xe1\xd3\xff\ -\xf88\xdf\xfc\xe2\xdf\xf0\xc1\xff\xf43\xdc\xfc\xf6\xb7r\xca\x98\xbd<\'\xb3.\ -\xd8\xba\x07q3\xc1\xf5]V/\x1b\x1f\xca2+\x04d~\r\xc7\xcb\xc7=\xfe\x1d\xc8O>p_\ -\r\x0f\xf7\x85\x180\xd8H\x0c\x0b\x8c\xb1\r,\xe7\x91o\\$Z\x88\x81\x88\xf4\x8f\ -\xc9`^c\x1bZZ\xf3\xd5\x08\x83pF\x88$\xb43[\xb7S_28\xbd\x03xh\xdc,\xa6"}\x1c\ -\xd7\x1b\xa4\xe7\x95\xbc\xea\xb0\xe3\x95\xa4\xa732\x01\x8e\x90\xc8|BQ<\x95\ -\xb5\xf1Q0\xd0m\xf6\x08\xabA?\xef^e\xee\xbfK\x01\xae\xe38\xec\xdc\xb9\x93,\ -\xcb\x98\x98\x98 \xcb2\xe6\xe6\xe6\xf8\xfa\xd7\xee4\x85\xf5Q\x88\xc7\xa7?\ -\xfdi\x1c\xc7\xa1^\xaf\x13E\x11B\x08\x9a\xcd&Zkn\xba\xe9&\xda\xed6\x8f>\xfa(\ -\xadV\x8b+\xae\xb8\x82J\xa5\xd2\x17\x90$I\xb8\xfb\xee\xbb\x99\x9a\x9a\xe2\ -\xf4\xd3O\xe7\xfc\xf3\xcf\x9f\xe7\xdez\xc9\xeb+\xbe\\z\xe8[$0\x83Q*\x8f\x8d\ -\xa7\x1a\x12\xa9\x90\xd2\xa1\x0b<\xb37_\x7fbw\xcc\xd4\xe44\xbb\xf7\xeec\xd7\ -\xbe\xfd\x1c\x98\x9ca\xae\xd1\xa6\xddK\xe9\xa5\x1a\xbc\x80\xd4HR\x14F-E\x86>\ -\xda\x08\xe2,#N\xa1\xb1k\x12*Khdm\xaa\xa2\xca\xe7\xff\xe5\xeb\xbc\xf9\xbc\ -\xf7\xe0\n{\xeaeU\xd8x\xf1\nV\xfe\xcbR^\xdc;\x0b\xee\x08q7\x86\x14\xc2\xd11Z\ -]\x89\x11y\xddE\xa6!\xedYG\xb70\xd6,\xf5\xf2\x8f9\x1f\xb8\xb4R\xc4\xdaFR\x95\ -\xd1\xf8\x08D\xa2\xf1|\x87\xd9\xc9&\x821$\xae]L\xca\x18B\xdf\xa3\x95\xf6\x98\ -m\xb70\xc6\xb0z\xcdq\\\xfa\x86\r\\y\xd9j\xd6\xaf\xb5\x87\xfe\xce\xa33\xfc\ -\xee\x9f\xde\xc5\x13Omc\xb6\xa9\xd0\xaa\x02\xb2\x86\x14\x8aZ})\xb7\xfc\xdc\r\ -\x9c\xbf\x0e\xfe\xea\xaf\xbf\xc5\xcc\xbe\xa7\xb8\xe7\xf3\x7f\xcb\x8a1\x97\ -\x11\xa5\x11\xda\xa0\x93\x04%$\xae\xb4\xe5\xe4^\xc5\x9d\xaf\x12/\x91\xa2|\ -\xcc\x19\x16\x87y\x14\x99Qz(\xf3kx\xa7\xe1\x9f\xf9\xb3\xd6\x8fX\x8a\xc11\x86\ -2\xa6\x16\x9e\xaa\xef{6\xda\xc6<\x1c\x0f!\x14=\\\x9e\xdb\x9fr\xcfC\xbby\xe4\ -\xc9]\xdcu\xdf\xc3,\x19\xf79\xe7\xec\x15\\{\xf99\\s\xe9\xd9L\xa8*\x18h\xcd6\ -\xa8\x8d\x8dP\xf2\xeaD\x03\xed$F\xbav\xf6\xdd\x04\xb6\xee\xea\xb2s\xc7~z\xed\ -\x0e\x81\xebp\xf1k\xce`\xed\x04\xb8\xa3\x01\x8d\x86\xc1u\x04ah\x9b\x94\xf6:\ -\x10\x84\xfc\xc4\' Zk\x94R4\x1a\r\xdb\xc3o(\xf0]\xb8\x9eZ\xad\x16\xdf\xfe\ -\xf6\xb71\xc6P\xab\xd5\xd8\xb3g\x0fccc(\xa5\xa8\xd7\xeb\xfd\xed\xbf\xf0\x85/\ -p\xe8\xd0!\x1a\x8d\x06\xb7\xdcr\x0b\xc6\x18\x92$a\xd7\xae]|\xf6\xb3\x9f%\xcb\ -2\xf6\xee\xdd\xcb\x05\x17\\@\xb3\xd9\xa4^\xaf\xbf\xec\xb59z\xc8\x02Y\x98"\t\ -\xd8L\xd48A\x84.\x1aI\x0c\xec\x98\x83\xdf\xfe\xfd\xbfb\xcf\xc1.\xbd\xcc\x03\ -\xe1!\xa4\x83\x91\n-\x15\x86\x80\xc4HR#\xf1e\x8d\xc4@\xa2\x05:\x05R\'\xf7\ -\xe1+p5x=F\xc7\xaat;\x92\x8a\xe3\xf2\xfd\xa7_\xe0\xee\xfb\xb7\xf2\x9eKO\xc31\ -)J8\xac\xf4\xe0\xaa\rg\xf0\xd9\xaf?NV\r\xe9D)\xc4\x11\xdd\xa8\x83q\xbc|\xb6\ -\xaa\xed\x84\xd7h\xdb\x9a\xdd\x08Df\xd0\xbd\xd4\xb6O\x9727\x95d\xde\xbb]\x90\ -\xa5\x06\xa1\r2MQ\x99\xa215\x83\xe2x\x14\x02#\xc0w=\x82 \xe0\xe43\xcf\xe5\ -\x92\xd7o`\xc3\xc5\x0e\xcb+\xd0\x05\xee\xbfw\x9aO\xfc\xfd7xz\xfb>\xba\tH\xe1\ -\x13\xf8\xe38#\x82V\xa3\x8dJ\xa7\x18\t}\xae\xbex\x03?\xb3\t^x2\xe3\xfdo\xdd\ -\xc8ik.\xa3\xae\xa0\xd7:\x80_\xab\xd8\xeb\xf1\xf3\x0f!\xe9Y\x11t}\x8e\x08\ -\xcd\xe5S\xee\x9f\xba\xc9r!\xccG\x18\xf3E,\xc3\x0cb\x13\x80]0\xabXJx\xc8eU\ -\xa4\xd3\x1e\xf1\x06\xe7\xbb\xbc\x0c\xc5j\xf6\xb9\xa5\x93eV@\\\x9f\x08\x97-\ -\xfb{|\xee\xcb\x0f\xf3\xe5{\xb7\xb2\xfd`\x97%+\xd6\xb1\xaf7\xcb\xae\x87\xb6\ -\xf2\xe4\xf3\xcf\xb1u\xeb\x8b\xfc\xec\rWr\xfa\x8a\x8a\x15\x8f\x9f\xba\x1bZ\ -\xf2\xef\x89\xebzD\xc0\xe1\x0e\xdcv\xf7\xf7\xf9\xca\xdd\x0f\xf1\xe2\xaeC\xa4\ -\t\xb8B\xe3\x8b\x84\xff\xf2\xfe\x9b\xf9\xcf?s6\xc1\xa8\xc0D\xf6\x91S\x12\x82\ -\x7f\xa7\xd5<}\xdf\xc7u]\x1a\x8d\x06\xbe\xef\xe3y^?\xb8\x1e\x86!\xbd^\x8fZ\ -\xad\xc6\'>\xf1\t\xa4\x94|\xf3\x9b\xdf\xe4\x93\x9f\xfc$\xef\x7f\xff\xfb\xb9\ -\xf4\xd2K\xd9\xbbw/\xb5Z\x8d\xc3\x87\x0f399\xc9\x19g\x9c\xc1\x0b/\xbc\xd0\ -\x8fqx\x9e\xc7c\x8f=\xc6\xd2\xa5K\x99\x9a\x9a\xa2\xd5j\x01\xf4\x83\xf2/\x873\ -\x98\xd5\x15\xc1\xf2\xbc\xf2n\x08\xa5\xecJv\x1d\x9d\xd2\x96\x0e\x07\xa7#v\ -\x1d\x98DU\xd7"E\x95D\xf8\x18\r\x99\xd1d\xc6\x0e&B:\x08\xe5\xd0JR\x90\x0e\ -\xc2u\x10B\xd9\xf8\x82)FC\x83\xe3J\xe6\x0e\x1f\x02\x93\xd1\x0c$Z\xfb|\xe9\ -\x8eo\xf1\xceKO\xc3I4i\xd4fy\xbd\xca-\xefX\xc7\xedw~\x83=\x07Z\x10,\xc5\x1f\ -\x1d#\xc9R;@eI>\x13\x05O\x1a\\a\x90&\xc3\x08\x9b\xa6\x96\xe6\x99WY\xb1~\xa0\ -\xc9\x03\xd1\xa4\xb8"\x05\xd3De\x11Q{2OIM\x118\xf8\xbe\xcb\xa7\xff\xc7\x870\ -\x0e4R\xf8\xf6\x03p\xe7\xdd\xdfb\xfb\x0b\xcf\xa1\xd2\x06\xd2\xaf0\xc5\x18$6\ -\xda\x9df\n\x11\xb5\xf1L\x93\xe3\'\xea\x9cu\xe2R\xfe\xf7\xff\xf9L\\\xe0\xa4s\ -\x15\x8e\x86P\x82\x8e\x9a\xd4\xaa5\x9b:$\xb5\xbd\x96,\xb5~@\xc7\x03\x9d\x8b\ -\x87]g\xea\x88\x82\x0e\xebl,D\xfe\xd87\x138z:}\xe1\xca\xd2\xb9\xc0C\xe1p\xd3\ -E\xf68v\xf5E!\x06\xf5=\xc3)\xbbv\x15\x16\x89\x18\xb2\xb9\xc4P`>C\xa2\\\t\x19\ -\xa4\xb8\x1cl\xc3\xd7\x1ex\x96\x7f\xba\xeb{\xec\x99q\x18;\xed|\xa6\x0f\xcdP[\ -q*\xb2[c\xdb\xde-\xdcy\xdf3\x1c\xbfr-\xcb7]\xc0\xd2J\xd9L\xb2\x04\x1a=\xb8\ -\xf3\x9b[\xf8\xdc\xad\xdfd\xf3\x8e\x19F\x96\x9f\x8c\xb7t\t\x93\xb3S\xa8x\x8e\ -\xbf\xb9\xf5.\x1aq\x8f_z\xe7\xeb\x98\xf0A\xc7\xa0R\x9d\x7f\xf5~\xf21\xb48\ -\x8eq\x1c\x07\xc7q\x08\xc3\x90n\xb7K\xaf\xd7\xc3\x18C\xa7\xd3\xa1R\xa9\x006\ -\xfb\xca\x18\xc3\xaaU\xabh\xb5Z4\x1a\r\x00\xd6\xacY\xd3\xefF^\xa9T\xd8\xb8q#\ -\xff\xf8\x8f\xff\xc8C\x0f=\xc4\xa6M\x9b\x88\xa2\x88{\xee\xb9\x87k\xae\xb9\ -\x86\x87\x1ez\xa8\x9f\xf1U\xc4E^\x0e9\x98\xdfY\xfay\xcfF\xcf\xdbP\x03\x81t\ -\x90\xc0\x0b/ng\xc9\xd2\t\xe6\xba=ZB\xd3H#\x9a:\xa2\xe3\x18"\xd7\x90\xc8\x98\ -\xd8\x89Q\x15\x03n\x02\xaa\x8d\xa1\x891\xb3 \xe6@6@\xda\xdf\xd3\xd9\x03\xd4G\ -k\xe0\x86\xf4\x12\xc9L\x12\xf2\xc2\xc1\x1e\xb7}\xf3\x192\xcf\xc3\xaf\x84\xb8\ -\t\x9cT\x83\x1b7\xaegy\x90"\x93&\xda\x08t\xe6\xc2l\x8a\xaf\x03<\xedB\xa7C\ -\x14uq\xaa\nQ\x87\xa6\x99\xa5\xa3\xe6H\xe4,B\xcc\xe1\x9b\x06\xa1\xee\x12$\ -\x1d\x9cV\x13\xbfu\x98 \xd9K\xcd?D\xbd:\xc7yg/C\x99\x14\xe8 \x81z\x1d\x1e\ -\x7f\x02~\xef\xcf\x9e\xe1\xbd?\x7f+\x1f\xfb\xdb\x7f\xe6\xd9\xad\xb3\xb4:u\ -\xe2t)\x89X\r\xe68\xa8\x9c\x02\xfer\xe2L\x91\xf6f\x08\xf5$W\x9c\xb7\x94?\xf9\ -\xcd\x1bX\x06\xac@S7\t\xa1\x88 K\x90n\x08\xa6\x06\xc2\xa6\x0b\x18\\P\xbe]\ -\x7fD8\x03-w\x17|0\xc6~\x12\x02\x8d\xc2\xa00\xf9\x80z\xac(\xe2eG\xda\x1f\xc0\ -|\x8bVht\x9a`\xf2\x9e\\\xdd\xcc\xeac\xd7\xd8~c=l\x12F\xb7\xf8\xdd\xd8:\x1f\ -\x9bC7\xff\xe8\x854\x15\x9a4\xd7M\xe8\x02^\x15>\xf5\x85o\xd0RK\xf1O8\x83\x99\ -\xc33\x10\xd4ie>\xed\xb8\x06\xa3\xa7\xb1w\xd6\xe3\xcbw?J[\xd8\xe3\x1f\xcb\ -\xbbWr\xec\x91@%\x80\x7f\xf8\xfcW94\'\xd1\xde\xf1t\xc2\x139\xd4\xac\xd1[\xb2\ -\x8et\xf9\xe9\xec\xecz|\xe9\xde\x87\x99\xc5\xc6~\x1d\x0fp\x12\xc8:pD\x0c\xef\ -\xdf\x16c\x0cR\xca~yD\x1c\xc7\x18c\x08\x82\x00!\x04\x95J\x05!\x04Y\x96\xf5\ -\xf7I\xd3\x94 \x08\x90R\x92eY\xdf\xe5\x15\x04\x81m\xc5T\xa9p\xd1E\x17q\xef\ -\xbd\xf7"\xa5d\xc7\x8e\x1d4\x9bM6n\xdc\xc8\xcc\xcc\x0c###x\x9eG\x9a\xfe\xe0\ -\xf7\xf6C%\xa1\tG\x82I@H\\`\xd5\xca\xe5\xccMO\xe1W\xd6\x10\xb9\xfe\xa0XPJk\ -\x11\xa4)\xa41\xddV\xc3V\xe4\x01vE<\x18\xfe\xcaJ\xa3\x11\x95\x80v\xcf\xa6\ -\xcd\xa2}e\x03\xd6\xd2\x08D\x9e\x1e+s\xebF\x0b\x07\xe3x\xe8\x04\x9bI\x95\ -\x82\x18]A\xa7\x9d\xf2\x95G\xf6q\xc9#Mn~c\xdd\xd6\x84i8\xfb\x14\x97K/X\xcf\ -\xee{\x9f%BA\xb7I#\x9aC\x9a.\xdaxD-\x1f\xe1\xd4P#k1B\x92vR\\RTb \x9aatD\xf0\ -\xf6+\xcf\xe7\xbaM\x97p\xc6\xa9\x15;\xae\xf8\xb0\xa3\x01w|{\x8e\xc9\x17\xbe\ -\xc7\x1f\xbc\xf7\r\x8c\xf85B\xb7\xc2\x81\xc9\x19V\xad>\x8e\x03\xa9\xa122\x8a\ -\x1a\xf7\x99kw\x98\x9dm\x13:\x19K\xdc\x8clr\x0b:i\xb3\xee\xd45l\xbc\xf8\x12\ -\xce[\xbf\x96\xd7\xac\xaf!\x80Y@\x13\xe2\xe1\xe0\xa0Q\x12[\x048(\x83\xc0HH\ -\x87j!\x046\xb1\xa8H\x80\x90G\xab\xd0&\xdf\xff\x98\xaf$8\x1c\x9f\xb0"8oFo$\ -\xd2uA\xa7\x14\xb5F\xddD\xa3<\xc9T\x03\xbe\xf5\x9d\xa7\x10\xc1\x08\xd2\xaf\ -\xd1\xd3\x828\x03\xc7\xf3\x91:\xc5\xd1\x1d\xc6}\xcd\x15\xe7\xaf\xc6a\xc8Qg\ -\x06\xf7\x06\xc0+\xba-\x0b\x98\x9e\x05)<\x84\x91\x10u`\xfa ,[i\xcd\x1dc\xf0\ -\xbc\x90\xd0\x8c\xd2\x9aLAA\xcf@P\xfa\xaf^\xb5\x14\x86\xbe\'\xc1s]\x1aQ\x8a;\ -\xe2A\xd4\x83e\x13\xd0:\x0c\xe3c\xa0\xf7\xd2\x8dg\xe9\xe5\x1d\x8aL\xe1\x96=\ -\xe6\x937\xfa\x82P\xb8\xaf\\\xd7\xed\x8b\xc6\xb0\x00\x14E\x84\x85e\xb1a\xc3\ -\x06>\xf1\x89O\xf0\xe8\xa3\x8f\xf2\xe0\x83\x0fr\xd3M7\xf5\xf7)\xfe\x1b\x0e\ -\xd6\xbf\x14\xd6\x02\xc9g\x852\xaf!\x9e\xb7K.\xb0\x8e\x80\x9eNP\xd2cb\x14^\ -\xb3\xfeT\xbe\xb5\xf9 \xd4\xc6\xb1\xf5\xd2\x06\xe2\xc8n\x1f\xb8 ]+,\xd9 \xc1\ -\x13\xa3mv\x13\xda\xc6V\xa5D\xa7\xd2\x06\x8d3\x01\xa9\xc1\xe0!\xc7V37\x19\ -\xf3\xff|\xf1\x1b\\\xb6\xf1mL\x080m\xa8\xd4\xe0\xddo\xdb\xc4W\x15\xaf\xed@\ -\x00\x00 \x00IDAT\x1f\xdc\xc2\xbe\xee\x1c\x84\x1eh\x97z\xbdb\x83a\xdd\x98,\ -\xee"\xb3\x08\x93\xc4\xc4\x9d&g\x9ez\x12\x1b/~\x0b\x1b_\xbf\x8c\x13\xd7\xc2\ -\x84g?\xf6\x03S\xf0\xf4\xf3\x87\xf9\xfaC\xcf\xf3\x9d\'\x9fg\xaa9\xc79k+x\xbf\ -\xf0&\xd2$\xa2\rl\xdb\xb9\x8fF\xa7K\xd43DNd#gI\x8c[s\x19\xa9\x08\xb2\xe6\x14\ -\xab*p\xe3\xd5\x9b\xa8W\x1dj5x\xe3\xb95F\x1c[DY\xe9\xdfBE\x96\'\xa3\x8a"P\ -\x9cO\xd7\x17\x96\xda\x15\xb6\xc5\xf0L|\x90\xb2\x9ao\xa4\xf3\xc2\xa7\x05\xb1\ -\x91c\xc3@2\x84\x19\xbc\x97\xc1eIt\x96!\x04h!\xec:+\xc0\xf6]3|\xf2s\xff\xcc\ -\xfeFJ\xea\xd6\xe8f\x82\xd4H\x94\xe7"\xb2\x88\xaa\xe8\xb1\xa2j\xd8\xf8\xc9\ -\xdf\xcb\xcf\xe0\xd8\xd8\x990\xfd\xe3K\xc0w|b\xec p\xdc*\x18\t\x15\x07\xa7\ -\xa7\t&V\xd2\x8b#hMA3\x06\xe3\x12%\t\xbdx\x8au\xa7\x1cG\xbdb\xc5\xe3XKp\xc9\ -\xb1g|\t\xbca\xc3\xf9\xdc\xf1\xc06f\xf7\xed\x00S\xc5w&\x88t\x03ff\xa8\xfa)g\ -\x9f\xb4\x86@B\xa5xf\x94\x07if\xe3\x96\xc7\x90$Il\xe7\x8f\xfc?\xb0.\xac,\xcb\ -h4\x1a\xfd@y\xe1\xe6J\xd3\x94n\xb7\x8b\xef\xfb\x9c\x7f\xfe\xf9\xdc~\xfb\xedh\ -\xad9\xe7\x9cs\xc8\xb2\x8cN\xa7\xc3\xaaU\xab\x00~8\x01\x19$M.\xb0@\n\x04\xa0\ -u\xee\x9dJp\xf1\x08\x0c\xbc\xf5\xca7\xf2\xdd\xcd\xff`\xd7\xebv\xac?\xce\xf6\ -\x8aJl\x05\x97\x04\xebx\x02\xdbG\x06$\x86l\xe8,\xfd3J\xd7.\xe0\x1d\xf8\x98\ -\xe6,\x08I\xb8\xec$\x9e|f3\xff\xef\xad{\xf9\xf5w\xaca\xbcf\x07\xfe\xd7\x9c\ -\x08\x17\xac[\xce\xbe\xc7\xf6\xa2\x96\x9f\x8e\x96k\x98\x9b:\x0c\x9d\x03\xe0\ -\xc4,\xaf\xa4\xac[\xbd\x84k/\xbb\x90+/;\x8b\xe5\xe3\x83\x1a\x95\x18\xf8\xd6\ -\x16\xf8\xc2\x97\x1f\xe4\xd1\xa7^ \xd5.\x9df\x84F\x12\xd6\x8fc\xff\xd4\x0c\ -\xb3\x11\x98\x86\xa6\xb6\x0c\xa4S%\xc9\x0cc\xabW2;s\x18\xd7\x95\x1c\xbfn-\ -\x87\xf6oc\xf2\xd0\x0e6\xac?\x99\x0f\xff\xc2/\xf0\xad;nc\xe9\xc4\t\xbc\xe3\ -\xba\xf3m\x98\xde\xc0\xa8\x80\xa9\xc9\x03\xac\x98X\xdaw\xf0\xe8\\<\x8c\xb0^\ -\x95\xfe\x87p\x94\x0f\xe6\xa5?\xb6|G\xb3\xe03:\x96\x14\xf1\xb2\x85\xd6RnN\ -\x19#\xd0\x1aP\x0eRYq\xcdd\xc0\xb6\xddS\xf4\xea\xab\x89M\x9d\x8e\x96dF\xe2\ -\xa4\x0eR;h)\x19E\x932\xf4\x9c\x0c\xd5\x93\xc8!\xf1\xed\xb4\x1b\x84\xd5\x11N\ -Z\x05\x17\x9e\xb3\x8a}\xf7>\x8a\xe9y\x8c,]\xc1t\xbbK\x1a\xc0x\xe0\x90\xcdN\ -\xa1\xa2\xfdl\xba\xe4\n\xbc\xcc\xce\x9e\x8e\xf5\xad+9\xb6\xb4\xdbm\xbcj\x95w\ -\xdcp\x19\xbb\x0f\xb5xfw\x93\x8e2\x88\xd9\xe7\td\x8b\xb9]\x8fq\xde\xc5\xeb\ -\xf8\xa5\x1b/g\x85\xb4S\xe5f\xb3\xc9HX\xcf\xbf\x8a\xc76\x89\xa5\xa8H\x07\xfa\ -q\x92,\xcbX\xbe|9\xc6\x98~E:@\xab\xd5btt\x94z\xbdN\x9a\xa6\\\x7f\xfd\xf5\xdc\ -{\xef\xbd\\}\xf5\xd5\xac\\\xb9\x924M\xa9\xd5j\xf8\xbe?\xaf\xc8\xf0\xe5\xe8w\ -\xe3\x15\xc2\x0c}?\xc5 %\xdf\xc1\xa6\x96\xa2\xf3\xfeA\xe0\x1ax\xe3\x86S\xb8\ -\xe0\xccS\xb9g\xeb\x0c:QH\xd7\xc5\xf5\\\xeb\x92IR\xdb\xb7$w_\x91\x1fK/\xccC\ -\x95\x12<\xdf\xba\xbat\x8fe~\xc0\xe1\xfd\x870I\x86\x7f\xda\x19tk\x13\xdc\xfa\ -\xf5\xfby\xf7\r\xeff,\xb7\x1c*\xc0{\xde\xf2z\x1e\xdc\xfc\x05\xba\x9d\xbdt:1\ -\xabW/\xe7\x82\xf5\x1b\xb9\xe4\xfcu\\x\xa6\xe2\xa4\t\x08\x19\x18\x98\xf7<\ -\xbc\x9f\xaf\xde\xfb\x08[\xb6\x1ff\x7fCq\xb8#\xc9L\x00~\x157\xcc\x90R\x90\ -\x06\x1e\xd27H\x1fj\xcbB"\xe0\xb1\'\xb7\xb0|\xc5\x89l{q\'\xb5\x95K\xf1=\xc1\ -\x0b\x0f\xdc\xc7\xa9\x17\x9c\xc1\x07~\xf5wY=\xe2\xf0\xe7\x7f\xf2\xbb\xfc\xf2\ -\xcf\xdd\xcc\x95\x97\x9d\x83\x87m\n\xe8\t\x9b\xde\xb6z\xe9D^\x11\x0f\xa0PB\ -\x932h\xadQ\xc4\xc9\x07\x86\xb0\xbd\xcf&\xff\x14\xfa7\xce\xde\xac\x81[q\x98c\ ->\x02\x0e*\x89\xe0(\xd7\x87@yv"\x11\x03\xbd\x14\x8c\x03\xd2\r\xf1F\x96\xd1\ -\xf5\x97\x11{\xa3\xa4\xa9\x04\xa9H\x94B&-R\xd9\xc1\xa9\x0c\xd6\x91\xb7\xc7\ -\x15\xb9\x15\x92[;\xf9\xe34\x16zd\xd8g\xe3\xfd7mbzv\x92\xaf\xde\xf7$\xccL\ -\x13\x8e.\xa3\xd9h\x10\x870\xea\xf48\xfb\xcc\x95\xdct\xddF\xc6\\\x10\x89\x9d\ -\xbb\x94\xbcZ\xd1\xd4\xab\x1e1\xf0\x86\xf3\xc7\xd8w\xe0\x12\xbe\xf9\xd0V\x9e\ -{q\x1f\xcfo{\x82e\x13\x017\xbd\xfd\x8dlx\xcd\xf1\\\x7f\xfeI\xf8\x80\x8b\xa6\ -\x1b\x03E\xad\xd61f\xd8B(,\x86\xe5\xcb\x97s\xed\xb5\xd7r\xce9\xe7\xccscMLLp\ -\xc3\r7\xf0\x9a\xd7\xbc\x86N\xa7\xc3i\xa7\x9d\xc6M7\xdd\xc4%\x97\\\x82\xd6\ -\x1a\xdf\xf7\xb9\xfe\xfa\xeb\xfb\xd5\xec?\x0c\xceB7H\xdf\xa5"\x86^\xd0\xd6\ -\xb1\xe2\n\x8d&\xa5\xaa\x1c\x82:\xbc\xfb\xedW\xf3\xd4\'ncog\n\x1de8\xaa\x82r\ -=\xb2$\xb1=\xec\xdc\x904+\x8e(\x87\x9c\xd7\xc5\xd4\xcf\xc9\xcd\x83\x94\xbaL\ -\x08\xdb\x07\x183\x1d\xbaR\xd1\x9d\x9b"\xa8\xd79<\xb3\x8b\xdb\xeex\x8e5o9\ -\x8d\xd5A\x84g$W]p<\xef\xbb\xfa"\x9a1\xbc\xed\xb2\xd7p\xfa)#\x8c\xd5\x07k\ -\x93w\x80\xfb\x9f\x80{\x1f\xf8.\xdf\xfa\xcec\xe0V\x99\xebfL5\x12p]\xea\x13\ -\x13\x18\x1cZ\x8d\x06\x89c\x03\x12Qg\x8eY7#\x06k\x85x\xd0M\x12\xb6\xed\xda\ -\xc5\xf2S_\xcb\xa1\xdd\xdbP\xb5\n\xff\xf5\x8f\xfe\x80\x93\x8f\x87;o}\x80\xef\ -}\xfbv>\xf5\xb1\xdfg\xed\xb2\x00!s\x7f\xaa\xb0U\xe5\xbd\xb9\x0e\x81+!p\xf2\ -\xa2F\x032\xc3\x11Y\xff\xd6\xf6\xfb\\e\x0c\xf2\xe1DQ\xd2Y|0\xf6\xde\x99\xa1\ -\xfb6\xaf.\xefX\xba\xb1\xccQ~\x16\xff-H\x00(\xc2>\x19\x90d\x10\xa7\xa0E@\xcb\ -\xf8Dz\xd02\x12\r:U\xb4\x85\xa4\x9b\x89\xfe\x12\xbcGV\xb4\xd3\xef\xf4\xab\ -\x84A\x9a&\t\x0e\xe7\x9d\x10\xf2\xbe\xb7m\xc4w\xaa\xbc\xb0\xa7I32T\x03\xcd\ -\xb21\xc99\xebN\xe0\x86\xcb\xceg\xdd\xaa\xbcI\xe5\xb1\xcf\x80.9\xa6h\xda\xd1\ -\x0c\x8e_\xc5\xa3\xca\xbb\xaf=\x99\xb7\xbf\xe5d\x1as03\r\'\x1e\x0fd\x10\xc8\ -\x1e5\xdaDq\x17\xe5\x8d2\xb6d\x9cy\x0e\x9bcH!\x1ai\x9a\xf6\xc5b\xf9\xf2\xe5\ -\\y\xe5\x95\x84a\xd8O\xdf\x15B\xb0b\xc5\n\xae\xbb\xee\xba~\x17_\x80w\xbd\xeb\ -]x\x9eG\x92\xd8n\xec\x9b6m\x9ag\xb5\xfc \x9c\xf9\xbd0d\x1e\xce\x1dr\x8fHr?\ -\x9fD\xa2\xc8t\x82\'\x1dR\x03o\xb9t\x9c/?\xbc\x1ao\xe7a\xf6\x1eh \xc8\x10\ -\xa6\x8a!\x01\xed\x90\x89l \x1a\xc5\x00\xd0\x0f\xfc\xe6\xfdO\xe2\x0c\xa4\x8b\ -\x17V\x98=\xb4\x93\xf1\xb0\xca\xca\xfa([\x0f\xed\xc6\xafyxY\x87\xaf\xfc\xf3\ -\x97\xf8\xe05\xbf\x83\x14>Y\xd4a,\xf0\xf9\xb5\xf7\xbd\x91z\x1d\xbc\xbc\x05\ -\xc8d\x0c\xf7?\xde\xe4\xce\xfb\x1f\xe3\xd1\xe7vrh\xbaM\'\x83Dx\x18\xc7!s\x96\ -\xc0\x88\x02\x9d\xd1lE \x1a\x08_b\x92\x14g\xe98i\xaf\x8dN\x0f#\xb1\xeb\x8bw\ -\x80\xc9\xc3\x87\x98\x18]G{f?\xbf|\xcb\xfb\xb9\xe1z\xb8\xeb\xab\xf0\xdb\xbf\ -\xfe\x97\\\xb2~\r\x9f\xfd\xdb?e\xcdr{\xd8|\xf8\xa3\xd7\xd5\xd4\xf3R\xb1_\xf2\x9a^\xb9\xd4\xfc*\x19\x92\xe9\xc6\ -\x1cc#\xa3\xf8\x12F\x96\xc0\x84\x0f5\x07\x94C\xeeE\xc8\xf0\xa1\xff|km\xc3\ -\xbb\xeeO\xc9$Dk\xdd\x1f\xf8\x8d1\x84a\xd8\xcf\xa4*\xdcQ\xbd^\x8fJ\xa52\xcf=\ -U\xb4\x8a/\xb6+D\xa8p\x87\xfd \x9c\xc1\x97]!\xfa\xce\x94\xa1@\xaf!\xbfK\x12)\ -\x15^\xfe\xf0(ag\xfb\xff\xed\x7f\xb9\x9a\x9f\xff\xb5\xbf\xc6\x89\xa7\xf1\xc2\ -\x95$*\x1f\x90\xfc:F\xd6\xac\xf5\x92\xab\x1d\xaek\x9d\xff\x99-.\xc4\r\xb1\ -\xc1\xd1\x84)\r#\xe3kiE\r\xdaS{Y\xaeR\xaaZ\xf3\xda\xb3N\xe4\x9a\xcb.D\t\x88\ -\x90L5\x04\xcb\x03XS\x87f\x04;\xa7\x0c\x9f\xfa\xe2\xdd\xfc\xcb\x83\xdb8\x18\ -\xd7\xd1\xd5\tRV\x80;\x87tz\xb6H\xcd\x08\x8c\n\xc1\xad\xda\xfe\x03\x9d)p{T\ -\xebuZ8\xc8\xa0\x06\x87\x0e2>\xae\xf0#\x18ua\xcf\xbe\x84\n\x19\xaf]\xbf\x8a[\ ->\xf4V\xf6\xcc\xc2o|\xe8\xeb\xec{\xf1)\xceXU\xe1O\x7f\xe7\x9d\x1c?BQ\x9a\xd8\ -\xd7a?\xccoz!\x08H\xb28F\xb9n.\xa6\x8a4\x8d\x10RZ\xf33\x89\xecS*\x1c\xe2N\ -\x84\xf4B\x1cWa\x04\xc4Q\x82\xef\x17\xfd\x8c5E\x91\xa7@bDQ\x01b\xc8R\x8d4>N\ -\xbe\xa9N:H_\xe7\xb9\xae\xbe\xfd\xaf\x18Q\xf2\xf9\x81\xa1\rd\x18\xed#\xa5o\ -\x07\xc7(\xca\xd7D\x90\xb6w\x8d\xeb\x83\x90\xa4\xda\xea\xbc\x91\x83/\x8c\x04\ -2-Q\xd2G\t\x10$@\xdb\xa64k\x03~\xdd~\xc6\x00FS\x91\x1aL\x84\x10>\x87\x1b\xe0\ -\x8d@&\xc111t\x9bv0w\xaa\x90\x04`\\|7@d\xcd\xbe\x17\xd5\xaeL\x9fb\x9d\x93\ -\x82$\xcd\x90\xaeK\x96fxA\x00:\xc2q\x14\x98\x94\x9a\xf4\xe8\x00\xe7\x9e\x08\ -\xaf=\xd1G\x02]m\xad\x0e\t\x04\xbe\xc2MZ\xb9\xc8*\xa0J\x17\x9b\xa2\x19\xa8<\ -\xf9\xa1\x97\xe0\xf9\xae\xed(-@\xe9\x8c\xb4=\x83Su\xc08\xa4j\x846V>\xed:-\ -\xb6\xb1\x02\x06HzdY\x84\xaa\xd6\xc1\xd8\xe8b\xa2\xc1U\x1aE/Os\xaf\xf7S\xdc\ -\x07\x9a\xa8I\xba\x1d\xdc\xc0\xa7\xdbj\x13\xd6kt\xa3\x98\xc0\x0f\xf2\xdb\x98\ -b\xd2\x08\xe5b\x075-\xd0\xaaN\x9a\x9f\xbf\xf8^\x1a1\xdf\xe2\x03\x885\xe8\xd4\ -P\xf5\x04I\xd4\xc1d=*\x95\xb0\xff@\x14\xcb\x1d\x0c\xc7(\x0b1M\x93\x08L\x86\ -\x9b\x17\x96%I\x82\x11\x12\xd7q\xf3\x10\xa9\x9e\xd7\x19v!\xb3\xb3\xb3\xf8\ -\xbe\x7f\xc4\x9a\x14I\x92`\x8c9\xa2`\xad\x18\xf8\x8aN\xb1\xc0\xbcn\xb1\xc3\ -\xaf\x03\xfd\xb50\xb4\xb6\xdf\x88\x85\x03_\x92$(\xa5\xe6]\xa3\x9d\x95Kt\xa6p\ -\x95\xc3H \x07\x13\x07\x01\xa13\x88\x8fk\xed \xb4\x03\x8eO\x96j\x1c\x07\xa4\ -\x87m\x84\xa0\xcd\xbc\xd5@\x87\xaf\xa9H\xa5-\xdcA\xc3\xb1\x8a\xe2Z2\xa3\xc9\ -\xb2\x0c)%J\xda\xe7A\x9b\xfc\xef\xd8tL?\x0c\xe8t:\xf6>I\x81\x17\xf8t\xa3\x9e\ -My\xca\x8f9|\x0f\x0bq(\xc4\xa0\xf8wQp8\x1c\xdb\x18\xbeW/\xf5\xfa\xcb1\xd4\ -\x8d\xf7%v\x98\xf7\xf7A\x86\x96\xc2\xe6\xd0/\x95\xf0\xe1\xff\xe9\x97\xf8\xad\ -\xff\xed\xff$\x8ab\xa6[\x93\x10,\x03\xe1@7\x86J\x15\x02\x1f\x99e\xe8,\xb2\ -\x8f\xaa\xab\xd0:#\xebNC\x16\xe3T=T\xafAkv?+j\x927]\xfeZ\xae\xb9\xfc\xf5\xac\ -?\xcd%P\xb0\xb4\x06ss\xb6u\xc0\x92\xe5UR \xed%l\xde\xbc\x8d_\xfe\xc8_\x12\ -\x1c\xff:vL\x03cc\xa0CH\xba\xa0%\xb5\xd11\xa2v\x03)\x15:\x8e\xecB\xe8\x95\ -\x10g\xe5*T\xf7 \xadC\x93P_F\xfc\xc8#\xc8\xe3\xc6\x19\xf7%\xe3\x1e\xd0M\xe9\ -\xc4\x82?\xf8\x93\x8fr\xd2\x99\x8a/\x7f}\x86\xff\xfe\xf7\x9f\xc5\xf5\x14c~\ -\xc6_\xfc\xd1\xaf0\xe6\xd9\x14\x81y\x06\xdc0C\xb7S\xf9A^\x81o\x1f"\xd7)\xbeH\ -\xa9\x1d\x91\xd3\x04<\x1fU\xab\x91\x02\x93-\xfb\xe5\x1f\xa9\xd9\x06\x96\x18I\ -\xbe\xbb\x9d)\x0f\x05\x90\x9b3m\xc6\x97T\xf1l\x12\x1b\x08p\xc2\x1a\x88\x16\ -\xc4-p\x14\x08\x7f0\x81\x1c\xb6\x12\xd0$I\x84\xef\xe5\x02\xd3\xf7\x97:dIL\ -\xb7\x97\xa2*\x0e\xc6\xb5]\xad5\x83\xe2>7\x7f\x8f\x196\xde\xe3\xa5\n_\x83\ -\xf0C\x10\x92L84{\t\x9erp\x85\x8b\x14>q\'#\xf1!\x1c\x814\x82T\x16\x0f}\x9cg\ -\x95\x15\xcbf\x81\xd1\x8aT\xdb\xf9z\x0cxB"\xa4\x07&\xb4\xe2\x9a\x0f\xba\x9e\ -\x17\x00\td\x11\xa4\x1a\xed\x88\xc2\x13F\x82\x15\x9f"U3?S~\x86\x0c\xd2\x1ei\ -\x0cj\xa4\xcaLl\r\xa0\x04k!\x05\x81K\x94\xdf\xef\x14\x08\xa5\x8b\xe3\x07V\ -\xec\xbc\x90H\x15\xb7\xd3\xf6\x04p\x91\x83\xf5\x0b\\\x0f\xe5\xd9\x1b4\xd7\ -\xb1\x19\xea\xc6\x81\x04\x89\xc2\xc3w\x02T>YK\xf3{\x18wc\xea\xa1\x87\xeb{\ -\x90D\x84\xb5\x100\x04~\x80\x06:\xbd\x84 p\x91\x9e\x83ActL\xac\x05\xda\xc9\ -\x1b\x16\x88A=M\x96\xd9\xd6\xf5\x89\x06/\x84^\x04\xa1\x0f\xaeg\'\x1d\xa1_\ -\x03\xe32\xbd\x7f\x0f\xe3\xabV\x02\x0cM\x1e\xe7G\xb5\xda\xed\x16\xa3\xd5 \ -\x7fc\x06\xa3m\xaa\xa8F\xd0Kl\xd7Z\x18\xccX\x8d1\xa4i\xdaO-\xedv\xbb,Y\xb2\ -\x04\xb0\xc1\xe74M\x19\x1d\x1d\xb5k\xea\x08\xd1\x1f\xe4\x8aA4\xcb\xb2\xbe\ -\x108\x8e\xd3\x17\x93\xe1\x01r\xe1\xc2IJ\xa9\xfe~\x85\xf0t:\x1d\xc20\xec\xa7\ -\xa4\x16\x14\xb5\x10\xfdcj\x85P\x0e\x15o H\xb6\x9d\xf9`&np\x90\xf9\xe0\xee\ -\xc8\x81 Ie\xbf\xfd\xc6\x98\xfe\xfb\x17B\xf4{W)5tO\x872\x9a\x86So\xb3,\xc3u\ -\xec\xb9\xd2,%M\xd3~FUq\xdc\xa2H\xb0\xd7\xeb!\x84\xa0Z\xad\xda\xe0\xf9\xb1\ -\x0f\x80\xfex)\x04\x12\xa8\x03g\xac\x0c\xf8\x9d\x0f\xfe&\x7f\xfe\xf1\xcf\xe1\ -\x8c-\xa5\xa9+\xa8\xca\x12\xe6\x1a=h\xb4@\x1a\x1cW\xe3\x12\x93E\x1dt\xd2\xc1\ -WP\x0f2\x021\xc9\n\xdf\xe5\x92\x8d\xaf\xe3\xda\xab\xde\xc3\x19y\x83\xc2\xc2\ -\xb9b\x809`\xc7t\x93\xfb\x1ey\x8e\x1b\xdf\xfc:\xd2$a4\x10\\p\xe1\xe9\x9cp\ -\xf6F\xb66B\xc2\x15\x19\x91\x8a\xd0BC\xd6C\xc4\x11\xf1t\x86\xebz6\x07\xc0M\ -\xc0\x15@\x87\xb4\x95\x90&\n\x82eH\xcf\xc3;\xe3\x04*\xf1\x0c\xdd\xd9\x83LMu\ -\x98\x18\xaf\xb0\xfcd\xf8\xc6}\xf0\x7f\xfc\xd6\x17\xd9\xb9s\'\xab\x96\x8e\ -\xd3\x9a\xda\xcbG~\xed\xfd\x8c)\x08\xc5\xcb\x88\xc7\x10\xc5\xecH\x08qDq\x8eF\ -\x10g\t\xc6\xf3\xe8\x19\xe8d\xf9\xa4\xbdf\x07\x95\x83\xc0\xf3[\xa1\xd9\x88\ -\x99\x9a\x9af\xb6\xd5%5\x0e\x95\x91\xa5\x8c,\xad0V\x83\x0b\xd7U\xe9\x01SMHcX\ -\xb9\xd4\x0e"\xb3\xb33\xac\\R\xb7wP\xa4\x03\x97\x89(R\x85\xad\xf5\xe7\xfb.i\ -\x14a4\xb8A\x05\x90$)\xe8\x9ams\xdd\x05\xe6R\xd87\x05{\xf6w9<=E\xb7\xd7\xb6\ -\xe3\xa4r\x08\xc3\n\xe7\xad_\xc5I\x13\x92\x98*I\xde\x93D)\xc8\x02;\x83o\xa5\ -\x82j`\x85\xbf\x8b\xad\x8f\xd99\t\xb2:Nj\\\xa4\xc9\x1b\xb3\x98\x04L\nF\x93jA\ -+sh\xe5\xcfY\x87\x9a\x1d$E\xbe\x12%\xfd\xe4q\xd28%P>x.\xb1pi0\x10:\xbb@\x98\ -\x15\x05\x034\x9a\xb0\xb6\x0e\x15\xb7\x0e\xca\xc1\xf1}Z\x19\xa4j\xe0\xd4K\ -\xf2\xeb\x8c\x13\xd0\xae\rO\x8d\x005o\x04\xa5$(E\x96Ym\x96\xa48\x08T\x91\x15\ -\xa7\xb1\xe9\xde\xd2#E\xe2\xd4\xe0`\x1b|\xa7\xb0#=k\xe1\x08;\xe8w\x13\xfb\ -\x9c\x8f\x84^.\x04\x12\xa3S\x84Q\x90e\xc4Y\nn\x88\n\\\xba@\xa4\xa1\x9bHB?\ -\x00\x05\x87Z\xb0\xff \xec\xdev\x98\x03\xfb\xf7a\xe2\x98\xa5\xe3\xe3\xacY\ -\xb3\x86\x89\x89\x80SO\xc9\xd7\xde\x01H\xa13\x07\x13K\x00\xe33>q\x9c\xb5d\ -\x84\xf5\x89\x16i\xfc\xc5\\C\x02#\xd5\x1a\x90\x12\xf5z\xf8\xaemOd/_\xcc\x9bQ\ -\x03\xfdY\xf5\xf0`?\xec\x12)\x1a\xf3eY\xc6\xec\xecl_X\n\xd7\x89\x10\xa2\xbfN\ -Eq\xccb\x7f!D\x7f\x91\xa4\xc2\xdf\xef\xba.Zk:\x9d\x0e\xb5Z\r\xa5\x14\xcdf\ -\x93Z\xad6o\xfd\x8b,\xcb\x10B \xa5\xec\xcf\xc2a`\xe9\x14B4\xbc\xce\x06\xd0?_\ -\xa7\xd3!MS*\x95\n\x8e\xe3\x1cQ`\x97\xa6i\x7f\xd5\xbf\xe2<\xc5\xa0\xaf\x94"I\ -\x92y\xd5\xe1\x85\xb0\x14\xe2\x91fv\xffJX\xc1Q\xf3\x87\xe4(\xb6\x8bF\x15\xe3\ -GQY\xae\xb5F\x1b\x8d:\xc6\xb5`?\x96\x80\xb8\xf9T\xe5\xc41\xa8^8\xc2\xf6m\x1b\ -\xf9\x8bO\xdd\x8a\xb7t-\x8dV\x03/\xa81\xb2\xb4B\xb71\x85L:\xd4=\x8d\x17\xf4\ -\xa8\x8d9\x9cu\xfa\xa9\\t\xeeI\\\x7f\xf9\xc9\xac\xa8\x0e\xbe\xb8\x02;\x00\ -\xced\xb0ek\xc4\x13\x9b\x9f\xe6\x9eo~\x83\xf6\xdc\x0c\x87\xf7o\xa7\xd1\xbe\ -\x85\x9f{\xdb\xe5\xc4\xd8\xca\xe5\x0f}\xf8f~\xe6\x03\x9f\xc2\x8cT\xd1\xbd.8\ -\n%$c\xf5\x1a\xddF\x9b,\x15\xc8\xc0\x03\xcf\xb3.\x8b,\x06#P\xaeC\xa8\xa0\xd5\ -\x9a\xa2Zw\x99\xde\xb3\x8d\xcb.<\x99\xb1\xa5\x15\x9a\t|\xec\xf6\xbd|\xfc\xd6\ -{\xd1q\x840\x92\xb4y\x88w]\xb5\x81w\xbfy\r5\xec,\xb6\xdd\xeaP\xabU\x8e~sr\ -\x86\x97\x9a\x1c~\xf0\xa2(B\xf9\x1e\xda\x1d\xb1\xef%\xf7\xd5\xecl\xc2]\xf7n\ -\xe5\xae{\x1e\xe4\x85\xed{\xf0\xfc:\xda8\xa4Z\x92\x1aE\x82O*<\x8c\xf2\xf1\ -\xe9\x11vvs\xf2\x8a\x11\xde\xfe\xb6\x1b\xb9r\xd3J&5T%T\x96\x1cG\x8f6\x0e\xc6\ -V\x8b*\x06n5\x83\xb5J\x8au\x1f}\xbb>{\x94A7\x05\xe9CS\xc3\x03\x8f5\xb8\xef{\ -\x9b\xd9up\x86\x17w\x1fdrn\x8e,\x9f]i\x93\xa2\x93\x84\xd0\xf10I\x8fz\xc5\xe3\ -\x9c3O\xe3\xcd\x9b6r\xe9\xc5\x13\xd4\x8b\xcf\xd2\xc0G\xff\xe2\xf3\xb4:1\xedD\ -\x10\xbb\xa3d\xe12\xf67\r\xb1\x08mk\x7f\x89M\x89"\xb5E\x87\xc6\xba\xc7\xda\ -\x89\xe2\x7f\xfd\xe8=T\x98C&=\x94V8j)q\n\xc2\x83U\xe3\x0e\xbf\xf7\x8b\x97S\ -\xf7B \xa1\xd3\xd5|\xf1\x1b\x0f\xf2\xaf\x0f=\xc5\x9c\xa9\x91\xe0P\x95\x19\ -\x95\xd0#N\x12\xa4\x82\xc0U\xbc\xf3\xea\x8dl\\7A\xcdQ\xcc5;\xfc\xf5gn\xe5\ -\x80\x1e\xe7\xb9}3\xac]{<\xddV\x13\x1du\xf0}\x9fN\x02K\xaa.\xabj\x9a\x0f\xff\ -\xca[\xf1"\x89\xe7B\x96&x\xa1;\x88i\xe0\x0e\xd2\xe94\xe08D\x06\x9e\xdc\x0e\ -\x7f\xf9\xc9\xcf\xd3\xc2\x10\x8cT0\xa2\x87\xa7Bf\xf6E\x8c\x8f\xd4\x19\t\xbb,\ -\x1bU|\xe8\x96\x1b\x88b\x18\x95\x02\xe9\x87\x98n\x0b\x11V\xf0\x1d\x9b\x11X,\ -\xe5\x9cH\xd8\x9f\xc2]w=\xc7\xd7\xeey\x88\xdd{\xda CL\xa0\xe9\xc4\rh\'xY\x8be5\x87\xf3\xcf=\x857m\xbc\ -\x90\xd7\x9d{\x1c\xcb*v\x06\xe9\xa6\x905#\xbc\xaa\x8f\x94\xf0\xdc\x01\xf8\ -\x97\xaf=\xcc}\x8f=\xcbT\xc7p`\xba\x85R!\xa1Wa\xf9I\xab\xf8\x87/=\xc0uW]N\ -\xa8!\xac\xc2\t+a\xfd\xba\xb5<\xf6\xfcv\xeaKW\xd0\xeaDdi\x82\t@\x07\x86\xc4h\ -\xdb\xae9\x95\xd0\x8e\xc0s\xa8\x8fW\xf0z\xb3L\x1f\xdc\xc5\xd8X\r\x15\xb5\xf8\ -\xf4\xc7\xfe\x98+\xce\xb0\xb3\xc4\x9e\x82\xe7\x0fvh\xb5\x04+O8\x91\xc6\xce\'\ -\xd8\xf8\xda\xd3\xf9\xc3\x0f^I4\xd5!\x18\xb7\x0fT\xad\xfa\xf2\xe2\x01\xf6\ -\xe1\\\xe8\x9b\xed\xfbl\x114S\xeb\xed{v\x17\xfc\x8f\xcf\x7f\x95\xaf\x7f\xfb{\ -D\xda\xa3\xbad9\xa2v\x1c\x87\x1bm\x84\xe3#\\\x1f\x1c\x9f\x04\x87HKH\r\xedD1\ -\x1e\x1c\xcf\xde\xb6\xe6\x8f\xff\xe6\x8b\xfc\xe5\xa7\x0c\xef|\xfb\xe5\xbc\ -\xf7=\xe7\xb0\xca\x83\x99,fBY\x17\x88[\xf8\xd9\x87\xa2\xab\x06\x87\xc4@\xb7g\ -\x07\xc3X\xc1l\x06\xdf}\xb4\xc9]\x0f~\x9f{\x1e|\x8c\x96\xf6iD\x86(\x11\xe0/\ -\xa5Z\x1fAy\xb6\xd9Z\xdci\x92y.\xc6\xd1\xb4\x84`\xff\xd3s\xdc\xfb\xdc\x979\ -\xfd_W\xf3\x8ek\xaf\xe0\x9a7\xd8\xf8\xc8}\x9b\xf7\xb0\xe7\xd0,\x84\xe3\xf8c>\ -\xa9;\xc3\xa1)\xdbbD\x06^?q\xd9\xb6kN@\xb8d\xc6Z \xf7|o+Jvl\xb2\x83\tQ\xa2G\ -\x92h\x82Pp\xf2r\xc9t\x17\xfc\x00\x94p\xd1\x1e\xec\x9e\x8ex\xe4\x99\xbd\xb4\ -\xbd\x15d\xd2\xa35s\x98\x8a\xafH\x92\x08%\rK\xeb>\xaf\xdfp!\xa2\xe2`p\xf0G\ -\x02\xf0\xea\xdc\xf1\x95o1kjl=\xd0cv\xae\x85\xeb8(\xc7\xa1\xd9\x8dY>\xea3\ -\xc6\x0c?\xfb\xde\xb7r\xea\x92\n\x02\xa8\xe7s\x01\x85 \x8d;\xa0\xf2gA[\x1f\ -\xb6F\x92\nx\xe8\xa9\xed|\xfb\xfb\xdb\x98\xc9@TC\x122<\xb7J\xe7P\x8f\xf1\x91\ -\nNk+o{\xf3\x05\xfd\xc9S\xa2\r\xbe\x92\x08\xdbp\x89(\x83XY\x0bjO\x17>\xf3\ -\xe5\xa7\xf9\xec\xad\xff\xca\xdcL\x8b\x91\xb5\xa7\xd1\xf5}\xb2T\xa0{=\xc8R\ -\xa4\x11xN\x85 T\xb8\x8e \xe9\xb6\xf8\x87{\xee\xe7\x1f\xef\xb8\x9d\x8b\xce9\ -\x91\xdf\xf8\x85w\xb3\xe1\xcc:aX\xc7\xa4i>\xdb.li\xdd\x17\x91\x828\xea\xe2\ -\x15kF\xa46\xd5\xd3 \xd9\xb9g/\x8f?\xfe8\xb7}\xe9\x8b\xf3b\x19\xc5\x8c\xbb\ -\xd7\xeb\x91\xa6)+W\xae\xe4k_\xfb\x1a\xeb\xd6\xad\xe3\xaa\xab\xaeb\xfd\xfa\ -\xf5T*\x15z\xbd\x1e\x93\x93\x93|\xe4#\x1f\xe9[-Zkj\xb5\x1a\x1f\xfc\xe0\x079\ -\xe3\x8c3\xe6\xb9\x81\x8a\x81\xb4\xddn\xf3w\x7f\xf7wl\xde\xbc\x998\x8e\x91R2\ -99\xc9\xf5\xd7_\xcf\xaf\xfe\xea\xaf\x02\xb6\xb6\xe3\xbe\xfb\xee\xe3\xce;\xef\ -dnn\x0e\xad5\xcdf\xb3\x9fi477\xc7\xd9g\x9f\xdd\xb7.*\x95\n\xedv\x9bv\xbb\xcd\ -G>\xf2\x91~\xdb\x8f\xc2\xaa\xb9\xf9\xe6\x9b\xb9\xec\xb2\xcb\xfa\x96\x91\xeb\ -\xba\xfd\xe6\x86\x85\x90\x15\xdf\xed"\xbe\x01\xd6\x82\xb9\xff\xfe\xfby\xfc\ -\xf1\xc7y\xec\xb1\xc7h4\x1a\x8c\x8e\x8eR\xadV\x89\xe3\x98V\xab\x85t\x14\x9b7\ -o\xe6\xf6\xdbo\xa7^\xaf\xb3q\xe3F\xae\xbb\xee:<\xd7\xa3\xd5nQ\xa9T\xe8t:\xc4\ -qL\xadV\x9bg\xdd\x14\xae\xafc\xc9\x8f\x99C\x90\xe2\xab\x0e \xa8H\x9f\x14\xf8\ -\xe5\xf7\xbd\x8e\x17_|\x82G\x9f\xde\xca\xca\xb1q^\xf7\xba\xf3\xb9\xe2\x8d\ -\xaf\xe7\xc2\xb3j\x84\xd8\xc9Y\x11\xcc\xecb\xd7\xb1\xee)\x9fo<\xb8\x83;\xeey\ -\x88\'\xb7\x1d\xa4\xa1+\xcc$>S3\x11\xee\xd8\x1a\\\xd7ej\xf60\xb3\xa2\xc7\xea\ -\xea\x08\xb7\xdd\xf9"?\xfb\xb6Sht\xc1\x0f\xe1\xbf\xfd\xe6\x95\xfc\xe7_\xfd8\ -\xae\x11D\xc2\'u\x03\xa6\xba\x1dH\x12\x82\xf1\x11z\xad\x0e\x98\x10FF!j\xd1\ -\xdc\xf6\x1cU\xaf\xcd)+\xea\x9cx\xf2\t\xfc\xf6o]E\x08\xfc\xd3mO\xf1\xce\x8dg\ -\x93\x84\xf0\xf0\x13[\xa0V\xe3\xc0\xf6\xad,wS~\xf1\xe6\xeb\t\x81\xd1%\x1e$\ -\xad\xbc\xf1\xe1\xc2\xaf\xdbK\xdc\xa5!\xbf\xe6\xb0E\xd2\x03\x12\x07\xfe\xeaS\ -Or\xebW\xee&\x12\x1e\xd5\x15g\xd2\x9d\xed\xb2{\xa6\x8b\x1f\x06\x8c\xae8\x818\ -I\xe8$\x11q\x12\x81\xc8\xec\x9b\xaeU\xf1\xe4\x18\x9d\x999\x1a3-\xc6\x97\x9eD\ -W7\xf9\xfb/\xde\xc9do\x8a_\xff\xc0\xe5,Wc\xc4\xd8\xf5\xd4\x87\x1b/\xf4\x85D\ -\xe4\x1d\x08B\x97\x0e\xb0s\x1an\xbbg\x0b\xb7\xdd\xf5\x10\xcf\xed\x9d!V#h\xaf\ -\x8e\tk0j?\xb5\xb6\xc6.\xf3g\x14\xb8\x1e\x91\xab\xe8\xf6\xda6\x12\xecy\xd0nq\ -\xf8\x89\x1dL\xcd~\x99\xefoY\xc7\x07?p\x1e:\x18\xfb\xff\xd9{\xf3pI\xab\xfa\ -\xde\xf7\xb3\xd6;\xd7\xb8k\x0f\xbdwOt\xd3-\xf3\xd0\xcc \x83\x08\x08\x8a\x03\ -\x12G\x8c\xc6\xf1\xe4\x98\xc4\'9\xc6L7\x9eDM\x8c1\xc6LG\x13\xa3GO\x1cbPDeP@@\ -\xe6\xa1\xa1\x81nh\xa0i\x9a\xa6\xe7\xee=V\xed\xaaz\xe7\xb5\xee\x1f\xeb}\xabw\ -\xa3\x89\xc4\xf6\x06\xee}\xeez\x9ez\xf6\xd0\xd5\xbb\xaa\xdea\xfd\xd6\xfa}\'d\ -\xab\xc1T\x1f\xf4T\n\x95\x0c\xec\x1a\xc1\xd0\x10ag\xceTP\x0cPk\xa9\xach\xa3H\ -\xa2\xdc\xc6\xf2\x86\xc8d\x8d\xdc\x02I\x80\xa5\xebd"A\xba\n\xe9[T\x83\xfd\ -\xb1\xc9q\x0e\xbd\xd4b__\x12\xe2\x91\xa5\x82\xe6\xe8* \x83$"KC:IB\'\x16\xf42\ -\xd3\xcf\x96\x0e\\t\xe9\xeb\xf8\xeb\x7f\xbd\x95eG\xafa*\x14\xf4,\x9b\xe1\xb1\ -\xc5\xcc\xcdw\x11M\x9b\x8e\x8c\xe9\xce\xceq\xe7\xba\x9d,\x7f\xe5R\xda\xed\ -\x98\xa1\x86G\x14\xf6hT\x0c>e\xecZJ<\xcb\x19x{\xddv\xff\xa3d\xc10^0D;S\x90\ -\xc6\xe8\xca0LX\xe42fi+\xe6\xf27\xbc\x11\x00\xcf5\x19\xefQ\xd8\xc3\xf7\xabt\ -\xba!v\xdd\xa1\x0b|\xef\xce=|\xee+\xdf\xe1\xe9gv\xe3\xad<\x86\xc6Qct\xf6\xcd\ -\x18g?W\x98`\n!PZ\x11\xeb\x9c(7\xac\xb1\xdaH\x934\xeaPk\xd4ylO\x9b?\xfd__\ -\xe2\xad\xaf}%\x97\xbfz\r\r\xc7.tH\x0b\xa8\x80\xcf\xcboq=\x8f,M\xc9\x15\xb8^\ -@\xa6r\xd6\xae\xbd\x8f\x1bo\xbe\x85\x8d\x1b\x1ec\xa8iDiQ\x14\x11\xc7\xf1`\ -\x87Q\xa9Tp\x1c\x87\xd9\xd9Y\xb2,c\xc3\x86\r<\xf6\xd8c\xacY\xb3\x86\xf7\xbf\ -\xff\xfd\x8c\x8d\x8d\xf1\xd8c\x8f\x1d\xa0\xa0\xeet:DQ\x84\xe7y?\x95\xd5]\x16\ -\x93F\xa3A\x9a\xa6\xf4\xfb}\xa4\x94x\x9e\xc7\xf8\xf8\xb8Y\xd0$\t\xd3\xd3\xd3\ -\xdcp\xc3\r\xdcp\xc3\rT*\x15\xba\xdd.\xd5j\x95z\xbd>\xa0\xb5\x8e\x8c\x8c\x0c\ -\xac\xcaK\xe08\x08\x02\xaa\xd5\xea\x00\xac\xb6,kP`\x86\x87\x87\x07\x00~\x89u\ -(\xa5\x06\xcc\xa7\x85\xdf\x97\xf7\xf8\xfd\xf7\xdf\xcf\x03\x0f<\xc0c\x8f=6x\ -\xff\x8dF\x83$I\x06-\xbbF\xa3\x01\xd2\xb4\xa6\x92$\xa1\xd3\xe9p\xd5UW\xb1n\ -\xdd:.\xbb\xec2\xce>\xeb\xec\xc1{{>\x1e\xf2B\xc2\x9e\xfe+\xc6\xc1\x15\x10\ -\xa1\xc1\x97\xa0\xe7\x89\xc2\x0e\x95\xca\x18\xd2\x81\x7f\xfa\xe4\xfb\xb8\xe3\ -\x91\xad\x9cq\xc2\xca\xc1S5f\xc2t0\xad\xaa\xe7\xda)\x8f=\xb6\x95\xeb\xae\x7f\ -\x80-\xcf\xcd\xb2gj\x0e\xbc&\xb2\xb2\x88\x9e\xae\x90R\x85\xf1:i7$u\x03*\x8b\ -\x86\x99\xdf\xb1\x89^ \xf9\xc2\xff\xf9\x1e\'\x1e\xf7?8\xfee\xe6\xbe=c)\x9c{\ -\xccrn|p\x1bye\t\xa2\xd92v\xae\xd5\x80H8\xa0"\x90\x8a\x96\x05\xe4!\xd2\xcb9}\ -\xcd*.8\xffL.>\x7f1;;\xf0\xb1?\xbf\x8apj\x1b\xefy\xfd\xb1l\xef`\xfa\xf1\xbd.\ -+\x97\xd4\xf8\xe4\x87\xde\xcbI\xabl\xdcTC\xde\x05\xc7\xa6?7G\xa55\xfa\x82\ -\x0eS\x9e\xe7\x83mr\xd9+\x05x\xf8\xb1\x9d\xfc\xfe?\xfc\x90m\xf3>\xb3Y\x83\ -\x08\x07=\xab\xc8e\r\xab1\x84\xb6\x04\xfbff\xc1\x16\xd8\x0exU\x87\x0cM\x9e\ -\xf7\xa0\xd7!I\x05\x96=Bmb9\xfbf\xf6\x81T\x8c\x8e\xae\xe0\xfa\x9f\xbe\xfe\xf5\xaf\xb3q\xe3\xc6\x01\x161>>N\x9a\xa6LMM\x11\x86\ -\xe1`\x87\x04\xfb1\x8e\xf2{\xc7q\x06\xed\xa32\x13\xbc|\x8d$1m\xc1\xf2\xf9\ -\x0bYJ%i\xc0\xb6m\xe6\xe7\xe7\xb9\xef\xbe\xfb\xb8\xf1\xc6\x1bY\xbf~\xfd \xcb\ -\xa3R\xa9\x0c\xc8\x03q\x1c\x0f\x1e\xf5f\x83\xd9\xd9Y\x1c\xc7a\xd9\xb2et\xbb]\ -\x1ey\xe4\x11&\'\'y\xe2\x89\'x\xe3\x1b\xdf8\x08\x89J\xd3\x948\x8e\xf1}\xff?\ -\xa5\xd5\xf8\x7fr\x1c\xe4\xbb\x10\x05\r\xc7\xa5\x1aX\x05\x1fE\x12G)\x17\x9d\ -\xb0\x92~f\xee\xfd\x92\x84\x1a\'p\xeb\xbam\\\x7f\xdb\x9d\xac\x7fb\x0b\x9d\ -\xc4\xa5\xaf\x87\x10\xce(jl\x82$\x03\x94m\xe8\x9cv\xcd\xacrk\xc62\xa0?\xd7\ -\xa6\xb9l%s\xb3\xcf\xd1\xb4\x02\xbe\xf4\xad[\xf9\xe4G_\xc92\x17\xe6\xe6\x14\ -\xbf\xf5\xee\xd7\xb2n\xe3?\xb0\xcfI\t\xb3\x14R\x01\xc3#\xb0g;\xceh\x13?\xea1\ -\xfb\xcc\x13,\x1fk\xf0+\xbfr\to\xbc\xeceL4\xe1\xb6\x875\x7f\xf2g\x7f\x89\xe5\ -\x05,\x1b\x1e"\x01\x9e\xda<\xcb\xde\xadO0q\xc8*\xde}\xe9\x99\\t\xbc]l\x97\n\ -\xe9r\x9aSi\r\x13F1A\xf0\xf3\xe5\xfe\x0bU\x9de;+\x8a"\xee\x7fh\x1d\xcfM\xcf\ -\xb2O\x8f\x92\xd8.\xb8\x15\x84\xed\x1b\x93\xf6L\x91\xab\x1c\xaf\x1a T\x8c\ -\xce#t\xda+|x\x04H\x1b\xe1\x07d\x9d9\xe4\xf0(\xf4=\x883R\xabA\xbb\xbd\x9bG\ -\x1e\xdb\xcb\x83\xebfYzjkA\xd7*\x1d\xf0\x14\x05\xb69[.\xfcd}\x9f/\x7f\xeb\ -\x1a\x1e\xd8\xb8\x1d\x7f\xd1j\xbaT\xe9\xce&\xc6\xe7\xda\xb6L\xf1P\x1a<\xcb\ -\xb0\xeaJ\xca\xef\\\x84v\xa4\xa1\xf8\xd8>\xb4\xe7\xc9\xbbm\x90)+C\xbe=\x98\ -\x00\x00 \x00IDAT\x96-\xe1\xc8eC\xbc\xfe\xd2q~p\xfd!l\x9e\xec\x10\xc6\x12\ -\xfcQp,CE\xd6\xa5\x10\xa2\xd4\xa2\xc8\x81\xc2\\\xa3\xc9unV\xd8v\x0e\xda3\xb8\ -\x8d\x16 5\x81\xd0\xf8\x85\xfe\x06e\xdef\n\xa4\x99`\xae\x97BU@j\x817\x04I\ -\x1f-\x12r\x99\x90\xa9\x84L\r\x9afx\x8e\x99\xf4\xdf\xf9\xd6+\xf8\xf0\xc7\xff\ -\x96`\xc9\xb1Dn\xcd\xd0\xce\x9a\x13\x06d\xce$\xc1\xc8b\xee~\xe8\x11\xb6\xed\ -\xb9\x82%\xc5\xc2E\n\x03*\xc9"I\x12\xad\xd1\x96E&`\xa6\x07\xf7>\xfc82\xa8cy5\ -T\xa4\xa0\xd2\x00\xcf\x83n\x17t\x82C\xcc\xd9\'\x1eOK\x16\x0b\xab\xcc\xc8`\ -\xdc\x8a\xc7\\n,\xcf~\xf7\xcf\xbf\xc3\xc3\xcf\xec\xa1\x9d\x07\xa4\xa1\x84}s\ -\xa6\x1d\xebW\xcd\xcd\xa5\xfb\x08\xcc\x04frd,S\xc1\xa4o(\xca\xd25\x8c\x8f4\ -\xc4\x19\x1e\xc5m\x8c\xf1\xd0\x13O\x92~\xebV\x86G\xde\xce\x05\xab\xf7O\x02\ -\x96\x96\x85\xe6\xa1\xd4\xb1\x98s$\x80\x9d{\xf6\xf2\xf5\xaf\x7f\x9d{\xef\xbd\ -\xd7\x84\xac\xadZe\xc0\xe5\xa2}U^\xe3\xe5J\xb9\x04\xc3\xdb\xed6\xbe\xef\x93$\ -\t\x96e\xd1j\xb5\xd8\xb1c\x07\xd7_\x7f=\xb3\xb3\xb3T\xab\xd5A{Ik}\x00\x0b\ -\xcb\xf3\xbc\x9f\x99KQb\x89Q\x14\xd1\xef\xf7Y\xb6l\x19SSS\\\x7f\xfd\xf5\xdcw\ -\xdf}\xd4j5|\xdf\'\xcfs\xa6\xa7\xa7\xa9V\xabT\xab\xd5\x81\x06\xa2d\x7f-\x04\ -\xf8+\x95\xca\xe0=\xcc\xcf\xcf\x0f\xec\xd2K\xc1]Y\xb0\xcaQ\x16\x1f\xc3\xd82\ -\xbf\xcf\xb2\x8c\x1f\xff\xf8\xc7\\}\xf5\xd5\xcc\xcc\xcc\xb0j\xd5\xaaA+O)\xc5\ -\xdc\xdc\xdc\x00\xbb\xb0m\x1b\xdf\xf7\x99\x9c\x9c\x1c\xecx\xa6\xa7\xa7\x11B0\ -11A\x9e\xe7\xdcq\xc7\x1d,Y\xb2\x84\xbd{\xf7\xb2x\xf1\xe2\xc1\xb1)C\xa5\xe2$\ -\xc6w\xff\x8bR\xad\xfe\x9dq\x90\x05\xc4\x06\xdb0)\xcaN\xaa\x03\x8c\xfaF\xe6_\ -\xb1\x0c\xec\xf0\xf0\xfa\x9d|\xf3{7\xf3\xc0\x93;\xe8Z\xc3\xcc\xe6>=y$\xaaR\ -\x83\xb8g\x84d\x96\x052/T\xd9\x89\xa1\xa1\n\t\xbd\x1e\x0c5\xc1\xee\xd1\xee\ -\xb7\x19\x1d\xa9\xb1w\xe7$k\xb7<\xcd\x0f\xef8\x827\x9f\xb0\x98E-\t\r8\xf1\ -\xf81\xee\xd8\xd2!\xcc$\xd4F\xa1\x9b\x83]\xa1\x1a\xf7\x10\x9d\xcd\x9cvt\x93\ -\x0f\xfe\xda\x95\x9csj\x8d\xc9>\xfc\xf5\x97\x9e\xe0\xbb\xd7~\x1f\xbf\xd9\xe2\ -\xb9\xbds\x1c{\xdc\x1a\x12`j\xcfN\xaa\xc9>\xae8\xebb~\xf3\xf5\x87\xd2\x00l?3\ -K]<\xf0$ZH\xdc\x17P<\x80\x03@\xb82\xa8\xde\xf7}\xde\xf5\xae\xcb\xb8\xbbW\xe7\ -\x07\x0f>M\x1e\xc5f\x82\xd69\xd2r!Op-\x01q\x9f%\x8bZ,\x19]\x8e\xc83\xa6\'\ -\xf729=K\xa6R\xa4\'\x99\xf5\x1c:\xfdI\x101\x95\xa5\x8bi\xef\xdb\x87W_F\x98\ -\x84|\xeeo\xbe\xc9\xc5_\xfb\x105i4%v>\x8fU1\x17{\xb7\x17#\xaa#\xcc\x03_\xfc\ -\xd6u\xac\xdf\xbc\x8f\xc8n\xd1O=\x82\x91Ed3\xa1\xa1\xfc\x88\x14\xbf^%\xe9\ -\xb6Qa\x9fZ\xcd\'\x8aB\xb2~\xc8\xd0h\x0bG\xc0\xe4\xdc>\xa8hP\nQ\x13\x8c\xfa\ -\x01\x87\x8c8\xfc\xe5\x1f]\x80\x0f\x84S\xdb\x18\xa9,\xa6\xadR\xe6\xbb{\xa9\ -\x0c\x8d\x10\xf6\xa6\xb0\x83\x06\x99r!\x08 \x8b\xd0y\x8e\xb4-D\x96\xa3\xd3\ -\x1c\xdb\x81,\x0fA\xa7X\xb6\xc6Q\xc6\xfdY\xe6}Z\xb6\xa0\x92\x1aA\xa6o\x19_;\ -\x81Y\xa5V\xebMz\xb9\x02\xa7fH\x13\x96\x03Z\x91\xe71J+\x1c\xcb\x1a\x08?\x05\ -\x86\x0cr\xca1\xc3\x1cq\xc88[\xbb=\xb0\x0c\x85\xd6\x08`b\x18\x1a\xa6\x1b\xcf\ -`[\x01\xd7\xdcp+\'\xfc\xc6+\xa9H\n\x9e\xac_\\\x17\x9a,\xcf\xb0\x02\x87\xf9\ -\xdc\xcc\xefW}\xf7z\xb4\x1c\xa2\x1f% *\xa6\x08\xc7)\xb8\x12G\xa6\xd4{s\\q\ -\xc1Q\xd4\x95\xa9\x9a\x8e\r\xbd\x0c\x12\xdb\xd4\xbe\xbf\xfe\x97\x07\xb9\xfd\ -\xb1\x1d\xec\xe9d8CK\xf1\xfc\x06\xdd^DI6\x90smZ2\x81\xa4\x87\x12\x12\xc7\xad\ -\x90j\x97n\x02\xa9\xa8\x18-\x8ep0\xd93>I\x1a\x90$\x12jG\xb2u\xc6\xe7\x0f\xfe\ -\xec+\xfc\xe8\x9f\x7f\rK\x98PL\x0b\x8cf\xcb)\xb0\xba~\x17\xab\xda$\xcf5W]\ -\xf5\x1d\xd6ox\x1c\xcbv\r\xb9\xa0\xdf\xc5\xb5\x1d\xf24\xc3u]*\x95\n\x8b\x16-\ -\xe2\xf0\xc3\x0fg\xe5\xca\x95X\x96E\xbb\xddf\xef\xde\xbdl\xd8\xb0\x81\xe7\ -\x9e{\x0e0\xe0o\xb9R\xbf\xf1\xc6\x1b\x07\xbb\xf3\xb2%S\xb2\xa1J0\xba\xc4F\ -\x9e\xcf^*w\x18\x8dF\x83\x1d;v\x90e\x19\x9b6mbxx\x98~\xbf\x8f\xef\xfb\xc4q<\ -\x88{\x1d\x19\x19\x19`3\xa5\xa8n\xe1n\xa2\xc4.\xb2,\x1b\x80\xd5e!<\xf7\xbc\ -\xf3\x85\xca3#\x0b.\xdeK\t\xb4/\xdc\t\xdcz\xeb\xad\\\x7f\xfd\xf5\x84ah\x00\ -\xf2^\x0f\xdf\xf7\xe9v\xbb\x83\xac\xf2z\xbd\xcea\x87\x1d\xc6\x11G\x1ca\xdec\ -\x9a\xb0w\xef^\x1e~\xf8a\xb6m\xdb6`\x9b\xe5yN\xa3\xd1\xe0k_\xfb\x1a\xc3\xc3\ -\xc3\xf4z=\x1a\x8d\xc6\xa0-(\x840\xf4\xfb\x17y\x1cT\x01)\xb5\xd1\x1a\xd3\xd5\ -\x90\xba\xcc\xa9f\x00\xd6\xd6$\xdc~\xd3ml}f\x07I\xe2\xb1\xbb\xaf\x90#\xcbP\ -\xee\x08 \xa0\xde\x07\xdd7\xf4M\xcfP\x17IB#\xf8\x13\x02*\x1e\x96\x15\x93\xcb\ -\x0cTJ\x84O\x16\xd4\xd8<\xdd\xe5\xdfn\xb8\x85+\xcf\xfeU\xf6M\xf6\xd1\xa3\x15\ ->\xfeGo\xe1\x95\xef\xf8\x14C\xf5*s;\x9e\xc5]\xb4\x1cK\x870\xb7\x87\xf7\xbe\ -\xf9"\xde\xf1+\'\xd1\xf0Ln\xc4?\x7f\xe3~\xee{h\x03\xd2k1\xdd\xcdh-Y\x8d\x0cZ\ -\xc4\xc0\xdd?\xb9\x89\xb7]\xfa\n\xde\xf3\xfa\xd3i\x02\x96\xea\x15\x1f\xd2\ -\x06i\x0f\xd2\xf3\xca\x8f\xfa\x8bv#%\xf0\xc7\xff\xfd<\xf6\xfd]\xc6\x86\x8dO3\ -;\xb7\x13r\x1b\xc7\xab\xe0\x08\xc1\x9b.\xb9\x84\xd7^p\x08K\x86`\x91\xb7_\xb4\ -\xb8e;|\xf7\xbbw\xf2\xdd[\xee\xa0V[L\'\x03\xe2\x84\xfe\xde\xd4(\xf4l\x87\xf6\ -\\\x84g\xb9\xac{\x08.<\x15<\xd71T^\x12\xd2$\xa1Zm\xd2\x01\xbe\xfa\x9d\r\xac\ -\xdf2\xc9t\xe2 \x82&(\xdfx\xfd\xb8>\x90c\x91\xc3\xfc^\x86D\x8a\xeb\xa5\xe8\ -\xb8C\xd3\x02\xea\x10wv095\xc3\xcb\x8e>\x9e\xcd\xcf=\x8b\xa8T\xa9K\x9b\x11[\ -\xf0w\x9f|\x1bu\xca\x05\x85f_BD\xa0\xe6x\xcbkOgi\x05\xc8{\x90{\x08\xe9\x18\x18\ -\x05\xb8\xfe\xfey\xbe\xf7\x93\x87\x98\x17MT\xdd#\xb5\xab\x84\xb3\xf3\xe0H*\ -\xae\xa0?7\xc5\xf2!\x8f\x97\xb5,.>\xfb"N>\xf5h\x84\r{\xa6\xe0\xe9\x1d=\xeeZ\ -\xf7$w\xae{\x82(\xeab\xd7F\xc9m\x0f\xdd\x0b\xcd\xa7v\x1at\xfa1\xd5J\xc0w~\ -\xb0\x89\x0f\xbe\xf1pc\x89\x0fX\xaeiy\xe19X\x81Y\xf8\xfc\xe4\x8e\xdbyt\xfdz,\ -\xd7Ed)\xbd^\x8f\xb1V\x83\xdd{v\xd2\x1a\x1a\xe1\xac\xb3^\xc1\xf9\xe7\x9f\xcf\ -\xa1\x87\x1ez\x00\xfb\xa8\x1cQ\x14\xf1\xcc3\xcfp\xc3\r7\xf0\xd0C\x0f\r\x8a\ -\xc8\x0bI\xbc\xfb\xb9\xf7\x90\x94\x8c\x8c\x8c\xd0\xeb\xf5\x98\x9f\x9f\xc7\ -\xf3<\xb2,\xa3\xd5jq\xce9\xe7p\xe2\x89\'\xa2\xb5fll\x8c4M\xd9\xb5k\x17K\x97.\ -\x1d\x84+\xbdP\xc1\xdc\xbf7\x84\x10\xf4\xfb}\xa6\xa6\xa6\xb8\xfa\xea\xab\x07\ -\xe9\x81\xe5qh\xb7\xdbx\x9e\xc7q\xc7\x1d\xc7\x85\x17^\xc8\t\'\x9cp\x80\x8e\ -\xa5\x14g\xbe\xe1\ro`\xe7\xce\x9d\xac]\xbb\x96;\xee\xb8\x83]\xbbv\rh\xc5\xa5\ -Z\xa8D\x00\x07\xa3\xa3\xf9\xc7\xdfz\x15\x1f\xfd\xe4.\x1e\x9d\xd9\x8a\x90\ -\x0eG\x1e:\xc6_}\xe2\x9d\xd41bE\x17\xb0\x94\xd1\x05V+\xb0t9\x9c\xf0\x9e\xb3\ -\xb9\xec\x82\xa3\xf9\xc0g\xbe\xc1|\xa2\xf0\x17\x8f\x12v\x14^\xad\x89\x88\x15\ -YV\xa5\xd2lr\xfb\x1d\xeb\xb8\xe0\x94\x93\xcc\x0bJI\x9e%\xe4B\xa2qxt\xcb\x14\ -\xd7\xdct\x17\x93\xfd\x1c\xed\xb5\xb0\x83!\xe8f\xd0\xed\x83\xef!\xb2\x10\xab\ -?\x85\xea\xee\xa11\xe4\xb2d\xb8\xc6P#\xe0\xc8#\x0fgxx\x98g\xb7\xee`\xd3\x96\ -\xad<\xbde\x03\xe3^\x80\xebf\x1c~\xc82>\xf5\xb17"C\xa8\x14\x00\xf7\x15\xaf>\ -\x93PT\xd1\x95Q\xba* \xcc`jv\x8e\x9b\xee~\x98p\xd02)Z \x85e\xa7c\xe5\xd4]\ -\xcd{\xdf|9"o\xe3\x03\xbep\x91\xb1D\xa415?e\xac\x96\x15\x99\xcc\n\x89@`!\n\ -\xab\x98\xc1\xf2\xa6\x8cP\xd6\x1aKgH\x9d!\xc9\x06\x8d30\x1b\xdf\x8a\r\x97_x\ -\n_\xbd\xfaFB\x99\xd0\x919d\xa19\xdb\x99\x06a\xa1,\x9b\xa7w\xec\xe2\xa1\x8d]\ -\x16\xad\xa9Q)-b\x04DI\x8ak\xbb\xf4\x8b\xfb\xfa\x86[\xee\xa5\x9f[\xa4R\x90k\ -\x81\x14\xa0\xd2\x98\xc0RX\xe9\x1d[\xa5\x90u\xc1\x16d\x99\x8dr\ -\x04]\xe0\xea\x1b\xefb\xf3\xf6Y\x18^\x01~\x03\xa5M\xbb\xb8\xe2\t\x82\xdb\xb7o\xc7\xf7}\x16/^\xcc\xec\xec\ -\xec`\x17\xf5\xd6\xb7\xbe\x95K.\xb9d\x80\x11\x95\xc3u]\x92\xcc\x14S\xcf\xf5X\ -u\xe8*\xea\xf5:CCC\xdc{\xef\xbd\xac_\xbf\x9eZ\xad6(HI\x92\x0c\xf0\x8f\x85\t\ -\x84/\xe6\xf8%#1\xca\xb0\x84Df\xccbD\x8a\xe3\x05D\x1a~\xfd}ga\x0f/\xe6\x1f\ -\xaf\xb9\x93\x86\xe3\xd1\xee\xed\x80J\xbd\xc8\x101\xd2j\xd9\xef#\xc9\xf1\xa5\ -\xc0\x92\x0eB[\xccE)\x19i\xb1=\xd7\xa4\xdd\x0c\x82\x00\xbbQG:6\xfft\xcd\xcd\ -\xbc\xea\xd5g\xb3\xb80\xbe\xfd\xfd\xf7\xbf\x9a\xcb.\xff\r\x8e;\xfc\x18\x8e<\ -\xead\xdey\xe59\x0c\xd5\xa0f\xc1\xbf|\xfbI>\xf3O\xdf@\r-CU\x97\x10)I\x16\'x\ -\xcdQ\xe2N\x8ff-\xc0V\xf0\xb67\\\xcaq\xab\x1bd\xb1\x06\xbbtI:\xb0\xe2\x1f\ -\xcc\xce\xa3\x1c.\xd0P`\xa5\xf0\xf9?\xfcU>\xf2\xfb\x9fatd\x82?\xfe\xbdw\x9a\ -\xce]\x15\xf2\x10\x9aA\x11~V/\xb4\x12Z\xd1\xaaI\xce8v\x84W\x9e}\n_\xbb\xf5Q\ -\xa4\xce!\x8f\x89{]\xc3\xfb\xc4&J%\x8f?\xb1\x998;\t[@`\x0b\xa4]A\xe2\x11c\ -\xf3o\xdf\xfb\t\xbbf#\xfc\xe6\x12"*(\xe1\x9b\xa8\xce$E\x92`g\x1d\x16U2\xc6\ -\x87\x9b\xbc\xe9\xa2\xb3\xb8\xf2\x8a5\x04va\x8b\x01\xd8\xf2pv\xcd\xc0W\xbf\ -\xf6C\xee\x7f\xf0!\x1c\x99\xf0\x89\x0f\xbf\x91\x15\x01\x90\x1b\xb6\x9d\x05\\\ -y\xf9\xabp\xeb\x96q\xe3\xc5D\xd7>\xb6y\x057\xddv\'\xd8M\x03((\rZ\x9a\xc9VklK\ -Pq5\xef~\xcd"\x1c\x16\xe1a,F,m.1\xcb2m\x17\x13\x88\xa6QB\x03\x16B\xab\x05\ -\xbea\xa5\xfd\x8bB\x92\x15\xc5%7\x9em,\x90\xc4(\x03\xb3\x1c\xb1\x18.8c\r?|d\ -\x17^}\x84\xb8\xd73\xa2\xc0$\xc2\xae\xd4\x98\x99\x9f\xa2\xe14\xf8\xfe-ws\xe1\ -\xc9\x17\x9bH\xfb\xe2b\x90E-\xb1]\x98\x05\xeeZ\xbb\x81X\x06\xa4\x96K\x9e\x15\ -\xefE)\x9a\xbe\x83\x8ec^~\xd42\x0e\x9f\x00\xe2\xae\xf9\xecHRm\x0ca\xee^\x17\ -\xb2a\xf3v\xac\x91\xc5\xe4\xf8\x06\xcf\x88B\xbc\xe1atw\x1fi\xd4\xe6\xa2\x0b/\ -\xe6\xd7\xder$\xcb\x02\xb0u\n\xb9B\xa7\x1a[\xb8\xd8\x9e\xe4\xf0q\x98\xb8b\ -\x19\xdb\x9e;\x9ck\xefx\x08%c|\xcf%\x17\x1a\xcfu\x88\xad\x9cDk\xb6M\xce\xb1\ -\xfei\xcd\xe9G\x1a\xb5\xa1\'0,\xbf~\x07\\\x9f\xb5k\x1f\xe2\xd9m\xdb\x19\x1d\ -\x1bgrz\x86\xe6P\x1d2\x9f<\xeeq\xe5\xdb\xdf\xce\x9a5k(m\x17J\xe3\xbe\x85+\ -\xe6J\xa5\xc2\xde\xbd{\x19\x1f\x1f\xa7\xd1hp\xce9\xe7099\xc93\xcft\x0e\xe3M\x98\x8d\ -\xe1}\xbfw\r\x7f\xf3\xe5\xeb\xa9\x8f\x1fOf\r\x1b\xcai\xda\'\x0bs\xdc\xa0\x81\ -_\xf5\x18\xaf:T5\x9cu\xf2\xd1\x00hG\x98\xc8BY\x98\xfd\t5\x80{\x7f\x19k\x17[\ -\xc3\x08p\x88\x03\xcb\x80\xbf\xff\x83\xdf\xe5\x13\xbf\xf9N\xaa\n\xea\xb9q}\ -\x1a*V\xf1Y\xd2%\x8b\xbb\xe4YH\x92E$yD\n\xbc\xe7]g2\\k\xd0\x9b\x9b1\xbeZq\ -\x08\xbeC}\xa4I\xa7\xd7e_{\x96n\n\x91Rd\xd8$\x04\xc4x<\xb9\x13\xee\xb8\xff\ -\x19\x12\x15\x80]E\xa5\x8a\xc7\x05\xb7\x0e2@9\x86\x08\xf0\x83\x1f\xdd\xcaT\xbb\ -\x87\xe37\xc0r\x90\xae\x0fQJ\xe0\xf9dQ\xc4\xd8P\x9d+^w$CAa\xbd\xa2R2Kc\x076\ -\xae\x0fin|o\x02\x01\xef\xbc\xf2\x02\x9a\x95\x8c$\xdcK\xbd\xa6\xc9\xd4<\xfd\ -\xa4\r\x01\xa4"\xc7\xa95\xb9\xed\xee\x87\x0cA\xcc2D\x17\xd3J\xb0@)\xee\xbe\ -\xf7~\xb4\x02\xd7\x0fp>\x0e\x98\x96M\xb5Z\xe5\xc2\x0b/\xe4\xac\xb3\xcebzz\ -\xfa\xa0\xef\xa1n\xb7\xcb\xb2e\xcb\x06\x00\xf3\x9b\xdf\xfcf\x0e=\xf4P\xc0L\ -\xee%\xb5\xb6\xa4\x01\x97\xdfGQt\xd0\xaf\r\x06\xe8\xff\xde\xf7\xbe7(J\x8dF\ -\x83\x9d;wb\xdb6\x87\x1dv\xd8\xc0\xfd\xb6\xdf\xef\xef\xa7\xeer\xa0Y\xa1\xeb\ -\xb8x\xaew@\xfb\xef\xf8\xe3\x8f\xe7\x92K.\x01\x8c\xfdJyL\x17\n\x1c_\n\xe3\ -\xa0\n\x88i\xe1\x98\x9c\x10\xabp\xf2U8\xe48\xe8\xe2\x91\x03\xaee1R\xb1\xf0\ -\x80\xd7\x9e6\xcc\x97\xfe\xe2\xb78v<\xa1\xa5v\xa3\xfa\xb3$aD\x9a\xe4h\xe1`9\ -\x15\xb4\xed\x93\xe2\x10*\x89\xf4\xeah%\xd1Ij\xe89\xb5\x8aY&\xa5!y\x1c\x93W\ -\xc7\xb8g\xe3V\xbe\xf7\xa3mf\x0b\xde\x85\x0f\xff\xda%\\p\xea\nr\xe0\xee\'4\ -\x1f\xf8\xe8\xd7\xb9c\xe3N\xa6D\x83\x9d\x9d\x18\xa7\xdeDE}\x03\xdeV\x1b\xcc\ -\xcfu\xf0EN\x85\xc8xa\xe9\x98^b<\xa7\x12\x02\x90Uswi\x85 \xc6)z\xe8\xbf\x8c\ -\x91\xb4{\xe8^Ng:f\xa4\t\x95\n\xccw\xc1\xae\x18*h\x1f\xd8\x17\xc3\x1c5\xfa~\ -\x8b\x8e3\xcc\x8c3\xc2n\xd9b\x1a\xd8\xba\x0b\xf2D\x81\xb0\xf1\xc7\xc7\xc1\ -\xb3\x11\xae\xc4\xadz$2\xa5\x9ft\xe9\xc4 ]I\x82E\x17\xdbd\x9dl\x9cd>\xa9\x93\ -\x8b\x808\xd5E(y\x8c\x90\xc6\x900i\xcf\xd0p\x15\x9f\xfd\xc4\x1fr\xf6\xc9M\ -\x02\xc0Is*2%\x99\xef\x11\xf7cF\xab\xa6\xb8\xcd\xcf\xe4|\xf4\x83\x97s\xd2\ -\xaaa\xaa(|2|K\x13\xf6\xbax\xb6\xc6"CG\xf3\x88$\xc6\xc7\xe0\xb4\xfd.\x04\xbe\ -\x8d\xabc\xec\xbcHG/Dm\xb96\xad\tG\x1a\x07T\x17\xa8\xe8\x08/\x8fq\x15\xb8z\ -\xbfy\xa0\xe9\xec\xd8\xe4\xa2h\\\x15\x1e_\x86\x8a\xaa\x06\x00\xb7,\x7f\x16\ -\xfbo<\x85Y\xfc\xdb\x02<\xcf\xc2\xca\xe1\x94\xe3j\x1c\xb2\xa8E\xda\x9d\xc1\ -\xf1\x00b\x1cG\x90G1Vc\x98N.\xd9\xd7W\xdc\xb6\xb6g\n\xc8\xc0\xb1P\x93\x92\ -\xa3\x80\xbb\x1ex\x88\x04\x8f\xcc\xa9\x98\xddCP\xc3r\x03\x84\xb0\xe9\xcc\xb5\ -\x19o59\xfb\xd4\xd5\x85\x9f\x98\x0b\xd2\'\xca\rq0\x046<\xbe\t\x85M\x14\xc5P\ -\x8a\xfdTF\x1a\x87x\xb6\xc3\xd1G\x1f\xcd\xb2\x11\xc3T\x9f\x07\xbaV\x85\x19\ -\xed3\x95\xd9\xf4\x91([\xa0\x85\xd9\xe9-\x9f\x80\xe6\xc8\x1896X\x1e:\xd1da\ -\x0e^\x83X\xf8h\xb7\xc1=\x0fm +>J\x14\xa7\x80\x047\xa0\xd7\x9ec\xcb\x96-H\ -\xdbbr\xdf4CC\xc3\xb4\xdbm\xaa\xd5*\xefx\xc7;\x00\x85\x1fx\x83\x890I\x12\xfa\ -\xfd>Q\x14\r&\xb8n\xb7;8\xdeeqY\xb2d\tg\x9f}\xf6\x0b\xca\xdc\xfey\xc3\xb6m\ -\xa6\xa7\xa7\xb1m\x9b\xf3\xce;\x8f\x89\x89\x89\xc1\xbf\x95\xd6)\xb0\x7fwT~\ -\x0f\x0c2\xc4\x0ff\x08!\xb8\xe3\x8e;\x06\x8a\xf4\xdd\xbbw\xd3j\xb5\xb0,\x8b\ -\xcb/\xbf|\xc0F\xabT*\xfb\xf5_\xc5\xae\x05 \x8a#\xd2\xcc,\x9e\x1c\xdbA\x15\ -\x14\xeaF\xbd\xc1\xeb_\xffz\x96.]:\xb0/Y\xd8\xba\xfa\xff\x86\x0eDKc\x16\xa4\ -\xa5\xc1@\x05\x03\'\xd0\xf2\xd4\xcc\xf7\xba4\xaa\x0e\x1a\x8d\x87\xf9\xc7\x97\ -/\xb7\xf9\xe6g>\xcc\xef\x7f\xfa\x9b\xdc\xb3\xab\xc2sm\x88\xfb]p=*\xbeK7Sd\ -\x16\xd0\xa8\xd1\xd5\t\x04fRC\xcc\xe3\xb8\x12[\xa6\xe8\xb8K\xa43\x92\xbc\x86\ -J\\n\xfa\xf1\xb5\xbc\xeb\x82\x0f\xe1{\xf3\x90JfzU\xbe\xfc\xc3G\xf8\xf4\xbf\ -\xde\x8e\xb7\xf8e\x84\xb5\nA\xbd\x8ek)\xda\xdb\xb7\x81\xedA\xd0\xc4\xa95I\ -\xdbs\x04A\xcaQ\xcb\x87\x11*\x05R\x12\xe1\x91bn\xaa\n\x9e\xc9\xce\xd61\xa8\ -\x1c!\x14B\x04\x07oj-\xc0mU\xc9\x01\xafn1\x9d\x99\x9c\xee\xac\x01\xf7\xac\ -\xd7\xdc~\xd7Zv\xec\x99\xa4\x1b\xa5\xccwC\xe6z1\xd3\xbd\x98\xf9$GKC\xe5[>>A{\ -\xb2\x0b5\xe3\xd3C\xdcA\'9\xd3\xd2\xc6\x93\x19\xa1\x8e\xd97\x1b\xb3\xbc\xe5\ -\x91 \x89\x8b\x06\xcf\x83\xeb\xf7\xa0\xedq\x84P\xe4Yf\xda\x16Qb\x84py\ni\xc8\ -1\xabWs\xea\xf1\x0eu\x1b\\\x85\xe9\xb5\xd9\x02\xa7\xee\x92\xe30\x9f\xe6(a\ -\xb1d\xd8\xc2%\x03\x153\xbbs\x1b\xade\xcb\xb1\x85GPq\xa0\x80g\x1dO\xe0\x08E\ -\x82\xb1\xcb\xd7\x944\xcd\x18G\xdadZ\x19\x16\x860\xedL\x85B\xaa\x1c\x17\x08\ -\xc8\xb0E\xbf\x10K\x9b\xf6\x9c%\xcb\xbflv\x1e\xaap\'\xd6\x82\x05\xf6\xe9\xa6\ -`\xc8\x81\xb5=\x83\xe7,$\x7f\x98\x91A\x0eu\xd7\xe1\xf2\xcb.\xe6O\xbf\xf4\x03\ -\xbcZ\x0biK\xe2p\x1e\xec*\xb9tA\xa5h\xaf\xc9\xf7o\xbe\x8b\xf3\xd6\\\x8c\xb6\ -\xcc\xdf\x10(4\x9a\xc9\xae\xc5}k\x1f\xc6\xf2\x1b$\x14\xf4^\xcb#\x8d\x15\xd2\ -\xf1\xb1m\x973\xcf8\x95V\x11\xd6\x19+\xc7\x90\r\x85\x11\x1e>\xbd\x1d:\xfd\ -\x10\xdf\x1f#U\xa6\xe8\xe5a\x17|\x97,I\xa9\xfb>y\xa6\xb9\xe9.\xcd\xbe\xdd\ -\xcf\xd2Nb\xc6\xc6GiU<\x92\xde\ -\xf6v\xfe\xe0\xcb\xeb\xb8m\xfd\x0e\xb6<\xdb\xc5\xb1,\xb4U!\x0b\x0b`\xad^5\ -\xcb\xf1z\xcdl\x07\xba\x1d\xd2$F\xd8)\x96\xeeS\x93\x16Y\xaa9\xf9\xb0C\xf9\ -\xab\xff\xf9j|\x07T/EV\xea\xe8\x04~x\xe3M\xd4k\x8b\x99\x9e\xcb\xc1o\x12\xce\ -\xf7\x08\xf39h\xd5@U!\x83\xb4;K\xb5e\xb3jq\xc0+N\x1b*\x84r\x9a\x8acv\x00P\ -\x12\x05,\x84(\xed\x1d\xcd\xce\xeb\xa7\xf3\x13\xccA([\x19\xb0\xc0Oh\x90%a\ -\x81\x90\x030>\x05\xa6\x8c\xb6\x8d\x1b\xeez\x8eo\\}\x13[v\xcd1;\x9f34\xb6\ -\x94(\x15\xe4\xc2!J!V\x01\xc2\x1b\xc5\x1am\x90\xe5\x90\xcc\xcf\xf1\xc4\xd6}\ -\x8c/Z\xca\xde\xb0G\xaf\x9f\x98\x9e}\xe0A\xae\xf0\xdd\x1a\xd9\x9c`z\xa6\x8d\ -\\\xb5\x08A\x8a\x8fG\x08<\xb3u/a\xea\x929\n\xb2\x1c\xbb\x12\x90\x8512OqEN\ -\xa5\x19\xf0\xf2S\x8e\xa7f\x1b\x93F\x1c\xc0\xd6\xc4\xfd.\x96g\xf4!\x9ec\r\ -\xc0\xe8$\xec\xe3\xe8\x94\xd6\xb2\xe5\x90k:Q\x97J\xadE\x9a\x85\xb8vI\x0b\x8d\ -\x91\x95\x00\x17\x10iF\xd2\x9dG\xb8Fek\x12\xb9\n\xcb{a4 \xaa0\x17\x1f0\xfb\ -\xf2\xdc\xb4\xba\n\xc39\xbd\xf0\xc2;\xe0z\x94\xa6`\x08\xb3\x94Q\x80\xa5E\xc1\ -B+\xd9h\x0c\xfeF?N\xa8\xba\xa6E\x89\x86_y\xcd\xa1\xfc\xd5\x17\xe7Q\xd1,Au\ -\x88x\xef\x1c\xc1\xea\xe5\x84Ss\x10T\xd1:\xe5\xfe\r\xcf0\x9f\x19\xba\xad+\ -\x8dI\xa2F\xb0o\x066=\xb7\x17]Yi\x8a\xa2%MAn\xcf\xe3\xd7*\x8c\rU8\xf7\xaccp\ -\x01\xa9#\xa4r\xd1R\xe2Xf\xb7\xb9\xf1\xe9=\xc4\x1a\x94\x94H\xdbAY>\xf4{\xc8j\ -\x8d\xd5z\r\x90?%\xaa+\xed>\\\xd7\x1d\xd0e\ -\xcb\xf6Q\xd9BZ\xbcx1\xa3\xa3\xa3\x07]@z\xbd\x1e\xa3\xa3\xa3\xb8\xae\xcb\xa2\ -E\x8b\x00STJ\xbd\xc4Bo\xaa\x85\x96\xefp\xa0E\xfc/:6m\xda\x84\xe7y\xa4i\xca\ -\xf4\xf44\xabW\xaff\xfb\xf6\xed\x9cq\xc6\x19\x03\x16U\xf9\xb5Z\xad\x0eD\x89\ -\xa5\xf6#\x8cB\x02\xdf\xbc\x87~\xd8\xa7\x12T\x0ep\xd9=\xe2\x88#\xb8\xed\xb6\ -\xdb\x06\x82\xcd\x12\xd7y\xa9\x08\t\x0f\xde\x89\xab\x04\x05\n^\xa4\x14\xc5\\\ -S<\xca\xef\x1d)\xca(\n\\\tc\xcd\x80:\xf0\xe9\xf7\x9e\xc4\x87.\\\xce\x9a\xe1\ -\x0c\xbb\xbd\x97\xb4\xd7\xc3j4a\xa8\x06I\x07j\x1a\xc2i\x08{\xf8\x8e\xc3Dc\ -\x18\xdd\xeb\xe3\x92\xd0\xa4\xcdG.=\x81\x7f\xfa\x9dW\xb3\xd8\x87\xb9>\xcc9\ -\xc3t\x84\x83_\x87\xff\xf6\xeboFM?\xc7\n\xdf\xa6\xd6\xcb\xa1\xa7\xf1F\x1a\ -\xc6\x92\xbb\xd223xw\x07\xcb\x1b1\xe7\x9fy4\x93s\x10\xdb\xc6\xac\xb0\xc6\x81\ -\xbd\xfc\x14\x9b\x9c\xaa\xe1\xf3\xe3\x80\xce\x11:\x1b\x00\xb1\x0b{\xeb)\x94H\ -P\xd1\xddP\xa6\xcf\xafB\xc8c\xf2\xcc\xb4*:\xc0n\x05W\xdd\xfe\x0co\xf8\xe0\ -\x17\xf8\x93\xcf\x7f\x97\x07\x9fK\x90\xa3\xc7\x90\x0f\xadf:\x1b\xa2\'\x9aD\ -\xb2\n^\x15;p\x11\xae&\xd7\xf3\xa0\xe6@\xf6\x11\x81\xc7L\xa2@\x04\xe8^b\x14\ -\xe2\xb6\x84\\\x93Y\x01~e\x11\xfd\xf9\x0c\x1f\xa8\xd2\xa3Blb\xeb\xd3\x1e\xa9\ -\xd6\xc4Q\x82\xd7\x1a%\x8b"\xb0$2\ti\x05.q{\x9aSN\\Z\x8a\xa7\x99\xcfS\xb4\ -\xb0q\xabM\x84\xed\x13f\xf9\xc0\xd2\xdf\x06\x9c\xa0A\x1a\x8c\x10\x8b\x1a;\ -\xbb\x02\xb7\xd6*\x80\xf6\x00\xb4\x03\x89\x85\xe5\x0f\xa1\x95\xb9TjJS\xb34\ -\xb9V\xc4\xc2\x02Q\x05Y1\xc5A*2+#C\x17&\x9b6d\x1eh\xb7\xc8Na\xb0;\x94\xe4\ -\xd8d8\xaa\xb8\x98s\xdbl1D\x86\xc9\xac\xcdA\xaab\x82\xf7\x90\xcaGh\xe7\x00\ -\x1c\xcb\xf1\\\xa28\xc7r<\xaa\x02&l8\xf7\x98%,\xb2\xfb\xb4\xa7\xf6\x10,YA\ -\xd8O\xa11\x02\x89\xc6\xb6\xaaD4\xf9\xe7o=\x82r \xd7\x8a\x14A\x02|\xe3\xdbw\ -\xe2\xd5\'H\x85B\xb8\x89q\x81\x8e;\xf8C\x15\xecp\x8a\x97-\xf69\xfb8\xc8\xfa\ -\x11\xbe\xc8p\xf2y\xdc\\Q\x1a\xd9o\xdf;I\xe6\x04\xa4n`\xb0um\x94\xe1\xaa\x1f\ -"\x83\x1aa\xe8\xd0\x0b\x961\xe3\xafb\xd2Z\xcedZa^6I\x82\xc5\xf4+\xcb\x99\x93\ -K\xd8\x9b\x8f1)\x17\xd1\xf6\x16\xd1\xd5.m\x05\xd4+\xe6\x98d!d\x11\xcc\xcd\ -\x82\xb0q\xa4G\x14+f\xe7\xa0\x1a\x98\x90$#8\xcd\x98\x9d\xdbG\xbd\xe1\x13\'}\ -\xa2\xa8O\xadZ%Oa\xf1\xa2%T\xab\xc3\x90\x88\xfd\x0b\xc8b\x94\xf4\xdc\xb2\xc5\ -\xb2\x10\xb4\x06\xa3./\x01\xe0\xd5\xabW\xff\x02\x13\xce\x81CJI\x9a\xa6\xacZ\ -\xb5\xca\xdc\x85\xcf\xf3\x9d{~\xabga\xb1;\xd8\xe2\x01&\xeb\x04\xcc\xe7\xf6<\ -\x8f0\x0cq\x1c\x87\xe5\xcb\x97\x0fZt\x0b[u\xa5\x08\x10LK\xaf\xe2\x07\x03BG5\ -\xa8@!\xdct\x8b\xac\x95U+\x0f\xa53\xd7\xa6\x1aT\x88\xfa!\xa3\xc3#\xa4qB\xd8\ -\xeb\xbf\x04\xcc\xdc\x0f\xb6\x80\x94\x9f\\\xee\xff~!\xbd\xd5Z\xf0\x94\x9f\ -\xf5pQTU\xc2\x07_{"\x9f\xfe\xe8\xfb9\xff\x84U\x04\xe9\x1cy{\x0f\xc4s\x05\x7f\ -U\x98\x9c\x8a~\x1f\xcf\x92Ln\xdf\xcaX`\xb1\xbcn\xf1\x17\x1f\xfd W^\xb8\x86\ -\x97\x8d\x98\xe8\x91-\x93\xf0?\xfe\xeckl\x9a5\x93\xf3E/_\xc9[.9\x97\xee\xaeg\ -p\x15\x08i\x13w\xfa\xb0x1\xccw\xa0Y\xa51\xe4A4\xcd\xe2\xe1*CM3\xf1\xc798\xa4\ -\xf8\xda\xe0\x1de\x910\xf9\xdc\x12\x13\x82E\xd1_/\x86V\x07\xe8\r\x06\xadq@\ -\xe7\xfb\xd9SH\x89\xb6\xcd\xeb<\xb8\x15\xfe\xf4\x7f\xdd\xc3\x97\xbe\x7f\x0f\ -\xebw\xa7$\xd5\xe5\xc4\xde"\xb6\xef\xe9\x93:-\xe2\\\x12\')J\x80ekT\x1e\xa2\ -\xba{\xd1\xdd}XVHm\xc4\xa4?j\xadq\x83\xa0\xf0\xe7\xda\xafP\xe9\')I&\xc83\xab\ -8\xe69\x92\x18\xdb\x86~\xdcGI\xc0+\xe2,\xb3\x1ciIl\x9d\x91\xf6;T\x1c\xc1h\ -\xcb|\x86\x0c\xb0lI\x86"G\xa3\xd1\x04\xb6c\xce\xafN\xc8\xc2y\xb2L\x91(\xf3\ -\xdc\xe6\x90i[\xe4\x19\x88\xe2\xb8\xe8\x01\xe4]\\:Jb)@\x08\xb4(V e\xd4\xa2\ -\x05B\xaaA8\xa3Q\xdf{\x85\xd7\xfd~\xca\xaf\xb9\xce\xb4aV\xe9\xf2b^pI\xcb\xdc\ -\xec*D\xb1K\xd1\x96)fz\xbfmny\x8e\x1c\xbfB\x1c\xa7X\x18\xf6\xd8\xeb.8\x03;nS\ -\xf7]t\xae`f\xd6\xd0\x9b\x85D\x08\x8b\xb9P\xb3\xf6\xd1\xa7\x98\x89 \xb3$\t\ -\xb0\xaf\r\xcf\xec\x98\xa3\x9f\xda\xe4B\xa0\xa2\x1et\xe7\xc1R\xb8:D\xa4s\x9c\ -w\xfa\xb1\xb8\xc0P\xc5)\xda\xb2\x1a\xd2\x88\xe2\x93\xa3\x94"\xd3\n-E\xb1k\ -\x15\xb8K\x96\x82\xef\x93\xb4\xe7\xcdq\xd5\x12\x1dkRm\x81\xed\x80\xe5\x92[\ -\x1eJ\x06dV\x95\xd4\x0e\xc8\xac\x80\xdcv\xb0\xc7\xc7\xc1\xb5`v/\x10\x83\x93\ -\x83L\tZU\xaa\xbe p,,\x01I\xb4\x1f\x132\xbdh\xc5\xd4\xd4\x94a\xfe(\x8dUL\xc4\ -B\x08\x1a\xf5!s\xf4\xad\x17\x86a,\xb4\xf2)3:\xf2\xf8\xa6\xb3h\x89i\xe8N\xe1:6\xb4#H\x04\xde\xe2e\xb4;m\ -\x86\x1b\x16\'\xbfl\x11\xd7}\xf1\xc3\\|b\x8b\xe5K`>\x87\xeb\xee\x9b\xe1]\x1f\ -\xfd\x0b\xae\x7f\xe0i>\xf5\xf7\xdf!\x00\xa2\x08\xae\xbc\xe2\x15\xb4\xaa9nU\ -\x9bi\xa7:\x02s\x11\xd8\x19V<\x8dL\xfa\x9c\xf5\xf23\x98\x99\x9a\xa4"\nPUZ\ -\x85\xe1`^\xd8\xfa\xed/z\x07~\x00\xb1\xb0f\x80\xd0\x05U\xf4g=\xdf\xa4\x0e"<"\ -`g\x07\xber\xd5\xad\\w\xcfcl\xde\xd6&S5B\xa7\x85\xb2L&G\xa3U\x07;\xc7\xf3\ -\x04\x1e}\x9c\xbcC\xdd\x8a\x18\n$M7G\xf6f\xe8\xee\xdcL\xd3\x85\xac;\x83L\xfa\ -fe\xa9\x8a\x14\x0c\xa9\x11:G\xa1\x07\xb9\x189\x1e\n\xc7\xe4P$9ZX\xd8\xb6\x85\ -JB\xc8\x13\x1c[\x80\xca\x89{]\x02\xc7\xc6w\xcd"\xc0\x07<4\x0e\x19"\xeda\xeb\ -\x14\x9b\x14\x8b\x14T\x82mk\x1c;\'\x90\n\x87\xfd\xbb\x12\xdf\xd2\x88b\x1f&\ -\xb4\xa24o\xcc\x80LZd\xd2E"M\xaa\x9964Wc\xa5!\x8c[\x0bz?]Z\x17%Yg\xa0S\xecR\ -\xb4\xfa\x08g@\xf5\xb0\x9d\x18\x19M\xc1\xd4\ -\x16d\x7f\x0fYg\'y8\x85o%\xd8\xc2\x9c7w\xc0m\x96\xd8\x96\x83\xce\xf5\xbe\xa5\ -\xa4=\x00\x00 \x00IDAT~\x87\xd9\ -\x16\x1a\x89\xce\xcd\xcd\xd1j\xb5~\xe1s\xf7R\x19e\xcb\xae\x0c\xb5*?o\xbd^\ -\xff\x85A\xfa\xb2\x88\xe4y>\xc8\x10I\xd3t\xf0\x15\x18d\xa1\xbc\xd8\xe3\xc55\ -\x93G\x92\xa5)\x13#Mj\x02F\x1d\xf8\xf0;\x8f\xe2#\xefz-K\xaa9\xc9\x96\x8d`i\ -\xec\x9aO\xdc\xd9\x87\xe7\xc4\\\xf9\xe6K\xf9\xfbO\xbe\t\xd1\x85*f2\xfa\xe7\ -\xef\xac\xe3\x8f?\xf7%\xf6\xa4\r\xe4\xe8\xcb\xb8\xe9\x9e\x8d<\xf0xL\xdd\x87U\ -\x87\xc0\xeb_w\x1e\xdd\xdeN\x9c\xa61\xe5c\xb6\xc7H3 \x9f\xdf\x8bC\xc6\xdb\ -\xdfr\x06\x0f\xad]\x0b\x98\x05\xa1kI\xfe\xc3\x89\xe9y\xd5\xe1y\xbc\x9e\xc1\ -\x0e\xac<\xb8Z\x14\x0c\x03\xe1\x90\x0bC+\xbe\xea\xbaG\xb9\xee\xf6\x07\xe8[\ -\xc3\xb0\xe8e\xd0\\B\x98\x9a\nf\x8d4\xe8v\xf6"\xe2\x19\xecd/V\x7f\x07Vw;\xb5\ -d\x92\xe5\xb5\x94\x93W\x8dp\xf1)\x87\xf3\xdasO\xe5\xc2W\x9cL\xe0ht\xd4+\xf0\ -\x1bez\xee(\x13\xb5)\x05\xc2\xf2\n\x96\x8dG\x8a\t\x8a\xb2<\x1f-\npY\x99\x82#\ -\xb5B\xeb\x1c\x8d\x01K\xb7?g\nAN\x89\xec\x14\xf1\x9d\xc2Pc\x89\x0b\xacJJ\xd0\ -\x8a<\t!K\x0b\xb8\xa4h\xea\xe8\x04\x938h\x8eR^\x14\x90D\x1a\x9d;\xd2\xc2*\ -\xf7x*7\x0f\xa1q\x04E\x01d\x7f+G\x15\xaf+\xf2"n\xf4g\xa5x\xff\xe7\x86\'-\xd2\ -4C+\x85\xeb\x1a\xd3\xc9,1\x1e\xa1\x17\x9e\x7f\x0eI\x7f\x1e\x9d\x85Pu\x91\x81\ -\x03*%\x8b"\xfcj\reU\xf8\xd1\xed\xeb\xe8h\xd3\x92\xbc\xe5\xde\xfb\x99\x8d\ -\x13R!\xb1\x9c\x8a\xb1x\xf7\xeaX\xb9"\xeb\xcfp\xd6i\xc7\xb2l\xccp\x05L\xaf\ -\xd3\xb0\xe7r\xcbB\x14\xb4\xe4\x86\xe7b\xab\x04;/|\xcb\xc6\x97 \xa4\r\xbeOu\ -\xa4\xc5P \xc8\xba\xbb\xa9\xa8)D\xe7Y\x9a\xbaC\x9d\x0eu\xe6\xa9\xd2\xa6\xae\ -\xe7\xa8\xeb\x0eu\xda\xd4u\x87\x86j\x13\xe4s4\x1b\x9aa9O#\x9ba\xb4\x922,f\ -\x19\x96\x1dto7uO\x19m\rf\'B\x92@\x9c\xa1\x94Dk\x81\xd0\x12\xa1K\x07\xda\x8c\ -86\xda\x9a\\\xed?\xaf\xff\xdeX\x98\x8dQ\x02\xd9`V\xe9333\x07y\xf6^\xfcQ\xab\ -\xd5\x0e\xc0X\xb4\xd6\x84aH\x1c\xc7\x07\x14\xcf\xff\xecXH7.w7\xa5\xb6\x04\ -\xf8)Q\xe2\x8b5^\\$F\x83my\x90jl[\x10`\x04\xb0\xef\xbfl5\x87\xad\xfa\x10\x9f\ -\xfb\xd2U\xac\x7fv\x0f\x157\xc1\xad(>\xf2\xa1\xf7s\xd1\x89f\x9an\xd5\xa0\x13\ -\xc1U7o\xe4\xcb\xdf\xff1\x93\xaaFu\xd1J\xa6\xda\x1d\x86\x86W\xf2\xf1O\x7f\ -\x89\xaf\xfc\xed\x87\x18o\xc1[\xdev\x02\xffr\xcbOp\xbc\x16\xb3{\x12Ds\x14\ -\x19v\xa8\xe8>\xaf<\xe7|,\t\x9d\xb9Y\xd3V\x93\x05\xe8\x9d\xa7\xc5\xe4dv\x15\ -\x0c~*\x87\xa9 \x83\xdb\xa7`\xf9 \xf2b\x07RF}\xe6\xd8\x96e\x96\xb5\xd2\xec>f\ -b\xb8\xf6\xf6\xb5\xc4\xce\x10:\xf3\x8c\xfdH\xda+\x0c\x9d\x12|K\xd0\xdb\xba\ -\x91\xa3\x8e\\\xc1\x99\xc7\x1f\xc9\tG\xae\xe0\xb4c\x17\xb3|\xd4\xbcj\x8e\x01\ -\xf8C`{\x1b6\xac\x7f\x9c\xbd\x93]\xb4\x06iK\xa2$\x82L\x0c\xa2]\xb5e\x17\x8c%\ -\x1b]\x98w/Z4\xca\xb3\xb3s\xa84G\xb86R\x98\xf8P\x1b\xb0]\x9fT\xc7\xdcy\xefC\ -\x9cv\xf8\xc9\xc6]F\xa5xv\xc9\x922\xad\x15\xac\x92@\xa1\xc8\x92\x08\xa4\x85c\ -I\x04Y\xd1o/\x13\x06m@\x1f\xc0\xd0\xcb\x04d\xd2\x06]d\xc3k\xb3\xfbAK\xc3\x13\ -\xd39y\x9a\x19]t\xc9\xcc(c\x00K\xbc)\xcf\x8cD\xff I\xd5\xb6\xa4\xd8\xf9\x80@\ -R\xf5\r\x05\xf6\xc2\xf3\x0f\xe3K\xdf\t\xd8\xdd\xef \\\xdb0\xf4\xe2\x18\xd2\ -\x04\x19T\xd1N\x95\x9f<\xb8\x99\xb7\xb7\r4v\xdb\xbaG\xa1V#\xd5\x1e\x96\xb6AZ\ -x\xaeE\xda\xd9M\xd3\xcex\xcdE\xa7\x19\xbcH\x14\x1fA\xba -\xb4m\xca\xb3\r\x8c\ -7+\xf8dDQ\x88\x10\x0eZK\xf4\xf4\x1chE/O\xe8\xcd\xefbi]s\xe6\xc9\x87\xd1oO\ -\x92ZF9.\xb5\xb9\x04-e(\xbcJh\xf2\xa23\xd8\r\xfb\xd4\xea\x15:\xb3sx\r\x87\ -\xa5c\xe3D\xed>J\xd9dV\x9d\xaa/\xf0H\xd0\xca\xc5w0\xa0\x97v8\xea\xf0c\xd8\ -\xb2m\x92\\X\x85\xc9\xa5\xc0\xb1$\xbbv\xed`\xf5\xaa\xa5X\xce\xcf\x9f>J\x10\ -\xbbT\xa7\xf7\xfb}l\xdb\xa6V\xab\xf1\xd4SO\x1d\xd4y{)\x8cV\xab5p\xe3-\xdd|\ -\x93$a\xdf\xbe}\x1c}\xf4\xd1/\xf8\xef\xfc\xac\x9f\xfd\xc2]\xfc_\x7fx6\xad*\xbc\xf3\xed\x17\xf1\x85\xaf]\x87\ -\xe7\xae\xc4\x8aS\xd2\xfe$#\x8d\n\xbf\xfa\xf6S\xf9\xf6\xbf=\xc0\x91\x87\x1d\ -\xbe\x7f\xd70\xd0\x0c\x94w\xfa\x81\x13\xd4~\x15\xfa\xcfba\x99I\xa8\xdc\xc3X\ -\xd2\x022\xf2L\x83g\xb8\xfb\x1b6\xf7y|\xeb\x1e\xfcek\x08#\xdfT\xcd(\x86\x86\ -\x03"AF\x1dN\\\xb3\x82\xdf|\xd7\xe5\x9cq\x94\xc7\x98G\x11@k\x9e&0,\xe4\x1e@\ -\x13\x84N\xcd2])\x84\xd6\xa6XY6Bhr\x95\r&n\xa3\xc1\xd6h\x04G\x1f\xb1\x92\xb5\ -O\xde[\xf4\xbcm\x84e\x91%\t\xc2r\x10\x05u\xf5\xee\x07\x1f\xe5}W\x9e\xcc\x98\ -\x05X\x15r\x15a\xc9\xc2\x1a$\xc5\xf8e)\r\x8e\x8d\xe5\x18\'*\x05\xe4Y\x8c[\ -\x86\x91\xe7\x8a\x05ev\xc0P\xcb\x05\xe4\xc2\xe8\xc2\x85\xb0\n\xfe\xad\x1e\ -\x1cS\x95C?I\x07\x18\x8ckyf\x92\x97\x800g*\xd3\x07\xab\xc7Q(\x9d\xe3X\x16\ -\x02M\x1e\'d*\xc3\n|\xd2\x14\x964\xe1\xc2W\x9c\xc1\xbf\xddx\x1fi\x16\x91k\ -\xcb\x08\xec,\x9fTkre\xb3m&\xe3\xfe\x8d\xa0\x02\xd8:9Km|%:\xb2\xc82\tJb+E\ -\x12v9n\xcdrN;\xaa\xb0\x9d\xb7\x8b\xe3"]r%\x11\xd6~\xdc\xf0\xd0%c\x8cT\x1c\ -\xb6G}\xa4[\'\xb7\\#\x0er$"\x9f\xa7\xde\xac\xf0\xcas\x8e\xe7O>p\x02J\x99\xf4\ -\xc9\xe7\xc1\x90\x03\xfc-\xc7,2\x1cJ\xc2A\x11\xd9\x8e1\x80\xf0<\xb3\x10\xe9%\ -0\xe6\x9aV\xa5\x00H\x14:\x0e\xd1\xdaBJ\x07\xa9%\xe4&>\xd5um\x1e\xdf\xb8\x81\ -\xd5\x87N\x14\xf6\x08\xff\xf1(\x0b\xc8\xcf\x9a\xec6o\xde|Pg\xef\xa50\x86\x87\ -\x87\x07\x16\xf6%y\xc0u]6o\xde\xccy\xe7\x9d\xf7\x82\xff\xce\xc2\xcc\xf4\x85\ -\xe3\xa9\xa7\x9e\x1a(\xedKQdY\x90_\n\x05\xe4Ena\x81\xed\x18V\x8d_o\xe0\xfa\ -\x1e\xdd\xde\x0c2KYQ\x81\xc5)\xfc\xc1\xe5g\xf0\xa3\xcf\xbd\x9f\xc3d\xcc(f"m\ -\xe7\xf0\xc9/\xae\xe5c_\xb8\x86iw1b\xd1\xa1l}\xfa9\x9c\xa3\x8e\xc3\xad\xd6H\ -\x94GO\x8cs\xf7\xc6}|\xef\xb6\x19\xa6\x80w]v4\xa7\x1f9\xc2\xd2 GM\xef\xc1\ -\x939g\x9f\xf9r\x16\xb7\xe0\xbe{\xeea\xc5\x8a\x15@\xa9;\xd3\xc6W\xbb\x98\xee\ -J\x1c\xe4\xc0Qr\x96\x8b\xa1\x17~U\x83\x9b\xda\xfcJ\xa2\n\xean\xa2\xe1\x8e\ -\xb5\x8f\xa0\xbc\x06a\x86\x91A[\n\x1cp\xf2.\r\xd9\xa7\x92L\xf1;\xef}#\x97\ -\x9c\xe0q\x88g\x94\xd8\xd5<\xc4K\xba4\xed\xd4(\xb13\x901\xcc\x84\xb0{r\xca\ -\xb4B2Hb\x058\x08\xd7E\x93\x93\x17\x1c}\x89Y\xa1z\xc5\xde\xe8\xf4\xe3VRu\x13\ -l\xdbxpd\x08\x90\x0e\x99\x15\x90X\x15BQa\xf3\xee9\xae\xbe\xf1Y&3cA\x12I\x9f\ -\x8c\x80\\V\x08\xb5G&\x1cB\xcbe\x1e\xc9\xa6\xc9\x98>\xa6\xa8M\xcd\xa7\x803\ -\x98\xe8\x7f\xd6(\xf5\x1aJ\x83\xc2.\x8e\xb7A#4\x92D\t\xfa\x99fO\xdf,\x16\x12\ -\x018\xc6nE\x0b\xcfP\xac-\xffg\x9e\x99\x17:\x04FDX\xc6\xb6Z\xb6Dhcs\xe2\x16\ -\x98\xc0\xe5\xaf9\x89\x91\x9aK\xc52\xdeX\xd2\x16\xb8\x81G\x92\xa4\xa4\xc2Cy\ -\x8b\xb8\xee\x8e\xf5\\s\xf3CP\x1f\xa2\xa7\x058E~\x8a\x12\xe88\xa6\xee\x08.\ -\xbb\xf0\xe5\x04@\xd56\x01_\x86\x92l\xd6oR\xec/ \x87\xaf\xa8\xb1|l\x18\x9f\ -\x1cO\x08\xc3\x0e\xc9\x81X\xa1{1\x9dN\x8f\xc7\x9f|\x82]s\xd0\x90P\xc3(\xf4\ -\x87(T\xfa\xecW\xfc\xd7\x8a\xdfU\x80\x99}\x1a\x9d\x99\xfbG\xe60\xec\x99\xdf{\ -`p\xb4\x18\x92\xa8(\xf4\xb6\x8d\xa849\xff\xbc\x0bp-\x0f[\x1a,\xc4*4\xff\x0f<\ -p\x1f\xbd\xfe<\xfb\xedb\xfe\x83c\\L\x8a%\x13\xa9\x04\xd37m\xda\xc4\xce\x9d;\ -\x7f\xe1s\xf7R\x19K\x96,\x19d\x9e\xe4yN\x9e\xe7T*\x15\x1ey\xe4\x11\xf6\xec\ -\xd9\xf3\x82\xfeFY<\x9eO\x87\x0e\xc3\x90\x07\x1f|p`\xa2\xb8\xd0\x82\xa5\xb4\ -\x84\x7f\xb1\xc7\x8b^@J\xf7\xd1~\x9a\x12\xab\x84z5\xc0\xb7\x15"\xcd\xf1$\x0c\ -\xf91V\x16\xb2\xa8\x12R#Dh\xf8\xb3\xbf\xf8*_\xf8\x97o\xb3\xe2\xf83\xc9\x82!\ -\xe20\x83f\x8bTi\x92\xed\xbb\xa9\rO\xd0\xcd\x03v\xcc)>\xf7\xc5\xff\xc3T\xc7\ -\xac\xde?\xf0\xce7\x11\xee\xdb\xce\xb0\'\x18\x0el\xde\xf8\x9a\x93yn7XN\x80\ -\xd6\x82T\x1b\xc3T\xa3:gP\x14\xc4O5\xae\x8aq\x00\x85Q\x0c\x8a\x07P\x18\xfaA\ -\x96\x1a5\x89\x90\xb6iSH\xd8\xba}\'\x13\xcbWA\x94\xc2\xdc\x1cR\x19\xb0\\\xc4\ -}\\\x9d`%\xf3\xbc\xe2X\xbfXJj\x84\xea\r\xc0c#\xca0}d\xdf\x85m;a>\xce\xa86G\ -\xb0\xdd:yV\x90\xa5\xa5 \r{\x08\xa9\xcd\xaa\x05p\x84\xc4%\xa5\x06\x1c\xbb\ -\x12Znf\xdaRJ\x99\xb7-l\xb4\x1d\x10\xe2\x11\xd9U\xda\x99\xcf\xdf|\xe5*\xee{2\ -a\x1e\x98\xca\x8c\xf2\xb9\x07\x84\x9e\xc5<\xd0\x06\xb6\xf6\xe1\xaa\x9b\xd7\ -\xf2\xe8.\xf3o^\xabF\x8cM?\xca\rsJ\x98\xfd\xd8B\xd2\x9ea\xe8e\xe4\x85\r\xc9\ -\x01\\pa\x91h\x8b~n\xb1}\n&#\xb3\x92\xee\x03\xf3Z\xd2\xc3\x144%\x0e\x1e\x05\ -\x11\x08\xc2~\x1f\x95\xa6 -\xdc\xc0#\x8f\x15~qo\x1e\xb5\x0c\x1a\x9e\xa6\xe6(\ -,\x15A\x16\x93\xe7)\xc4\t\xda\xa9"\xeb\xe3\xdc\xf5\xd0&\xee^\xfb(Ak1:\xca\ -\xc0\xf5\xc0rp\xa4\x80\xb8\xc7H\xc5\xe2\xbc3\x16\x17\x84\x04c\xa9\xa2\n,`0g\ -\xe4\xa6`\x8dVa\xc9H\x83\x8a\x05\xae\xd4\xa6\xba\xd8\x8e\xb9QF\xc6\xb1[\xa3\ -\xac{\xec\tn\xb9{3\xf3\x05n\xe1.x8\xfb\x8f\xe2\xe0Z\xdd=\x03\x7f\xf2\xf1?\ -\xe3\xaa\xabo\'\x07\xdaaa\xb9\x91N\xa7C\x9e\xff|\x90x\xe1\xaa\ -\xbat\xe1\x8d\xa2\x88\x87\x1f~x\x90\x9f\xfe\xff\xe6\xd1h4\x18\x1e\x1e\x1e\ -\xb8\xfb\x96\x9a\x8f\xa7\x9f~\xfa\x05\xfb}\xfd\xac\xddG\xa9\xea\x7f\xe2\x89\ -\'\xe8\xf5z\xa4iz\x80\xcd\xfd\xbf\xb7c\xf9\xaf\x1e/j\x01\xd1\xc2\xb42\x94\ -\x04\xc7\xf1p\xa5[L\xbc\x19He&LRH\xfb\xa0S\xb4\x8a\xb9\xe5\xc6\x9bx\xf2\xc9\ -\x8d\xd8\xb6M\xa7\xd3)\xda\xf0\xcaP\xae\xd2\x0c\xc6\xc6\xe9v#\xf0j\xe0\xd7\ -\xc0\xab\xf2\xf9\x7f\xfaW\xa6\x15\x9c|\xd8\x10\x17\x9ew\x16\x9e\n9\xf5\xd8\ -\xd5\x1c\xb7\x12\x1eyd\x9a\xdd{&Y\xba|%\n\xb3!\xc8\xe2\xd8L\xaa\xff\x91\xd5\ -\xf3\x0b\xc3`/:\xc3\xf2+f\x92\x8a2r\xb7Nf5\x88\xbcafU\x9dO\ -\xfd\xe3\xb7\xf8\xcb\xaf?\xc2\x93\x93\xa6`\xb4\x81\xb6\x80\x1d9<2\x05\x9f\ -\xfa\xf2}|\xe2\x8b\xdf\xe5w\xfe\xfc\x8b<\xbc\x0b\xa6\xb5)$V\xd0`\x10ld\x19\n\ -n\xa9\r\xb2\xb2\x14\x91\x9a\x14\xb8$\xc9L\xb1\xf4+f\'\x92C.lb\x19\xf0\xd5\ -\xab\xefc\xdb\x9c)\\s@\xaf\x10\xdc\xf5\x8b\xf7\x91=\xef\x12\xfe\xcf\xdfT\x92\ -\xa0RA:\xa5j^\xe3\xba\x12\x87\xfdN\xc8\xef~\xcb\xeb\xb0\xd2y|\x91\xe2;\x90\ -\xf7\xe6\xa9,^\x8c\xca\x15\xddT\x18M\x91\x08\x08\xfb\x19\xf6\xe88\xf4C\x98\ -\x9f\xc3\xd2\x11\xbeN8\xef\xf4\x13YR1\x97\xb4M\n*F\x06\xc1\x80\xf6\xde\x9b\ -\xef\xe0Y\xe6\xb8H\x05\xef~\xdb\x9bH\xe7g\xa9y\x96\x896\xa8\x04\x06\x1f\xeb\ -\xc7\xf8\xad\t\x08F\xf8\xe2\xb7\xbe\xcf\xf7o\xddD\xbf\xe8&&\x14\x14tL\xb1\ -\x8d\x8a\xe3\xb3y\x06\xfe\xe83_e\xd3T\xc6?|\xed:>\xfa\xd9\xef\xd1\xb1a\n\x93\ -KU\x1aBZ\x14\xf0R\x9e\xe2\xd4k \x89b^\xf7\xba\xd7\xb2w\xdfn@Q\x0b|\x84\xca\ -\xa9\xd7\x9b|\xe63\x9f\xc5\xb2\x1c\xe2\xf8\xa7M\xfdJf\x120\x08dZxn6m\xda\xc4\ -\xcd7\xdf\xfcKYA\x97\xb9\x1d\xa5hpaf\xf8\x7f\x95c\xed\xb9\xe7\x9e;\xb0&\x19\ -\x1b\x1bcff\x86\xe5\xcb\x97\xf3\xf9\xcf\x7f\x9e-[\xb6\x0c\x9e\xb7\x905\xb5\ -\xf0\xbd\x95\xe6\x8b\xe5\xf7`l\xe0\xbf\xf2\x95\xaf\x10\x86\xe1@y^\xd2y\xc30|\ -I\xec>\xe0%\x80\x81\xa8\xe2~/\x15\xdb\xa2\xe0\xfc\x98_\n\x10\x85\x99\xa1L\ -\xd1\xd8\x9c\x7f\xfe\xf9\x04\xa3\x87s\xd5\xb5\x0fr\xc3\xdd\xebQ\xd5:vc1\xda\ -\xf3\xc9\xa3\xc2\xab"\xa8\xe2)\x9b\xb4\x13\xd3\xed\xf6\xd8\xf0\xd8n\xee\xbc\ -\xf7\t\xdep\xd6Q\xbc\xef\xfdg\xb1\xfe\xa1Gy\xc7\xe5\xaf"O\xe1\xbe\xfb\xeeC\t\ -\x8f\xf1\xa5-\xac\x02+p\xbd*\xe8\x10\x15v\x91\x95\x1a\x14\xda\xd0\x9f*\'\x07\ -nG\x8a\x9f\x8b\x1e~\xf15\xc92<\xdb&\x0eC\xf0\xab&\xbc\xc7\x96\xa4\xfd\xb6iBg\ -)\xbd^\x17\xe9\xbb\xa4*\xa5\x13*jN\x83\xbb\xd6u8\xf7\xd4\x06\xe36L\x03\x81\ -\xb0\x91\x81m2\x9e$<\xb5\x13\xfe\xe6k\xd7\xf0\xd0\x13\xdb\xc9T\x9dj}\x04\xcb\ -\xaa\xd1\t\xe7\xa1\xdf\x03W!-\xb0m\x89.\xdcg\xd1P\xb3%\xd0g\xd8\xaf\xf1\xeaW\ -\x1c\xc3\xd7n\xb9\x1f\xc7\xab1\xf7\xe4FXq\x04\x95\xe1\t\xfa\x9b\x9e\x81f\x80\ -\xf6[\xc4\xbd\x94\xa7v\xcf\xb3\xed\x9a[\xb9\xfa\x86\xdbX\xd4j0:\xe8\xcc\xa4\x1cJ\x9bU\xcb\x03.\xbb\xe4<\xfe\ -\xf7u\xf7\xe3L\x1cK:\xbd\xdbh|\xb2\x8c\xee\x8eY\xa8\x8d\x90x)\xff\xf0\xf5\ -\x1f\xd0\xde}\x1a\x97\xbd\xf2LV.\xb3\x8d\xe7\x99cv\xb9\xd39\xfc\xe8\xb6\xdd\ -\\}\xc3m\xac\x7fb;\x9e\xdf\xa0\xd2\x1c\xe7\xab?\xb8\x9bM\x93!\xbf\xf3\x1boc\ -\xf5\x18\xac\xf2\xcc\xaeH\xe7f7h\xd9\x05\xe1\x03\x89[\xf7x\xf9Ygr\xd3m\xb7\ -\xb0e\xeb\xb38\x9eE\x1c\xf5\xa9\xd7\x03z\x8e\xe4w?\xf2{|\xfc\x13\x7f>02\xcc\ -\xb2\xec\x80\x08\xda2\x9c\xa9\xdb\xed\x0e\xa2]\x1f}\xf4Q\xbe\xfb\xdd\xef\xd2\ -\xef\xf7\xd1Z\xbfd\xf4\x0c\xbf\xe8\x98\x9b\x9b\xe3\xd2K/\xe5\xdb\xdf\xfe\xf6\ - \x93\xbd\xcc\xf0\xf0}\x9fk\xae\xb9\x867\xbd\xe9M\xac\\\xb9\x12\xa5\xd4 \xe4\ -j\xe1\xe7\xaeT*\x83\xdd\x8b\xef\xfbDQ\xc4\xcd7\xdf\xcc\xc3\x0f?|@\x8e:0\xf0\ -\xd6*\xdbe/\xf6\xf1{\xd1\x0bHy\xcb\xda\x85L\xaf0B*\xa87&\xbc)\xb3 \xc3\xf4\ -\xbd\x1b\x1e\\t\xcaJ\x96\x04U\x8e\x1c\xf7\xf9\xc6Mw\xa0\xdc&\xdb\xc39Pu\x18\ -\x9a\x80\xf9\x0e\xf1\xec\x14\x8b\xc6}\xba\x93\x11\xb1\x05\x9f\xff\xca\xb5\ -\x1c}\xfcQ\xac\x1e\x85\xf7|\xe0]\x9cz8\xeci\xc3#\xeb\xd6\x11*\x9b\xdd{s\x8eX\ -bQ\x1b\xec\xfde\xd1\xa8\x97/l\xb71\xe0\xcf\x9b\xff[\x82\xc5J)\x04\x02\xdfu\ -\x083\x85\xedHN9\xe6p\xae\xbd\xeb1\xdc\xe6\x04Xu\xfaS\x19~s\x94(t\xe9\xf541\ -\x0e\x9f\xfe\xd25\xdc\xfd\xf01\xbc\xe3\xf2S8d\xc2P\x96\xdb1<\xb9\x19\xee\x7f\ -\xf01\xfe\xef\xf6\xde=^\xaf\xaa>\xf0\xfe\xee\xb5o\xcf\xf5\xdcON\x12B\x12!\ -\x01\x02\x89\x04\x10\n\xcc\x0b\xa8\xa5(W\xc1)h\xed\x14\xd1\xd6\xa9\xb5\xce\ -\x0c\xf3\xfavF{\x1bk-\xe3\xdbw\xea\xa5/N;~\xc6Z[\xdb*/\xbdX\x10\xc4(UD\x054\ -\x02\x12/\x90\x90\x0b\xc4\x84\xe4$\xe7\xf2\xdc\xf7u\xbd\x7f\xac\xbd\xf6s\xc9\ -\xc9\x85\x13\xe7\x93dX\xdf\xcf\xe7|\xcem?{\xaf\xbd\x9eg\xff~k\xfd\xae\xdf\ -\xdd\xbc\x85\xad{\xa7i\xb9\x05\x1c\xbfB\xab\x15b\x8bPI\x10\xdb\x05/!\x0e"\ -\x84+\xb2]P66aA\xd4\xc4sJlX%\xb8\xfd\x96k\xf8\xf8\xdf>\xc8\xd0\xea\xa5\xb4\ -\x92\x0e\xad\xad?\x86\xa9\xd3 \xe8d\xed\x8a+H\xbfH\x9c\xb6\x99\xee4\xa8\x1d\ -\x88\xd8S\xab\x11\x87s\xcc6:\xc8\x10\xac\xa5K\x99Ml\x82F\x83\xd1\xea(w\xfe\ -\xee_q\xf7\x1f\xdd\xce\xd9\xc3j5\xec\xc7\x10\xb5\xda\x94\xab\x1e\x0e\x12\xd7\ -\xb2Y\xb9\xd4b\xbc\xec\x91\x14|\xa6;M\xd5\x13\xc3\xf6\x95]\x0eI\x1c\xc4\xc4\ -\xa9`hj5\x8f\xff\xf0\x05\x1e}\xfc\xfbxV\xccp\xb9\xacJ\\{.\xe7\x9d^>N\xd5\xa1\ -Mg\xa8wKG\xd2\x91bI\x81c\xa9v5\xab&\xe05\x1b\xce\xe4\xa5G\x9f\xa6P\xa8\xd0\ -\x89C\xb5\xb0\xb1\x1de\xf3L\x048EUm\xa0\x15\x82m\xe3;\x11vPc\xe5\x92\x02\xd7\ -\\^ nA\xa1$\xba\xd7\xb5$R\xa6$I\xa8\xfc\x80Rb\xdb\x02a\xa92\xfe\xff\xe6\xd6_\ -\xe0\x1bO>\xcb\xdex\x9ezQ\xa8\x90g\xcf\x85\xf2\x18\xd4\xa690\xd3!\x19\x9a\ -\xe0O\xefy\x84\xbf\xfc\xe27X\xb5j%k\xcf^\x03\x8e\xc7s;v\xb3c\xcf\x0c\x8d\xc8\ -\xa1\x169H\x963z\xc6\xab\xd9?\xbd\x87\xd2\x19\x93ly\xa9\xc5/\xfe\xda\x87\xf8\ -O\xbfq+o\xbdp\x92\xb3&<\x8a\x85\x02\xc2\xca\x84\x91-\x88;\x11\x8e\xef"\x85\ -\xe4\xda\xeb\xae\xe1\x0b_\xf8\x02a\x1c051\xca\xbe\xe9\x97h5m\xe28\xe1\xbf\ -\xfc\x97?\xe0\xc6\x1bo\xe4\x8a+\xae\xc0u\xdd<\xd3\xbcT*\xe5\x8a\xc4q\x1c\\\ -\xd7\xe5\x9e{\xee\xe1\xc1\x07\x1f\xc4\xb2,\xea\xf5z_\x81\xc1S\x15\xdd\x07\ -\xe5\x97\x7f\xf9\x97\xf9\xe8G?\xca\xf2\xe5\xcb\x01\x95q?77\xc7\x03\x0f<\x00\ -\xc0u\xd7]\xc7Yg\x9dE\xb1X\xa4\x9dU0.\x97\xcb4\x1a\r\xca\xe5r^\xa2\xe4\xa5\ -\x97^\xe2\xef\xff\xfe\xef\xd9\xb4iS^[L\xfb;\xe28\xce[\xed\xc2\xc9\x91Lx\xc2\ -\x15Hwe/\xbb\x02\x1b\x1b\x84 \xb1P\xdd\xf6\xe86q\xd2\x99\xc2\xff\xc7y\x93\ -\xfc\xdcy7p\xfa\xd2a>\xf6\xf9\xafA\xa3\x89\x7f\xe6%\x04\xf5:\x04-\xdc\xf1\ -\x02\xcd\xc6~\x8a\xc52al\xd3n\x16\xf9\xc0\x07\xff\x89\xbf\xf9\x93\x9by\xc35e\ -<\xe0\x91\xaf|\x13i\xd9X^\x85\xaf|\xfdQ.{\xf5U$\x0e\xb4CI\xd1\xb5\x11\xa52\ -\x0b\xec;z\x18\xa8\xc34\x10\xf8+\x01\xdf\xf3\x89\xc2\x16\xaek#\xc2\x10\xc7-p\ -\xd5%k\x99\xfck\xc1\xc1\xfaA\xd2\x92\x0f\x96E\xab\x1d(\xa7\xaa7\x8cW-\xb2{\ -\xdb\x8f\xf8r\xfc<\xff\xf8\xe5\xef\xb0t|\x08\x0b\x15\xc6\xe7\x95\xaa\xbc\xf8\ -\xd3}\xd4\xe7\x9b\x8c\xad\\\x81\x8c\x1bXB"[-b\xdbA\x94\x84\x02\xbbP\xc4\xb1%q\xa7\xc9LG\xd5\xdeM\xec*\xa5\x91q\x86\ -\xc6\'\x8fK\x81@7\xe4\xd5F7\xc4\xcd\x94\x88L\xb1\x10\xf8\x02\xa2\x04.{u\x81\ -\x8d\xe7\x9d\xcd#?\xdc\r\xb6\xa7\x94\x86\xeeD\x15\xc6\x08J\xa4\x96\x03\x96\ -\x85\x88\x03\xd2`\x8e\xb1\n\\\xff\xf3\xafQ\xe5\xe8\x0b\xfa\x03a\x83P\xbe\x9b\ -T\xa8m\xa1L$\x16\x02)SRK\x90$1.\x0e\xb7]\xbd\x82\xf9\xdaM\xfc\xf9_\xff#\xe1l\ -\xc8\x923\xd63\xd3\xaa\x13S\xc0\xabN\x10\xee?H\xdd/\xe1W\xc6\x89\xd2\x0e\xb5\ -\xf9\x19\xb0R\xec\xd1)\x84(\x936"dG\xa8\x0e`A\x02\xc3U\xbct\x9e\xd6\xfe\xdd\ -\x8c\x8d\xda\x9c\xbf\xe1\\\xce:\xf3\x0cFG\xc6\x91\x08\x9a\xed\x16\xb6+\xf1=\ -\x8fTX\xd9g7\xc5/:\xbc\xe5\xd6\x7f\x8d \xe5\x89\'\xbeG\xb9:\xcc\xd2e+\xd8\ -\xb3g\x0fCC#\x84a\xc8\xb6m\xdb\xd8\xbau+\xf7\xddw\x1f\x96eQ(\x14(\x95JLOOS(\ -\x14X\xb9r%\xfb\xf6\xedc\xc7\x8e\x1d\x0c\x0f\x0fS,\x16\xb9\xfa\xea\xab\xb9\ -\xf7\xde{\x8f\xf3\x1d<\xb1\xe8\xf0\xddj\xb5\xcaM7\xdd\xc4\xbe}\xfb\xd8\xbcy3\ -cccT*\x15\x9a\xcd&ccc$I\xc2\xa6M\x9b\xf8\xf2\x97\xbf\xcc\xc4\xc4\x04SSS\xf8\ -\xbe\xcf\xd0\xd0\x10?\xfa\xd1\x8f\x98\x9e\x9e\xce+\x07\xeb\x9d\xc6\xe4\xe4$\ -\xcb\x97/g\xf3\xe6\xcd\xb9\x89K7\x93:\x19Bx\xe1\x84Ga\xa9\xfe\x1a\x99\xad\ -\x04\xe5F\xf4U\xc66J\xb18(\xf3M\x19eN\xf0$\xb86`\xa5\xc4\xed:%\x91r\xc7\x9b.\ -\xe0\xce\xdboa\xf9\xb8\x80\xb9\x17\xa0u\x00hA\xd9\xa7-*Db\x8c\xd9Y\xc9\x92\ -\x15gr\xdf\x17\xff\x8e\x14\x18\x9bp9\xeb\xdcW3_o\xd1\x8e`\xba\xd6\xe4\x07?\ -\xec\x90\x00n\xd1\xca"\xb1\xb2]\xd1\x11\xc6\xdfk\x04\xe9\x86\xa1\xe6\xc68\ -\x92T\x85*\xb7\xa7\xa7AF\x0c\x95\x1c*\x02\xde\xf9\xd6\x1b\xb8\xfc\xfc\xb3\ -\x90\xad\x03xI\x0b\x926\xbe# Ih\xd5Z`\x97\x89:\x92f\xc7\xc2-\x8eQ\x19^\xc2\ -\xd8\xe4\n\xbc\xb1I\x9a\xf5&\xb3ss\x14\x96Nr\xeb\xcd\xd71V\xf5\xf1d\x8c\x1d\ -\x07\x888\xc2s]\x88\x02\xd28\xc6\xf5=\x84\xed\x92\xb5M\'\x0f\xaf\xb5\x04\x0e\ -)i\xad\xcdy\x13p\xf7\x1f\xdc\xc6\xcdWn\xc4\xefL3b\x87\xb0\xffE\x90\x01\xae#\ -\xc0s\xa0Z\xa52\xbe\x84\xca\xd8R(V\xb3$8\x01\xa9dl|\x1c\xa2\x90\xb4\xd5b\xf5\ -\xda\xb39\xb0m\x17\x89\x14l\xdf\xf1"[w\xbcH,\xc1\xf5J\xc4Q\xa4\\E\xa9\n\x93}\ -\xd3/\x9c\xc3\xeb\xaf\xf89\x9c\xa4\xc9\x81\xed?\xc1IZ\x0c\x8f\r\xab\xf2\'\ -\xcd:\x96\xeb\x92\xb4Z\x04\x11$\x89Gb\x97\xf1+\x13\xd8CKiE\x0e;\x7f\xba\x9f\ -\xe3}\x8c\xd2\x9e\xaf\xfc\x9d\xd4\xa1\xdc2VM\xb1B\xf5\xe9\xbc\xfe\x9a\xd7c\ -\xcb\x88R\xd1\'m\xd6U\xa9\x1b\x11\x02\x91:>u\xb0l\x1f+\x8a\xf0E\xc8\xc5\x17\ -\x9c\xc5\xba\xd5\xca\x0fn\xe9\x0cP\x84\xb2z\x01\xa9\xae/e\xbb\xa4\x96\xa0\ -\xd1\xee \x81j\xd9!\xc9\x1a\x8a\xbd\xfb\xcd\xe7\xf3oo\xfdy6\xae\x1e\xc1oO\ -\xe3\xb4\xe7\xa1Q\'j\x8502\x05\xc51\x82\x83-\xc2\xf9\x00ob9\xde\xf8R\x92\xd9\ -\x1a\xe9\xfe\x03\xaaD\x7f\x18\x80\'\x18\x9e\x1a\x87\xb9\xfd\x0c\xc9\x0e\xa7\ -\r\xbb\xac(\xa5|\xe8}\xef\xe4\xb2\x0b\xcf\x01\x04i\n\xaeW\xc0\xf3\xc0\xd8\xea\xd3h7\x9a\xa4\xe5e4\xe7m\x86\xcbKhN\x1f\ -\xe0\xdc3&9p\xb0I\x02\xdcx\xdb/r\xd6\xfa\x8b\x98\xad\xb5I\xb1\xb9\xffK\x0f\ -\xd1\x8a\xd5\xc3\x9e\xa4Y\xd6\xf5\xe1\xf4\xc7B\xef\x9dT!\xa9\xda\x10\xa2\x8a\ -\xe3\xa9\x03mK\xd7q\n(\tX\xbf\n~\xfdW~\x91\x8b\xcf]\x85\x17\xce`\xb5gq\xe2\ -\x1a\xd8\x12WH\x1c\xd7\xc5\x16\x0ev\n\xb6L\x99\xdf\xbb\x97\xc6\xccA\xc6\xca>\ -$m\x8aV\x87k\xae\xbc\x84w\xbcy\x05\xe3%\x17\xd9\xae\x13\xb5\xea\x10u\x18*\ -\xf9J\xa0\xa7)\x85B\x81 \x91D)$6\x80\xea-/\xb1\x89\xa3\x0e\xa3\x15(E\x11c\ -\xc0\xc7~\xef&\xfe\xc3;n\xc5\x0b\xe7X\xbba\r\x15_`\xc5MH\x03h\xb7hLO\xd3\xd8\ -\xbf_E\xbc\t\x81m\t\xc6\xc6F\x98\xdf\xb7\x07\x9au\xbc\xa2\xcf\xcem[Y\xb1\xee\ -\\\xe28\xe6\xdd\xefy\x0f\xe7o<\x0f\xcbRn\x19\xc7\xf5I\x13I\x18&4\x1a*\t\xf0\ -\xdf\xbe\xe3\x8d\\r\xc1:\\/E$m\nv\xacjlE\x1dd\x1c)!h\xb9*\xda"\x94\x04\xb1E"\ -\x1d\xa4\xf0\x95c\xf9\xb8>}\xa2o\xa7\xa8\xde\xa9\xec\x91\xb0Rt\xb1\xcc\xa2\ -\xabL\xa7\x17_0\xc4\xba\xb3\xd6fY\xeb)\xa4\x11B\x86 #\xac8\x85X\xe2\n\x17\ -\x19\x85L\x0c\x97\xb9\xe9\xba\xd7\xa9]\xb3H\xbb\xe9\x12\x12\x924[\xdd#\x88\ -\x92\x14p\x88S\x81S(\xe6\x87\xf9B\xcd\x8f\x9d\xc0\x9do\xbb\x82\xdf\xffw\xbf\ -\xc2\xda\xc9\x02\xa3n\xcc\x92\xb1*v\x92\xc0|\r\x0b\x1bkt\x0c\x86\x86\x88\xda\ --\xc2f\x1d\xab\xe8a\x97\x1d\x9cN\r\xea\xd3,-@\xfb\xc5\x1fSjOS\xac\xbd\xc0\ -\xdb^w>\x0f\xfd\xf9or\xce\xb8\xda\xd1\'QJ\x98(\xff\x9c\x9e\x07\xdbq\x08\t\ -\x19\x1e\x1a\x02R\xa2N\x8b\x15\xabW\xf1\xaew\xbd\x8b\xeb\xaf\xbb\x81\xa1\xea\ -\x08\xb33\xf3\xaax\x80\x94t:\x1d\xe6\xe6\xe6\xa8\xd5jy\xd64\xc0\xee\xdd\xbbI\ -\x92\x84\xd5\xabW3==\x8d\x10\x82\xdbo\xbf\x9dK/\xbd47\xcb\x9c\xca\xe8\xfc\ -\x968\x8e\xa9T*LNN\xf2[\xbf\xf5[\xac[\xb7\x8ee\xcb\x96\xe5\xcd\xa5z\xab\xf5\ -\xee\xdb\xb7\x8f \x08\xf2\xf0\xdfZ\xadF\x18\x86\xb8\xae\xcb\xdc\xdc\x1c\x8dF\ -\x83\x8b/\xbe\x98\xdf\xfe\xed\xdff\xc3\x86\ry\xd8\xae6w\x01|\xfb[\x8f\xca\ -\x93\xc1\x8cu\xc2} \x9a\\\xe0f\xbf\xab\xb7%U\xcfs\x1a\x81\x0c\xb0\x9c"\xae\ -\x0e\xfdE\xe5\x008\xc4T\xca6RZ\xfc\xab3\xe13\x7f\xf4v~\xef\xa3\xf7\xf2\xf8\ -\xa3\x0fS]\xf7\xaf\xa8\xcf\x80=\xbc\x9c0h\xe3\xda\xb0\xe6\x8c%\xac\x18/\xf3\ -\xec\x9e6S\xcb\x8b\xbc\xf5\x97\xde\xc0\xb3\xff\xf5\x7fR\xf0\x1c\xbe\xf3\xf8c\ -\x04\xf1\x9bH\x1ch\xd4C\xc6G\xfc\xbe1vMnq&\\,U\xb8\x14\xf2\\\x87\xc1c\x1d\ -\xc7"j\x07x\xe3S\xca\xb8m\xc78\xaeO\xd0\x82\xab\xcfwx\xd5\xea7\xf1\xc7\x7fz?\ -On\xd9J\xa3\xb1\x0bd\x91\x12\t\xad@u\xa2\xb3\x92\x08a\xc5,[V%\xe8\xcc\xb1o\ -\xebOXw\xd6j\xee\xb8\xe3\x97x\xe3\xe5*)K\xce\xbc\xc0\xa8]\xa0P\x10\xcc5\xea\ -\x94:E\x9c\xc6n\xc6&\x8a\x14\xa2\x18\xd9\x9cF\xc8%8\xae\x9aY)c@\xe0\xb86\xa4\ -m\xa2\xd6\x1c\xe5\xe1e\x00\xbc\xfd\xc6e\\y\xd5\xaf\xf1\x99{~\xc8\xe7\xbf\xf8\ - \x8ep\xa8\x94+\x88\x82O\x10\xa6\xc4\xa9\x85\xe3\xda\xa4I\x8bpn\x1f\x91\x88p\ -Z\xf3\xac:}\x05I\xd2\xe0\xe0\xec^6\x9c\xbe\x91?\xfc\xb3\xf71\xe2\xc0\x18\xaa\ -\xfaG\xc1S\x01\x05\xb6\xe3P\xb4\xed<\x93~\xe3r\xf8\xcd\xb7]\xc6\xd2\x92\xe4\ -\x81\xaf<\xcc\xf4s/2\xb6t\x05\xce\xd8\x08\xb3\xf5}D\x89\xc0\xf7\x8b\xc4B\x85\ -B{I@\xda\xaeQ\xf2\x0b\x8c\x17\xaa\x99~\xb7s\x0b\xa2/\x1bT\x939\xd2$%\x89\\\ -\xac4\xc6MSD\xea\xe0&\x11\x05\xd9\xa2\x98\xd6\x10\x8c\xd1\xff\x8e\xf5\xbcq\ -\xba\xd0a\xb6xp\x1d\x9531\xe5\xc3\x15\x1bV\xf3\xfd\xef}\x97\xa9\x89\x154\xc2\ -\x18/\t\x88A\x9e\xd0\xfa\x00\x00\x1fYIDAT\x13\x89\x1bC\'\x92T<\x9f \xda\xc7\ -\xf2\xaa\xcfU\x1bJ\x08\xa0\xe8\x0b\x15g\x9b\xfb\xebS\xac<\x87^\xfd1\x8ec\xbc\ -\xa2O\x94$8\xb6\xc0\xb7 \x95\x11\x05\xdb\xa5\x19J\xae\xbeh\x19\x97^\xf4\xeb\ -\xfc\xed?\xef\xe0\xf3\xf7?BZ\x9f&\xb0\x0b\x04\xad&RH,\x19b\xc9\x0e\x8e\x15\ -\xe3\xd9J\xb9\xdb\x08\nc\x05\xea\xbb\xbf\xc7R_\xf0\xda+\xce\xe7\xedo\xb9\x92\ -\x8dg\xa8\x1b/\x0b\x15)\xef8\x82Bf2nuB\x8a\x05\x0f\x1b\x1b\x1bI\x9cF\xd8H\\\ -\xcf\x03\xd4\xea\xf7\xd6\xdbn\xe1\x17\xae\xb9\x8e\xbf\xfc\xec_\xf0\xc4\x13\ -\xdf\xc1\xf3<\xa4\x94\xb9#X\x87\xd4\xb6\xdbm\xca\xe52B\x08\xa6\xa7\xa7\xb9\ -\xe1\x86\x1b\xb8\xf9\xe6\x9b\x19\x19\x19!I\x12j\xb5\xda\xb1\t\x87\x93\x1c\ -\xed\xe0\x06\xe5\xa3(\x95J|\xe4#\x1f\xe1K_\xfa\x12\xff\xf0\x0f\xff\x90\x87\ -\xdf\xea\xbc\x97\x95+WbY\x16/\xbe\xf8"SSS\xcc\xcd\xcdQ\xadVs3\xd5\x8d7\xde\ -\xc8m\xb7\xdd\x96\xcf\xe3\xcc\xcc\x0c\xc3\xc3\xc3Y\xc8\xbb\xca\x0f\xe9-\xe2x\ -"\xb1\xe4\t\xdd\x07\xf5f\xb2:}\x8bz++\xbe\x01i&\xa1U\': /\xcd!\x88\xb0h\x12\ -\x84!\x1d\xa7\x8a%T}\xffo~o\x86\xbf\xfe\xc7\x07y\xe8;;a\xfc*\xeaa\x81R!\xa4\ -\xecm\xe7}\xef9\x8f7_v\x01\x7f\xf9w\x9bX\xbd\xe626^\\\xe1?~\xe8A~\xb2\xf9q*V\ -\xc8]\xff\xf9?r\xf1\xfaI\xa6\xaa\xdd\x82\x88\xbaL\x84\xad\x15\x87\x8c\xb3zP\ -\x8eZZ[\xb9d\xa07\x02\x0bz}\ -\x9ez\xea)v\xed\xda\x85\x94\x92j\xb5\x8a\xe7y\xac_\xbf\x9e5k\xd6\xe4\x15w\ -\xf5\xf1\xc7\x12F\xdbj\xb5\xd8\xb2e\x0b\xdf\xfa\xd6\xb7\xd8\xb2e\x0b\xb3\xb3\ -\xb3\xf9\x98\xf3\x9e\xe8\x9e\xc7\xf2\xe5\xcb\xd9\xb8q#\x97\\r\t\xabW\xaf\xce\ -\xef\xa1^\xaf\xb3y\xf3f\x9e\x7f\xfey\x1c\xc7\xc9\xbf\xd6\xad[\xc7\xc6\x8d\ -\x1b\x8fz\x7f\xff\xab9\xc1\n\xe4x\x89 \x99\x05\xdb!\xa4\xcc|;e\xacPDJx\xe4\ -\xbb{\xf9\xd4\xbd\x8f\xf1\x95\x1f\xa48c\xafbzn\x07\xc4?\xe4\x91/\xff>\xcbm\ -\xf8\xe7\x87\xb7\xf1\xd1O|\x8e\x0f}\xf4\x83x\x1e\xfc\xb7\x0f\x7f\x92`f\x9a\ -\xcb6\x9e\xcb]\xbfs\x1b\x05\xa0\xd3\x82\x91\x92V\x1e)6\xaa\xb9\x8f*=.\x94\ -\xe2\x10v\x8f\x02yyH Lb,\xdb\xc9\xbb\x13\xd6R\xd8?\x03\xd3s)\xb5\x86j\x03\ -\xbat\x89\xc3\xd2\xf1n=,\x1f\xbdC#\xefe\x1dD\xe0\xbb]a\xa0\x15\xdf\xc1\xd9\ -\x1a\x93\xa3CY\x99\xf2D\xf5\xd5\xf6}\x1c\xa1\xbd\xeaa\xfe\n\x89C\x9a)\x918U_\ -\x96\xa3\x9c\xc8\x9d\x10\xe6\xea0}\x00\x1a\xcd\x00\xb7\xe03<\xac\x9a\x10\x95\ -|(\x97t\x99\x8e^\xc5\xab\xcb_\xf4\x06\x1c\xf4\xf8\x19\xe8.\x06\xda\x11yK\x90\ -\x008P\x87\xd9ZB\x18\'\xcc\xcc\xd5\x88\xc3\x0ec#\xc3LMV)\x97\xa1\xe0\xaaD?;\ -\x82\xa2\x93f\xad@\xd5\x1c\xb6\xda\xca\xcd\xe3{\xfd\xf3\xa1\xa3\xf8@gj\xcbL\ -\xdd\xf7\xd2\xff^\xc6\x91\x12\x14\xbe\xdf\x15\x14:7N\xf8\xd0H\x95\xe9U\xbf\ -\x1fj\x9eU5_}\xbd\xee\xce\x15r\xf1\xac\xcb\xc3K\xa7Ws\x1d\x96$I\x88\xa2\x08\ -\xcf\xf3\xf2d\xb9}\xb5\x08g\xb4\xc0\xbe6\xec\xdd\x9bR\xaf\xcda%\x11\x95r\x91\ -\xa5\x13CL\x8dC\x12B\xc5\xef\x8e\xc3\x06\xc2D\xe5\xef{\xb6*ks\xa4\xcbk!\xd9+\ -\x90\xf5*xdd$\xff]g`k\x93\x8eV:\x8dF#ok\xab\x8f\xf5<\xd5\x83\xe6\xa9\xa7\x9e\ -\xe2\x13\x9f\xf8D\xde\xaf\xbcP(\xd0l6\xf9\xb3?\xfb3FFF\xf2\xeb\x86a\x98\x0b\ -\xce\xc1q\x01y\xabZ}\xcd(\x8a\xf2\x1c\x94\xa3\t\xf80\x0c\xf3J\xba\xfa\\:?E\ -\x08\xc1\xfe\xfd\xfb\x99\x9c\x9c\xec;\xb7\xbe\xc7cURz\xbcz\x87Q\xaf\xd7\x99\ -\x9d\x9d\xa5^\xaf\xb3t\xe9R|\xdf\xa7T*Q(\x14\xf2*\xbbzNt\x01\xca$I(\x16\x8bX\ -\x96\x95\xb7\x05>\x19\xda\xda\x9e4&\xac\xc5a\xa1\xdc\xeb\x02\xf0\xa9\x14\xb5\ -9\t.\xbch\x19w.\xbb\x85\xe7?|\x1f\xcf\xedy\x963\xa6J$q\x85e6\xcc\xc6)\xdb\ -\xb7\x1f I+|\xfa/\xbe\xc8\x87?\xfc&\xae\xbb\xeez>\xf3\xc9\xff\x97\xcd\xdf\ -\xdd\x8c\xcdm\xc4I\xd6\xc4\x8dnj\xa0\xd4\x85\xff,w\xd1Jcp\xf4\xaa\x8a\xad\ -\x83\xb4}\x10\x16U\x01\xe5\t8}B\x10R\xa6\x13B\xc5\xcbzkec\x91\xb1$NC\xa4%\ -\x98o\xa6T\x87}\n.\xdd\x02\x8e\xd9\xf9SI\xae<\x00\x1c!p\x0b\xc5\xeca\xd0\x82\ -L\x97\x0f\x11X\xd8\xe8\n`\xc2R_i\xaa\x82\xac\xfc\xa2\x8a\x9cZ\xb1\x04\x9a\ -\x1d\x1f\x84\xea\xf3\x95&Pt\xba\xa53\xe2\x14\xc20\xc1w$\xbe\xe3\xb0\xf0\xba:\ -\x0bZ\x93@\x92\x92\xa6\t\xae\xb4\xd4\xa5\xa8\x8f\x19\x1e\x1e\xce\x15\x84\x10\x82B\xa1\x90\'\xce\xe99\ -\xe9U&\xb6m\x13\xc7q~}\xcb\xb2\x8e\xb9\xdb\xa0\x16\xc2Z\t\xf5\x9eWJ\x99\xb7\ -\xc9\xd5\xf7\xd0[F\xe4X\x94\x87\xde%\xe9\xb1ig\xfb\xe4\xe4d>\x17\xbd\xf36\ -\xd8\xbb=MSJ\xa5R\xdf9\xf5\xef\xbd=\xdfO\x14\'\xd8\x89~\x9cH\x07("\x03\'w\\\ -\xa7@\xbd\x15\xe3\xd8p\xd6J\xf8\x9d\xff\xf3F6\xae)3\xbf\xe7)\xd6.\xab\xe2\ -\x02\x93\x8e`\xee`\xca\xd0\xc8*\x9e|z+\x1f\xbf\xfb\t\xde\xfc\xa6\xd5\xacz\ -\xd5Z\xb0l\x1e\xfb\xee4i\xd2\x15\xd8:\xabC\x19\xd5\x1c\x12\x04q\xe6\x8b9b\ -\x90\xd6QI)\x17\x0b\x94}\x8f\xa2cQ\x14\xbay\x93\xfa^\x01\x96x\xaa\xe8\x9dH\ -\xc1\x8a\xd5\xff\x8a\x8eE\xc9s)\xb9.\xe3#>\xae\xd5/T\xb5\x00I\xa2\x948\x96\ -\x84\x9d\x908\n\x11t?\xc8H\x8b4\xcc\x92\xe0\x12\x07\xd2l\xf9/\xc1\x91Ja\x15\ -\x84\xfa\xb2\xa5\xb2\x95\xebfQ#\x05\x18\xf1\xd4q\xa5\x9e\xe6\x8cV\xf6\x9ar\ -\xc1\xc6w\x1c\x04i^\xa8pA,\xb0d\x82\xebX\xf8\x9e\xc8\xfa\x84\xabT\x10KB\xd5R\ -\xf30\xe2\xc2\xa8\xd7\xbd~\xd2\x01+\xe9\x9a_\x04)2MT\xea\x88\xde fy\x81\xe5\ -\xa2*\x98\xa8wd\xb6\xc8~\xb6\xc8{Q\x1f\t\xbd?\xcf\xfa)\xe5\xbf\'\t\xb4ZIn\ -\x06\xca:\xcf\xaa9\xf0P%\xd2\x9d\xc1\xddG/\xd9\x88\x8e\xf2\xf9\xe9-y\xa1\x05\ -\x8a^\xc9v\xda\x91\x8e[\xcc?7\xbd?;R\xcd\x93\x9dv\xcdU\x9e\x95\xe2\x10c\x11a\ -\xe9`\x80# \x84\xa0\xddn\xe7\x82V\x97&\xd1+c}\xcc`\'=\xad\xf4\xb4\xdd_7Hr\ -\x1c\x87F\xa3\x81\xeb\xba\xec\xda\xb5+/U\xee\xba.\xadV\x8b\xa9\xa9\xa9Cv\x1b\ -\xfa\xde\xf5\xca\\\x0b^\xbd\xaa\xd7&!-\xa8_N\x99\x0f\xad\xccz\xcdRq\x1c\xe7>\ -\x06=\xd7\xbd\xf7\xfdr\xca\xe5\xe8\xact\xdb\xb6\xf3\x1dZ\xaf\xf9J\xfb\x8et\ -\xaft=\x17\x83\xcaIJI\xab\xd5\xca{\xa3\xeb99\xd1\x9c\xe2\n\x04H\x04\x96P=\ -\xae;\x89\xaa\x10Q.9xV\x80 \xe1\xd2s\xe0\x03\xef\xbd\x89u\xcb,.:kI\xde-oll%;\ -w\xcf\xe1\x95&\xd9\xf4\xc8\x13<\xf4(\xfc\xc1]\xef&L\x05\x9b\xbf\xff\x03U\x06\ -Kj\x93L\x92u\xd1P\xdd\xfd\xb4\x9f@\xb5m:>\xc2\xa0C\x14\xb6U\r"2\x9fA\n^\xac\ -\xf2]\xbc\x18\n)T\x842\x119H\xd2( \x0cZDQ\x0b\x1b\xb5\xd3\x08\xa3\xac\x10$]a\ -Y\xf0\x04\xae\xa3l\xcb\x02K\xb5f\x95\x02\x99*\xbf\x92p3c\x98\xcc\x94Go\xf8Xv\ -\x0e\xe2\x18GF\x14\xec\x04+\t\x90Q\x80H\x02\x1c\x19Q\x16J\xa0\xfb(\xe5F\xa4\ -\x84\xb6\x8d*\xe9\xdej\xd5\x8fz\xffi\xd8!i7\x88\xdbMd\xd8\xc6\x91)\x15\x0fJV\ -\xd7\x87b\xc5*\x10\x8cP\xa5]\x0c{P\xb5Um/\x19\x87 %\x8e\xb0\xf1lU\xc6\xc3\ -\x15jg`g;(\xbd\x10\xf0\x1c\xa5Ld\x9a\x12G\x11\x9dN\xb3g$\xfd\x01\xd9\x9a(\ -\x8e\x95\xa52\xcb\xc1\xd4\xb2\xc3\xb6\xa1RR\rWlIV\xfc03e%j\x17\xb2p)&\x1d\ -\xe5u\xd4\xa9\x01\xba\x82M\x97\xc1\xd09\x00\x8e\xe3P\xf6\xdd|\xfe\xed\xcc\ -\x91$\x03\x15\xb9\xe5K(Xj\\\xbe\xe8*\r\x920k8\x16s\xb4fP\x9a^A544\x94+\x8eR\ -\xa9\x94\x8fI+:-\xc4\xb5B\xd1\x99\xdaZ\xf9\x81\xea\xd6\xf7\xfc\xf3\xcf\xb3s\ -\xe7N<\xcf\xcb\xcbtt:\x1d\xce9\xe7\x1c5K\x99\x00\xd5Y\xdbz.\xb4p\xd5\n\xaaW\ -\xd0\xf6\x9a\xa2z[\xcc\x1e\x89^\x05\xad\xcf\xa9\x15\x98>\x97\xf6\xcf\xe8k\ -\xe9\xb2-\xc7B\x18\x86}\xb5\xc1\xf4\xdc\xe8s\x08!r%\xe3\xban\xdf\\\xeb\xda^\ -\xfau\xa5R\x89R\xa9\x94\xff\xedd\xa8\x87u\xea+\x90&\xb9\x14\xb7mH\xa4\xda\ -\x87\xd8\x04\xd8\xe9<%\xe05k\xe0#\x1fx\x177\xbf\xee5\xd8$\xcc7a\xff\xbe\x19\ -\xaa#KiK\x8f\xea\xf8i|\xe4c\x7f\xce\\\x1b\xde\xfc\xd6\xdb\xf9\xce\xf7\x9e\ -\xa2\xd5\xee\xae\xaa\xc9\n<\xda=\xc5\xc3\xb5C\xf3x\x1dH\x9e_\xc0\xf5\xbc\xba\x9f\xf9\xce\x9d;\ -\xf9\xfc\xe7?O\x10\x04\xb9\tE\x87\x96j\xc17\xb82\xd7B\xb3\xddn\x03j5\xae#\ -\xaf\xee\xbf\xff~\x0e\x1c8\x90\x0b\xd3(\x8a\xa8T*l\xd8\xb0!\x7f]\x1c\xc7\x14\ -\x8b\xc5>\xc1\xad\xfd\x1bQ\x14\xd1\xe9th\xb7\xdb\xb9\x0f&\x0c\xc3>Ev,\xe6\ -\x9d\xde\x9d\x87nI\xab\xfb{\xb4Z-\x84\x10\x87\x08\xea^\xc1~4<\xcf\xcb\xfd\ -\x1a\xbd\t\x80\xfa\xbcz\xfcz\xee\xf4\xf5\xf5=\xe8\xb1\r\x16b\xec\xbd\xd7\x13\ -\xc9\x89Wa\xc7\x8b@\xb5\x00\'\xb3A\xdb\x16\xed\xb0E\xc5K\xa8\nAHL\xbb\xde\ -\xe1\xe7\xceYF\x94E\xe48e\xd8\xfd\xd3\x17\xf0\x8b%\x0e\xb4[\x1ch\xa6\xd8v\ -\x99\x7f\xff\x9f\xff\x8a/|\xeav\xbe\xfe\x90\xcd\xce\x9f\xb6\x99\x13#e\x8a\xa5\xbb\x10\x92\x92d\x19q\x96\xedc;\xd9\x03\x1e\ -\x87$i\x84#lU\xdb\xe9(\xdb\xec\xb8\xd9\xc1q-p=\x90)I\x1c\x11K\xb0\x1d\x0f7\ -\x8b\xc0qm[Ii\x99\xa8e}\x12\xa1\xb6\x87B\xe5\x87\xd8j\xe0\xa8\xa6>\x12\xfcb\x11\xa2\ -\x80J\xc1c\xd7\xec\x1cg\x9c^\xe5K_{\x0c\xeb\xac\x8d`9t"\x89\xb0\x05\xf7}\xf5\ -Q\xce?w-Vq\x8c\x00\x1d\xfd\xe4\x00\x01\xb2\xdd\xc2*\xaa\x04\xad\xf9\xb9\x0e\ -\xc3#\xa3\xc7\xb5\x13\xd1N\x7f\xe1\xda\xd8\xae\x16\xc4\xb1\x12\xecY\xb2\x1f\ -\x16\x99# \x8b\xf1\xb1\x1cUs2;\x87\xba_\xa9\xc2rE&l3\\\xb7\xe7w)\xb0\x1c\xa7\ -_\x96\x89n\x18m\xcf\x9f\xb2i\xed\xbd3u\x1e\xe1\xb8\xdd\x81\xe77\xa1c\xbf\xe8\ -~\xb7z<\xcf\x87\x91\x9e\x96\xcc\xfe%z\xea\x9f\xf5\xccK\xdf\xb1z\x1eD\xef\x11\ -\x03+jP\x89\x91t\'\xc7u\xecL\xb7twM\x8b\xf1Zu\x85\x80\x1a\xa7e\xc9L\x19\xa5=\ -v\xce^\x85\xa9\xf0|\xad\xac\xfa\xc7\xa9\xef@\xdd\xdb\x91Yh\x15\xde\x8b\xe58Z\ -\x7f\x1e\x82\xad\x17\x0f\x16\x08\xa1\x17\x1f\xf9\x99\x8ex\xfd8\x8e\xb3\xe6Q?\ -\xe1\x1b\xdf\xf8\x06\xf5z\x1d\xd7u)\x97\xcb|\xedk_\xe3\x89\'\x9e\xe0\xdak\ -\xaf\xe5\x9ak\xae\xe9\xb3\xeb\xf7\nL\xcb\xb2r\x01\x1d\x04\x01\x0f=\xf4\x10\ -\x0f?\xfc0333\x14\n\x85<,u\xc7\x8e\x1d\xbc\xe1\ro\xe0\xado}+\xa0\x04\xb3\x16\ -\x9a\xdaA\xde\xcb\xa0b\x18\xfc\xff\xcb\x11\xaa\x0b\xbd\xb6\xf7\xf5G\xda\xc9\ -\xbc\xdc\x08\xa8\xc1\x1d\xd4\xd1\xfe\x0e\xf4\x85\xea\x0e\xde\xd7\x89V\x1e\ -\xc0)\x9e\x07\x92\xa6Y\xc5\xc5\x88\xc0\x8e\x88\xb1q(\xe2e\xd1\'\xba4\xb7zV\ -\x12\x90\x1dpB\x1ai\x91\x7f\xfa\xd6\x01>\xff/\xdb\xf8\xf6\x8e\x19f\x9b`y\x05\ -J\x8e\x83\'\x03\xc2\x83/\xf2\xc9\xbb\xde\xcb\xaa!8\x7f\x15Te\x84#\xda\x10\ -\xb5\x01\x01N\x11\x19;XN\xe1\xb8V\x97:9L\x8b\xcfn\xa8\xa5\xce\xee\xe8\x15v\ -\xb6R\x1e\x87\xbcF\xf7P\xd1\x0c\x0e(\xfb`\xca\x81\x0fh\xb6\xe8OH\xfb:a\x80\ -\xc8\xcf\xd0U&=\xaf\xe9\xfd\x0ej$\x83\xceXk!\x896\xe0\xa4\xee9\xa47\x81\xadW\ -\x1d\x1d:\x86\x9e\x1c\x8a\xfc:}#\xe4\xb0\xf7\xdb7\xc6\xde\x9f\x8fe\ru8\xa5\ -\xa3\x93\\\xb5\xc2\xa4?,\xcf\xea\x19\xcf"\x15\xc8\x11\xc9\xdf\x87~\x05\xdc\ -\x7f\xfd\xfe\xf9\x1d\xbc\xf6\xc2\x11b\xdd\x95\xf8\x9dw\xde\xc9\x0b/\xbc\xc0\ -\xc4\xc4Dnw\xafV\xab4\x1a\rFGG\x89\xa2\x88s\xcf=\x97\xff\xeb\xb7\xfe\x93\xb5\ -c\xfb\xf3\xb2\\.\x03\xe4\x1d\xf4\x9e\x7f\xfey\xb6l\xd9\xc2\xb6m\xdb\xf2(\xa3\ -z\xbd\x9e\x17\x0c\x9c\x9f\x9fg\xc3\x86\r\xbc\xf9\xcdo\xe6\x82\x0b.\xc8\x0b\ -\x06\xea\xd0\xdc\x93\xc1Ql8<\xa7\xb6\x02\x91iVJ5 \xb0Z\xc4\xd8\xf8\x8c\xe0h\ -\x0f7tc[% \xdb\xe0\xb4\x80\x02;\x1ae\x9e\xd9\x07\xef\xff\xd8\x17\xf8\xf1\x0b\ -\xb3\x14\xab\x13\xb4k-H\x12\xd6\xacY\x01\xf5\x9f\xf2W\x7fz\x07k\xaa\xaa\xbft\ -\x81\x8eR@I\xac\x92\x08\x9d2\xba(\xe1bc\x11\x06\x95A\xf7\x81\xd6+\xe5\xdeG\ -\xdd\xc9U\x8a\xecyM\xb6\xa9\xef9\xeb\xa0\xa28\xc2\xd8,\x88\x89\xd1\xadB\xb4\ -\x90\x1fT\x1cB\x0f\x96\x1e\x99\xdd\x87\x16\xe8\xfa\x85\xdd\x8c\xfc\xc1q\xf5)\ -#\xab_Mj\x9d\xd2\xfb\xba\xc3*\xb3\xde\xeb\xf6r\xc4\xfb]H\x11\x1c\xee\xf8\x85\ -\x8e]\xe8z\x0b\x9c\xafw\x90\x87\xe9\'\xf33Q \x83\xd7?\x8a\xc2`\xe0\xef}\x8b\ -\x96\x01\xb4\x8f\xe5S\x9f\xfa\x14\x8f?\xfexn\xfe\xd2\xe6\x96\xb9\xb99\xc6\ -\xc6\xc6r\xf3\x9265\x01\xb9\xd9G;\xfe\x8b\xc5"A\x10033\x83eY\x8c\x8d\x8da\ -\xdb6\x8dF\x83e\xcb\x96q\xdbm\xb7q\xc5\x15W\x00\xfd\x89\x87\'C\x9e\x83\xe1\ -\xc8\xd8\x1f\xfc\xe0\x07?x\xa2\x07\xb1x2\x13\x89\x80\x18\x15\xe9\xe1Q\xc0J3\ -\xbb\x8c\x92\xbb$\xd93\xac,*\x01`\xe1{>\x13c\xb0\xeaU\xeb\xd9\xb6\xf59\xe2N@\ -;\xe8\xe0\x14\xcb\x1c88\x8beIv\xbd0\xcb\xe5\x97\xbd\x8a\x82\x804\x92xv\xf6\ -\xc8uB\x95\xa1\x858\xa2\x99\xe6e\xdeE\xfes\xff\xf9\xba\x99\x1d\xe9\xc0\xf1}V\ -\x9dA\xef\xb7\xecY[\xf6\x9f\xbc+h,\xb2\xec\x96\xee9\xc4\x02#\xb0\x16R\x1e\ -\xbd\x12\xd0\x92J\x91Z\xd9\xb6\xc6"+*)3SX\xf7l}35`>\xeb\x1d\xde\xe0\xac\xea\ -\xa0\xa1\xfe\x99\xd6G\xa9\xebZ:\xa2\xecpd\xef\x95\xd4\xdb\xaf\xbe\xd0\x83Azo\ -\xf6\x08>\x13\x8b\xec\xde\xad\xecK\xbf\\\xf4\xff~\xb8!\x1d\xf9\xdf\xc7N~\xdd\ -\xee\xcf\x0b)\x8e^\x05}\xa4\x1d\x88\xe6\xd2K/e\xef\xde\xbd\xbc\xf0\xc2\x0b\ -\x00\x8c\x8e\x8eR(\x14\xf2\xfe\xe6\x9e\xe7\xe5!\xa9\xb6mS*\x95\xf2\xc8)\xed\ -\xc7\xd0\x91W\xcb\x96-c||<\x0f\xfd\xadT*\xbc\xedmo\xe3\xc2\x0b/\xccM5\xfa\ -\xbb\xce\x870\x9c\xdc\x9c\xe2;\x10 UUf\x03\x0e"\x88)0\x02\xb1\x9fw(\r]\x95\ -\xafa\x93\xe5+H\xf5a\x96\xd6P\xde;\xfa[?\x8e\xf8\xd0\xc7?\xcblX`\xd7\\\x04\ -\xc2gb|\x88\x97\xb6=\xc9\x07~\xf3-\xbc\xe3\xe6\xb3Xj\xab\x84>[\xc6\xa4\xed6\ -\xc2-fN\xe8\xa3\x0b\x89\xa3\xde\x03\xfd\x96\x8f\xb4\xef\xa7\x01\x1bx\xf6}A\ -\xeb\xcd\x11.a\x1d\xe6{J\xdag\x17\x1f\\\xf1\xf7]kP\x81,\xa0\x98\x16\xdaQ\xf4\ -\x8d{\xe0<\x8bM\xc4<\xdc^b\xf0\xfc}\x0c\x8c\xaf\xef5\x87\xbdB\xef\xd1\x0b\ -\x9dXg\x99\xf4\x1fu\xb8\x9d\xd4\xcf\x9c#\\d\xa1\x9d\xc8\xe1\x14\xc8B\x91KZ1x\ -\x9e\xc7\xc1\x83\x07\xb9\xfb\xee\xbb\xd9\xb4i\x13K\x96,all\x8cF\xa3\xd1\x97\ -\x1f\xa1\x13\xe2\xa4\x94\x14\x8bE\xca\xe52\xb5Z-O\xa2\x8b\xa2\x88\xb9\xb99\ -\xca\xe52\xaf\x7f\xfd\xeby\xe3\x1b\xdf\xc8\x8a\x15+\xf2\x1aS\xbd\xd9\xdd\xad\ -V\xeb\x90\x0cl\xc3\xc9\xc7)\xad@\xa4Tn\x90\xc4\x86\x989l\xda\xf8T!.@\xea\x80\ -\x80\x96\xa3j+\xd9\xa8\x0c]O6U\x94S\xaaLP\x9d\x14B\x07\x9e\xde\rw\xfe\xe1g\ -\xd8\xdd*PK]:\xf5:K\xa6\xaa\x88\xda.\xfe\xdb\xef\xfc\x06\xd7\x9c_\xa2\x0c\ -\x14$\x08=c\xba\x8d\xc9b\xa5\xc3\xa1\xde\xe2>3\xd5\xc0\xbf\x0e/ \x17\xd2\x0e\ -\x0b\x1cv,\x1c\xe2\xef8\xdc\xef\xbd/\xe8\xb9\xde\xe1\xd6\xeaG\x1d\xff\x11\ -\x9d\xdbb\xc1!\x0c\x1a\xf9\xf4\x91\x87\xbb\xc6\xe0\xf8\x8e\xbc\x02\x1fT \x0b\ -]] q\xfb|7G\rj\xfbY\xd3\xab\xdc{\x15\xfa\xc0v\xedHo\x1f,\xac@\xf4\xdffgg)\ -\x97\xcbx\x9e\xc7\xcc\xccL\x1e\x95533C\x10\x04\xd8\xb6M\xa1P\xa0P(\xe4Ux;\ -\x9d\x0eI\x92044\x84\x10\x820\x0c\xf1}\x9f\x8d\x1b7r\xf5\xd5W\xb3n\xdd\xba\ -\xbe\x1a[\xda\xe7\xa2w \xc6|ujp\xca+\x90(UU8\x12\x1a8\xcc\xe3ST;\x10\xe9\x81\ -\xed2/T\xd6\xb8V %\x19d\tUEu\x02\xd9\x04\xb7BM\x08~8\x07w\xbc\xff^\xb6\xcfD\ -\xc4\xd2\xc6\xb1c\xe2\xd9\x1d\xdct\xe5z\xdew\xc7\x9b8\xff4pS\xf0E\x96\xf9\ -\x0b\x87\xdaZ^\x16Y\xcd\r)\xbb\xe6\x0eKW\xf3\x15\x03\x82.\xcd\x04\xa3N\x02\ -\x93\xe8\xd6\xbfp\xe4\x95\xfc\xe1D\xb3 \xdb]\x1cI\xba\x0c:\xcc\x07\xcf\xd0c\ -\x0e\xeb\xf5\xcf\x1cr\x1d\x06\x85{v\x1f\xc7\x98\r\xdd\xebk\xea]Y\xf7\xfa\x83\ -\x8e\xa6\xa4\x16Rp\x87\xf3\x01\x1c^\x81t\xc7+{\xbaO. \xb3\x81\x81\x9d\xd7\ -\xcf\x9a^\'\xba\x14\xdd\xb9<\xdc`\xf4\xb1}d\x15\xae\x0f\x93;\xd1\x1b*\xaa[\ -\xa9\x16\x8bE\xe28\xe6\xd9g\x9f\xcd+\xe3n\xdf\xbe\x9d\xf9\xf9\xf9\xc0\xfd\x16\x87#+\x90\xfe3.\xa0@,\ -\x0b\xddc\xfbh\nD\x0c|\xcfFyx\x05\x92/M{\x04\xce!\xc2\xbeG\xa8[\xfd\xc2y0xuA\ -\x05\xd2w\xe4Q\xc8Cq\x17V"/g\x07B\xcfk\x8e\xbe\x03\x19\xfcY\xf6\xfc\xa4{f.L\ -\x9f\x19\xf0\xb0G\x1d\x07}\xf3\xd8{\xb1\x1e\x852\xf8}\xc1Qv\x0b\x1c\x1en\x17\ -\xd2\xfb{\x1c\xc7\xb8\xae\xdb\'\xf0\xf5\xeb\xb5\x19K\x97\xff\x88\xe387E\xe9,\ -r\x9d/\xd2\xbb\xcb0\n\xe3\xd4\xe4\x94V \xc8L(d&\x10\xd5\x1f$Kn\xc8\x1e\x8c\ -\xb8\xc7Q\xabJM\xe8\xd0\xcbL\xc8\xe7!H\t\xb1c\x13\x00?\xdc\x07\xff\xfd\x9e\ -\xef\xf1\xd9\xff\xef_`\xeaUx\xd5"\xe1\xdcv\xfe\xf8w\xdf\xcd/]\xe82\x12K*\x8d\ -iU\x86\xd6\xf5I-\x81%EV*D%\xb0\xb9\xc2V\to=Q8\xbd+\xe0tp<\xf93\xba\xb0\xb9\ -\xa6\xfb\x08\xebPV\xfd\xc7\xa3?t\x0b\xf9>\xfa\xcey\xac\x9f\x80A\x014\x10at\ -\xb4\xd3\xf4\x89\xa6|\x10\xc7\x9a\x97\xb1\xf0}\x1e~\x9e\x16\xe6\xe5\x1e\xaf8\ -\xfc\x18\xe5\x11\xe6\xff\x7f\x99\xd9\xaa\x7f\x00\x0b\\\xf8\xe5*\x10\x83aq\ -\x9c\xda\n\xe4x\x91\xd0\xee@\xd1\x07\x88\x89\xdbu\x9cB\x95\x8e\xed\xf0\xcd\ -\xe7\xe1o6=\xc3g\x1fx\x02\x86\'(\x14$\xc3r\x86\xbf\xfc\xd0;\xb9b9\x94\xa3&4g\ -`x,\xdb\x05\xf4\xac\xb5\xe3\xac"\xa9\xd3\x93\x19lu\xf5\xd5\xb1\x84Q\x1a\x0c\ -\x06\xc3\xc9\xce+z\xf9!-p\x8bd\xc9\xd4\x0e\x8e;\n\xd2\xc1\x95p\xe1\x99\xf0\ -\xde;6p\xcb\xd5ka\xf6Y\x9cV\x9d\xb9}5>\xf9?\xfe\x99:\x10\xb8e\xd2\xea\x12\ -\xa4\xe5\x13#2\x93S\x16\x91c\xbbH\xcb\xee\xb3\xfeh\xba{#\x83\xc1`8\xb51r\x8c\ -\x94N\xdc!\x89\xb3\x8cu\t\x04)~\n\xab\x0bp\xe7\xaf\\\xc9\xad\xaf[\x8f\xd7\ -\x9af\xacT\xe2\xa9\xa7\x9f\xe7\xde\x87g\xd8\x0b\xcc\xd9>M\x1c\xe2\xd4&\x8c!\ -\x92B\x994,\x10\x8e\xcd\xa0O\xb2\xd7\xe6~\\\xbew\x83\xc1`8\tx\x85+\x90\x94\ -\x84\x08\xd7q\xb0\xfd\xcc\'\x12\x05\xd8nBE4)\xc6\r6\x8c\xc2\'\xdew\x1dW\xad_\ -A4\xf7\x12\x13SK\xf9\xc4g\xee\xe1\x99\x19\xd8\x8f\xca1\xb1\xb2f\x11I\xaa:\ -\xf2I8\xd4\x89\x9e\x19\n{w GK\xe22\x18\x0c\x86\x93\x99W\xb4\x0fD\x92\x92d\ -\x1e\t\x07\xa1\xaa\xbd\xca\x14\x88@\xc4`9$\x94hHA\xdb\x82\x0f|\xe4>\xbe\xfa\ -\xd8\x16di\x88\xc9\xd3W\xf2?\xff\xef\x1b9\x1d\x18\xca\xce\x97\xf9\xe2\xb1\ -\x85jf\xb4p\xd9\x0f\x8e\x12fi0\x18\x0c\xa7\x06\xaf\xf0\x1d\x88\xc0\xc2\xa1\ -\x13\x044;\xf3 \x02\xb0\x03H\x03\x88,H|\x92\xf9\x06C\x168\x01\xfc\xf1\xfbo\ -\xe4\xda\xd7\xbf\x9a\xe9};i5S\xfe\xf6\x1f\xa7\xa9\x87\xaa\x12U\x1e]eAz\xa4\ -\xdc\nz\xfe\xf7\x8aU\xdd\x06\x83\xe1\x7f\x07^\xd1;\x10\x80 \x8c\xf1\xb0\xe5Q\xccX\xbd\x18\x05b0\ -\x18NA^\xe1&\xac\xcc\xdf\x91\x15\xb5\x92\x14IPa\xb9\x11\x10\n\x95\xd4\xae\ -\xd2\xb7-D\x12Q\x02VU\xe0-Wo\xe4\xfd\xef}\x0b?\xdd\xb9\x95\xcf\xfd\xcd?\x91H\ -\xd5D\xb0\xd9V\xfa \x05\xa2H\x1e]9\x18\xe5a0\x18NQ^\xe1\xddZ\x12T\xa9E\x81E%\ -\x97\xe5\xba\x1b\x87\rx\xba\xa2t\xe2!\xc3\x04\xc7\x07G\xc0\x85\xabm\xce\x9c\ -\xba\x94\xb8\xbe\x9b\xfb\x1e\xb8\x8f\r\xe7\x9d\xcd\x95\x97\xad\xa3X\x84z+a\ -\xb8d\xd3\xea\xb4\xf0\xdcr\x7f\x06\xf0\x91\xfaU\x18\x0c\x06\xc3)\xc4+\xdc\ -\x84\x15\x01Y\x97AY!\x86\xbc\xf4\x89\x0e\x92rH\xb1\xb59+\x02+FURt;\xaaXc\xea\ -\xf2\x17\x7f\xf5\xcf\xfc\xe0\xe9\xef\xf3_\xff\xe8\x83\x0c\x952\xdfG\xaa\x14M\ -^\xc3J\xa3\xcb\x7f\x1cRO\xc4`0\x18N-^\xe1\xcba\x0b\xb5\xcfpA\x82#\xc1O\xc1\ -\x97\xaaw\x88CJB\xa2r;t\xddB\x1fU\xc40\x89\x80\x10_\xc0\xaf\xdeq\x13\xeb\xd7\ -\x9f\xcb\xc7>\xf6Q\x820\xb3xI]\xb4$\xa5\xafi\x93e\x82\xaf\x0c\x06\xc3\xff\ -\x1e\xbc\xc2\x15\x88\x03\x14\xb3\xca\xbc\x80T;\x07[\x82#S<\xc0\xc5\xc5\xb2T\ -\xa8n\xa2\xb3\xff\x1c\x0b\x1c\x07\xa4C\'Pj\xe8W\xdfq\x1b#\xc3C<\xf3\xcc\xd3\ -\xb4:!\xaem\xd3\xdd\xcb\xa8\xf2\x89\xbd\xd1\xbd\xd2:r\x05]\x83\xc1`8\xd9ye+\ -\x10\tR\x8a\xcc/\x11\x03M\xa0\x06i\x03\x92\x04\x12\x81\x93\x85\xe5JK\xa5\x86\ -\xc4\xba\xe4UZ\x82\xc4\xa7\xe0C,\x95\xb9\xea?\xbc\xf7\xd7\xd8\xb5k\x07\xb6c\ -\xd1h\xd5\x06/\x95\x93\xf6|\x99\xdd\x88\xc1`8Uye\xfb@d\xd6V\x03\xc8\xfd!2\ -\x06\xe9\xa8\x86S\x96\xab\xdau\xb8\x90d\xa6\'A\x82\x83\xad\xfc\xe2\x12\x02[)\ -\x10a\xa90^\xdf\x81m\xdb\x9e\xe3\xec5k\xb0Hz\\\x1c\xdd"&\xc7\xd6R\xd5`0\x18N\ -n^\xd9\n\x04\x06\xfaR$=6\xa6,~w\x01SS\xde\xb0h\xa0I\x11\x0c6\x11Z\xa8\x01\ -\xd3`S)\x83\xc1`851\n\xc4`0\x18\x0c\x8b\xe2\x95\xed\x031\x18\x0c\x06\xc3\xa2\ -1\n\xc4`0\x18\x0c\x8b\xc2(\x10\x83\xc1`0,\n\xa3@\x0c\x06\x83\xc1\xb0(\x8c\ -\x021\x18\x0c\x06\xc3\xa20\n\xc4`0\x18\x0c\x8b\xc2(\x10\x83\xc1`0,\n\xa3@\ -\x0c\x06\x83\xc1\xb0(\x8c\x021\x18\x0c\x06\xc3\xa20\n\xc4`0\x18\x0c\x8b\xc2(\ -\x10\x83\xc1`0,\n\xa3@\x0c\x06\x83\xc1\xb0(\x8c\x021\x18\x0c\x06\xc3\xa20\n\ -\xc4`0\x18\x0c\x8b\xc2(\x10\x83\xc1`0,\n\xa3@\x0c\x06\x83\xc1\xb0(\x8c\x021\ -\x18\x0c\x06\xc3\xa20\n\xc4`0\x18\x0c\x8b\xc2(\x10\x83\xc1`0,\n\xa3@\x0c\x06\ -\x83\xc1\xb0(\x8c\x021\x18\x0c\x06\xc3\xa20\n\xc4`0\x18\x0c\x8b\xc2(\x10\x83\ -\xc1`0,\n\xa3@\x0c\x06\x83\xc1\xb0(\x8c\x021\x18\x0c\x06\xc3\xa20\n\xc4`0\ -\x18\x0c\x8b\xc2(\x10\x83\xc1`0,\n\xa3@\x0c\x06\x83\xc1\xb0(\x8c\x021\x18\ -\x0c\x06\xc3\xa20\n\xc4`0\x18\x0c\x8b\xc2(\x10\x83\xc1`0,\n\xa3@\x0c\x06\x83\ -\xc1\xb0(\x8c\x021\x18\x0c\x06\xc3\xa20\n\xc4`0\x18\x0c\x8b\xe2\xff\x07\xc1\ -\x94N90\x82\xbf\xc4\x00\x00\x00\x00IEND\xaeB`\x82' +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01\xf4\x00\x00\x01\\\x08\x02\ +\x00\x00\x00\xb1\xfb\xdb^\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\ +\x00 \x00IDATx\x9c\xec\xbdg{\x1cIv4\x1a\'\xcb\xb4G7\x00Z\x90\x1c\xb3\xb3\xab\ +u\x92V\xaf\xfc\xfd\xff_\xde+w\x1f\xadV\xd2:ifg\xe8\t\xd3\xbel\xe6\xb9\x1f\ +\xd2TVu7\x087C\x80\xac\x18\x0e\xba\xcbg5\x1a\x91QqN\x9e$fF\x8b\x16?8\x98\xd5\ +\xeb\xff\xfdgU$\x00\x18`\x06\x11\x88\x00\x80\xf4\x0e\x00\x01Df\x93 \xbd\x03\ +\t\x02\x01B \x0c\x83N\'\x8ez\x03t{\x10\x02y\xaaV\x8b"O\x95Tl\xcf\xc9\x0c\xc5\ +\x90\nJ1\xdb3_\x1f\x04*\x14\xa79\x1f>\xfd\xf3\xd1\xf8\xfe\r\x9d\xb5E\x8b\x9b\ +D\xf8\xa1\x1b\xd0\xe2\x13E\xb2<\x91E\xa2\xd9\x96\x00\x06\x13H\xbf\xd7\xcb\ +\xfa\x8d\x95\x1ed\xa8\x99\xa1\x00AP\x8c\xb2\x94\xe0\x9c\x15G\xb2\xa4N\x17"\ +\x10\xddA\x04\x94y&\x95\x04\x83\x08\x0c\x10\x81\x00E\xa4\x14\xd4\xcdI\x19\ +\x02\x02\x81\xf9\xc9\xcb\x96\xdc[\xdcN\xb4\xe4\xde\xe2\xc3`q\xf2\x9d\xe5r\ +\x80A\x9a\x83a\x165\xc8*z\xbdR\xd3\xba~C\xccL\xc4,%\xab\xb2,\xc3,\r\xa3X\x88\ +@\x880\x08\x99\xcbB)\xc9\xcc\xfaX!@\xac\xbb\x04RF\xce3\xae*\xe4\x89\x88\xcd\ +\xe1\x94\xae\xce\xf2t\x1dw\xfbW\xfe\x1cZ\xb4\xf8\x9e\xd0\x92{\x8b\x0f\x80,\ +\x99\xe7\xc9\\Xr%\xf7\xc6\xee\xc0\xd6\x901\xdb\xb5\xb6g(f"\'\xf7\xa1\x00\x96\ +\xacTYJ\x15\x16e\x18\x04$\xc8\x1c@\x02P`\x08\x02\x13X1\xeb\x07\x02\x063\x84a\ +\xf9+y5\x0c\xae: ^/\xa7-\xb9\xb7\xb8\x85h\xc9\xbd\xc5\x07\xc0j\xfa\x1a@\x18 \ +\x0c\x90\x16\x96(\x19\x10\x865\xc9x3\x15\xef3X\xef\x02M\xc8d\xdf\x00\xcc\xcc\ +\xac\x94RR)m\xca\x9bC\xd8\x9e\x83H\x04`fR\xac\x8c\x15\xaf;\x0f\xd2\x0bl\xfb\ +\x91\x8b\x10=\x83\xddQ\x00\xb2dqc\x9fK\x8b\x167\x87\x96\xdc[\xfc\xd0P\xaaL\ +\x16\xef\x08P\x8c8$\x02\xa7\x85g\xbf\xd8Pj\xe5\x8e[\x0b\x9e\xedV03 \x88\x98\ +\x8dS/\x98\x15\x11C\x911\xd9\xf5\x7fL\x04f\x16B\x08\x11\x88\x80\x02\x86b%\ +\xa5RJ)f\x023\x81A\x9a\xe5\xf5\x897]y\x9f\xf1u\x0f\xc3\xde\xbf\xbf\xc4\ +G\xd0\xa2\xc5\x0f\x8b\x96\xdc[\xfc\x10XM_\xdaLD\x93\xc6\xb2u7\xcd\xddI\xce\ +\xf0\xf8\xbd\xdf\xc1*\xb5&\xf8\xb6\xa3\xb8\xce\xe8N\xb6\xd7\xd6\xd5\xf9\xbd\ +\x91f\xe3\xbfq\x8f\x14\xca&\xccx\x16\x123\x13L\x92\xccx4>x\xff\x9d\xb7h\xf1\ +\x81\xd0\x92{\x8b\xef\x1dE\xb6\xca\x93y\x95\xb2\x82\x8a,\x1b\xb2\xdd!\xc9\ +\x99A\xdd\x9a~w\xf93\xdb\xc1h\xcav\xde\xb6\xd5e\xc2\xc0\xe3q\xf7(\xe1\xd6{\ +\x8b\xcc\xa6\xfa\xb0\xb5z\x98\x15\xf3\x83\xc7_\\\xeaCh\xd1\xe2\x07FK\xee-\ +\xbew,\xcf^\x19\xfa\xa4Z\x06d\x03\xfe\x88T\x02e\x05\x98\xd1\x8d\x00\xcd\xef\ +\x1dJ\x0b\xce\n4B\xb1\x1e\xa1o\x93\xed\xf5!\xac\xfe1>\x8f3W\x14oK\xf9\xda<|x\ +\xdd\x84N\xbda\x0c\x86\x93V\xb6\xb7\xb8\xe5\x10\x1f\xba\x01->r\xb0\x92\xc9\ +\xe2mc\x18\x91\x86_\xfa\xd1l\xb16\x88^\x91\x15Xgf\xa8(\x11z1\xf5b\x7f\xee={6\ +\xaa\xcbv\xff"\xdc|\x8f\xba\x8aw\xff`\xb3b\xec\xbf\xc6b\xd5@F+\xdb[\xdc\x01\ +\xb4\xe4\xde\xe2\xfbE\x91\'\xaa\xac\xea\t4e\xbbG\xf4\xd5\xb27CS!\xb1\xca\xaa\ +\x84\x99nD\xc3.E\xc2*nw\xd0fT\xb4vz\xcf\x93\xe1\xc6\xb2\xf3pH\x13\xb7}\x00hd\ +\xe8\x90+k\xd0\xca\xf6\x16w\x02-\xb9\xb7\xf8~\x91,\xde\xd9\x02\x8f\x00j\x02\ +\x9b\x1b\xf3`T\xc4^\x9bKI*\xacR.\xa5\x99W)\x10\x18t\xa9\x17Ws1y\xb2\x9d|\xd2\ +\xde\xc2\xe3u\xba\xf7d\xbb\xd7\x82m\xd0\x8d\xd7\xb3/=8\xfa\xe2\xc2w\xdf\xa2\ +\xc5\x07CK\xee-\xbeG0\xab\xd5\xec\x8dY\xa8\x0f\\\xf2\x86\xaa\xda\xb2.fC\xfd\ +\x0c\x80\xe6\xf7e\x86\xb4`wl7\xa6a\x97\xe2\xc0X(\xe4\x1f\xb0\xc1\xed\r\xd9\ +\xceM\xd2w\xb2\x1df@\xaa.|\xe3\x8d\x87\x82\xcd\xf0\t\x88B\xd1\xfe\xd5\xb4\ +\xb8\x03h\xbf\xa6-\xbeG\xa4\xcbSY\xa4.\x17\xc6\xc6)\x81\xcd\xa4F\x06je\xbe6\ +\xc0X\xe7Xe,\x95\x89u\x86\x01\x06=\x1at\x10\x08=\xdb\xf5Ud\xbb\xb7\xcf{d\xbb\ +\x8e\xb4\x86\x01\x92\xd5\xf4\xfc\xbbn\xd1\xe26\xa0\xcd\x96i\xf1=b5{\xedB\xa9\ +\xb5I\xeb\xaa\xc2\x90\xd4\x0c\xb3z\xe0Z\x8e9\x88\x90\x17(%w#\x8a#s\\\'\xa2(D\ +V \xc9\xab\xb1Nh\xb2\xba\xf7\xa6N\xfa\xec\xc9vx\xb2}\x83\xeb\x8dl\x17\x84<[_\ +\xf2ch\xd1\xe2\x03\xa0%\xf7\x167\x06f\xc5\xb2T\xaa\x94\xb2`Y\x14y\x9a,O\x88@\ +\xb4e&T\xf2\xdf\xb82\xec~\x18\xb3>\xe2\x88\xadq\xaf\x18\xeb\x8c\xf3\x12\xbd\ +\x98\xc2\xc0\xac\xec\xc5\x14\x87H\x0bd9JU?\xd0\xbe\xbf\xa0l\'\x7f\xab\xf5\ +\x8ct\xac5\x08\x08\x80,\x8b\xab}>-Z\xfc\x90h\xc9\xbd\xc5\x15\xc1\xacd\x91\ +\x95\xf9\xaa\xc8\xd6e\xbe.\xf3\xa4,2\xa5J%%\xa0*\x0b}S\x98Wy\x91n\xdb\xfbe\ +\xbb;\x87^YH\x94\t\xc7!\xba1\x05\x02\x00\x84@\xbfC\xdd\x08YAi\xc1E\xc9\xb5\ +\xdeA?;4e;|\xd9\xee7w\xb35\x82\x10\x98\x0e\xa653[\xdc\x01\xb4\xe4\xde\xe2\ +\xa2P\xb2(\xd2E\x9e-e\x91\x95ERf\xeb\xb2\xccX\xd5\x86\x8dz\xe1L\x10Y\x02\xb7\ +Vz5\xf3\x86M\x94q\x82\x9e\xea#T\xb7\xcav\x1fz\xd0h\x9asVp\x1cR\x1cQd\xca\x8d\ +Q\xaf\x83nLy\xc9E\xc9y\t\xc7\xf2~|u\x8b/\xef\xdd\x82\xeb\x16\x8clg\x10!\x0eI\ +_4\xee\xf6/\xfe\xa1\xb5h\xf1\xa1\xd0\x92{\x8b\xf7\xa0\xcc\x93lu\x9a\xaeN\xf3\ +d.e^\x97\xd9d\xd9\xdc/\xd3\x0e\xd8\x05\xf2\x18\xdb\x99\xed\r\x98\xe9\x92\xb6\ +%\xc9\xf8\xd9*z$\x11\xf9\xa5y\x99u\x01\xf7\xb4@Zp\x14\xa2\x1bQ\x14B\x1bA\x9d\ +\x88:\x91P\xccE\xc9\xba\x0f(\xa5\xab\xd2nO`\xfd\x16\'\xdb\tP\x9eE\xa3\xefN\ +\x08\xc4\x01\x84\x1dr5\x9a<\xb8\xca\xe7\xd8\xa2\xc5\x0f\x8b\x96\xdc[l\x87\ +\x92y\xba:K\xe6o\xd3\xd5)\xb3\xf28\xddIpo\xd8)\x19u\xed\xbb\xdcU\xb0\xd4\'e/\ +\x03\x12U\xb5\x99\x06\xe7\xd7\xb3[\xcc\xe0!/S\x9e\xc0\xf5\x8b0#/9/9\x14\xd4\ +\x8d)\x8eH\xd8pm\x1cR\x1cB*-\xe49/\xb8\x90(\x95.\x11CF\xa5\xb3\x97\xcf\xe3NL\ +$\x08a\x88\x80\xaa+v\x07\xfb\x9dv\xd2\xd4\x16w\x01-\xb9\xb7\xa8\x839[\x9f\ +\xad\xe7o\xd2\xe5\x89\x94\x85\xc7\xd6>\xffRC\x8f;;\x86\xbc\xa8h%\xdb=\x8a\ +\xf7\xce\xe1\x9dq\x1b\xb7\xfb<\xabG\xfd\xd7f\xd4\xf0\x03\xa45/\x9e\xf35\x07\ +\x82:\x11u"\n\x03\xe3\xa5\x08\x81NDqD\xdc\x85b\x14\xa5*%\x15\x92KI\xb59Q\x15\ +\x88 \x88\x84\x80\x10\x10\x96\xf1\xf5C\x83b:x\xf8\xe5\x85?\xca\x16->$Zroa\ +\xa0d\x9e\xcc\xdf\xae\xa6\xaf\x8al\xc5\x9eW\xb13\xf1\xdc\x89i\xa3\xbd\x9b\ +\xbb\xf9\xf90~Y\xddJ\xaa;\xcd\\;\xab\x9b\xe6\xba~\xb6\xa6l\xf7=\x9bjQ\xb7G*^\ +\xa5\xbc\xce\x10\x05\x14G\x14G\x14\nbb(\x00\x08\x04(\xa48\x04@\xca\xf6\x13\ +\x8a\xc1\x8aK\x05\xa5 \x19J\xe9\xc4y\xd3\x1a"(\x85\xa8\xbf\xdf\x1f\x8e\xcf\ +\xfb\x10[\xb4\xb85h\xc9\xbd\x05d\x91\xae\xa6/W\xb3W\xb2,\xfcq\x99h*o\xae\xaf\ +\xddE\xfa\x8d\xa3ky(u{}\x83\xd9}XO\xc6\t\xe7sd\xbb\xdb\xddKa\x043\xb2\x82\ +\xd3\x82\x05!\n)\x0e)\n\x10\x04\x04=Y\x1e\xdb\x07\x02\x00\x80 "\xe6\x80t\ +\xe1\x1a\xa5 \x15I\xc9\x92QJ\xe4\x12O\x1e\xb7\xb2\xbd\xc5\x9dAK\xee\x9f4\xca\ +\x8e\x9f\xcf\ +\xee\x9fu\xc7\xb1[3 m\xab\xab\xf6\xbb\xe4\xf8\x9a\xf9\xbe-i\xdd\x8eT\xf2@6\ +\xbf\x86I)(\x9b-\xe3\xfc"\xcf}"\xb2y2\x83\xf1~o\xd0&\xc9\xb4\xb8Kh\xc9\xfd\ +\xd3B\xb6>[\x1e\x7f]\xa4s\xb7F\x9b\x12\xef\xa1u\xbbJk\xfc\x8e \x05H\xc9\x85\ +\xb4\x14_wRj!NOWo!\xf4\xdd\xb2\xddm"\xafY\xfep\xa4\x8d\xd3{?\x1b\xbb\xd5\xb6\ +i9o\xdaHdGT\xd9J\x90\xd5\xd5\xbc\x1b\x9b\x1c<\xdcl\xfbN0\x17\xab\xd7\\\xcc\ +\xa4\xa2\xb0\x7f?\xea\xb5\xc5\xdf[|\x00\xb4\xe4\xfe\xa9@\xc9bq\xf2M2}YM"gi\ +\x9d\xacr7\xb0v\x89Mi\xacgA\x02\x00\x04!\x08)\x0cPH.e\xe5\x9c\xf8J\xba\x96\ +\xdb\xee\'\xaa\xdb\xa5\xad\x03\x97\x1akL(\x95\xabew\xfa]\xb2}\x17\xf5\xf3\ +\xb6E\x1b\x06\xd8\xcc\xcf1maF\xdc\xe9O\xf6/1pi={Q.\xbea\xc5\x00\x17\xcb\xd7y\ +w\x12\x8f\x9eE\xbd\xfd\x8bG+Z\xb4\xb8>Zr\xff$\x90\xad\xcf\xe6o\xffP\xe6k4h\ +\xdd\xcfF\x07\xe0rZljKC\xcb7\xd8W\x10\xba\x11\x95\x01\xf2\x82\x95\xb2\xfb\ +\x93\xe7t{\x1c^\xd5\x80\xe4-y\x93\xb5\x89\xec\xaa\x95[d{\xed\xa0\x8d7n\xc1\ +\xb5a\xb3\x9eLM\xde{\xb7\xed\'\ny\xb2\x9d\x1f=\xf9\x92.\\\xc3\x9dY\x15\xab7\ +\x90\xb2\x94\xac\x18D\x08\xd6S\x99N\xd3\xce\xb83\xfe"\xeeM.x\x9e\x16-\xae\ +\x89\x96\xdc?v0/N\xbf]\x9e|\x03+\xd8\xa9.\xd8\xbdL\x11\x18\x1b\xa6\x1e\xe6\ +\xac\'/n\xe9\t\xa2\x00\x81 =\xf2\xd3\x9c\xc7s\xba\xdd\xfeF\x98s\xf5\xb6\xd6\ +\xcc\xc6\xb2\x16\xfb>\xb9_@\xb67\xec\xf5\xeb\xcbv\xa5T\xa7?\xee]&\xb7}\xf9\ +\xf6w\x9d\xb0`\x11\x05e)\x15K\xc9\xa5d\xa9\x10\xa8\x19g\xff\x9ew\x0f;{O\xa3\ +\x96\xe2[|\xff \xde\x94C->\x16\xb0\x92g\xaf\xfe+\xd5uw\xb1!\xd8\x1b\x94M\xf5\ +\x19\x91\xea\xb4\xbe\xc9\xe9\xd8X\x93\x17\x9c\x15Mzu3.5\xc6\xab6\xdc\xf6\xaa\ +S\xe0\x8a\xd9\xab\xf4v\xa3\xb8k\xe4\xee"\x9f\xcc\x1b?\xed!n%\xdb\x9fv=W\xe4\ +\xbeQRF\x07R\x99\x15\x89\xa87\xfeQ\xd4\xe9\x1eNz\x83\xe1\xfb\xeb\x85\x95y2{\ +\xfe\xcf\x04\xa5C\x11B\x98\x8a\x95Z\xc5\x03\x08\x04\x05\x02A\xf7 \x1a=\x89\ +\xfb\xad\x17\xdf\xe2{D\xab\xdc?Z\xc82\x9b\xbe\xfam\xbe>s\xcc\xae\xb3\xd8\xc9\ +\xbc!\xc0\x0f\x1e\xd6\xca2n\xa7\xf5F\xc1\x00\xf6v`\x00\x88#"\xc1i\xeeU\x7f\ +\xb4\x9b4\xa5\n\xf2\xc8\xdbC3\xf2\xa9\xdf:\xd9n]\x94+\xbb\xed\x8d\xc5\x8b\ +\xc8v\x06\x83h\xb4\xff\x99\xa4\xeebU\xe4y\xb9\x9fe\x93\xf1^\xa0K\xc8\xef\x80\ +,R\xa5\x94\xb0\x1f\x94RJ)\x12\x02a@\x0c\x94N\xc5\xafO\xcb\xf44\xefL:{\xcf\ +\xa2\x96\xe2[|?h\xc9\xfd\xe3D\x91-O_\xfc\xa7,\x12a\xd3`<+F\xffW\xc5=\xe9R\ +\xb4\xee\xb1\xe1f|0\x0eH\xc4\xbc\xce\xab\xa1@\xf6"(%\xb3@\xd0x:\x80u\xe7\xad\ +:7\xeb\xb6P\xf7vl\xee\xb0\xe9\xb6{\xda\xbf~v\xd8\x87\x8eM\xb7\x9d\xe5p\xf2\ +\xb8;\xdcO\xd32\x8a\x82\xbcT\xefN\xf3uzv0\xee\xf5\x07}\xda|x\xd1\xc7\x8a\x90\ +\xcc\xa3\n\x03P\x1c\x00\x0c%\x95\x12BP\x1c\x92bh\xa3\x86\x14\x94\x9a\xcal\ +\x1av\'\xd1\xe8i\xd4\xdbo\xcb\xc4\xb7\xb8Y\xb4\xe4\xfe\x11"[\x9d\x9e\xbe\xfc\ +oVE\xc5\xec\r\x9f\xddS\xdd\x8e\xd9\xdfK\xeb.\xc4\xb8E{\xdbe\x06\xc2\x90\xfa\ +\xc4\xeb\xcc&\xb9\xdb\xbd\x03\x81\xbc\x04\x85h\xc4&]\xbd]\xbf\xd6\xe4y\xb2\ +\xddo\xff\x86,?\xdfd\xf4e\xbbkx\xdd\xa97\x86L\x18\xf5\xc6\xfb\x8f( \x82\x08\ +\x02\xcar\x95\x17r\xb1,\xb3l5\x1ef\x93\xc9(\x8a\xa3\xcd\xf3\x07a\xcc\x10\x84\ +\x92\xc2\xbe\x8c\x1f\xa7\xb2W\x14e\xcc\xd3\x0e\xbfe\xa5\x94\xa2 \xa00\xa4\ +\x90\x8d\x8a\'\x05\xb9>+\xd3i\x16\r\xa3\xd1\xd3\xce\xf0~K\xf1-n\n\xad\xe7\ +\xfe\xb1!]\x1e\x9f\xbe\xfc/\xb0\xda\xc6\xec\xe4\x91p-\x8d\xdd1\xfb\x16Zw\x99\ +\xe0\xd5dx\xee\x1c\xdbc\xadD(\xa4\xe5w\xbb\x06\x003e\x05wc\x08\xaa\xaa\x0f\ +\xb8\xd4r\xb33\x113\xfbn;\xacE\xae7kO\xc6\x97\xe0\r\x9f\xbd\xe6\xb6\xfbV\xfb\ +\x0e\xb7\xdd;y\xe5\xb6G\xd1~o0\xee\xef\r\xa3NWJ\xces\x95\x15*\xcfU)\x95 t;t\ +\xb8?\x18\x0cz\xa2\xdeS1\xab\x93o\xfeo( \xf6~,\xc50\x10"\xcbr\xc9"(O\xc4\xfa\ +k\xd8\x9en\x9b\x17\x0f!HD\xc3x\xf44n)\xbe\xc5M\xa0%\xf7\x8f\n\xeb\xd9\xab\ +\xb3\xd7\xbf\'\xf0\x0e\xcd\xae\xf9\x9b\x018b\xdf"\xd8\xb7\xd1:\\tT\x837\x8e\ +\xaa\xa0{\x0e*%V\x19\xbb\x81\xac\xbak)$\x17\x12\xbd\x98\x04U1\xd2z(\xb5\xfaN\ +\xeam\x9a\x8c\x8d\xaagT\xfe\x8a\xef\xb7x$\x8e\x06\xa7\xd7\x03\xaa\xcc\xee\\ \ +\xa2\xea\xdc\xb6\x8d\xcc\xdc\x89;q\xe7 \xcbe@\xd4\x1b\r\xfb{#FP\x94\xaa\xc8U\ +VpQH\xc5*\x0ch<\x8a\xf6\xc7\xc3\xb8\x13\xfb7\x7f\xf2\xed\xbf\x04A\xcc\xbd\ +\xa7:\x0f\xd2\x0cr%!g\xbf\xa7b\xae\xeb<\xe8\xeb\xe9\xe26\xf0(^\x10\x82\x80D4\ +\x88\x86\x8f;\xc3G$\xce\xf3\xf7[\xb48\x1f-\xb9\x7f\xecE\xa3\'-\xc5\xb7\xb82Z\xcf\xfd#A\xba<>{\xf5\xbbMf\xd7\xc2\xd1\xc0\ +cv\xa7\xcd\x81\xea\xfd\x96\xb0*_\x98\xd6m\xcfaL\x16b\x06\xa2\x00\x83\x0e\x96\ +\x19T5\x95\x13\x05\x02\xbd\x98\x97)z1G!\x8c\xc2\xb0\x04\x0bW\x00\xc0\xc9vl\ +\xb9\x98\x9f\x84S\xad\xe0m\xbb\xda\xfc\xf7\xedn{\xf3\x02\xcc\x8c\xac@Q\x8aa?\ +\xec\xc4b\xbe*\xb3\xac\x98\xbd;\x19\x8c\xf7\xba\xc3A\xd0\t\x82@\x05!\xe59\ +\x15\x05%\x99*N\x92$\xc9\xf7\xf7\x87\xddn\x17\x00\x828\n\xd7\x91\xe2LJ\xa1\ +\x08\x90\x00\x14\xa3\xdbQ\x8d\xbc\x1c}\x9bRA*\xd6\xb5*\x01H]\xb7\xa7d!\xd7\ +\xaa\xf8c\xb9x\x11\x8d\x9eD\x83\xfb"\x88\xd1\xa2\xc5e\xd0*\xf7\x8f\x01y2;\ +\xfe\xee\xd7`\xb9\xc5\x8d\x81emg\xafocv\xe7\xb7\xd4\xa8|\xc3UGmE\xcdP\xdf\ +\xe1\xc3C[1\xeb\x0c\xa5\xaa=\x1fH\x85U\x86n\x84^L\x8a\xf9\x1c\xd9n\xdf\xee\ +\x94\xed\xd80a\xb0\xd5\x99a\xe8\xd2\xc5\xe7\xc8v\x80\xf3\x12?\xfd\xe5\xdf\ +\xf6\xfa\xfd\xc5\xf1[.V"\xa4U"W+\xa9\xa4\x8c\xbb\x9d\xc1x\x1cu\xbaRqQp^\xa8\ +\xbcPE\xa9\x02\xc1\xa3\x9e\xe8\xf7\xe2\xc1h\x90-\xdf\xad\x8f\x7f\x8f\xf0\xfe\ +"\x8b\x94\xaeqF"\x12r\x10\xbc%.\xb7|\x9a\xde\xe7\xe6T\xbc\xa6x0\x84\xaeK\x1c\ +\xc6\xe1\xe0\xa8\xbbw$\x82-Q\xdc\x16-\xb6\xa2%\xf7;\x8f2O\xde\xfd\xe9\xdf\ +\x94*\x04m\xe1t/\xf7\xd1S\xee\xde{xVL\x8dx\xb8FD[\x8du\x9f\xd6\xcf\x01\x01\ +\x92\xb1\xce8/k\x01[\xa5\xb0\xca\x10\n\x0c\xbaNG{\x82\xbd\xe6\xb6\xa3F\xee\ +\x1e\xa7\xa3\xce\xe6\xfe\xca\xcb\xb8\xed\xa6\xefcFwx\xf8\x93\x9f\xfd\xa5^\ +\x99\xae\x96\xab\xe9q\x1c\xca\xbc\xe4\xd9\xa2,\n\x19\x10u\x87\x83\xfe\xde\ +\x88DX\x96\x9c\x17\xaa(\x94R\xaa,U\xbfK{\xc3\x18r\x99\x9d\xfeN\x84=\x15\x1ed\ +\xaa\x0b!B*\xa2\xf2\x18r}\x81\x8f\xca|\xa8\xbe\x8ag6\xa4/\xa2^\xbc\xf7Y<|\ +\xd0\x86[[\\\x04-\xb9\xdfm(U\xbe\xfb\xd3\xffW\xe6+\xd1Lv\xb4\xef\xbd\xb2\x8e\ +\x95C\xb3\xc9\xec\xe7j\xf6\x1a\'9\x89\xbe\xa5@\xccNh\xeeNrNsx1Z0#\xc9!\x15\ +\x8fz\x14\x06P\xd2\x9c\xdf\x1a\xe5\xdbe\xfb\xf6P\xea6Z\xaf\xc9v\xfb]\xa7\r\ +\xd9\xee\x1ek\xa4\xc2\x8f\x7f\xfe\xb7\x83aU\xdd\x97\x95Z\x9e\x1d\xcblA\x02\ +\x8b\x95LR\xc9R\x85q8\x18\xefuz}\xc5\xc8\x0b\x96R\x819M%\x88\x86\x9d\x9e\xaf\xd9\x1b\xef=f\xf7\x85\xb6\xbf\xe9rD\xe5\x9d\xa0\x90\xbc\ +\xca e\xe5\xa7\x13!\xcd9-\xd0\x8f\xa9\x17\x1bE\xefd;\x8cWnskpi\xd9\x0e\x86\ +\xaa\xcbv\xbf\xde\x80.9id;\xd0\x1f\xde\xfb\xea\xa7\x7f\xb1\xd9\xf8t\xb5\\O\ +\xdfE!\xe7\x85\x9a\xaf\xca"W\x04\xee\xf6\xfb\xfd\xf1\x9e\x08\xa3\xb2\xe4\xb2\ +T\xa1@\x92S\x9a\xac\xf6\xe9\x8f\x82lK\xb9\xea9.\x0b\x06\x84U\xf1E\xc9\x85\ +\xd4\x8b&\xdc\x1a\x8f\x9e\xc4-\xc5\xb7\xd8\x8d\x96\xdc\xef0\x16\xa7\xdf\xcd\ +\xdf\xfe\x8fvc\xe0\xaa\x0b8Z\xf73\x1a\xcdk}q+\xb3{\xf0\xad\xf9ss\x1f/\x01"(\ +\x85$\xe7\xb4\xb0i\x90\x00X[\xf0L\x04-\xe1\x99\xa1T\x15"eP%\xb37d;\xea\xe4\ +\xee\xa4\xba[\xef\xdcv\xd4e\xbb-&l\xd8W1\xbe\xfa\xd9\xdf\x0cv\xcc\xa5\xa7\ +\xa4\x9c\x9f\xbc\xe3b%\x02Z\xae\xcbu*Y\xaa \x08\x06{\xa3\xce`\xc0\x10E\xa9\ +\xe2@\x80\xb9\x9c\xfeF \xbf\xde\xe7T\xc1\xa7\xf8\xacd\xe9Q|\x10v\xc3\xe1\x93\ +\xce\xe8q\x9bQ\xd3b\x13-\xb9\xdfUd\xc9\xec\xf8\xdb\x7f\'4\x07+\x81 \xaa\x12`\ +N72\x00\xf24\xe4\xe5\x98\xbd\xb1r\x07\xce\xdf\xea\xbeg\xba\x91y\xc9I\x06=\ +\xdd\x07\xacQ\x93\xe6\x9c\x15\xe8\xc6\xd4\x8b!\xaa$\x9a\xdd\x03\x97,\x83\xd7\ +B\xa9\x1b\xb6\x8crs\xc0\xda\xbb\xe5m\xb2}4y\xf4\xc5W??\xf7&\x90\xaeV\xeb\xd9\ +I \x8a\xb2\xc4b]\xe6\xb9\x04s\xa7\xdb\x1d\x8c\xf7\x828V\x8a"\xa1\xf2\xe9\xef\ +\xe8\xc2\x0e\xfb\x05\xe1(\x9e\x81\xa2\xe4RA\x00\x81@\x18R\x10\x8fz\xf7~\x11D\ +\xdd\x1b\xbc\\\x8b\x8f\x00-\xb9\xdfI\x94E\xfa\xee\x9b\x7feU8+\xa6\xc6\xec\ +\xd0\xc4\xc2\x1bA\xd4*a\xc6\x81v\xd1\xf7n\x9d\xbe+1\xe6\xb2\xd0<\xb5\xce\x91\ +\x97\xc6\x84!"\xa98/\x91\x97\x08\x03\xf4;\x08\x03\xf2\xedr_\xb6\xf3\x8e\xc5\ +\x0b&\xc94\x98=\x8a:?\xfe\xc5\xdf\x85\xe1\x05\xd2Q\x98\xd7\xcbe2?\t\x84,J^\ +\xae\xcb"W\x82\x10\xf7\xba\xfd\xd1(\x88\xbb\xe5\xec\x0f\xa2\x98\xe2\xc6\xc2\ +\x9eLP\x00\x18B\xdf\x80\x10D\x04\xc5(JV\x8a;\x91\xa0\xcedr\xf4\xab\x1b\xba\\\ +\x8b\x8f\x04\xadaw\'1}\xfd{\x93\x1e\x03/L\n\xcb\xec^6\xb5\x95\xf5\\%\xc5\xec\ +\xe6c;\xe1\\u\xec\x96}`d\xf6f7\xb0\x13\xdb\xf4\x83\xbeT\x1cQ\x14rV`\x9d!+\ +\x01\x06\x11u"\x84\x82\xd3\x02gK\xc4\x11\x0fb\x04\x81\xc7\xe0\xee|\xbcqF\xef\ +\xa7\xf3t\x9c!\xe3\xf6\xda"ht\x11\xc8\x0b\xf6TD\xfd\xd1\xa87\x1c\xceO\x8e\ +\x85\x9c\xef\xef\xc5\xabD\xae\xd32]\'E\x9a\xf5\xf6\xf6B\x847\xa7\xda\x15S\'\ +\xc5X\xb1\x88\xb0\x8a\xb0`\x16\xa5d\x02\x82\x80z1\x95\x8a\xd2L\xa1\\\x8c\x8a\ +,\x88:7u\xd5\x16\x1f\x01Z\xe5~\xf7\xb0\x9a\xbd\x9e\xbe\xfa\xad.j"\xb4\xfdbG\ +\xa2Za\xaa\x19\x9d\xc8\x16m\xdf\x1aAm,\xfa\xcc\xbeK\xad_\x9d\xb3v\xf0\xbb;\ +\xabb\xa4\x05\xaf3\xad\xe2\x8d\x85"\x15\xd2\x02\xa5\xd2\xe9\xf0\x08\x84/\xc6\ +\xaf)\xdbI\xff\xd4=\x153\xd6\xa9z\xf6\xec\xe9\xd1\xe7?\xbd\xd4m\xe5i\xba<{G\ +\x9c\x97\n\xcb\xb5,r\tF7Z\r\xa2\xc5M\xd82J\xc4\xe3\xb2\xf3y\xd0\x19eY\xa1d\ +\x11\x15/\x83\xe2\xady.\x03\x08\xe8\xc4A\xa9h\xb9.\xc2(\xeeO\x8e\x86\xfbO\ +\xda\xe1N-4Zr\xbfc\x90e\xfe\xf6\xeb\x7f6\x86L\xcd\x8d\xd1\xa1B\xf3\xdb$\xa1\ +\xcb\x82\x01u\x8e\xd9e\xc84b\xad>\xea\xfd\x01\xd59\xb9y~\x07g\x86o\xdd\xb0\ +\xf1\xd6\x9cGS\xfc2\xe5\xbc\x80\x8b\xb6J\x85\xac`\xa9\x10\x87\xd4\x8d\x10\ +\x05&\x97f\xcb\xc0\xa5\x1a\xbf3\x83\xd4\x8e\xdcv"b[_A*\x94\x92\xc1\x90\x8c\ +\xbf\xf8\xd5\xdf\xf4\x06\x97\x98wIcqv\x9a-\xa7A\x88u*\xd7\x89\n\xb1\xda\xeb\ +\xcc\xaeM\xeeL"\x0c\xc6?\x91\xa2\x1f\x08\x98Zj$\xe4\xf4\xb7(\xe6@\xe5\xf9\ +\x88@\x9c-d\x18 \x10\x10A\xdc\x1f?\x1c\xec?\r[\x0b\xfe\x93GK\xeew\x0c\xd37\ +\x7f\\M\x9f\xfb\x82]\xcbsAT\x99\xec\xf5Z\x8f[e\xbb\xf5\xe5\xe1\xbdn\xf3\xdf\ +\xa9\xf9\x96}\xd2\xda\xcd\xeb\xde[>wk\x13\x8e\xe2W)\xa7\x85\xce\x99!\x10\x94\ +\xe2\xb4@)\x11\x08t#\x8aC\xe8\xc2\x8a\xbe\x96\xbf\x94l\xd7w+%\xb2\x82\x15s\ +\x14\xa0(qx8\xf9\xc9\xcf\xff\xfa\n\xb9\x8beQ\xcc\x8e\xdfA%RQ\x9a\xae\xfat|\ +\xd5\x04H\x07f\xc4ky\x9f\x830\x10\x02\x00\tb\x04\xa2<\xe9\xe0\xb4\xfa\xc5\ +\x10\xd2\x02\xb35\x8f\xfbU\xbe\xbf\x10\xe1`\xf2\xb8\xa5\xf8O\x1c-\xb9\xdf%\ +\x14\xd9\xfa\xed7\xffBPU\x1c\x15\x96\xd9]\xadGQ\x91J-\xa0\xba\xc3\x90y\x1f\ +\xf5S}\xb1\xb6\xcbn4Y\x9d\xb7\x91\xfa9\xdf<"R\x8c\xac\xe0u\xcai\xc1\xa54\xd2\ +U*\xce\x0b\xe4\x92\x05Q\x14R\x14\xe8\x19\\\xed\tk\xb4\x8e\x86l\x87\x97x\xae\ +\x87}\x02\x98\xafM\xef\xe1\xcaR\xfe\xecg?\xdf\xbfwt\xee\xdd\xed\xc4j6/\xd6ge\ +\x99p\xfeF\x9cw\x7f\x17\x013G\x8bt/\x97B\x98tW\x96\x12\xfd(\x19v\x17\xba\x00\ +\x8f\x0e\xab\xbe\x9b\xb3 \xdc\xdf#\xc5(%\xa4\x9d0P\x88p0~\xd4\x9f\x1cE\x9d\ +\xc1\xf5Z\xd2\xe2N\xa2%\xf7\xbb\x84\xd3\x97\xff\x95.\xde\xfaN\xba\xae\x14\ +\xe6H\xbc9[\x9eg\xcb\xbcG\xb6o\x11\xf8N\x1bn\xc8\xf6\x8b\x12\xbbO\xf1\xde\ +\xf7\xec\x02\xe4\x0e\xab\xb6\x19\xc8\x0b^\xa5JS\xbcR\xac\x18\xa52\xe36\x15C\ +\x08\x84\x82\x82\x00\xa1 !L\x10\x02V\xa4k\xd9\xae?\x16\xa5L\x0f\x11\x08\xc4\ +\xa1\xf9\xdc\x96)\xaf3v\xd4\xcf\x8c\xd1\xa0\xf7\xcb_\xfd\xbd\x08\xae\x98k\ +\xc0J\xad\xcf\xde\xae\xa7\x7f\x10\x90W;Cu*P\xa6\x0e\xd6EL`"\x1d\xc3\xa6Qt\ +\x1aR\xa2\xef\xa9\x948[q\x9a\xf3\xfd\xb1\xe8FUb\xa8O\xf1D\xa2\xbf\xf7p\xb8\ +\xff4\xea\x0e\xaf\xd9\x9e\x16w\x0b-\xb9\xdf\x19\xe4\xe9\xe2\xdd\x9f\xfeM\x0f\ +}\xacd\xbb0\xe6+\x99\xf8)\x00\x90\xcb\x8d9W\xb6\xfb\xee\x8ag\xe3P}\xa57\xc8\ +\xd5K\xb9\xd9\xc2\xef\x15e\xfbt\xbe\x8d\xdf\xdfO\xee\x15\xb3\x9b&1r\xc9Y\xae\ +\xd2\x9c\xf3\x92\xa5b\xa5P*\xe4%\x8a\xd2T\xcau\xb7&\xec\x00\xaeM_D\x08\x8aCt\ +"\x08\xaal\xfa\xd9\x9a\x0b\xc9\x95x\x07\xbe\xfc\xea\xabGG_\xecl\xdd\x05p\xfc\ +\xa7\x7f\xa2r}\x9d3\x00\x00XQ\'\xc3\xbd\x82c\xdd\xf8.\xcdCu\xa2ok\x9d\xf1t\ +\xc5\x8aq0\xa4~\x87\x1a\x7f\xc7\x0c\x94\nR\xd6(~t\xf8Y\x18\xbf\x7f\x9a\xef\ +\x16\x1f\x07Zr\xbf3\xa8d\xbbcg_\xb6{\xb3,\x19\xad}\xae\xdb\xbe\x8d\xd9\xab\ +\xb5N\xac\x13\xd5\xd6o\x9c\xac\x06\xae\x11<7\xde\\\x98\xdc\xfdKV\xa3l]\xf0\ +\xb3(U\xa6\'\xcd\x90,%J\xc5E\x89R\x19\x9d\xee?\x1f\x90\x1e\xa7\x0b%\x04\x05\ +\x840$\xdf\xc3\xd1\r"\xa0\x90\x98\xadM\x01G\x1d\xc5\x8d\xe3\xf8W\x7f\xfd\x8f\ +\x17\xcay\xaf\xce\xa5dv6;}\xcdL"\xea\xe7\x8bW\x11e7\xf1\xb7\xc5\x10\x11\xc2\ +\x11D\x0c\x99P9\xd7\x1f\xc2l\xcd\xcb\x94\xbb\x11M\x06\x14\x87\xd8u!\xd6%\x85\ +%+\x00\xad\x17\xff\x89\xa1%\xf7\xbb\x81"[\xbd\xfd\xe6_D5\x89\x92\x91\xed\xd6\ +vo\xba1\r\xd9\xeeGAk\xb2\xbd)\xcf}Fw\xeb-\xd5\xfb\xc2\xdd\x9d\xae\xe6\xae\ +\xd7(\xbd\xb1\xe0o\xf6\x0em\xc0\x1bE\xeb]\xbc\xf1\xa4\xc0\x0c\xc5\\\x96\x9c\ +\x97*/\xb9\x94\xacK\xaf\x94\xb2:\xa5\x96\xf0\x0c\x10X\x93\xbb\xae\xc0\xc3\ +\xf5\xf30 \x08\xeb\x0c\xcbT\x19\xf1\x0e\x00\xf8\xfc\x8b\xaf\x8e\x9e~\xb1\xa5\ +\x81;\xb0>\xfbvu\xf6\xed:-\xf5\xdfS\x1c\xc2\xf9$\xd7\x06W\x1f=Q\x92\xe3l\xa5\ +\xa4\xc4\xb8O\xa3\x1e\xd1\xb6\x92\xf7\x9b\xc7\xeb\x8c \xddu\t\x11\xf6\xc7\ +\x8f\x86\x07\xcfZ\x8a\xff\xb8\xd1\x0eb\xba\x1bX\x9d\xbd\xd4i\x8e[2U\xaaU&\ +\xc9\xafq\xac\xff\xb7_c\xcaMf\xf7\xb8\xdcv\x0f\x1b\xc97\xde\x19\xd8\xef\x12\ +\xc0`\xd2\xf2\x97@\xac\xffs\x17\xf7i\x95v\x89v\xaf\xed\xb6)\xae\x8d\xe6^\xb8\ +jy\x14"\x0cE\x8f\xc1\x0c\xa9\x94R\\\x94\xc8K\xce\n\xcdb$\x08\xcc\xec\x17]h&_\ +\x926\xda\xd1\x8b\x91\x15TH\x10L\n\xe6\xab\x17\xdf=x\xf4\xe4\xe2\xe2}5?I\xd3\ +\x82\x8c\x9b\xc4\xccM\x9f\xe4\x1a0\xdd\xb7b\x94\xc1\xbd\x14y@\xd3\xc3\x89\ +\xe8\x84U\t\x9d\xf7\x1e\x1f\n\x04\x82\xb4\x17\xafd\xb9<}\xbe\x9e\xbd\xee\x8d\ +\x1e\x0c\xf7\x9f\xb4^\xfc\xc7\x8a\x96\xdc\xef\x00d\x99\xaf\x17oQ\xe7s\x1d\ +\x01\xb4"\xbb\xa6G\xf5\xffz\xaa;\xd1\xa0\xfaf\x97\xb0\xc9\xec5\x86w\x14kv\ +\xa9\x8euLo\x93\x0f\x99\x98@v\\\x7f\xc5\xef\xc4`\xd7\xc2ZSiK\xc7\xe3]\xcf>\ +\x8f\xe8\x0e\xa6v\x17Z\x90\xb3\xbbW\x10H\x08t"\x8e#\xea\xc5TH.%J[\xb8\xe6\ +\xbd\xdd\n\x11\xba1\x15\x89r\xbb\xe4E\xfe\xee\xcd\xab\xc7O>\xdb\xb6\xfb\xb63\ +\x84\x03\x85\x99U\xd97\xa5\xd9\xab\xe6\x95\x92\xc2\xf1\x97\x8f\x1e|\x06 [\ +\x9d\xe4\xf3\x17\xf9\xfa\xf4r\'\x81)\x1a\xac\xbd,%\xcb\xd5\xf4\xe5z\xfe\xba7\ +z0:x\xd6R\xfc\xc7\x87\x96\xdc\xef\x00\x92\xc51\xabB\x90\x95\x9a\xf0\x148\xd5\ +\xf9\xaaf\x91\x9b\xc7y4wq\xfe*\xd8\x91\x9aY$\xd3t\xf6"_\xbd\xbb\xc2\xf9k^<\x00Bot\x7ft\ +\xf0\xac\xa5\xf8\x8f\x03\xadr\xbf\xed(\xb2U\x91-\x1cM\x10\xc8\xe8\xcb\xba\ +\x90\xf7\xb2e\xb6\xa0\x92\xd7\xd5\nG\xa8\x96\xb6-\xe0\xbd\xb7\xc4O\xce\n\xb2\ +\x8f\x02\x9a\x0f\xb4BeW\xf6\xc0\xa8vPM5\x10\xcf\xd7\xc7\x97\xf2\x83\x9c\x17\xef(>\x99\xbfK\x16\xefz\ +\xc3{\xc3\x83g\x9d\xfe\xe4z7\xd1\xe2\x03\xa3%\xf7\xdb\x8edq\xbc\xe1\xaa\xe8W\ +\xe3\x7f\xa0\xa6\xd4k\xf0\xe2\x93\xc6\x1e\xa9h\xd2\xc5)\x9b\xccN\x82\x9cd\ +\x17\xd0\xffj\xe7\xf2Nm\xa8D\x81\x99\xc8pf\x95.\xbe\x9d\xcf\xb7\xae\xf5\xdcu\ +\xd7*O\xb6\xbb\x9e\xcb\xc6\x12\xac%cK\t\xd4\xdd\xa7\xa6#\xa4\x9b)\x04\x04 \ +\x04)\xc9RAVI(\xe6c\x8cC\x04\x82\x94\x82\xcby\x9f\xcf\xa7\xeb\xf5\xb2\xdf\ +\xbf\xa8\x1f\xbd\xff\xf0\xc7y\xbaL\xd7S\xd8\xc0\xac\x05\xdb\xdf\xd6\xfb\xc5<\ +\x11\xa4\x82\x8a\x1f\xde?\xfaqp\xb1\x88n\xd8\x1d\x8f\x1e\x8de\xbeJf\xcf\xb3\ +\xc5\x1b\x98\xd4\xc7\x0b\xc1Q\xbcR(\x15+\x85dy\x9c,\x8f;\xfd\xc9\xe8\xe0\xb3\ +\xee\xf0\xbc\xae\xa5\xc5mFk\xcb\xdcv\xbc\xf9\xe6_K\xab\xdc\xab\xb1K\xae\xfc\ +\x80eg\x00:\xf1\xcf\xcfttN\x8e\x039\xab\xc3\x91z]\xa7W,O\x01 \xaaDzl\xf0\xbb\ +\x0ehj\xeed\x06+@1+f\xb0\xf1H\x00k\x93X\xbf\xc6\x1cY\x8b\xaaz\x86\x8c\xbd4\ +\x99G\x91J\xbc\x9b6\x18\xa6vn\x0c\xb3bVJ9[F\xd9\x9a\x036\xce\x0bV\xac\xe0\ +\xb5\x14&CF1\xa4\xd2v\xbc\x89\xf9\x12h\x9e\xa8$\xd7N\xbci\xe4\xe3\'\xcf\xbe\ +\xf8\xd1\x9f]\xfc\xf7U\x16\xd9\x9b\xaf\xff\xb5,\xb2NDQ\xa0\x1bB\x92z\x92\x83\ +\x90\x13A\x85_\xf3k\x13D\xc8T\xdc?\xf8j|\xf0\xf0\xe2\x17\xf5\xa1)>_\xbecU^\ +\xe5pM\xf1\xf6\x17\xd4\xe9OF\x07\xcf\xba\xc3{WkL\x8b\x0f\x88\x96\xdco5\xca"}\ +\xf3\xbf\xff/\x11\x0b\x93\xfcBz$\xba\xc7\xf2\xde\x80\x1f\xe2\xc6\x90\xa3-\ +\xe4\xee\xe56R\xc5\x9f\rX\xc1N\xa6\xdad\xe5\x9cT\xf0\x8buYrg\xc5\xbe\xf5\xcd\ +\xbc\x83\xdc\xbd\xdc\x19\xfd\xe2\xf9\xfb\x96\xdaE\xf5\xf4\xe0\x05\x08,\xb1\ +\x9b\x13+\xa54\xa1+\xbb\xa0\x0c\xebW\xd7ac\xd0\x03\x80b\xeb\xf9\xdbB\xc1\xcc\ +\x90\xcaV\x8a\x04\xb2\x82gk\xdf\xb1G\xa7\xd3\xfd\xab\xbf\xfe\xc7\x0b\x86U5\ +\xd2\xe5\xe9\xdb\xef~\x13\t\x15\x87\x0c\n\xb9\xf7\x0c\x9d\xfby\xa1T\xb1\x8a\ +\xcbW\x81\x9cn\xd5\xefZ\xb0s\xe7\xe1\xe1\xe3\x8b\n\xf6s \x8b4\x9d\xbf\xc8\ +\xe6\xaf\xae@\xf1\x0c\xe8\x01\xc0\xb6\x84\x01:\xbd\xf1`\xffi\x7ft\xbf\xf9}jq\ +\x8b\xd1\xda2\xb7\x1ay2wO\xf3T\xa5\xfdY\xe8w\xcc\x15K\xc2\xcb\xd2\xa8S\xb1\ +\xcf\xa4\x80elr}\x84#v-\xd8=f\xdfB\xee.\xbb\xd1S\x06,\xa0{\x97\xaa\xec\xc0E`\ +\xedv\xdb]\xd9\x07\x13\xdd:a\x9a\xea\x9a\xed\x8c\x14\x905e\x8c\x13T\xd92\xb4\ +e`\x8f=\xc66\x8c\xdcS\x00\t\x02\x834\xddG!\x05\x01\x97\xd2}\xe4\x9c\xa5\xe9t\ +zzpx\xff\xa27\x04t\x07\xfbA\x18+\x99\x12\x10\x8e\x8e\xca\xe80\x10\x1c\x05\ +\x90\x9d\x01\xe1+\x9e\xfd\x96\xcbU3\x84@Hs\xccS\x1e\x882\xcf\xd6\xbd\xf0\xba\ +!\xcd \xea\x0e\x0e\xbf\xea\xee=I\xe7/\xf2\xe5[Uf\x17?\x96\x80@ \x10\x90L\xa5\ +\x84b\xce\xd6\xb3,\x99-\xbb\xa3\xbd{_\xb6F\xcd]AK\xee\xb7\x1aE\xba\xa8\x94\ +\xf8\x06Y\x1b\x9b\xb9\xda\xec(\x8d\x08>\xa17\xd2\xf2*\xcf\xc6\xbc\xd4\x98=0\ +\x9c.\xea\xca\xddo\x80\xcb(a\x82R\xe6\n&j\xba\x9d[\xd1\xa0\xfb-\xb7d\xedug8\ +\xf9\xcf\x17\x86\xf9u\xfe<@pS\'\x111\xb9)\xf3l\xffV%g6?\x19\xb7\x9e\xcd\x15m\ +d\x98H\x07\x82\x11\x07\xe4\x8ft\x05pr\xfc\xe6R\xe4\xbe\x9a\xbf+\x8b$\x10\x00\ +D\xba*\x12y\x1c\x86\x02 !\x04(\x80\xec\xc6XV\x1f\x01A1f+^\xe7\x00\xb0\x98\ +\x1e/g\xc7\x83\xe1\xe4\xe0\xc1\xb3\xe1\xf8\xbaf\x88\xa6\xf8\xde\xe4Y6\x7f\ +\x95\xce_^\x8a\xe2\x01\x04\x84 \x84T$\x15$s\x9e,\x8e\x9f\xff\xba7\xbc7\x98\ +\x1c\xb5\x14\x7f\xfb\xd1\x92\xfb\xadF\x99\xfb\xc5\xa7\x08`\xf7XLd\x9cb\x0b/\ +\x80g\'\x19\x82\xc7c\xb0\x04i\x19\x1d\xf0i\xdd\x18 \x02\xc2\xd1\xfa\x0erwJ\ +\x19\x04(\x1bY%K\xeeM\x89\xbc\x1b\xd5\x9d\xd4e{\x8d\xe7\r\xb3\x93+\x8ff\x9e\ +\x0b\xec\x05\xd8(\xec\x1d=\xcaNT\x11_w\xa4iv\x1c"\xc9\xed\x1d31x6=+\xcb\xe2\ +\xa2\xa3U\x99\x97\xa7\xdf\x81\x89\x99\x15P\xa4i\x9a\x95\xdad\x02\x91R\xe8\ +\x04y\xa7g\xc6\xaf\x12!+p\xb6\xe2\xa2\xe4q\x9f\x88\xcct\xb2\xc9j\xfa\xfc\x7f\ +\xa7\xfd\xe1dr\xff\xc9h|\xdf\xc5\x93\xaf\x06\x11\xc4\xbd\xfd\xcf;{\x8f\xd3\ +\xe9\xf3t\xf1\x8aeq\xa9\xc3\x9d\x8a\x97\x12Rq\xb2p\xe1\xd6\xd6\x8b\xbf\xd5h\ +\xc9\xfdVC\xca\x1c0|\xea\xa7\xc4Xe\x0e\xbb\xd5\x8b\xa3R\xb5\x16n/v\xbcnv#k\ +\xbf;\xeb\x1dd\xdd\x18\xcd\xecN\xbf7<\x19\xf2=\x19\x9b\x16y.\xb7\xee\xd8R=}X\ +:G%\xdbmP\xd5\xae\xab\x92-I\xfbS\xe6\x9a\xe4\xdac\xff\xf7N\xef\xa1\xdaR3\xfe\ +u\x1a\xa5\t\xa0\xea\x96\x86\x01\x84\x80R\xf6\x9a\x84"\xcf\xe7\xb3\xe9E\xc5;\ +\xd1\xe4\xc1\x8f\xe6\xa7/\xd2\xe51\xb3\x8a"\x15q$\xd9\xf4\xcaA :!\xbb.e\xb6\ +\xe6\xf9\x9a\xa3\x00\xbaf/L<\x13JA1T1;y>\x9d\x1f\x8f\xc6\xf7\x9e\x0e\xc7\x0f\ +\xe8z3n\x8b \xee\x1f\xfe\xa8;~\x92\xcc\x9eg\x8b\xd7\x97\xa6x\xab\xe2\xb5\x17\ +\x9f\xad\xa6\xd9zj(~p\xd8z\xf1\xb7\x10m@\xf5V\xe3\xf5\xff\xfc_U\xa6\x86\xed\ +\x84\x13\xc9\xceR\x815.<\x9b\xdd\x13\xd9\xfe_\\\x95\x80"\x8c`\x17V\xb0\x0bA$\ +\x02P\x00!\xcc\xbf\x8a\xdf\x05\xfc\xfc\x1bX\xabZ\xffS\xca\xfcT\x96\x90\xb8\ +\xd4\x03\x8aT3\xb2ZK\x91q\x8d\xb5\x890\xcd\x88\xae{\x07\x13P\x15\xd5\xd5\xa1\ +\xbc`*K\x9d*\xa3\xa3\xa9\xfa\xc5\xa4\xeb\xd8\xdd\x01\xb3\x12\x00C\xd9v\xe8\ +\x024lgkb7o\x1f\xf4h&\xf3!+f0\x8e\x9e~\xf6\xf9\x97?\xb9\xd4\xefn\xbd8^\xbd\ +\xf9\x8d\x10AN\xf7R\xd5e\x90 \xea\x88\xa4\xa3\xde\x02*+1]r^\xf2\xa8G{}\x12\ +\xf5\xce\x91\x01\xa9\xbc\xda\t\x8c0\xee\x0f\x0f\x9e\xf5\xc7\x8f/\xd5\x86]Pe\ +\x96\xce_e\x8b\xd7\xaaL\xafp\xb8\xed\x81\xcc\xe3O\xdc\x1d\r\x0f>k\xc3\xad\ +\xb7\r\xadr\xbf\xdd\xe0\xda\x84\x0f\xcc\xdc\xfc\xf3!#\xe2}a\xef\xf30\xb1\x93\ +\xc5n\x9b\xeb\x1d\x9c/#\x00\xab\xd9k\xca]\x98Q\xb0\xb5+V\xcd\xb9\xb8\x19r\ +\xdeN\xce\x93\x81k\x9b1\xdd\xed3\x86h<7\x98\x9c\xf1\xca\x84\xbfL\xf8\xd6=\ +\xca\xecnZ\x14"-X\xd73\xd0\xe7O\x92\xe4\xa2\x97\xb0\xe8\xf6\'+\x11\x82\x8b\ +\x18\xef\xa2h\xc4\xd4\x11\xc8E9W,\x17\tfk\x0e\x03\xdc\xdb\x13\xbdxK\xfd/\x02\ +B\x01fH\xdb\x1b\x95\xf9z\xfa\xfaw\xeb\xd9\xeb\xc1\xfe\x93\xde\xf0\xba4*\xc2N\ +\xff\xe0\x8b\xde\xf8I:\x7f\x99\xce_]\x96\xe2\x8dQcU|\x9e.N_\xfe\xe7\xb2\xa5\ +\xf8[\x86\x96\xdco7|\xb7\xd57X\x00\x06\x04\\\xdc\xd4\xb3\xd5\x9bg\xd8B\xce.\ +\x9c\xe9\xb2\xdd\xb7\xfds\xcc\xee\x9e\nl\x0bt\xbe\xca\xeeA\xa7\x17`[?\xa2\ +\xea\x87R\xab /\xfc7\xfe\x81U0\xc1oU\xa3\x01\xdbQq(\x81@&\xf0Z\xc5\xa1\xcd\ +\x91Q@\x82L"\xa0v\x8e\xd6\xab\xa5RJ\x88K\x18#$\x04($\x94\xcc\x8a\x8a\xa9\x00\ +\xb4\xa5~\xb6BZ\xf0\xa8G{=\n\xc4y\x9d#\x11B\xaaT<3\xf2d\x96\'\xb3ew8\xdc\x7f\ +\xd6\x1d\xdd\xbf\xa6QCA\xd4\xdb\xff\xbc\xbbw\x94.^\xa7\xf3\x17\xaa\xb8\x12\ +\xc53I\x05\xa9,\xc5wF\xfd\xc9\xe3\xfe\xf8\xa1\x10-\xb7|`\xb4\xbf\x80\xdb\x8d\ +\xcdj(\x15\xb3\xc3\xbc\xa3\xfa\xf3\xbc\'\xd2=\xfb}\x83\xf5\xab\xdcq\xcf\xd76\ +\xb2\xdd\xcb\x80\xacu\x0e\xb5G\x82m\x14ZO\x82\xdc\x9e\x8e\xd8\xbc\x97\xea}\ +\xd3K\xf2\x1a\xe0\xfc&W\x06\xa5\xd9\xb7P\x15\\\xe5\xcd<\xcd\xcd\x8f\xd0~Tz\ +\xfa\xba\xba\'\xa2iKI\xb7?ei\x92$\xab\xc1`\xb4q\xcb;A$\xa8s\x80\xf4\xa56\x9e\ +\x981]\xf3t\xc5q\x80\x07vV\xbc\x8b\x17\xec\xd5\x14/\x15\x00\x14\xe9r\xfa\xea\ +\xbf\xc3\xd3o\xfb\xe3\xc7\xfd\xf1#\xba\x1e\x8dR\x10\xf5&\xcf\xba{\x8f\xb3\ +\xc5\x9bd\xf6\\\x15\x97{F\t\x08A\x00)HJH\xe6<[\xe4o\x16\xcb\xb3\xe7\xc3\xfd\ +\xa7-\xc5\x7fX\xb4\x1f\xfd-\xc7\x0e=\x0e\x1dX\xac\x15T\xe7\x06m\xd5\xc0\xfe3\ +\x00\xacKO\xf0H\x9c\xae\xb9\xfc\xee\xa5v\tv\xafv\xe7\xc6\r\xfa\xbe:W+\\\x9e&\x01\xae\ +\x9ab@\x08\x03d\xaa\xcaB\xca\xb34K\x93^\x7f\xb0\xa3\xa9\xef\xc1`\xfch=\x7fKE\ +\xfa\xe8\xe8\xe9xRi\xd8\xaaf\xaf.\xcb~\x99\xd4dG\xf1\xfa\x1f3\xf2tv\xfar\x16\ +w\xf7\x06\xfbO\xbb\xc3{\xd7M\x8d\x0f;:5>\x9d\xbf\xcc\x16o.\x95TC\x1bI5\xe9\ +\xf2$]\x9e\xf4\x86\xf7F\x87\x9f\xc7\xbd\xbd\xeb4\xac\xc5E\xd0\xe6\xb9\xdfj\ +\xac\xa6/\xe7o~o\x87\xda\xd8\xf0\xa2K$\xb1\xe6\xb9\x13\xeen\xab\xd9\x81H\xb3\ +{=\x99\x1cB\x08\xe1R\xdc\x85 \n \x02\x04\xa2\xcasw\xa3\x99*e\xed\x98\xd0f\ +\xb8\xfb\xe9\xedJ\x82%\x9b\\s\xf6jCZ\xe2\xf4+\xce\xe8\xc6\xb8\x16\xd9D}/\xbd\ +]\xd4\x93\xdc\xa9\xde\xd3\x80\x95\xf4\x8a\x85\x99\xffu\xda\xbb~\x0fg\xf7\x13\ +\x18`\x05\xdb\x14K\xeb\xa6I\xf5Zr\xbf\xedXO_N\xdf\xfe\xde\xd0\ +\x1b\xd9\xc22v`)\x9aR\xbd\xb6\x06\x1e\xe9\xeb\x03\x84\xa7\x92\x89\x8c;c\x9c\ +\x19\n\xea\xb2\xdd\xa5\xbd[\xf8\xb1S\xe5\n\xcbhC\xc6\xce\x81dY\x17N\xb6{f\ +\xbb\x03\xf9\xff\xe9\x969\xa9\xee\x9ag\xb7\xf9\xb6Le\xa1x\xd3\x82X\xcf\xbd\ +\xf2j4\x93\xbb\xafv\xcd\x96\x81%w"\x17\x18\xb6g6w\xe6P\x94\xc8K(\xe6\xb4\x00\ +\x01\xddn\xe7/\xff\xfa\x1f\x85\xb8\xc4\xc4\x1d7\x02Ve:\x7fu\x83\x14\xdf\x1f?\ +\xea\xed=\x12\xc1u\xa7\x04\x81\xf1\xe2_\xa7\xb3\x177B\xf1qoot\xf0\xec\xfa\ +\xf5\x15Z\xa0%\xf7\xdb\x0fY\xa4o\xbf\xfe\'-1-\xb3\x1br\x87\xf5\xdf=\x93\x1d\ +\xa8\x93;,\xe9;\x97\xdbIx\xad\xdc\xad=C&\xacJ^\xb1_`\x83\xdc\xf5O;\x1c\xde\ +\xca\xf6\x06\xb9[v\xdd\xce\xec\xa6\xe1\x9e\xe9\x0e\x9f\xd6\xbdG\x0c\xbb\x1bl\ +\x16\x90\xa3`\xff\xf1\xc0*w\xd9\xbc>{\rW6\x84\xea\x8cuK\xee\\\xd9Gur\xd7\x7f\ +\x19B /1[1\x800\x0c\xff\xeao\xff\x9f\x8b\xd6\xfe\xbdi\xb0,\x92\xd9\x8bl\xf1\ +\xea\xb2e\xd9\xb1\xc3\xa8\x19L\x8ez{\x0fE\x10\xdfH\xdb\xb2\xe5\xdbt\xf6B\x16\ +\xeb\xdaz\x00\xbbs\xa1\x1c\xa4\x99\xb8\xdc|\xf4\x9d\xde\xde`\xffYot\xddl\x9f\ +O\x1c-\xb9\xdf\x01\x9c|\xf7\xefyr\x06\x8f\xa6\x9dB\xaf\xf90\x04pSm\xfb\xe6L\ +\xc5\x9c\r\xf1n5\xbc\x11\xef\xd4(\xe3n\x8d\xfbF\x06\xa4R\x80\xb4n\x8csIL\x92\ +LM\xb7\xeb\x83\x19~|\xc0\xf7e\xfc\x8e\x07\x9e\r\xef\xf7\x01\xd5\xf5\xfdN\x04\ +\xe0\x86\xe1\xeeZ`u:A\xf7D\x0c\x866^\xec\x0frV\xbbs\x906\xc9]\x7f\xb8\xf3\ +\xb5*J\x10\xd1_\xfe\x9f\xbf\xeb]x\xbe\xec\xef\x03F)_C\xc5+\xaf\xdb\x13A\xdc\ +\x9f\x1c\xf5\xc7GAx\x13\x14\xafd\xb6|\x93N\x9fk\x8a\xf7\x99\xe5":\\2t\r\x03\ +\xbd\x7f\xd8\x19\x8e\x0e\x9e\xf5\xf6\x8c\x89T\x142/\xca \x10\xdd\xce\x87\xe9\ +\\\xef\x1cZr\xbf\x03X\xcf^O\xdf\xfc\xd6\x86R\x89\x88\x1d\xe3\xe9\xb1\xab\xae\ +N\x0cW\x1d@\xa5\x9a\xdc\xdf\x95\x10\xb0\x13\xd7y\xe2\xbdF\xefdgb\x12\x80\xdf\ +u\x00h\x90{5cjC\xb1\xa3\xa1\xdb\xd1\xf0\xdc\xab\xee\xc8y.[\x94;\xaa\\\x1a\ +\xb7\xab\x8e\x93\x9akX)\xee\xe6\xc5\x96\xce\xf3\xb7\xa9\x8d\xb0\xa3x\x9d6W.\ +\x0fR+w+\xf0m\x8bm@\xa1\xfe7ADI\xce\xcb\x94\t\xf8\xe5_\xfe\xcdh\xef\xc3\x0f\ +\xa6gUf\xcb\xb7\xe9\xec\xb9\xacM\xe7r\xb1c\x9b\x14O"\x88z{\x0f\xfa\x93\'a\ +\xd4\xbb\x89\xb6\xc9|}\x92N\x9f\x17Y\xad\xbe\xc2\x05}\x16\xa9\x07\xdf*\x9d\ +\xd2\x890\xee\x0f\x0f\xbf\xc8y\xb8L\x14+\xc5J\xc6\x11\xdd?\x1c\x85Q;F\xe7=h\ +\xc9\xfd\x0e\x80U\xf9\xf6\xeb\x7fV2\xd3jW\x18\xd5\xab\xf3\xc9,G\xc2\x8a\xf7\ +\xda_Qm\xcal\'\xdeA\xa8\xe6\x9f\xf6\xf2\x0f\x85\xf5\xe4\xbd\x1cDw>\x13\x9b\ +\xf4\x98\x9dk\x16\xb7\xe7\x93l2{\x9d\xdd+\xc3\xc7S\xe6V\xc4W\xb2\x1dMr\xd79\ +\xe9\xca\xbb\x06`\x9f\x1c\xe0R\xdd\xad\x18\xd7m\xb05\x04\x1c\xb9;g\xc6\xb6\ +\xee"\xe4\x9e\x97\xbf\x03\x86\xd6=\x8b\xc6\x87\x8b\xc5\ +\xc2y"\x00\xa0P\x89\xf3&\xaa\x04\x99\xc6\xd8\xa5\x1a\xa8z\xf1=\x17g\x17\x99\ +\xb7\xd4\xa0\x7f\xd4\xc8\xdd\x9d\xdd\xb8A\x9a\xe5\x95\xb4Dm)\x1b\xbaJ\xa4\ +\xe7*\xc1EP\xf5\xa7\xe3\x91\xbb\xffdRo21c\xb6VR\xe2\xab\x9f\xfc\xfc\xfe\xc3\ +\x9b\x991\xe3\xc6\xc0\x9c\xaf\x8e\x93\xd9\xf32\x9d]\xfa\xd0M\x8a\'\xd1\x1d=\ +\x18\xee?\r;W\x1c\x8b\xdbl[r\x9aL\x9f\x17\xd6W\xbc\x14t}\x05i\x92U\x95\x88\ +\xfaa\xff~\x7f\xf4\x10JH.\xc7\xfb\xd7\xaa\x95\xf6\xd1\xa3%\xf7\xbb\x01Yf\xef\ +\xbe\xf9gV\xa5\xe5]\xb6:\xd7%>j\x1by\x0b\xbf\xdb\x1d\xcc\x82cO"\x08\x9b\x88h\ +\xf8\xbd\x9e\x99\xe8\xf30\\q-\x97j\xa8\x89\xb6b\xd3\x8b0\xbb\x83G\xeb5\x8f\ +\xa6\x96!c\x1d\x1b\xb3\x8f\xbb\x96\x17\x02\xad\x16\x15\xb3\x92\xd6]\xb7\t0pA\ +T?\x9a\xea~VV\x939\x8a\xbd\xdd\xea\xed\xa5U\xcaI\xce_\xfe\xe8\'\x8f\x8e\x9e]\ +\xee\x97\xf7C\xa1X\x9f&\xb3\xe7\xc5\xfa\xf4\n\xc7\xca\x1a\xc53\x91\xe8\x8e\ +\xee\xf7\xc7\x8f\xe3\xde\xcd\x10\xe8u\xdaf)\x1e\xcc\n`\x11\xf6E0V\xd4?\xfa\ +\xf2\x8b\x1bi\xdb\xc7\x8a\xd6\xb7\xba\x1b\x08\xc2No\xf4`={\xc9\xd5dL\x046Ed\ +\xf4\xf4D\x9a\xfft\xf5+\x18G\xc6f\xcepm\xaa&\xd6\xc1D\x90\x02\x0bek\xc3+\xe8\ +y\x9b\x14H\xcfvd\xd5\xb5\xfb\x8bg;\x80\xb3\xe6\xad;\xa9\xdc\xfc\xef}`3\x8f\ +\xb7\xd1\xd7\xd6jb\xd3b\xb8Wr\xe6\x8e\xe1ne"\xa3\x15\xb9\xa3\xf2\x8d\xdc\xd9\ +\x9b\x97\x03v7\x8b|:\xa7\rn\x07#\np\x95\\\xbf\x1f\x10Q\xff \xea\x1f\x94\xe9,\ +\xd1\x95\xc8.\xa3\xdb\x02B@\xac\x18\x92u\x9cY%\xf37\xc9\xfcMgpox\xf0\xf4\xfa\ +\x14o\xdb6_\x9f~\xadU\xfc\xc5\xa1K\xe8\x04\x02R\t\xa9X\x95\x89*\x13Pg5\xed\ +\xf4\xc7\x0f\xdb\x8c\x9a]h\x95\xfb\x9d\x81\'\xde\x1by2:H\xea\x16k\x192\xf0\ +\xb2]*\x17\xdd\nb?M\xa5\xf2hP\xe5W\xd6\x9e\xa3\t\x96\xb7\x9dlvD_\xadm2\xbb\ +\xedi\xdc{\xdb0\xcf\xd0\xf7\x86\xacz\x1b\xc9\x97\xee5r\xb7j\xdc\rW2aU\xa9\ +\x1c\x83\xfb\xb2\xbd\xf2a\x9c\x9b\xa3?\x8b*[\xa6\xe6\xcc\xb8\x9d\xfd\x9bPL\ +\xf3\xb5\xfa\xec\x8b\xdb\xab\xdc}\x94\xe9<\x9d\xbf\xc8\x96\xef\xc0\xea\xfd{\ +\xd7\xa1\x18\x92\xad\x85E\x00\xa3\xd3\xdf\x1f\x1c<\xed\x0en\xa6\xa0c\xbe|w\ +\x05\x13\x89Y\xea\xd1\x18E)K\xa9\xf4\xb7>\xec\x0c\x87\xfbOz\xa3\xfb7\x92\xb3\ +\xff\x91\xa1%\xf7\xbb\x84\xc5\xf1\xd7\xcb\x93?y\xd1G\xb6\x1cmvh\x90;\xaaM^d\ +\xd5f\xd5l\xe7wTvI\x83\xde\x9d\xae\x86\x15\xec\x8e\x1c\xb1\x95\xd9\xf9\x9c\ +\x99\xf8\xec)+Z\xf7\x9a\xef\xb1\xbbn\x90\xf3U\xfc\x0cK\x06\xac-\x04\xd6\xb3`\ ++U\xb1\xf3\x06\xb9\xc3#n\x9dnW\xeb\x03\xbdN\x7f2<\ +\xf8\xac38\xb8\x91\xb6\x15\xeb\xd3d\xfa\xdd\x05U\xbc\x02\xba\xa3G\xbd\xbd\ +\x87"\x10E\xb6Lf\xaf\x93\xe5\\\xb1\x99>7\x8c\xba\x83\xc9\x93\xc1\xe4qK\xf1>Z\ +r\xbfK`U\xbe\xfb\xfa\x9f\xa5\xccl\xda \xaa\x81K\x8e!\x05Q\xfdwj\xd2%\xc9T\n\ +\xf6\xd9\xba\x96u\xe8D{\xc5\xad\xb5\xab[\xcf\xdd\x93\xbf\x95`G\xc5\xef\x9a:w\ +\xd3:\xb3k\x95\xf7\xf4Q\xb5\xc9_\xe5=kTWu\xee\x8aM\xa9\xd7\xec\xacT\xbd:X\ +\xb5\xa7\xa3l\xd4\xb8\xdb\xc5Z\x89M \xc1\xeb\x06P=\xee\x80\x89\x99A\xb4\xce\ +\xf8\xe1\xd3\xbbD\xee\x1a\xb2H\xd3\xf9\x8bl\xf1\xfa\n\x95\xc84\xc5+O\xfdw\ +\x87\x87\xc3\xfdg\xd7\x9c\xf8\xc9\xa1X\x9f&\xf3\x97\xc5\xfad\xbb\x89DP\nE)G\ +\x87?\x1a\xdd\xffR*\xccf\xcb\xac\x90\x83\xb8\xe0\xb3\xdf\xe52\xd3F\x8d>2\x0c\ +\xbb\x83\xfd\'\x83\xf1#q\x139\xfb\x1f\x01Zr\xbfcX\xcf^\xcf^\xff\xb6\xe2b\xdf\ +\x8da\xebj\x10|~o\x88w\xb3\xd2n\x13\x1e\xc9\xba>\x03\\u\x17\xd4\xe0\xe9z\xbc\ +\xb4\x12\xd2z\xdb\x86\xe6\xb5\x87l\xc0\xebd\xaa\xcb\xbb\xc5\xaaU\rr\xafN\xe6\ +\xbb\xed\x0c]o\xd8\xa9vj\x92\xbb\xcf\xda\x00\xeb\x88\x85U\xfd6\x03g\xbb\'\ +\x03"V\x0cBV\xe0\xde\xd1\xdd#w\rUf\xc9\xf4\xbbt\xfe\xf2\xcaF\x8d\xae7\xa1\ +\x7f!\x9d\xfedp\xf0\xec\xa6\x8c\x9a2\x9d\'\xb3\xef\x1aq\x02\xc5($\n\xa9b\x11\ +?z\xf2\xf3%\r\xe7\x8b\xb4(\xa4b\x16D]\x9e\x85\xe5w\x04\xa9\xec\x0c\xddZR\x04\ +ag0y<\x98\x1c\x05a\xe7F\xdavw\xd1\x92\xfb\xdd\xc3\xe9\xf3_\xe7\xeb3\xe8\x02\ +\x01\x8e\xd3\x01\xa0\x96\x19\xe9\xf1\xb3\x0e\x8b\xb2\xaf\xdf\xcd\xfe\x80fw\ +\xbbX92\xfe9\r<\xbb\xc5\xbdx\xdf\x9f\x8d\xaf\xd2E\x82\xaa\xf0x\xbc\xa6\xe1\ +\xdd\x13\x05`\'8\xad\xf5#\xd6KAM\xb9W{xNN\xdd\x991\'\xf4\x1d\xfc\xf7\x18\xee\ +\xae\x01\x85\xc4\xe1\xd1O\x1e=~z\x91\xdb\xba\x9d\x90\xf9*\x9d\xbf\xbcZ=a3\ +\xb7\x1f\xd7)~\xf2\xa4;\xbc\xd7|\xca\xbb\x12\\\x9c@JUH\xc3\xd7\xccj\xaf?\xe9\ +\xed\x7f>+\x82^76U\x84\x18\xa0\x10\xd91\xad\xbf\xf6\xdbVQ|\x10\x0f&\x8f\x07\ +\xfbO>e\x8ao\xc9\xfd\xee\xa1\xcc\x93w\x7f\xfa\x17\xb0\x146\xd6\xe82\xd9\x8d\ +\x87n\xd2e\xe02%I/[\xf8t.\xfc?K\xaa4\xbc\x17\x95\xf5\xd8\xdd\xe3M\x8fgk_\xa2\ +\xf7~\xa1*\xb7\xa3\xd6\xcb\xb8W\xf26{AWk\xb4\xfb\x9d\x89\xf3\x7f4\xb3;\xb3\ +\xbd\xde\x01\xd4\x9a\xe4\xc8\xdd9\xf8\r\xc3\x9d\xc8R?\xd7I\x9eQ*\x1c}\xf9\ +\x97\x93\xfd;?Q\x9c5j\xde\\\xa1\x9e\xf0&\xc5G\xdd\xd1`\xffi\xef\x86f\x05)\ +\xf3\xd5\xec\xddw\xab\xd9\x1bS-B\xa9\xbd\xf1C1z\xaa\x14;\x0f\x91\x01AB1\xe4\ +\xec\x0fT\xcel\xbe\x17\x14 m\xaf\x00P\x10F\xfd\xf1\xa3\xc1\xe4\xf1\xcd\x0c\ +\xcb\xbakh\xc9\xfdNb5}1\x7f\xfb\x87Z\xce;\x00\xcf\x88\x07l\xd4\x14\x86\xab\ +\xd9)\xf7:\xb9[\x17\xa6Z\xe1\x9b7\x1b\x82\xac\xd2\xec\xd8\xd0\xea\xe7|\x95.\ +\xf6%\xabE\x82\xfdHk\xdd\xeb\xf7\xce\xc9l\x98\xda\xf8\xed6\xc0k\xf6!\xa7\xcd\ +\xeb\xcd\xf0&`\xf2<\x19\xd7\x9dT\x06\xbdw6\x06\xa4\xc2\xd3\xaf\xfejo|[F\xa8^\ +\x13J\xe6\xe9\xfcU:\x7f\xc9\x17\xa8D\xe6~\x83\xfa\x97\xb4I\xf1ag0\x98<\xe9\ +\xef=\xa4\x9b\xa8\x9aYd\xab\xe5\xd9\xcb\xe5\xec\x8d*\x0b\x11L\xa4\x18\xe9&T\ +\xcf\xa2\x82\x98)\x90\xa7\xfdx\xc1\\\xfb\x9aZ\x8a7\xb1\x1f!D\x7f\xef\xd1\xf0\ +\xe0\xe9\xa7F\xf1-\xb9\xdfU\x9c\xbe\xf8M\xbe:\xb6\xa69\x9c6\'\xda\xe2\xa8\ +\x10\xd9\xd96\xfc\x00,\xc3\xe3q\x0f\x1e\xaf:\xa9\xd4\xa4q\xcbwt)N?\xff\xbbF\ +\xb5\x17\xd7\x14\xaf/\xa9\x9f\xc9(wB\x95&C\rr\xaf\x95q\xaf\x8e\xddi\xb8\x93O\ +\xeeN\xdd{\xe4\xfe\xf9\x9f\xfd\xed`8:\xf76\xee\x18tA\xc7d\xf6\\\x15\xc9\xce}\ +6\xd6lR\xbc\xfe]\x85q_\xab\xf8\x1bI\\)\xf3dq\xfa\xe2\xf4\xdd\xb2T\xa1\x105\ +\xe1\xa13_\xa3\xa8$\xcc\x86\x1d\x16\xdbdH\xa9 e\x8d\xe2\x07\xfbO\xa2\x1b\x19\ +y{\x17\xd0\x92\xfb]\x85\x92\xf9\xf1\xb7\xff\xa65\x17\xf9\x1c\xadk\xbe\x83@U\ +\x04\xd5\'w\xb3\x97\xfb\xe9\xc9|\xd4W\xfa\xb6wS\xa6o\xf3\xd3\xb7}\x934/n7dw\ +\x7f\xf3\x9aM\xa9\xf2p\xbc\xc3|W\xc8Z4U-0\xb7\x8f\x8d\xb1V\'tV\x8c\xdd\xc1K\ +\x82\xf4\xe2\xb7\xee\xd5\xc6i\xc1\x14|\xf5\x8b\x7f\x88\xa2\x8f\xd0\xc6e%\xb3\ +\xc5\xebt\xfeR\xe6\xab\xe6\xa6\xddG9\x8a\xd7,\xef(>\x08;\xfd\xc9\xd1`\xf2\ +\xf8F\xea\t\xbf\xfc\xfa\xeb\xe5*!\xff\xa9\x93\xc1\xccD\xe8\xf7;\xb3\xd9\xabA\ +G\rbY\x97\x05U\xe3+\x8a\x07HPo\xf4`|\xffG\xc1\xc7\xf8Kl\xa0%\xf7;\x8c|=={\ +\xf1k\xb6u\xde\xe1(\x9b\xec\x03\xac\x9f\xea\xe8\xc8\xbd.\xd8\x8d\x1f\xcf\xd5\ +{\xb3\xde\xbe8\x0b|\x97N\xdf\xfe\x05\xda\xf6\xbd\xaau/[\x0f\xda\xb2\x8e\xaaM\ +\xd6\x9d1w\xc8:A\x91\x98m\x9e\x0cUU|5\\\xde;3\xb1wB\xab\xc8\t6\t\x12\xbe\xe1\ +n\x9b\xe2\xdc\'M\xfdA\x18\x7f\xf5\xf3\x7f\x10\xc1G;\xae\x9bY\xe5\xcb\xb7\xc9\ +\xec\x85\xcc\x16f\xcd\x05\x8e\xf2)^\xd7\x9b\xb4\x14\x1f\x87\x83G{\x07GQ\xdc\ +\xbdN\xab\x92\xf9\xf4\xe5\xcb\xb7\\\x99/\xe6\xbb\xd0\xebtU\xb9\x8az\xe3<\x9b\ +\xc6\xeaM\x14\x06\xbb\x9a\xab\x9f\xbaJK\xf1"\x0c\x07\x93\xc7\xc3\xc9\xd3\x8f\ +\x9b\xe2[r\xbf\xdbX\x9d}\xb7x\xf7?\xb05\xb7*\xcb\xc5\x19\x94\xb4\xe9\x9b;#\ +\xde\xecl\x02\x89n\x93}qA\xcd\xca\x95o\x9a\xd7\x1e\xf8}[\xb6\xb5\xe2\xfc\xbd\ +\xad\x07\xee\xbe\xa5\xe4=?\xd8\x95\x96\xdc\xf5{UK\xbc\xaf\xd2!]yH=0\xd5U\x1b\ +ts\xf2\xd9+\x18\x7f\xab\xf6\x94b;\x8cno\xef\x8b\x9f\xfe\xcd\xf6\xbb\xf9\xb8\ +\x90\xafN\x92\xe9we\xb6`\xbe\xe8\xe8\'\xf7\x04(\xf5\xdc\x8b\xfa<%\xe72\x9c\ +\x1c\x1e\x8d\x0f\x1fw\xbaW\xb6\xbcyv\xfcv:_)[k_\x10\x05\x04Vi\x7f\xef\xc1:)e\ +\xf2no2B\xf2-\xab\xed\xfa\x1d^\xdb\xb4\x8f\x04\x86\x08\x82\xfe\xde\xc3\x8f\ +\xd8\xa8i\xc9\xfd\xcecy\xfa\xed\xf2\xf8\x7f\x9d\xd5\xee\x13\xb71Dj#N\xfdW\ +\x9bNc\xb9\xccO\x93lH{\x07\xdf\x18\xd9\x00\xef\\\xa8o\xf0y\xf6=\xa7pw\xe2\ +\xbb1d\x9e!\\\x87\xc2JOS\x02\xe5\xfb-\xb6\xb9Z\xd5W\xbd\x82\x17w\xad\x0fL\ +\xb5\x16\xbfa~\xe7\x08\x99\xdd\xf6\x0e\x1e\x1f}\xfe\xb3]\xb7\xf5\xf1A\x16i\ +\xbe|\x93\xcc^*y\x89\xb9\x9f\xc8<\x18\x19\xa3\xa6T\x9c\xe6(\x15\xf5\xfa\xa3\ +\xfd\xfbO\xf6\xf6\x1fn\x91\x1b\x17@\x99gi\xb2\xce\xf2<\x0c\x82@\x04E\x91\xa5\ +i^\x14E\x1cQ\xd09\\\xcd^\x8fza(\x96\xc5\xea\xddy\x93\x80\x13X\x9bH\x12R\x01`\ +"\x11\xf5F\xc3\xc9\x93\xde\xde\xcdd\xfb\xdc\x1e\xb4\xe4\xfe1`\xfe\xf6\x0f\ +\xeb\xe9\x0b\xcb\xef\xda\x9f\xa8\x99\xc7^\x02{\xd3\xd0n8-\x9b\xa3R}\x15o\xcf\ +W\x03o]\xbb\x89J\x0e\x9fk\xc1\xeft\xee\xed{\xff\xe9\x81\xcd\x9f\xab!w\xe7\ +\xb7\xf8\xe9\x8f\xc6t!\xdbST\xb3\xeb\x01U\xc5pe\x03\xc9z\xef\xc6u\xb5u\xf3\ +\xe0\xc9\x8f\x0f\x1f\xdc\xc9\x11L\xd7\x81\x8d\xb86\xa7\xd0;\x1f\r;>-8\xcb\ +\x99\x81\xfep|\xf8\xf0\xf3\xd1\xf8\xdeu\x9a\x94\'\xc9rv\x16u\xfb\x80LR\x99\ +\xad\xe7\xdd^?-\xe3 {>\x1a\xc6\xf9\xfa-+nt!\xfeWHg\x13T\x13?1@\x14u\x06\xc3\ +\xfd\x1b\xcb\xf6\xb9\rh\xc9\xfd\xa3\x00\xf3\xd9\xab\xff\xca\x96\xef`\xf2\xd6\ +\xeb\x82}\xab~\xd7\xfa\xd7\xbd\xdf8\xa37\x9c\xc9\xad\xd3?.\xf9\x859W\xa7\xd7\ +.\xce;\xd6\xeb\xc5MG\xc8\xfcUn\x92\xbbs\xc9\xab~\x87\x01\xe3\xd9\x92\xf6\xdf\ +u\xba\x0c\x9c\'cRell\xa2q\x9f\x9a\xdc\x9f}\xf5\xab\xe1\xde\xcdTV\xb9s\xd0S\ +\xe8%\xd3\xef\xe4\xee\xa4\x1a\x1f>\xb32\xa0\x14\xb2\x92\x93\x1c\xa5d\x02\xfa\ +\xa3\xc9\xfe\xbd\'\xa3\xc9\xd5\xc52+5}\xf7\x06"\x8c;]\x86JRY$g"\x18J\x95\r\ +\xf0\x86\xb9\x90EV%\x03lm!\x01\x0c\xc5(%$\x9b\xbf\x88(\xee\x0f\x0f\x9e~\x1c\ +\x14\xdf\x92\xfbG\x02V\xe5\xe9\x8b\xdf\x14\xc9\xd4\x1b\xa4\n\xff\xbb]\xcb\ +\x1b7+\xedLG\x96\x05k\x89\x91\xce\x94\xb7\x8b5\xb2<\xaf)[w\xaa\xba\x88m\xde\ +\rm!\xf9\xday\xa8\xb1\xdeJlg\x9eT\xc9@\xcc\xba$0\xea\xf4N\xb5,\x1a\xaf\x0f\ +\x80\x9d[\xd5/?\xe9\xdf\x02\x03\xac\x98D\xf0\xa3\x9f\xff\xfd5c\x83w\x1d,\x8b\ +t\xfe2\x9d\xbf\x92\xe5y\xf5\x8fw\xd9.\xa5\xc2:\xe3\xb4\xd0\xb1l\xf4\x07\xa3\ +\xc9\xfd\xa7{\xfbW,\xdb\xcb\xcc\x8b\x93\x13\x11\x8a4\x93\xa3\xbd\xbd\xa2(\ +\x16\x8bD\xa5gao?,_\x085W\xd2M\x9a\xfb\x9e\xa6*3C\xb71\xfd\xa2\xb8?\x98<\xee\ +\x8fof\xf6\xf0\x0f\x85\x96\xdc?\x1e(\x99\x9f>\xffu\x99/\x9dN\xaf\xf3\xbb^\rl\ +\xf0\xbb\x07\xdb\rh\xf8I5\xf6\x8f\xe4:_\x98]"\xbd\xb9zS\xa4\x9b\x82\x01\xec\ +\xe5\xed\xd85\xa6N\x9ao\xac\xb3\t\xe8y)\xefl\xbe\xead\xcfQ\xe5\xc08\x0f\xa7^\ +[\xd8\xb6\xc1\x9e<\xee\x0e\xbf\xfc\xd9\xdf^\xcd/\xfe\xc8`U\xfc\xf3\xadF\xcd{\ +?\xa0\\"\xc9\xb9\x94\x08\x03(\x850\x1e\x8c\xef\x1d\x8d\x0f\x1e\x8b\xcb\x8beV\ +j\xbd\x9cC\x81\x85(\xf2r0\x1c,\xd7\xc5z>\x13r\xd5\x1fu\xd5\xf2\x7f\xbc,\xa9\ +\xf3\xe0(\xde\xce\n\x02\x10\x820\x1eL\x8e\x86\xfbGw\x94\xe2[r\xff\xa8\xe0\ +\xf1{\x15_\xad?\x9b\xfa\xec\xc4\xd4\xfcKtB\xd9\x0e\xfc\xa7\xfa\xb6\xe6\x97\ +\xc5-\xef\xf4wj\xfb\xed\xfe\xaem\xa5\xf5\x1d\xdfM;\xb3G\xc5\xf6\xaeT\x80U\ +\xee\xd67g0\xd8U\x0cf\'\xe1\xe1\x0e\xf2J\xca\x90\x8d\xa06{\x1d&u\x00\x00 \ +\x00IDAT,~\xbd\xe7\xf8\xf0\xe8\xe8\xb3\x9f\xee\xbc\x81O\x0f\xacd\xbez\x97L\ +\x9f\x97\xf9\xd2\xad\xbcP\xd7G`F)\xcd\'\x9f\x97\\\x94\x88:\xbd\xc9\xbd\xa7\ +\xa3\xc9\x83\xe0\xf25\x1dW\xb3\xb3"/\x06\xa3\xf1z\x9d\x80\xd1\xe9v\xcef\xa9J\ +\xcf\x06=@\x9e\x14\xe9\x8c\xe8B\xd9\xab\xfa\xdb\xee\xc2\xad\xfak\xa0)~0~|\ +\xe7\xf2&[r\xff\xd8\xa0d~\xfa\xe2?\xcat\xe1\xe2\xab\xe41/9\xf9N6A\xa4&E}\xad\ +\xbc!Rk\xecN\xe7Qu\xe3\\\x17\xe6t\xb7\xe4X{\xdbv\x82O\xeez\x07\x9b\xe7\x0ec\ +\xcb\xb8\xb6Z]o\xbf\xea\xcc^\x97\xe0\xc9vT\x87\xa3:?L\xff\xc0\x8c\xa3\xcf\ +\x7f>>xt\xfe-\x7f\x8a`\xceV\xef\xd2\xd9\xcb"\x9d\xe2\x82\xe4\xee\x0e\x85\x91\ +\xc9\x8a\x91\x15\\HDQ\xbcw\xf0dr\xef\xe8\xb2\x14\x9f.\x17\xc9j\x8e\xa0;\x18\ +\x0e\x17\xcb\xa4\x13\x87e\xa9\xd6I\xd1\xc34\xa0e\xb6>&=\xe7\xfb\x05\xb0\x95\ +\xe2Ep\xf7R\xe3[r\xff\x08a\xf8=[T\xa6y-K\xd2F\\\xe16\xd7\xe0L\x19c\x84zTX\ +\x11\xe1FV\xe56\'}\'v\xf1\xbe!\xd3MZ\xb7>\xbbY\xd2{\x109\xff\xc4\xe5\xb9\xb3\ +V\xe8\xca\x8atX\xeb\xdd\xaba`\x95{M\xb6\xeb\xc3aW\xda\x0b\xd9\x15\x14|\xf5\ +\xc9\x1b\xee\xe7#_\x9f\xa4v"\xecK\x81a\x86>IF\x96s\xa9\x10\x86\xf1h\xff\xd1\ +\xe4\xdeQ\x14\xf7.~\x9e\xb2(Vg\xc7%D\x7f0\x12A0\x9d.{\xb1HR\x0e\x03\xd9\xe1\ +\xe3,9VeN\xe2\xda\x14?~<\xdc\xbf\x1b\x14\xdf\x92\xfb\xc7\t%\xf3\xb3\x17\xbf)\ +\xd29\xdcL\xaa\xb0\xccN\x86\x1d\x9b\x04]\tb\xb3Tsp\xb0\xd3%\xb98\xce\xe3t\ +\xfb\xc2\x9b\xeba\x08w\xe3a\x81<\x16f(\x93\x15\xc4\xd0\xca\xddcv\xc090\xf0\ +\x8c\x17\x9f\xe8\xcd#\r\xbbKU\xcc\xce\x8cn\x7f\xef\xcbOc\xf8\xd25Q$\xd3d\xf6\ +\xbcX\x1d_\xf6\xc0\x8a\xe2\x15\xd2\x82\xa5\x84\x08\x82\xbd\x83\xa3\xc9\xbd\ +\xa3\xb8s\xd1\xd1O\xac\xd4\xe2\xec\x84\x82 M\xcb\xf1x\x9c\xe6e\xba^G\x81P\ +\x14t\xc3\x9c\x90\xad\xa7\xdfA&\xb8\xb8\x8a\x07\xf4\xe0\tY+S\x13\x0c\x0f\x9e\ +\x0e\xf7\x9f\xdcr/\xbe%\xf7\x8f\x16\xac\xca\xb3W\xff\x95\xafN+~\xf7\xc8\xdd\ +\xdf\x936d\xb8^\xbba\xd8\\\xe5\xabr\xbe\xa2w\xb4\xce[\xd7\xa3\xc9\xf8\x1b\'\ +\xd0cV\tZ\xbc\x1br\x07+V\x9eZ\x07{\x84\xeeX\xdb\x8er\xb2O\x05.\x0f\x92\xf5\ +\xc4\xdd>\xb9\x8f?\xb1\xe1K\xd7\xc4\x95gpe\x98\x1a\x06v\xe8\x13\x04\xd1h\xff\ +\xe1\xc1\xfd\xcf:\xbd\x0b\x8d#\x95e\x99.\xe7\xa0\xa0\x94\xac\x94\x1a\x8eF\ +\xd3\xd9ZfI\xb7\xdb\t;A@\x94\xad\xdf\x15\xcb\xe7\xc4\xc5%(\xde>\xb9V5\x0c\ +\xeeB\xb8\xb5%\xf7\x8f\x19\xac\xca\xd3\xe7\xbf\xb6\xfa]\xd7M1_T\xe3(\xfb\xdf\ +\xed\xe6\xe4\xab6\xa1\xd2Y\x13\xb5}\xcf\xbd\xee{\x96\x9b\x92|\xfb\xd6\xf7\ +\xd0\xban\xbf\xc9\x81\x81\x91\xe1\xd6\xab\xd1\x15c\xea\xe7w\xb91\x9b\x12\x1e\ +5r\x87\xc9\xab\xb1\x871\xf0\xe8\xd9O\xf7\xef\x1d\x9d{\xd3-\x9a(\xb3e:\x7f\ +\x99-\xdf\\m\x06\xd7RAJN\x0b\x94\x92\x85\x10\xe3\x83\x87\xe3\xc3\'\xdd\xfe\ +\xde\xfb\x0ff^\x9c\x9d\x96R\x0e\xf7\xc6\xcbU\x12\x10\x11\x89\xe9"\x1dD\xe8\ +\x0f{E\xa9\x888\x9d\xbf\xa0\xf2\x94U\x0e\xef\xc9v\x17\x1a"\xa7I\xf1\xe3G\xfd\ +\xc9Q\x18\xdd:\xcb\xae%\xf7\x8f\x1c\xac\xca\xe9\xeb\xdff\xabc\xf2R!\x1d\xbd\ +\xb9Y<\x1a\x16<\xd5\x85;or\xb0\'\xf6\xb7\x06E\xb77\xc6{\xc7\xb5\x83w\xec\xd0\ +X\xcf\x1b\xbb\x01\x8e\x85\xd9\xd6\xf0\xf5\x88\x9b\x1b\xaez\x95\xfb\xe8_\xc2H\ +w\x17v\xae\xe6(d#\xe3\x83\xaf~\xd1\x1a\xeeW\x84,\x92t\xf6\xfc\xcas?\x95\n\ +\xa5\xd4*\x9eCA\xe3\x83\x07\xfb\x0f\xbe\xb8H5\x98\xf5|\x9a\xacW\xdd\xfe^\xdc\ +\xe9Lg\x8bn\x1c\xa6IY\xcar2\xea*\x11\x02Tf\xebb\xfd\x1a\xe5\x14\\\xe8\x18\ +\xce\xaeSmn`\xa0\xf4\xbdx\x11\x0c&G\x83\xfd\'\xb7\x8a\xe2[r\xff$0\x7f\xfb\ +\x87\xf5\xece-\xbb\x91k_\xe6\xc6\xd7\xd7\x1f\t\xc5\xa8\xe5\xb6_6\xcd{\x8b\ +\xc1\xb2-\xd1\xe6\xfd>\xccN\x8do\xfb+\xd693\xec\xbe\xd5\xbeN\xaf\xd8\xdc\x0e\ +YB\xc3j\xf2*\xc9\xd8}M\xa6\xcdp|\xff\xd9\x8f\xfe\xfc\x12\xf7\xdcb\x03\xaa\ +\xcc\xd3\xf9\xcbt\xfe\xf2\ns?1PH\x14%\xa7\x05\xa4\xe48\n&\x87\x0f\xf7\x0e\ +\x9f\xbd\x97\xe2\xf3$I\x97\xb3L\xd2x2)\xa5Z\xceWQ\x804W{\xc3N\xdc\xed.\x96ID\ +H\xb2T\xc8\x19\x8acp\xb6U\xc5\x9f\xf3\x85oR|\x10\x0c\xc6G\x83\xc9Qx\x998\xf0\ +\xf7\x87\x96\xdc?\x15\xacg/\x17\xef\xfe\x87Y\x91\xb5f\x1c7:\x1b\xde\xd3\xefU\ +\x9e;\x9b\xca\xba\xde\xb9\xf82\x1c\xbfC\xa4\xfb\'\xf3^6h\x9d\x9b\x8b[\x14\ +\xbd\xbe\r\xc0N\xa2\xea\x1e5\xc8\xaf\xf8\xe8\xf8\xbd\xb1\x08T\x0f5.\x0f\xd2\ +\x7f\x1ax\xf6\xd5_\\\xb3\x16J\x0b\rU\xe6\xe9\xecy2\x7fq\x05\xa3\x86\x81\xa2D\ +^rVBJ\xee\xc4\xc1\xf8\xe0\xc1h\xffI\xdc;\xcf\xa8Q\xb2\\\x9e\x9d\xb2\x08d\xc9\ +\xc3\xbd\xd1*)\x8a4!F\x18\xd1ho\x94d\xb2\xccs(N\xb2\xb4\x1f\xaeT\xfe\x8e\xcb\ +5\xa3\x1aKu\x91\xafye\xd4\xe8C\x88\xfa{\x0f\x87\x07\xef\xef{\xbeo\xb4\xe4\ +\xfe\t!Of\xb3\xd7\xbf\x95e\xeaR\na\x93\xde\xadT\xb5T\xbfi\xb6oe\xe7\xf7\'\ +\xbb\xef\x04o\xbc\xdb\xe5\xc3\xd4\xd6o]c:\x1fr\x93v4]\xf5\xba\x0f\xd3\xb4e\ +\xea\xe4^?9\x87q\xef\xc7\xbf\xf8\xfb\x8f\xac^\xe0\x87\x85,\x92t\xfe\xf2j3\ +\xb82\x90\x15\xc8J.J(\xe6N(\xc6\x07\xf7G\x87\xcf\xe2\xeeN\x8aWe\xb1\x9aO\xc3\ +\xb0\x93\xe6e\x10\x88(\xea\xcc\x16I\x84"\x8c\xe3(\x14A\xdc[\xae\xd6\xa2\xcc3\ +\x15\x0e\xfa\x08E\x91\xcd\xfeT\xe6\xab\xads\x94\x9d\xdf0\xa9P\xaaj@\xdc\x07\ +\xa7\xf8\x96\xdc?-\xa82\x9f\xbd\xfd}\xb6:\x01`=\x12\xb2\xf3u\xb0U\xeb\x8e\ +\xdd\xb9\x12\xb6\xd7F\xf3{\xc6\xdb7\x9dc\xaf\xbb,\x97\xdai\xaa\x1a\x03f\x04\ +\x93\xef\xc6`\x83\xca\xb9\xee\xc2;\x10\x91\xdfs\x98C\x98\xef\x1f\xfd\xe8\xfe\ +\xa3\xcf/v\x8b-.\x01m\xd4d\x8b\xd7\xea\xdc25[\xc1\x8c\xb4\xe0\xacDQ23:\x11\ +\xedM\x0e\x86\x07O\xbb\x83\xeds\x97+%\xb3\xc5\xb4\x90\xe8\xf6\x07\xb3\xe9|0\ +\x1c$\xa9LV\xabq?\x16q(\x82\xb0\x90\xc8\xd6+R\xccQ|\xef\xfe$_\xbdK\xa7\xdf\ +\x94\xd9%\xaa`\x9a\x86A\xa7\xfa\xc0\x8e\xbb\xa0\xde\xf0\xde\xf0\xe0\xd9\xf9\ +\x8f\x17\xdf\x13Zr\xff\x14\xb1:{\xbe<\xf9\xda\xcd\xc3P\x99\xf0\x9a\xd5M]Ir9\ +\xdf:1\xd0\xff\xa2\xec\xa2\xfbsT~\xb5y\xfb\xd2nZ\xf7\xb2\x18\xfdE\xb3\xe4u@&\ +<\xe0\'>Z\xbev\x14\x8fMy^\xdd\x91\x9f8\x0f\x06\x0b\x11}\xf5\x8b\xbf\xfb(\xe7\ +\xd5\xbb%`Y\xa4\x8b\xd7\xe9\xfc\x85*.I\xf1\x04f$9g\x05J\t\x00\x9d\x08\xa3\ +\xf1\xfep\xffIwp\xafY\xba\x1a\x00\xb0<=^\xa7\xd9hoRHUdy\x18\x04\xcb\xa4\x1c\ +\xc4\xe8\xf6\xbbEQ\n\x11\xac\xd3\x82d\x810\x9e\xec\x0f\xc3(\xca\x16o\xd2\xd9\ +we\xb6\xdc<\xd5{n\xeavP|K\xee\x9f(\x8at>{\xf3\xbb2[\xd5\xadv7v\xa9\nK6J\xfe\ +\xeeD\xe3\xaf\xe9|\x87}s\xcdV!\xefQs\xfd\x10vcl\xb5\xcb\xee\xa2\xc3&e\xc6\ +\xa7r\xd4\x83\xa8.\xbe\xda\xb8^5\x94\xab\x92\xed\x87\x0f?\x7f\xf8\xe4G\xdb\ +\xef\xa4\xc5\xcd\x81U\x99\xaf\x8e\x93\xe9w\x9b3\xb8\xee<\xc4~3\x15#\xcd9- \ +\x15\x08\xdc\ti0\x1a\x0f\x0f\x9e\xf5\x86[(>[\xce\xd7\xeb\xb5\x08\xbb\xddnw\ +\xb1J\x88\x15+\x94\xb2\xdc\x9f\x0c\x0b\xc9,\xa5R\xbcN\xb2N(\xa2^w4\x1e\x01\ +\xc8\x96o\xd2\xf9\xab2\x99^\xfa\xa6\x1a\x14\x0ftG\xf7\x06\x93\xa3\xee\xe0\ +\x07\xaa\x1a\xdd\x92\xfb\xa7\x0bV\xe5\xe2\xe4O\xab\xd3\xef\xfc\xe2\x04\xa8\ +\xf2\xdd\x99\x01\xe1\x12\x04\xebj\xf72\xf1\xd4\xf7\xad?\x97\xd6\xb1\xe1\xb3\ +\x93\xf5^\xf4\x92%w\xf3\xe7\xceF\xbdo\t\xa2\xd6\\\x9a\xad-\xd3c\xa0L\x1f\xc0\ +"\x88~\xfc\xcb\xbf\x0f/_\xc7\xaa\xc5\xd5\xa0gpM\xe7/\xcbt\xfe\x9e=\xbd\xf7\ +\x8e\xe2\x93\x8c\xd3\xc2d\x81\xc5\x11\xfa\x83\xd1`r\xb4Y\x99]\x95\xc5j6M\x0b\ +5\x1c\x0e\x19b\xb1L\x02.AA\xb7\x17\x86a\x9c\xa4\x99`\x95\xe4*$\xd5\x1b\x0e\ +\x06#\xe3\x98\x17\xeb\xd3d\xf6\xbcX\x9f^\xe1\xbe\xa4G\xf1\x00\xba\xfd\xc9\ +\xf0\xf0\xb3\x1f\x80\xe2[r\xff\xd4\x91\xad\xcf\xe6o\xffX\xe6\xabZ\xaa\xbb\ +\x15\xb3v\xfeTb\xbf\x1c\xcdU\xb1\x95\xd0\x9bK\xf5\xaa\xeb\xb5\xa8\xaei\x95))\ +c\xb7\xda22\xd6\x9f\xf1mw\xd4=\x19\xae\x9f\xb6\xd1\x003;\xb6\xe9\x0c\xf8^+\ +\xdb?\x08\x98\xf3\xd5q2{^\xa6\xb3\xed\xdb\xb7\xadt\x14\xbfJ9+\xc0\x80 tB\xf4\ +\xfa\x83\xe1\xfe\xd3\xee\xde\x03\xe1\xcd\xbd\'\x8b,\x99\xcf9\x88\xf3\xa2\x1c\ +\x0c\xfai&\x93\xf5\xba\x13\x90\x08\x83^\xaf\x9bK\x94\xe9ZJ\x95\x15j\x7f\x7f\ +\xd8\xe9\xf7\x82\xc0t\x0f\xc5\xfa4\x99\xbf\xbcBq\x05lP|\x7f\xef\xc1\xf0\xe0Y\ +\xdc\x1d]\xe1T\x17DK\xee-\xb4\x84\xffv=}\xce\xde`q\x976SS\xd1\r\\0S\xec"[6\ +\x82\x99\xde\x16\x9f\xe0\xe1\xc6\xa3\xda\x1f\xb5C\xd8\x06\x82\x1b\x9a\xdd\ +\xaf!\xc3\xb5\x93\xbb\x8b\x91\xe7\xc9\xb0\x08\xa2\x9f\xfc\xf2\x1f\x820\xba\ +\xc0\x1d\xb6\xf8^\xb0K,\x9fCX\x9a\xe2\xa5\xc2"am\xc4\x0bB\x1c\xa1\xd7\xed\ +\xf5\xf7\x9f\xf4\xc7\x8f\x1d\xc5\xcb<]/\x17qw\x98fy\x99\x17\xdd^w\xbe*\x84L\ +\xfb\xfd\x1e\x05$\x82x\x9d\xa4!\xcbu\xa6F{\xbd\xc1p \x82*]\xaaHg\xeb\x93\xff\ +\xdd\xd5\xf7\x9c\x0f]/^Z/\xbe;<\x1c\x1d|\xf6=y\xf1-\xb9\xb70(\xd2\xc5\xfc\ +\xf8\xeblu\n\x98\x19\xe7h\x8b\xc6\xbdb\xe6\xcc\xf6/Y\xbd\xd7h\xb8%\xd5k\xb5\ +\x9b\xa1u3\xb5\x9eo\x16m)\xe5\x08g\xbe\xfb\x16\xbc=7\xd5/A\xce\x96b\x86b>\ +\xfa\xec\xcf\x0e\xee?\xb9\xd2\xbd\xb6\xb8I\x14\xe9,\x9d>\xcfW\xef\xdc\x9a\ +\xf7\x12\x96\xfez\xe4%\xd6\x19k2\x8d\x02t"t\xbb\xbd\xde\xde\xc3\xfe\xf8q\x10\ +u\x01\xa82_M\xcf\x14\x85\x9dno\xb9L\x82\x80\x00\xb1J\xb2q?B\x10\x84a\x94\x17\ +*KV\xa4\x98\xc3\xf0\xfe\x83\x03\x12^:,s\xbe>I\xe7/\xafo\xd4h/\xfe\xfb\xa0\ +\xf8\x96\xdc[\xd4\xb0\x9e\xbfY\x1c\x7f#\x8b\x84\xdcH\'G\xab\x0e\xd71h6\x1e\ +\x03\xb6\x05Tk;m\xb1\xd7M#\xaa\xd96\xcc\x9eu\xa7\xde/\x10f\xadvWN\xd8\xcf\ +\xe37i\xee\x0cS\x15\xb27\x98|\xf9g\x7f\xd5N\xbat{P\xa6\xf3t\xfe2[\xbe\xe5\ +\x8bU"#2\x95\xe2\xf3\x92\xf3\x02\x85\x02\x01a\x808D\x1c\xc7\xc3\xc3/z{\x0f\ +\xb5\x8aO\xce\xde\xad\xb2r\xb87f\x88\xe5b\x1d\n\xce\x0b\x0eH\xf5z]\t\x16$\ +\xd6IN\xb2\x90L\xf7\x1f\x1d\x06as\xd2\x8fKy\xf1\xb5\xb8\xd1F\xb8\xb538\x18\ +\xee?\xe9\x0e\xb7gs^\x01\xff?{o\x1ef\xd9q\xdd\x87\x9d\xaa\xbb\xbf\xfb\xb6~\ +\xfdz\xefY1 0\x04@\x82 )\x1a\xdc\xc5\x9d\xb6d9\x92A\xc6r\xe4\xc4r\x12\xcbq$9\ +\xf9$\'\x7f\xc4\x96\x15\xd9\xf9\x92O\x12\x15k\xb1\x95O\x8a%[\xfa\x12}\x11-Z2\ +-j\xa1(\x12\x04@\x10\xfb>\x0bf03=\xbdoo_\xee\xad\xe5\xe4\x8fz\xb7^\xdd\xfb^\ +\xf7\xf4\x0c\x00\x02\r\xf6\xf9\x807\xb7\xefR\xb7\xaan\xd5\xafN\xfd\xce\xa9SG\ +\xe0~$Y\x91\x92wj+\xed\xdau\x14|\xa8\xf0\xee\xb1\xa8c\xccb\xed\x91\x065\xda\ +\xc2\xc6\x9a4q\xcc\x0f$*\xb6\x01\xf8YW\xc8\xe1/@Jm\x87\x11dO\xe5rH\xe3\xa8s\ +\x03*\x9f\x10z\xdb\xd9\xf7x\xfeA\xc3\xcc\x1e\xc9wLD\xdc\xed5\xaeG\xad\x8d\ +\x83@\xbc\xd2\xdf\x19\x07\x00\x88\x05r1\xf0\x98tlpm\xe2\xb8^X^\xc8\x95\xe7)\ +\xb5\xe3v\xa3\x1f1&0\x0c\xf31\x97\xbdN\xc7\x02dH\n\xa1\x87\xc4B)\xb8\xc0\xa8\ +\xd7\x0b|\xcf\xf1\xdd\xb0\x90\x1f}\x17\xeb\xd5\xfb\x8d\x15sz\x91\x91\xbdHM\r\ +\xf1\x98D\x9a\xf6\xc2\x89\xfc\xc4\xe2k\x02\xf1G\xe0~$\xe3E\xb0~k\xf7z\xa7\ +\xbe:f\xc1\x8f\x12\x92\xf9wO\xc11G\xe6\x89\xac2\x9f\x86u\x93Z7\x90}$\xdc\xa3\ +y2C\xb8\x0f\xce\x0f\x95\xfe$\xb6o:\x0e\xa6r\xa3\\8yvb\xf2h\xc7\xa57\xaf\xf0\ +\xa8\xd5\xab/\xc5\x9d\xed\x83`\x17!\x10sP{\xear\x81\x12\x81s \x04\x1c\x1b\ +\x1c\x8bX\x8e\xe7\xe4g\xcb\x93\x8b\x923\xd6\xef\xf7\x99\xb4l\xdbu\xfdV\xbb\ +\x87,\xb2m\xcbvm\xc7\xf5\xe38"Btct\x08\xf7\xc2P\xb9H\x8e\xc9X\xbf\xd9\xab_\ +\x8f;\xdb\xfb6\xf9\x91\x1c&\x10/\x10d2fy\xb9r8\xb10\xd6\x9b\xf3\xe0r\x04\xee\ +G\xb2\x9f\xc4\xfdVc\xe3R\xd4\xad\xebF\xf6Z\xf8\xcc\x8c\xd1\xd8!\xd5\r\x06kMS\ +\xe7\xf7@p0\xa0\xe1\xc4q\xbc\xc0\xe7\x02d\ +\x1c1.\x85\x90\xc5R.,\xee\xe9\xe5"\xe2N\xaf\xb1|\xc0\xe9\xc50\x93\xea\xd9\ +\x04\xe2\x95\x16\xef\x04\x85\xc2\xc4\xb1\xa00uk\x10\x7f\x04\xeeGrc\xe9\xb5\ +\xb7\xbb\xf5\xf5\xa8\xd7\x94<\x1a\x9c\x1a\xc7\xc1\x8f\x8d\x8c\x9a\x1c%Z\xf2x\ +`\x1f>\xad\xd5tS\xf9\xd9\x0f\xd6\x93\xf3\xc3\x93\x19\xe6}\x98\xe8\x98\x1e\ +\x82\x03\xd5\x89\x00@u\xf6\xc4\xcc\xfc\xa9\xd1{\x8e\xe4M+"\xee\xf6[k\xacW;\ +\xc8:\xd2\x98\x83\x90\x00\xc927\x81\xc0\x05\xd8\x14,\x8b \xa2$\x8e\xe7\x15\ +\x1c\'\x17\x96\xa6\x89\xedD\xfd\xd8\xa24\x8a\xb9`\xb1\xebX\xd4\xb6l\xc7\x8b\ +\xe3\x18\x19\x8b8\x96J9?\xcci\x17\xc9\xf1\x19k\xae\xb2^\x8d\x1fxY\x16$Z<"\ +\x08\t2QJ\x9c\xa0\x10\x96\xe6\xdc\xa0t\xb3aj\x8e\xc0\xfdH\x0e*R\xb0N}\xbdS_c\ +q\x07\xc6\xab\xf0\xc6\x1a~\x1c\x9e\x19\x17\xacw\xf8tf}\xd4>\x98\x0e#\xda:\ +\x18 \xaeOj\x9d\x1d\x0c\xf4\x072\x86^J<\xe3\t\x10\xb2p\xe2\xcerefL\x99\x8e\ +\xe4\xcd/\x89\xefJ<\xce\xb0i6T&!fH\xc8\xd0\x8c\x89\x001\x03\x8b\x02\xa5 $\nI\ +<7?1u\xc2\xcd\x15\xda\xed\xaem\xdb\x04H\xa7\x17\x05\x94S/p=\xbf\xd7\xeb\x83`\ +\x11\'a\xce\xf6|\xcf\x0b\xf6\x8d\xee\x8b\x18wwz\xb5%\x16\xdd`Y\xd6h\x861\xf1\ +\x9bTY\xa5\x84\xfa\x85\xeaM\xb9\xc6\x1f\x81\xfb\x91\xdc\x9c \xca^k\xbb][\x89\ +\xba\xe6\x82\xec\xfd\xe3C\xa6\x06\x82\xd1\xad?0{y\xcc\xf1\x01a}p&\x1b9a\xc8\ +\xcc\xe8\xe8\xc5\x9a\xa9w\\\x7f\xf1\xe4\xd9\xb0P\xde;\xffGr8\x84\xf5j\xbd\ +\xc6\n\xeb\xee\xec\xb5\x03\x01\x02H\x84\x88\r\xa6\x92\xba\r\x10\x80\x98\x03\ +\xa5\xca\x06+\x03\xbf\x90+\xce\xfa\xb9\x02\xa1N?\x8a\x1d\x9bF\xb1\x04\x11{\ +\xae\x05\x96C,\x87\xf5\xbaB \xb1\xad\xcadi\xd4\x85fT\xe2\xce\xf6^c\xcf^\xa2!\ +>\x1b\xa6\xa60u@\x88?\x02\xf7#\xb9E\x89{\xcdv}\xbd\xd7\xda\x12|\xff\x1dv\xc6\ +4\xb0\xec\xa9\xacI\xf5\x96\xb4u\xe3\xee\xa1J\xaeC)`r6\xf1\xf1T{\xe9\x15\xca\ +\xd5\xf9c\xb7\x1f\xed\xb2\xf4V\x12\xdeo\xf6\x1a\xd7\x95\xc5u,U(%0\x01\\\xa2\ +\xa9\x92\x90\xc4\xfaJ\x00"&\x02?\x1f\x16g\xd0\xf2\x1c\xdb\xa2N>\x8e\xfa\x16\ +\xcaX\x82o#\xb5]b\xd9\xfd~\x0c,b`U\xabE\xd7?P\xfba\xbdZ\xaf\xbe\x1cwwn\xaa8c\ +\xfc&\t\xf1\xc3Ji\xfa6\xdb\xdd\xcf\xa7\xeb\x08\xdc\x8f\xe4U\x89\xe0q\xaf\xb5\ +\xd3inD\x9d\xfa8\xfae\x0f\x19cD\xcd\xd27\x98\xb9m\x04\xd6\xc1\xd0\xbe\x8d3\t\ +\xc7n\xec\x138D\xf6\x01\xb6\x83D\xb4lwz\xfe\xd4\xe4\xd1J\xa5\xb7\xa8\xec\xbf\ +\x83+\x13C\xff\x19S,B\x00\xd4~ R\xa05=}\x02\xed\xa0\xdfk\x97\xca\xd3\x11C\ +\xe4\x11"X\x16q\x1c\x9bZv\xccd\xdc\xeb\x10j\xe5\x8b\xe1X\x17\xc9\xb1\xc2z\ +\xb5~c5\xda\xdbor\xac\x8cB<\xa54W\x9a\xcbO,\xec\x05\xf1G\xe0~$\xaf\x8d\xb0\ +\xa8\xd3mmw\x1b[q\xbf5\xf6\x86\xbd\x14x\x1c=7\xca\x98\xef\x03\xeb`\xb2\xf3\ +\xc9d;\xed]\x90\x01|\x04R\x9e\x9c\x9d\x9e;y\xa4\xb0\xbf\xe5E\x196\xa3\xd6:J\ +\x9e\xba@@{\xbe\xf34\xc0\x13\x00\x8b\x12\x04\xe8E2bX\x9d:\x1e\xe4K\x9dn\x9f\ +\x12\x0c\x8b\xd3\xedv\xc7E\x06\xb6\xed\xb8\x0e\x00\x91\x12{}f!\xb7=\xaf2u\ +\x13\xb1\xc0\xe2\xceN\xaf\xbe\xc4n2\x86A\n\xe2%\x00\x01J\xa9\x9f\x9f\xcaW\ +\x16G\x89\x9a#p?\x92\xd7T\x10\xa3~\xab\xd7\xde\xed\xb5v\xa2^k\x14\xbf\xc7\ +\xb66\xdc\xeb\x9e\x91\xd5\xa7`\xa0\xf9P\x9dO\xa1\xffp\x9e\x9dlB2H\x89\x00!\ +\x94\x16\xca\xd5\xea\xcc\xf1 \xf7:\x06l:\x927\x9bH\x1e\xf5\xd4&\xdd\xda\xdd\ +\x0b\x00\x00\x10\xa0\xcf\x80\x00HD\x85\x95\x8a\x9c\x91\x08\x94\x80m\x11\xc6\ +\xb1\xd9\x95An\xb2:=\x17s\xc9\x18\xcb\x87\x85\x88S\x8c\xda\x96m[\x9e\xa7\x9c\ +v#\x0e"\xeay\xbe[\x9e\xac\x98Qhn(qw\xa7\xdfX\xbd5\xa2\xc64\xb7\x8e\xe5\xe2\ +\x8f\xc0\xfdH^/aQ\xb7\xd7\xde\xed\xb5w\xfb\x9d\x864\xf4&L\xfd\x03c\xcf\x8f\ +\x12\xee0\x1e\xd6\xd5\xe1 &\x8c\xb9q\x1eIv\x86U\'\x1d\xd7/Wf\xca\x95Y/x\x83w\ +\xb6<\x927J\xa4\x88\xa3\xd6z\xbf\xb1\x9a\xd9\xfb)\xe6\xc0\x05\x12\x92\xc4\ +\xf32bL\xda\x94\x10\x82\x8d\x0eJ\x08\xe7\x16\x8f\x03r\x81>\xa0\xb0l?\x8a\x99\ +\x0f1\xf89\xdb\xb6y\x1c\xa3\xc4\x1e\x93\xc5\xd0\xf5r9\xd7\xbb\xb90\xd1\xaf\ +\x86\x8b\x1f\x85\xf8\xb0<\xef\xe5\xcap\x04\xeeG\xf2\x1d\x10\xc1\xa2~\xaf\xd9\ +k\xd7\xa2n\x93\xc5=)\x06@oj\xe8\x993\xa3\xba\xbci>\x05\x03\xe8\x93\xe3aHwss\ +\x11Ji\x10\x16\xcb\x95\x99\xe2\xc4\xb4e\xdd\xd8\xab\xe1H\xde<2\\\xc5\x86\xf8\ +\xe8\xb7\x1f\x7f\xf9\xd2eP\x01\xde\x08 b\xa1P\xf8\xbe\xbf\xfa\x19\xd7\xbd\ +\xe9h\xfb(X\xaf~\xbd\xdf\\C9p\x04PDG\xc4\x07Vx\xbd\r\xaf\n\x9e\x07\x08\x96\ +\x05\xed\x9e\x10P\xa8T\xe7m\x87\x02X\x02m\x87\x92XR\xca\xbb\x8ec[~\xc8\xb8 <\ +\x8a\xa4m\x13\x91/\xe5\xfd\xfd]$\xc7\t\xeb7\xfa\x8d\x95\xb8\xbdu\x13\xb6\xab\ +q\x10\x0f\x00A~2_9v\xd4\xdc\x8f\xe4u\x17\xcb\xf1Bg*,N\x01\x80`Q\xd4oG\xddV\ +\xd4o\xc7\xfd6c\x11&k\xae3\x80\x0ec\x10\\\x1f\xa0\xd6\xd6\x07\xb7\x0c\xc2\ +\xc2\x0cv\x92r\xbd\xc0\xcf\x15\xc2\xe2D\x98/\xbb\xdeMw\xb3#y\xc3%1\x8c\xa3\ +\x94\x12\x11;\x9dN\xab\x95\xb2\xe5\xa0D)\xa5\x94\xb2\xdeht\xda\x1dJSd\x88\ +\x90\xb2\x90\x0f\'&&\xa2(\xde\xd9\xd9\x91(\x03?\xa8T&\x08!\xc4rr\x93\xa7\xfd\ +\xd2\xc2\xee\xc6\x95\xad\xf5\xeb\x04\xf9\xd4D@\tx6\xd1.4\x00\x00d\xa0RX\x04\ +\x84\x84\xd0\xb7\xfbqkw\xfbz\xb92o;\x94\x12F\x9c\x02\xed\xf7\xa8\xed\xf5\x85\ +t;5;(\xa0\x97\xb3\xfb}\x94\xb8\xbb\xd3\x9c\xac\x12\xef`.4Z\x1c\xbf\xe4\xf8%^\ +n\xa9\x18\x06\x07\\\xe0\xaaz\x87M\xc1\xa2C.\xbe\xd7\xda\xe9\xb5w\x8e\xc0\xfd\ +H\x0c\x15i\xe3Q\xdcx\x1c\xbbk 9x\x13t\xe2,=\xf9Y\xb0^K\xab\xa3\xe5x9\xc7\xcb\ +\x15&\x01\x00Q\n\x1e\xc7Q\x8f\xf5\xbb,\xee\xc5Q\x8f\xb3H\xf0X\x08\xae\xba4\ +\x8c\xf8\xc9$XO4\xdfB\x08\xb5,\xc7v<\xcf\x0b\xe1hF\xc5r\x82\xb0z\xbb_:\xd6o\xaeF\xcd5)\ +\xf7_-\x98T\x9dz\x96\xc2\xd1\xd4\xf5\xbbTT\xe7\x11Bp\xce\xc5\xe5/\x91\x97\ +\x7f\x17P\x82\xe9<80\'\x01\xee\xbc _\xfc\xcd\x8c\x0f\xd9\x91\xbc\xf5D!\xfb\ +\xa0U\xc4=\xf1\xf8\xcf\xc2\xc6\xb7\x86\xc8\xae\xa2mI\x8e\xab\xdf\x90O\xff<\ +\xb2\x9b\x88\x87uk\x99Q9a\x8c\xf5\xfb}.\xb4\xea:\x0c0\xc7\x18c\x8cq\xce\x85\ +\xe0\x9c15\xcfS\xea\n"r\xce\x93Q\x01r\xb9`nvvee\xb5V\xab\xa9\x01\xe3\xfa\xf2\ +r\xb9\\:~\xfc\x18\xc2\xc0\x80J\xa8\xe5\x15fJ\x0b\xf7\x15f\xee*\x14\xcb\x94\ +\x00!`Yj\xc9\xdb\xd0\xf0\x13\x0b\xa4\x94L\x14\xa0Q[\xdb\xd9Zw,\xb0,\xd2\xeb\ +\xf5l",?\xdfg\x10\x04\xd3n\xfe\x18\x8f\xea\xbc}I\xc4\xab\xdd\xfaF\xa7\xd9B\ +\xea\xb0\x987\x1a\xedN\xeb\xc6\x01\xce2b9~8y\xba|\xec=A\xf98\xb5\xbc\x83V \ +\x1c\x81\xfbw\xa5\x98\xd3\xde8\xea\xe3\xd5\xff\x082\x1e^N\xc2\x9dk\xdfr\xf9\ +\xca\x17q\xe7\xb97"\xa7G\xf2\x1d\x15=\xde\xf3\xeb_#\xeb\x0f\xa5\xae\x19\xeb\ +\xc2\xe4\xd2Wp\xfb\x99\xd75\'&\xb8\xc7q,\x85I=\x0f\x90\x96s\xae\xf0=\x8e\xe3\ +(\x8a8\x17\x00\xc0\x85P\xe7\xd5I\x163\x00 @fg\xa6\t\xc0\x95\xab\xd7\xe28n\ +\xb7;++k\xb33\xd3\xe5R\x91s\xa1\r<\xaa\x98^~\xaa8\x7f\xef\xe4\xe2=\xf9b\x05%\ +\x9a\xeb\xe1\x94\x1d_H$@+\x05\xe0\xd1\xce\xe6\xc6\x8aE\tg\x1dB\xa9\x94\xc2sI\ +D\xf3 \xdd\xa0x\x1a\x89#\xa2\x1aD\xd7E\xf7\n\x89w\x11\xb9m[\x82\xc5,6\xfa\ +\xda\x81\x85\xda^8yz\xe2\xd8{\xc2\xc9\xd3\x96}c3\x189\x02\xf7\xefB\xd1\xc8\ +\xaez\x0ek\\#\x8d\x97S\x1bYd~\x11A\xc4r\xeb\x99#\xaf\xd9\xb7\xb0\x983\xb9(\ +\x8ap\xe9\xcfSK\xc82nL"\x96\x9bO\xddT\xbc\xf2\x9b\xcdL&K2\xb5\x88\x94$9"\xfa\ +\x1e!\xc4 ?\xe9\xe6\xad4w\xc6\xf9\xe4de\xb2:\xb9\xb4\xb4\x14E\xd1\xca\xcaJ\ +\x14E\xa5RI&\xde8\xa3yp\xc3\xc9\x89\x85w\xce\x9c\xbaOyy\r]h\x12\x07-!\xa0\ +\x9c\xa7\x84\xd7\xb66\x96-b\xc5Q\x07\x90S\xc7\'\xc8,/d\xa4\x18\xe4f,\xaf\x84\ +(A\xb4\xfb\xf5\x97\xfb;\xe7\xfb\xad\x8dN\xb3\xd1\xdc\xad\x8f\xbe\xee\x80B,\'\ +(\x1f//\xbe;_\xbd\xdd\xb2]:n\x7f4\x15P)\x16G\xe0~\x18\x05%\x88\x08D\x04"\x1e\ +\xf7_\x1fnd~AD\xad\x13\xb1\xe6\xca@m\x1fj\xeb\xe9\xb6N\x08 bT\x7f\xfd:\xf3\ +\x91\xbc\xe1\xa2\x86|!\x84Rxe\x7fw\xd0\x12\x06{\x9d\x18A\x1d\x14\xf2\xc6\xad\ +\xd7u\xb0GC\xc6\xe2/\x12$\x04(\xa5\x84\xe8(B\x86F\x92\xccB\x84\x14\x00\xc8\ +\x19C\xc4\x99\xe9\xa9Z\xbd\xb1[\xab]\xb9\xb6\x14\x04\xc1Tu\x92\xb1\x1b\xb0\ +\xd8nP\xaa,\xdc=w\xea\xdd\xf9\xf2\xec\x00H\x13\x17IB@H\x12\x06\xb6\x03\x8d\ +\xad\xcd%\x82H\x00;\xcd\x9d\\\x18\n \x16p\xe2\xcfZv\xd9\xf1J\x00\x04\x81\xa0\ +\xe8\xb1\xd65\xde[f\xbd\x1dy0\x03\xe9^B,\xc7\xf2\x8a\xf5.\xddn"\x97@I\xa2\ +\x8c\x01\x10\x00.\xa1\x1b!\x17pdP=4\xa2\xdb\xb7\\\x7fT>\xf3K\x00\x83m?\x07\ +\xcb\x18\x06\xbf\x04P\xd2\xc5\x8fY\xf7\xfc\x83\xfd\x93\xd2\xd6*\x8e\x01\x825\ +\xec\xb7\xc34\xd1<\x89V\xa0\x14\xa5\xa3m\xa3\xdfzb\xd2t\x8a\xe3\x86\xdc\xdb|\ +xp\xb0\x92\'#\xca\x12S8\xfd\x9dl\x0f\xa3\xebz\x08\x00M\x84\x10B)M\x00n\x80\ +\xf5\x84\x10U.\x95O\xceyeb\xc2\xb6\xed\x17_Y\x98\xb4\'\x8bv\xce\xa3\xae5\xd0\x02\t\x1ci\xee\x87AL\xcb\x12c\x8c\ +\xb08H.\x0c\xb1\xd8P\xde1Q\xf6\xf7Q\xdeM\xd9.\x7f\xdc\xef\\\xa8\xb6\x1f\x1e\ +\xa4\x03\xa9\t\x81\xf0\xa6\xd9\x99\xbf\xeb\xd8G^\xe7\xdf\x15\xa2[\xc5f\xe9\ +\x13}\xf4\x16k_\xf2\xd9&\x05\x0e\x00\x92\xb8+\xa5\xd4\xb6m\x8d\x83\xfa\ +OH\xc0]5\t\xd7u\xdf\xa0\xc1>\x15[F\xe5{h2M\xf2\xacs5\xa0\x1c\r\xd1\xe75\xac\ +\xbf\xe6\xa3\x14\xb5\x9cB\xe5XX\x9e\xeb6\xb6\xda\xb5e\xdbjm\xae_\xa9V\x8f\ +\xcd\xcc-\xf4\xa3\xa8\xd3g\xf9\xbc3\x88\x82G|\nyl^\x94\xac\xad\xba\xb0\x8e\ +\xe9(\x10|\x97H\x891G.\xc1\xa2\xc4\xb6\xc0wH\x18X\x8eM8\xc7~_ \xe2\r\xb3|\ +\x04\xee\x87F\xc6,\xe8\xc8XS\x93_\xbc\xd1\x1e,\xba\xeb\xba\xae\xabf\xdf\x96e\ +1\xc6\x94\n\xaf/\x99\x9a\xda\x11-\xf3\x96\x17=\xe4k\x8aF\x87\xdbUMB\xcd\xf3\ +\x14\xa7\xf1\x866\x86!\xbekh\xd6\xe0\xaeo\xd2\x86V\xb3/\xa8\xdbL>\xe7\xf5h\ +\xd8\x94\xda\xf9\x89\xb9\xb0<\xd3mn\xf9\xbb\xcb\xbd\xd6V\xbb\xee\x83\x9f\'(e\ +\xcc\x06\xce\x0e\x94Hb\x83]!\xac=\xdc\xb1 \t\xf8%\x11\xf2>i\xf5 \xe6H)\x84\ +\xbeU\xc8Q!\xb1\x1f\tT\xf4\xfa\x01\xb2\xfc\xdd\x02\xee\x18\xb7\x90\xb5\x81\ +\xb5\xa1\xb7\x85\xac\x032\x06\xea\x10; ^\x19\xbc\t\xe2\xe4\xc1-\x00\xb9\x89\ +\x80m7\xf7v\xc1 n kC\x7f\x1b\xe2&\xf2\x1eP\x9b\xb8E\xe2W\xc1+\x11\xb7\x047\ +\x8a\x07\xa4]\xdd\x01@\x82\x03\x90\x99\x8f\xa5y\xf7}\xddfM5M\xeb\xec\xb6ms\ +\xce\x95\xbb\x98fl\\\xd7\xd5j\xfbaFv\xc4\xa8\x81q\x1b\xa2\x1aD\xbb*\xe2\x15q\ +B\x92\x9b\x06o\x82\xb8%\xb0\x8fv\xf3H\xb5\n\x05|&_\xa7I\x9b\xd7\x90\xaa\xbe\ +\xe5\x9c\x9ay\x1e\xd5\xd6\xf5\xd5\xb13W}R\xff\xbe~\x05!\x84\x86\xa5\x99\xb04\ +\xd3\xdc]__\xde\xb6\xec\xde`XR\xe4:!\x88`\x01\xcf\xfb\x16\x1d\xee\xa14\x18\ +\xb8,\x02\xd4\x86\xc0\x85\x9co\x95\xf36\xa0\x8c\xa2\xc4jz\xe0\xcc\xbee\xc1}\ +\x80\x83\xb5\xf3\xd0\xb8\x84\x8d\xcb\xb8\xfb\x12\xd6/@g\x15D?}#\x85\xa0J\xca\ +gH\xe5\x1e2q\x96N\xdeE&\xee|\xad\xde\x0e"\x92;\xcfc\xfde\xac\x9d\x87\x9dg\ +\xb1\xf1\nD\xb5\xd4\xc7\xb1|R\x0c\x8b\xc5\xc2-l\x14\xf7j2#\x84\xa8\xd5\xea\xadV+\x8ac)\xa5m\xdb\ +\xb9 \x98\x99\x99v]W\xe3\xbb\xe6\xaf\xb5\xda;\xaa\xea\xde2 "b?\x8a\xda\xadv\ +\xb7\xd7\x8b\xfa}\x9eL\x16]\xd7\xcd\x05A\xb1X\x08\xc3\x83:\xdd\x12 \x99a&\ +\x03\xee7Na\xdc\x83\xaf\xb9\xb8A\t\xc8\x8e\x94r\xe8\xd0\xa2&\xd8\x08\x12p\ +\xb7-\'B\xb0\xa8\xd1M\x11b\x8e\x12\x89\xe3P\xdf%1KB\xeb$\xbd\x19`?\xaa]\xcb[\ +\r\xdc\x070\xc1:r\xe5A\\{\x18W\xfe\x02:+\xea\x82I\\\x00\xe8\xb5\xfb\x12z\x9b\ +\xd8\xdb\xc4\xb5G\x00Q\xe6\x17\xc8\xc9\xef\xb3N\xff\r2y\xcf\xad\xbf\x1d\x11\ +\xe2\xa6X\xfe\x1a.\xff\x05\xac|\x15\xe2$8*\xd1\x1f\'\xc9\x86\xe8\xe3\xee9\ +\xac\x9d\x87\x8b l\x87.|\x82\x9c\xf84=\xfe\x19\xb0s\x03\x9a\xb0\xfe\x8a\xfc\ +\xd6?\x06\x00\x0b @\x0c\x08)\x99~\xe8\xaa\\ZmO.\xd1\xed\xa7`\xfb)\xa9oH\x17\ +\xdc\xfe\x81\xaf\x92\x89b\x92#B)\x85\xda\xb3\xd63?\x93\xbd9I\x10\x81\xe0\x9d\ +\x7f\x07\xa6\xde\xa5\x96q+\xee_>\xf7\xab\xd0x9\xf5\x08\xa4V\xbb\x90\xa9\xfb\ +\xec\x8f\xff\x16\xf1o\xb0S\x81\x86\x0f\x94L>\xff\xaf\xf1\xe2\xef\x18\xd7\xb2\ +Q\x10\xac\x0f~\xc1\xda\x17\xdcu\xfd\xcb\xe5\xaf\xe1\xea\x83\xb8\xf4\'\xd0]3k\ +&\x95a\xe4\xd8\xbc\x8c\xcdW\xe0\xf2\x1f\x08;\xa4\xc7?E\xcf<@\xe7?\xb4\x7f\ +\x86\x0f"*\x1b\x9dNgum}}}cssk\xb7\xb6\x1b\xc7\xd90&\xb9\\0==\xbd8??3;37;\xa3\ +\x1f\x14R\xbe\xf4\xd2K\x9dN7Y\xb8\x88R\xe2\xdc\xdc\xcc\xc9\x13\'\xc6\xaa\xa2\ +\xea`ee\xf5\xfa\xca\x8af\xa3\x11\xa5\xeb\xbaw\xbd\xfd\xac\xe7y\xea\xb6~\xbf\ +\x7f\xe5\xea\xb5\xeb\xcb+\xab\xabk\xddn\xd7L\xe3\x07\xbe\xff\xfb\x8e\x1d[\ +\x04\x03\xe3\x14\xf1R\xaf7\xce_\xb8h\xa8\xc6H)=y\xf2\xc4\xcc\xf4\xf4-T\x08\ +\xe7|yeukk{}cc{{\'\x9d\x07\x00\x00\xdb\xb6\xab\xd5\xc9\xf9\xb9\xb9\x99\xe9\ +\xa9\xb9\xb9\xd9\xd1d2N\x90\x83\xa2\x1aurS\x18\xfd\x1d\x9by8\x8e\xe3\xf8\x9e\ +\x14\xc2\xd8I\x92\x00\x02!\x04y\xb7\x17\x8b\xd0\xa39\x8f\x00\x82\x04`\x0c\ +\xb8D\xc7\xa6\xbe\r\x04\x04\xd7\xad&=\x1d\x1f;p\xbd5]!u\xafFD\xb9\xf2\r<\xff\ +o`\xfd[\xc30\xb6\x19\xcc\x1a\xba\x84\x1bW\x01\x80\x10\xec\xac\xe2\x0b\xff\ +\x17^\xfbc\xfa\x8e\x9f\xb4\xde\xf6\x9f\xdfj\x06\xbe\x8e/\xfe\x06\xac?\x94}]\ +\x16g\xd3\x83\x8d`r\xe9+\xb0\xf4\x15\xb9\xf8\tr\xcf\x8fc\xe5\x1e)%\n\xa4\xd4\ +\x01\x11\x83v\x86R\xa3\x7f\xa6D\x99\xb8N\xe6\x81\xce\x83\xfa\xd3\x0eQ{\xc2\'\ +$>\x10\x1b\x88\r\xc8\x07\xe3\x84\xe9{\xa3\x8e,\xcf\xbc_\xda%\x98\xfb^\xaa\ +\xc0=\xe5_?\xfc\x13k\xe7q\xf7%\x98\xfb\xc0>]h\x98\xa0\x94\xb2\xb5L\x97\xfe8U\ +Q\xc4H\x16\x80L\xdeM\x8e\x7ff/+\xf1\xd0jV\xbf(_\xfaM\xb8\xf6\x9f@\xd9\xa9F\ +\xc7\xc2\xd4\xe8\x05\x83\xf2\xf2\x8e|\xe5Kr\xe5/\xe9\x99\xcf\xdb\xf7\xfe$8\ +\x85}\xbe\xf5>\xc5\x81D;>\x7f\xe1\xe2\xb9s\x17\xb6\xb6\xb7\xf7\xd1\x1f\xbb\ +\xdd\xde\xd5\xab\xd7\xae^\xbd\x16\x86\xe1m\xa7O\xdds\xcf]\xa5b\x11\x11\xe3(~\ +\xf2\xc9g:i\xec\xbb\xa3s\xfb\xf1c\xc7\xcc\xad\x1e\xcc&\x87\x88W\xaf]{\xe6\ +\xd9\xe7\xcd\xecPj\x9d\x8c\x00\x04\x93\xf7h?nsh\ +\x14B\x88\xc1^E\xc3\xb4\t\x01)\xe4s\xcf\xbf\xf0\xf8\xe3O\x8a1{L\xc3\xb0o\x90\ +!\xbd\xa3G}\xce9\xe3l\xe4f\xd5(\xf6[\xff\xac{%"nmo\x7f\xf3\x9b\x0fonm\xefQ\ +\x1bi[\xcd\xe0\xda\xa0\x8fDQt\xe9\xf2+\x9dN\xfb\xb6\xd3\xa7\xe8\xe1\xdf\xee<\ +,\x14r\xf9\x1c\xd7\ +\xa1\x10B\xc8h\x8b\xb2,\xbbPY\xe0H\xa2\x9d\x8b\x80@\x00$\x12\xc6\xa9d\xfd\ +\x04$P"\xb8\x96$\xf6\x8dx\x99\xb4\x1c\xee\xf1\x10q\x087\xdd\xe3\x9fg\xe5\xbb\ +\x01\xf6@=u?Pf\x15c\xa7\xca\xac\x92\xee3\x83kd\xe4OD\xe8\xac\xca\x0b\xbf3\ +\xb6I\x99\xbd:\xee\xd6\xe1\xf1\xff\x85n?\x0eh\xd0b\x88\xc3\xff\xf4\x9f\x9amO\ +^c\xdc\x9c\xa4\xeb\x14\xbag\x7f\xba3\xf9\x91(\x8a\x06\x9b\t\x98iB\x06\x98\ +\x8c\xbd\x03t>\x11\x87\xcf`\xda\xba>p\xc4J\xc53`\x8c\xa7j#C\xa3\'\xdd\xd5\ +\xac\xf08\x8ews\xf7u\xfd3f\xda\xc6\xb3\xaa\xe0\x80\xab\xdfL9\xa8\xa4+Pc\x13]\ +\xfd:e\x8d\xc1\xe3\xa3\x90\x81\xc8f?\x8a\xd4\x1b}\\\x08\xc1Y,_\xf8\xf5\x01\ +\xb2\xa7\xaaed\xb0I\xe5p\xa4V\xf5\x83*\xf5k_\x96\x17\x0c\xeb\xee\x1eE\xd0\ +\xa5\xb8zm\xe9\xf1\'\x9f2\x90]\x7f\x82\x81v\xec8n>\x1fNLLT\'\'\xab\xd5J\xa52\ +Q\xc8\xe7\x1dGwu\xa2^-\x84x\xe1\xa5\xf3\xadvv\xa7M\xb9\x07\xb8\xab\xed5\xfa\ +\xfd~\xb2\xef\xc4\xb0\xa4\x8c\xc5\xcf<\xfb|\xbf\x9f\xd9\xfc\x16G\x8e\x87)\ +\x9biFQ\x14Ec6\x84C\x99\xcd\xc9\xd8\n\xa9\xd7\xeb\xdfx\xf0\xa1\x04\xd9\xc7\ +\xdcoYV\x98\xcb\x95K\xa5\xead\xa5Z\x9d\x9c\x9c\xac\x94JE\xdf\x1b\xf5\t\xc6\ +\xf5\x8d\xcd\xfap\x84xkJ\xb1<\x1dCn\xd0W\tz\x1e\xb5|\x9f:\x0e\xb5m\xe28\x8e\ +\xeb\x86>\x03\x18\xdf\x95\xf6\x92C\xaf\xb9k\x80\xe8\xdb\xf3\xcd\xd3?]y\xf9\ +\xff\x08Z/fyvB:\xee\xa9\x8ew\xa2\xed\x9f\xe9\xdb\xd3\x92zTD>_/\xf6\xce\x97\ +\xfb\xcf\xd9\xa2\xad\x92\x1b\xb0(\x1a\x8e\x01\x00@^\xf9\x8f\xf4\xcc\x03\xa4r\ +6\xf3jH\x90\x8e\xc5\x11\xbe\xf4\x1b\xd6\xfa\x83)\xec6\xe9\x11E\xa1\x8cQ!a\ +\xa0\xc2\x0f\x9eB\x00\x82V\xd0:\xf3\xe3\xbd\xe9O\xaa\xdd!i\x1c\x81\xe4\xa90\ +\x03YU\xdd\xf8\xc7\x04\xe5\xcc(E\x06\xd8\x01"\x86\xc1>\xc2\xc3I=I\xb6,\x18C\ +\xec\x00\x80Z!b\x14\x7f00p\xb1]\xfcH\xd8}iX.\xb3\xcf+\x95\xff\xea\x97\xe5]\ +\xff--\x9f\xc9hy\xe6\xdb\x19c\xf9\xdd\'R\xa3\xd10\xcf\x08\x08\xbcp\x9b,\xbeM\ +\xa7`N\x98\x18cb\xf9\x1b\xdeK\xbfb\x98\xe8\xf4$\xcc`o\x88\xddqN\xc4v\x89[E\ +\x00pD\xddg[A\xbc\x9c|\x97\x11\xa5\x1e\x11\x00\xc4K\xbfA\x8e}\x92\x16\x8e\ +\xc18\xd1\xfa)\xe7|\xb7V{\xe4[\x8f\x1a\xa4\xf6p\xfcF a.(\x16\x0b\xe5b1\x97\ +\x0b\x94ET\xaf\xbb\xe9t{\xf5z\xa3Vo\x98\xae#i\xb2~\x98\xe4(\xa4\xea:\xd4;A\ +\x9b\x12E\x0c 6\xeb\x81R\xe2\xfb\x81c\xdb\xb6\xe3\xb8\x8eC\x08\x11Rr\xcel{\ +\xc8\xb9\x9bi\xa6\x8d\x9f`\x12D{U\x88z\xbc\xdb\xed>\xfa\xd8\x13\xb5z]\x8fm\ +\xe6\x9d\x9e\xeb\x16\na\xa9T*\xe4C\xe5\x8c\x9b\xb83\x92~\xbf\xdfh6k\xf5\x86\ +\xa1\xef\xabo-4\xb39\xa6r\x0e\xbfX\x96]\x9e>\xbd\xb3\xf2B\xce\x05\x8b@\xcej\ +\xfa\x9e\xcf0\x90\x12)p\x0f[ Z\xe9^xc9\xac\xe0\x9eQ$\x15o\xdb\xa3S\xad\xf9\ +\x9f<\xbe\xf4\xf3\xb9\xfe%\r4={n}\xe2\xaf5\xc3wFvU?\x8b\x88\r|\xfbz\xfe\xa3\ +\xc5\xfe\xc5\xe3\xb5\xdf/\xf6\xcfg\xd5UHt\xed\xde\xba\\\x7f\x94L\xdc\x99\x81\ +\xa7\xe1&\x8d\x1bO\xfb\x97\xff]\xa2\x9e\xa7in}`RC:q\xfdg\x82\xd7\x08v\xfd\ +\xc4\x8f\xf6f>K\xb4\x95L\x02R\x87\x88\x08\xa9erG\x04\xc5\xbe\x14\rI\xee\'\ +\x00\x084\x19\x01\x10\xd1rQ9\xd9\x1a]\xd1\x96r\xa8\xfe\x8f&\x9b\x88^0\xa2|\ +\xe4\x11\xb1\x16\xbcc\xce*\xbb\xbc\x96-\xb5\xce\x0co\xe3\xdaCP>3\xfa\xed\x86\ +\xa6\xd4\xe65\xaf}.\xf5\xd4\xf0V\x02\x04\xa2\xd9OC8o\xbaW\xab\x9c3\xc6Xk\xcd\ +}\xee\x17@\n \xc9\xd4\'\xab\xf8\x93\xa6\x7f\xe7z\xe9\xb3m\xef\x14\xb7\x8aj\ +\xeb1"#\x9foU:O.4\xfe\xc8\xc2(!E\xd2\x1c\x0e"\xb4\xae\xcb\xe7\xff\x15\xb9\ +\xff\x7f\xdb\x87V\x12B\xf4z\xbdg\x9f{\xbe\xd31\x9d[\x06\xf7[\x94\xcc\xccLOV&\ +<\xcf\xcb\xf8\x86\xabJ(\xe4\xc3r\xa98;;\xbd\xbc\xb2\xba\xb9\xb9\xb5\x0f\xeb0\ +J\x86\x98\xa3\x0b\xe7\\Js\xd2`\x92~\x83?\'\xca\xa5Je\xc2\xf7\\\xdbq<\xd7\xf5\ +q\xe2Xe\xa2<\xba\xcc\xdd\x8cf\xc59wl\xfb\xe4\xf1c\xb9 \xb8\ +r\xf5\xda>\xf85\x8a\xaa&\xc1ml!\x9d!\xfd\x88e\xd1c\x0b\x0b\x95JYGL\xd4\x1f\ +\xd1u]\x15\xe813\xf0\xe8\x0f4\x9a\x0b\x93\xc6\xc9<\xa2\x90\xbdV\xab\x9f?\xff\ +\xb2q\xcf0\xe5\xf9\xb9\x99\xb9\xd9\x19\x1d\xc0\xc0\x1c\xa8Tm\xa8\xb2PJgg\xa6\ +\x82\xc0\x7f\xe5\xca\xd5~?\xc2\x81\xd9\xf9-.\xa2u\xb5\x10\x00\x00a\x1c\xb6\ +\x9b\xd8\x8d\xa4kwr.XVv\xeas@9\xdc\xe0NF\x04\x00"w\xee\xca\xcc\x8f\x9dY\xfb\ +\xa5npfe\xfe\xc7\xa8\x9b\x0b\x92\x08p`\xb4B=\x1e\x082\xb14\xf1Cg7\xbe@1\x1e2\ +\xd4d\x08\x16X;\x8f\x9du\x08gI\x12\x87HsAb\xebyg\xf7\t3Ccu\xdeFp\xd7J\xe5\ +\x81\xae{L\xd0\xc1\xa6\x01\x88\xd8\x0c\xdf\xb9Y\xfa\xd8t\xfb\x9b\x8b\xb5?\ +\xb0Dwk\xfeG\xba\x8b\x9f\xf3\x1cW9\xbd!\xa2m\xdb\xdc\t\xa3\xfc\x9d\x03\xef\ +\xc3\xe4\xd5\xae\xa8e\x8d\xa5$\xa5\x1fq\xa7\x12\xe5n\xd3\x0b\x0em\xdb\x06\ +\xcf\xb3s9\x11\x86\x90\xcb\x11{\xef%\x91\x19\x8c6\x8a\xa3D\x87\x84Ua\t\x18c\ +\x8d\xf0\xbe\xc5\xfa\x7fH\xf9\xd8df-\x9bO\xca\xf5G\xc9\xdc\xfb3*\xa7\x06\xf7\ +|\xe3\x99\x01:\x9b\xea\xf3 \x05\xe0\xf9\xdbI\xf9\x0e+\r\xee\x83\xb9Z{+\\\xfa\ +\xfd\xe1\xad&\x03\x86\x08\x00\xf5\xc2\xfb6g\x7f\x84\xbaE?yVc\x96\x92\xdd\xfc\ +\xf7xb\xebD\xed\xff#\xb8\xc7>8\xf5\xcbr\xf9k\xe4m\x7fk,\xf6q\xce\xbb\xdd\xee\ +\xa5\xcb\xafH\x99\xa1\x0b\x88eY\'\x8e/NOUm\xdbV\xf1\x1b2\x83\x93\xce\xc3\xc0\ +\xe9\x10\xb1:Y\x89\xa2hum\xe3f\xc9\x07\x1c\xd0\xf1\x19\xc0\x1d$B\x089q|qzjJ\ +\x0f0\x07\t\x14\x83I\xa2#2&cf\xa7`\x8c]\xbbv\xad\xd9j\x99yP2=]=~lQ\xbf\xd4\ +\xac\x10L\xdc"\xcc:\ts\xc1\xb1\xc5\x85W\xae\\\x13B\xbc\x85\t\x19%\xa2\xb7-\ +\xa2F\xc2,b\xde\'L@\xc4\xa0\xd6\x05\xd7\x86\xc0\x05\xc7V$\xe5M\xc8a\x05wb\ +\x84\n\x1a\x13\x84\xda9u\xf5\xd4?\xa5N\xe0\xf9%\xb3\x05\xab\xa7\x86j~\x1c\ +\x13B8\xe7\xad\xdc=m\xef\xf4\x80\x9cA\x1c\xf8\xaai\xb4j^\x95\x9d5+Q\xdf\xd00\ +*\xba\xd7\xff0\xc9Q\xd2\xf82\xd43\xc0v\xf1\xc3\xcb3\x7f\x0f\xed\xd0&\xc46\ +\xb4-)%@yk\xf2\xafS7\x1f\x88\xdd\xf6\xf1\x1f\xf6]\xcfu]\x15\xf2\x85\x10\xa2Z\ +\xb9*\xa3n\xf1B\x08;eW\x19\xf1\x8a!\xc4"\xa0x\x00H\xc0]%\xbb_T\x90\xd1\x8e<\ +\xc2\xbf\xeb\xf0\xaa\xb6!\x91\xbfX\x0b\xee\x9d\xe8==\xd6\x10\n\x84\x00\xc6\ +\xf8\xca\x97`\xee\xfd\xba\xf6Ld\'\x8d\x8bv\xb4n\xf0\xfb\xe9\x04\xa8\xcbf?f;\ +\xae96\xeb\xdd_\xc9\xd2\x7f\xb2{+\xa9\x9c\x0f\xc7f"h\xb0;\xfb\x80\x9b\xafjlU\ +\xaf\x1e8\xf91\xc6\x18\xe3\x9co\x14?9\xd9y\xac\x10]\x1ef@\x8d1\x03\xe1\xb8\ +\xf6\x10\x9cy\x00\x0c\'\x07\x13\xc8vwk\xcb++\xd9\x82\x03LU+\xf3\xf3s:8\x8f\ +\x0e\xabi>nfC5\xdd\xc9\xcaD\xab\xd5N[So\x19\xd4\x06O\xcdLO-\xcc\xcf\xeb\xb00\ +\x99.s\xb0x\xce\xd9\xa1k\xf4\x0e\xad\xb6w\xbb\xdd\xd5\xc1R\xa9\x94\x14\n\xf9\ +\xd3\'O\xe4r9\xd5\x14u\xc0"\xd3E\'S\'R\xcaB>\xacNV66\xb7n\xa9\x06\x0e\x91 k^\ +U\xb5\xac6Yu,p,\xe2\xd9\x10\x0b\x88\x186\xba\xe8X\x10x\xc4\xbd\x19\x88?\xac\ +\xe0\x0e\x896\xa9\x9a\xa9\x8an\xa80QY\x96,\xebDF=15w\xc5\xd1\xd3\xc1\x8e\xe9\ +\x88(\x9b\xfe\xd9b\xff\xbcJ8\xfb\xa6\xb8\x86\xbdMH\x03\x13c\x8c\xb77\n\xdb\ +\x0f\xe9\xdc\x0c\xa1\xd0\x98\xe07\xc3w\xac-\xfcw\x8e\x9b3\xe1)\x99G\xab\xf8\ +\xba\xb4\x1d~?\xf3<\xdf\xf7}\xdfW\xf1T\xd5yU\x1cU@\xa5\xbcs\xce\t!\x84\x9a\ +\xf3\x83\xf4\x9c\x95\x10\x00\xb0,+\x08\x02s\xd7\x02\x15\x05L\xc3\xdc\xd8\xda\ +\x84AthL\xad\xb7\x82\x14\xee\x9b\xb8\xa0j\x95\xd9\xe1V\xf1\xa3\xe5\xde\xb3)3\ +\x80\xa9\xc2#\xe2\xd6S\xc8\xfb\xc4\xd1\x9b\x03\x0e\xc1\xdd\xddz\xd0\x896\xc6\ +\x18\x8a\x01\x00@\xf8\xf3r\xee\xa3n\x82J\x90v\x8d\xcfm=\x02(\xb3/Mr\xdb)\xbe\ +\x9bT\xee\n\xfdPA\x89z\\[h\xa2(R\xe0\xc2\x00\xda\xdem\x85\xfee\x83\xdbI\x19\ +\x87\xb1~Q\xb6\x96h\xe9t\xc6\xc1\\\x8d\xee\xeb\x1b\x1bB\x0c\x1d\r\x11\x90\ +\x00\x04Ap\xf2\xc4\x89\\.\xa7\x03&\x9b\x00jRRq"\x90\xcc\xd5\xaa\xd5\xc9N\xb7\ +\'\xa5L\x9b"oJc\x1b\n\xa5\xe4\xf8\xf1E\x15\x94_\xab84\x11U3\x07\x08\xf1\xb8\ +\xdf\xd5\x8c\xda^\xaf7vvv\x8c\xcc\xa3\xea\xa9\xf3s\xb3\xc5bQE\x0c\xd6\x15\ +\x92\x99Lk\xe3\x99\xaa+u~\xa2\\j4\x9a\xfd(\x1a}\xf3\xad\xd5\xc9\x9bPxgC\xb2\ +\xc1\xda\x08.\x86\xe5\xb2(\x04\x14<\x9b0\x0e}\x8e\xe8VI\x10\x8a\xce\x1a\xc5\ +\x18\xb2:\xe4\x189\xc4\xe0\x0e\x89\x89\xcfq\x1cLxa\x15\xa7T+\x98\x03p\x8f\ +\xb7\xad\xfe.\x15]\xe0]\x88\x1a\x18\xd5e\xd4\x90QS\xb0\xbe\xe0\x91\xe0\\\x08\ +\xe9\xf7\xaf\x00(\x8c\x18\xd8\xf1L\xb7\x16\xecm\xe3\x88#0\xd4^\xa2\xbc=\xb4[\ +\x8e\xf0\xf5\x82\xe6v\xe6~\xd8\x0bKfHt\x9d\x82\x1e\x8dT\x18)\xdf\xf7\x15\x16\ +(XW\xed\xdb\xb6\xed\xc1@\x92\xb4{\x00\xa04Y\xb3:\xde\t\x07m\xdb\xce\xe7\xf3\ +\xe64\\\xe3\xbb\xde\x9bf\\m\x82Q\x16Hu\xe9\xc4\xf6\xa5\x07\x1b\x13\xdf\xbb\ +\xc1\x99\xae\xb3\x18\xb2\xa5TNL\x88o]\x93\xd7\xfe\x98\xdc\xf6\x83\x9a\xd7\ +\x1a,\xbd\x89\xda\xf9\xe6\xf3)dOA\x07\x0c\xd3\x85f\xba\xfa\xbb\xd8\xafAI\xd7n\xca\x9f\ +\xa4V\xab\'\x8f\xe9w\x93\xca\xc4D\xa52\xa1?hf\xc2d\xd6\x80\xa9\xd4\xab\x94\ +\xf3a.\x08\xfcN\xa7;\xa2,\xdf\n\x96U*\x95\x89r\xd9\x04w3\xf2\x17M\xefY\xb1\ +\x7fRj2;6\'\x9a\xa4b\x8c\xad\xad\xaf\x0ba.\x97%\x00X,\x14\x8f-.\x98\xa3]\x86\ +\xa72u&\xad\xd4\xab\xf3\xbe\xef\x95\xcb\xc5\x8d\xcdmD9R\'o\tA\xc9ZK`\xa8\xed\ +\x19\xa1\x04<\x07\\\xc7*\xcf\x9f\xb6\xdd\x9c\xe0\x0b\xad\xdaz\xdc^\xb7\xb0;T\ +\xc6\xc6\xc9!\x06wM;\x00\x80\nB\xad\x94\x11\x1d\x94\xdc\xed]q7\x9e\xb4\x1b/\ +\x92\xce5\xd2\xdf\x01\xde\x05\xde\x1d\xae`\x1c\xa7*&g\x8c\n#\x04\x08"\xeb\ +\xe0\x88\x7f\x0em_\x07\x99\xa8\xab\xa3M\r\xb1]\xbe\x1f&\xef\r\xfd\x9c\x198\ +\xd7\xa4\x17\xa5\x94\x9a\x00u]W)5$\xd9/F\rTB\x08\xd7u\xe38V^tB\x08\x92\xd6\ +\x8bM\xf3\xa3:o\xdbv.\x97\xd3L\x94\xee\xc6\xda\x10*G[P\xc6wsL\x9d\x0c\xea\ +\x9c\x1a[89\x8e\xc3\x18\xeb\xbb\x93\xbb\xf9\xf7\x84\xb5\xa5l\xaet\x9a2\xc6K_\ +\x84\xd3\x7f\x1d\xc1F\xc3XGZW\xdc\xce\x15\x03\xd9S\x8fK\xbb\x10\x9f\xfc\xbcg\ +Pj\xfaA\xc6\x18i\x9c\xb7X-y\x0b\x8e\xe6<\xbf\xf5\x17a\xfby\n|X\x00B\x94U\x12\ +\x11\xa5\x14(Q"J\x04\x9b\xd7\x8d\x0f\xa8\x94o\xc3y\x9451n&\x954l\x03\x8c\xb1\ +~\xbf_\xaf7\xd2_\x9fX\x965;;\x13\x04\x81\x9e\x87\x99\x1f\x02\x12,\xd3Z\xb3\ +\x89\xecJ\xf2a\xd8\xedt\xb5\xf7\x95N9\xfb\xc9\x0e \xf3\xb33a\x18\x9a\x90\xaa\ +\xb3\x91\xb6U\xed\x95\xb8\xf6\x10\x00cI4I\xdf1\x1c\xab\xe28\xde\xde\xd9\xd5W\ +\xf4\xa3\x93\x93\x95B\xa1\xa0*d\x94\x1eD\xc3\xb7\xd5\x1a\xb1\x9cK)\xf3\xf9p{\ +g\x87s2\x92\xf2[AX{\x15yOU.\xe3{\x0e\xe1\xb9\xf2\x82\xed\xe6\x00\xc0\xb2\xdd\ +\xf2\xd4q9\xb9\xd0\xdcYa\xed5\x8a\xbd=&wx\x88\xc1\x1d\x0c|\xd7\xde\xb2\x94R\ +\xc1\xfa\xf6\xb5\x7f\xef\xac}\x95v\x96Io=A\xea\xb4\xbf9\x8cp\xca\x19\xed/\ +\xadK\xa2\x88\xcd&\xa8\xc0=\xd7]"(\x8c\x94\xb3\x99\x13\xc5\xb7\x05a!\xb3\x99\ +\x91VRTR\xc4\xb0R\x9a\x03\x80Rm\x14E\xc39W\xcfr\xce\x87\x93h\r\xeb\xa6c\xb8\ +\xe2\xdc-\xea\xfb\xbe\xe9\x90@n\xb85\x81*\xc2@{\x1d\xeb^9\xacsM\xce$\x08e\ +\xd7\xf2\xf7O\xb5\x1f\xf1\xd9\xfa0\xb5\xb4`\xe3\x92\xac_"\xe5;L\x9b\x87S{\ +\xc2\xe6\xbbCd7)&\xc4\xb8\xfc\x0e2qV\xf7v\xd3\x8c\xc9\x18\xa3\xad+D\xf6\x8dR\ +g\x0bd\xc5[\x10m\xa6\xbe&"$\xb0ae\xec\xc6\xfa@\xeb\xa6zr#"\xec\xef`\xe2\x83(\ +\r\xd7\xacv\xa7\xd3\x8f2\x11\xa4\xc1u\xdd\xf9\xb9Y\xc5?\x98\xfb\x9c\x98\xd5\ +\xae\x001\x83\xf8z\xc8/\x16\xf2;;\xbb<\xf1T\xb9%_\x91As,O\x94\xf7\xd9qE\x1f\ +\x9b \x9b\x96\xe1\xa8\xbb\xbf)Uk<\xfd~?\xc3\xc9PJ\xcb\xa5\xe2\xe8\x16}f\x06\ +\xb4\xfd,C^)6\xd2\xf7|\x8b\xda\x1c\xe2\xa4h\x90>8\xc4\x82\x92\xf3\xf6u\x00 \ +\x00\\\x80\xdc\xc3\xe1\x91X\x8e_N\xad\xb7\xa0\xd4R\x10\xdf\xaeo\xc6\xadU\xe0\ +-\x9aL\xe6!\x99\x84\x1fnp\x87\xa4}$-\x838k\x7f\xe6]\xfcw\xb4\xf6\x02(\xff\ +\x87\x0c\xffk\xd6\x9c\t[\xc3\xfe\x0f\x00i\xd0T"\x18\x18\xb8\xac\x9a\xb2\x15\ +\xef\x0c\xe9\x8bq)\xd3\xfc\x82r%\xceXt\xb5\x83\x04&\x86Js\x82\x0c\x89\xb9X\ +\xdb\x00\xd5\x9fC\x95G\xf3m\xa6\xdan\xfc\x12B\xd5Pav\xa1Lw\xca\xca\xb0Q\xc00\ +\xb5\x11"\xdbdfL{F\xe4\x1fk\xbb\xa7|\xb6\x9e\x1a\x18\x0c\xe6\x1a\xfa\x9br\ +\xe5AZz\x9b\xd6\xbeew\xb3\xb0\xf3\x90a\xa80*\x91\x10\x00\xe03\x1f1\xe7\xefZC\ +T\x95\xef\xf7\xb7\xa8d\xa9\xcf4\x8a\xd7F+I\xdd\x90\xfa\xb8\xe3\xac\x0bf\xce\ +\x11\xb1_\xd3\x1f\xcb\x1cc:\x9d\x8e\x1cF\xec\x1a\x0c\x0b\xf90\x17\x86\xa1F\ +\xf6\xb1\x8c\x87:cn\xf8\xa9\x07\x0c\xce\xb9\xe7y\x94R\x10j\xd9\x0e\xdc\x92\ +\x17\xe0 \xfd\xc0\x0f\xd4\x8cPO\x11nH\xbf\xa4E7\x0b]@\xc8\xa0\xaa\xd9)\xe28\ +\x16\\dn\xb3,R.\x97M;\xeah6t\xd7 \x86C\x9a&$=\xcfu\\\'\x1a\xc4BxUS\x997\x9b\ +\xf0\xd6u\x141\x00 \x00\x17{.R\n\xca\xc7\xe8\xb8\xcd\x06(\xb5\x8a\x959\x9c\ +\x98\xed\xb6v:\xb5e\xc2\x1a\x94\x0c\xaa]"=\xf4\xe0\x8e\x89H\xd6%\xcf\xfc\xa2\ +u\xe9wA\xb2=1}\xb4\xdbg\xac\xa0$\xddt\x87\x1ct\xaao\xab\xa6LD\'\x95\xc2P\x08\ +\x00 \xf5\xac\xdc\xa4\x93X\x90L\xd46\x05\x92\x96\x9dQ\xabMeJ\x99\x10\x86z\r\ +\xd9\x83?\x01Pz\x1eI\xf6\xcd\x19\xab\xa6\xe1\xd8\xa8 \xc4\x98\x82g\xa8\x95q\ +\xfdP\xb3I\xaa\xc7r\xcew\xf3\xdf3\xd1}\xca\xc2\xfe\xf8\xbc\xa1\xc4\xeb_\xc5\ +\xdb\xfe\xa6\xa4\xa1\x022\xe8\xac\xf8\xed\x0b#U7\x10\x1e\x1c\x13s\x1fw\x8cR\ +\x98|\x8e\x10\x02D\x0f \xb5\x96x\xa4&n\x14OF\xd7X\x06\xfa3\xf7# \xef\xe9\xaa\ +KaY\x14\x8fB\xcc(\xc1=6wz\xd2i\x8e\x94\x8e\xe3\xc4ql\xdb\x19\x0b\xe7x\xa6\ +\xfb\x86B)u=\xd7N\x13\xdc7)Dc\xbaQ\x9dYZF\x8fv\x9cs\x89\xd2xVe\xc3*\x14\n\ +\xda\xac\xbdO6\xf4\x98\'\xa5\xd4\x15\xa2C\xceP\xdbk\x04w\x03\x8c\xe4D\xa7\x13\xd5q\xe3\xf1\x81%\xb9\ +\xb7\x9b\xdf\xfc\xb3\xc1y]\xe7I)\x90\xd8b\xfa\xfd\xa3\xc8\x9e\xaa\x7f\xe2$cv\ +\xfa-\x90\x8c\xe5D\xd3V\xe3h"H\x06\xe6\x8c\x98__\x8f\xd3\xc6mf\x1eFjz0\xc388\ +\xb2\xeb\xa1\xd7\xb4x\x9b\x1a\x88!\x07\xf9\xac\xa9{\x08\x01J^\xddf\xa7\xd9w\ +\xe2\xd8l\x98ub\xc4"\x1c\x18p\xd4\xe5\x837\xf2L\x85\x0c\xb8J\x04\xd8\x83\xf7\ +?\xa4\x82\xbc\xc7;k\xeaX\xa9\xedc\xc5\xf6\x8b^\xfe@\xa1\xa7Yg\xc3\xc3z)\x80r\ +\x0e\\\x07Z\xfdC\xa9\x1f\xbd\xcf\x00\x00 \x00IDAT\xcb\xb9\xeb\xc6\xc4\x18\ +\xe3\xb5\x97\xdd\xf3\xbf\t0\xc2\'\x98g\x00\x81\x90\xd8\x99\xeaz\'\xfb\xeellW\ +\x19\xcd\x0b\xe2!\x10\xb5\xfc\xbe\xd2}b\xa6\xfd`r\xb3\x16m\xdf\x1b\xbc\x14\ +\xcc\xe9\x02-&\xf7\xa7\xb4\xe5A\x06$\xa7\xfd\xcd\xfd\x89\xce[\xefu\xfaE@\x86\ +\x8e\x9b\xfb\x91\x0f\x07H-C\xe5+A\xcd\xd8ds>\xa2oZ[\xa5\xef\x9dj}\xc3\x13\ +\xbb\xa9[\xcd\xf9\xfc\xb5?\x14\xf3\x9faP&\xedk^\xef\x95\xd4\xcc\xc9\x80\xd4\ +\xa8z?T\xde\x911T\xe8jW\x07\xcc*!\xb5\x87+K\xb3$\x92\x19\xac\xcd\xa0\xe62\ +\xdcz\x16\xdf1uF\'\xc8\xba&\x93&\x93\xe0\x01\xb6e\xa5)\x02\x02\x00\xfd(:\xe8\ +l\xc9\xa8Lj\x08$-\xed\xe6%\xf3\xc6\x9b\xcb\xc6\x1e\t\x9a\xcd{\x0c\xbc\x9au\ +\x02@(!\xe9gAJ\xa9\xeb\xe4@\xafL\x0fxjT`\xd9\xb0h\x87\x9e\x93\x89\x9b\xd7\ +\x00%\x00H\xdc\x8fm\xcfM\x9c\xe0{5\xb2\xeb\x83f\xb3)D&\xc4\xe3\xadc\xf4\xab\xc5\xf7tb\x99\xbf\xb5S\ +\x80~\x97\xe3:\xd0K5?!Dk\x10j\xe6\x16%\x8a"]!o\x8d\x08b\xbc\xb3\xaa\xac\x83r\ +\x1f\xb6\x9d\x90\\\xe5@\xad\x08E\xc4Z\x03\x7fJD\xd0{\n\x1c>p\xcf\xa8\xedQ\ +\x14\xe5{\xca\xbd:\xbb\n_I#\xbco{\xe6\x01\xdb\xf6\xf4\xdak\x92\x80\xbb\xf6\ +\xcf%\x848\xb2=\x86\xd5\x81,\xfa\x98]\xa5\xef- \xb1\x01\xb3\xbb\xda\xeb\x14H\ +o\x03/\xfe.\xbc\xefg\xe1F\x1b\xfa\xdc\xb4\x0c\xd5\xe1\xc1\xff\xa9yF\xb4\xbd\ +\xf7\x93{\'\x88\x90\x19$\x00\xc6\x81\xfe\xe0\xf6\x81V\x95\xf1\x89\xec\xf8g\ +\x1a\xc1]\xa5\xfe\x8b\x00i=/\xc9\x9b\xbb\xf5P@+n\xb42\xccm\x9ac\x8e\xa6>BK\ +\xa7\xc6\xda*\xccWs\xab\x18;U\x9f\xaf\x0f\x07\xb9\xf4\xd7/u_,\xc8\x8d\xc8\ +\x1f\x1f\x8d}T\xa8\x8c$\xf5T\xfa\xf6H\xdc\x95\x8c\xc9D\x1dX\x16\r\xc3\\\xc6\ +\xd5\x9ds~}e\xe5\xe0\xe0nr}\x00 \xa5\xac\xd7\x9b\xa3\xb4\xcc\x81\x03\x8a\x0c\ ++\x02\xf7\xa0\xc8_\x85dU\xcc\xd1\x0f\x94\x0fC#\x14\xfb\xe0\xfe\x8d\x8dM\xb5@\ +\xe9\xd6\xde\xdah\xb6F\xf6\xb7\xba\xc5\xa9\xcc\x9bAP2\xde\x1e\xc4#\xe2|\xcf\ +\x92x\xf9i\xdb\xcb\x1f$A\xd6\xbc\x8a\x92\x03\x00\x10\xe0|\xe8us(\r\xaa\x86)\ +\x95\xc5ql\xb1\xdd\xf1\xf7\x11\x02\x844\xa7>\xe3\xe7\n\xb9\\.\x97\xcb\xe5\ +\xd3\x92\xcb\xe5\x82 p]\xd7\xb6\xadR\xff\\V\x01\x1f\xd0\x05\xa0z\x88\xa9[)\ +\x89\xbd\x85Vpg\xf6\x8d\xe61"\\\xf8\x1dq\xee\xb7\xf6\xda\x8dH\x89\\{H^\xff\ +\xf3[\xae\x8b\xec8D\x80t\xd7\xa1\xb7y\xd3\xe9\x8c\x15\x93\x8b\xcf^I\x99U\x07\ +~A\xb6\xbbY\xfaxr\xff\x98\t\x8d\xd5[-/\xfd6An\x189\x93;\x11$\r\xc4\xf4\x07\ +\xc6:x\x90\x11i\x07\xb7gk\xc0(\x8b\xcb6\xa7;\x0f\x05A\x10\x04A.-\xc1\x88L\ +\xb2\x0b\xa7\xd6\x7f\xad\x0c\x9b\xeaf\x1d\xe7G\xe3\xbb\x99\r\x00\xd0\x88\x9f\ +\xcb\x05\xd9\x92\x02\xac\xae\xae\x8d\xdbFuO1\xf1}w\xb7\xd6\xed\x99\xcf\x92$\ +\xd6\xcf\x01\xb1\xcc\x18\x84^{\x0b\xe4~\xa6#U!\xa5b\x81\x90\x94\x11\x02\x00\ +\xb6\xb6w\xae^[:\xf8kL\xbe4\x8a\xe2\xcd\xad\xed\xf4hw\x88\x91\x1d\x00X\xe2\ +\xdb.\x10\x84\x1c\xaf\xb6\x13j\x07\x13\xa7\x0e\x92\x9a\x8c[\xbc\xb3\x0e\x00\ +\x84(\xfa~X5\x87\x12\xdc\xcd\x95\x8a\x8c1\x82\xa3\xee\x8f\xc3\x0eo\x853a\x18\ +\x86ah\xc2z\x18\x86\xaa\x93\xabUs\xe5\xeesa\xff\xf2\xe0A2\x82e\x98\xd2\xda\ +\x88\xb1\x94nK\x03\xd9xe\x9f\x00\x01\xf9\xc4?\xe7\x8f\xfd\x1c6\xaf\x0c\xd3\ +\xd3\xa69\xc1\xc5+\x7f$\x1e\xfcI\xfe\xf5\x7f \xae}\xe5\xa6+"\xe5\xb4\x97\xd8\ +B\x81\x90h\x1b\x96or\xb4H\xd9c\r\x9dOy\x8c\xecK\xce\x8c\x84\x9a\xb9=\xb6+\ +\xa94u\xf6\x08\x01D*\xfb\xc3\x93)\x8f\x14\xe4\xc5;I\xe5\xae\xbd\\\t3\x86\xc7\ +\x9d\xd2\xc7\x98U2\x86a\xa3\xfe\x11\x81\x90\xc9\x8d?\x98j?\x9c\xdfCT\xab\xc8\ +\xe5re\xb92w\xfdW\x0b\xf5\x87\x17_\xf9\xd9\xe9\xd6\xd7\xc30\x17\x86\xa1\x8e\ +\x1f`\xae\xda7\x91]\xfd\x16\x0b\x05\xdb\xb23XS\xaf7\x1e{\xe2\xa911\x1e\xf6\ +\x10M\x0f\xf6\xa3\xe8\xca\xb5k\xc6n\xa8\xf8j\x80\xec\xb5\xd0\xdco\xfcxF\xe3\ +\xf1}/\x1f\xe62yf\x8c\x9d;\x7f!\xbd#\xeb\xde\xafL\x86:U\'\xcb\xcb+\xedvf\xa4\ +$\x07\xcc\xdb\x9bPPDC\'\x19\xbe\xa7q\xcc/-X\x8e\xbf\xc7\xc5\x94\xc4\x8dW\xf4\ +\xc8\xa7\xe6\x01Z\x0e1-\xa3I\x15\x03\x86\x0c\x98#\x833\x85\xde\x8b,\xf7\x01\ +\xa5\x82\x99\xde\x17jM\xbf\x94\xd2g\x1bS\xeb\xbfC \x1d\xd4ph\xb1LQ\x8a\x19|i\ +\x87w\xf7\xdc\xf9\x80\xad\xa9\xcb\x19\xaf\x0f\x9d\xa0<\xf7\x7f\xe3\xda\xc3d\ +\xfa=d\xe6{\xa0t\x1b8\x05d]\xac\x9d\xc3\x95\xaf\xc1\xf5?\x03\x11\x01\x80x\ +\xe4\x1f\x13\xcb\xa3\x8b\x1f;@\x1dX\x03\x83R\n\xfb\x8cc\xd6\x83\x17~UR\x9b\ +\xbe\xeds`\x19\x9bR\xb2\x8e\\\xfd&T\xdf\t\xde\xd4\x98TM\x0f\x19\xc0\xa1\xc9j\ +O\x9d~\xe8\xb3o\xba\xcdD\xee\xd4z\xf1\x13\xc7\xd5v"\x19|\x1f%\xf1\r\xfd\x1d-\ +7\x9e\xf9^\x1aT\xf6B\xf6L\xfd\xf7\xdc\x99\xed\xfc\x07\xe7\xea_\x1e&\x95r\x91\ +\x02 r\xe2\xf2\xaf\x04V\x14\x9f\xfa\xe1L\xe6\xb5\xd7\x8d\xb3\xf6\xe7\xe1\xc5\ +_\xb5\xfak\x00h\xf7\xd7\'.\xfe|\xd8\xbb\x14\xbf\xfd\'\x88_P\xe5\xcaL#\xcc\ +\xc5\n\x94\xd2 \xf0\'\xb31i\x11\x80\\|\xf9\xe5\xa9\xea\xe4;\xee\xb9{|\xdd\ +\xe9[\r\x0f\x1c\xce\xf9\xb9s\x17j\xf5\x06I\xf9\xa8\xdc\x02e>|\xf6Uk\xb8\x07z\ +\xdc\xec\x11\xb6m\x17\x8b\x85V\xbb\x93\x19\x96\x96\x97W\x9e~\xe6\xd9\xf7}\ +\xcf{\x0fb\x03\xd0\xbd{kk{iy99\x8d\x06\xac\xbf\xe6\x93\x92\xef\x90\xc4\x8d+\ +\xca\xb7\x9dK\x10r\x8fUK\xb6\x1f\x94\x16\x0f\x92\x1a\xefn\x8a~\r\x00\x08\x01\ +1\x92\xe0\xe1\x03w%z!\x89\x94\x92[%G\xd4\x86\xd7R|4\xe4\x97\xbf\x18\xcf\xdfO\ +\xe7\xdeo\xce\xaf\xd5X\'\x84\x08v\x1e\xae\\\xfcuW\x87\x84\x844\x1eA\xaas\x91\ +\xf4\x12$\xcb\xb2b+\xb7T\xf9[wl\xfc\xd2 \xf6\xac\x89\x8f\x86\xfa\x0e\x88X?\ +\x8f\xb5sp\xf9\x8b\xe0U\xc0\xf6\x81G\xd0\xdf\x02i\xe82\xfd\x1a\x7f\xf8\xa7\ +\xec\x0f\xfe\x12]\xf8\xc8hy\xcd.!,_P\xcf\xd2VS\xd3gF\x1f\xf76\xe5\xe3?\xc3\ +\xae|\t\xc2yby\x88\x12X\x17:\xd7\xb1\xbdl}\xea\xffE\xb7:\xbeZM\xdf\x15\x1d?k\ +_\xdf\x1b\xdd\xa55\xf3\xce\xb9\xdd\x08\xefc\xcd?ux\xb2\xe7u&}\xf3\xd80\x87\n\ +wZ,|\xca\x1fgJ\xd5\xb0\xaek^\xbdw\xb3\xf4\xf1\xc9\xf6#\xae\xa8\xa529H\x13\ +\x01\x81\xb0Fp\xee\xff\xf4v\x1f\x93\x8b\x9f\x96s\x1f\x05\xaf\x92\xcc\xf6\xeb\ +\xb0\xfe\xb0\xbd\xfag\xf6\xc6\xc3D\xf6\x00\x92\xf9\x19A\xf7\xfa\x1f8\x9dW\ +\xe4;\xfe\x072\xfb~\x8dY\xa6~\x9a\xc9\xc6\xc4Di\xb7V3\xd4m\x02\x00\x82\x8bG\ +\xbf\xfd\x18c\xec\xdd\xf7\xbdk\xaf\xaa\xd3$\xbb\x10\xa2\xd7\xeb=\xf5\xf4\xb3\ +K\xd7\x973\xc8>\xbc\xf9&\x14U\x92\xfa\xe7\xf5\x14s\xc4\xd5\x1f\xa5\\.\xed\ +\xee\xd6{\xfd\x94)\x02\x11\x9fy\xf6y\xd7\xf5\xee{\xd7;\xf7I\xd0\xd4\xdb666\ +\x9f~\xe6\xb9\xd1M\xba\xc7\xae\xcc>\x14"\xfa\xbb\xa2\xbb\x01\x00\x08\xc0\xf7\ +\x8e\x11\x16Vo\'\x07\xb0\xd2\xa1\x8c\xe3\xfa%H\xf4X6\xb2\xdf\xcc\xa1\x04ws\ +\xe2\x86\x88\xb1;\xe5\xf4j{\x81\x08\x89k\xde\x13?\rw\xfcWt\xfeC\xa4t\x06,\ +\x0fYW\xb6\xae\xd3\x9d\x97\xfc\x95\xaf\xdbk\x7f9\xe8\xdb0\xc2\x98\x03\x98\ +\x9a`\xa6ck\xe7\xeef\xfe\xde\xad\xf6\xfdS\xed\x87G\x00=\xfd\xa7\x12\xd1\x87\ +\xee\xea\xf8R\x11\x02\xbd-\xfe\xc8\xffd\x7f\xf8W\xe8\xcc{\xf7)>\xb7+\xb1=\ +\x19\xc81{D\xa4\xca.b\xdc|\x0c\x90\x0c\xf8l\x85wV\x00t\\\xbbA\x84\xd1\xa9\ +\x8f6\xd5\xee!\xaaNT=\x98>\x91\xb17\xdf\xf4\xef\x9c\xec<6L\\\x97qlV\x01\x00\ +\x91\x17\xef\xa4\xe1\xac5.\xd2\x96~\x9d9Q\xb0,+\xf2\xe6W\xca?pj\xe7\xb7\xc7\ +\xa4?\x8cA\xc6\xe9\xfa\x83t\xf3Q\x08\xfe\x15\xe6\x8f\x83\x9d\x07\xd6\x82\xf6\ +2D;\x03\xb7\xa2\xcc\xfa\x00D\xb2\xfb\x8c\xf5\xc8O\x92w\xfe#z\xfb\x0f\x13\x9a\ +\r\xd1\xa3\xf3\xa0\n\x9e\x0b\x82\xa9\xea\xe4\xeaZv\x87\x8a8f\xdf~\xec\x89\ +\xddZ\xfd\xae\xb3w\xce\xcd\xcdf\x8a\xa3\x91\x9d1v\xe5\xea\xd5\x17^8\xb7\xb9\ +\xa5\xd4\xffQ\x1eFY\xba\xdfp@\x1bO\x10\x8d\x8ev\xbe\xe7U*\xe5\x95\xd5\xf5\ +\xcc#\x9c\xf3G\xbf\xfd\xedN\xa7\xfd\xae{\xdf\x99\xcf\x8f1\x15\xeaIL\x1c\xc7\ +\x17.\xbe\xfc\xdc\xf3/\xf6R\x8e7\xdf\xb9A\xebu\x12\xd6\xbc\xa6\x0e\xa4\xdc3\ +\xd8\x80\x13L\xb8\xe1\xe4\xc1R[R\xdc}\xc6\x8e\xaa\xe5P\x82;\x18\xeeh\x88\xd8\ +\xf6\xef\x08\xbb\x17\xc6`\x90\xc6\x8e\xfe\x0e<\xfb\x05\xf9\xc2\xaf\x80?\x05v\ +\x08\xbc\x03\xbdm\x1b\x19\x98K\xa5M\xa0\xd9\x17\xce\xac\xf4VD\x9c{\xcb\x13?\ +\x14\xb0\xd5||5\x95T\x863\xc1\x11\x85#\x0b\xa6\x04\x10\xa1\xbd,\x1e\xf9i\xf8\ +\xc0\x17\xe8\xf4}c\xdfN\x08\x89\xbd\x99\xc8\x99\r\xe2\x95\xf1\xa9\x99\x13\ +\x17L\xb8\x15\xcdTPg\xbc&\xae]V\xc6[\x1d\xf6\xd42L|\x1f\xd6\x89\x93\xdb\xc9\ +\xdf_\xe9>E\x90\x8fB\xe7\xd8/%\xad0>\xfe\x83\xce\xde\xdb\x89\xe8\xc15\x13\ +\xd3f\xbb\xf0\xa10\xba<\xddzp$\xe54\x18\x89\x08:+\xa4\x93T\x9a9\xde\x8cU\x0b\ +\xa2\x1a>\xfe\xcf\xb0\xb3B\xdf\xfbOL\\\xa6\xe3BGLV*\x9dN\xb7\xd1le^*\xa5\xb8\ +p\xe1\xe2\xa5K\x97\x8f\x1f[=\ +\xb8\xa0\x9dFR\xe6\xa8\x94Z4T\xd6\x92\xfa\x104h\x04w\x0f\x11G\'e\x92\x15\xc9\ +{5\xb8\xa8\xee\xadL\xb5\xed\xdc\xd9\x97\xab?\xd6\xb3\xe7R\x13h\x92\x01\x914\ +\x8e`\xc2\x97@\x16\x7f\xb1\xf1\xb2\xf8\xc6?\xc4d\r\x9b\xc9l\xaa\xdf\x9d\xf2\ +\xc7\xba\xce|\xd6~h\xe4rx\xa0\xdf\x95\xa8\xe4*\xd8\xc7\xf8j\xddk\xd4\xd9[\ +\xc6vo\xcb\xb2\x84Sn\x05g\x87\xa5\xd3\xa3lf\xc0H\xea<\x9e\xfe\xf0\xa8\xf5r\ +\xec\x8b\xf4(\xa2w(\x15\xee\xe4\xe5\xa9\xffz7w_\xda\xf002Hg*$95v8\xc7\xe2i\ +\xbc\xff\x0b0{\xff^y\xb0\x8dP\x8e\x96ey\xae{lq>\xcc\xe5\x86\xc9\xa6?\t\x0c\ +\xd2E\x16s\xc6\xd8(P\x02 \x00\x86anvf\xda\x98\xbb\x10\xcc\xde\xf6FI\xba\x13\ +\xe9?\xd2\xdfEo\xc7\x91\xcb\x05\xc7\x16\xe6]g,w<\x18\xf6vvw_~\xf9\xd23\xcf>\ +\xf7\xf43\xcf\xbe\xf4\xd2\xf9\x95\xd5\xb5\x11dG\x00\x98(O\x14\x0b\xf9t\xabx3\ +\ry\x07\x10\xdeYG\xd6\x85\xfd\xd9vBs\x95S\x07I\re\xcc\x9a\x03\xd7R\xb9\x8fa\ +\xf6\x96\xb2\xfa\x06K\xc6e\x85X\xcef\xe9S\xbb\xe1{\xd5\xb5\xe1\xaf\xa1\x18\ +\x0e\xbd\xee\xcc\xe9n\xe2\xc1}\xbd\xf2\xb9\xed\xdc{\x07\x8fd\x94\xd64Ga*nj\ +\xff\x01\r1\xed\xdc\xd9\x0b\xd3?\xb1\x1b\xbc+;<$O\x0e\x95\xeb\x94\x0e\x0b\ +\xd9\x9b\xd5\xf9\x85\x8f\x9a\xe4\xb8i\xcb\xa5\x94rwj\xb9\xf2\x80\xa0\xfe\xf0\ +YS#\xceHz\x82"\xf7\x8aQ\x04\x06\x08\x1a\x83\xc1\xfe\x06U\x9d\xbdQ\xe5}\xab\ +\xf4\xf1\xbe3\x95\x86\xdaq\x0b\xc4\x10\x857\xc9\x8f\xff\r\xcb\x88h\xbf\xff\ +\x8b\xf4\xc6UzON\xe1V/O\xfe\xe8Z\xe1\x93\x98i\xd2\x9ak\xd2\xa3\xfe\xe0\xed&y\ +\x95\xcdU<\xfd\xe1\xe8=\xbf \'\xee\xc9\xac\xc0\x1c\xcd\x83\xb9)\x87\xefy\'N,\ +NV&\xf4\x88\xad_\x9f\xfc\x8e\xed\x83C\xd0\x0cs\xa1\x02D\xc3\x8b\x12o\xd9]\ +\xfd\xb5]\xc4dTC6M=\xb4k\x8dG5\x800\xcc\x9d8q\xcc\xf7=\xd8O\xd2\x9f#\x9b8)\ +\x14\xc2\x99\xe9\xaam\xdb\x88\xa3W\x0f\x87\xa0\xe4\xac=\xf0\xf9\xd9\'\xb4\ +\xaf_Z\xb0\x92}\x86\xf7\x17\xd6\xb8\xa6\xc3\xdf2\xb1g\xa5\x1c>ZF\xab\xb1\xa6\ +Q\x8b\xbb\x13\x97\xab\x7f\x8f\xef\xf8\xd3\x9d\x87\xb2\xe8lB^\xca\r\x06\x00@R\ +o\xa5\xf2C\xeb\xc5O\xce\xd4\x137s\xd5\x86L\xd2F\xdbf\x13\x93\x9an\xca\xdacG\ +\xdd\xd0\xf7\x8f_\x9a\xfa\xfb\xd5\xf6\xc3\x0b\xcd\xafxlk\x08\x19Y"\xc8\xa0SF\ +\xb8~Y8\x8dw\xff\xa4}\xea\xaf\xa1\xed@\xb2_\x8f\x1e\xc9\xb4\xd9\xaa^x\xdfe\ +\x11\x9f\xde\xf9\xb7\xb6\xec$/J\x05\xc31\x12\x1f\x8eR\x03\xb5},^g\xb4l\xb3\ +\x0e\xf7\xd5\xe5\xf7R\xde#o\xae\xed\xbf\xcdo\xa7\xb7\xae7K\x9d\xe43\x9a\xfe\ +\x18\xcd\xcf\xef\xcf\xc9@2\xc2!\xa2\xae|s\xdb\x13\x0e\x95k\xd5\x1f\xa9\x07\ +\xf7,4\xbe\\\x8c.\x0e\xbfrfn4\x96aO\n.\xecR\xe3\xd8\xdf\x16\'\x7f0(L[\t\x7f\ +\x85F\x04|\x9d\x07\xcb\xb2\xcc\x06\xa0\xee\xf4=\xef\xd8\xe2|\xa1\x90\xdf\xd8\ +\xd8J\xdcE\x12vn|\x8f\x1e*\xf8\xd3S\xd5\x99\x99)\x8bR\xce3\x91\x84!I\xe7\xe6\ +\xe4\xb5X\xc4\x84:\xe7\xfb|\x14Hb6(\x8d\xc7\xac\x930\x17\x9c>y|s{g{{\x8f\x95\ +\x86\xd9\x1c\xa6\xfe\x9c\xaaNNOU)%I\x17;\x94\xb4\x0co\xaf\xa8-\x01\x10@\xec\ +\xc1\xb6\x13\xcb\t\xca\x07ZM-Y\x87w\xd6\x01\x08\x10\xe4bO\xb5\x9dX\xee\xe1\ +\x03w0\xd4g\xd5\xc9\xd5^\\\xb1[\xbe2\xf5\xa3m\xef\xe4|\xf3\xcf}\xbe\x010\xd6\ +\xb0\x99\x08"\x10\xd2\xf1\xcf\xacU\x1f\xa8\x05\xef \x12-\xbd\x12\x8a\xc0\x10\ +\ru"\xc9\x12S\xb3)\xeb\xd8\xbff\xc68)n\x94>\xdd\x08\xee\x99j?Tm\x7f\xcb\x17\ +\xc6No\xc3\x03b\x8c\x1f\xc3\x87\xb9[\xed\xcf~\x1aO\x7f\xce\x9d\xbc\x9d"\xd0\ +\x11L\xd1l\x00cL\x08\xb1[\xfc@lW\x16\xeb\xff\xa1\xdc\x7f1\xd5\xdc\xb3\xd0l\\\ +\xe1}\xe5f\x9b\xaaO\x14\xa0\xf6\x0bTw\x8fN\x02P\x8c\x1f\x0f\xc6}\x11\xc3\'\ +\x92\xef\x84\xef\xabt\x1e\xa72\xcabk\x1a\xdf\xf9\xcc\x87\x9c\x1b\x05\x93\xd1\ +\xa2gN\x1a\xd6\x15\xb0\x12B8\'\xf5\xf0\xbe\xb6w\xdbd\xe7\xdbS\x9d\x87\xf2\ +\xd1U\x0223\xf7\x1a\xd4\x0c\x18s)B\x00\x91\xd9\x13\xf5\xf2\x87\xda\xd3\x9f\ +\xa2\x95\xbbrN\x0e\x0c8\x1b\xc55\xf5-p\x18\xfbw\x90\x01\xc5*T&\xca\xf90\xac7\ +\x1a\xb5Z\xa3\xd3\xed\xde\xb08\xc5bqz\xaaZ*\x15\t\x80\x82\xc5\xd1\xc9\xd7\ra\ +:=!C\x00\xa26\x13\xde\xff\xa9\xfdE\x15\xcbL\x13\x11\xc7\xce\xfc\xf4G\xc9\x8c\ +v\x00\xe0y\xde\xc2\xfc\\1\x9f\xdf\xdc\xde\xe9t\xba\x07\xccR\xb1\x90\x9f\x9a\ +\xaa\x96KED\x14B\x8cz\x82\n)\x0e\x05\xc4\xa3d\\\xed\xc8\xb1\x87O\x8b\x92\xbd\ +\xf6Z\x1a\x15\xd6\xb8\x02 \x01\x00\x8d02\xa3\x92\xab\x9c<\x94\xe0\x9eAv\x05\ +\xee\x88\xc8\x006J\x9f\xd9\t\xef\x9fn}\xad\xda}\xdc\xe5\xbb\x96\x8c\tp\x02R\ +\xb5S\xa4\xb6\x04GR?rgw\xca\x9fh\x94\xee\x97\xd4\xb7\xa4$DF\xee|-w/\xc2\xc0i\ +\x84\x12B-\xcb\xb2\xa8eY6\xc6P\x1c\x86\nQ@\x06\x00\x8e\xe3\x98\xd3v\xad_s\ +\xcec\xbax\xdd}`\xb5\xf4\xd9J\xfb\xf1\xc9\xde\x13\x01[\xb3e\x97\xca\x98\x80$\ +\xc0\x07~,\x08\x928\x92\xba\x82\x06\xb13\xd3.\xff\x95\xde\xcc\'\xbd\xd2|.\ +\x08\x9d\x91xL\xa3EV\xfd\xa7\x9d;{\xde\xbb\xad\xdc}f\xa6\xfd\x97\xb9\xe8\xba\ +\x051EFS\xa1\x10\t\x02A\xea"u\xc1\xf2q\xea\xdd\xe0O\x1a\x03\n!\x840w\xaa\x9e\ +\x7f7\x08\x8e\t\x88PB\xa8E)\xb5l\xdb\xb6!\x86\xd2\x1d\xe4F\xb0\x9bQ\xde\xd5\ +\x08\xd4,\xbew\xa3\xf7\xbd~\xbc\x86d\x18W\x11\xd4\x00B)\xa5\xc4&\x88\x85\x93\ +P}\xd7\r\xd5v\xfd\x160\xb0\xd5Dv\x95\x01\xce\xb9\xa0\x13\x1b\xf6\xa76\x0b\ +\x1f-\xf6\xcfM\xb7\x1f\n\xa3\xab\x0e\xb6\t2*cBp\xb0"\x01\x88\x04\x0b\xa9#\ +\x88\x1f9\xd3\xf5\xfc{\x9b\xe5\x0fB8\xe7y\xbe{\xa3\xdd62\x03|\xa6\r\xa8q\xd7\ +u\x9d\xe9\xa9\xeaTu\xb2\xd3\xe96\x9a\xcdN\xa7\xc79\x17R\xeaq\x85R\xe28N!\x9f\ +\xafV+\x85|\x9e&[\t\xaa\xc7\x8d\xb7\r\x0c\xb37\xc4\xc40\x17\x94\x8aE `QjY\ +\x94Zv\xe0\xfb\x8e{\x8bA\x8dT\xd9=\xcf-\x16\x0b\x04\x80RbY\xb6\xfa\xb8\xc5Ba\ +\x9f\nq]7\xf3]\x18cD\xcaR\xa9X*\x15\xdb\xed\xce\xf6\xeen\xb7\xdb\xd7\xb3.3\ +\x11J\xc9\xc0\xb5t\xaa:1Q\xb6(U\xc3\'!$\xcc\xe5\x84\x90T\xb51\xdb\xb6,+\x9f\ +\xcf\x1fD\x15x\xc3E\x07\x1b@\t|\x0f\xb5\xfd\x86{-i\x11\xff\x7f{\xef\xfe\x1b\ +\xd7q\xe6y?u\xae\xdd\xa7\xaf\xbc4u#u#%Y\xa2\xed\xc8\xb2\x13\xc7\xce&\x93\xcc\ +$c\xcf&\xeb\xcc\xcc\xee\xecb\x81\xc5\x02\xefO\x0b,\xf6\xcf\x19\x0c0x\xf1\x02\ +/\x06\x03\x0c2~\xd7\xef$\xefd\xc7\x8e\xb3\x13G\x8e-\xcb\x17I\xbeP\xb2l\x8a\ +\x92LR\x94\xd8$\xc5>};\x97\xaaz\xde\x1f\xaa\xbbX<}QK\xb6(\x92\xaa\x0f\x0c\ +\xa1\xdd\xacS\xa7\xaa\xfa\x9co=\xe7\xa9\xe7<\x15\xdce\xc1*\xc0=\xa6\n\xd3\ +\xcd\xa5r\xfbv\x9e\xb8\xcb+I:\xbe\xc5\r&.Gqo/\r\xff\xe5\xad\xa1?O\xc5\xcb^4\ +\x9f\x8eoY\xbcA\x00\xd1\xb0b\xb3\x18\xa4\x0eE\xa9\t\xee\x8e\x98\xa6i\xb5sgSJ\ +\xabC\xdf[\xcf\x7fWVeY\x96\xeb\xba"/\xa0x\x19\xbd\xb3\x19\xa2\x01\xb0\xd9/a\ +\x9a\xa6\x88\xa0\xe0\xdcdFa\xa5\xf8\'\xe5\xc2\x1f\x1b\xac\xe1\xb2\xb5tt+E\ +\x97-^\x07\xe0\x80\xc0\x8dTd\x8f6\xdd\t\xea\xee\x05wH\xa4!4\x8c\xeeQ\xde\x9d\ +\xbe y\xf30\xc3X\xcf}\xe7n\xf6\xdb&\xab\xa5\xe8r:\xba\xe5\xd2\xb2\x89\xedWH\ +\x0c\x07\xed<\xf7\x0e\x18\xc5c\xe9\xe1\xc3\xe9\xfc\xa8\xeb\xbaD\xc10\x8cf\ +\xfe\xe9\xeb\xee\t1a\x88:-%-b6\x9bM\xa5R\xa2\x97\x03\xfe("\x8cD\xdc\xe7\x0b{\ +\xfe\x8fD|\x8e8\xa9\xf8\xed\xd2\xe9t&\x93\xf1R^\x9f\xa5\xd4\xcesu\xbe\xe2$N\ +\x1d\x86a+\x84\x861\xceM\xdf<]\xf1\xbee`l\xd1\xf5t\xbc\x94\x8e\x97l\xb6n\x00\ +\x03\x04n8\x915\x12\xb8\xe3\x91\xbb\x9f;\xc3r1P\xae\xa3XJ6\xf9\xae\xcd\x90\ +\x13|\xa2\r\xe2\x02\x90\xd6k.\x97\xcd\xe5\xb2\xd0z\xeb\x12\xc5FE\xc2\x08\xb0\ +m[>\x8d\x89\xbe\x8b\xf1\x8fc\x8a(\xfd!-\x97\x0e1\xfa-2\x9b\xa696V\x1a\x1e\ +\x1e"\x848\x8e\x93N\xa7E\xea$\x91\xcfr\x90Q\xed\x1cO\xc30\n\xf9\xfc\x13\xc7\ +\xd3\x88h\xdb\xb6\xf8\xa5\xc4\xbd\xd0k\xceS\']\xb5\x9e\xf6/\xc2\xc5hp\xce\ +\xe3\x98\x06A\x10F\x91\x98\xc9\x08!\xb6m{^\xdaK\xa7\xc5\x8e\xaff{{E\x91Bj\ +\xdf\xde={\xf7\x8c\x99\xa6\xe9\xba\xaeH\x12\xe5y\xde}\xe5U~$lJ6\xc06=\xa8\ +\xab\x0c\xbc\xd7\x12\xc6J\x16\x13\xd6;\xbdEf\xe4(<\x94T\xe3[\x82\xfa\\\xac^I\ +ma\xe5\x88\x18\x9b\xfb+\xa9\xfd\x15\x00Pn\x03q`\xaa\x9d\x8d\x00\x00x{\xfbG)\ +\x9aB\xdd\xa4\xef\xb8\xd3\xa2TM\x15\xa9\x922J/\x8a"q{o8\x85\xad|\x84\xb9(}\ +\xa8\xa2\xd4\x908J\xac\x10\xb6v5\xea\xb6\x9f\xaa\xea\x0b\xc2\xf6n\xf1\xa6i\ +\xca;\x07\xadb\xe0\x14\x02\xef\x98\x1c\x10\x00\x90S\xa0\xe7y\xc4\xc9$d]\x1a\ +\xda\x88h\x18\x86\x14w\xf9R\x92\xd5;\xf0\xbc\x13\xa2,\xab\x8aIHT\x9b\xf0\x0f\ +\xa8\x13\x95\xab\xec1{_\x1a$*\x91\x17\x83*\xac\xe2\x1a\x90\x97\x01\xe7\x16\ +\xb3R\xb5\xd4\xde\x1a<\x93\x18|q\x94\xd3v%Ie\xbfg\x93H{7g\xd1\x86\xc4x\xaa\ +\x17\x80\xaat\x96E:\x0b\xcb\xf5gad\xb4\x1e\x05:^\x81\xf3\xd2\xe9\xce)-\xf1#\ +\x8ao\xd4\xebv\xf0\xf1T\xab\x95\xb7\x89e\xb5\xf4!q/t=\n\xda\x97\xa8Z\x8f\xfa\ +\xa3\xc8\tO\x8c[:\x9dR\x8f\xed\x1c\x13\xf1=\xa5T\\\xe4\x9csQ\xbfzK\xde\xef\ +\xbc\xb5\xc5\xc4\xfeM\xe1\x05\x15;rt-3\xf8^K\xb4~\x9bGU\x00 \x00q\xef\x85Y\'\ +S\xb2\xd3C\xb0\x13\x17T\xa1\xe3J\x92W\xb9eY\xeae$\xa4\n7\xafI&d\x0b\x00\xd4\ +\x8d\xe7\xd5\x8bO\xa8\x8f\xb4\xe0z\xb5A6@\xca\xb4\xf0H\xc8\tCu\xcb&|\x08\xf2\ +.\x92\xe1\x1f\x89\xbd\xea\x13g\x94\xcf\n\xa0\x18Jr>\xebt\x11@[\xdceD\x87\xa9\ +\xbc\xff)O-\xd2\xb1RJe\xf3\xd4\xee\x0f\xe2-\x81\xcdZ\xa3*\xbbt\x9a%:\xa2\xce\ +g\xfd\xdd \xbd.\x00YX\x15#!\xac\x89\xc1\x97W\x02\xc0\xa6iU]\xc6\x90\x8d\xb17\ +oo\xddG\xdfAI\x0f)\xc73q\x01\xa8\xbf\xbe\xfa\xc3%\xd6\'\x08!\xc2\xff \xb6(`\ +\x8c\'\xfc\xec\xb9\x0egHb$\x85\xa1\x03\x00j\xb2\xe2\x07\x982\x13\x17\x86\x98\ +\xf8\x13\xf7\xc2=\xf5\xbd\xebl\xa7\xdaO\t\x7fZb\xf4\xe4\x98\x88\tO\x15w\x19\ +\x8ds\xbf]\xdbzx\\\xa7\x8d\xd6{\xcb}v\xe4\xf0\x86\x8f\xf4\x0fX\x10 \xa7\x1b\ +\xe1\x8f\xd0s\xaa\x00\xc3\xf4FZ>\xe4\x1d)\xee\x02U\xfe\xa4jKqWWuT1\xb5\xd4\ +\xfc\xb4m\xa7\x9e\xaa\x05\xd2(\xb66\xc7\xed\xf6\xd1\xf7\xc4\xa5,\xd2U\xaaO\ +\x03\x9d\xb2\xab\xb6\xc7T\xde\xdd\x97O\x0c}\x8cw\xd8\xac\xec\x8a#"\xb9\xc0H6\ +\x9b\xd2\xc2\x0f`\xb4\x83\xe5\xc5\xf7"\xf0C\xd4\x00\xed\xb9Pu\xb0\x0c~#\x91\ +\xcd\x0f\xe6\x84\x10\xcb\xb2\xc4\x08\x80\xa2\xad\xb2#\xc2X\x96w\xf2\xfd\xca\ +\x90\x98<`\xf3\xe4\x9a\x98Y\x13\x93kb\xf0U;\xb1\xeb\xe0\xf7o\x92:\xc7t\xbd\ +\x00:\x7f}\xb5\xa9\xa2\xb5\xd2\xc8\x10\x87\x18\x86\xb1^\xa90\xa6\xbe\xb0\x03\ +\x84\x90|\xbe\x8b\xa7[*;\x00\x98\xa6)\xc4]\xeac\xd7\x8b\xf6\x9e\xa3\x9a\xb80\ +\x84\x16\xcb\x8b\xa1\xff\x03\x01\xd9l\xf1\xa8#\x9c\x98q;\x17K\xe4\x80\xc8\ +\xc9ULx\x8c11\xa4b\xf2\xeborm+b\xff\x86\xdcH\xaf\xd7\x8e\x1c\xb67,\xac\xec{B\ +\xab\xf3\xc8\x02\xb8\x97\xd9\x9e.L\xc8x\xca\x9d*\xee\x89{[\n\xa5\x0c\x9eI,\ +\xd9\xabf\xb2\xd9\x8e\xa1$m\xa7^\xc2\xc4\x03\xe5I\xbf\xff\xd3\xa8\xa0Z\xad]\ +\xbb6\xc7\x11\xbf\xf5\xf4\x93\xe2~\x90a\x03\xa2f\xf5\xf1\x1c6_\xd0\x89&\xa9\ +\x06W\xe2\x8c\t\xcbH\xde\x84\x9d"\xd2\xa9#\t\x83\x88(&\xb6\xa1x{\xe4\xb9\xd4\ +\xee\xf7\xbf\x91\xc4\xb9\xe6\x17\x16WVV\\\xd7=\xf9\xc4\t9\x03\x19\x86!\x03\ +\x16\x13G\xc9\x9b\xb9\xebL\xd6\xeb,\xbe\xef_\x9b\xbb\x0e\x00g\x9e9\r\x9b\'WY\ +\xa1\x18|1&\x97\xaf\\E\xc4}\xfb\xf6d=O\xb5\x9d\xe5\xc5 \xdb\xa0\xfe\xd0\xf2\ +\xb7\x1ep>Ce\xf7gU\xce\xd4\x9f>1\xb6\xaa\xbe\x9bm\xdf\xa0\xb4\xdc\xdbo\xedo\ +\x98z\xa9\x94\x9brS\x89!J\xfc\x88B\x8e\xa1}\x85\x0cr\xdd\xf6\xea\x8bza\xa8\ +\x0fs]}\x86\x9d\x95\x00\x804\xf0\xa5\x95\xa0*{\xe2vH\xfc\x16\xea\xf3\x01"\nq\ +\x97\xf7\xb2\x9c\x03\xee\xebQo\xeb\xe1\x91\xdfZ\xf9\x04\x88)v7\xdb\x07\xdfk\ +\x89\x06\xb4\xbe\x08\x00\xa4\xaf\x87\xc7\xb0R\xe9\xe2F:\xc9\x9d*\xee\xd0\xcd\ +p\x96vbW\x1f\x85zK\xcb{XX%\xa8\xec\xbc,\xcb\xab\xf6]\xe7\x05\xad\xbaY|\xdf?w\ +\xfe}\x00x\xe6\xf4\xd3\xf2\xf6^^.[\xb6\x95\xf1B\x8c\rI\xdf\xc1\xe2.\x90\x96\x82a\x18\xc2w,\ +\xaf\x9eN\xb5\x92w\xb5\xbc2\xa4\xb8\'\xd4M=\xa4\xd3@\xc0\xcd\xc8+U^\xd6\x9f_\ +\xfd\xe2\xec\xdb\xef\xb8\xae\xf3\xf2K?\x19\x1d\x19\x91\x95\xab\xfa\xd2\xd9\ +\x9e>\xb2\x9e\xe8\xaf*\x10\xb2\xd7W\xaf~\xf9\xee{\xe7\x1d\xc7\xf9\xd3\x1f\ +\xff\xf1\xe8\xe8HB\xc8\xe4m)\xeb\x97\xdfw\xf6\xbd\x7f\xf7;\x07\x81\xb7_\x1fL\ +\xdc\xd8\xea\x14\xd8\xbf~\xf9s\xc8\xca/_\xfe\xfc\xad\xb3o\xbb\xae\xfb\xef~\ +\xfag\xa3\xa3#\tE\xc0\xcd/\x01\xc8\x9fR\x8c\x86\xdaf\xe1\xfcQ\xbb\x90\x18|\ +\xf5z\xb8/\xbdH\xb4\xf6\xec\x1f\xfe\xb0\x7f\xdf\xbe?\xfe\xd1\x1f\x89(\xbd\ +\xc4E\xd2g`\xa5u\xef\xfb\xd5\x1b7\xe7\x13IT\x081&&\xc6m\xdb\xeel\x9bly\xa7\ +\xe9\xd0\xff\xb7\xeb\x83z\xc1t\xceI\x83W\x98\xb8P\xe5-\x99\xb0\xa2\xa0c\xc2K\ +\x9cBH\xf97\xd5\xbb\xad\x81\x05k\xb5\xfb\t-SO\'\x07\xb0\xd9l\xce\\\xf9\xbc\xdehl~\x82\'\xc5\ +b\xbe\xd4\x9e\xaa;{\x01\x1d?b\xd7\xcb{@z\xd5\xd9\xf9\xa7\xc1k#\xed\'\x1bu\ +\xb2\xef: \x89{A\xce+\xdfT\xef\xb6\x8c\xd8\xbf!>\xf41\xdb\xd3\x85\xf1\xc1\ +\xf6Z\xc2\xb8\xfd\x10\x80\xf7\xf0\xf0$\x17fw\x83\xb8\x0b\xd4{\xa6\x97\xa0@\ +\xef\x0b\xe2\xbe.\x14lo\xe2\xda\xf2!\xb6\xdf\x17\x17{m\x03\xc0\xd3ON\xaf\x94\ +W\xf2\xf9\xdc\xf4\xa9\'\xfa??\x0e~^\xd9\xa9\x99\xcbW\xae]\x9b+\x95J\xdf}~#\ +\xed;\xe7\xfc\xe9\xa7\xa6WVV\xc5I\xadv$Y\x9f\xb3<\xc0\xed\xaa6\x06\xdb\xa1{\ +\x1b\xe1(JlR\xffS\xf7\xa9V\x8a\xddSON/\x97Wr\xb9\xec\xb1c\x93"\x92G\x8es\xaf\ +\xdf\x17\x11\xe5R\xc7F\x03\x80HgT\x82\x07V\x079\xbdq\xce\xab\xd5\xda\xd9\xb7\ +\xdfi6\x9b\xe2\xd1\xa5\\^y\xe3\xcd\xdf~\xeb\xe9\xa7N\x9d<\x99N\xa7\xfa\x9cBV\ +\xc2\x18\xbbsg\xf9\xd2\xc7\x9f\x94\xcb\x89\x9d\xcd\xd14\xad\xa9\xc9I\xcf\xf3\ +zY\xa9_\xe7G\xec\xc57^\xe7\x83\xdd\x9b;B\xc7;a\x8de\x11\xb0(\xb4\xb8{!B\xdc\ +\xdc\xbe\xc1j+\xf3p\x1d\x00\x08\x81>\xc9\x06\xdc\xdc\xde\xcet\x92\xbbG\xdcU\ +\x1e\xea\xa5\xa0\xde\x93b\x8d\x88\xb2\x96\xe80\xc6\xc4\xa9\x87\x86\x8a\x7f\ +\xf5\x1f\xfeB\x86\x16|\xcd\xf6\xa8\xd6\x1f"\x86A8\xbf\xb0\x88\x9b[\x82\x88\ +\xc3CC\xff\xf1\x9b;\xe9=\x11\x13[{\x95\x8c\xb5\x1a\xfa\xa0\xef\xbbK+Xv\xa7X,\ +\xfc\xfb\xbfxE\x9dE\xa4d\xab\x0f\xe9\x89\x1a\xe4\xef"["\xdf\\\xff\xa6\x06D\ +\x9e\x88RZ\xad\xd6\xdey\xf7\xbd\xbbw\xd7\xc5\x19D\x81F\xa3y\xee\xbd\xf7\xaf_\ +\xbf\xf0xc\xbe\x00\x00 \x00IDATy\xf8\xf0\xa1\xc9\xa3G\x86\x86\x8a}*YZ\xba=w\ +\xe3\xc6\xdc\xb5\xb9F3\xe8H3@\xf6\xee\x1d;tp\xa2\xab\xbfb\x87\xb2\x0b\xba\ +\xd0\x0f\xe4\x91L\xed\xdb/\x14}t \xb3\x1d\x99|\x08@\xec9U\x10\xd3\xf6\x86\ +\x0ew~\xbf;\xc5}\x0bH\xe8\xbb\xf8R\x8a\xbb\xe0\x1b\xbc\x1bQYE\xe0b\x8f\x11\ +\xdcp\r\xa9\xb1.[#\x01B\x9bD\xf7\x13\x96{\xa7\xec\xdeW\xb5\xb2;r2\x93\xdf\ +\xa8\xe2\xde\xe7\xf0\xa4\xb8?\xe0t\xd3\xb3\x85R\xd9\xe38\xfe\xfc\xea\xd5\x85\ +\xc5E\xd5\x81 \xb9}\xe7\xce\xed;w>\xfdlf\xcfXi\xff\xfe}CCE\x11\xe3!\xc6-\x08\ +\xc2\xd5\xd5\xd5\xc5\xc5[\xabkw\x83@\xca\xfa\xa6\x1a\xf2\xf9\xdc\x93\xa7Nn\ +\xff\xc8\x10\x8ddSj\xdf\x9e;r\x18\xde\xd0\x91\x81j\xab\xddB\xdaDa\xb6\xf7\ +\xcfKcuI\xbd\xb9\x1b\xc4]\xde\xc6\xe5\xf2\xca\xfc\xc2\xc2\xc2\xc2"\x00\xe4\ +\xf3\xf9\xb1\xb1\xd2\xf4\xa9\x93j\x99\x0b\x17/\x01\xc0\xd4\xe4Q\xd7ug._)\x97\ +W\xc20t]\xb7T\x1a}r\xfa\x94\xf4\xcc\xde\xb3\xf0\x13\'\x8e\x8b\x95\xcc\x96\ +\x0c\xb5S)\t\x9f;\x00\xd4j\xb5\xf9\x85E\xc30D\xd0\x9e*F\xe5\xf2\xca\xec\xb5\ +\xb9r\xb9\xac6R\x16\x08\xc3p\xf6\xda\\\xb9\xbc\xe2\xfb>\x00\x8c\x8f\x1f\x98\ +\x9a<\x9a\xcb\xe5\x84f]\xfa\xf8\x13D\xb8\xb5\xb4\x04\x00\xbe\xef_\xb8\xf81\ +\x00\xda\xb6=y\xf4\x08\xe7\xbc\xcfI}\xdf\x9f\xbd6\xd7udz\xf5W\x16\x9e\x9a\ +\x9a\x9c\x18O&\xbeP\xfd\x12\x1b\xef(!r\xceo--\xcd\xcd\xdd\x10\xed/\x95J\x13\ +\x13\xe3\xf2py"B\xc8\xd4\xe4\xd1|>\xaf~?s\xf9J\xb3\x19\x0c\x0f\x15\xc7\xc6J\ +\xa2;7\xbf\x9aG\xc4\'N\x1c\x97\x81\x16\xea\xd9\xd5>\xce/,\xce\xcf\xcf//\x979\ +\xe2P\xb1p\xe8\xe0\x84\'S\xabo.\x1c\x86\xa1\xfc5\xc5P\x88.\xcb\x02\xf3\x0b\ +\x8b\xe5r\xd9u\xdd\xe9S\'\xe7\x17\x16\x17\x16\x16\xcb\xe5\xf2\x0b/\xbap\t\x00\xce\xf8\xf0\x82\xfc\x93_\xad\xbe\ +\xff\xc1\x87\x00\xb0\x7f\xdf\xbe\xc9\xa3G\xfa\x9c\xf4\xc2\xc5\x8f\xcf\xbf\ +\xffA\xe7I_\xfe\xd3\x1f\x8b(\xc3\xbe\xfd]\x9c\xb9|\xe5\x87\x7f\xf4\xfd\'\xa7\ +Ou\x1d\xfc\xb6\xc4\xb7\xd4\xf3\xec\xdb\xef\\\xfd\xe2K\xb5\xfd\x17.^\x9a>u\ +\xf2\x87\x7f\xf4}\xd9$q\xa2\xd1\xd1Q\xf1\xd6\xa5T\xdek\xd7\xe6\x16\x16o=\xf7\ +\xec\x99\xb1\xb1\x12\x00Tk\xf5\x8b\x97>\x01\x80\x13\xc7\x8f%B,ZO0\x9c\x8b\ +\x9f\xfe\xbd\xf3\x1f\xa8\xa3\xba\xb4t\xfb\xf2\x95\xab\xcf|\xebi\xb5\x9d\xa2\ +\xf0\xcc\xe5+\xe7\xdf\xff0\xd1\xbb\x8f.\\|\xf9O\x7f2::"\n///\xbfw\xfe\x83\ +\xf1\x03\xfb\x97\x97\xcb\xb2\xdag\x82P>\x91\xc8G\x96(\x8a\xb2\xd9\xcc\xd3ON\ +\x7f\xf1\xe5\xec\xea\xda\x9a\x8c\x18J\xb8V\xe4!\xea\xe0)j.5}\xe3\xa8l63}\xea\ +\x89\xd1\xd1\x11\xf5\x8d\x1e\xd0lohm\x11i\x00 \xf25\xde\x9f\x0b\xa5\x93\xb8z\ +\x13\xd5\xa4\xed=\xc3\x1f\x8f\xf6\xcaK\xb3\x83\xc5]\x15\x17JY\xa5\xe2\xe7r\ +\xd9\xa7\x9fz\xf2\x89\x13\xc7\t!KK\xb7\xdf\xff\xe0\xa3ryE\x88\xa3\xea\xb88\ +\xff\xfe\x87\xae\xe3<\xf7\xec\x99\xd1\x91aBH\xadV\xff\xf8\x93O\xfdj\xf5\x97\ +\xff\xdf\xaf\xff\xc3_\xfe\xb9Hlt\xcf\xc2\xaf\xbf\xf1\xdb?{\xe9\'\xae\xeb$\\\ +\x04\xad\xb5\xa3n\x8d<\xff~K\x83\x9e{\xf6Lit\x04\x08Y]]\xfb\xf8\x93O\x01\x81\ +qF)m6\x9ba\x18\x9e8~\xec\xe9\xa7\x9e\xcc\xe7sqL?\xbf\xfa\xc5\xfb\x1f|x\xf6\ +\xedwFGGR\xae\xfb\xf4S\xd3\x88\xb8\xbc\\\xbe\xb3\\\xcef\xb3\'\x8e\x1f#\x848\ +\x8eM:\x1e\xda\xe5y/^\xfa\xf8\xfd\x0f>\x02\x80\x13\xc7\x8f\x1d9|\x88\x18F\ +\xadV\xfb\xf8\x93O\xcb\xe5\x15\xd1_\xc7qT\x13\xf2\xfc\xfb\x1f\x8e\x8e\x8c\ +\xbc\xf8\xc2\xf3)\xd7\x8d\xa2\xe8\x93Og\xca++o\xfd\xfe\xed\x89\xf1\x03\x85B\ +\x97\r\xc0T\x17\xca\xd2\xed;K\xb7\xef\xec\xdf\xb7\xf7\xc4\x89\xe3)\xd7\x05Bn\ +\xdc\xb8y\xe5\xf3\xab3\x97\xaf8\x8e\xf3\xfcw\x9e\xdb4V\x8aA\x8d\xaarC2\xdef\ +\xa38l\x88\xbbxH\xe2\x9c\xbf{\xee\xfc\xe7W\xbf\x00\x80\xe3\xc7\xa7&\x0e\x1c`\ +\x8c\xf9\xd5\xea\xd5\xab_^\xfc\xf8\x93V\x0b\xdb\x1e\xad\x85\xc5\xc5\xb3o\xbf\ +#\xc6\xff\xe8\x91C\xf9|\xbeV\xaf\x7f\xfc\xf1\xa7W>\xbf\xfa\xfao\xde\xfc\xf7\ +\x7f\xf1s1\x14\x8cq\x00XX\xbc\x05\x8b\xb7FGG&\x8f\x1e\x89\xa2x\xfc\xc0~u`\ +\xa5\xf3\'\x8ec\xd34\x8e\x1e9\x94\xcdxw\x96W\xda9\xdc\xef\t\xc1\x8d\r\xbc\ +\x89j\xb1\x13B\xf6\x8c\x95\xa6&\x8f\x14\n\x05\x99\x9ba\xd78\xdcw1\xc8cZk\xed\ +\xd0\xdb\'GX\xaa0nX\xf7\xcew\xc6\xe3\x9a\xcc8\xc6\xfa\xbe\xe0\xeadF{U\xb2S\ +\xc5]\x15M\xc6\x98i\x1a?\xf9\xf1\x8f\x10Q\xbc\xe8L\x08\xd9\xb3g\xec\xb9\xe7\ +\xce\xfc\xcb\xeb\xbf\xb967\xf7\xc2w\xbf\xa3\xea\xb5\xe38\x7f\xf2\xc7?\x14)\ +\xf4D\xc9C\x87\x0f\xbe\xfe\xc6\x9b++\xab\x17.^\xfa\xde\x8b\xdfU=\x00\x9d\x85\ +\x0f\x1e\x9ax\xe3\x8d\xdf\xae\xac\xae\xce\\\xbe\xf2\xcc\xe9\xa7\xef\xd9N\xa1\ +,\xeb\xeb\x95\x8f?\xf9\x0c\x00\x9e\xff\xces\xc7\xa6&\xc5\x83\xf6\xbe\xbd{\ +\xf6\xed\xdb\x93\xcf\xe5\x1d\xc7f\x8cMM\x1e-\x95F\xc5+H\x94R\xc3 \xd3\xa7\ +\x9eXX\\\xbcukin\xee\xfa\xb1\xa9\xc9\xa3G\x0e\x8bP\x90;\xcb\xe5l\xc6;u\xf2\ +\x84|\xbfQ=\xa9\x8c\xc8\\_\xaf\x08e\x17\'%\x84\x18\x86\xb1w\xcf\xd8\xe1C\x87\ +\xfe\xe5\x8d\xdf\xac\xac\xac\x9e{\xef\xfdD\x7f\xb3\xd9\xec\x1f\xff\xe8\x07\ +\x8e\xe3\x88\xc2\xc3\xc3\xc3\xaf\xfe\xcf\xff\x17\x00\xe6\xe7\x17\xf3\xf9|W}\ +\xe1\x9cc\xfb\xd9e\xf2\xe8\x91\xef>\xffm1V\xa2\x83##\xc3\x7fx\xe7\xdc\xc5K\ +\x1f\x9f8>\xa5\xeey\xcf\x95_P5\xcc7\xe9\xfc\xbdF\xb5R\xf1\x85\xb2?\xff\x9d\ +\xe7&\x8f\x1e\x11\x82[,\x16\xc6J\xa3\xef\x9d\xffp\xbdR\x01\x00l;\xeb\xdf\xfe\ +\xc3\xbb\x00\xf0\xdd\xe7\xbf-\x86"\x8e\xe3t*\xf5\xe2\x0b\xcf\x87a8w\xfd\xc6g\ +3W\x9ez\xf2\x14\xe7\x9c\xb5\x97\xc7\x9f\x9c>\xf5\x9do?+\xe3\xacep^bN\x12-\ +\x19\x1e\x1e\xf2\xbc\xf4\xddu\x7f\xbdRi6\xbbJ\xbc\xe8T;\x10E\xcd.\xd06\xe1\ +\x0b\x85\xc2Xi\xf4\xc0\xfe}\xe9t:\x91\x9c\xb2\xff\x80h\x1e9\xb1\xff\x950\xb4\ +\xc5\x1b\xa4]\x7f0b\xb9\xe9\xc2@\xa9}\xe3\xcau\xb9X\xd4;\xfc\xd1\xe8\xff\x82\ +\xeb\xcev\xe4Iqg\x8c\t\xeb&\x8ec\x91\xa5(\x8a\xa2\xb1\xd2(\x00\x84a$\x9e\xa0\ +\xe5\xc3\xf8\xd1#\x87\xb2\xd9L\xa4`\x10\xf2\xd4\xf4)\x00\xb8\xf2\xf9Uql\xff\ +\xc2\xd3\xa7\x9e\x00\x80\xd9ks\x9d\xedi\xdd\xf0\xed\x1fF4/\x8e\xe3\xd9k\xd7\ +\x00`h\xa8x\xe8\xe0D\xdc\x86R:T,Z\x96)\x93\x97\xa5S)\xf1\'q\xae8\x8e\xf7\xee\ +\x19\x03\x00\xc6Z+xq\x1c\x0b\xd3\x12\xdba\x7f\x1b+\xaa\x9bOJ)\xbd67\x07\x00\ +\xc3CC\x87\x0f\x1d\xdc\xd4\x05\x83<\xf5\xe44\x00\xcc\xcd]\x97\xe7\x12\xc7\ +\x1e9|\x08\x11e\xc9T\xca\xdd\xbfo\x1f\x00\x04a\x17\xc1R\x05N|s\xea\xd4\x13r\ +\xfc\x05\x93G\x8f\x8c\x8c\x0c\x03\xc0\x97\xb3s\xa2\xfd\xadc\x95eR\xd1w)\x9a\ +\xed\x95\x8c\x9e)My;\x1d\x90\x1c\xd5\xc3\x87\x0e\xaa\xf9 \r\xc3\x98\ +81~`h\xa8\xe0&\x13\xd2&\xd7K%\xae\xeb\x0e\x0f\x0f\x1d9|\xe8\xc4\xb1\xc9\x03\ +\xfb\xf7\xa5R\xa9T*\x95\xc8\x97\xa9\xf5};\x834\xa0\r%\xb5o\x8fb\x99\xcdo\x90\ +\xf6\x82\x05k\xac\xbd\x7fr\x9fH\xf9T~_\xff\x17\\w\xaa\xe5\x0e\x1d\x0f\xc8\ +\xcdfp\xf3\xab\xaf\xee,\x97\xd7\xd7\xd7\xeb\xf5M\xdb\xdfDQ\xa4\xc6\xb4\x8c\ +\x8c\x8c\xc8\x80th\xbf[q\xa0\xfd\xdc=\xbf\xb002<\xdc\xa70\xe7\\\xbe\xa2r\xe7\ +\xce\xb2P.\xd9$\xbe\xf9\xedj\xf1Z9\xa5\xf4\xd6\xd2m\x008\xb0\x7f\xbf\x88\xa8\ +I\x18\xa7\xb2#++\xab\xf3\x0b\x0bw\xefV\x96\xcb\xe5\xcd\x05\xb8\x92\x97\xa3\ +\x15\x9a",t\xe1\x9dP\x1fM\xc4\n\'c\xac\xbc\xb2\n\x00\xfb\xf7\xef\xa3\xed\x08\ +q\xd2~]P\xf8\x19\xc2(\xbasg9\x97\xcb\xca\xfe\xe6\xf39\xd9_\xd2z\xf5\x91\xcb\ +\xd1\xee\x94\x18\xd9e\x00(\x8d\x8e\x98\x86!\x9f\x03H;\xf1\xd3\xc1\xf1\xf1\ +\xd5\xd5\xb5\xc5[\xb7\x8e\x1f\x9b\x945pe=\xb6\xa5\xa1\x1c\x01\x80\xb1v>\x96\ +\xcd\x1ev\x15\xd1Z\xce\xb9\x1c\xd5V \xbc\x92cg\xef\xdeV\x1aU\xcey\x1c\xc7b}8\ +\n\xa3\x7f}\xeb\xac\xac\x87\x00!\x04\xa28\x06\x80[K\xb7\xd5\xeb\xa4X,\x08\ +\x8b\x01\x15\xe4\xb0$\x12\xc8\x88\x0bC\xf4\xc2u\xdd\x92\xeb\x8e\x0c\x17\x19\ +\xe7A\x10\xd4\xeb\xcd \x0c)\xa5\x9c3\xe4\xadH\'\x83\x18\xc4 \x96i\xa6Rn6\x93\ +\xc9d<\x99\xfdX\xec" \xc4\xfd\x01\xf2\xc3h\x1e\t\xb1\x7f\x038\x07\x02\xbc\ +\xf7\x1b\xa4\xa6\x93\x19,\xb5/\xc6\x95\x96\xd5\xd8?R>U\xb8\xc7\xb6|;X\xdcA\ +\xb1\x1c\xc30\xfc\xcdo\xff\xb5^\xaf\xdb\xb6],\x16\x0e\x1f:(T\xef\xd3\xcf.C;\ +\xdf\x9e\xba\xa2e\xb4\xb7\xe9\x10\x8a\xb0Y\x8e[\x86d\x9f\xc2\x8aBq\xd5\x8b\ +\xc0\xdb\xa9eQ\x11wy\x94\xf8\x86t{\xcdZT~\xf9\xca\xd5O>\xfd\x0c\x00D\x172\ +\x19\x8f\x10\xb2\\^Y^.\x8b\xa3I+\xf5\xc7\xa6wL\x94\xa0\x9d\xe4I\xe5\xf3\x87\ +\\\t\xec\xeco3h\xa6\xd3\xa9\xcd\xcb}\x1b\x9e\x07Ji;\x10f\x93\xc0%J\xaac%\x87\ +K\x88\xaca\x18\x8c3\x00@\x8e\xea4\x99\xb0\xdc\xf9F\xec\xa3L\xb6\xd53\xf0Qv\ +\xa1\xfd\xa7M\xaf\xc8\xcb\xd6\xca\xd1\x88\xda\x9bBDq\xbc\xbc\\\x86\x1e\xb4\ +\x93E\xb3v\x95\xa0V+\x95\x9d\xb4\xf3\xae\x88\x18\x1b\xa2$\xd6\x97\xb9\xb1\ +\xc4\x04\xe0\xd8v\xa1\x1d\x11\xd4\x15y\xac\x9aP>\x95JIo\xbb\x96\xf5\xed\x0f\ +\x0b\xee\xd2f\x19\x00\x00\xfb\xbdA\x9a)\x1d\x87\x01~\xcd\xd8\xbf\xc9\xe3V\ +\xf0\x15\xa5\xd8s7\xed\xfc\x81{F\xca\xeflq\x87\xf6\x9d\xff\xc1\x87\x17\xea\ +\xf5\xfa\xd8X\xe9\xdb\xcf>c\xb6\xf7O0\x0cC\x88;\xdb\x9c!\xb2\xd9l\x8a\xb4\ +\x85mC\x189\xe72\x9a-\x9dJ\xa9Z\xdcY\x981\xd6h\x88\xd4N\xe0\xa57\x854Iq\xef4\ +\xa23\x9e\x07\x00\x8dFC\xcbF\xcd\xd5Z-\ +\x0cCuJ\x86\xb6jK\x97\xfa\xa6\xce*\xe6\xb60\xb4\xe5\x16t\x12\xcf\xf3\xd2\xe9\ +\xb4X\x17\x95\xbb;\xc9m\xfc\xe4Q\x9e\xe7%\x0e\x91\t\xee\xb5\xb2\xef\x08hc\ +\x99Gu }\xc3\x1f\r+]<8Hmq\xe5\xba\x8cM\x88Y\xcf{\xce\x1b><\x88\xef~G\x8a;\ +\xb6\xc3\x9c\xa5\xc5\xea86\x00\xc8\xfb\x16\x11\xc30\x14\xd1)\xd0\xe1/\xbesg\ +\xf9\x83\x0f/\x08\xbd\x13Z\xf9\xc5\x97\xb33\x97\xaf\x00\xc0\xe1C\x07\xf9\xe6\ +u\xbc\xce\xc2_\xce^\x9b\xb9\xfc9\x00\x1c:4\xd1i\x9a\xb5\xf5*\xf1\xbfx\xe4\ +\xf0\xa1L&\x13E\xd1\xff\xfe\xdd\xef\xc5\xd3\x80\x90\xbf\x0f?\xbax\xf5\x8b/\ +\xa5\x95W\xaf\xd7\x85\x01+\x8e\xba\xf9\xd5\xfc\xe2\xad%\x00\x10\x96\xbb\xd0\ +\x1aB\x0c\x00X\xbb\xbb.\xbc\x1c\x8a\xbeo\x9cTTx\xe0\xc0\xfe\xa1\xa1b\x14E\ +\xff\xfa\xd6\xd9 \x08\xe5I\xaf~1\xfb\xd9\xcc\x15\x008~lJ\x1c"\x07\xc7\xdc\ +\x9cY^\xd4\'\xbb\xd2\xf9[\xb4\xec\xf6\xf6\x0e\x9f\x7fx\xe7\xbdryE*l\xbd\xdex\ +\xe7\xdd\xf3q\x1c{\x9ew\xe8\xe0\x84\xe8\xd4\x9e\xb1\x12\x00|\xfa\xd9L\x14E\ +\xe2\x9b0\x8a\xce\x7f\xf0a\xbb\xf1r\xdc\xfa]\x00\xadQ=r\xc8q\xecD\x07\r\xc3\ +\x98\x9b\xbb!\xc3\xed\xc5E\x92J\xb9\xe2]\xaas\xef}\xa0\xa6p\xb9\xbb\xbe\xfe\ +\xc1\x87\x17\xfe\xf0\xee{\xeb\xeb\x15)\xdc\x00@\x80$\xccg9D\xaa\xbe[\xed\xcd\ +f\xa5Rg\xb3\xd9l6+>\xc8\x7fU\xb2\x9b\x91\xb2\xaezc\xb4\xb2\xef\x0c\x90\xcb\ +\xdd\x91\x18\xeb\xedB\x19,G\x18\x0b\xd7Y\xb3ue\xf6YG\x1d|[\xbe\x9d\xea\x96\ +\x91\x16\x9f\xf0\xd8\x1e?v\xec\xb3\x99\xcb\x9f\xcd\\\xa9\xd5\xea\x9e\x97\x0e\ +\xa3hi\xe9\xb6m\xdb\xc5Ba\xbdRI\xe8\xc4\xf0\xf0\xd0\xd5/\xbe\xbcq\xe3\xe6\ +\xf0\xc80r^\xad\xd5\xeb\xf5:\x00\x1c>t\xf0\xd8\xd4\xa4\\\x0c\xec_\xf8\xd0\ +\xc1\x89\xa9\xc9\xa3\xd0\xcd#\xdc\xd9N\xf1\xf9{/<\xff\xd6\xd9?\xac\xae\xae\ +\xfd\xe2\xd5\xd7\xc4\xfa\xad\xefW\xab\xd5*\x00\xa4\\\xf7\xf0\xe1\x83\x9f\x7f\ +~\xb5^o\xbcu\xf6\x0fB\x07\xd7+\xfe\xd2\xd2\xed#\x87\x0f]\xbfqS\xea\x8ba\x18{\ +\xc6J3\x97\xafDQ\xf4\xcf\xff\xeb\xf5l6[\xadV\xff\xec\xa5\x9f\xf4j\xc0\x8b/<\ +\xff\xfb\xb3\xef\xac\xae\xae\xfd?\xaf\xfd\xd3\xbe}{\xd5.L\x9f:\xb9\x7f\xdf^\ +\xd8p\xe5\x03(;\xb5b\xf2\xbd\x9b{\x93\xcdf\xa2(~\xfd7\xbf\x1d\x19\x19vl\x9b#\ +\xde\xb9\xb3\x0c\x00\xb6m?w\xa6\xf5^\x15"\x1e9r\xf8\xcer\xb9Z\xab\xbd\xfa?\ +\xffidx\x88#\xae\xad\xdd\x05\x80\x8c\xe7\xd5\x1b\x8d\xfe\xa7\xe8\x1c\xd5\x17\ +\xbf\xfb\xfc\xbb\xef\xbd/;(\x85\x8fM\x1d\x9d\x9a<:\ +\xc8\x1d\xa8\x96)\x14\xf2?\xfa\xe1\xf7?\xf9tfi\xe9\xf6\xe2\xe2-\xf1e6\x9b=\ +\xf9\xc4\xf1\x91\x91a\xce\xf9\xf7^\xfc\xee\xcc\xe5+\xcb\xe5\x95\xcbW\xae\x02\ +\x80\xe7y\xcf=\xfbL*\xe5^\xbfqS\x9a\xc8\xa2\x9e\'N\x1c\xff\xfc\xea\x17\xd5jM\ +\xb8\xb3\xbb\x9eTt!\xe3y/\xff\xe9\x9f|\xf2\xe9\xcc\x17_\xce\xca.d2\xde\xf4\ +\xa9\x93\x07\xda1?\xaa~\x11E_HGTOW\xa4~e2\x99\x1f\xfc\x9b\xd3\x97>\xfe\xe4V\ +\xfbD\x00P*\x8d\x9e:y\xa2X(Hs{\xff\xbe\xbd\xcf\x9dy\xe6\x93\xcff\xa2(\x12\ +\xce\x93Ri\xf4\xe4\x13\xc7\xaf|\xfe\xc5\x80\xe2\xaev\xb0T\x1a\x95\xa3*;x\xf0\ +\xe0\xf8\x89cSo\xfe\xef\xb7\xa0\xfd\xd0\x03\x00\x8e\xe3|\xf7;\xcf]\x9b\xbbq\ +\xf3\xab\xf9\xf5\xf5\xd6^\xe5\x8em\x8f\x8f\x1fx\xf2\xc9S\x8em\xb7\x9f\x9f6Y\ +\xe8}~e\xd2\x8e\x89\x84\xf6J2\xaak\x15\n\x89\xa3\xd4\xa9\xda\xb8\xcf\x84\xfe\ +\x9am\x02r\x1a\xb7\xfd\xe3\x94\xf6~\x83t\xe8\xd0 .\x14Z\xbf\xc3\xa3\x96-\xd2\ +\xe7!\xc0\xcd\xed\xb5R\xfd\x96\xe8U\x06\xba{\xb7\x1b\x88(\x82\xbeE@\xba\x9a%\ +\xaa\\^A\xc4|>\'\xec2\xf9\x8e\x8f0B\x7f\xfd/\xbf\x01\x80\x1f|\xff{\xe3\x07\ +\xf6\x13Bn\xddZb\x9c[\xa6Y(\xe4\xa5\x96\x89\xf57\xce\xf9\xffz\xfd\xcd^\x85\ +\x13\x8d\x11f\x97\xfc_a\xfb\xab\xbb\xc9\xf0\xcd\xfbn3\xc6\xee\xde]G\xc4L\xc6\ +K\xa7\xd3r\'eQ\xbe\xdeh4\xea\r\xd32\x0b\xf9\xbc\xd1\xde2\x8d\xb4\xb7\x1c\x13\ +af\xfb\xe1\x81\xdeZ\xaa\xdc@\xa4\ +\xed\xdaz\xbc\x03\x05\x90\xe9\x9d\xfd\xb1\x17;^\xdc\xa1\xfd\x9a{Wq\x97F\xa2j\ +xZ\xa6i\xdb\xb6\x14q\xa9t\xd2\xa6\x96B\xdf\xabp\xa7\xe8\xa8* \x85I\x1c\x92\ +\x90!9\x19\xa8\xb3H\xa7\xdf@\xd6\xa0\xca\x998Jh1\xe9p \x90\xcd\xebr"\xcfA\ +\xc2b\x15\x87$\xe6\'i\xfe\xab\xa2&\xeb\xe9<\x11\xb4\xcdvDt\x1cG\x18\xbc\x89\ +\'$\xf9\x03%\xe6\x1b\xe96I\xfc^\xaa\x11\xadV\x92\x18UU\xf1\xe5ht\x0e\x1dQ\ +\x1e8\xc8\xe6\xf7\xbc:\x87B\x96\x91\x95\xf4\t\x92\xd1hhc\x19Y$\xccv\xce\xbb\ +\x9b\xedN\xa6d\xa7\xbb\xec\xc0\x95\x80GU\xda\x90/d\xf4\x0c\x7f\xb4\xbda\'[\ +\xba\xdfv\xeeHq\x97\xa6+\xb4\xefd\xf9\x8c\x0f\x8a\xb8K\x1f\x88H\x12"\x0f7\ +\x15\xbdNh\x8a\xea\xfc\xedSX\x15\xf7>\x8d\x94\xea uD\xb5\x1c\xc9f\x17s\xd7.$\ +&\t\xdc\xbcx\xab\xd6\x908JN0Ry\xd5\x93\xf6\x9a\x9fTA\xef\xfc\xac~#\xfe\x15\ +\xeb\xab\xea)T\xc9\xee\x1c.9\x0e]{\xaa\x9e\x02;\xf2\x1c\x0c2\xaa\x9dC\xa7Z\ +\xe5F;\x9aE=<1\xc5\xca?\xa9\'\xd2h6@&\x83d\xfa\xe6k<2HeQeNf\xba\xe8\x9dFf\ +\xd0\xda\x12\xecHq\x07E\xdf\xa5\xb8\xc0\xe6uTB\x88\xf8R\xcb\xcd=@Swd(\xa4D\xb5\x16\x13w&\xb4\xd7B\xd5\x94\xb6\xa6\x92\xc7C\ +\xd58B\x88\x08\xfe\x1b\xb0\xf0\x03\xb76\xa1\xcb\xf2_\xf9\xbd*\xee]\xcf%;\xab\ +\xfe\xa9\xb3\x18Q\x02f:\x07\xe7\xc1\xba\x908J\xedK\xa2\xfd\x89\x13%&\xb0\xce\ +b\x0f\xdc\xa4\xfb\xaa\xf0~\x87B+\xbb&\x01\xf28\xb8\xf3\x11\xb2\x08\x00\x82\ +\x88w\xd5Nb\xda\xc5\xf1o\xdf{G\x0e\xe4\xcd;\x1f!m@\xff\xf0G\xd3)NX\xb2\x01\xd6\\E\xd6\ +\xda\xda\xac_\xf8\xe3\xc8\xe4 \xef@\xf5b7\x8b\xbb\x10e\xb3\x9d\xda\t\xdb\xa1\ +\x84\xbd\xcc\xf6\xc1\x0bk4\x9a\xc7\nN\x1b2f\xb1Wl\xbb\xe9fS\xb9\xbd\xf7\xae\ +\x0b\xb9\xcc\x11\xc6x\xcfUY;3j{\xc3\xdd\xfe2(\xbbY\xdcA\x89\xd9P\xa3\xf1zY\ +\xe2\xf7UX\xa3\xd1<>\xc4\xfeM\xb1\x91\x1ec=c\xdb\x07|k\x89\xd6nq\xe9m\xa7=\n\ +\x11#\xd3w\xf3\xebA\xd8\xcd\xe2.W\xf0:C\x0c\xbffa\x8dF\xf3\xf8\xc0#\xbf\x95i\ +\xbd\xf7\x8e\x1c\xb67H0\ +e\x7fv\xb3\xb8C\xb7\x90m\xe8\xad\xd7\xf7UX\xa3\xd1<&\xc4\xfeW"\xa5/e\xd8\xeb\ +%Ro\xe8\xf0`U\xdd@N\x01\x00\x11h\x8f\xed\x12\x0c\xcbM\x0f\r\xb4sS\x7fv\xb9\ +\xb8\xc3}\xaa\xb3\x96r\x8dF\xa3\xc2\x82\xbb,X\x03!\xc7\xb4\xbbC\xc6\xcd\xed\ +\x19$\xcd:\x8f\xeb\xb4\xde\xdar\xa0\xcf[K\xe9\xa1\x81v\xd1\xbb\';r\x9b=\x8dF\ +\xa3\xd9\x1aZ^\x14\xd2\xdaC\xa3\x13b\x98\xe9\x01\xcd\xf6\xcau@\xf16u\xbf]\ +\xf4\x06Z\x95\x1d\x00-\xee\x1a\x8dF\xd3\x1d\xd6,\xf3\xd0\x97\xfb_\xf70\xdb\ +\xf7\x99v\xfa\xdeU\x05wY\xb0\xda\xfa\xdc+\x98\x92\x90\xcc\xc8\xe4 \xab\xb2\ +\x83\xa0\xc5]\xa3\xd1h\xba\x82r\xff\xeb^\x8b\x9f\xc4t\x06\xf3\x8fc\xec\xb7\ +\xb7H\xed\xedmw2%+Ux\x90\x96vC\x8b\xbbF\xa3\xd1t\x81\xd6o\xf3\xb8.\xf6\xbf\ +\xeee\xb6\xa7\x8b\xe3\x83\xa4\x07\xa0\xf5\xdb<\xaa\xb6>\xf7t\xefX\x99\x91\ +\xc9\xaf\xd3\xe0\x04Z\xdc5\x1a\x8d&\t\xf28\xae\xb6\xcc\xf6\x98BW/\x8a\xe9dR\ +\xf9{\'\x1b@\x16\xc5\xfe\r\xf1\xb9O\xb2\x81\xf4\xd0!\xc3r\x1f\xb0\xb9\xdd\ +\xd0\xe2\xae\xd1h4Ib\xff\x06\xd2P\xac\xa3v\xdfH\x8f\x90l\xe9\xc4 \xbb#E\x95k\ +"\x91$\xb4\x93\rtb\xa7\x8b\xe9\xe2\xc4\xd7jq\x07Z\xdc5\x1a\x8df\x13\x9c6h\ +\xfd\x0e@\xeb\xad\xa5\xaer\xecx\xa3\x03\x85?\x86\x15\xd6X\x06\x00\x02@Y\x8f \ +\x19B\xbco\xd4!#\xd0\xe2\xae\xd1h4\x9b\x88\xfd\x9b"f\x91\xf6\xca\xfd2\xe8\ +\xeeH\x18\xb5\xd3\xc8p\xe8\x19o\x93\xca=\xe0v\x1c\xfd\xd1\xe2\xae\xd1h4\x1bl\ +$\x1b\x80\x9e\xa9}S\xf9\xfd\x03\xed\xb5\xd4(\xf3\xa8\x02\xc2l\xa7\xd0k\x1du\ +\xc00\xf9\xfbE\x8b\xbbF\xa3\xd1l\x10\xfb7\xc5\xfai\xcf\xdc/\x84\xa4\x06I\xb3\ +\x8e,j\x87?\xf2\xdea\xf2\xe9\xa1C\x83l\xee\xf1\x00hq\xd7h4\x9a\x16,\\g\xc1]\ +\x00\xc0\xde^\x14;=4\x88\xd9\x1e\xd7\x16\x91\xb6\x93\xb63\xe8:M\x98\x8e7\xd8\ +\xe6\x1e\x0f\x82\x16w\x8dF\xa3i!3\xad\xf71\xdb\x07\xf1\xb6#\x0biu\x1e\x00\ +\x08\x00\xe7\xd0=\xde\x06\xc0\x1b\xfeZ\xdbq\xf4G\x8b\xbbF\xa3\xd1\x00\x00\ +\xd0\xc6\xb2x\xd5H\xbc\xb5\xd4\xb5\x8c\x9b\xdd3\xc8\xe2g\xec\xdfle\x7f\x04\ +\x88{\xc5\xdbdF\x9d\xcc\xc8\xd7ip\x7f\xb4\xb8k4\x1a\r\x00\xa0\xb0\xb5\x01\ +\x802\xe8\xbac\xf5\x809\xc2x\\\xa3\x8d\xdb \xd6Q9|\xbdx\x9b\x07g\xf7\xa7\xfc\ +\xd5h4\x9a{\xd2J6\x00\xc0{\'\x1bp\xf3\xfbM;\xd5\xaf\x12\xca(e\xdc\xbfA\x90\ +\x03\x10\xec\x13oS8`:\x99o\xa0\xdd\xbd\xd1\xe2\xae\xd1h\x1e{\x90\xc9d\x03\ +\x94u\xdf"\x95\x98\x8eW\xec\x99#\x8cQ\x1a\x06QH\t\x89W\x9ch\x15\x81\x10\x80\ +\x98A\xf7\xa4\xed\x84\x0c\x92\xb7\xe0k\xa2\xdd2\x1a\x8d\xe6q\'\xae-"\r\x01\ +\x80c\x8fd\x03\x00\xe9\xe2\x041\xed\xae\x87s\xc6\xd7\xcb\xe5 lzi\xf4\xe0\x0e\ + \'}\xc3\x1f\x9dL\xa9\xff\x13\xc07\x82\x16w\x8dF\xf3X\x83\x9c\xd2\xda\xa2\ +\xf8\x1c\xd3\xee1\x8b\x86\x9d\xea\x13\xdb\xde\xa8\xd5\xd6\xca\xcb<\xa0f|\x97\ +\x06>\x10\x03D\xf8c\x8f\xcd=\xbc\xaf\xbd\xf9\xf5 h\xb7\x8cF\xa3y\xac\x89\xab\ +\xf3\xc8b\x00`\x1c\x19\xefnkg\x86\'\xfb\xe4\x08C\xc0\xc2\xd0(\xd2 \\\x9f\'\ +\xc4 \x00\xacw\xf8c\xaa0\xb1\x05f;h\xcb]\xa3\xd1<\xce \x0bi}\t\xda1\x8b]\xcb\ +X\xa9\xbc\x93-\xf5\xa9\xc42\xadT~\xc4\xb5j\x04C\xb1\x8e\xda+\xfc\xd1\xb0S\ +\xdfx\xf6\xc7\x9e\xad\xda\x9a\xd3h4\x1a\xcd6$\xf6o\x02\xa7\xad-R{\xeck\xda?f\ +\xb1Y\xab\x87\x11\x02\xad8\xb8\x06`\x12\x00\xca\xb0\xd7\x16\xa9\xfd\x9f\x00\ +\xbeY\xb4\xb8k4\x9a\xc7\x14N\x1b\xb4\xb1\x0cb\xeb\xbb\x1e1\x8bN\xa6d\xa7\x87\ +z\xd5\x10\x06a\xa3\x11"\x18._!\x18#\x98\x1c!\xee\xb1\x1d\x87\x9d\x1e\xea\xff\ +\x04\xf0\xcd\xa2\xc5]\xa3\xd1<\xa6\xc4\x95\x1b\x80\x1c\x080\x8a\xbdb\x16\xd3\ +C\x87\xba\x1f\x8cP\xaf\xd5\xe3(\xe6`:F\xd3\x8c\xca\x08\x06!\x10Sd\x8c\x13\ +\xb1.K\xc8Fv\x01B\xbc\x91\xadXG\x95hq\xd7h4\x8f#<\xf2Y\xb0\n\xad\x1d\xab{$\ +\x1b\xc8\xed\xb3\xdcl\x97? \xd4k\xf5\xa0\x19\x12\xd36\rfE\x8b\x04\x11\x89!^\ +\x80\xb2\xd3\x05;]4\x80\xc7a5\x0e|\xa1\xf3nn\xef\xc3H\xda\xde\x07-\xee\x1a\ +\x8d\xe6q$\xf2o\x88$\x03\xb4\x87\xd9N\x0c\xcb\xeba\xb6W+~\x18\xc6\x86esF\x1d\ +R!\xac\x82\xc4$\x00\xf5\x80\xbb\xf9\x83\xf9=\x93\x00\x040L\x03m\xac|\xd5\xac\ +\xdc&\x96\xe3\r=\xdcd\x03\x9d\xe8h\x19\x8dF\xf3\xd8\xc1\x82\xbb@kG\xd6(\xb6\ +\xdd-u\xbbkq\xd7h4\x8f\x11qu\x1e\x11\t@L\xbb\x9b\xedV\xaa\xe0dF\xe5\xff"\xe7\ +\xfe\xba\x1f3b\x1a\x18sp,0\x90E\x9c\xdaP!\x06\x00\x10\xcaXH\xcd\xfc\xc8d\x14\ +\x134m\'\x9d\xe6\x8c\x8bC\xdbU\x80i\x99\xa6\xbd\xd5b\xab\xc5]\xa3\xd1<.\xd0f\ +\x996W\x08\x00\xed\x95#\xcc03\xa3\xc76\xca\xc7q\xbd\xda\x88)\x02p4L\xd7"4hR\ +\x00\xdbA\x88\x1a\x04\x00\x91S\x92\xf7\x8a{\x83\x08\x18gn\xcaK\xb9V\xadQg\ +\x8c\x03\xe7\xad*\rc\xa4T2\x8c\xad^\xe0\xd4\xe2\xae\xd1h\x1e\x0f\x90\xc5\x95\ +\x1b\x00\xd0o\x83\xa4\xfc~\xf9\xd6R\x14\x84\xd5J\x8d\x986!`\x98\x8em\xf2\xb0\ +Q3m7?\\\\\x9b\xff(c! \x82=b\x18{\x1a!g,v\xbd\xbc\xe3Xa}\x1dXL\x0c\xe2\xa4\ +\xd2\x04\xc0yg\xfe\x95\x00\x00\x1cPIDATq\xdcl>\xe78[\x1d\x07\tZ\xdc5\x1a\xcd\ +cB\\\xbf\xcdi\x93\x00\xc4\xac\xc7[K\x96+\xf7Z\n\x1a\xcdf3DB\x90S\xc3r,B\xc3z\ +\xc3J\xa5\xf2CC\xcd\xda\x9a\xc1\x1a\xc4\x02L\xed\x8bx1\x88\x90\xb3\xd8\xcb\r\ +\x19@\xa3\xba\xbf\xbez\xdb@\x7fhd\xac\xb8\xe701\x8c-^DU\xd1\xa1\x90\x1a\x8df\ +\xf7\x83\x9c\xc6\xd5\x05\x00@\x00\xd63\xfc\xb1\xb5\xd7R\xd0h\xd6j\x01r@\x04\ +\xc3\xb4\x1d\x935\xeb5\xcbM\x15\x86\x87\x01`\xed\xf6\x97\xb6\x85\xdc\x1d\x8f\ +`\xb4\x112\xc6\xa8\x97\x1b\x06\x1e\xb1\xa0\xb1V\xfe\xca\x84j&m\x16\xc6\x8e\ +\x18\xa6\xf9\x08\x95\x1d\xb4\xe5\xae\xd1h\x1e\x07hm\x01Y(\xbc\xed]\xcdv\xd3N\ +\xb9\xf9\xfd\x00\xd0\xac7\xeb\xb5\xa6a\x1a\x8cq\xcb\xb2,B\x1b\xd5z\xca\xf3\ +\xf2\xc3\xc3\x00\xb0\xbe\xb2`a\xd3H\x1f\x8c\xa0Xo4\r\xd3N\xa7\xb3\xc8\x02\ +\x8c\x9a\xab\xab\x8b\x96\xd1\xcc\xb8\x98\x1b\x197mo\xcb\xbb\x98D\x8b\xbbF\ +\xa3\xd9\xe5 \x8f\xe3\xda-\xe8\xebmO\x0f\x1f%\xc4\xa8W\xebA\x10\x1b\x06A$\ +\x96e9\x164j\x8dT&\x93\x1f\x1a\x02\x00F#\x7f\xe5F.\xbf\x8f\x99#\xcdZ\xc5rs\ +\xb6e\x01F4\xa8\xfb\xeb\xb7,\xd2\xcc\xa5\xc1r\xd2\xe9\xde\xfbho%Z\xdc5\x1a\ +\xcd.\'\xf6\xbfBN\x01\x80\xf5\xf0\xb6\xdb\xa9\xbc\x9b\x1d\xabUjAH\t0N,\x83\ +\x80mb\xcd\xf7\xbd\\.W,\x8abkwnx\xb9=\xa6;\xd2hT\xad\xf4\x10pj\x12\xacW\xd6\ +\xea\xd5e\x934\x0b\x9e\x01\x00\xde\xd0\x91\xceW[\x1f\t\xdb\xa2\x11\x1a\x8dF\ +\xf3\x90\xe0\xb4\x19\xd7\x97\x00\x10\x90tO6@ 5\x1a\xc4&g\xdc\xb6-\xc3@\x1a\x04\ +\x96\x89\xf9\xd2\x98amr\xad \x0b\xe3\xda\xa2\xf8L\xd9\xe6,\x92m\xec\xcc\xe8\ +\xf6\xcf\xfe\xd8\x0b-\xee\x1a\x8df\x87\x11Un\x00r \xd0\x08\x91s\x0e\x00\x84\ +\x18\x88<\xe5\x15\xbc\xc2\xa1Fdr\xce-\xd3\x00`\xb4\x19\x98\x16\x14Jc\xc4Hj]T\ +\xb9\x0e\x9c\x02\x00"t7\xdb\x89\x91\xd99\xef\xa3v\xa2\xc5]\xa3\xd1\xec$Xp\ +\x97\x05k@ \xa2\x18QpRY\x00\xa0q\xd3\xf3F\xd2\xf9\x83\x8d\x90 2\xc7\xb1\x019\ +\r\x1an\xca\xc9\r\x8f\x12#\xe9W\xe1Q\x955\x97\xc5\xe7\x98A\x97M\xb4\x01\xd2\ +\x85q\xd3\xc9<\xf4\xfe<4\xb4\xb8k4\x9a\x9d\x04\xad\xdf\x06\x00@\xa4\x98\x1a;\ +\xf4\x84\xeb\xe5y\xdc\x8c\x9a\xf5(6\x1a!!\xc0\x1d\xd7F\xceh\xb3\x91\xce\xa62\ +\xc5\x11\xd2-p=\xaa\xcc\x89\x94\x8f\x9c\x83LG\xa3B,7]\x9cx\xd8}y\xa8\xec\xc8\ +\x85\x02\x8dF\xf3x\x824\xa0\xc1] \x103\x12\xb3\xa2\xe9\xe4\t1\x10L\xcaS!5\ +\x01\xb8i r\x167k^\xce\xcb\x0euWv\xd6\\\xe1aE\x18\xeb1\xeb\xba\x89\x1exC\x87\ +\x89i?\xe4\xde<\\\xb4\xe5\xae\xd1hv\x0c\x91\xff\x15\xf0\x18\x01\x83\xc8\x8c9\ +\xe1\x8cr\xd3\x89cdH,\x0b\x80#\x02\xa1\xf5jv\xb8\xe8\xe5z&\xe6\x8d\xab\xf3\ +\x00\xad}<\xba\x86?Z\xa9|*\xb7\xf7!vcK\xd0\xe2\xae\xd1hv\x06<\xae\xd1\xc6\ +\x1d \x10E\x10RN\x08\x8f\xa38b$\n8 \xb1\x08DqL0\x1e\xda3b\xa7z\xee\x94\xc4\ +\xa3*\x8fk\xd0g\x1d\x15\xc0\x1b\xde\x19\xdbq\xf4G\x8b\xbbF\xa3\xd9\x19D\xfeW\ +\x80\x1c\x01\x1a\x11"\x07\'\x97\x8e(E\xca\x18r\x02\xc0\r\xd30\xa08\xaf\x96\xf9\ +\xc7W_;s\xe6\xb4h\xff\xc6\x89f\xaf\xe5\xf3\xf9D\xc9\xfe\xcd\x96\x87\xbc{\xee\ +\xfc\x99gN\xab\x85\xe5 \xb8\xae+F\xaf\x7fG\xeey\xf6^t\x9e\xe8~k\xf8\xfaT\xfc\ +\xea\xec\xec\xb5\xe9S\'\xb7\xfe\xd4\x92\xa1\xe1\x91\xc8X\xb5l\xde\xf0\xeb4\ +\xa6\x88H\x00\x90\x03\xb6=._\xd3oB\xa0\xbb\xef\xc6\xb4\xcc\xfe>\x9d\x9d\x8b\ +\x16\xf7\x9d\x87P\xf63g\x9e)\x97\xcb\xf3\xf3\x0b\x13\x13\xe3\xd3\xd3\'_\x7f\ +\xe3\xcd\x84\xbe\xcf\xcf/\xbc\xfc\xd2O\xa6&\x8f\nM?\xf3\xcc\xe9\xcff\xae\x08\ +\xf9\x98_X\'\xbeT\x0b\x87a(\x9at\ +\xe1\xe2%\xf9\'\xd1B\xb5\xd9RRE\x93.\\\xbc\xe4\xfb~>\xbf\xf1\xd6\xc9\xcc\xe5\ ++j\r\xbd\xe8\xd5\xec{\x92\xcf\xe7S\xae[\xf1\xab\xa2#\x89\xce\xfa\xbe/k\x0b\ +\xc3\xf0\xc2\xc5K\x17.^\n\xc3\xb0s\x10DO\xe5\x08\xf7?Q\x18\x86\xa2_\xb2\xf2\ +\xe5rY\x0e\xaf\x1c+\xb5\xe3r|\x84GKV+\x87Z\xd6 \xff$\xca\x8b\x06\x0f> \x0f\ +\x83\xda\xdd[A\x10\x01\x02!\x04\x810g\x1f\xc9?!\xfe\x03+\x8f\x0f\xcfm\x82\ +\x00H\xb9X]\xdduhq\xdfy\xcc\xcf/\x08/\xc1\x8f~\xf8\x83\x89\xf1\x03/\xbe\xf0\ +\xfc\xf8\xf8\x81\xe9S\'\xe7\xe7\x17\xba\x96\xff\xdd[g\x9f=s\x1a\x00|\xdf\x97\ +Va!\x9f\xab\xf8\xd5M\xdf\x14\xf2\xe2&w]\xf7\xdc\xb9\xf3\xff\xf4\xab_\xff\xf2\ +W\xff\xdcY\xdb\xcc\xe5+\x13\xe3\x07\xf2\xf9\xfc\xf4\xa9\x93\x9f\xcd\xb4\x94b\ +\xf6\xda\xdc\xb9s\xe7E\xdbf._\xb9p\xe1"\x00\\\xb8pq~aq\xb9\xbcr\xee\xdcy\xd7\ +u\x7f\xf7\xd6Y!:\xbe\xef\xff\xee\xad\xb3\xae\xeb\xbe{\xee\xfc\xec\xec5QRx\ +\xbd\xc5\x83\x88\xa8SJ\x8f8J4)\x08B\xf1y\xb9\xbc\x02\x00j\r\xe2\x9b^tmv\x7f\ +\xc4\xd9_\x7f\xe3M\x00\x10\xde-\xd1G\xe1\xef\x02\x80\xe5\xe5\xf2/^}M\xea\xf5\ +\xbb\xe7\xce\x8b/_\x7f\xe3\xcd\x8a\xef\xab\x830\xbf\xb0x\xe1\xc2%\x00\x98\ +\x99\xb9\xdc9\xb5$N\x04\x00\xbf\xfc\xd5\xaf+\x15\x1f\x00^\x7f\xe3\xb7B\x9d_\ +\x7f\xe3\xb7b|\xc4ht\x0e\x9d\x1c\x9fT\xb7\xa1\x9e\xbd6\xf7\xd6[o\xcb\xe6A\ +\xfbA!\x08\xc2 \x08E\xcb\x1f!Q\x14\xb5\x9d/\x181\xaf\xe2\x13\xbf\xbc\xd2X[\ +\xad\xde\xad\xf9\r\x0f\xe0\x1bZ\xedD\x8e-\xf8\xc6w,fq\xf4\xcd\xd4\xbf\xcd\ +\xd0n\x99\x1dL\x18\x86\t?{\'B\x86\xee\xcb\x93\xfb_\xff\xcb\x7fv]7\x0c\xc3_\ +\xfe\xea\xd7\xd2\xd8\x97|6s\xe5\xe5\x97~\x0c\x00\xd3\xd3\'\x7f\xf9\xab_\x0bO\ +\xce\x85\x0b\x97^~\xe9\xc7r\x9e8\xf3\xcc\xe9\xbf\xfe\x9b\xbf\x15\x1e\tiE>9}r\ +v\xf6\xda\xc4\xf8\x81\xcff\xae<9}2\x0cC1?\x01\x80\xea\xf5N\xf4H\xccXB\xf2\ +\x9e=sZ\xf5\x0b\x8b\x1a\xfe\xeb\x7f\xf9\xcf\xe2\x8c\x7f\xf7\xf7\xff\xd0\xa7S\ +]\x9b}\xcf\xa1\x98\x9d\x9d\xcb\xe7s?\x7f\xe5\xa7\xea\x97\x1f]\xb8\xd4\xb9\ +\x0c\x00\x00/\xbe\xf0\xbc\x18\xab\xbf\xfe\x9b\xbf\xfdy\xa9\xf4\xf3W~&\x07\ +\xe1\xc2\xc5K\xae\xeb\x8c\x8f\x1f\xe8\xf5C\xa8\'\x9a\xbd6\x97\xcf\xe7\xe4$7;\ +{\xcdu\x1d1J\xe2\xf0^C\'\xc7\'1\xd4\x00p\xe1\xc2\xa53gN\xbb\xae[*\x95~\xf7\ +\xd6Y\xdf\xf7\x85\x8fN\x94/\x14\xf2b\xaaxT\xd8\xa9|\xd0\xbcc\x12\x00\x04\xd3\ +6m\xcbaq\xcc(\x03BR\x8ei\x18\x06r\xf6u\x9d3\x84@j\xaf\xe1\x0c1\xc6Mv\x17\x83\ +\x96)@\x009\x8b\x00\xbco\xa0\x1b\xdb\x0c-\xee;\x8f\x89\x89\xf1\x99\xcbW\x9e\ +\x9c>\xf9\xee\xb9\xf3SS\x93\xb3\xb3\xd7\n\x85|\xb9\xbc"\xe5@\xf2\xbb\xb7\xce\ +\x96\xcb+R\x9b\xf2\xf9\xbc4\xd5+~\xb5\x90\xcf\x89o\x00\x0e\x00@\xa5\xe2\x8f\ +\x8d\x95\xa0-\xaf\xae\xebNM\x1dM\x98\x99\xc2\x11!\xd6`\x05\xb3\xd7\xe6\xa6O\ +\x9d\\.\x97\xef\xe9)\x9e>u\xf2\xff\xfc\xbf\xfe\xef\x17_x~\xe6\xf2\x95\xff\ +\xf4W\x7f\xb9\\^\t\xc3P\x98\xb7\x00P\xc8\xe7D\xd7\x84*\x81\xa2e\x92\xc4)\x96\ +\xcb+\x05\xc5?\xa3~N\xd0\xab\xd9\xfd\x1b|\xe6\x99\xd3S\x93G\x7f\xf1\xeak\x89\ +I4\xf1\xb8#\xbf\xef3[\x88s\t\xeb\xbbsbH\x9c\xc8\xf7\xfd\xe5\xf2J\xd8\x1e\x99\ +R\xa94V*={\xe6\xf4\x85\x0b\x97~\xf7\xd6\xd9\x1f\xfd\xf0\x07b\xeaM\x0c\x1d(\ +\xe3\x93\x18j\x00X.\x97gf.\xcb\xf2A\x18\x96\xcbey\xc1?11>3sy\ +\xfaT\xcb\x8e~\xf1\x85\xe7\xe7\x17\x16\xcb\xe5\xb2P\xd5\xf9\xf9\x85\xe9\xe9S\ +j\x9d33W~\xf4\xc3\x1fHY\x9c\xb9|\xe5\xa3\x0b\x97\xa6O\x9d\x9c\x9a<:\xbf\xb08\ +1~@:v:\x9b\xed\xba\xaeh\xb9p\x8f\xe4\xf3y\xd7u\xc5"p\x18\x86\x15\xdf\x17-\ +\xfc\xc5\xab\xaf\x15\nIY\xef\xca\xc4\xf8\x81\xdf\xbduV\x08b\x18\x86\xd2-3{mn\ +b\xfc\x80\xda\x86^\xcd\xbe\xe7)\xf2\xf9\xfc\xb3gN\xbf{\xee\xfc\xcb/\xfdD\x1d\ +\xc6\x0b\x17/\x89\xe8#i\x1a\xdf\x93\xe9S\'\xcf\x9f\x1f\x1b+U*\xfe\xfc\xfc\xc2\xcb/\xfd\xb83\x14R\xfe\x0b\x00\xff\ +\xe3\xbf\xff\xb7\'\xa7O\xfe\xe2\xd5\xd7\xe6\xe7\x17D($\x08\x9d\xbap\xe9\x1f_\ +}-\x08\xc3\xe9S\']\xd7-\xe4s\xaf\xbf\xf1\xe6\xfc\xfcB\x18F\xa5\xd2\xa8\xea\ +\x93\x99_X\xac\xf8\xbe\xfa\xcd\xd4\xe4\xd1w\xcf\x9d\x9f_X9}\xf2\xcc3\xa7\xc7J\xa5\x7f|\xf5\xb5\xe9\xe9\x93\xaaU\ +855\xf9\xcb_\xfd\xb3\x14\xcag\xcf\x9c\xfe\xbb\xbf\xff\x07q\xd4\xb3gN\x8f\x95\ +J\xf9|\xfe\xe7\xaf\xfc\xf4\xf57~;;;\'|\x11\xf3\x0b\x8b\xa2\xa9]Qk\x90\xdd\ +\x17\xdem5\xde\xa6W\xb3\x07\x19m\xe1\xa3W\x0b\xff\xe8\x87?x\xfd\x8d7\xdf=w>\ +\x9f\xcf\x8f\x95F\xfb\x1c+\x07!\x0c\xc3\xcff\xae\x88u\x8e?\xdf<\x07w\x9eH(\ +\xf2\xdf\xfd\xfd?\x88\xf2/\xbf\xf4\xe30\x8c^\x7f\xe3M\xd1M\x11\xae\xda9t\x89\ +\xda\x12C-\x7f \xf1\xb3\x8a\xa9\xe2\x97\xbf\xfa\xf5\xeclk\xc1@\x8c\xb6\xf8\ +\xdf\xad\x17w\x00(\x8cN\xac\xd10\xae-Y\x06\'@X\x1c\xb2\x18\x00D\xe8\x0c\x00\ +\x01\xf8\x1a\xab\xaa\x88\xe8X\x8d\xc2\xd0X\x10\x01"\xda$v\xb1)\x96Q9\xd8\xbb\ +\xd2l\x07\x00\xf2\x10W\xa25\x0f\x19\xdf\xf7\xa5we\xc0C\x84\x85\x9b8d~a\xd1u\ +\x1dyK\x8b2\xea7\x0fPs\xd7\x13\r\xd8\x1e\x00X.\x97\xc30\x1a\xa4\rb\x10\xc6J\ +\xa3\x83\xf8\xd0\xbfq\xde=w\xbeP\xc8\xf7z\x08P{\'z4x;\x13\xfd\xea\xfc\xad\ +\x07\x1ca\x95\xc4\x0f\xdd\xf5\x9bGK\x14\xd4\x83\xc6:\x8b\x1a\x80\x94\xc5!"\ +\x03N\x018g\x8c\x00\x07\x10q\xefHHWc\x9e\xb4\xfe\xe9&i\x88h:)\xc3\xcer\x8e\ +\x18W\x91E\x00\x84q\xf0FOd\x87\xf6=\xdc^="\xb4\xb8k4\xf7\xc7\xebo\xbc96V*\ +\x95J\xbe\xef\x7ft\xe1\xd2\x7f\xfa\xab\xbf|$\xf3\xca\xe3\x02""g,\xa6\x8d2k\ +\xdc\xaa\x86\xf98\x8a)\xe7\x06A\x038\x10$\xc0\tp\xd3@\x03\xa8a\x00G\x93\x10\ +\xf1\xde)kW\xd0zK\xc9 \xc2\x0b\x03\x00\x84#A\xc3\xf5\x86\x8fd\x8b{\x1fa\xe7\ +\x1e*Z\xdc5\x9a\xfbc\xb9\\\x9e\x99\xb9"\x96U\x9f=s\xfa\x91\xafF>&D\xfeM\x08\ +\x97\xc1\x1a[\xb9\x1b\x07\x14L\x83\xb0v@#\x01\xdc3d\x86\xe1\xdd\x8cMy\xe6h\ +\xdc\xac\xc4\xcd5\x1a\xd5\x11\xc1 \xe0\xb9\x04\x01\xb85D!E\x90\x11\x02\x1c\ +\x0c\']\xf0r#\x86i?\xd2>=\\\xb4\xb8k4\x9a\x1d\x80\xbf\xfc\x85Co\xbb\xe9\x92\ +\xdft\x10\xa0\x1e`\x10#!\x04\x11-\x83\xec\x1f6W\xd7\xcb\x9e\xd5\xe0h\xd0\xf6\ +\x16\x1f\x08\x90u!\x9d&\x80\x00V\x01\x8a\xdfz\xb4]\xd8b\xf4KL\x1a\x8df\x07\ +\x10Ea\x18s\x1e\xafy\x0e-d,\xdb\xb6,\x93\x98\x06\xa4\x1d\xa3\x901\xa3(\xe6,\ +\xa86QUv\x93@\xca!\xc0\x01\x10 \xae@\xe3\xfa\xa3\xed\xc2\x16\xa3\xa3e4\x1a\ +\xcd\x0e\x80\xd1\xb8\xd6\x00\xcb\x88\x11VjA\xb1\x90\xc9\xa7m\xe4\xc8-\x93\ +\xb0\xb8Y\xad\xdf\xe5\x9c!\x92\x8d\xdd\xb4\x11R.\x10CY_\xad/\x80=\x02\xf6\ +\xe3\xe2F\xd3n\x19\x8dF\xb3MA\x1ec\xdc@Z5h\xe5\xf6\xf2j\x10q\xcb\x00\xcf\x85\ +\x88"\x80E\x0c\x0b\x08AN9\xa3\x00\x88H8\x82\xe7\x12h\x9b\xedC\xd9\x8eM8L\x0f\ +\x86\x9e\x81\xdd\x98\xbd\xbd\x13m\xb9k4\x9am\x04\xf2\x18i\x83\x87\x15\x1e\ +\xf9\xad\x98E\x02\x88\xc0\x18\n\xa1nF`\x19\x04\x80\x02\xa7\x00@\x00,\x93\x00\ +\x90\x88n\xe4\xeeE\x84t\xc2l\x17\xb0\x06\xd4o@vrK\xbb\xf4\x88\xd0\xe2\xae\ +\xd1h\x1e)\xc8\x90S\xa4\r\x1eUxT\xc5\xb8\x86\r*\x9c6\x81\xc7j\xa6\ +\xc6\x04\x04\x80#pT\xfe_\x01\x01\x00A$\x120\xdao0eR\xdd\xccvyD\xf5\x0b(<\r\ +\xbb4\x8d\xbb\xe4\xff\x07_\xffI\xbb\x17\xf3\xcc{\x00\x00\x00\x00IEND\xaeB`\ +\x82' def getSplashBitmap(): return BitmapFromImage(getSplashImage()) @@ -1995,30 +2854,2073 @@ def getSplashImage(): stream = cStringIO.StringIO(getSplashData()) return ImageFromStream(stream) +#---------------------------------------------------------------------- +def getIDESplashData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01\xf4\x00\x00\x01\\\x08\x02\ +\x00\x00\x00\xb1\xfb\xdb^\x00\x00\x00\x03sBIT\x08\x08\x08\xdb\xe1O\xe0\x00\ +\x00 \x00IDATx\x9c\xec\xbdg{\x1cIv4\x1a\'\xcb\xb4G7\x00Z\x90\x1c\xb3\xb3\xab\ +u\x92V\xaf\xfc\xfd\xff_\xde+w\x1f\xadV\xd2:ifg\xe8\t\xd3\xbel\xe6\xb9\x1f\ +\xd2TVu7\x087C\x80\xac\x18\x0e\xba\xcbg5\x1a\x91QqN\x9e$fF\x8b\x16?8\x98\xd5\ +\xeb\xff\xfdgU$\x00\x18`\x06\x11\x88\x00\x80\xf4\x0e\x00\x01Df\x93 \xbd\x03\ +\t\x02\x01B \x0c\x83N\'\x8ez\x03t{\x10\x02y\xaaV\x8b"O\x95Tl\xcf\xc9\x0c\xc5\ +\x90\nJ1\xdb3_\x1f\x04*\x14\xa79\x1f>\xfd\xf3\xd1\xf8\xfe\r\x9d\xb5E\x8b\x9b\ +D\xf8\xa1\x1b\xd0\xe2\x13E\xb2<\x91E\xa2\xd9\x96\x00\x06\x13H\xbf\xd7\xcb\ +\xfa\x8d\x95\x1ed\xa8\x99\xa1\x00AP\x8c\xb2\x94\xe0\x9c\x15G\xb2\xa4N\x17"\ +\x10\xddA\x04\x94y&\x95\x04\x83\x08\x0c\x10\x81\x00E\xa4\x14\xd4\xcdI\x19\ +\x02\x02\x81\xf9\xc9\xcb\x96\xdc[\xdcN\xb4\xe4\xde\xe2\xc3`q\xf2\x9d\xe5r\ +\x80A\x9a\x83a\x165\xc8*z\xbdR\xd3\xba~C\xccL\xc4,%\xab\xb2,\xc3,\r\xa3X\x88\ +@\x880\x08\x99\xcbB)\xc9\xcc\xfaX!@\xac\xbb\x04RF\xce3\xae*\xe4\x89\x88\xcd\ +\xe1\x94\xae\xce\xf2t\x1dw\xfbW\xfe\x1cZ\xb4\xf8\x9e\xd0\x92{\x8b\x0f\x80,\ +\x99\xe7\xc9\\Xr%\xf7\xc6\xee\xc0\xd6\x901\xdb\xb5\xb6g(f"\'\xf7\xa1\x00\x96\ +\xacTYJ\x15\x16e\x18\x04$\xc8\x1c@\x02P`\x08\x02\x13X1\xeb\x07\x02\x063\x84a\ +\xf9+y5\x0c\xae: ^/\xa7-\xb9\xb7\xb8\x85h\xc9\xbd\xc5\x07\xc0j\xfa\x1a@\x18 \ +\x0c\x90\x16\x96(\x19\x10\x865\xc9x3\x15\xef3X\xef\x02M\xc8d\xdf\x00\xcc\xcc\ +\xac\x94RR)m\xca\x9bC\xd8\x9e\x83H\x04`fR\xac\x8c\x15\xaf;\x0f\xd2\x0bl\xfb\ +\x91\x8b\x10=\x83\xddQ\x00\xb2dqc\x9fK\x8b\x167\x87\x96\xdc[\xfc\xd0P\xaaL\ +\x16\xef\x08P\x8c8$\x02\xa7\x85g\xbf\xd8Pj\xe5\x8e[\x0b\x9e\xedV03 \x88\x98\ +\x8dS/\x98\x15\x11C\x911\xd9\xf5\x7fL\x04f\x16B\x08\x11\x88\x80\x02\x86b%\ +\xa5RJ)f\x023\x81A\x9a\xe5\xf5\x897]y\x9f\xf1u\x0f\xc3\xde\xbf\xbf\xc4\ +G\xd0\xa2\xc5\x0f\x8b\x96\xdc[\xfc\x10XM_\xdaLD\x93\xc6\xb2u7\xcd\xddI\xce\ +\xf0\xf8\xbd\xdf\xc1*\xb5&\xf8\xb6\xa3\xb8\xce\xe8N\xb6\xd7\xd6\xd5\xf9\xbd\ +\x91f\xe3\xbfq\x8f\x14\xca&\xccx\x16\x123\x13L\x92\xccx4>x\xff\x9d\xb7h\xf1\ +\x81\xd0\x92{\x8b\xef\x1dE\xb6\xca\x93y\x95\xb2\x82\x8a,\x1b\xb2\xdd!\xc9\ +\x99A\xdd\x9a~w\xf93\xdb\xc1h\xcav\xde\xb6\xd5e\xc2\xc0\xe3q\xf7(\xe1\xd6{\ +\x8b\xcc\xa6\xfa\xb0\xb5z\x98\x15\xf3\x83\xc7_\\\xeaCh\xd1\xe2\x07FK\xee-\ +\xbew,\xcf^\x19\xfa\xa4Z\x06d\x03\xfe\x88T\x02e\x05\x98\xd1\x8d\x00\xcd\xef\ +\x1dJ\x0b\xce\n4B\xb1\x1e\xa1o\x93\xed\xf5!\xac\xfe1>\x8f3W\x14oK\xf9\xda<|x\ +\xdd\x84N\xbda\x0c\x86\x93V\xb6\xb7\xb8\xe5\x10\x1f\xba\x01->r\xb0\x92\xc9\ +\xe2mc\x18\x91\x86_\xfa\xd1l\xb16\x88^\x91\x15Xgf\xa8(\x11z1\xf5b\x7f\xee={6\ +\xaa\xcbv\xff"\xdc|\x8f\xba\x8aw\xff`\xb3b\xec\xbf\xc6b\xd5@F+\xdb[\xdc\x01\ +\xb4\xe4\xde\xe2\xfbE\x91\'\xaa\xac\xea\t4e\xbbG\xf4\xd5\xb27CS!\xb1\xca\xaa\ +\x84\x99nD\xc3.E\xc2*nw\xd0fT\xb4vz\xcf\x93\xe1\xc6\xb2\xf3pH\x13\xb7}\x00hd\ +\xe8\x90+k\xd0\xca\xf6\x16w\x02-\xb9\xb7\xf8~\x91,\xde\xd9\x02\x8f\x00j\x02\ +\x9b\x1b\xf3`T\xc4^\x9bKI*\xacR.\xa5\x99W)\x10\x18t\xa9\x17Ws1y\xb2\x9d|\xd2\ +\xde\xc2\xe3u\xba\xf7d\xbb\xd7\x82m\xd0\x8d\xd7\xb3/=8\xfa\xe2\xc2w\xdf\xa2\ +\xc5\x07CK\xee-\xbeG0\xab\xd5\xec\x8dY\xa8\x0f\\\xf2\x86\xaa\xda\xb2.fC\xfd\ +\x0c\x80\xe6\xf7e\x86\xb4`wl7\xa6a\x97\xe2\xc0X(\xe4\x1f\xb0\xc1\xed\r\xd9\ +\xceM\xd2w\xb2\x1df@\xaa.|\xe3\x8d\x87\x82\xcd\xf0\t\x88B\xd1\xfe\xd5\xb4\ +\xb8\x03h\xbf\xa6-\xbeG\xa4\xcbSY\xa4.\x17\xc6\xc6)\x81\xcd\xa4F\x06je\xbe6\ +\xc0X\xe7Xe,\x95\x89u\x86\x01\x06=\x1at\x10\x08=\xdb\xf5Ud\xbb\xb7\xcf{d\xbb\ +\x8e\xb4\x86\x01\x92\xd5\xf4\xfc\xbbn\xd1\xe26\xa0\xcd\x96i\xf1=b5{\xedB\xa9\ +\xb5I\xeb\xaa\xc2\x90\xd4\x0c\xb3z\xe0Z\x8e9\x88\x90\x17(%w#\x8a#s\\\'\xa2(D\ +V \xc9\xab\xb1Nh\xb2\xba\xf7\xa6N\xfa\xec\xc9vx\xb2}\x83\xeb\x8dl\x17\x84<[_\ +\xf2ch\xd1\xe2\x03\xa0%\xf7\x167\x06f\xc5\xb2T\xaa\x94\xb2`Y\x14y\x9a,O\x88@\ +\xb4e&T\xf2\xdf\xb82\xec~\x18\xb3>\xe2\x88\xadq\xaf\x18\xeb\x8c\xf3\x12\xbd\ +\x98\xc2\xc0\xac\xec\xc5\x14\x87H\x0bd9JU?\xd0\xbe\xbf\xa0l\'\x7f\xab\xf5\ +\x8ct\xac5\x08\x08\x80,\x8b\xab}>-Z\xfc\x90h\xc9\xbd\xc5\x15\xc1\xacd\x91\ +\x95\xf9\xaa\xc8\xd6e\xbe.\xf3\xa4,2\xa5J%%\xa0*\x0b}S\x98Wy\x91n\xdb\xfbe\ +\xbb;\x87^YH\x94\t\xc7!\xba1\x05\x02\x00\x84@\xbfC\xdd\x08YAi\xc1E\xc9\xb5\ +\xdeA?;4e;|\xd9\xee7w\xb35\x82\x10\x98\x0e\xa653[\xdc\x01\xb4\xe4\xde\xe2\ +\xa2P\xb2(\xd2E\x9e-e\x91\x95ERf\xeb\xb2\xccX\xd5\x86\x8dz\xe1L\x10Y\x02\xb7\ +Vz5\xf3\x86M\x94q\x82\x9e\xea#T\xb7\xcav\x1fz\xd0h\x9asVp\x1cR\x1cQd\xca\x8d\ +Q\xaf\x83nLy\xc9E\xc9y\t\xc7\xf2~|u\x8b/\xef\xdd\x82\xeb\x16\x8clg\x10!\x0eI\ +_4\xee\xf6/\xfe\xa1\xb5h\xf1\xa1\xd0\x92{\x8b\xf7\xa0\xcc\x93lu\x9a\xaeN\xf3\ +d.e^\x97\xd9d\xd9\xdc/\xd3\x0e\xd8\x05\xf2\x18\xdb\x99\xed\r\x98\xe9\x92\xb6\ +%\xc9\xf8\xd9*z$\x11\xf9\xa5y\x99u\x01\xf7\xb4@Zp\x14\xa2\x1bQ\x14B\x1bA\x9d\ +\x88:\x91P\xccE\xc9\xba\x0f(\xa5\xab\xd2nO`\xfd\x16\'\xdb\tP\x9eE\xa3\xefN\ +\x08\xc4\x01\x84\x1dr5\x9a<\xb8\xca\xe7\xd8\xa2\xc5\x0f\x8b\x96\xdc[l\x87\ +\x92y\xba:K\xe6o\xd3\xd5)\xb3\xf28\xddIpo\xd8)\x19u\xed\xbb\xdcU\xb0\xd4\'e/\ +\x03\x12U\xb5\x99\x06\xe7\xd7\xb3[\xcc\xe0!/S\x9e\xc0\xf5\x8b0#/9/9\x14\xd4\ +\x8d)\x8eH\xd8pm\x1cR\x1cB*-\xe49/\xb8\x90(\x95.\x11CF\xa5\xb3\x97\xcf\xe3NL\ +$\x08a\x88\x80\xaa+v\x07\xfb\x9dv\xd2\xd4\x16w\x01-\xb9\xb7\xa8\x839[\x9f\ +\xad\xe7o\xd2\xe5\x89\x94\x85\xc7\xd6>\xffRC\x8f;;\x86\xbc\xa8h%\xdb=\x8a\ +\xf7\xce\xe1\x9dq\x1b\xb7\xfb<\xabG\xfd\xd7f\xd4\xf0\x03\xa45/\x9e\xf35\x07\ +\x82:\x11u"\n\x03\xe3\xa5\x08\x81NDqD\xdc\x85b\x14\xa5*%\x15\x92KI\xb59Q\x15\ +\x88 \x88\x84\x80\x10\x10\x96\xf1\xf5C\x83b:x\xf8\xe5\x85?\xca\x16->$Zroa\ +\xa0d\x9e\xcc\xdf\xae\xa6\xaf\x8al\xc5\x9eW\xb13\xf1\xdc\x89i\xa3\xbd\x9b\ +\xbb\xf9\xf90~Y\xddJ\xaa;\xcd\\;\xab\x9b\xe6\xba~\xb6\xa6l\xf7=\x9bjQ\xb7G*^\ +\xa5\xbc\xce\x10\x05\x14G\x14G\x14\nbb(\x00\x08\x04(\xa48\x04@\xca\xf6\x13\ +\x8a\xc1\x8aK\x05\xa5 \x19J\xe9\xc4y\xd3\x1a"(\x85\xa8\xbf\xdf\x1f\x8e\xcf\ +\xfb\x10[\xb4\xb85h\xc9\xbd\x05d\x91\xae\xa6/W\xb3W\xb2,\xfcq\x99h*o\xae\xaf\ +\xddE\xfa\x8d\xa3ky(u{}\x83\xd9}XO\xc6\t\xe7sd\xbb\xdb\xddKa\x043\xb2\x82\ +\xd3\x82\x05!\n)\x0e)\n\x10\x04\x04=Y\x1e\xdb\x07\x02\x00\x80 "\xe6\x80t\ +\xe1\x1a\xa5 \x15I\xc9\x92QJ\xe4\x12O\x1e\xb7\xb2\xbd\xc5\x9dAK\xee\x9f4\xca\ +\x8e\x9f\xcf\ +\xee\x9fu\xc7\xb1[3 m\xab\xab\xf6\xbb\xe4\xf8\x9a\xf9\xbe-i\xdd\x8eT\xf2@6\ +\xbf\x86I)(\x9b-\xe3\xfc"\xcf}"\xb2y2\x83\xf1~o\xd0&\xc9\xb4\xb8Kh\xc9\xfd\ +\xd3B\xb6>[\x1e\x7f]\xa4s\xb7F\x9b\x12\xef\xa1u\xbbJk\xfc\x8e \x05H\xc9\x85\ +\xb4\x14_wRj!NOWo!\xf4\xdd\xb2\xddm"\xafY\xfep\xa4\x8d\xd3{?\x1b\xbb\xd5\xb6\ +i9o\xdaHdGT\xd9J\x90\xd5\xd5\xbc\x1b\x9b\x1c<\xdcl\xfbN0\x17\xab\xd7\\\xcc\ +\xa4\xa2\xb0\x7f?\xea\xb5\xc5\xdf[|\x00\xb4\xe4\xfe\xa9@\xc9bq\xf2M2}YM"gi\ +\x9d\xacr7\xb0v\x89Mi\xacgA\x02\x00\x04!\x08)\x0cPH.e\xe5\x9c\xf8J\xba\x96\ +\xdb\xee\'\xaa\xdb\xa5\xad\x03\x97\x1akL(\x95\xabew\xfa]\xb2}\x17\xf5\xf3\ +\xb6E\x1b\x06\xd8\xcc\xcf1maF\xdc\xe9O\xf6/1pi={Q.\xbea\xc5\x00\x17\xcb\xd7y\ +w\x12\x8f\x9eE\xbd\xfd\x8bG+Z\xb4\xb8>Zr\xff$\x90\xad\xcf\xe6o\xffP\xe6k4h\ +\xdd\xcfF\x07\xe0rZljKC\xcb7\xd8W\x10\xba\x11\x95\x01\xf2\x82\x95\xb2\xfb\ +\x93\xe7t{\x1c^\xd5\x80\xe4-y\x93\xb5\x89\xec\xaa\x95[d{\xed\xa0\x8d7n\xc1\ +\xb5a\xb3\x9eLM\xde{\xb7\xed\'\ny\xb2\x9d\x1f=\xf9\x92.\\\xc3\x9dY\x15\xab7\ +\x90\xb2\x94\xac\x18D\x08\xd6S\x99N\xd3\xce\xb83\xfe"\xeeM.x\x9e\x16-\xae\ +\x89\x96\xdc?v0/N\xbf]\x9e|\x03+\xd8\xa9.\xd8\xbdL\x11\x18\x1b\xa6\x1e\xe6\ +\xac\'/n\xe9\t\xa2\x00\x81 =\xf2\xd3\x9c\xc7s\xba\xdd\xfeF\x98s\xf5\xb6\xd6\ +\xcc\xc6\xb2\x16\xfb>\xb9_@\xb67\xec\xf5\xeb\xcbv\xa5T\xa7?\xee]&\xb7}\xf9\ +\xf6w\x9d\xb0`\x11\x05e)\x15K\xc9\xa5d\xa9\x10\xa8\x19g\xff\x9ew\x0f;{O\xa3\ +\x96\xe2[|\xff \xde\x94C->\x16\xb0\x92g\xaf\xfe+\xd5uw\xb1!\xd8\x1b\x94M\xf5\ +\x19\x91\xea\xb4\xbe\xc9\xe9\xd8X\x93\x17\x9c\x15Mzu3.5\xc6\xab6\xdc\xf6\xaa\ +S\xe0\x8a\xd9\xab\xf4v\xa3\xb8k\xe4\xee"\x9f\xcc\x1b?\xed!n%\xdb\x9fv=W\xe4\ +\xbeQRF\x07R\x99\x15\x89\xa87\xfeQ\xd4\xe9\x1eNz\x83\xe1\xfb\xeb\x85\x95y2{\ +\xfe\xcf\x04\xa5C\x11B\x98\x8a\x95Z\xc5\x03\x08\x04\x05\x02A\xf7 \x1a=\x89\ +\xfb\xad\x17\xdf\xe2{D\xab\xdc?Z\xc82\x9b\xbe\xfam\xbe>s\xcc\xae\xb3\xd8\xc9\ +\xbc!\xc0\x0f\x1e\xd6\xca2n\xa7\xf5F\xc1\x00\xf6v`\x00\x88#"\xc1i\xeeU\x7f\ +\xb4\x9b4\xa5\n\xf2\xc8\xdbC3\xf2\xa9\xdf:\xd9n]\x94+\xbb\xed\x8d\xc5\x8b\ +\xc8v\x06\x83h\xb4\xff\x99\xa4\xeebU\xe4y\xb9\x9fe\x93\xf1^\xa0K\xc8\xef\x80\ +,R\xa5\x94\xb0\x1f\x94RJ)\x12\x02a@\x0c\x94N\xc5\xafO\xcb\xf44\xefL:{\xcf\ +\xa2\x96\xe2[|?h\xc9\xfd\xe3D\x91-O_\xfc\xa7,\x12a\xd3`<+F\xffW\xc5=\xe9R\ +\xb4\xee\xb1\xe1f|0\x0eH\xc4\xbc\xce\xab\xa1@\xf6"(%\xb3@\xd0x:\x80u\xe7\xad\ +:7\xeb\xb6P\xf7vl\xee\xb0\xe9\xb6{\xda\xbf~v\xd8\x87\x8eM\xb7\x9d\xe5p\xf2\ +\xb8;\xdcO\xd32\x8a\x82\xbcT\xefN\xf3uzv0\xee\xf5\x07}\xda|x\xd1\xc7\x8a\x90\ +\xcc\xa3\n\x03P\x1c\x00\x0c%\x95\x12BP\x1c\x92bh\xa3\x86\x14\x94\x9a\xcal\ +\x1av\'\xd1\xe8i\xd4\xdbo\xcb\xc4\xb7\xb8Y\xb4\xe4\xfe\x11"[\x9d\x9e\xbe\xfc\ +oVE\xc5\xec\r\x9f\xddS\xdd\x8e\xd9\xdfK\xeb.\xc4\xb8E{\xdbe\x06\xc2\x90\xfa\ +\xc4\xeb\xcc&\xb9\xdb\xbd\x03\x81\xbc\x04\x85h\xc4&]\xbd]\xbf\xd6\xe4y\xb2\ +\xddo\xff\x86,?\xdfd\xf4e\xbbkx\xdd\xa97\x86L\x18\xf5\xc6\xfb\x8f( \x82\x08\ +\x02\xcar\x95\x17r\xb1,\xb3l5\x1ef\x93\xc9(\x8a\xa3\xcd\xf3\x07a\xcc\x10\x84\ +\x92\xc2\xbe\x8c\x1f\xa7\xb2W\x14e\xcc\xd3\x0e\xbfe\xa5\x94\xa2 \xa00\xa4\ +\x90\x8d\x8a\'\x05\xb9>+\xd3i\x16\r\xa3\xd1\xd3\xce\xf0~K\xf1-n\n\xad\xe7\ +\xfe\xb1!]\x1e\x9f\xbe\xfc/\xb0\xda\xc6\xec\xe4\x91p-\x8d\xdd1\xfb\x16Zw\x99\ +\xe0\xd5dx\xee\x1c\xdbc\xadD(\xa4\xe5w\xbb\x06\x003e\x05wc\x08\xaa\xaa\x0f\ +\xb8\xd4r\xb33\x113\xfbn;\xacE\xae7kO\xc6\x97\xe0\r\x9f\xbd\xe6\xb6\xfbV\xfb\ +\x0e\xb7\xdd;y\xe5\xb6G\xd1~o0\xee\xef\r\xa3NWJ\xces\x95\x15*\xcfU)\x95 t;t\ +\xb8?\x18\x0cz\xa2\xdeS1\xab\x93o\xfeo( \xf6~,\xc50\x10"\xcbr\xc9"(O\xc4\xfa\ +k\xd8\x9en\x9b\x17\x0f!HD\xc3x\xf44n)\xbe\xc5M\xa0%\xf7\x8f\n\xeb\xd9\xab\ +\xb3\xd7\xbf\'\xf0\x0e\xcd\xae\xf9\x9b\x018b\xdf"\xd8\xb7\xd1:\\tT\x837\x8e\ +\xaa\xa0{\x0e*%V\x19\xbb\x81\xac\xbak)$\x17\x12\xbd\x98\x04U1\xd2z(\xb5\xfaN\ +\xeam\x9a\x8c\x8d\xaagT\xfe\x8a\xef\xb7x$\x8e\x06\xa7\xd7\x03\xaa\xcc\xee\\ \ +\xa2\xea\xdc\xb6\x8d\xcc\xdc\x89;q\xe7 \xcbe@\xd4\x1b\r\xfb{#FP\x94\xaa\xc8U\ +VpQH\xc5*\x0ch<\x8a\xf6\xc7\xc3\xb8\x13\xfb7\x7f\xf2\xed\xbf\x04A\xcc\xbd\ +\xa7:\x0f\xd2\x0cr%!g\xbf\xa7b\xae\xeb<\xe8\xeb\xe9\xe26\xf0(^\x10\x82\x80D4\ +\x88\x86\x8f;\xc3G$\xce\xf3\xf7[\xb48\x1f-\xb9\x7f\xecE\xa3\'-\xc5\xb7\xb82Z\xcf\xfd#A\xba<>{\xf5\xbbMf\xd7\xc2\xd1\xc0\ +cv\xa7\xcd\x81\xea\xfd\x96\xb0*_\x98\xd6m\xcfaL\x16b\x06\xa2\x00\x83\x0e\x96\ +\x19T5\x95\x13\x05\x02\xbd\x98\x97)z1G!\x8c\xc2\xb0\x04\x0bW\x00\xc0\xc9vl\ +\xb9\x98\x9f\x84S\xad\xe0m\xbb\xda\xfc\xf7\xedn{\xf3\x02\xcc\x8c\xac@Q\x8aa?\ +\xec\xc4b\xbe*\xb3\xac\x98\xbd;\x19\x8c\xf7\xba\xc3A\xd0\t\x82@\x05!\xe59\ +\x15\x05%\x99*N\x92$\xc9\xf7\xf7\x87\xddn\x17\x00\x828\n\xd7\x91\xe2LJ\xa1\ +\x08\x90\x00\x14\xa3\xdbQ\x8d\xbc\x1c}\x9bRA*\xd6\xb5*\x01H]\xb7\xa7d!\xd7\ +\xaa\xf8c\xb9x\x11\x8d\x9eD\x83\xfb"\x88\xd1\xa2\xc5e\xd0*\xf7\x8f\x01y2;\ +\xfe\xee\xd7`\xb9\xc5\x8d\x81emg\xafocv\xe7\xb7\xd4\xa8|\xc3UGmE\xcdP\xdf\ +\xe1\xc3C[1\xeb\x0c\xa5\xaa=\x1fH\x85U\x86n\x84^L\x8a\xf9\x1c\xd9n\xdf\xee\ +\x94\xed\xd80a\xb0\xd5\x99a\xe8\xd2\xc5\xe7\xc8v\x80\xf3\x12?\xfd\xe5\xdf\ +\xf6\xfa\xfd\xc5\xf1[.V"\xa4U"W+\xa9\xa4\x8c\xbb\x9d\xc1x\x1cu\xbaRqQp^\xa8\ +\xbcPE\xa9\x02\xc1\xa3\x9e\xe8\xf7\xe2\xc1h\x90-\xdf\xad\x8f\x7f\x8f\xf0\xfe\ +"\x8b\x94\xaeqF"\x12r\x10\xbc%.\xb7|\x9a\xde\xe7\xe6T\xbc\xa6x0\x84\xaeK\x1c\ +\xc6\xe1\xe0\xa8\xbbw$\x82-Q\xdc\x16-\xb6\xa2%\xf7;\x8f2O\xde\xfd\xe9\xdf\ +\x94*\x04m\xe1t/\xf7\xd1S\xee\xde{xVL\x8dx\xb8FD[\x8du\x9f\xd6\xcf\x01\x01\ +\x92\xb1\xce8/k\x01[\xa5\xb0\xca\x10\n\x0c\xbaNG{\x82\xbd\xe6\xb6\xa3F\xee\ +\x1e\xa7\xa3\xce\xe6\xfe\xca\xcb\xb8\xed\xa6\xefcFwx\xf8\x93\x9f\xfd\xa5^\ +\x99\xae\x96\xab\xe9q\x1c\xca\xbc\xe4\xd9\xa2,\n\x19\x10u\x87\x83\xfe\xde\ +\x88DX\x96\x9c\x17\xaa(\x94R\xaa,U\xbfK{\xc3\x18r\x99\x9d\xfeN\x84=\x15\x1ed\ +\xaa\x0b!B*\xa2\xf2\x18r}\x81\x8f\xca|\xa8\xbe\x8ag6\xa4/\xa2^\xbc\xf7Y<|\ +\xd0\x86[[\\\x04-\xb9\xdfm(U\xbe\xfb\xd3\xffW\xe6+\xd1Lv\xb4\xef\xbd\xb2\x8e\ +\x95C\xb3\xc9\xec\xe7j\xf6\x1a\'9\x89\xbe\xa5@\xccNh\xeeNrNsx1Z0#\xc9!\x15\ +\x8fz\x14\x06P\xd2\x9c\xdf\x1a\xe5\xdbe\xfb\xf6P\xea6Z\xaf\xc9v\xfb]\xa7\r\ +\xd9\xee\x1ek\xa4\xc2\x8f\x7f\xfe\xb7\x83aU\xdd\x97\x95Z\x9e\x1d\xcblA\x02\ +\x8b\x95LR\xc9R\x85q8\x18\xefuz}\xc5\xc8\x0b\x96R\x819M%\x88\x86\x9d\x9e\xaf\xd9\x1b\xef=f\xf7\x85\xb6\xbf\xe9rD\xe5\x9d\xa0\x90\xbc\ +\xca e\xe5\xa7\x13!\xcd9-\xd0\x8f\xa9\x17\x1bE\xefd;\x8cWnskpi\xd9\x0e\x86\ +\xaa\xcbv\xbf\xde\x80.9id;\xd0\x1f\xde\xfb\xea\xa7\x7f\xb1\xd9\xf8t\xb5\\O\ +\xdfE!\xe7\x85\x9a\xaf\xca"W\x04\xee\xf6\xfb\xfd\xf1\x9e\x08\xa3\xb2\xe4\xb2\ +T\xa1@\x92S\x9a\xac\xf6\xe9\x8f\x82lK\xb9\xea9.\x0b\x06\x84U\xf1E\xc9\x85\ +\xd4\x8b&\xdc\x1a\x8f\x9e\xc4-\xc5\xb7\xd8\x8d\x96\xdc\xef0\x16\xa7\xdf\xcd\ +\xdf\xfe\x8fvc\xe0\xaa\x0b8Z\xf73\x1a\xcdk}q+\xb3{\xf0\xad\xf9ss\x1f/\x01"(\ +\x85$\xe7\xb4\xb0i\x90\x00X[\xf0L\x04-\xe1\x99\xa1T\x15"eP%\xb37d;\xea\xe4\ +\xee\xa4\xba[\xef\xdcv\xd4e\xbb-&l\xd8W1\xbe\xfa\xd9\xdf\x0cv\xcc\xa5\xa7\ +\xa4\x9c\x9f\xbc\xe3b%\x02Z\xae\xcbu*Y\xaa \x08\x06{\xa3\xce`\xc0\x10E\xa9\ +\xe2@\x80\xb9\x9c\xfeF \xbf\xde\xe7T\xc1\xa7\xf8\xacd\xe9Q|\x10v\xc3\xe1\x93\ +\xce\xe8q\x9bQ\xd3b\x13-\xb9\xdfUd\xc9\xec\xf8\xdb\x7f\'4\x07+\x81 \xaa\x12`\ +N72\x00\xf24\xe4\xe5\x98\xbd\xb1r\x07\xce\xdf\xea\xbeg\xba\x91y\xc9I\x06=\ +\xdd\x07\xacQ\x93\xe6\x9c\x15\xe8\xc6\xd4\x8b!\xaa$\x9a\xdd\x03\x97,\x83\xd7\ +B\xa9\x1b\xb6\x8crs\xc0\xda\xbb\xe5m\xb2}4y\xf4\xc5W??\xf7&\x90\xaeV\xeb\xd9\ +I \x8a\xb2\xc4b]\xe6\xb9\x04s\xa7\xdb\x1d\x8c\xf7\x828V\x8a"\xa1\xf2\xe9\xef\ +\xe8\xc2\x0e\xfb\x05\xe1(\x9e\x81\xa2\xe4RA\x00\x81@\x18R\x10\x8fz\xf7~\x11D\ +\xdd\x1b\xbc\\\x8b\x8f\x00-\xb9\xdfI\x94E\xfa\xee\x9b\x7feU8+\xa6\xc6\xec\ +\xd0\xc4\xc2\x1bA\xd4*a\xc6\x81v\xd1\xf7n\x9d\xbe+1\xe6\xb2\xd0<\xb5\xce\x91\ +\x97\xc6\x84!"\xa98/\x91\x97\x08\x03\xf4;\x08\x03\xf2\xedr_\xb6\xf3\x8e\xc5\ +\x0b&\xc94\x98=\x8a:?\xfe\xc5\xdf\x85\xe1\x05\xd2Q\x98\xd7\xcbe2?\t\x84,J^\ +\xae\xcb"W\x82\x10\xf7\xba\xfd\xd1(\x88\xbb\xe5\xec\x0f\xa2\x98\xe2\xc6\xc2\ +\x9eLP\x00\x18B\xdf\x80\x10D\x04\xc5(JV\x8a;\x91\xa0\xcedr\xf4\xab\x1b\xba\\\ +\x8b\x8f\x04\xadaw\'1}\xfd{\x93\x1e\x03/L\n\xcb\xec^6\xb5\x95\xf5\\%\xc5\xec\ +\xe6c;\xe1\\u\xec\x96}`d\xf6f7\xb0\x13\xdb\xf4\x83\xbeT\x1cQ\x14rV`\x9d!+\ +\x01\x06\x11u"\x84\x82\xd3\x02gK\xc4\x11\x0fb\x04\x81\xc7\xe0\xee|\xbcqF\xef\ +\xa7\xf3t\x9c!\xe3\xf6\xda"ht\x11\xc8\x0b\xf6TD\xfd\xd1\xa87\x1c\xceO\x8e\ +\x85\x9c\xef\xef\xc5\xabD\xae\xd32]\'E\x9a\xf5\xf6\xf6B\x847\xa7\xda\x15S\'\ +\xc5X\xb1\x88\xb0\x8a\xb0`\x16\xa5d\x02\x82\x80z1\x95\x8a\xd2L\xa1\\\x8c\x8a\ +,\x88:7u\xd5\x16\x1f\x01Z\xe5~\xf7\xb0\x9a\xbd\x9e\xbe\xfa\xad.j"\xb4\xfdbG\ +\xa2Za\xaa\x19\x9d\xc8\x16m\xdf\x1aAm,\xfa\xcc\xbeK\xad_\x9d\xb3v\xf0\xbb;\ +\xabb\xa4\x05\xaf3\xad\xe2\x8d\x85"\x15\xd2\x02\xa5\xd2\xe9\xf0\x08\x84/\xc6\ +\xaf)\xdbI\xff\xd4=\x153\xd6\xa9z\xf6\xec\xe9\xd1\xe7?\xbd\xd4m\xe5i\xba<{G\ +\x9c\x97\n\xcb\xb5,r\tF7Z\r\xa2\xc5M\xd82J\xc4\xe3\xb2\xf3y\xd0\x19eY\xa1d\ +\x11\x15/\x83\xe2\xady.\x03\x08\xe8\xc4A\xa9h\xb9.\xc2(\xeeO\x8e\x86\xfbO\ +\xda\xe1N-4Zr\xbfc\x90e\xfe\xf6\xeb\x7f6\x86L\xcd\x8d\xd1\xa1B\xf3\xdb$\xa1\ +\xcb\x82\x01u\x8e\xd9e\xc84b\xad>\xea\xfd\x01\xd59\xb9y~\x07g\x86o\xdd\xb0\ +\xf1\xd6\x9cGS\xfc2\xe5\xbc\x80\x8b\xb6J\x85\xac`\xa9\x10\x87\xd4\x8d\x10\ +\x05&\x97f\xcb\xc0\xa5\x1a\xbf3\x83\xd4\x8e\xdcv"b[_A*\x94\x92\xc1\x90\x8c\ +\xbf\xf8\xd5\xdf\xf4\x06\x97\x98wIcqv\x9a-\xa7A\x88u*\xd7\x89\n\xb1\xda\xeb\ +\xcc\xaeM\xeeL"\x0c\xc6?\x91\xa2\x1f\x08\x98Zj$\xe4\xf4\xb7(\xe6@\xe5\xf9\ +\x88@\x9c-d\x18 \x10\x10A\xdc\x1f?\x1c\xec?\r[\x0b\xfe\x93GK\xeew\x0c\xd37\ +\x7f\\M\x9f\xfb\x82]\xcbsAT\x99\xec\xf5Z\x8f[e\xbb\xf5\xe5\xe1\xbdn\xf3\xdf\ +\xa9\xf9\x96}\xd2\xda\xcd\xeb\xde[>wk\x13\x8e\xe2W)\xa7\x85\xce\x99!\x10\x94\ +\xe2\xb4@)\x11\x08t#\x8aC\xe8\xc2\x8a\xbe\x96\xbf\x94l\xd7w+%\xb2\x82\x15s\ +\x14\xa0(qx8\xf9\xc9\xcf\xff\xfa\n\xb9\x8beQ\xcc\x8e\xdfA%RQ\x9a\xae\xfat|\ +\xd5\x04H\x07f\xc4ky\x9f\x830\x10\x02\x00\tb\x04\xa2<\xe9\xe0\xb4\xfa\xc5\ +\x10\xd2\x02\xb35\x8f\xfbU\xbe\xbf\x10\xe1`\xf2\xb8\xa5\xf8O\x1c-\xb9\xdf%\ +\x14\xd9\xfa\xed7\xffBPU\x1c\x15\x96\xd9]\xadGQ\x91J-\xa0\xba\xc3\x90y\x1f\ +\xf5S}\xb1\xb6\xcbn4Y\x9d\xb7\x91\xfa9\xdf<"R\x8c\xac\xe0u\xcai\xc1\xa54\xd2\ +U*\xce\x0b\xe4\x92\x05Q\x14R\x14\xe8\x19\\\xed\tk\xb4\x8e\x86l\x87\x97x\xae\ +\x87}\x02\x98\xafM\xef\xe1\xcaR\xfe\xecg?\xdf\xbfwt\xee\xdd\xed\xc4j6/\xd6ge\ +\x99p\xfeF\x9cw\x7f\x17\x013G\x8bt/\x97B\x98tW\x96\x12\xfd(\x19v\x17\xba\x00\ +\x8f\x0e\xab\xbe\x9b\xb3 \xdc\xdf#\xc5(%\xa4\x9d0P\x88p0~\xd4\x9f\x1cE\x9d\ +\xc1\xf5Z\xd2\xe2N\xa2%\xf7\xbb\x84\xd3\x97\xff\x95.\xde\xfaN\xba\xae\x14\ +\xe6H\xbc9[\x9eg\xcb\xbcG\xb6o\x11\xf8N\x1bn\xc8\xf6\x8b\x12\xbbO\xf1\xde\ +\xf7\xec\x02\xe4\x0e\xab\xb6\x19\xc8\x0b^\xa5JS\xbcR\xac\x18\xa52\xe36\x15C\ +\x08\x84\x82\x82\x00\xa1 !L\x10\x02V\xa4k\xd9\xae?\x16\xa5L\x0f\x11\x08\xc4\ +\xa1\xf9\xdc\x96)\xaf3v\xd4\xcf\x8c\xd1\xa0\xf7\xcb_\xfd\xbd\x08\xae\x98k\ +\xc0J\xad\xcf\xde\xae\xa7\x7f\x10\x90W;Cu*P\xa6\x0e\xd6EL`"\x1d\xc3\xa6Qt\ +\x1aR\xa2\xef\xa9\x948[q\x9a\xf3\xfd\xb1\xe8FUb\xa8O\xf1D\xa2\xbf\xf7p\xb8\ +\xff4\xea\x0e\xaf\xd9\x9e\x16w\x0b-\xb9\xdf\x19\xe4\xe9\xe2\xdd\x9f\xfeM\x0f\ +}\xacd\xbb0\xe6+\x99\xf8)\x00\x90\xcb\x8d9W\xb6\xfb\xee\x8ag\xe3P}\xa57\xc8\ +\xd5K\xb9\xd9\xc2\xef\x15e\xfbt\xbe\x8d\xdf\xdfO\xee\x15\xb3\x9b&1r\xc9Y\xae\ +\xd2\x9c\xf3\x92\xa5b\xa5P*\xe4%\x8a\xd2T\xcau\xb7&\xec\x00\xaeM_D\x08\x8aCt\ +"\x08\xaal\xfa\xd9\x9a\x0b\xc9\x95x\x07\xbe\xfc\xea\xabGG_\xecl\xdd\x05p\xfc\ +\xa7\x7f\xa2r}\x9d3\x00\x00XQ\'\xc3\xbd\x82c\xdd\xf8.\xcdCu\xa2ok\x9d\xf1t\ +\xc5\x8aq0\xa4~\x87\x1a\x7f\xc7\x0c\x94\nR\xd6(~t\xf8Y\x18\xbf\x7f\x9a\xef\ +\x16\x1f\x07Zr\xbf3\xa8d\xbbcg_\xb6{\xb3,\x19\xad}\xae\xdb\xbe\x8d\xd9\xab\ +\xb5N\xac\x13\xd5\xd6o\x9c\xac\x06\xae\x11<7\xde\\\x98\xdc\xfdKV\xa3l]\xf0\ +\xb3(U\xa6\'\xcd\x90,%J\xc5E\x89R\x19\x9d\xee?\x1f\x90\x1e\xa7\x0b%\x04\x05\ +\x840$\xdf\xc3\xd1\r"\xa0\x90\x98\xadM\x01G\x1d\xc5\x8d\xe3\xf8W\x7f\xfd\x8f\ +\x17\xcay\xaf\xce\xa5dv6;}\xcdL"\xea\xe7\x8bW\x11e7\xf1\xb7\xc5\x10\x11\xc2\ +\x11D\x0c\x99P9\xd7\x1f\xc2l\xcd\xcb\x94\xbb\x11M\x06\x14\x87\xd8u!\xd6%\x85\ +%+\x00\xad\x17\xff\x89\xa1%\xf7\xbb\x81"[\xbd\xfd\xe6_D5\x89\x92\x91\xed\xd6\ +vo\xba1\r\xd9\xeeGAk\xb2\xbd)\xcf}Fw\xeb-\xd5\xfb\xc2\xdd\x9d\xae\xe6\xae\ +\xd7(\xbd\xb1\xe0o\xf6\x0em\xc0\x1bE\xeb]\xbc\xf1\xa4\xc0\x0c\xc5\\\x96\x9c\ +\x97*/\xb9\x94\xacK\xaf\x94\xb2:\xa5\x96\xf0\x0c\x10X\x93\xbb\xae\xc0\xc3\ +\xf5\xf30 \x08\xeb\x0c\xcbT\x19\xf1\x0e\x00\xf8\xfc\x8b\xaf\x8e\x9e~\xb1\xa5\ +\x81;\xb0>\xfbvu\xf6\xed:-\xf5\xdfS\x1c\xc2\xf9$\xd7\x06W\x1f=Q\x92\xe3l\xa5\ +\xa4\xc4\xb8O\xa3\x1e\xd1\xb6\x92\xf7\x9b\xc7\xeb\x8c \xddu\t\x11\xf6\xc7\ +\x8f\x86\x07\xcfZ\x8a\xff\xb8\xd1\x0eb\xba\x1bX\x9d\xbd\xd4i\x8e[2U\xaaU&\ +\xc9\xafq\xac\xff\xb7_c\xcaMf\xf7\xb8\xdcv\x0f\x1b\xc97\xde\x19\xd8\xef\x12\ +\xc0`\xd2\xf2\x97@\xac\xffs\x17\xf7i\x95v\x89v\xaf\xed\xb6)\xae\x8d\xe6^\xb8\ +jy\x14"\x0cE\x8f\xc1\x0c\xa9\x94R\\\x94\xc8K\xce\n\xcdb$\x08\xcc\xec\x17]h&_\ +\x926\xda\xd1\x8b\x91\x15TH\x10L\n\xe6\xab\x17\xdf=x\xf4\xe4\xe2\xe2}5?I\xd3\ +\x82\x8c\x9b\xc4\xccM\x9f\xe4\x1a0\xdd\xb7b\x94\xc1\xbd\x14y@\xd3\xc3\x89\ +\xe8\x84U\t\x9d\xf7\x1e\x1f\n\x04\x82\xb4\x17\xafd\xb9<}\xbe\x9e\xbd\xee\x8d\ +\x1e\x0c\xf7\x9f\xb4^\xfc\xc7\x8a\x96\xdc\xef\x00d\x99\xaf\x17oQ\xe7s\x1d\ +\x01\xb4"\xbb\xa6G\xf5\xffz\xaa;\xd1\xa0\xfaf\x97\xb0\xc9\xec5\x86w\x14kv\ +\xa9\x8euLo\x93\x0f\x99\x98@v\\\x7f\xc5\xef\xc4`\xd7\xc2ZSiK\xc7\xe3]\xcf>\ +\x8f\xe8\x0e\xa6v\x17Z\x90\xb3\xbbW\x10H\x08t"\x8e#\xea\xc5TH.%J[\xb8\xe6\ +\xbd\xdd\n\x11\xba1\x15\x89r\xbb\xe4E\xfe\xee\xcd\xab\xc7O>\xdb\xb6\xfb\xb63\ +\x84\x03\x85\x99U\xd97\xa5\xd9\xab\xe6\x95\x92\xc2\xf1\x97\x8f\x1e|\x06 [\ +\x9d\xe4\xf3\x17\xf9\xfa\xf4r\'\x81)\x1a\xac\xbd,%\xcb\xd5\xf4\xe5z\xfe\xba7\ +z0:x\xd6R\xfc\xc7\x87\x96\xdc\xef\x00\x92\xc51\xabB\x90\x95\x9a\xf0\x148\xd5\ +\xf9\xaaf\x91\x9b\xc7y4wq\xfe*\xd8\x91\x9aY$\xd3t\xf6"_\xbd\xbb\xc2\xf9k^<\x00Bot\x7ft\ +\xf0\xac\xa5\xf8\x8f\x03\xadr\xbf\xed(\xb2U\x91-\x1cM\x10\xc8\xe8\xcb\xba\ +\x90\xf7\xb2e\xb6\xa0\x92\xd7\xd5\nG\xa8\x96\xb6-\xe0\xbd\xb7\xc4O\xce\n\xb2\ +\x8f\x02\x9a\x0f\xb4BeW\xf6\xc0\xa8vPM5\x10\xcf\xd7\xc7\x97\xf2\x83\x9c\x17\xef(>\x99\xbfK\x16\xefz\ +\xc3{\xc3\x83g\x9d\xfe\xe4z7\xd1\xe2\x03\xa3%\xf7\xdb\x8edq\xbc\xe1\xaa\xe8W\ +\xe3\x7f\xa0\xa6\xd4k\xf0\xe2\x93\xc6\x1e\xa9h\xd2\xc5)\x9b\xccN\x82\x9cd\ +\x17\xd0\xffj\xe7\xf2Nm\xa8D\x81\x99\xc8pf\x95.\xbe\x9d\xcf\xb7\xae\xf5\xdcu\ +\xd7*O\xb6\xbb\x9e\xcb\xc6\x12\xac%cK\t\xd4\xdd\xa7\xa6#\xa4\x9b)\x04\x04 \ +\x04)\xc9RAVI(\xe6c\x8cC\x04\x82\x94\x82\xcby\x9f\xcf\xa7\xeb\xf5\xb2\xdf\ +\xbf\xa8\x1f\xbd\xff\xf0\xc7y\xbaL\xd7S\xd8\xc0\xac\x05\xdb\xdf\xd6\xfb\xc5<\ +\x11\xa4\x82\x8a\x1f\xde?\xfaqp\xb1\x88n\xd8\x1d\x8f\x1e\x8de\xbeJf\xcf\xb3\ +\xc5\x1b\x98\xd4\xc7\x0b\xc1Q\xbcR(\x15+\x85dy\x9c,\x8f;\xfd\xc9\xe8\xe0\xb3\ +\xee\xf0\xbc\xae\xa5\xc5mFk\xcb\xdcv\xbc\xf9\xe6_K\xab\xdc\xab\xb1K\xae\xfc\ +\x80eg\x00:\xf1\xcf\xcfttN\x8e\x039\xab\xc3\x91z]\xa7W,O\x01 \xaaDzl\xf0\xbb\ +\x0ehj\xeed\x06+@1+f\xb0\xf1H\x00k\x93X\xbf\xc6\x1cY\x8b\xaaz\x86\x8c\xbd4\ +\x99G\x91J\xbc\x9b6\x18\xa6vn\x0c\xb3bVJ9[F\xd9\x9a\x036\xce\x0bV\xac\xe0\ +\xb5\x14&CF1\xa4\xd2v\xbc\x89\xf9\x12h\x9e\xa8$\xd7N\xbci\xe4\xe3\'\xcf\xbe\ +\xf8\xd1\x9f]\xfc\xf7U\x16\xd9\x9b\xaf\xff\xb5,\xb2NDQ\xa0\x1bB\x92z\x92\x83\ +\x90\x13A\x85_\xf3k\x13D\xc8T\xdc?\xf8j|\xf0\xf0\xe2\x17\xf5\xa1)>_\xbecU^\ +\xe5pM\xf1\xf6\x17\xd4\xe9OF\x07\xcf\xba\xc3{WkL\x8b\x0f\x88\x96\xdco5\xca"}\ +\xf3\xbf\xff/\x11\x0b\x93\xfcBz$\xba\xc7\xf2\xde\x80\x1f\xe2\xc6\x90\xa3-\ +\xe4\xee\xe56R\xc5\x9f\rX\xc1N\xa6\xdad\xe5\x9cT\xf0\x8buYrg\xc5\xbe\xf5\xcd\ +\xbc\x83\xdc\xbd\xdc\x19\xfd\xe2\xf9\xfb\x96\xdaE\xf5\xf4\xe0\x05\x08,\xb1\ +\x9b\x13+\xa54\xa1+\xbb\xa0\x0c\xebW\xd7ac\xd0\x03\x80b\xeb\xf9\xdbB\xc1\xcc\ +\x90\xcaV\x8a\x04\xb2\x82gk\xdf\xb1G\xa7\xd3\xfd\xab\xbf\xfe\xc7\x0b\x86U5\ +\xd2\xe5\xe9\xdb\xef~\x13\t\x15\x87\x0c\n\xb9\xf7\x0c\x9d\xfby\xa1T\xb1\x8a\ +\xcbW\x81\x9cn\xd5\xefZ\xb0s\xe7\xe1\xe1\xe3\x8b\n\xf6s \x8b4\x9d\xbf\xc8\ +\xe6\xaf\xae@\xf1\x0c\xe8\x01\xc0\xb6\x84\x01:\xbd\xf1`\xffi\x7ft\xbf\xf9}jq\ +\x8b\xd1\xda2\xb7\x1ay2wO\xf3T\xa5\xfdY\xe8w\xcc\x15K\xc2\xcb\xd2\xa8S\xb1\ +\xcf\xa4\x80elr}\x84#v-\xd8=f\xdfB\xee.\xbb\xd1S\x06,\xa0{\x97\xaa\xec\xc0E`\ +\xedv\xdb]\xd9\x07\x13\xdd:a\x9a\xea\x9a\xed\x8c\x14\x905e\x8c\x13T\xd92\xb4\ +e`\x8f=\xc66\x8c\xdcS\x00\t\x02\x834\xddG!\x05\x01\x97\xd2}\xe4\x9c\xa5\xe9t\ +zzpx\xff\xa27\x04t\x07\xfbA\x18+\x99\x12\x10\x8e\x8e\xca\xe80\x10\x1c\x05\ +\x90\x9d\x01\xe1+\x9e\xfd\x96\xcbU3\x84@Hs\xccS\x1e\x882\xcf\xd6\xbd\xf0\xba\ +!\xcd \xea\x0e\x0e\xbf\xea\xee=I\xe7/\xf2\xe5[Uf\x17?\x96\x80@ \x10\x90L\xa5\ +\x84b\xce\xd6\xb3,\x99-\xbb\xa3\xbd{_\xb6F\xcd]AK\xee\xb7\x1aE\xba\xa8\x94\ +\xf8\x06Y\x1b\x9b\xb9\xda\xec(\x8d\x08>\xa17\xd2\xf2*\xcf\xc6\xbc\xd4\x98=0\ +\x9c.\xea\xca\xddo\x80\xcb(a\x82R\xe6\n&j\xba\x9d[\xd1\xa0\xfb-\xb7d\xedug8\ +\xf9\xcf\x17\x86\xf9u\xfe<@pS\'\x111\xb9)\xf3l\xffV%g6?\x19\xb7\x9e\xcd\x15m\ +d\x98H\x07\x82\x11\x07\xe4\x8ft\x05pr\xfc\xe6R\xe4\xbe\x9a\xbf+\x8b$\x10\x00\ +D\xba*\x12y\x1c\x86\x02 !\x04(\x80\xec\xc6XV\x1f\x01A1f+^\xe7\x00\xb0\x98\ +\x1e/g\xc7\x83\xe1\xe4\xe0\xc1\xb3\xe1\xf8\xbaf\x88\xa6\xf8\xde\xe4Y6\x7f\ +\x95\xce_^\x8a\xe2\x01\x04\x84 \x84T$\x15$s\x9e,\x8e\x9f\xff\xba7\xbc7\x98\ +\x1c\xb5\x14\x7f\xfb\xd1\x92\xfb\xadF\x99\xfb\xc5\xa7\x08`\xf7XLd\x9cb\x0b/\ +\x80g\'\x19\x82\xc7c\xb0\x04i\x19\x1d\xf0i\xdd\x18 \x02\xc2\xd1\xfa\x0erwJ\ +\x19\x04(\x1bY%K\xeeM\x89\xbc\x1b\xd5\x9d\xd4e{\x8d\xe7\r\xb3\x93+\x8ff\x9e\ +\x0b\xec\x05\xd8(\xec\x1d=\xcaNT\x11_w\xa4iv\x1c"\xc9\xed\x1d31x6=+\xcb\xe2\ +\xa2\xa3U\x99\x97\xa7\xdf\x81\x89\x99\x15P\xa4i\x9a\x95\xdad\x02\x91R\xe8\ +\x04y\xa7g\xc6\xaf\x12!+p\xb6\xe2\xa2\xe4q\x9f\x88\xcct\xb2\xc9j\xfa\xfc\x7f\ +\xa7\xfd\xe1dr\xff\xc9h|\xdf\xc5\x93\xaf\x06\x11\xc4\xbd\xfd\xcf;{\x8f\xd3\ +\xe9\xf3t\xf1\x8aeq\xa9\xc3\x9d\x8a\x97\x12Rq\xb2p\xe1\xd6\xd6\x8b\xbf\xd5h\ +\xc9\xfdVC\xca\x1c0|\xea\xa7\xc4Xe\x0e\xbb\xd5\x8b\xa3R\xb5\x16n/v\xbcnv#k\ +\xbf;\xeb\x1dd\xdd\x18\xcd\xecN\xbf7<\x19\xf2=\x19\x9b\x16y.\xb7\xee\xd8R=}X\ +:G%\xdbmP\xd5\xae\xab\x92-I\xfbS\xe6\x9a\xe4\xdac\xff\xf7N\xef\xa1\xdaR3\xfe\ +u\x1a\xa5\t\xa0\xea\x96\x86\x01\x84\x80R\xf6\x9a\x84"\xcf\xe7\xb3\xe9E\xc5;\ +\xd1\xe4\xc1\x8f\xe6\xa7/\xd2\xe51\xb3\x8a"\x15q$\xd9\xf4\xcaA :!\xbb.e\xb6\ +\xe6\xf9\x9a\xa3\x00\xbaf/L<\x13JA1T1;y>\x9d\x1f\x8f\xc6\xf7\x9e\x0e\xc7\x0f\ +\xe8z3n\x8b \xee\x1f\xfe\xa8;~\x92\xcc\x9eg\x8b\xd7\x97\xa6x\xab\xe2\xb5\x17\ +\x9f\xad\xa6\xd9zj(~p\xd8z\xf1\xb7\x10m@\xf5V\xe3\xf5\xff\xfc_U\xa6\x86\xed\ +\x84\x13\xc9\xceR\x815.<\x9b\xdd\x13\xd9\xfe_\\\x95\x80"\x8c`\x17V\xb0\x0bA$\ +\x02P\x00!\xcc\xbf\x8a\xdf\x05\xfc\xfc\x1bX\xabZ\xffS\xca\xfcT\x96\x90\xb8\ +\xd4\x03\x8aT3\xb2ZK\x91q\x8d\xb5\x890\xcd\x88\xae{\x07\x13P\x15\xd5\xd5\xa1\ +\xbc`*K\x9d*\xa3\xa3\xa9\xfa\xc5\xa4\xeb\xd8\xdd\x01\xb3\x12\x00C\xd9v\xe8\ +\x024lgkb7o\x1f\xf4h&\xf3!+f0\x8e\x9e~\xf6\xf9\x97?\xb9\xd4\xefn\xbd8^\xbd\ +\xf9\x8d\x10AN\xf7R\xd5e\x90 \xea\x88\xa4\xa3\xde\x02*+1]r^\xf2\xa8G{}\x12\ +\xf5\xce\x91\x01\xa9\xbc\xda\t\x8c0\xee\x0f\x0f\x9e\xf5\xc7\x8f/\xd5\x86]Pe\ +\x96\xce_e\x8b\xd7\xaaL\xafp\xb8\xed\x81\xcc\xe3O\xdc\x1d\r\x0f>k\xc3\xad\ +\xb7\r\xadr\xbf\xdd\xe0\xda\x84\x0f\xcc\xdc\xfc\xf3!#\xe2}a\xef\xf30\xb1\x93\ +\xc5n\x9b\xeb\x1d\x9c/#\x00\xab\xd9k\xca]\x98Q\xb0\xb5+V\xcd\xb9\xb8\x19r\ +\xdeN\xce\x93\x81k\x9b1\xdd\xed3\x86h<7\x98\x9c\xf1\xca\x84\xbfL\xf8\xd6=\ +\xca\xecnZ\x14"-X\xd73\xd0\xe7O\x92\xe4\xa2\x97\xb0\xe8\xf6\'+\x11\x82\x8b\ +\x18\xef\xa2h\xc4\xd4\x11\xc8E9W,\x17\tfk\x0e\x03\xdc\xdb\x13\xbdxK\xfd/\x02\ +B\x01fH\xdb\x1b\x95\xf9z\xfa\xfaw\xeb\xd9\xeb\xc1\xfe\x93\xde\xf0\xba4*\xc2N\ +\xff\xe0\x8b\xde\xf8I:\x7f\x99\xce_]\x96\xe2\x8dQcU|\x9e.N_\xfe\xe7\xb2\xa5\ +\xf8[\x86\x96\xdco7|\xb7\xd57X\x00\x06\x04\\\xdc\xd4\xb3\xd5\x9bg\xd8B\xce.\ +\x9c\xe9\xb2\xdd\xb7\xfds\xcc\xee\x9e\nl\x0bt\xbe\xca\xeeA\xa7\x17`[?\xa2\ +\xea\x87R\xab /\xfc7\xfe\x81U0\xc1oU\xa3\x01\xdbQq(\x81@&\xf0Z\xc5\xa1\xcd\ +\x91Q@\x82L"\xa0v\x8e\xd6\xab\xa5RJ\x88K\x18#$\x04($\x94\xcc\x8a\x8a\xa9\x00\ +\xb4\xa5~\xb6BZ\xf0\xa8G{=\n\xc4y\x9d#\x11B\xaaT<3\xf2d\x96\'\xb3ew8\xdc\x7f\ +\xd6\x1d\xdd\xbf\xa6QCA\xd4\xdb\xff\xbc\xbbw\x94.^\xa7\xf3\x17\xaa\xb8\x12\ +\xc53I\x05\xa9,\xc5wF\xfd\xc9\xe3\xfe\xf8\xa1\x10-\xb7|`\xb4\xbf\x80\xdb\x8d\ +\xcdj(\x15\xb3\xc3\xbc\xa3\xfa\xf3\xbc\'\xd2=\xfb}\x83\xf5\xab\xdcq\xcf\xd76\ +\xb2\xdd\xcb\x80\xacu\x0e\xb5G\x82m\x14ZO\x82\xdc\x9e\x8e\xd8\xbc\x97\xea}\ +\xd3K\xf2\x1a\xe0\xfc&W\x06\xa5\xd9\xb7P\x15\\\xe5\xcd<\xcd\xcd\x8f\xd0~Tz\ +\xfa\xba\xba\'\xa2iKI\xb7?ei\x92$\xab\xc1`\xb4q\xcb;A$\xa8s\x80\xf4\xa56\x9e\ +\x981]\xf3t\xc5q\x80\x07vV\xbc\x8b\x17\xec\xd5\x14/\x15\x00\x14\xe9r\xfa\xea\ +\xbf\xc3\xd3o\xfb\xe3\xc7\xfd\xf1#\xba\x1e\x8dR\x10\xf5&\xcf\xba{\x8f\xb3\ +\xc5\x9bd\xf6\\\x15\x97{F\t\x08A\x00)HJH\xe6<[\xe4o\x16\xcb\xb3\xe7\xc3\xfd\ +\xa7-\xc5\x7fX\xb4\x1f\xfd-\xc7\x0e=\x0e\x1dX\xac\x15T\xe7\x06m\xd5\xc0\xfe3\ +\x00\xacKO\xf0H\x9c\xae\xb9\xfc\xee\xa5v\tv\xafv\xe7\xc6\r\xfa\xbe:W+\\\x9e&\x01\xae\ +\x9ab@\x08\x03d\xaa\xcaB\xca\xb34K\x93^\x7f\xb0\xa3\xa9\xef\xc1`\xfch=\x7fKE\ +\xfa\xe8\xe8\xe9xRi\xd8\xaaf\xaf.\xcb~\x99\xd4dG\xf1\xfa\x1f3\xf2tv\xfar\x16\ +w\xf7\x06\xfbO\xbb\xc3{\xd7M\x8d\x0f;:5>\x9d\xbf\xcc\x16o.\x95TC\x1bI5\xe9\ +\xf2$]\x9e\xf4\x86\xf7F\x87\x9f\xc7\xbd\xbd\xeb4\xac\xc5E\xd0\xe6\xb9\xdfj\ +\xac\xa6/\xe7o~o\x87\xda\xd8\xf0\xa2K$\xb1\xe6\xb9\x13\xeen\xab\xd9\x81H\xb3\ +{=\x99\x1cB\x08\xe1R\xdc\x85 \n \x02\x04\xa2\xcasw\xa3\x99*e\xed\x98\xd0f\ +\xb8\xfb\xe9\xedJ\x82%\x9b\\s\xf6jCZ\xe2\xf4+\xce\xe8\xc6\xb8\x16\xd9D}/\xbd\ +]\xd4\x93\xdc\xa9\xde\xd3\x80\x95\xf4\x8a\x85\x99\xffu\xda\xbb~\x0fg\xf7\x13\ +\x18`\x05\xdb\x14K\xeb\xa6I\xf5Zr\xbf\xedXO_N\xdf\xfe\xde\xd0\ +\x1b\xd9\xc22v`)\x9aR\xbd\xb6\x06\x1e\xe9\xeb\x03\x84\xa7\x92\x89\x8c;c\x9c\ +\x19\n\xea\xb2\xdd\xa5\xbd[\xf8\xb1S\xe5\n\xcbhC\xc6\xce\x81dY\x17N\xb6{f\ +\xbb\x03\xf9\xff\xe9\x969\xa9\xee\x9ag\xb7\xf9\xb6Le\xa1x\xd3\x82X\xcf\xbd\ +\xf2j4\x93\xbb\xafv\xcd\x96\x81%w"\x17\x18\xb6g6w\xe6P\x94\xc8K(\xe6\xb4\x00\ +\x01\xddn\xe7/\xff\xfa\x1f\x85\xb8\xc4\xc4\x1d7\x02Ve:\x7fu\x83\x14\xdf\x1f?\ +\xea\xed=\x12\xc1u\xa7\x04\x81\xf1\xe2_\xa7\xb3\x177B\xf1qoot\xf0\xec\xfa\ +\xf5\x15Z\xa0%\xf7\xdb\x0fY\xa4o\xbf\xfe\'-1-\xb3\x1br\x87\xf5\xdf=\x93\x1d\ +\xa8\x93;,\xe9;\x97\xdbIx\xad\xdc\xad=C&\xacJ^\xb1_`\x83\xdc\xf5O;\x1c\xde\ +\xca\xf6\x06\xb9[v\xdd\xce\xec\xa6\xe1\x9e\xe9\x0e\x9f\xd6\xbdG\x0c\xbb\x1bl\ +\x16\x90\xa3`\xff\xf1\xc0*w\xd9\xbc>{\rW6\x84\xea\x8cuK\xee\\\xd9Gur\xd7\x7f\ +\x19B /1[1\x800\x0c\xff\xeao\xff\x9f\x8b\xd6\xfe\xbdi\xb0,\x92\xd9\x8bl\xf1\ +\xea\xb2e\xd9\xb1\xc3\xa8\x19L\x8ez{\x0fE\x10\xdfH\xdb\xb2\xe5\xdbt\xf6B\x16\ +\xeb\xdaz\x00\xbbs\xa1\x1c\xa4\x99\xb8\xdc|\xf4\x9d\xde\xde`\xffYot\xddl\x9f\ +O\x1c-\xb9\xdf\x01\x9c|\xf7\xefyr\x06\x8f\xa6\x9dB\xaf\xf90\x04pSm\xfb\xe6L\ +\xc5\x9c\r\xf1n5\xbc\x11\xef\xd4(\xe3n\x8d\xfbF\x06\xa4R\x80\xb4n\x8csIL\x92\ +LM\xb7\xeb\x83\x19~|\xc0\xf7e\xfc\x8e\x07\x9e\r\xef\xf7\x01\xd5\xf5\xfdN\x04\ +\xe0\x86\xe1\xeeZ`u:A\xf7D\x0c\x866^\xec\x0frV\xbbs\x906\xc9]\x7f\xb8\xf3\ +\xb5*J\x10\xd1_\xfe\x9f\xbf\xeb]x\xbe\xec\xef\x03F)_C\xc5+\xaf\xdb\x13A\xdc\ +\x9f\x1c\xf5\xc7GAx\x13\x14\xafd\xb6|\x93N\x9fk\x8a\xf7\x99\xe5":\\2t\r\x03\ +\xbd\x7f\xd8\x19\x8e\x0e\x9e\xf5\xf6\x8c\x89T\x142/\xca \x10\xdd\xce\x87\xe9\ +\\\xef\x1cZr\xbf\x03X\xcf^O\xdf\xfc\xd6\x86R\x89\x88\x1d\xe3\xe9\xb1\xab\xae\ +N\x0cW\x1d@\xa5\x9a\xdc\xdf\x95\x10\xb0\x13\xd7y\xe2\xbdF\xefdgb\x12\x80\xdf\ +u\x00h\x90{5cjC\xb1\xa3\xa1\xdb\xd1\xf0\xdc\xab\xee\xc8y.[\x94;\xaa\\\x1a\ +\xb7\xab\x8e\x93\x9akX)\xee\xe6\xc5\x96\xce\xf3\xb7\xa9\x8d\xb0\xa3x\x9d6W.\ +\x0fR+w+\xf0m\x8bm@\xa1\xfe7ADI\xce\xcb\x94\t\xf8\xe5_\xfe\xcdh\xef\xc3\x0f\ +\xa6gUf\xcb\xb7\xe9\xec\xb9\xacM\xe7r\xb1c\x9b\x14O"\x88z{\x0f\xfa\x93\'a\ +\xd4\xbb\x89\xb6\xc9|}\x92N\x9f\x17Y\xad\xbe\xc2\x05}\x16\xa9\x07\xdf*\x9d\ +\xd2\x890\xee\x0f\x0f\xbf\xc8y\xb8L\x14+\xc5J\xc6\x11\xdd?\x1c\x85Q;F\xe7=h\ +\xc9\xfd\x0e\x80U\xf9\xf6\xeb\x7fV2\xd3jW\x18\xd5\xab\xf3\xc9,G\xc2\x8a\xf7\ +\xda_Qm\xcal\'\xdeA\xa8\xe6\x9f\xf6\xf2\x0f\x85\xf5\xe4\xbd\x1cDw>\x13\x9b\ +\xf4\x98\x9dk\x16\xb7\xe7\x93l2{\x9d\xdd+\xc3\xc7S\xe6V\xc4W\xb2\x1dMr\xd79\ +\xe9\xca\xbb\x06`\x9f\x1c\xe0R\xdd\xad\x18\xd7m\xb05\x04\x1c\xb9;g\xc6\xb6\ +\xee"\xe4\x9e\x97\xbf\x03\x86\xd6=\x8b\xc6\x87\x8b\xc5\ +\xc2y"\x00\xa0P\x89\xf3&\xaa\x04\x99\xc6\xd8\xa5\x1a\xa8z\xf1=\x17g\x17\x99\ +\xb7\xd4\xa0\x7f\xd4\xc8\xdd\x9d\xdd\xb8A\x9a\xe5\x95\xb4Dm)\x1b\xbaJ\xa4\ +\xe7*\xc1EP\xf5\xa7\xe3\x91\xbb\xffdRo21c\xb6VR\xe2\xab\x9f\xfc\xfc\xfe\xc3\ +\x9b\x991\xe3\xc6\xc0\x9c\xaf\x8e\x93\xd9\xf32\x9d]\xfa\xd0M\x8a\'\xd1\x1d=\ +\x18\xee?\r;W\x1c\x8b\xdbl[r\x9aL\x9f\x17\xd6W\xbc\x14t}\x05i\x92U\x95\x88\ +\xfaa\xff~\x7f\xf4\x10JH.\xc7\xfb\xd7\xaa\x95\xf6\xd1\xa3%\xf7\xbb\x01Yf\xef\ +\xbe\xf9gV\xa5\xe5]\xb6:\xd7%>j\x1by\x0b\xbf\xdb\x1d\xcc\x82cO"\x08\x9b\x88h\ +\xf8\xbd\x9e\x99\xe8\xf30\\q-\x97j\xa8\x89\xb6b\xd3\x8b0\xbb\x83G\xeb5\x8f\ +\xa6\x96!c\x1d\x1b\xb3\x8f\xbb\x96\x17\x02\xad\x16\x15\xb3\x92\xd6]\xb7\t0pA\ +T?\x9a\xea~VV\x939\x8a\xbd\xdd\xea\xed\xa5U\xcaI\xce_\xfe\xe8\'\x8f\x8e\x9e]\ +\xee\x97\xf7C\xa1X\x9f&\xb3\xe7\xc5\xfa\xf4\n\xc7\xca\x1a\xc53\x91\xe8\x8e\ +\xee\xf7\xc7\x8f\xe3\xde\xcd\x10\xe8u\xdaf)\x1e\xcc\n`\x11\xf6E0V\xd4?\xfa\ +\xf2\x8b\x1bi\xdb\xc7\x8a\xd6\xb7\xba\x1b\x08\xc2No\xf4`={\xc9\xd5dL\x046Ed\ +\xf4\xf4D\x9a\xfft\xf5+\x18G\xc6f\xcepm\xaa&\xd6\xc1D\x90\x02\x0bek\xc3+\xe8\ +y\x9b\x14H\xcfvd\xd5\xb5\xfb\x8bg;\x80\xb3\xe6\xad;\xa9\xdc\xfc\xef}`3\x8f\ +\xb7\xd1\xd7\xd6jb\xd3b\xb8Wr\xe6\x8e\xe1ne"\xa3\x15\xb9\xa3\xf2\x8d\xdc\xd9\ +\x9b\x97\x03v7\x8b|:\xa7\rn\x07#\np\x95\\\xbf\x1f\x10Q\xff \xea\x1f\x94\xe9,\ +\xd1\x95\xc8.\xa3\xdb\x02B@\xac\x18\x92u\x9cY%\xf37\xc9\xfcMgpox\xf0\xf4\xfa\ +\x14o\xdb6_\x9f~\xadU\xfc\xc5\xa1K\xe8\x04\x02R\t\xa9X\x95\x89*\x13Pg5\xed\ +\xf4\xc7\x0f\xdb\x8c\x9a]h\x95\xfb\x9d\x81\'\xde\x1by2:H\xea\x16k\x192\xf0\ +\xb2]*\x17\xdd\nb?M\xa5\xf2hP\xe5W\xd6\x9e\xa3\t\x96\xb7\x9dlvD_\xadm2\xbb\ +\xedi\xdc{\xdb0\xcf\xd0\xf7\x86\xacz\x1b\xc9\x97\xee5r\xb7j\xdc\rW2aU\xa9\ +\x1c\x83\xfb\xb2\xbd\xf2a\x9c\x9b\xa3?\x8b*[\xa6\xe6\xcc\xb8\x9d\xfd\x9bPL\ +\xf3\xb5\xfa\xec\x8b\xdb\xab\xdc}\x94\xe9<\x9d\xbf\xc8\x96\xef\xc0\xea\xfd{\ +\xd7\xa1\x18\x92\xad\x85E\x00\xa3\xd3\xdf\x1f\x1c<\xed\x0en\xa6\xa0c\xbe|w\ +\x05\x13\x89Y\xea\xd1\x18E)K\xa9\xf4\xb7>\xec\x0c\x87\xfbOz\xa3\xfb7\x92\xb3\ +\xff\x91\xa1%\xf7\xbb\x84\xc5\xf1\xd7\xcb\x93?y\xd1G\xb6\x1cmvh\x90;\xaaM^d\ +\xd5f\xd5l\xe7wTvI\x83\xde\x9d\xae\x86\x15\xec\x8e\x1c\xb1\x95\xd9\xf9\x9c\ +\x99\xf8\xec)+Z\xf7\x9a\xef\xb1\xbbn\x90\xf3U\xfc\x0cK\x06\xac-\x04\xd6\xb3`\ ++U\xb1\xf3\x06\xb9\xc3#n\x9dnW\xeb\x03\xbdN\x7f2<\ +\xf8\xac38\xb8\x91\xb6\x15\xeb\xd3d\xfa\xdd\x05U\xbc\x02\xba\xa3G\xbd\xbd\ +\x87"\x10E\xb6Lf\xaf\x93\xe5\\\xb1\x99>7\x8c\xba\x83\xc9\x93\xc1\xe4qK\xf1>Z\ +r\xbfK`U\xbe\xfb\xfa\x9f\xa5\xccl\xda \xaa\x81K\x8e!\x05Q\xfdwj\xd2%\xc9T\n\ +\xf6\xd9\xba\x96u\xe8D{\xc5\xad\xb5\xab[\xcf\xdd\x93\xbf\x95`G\xc5\xef\x9a:w\ +\xd3:\xb3k\x95\xf7\xf4Q\xb5\xc9_\xe5=kTWu\xee\x8aM\xa9\xd7\xec\xacT\xbd:X\ +\xb5\xa7\xa3l\xd4\xb8\xdb\xc5Z\x89M \xc1\xeb\x06P=\xee\x80\x89\x99A\xb4\xce\ +\xf8\xe1\xd3\xbbD\xee\x1a\xb2H\xd3\xf9\x8bl\xf1\xfa\n\x95\xc84\xc5+O\xfdw\ +\x87\x87\xc3\xfdg\xd7\x9c\xf8\xc9\xa1X\x9f&\xf3\x97\xc5\xfad\xbb\x89DP\nE)G\ +\x87?\x1a\xdd\xffR*\xccf\xcb\xac\x90\x83\xb8\xe0\xb3\xdf\xe52\xd3F\x8d>2\x0c\ +\xbb\x83\xfd\'\x83\xf1#q\x139\xfb\x1f\x01Zr\xbfcX\xcf^\xcf^\xff\xb6\xe2b\xdf\ +\x8da\xebj\x10|~o\x88w\xb3\xd2n\x13\x1e\xc9\xba>\x03\\u\x17\xd4\xe0\xe9z\xbc\ +\xb4\x12\xd2z\xdb\x86\xe6\xb5\x87l\xc0\xebd\xaa\xcb\xbb\xc5\xaaU\rr\xafN\xe6\ +\xbb\xed\x0c]o\xd8\xa9vj\x92\xbb\xcf\xda\x00\xeb\x88\x85U\xfd6\x03g\xbb\'\ +\x03"V\x0cBV\xe0\xde\xd1\xdd#w\rUf\xc9\xf4\xbbt\xfe\xf2\xcaF\x8d\xae7\xa1\ +\x7f!\x9d\xfedp\xf0\xec\xa6\x8c\x9a2\x9d\'\xb3\xef\x1aq\x02\xc5($\n\xa9b\x11\ +?z\xf2\xf3%\r\xe7\x8b\xb4(\xa4b\x16D]\x9e\x85\xe5w\x04\xa9\xec\x0c\xddZR\x04\ +ag0y<\x98\x1c\x05a\xe7F\xdavw\xd1\x92\xfb\xdd\xc3\xe9\xf3_\xe7\xeb3\xe8\x02\ +\x01\x8e\xd3\x01\xa0\x96\x19\xe9\xf1\xb3\x0e\x8b\xb2\xaf\xdf\xcd\xfe\x80fw\ +\xbbX92\xfe9\r<\xbb\xc5\xbdx\xdf\x9f\x8d\xaf\xd2E\x82\xaa\xf0x\xbc\xa6\xe1\ +\xdd\x13\x05`\'8\xad\xf5#\xd6KAM\xb9W{xNN\xdd\x991\'\xf4\x1d\xfc\xf7\x18\xee\ +\xae\x01\x85\xc4\xe1\xd1O\x1e=~z\x91\xdb\xba\x9d\x90\xf9*\x9d\xbf\xbcZ=a3\ +\xb7\x1f\xd7)~\xf2\xa4;\xbc\xd7|\xca\xbb\x12\\\x9c@JUH\xc3\xd7\xccj\xaf?\xe9\ +\xed\x7f>+\x82^76U\x84\x18\xa0\x10\xd91\xad\xbf\xf6\xdbVQ|\x10\x0f&\x8f\x07\ +\xfbO>e\x8ao\xc9\xfd\xee\xa1\xcc\x93w\x7f\xfa\x17\xb0\x146\xd6\xe82\xd9\x8d\ +\x87n\xd2e\xe02%I/[\xf8t.\xfc?K\xaa4\xbc\x17\x95\xf5\xd8\xdd\xe3M\x8fgk_\xa2\ +\xf7~\xa1*\xb7\xa3\xd6\xcb\xb8W\xf26{AWk\xb4\xfb\x9d\x89\xf3\x7f4\xb3;\xb3\ +\xbd\xde\x01\xd4\x9a\xe4\xc8\xdd9\xf8\r\xc3\x9d\xc8R?\xd7I\x9eQ*\x1c}\xf9\ +\x97\x93\xfd;?Q\x9c5j\xde\\\xa1\x9e\xf0&\xc5G\xdd\xd1`\xffi\xef\x86f\x05)\ +\xf3\xd5\xec\xddw\xab\xd9\x1bS-B\xa9\xbd\xf1C1z\xaa\x14;\x0f\x91\x01AB1\xe4\ +\xec\x0fT\xcel\xbe\x17\x14 m\xaf\x00P\x10F\xfd\xf1\xa3\xc1\xe4\xf1\xcd\x0c\ +\xcb\xbakh\xc9\xfdNb5}1\x7f\xfb\x87Z\xce;\x00\xcf\x88\x07l\xd4\x14\x86\xab\ +\xd9)\xf7:\xb9[\x17\xa6Z\xe1\x9b7\x1b\x82\xac\xd2\xec\xd8\xd0\xea\xe7|\x95.\ +\xf6%\xabE\x82\xfdHk\xdd\xeb\xf7\xce\xc9l\x98\xda\xf8\xed6\xc0k\xf6!\xa7\xcd\ +\xeb\xcd\xf0&`\xf2<\x19\xd7\x9dT\x06\xbdw6\x06\xa4\xc2\xd3\xaf\xfejo|[F\xa8^\ +\x13J\xe6\xe9\xfcU:\x7f\xc9\x17\xa8D\xe6~\x83\xfa\x97\xb4I\xf1ag0\x98<\xe9\ +\xef=\xa4\x9b\xa8\x9aYd\xab\xe5\xd9\xcb\xe5\xec\x8d*\x0b\x11L\xa4\x18\xe9&T\ +\xcf\xa2\x82\x98)\x90\xa7\xfdx\xc1\\\xfb\x9aZ\x8a7\xb1\x1f!D\x7f\xef\xd1\xf0\ +\xe0\xe9\xa7F\xf1-\xb9\xdfU\x9c\xbe\xf8M\xbe:\xb6\xa69\x9c6\'\xda\xe2\xa8\ +\x10\xd9\xd96\xfc\x00,\xc3\xe3q\x0f\x1e\xaf:\xa9\xd4\xa4q\xcbwt)N?\xff\xbbF\ +\xb5\x17\xd7\x14\xaf/\xa9\x9f\xc9(wB\x95&C\rr\xaf\x95q\xaf\x8e\xddi\xb8\x93O\ +\xeeN\xdd{\xe4\xfe\xf9\x9f\xfd\xed`8:\xf76\xee\x18tA\xc7d\xf6\\\x15\xc9\xce}\ +6\xd6lR\xbc\xfe]\x85q_\xab\xf8\x1bI\\)\xf3dq\xfa\xe2\xf4\xdd\xb2T\xa1\x105\ +\xe1\xa13_\xa3\xa8$\xcc\x86\x1d\x16\xdbdH\xa9 e\x8d\xe2\x07\xfbO\xa2\x1b\x19\ +y{\x17\xd0\x92\xfb]\x85\x92\xf9\xf1\xb7\xff\xa65\x17\xf9\x1c\xadk\xbe\x83@U\ +\x04\xd5\'w\xb3\x97\xfb\xe9\xc9|\xd4W\xfa\xb6wS\xa6o\xf3\xd3\xb7}\x934/n7dw\ +\x7f\xf3\x9aM\xa9\xf2p\xbc\xc3|W\xc8Z4U-0\xb7\x8f\x8d\xb1V\'tV\x8c\xdd\xc1K\ +\x82\xf4\xe2\xb7\xee\xd5\xc6i\xc1\x14|\xf5\x8b\x7f\x88\xa2\x8f\xd0\xc6e%\xb3\ +\xc5\xebt\xfeR\xe6\xab\xe6\xa6\xddG9\x8a\xd7,\xef(>\x08;\xfd\xc9\xd1`\xf2\ +\xf8F\xea\t\xbf\xfc\xfa\xeb\xe5*!\xff\xa9\x93\xc1\xccD\xe8\xf7;\xb3\xd9\xabA\ +G\rbY\x97\x05U\xe3+\x8a\x07HPo\xf4`|\xffG\xc1\xc7\xf8Kl\xa0%\xf7;\x8c|=={\ +\xf1k\xb6u\xde\xe1(\x9b\xec\x03\xac\x9f\xea\xe8\xc8\xbd.\xd8\x8d\x1f\xcf\xd5\ +{\xb3\xde\xbe8\x0b|\x97N\xdf\xfe\x05\xda\xf6\xbd\xaau/[\x0f\xda\xb2\x8e\xaaM\ +\xd6\x9d1w\xc8:A\x91\x98m\x9e\x0cUU|5\\\xde;3\xb1wB\xab\xc8\t6\t\x12\xbe\xe1\ +n\x9b\xe2\xdc\'M\xfdA\x18\x7f\xf5\xf3\x7f\x10\xc1G;\xae\x9bY\xe5\xcb\xb7\xc9\ +\xec\x85\xcc\x16f\xcd\x05\x8e\xf2)^\xd7\x9b\xb4\x14\x1f\x87\x83G{\x07GQ\xdc\ +\xbdN\xab\x92\xf9\xf4\xe5\xcb\xb7\\\x99/\xe6\xbb\xd0\xebtU\xb9\x8az\xe3<\x9b\ +\xc6\xeaM\x14\x06\xbb\x9a\xab\x9f\xbaJK\xf1"\x0c\x07\x93\xc7\xc3\xc9\xd3\x8f\ +\x9b\xe2[r\xbf\xdbX\x9d}\xb7x\xf7?\xb05\xb7*\xcb\xc5\x19\x94\xb4\xe9\x9b;#\ +\xde\xecl\x02\x89n\x93}qA\xcd\xca\x95o\x9a\xd7\x1e\xf8}[\xb6\xb5\xe2\xfc\xbd\ +\xad\x07\xee\xbe\xa5\xe4=?\xd8\x95\x96\xdc\xf5{UK\xbc\xaf\xd2!]yH=0\xd5U\x1b\ +ts\xf2\xd9+\x18\x7f\xab\xf6\x94b;\x8cno\xef\x8b\x9f\xfe\xcd\xf6\xbb\xf9\xb8\ +\x90\xafN\x92\xe9we\xb6`\xbe\xe8\xe8\'\xf7\x04(\xf5\xdc\x8b\xfa<%\xe72\x9c\ +\x1c\x1e\x8d\x0f\x1fw\xbaW\xb6\xbcyv\xfcv:_)[k_\x10\x05\x04Vi\x7f\xef\xc1:)e\ +\xf2no2B\xf2-\xab\xed\xfa\x1d^\xdb\xb4\x8f\x04\x86\x08\x82\xfe\xde\xc3\x8f\ +\xd8\xa8i\xc9\xfd\xcecy\xfa\xed\xf2\xf8\x7f\x9d\xd5\xee\x13\xb71Dj#N\xfdW\ +\x9bNc\xb9\xccO\x93lH{\x07\xdf\x18\xd9\x00\xef\\\xa8o\xf0y\xf6=\xa7pw\xe2\ +\xbb1d\x9e!\\\x87\xc2JOS\x02\xe5\xfb-\xb6\xb9Z\xd5W\xbd\x82\x17w\xad\x0fL\ +\xb5\x16\xbfa~\xe7\x08\x99\xdd\xf6\x0e\x1e\x1f}\xfe\xb3]\xb7\xf5\xf1A\x16i\ +\xbe|\x93\xcc^*y\x89\xb9\x9f\xc8<\x18\x19\xa3\xa6T\x9c\xe6(\x15\xf5\xfa\xa3\ +\xfd\xfbO\xf6\xf6\x1fn\x91\x1b\x17@\x99gi\xb2\xce\xf2<\x0c\x82@\x04E\x91\xa5\ +i^\x14E\x1cQ\xd09\\\xcd^\x8fza(\x96\xc5\xea\xddy\x93\x80\x13X\x9bH\x12R\x01`\ +"\x11\xf5F\xc3\xc9\x93\xde\xde\xcdd\xfb\xdc\x1e\xb4\xe4\xfe1`\xfe\xf6\x0f\ +\xeb\xe9\x0b\xcb\xef\xda\x9f\xa8\x99\xc7^\x02{\xd3\xd0n8-\x9b\xa3R}\x15o\xcf\ +W\x03o]\xbb\x89J\x0e\x9fk\xc1\xeft\xee\xed{\xff\xe9\x81\xcd\x9f\xab!w\xe7\ +\xb7\xf8\xe9\x8f\xc6t!\xdbST\xb3\xeb\x01U\xc5pe\x03\xc9z\xef\xc6u\xb5u\xf3\ +\xe0\xc9\x8f\x0f\x1f\xdc\xc9\x11L\xd7\x81\x8d\xb86\xa7\xd0;\x1f\r;>-8\xcb\ +\x99\x81\xfep|\xf8\xf0\xf3\xd1\xf8\xdeu\x9a\x94\'\xc9rv\x16u\xfb\x80LR\x99\ +\xad\xe7\xdd^?-\xe3 {>\x1a\xc6\xf9\xfa-+nt!\xfeWHg\x13T\x13?1@\x14u\x06\xc3\ +\xfd\x1b\xcb\xf6\xb9\rh\xc9\xfd\xa3\x00\xf3\xd9\xab\xff\xca\x96\xef`\xf2\xd6\ +\xeb\x82}\xab~\xd7\xfa\xd7\xbd\xdf8\xa37\x9c\xc9\xad\xd3?.\xf9\x859W\xa7\xd7\ +.\xce;\xd6\xeb\xc5MG\xc8\xfcUn\x92\xbbs\xc9\xab~\x87\x01\xe3\xd9\x92\xf6\xdf\ +u\xba\x0c\x9c\'cRell\xa2q\x9f\x9a\xdc\x9f}\xf5\xab\xe1\xde\xcdTV\xb9s\xd0S\ +\xe8%\xd3\xef\xe4\xee\xa4\x1a\x1f>\xb32\xa0\x14\xb2\x92\x93\x1c\xa5d\x02\xfa\ +\xa3\xc9\xfe\xbd\'\xa3\xc9\xd5\xc52+5}\xf7\x06"\x8c;]\x86JRY$g"\x18J\x95\r\ +\xf0\x86\xb9\x90EV%\x03lm!\x01\x0c\xc5(%$\x9b\xbf\x88(\xee\x0f\x0f\x9e~\x1c\ +\x14\xdf\x92\xfbG\x02V\xe5\xe9\x8b\xdf\x14\xc9\xd4\x1b\xa4\n\xff\xbb]\xcb\ +\x1b7+\xedLG\x96\x05k\x89\x91\xce\x94\xb7\x8b5\xb2<\xaf)[w\xaa\xba\x88m\xde\ +\rm!\xf9\xday\xa8\xb1\xdeJlg\x9eT\xc9@\xcc\xba$0\xea\xf4N\xb5,\x1a\xaf\x0f\ +\x80\x9d[\xd5/?\xe9\xdf\x02\x03\xac\x98D\xf0\xa3\x9f\xff\xfd5c\x83w\x1d,\x8b\ +t\xfe2\x9d\xbf\x92\xe5y\xf5\x8fw\xd9.\xa5\xc2:\xe3\xb4\xd0\xb1l\xf4\x07\xa3\ +\xc9\xfd\xa7{\xfbW,\xdb\xcb\xcc\x8b\x93\x13\x11\x8a4\x93\xa3\xbd\xbd\xa2(\ +\x16\x8bD\xa5gao?,_\x085W\xd2M\x9a\xfb\x9e\xa6*3C\xb71\xfd\xa2\xb8?\x98<\xee\ +\x8fof\xf6\xf0\x0f\x85\x96\xdc?\x1e(\x99\x9f>\xffu\x99/\x9dN\xaf\xf3\xbb^\rl\ +\xf0\xbb\x07\xdb\rh\xf8I5\xf6\x8f\xe4:_\x98]"\xbd\xb9zS\xa4\x9b\x82\x01\xec\ +\xe5\xed\xd85\xa6N\x9ao\xac\xb3\t\xe8y)\xefl\xbe\xead\xcfQ\xe5\xc08\x0f\xa7^\ +[\xd8\xb6\xc1\x9e<\xee\x0e\xbf\xfc\xd9\xdf^\xcd/\xfe\xc8`U\xfc\xf3\xadF\xcd{\ +?\xa0\\"\xc9\xb9\x94\x08\x03(\x850\x1e\x8c\xef\x1d\x8d\x0f\x1e\x8b\xcb\x8beV\ +j\xbd\x9cC\x81\x85(\xf2r0\x1c,\xd7\xc5z>\x13r\xd5\x1fu\xd5\xf2\x7f\xbc,\xa9\ +\xf3\xe0(\xde\xce\n\x02\x10\x820\x1eL\x8e\x86\xfbGw\x94\xe2[r\xff\xa8\xe0\ +\xf1{\x15_\xad?\x9b\xfa\xec\xc4\xd4\xfcKtB\xd9\x0e\xfc\xa7\xfa\xb6\xe6\x97\ +\xc5-\xef\xf4wj\xfb\xed\xfe\xaem\xa5\xf5\x1d\xdfM;\xb3G\xc5\xf6\xaeT\x80U\ +\xee\xd67g0\xd8U\x0cf\'\xe1\xe1\x0e\xf2J\xca\x90\x8d\xa06{\x1d&u\x00\x00 \ +\x00IDAT,~\xbd\xe7\xf8\xf0\xe8\xe8\xb3\x9f\xee\xbc\x81O\x0f\xacd\xbez\x97L\ +\x9f\x97\xf9\xd2\xad\xbcP\xd7G`F)\xcd\'\x9f\x97\\\x94\x88:\xbd\xc9\xbd\xa7\ +\xa3\xc9\x83\xe0\xf25\x1dW\xb3\xb3"/\x06\xa3\xf1z\x9d\x80\xd1\xe9v\xcef\xa9J\ +\xcf\x06=@\x9e\x14\xe9\x8c\xe8B\xd9\xab\xfa\xdb\xee\xc2\xad\xfak\xa0)~0~|\ +\xe7\xf2&[r\xff\xd8\xa0d~\xfa\xe2?\xcat\xe1\xe2\xab\xe41/9\xf9N6A\xa4&E}\xad\ +\xbc!Rk\xecN\xe7Qu\xe3\\\x17\xe6t\xb7\xe4X{\xdbv\x82O\xeez\x07\x9b\xe7\x0ec\ +\xcb\xb8\xb6Z]o\xbf\xea\xcc^\x97\xe0\xc9vT\x87\xa3:?L\xff\xc0\x8c\xa3\xcf\ +\x7f>>xt\xfe-\x7f\x8a`\xceV\xef\xd2\xd9\xcb"\x9d\xe2\x82\xe4\xee\x0e\x85\x91\ +\xc9\x8a\x91\x15\\HDQ\xbcw\xf0dr\xef\xe8\xb2\x14\x9f.\x17\xc9j\x8e\xa0;\x18\ +\x0e\x17\xcb\xa4\x13\x87e\xa9\xd6I\xd1\xc34\xa0e\xb6>&=\xe7\xfb\x05\xb0\x95\ +\xe2Ep\xf7R\xe3[r\xff\x08a\xf8=[T\xa6y-K\xd2F\\\xe16\xd7\xe0L\x19c\x84zTX\ +\x11\xe1FV\xe56\'}\'v\xf1\xbe!\xd3MZ\xb7>\xbbY\xd2{\x109\xff\xc4\xe5\xb9\xb3\ +V\xe8\xca\x8atX\xeb\xdd\xaba`\x95{M\xb6\xeb\xc3aW\xda\x0b\xd9\x15\x14|\xf5\ +\xc9\x1b\xee\xe7#_\x9f\xa4v"\xecK\x81a\x86>IF\x96s\xa9\x10\x86\xf1h\xff\xd1\ +\xe4\xdeQ\x14\xf7.~\x9e\xb2(Vg\xc7%D\x7f0\x12A0\x9d.{\xb1HR\x0e\x03\xd9\xe1\ +\xe3,9VeN\xe2\xda\x14?~<\xdc\xbf\x1b\x14\xdf\x92\xfb\xc7\t%\xf3\xb3\x17\xbf)\ +\xd29\xdcL\xaa\xb0\xccN\x86\x1d\x9b\x04]\tb\xb3Tsp\xb0\xd3%\xb98\xce\xe3t\ +\xfb\xc2\x9b\xeba\x08w\xe3a\x81<\x16f(\x93\x15\xc4\xd0\xca\xddcv\xc090\xf0\ +\x8c\x17\x9f\xe8\xcd#\r\xbbKU\xcc\xce\x8cn\x7f\xef\xcbOc\xf8\xd25Q$\xd3d\xf6\ +\xbcX\x1d_\xf6\xc0\x8a\xe2\x15\xd2\x82\xa5\x84\x08\x82\xbd\x83\xa3\xc9\xbd\ +\xa3\xb8s\xd1\xd1O\xac\xd4\xe2\xec\x84\x82 M\xcb\xf1x\x9c\xe6e\xba^G\x81P\ +\x14t\xc3\x9c\x90\xad\xa7\xdfA&\xb8\xb8\x8a\x07\xf4\xe0\tY+S\x13\x0c\x0f\x9e\ +\x0e\xf7\x9f\xdcr/\xbe%\xf7\x8f\x16\xac\xca\xb3W\xff\x95\xafN+~\xf7\xc8\xdd\ +\xdf\x936d\xb8^\xbba\xd8\\\xe5\xabr\xbe\xa2w\xb4\xce[\xd7\xa3\xc9\xf8\x1b\'\ +\xd0cV\tZ\xbc\x1br\x07+V\x9eZ\x07{\x84\xeeX\xdb\x8er\xb2O\x05.\x0f\x92\xf5\ +\xc4\xdd>\xb9\x8f?\xb1\xe1K\xd7\xc4\x95gpe\x98\x1a\x06v\xe8\x13\x04\xd1h\xff\ +\xe1\xc1\xfd\xcf:\xbd\x0b\x8d#\x95e\x99.\xe7\xa0\xa0\x94\xac\x94\x1a\x8eF\ +\xd3\xd9ZfI\xb7\xdb\t;A@\x94\xad\xdf\x15\xcb\xe7\xc4\xc5%(\xde>\xb9V5\x0c\ +\xeeB\xb8\xb5%\xf7\x8f\x19\xac\xca\xd3\xe7\xbf\xb6\xfa]\xd7M1_T\xe3(\xfb\xdf\ +\xed\xe6\xe4\xab6\xa1\xd2Y\x13\xb5}\xcf\xbd\xee{\x96\x9b\x92|\xfb\xd6\xf7\ +\xd0\xban\xbf\xc9\x81\x81\x91\xe1\xd6\xab\xd1\x15c\xea\xe7w\xb91\x9b\x12\x1e\ +5r\x87\xc9\xab\xb1\x871\xf0\xe8\xd9O\xf7\xef\x1d\x9d{\xd3-\x9a(\xb3e:\x7f\ +\x99-\xdf\\m\x06\xd7RAJN\x0b\x94\x92\x85\x10\xe3\x83\x87\xe3\xc3\'\xdd\xfe\ +\xde\xfb\x0ff^\x9c\x9d\x96R\x0e\xf7\xc6\xcbU\x12\x10\x11\x89\xe9"\x1dD\xe8\ +\x0f{E\xa9\x888\x9d\xbf\xa0\xf2\x94U\x0e\xef\xc9v\x17\x1a"\xa7I\xf1\xe3G\xfd\ +\xc9Q\x18\xdd:\xcb\xae%\xf7\x8f\x1c\xac\xca\xe9\xeb\xdff\xabc\xf2R!\x1d\xbd\ +\xb9Y<\x1a\x16<\xd5\x85;or\xb0\'\xf6\xb7\x06E\xb77\xc6{\xc7\xb5\x83w\xec\xd0\ +X\xcf\x1b\xbb\x01\x8e\x85\xd9\xd6\xf0\xf5\x88\x9b\x1b\xaez\x95\xfb\xe8_\xc2H\ +w\x17v\xae\xe6(d#\xe3\x83\xaf~\xd1\x1a\xeeW\x84,\x92t\xf6\xfc\xcas?\x95\n\ +\xa5\xd4*\x9eCA\xe3\x83\x07\xfb\x0f\xbe\xb8H5\x98\xf5|\x9a\xacW\xdd\xfe^\xdc\ +\xe9Lg\x8bn\x1c\xa6IY\xcar2\xea*\x11\x02Tf\xebb\xfd\x1a\xe5\x14\\\xe8\x18\ +\xce\xaeSmn`\xa0\xf4\xbdx\x11\x0c&G\x83\xfd\'\xb7\x8a\xe2[r\xff$0\x7f\xfb\ +\x87\xf5\xece-\xbb\x91k_\xe6\xc6\xd7\xd7\x1f\t\xc5\xa8\xe5\xb6_6\xcd{\x8b\ +\xc1\xb2-\xd1\xe6\xfd>\xccN\x8do\xfb+\xd693\xec\xbe\xd5\xbeN\xaf\xd8\xdc\x0e\ +YB\xc3j\xf2*\xc9\xd8}M\xa6\xcdp|\xff\xd9\x8f\xfe\xfc\x12\xf7\xdcb\x03\xaa\ +\xcc\xd3\xf9\xcbt\xfe\xf2\ns?1PH\x14%\xa7\x05\xa4\xe48\n&\x87\x0f\xf7\x0e\ +\x9f\xbd\x97\xe2\xf3$I\x97\xb3L\xd2x2)\xa5Z\xceWQ\x804W{\xc3N\xdc\xed.\x96ID\ +H\xb2T\xc8\x19\x8acp\xb6U\xc5\x9f\xf3\x85oR|\x10\x0c\xc6G\x83\xc9Qx\x998\xf0\ +\xf7\x87\x96\xdc?\x15\xacg/\x17\xef\xfe\x87Y\x91\xb5f\x1c7:\x1b\xde\xd3\xefU\ +\x9e;\x9b\xca\xba\xde\xb9\xf82\x1c\xbfC\xa4\xfb\'\xf3^6h\x9d\x9b\x8b[\x14\ +\xbd\xbe\r\xc0N\xa2\xea\x1e5\xc8\xaf\xf8\xe8\xf8\xbd\xb1\x08T\x0f5.\x0f\xd2\ +\x7f\x1ax\xf6\xd5_\\\xb3\x16J\x0b\rU\xe6\xe9\xecy2\x7fq\x05\xa3\x86\x81\xa2D\ +^rVBJ\xee\xc4\xc1\xf8\xe0\xc1h\xffI\xdc;\xcf\xa8Q\xb2\\\x9e\x9d\xb2\x08d\xc9\ +\xc3\xbd\xd1*)\x8a4!F\x18\xd1ho\x94d\xb2\xccs(N\xb2\xb4\x1f\xaeT\xfe\x8e\xcb\ +5\xa3\x1aKu\x91\xafye\xd4\xe8C\x88\xfa{\x0f\x87\x07\xef\xef{\xbeo\xb4\xe4\ +\xfe\t!Of\xb3\xd7\xbf\x95e\xeaR\na\x93\xde\xadT\xb5T\xbfi\xb6oe\xe7\xf7\'\ +\xbb\xef\x04o\xbc\xdb\xe5\xc3\xd4\xd6o]c:\x1fr\x93v4]\xf5\xba\x0f\xd3\xb4e\ +\xea\xe4^?9\x87q\xef\xc7\xbf\xf8\xfb\x8f\xac^\xe0\x87\x85,\x92t\xfe\xf2j3\ +\xb82\x90\x15\xc8J.J(\xe6N(\xc6\x07\xf7G\x87\xcf\xe2\xeeN\x8aWe\xb1\x9aO\xc3\ +\xb0\x93\xe6e\x10\x88(\xea\xcc\x16I\x84"\x8c\xe3(\x14A\xdc[\xae\xd6\xa2\xcc3\ +\x15\x0e\xfa\x08E\x91\xcd\xfeT\xe6\xab\xads\x94\x9d\xdf0\xa9P\xaaj@\xdc\x07\ +\xa7\xf8\x96\xdc?-\xa82\x9f\xbd\xfd}\xb6:\x01`=\x12\xb2\xf3u\xb0U\xeb\x8e\ +\xdd\xb9\x12\xb6\xd7F\xf3{\xc6\xdb7\x9dc\xaf\xbb,\x97\xdai\xaa\x1a\x03f\x04\ +\x93\xef\xc6`\x83\xca\xb9\xee\xc2;\x10\x91\xdfs\x98C\x98\xef\x1f\xfd\xe8\xfe\ +\xa3\xcf/v\x8b-.\x01m\xd4d\x8b\xd7\xea\xdc25[\xc1\x8c\xb4\xe0\xacDQ23:\x11\ +\xedM\x0e\x86\x07O\xbb\x83\xeds\x97+%\xb3\xc5\xb4\x90\xe8\xf6\x07\xb3\xe9|0\ +\x1c$\xa9LV\xabq?\x16q(\x82\xb0\x90\xc8\xd6+R\xccQ|\xef\xfe$_\xbdK\xa7\xdf\ +\x94\xd9%\xaa`\x9a\x86A\xa7\xfa\xc0\x8e\xbb\xa0\xde\xf0\xde\xf0\xe0\xd9\xf9\ +\x8f\x17\xdf\x13Zr\xff\x14\xb1:{\xbe<\xf9\xda\xcd\xc3P\x99\xf0\x9a\xd5M]Ir9\ +\xdf:1\xd0\xff\xa2\xec\xa2\xfbsT~\xb5y\xfb\xd2nZ\xf7\xb2\x18\xfdE\xb3\xe4u@&\ +<\xe0\'>Z\xbev\x14\x8fMy^\xdd\x91\x9f8\x0f\x06\x0b\x11}\xf5\x8b\xbf\xfb(\xe7\ +\xd5\xbb%`Y\xa4\x8b\xd7\xe9\xfc\x85*.I\xf1\x04f$9g\x05J\t\x00\x9d\x08\xa3\ +\xf1\xfep\xffIwp\xafY\xba\x1a\x00\xb0<=^\xa7\xd9hoRHUdy\x18\x04\xcb\xa4\x1c\ +\xc4\xe8\xf6\xbbEQ\n\x11\xac\xd3\x82d\x810\x9e\xec\x0f\xc3(\xca\x16o\xd2\xd9\ +we\xb6\xdc<\xd5{n\xeavP|K\xee\x9f(\x8at>{\xf3\xbb2[\xd5\xadv7v\xa9\nK6J\xfe\ +\xeeD\xe3\xaf\xe9|\x87}s\xcdV!\xefQs\xfd\x10vcl\xb5\xcb\xee\xa2\xc3&e\xc6\ +\xa7r\xd4\x83\xa8.\xbe\xda\xb8^5\x94\xab\x92\xed\x87\x0f?\x7f\xf8\xe4G\xdb\ +\xef\xa4\xc5\xcd\x81U\x99\xaf\x8e\x93\xe9w\x9b3\xb8\xee<\xc4~3\x15#\xcd9- \ +\x15\x08\xdc\ti0\x1a\x0f\x0f\x9e\xf5\x86[(>[\xce\xd7\xeb\xb5\x08\xbb\xddnw\ +\xb1J\x88\x15+\x94\xb2\xdc\x9f\x0c\x0b\xc9,\xa5R\xbcN\xb2N(\xa2^w4\x1e\x01\ +\xc8\x96o\xd2\xf9\xab2\x99^\xfa\xa6\x1a\x14\x0ftG\xf7\x06\x93\xa3\xee\xe0\ +\x07\xaa\x1a\xdd\x92\xfb\xa7\x0bV\xe5\xe2\xe4O\xab\xd3\xef\xfc\xe2\x04\xa8\ +\xf2\xdd\x99\x01\xe1\x12\x04\xebj\xf72\xf1\xd4\xf7\xad?\x97\xd6\xb1\xe1\xb3\ +\x93\xf5^\xf4\x92%w\xf3\xe7\xceF\xbdo\t\xa2\xd6\\\x9a\xad-\xd3c\xa0L\x1f\xc0\ +"\x88~\xfc\xcb\xbf\x0f/_\xc7\xaa\xc5\xd5\xa0gpM\xe7/\xcbt\xfe\x9e=\xbd\xf7\ +\x8e\xe2\x93\x8c\xd3\xc2d\x81\xc5\x11\xfa\x83\xd1`r\xb4Y\x99]\x95\xc5j6M\x0b\ +5\x1c\x0e\x19b\xb1L\x02.AA\xb7\x17\x86a\x9c\xa4\x99`\x95\xe4*$\xd5\x1b\x0e\ +\x06#\xe3\x98\x17\xeb\xd3d\xf6\xbcX\x9f^\xe1\xbe\xa4G\xf1\x00\xba\xfd\xc9\ +\xf0\xf0\xb3\x1f\x80\xe2[r\xff\xd4\x91\xad\xcf\xe6o\xffX\xe6\xabZ\xaa\xbb\ +\x15\xb3v\xfeTb\xbf\x1c\xcdU\xb1\x95\xd0\x9bK\xf5\xaa\xeb\xb5\xa8\xaei\x95))\ +c\xb7\xda22\xd6\x9f\xf1mw\xd4=\x19\xae\x9f\xb6\xd1\x003;\xb6\xe9\x0c\xf8^+\ +\xdb?\x08\x98\xf3\xd5q2{^\xa6\xb3\xed\xdb\xb7\xadt\x14\xbfJ9+\xc0\x80 tB\xf4\ +\xfa\x83\xe1\xfe\xd3\xee\xde\x03\xe1\xcd\xbd\'\x8b,\x99\xcf9\x88\xf3\xa2\x1c\ +\x0c\xfai&\x93\xf5\xba\x13\x90\x08\x83^\xaf\x9bK\x94\xe9ZJ\x95\x15j\x7f\x7f\ +\xd8\xe9\xf7\x82\xc0t\x0f\xc5\xfa4\x99\xbf\xbcBq\x05lP|\x7f\xef\xc1\xf0\xe0Y\ +\xdc\x1d]\xe1T\x17DK\xee-\xb4\x84\xffv=}\xce\xde`q\x976SS\xd1\r\\0S\xec"[6\ +\x82\x99\xde\x16\x9f\xe0\xe1\xc6\xa3\xda\x1f\xb5C\xd8\x06\x82\x1b\x9a\xdd\ +\xaf!\xc3\xb5\x93\xbb\x8b\x91\xe7\xc9\xb0\x08\xa2\x9f\xfc\xf2\x1f\x820\xba\ +\xc0\x1d\xb6\xf8^\xb0K,\x9fCX\x9a\xe2\xa5\xc2"am\xc4\x0bB\x1c\xa1\xd7\xed\ +\xf5\xf7\x9f\xf4\xc7\x8f\x1d\xc5\xcb<]/\x17qw\x98fy\x99\x17\xdd^w\xbe*\x84L\ +\xfb\xfd\x1e\x05$\x82x\x9d\xa4!\xcbu\xa6F{\xbd\xc1p \x82*]\xaaHg\xeb\x93\xff\ +\xdd\xd5\xf7\x9c\x0f]/^Z/\xbe;<\x1c\x1d|\xf6=y\xf1-\xb9\xb70(\xd2\xc5\xfc\ +\xf8\xeblu\n\x98\x19\xe7h\x8b\xc6\xbdb\xe6\xcc\xf6/Y\xbd\xd7h\xb8%\xd5k\xb5\ +\x9b\xa1u3\xb5\x9eo\x16m)\xe5\x08g\xbe\xfb\x16\xbc=7\xd5/A\xce\x96b\x86b>\ +\xfa\xec\xcf\x0e\xee?\xb9\xd2\xbd\xb6\xb8I\x14\xe9,\x9d>\xcfW\xef\xdc\x9a\ +\xf7\x12\x96\xfez\xe4%\xd6\x19k2\x8d\x02t"t\xbb\xbd\xde\xde\xc3\xfe\xf8q\x10\ +u\x01\xa82_M\xcf\x14\x85\x9dno\xb9L\x82\x80\x00\xb1J\xb2q?B\x10\x84a\x94\x17\ +*KV\xa4\x98\xc3\xf0\xfe\x83\x03\x12^:,s\xbe>I\xe7/\xafo\xd4h/\xfe\xfb\xa0\ +\xf8\x96\xdc[\xd4\xb0\x9e\xbfY\x1c\x7f#\x8b\x84\xdcH\'G\xab\x0e\xd71h6\x1e\ +\x03\xb6\x05Tk;m\xb1\xd7M#\xaa\xd96\xcc\x9eu\xa7\xde/\x10f\xadvWN\xd8\xcf\ +\xe37i\xee\x0cS\x15\xb27\x98|\xf9g\x7f\xd5N\xbat{P\xa6\xf3t\xfe2[\xbe\xe5\ +\x8bU"#2\x95\xe2\xf3\x92\xf3\x02\x85\x02\x01a\x808D\x1c\xc7\xc3\xc3/z{\x0f\ +\xb5\x8aO\xce\xde\xad\xb2r\xb87f\x88\xe5b\x1d\n\xce\x0b\x0eH\xf5z]\t\x16$\ +\xd6IN\xb2\x90L\xf7\x1f\x1d\x06as\xd2\x8fKy\xf1\xb5\xb8\xd1F\xb8\xb538\x18\ +\xee?\xe9\x0e\xb7gs^\x01\xff?{o\x1ef\xd9q\xdd\x87\x9d\xaa\xbb\xbf\xfb\xb6~\ +\xfdz\xefY1 0\x04@\x82 )\x1a\xdc\xc5\x9d\xb6d9\x92A\xc6r\xe4\xc4r\x12\xcbq$9\ +\xf9$\'\x7f\xc4\x96\x15\xd9\xf9\x92O\x12\x15k\xb1\x95O\x8a%[\xfa\x12}\x11-Z2\ +-j\xa1(\x12\x04@\x10\xfb>\x0bf03=\xbdoo_\xee\xad\xe5\xe4\x8fz\xb7^\xdd\xfb^\ +\xf7\xf4\x0c\x00\x02\r\xf6\xf9\x807\xb7\xefR\xb7\xaan\xd5\xafN\xfd\xce\xa9SG\ +\xe0~$Y\x91\x92wj+\xed\xdau\x14|\xa8\xf0\xee\xb1\xa8c\xccb\xed\x91\x065\xda\ +\xc2\xc6\x9a4q\xcc\x0f$*\xb6\x01\xf8YW\xc8\xe1/@Jm\x87\x11dO\xe5rH\xe3\xa8s\ +\x03*\x9f\x10z\xdb\xd9\xf7x\xfeA\xc3\xcc\x1e\xc9wLD\xdc\xed5\xaeG\xad\x8d\ +\x83@\xbc\xd2\xdf\x19\x07\x00\x88\x05r1\xf0\x98tlpm\xe2\xb8^X^\xc8\x95\xe7)\ +\xb5\xe3v\xa3\x1f1&0\x0c\xf31\x97\xbdN\xc7\x02dH\n\xa1\x87\xc4B)\xb8\xc0\xa8\ +\xd7\x0b|\xcf\xf1\xdd\xb0\x90\x1f}\x17\xeb\xd5\xfb\x8d\x15sz\x91\x91\xbdHM\r\ +\xf1\x98D\x9a\xf6\xc2\x89\xfc\xc4\xe2k\x02\xf1G\xe0~$\xe3E\xb0~k\xf7z\xa7\ +\xbe:f\xc1\x8f\x12\x92\xf9wO\xc11G\xe6\x89\xac2\x9f\x86u\x93Z7\x90}$\xdc\xa3\ +y2C\xb8\x0f\xce\x0f\x95\xfe$\xb6o:\x0e\xa6r\xa3\\8yvb\xf2h\xc7\xa57\xaf\xf0\ +\xa8\xd5\xab/\xc5\x9d\xed\x83`\x17!\x10sP{\xear\x81\x12\x81s \x04\x1c\x1b\ +\x1c\x8bX\x8e\xe7\xe4g\xcb\x93\x8b\x923\xd6\xef\xf7\x99\xb4l\xdbu\xfdV\xbb\ +\x87,\xb2m\xcbvm\xc7\xf5\xe38"Btct\x08\xf7\xc2P\xb9H\x8e\xc9X\xbf\xd9\xab_\ +\x8f;\xdb\xfb6\xf9\x91\x1c&\x10/\x10d2fy\xb9r8\xb10\xd6\x9b\xf3\xe0r\x04\xee\ +G\xb2\x9f\xc4\xfdVc\xe3R\xd4\xad\xebF\xf6Z\xf8\xcc\x8c\xd1\xd8!\xd5\r\x06kMS\ +\xe7\xf7@p0\xa0\xe1\xc4q\xbc\xc0\xe7\x02d\ +\x1c1.\x85\x90\xc5R.,\xee\xe9\xe5"\xe2N\xaf\xb1|\xc0\xe9\xc50\x93\xea\xd9\ +\x04\xe2\x95\x16\xef\x04\x85\xc2\xc4\xb1\xa00uk\x10\x7f\x04\xeeGrc\xe9\xb5\ +\xb7\xbb\xf5\xf5\xa8\xd7\x94<\x1a\x9c\x1a\xc7\xc1\x8f\x8d\x8c\x9a\x1c%Z\xf2x\ +`\x1f>\xad\xd5tS\xf9\xd9\x0f\xd6\x93\xf3\xc3\x93\x19\xe6}\x98\xe8\x98\x1e\ +\x82\x03\xd5\x89\x00@u\xf6\xc4\xcc\xfc\xa9\xd1{\x8e\xe4M+"\xee\xf6[k\xacW;\ +\xc8:\xd2\x98\x83\x90\x00\xc927\x81\xc0\x05\xd8\x14,\x8b \xa2$\x8e\xe7\x15\ +\x1c\'\x17\x96\xa6\x89\xedD\xfd\xd8\xa24\x8a\xb9`\xb1\xebX\xd4\xb6l\xc7\x8b\ +\xe3\x18\x19\x8b8\x96J9?\xcci\x17\xc9\xf1\x19k\xae\xb2^\x8d\x1fxY\x16$Z<"\ +\x08\t2QJ\x9c\xa0\x10\x96\xe6\xdc\xa0t\xb3aj\x8e\xc0\xfdH\x0e*R\xb0N}\xbdS_c\ +q\x07\xc6\xab\xf0\xc6\x1a~\x1c\x9e\x19\x17\xacw\xf8tf}\xd4>\x98\x0e#\xda:\ +\x18 \xaeOj\x9d\x1d\x0c\xf4\x072\x86^J<\xe3\t\x10\xb2p\xe2\xcerefL\x99\x8e\ +\xe4\xcd/\x89\xefJ<\xce\xb0i6T&!fH\xc8\xd0\x8c\x89\x001\x03\x8b\x02\xa5 $\nI\ +<7?1u\xc2\xcd\x15\xda\xed\xaem\xdb\x04H\xa7\x17\x05\x94S/p=\xbf\xd7\xeb\x83`\ +\x11\'a\xce\xf6|\xcf\x0b\xf6\x8d\xee\x8b\x18wwz\xb5%\x16\xdd`Y\xd6h\x861\xf1\ +\x9bTY\xa5\x84\xfa\x85\xeaM\xb9\xc6\x1f\x81\xfb\x91\xdc\x9c \xca^k\xbb][\x89\ +\xba\xe6\x82\xec\xfd\xe3C\xa6\x06\x82\xd1\xad?0{y\xcc\xf1\x01a}p&\x1b9a\xc8\ +\xcc\xe8\xe8\xc5\x9a\xa9w\\\x7f\xf1\xe4\xd9\xb0P\xde;\xffGr8\x84\xf5j\xbd\ +\xc6\n\xeb\xee\xec\xb5\x03\x01\x02H\x84\x88\r\xa6\x92\xba\r\x10\x80\x98\x03\ +\xa5\xca\x06+\x03\xbf\x90+\xce\xfa\xb9\x02\xa1N?\x8a\x1d\x9bF\xb1\x04\x11{\ +\xae\x05\x96C,\x87\xf5\xbaB \xb1\xad\xcadi\xd4\x85fT\xe2\xce\xf6^c\xcf^\xa2!\ +>\x1b\xa6\xa60u@\x88?\x02\xf7#\xb9E\x89{\xcdv}\xbd\xd7\xda\x12|\xff\x1dv\xc6\ +4\xb0\xec\xa9\xacI\xf5\x96\xb4u\xe3\xee\xa1J\xaeC)`r6\xf1\xf1T{\xe9\x15\xca\ +\xd5\xf9c\xb7\x1f\xed\xb2\xf4V\x12\xdeo\xf6\x1a\xd7\x95\xc5u,U(%0\x01\\\xa2\ +\xa9\x92\x90\xc4\xfaJ\x00"&\x02?\x1f\x16g\xd0\xf2\x1c\xdb\xa2N>\x8e\xfa\x16\ +\xcaX\x82o#\xb5]b\xd9\xfd~\x0c,b`U\xabE\xd7?P\xfba\xbdZ\xaf\xbe\x1cwwn\xaa8c\ +\xfc&\t\xf1\xc3Ji\xfa6\xdb\xdd\xcf\xa7\xeb\x08\xdc\x8f\xe4U\x89\xe0q\xaf\xb5\ +\xd3inD\x9d\xfa8\xfae\x0f\x19cD\xcd\xd27\x98\xb9m\x04\xd6\xc1\xd0\xbe\x8d3\t\ +\xc7n\xec\x138D\xf6\x01\xb6\x83D\xb4lwz\xfe\xd4\xe4\xd1J\xa5\xb7\xa8\xec\xbf\ +\x83+\x13C\xff\x19S,B\x00\xd4~ R\xa05=}\x02\xed\xa0\xdfk\x97\xca\xd3\x11C\ +\xe4\x11"X\x16q\x1c\x9bZv\xccd\xdc\xeb\x10j\xe5\x8b\xe1X\x17\xc9\xb1\xc2z\ +\xb5~c5\xda\xdbor\xac\x8cB<\xa54W\x9a\xcbO,\xec\x05\xf1G\xe0~$\xaf\x8d\xb0\ +\xa8\xd3mmw\x1b[q\xbf5\xf6\x86\xbd\x14x\x1c=7\xca\x98\xef\x03\xeb`\xb2\xf3\ +\xc9d;\xed]\x90\x01|\x04R\x9e\x9c\x9d\x9e;y\xa4\xb0\xbf\xe5E\x196\xa3\xd6:J\ +\x9e\xba@@{\xbe\xf34\xc0\x13\x00\x8b\x12\x04\xe8E2bX\x9d:\x1e\xe4K\x9dn\x9f\ +\x12\x0c\x8b\xd3\xedv\xc7E\x06\xb6\xed\xb8\x0e\x00\x91\x12{}f!\xb7=\xaf2u\ +\x13\xb1\xc0\xe2\xceN\xaf\xbe\xc4n2\x86A\n\xe2%\x00\x01J\xa9\x9f\x9f\xcaW\ +\x16G\x89\x9a#p?\x92\xd7T\x10\xa3~\xab\xd7\xde\xed\xb5v\xa2^k\x14\xbf\xc7\ +\xb66\xdc\xeb\x9e\x91\xd5\xa7`\xa0\xf9P\x9dO\xa1\xffp\x9e\x9dlB2H\x89\x00!\ +\x94\x16\xca\xd5\xea\xcc\xf1 \xf7:\x06l:\x927\x9bH\x1e\xf5\xd4&\xdd\xda\xdd\ +\x0b\x00\x00\x10\xa0\xcf\x80\x00HD\x85\x95\x8a\x9c\x91\x08\x94\x80m\x11\xc6\ +\xb1\xd9\x95An\xb2:=\x17s\xc9\x18\xcb\x87\x85\x88S\x8c\xda\x96m[\x9e\xa7\x9c\ +v#\x0e"\xeay\xbe[\x9e\xac\x98Qhn(qw\xa7\xdfX\xbd5\xa2\xc64\xb7\x8e\xe5\xe2\ +\x8f\xc0\xfdH^/aQ\xb7\xd7\xde\xed\xb5w\xfb\x9d\x864\xf4&L\xfd\x03c\xcf\x8f\ +\x12\xee0\x1e\xd6\xd5\xe1 &\x8c\xb9q\x1eIv\x86U\'\x1d\xd7/Wf\xca\x95Y/x\x83w\ +\xb6<\x927J\xa4\x88\xa3\xd6z\xbf\xb1\x9a\xd9\xfb)\xe6\xc0\x05\x12\x92\xc4\ +\xf32bL\xda\x94\x10\x82\x8d\x0eJ\x08\xe7\x16\x8f\x03r\x81>\xa0\xb0l?\x8a\x99\ +\x0f1\xf89\xdb\xb6y\x1c\xa3\xc4\x1e\x93\xc5\xd0\xf5r9\xd7\xbb\xb90\xd1\xaf\ +\x86\x8b\x1f\x85\xf8\xb0<\xef\xe5\xcap\x04\xeeG\xf2\x1d\x10\xc1\xa2~\xaf\xd9\ +k\xd7\xa2n\x93\xc5=)\x06@oj\xe8\x993\xa3\xba\xbci>\x05\x03\xe8\x93\xe3aHwss\ +\x11Ji\x10\x16\xcb\x95\x99\xe2\xc4\xb4e\xdd\xd8\xab\xe1H\xde<2\\\xc5\x86\xf8\ +\xe8\xb7\x1f\x7f\xf9\xd2eP\x01\xde\x08 b\xa1P\xf8\xbe\xbf\xfa\x19\xd7\xbd\ +\xe9h\xfb(X\xaf~\xbd\xdf\\C9p\x04PDG\xc4\x07Vx\xbd\r\xaf\n\x9e\x07\x08\x96\ +\x05\xed\x9e\x10P\xa8T\xe7m\x87\x02X\x02m\x87\x92XR\xca\xbb\x8ec[~\xc8\xb8 <\ +\x8a\xa4m\x13\x91/\xe5\xfd\xfd]$\xc7\t\xeb7\xfa\x8d\x95\xb8\xbdu\x13\xb6\xab\ +q\x10\x0f\x00A~2_9v\xd4\xdc\x8f\xe4u\x17\xcb\xf1Bg*,N\x01\x80`Q\xd4oG\xddV\ +\xd4o\xc7\xfd6c\x11&k\xae3\x80\x0ec\x10\\\x1f\xa0\xd6\xd6\x07\xb7\x0c\xc2\ +\xc2\x0cv\x92r\xbd\xc0\xcf\x15\xc2\xe2D\x98/\xbb\xdeMw\xb3#y\xc3%1\x8c\xa3\ +\x94\x12\x11;\x9dN\xab\x95\xb2\xe5\xa0D)\xa5\x94\xb2\xdeht\xda\x1dJSd\x88\ +\x90\xb2\x90\x0f\'&&\xa2(\xde\xd9\xd9\x91(\x03?\xa8T&\x08!\xc4rr\x93\xa7\xfd\ +\xd2\xc2\xee\xc6\x95\xad\xf5\xeb\x04\xf9\xd4D@\tx6\xd1.4\x00\x00d\xa0RX\x04\ +\x84\x84\xd0\xb7\xfbqkw\xfbz\xb92o;\x94\x12F\x9c\x02\xed\xf7\xa8\xed\xf5\x85\ +t;5;(\xa0\x97\xb3\xfb}\x94\xb8\xbb\xd3\x9c\xac\x12\xef`.4Z\x1c\xbf\xe4\xf8%^\ +n\xa9\x18\x06\x07\\\xe0\xaaz\x87M\xc1\xa2C.\xbe\xd7\xda\xe9\xb5w\x8e\xc0\xfd\ +H\x0c\x15i\xe3Q\xdcx\x1c\xbbk 9x\x13t\xe2,=\xf9Y\xb0^K\xab\xa3\xe5x9\xc7\xcb\ +\x15&\x01\x00Q\n\x1e\xc7Q\x8f\xf5\xbb,\xee\xc5Q\x8f\xb3H\xf0X\x08\xae\xba4\ +\x8c\xf8\xc9$XO4\xdfB\x08\xb5,\xc7v<\xcf\x0b\xe1hF\xc5r\x82\xb0z\xbb_:\xd6o\xaeF\xcd5)\ +\xf7_-\x98T\x9dz\x96\xc2\xd1\xd4\xf5\xbbTT\xe7\x11Bp\xce\xc5\xe5/\x91\x97\ +\x7f\x17P\x82\xe9<80\'\x01\xee\xbc _\xfc\xcd\x8c\x0f\xd9\x91\xbc\xf5D!\xfb\ +\xa0U\xc4=\xf1\xf8\xcf\xc2\xc6\xb7\x86\xc8\xae\xa2mI\x8e\xab\xdf\x90O\xff<\ +\xb2\x9b\x88\x87uk\x99Q9a\x8c\xf5\xfb}.\xb4\xea:\x0c0\xc7\x18c\x8cq\xce\x85\ +\xe0\x9c15\xcfS\xea\n"r\xce\x93Q\x01r\xb9`nvvee\xb5V\xab\xa9\x01\xe3\xfa\xf2\ +r\xb9\\:~\xfc\x18\xc2\xc0\x80J\xa8\xe5\x15fJ\x0b\xf7\x15f\xee*\x14\xcb\x94\ +\x00!`Yj\xc9\xdb\xd0\xf0\x13\x0b\xa4\x94L\x14\xa0Q[\xdb\xd9Zw,\xb0,\xd2\xeb\ +\xf5l",?\xdfg\x10\x04\xd3n\xfe\x18\x8f\xea\xbc}I\xc4\xab\xdd\xfaF\xa7\xd9B\ +\xea\xb0\x987\x1a\xedN\xeb\xc6\x01\xce2b9~8y\xba|\xec=A\xf98\xb5\xbc\x83V \ +\x1c\x81\xfbw\xa5\x98\xd3\xde8\xea\xe3\xd5\xff\x082\x1e^N\xc2\x9dk\xdfr\xf9\ +\xca\x17q\xe7\xb97"\xa7G\xf2\x1d\x15=\xde\xf3\xeb_#\xeb\x0f\xa5\xae\x19\xeb\ +\xc2\xe4\xd2Wp\xfb\x99\xd75\'&\xb8\xc7q,\x85I=\x0f\x90\x96s\xae\xf0=\x8e\xe3\ +(\x8a8\x17\x00\xc0\x85P\xe7\xd5I\x163\x00 @fg\xa6\t\xc0\x95\xab\xd7\xe28n\ +\xb7;++k\xb33\xd3\xe5R\x91s\xa1\r<\xaa\x98^~\xaa8\x7f\xef\xe4\xe2=\xf9b\x05%\ +\x9a\xeb\xe1\x94\x1d_H$@+\x05\xe0\xd1\xce\xe6\xc6\x8aE\tg\x1dB\xa9\x94\xc2sI\ +D\xf3 \xdd\xa0x\x1a\x89#\xa2\x1aD\xd7E\xf7\n\x89w\x11\xb9m[\x82\xc5,6\xfa\ +\xda\x81\x85\xda^8yz\xe2\xd8{\xc2\xc9\xd3\x96}c3\x189\x02\xf7\xefB\xd1\xc8\ +\xaez\x0ek\\#\x8d\x97S\x1bYd~\x11A\xc4r\xeb\x99#\xaf\xd9\xb7\xb0\x983\xb9(\ +\x8ap\xe9\xcfSK\xc82nL"\x96\x9bO\xddT\xbc\xf2\x9b\xcdL&K2\xb5\x88\x94$9"\xfa\ +\x1e!\xc4 ?\xe9\xe6\xad4w\xc6\xf9\xe4de\xb2:\xb9\xb4\xb4\x14E\xd1\xca\xcaJ\ +\x14E\xa5RI&\xde8\xa3yp\xc3\xc9\x89\x85w\xce\x9c\xbaOyy\r]h\x12\x07-!\xa0\ +\x9c\xa7\x84\xd7\xb66\x96-b\xc5Q\x07\x90S\xc7\'\xc8,/d\xa4\x18\xe4f,\xaf\x84\ +(A\xb4\xfb\xf5\x97\xfb;\xe7\xfb\xad\x8dN\xb3\xd1\xdc\xad\x8f\xbe\xee\x80B,\'\ +(\x1f//\xbe;_\xbd\xdd\xb2]:n\x7f4\x15P)\x16G\xe0~\x18\x05%\x88\x08D\x04"\x1e\ +\xf7_\x1fnd~AD\xad\x13\xb1\xe6\xca@m\x1fj\xeb\xe9\xb6N\x08 bT\x7f\xfd:\xf3\ +\x91\xbc\xe1\xa2\x86|!\x84Rxe\x7fw\xd0\x12\x06{\x9d\x18A\x1d\x14\xf2\xc6\xad\ +\xd7u\xb0GC\xc6\xe2/\x12$\x04(\xa5\x84\xe8(B\x86F\x92\xccB\x84\x14\x00\xc8\ +\x19C\xc4\x99\xe9\xa9Z\xbd\xb1[\xab]\xb9\xb6\x14\x04\xc1Tu\x92\xb1\x1b\xb0\ +\xd8nP\xaa,\xdc=w\xea\xdd\xf9\xf2\xec\x00H\x13\x17IB@H\x12\x06\xb6\x03\x8d\ +\xad\xcd%\x82H\x00;\xcd\x9d\\\x18\n \x16p\xe2\xcfZv\xd9\xf1J\x00\x04\x81\xa0\ +\xe8\xb1\xd65\xde[f\xbd\x1dy0\x03\xe9^B,\xc7\xf2\x8a\xf5.\xddn"\x97@I\xa2\ +\x8c\x01\x10\x00.\xa1\x1b!\x17pdP=4\xa2\xdb\xb7\\\x7fT>\xf3K\x00\x83m?\x07\ +\xcb\x18\x06\xbf\x04P\xd2\xc5\x8fY\xf7\xfc\x83\xfd\x93\xd2\xd6*\x8e\x01\x825\ +\xec\xb7\xc34\xd1<\x89V\xa0\x14\xa5\xa3m\xa3\xdfzb\xd2t\x8a\xe3\x86\xdc\xdb|\ +xp\xb0\x92\'#\xca\x12S8\xfd\x9dl\x0f\xa3\xebz\x08\x00M\x84\x10B)M\x00n\x80\ +\xf5\x84\x10U.\x95O\xceyeb\xc2\xb6\xed\x17_Y\x98\xb4\'\x8bv\xce\xa3\xae5\xd0\x02\t\x1ci\xee\x87AL\xcb\x12c\x8c\ +\xb08H.\x0c\xb1\xd8P\xde1Q\xf6\xf7Q\xdeM\xd9.\x7f\xdc\xef\\\xa8\xb6\x1f\x1e\ +\xa4\x03\xa9\t\x81\xf0\xa6\xd9\x99\xbf\xeb\xd8G^\xe7\xdf\x15\xa2[\xc5f\xe9\ +\x13}\xf4\x16k_\xf2\xd9&\x05\x0e\x00\x92\xb8+\xa5\xd4\xb6m\x8d\x83\xfa\ +OH\xc0]5\t\xd7u\xdf\xa0\xc1>\x15[F\xe5{h2M\xf2\xacs5\xa0\x1c\r\xd1\xe75\xac\ +\xbf\xe6\xa3\x14\xb5\x9cB\xe5XX\x9e\xeb6\xb6\xda\xb5e\xdbjm\xae_\xa9V\x8f\ +\xcd\xcc-\xf4\xa3\xa8\xd3g\xf9\xbc3\x88\x82G|\nyl^\x94\xac\xad\xba\xb0\x8e\ +\xe9(\x10|\x97H\x891G.\xc1\xa2\xc4\xb6\xc0wH\x18X\x8eM8\xc7~_ \xe2\r\xb3|\ +\x04\xee\x87F\xc6,\xe8\xc8XS\x93_\xbc\xd1\x1e,\xba\xeb\xba\xae\xabf\xdf\x96e\ +1\xc6\x94\n\xaf/\x99\x9a\xda\x11-\xf3\x96\x17=\xe4k\x8aF\x87\xdbUMB\xcd\xf3\ +\x14\xa7\xf1\x866\x86!\xbekh\xd6\xe0\xaeo\xd2\x86V\xb3/\xa8\xdbL>\xe7\xf5h\ +\xd8\x94\xda\xf9\x89\xb9\xb0<\xd3mn\xf9\xbb\xcb\xbd\xd6V\xbb\xee\x83\x9f\'(e\ +\xcc\x06\xce\x0e\x94Hb\x83]!\xac=\xdc\xb1 \t\xf8%\x11\xf2>i\xf5 \xe6H)\x84\ +\xbeU\xc8Q!\xb1\x1f\tT\xf4\xfa\x01\xb2\xfc\xdd\x02\xee\x18\xb7\x90\xb5\x81\ +\xb5\xa1\xb7\x85\xac\x032\x06\xea\x10; ^\x19\xbc\t\xe2\xe4\xc1-\x00\xb9\x89\ +\x80m7\xf7v\xc1 n kC\x7f\x1b\xe2&\xf2\x1eP\x9b\xb8E\xe2W\xc1+\x11\xb7\x047\ +\x8a\x07\xa4]\xdd\x01@\x82\x03\x90\x99\x8f\xa5y\xf7}\xddfM5M\xeb\xec\xb6ms\ +\xce\x95\xbb\x98fl\\\xd7\xd5j\xfbaFv\xc4\xa8\x81q\x1b\xa2\x1aD\xbb*\xe2\x15q\ +B\x92\x9b\x06o\x82\xb8%\xb0\x8fv\xf3H\xb5\n\x05|&_\xa7I\x9b\xd7\x90\xaa\xbe\ +\xe5\x9c\x9ay\x1e\xd5\xd6\xf5\xd5\xb13W}R\xff\xbe~\x05!\x84\x86\xa5\x99\xb04\ +\xd3\xdc]__\xde\xb6\xec\xde`XR\xe4:!\x88`\x01\xcf\xfb\x16\x1d\xee\xa14\x18\ +\xb8,\x02\xd4\x86\xc0\x85\x9co\x95\xf36\xa0\x8c\xa2\xc4jz\xe0\xcc\xbee\xc1}\ +\x80\x83\xb5\xf3\xd0\xb8\x84\x8d\xcb\xb8\xfb\x12\xd6/@g\x15D?}#\x85\xa0J\xca\ +gH\xe5\x1e2q\x96N\xdeE&\xee|\xad\xde\x0e"\x92;\xcfc\xfde\xac\x9d\x87\x9dg\ +\xb1\xf1\nD\xb5\xd4\xc7\xb1|R\x0c\x8b\xc5\xc2-l\x14\xf7j2#\x84\xa8\xd5\xea\xadV+\x8ac)\xa5m\xdb\ +\xb9 \x98\x99\x99v]W\xe3\xbb\xe6\xaf\xb5\xda;\xaa\xea\xde2 "b?\x8a\xda\xadv\ +\xb7\xd7\x8b\xfa}\x9eL\x16]\xd7\xcd\x05A\xb1X\x08\xc3\x83:\xdd\x12 \x99a&\ +\x03\xee7Na\xdc\x83\xaf\xb9\xb8A\t\xc8\x8e\x94r\xe8\xd0\xa2&\xd8\x08\x12p\ +\xb7-\'B\xb0\xa8\xd1M\x11b\x8e\x12\x89\xe3P\xdf%1KB\xeb$\xbd\x19`?\xaa]\xcb[\ +\r\xdc\x070\xc1:r\xe5A\\{\x18W\xfe\x02:+\xea\x82I\\\x00\xe8\xb5\xfb\x12z\x9b\ +\xd8\xdb\xc4\xb5G\x00Q\xe6\x17\xc8\xc9\xef\xb3N\xff\r2y\xcf\xad\xbf\x1d\x11\ +\xe2\xa6X\xfe\x1a.\xff\x05\xac|\x15\xe2$8*\xd1\x1f\'\xc9\x86\xe8\xe3\xee9\ +\xac\x9d\x87\x8b l\x87.|\x82\x9c\xf84=\xfe\x19\xb0s\x03\x9a\xb0\xfe\x8a\xfc\ +\xd6?\x06\x00\x0b @\x0c\x08)\x99~\xe8\xaa\\ZmO.\xd1\xed\xa7`\xfb)\xa9oH\x17\ +\xdc\xfe\x81\xaf\x92\x89b\x92#B)\x85\xda\xb3\xd63?\x93\xbd9I\x10\x81\xe0\x9d\ +\x7f\x07\xa6\xde\xa5\x96q+\xee_>\xf7\xab\xd0x9\xf5\x08\xa4V\xbb\x90\xa9\xfb\ +\xec\x8f\xff\x16\xf1o\xb0S\x81\x86\x0f\x94L>\xff\xaf\xf1\xe2\xef\x18\xd7\xb2\ +Q\x10\xac\x0f~\xc1\xda\x17\xdcu\xfd\xcb\xe5\xaf\xe1\xea\x83\xb8\xf4\'\xd0]3k\ +&\x95a\xe4\xd8\xbc\x8c\xcdW\xe0\xf2\x1f\x08;\xa4\xc7?E\xcf<@\xe7?\xb4\x7f\ +\x86\x0f"*\x1b\x9dNgum}}}cssk\xb7\xb6\x1b\xc7\xd90&\xb9\\0==\xbd8??3;37;\xa3\ +\x1f\x14R\xbe\xf4\xd2K\x9dN7Y\xb8\x88R\xe2\xdc\xdc\xcc\xc9\x13\'\xc6\xaa\xa2\ +\xea`ee\xf5\xfa\xca\x8af\xa3\x11\xa5\xeb\xbaw\xbd\xfd\xac\xe7y\xea\xb6~\xbf\ +\x7f\xe5\xea\xb5\xeb\xcb+\xab\xabk\xddn\xd7L\xe3\x07\xbe\xff\xfb\x8e\x1d[\ +\x04\x03\xe3\x14\xf1R\xaf7\xce_\xb8h\xa8\xc6H)=y\xf2\xc4\xcc\xf4\xf4-T\x08\ +\xe7|yeukk{}cc{{\'\x9d\x07\x00\x00\xdb\xb6\xab\xd5\xc9\xf9\xb9\xb9\x99\xe9\ +\xa9\xb9\xb9\xd9\xd1d2N\x90\x83\xa2\x1aurS\x18\xfd\x1d\x9by8\x8e\xe3\xf8\x9e\ +\x14\xc2\xd8I\x92\x00\x02!\x04y\xb7\x17\x8b\xd0\xa39\x8f\x00\x82\x04`\x0c\ +\xb8D\xc7\xa6\xbe\r\x04\x04\xd7\xad&=\x1d\x1f;p\xbd5]!u\xafFD\xb9\xf2\r<\xff\ +o`\xfd[\xc30\xb6\x19\xcc\x1a\xba\x84\x1bW\x01\x80\x10\xec\xac\xe2\x0b\xff\ +\x17^\xfbc\xfa\x8e\x9f\xb4\xde\xf6\x9f\xdfj\x06\xbe\x8e/\xfe\x06\xac?\x94}]\ +\x16g\xd3\x83\x8d`r\xe9+\xb0\xf4\x15\xb9\xf8\tr\xcf\x8fc\xe5\x1e)%\n\xa4\xd4\ +\x01\x11\x83v\x86R\xa3\x7f\xa6D\x99\xb8N\xe6\x81\xce\x83\xfa\xd3\x0eQ{\xc2\'\ +$>\x10\x1b\x88\r\xc8\x07\xe3\x84\xe9{\xa3\x8e,\xcf\xbc_\xda%\x98\xfb^\xaa\ +\xc0=\xe5_?\xfc\x13k\xe7q\xf7%\x98\xfb\xc0>]h\x98\xa0\x94\xb2\xb5L\x97\xfe8U\ +Q\xc4H\x16\x80L\xdeM\x8e\x7ff/+\xf1\xd0jV\xbf(_\xfaM\xb8\xf6\x9f@\xd9\xa9F\ +\xc7\xc2\xd4\xe8\x05\x83\xf2\xf2\x8e|\xe5Kr\xe5/\xe9\x99\xcf\xdb\xf7\xfe$8\ +\x85}\xbe\xf5>\xc5\x81D;>\x7f\xe1\xe2\xb9s\x17\xb6\xb6\xb7\xf7\xd1\x1f\xbb\ +\xdd\xde\xd5\xab\xd7\xae^\xbd\x16\x86\xe1m\xa7O\xdds\xcf]\xa5b\x11\x11\xe3(~\ +\xf2\xc9g:i\xec\xbb\xa3s\xfb\xf1c\xc7\xcc\xad\x1e\xcc&\x87\x88W\xaf]{\xe6\ +\xd9\xe7\xcd\xecPj\x9d\x8c\x00\x04\x93\xf7h?nsh\ +\x14B\x88\xc1^E\xc3\xb4\t\x01)\xe4s\xcf\xbf\xf0\xf8\xe3O\x8a1{L\xc3\xb0o\x90\ +!\xbd\xa3G}\xce9\xe3l\xe4f\xd5(\xf6[\xff\xac{%"nmo\x7f\xf3\x9b\x0fonm\xefQ\ +\x1bi[\xcd\xe0\xda\xa0\x8fDQt\xe9\xf2+\x9dN\xfb\xb6\xd3\xa7\xe8\xe1\xdf\xee<\ +,\x14r\xf9\x1c\xd7\ +\xa1\x10B\xc8h\x8b\xb2,\xbbPY\xe0H\xa2\x9d\x8b\x80@\x00$\x12\xc6\xa9d\xfd\ +\x04$P"\xb8\x96$\xf6\x8dx\x99\xb4\x1c\xee\xf1\x10q\x087\xdd\xe3\x9fg\xe5\xbb\ +\x01\xf6@=u?Pf\x15c\xa7\xca\xac\x92\xee3\x83kd\xe4OD\xe8\xac\xca\x0b\xbf3\ +\xb6I\x99\xbd:\xee\xd6\xe1\xf1\xff\x85n?\x0eh\xd0b\x88\xc3\xff\xf4\x9f\x9amO\ +^c\xdc\x9c\xa4\xeb\x14\xbag\x7f\xba3\xf9\x91(\x8a\x06\x9b\t\x98iB\x06\x98\ +\x8c\xbd\x03t>\x11\x87\xcf`\xda\xba>p\xc4J\xc53`\x8c\xa7j#C\xa3\'\xdd\xd5\ +\xac\xf08\x8ews\xf7u\xfd3f\xda\xc6\xb3\xaa\xe0\x80\xab\xdfL9\xa8\xa4+Pc\x13]\ +\xfd:e\x8d\xc1\xe3\xa3\x90\x81\xc8f?\x8a\xd4\x1b}\\\x08\xc1Y,_\xf8\xf5\x01\ +\xb2\xa7\xaaed\xb0I\xe5p\xa4V\xf5\x83*\xf5k_\x96\x17\x0c\xeb\xee\x1eE\xd0\ +\xa5\xb8zm\xe9\xf1\'\x9f2\x90]\x7f\x82\x81v\xec8n>\x1fNLLT\'\'\xab\xd5J\xa52\ +Q\xc8\xe7\x1dGwu\xa2^-\x84x\xe1\xa5\xf3\xadvv\xa7M\xb9\x07\xb8\xab\xed5\xfa\ +\xfd~\xb2\xef\xc4\xb0\xa4\x8c\xc5\xcf<\xfb|\xbf\x9f\xd9\xfc\x16G\x8e\x87)\ +\x9biFQ\x14Ec6\x84C\x99\xcd\xc9\xd8\n\xa9\xd7\xeb\xdfx\xf0\xa1\x04\xd9\xc7\ +\xdcoYV\x98\xcb\x95K\xa5\xead\xa5Z\x9d\x9c\x9c\xac\x94JE\xdf\x1b\xf5\t\xc6\ +\xf5\x8d\xcd\xfap\x84xkJ\xb1<\x1dCn\xd0W\tz\x1e\xb5|\x9f:\x0e\xb5m\xe28\x8e\ +\xeb\x86>\x03\x18\xdf\x95\xf6\x92C\xaf\xb9k\x80\xe8\xdb\xf3\xcd\xd3?]y\xf9\ +\xff\x08Z/fyvB:\xee\xa9\x8ew\xa2\xed\x9f\xe9\xdb\xd3\x92zTD>_/\xf6\xce\x97\ +\xfb\xcf\xd9\xa2\xad\x92\x1b\xb0(\x1a\x8e\x01\x00@^\xf9\x8f\xf4\xcc\x03\xa4r\ +6\xf3jH\x90\x8e\xc5\x11\xbe\xf4\x1b\xd6\xfa\x83)\xec6\xe9\x11E\xa1\x8cQ!a\ +\xa0\xc2\x0f\x9eB\x00\x82V\xd0:\xf3\xe3\xbd\xe9O\xaa\xdd!i\x1c\x81\xe4\xa90\ +\x03YU\xdd\xf8\xc7\x04\xe5\xcc(E\x06\xd8\x01"\x86\xc1>\xc2\xc3I=I\xb6,\x18C\ +\xec\x00\x80Z!b\x14\x7f00p\xb1]\xfcH\xd8}iX.\xb3\xcf+\x95\xff\xea\x97\xe5]\ +\xff--\x9f\xc9hy\xe6\xdb\x19c\xf9\xdd\'R\xa3\xd10\xcf\x08\x08\xbcp\x9b,\xbeM\ +\xa7`N\x98\x18cb\xf9\x1b\xdeK\xbfb\x98\xe8\xf4$\xcc`o\x88\xddqN\xc4v\x89[E\ +\x00pD\xddg[A\xbc\x9c|\x97\x11\xa5\x1e\x11\x00\xc4K\xbfA\x8e}\x92\x16\x8e\ +\xc18\xd1\xfa)\xe7|\xb7V{\xe4[\x8f\x1a\xa4\xf6p\xfcF a.(\x16\x0b\xe5b1\x97\ +\x0b\x94ET\xaf\xbb\xe9t{\xf5z\xa3Vo\x98\xae#i\xb2~\x98\xe4(\xa4\xea:\xd4;A\ +\x9b\x12E\x0c 6\xeb\x81R\xe2\xfb\x81c\xdb\xb6\xe3\xb8\x8eC\x08\x11Rr\xcel{\ +\xc8\xb9\x9bi\xa6\x8d\x9f`\x12D{U\x88z\xbc\xdb\xed>\xfa\xd8\x13\xb5z]\x8fm\ +\xe6\x9d\x9e\xeb\x16\na\xa9T*\xe4C\xe5\x8c\x9b\xb83\x92~\xbf\xdfh6k\xf5\x86\ +\xa1\xef\xabo-4\xb39\xa6r\x0e\xbfX\x96]\x9e>\xbd\xb3\xf2B\xce\x05\x8b@\xcej\ +\xfa\x9e\xcf0\x90\x12)p\x0f[ Z\xe9^xc9\xac\xe0\x9eQ$\x15o\xdb\xa3S\xad\xf9\ +\x9f<\xbe\xf4\xf3\xb9\xfe%\r4={n}\xe2\xaf5\xc3wFvU?\x8b\x88\r|\xfbz\xfe\xa3\ +\xc5\xfe\xc5\xe3\xb5\xdf/\xf6\xcfg\xd5UHt\xed\xde\xba\\\x7f\x94L\xdc\x99\x81\ +\xa7\xe1&\x8d\x1bO\xfb\x97\xff]\xa2\x9e\xa7in}`RC:q\xfdg\x82\xd7\x08v\xfd\ +\xc4\x8f\xf6f>K\xb4\x95L\x02R\x87\x88\x08\xa9erG\x04\xc5\xbe\x14\rI\xee\'\ +\x00\x084\x19\x01\x10\xd1rQ9\xd9\x1a]\xd1\x96r\xa8\xfe\x8f&\x9b\x88^0\xa2|\ +\xe4\x11\xb1\x16\xbcc\xce*\xbb\xbc\x96-\xb5\xce\x0co\xe3\xdaCP>3\xfa\xed\x86\ +\xa6\xd4\xe65\xaf}.\xf5\xd4\xf0V\x02\x04\xa2\xd9OC8o\xbaW\xab\x9c3\xc6Xk\xcd\ +}\xee\x17@\n \xc9\xd4\'\xab\xf8\x93\xa6\x7f\xe7z\xe9\xb3m\xef\x14\xb7\x8aj\ +\xeb1"#\x9foU:O.4\xfe\xc8\xc2(!E\xd2\x1c\x0e"\xb4\xae\xcb\xe7\xff\x15\xb9\ +\xff\x7f\xdb\x87V\x12B\xf4z\xbdg\x9f{\xbe\xd31\x9d[\x06\xf7[\x94\xcc\xccLOV&\ +<\xcf\xcb\xf8\x86\xabJ(\xe4\xc3r\xa98;;\xbd\xbc\xb2\xba\xb9\xb9\xb5\x0f\xeb0\ +J\x86\x98\xa3\x0b\xe7\\Js\xd2`\x92~\x83?\'\xca\xa5Je\xc2\xf7\\\xdbq<\xd7\xf5\ +q\xe2Xe\xa2<\xba\xcc\xdd\x8cf\xc59wl\xfb\xe4\xf1c\xb9 \xb8\ +r\xf5\xda>\xf85\x8a\xaa&\xc1ml!\x9d!\xfd\x88e\xd1c\x0b\x0b\x95JYGL\xd4\x1f\ +\xd1u]\x15\xe813\xf0\xe8\x0f4\x9a\x0b\x93\xc6\xc9<\xa2\x90\xbdV\xab\x9f?\xff\ +\xb2q\xcf0\xe5\xf9\xb9\x99\xb9\xd9\x19\x1d\xc0\xc0\x1c\xa8Tm\xa8\xb2PJgg\xa6\ +\x82\xc0\x7f\xe5\xca\xd5~?\xc2\x81\xd9\xf9-.\xa2u\xb5\x10\x00\x00a\x1c\xb6\ +\x9b\xd8\x8d\xa4kwr.XVv\xeas@9\xdc\xe0NF\x04\x00"w\xee\xca\xcc\x8f\x9dY\xfb\ +\xa5npfe\xfe\xc7\xa8\x9b\x0b\x92\x08p`\xb4B=\x1e\x082\xb14\xf1Cg7\xbe@1\x1e2\ +\xd4d\x08\x16X;\x8f\x9du\x08gI\x12\x87HsAb\xebyg\xf7\t3Ccu\xdeFp\xd7J\xe5\ +\x81\xae{L\xd0\xc1\xa6\x01\x88\xd8\x0c\xdf\xb9Y\xfa\xd8t\xfb\x9b\x8b\xb5?\ +\xb0Dwk\xfeG\xba\x8b\x9f\xf3\x1cW9\xbd!\xa2m\xdb\xdc\t\xa3\xfc\x9d\x03\xef\ +\xc3\xe4\xd5\xae\xa8e\x8d\xa5$\xa5\x1fq\xa7\x12\xe5n\xd3\x0b\x0em\xdb\x06\ +\xcf\xb3s9\x11\x86\x90\xcb\x11{\xef%\x91\x19\x8c6\x8a\xa3D\x87\x84Ua\t\x18c\ +\x8d\xf0\xbe\xc5\xfa\x7fH\xf9\xd8df-\x9bO\xca\xf5G\xc9\xdc\xfb3*\xa7\x06\xf7\ +|\xe3\x99\x01:\x9b\xea\xf3 \x05\xe0\xf9\xdbI\xf9\x0e+\r\xee\x83\xb9Z{+\\\xfa\ +\xfd\xe1\xad&\x03\x86\x08\x00\xf5\xc2\xfb6g\x7f\x84\xbaE?yVc\x96\x92\xdd\xfc\ +\xf7xb\xebD\xed\xff#\xb8\xc7>8\xf5\xcbr\xf9k\xe4m\x7fk,\xf6q\xce\xbb\xdd\xee\ +\xa5\xcb\xafH\x99\xa1\x0b\x88eY\'\x8e/NOUm\xdbV\xf1\x1b2\x83\x93\xce\xc3\xc0\ +\xe9\x10\xb1:Y\x89\xa2hum\xe3f\xc9\x07\x1c\xd0\xf1\x19\xc0\x1d$B\x089q|qzjJ\ +\x0f0\x07\t\x14\x83I\xa2#2&cf\xa7`\x8c]\xbbv\xad\xd9j\x99yP2=]=~lQ\xbf\xd4\ +\xac\x10L\xdc"\xcc:\ts\xc1\xb1\xc5\x85W\xae\\\x13B\xbc\x85\t\x19%\xa2\xb7-\ +\xa2F\xc2,b\xde\'L@\xc4\xa0\xd6\x05\xd7\x86\xc0\x05\xc7V$\xe5M\xc8a\x05wb\ +\x84\n\x1a\x13\x84\xda9u\xf5\xd4?\xa5N\xe0\xf9%\xb3\x05\xab\xa7\x86j~\x1c\ +\x13B8\xe7\xad\xdc=m\xef\xf4\x80\x9cA\x1c\xf8\xaai\xb4j^\x95\x9d5+Q\xdf\xd00\ +*\xba\xd7\xff0\xc9Q\xd2\xf82\xd43\xc0v\xf1\xc3\xcb3\x7f\x0f\xed\xd0&\xc46\ +\xb4-)%@yk\xf2\xafS7\x1f\x88\xdd\xf6\xf1\x1f\xf6]\xcfu]\x15\xf2\x85\x10\xa2Z\ +\xb9*\xa3n\xf1B\x08;eW\x19\xf1\x8a!\xc4"\xa0x\x00H\xc0]%\xbb_T\x90\xd1\x8e<\ +\xc2\xbf\xeb\xf0\xaa\xb6!\x91\xbfX\x0b\xee\x9d\xe8==\xd6\x10\n\x84\x00\xc6\ +\xf8\xca\x97`\xee\xfd\xba\xf6Ld\'\x8d\x8bv\xb4n\xf0\xfb\xe9\x04\xa8\xcbf?f;\ +\xae96\xeb\xdd_\xc9\xd2\x7f\xb2{+\xa9\x9c\x0f\xc7f"h\xb0;\xfb\x80\x9b\xafjlU\ +\xaf\x1e8\xf91\xc6\x18\xe3\x9co\x14?9\xd9y\xac\x10]\x1ef@\x8d1\x03\xe1\xb8\ +\xf6\x10\x9cy\x00\x0c\'\x07\x13\xc8vwk\xcb++\xd9\x82\x03LU+\xf3\xf3s:8\x8f\ +\x0e\xabi>nfC5\xdd\xc9\xcaD\xab\xd5N[So\x19\xd4\x06O\xcdLO-\xcc\xcf\xeb\xb00\ +\x99.s\xb0x\xce\xd9\xa1k\xf4\x0e\xad\xb6w\xbb\xdd\xd5\xc1R\xa9\x94\x14\n\xf9\ +\xd3\'O\xe4r9\xd5\x14u\xc0"\xd3E\'S\'R\xcaB>\xacNV66\xb7n\xa9\x06\x0e\x91 k^\ +U\xb5\xac6Yu,p,\xe2\xd9\x10\x0b\x88\x186\xba\xe8X\x10x\xc4\xbd\x19\x88?\xac\ +\xe0\x0e\x896\xa9\x9a\xa9\x8an\xa80QY\x96,\xebDF=15w\xc5\xd1\xd3\xc1\x8e\xe9\ +\x88(\x9b\xfe\xd9b\xff\xbcJ8\xfb\xa6\xb8\x86\xbdMH\x03\x13c\x8c\xb77\n\xdb\ +\x0f\xe9\xdc\x0c\xa1\xd0\x98\xe07\xc3w\xac-\xfcw\x8e\x9b3\xe1)\x99G\xab\xf8\ +\xba\xb4\x1d~?\xf3<\xdf\xf7}\xdfW\xf1T\xd5yU\x1cU@\xa5\xbcs\xce\t!\x84\x9a\ +\xf3\x83\xf4\x9c\x95\x10\x00\xb0,+\x08\x02s\xd7\x02\x15\x05L\xc3\xdc\xd8\xda\ +\x84AthL\xad\xb7\x82\x14\xee\x9b\xb8\xa0j\x95\xd9\xe1V\xf1\xa3\xe5\xde\xb3)3\ +\x80\xa9\xc2#\xe2\xd6S\xc8\xfb\xc4\xd1\x9b\x03\x0e\xc1\xdd\xddz\xd0\x896\xc6\ +\x18\x8a\x01\x00@\xf8\xf3r\xee\xa3n\x82J\x90v\x8d\xcfm=\x02(\xb3/Mr\xdb)\xbe\ +\x9bT\xee\n\xfdPA\x89z\\[h\xa2(R\xe0\xc2\x00\xda\xdem\x85\xfee\x83\xdbI\x19\ +\x87\xb1~Q\xb6\x96h\xe9t\xc6\xc1\\\x8d\xee\xeb\x1b\x1bB\x0c\x1d\r\x11\x90\ +\x00\x04Ap\xf2\xc4\x89\\.\xa7\x03&\x9b\x00jRRq"\x90\xcc\xd5\xaa\xd5\xc9N\xb7\ +\'\xa5L\x9b"oJc\x1b\n\xa5\xe4\xf8\xf1E\x15\x94_\xab84\x11U3\x07\x08\xf1\xb8\ +\xdf\xd5\x8c\xda^\xaf7vvv\x8c\xcc\xa3\xea\xa9\xf3s\xb3\xc5bQE\x0c\xd6\x15\ +\x92\x99Lk\xe3\x99\xaa+u~\xa2\\j4\x9a\xfd(\x1a}\xf3\xad\xd5\xc9\x9bPxgC\xb2\ +\xc1\xda\x08.\x86\xe5\xb2(\x04\x14<\x9b0\x0e}\x8e\xe8VI\x10\x8a\xce\x1a\xc5\ +\x18\xb2:\xe4\x189\xc4\xe0\x0e\x89\x89\xcfq\x1cLxa\x15\xa7T+\x98\x03p\x8f\ +\xb7\xad\xfe.\x15]\xe0]\x88\x1a\x18\xd5e\xd4\x90QS\xb0\xbe\xe0\x91\xe0\\\x08\ +\xe9\xf7\xaf\x00(\x8c\x18\xd8\xf1L\xb7\x16\xecm\xe3\x88#0\xd4^\xa2\xbc=\xb4[\ +\x8e\xf0\xf5\x82\xe6v\xe6~\xd8\x0bKfHt\x9d\x82\x1e\x8dT\x18)\xdf\xf7\x15\x16\ +(XW\xed\xdb\xb6\xed\xc1@\x92\xb4{\x00\xa04Y\xb3:\xde\t\x07m\xdb\xce\xe7\xf3\ +\xe64\\\xe3\xbb\xde\x9bf\\m\x82Q\x16Hu\xe9\xc4\xf6\xa5\x07\x1b\x13\xdf\xbb\ +\xc1\x99\xae\xb3\x18\xb2\xa5TNL\x88o]\x93\xd7\xfe\x98\xdc\xf6\x83\x9a\xd7\ +\x1a,\xbd\x89\xda\xf9\xe6\xf3)dOA\x07\x0c\xd3\x85f\xba\xfa\xbb\xd8\xafAI\xd7n\xca\x9f\ +\xa4V\xab\'\x8f\xe9w\x93\xca\xc4D\xa52\xa1?hf\xc2d\xd6\x80\xa9\xd4\xab\x94\ +\xf3a.\x08\xfcN\xa7;\xa2,\xdf\n\x96U*\x95\x89r\xd9\x04w3\xf2\x17M\xefY\xb1\ +\x7fRj2;6\'\x9a\xa4b\x8c\xad\xad\xaf\x0ba.\x97%\x00X,\x14\x8f-.\x98\xa3]\x86\ +\xa72u&\xad\xd4\xab\xf3\xbe\xef\x95\xcb\xc5\x8d\xcdmD9R\'o\tA\xc9ZK`\xa8\xed\ +\x19\xa1\x04<\x07\\\xc7*\xcf\x9f\xb6\xdd\x9c\xe0\x0b\xad\xdaz\xdc^\xb7\xb0;T\ +\xc6\xc6\xc9!\x06wM;\x00\x80\nB\xad\x94\x11\x1d\x94\xdc\xed]q7\x9e\xb4\x1b/\ +\x92\xce5\xd2\xdf\x01\xde\x05\xde\x1d\xae`\x1c\xa7*&g\x8c\n#\x04\x08"\xeb\ +\xe0\x88\x7f\x0em_\x07\x99\xa8\xab\xa3M\r\xb1]\xbe\x1f&\xef\r\xfd\x9c\x198\ +\xd7\xa4\x17\xa5\x94\x9a\x00u]W)5$\xd9/F\rTB\x08\xd7u\xe38V^tB\x08\x92\xd6\ +\x8bM\xf3\xa3:o\xdbv.\x97\xd3L\x94\xee\xc6\xda\x10*G[P\xc6wsL\x9d\x0c\xea\ +\x9c\x1a[89\x8e\xc3\x18\xeb\xbb\x93\xbb\xf9\xf7\x84\xb5\xa5l\xaet\x9a2\xc6K_\ +\x84\xd3\x7f\x1d\xc1F\xc3XGZW\xdc\xce\x15\x03\xd9S\x8fK\xbb\x10\x9f\xfc\xbcg\ +Pj\xfaA\xc6\x18i\x9c\xb7X-y\x0b\x8e\xe6<\xbf\xf5\x17a\xfby\n|X\x00B\x94U\x12\ +\x11\xa5\x14(Q"J\x04\x9b\xd7\x8d\x0f\xa8\x94o\xc3y\x9451n&\x954l\x03\x8c\xb1\ +~\xbf_\xaf7\xd2_\x9fX\x965;;\x13\x04\x81\x9e\x87\x99\x1f\x02\x12,\xd3Z\xb3\ +\x89\xecJ\xf2a\xd8\xedt\xb5\xf7\x95N9\xfb\xc9\x0e \xf3\xb33a\x18\x9a\x90\xaa\ +\xb3\x91\xb6U\xed\x95\xb8\xf6\x10\x00cI4I\xdf1\x1c\xab\xe28\xde\xde\xd9\xd5W\ +\xf4\xa3\x93\x93\x95B\xa1\xa0*d\x94\x1eD\xc3\xb7\xd5\x1a\xb1\x9cK)\xf3\xf9p{\ +g\x87s2\x92\xf2[AX{\x15yOU.\xe3{\x0e\xe1\xb9\xf2\x82\xed\xe6\x00\xc0\xb2\xdd\ +\xf2\xd4q9\xb9\xd0\xdcYa\xed5\x8a\xbd=&wx\x88\xc1\x1d\x0c|\xd7\xde\xb2\x94R\ +\xc1\xfa\xf6\xb5\x7f\xef\xac}\x95v\x96Io=A\xea\xb4\xbf9\x8cp\xca\x19\xed/\ +\xadK\xa2\x88\xcd&\xa8\xc0=\xd7]"(\x8c\x94\xb3\x99\x13\xc5\xb7\x05a!\xb3\x99\ +\x91VRTR\xc4\xb0R\x9a\x03\x80Rm\x14E\xc39W\xcfr\xce\x87\x93h\r\xeb\xa6c\xb8\ +\xe2\xdc-\xea\xfb\xbe\xe9\x90@n\xb85\x81*\xc2@{\x1d\xeb^9\xacsM\xce$\x08e\ +\xd7\xf2\xf7O\xb5\x1f\xf1\xd9\xfa0\xb5\xb4`\xe3\x92\xac_"\xe5;L\x9b\x87S{\ +\xc2\xe6\xbbCd7)&\xc4\xb8\xfc\x0e2qV\xf7v\xd3\x8c\xc9\x18\xa3\xad+D\xf6\x8dR\ +g\x0bd\xc5[\x10m\xa6\xbe&"$\xb0ae\xec\xc6\xfa@\xeb\xa6zr#"\xec\xef`\xe2\x83(\ +\r\xd7\xacv\xa7\xd3\x8f2\x11\xa4\xc1u\xdd\xf9\xb9Y\xc5?\x98\xfb\x9c\x98\xd5\ +\xae\x001\x83\xf8z\xc8/\x16\xf2;;\xbb<\xf1T\xb9%_\x91As,O\x94\xf7\xd9qE\x1f\ +\x9b \x9b\x96\xe1\xa8\xbb\xbf)Uk<\xfd~?\xc3\xc9PJ\xcb\xa5\xe2\xe8\x16}f\x06\ +\xb4\xfd,C^)6\xd2\xf7|\x8b\xda\x1c\xe2\xa4h\x90>8\xc4\x82\x92\xf3\xf6u\x00 \ +\x00\\\x80\xdc\xc3\xe1\x91X\x8e_N\xad\xb7\xa0\xd4R\x10\xdf\xaeo\xc6\xadU\xe0\ +-\x9aL\xe6!\x99\x84\x1fnp\x87\xa4}$-\x838k\x7f\xe6]\xfcw\xb4\xf6\x02(\xff\ +\x87\x0c\xffk\xd6\x9c\t[\xc3\xfe\x0f\x00i\xd0T"\x18\x18\xb8\xac\x9a\xb2\x15\ +\xef\x0c\xe9\x8bq)\xd3\xfc\x82r%\xceXt\xb5\x83\x04&\x86Js\x82\x0c\x89\xb9X\ +\xdb\x00\xd5\x9fC\x95G\xf3m\xa6\xdan\xfc\x12B\xd5Pav\xa1Lw\xca\xca\xb0Q\xc00\ +\xb5\x11"\xdbdfL{F\xe4\x1fk\xbb\xa7|\xb6\x9e\x1a\x18\x0c\xe6\x1a\xfa\x9br\ +\xe5AZz\x9b\xd6\xbeew\xb3\xb0\xf3\x90a\xa80*\x91\x10\x00\xe03\x1f1\xe7\xefZC\ +T\x95\xef\xf7\xb7\xa8d\xa9\xcf4\x8a\xd7F+I\xdd\x90\xfa\xb8\xe3\xac\x0bf\xce\ +\x11\xb1_\xd3\x1f\xcb\x1cc:\x9d\x8e\x1cF\xec\x1a\x0c\x0b\xf90\x17\x86\xa1F\ +\xf6\xb1\x8c\x87:cn\xf8\xa9\x07\x0c\xce\xb9\xe7y\x94R\x10j\xd9\x0e\xdc\x92\ +\x17\xe0 \xfd\xc0\x0f\xd4\x8cPO\x11nH\xbf\xa4E7\x0b]@\xc8\xa0\xaa\xd9)\xe28\ +\x16\\dn\xb3,R.\x97M;\xeah6t\xd7 \x86C\x9a&$=\xcfu\\\'\x1a\xc4BxUS\x997\x9b\ +\xf0\xd6u\x141\x00 \x00\x17{.R\n\xca\xc7\xe8\xb8\xcd\x06(\xb5\x8a\x959\x9c\ +\x98\xed\xb6v:\xb5e\xc2\x1a\x94\x0c\xaa]"=\xf4\xe0\x8e\x89H\xd6%\xcf\xfc\xa2\ +u\xe9wA\xb2=1}\xb4\xdbg\xac\xa0$\xddt\x87\x1ct\xaao\xab\xa6LD\'\x95\xc2P\x08\ +\x00 \xf5\xac\xdc\xa4\x93X\x90L\xd46\x05\x92\x96\x9dQ\xabMeJ\x99\x10\x86z\r\ +\xd9\x83?\x01Pz\x1eI\xf6\xcd\x19\xab\xa6\xe1\xd8\xa8 \xc4\x98\x82g\xa8\x95q\ +\xfdP\xb3I\xaa\xc7r\xcew\xf3\xdf3\xd1}\xca\xc2\xfe\xf8\xbc\xa1\xc4\xeb_\xc5\ +\xdb\xfe\xa6\xa4\xa1\x022\xe8\xac\xf8\xed\x0b#U7\x10\x1e\x1c\x13s\x1fw\x8cR\ +\x98|\x8e\x10\x02D\x0f \xb5\x96x\xa4&n\x14OF\xd7X\x06\xfa3\xf7# \xef\xe9\xaa\ +KaY\x14\x8fB\xcc(\xc1=6wz\xd2i\x8e\x94\x8e\xe3\xc4ql\xdb\x19\x0b\xe7x\xa6\ +\xfb\x86B)u=\xd7N\x13\xdc7)Dc\xbaQ\x9dYZF\x8fv\x9cs\x89\xd2xVe\xc3*\x14\n\ +\xda\xac\xbdO6\xf4\x98\'\xa5\xd4\x15\xa2C\xceP\xdbk\x04w\x03\x8c\xe4D\xa7\x13\xd5q\xe3\xf1\x81%\xb9\ +\xb7\x9b\xdf\xfc\xb3\xc1y]\xe7I)\x90\xd8b\xfa\xfd\xa3\xc8\x9e\xaa\x7f\xe2$cv\ +\xfa-\x90\x8c\xe5D\xd3V\xe3h"H\x06\xe6\x8c\x98__\x8f\xd3\xc6mf\x1eFjz0\xc388\ +\xb2\xeb\xa1\xd7\xb4x\x9b\x1a\x88!\x07\xf9\xac\xa9{\x08\x01J^\xddf\xa7\xd9w\ +\xe2\xd8l\x98ub\xc4"\x1c\x18p\xd4\xe5\x837\xf2L\x85\x0c\xb8J\x04\xd8\x83\xf7\ +?\xa4\x82\xbc\xc7;k\xeaX\xa9\xedc\xc5\xf6\x8b^\xfe@\xa1\xa7Yg\xc3\xc3z)\x80r\ +\x0e\\\x07Z\xfdC\xa9\x1f\xbd\xcf\x00\x00 \x00IDAT\xcb\xb9\xeb\xc6\xc4\x18\ +\xe3\xb5\x97\xdd\xf3\xbf\t0\xc2\'\x98g\x00\x81\x90\xd8\x99\xeaz\'\xfb\xeellW\ +\x19\xcd\x0b\xe2!\x10\xb5\xfc\xbe\xd2}b\xa6\xfd`r\xb3\x16m\xdf\x1b\xbc\x14\ +\xcc\xe9\x02-&\xf7\xa7\xb4\xe5A\x06$\xa7\xfd\xcd\xfd\x89\xce[\xefu\xfaE@\x86\ +\x8e\x9b\xfb\x91\x0f\x07H-C\xe5+A\xcd\xd8ds>\xa2oZ[\xa5\xef\x9dj}\xc3\x13\ +\xbb\xa9[\xcd\xf9\xfc\xb5?\x14\xf3\x9faP&\xedk^\xef\x95\xd4\xcc\xc9\x80\xd4\ +\xa8z?T\xde\x911T\xe8jW\x07\xcc*!\xb5\x87+K\xb3$\x92\x19\xac\xcd\xa0\xe62\ +\xdcz\x16\xdf1uF\'\xc8\xba&\x93&\x93\xe0\x01\xb6e\xa5)\x02\x02\x00\xfd(:\xe8\ +l\xc9\xa8Lj\x08$-\xed\xe6%\xf3\xc6\x9b\xcb\xc6\x1e\t\x9a\xcd{\x0c\xbc\x9au\ +\x02@(!\xe9gAJ\xa9\xeb\xe4@\xafL\x0fxjT`\xd9\xb0h\x87\x9e\x93\x89\x9b\xd7\ +\x00%\x00H\xdc\x8fm\xcfM\x9c\xe0{5\xb2\xeb\x83f\xb3)D&\xc4\xe3\xadc\xf4\xab\xc5\xf7tb\x99\xbf\xb5S\ +\x80~\x97\xe3:\xd0K5?!Dk\x10j\xe6\x16%\x8a"]!o\x8d\x08b\xbc\xb3\xaa\xac\x83r\ +\x1f\xb6\x9d\x90\\\xe5@\xad\x08E\xc4Z\x03\x7fJD\xd0{\n\x1c>p\xcf\xa8\xedQ\ +\x14\xe5{\xca\xbd:\xbb\n_I#\xbco{\xe6\x01\xdb\xf6\xf4\xdak\x92\x80\xbb\xf6\ +\xcf%\x848\xb2=\x86\xd5\x81,\xfa\x98]\xa5\xef- \xb1\x01\xb3\xbb\xda\xeb\x14H\ +o\x03/\xfe.\xbc\xefg\xe1F\x1b\xfa\xdc\xb4\x0c\xd5\xe1\xc1\xff\xa9yF\xb4\xbd\ +\xf7\x93{\'\x88\x90\x19$\x00\xc6\x81\xfe\xe0\xf6\x81V\x95\xf1\x89\xec\xf8g\ +\x1a\xc1]\xa5\xfe\x8b\x00i=/\xc9\x9b\xbb\xf5P@+n\xb42\xccm\x9ac\x8e\xa6>BK\ +\xa7\xc6\xda*\xccWs\xab\x18;U\x9f\xaf\x0f\x07\xb9\xf4\xd7/u_,\xc8\x8d\xc8\ +\x1f\x1f\x8d}T\xa8\x8c$\xf5T\xfa\xf6H\xdc\x95\x8c\xc9D\x1dX\x16\r\xc3\\\xc6\ +\xd5\x9ds~}e\xe5\xe0\xe0nr}\x00 \xa5\xac\xd7\x9b\xa3\xb4\xcc\x81\x03\x8a\x0c\ ++\x02\xf7\xa0\xc8_\x85dU\xcc\xd1\x0f\x94\x0fC#\x14\xfb\xe0\xfe\x8d\x8dM\xb5@\ +\xe9\xd6\xde\xdah\xb6F\xf6\xb7\xba\xc5\xa9\xcc\x9bAP2\xde\x1e\xc4#\xe2|\xcf\ +\x92x\xf9i\xdb\xcb\x1f$A\xd6\xbc\x8a\x92\x03\x00\x10\xe0|\xe8us(\r\xaa\x86)\ +\x95\xc5ql\xb1\xdd\xf1\xf7\x11\x02\x844\xa7>\xe3\xe7\n\xb9\\.\x97\xcb\xe5\ +\xd3\x92\xcb\xe5\x82 p]\xd7\xb6\xadR\xff\\V\x01\x1f\xd0\x05\xa0z\x88\xa9[)\ +\x89\xbd\x85Vpg\xf6\x8d\xe61"\\\xf8\x1dq\xee\xb7\xf6\xda\x8dH\x89\\{H^\xff\ +\xf3[\xae\x8b\xec8D\x80t\xd7\xa1\xb7y\xd3\xe9\x8c\x15\x93\x8b\xcf^I\x99U\x07\ +~A\xb6\xbbY\xfaxr\xff\x98\t\x8d\xd5[-/\xfd6An\x189\x93;\x11$\r\xc4\xf4\x07\ +\xc6:x\x90\x11i\x07\xb7gk\xc0(\x8b\xcb6\xa7;\x0f\x05A\x10\x04A.-\xc1\x88L\ +\xb2\x0b\xa7\xd6\x7f\xad\x0c\x9b\xeaf\x1d\xe7G\xe3\xbb\x99\r\x00\xd0\x88\x9f\ +\xcb\x05\xd9\x92\x02\xac\xae\xae\x8d\xdbFuO1\xf1}w\xb7\xd6\xed\x99\xcf\x92$\ +\xd6\xcf\x01\xb1\xcc\x18\x84^{\x0b\xe4~\xa6#U!\xa5b\x81\x90\x94\x11\x02\x00\ +\xb6\xb6w\xae^[:\xf8kL\xbe4\x8a\xe2\xcd\xad\xed\xf4hw\x88\x91\x1d\x00X\xe2\ +\xdb.\x10\x84\x1c\xaf\xb6\x13j\x07\x13\xa7\x0e\x92\x9a\x8c[\xbc\xb3\x0e\x00\ +\x84(\xfa~X5\x87\x12\xdc\xcd\x95\x8a\x8c1\x82\xa3\xee\x8f\xc3\x0eo\x853a\x18\ +\x86ah\xc2z\x18\x86\xaa\x93\xabUs\xe5\xeesa\xff\xf2\xe0A2\x82e\x98\xd2\xda\ +\x88\xb1\x94nK\x03\xd9xe\x9f\x00\x01\xf9\xc4?\xe7\x8f\xfd\x1c6\xaf\x0c\xd3\ +\xd3\xa69\xc1\xc5+\x7f$\x1e\xfcI\xfe\xf5\x7f \xae}\xe5\xa6+"\xe5\xb4\x97\xd8\ +B\x81\x90h\x1b\x96or\xb4H\xd9c\r\x9dOy\x8c\xecK\xce\x8c\x84\x9a\xb9=\xb6+\ +\xa94u\xf6\x08\x01D*\xfb\xc3\x93)\x8f\x14\xe4\xc5;I\xe5\xae\xbd\\\t3\x86\xc7\ +\x9d\xd2\xc7\x98U2\x86a\xa3\xfe\x11\x81\x90\xc9\x8d?\x98j?\x9c\xdfCT\xab\xc8\ +\xe5re\xb92w\xfdW\x0b\xf5\x87\x17_\xf9\xd9\xe9\xd6\xd7\xc30\x17\x86\xa1\x8e\ +\x1f`\xae\xda7\x91]\xfd\x16\x0b\x05\xdb\xb23XS\xaf7\x1e{\xe2\xa911\x1e\xf6\ +\x10M\x0f\xf6\xa3\xe8\xca\xb5k\xc6n\xa8\xf8j\x80\xec\xb5\xd0\xdco\xfcxF\xe3\ +\xf1}/\x1f\xe62yf\x8c\x9d;\x7f!\xbd#\xeb\xde\xafL\x86:U\'\xcb\xcb+\xedvf\xa4\ +$\x07\xcc\xdb\x9bPPDC\'\x19\xbe\xa7q\xcc/-X\x8e\xbf\xc7\xc5\x94\xc4\x8dW\xf4\ +\xc8\xa7\xe6\x01Z\x0e1-\xa3I\x15\x03\x86\x0c\x98#\x833\x85\xde\x8b,\xf7\x01\ +\xa5\x82\x99\xde\x17jM\xbf\x94\xd2g\x1bS\xeb\xbfC \x1d\xd4ph\xb1LQ\x8a\x19|i\ +\x87w\xf7\xdc\xf9\x80\xad\xa9\xcb\x19\xaf\x0f\x9d\xa0<\xf7\x7f\xe3\xda\xc3d\ +\xfa=d\xe6{\xa0t\x1b8\x05d]\xac\x9d\xc3\x95\xaf\xc1\xf5?\x03\x11\x01\x80x\ +\xe4\x1f\x13\xcb\xa3\x8b\x1f;@\x1dX\x03\x83R\n\xfb\x8cc\xd6\x83\x17~UR\x9b\ +\xbe\xeds`\x19\x9bR\xb2\x8e\\\xfd&T\xdf\t\xde\xd4\x98TM\x0f\x19\xc0\xa1\xc9j\ +O\x9d~\xe8\xb3o\xba\xcdD\xee\xd4z\xf1\x13\xc7\xd5v"\x19|\x1f%\xf1\r\xfd\x1d-\ +7\x9e\xf9^\x1aT\xf6B\xf6L\xfd\xf7\xdc\x99\xed\xfc\x07\xe7\xea_\x1e&\x95r\x91\ +\x02 r\xe2\xf2\xaf\x04V\x14\x9f\xfa\xe1L\xe6\xb5\xd7\x8d\xb3\xf6\xe7\xe1\xc5\ +_\xb5\xfak\x00h\xf7\xd7\'.\xfe|\xd8\xbb\x14\xbf\xfd\'\x88_P\xe5\xcaL#\xcc\ +\xc5\n\x94\xd2 \xf0\'\xb31i\x11\x80\\|\xf9\xe5\xa9\xea\xe4;\xee\xb9{|\xdd\ +\xe9[\r\x0f\x1c\xce\xf9\xb9s\x17j\xf5\x06I\xf9\xa8\xdc\x02e>|\xf6Uk\xb8\x07z\ +\xdc\xec\x11\xb6m\x17\x8b\x85V\xbb\x93\x19\x96\x96\x97W\x9e~\xe6\xd9\xf7}\ +\xcf{\x0fb\x03\xd0\xbd{kk{iy99\x8d\x06\xac\xbf\xe6\x93\x92\xef\x90\xc4\x8d+\ +\xca\xb7\x9dK\x10r\x8fUK\xb6\x1f\x94\x16\x0f\x92\x1a\xefn\x8a~\r\x00\x08\x01\ +1\x92\xe0\xe1\x03w%z!\x89\x94\x92[%G\xd4\x86\xd7R|4\xe4\x97\xbf\x18\xcf\xdfO\ +\xe7\xdeo\xce\xaf\xd5X\'\x84\x08v\x1e\xae\\\xfcuW\x87\x84\x844\x1eA\xaas\x91\ +\xf4\x12$\xcb\xb2b+\xb7T\xf9[wl\xfc\xd2 \xf6\xac\x89\x8f\x86\xfa\x0e\x88X?\ +\x8f\xb5sp\xf9\x8b\xe0U\xc0\xf6\x81G\xd0\xdf\x02i\xe82\xfd\x1a\x7f\xf8\xa7\ +\xec\x0f\xfe\x12]\xf8\xc8hy\xcd.!,_P\xcf\xd2VS\xd3gF\x1f\xf76\xe5\xe3?\xc3\ +\xae|\t\xc2yby\x88\x12X\x17:\xd7\xb1\xbdl}\xea\xffE\xb7:\xbeZM\xdf\x15\x1d?k\ +_\xdf\x1b\xdd\xa55\xf3\xce\xb9\xdd\x08\xefc\xcd?ux\xb2\xe7u&}\xf3\xd80\x87\n\ +wZ,|\xca\x1fgJ\xd5\xb0\xaek^\xbdw\xb3\xf4\xf1\xc9\xf6#\xae\xa8\xa529H\x13\ +\x01\x81\xb0Fp\xee\xff\xf4v\x1f\x93\x8b\x9f\x96s\x1f\x05\xaf\x92\xcc\xf6\xeb\ +\xb0\xfe\xb0\xbd\xfag\xf6\xc6\xc3D\xf6\x00\x92\xf9\x19A\xf7\xfa\x1f8\x9dW\ +\xe4;\xfe\x072\xfb~\x8dY\xa6~\x9a\xc9\xc6\xc4Di\xb7V3\xd4m\x02\x00\x82\x8bG\ +\xbf\xfd\x18c\xec\xdd\xf7\xbdk\xaf\xaa\xd3$\xbb\x10\xa2\xd7\xeb=\xf5\xf4\xb3\ +K\xd7\x973\xc8>\xbc\xf9&\x14U\x92\xfa\xe7\xf5\x14s\xc4\xd5\x1f\xa5\\.\xed\ +\xee\xd6{\xfd\x94)\x02\x11\x9fy\xf6y\xd7\xf5\xee{\xd7;\xf7I\xd0\xd4\xdb666\ +\x9f~\xe6\xb9\xd1M\xba\xc7\xae\xcc>\x14"\xfa\xbb\xa2\xbb\x01\x00\x08\xc0\xf7\ +\x8e\x11\x16Vo\'\x07\xb0\xd2\xa1\x8c\xe3\xfa%H\xf4X6\xb2\xdf\xcc\xa1\x04ws\ +\xe2\x86\x88\xb1;\xe5\xf4j{\x81\x08\x89k\xde\x13?\rw\xfcWt\xfeC\xa4t\x06,\ +\x0fYW\xb6\xae\xd3\x9d\x97\xfc\x95\xaf\xdbk\x7f9\xe8\xdb0\xc2\x98\x03\x98\ +\x9a`\xa6ck\xe7\xeef\xfe\xde\xad\xf6\xfdS\xed\x87G\x00=\xfd\xa7\x12\xd1\x87\ +\xee\xea\xf8R\x11\x02\xbd-\xfe\xc8\xffd\x7f\xf8W\xe8\xcc{\xf7)>\xb7+\xb1=\ +\x19\xc81{D\xa4\xca.b\xdc|\x0c\x90\x0c\xf8l\x85wV\x00t\\\xbbA\x84\xd1\xa9\ +\x8f6\xd5\xee!\xaaNT=\x98>\x91\xb17\xdf\xf4\xef\x9c\xec<6L\\\x97qlV\x01\x00\ +\x91\x17\xef\xa4\xe1\xac5.\xd2\x96~\x9d9Q\xb0,+\xf2\xe6W\xca?pj\xe7\xb7\xc7\ +\xa4?\x8cA\xc6\xe9\xfa\x83t\xf3Q\x08\xfe\x15\xe6\x8f\x83\x9d\x07\xd6\x82\xf6\ +2D;\x03\xb7\xa2\xcc\xfa\x00D\xb2\xfb\x8c\xf5\xc8O\x92w\xfe#z\xfb\x0f\x13\x9a\ +\r\xd1\xa3\xf3\xa0\n\x9e\x0b\x82\xa9\xea\xe4\xeaZv\x87\x8a8f\xdf~\xec\x89\ +\xddZ\xfd\xae\xb3w\xce\xcd\xcdf\x8a\xa3\x91\x9d1v\xe5\xea\xd5\x17^8\xb7\xb9\ +\xa5\xd4\xffQ\x1eFY\xba\xdfp@\x1bO\x10\x8d\x8ev\xbe\xe7U*\xe5\x95\xd5\xf5\ +\xcc#\x9c\xf3G\xbf\xfd\xedN\xa7\xfd\xae{\xdf\x99\xcf\x8f1\x15\xeaIL\x1c\xc7\ +\x17.\xbe\xfc\xdc\xf3/\xf6R\x8e7\xdf\xb9A\xebu\x12\xd6\xbc\xa6\x0e\xa4\xdc3\ +\xd8\x80\x13L\xb8\xe1\xe4\xc1R[R\xdc}\xc6\x8e\xaa\xe5P\x82;\x18\xeeh\x88\xd8\ +\xf6\xef\x08\xbb\x17\xc6`\x90\xc6\x8e\xfe\x0e<\xfb\x05\xf9\xc2\xaf\x80?\x05v\ +\x08\xbc\x03\xbdm\x1b\x19\x98K\xa5M\xa0\xd9\x17\xce\xac\xf4VD\x9c{\xcb\x13?\ +\x14\xb0\xd5||5\x95T\x863\xc1\x11\x85#\x0b\xa6\x04\x10\xa1\xbd,\x1e\xf9i\xf8\ +\xc0\x17\xe8\xf4}c\xdfN\x08\x89\xbd\x99\xc8\x99\r\xe2\x95\xf1\xa9\x99\x13\ +\x17L\xb8\x15\xcdTPg\xbc&\xae]V\xc6[\x1d\xf6\xd42L|\x1f\xd6\x89\x93\xdb\xc9\ +\xdf_\xe9>E\x90\x8fB\xe7\xd8/%\xad0>\xfe\x83\xce\xde\xdb\x89\xe8\xc15\x13\ +\xd3f\xbb\xf0\xa10\xba<\xddzp$\xe54\x18\x89\x08:+\xa4\x93T\x9a9\xde\x8cU\x0b\ +\xa2\x1a>\xfe\xcf\xb0\xb3B\xdf\xfbOL\\\xa6\xe3BGLV*\x9dN\xb7\xd1le^*\xa5\xb8\ +p\xe1\xe2\xa5K\x97\x8f\x1f[=\ +\xb8\xa0\x9dFR\xe6\xa8\x94Z4T\xd6\x92\xfa\x104h\x04w\x0f\x11G\'e\x92\x15\xc9\ +{5\xb8\xa8\xee\xadL\xb5\xed\xdc\xd9\x97\xab?\xd6\xb3\xe7R\x13h\x92\x01\x914\ +\x8e`\xc2\x97@\x16\x7f\xb1\xf1\xb2\xf8\xc6?\xc4d\r\x9b\xc9l\xaa\xdf\x9d\xf2\ +\xc7\xba\xce|\xd6~h\xe4rx\xa0\xdf\x95\xa8\xe4*\xd8\xc7\xf8j\xddk\xd4\xd9[\ +\xc6vo\xcb\xb2\x84Sn\x05g\x87\xa5\xd3\xa3lf\xc0H\xea<\x9e\xfe\xf0\xa8\xf5r\ +\xec\x8b\xf4(\xa2w(\x15\xee\xe4\xe5\xa9\xffz7w_\xda\xf002Hg*$95v8\xc7\xe2i\ +\xbc\xff\x0b0{\xff^y\xb0\x8dP\x8e\x96ey\xae{lq>\xcc\xe5\x86\xc9\xa6?\t\x0c\ +\xd2E\x16s\xc6\xd8(P\x02 \x00\x86anvf\xda\x98\xbb\x10\xcc\xde\xf6FI\xba\x13\ +\xe9?\xd2\xdfEo\xc7\x91\xcb\x05\xc7\x16\xe6]g,w<\x18\xf6vvw_~\xf9\xd23\xcf>\ +\xf7\xf43\xcf\xbe\xf4\xd2\xf9\x95\xd5\xb5\x11dG\x00\x98(O\x14\x0b\xf9t\xabx3\ +\ry\x07\x10\xdeYG\xd6\x85\xfd\xd9vBs\x95S\x07I\re\xcc\x9a\x03\xd7R\xb9\x8fa\ +\xf6\x96\xb2\xfa\x06K\xc6e\x85X\xcef\xe9S\xbb\xe1{\xd5\xb5\xe1\xaf\xa1\x18\ +\x0e\xbd\xee\xcc\xe9n\xe2\xc1}\xbd\xf2\xb9\xed\xdc{\x07\x8fd\x94\xd64Ga*nj\ +\xff\x01\r1\xed\xdc\xd9\x0b\xd3?\xb1\x1b\xbc+;<$O\x0e\x95\xeb\x94\x0e\x0b\ +\xd9\x9b\xd5\xf9\x85\x8f\x9a\xe4\xb8i\xcb\xa5\x94rwj\xb9\xf2\x80\xa0\xfe\xf0\ +YS#\xceHz\x82"\xf7\x8aQ\x04\x06\x08\x1a\x83\xc1\xfe\x06U\x9d\xbdQ\xe5}\xab\ +\xf4\xf1\xbe3\x95\x86\xdaq\x0b\xc4\x10\x857\xc9\x8f\xff\r\xcb\x88h\xbf\xff\ +\x8b\xf4\xc6UzON\xe1V/O\xfe\xe8Z\xe1\x93\x98i\xd2\x9ak\xd2\xa3\xfe\xe0\xed&y\ +\x95\xcdU<\xfd\xe1\xe8=\xbf \'\xee\xc9\xac\xc0\x1c\xcd\x83\xb9)\x87\xefy\'N,\ +NV&\xf4\x88\xad_\x9f\xfc\x8e\xed\x83C\xd0\x0cs\xa1\x02D\xc3\x8b\x12o\xd9]\ +\xfd\xb5]\xc4dTC6M=\xb4k\x8dG5\x800\xcc\x9d8q\xcc\xf7=\xd8O\xd2\x9f#\x9b8)\ +\x14\xc2\x99\xe9\xaam\xdb\x88\xa3W\x0f\x87\xa0\xe4\xac=\xf0\xf9\xd9\'\xb4\ +\xaf_Z\xb0\x92}\x86\xf7\x17\xd6\xb8\xa6\xc3\xdf2\xb1g\xa5\x1c>ZF\xab\xb1\xa6\ +Q\x8b\xbb\x13\x97\xab\x7f\x8f\xef\xf8\xd3\x9d\x87\xb2\xe8lB^\xca\r\x06\x00@R\ +o\xa5\xf2C\xeb\xc5O\xce\xd4\x137s\xd5\x86L\xd2F\xdbf\x13\x93\x9an\xca\xdacG\ +\xdd\xd0\xf7\x8f_\x9a\xfa\xfb\xd5\xf6\xc3\x0b\xcd\xafxlk\x08\x19Y"\xc8\xa0SF\ +\xb8~Y8\x8dw\xff\xa4}\xea\xaf\xa1\xed@\xb2_\x8f\x1e\xc9\xb4\xd9\xaa^x\xdfe\ +\x11\x9f\xde\xf9\xb7\xb6\xec$/J\x05\xc31\x12\x1f\x8eR\x03\xb5},^g\xb4l\xb3\ +\x0e\xf7\xd5\xe5\xf7R\xde#o\xae\xed\xbf\xcdo\xa7\xb7\xae7K\x9d\xe43\x9a\xfe\ +\x18\xcd\xcf\xef\xcf\xc9@2\xc2!\xa2\xae|s\xdb\x13\x0e\x95k\xd5\x1f\xa9\x07\ +\xf7,4\xbe\\\x8c.\x0e\xbfrfn4\x96aO\n.\xecR\xe3\xd8\xdf\x16\'\x7f0(L[\t\x7f\ +\x85F\x04|\x9d\x07\xcb\xb2\xcc\x06\xa0\xee\xf4=\xef\xd8\xe2|\xa1\x90\xdf\xd8\ +\xd8J\xdcE\x12vn|\x8f\x1e*\xf8\xd3S\xd5\x99\x99)\x8bR\xce3\x91\x84!I\xe7\xe6\ +\xe4\xb5X\xc4\x84:\xe7\xfb|\x14Hb6(\x8d\xc7\xac\x930\x17\x9c>y|s{g{{\x8f\x95\ +\x86\xd9\x1c\xa6\xfe\x9c\xaaNNOU)%I\x17;\x94\xb4\x0co\xaf\xa8-\x01\x10@\xec\ +\xc1\xb6\x13\xcb\t\xca\x07ZM-Y\x87w\xd6\x01\x08\x10\xe4bO\xb5\x9dX\xee\xe1\ +\x03w0\xd4g\xd5\xc9\xd5^\\\xb1[\xbe2\xf5\xa3m\xef\xe4|\xf3\xcf}\xbe\x010\xd6\ +\xb0\x99\x08"\x10\xd2\xf1\xcf\xacU\x1f\xa8\x05\xef \x12-\xbd\x12\x8a\xc0\x10\ +\ru"\xc9\x12S\xb3)\xeb\xd8\xbff\xc68)n\x94>\xdd\x08\xee\x99j?Tm\x7f\xcb\x17\ +\xc6No\xc3\x03b\x8c\x1f\xc3\x87\xb9[\xed\xcf~\x1aO\x7f\xce\x9d\xbc\x9d"\xd0\ +\x11L\xd1l\x00cL\x08\xb1[\xfc@lW\x16\xeb\xff\xa1\xdc\x7f1\xd5\xdc\xb3\xd0l\\\ +\xe1}\xe5f\x9b\xaaO\x14\xa0\xf6\x0bTw\x8fN\x02P\x8c\x1f\x0f\xc6}\x11\xc3\'\ +\x92\xef\x84\xef\xabt\x1e\xa72\xcabk\x1a\xdf\xf9\xcc\x87\x9c\x1b\x05\x93\xd1\ +\xa2gN\x1a\xd6\x15\xb0\x12B8\'\xf5\xf0\xbe\xb6w\xdbd\xe7\xdbS\x9d\x87\xf2\ +\xd1U\x0223\xf7\x1a\xd4\x0c\x18s)B\x00\x91\xd9\x13\xf5\xf2\x87\xda\xd3\x9f\ +\xa2\x95\xbbrN\x0e\x0c8\x1b\xc55\xf5-p\x18\xfbw\x90\x01\xc5*T&\xca\xf90\xac7\ +\x1a\xb5Z\xa3\xd3\xed\xde\xb08\xc5bqz\xaaZ*\x15\t\x80\x82\xc5\xd1\xc9\xd7\ra\ +:=!C\x00\xa26\x13\xde\xff\xa9\xfdE\x15\xcbL\x13\x11\xc7\xce\xfc\xf4G\xc9\x8c\ +v\x00\xe0y\xde\xc2\xfc\\1\x9f\xdf\xdc\xde\xe9t\xba\x07\xccR\xb1\x90\x9f\x9a\ +\xaa\x96KED\x14B\x8cz\x82\n)\x0e\x05\xc4\xa3d\\\xed\xc8\xb1\x87O\x8b\x92\xbd\ +\xf6Z\x1a\x15\xd6\xb8\x02 \x01\x00\x8d02\xa3\x92\xab\x9c<\x94\xe0\x9eAv\x05\ +\xee\x88\xc8\x006J\x9f\xd9\t\xef\x9fn}\xad\xda}\xdc\xe5\xbb\x96\x8c\tp\x02R\ +\xb5S\xa4\xb6\x04GR?rgw\xca\x9fh\x94\xee\x97\xd4\xb7\xa4$DF\xee|-w/\xc2\xc0i\ +\x84\x12B-\xcb\xb2\xa8eY6\xc6P\x1c\x86\nQ@\x06\x00\x8e\xe3\x98\xd3v\xad_s\ +\xcec\xbax\xdd}`\xb5\xf4\xd9J\xfb\xf1\xc9\xde\x13\x01[\xb3e\x97\xca\x98\x80$\ +\xc0\x07~,\x08\x928\x92\xba\x82\x06\xb13\xd3.\xff\x95\xde\xcc\'\xbd\xd2|.\ +\x08\x9d\x91xL\xa3EV\xfd\xa7\x9d;{\xde\xbb\xad\xdc}f\xa6\xfd\x97\xb9\xe8\xba\ +\x051EFS\xa1\x10\t\x02A\xea"u\xc1\xf2q\xea\xdd\xe0O\x1a\x03\n!\x840w\xaa\x9e\ +\x7f7\x08\x8e\t\x88PB\xa8E)\xb5l\xdb\xb6!\x86\xd2\x1d\xe4F\xb0\x9bQ\xde\xd5\ +\x08\xd4,\xbew\xa3\xf7\xbd~\xbc\x86d\x18W\x11\xd4\x00B)\xa5\xc4&\x88\x85\x93\ +P}\xd7\r\xd5v\xfd\x160\xb0\xd5Dv\x95\x01\xce\xb9\xa0\x13\x1b\xf6\xa76\x0b\ +\x1f-\xf6\xcfM\xb7\x1f\n\xa3\xab\x0e\xb6\t2*cBp\xb0"\x01\x88\x04\x0b\xa9#\ +\x88\x1f9\xd3\xf5\xfc{\x9b\xe5\x0fB8\xe7y\xbe{\xa3\xdd62\x03|\xa6\r\xa8q\xd7\ +u\x9d\xe9\xa9\xeaTu\xb2\xd3\xe96\x9a\xcdN\xa7\xc79\x17R\xeaq\x85R\xe28N!\x9f\ +\xafV+\x85|\x9e&[\t\xaa\xc7\x8d\xb7\r\x0c\xb37\xc4\xc40\x17\x94\x8aE `QjY\ +\x94Zv\xe0\xfb\x8e{\x8bA\x8dT\xd9=\xcf-\x16\x0b\x04\x80RbY\xb6\xfa\xb8\xc5Ba\ +\x9f\nq]7\xf3]\x18cD\xcaR\xa9X*\x15\xdb\xed\xce\xf6\xeen\xb7\xdb\xd7\xb3.3\ +\x11J\xc9\xc0\xb5t\xaa:1Q\xb6(U\xc3\'!$\xcc\xe5\x84\x90T\xb51\xdb\xb6,+\x9f\ +\xcf\x1fD\x15x\xc3E\x07\x1b@\t|\x0f\xb5\xfd\x86{-i\x11\xff\x7f{\xef\xfe\x1b\ +\xc9u\xdey?\xe7\xd4\xbd\x9a}#\xd9\x9c\x1b\xa9\xb9*\xf2\xcc(\xc9h\x94D\x91w\ +\xe1\xd7\xce\xeb\xbc\xf6\xc2\x86\x9c56\xbbX`\xb1\xc0\xfe\xb4\xc0b\xff\x9c @\ +\xb0X\xe0\x85a\xc0p\x04\x08+!\xc6+\xad\xbck\xbdr\xa2\x89\x12{4N\xc4\x19\xc7\ +\x99;\xc9\xb9\xb09$\xbb\xfaR\x97sy\xf6\x87\xd3],V_\xd8\x9c\x19r\xd8\x9c\xf3\ +\x81!\xf74\xabO\xd59]\xf5=O?\xe79\xcf\x13m\x88\xe8\t\xc0\x0eS\x85\xe1\x14\ +\xdd\xe2\xb1\xc9\x13\xf7\xf4NJ\x1d\xdf\xea\x01S\xb7\xa3z\xb6\x1fN\x7f\xffA\ +\xf5O\\\xb6\xea\'K\x1e{`\xca\x0e\x01Dj2\xa3\x12\xb9\'\x13wA:3\x86a\x98\xbd\ +\xdc\xd9\x9c\xf3f\xf5_l\x96\xfe0m\xca4M\xc7qT^@\xb5\x19\xbd\xff2\xd4\x05\xc0\ +v\xbf\x84a\x18*\x82BJC\xd0\xf2Z\xe5\xff\xae\x97\xff\x88\x8a\x8e#\xd6\xbd\xe4\ +\x81\xcbWM\xd9\x06\x90\x80 \xa9\x9bX\xb3\xa1\xb3\xc0\x9d\xa3\xe0TU\x1aBJ\x07\ +Gy\xf7\xfb\x82\xd2\x87GP\xbaY\xfc\x83\x8d\xa9\xdf7D\xcb\xe5\xab^\xf2\xc0\xe1\ +u\x03{[H\xa8\x8dVI\xfa\'h\xe5Uo\xfa\x94W\x9au\x1c\x87d\xa0\x94\x86\xa5\xdf\ +\xb9\xe3\xbc\xa6&\x0c\xd5\xa6\x99I\x8b855\xe5\xba\xae\xea\xe5\x98_\x8a\n#Q\ +\xcf\xf9\xf2\x91\xff\x94\x8b\xcfQ\'U\xdf\x9d\xe7y\x85B\xc1w\xfd\x11K\xa9\xfd\ +\xe7\xea\xdf\xe2\xa4N\x1d\xc7q7\x84F\x08)\x8d\xc0\xb8\xd4\xf0\x7f\x97"3\xf9\ +\xa6\xc7\x1ez\xec\xa1%6)\x08@\x90\xd4N\xcc\x99\xc8\x99O\x9c\xe3\xd2\x9eN\x17\ +\x03\xd3u\x143\x93M~\xe0e\xa4\x13|\xee\x1a\xd4\r\x90Z\xaf\xc5\xe2T\xb18\x05\ +\xdd]\x97\xa8\n\x15)#\xc0\xb2\xac\xf4\xd7\x98\xea\xbb\x1a\x7f\xc68b\xea\x0f\ +\xe9\xbat\x08\x1d\xb5\xc8l\x18\xc6\xdc\\mz\xbaJ\x08\xb1m\xdb\xf3<\x95:I\xe5\ +\xb3\x1cgT\xfb\xc7\x93RZ.\x95\xbe\xf2[\x1e"Z\x96\xa5\xbe)\xf5,\x0c\x9b\xf3\ +\xb2\x93n\xb6\x9d\xde7"\xd5hH)\x19\xe3Q\x14\xc5I\xa2f2B\x88eY\xbe\xef\xf9\ +\x9e\xa7*\xbe\x1a\xbd\xf2\x8a*\x85\xd4\xb1\xa3G\x8e\x1e\x993\x0c\xc3q\x1c\ +\x95$\xca\xf7\xfd]\xe5U~!lK6 \xb6\xfdP\xcf2v\xad%d\x99,&bxz\x8b\xc2\xcc\x19\ +\xd8\x93T\xe3\xfbB\xf6wq\xf6N\xea\t\xabDDf\x1co\xb8\xc7\x1b\x00\x90y\x0c\xd4\ +\x07\xdd^6\x02\x00\x90\xbd\xf2\x8f\xa9h*uK}\xc7\xfd\x16e\xd6TIU2\x8d\xd2K\ +\x92D=\xde[Na\xb3\x94`1\xf1N62-\xe4>\xa5V\x08\xbbU\x8d\x06\xd5S\xcd\xfa\x82\ +\xb0W-\xde0\x8c\xf4\xc9A\xb3\x12\xd9\xe5\xc8\x7f5\x1d\x10\x00H\xa7@\xdf\xf7\ +\x89]\xc8\xc9zjh#"\xa54\x15\xf7tS\x929<\xf0\xbc\x1f\x92YVU\x93\x90j6\xe7\x1f\ +\xc8NTN\xa6\xc6\xec\xae4H5\x92\xde\x0cYaU\xf7@z\x1bHi\n\xd3m\xb9G[\xf0Fn\xf0\ +\xd5\xa7\xec\x9e+)U\xf6\x1d/\x89\xf4\xaa9\xabk\xc8\x8dg\xf6\x06\xc8*\x9di\ +\x92\xfe\x83\xd3\xf5gedt\x7f\n\xf4m\x81\xf3=\xaf\x7fJ\xcb}\x89\xea\x9d\xec};\ +\xfexf\x9bM\x1f\x13\xd3\xec\xeaC\xeeY\x18\xf8)\xe8\xdd\xa2\xd9v\xb2_J:\xe1\ +\xa9q\xf3<7\xfb\xd9\xfe1Q\xefs\xce\xd5M.\xa5T\xedg\x1f\xc9\xdd\xce[\xfb\x0c\ +\x0b\xee)/\xa8\xaa\xc81\xf0\x98\xf1k-\xf1\xf6#\x994\x01\x80\x00\xb0\xe1\x0b\ +\xb3v\xa1fyU\x98\xc4\x05U\xe8\xbb\x93\xd2\xbb\xdc4\xcd\xecm\xa4\xa4\n\xb7\ +\xafI\xe6d\x0b\x00\xb2\x85\xe7\xb37\x9fR\x9f\xd4\x82\x1bv\r\xe9\x05\xa42\xad\ +<\x12\xe9\x84\x91u\xcb\xe6|\x08\xe9S\x94\x86\x7f\xe4j\xd5\xe7\xce\x98\xfeV\ +\x80\x8c\xa1\x94\xceg\xfd.\x02\xe8\x89{\x1a\xd1ad\xf6\x7f\xa6\xa7V\xe9X9\xe7\ +\xe9\xe5e\xbb?\x8e\xb7\x04\xb6kMV\xd9S\xa7Y\xae#\xd9\xf9l\xb4\x1bd\xd8\r\x90\ +\x1e\x9c\x15#%\xac\xb9\xc1O\xef\x04\x80m\xd3jv\x19#\xbd\x18k{y\xeb\x11\xfa\ +\x0e\x99\xf4\x90\xe9x\xe6n\x80\xec\xb7\x9f\xfd\xe2r\xeb\x13\x84\x10\xe5\x7fP\ +%\n\x84\x909?{\xb1\xcf\x19\x92\x1bIe\xe8\x00@6Y\xf1SL\x99\xb9\x1bCM\xfc\xb9g\ +aG}\x1f8\xdbe\xed\xa7\x9c?-7z\xe9\x98\xa8\t/+\xeei4\xcen\xbb\xb6\xffH\xd6\ +\xe6\x9d\xee\xbe\xe5\x11\x159\xfc\xe9\xd3\xa3\x03\x16\x14(\xf9V\xf8#\x0c\x9d\ +*\x80\x1a\xfeL\xd7\x87<\x91\xe2\xae\xc8\xca_\xaa\xda\xa9\xb8gWu\xb2bjf\xf3\ +\xd3\xf6\x9czY-H\x8dbs{\xdc\xee\x08}\xcf\xdd\xca*]e\xf6\xd7@\xbf\xecf\xaf\ +\xc7\xc8\xec\xddO\x7f1\x8c0\xdea\xbb\xb2g\x1c\x11\xf9\x05F\xb2\xdd\x94V~\x00\ +\xda\x0b\x96W\xef\xab\xc0\x0f\xd5\x02\xf4\xe6\xc2\xac\x83e\xfc\x07\x89l\xffa\ +N\x081MS\x8d\x00d\xb45\xed\x882\x96\xd3\'y\xb72\xa4&\x0f\xd8>\xb9\xe6f\xd6\ +\xdc\xe4\x9a\x1b\xfc\xac\x9d8p\xf0G_Rv\x8e\x19x\x03\xf4\x7f\xfb\xd9KUW\x9b\ +\x1a\x19\xea#\x94\xd2\xcdFC\x88\xec\x86\x1d \x84\x94J\x03<\xdd\xa9\xb2\x03\ +\x80a\x18J\xdcS}\x1cx\xd3\xee8\xaa\xb9\x1bCiqz3\x8c\xfeA@\xb6[<\xd9\x11\xce\ +\xcd\xb8\xfd\x8b%\xe9\x80\xa4\x93\xab\x9a\xf0\x84\x10jH\xd5\xe47\xda\xe4:P\ +\xb0\xe0nZHoXE\x0e\xcb\x9fVV\xf6\x8e\xf0\xe6\x12\x8a\x08v2\xdb\xbd\xf2B\x1aO\ +9\xa9\xe2\x9e{\xb6S\xa1L\x83grK\xf6\xa9\xa8\x99\xa6\xb9\xb6\xf6\xa4\x11\x04\ +\xae\xe3\xbe\xf6\xda\xab\x00\x90\x95\x80t\x85\'\xfb\xf0\xef\xf8k4k\x0c\xaa\ +\xe7!\r\x1bP-g\x7f\x9e\xc3\xf6\x1b:\xd5w\xb3\xb7\x8e\x97^j\xee\x8c9\xcb(}\ +\x08\xfbE\xa4_Gr\x06\x11\xc9\x98\xd84\xe3\xedI\xcf\x95\xed\xfe\xf8\x0fR\xd6\ +\x04S\x8d\xa4\x01\x8b\xb9#\xd3\x87y\xe0L6&\xd9\xc95m07\xf8\xfd\xe2\x9e\xf6.{\ +\r\xd9/:\xfd\xae\xc7\xec2f\xaa?g\xe5,\xfb\xd5\xe7\xc66\xab\xefF\xcf7\x98Z\ +\xee\xbd]\xfb[\xa6\x9e\xeb:\xae\xe3\xe6\x86(\xf7%*9\x86\xde\x1d2\xfa\xbe\x1d\ +\xdd\x97\xec\x8d\x91\xfd17\xd0g8\xf0KI\r\xfc\xd4J\xc8*{\xeeq\xc8}\x17\xd9\ +\xdf\x07\x88\xa8\xc4=\xfd\x06\xd39`W?\xf5\xf6\x1f\x99\x04\xdd\x95O\x00\xc6q\ +\xb0\xd9>~\xad%\x1e\xf1\xf6\n\x00\x90\x91\x1e\x1ej\xba^e+\x9d\xe4\xa4\x8a;\ +\xf4\x19\xce\xeb\xeb\x1b\x96e\xfa\xbe\x9f\x0b\x7f\x86\x8c5\xaa\xfe\x1b4[W\ +\xbf\xf8\xd5\x89\xe3\xc7_\x7f\xfd\x02\x00\x18\x86\x81\x99\xca\xcbi\xe3Y\xfbn\ +\xc4\r\x9d\xbei\xf4*=\xa9{4;a`\x86\xac\xa1\x97U\x99\xf4\xf5\x08e\xe9\x973u\ +\xdf\x8fp\xfed\x85\xcf\xcc8\xd0\xb3\x97af\x16\xc1\x06v?mj\x9c/%m_\xd9\x929a\ +\xcd\xb5\xfft\xde\x83\xfe1\xc9\xcd\xafr;\x03\x07\x9f\xf4<3\xd9\xaf8;8\xe3_\ +\x80\xea\xe0?\xdf\xbcu\xe2\xc4q\xdf\xf3\xb2\xdf~\xf6\xab\x87\xed_J\xdaq\xe5|\ +\x00\x00D\\[{\xd2\xe9f\xcb\xda\xba\x86\xa3G\x8e\xa4\x1e\xeal\xaf\xd3\x99^u9\ +\x15\xf7\xec\x17\xb7\xdb\xc1\xcc\x1aLYq\x1f\xff\xcb\xea\xbfKS\x81NM\x10\x99\ +\x8f\x93\xd9\xf6 \xa4W\xae~4\xa8\'\x143\xfe\xd5\xdd\xce[\xfbO\xd2\xb8\xab"\ +\xa3\xfa3\xf1\xa68\xc5\xa3c\xd7Z\xba\x83\xb2\x1bC\xc5F,\xccN\x9f&tK\xd2\'X\ +\xdcS\xc9@\xc4\x1b\xbf\xfe\xa7\xff\xff\xd3\xbfv\x1c\xe7;\xff\xea[33\xd3\x98Y\ +h\xcd\x1e\t\xdd;I=\xe1\xa0\x8c\xa6\xf4\xd6\xc9i\x10\xd9\xce\xe8\x8bIoh\xf5_u\ +Sf\xe7\x8c\xec4\x03\xdb\x1f\xf2\xf4\xbf#d=w\xa2\xec]\x9e\x13\x11\xd8\xee\x00\ +\xc9\x9e"7E\xa5\xef\xf7\xf7}\xb7\xdd\xef\x1f\x87\xb4e\xd8>\xfe\xc3\xda\x7f\ +\x96\x07\x95d\xe6We{fG\xbe\x7fv\xc9\r~\xfa\x02v)\xeb\xd9\x1b\xec\xfa\xf5_\ +\x7f\xfa\xd7\x7f}\xfc\xd8\xb1?\xfa\xc6\xff\xa5\xa2\xf4p;\xc3:\x0e\x00\xa9u\ +\x1f\x04\xcd\xbb\xf7\x96rIT\x08\xa1\x0b\x0b\xf3\x96e\xf5_[z\xe5\xfd\xb3\xd7S\ +\x0fl\xf6\x86\xe9\x9f\x93\xc6o0w\xa3\xa6_D\xce\x8a\x82\xbe\t/w\nu\x93?\xaf\ +\xde\xed\x0f"Z\x97q7\t\xf9\x08\xe7\xb8W99Nk2i\x88\xb0\x0e\x00D%m\x1f\xe2\xe1\ +1\xbd\x8a35\xb7\xed\x9d]\\\xf2A"\xf7\xd8,/\xaf\x00@\x1c\xc7\x0f\x1e>\xfa\xf8_~\xf5\ +\xed\xe3\xc7\x8f\xa5\x87\r;\xbb\xfag*ya\x18.\xde\xf8u\xbb\xd3\xd9\xfe\x0b\ +\x9eT*\xa5\xda\xec\xcc@e\xcf\xbeHO\xf1,\x03;\xac\xcd\xfe?\x8d\xdf\xda\x8e7\ +\xea\xb0g!k\xa3<\x97\xde\xed\x1b,\xb8\xab^\x8c0\xdb\xbd\xf2\xfcx\xb5\x96\x90\ +\xf5~\x04\xe0\x0e\x1e\x9e\xfc\xc2\xec\xa4\x8a;\x00dm\x81\xdf~\xfdb\xbd\xbeV*\ +\x15/\x9c\xff\n\xdd\xbe\xe0\x83\xbdm\x84\x99\xd8\xb8\xbc\xd5\x00\xcf\xf5F\ +\x19\xf1\x84\x8c8\xf8\xa9O\x94>\x06\xbb=\xcb\xd3i\xf7\xf8\x17\xb6G\x8d\x8fy\ +\xf6=\x1d\xfc\xf47\x81\x94\xb2\xd9l}\xfa\xf3\xbf\t\xc3Py\xc9\xeb\xf5\xb5\x8f\ +>\xfe\xe9\xef\xfe\xceo_8\x7f\xde\xf3\xdc\x11\xa7H\x1b\x11B<~\xbcz\xedW\xffP\ +\xaf\xe7*\x9b\xa3a\x98\xe7\xce\x9e\xf5}\x7f\x98\x95\xba\x17_\xe2sos\xcco$w\ +\xba\x89\xd0\xf1~DgU\x05,*-\x1e|\x10!N\xf1\xd8x\xad\xd5e\xbc\t\x00\x84\xc0\ +\x88d\x03N\xf1h\x7f:\xc9\x89\x14\xf7\xd4bJ\x17g\xaa\xd5\xca\x9f\xfe\x9b\x7f\ +\xad\xba}\xf7\xee\xed[\xb7;\ +a\xd4\x97f\x80\x1c=:w\xf2\x95\x85\x81\xfe\x8a\t\xe5\x10ta\x14(\x934\xb5\xef\ +\xa8P\xf4\xd9\xb1\xccv\x14\xe9\x8f\x00\xc4\xa1S\x051,\xbfz\xaa\xff\xfd\x89\ +\x14wEj:\xa5\x8b3\xc3\xee~\xf5 \xa9x\xf6\xf4x\xec\xbd\x7f\xc8\xef6\xcds%\xab\ +\xec\x8c\xb1_\xff\xd3?-\xaf\xacd\x1d\x08)\x8f\x1e?~\xf4\xf8\xf1?~\xb9xd\xaev\ +\xfc\xf8\xb1j\xb5\xa2b<\xd4\xad\x18E\xf1\x93\'OVV\x1e55U\xb8x\xe1+\xb3\xb33\xd9\x1d=\xfb\xd17\xcd3\xc0[+\xc8#\xe8\xe6k\xdc\ +\x9d\x0b\xa5\x1f\xd6\xbc\x87\xd9\xa4\xedC\xc3\x1f\xcf\x0c\xcbK3\xa9\xe2\x9e[\ +a\xdf\n\x1c\xeb\x85\xd0\xae\xae\xd6?\xfe\xf8\x7f\xc5IR,N]\xbcp\xde\xf3\xf4\xb0\xe0>\ +J\x0e\x04\xa4\xc4\x11u\xefF$~IA\x11\xf3\xe6\xb2z-qx\xf8\xa3\xe5\xb9\xe5q|\ +\xf7\x99\x0b\xd8\xd5\xd1\x07\x87\xac\xb2g\xa3\x17\x00@9^\x94d\xa7?\x93\xd3\ +\xc0\xe4\xac\xb8\x13B\xd2\x0cPiTrj\xdako\x8cF\xa3\x19\x00JU\xd4\x14\x00\x18\ +\x1fa\xb6\x9f\x1ak\xd7R\xe3."\xef\xb564\xfc\xb10<\xfb\xe30&R\xdc\x95\xfb%U\ +\xf6\xac[\x06zR\xdeo\xbc\xa7\x06x\x1a\x9f\x00\x99\x99 -\xe2A2\xbbK\xf4.\x12\ +\x8dF\x93\x83wVQ$\xcal\x97r\xb0\xd9n\x17j\x967\xa0\x02W\x0e\x994y\xe7\xb1z="\ +\xfc\xd1\xf2\xa7\xed\xa9]\'\x1e\x9fHq\x87\x9e\x04C\xa6\x82h\xaa\xc2\xca\xe7N\ +3E\xd3\xd3\x8f\xa4.\x97tA5\x15\xf7t\xbf\t\xf4"\x1f\xd2\xc3\xb4\xbek4\x9a.(\ +\xd2 \x99\x91\xf9\x1a\xc7\xaa\xb5\x944n\xa79m\x87\xa7\x91\x19\xb7\xb5\x1c\ +\x93*\xee\xd0\xd3\xf7\xdc\xde?\x85\xb2\xc4\xb3\x11\x0b\xb9\xc8\x84\xac^\x0f\ +\x14\xf7\\t\x9aF\xa3\xd1\x00\x00k=P\xb1\xedB\xa0\x1c\x96\xafq\xbcZK"\\S\xc5\ +\xaf\x01\x80\x8f\xd8\x03U:f:\xc5\xa7\xb8\xd4I\x15we\xb0\x0f\x13\xdf\xac\x15\ +\x9f}3\xf7b\xd8\xc1::M\xa3\xd1\xf4\xb3U\x91cd\xb9jo\x9cZK(\x93t\xd7\x12\x02\ +\x13\x83\x8f"\x86\xedUO>\xcd\xb5N\xae\xb8\xc3N\xb2\xbb+Q\xd6\n\xae\xd1hv\x84\ +\xb7V\x94\xb7\x9d\x8b\xa1a\xae\xdex\xb5\x96x\xeb\x01\xf2N\xf7\xf5\xf0\xf0G\ +\xbf\xfa\n5vnm \x93Z\xacC\xa3\xd1h\xf6\x13\x14qj\xb6\xf3!f;5]w\xacZK\xc8z5\ +\xf9F\x84?\x1av\xc1)\x1d\x7f\xba\xab\x05-\xee\x1a\x8dF3\x0e\xacy\x1f\xa5\x00\ +\x022\x9fQb\x0bo\xbcd\x03"|\x82\xa2[\x8bQ\xad\xca\x0e\xa40sv\x9c=P\xc3\xd0\ +\xe2\xae\xd1h4; y\'\x8dYT\xb1\xed\xfd\x18\xce\x94[<\xbas[(\xd3\x1caB\x0e]\ +\x95\xb5\n\xb3\x96?\xfdtW\xab\xd0\xe2\xae\xd1h4;\xc0\x82{\xaa\x90\x9e\x10Cc\ +\xdb\xc7\xdc\xb5\xc4[\x0fd\xeam\xe7C\x0e"\xb40\xb2\xf8\xf58hq\xd7h4\x9aQ\xc8\ +$\xe8fZ\x1f^\x91\xc3\xf2\xa7\xc7J6 \x19k\xdeS\xafU\xf8\xe3@\xbc\xf2\xfc8\xc1\ +\x94\xa3\xd1\xe2\xae\xd1h4\xa3`\xc1\xfdn!=\x89"_\x8c\xb9\x8b?N\xf8#\x00\x0b\ +\xee\xa2\xe4\xa0j8\x0f\t\x7f\xa4\xa6\xe3U\xc7\xaa\xdc4\x1a-\xee\x1a\x8dF3\ +\x14\x11m\x88h\x1d\x94\x1c\xf3\xc1\x0e\x19\xa7xd\x9c4\xeb\x92\xb5y\xfb\x91z=\ +\xcal\xaf\x8eUEoG\xb4\xb8k4\x1a\xcdP\xba^\x14\xd2\xad\xa1\xd1\x0f\xa1\xc6X\ +\xbb\x96\x00X\xe3\x0e\xa0\xaa\xa9;\xaa\x8a\xdeX\xab\xb2c\xa0\xc5]\xa3\xd1h\ +\x06#\xc2\xba\x8c\x83\xb4\xfe\xf5\x10\xb3\xfd\x98ay;7\x15m\x88\xe8I\xf7\xb5\ +\x1c\x12LIHa\xe6\xec\x98U\xf4vD\x8b\xbbF\xa3\xd1\x0c\x04\xd3\xfa\xd7\xc3\xbc\ +(\xc4\xb0\xc7\xf3\x8f#\x0b\xb6\x92\r\x0c\xf3\xb6\xdb\x85\x9a\xe9\x96\x9f\xe6\ +J\x07\xa1\xc5]\xa3\xd1h\x06\xc0\xdb\x8f$k\xab\xfa\xd7\xc3\xccv\xaf2?Nz\x00\ +\xde~$\x93f\xf7\xf5P\xf7\x8eY\x989\xfb,\x17\x9cC\x8b\xbbF\xa3\xd1\xe4A\xc9X\ +\xb3k\xb63\x0e\x03\xbd(\x86]pK;\'\x1b@\x91\xb0\xe0\xaez="\xd9\x80W=IM\xe7)/w\ +\x10Z\xdc5\x1a\x8d&\x0f\x0b\xee"\x8f\xd5:\xea\xe0Bz\x84L\xd5^\x1b\xa7:R\xd2\ +\xb8\x85"\xe96;$\xd9\x80\xe5U\xbc\xca\xc23]q\x1fZ\xdc5\x1a\x8df\x1b\x92wx\ +\xfb1@w\xd7\xd2@9\xb6\xfd\xd9\xb1\xc2\x1f\xe3\x86\xe8\xac\x02\x00\x01\xe0bH\ +\x90\x0c!\xfesu\xc8(\xb4\xb8k4\x1a\xcd6XpO\xc5,\xf2a\xb9_\xc6\xad\x8e\x84i\ +\xd2v\tC\xe3m\xdc\xe2S\x96\xe3\x18\x8d\x16w\x8dF\xa3\xd9b+\xd9\x00\x0cM\xed\ +\xeb\x96\x8e\x8fUk\xa9S\x97I\x03\x94\xd9\xcea\xd8:\xea\x98a\xf2\xbbE\x8b\xbb\ +F\xa3\xd1l\xc1\x82{j\xfdt\xe8&RB\xdcq\xd2\xac\xa3Hz\xe1\x8frx\x98\xbcW=9Nq\ +\x8f\xa7@\x8b\xbbF\xa3\xd1t\x11\xf1\xa6\x886\x00\x00\x87{Q,\xaf:\x8e\xd9\xce\ +Z+\xc8{I\xdb\xc5\x90,\xc1\xb6?^q\x8f\xa7A\x8b\xbbF\xa3\xd1tI3\xad\x8f0\xdb\ +\xc7\xf1\xb6\xa3\x88ys\t\x00\x08\x80\x9408\xde\x06\xc0\x9f~\xa6r\x1c\xa3\xd1\ +\xe2\xae\xd1h4\x00\x00\xbc\xb3\xaa\xb6\x1a\xa9]K\x03\x8fq\xa6\x8e\x8c\xb3\ +\xf8\xc9\x82{\xdd\xec\x8f\x00lX\xbcMa\xd6.\xcc<\xcb\x05\x8fF\x8b\xbbF\xa3\ +\xd1\x00\x00*[\x1b\x00\xb8\x80\x81\x15\xab\xc7\xcc\x11&Y\x8bw\x1e\x81ZG\x95\ +\xf0l\xf16O\xcfsH,\xa9\xd1h4\x93N7\xd9\x00\x80\x1c\x9el\xc0)\x1d7,wT#\\p.dp\ +\x97\xa0\x04 8"\xde\xa6|\xc2\xb0\x0b\xcf\xe1\xba\x87\xa3\xc5]\xa3\xd1\xbc\ +\xf4\xa0H\x93\rp\x01\x08\x83\xccv\xc3\xf6+Cs\x84\t\xce\xe3(\x899!l\xcdN\x9e \ +\x10\x02\xc0\x04\xc8A\xbf\x00\x80\x90q\xf2\x16<#\xda-\xa3\xd1h^vXk\x05y\x0c\ +\x00\x12\x87$\x1b\x00\xf0*\x0b\xc4\xb0\x06~\\\n\xb9Y\xafGq\xe8{\xe8\xc3c@IF\ +\x86?\xda\x85\xda\xe8_\x00\xcf\x05-\xee\x1a\x8d\xe6\xa5\x06%\xe7\xad\x15\xf5\ +\x9a\xf1\xc11\x8b\xd4rG\xc4\xb6wZ\xad\xf5\xfa\xaa\x8c\xb8\xc16x\x14\x00\xa1\ +\xa0\xc2\x1f\x87\x14\xf7\xf0\x9f\xb9\xf8\xf58h\xb7\x8cF\xa3y\xa9a\xcd%\x14\ +\x0c\x00\x84D!\x07\xdb\xda\x85\xe9\xb3#r\x84!`\xb9:\x8b<\x8a7\x97\x08\xa1\ +\x04@\x0c\x0f\x7ft\xcb\x0b\xfb`\xb6\x83\xb6\xdc5\x1a\xcd\xcb\x0c\x8a\x98\xb7\ +\x1fB/fq\xe01\xa6[\xb2\xa7j#\x1a1\r\xd3-\xcd8f\x8b`\xac\xd6Q\x87\x85?R\xcb}\ +\xee\xd9\x1f\x87^\xd5\xfe\x9cF\xa3\xd1h\x0e ,\xb8\x07\x92wK\xa4\x0e\xa9k::f1\ +l\xb5\xe3\x04\x817l\\\x070\x08\x00\x178\xacD\xea\xe8_\x00\xcf\x17-\xee\x1a\ +\x8d\xe6%E\xf2\x0e\xef\xac\x82*}7$f\xd1.\xd4,\xaf:\xac\x858\x8a;\x9d\x18\x81\ +:r\x8d C0$\x02\x1bR\x8e\xc3\xf2\xaa\xa3\x7f\x01<_\xb4\xb8k4\x9a\x97\x14\xd6\ +\xb8\x0b(\x81\x80\xe08,f\xd1\xab\x9e\x1c\xfca\x84v\xab\xcd\x12&\xc1\xb0ih$u\ +\x04J\x080\x8eBH\xa2\xd6e\t\xd9\xca.@\x88?\xb3\x1f\xeb\xa8)Z\xdc5\x1a\xcd\ +\xcb\x88L\x02\x11=\x81n\xc5\xea!\xc9\x06\x8a\xc7Lgj\xc0\x1f\x10\xda\xadv\x14\ +\xc6\xc4\xb0\x0c*\xccd\x85 "\xa1j\x03\x94\xe5\x95-\xafBA\xb2\xb8\xc9\xa2@\ +\xe9\xbcS<\xba\x17I\xdbG\xa0\xc5]\xa3\xd1\xbc\x8c$\xc1]\x95d\x80\x0f1\xdb\t5\ +\xfd!f{\xb3\x11\xc41\xa3\xa6%\x05\xb7I\x83\x88\x06\x12\x83\x00\xb4#\xe9\x94^\ +)\x1d9\x0b@\x00c\x0fxg\xed~\xd8xDL\xdb\xaf\xeem\xb2\x81~t\xb4\x8cF\xa3y\xe9\ +\x10\xd1\x86\x8c6\x81\x8c2\xdb\xdd\xf2\xfc\xc0\x8a\xd5a\xbb\x13F\xcc0-!\xb8e\ +Q\x8b=\x02B\x08@\xc2\x91\t\x07\xd0\xdf\x9a)\x088~\x15\xd0\xf2\xab\xaf\xecQ\ +\xd2\xf6\x11h\xcb]\xa3\xd1\xbcl \x0b\xee\xaaW\x9c\xe3\xe0\x1ca\xa6\xe3U\xe6\ +\xfb?\xd9\x0e\x9aQ\x94\x98\xa6\xc19\xb7\x1d\xcfL\xee\x81\x0c\tP\x00h\xc7H\ +\xa9\xddn\x85^\xc2\x12\x01q\xc8\x00\x19\x01#\xa633\xa5\x01M\xed5\xdar\xd7h4/\ +\x17\xbcS\x97I\x13\x08H9\xd4l\xf7+\xaf\x10\x9a\xb7}[\x8df\x181BM)\xd1\xb2l\ +\x13\x03\xc2\xd6\x10\x08\x10\x888\xc4LJ\xe4\xa6c\xb5;a\x1cE\x12%\x97T\x80\ +\xe3\xcd\x9c\x88\xc2h\xef\xbb\x95G[\xee\x1a\x8d\xe6\xe5"M6\xc0\x05\x0e\xcc\ +\x11f\xd8\x05\xa7t,\xf7fs\xa3\x113i\x18\x94si\xdb\x14y\xcc\xc2\x15\x872\x00\ +\x8a\x08\xedP\x98\xa6e\xf93q"\xa2\x8du@\x04@\x02\x84PJ\x08mq6\x7f\xe64!\x03#\ +$\xf7\n-\xee\x1a\x8d\xe6%B&M\xc9Z\xb0C\x81\xa4\xd3\xb9\x02I\xc1F#N\xa4eR\t\ +\xc4\xb2@\xb2$\x0e7\x8a\xb4\t@\x81@\'\x92\x12\x8c\xf2\xec\xaba\x9b\xb7[\x1b\ +\x94\x1a@\x00\x94G\x1f\xa0[\x915a\x96\xb3\xafnw-\xee\x1a\x8d\xe6%\x825\x97\ +\x10\x91\x000>\xd8l7\xdd\xb2]\x98M\xff\x89R\x06\x9b\x01\x13\xc4\xa0\xc8$\xd8\ +&P\x14\x89\xe4\x164\x08\x05\x00\xc2\x85\x88\xb9Q\x9a9\x9b0\x82\x86e{\x9e\x14\ +R}\xb4\xd7\x04\x18\xa6aX\xfb-\xb6Z\xdc5\x1a\xcd\xcb\x02\x0f\xeb<\\#\x00|X\ +\x8e0j\x14f_\xdd:\x9e\xb1v\xb3\xc38\x02H\xa4\x86c\x12\x1e\x85\x1c\xc0\xb2\ +\x11\x92\x0e\x01@\x94\x9c\x94\xfc\xca\xd1(\x01!\x85\xe3\xfa\xaec\xb6:m!$H\ +\xd9m\x92\xd2\x99Z\x8d\xd2\xfd^\xe0\xd4\xe2\xae\xd1h^\x0eP\xb0\xc6]\x00\x18U\ + \xa9t<\xdd\xb5\x94Dq\xb3\xd1"\x86E\x08P\xc3\xb6\x0c\x19wZ\x86\xe5\x94\xa6+\ +\xebK\xbf,\x98\x08\x88`\xcdPz\xa4\x13K!\x98\xe3\x97l\xdb\x8c\xdb\x9b \x18\ +\xa1\xc4v=\x02`\xdb\xceT\xa9h\xdb\xfb\x1d\x07\tZ\xdc5\x1a\xcdK\x02k?\x92<$\ +\x00L\x0c\xd9\xb5d:i\xad\xa5\xa8\x13\x86a\x8c\x84\xa0\xe4\xd4\xb4M\xc2\xe3v\ +\xc7t\xddR\xb5\x1a\xb6\xd6\xa9\xe8\x10\x13\xd0=\x96\xc8J\x94\xa0\x14\xcc/V)\ +\xf0\xa4\x1dl>yD1\xa8\xce\xccU\x8e\x9c"\x94\xee\xf3"j\x16\x1d\n\xa9\xd1h\x0e\ +?(9k.\x03\x00\x02\x88\xa1\xe1\x8f\xddZKQ\'l\xb5"\x94\x80\x08\xd4\xb0lC\x84\ +\xed\x96\xe9\xb8\xe5\xe9i\x00X\x7f\xf4\xcf\x96\x89\xd2\x99O`\xb6\x13\x0b!\ +\xb8_\x9c\x06\x99\x88\xa8\xb3^\xbfo@\xb3\xe0\x19\xe5\xb9\xd3\xd40^\xa0\xb2\ +\x83\xb6\xdc5\x1a\xcd\xcb\x00o-\xa3\x88\x95\xb7}\xa0\xd9nX\xaeS:\x0e\x00a;l\ +\xb7BjP!\xa4i\x9a&\xe1\x9df\xdb\xf5\xfd\xd2\xf44\x00l\xae-\x9b\x18R\xef\x95\ +\x04*\xedNH\r\xcb\xf3\xa6PD\x98\x84O\x9e\xac\x984,8X\x9c\x997,\x7f\xdf\xbb\ +\x98G\x8b\xbbF\xa39\xe4\xa0d\xac\xf5\x00Fz\xdb\xbd\xe93\x84\xd0v\xb3\x1dE\ +\x8cR\x82HL\xd3\xb4M\xe8\xb4:n\xa1P\xaaV\x01@\xf0$X\xbb[,\x1d\x13\xc6L\xd8j\ +\x98N\xd12M\xc0\x84G\xed`\xf3\x81I\xc2\xa2\x07\xa6\xedy\xc3\xebh\xef\'Z\xdc5\ +\x1a\xcd!\x87\x05\xf7Qr\x00\x10C\xbc\xed\x96[r\xa6\xe6Z\x8dV\x14s\x02B\x12\ +\x93\x12\xb0\x0cl\x05\x81_,\x16+\x15u\xd8\xfa\xe3\xbb~\xf1\x88\xe1\xcct:M\ +\xd3\xab\x82\xe4\x06\xc1vc\xbd\xdd\\5HX\xf6)\x00\xf8\xd5\xd3\xfd[[_\x08\x07\ +\xe2"4\x1a\x8df\x8f\x90\x02\ +\xeds\xd7h4\x93\x8d\x88\x9e\x88h\x1d\x00\x101M6\x90pHT-l\x02\x94\x9a\x95\xb9\ +3\x00 8\x0f\x9b-&\x80\t4\r\x03@\x12\xc9,\x8bLUg\x81\x90h\xfd7\xb6I\xd4_\x0b\ +\x8e\x9a,\xb6A\x0c\xdb\x9f>\xbd\xaf}{\x06\xb4\xb8k4\x9a\x89\x06\x93\xcd[\xea\ +\x95\xda\xb5\x84\x00Q\x02"\r\x97A\xa8\x1c9k\xda\xaeH\x92v\xab\x13s\x90B8\xb6\ +)\x04c\x9dV\xb5V\xb5\x0be\x00H6o\x99\x10\x02@\'F\xd7\x1a\x1c$3U\xfb\xad\x83\ +\x96\xb4}\x04Z\xdc5\x1a\xcdD\xc2\x19\x8f\x19B\xbcJX\x9b\x10\x83\x0b\x94\x12%\ +B\xc4@f\x02!-\xc7/V\x8fK\xa5\xec\x0c\xa5\x94\x96e\x08\xc1\x08\xebL\x1f\x99\ +\xb1\xbc"\x00H\xde\x11\xed\x87\x00 $\x18\x04\xe8 i\xb7\xbc\xaa]\x98\x1d\xf0\ +\x87\x83\x8a\x16w\x8dF3a b\xb0\xd9\xe0`ZT\xd2\xce\x12\x10\n\x00\xa2\xab\xec(\ +e\x9a*\x8c\xa0\x14\xb3\xc7\xcf\x8b8j\xb7\xa3\x98\xa1\x90\xc26\r\x94\x02X\xa7\ +R\x9b\xa5v\xb7\xfe5\x0f\xee!JBT\x0c\xe5\xa0=K\x07\xac\xf8\xf58\xe8\x05U\x8dF\ +3al\xae=\xd9\xac\xaf9&\xf5\xc8:\x91!\x01"\x042\x0ea\x92Uv@)\xa6\xcaG\x08\x90\ +\xa0\x19\xc6\x1c\x84\x94\x8ee"J"\xc2J\xad\x96*\xbb\x887\xd3"\xda\x88\x83\xd7\ +Q\xdd\xd2q\xd3)\xeeS\xf7\x9e\x13Z\xdc5\x1a\xcd\x84\xd1i\xb7\x81K\x8c[\xbc\ +\xfd\x08\x80"@\xccPmS\xca(;\x1a\xa6\xe5\x17\xe7\xda\x11p\x01(\xa5cQ)\xb9\x88\ +\x9a\x95\xd9Y\xc3\xf6z\x8d!k\xdc\x01\x00B@\xe2\xc0,\x92\x07=\xfb\xe30\xb4\ +\xb8k4\x9a\t\xc3/\x95\xc04\x93\xe6}\x14\x11\xa1$f\xd8Ir\xca.M\xd3\xa8\xce\ +\x9dK\x84\xc3\x18\x07\x00\xdb\xa2\x823L\xc2\xea\xdc\x1c\xb5\xdc\xb4)\xdeY\ +\x95I\x13\x00\x10\x81\xf1A\x0e\x19\x00\xbfz\xf2 g\x7f\x1c\x86\xf6\xb9k4\x9a\ +\t\xa3\\.\xf1\xce\xa6-\xdb\x00THhG\x98u\xa7\xa0\x94\x96\xe5\x94f\xcf&\xd2\ +\xe7\\PJL\x83\xf0$F\x11\xcf\x1c\xd9\xa6\xec(9\x0b\xee\x01 !\x84\t\x14r@\x90\ +\x8ca\x17\x9c\xd2\xf1}\xea\xd8sE\x8b\xbbF\xa3\x990\xa8a\x14\xbdX\x84\x00\x04\ +\xc2H\n\x89Ye\xb7\x1d\xbf<{\xb6\xc3,\x004\x0cJ\x08J\x96\xa0d3G\x8f\xe4\x02\ +\x19yk\x19y\x08*\x15\xf0\x10\xb3\xbd0s\xf6\x80g\x7f\x1c\x86\x16w\x8dF3a\xc8\ +\xa4)\xc2:\x01\xc29F\xc96ew\xbdbq\xfaL\xc4\x0c)\xa4e\x99\x94"\x8f"\xd3\xc0Rm\ +\x8e\x9a\xdb\\+(b\xd6ZQ\xaf\xb9\xd8\x9eE\xb2\x87U\x98=\xf8\xd9\x1f\x87\xa1\ +\xc5]\xa3\xd1L\x18I\xe3.\xa0\x04\x02\x9d\x18\xa5\x94\x00@\x08E\x94\xae_\xf6\ +\xcb\';\x89!\xa54\r\n x\x18\x19&\x94ks\x84\xe6\xb5.i\xdc\x01\xc9\x01\x00\x11\ +\x06\x9b\xed\x84\x16&g?j?Z\xdc5\x1a\xcd$!\xa2\r\x11\xad\x03\x81\x84c\xc2\xc1\ +v\xa7\x00\x80\xb3\xd0\xf7g\xbc\xd2+\x9d\x98 \n\xdb\xb6\x00%\x8f:\x8ek\x17\ +\xa7g\t\xcd\xfbUd\xd2\x14\xe1\xaaz\xcd\x04\x0c(\xa2\r\xe0\x95\xe7\r\xbb\xb0\ +\xe7\xfd\xd93\xb4\xb8k4\x9aI\x82\xb7\x1f\x01\x00 rt\xe7N~\xc5\xf1K\x92\x85I\ +\xd8N\x18\xed\xc4\x84\x80\xb4\x1d\x0b\xa5\xe0a\xc7\x9br\x0b\x95\x192(p=i\xdc\ +V)\x1f\xa5\x844\x1dM\x16b:^ea\xaf\xfb\xb2\xa7L\xe4B\x81F\xa3y9A\x1e\xf1h\x03\ +\x080A\x98\xa8\x18v\x89\x10\x8a`p\xe9\xc6\xdc\x00\x90\x06E\x94\x82\x85-\xbf\ +\xe8OU\x07+\xbb\x08\xd7d\xdcP\xc6:\x13\x03\x8b\xe8\x81_=E\x0ck\x8f{\xb3\xb7h\ +\xcb]\xa3\xd1L\x0cIp\x1f$C\xc0(1\x98$Rpi\xd8\x8c\xa1@b\x9a\x00\x12\x11\x08o7\ +\xa7\xa6+~qhb^\xd6\\\x02\xe8\xd6\xf1\x18\x18\xfeh\xba%\xb7xt\x0f\xbb\xb1/hq\ +\xd7h4\x93\x81d-\xdey\x0c\x04\x92\x04b.\t\x91,a\x89 I$\x01\x89I a\x8c \xab\ +\x1e\x99\xb1\xdc\xa1\x95\x92d\xd2\x94\xac\x05#\xd6Q\x01\xfc\xe9\xc9(\xc71\ +\x1a-\xee\x1a\x8df2H\x82\xfb\x80\x12\x01:\t\xa2\x04\xbb\xe8%\x9c#\x17\x02%\ +\x01\x90\xd4\xa0\x14*\xd3\xb3\x86\xe3\x8fj\xa4qG\x95\xf3\xe0\x1c\x07\x86?:\ +\xc5#\x96W\xd9\xbb^\xec\x1bZ\xdc5\x1a\xcd\x04 \xe2@t\xd6\x80@\x9c \x17(\xc1n\ +\xb7\xc28f\x00@\t\x01\x00B\r@Q\x99\x9d\x19\xd5H\xb8&\x93\xcd\x01E\xb4{\x10jz\ +\xd5\t\x0e\x7f\xcc\xa2\xc5]\xa3\xd1L\x00,\xb8\x87\x80\x04\x81\x0bp-`\xe8D\ +\x9cp\xc6\x00\x08\x00\x02\x02\x02 "\x8f\xda\x865$\x0f\x0c\x8a$\xb8\x03\x00\ +\x04 \xe1\x88\x83\xccv\xb7\xb2`d\xf2\x13L4Z\xdc5\x1a\xcdA\x87\x87Ox\xb4NT1\r\ +\n\x14\x88A\x84\xb4\x1c\xc1\x85Rv\x00D$\xa6IL\xc7\x1b\xdaH\xfb\xa1J6 \x86\ +\x84?R\xcb\xf3\xca\'\xf6\xb0\x1b\xfb\x8b\x16w\x8dFs\xc0A\x16\xdc\x07\x00\x04\ +\x10\x12\x01\x00\x81P\xec\x14\xdd\x16\xf7\xa7\xe3XJ)\x00\xc0\xa0dv\xa6l\xd8\ +\x83\xedn\x14I7H\x06\x80q\x1c\xb8k\xc9\x9f>\xdd\xbf\x91ur9<=\xd1h4\x87\x12\ +\xdeY\x15I\xa0\xcc\xf64r\x11\x81@\xb4\xe6\xb8\xb1\xed\x14,\xff\x88a\x9a\x96\ +\xed\x1a\xe6\xd0\xc4\xbc\xac\xb9\x84\x92\x01\x00"\xc8AI\xdbM\xaf\xe2L\xcd\ +\xedY\'^\x00Z\xdc5\x1a\xcd\xc1\x05Q$=\xb3=\xbb\x04J\x00\x00\x08\x0b\x9b\x86\ +\xc5\nG\xbf2\xc8\x10O\x9b\x10\xc8\x1a\xbc\xf5@\x1d2\xd8l\'\xa40s\xf6\xf9_\ +\xfd\x0bE\x8b\xbbF\xa39\xb8\xf0\xf6c\xc9:\x04\x80\xcb\x01\x89\x1bI\xb7\xb4\ +\xe9 e\x97\x11\xf0\x16\xf2f\x126d\xd2V\x95Q\xa5\xc4\x81\xdev\xa7xl\xe2\xaa\ +\xe8\xed\x88\x16w\x8dFs@A\xc9\x93`\t\x94\xb7}P\xe4\xa2\xe1\x96\x9d\xa9#\x99\ +\x0f\x08\x90!\xf0\xa6H\x828lFa\x12\xc7\x9c\x0bY\x9d"\x94\x12\xc0\xc1f;1,\x7f\ +\xfa\xd4^\xf6\xe3\xc5\xa0\xc5]\xa3\xd1\x1cPXk\x05ED\x86\xe5[\'\xa4X{\x15\x00\ +@\xc6 \xdb\x984X\xdc\x8a:\xed8\xe6I"\xb8\x90\x88\x80\x00\x96A(%\x00\xc0\xe5\ +\xe0ZK^\xe5\x95I\xac\xa2\xb7#Z\xdc5\x1a\xcdA\x04\x05c\xcd\x07\xa0\xf2\x04\ +\xc8\x01f\xbb\xedM\x89$\x88\x9bK \xdaQ\x98\xc4\t\xe7L\xaap\x1a @\x00(\x05&\ +\xc04\t\x81\xee\xae\xa5AU\xf4|\xf7\x10\x85?f\xd1\xe2\xae\xd1h\x0e"I\xe3\x0e\ +\xca\x04\x00\x98\xec\xdbpD\x80\x0bx\xfc\xa8\x15/\xfd\xa6\xe2\x83AQ\xca\xae\ +\xa0g+\xe2I\x04!\xc11\x11\x10"\x06q\x02\x84\x82A\x00\x00\x10\x81R \x84\x16f_\ +\x9d\xd0*z;\xa2\xc5]\xa3\xd1\x1c8D\xdc`\xedG\x00 %H\xd1\xe7%\x07Xo\xe1Z\x83\ +\xcf\x96\xa8A\t\xe26MOw5%\x82X\x16\xf5|\xdb4\r\xb4\x90\x18\xdc\xa0@\xa4P\xda\ +\x1e3\x191R\xb1&\xb8\x1c\xc7h\xb4\xb8k4\x9a\x83\x06&\x8d\xbb\xdd\xf4^"\xbf\ +\x04J\x08D\x0c6[\xd2wh\xc1%\x08\x90\x86\xbe#\x02\x00\x12J-\xd3p\x1c\xd3\xb6\ +\r\xc7\xa2\x04E\x1c1\xce\x05H\xc9\x19"\x10B\xc00\xa4c\x92\xa0\xc3\x19\x8bGD\ +\xc7O4Z\xdc5\x1a\xcd\x81A4A6y\xb8!\xa2M \x06\x85?\x02\xc0zS\n\t\xd3\x1e\xa1\ +\x04$ve\xdd0\xa9\xe3\x98\x8em\xda\xb6a\x10\x94R\xf0$\xe9DBH\x04D \x04\x89\ +\x8d\x04(2@\xc98\x98\x14\x0b.\x11,\x06\xef\xb0\x05A*\xb4\xb8k4\x9a\x03\x80dl\ +\xe3\xd7\xedN\x10\'hSn\x99\x04p@\xf8#!\xd0\x89\xb1\xd1A\xdf%\xae\rB\x80D\xb0\ +mZ\xa9\xf8\xb6I@J\xcey\x12&\x82\x0b)\xd5\x07\x80\x00Jb\x81?o8\x15!\x90b\x88\ +\xed;D&\x02\x89A\x80\xb3x\xff\xfb\xba?hq\xd7h4/\x1cl\xd5\xafonlp\x8e\x08\xe0\ +L\xd1\xc1\xbb\x96\x08\x00\xc0z\x0b\x01`\xca!\x84\x10\xcb&\x96A,\x93"\x8b\xdb\ +\x1de\xa4\xf7v\xafn}\x92\xb4\xa2\x82L\x98a\xac\x11B$\x12\x0b=\xcfL\xd4\x91<\ +\t\xf7\xb3\x9f\xfb\x89\x16w\x8dF\xf3\x82I\xc2\xc6\xe6\xc6\x86\xb2\xd3)%\xa6\ +\x01\x88 T\x06\x98^p\x8b\x94 $\nI\n.\x9d-\x13\xc7\xa2\x94\x02A\x94\x88\x82s\ +\xce\xba\xd12\xfdN\x1c\x04\xf0\xa7\xdcvL9\xe7\x00\x08\xc4\xf0lC\xfd\x89\x02p\ +\x16\xedcG\xf7\x15-\xee\x1a\x8d\xe6\x05\xc3\x92D\xc52r\x01\xbe\x05\x04\x80KD\ +\x04\x89 \x04\x08\t\x08@\x081\rb\xdbd\x8a\x02"J)$\x07\xe5\xb5!0\xba(\x1e\xda\ +$\xb0\xcas1/H\x89\x16IL\xdeB\x01\x00@9\x1e!C\x00\x00\x0c\x95IDAT\x08H\x1e#\ +\xe2\xc0:\xda\x93\x8e\x16w\x8dF\xf3\x82\xb1\xdd"\x10\x82\x12\xb9@\xc7$\xc40\ +\x12\x86Q\xc2\t!\x06%\xb6E\x0c\n\x84 J@)\xb9\x04\xe8\x19\xe8\xe3H2\x01"\x92\ +\x0e\x15K\x9e\xe5\x02\x10\xe4\x91\x14<\xfd(\x8a\x04Q\x12b\xecU\xdf^\x1c\x873\ +z\xff%!\x08\x82\xa5\xe5\x95 \x08\xc6? \x8e\xe3\xfe\x8f,-\xaf\xac\xd6\xeb{x\ +\xa1\xbbg\xb5^\xdf\xedU-^\xbf1b(F\x7f\xe4\xea\x17\xd7vw}\xcf\xe3\xec\x07\x87\ + \x08\x16\xaf\xdfx\x81\x17`9\x9e\xed\xcf\x10Bff\n\xe5\xd9\xb2](x\xae\xe9\xd9\ +\xd4w\x88c\x01%\x12\xa5\x14\x02\x11\xbbq\x8f\xbb5\xb3\t!RJ\x1e\xb5y\xdc\x12B\ +lk\x00\x85\x8a\xa0<|h\xcb}"\x89\xe3\xf8\xc3\x8f>v\x1cgn\xaev\xf3\xe6\xad \ +\x08\xbe\xfd\xad?v\x1c\'{\xcc\xe2\xf5\x1b?\xfb\xe4\xd3\x85\xf9\x13\xab\xf5\ +\xb57/_\xba\xfc\xc6\xa5 \x08~\xfc\xee{s\xb5\xd9\xd5\xfa\xda7\xbe\xfe\xb5sg\ +\xcf\x00\xc0_\xbe\xfb\x1e\x00Dq|\xee\xec\x99\xaf\xbe\xfd\x16\x00\xfc\xd9\x9f\ +\xffE\xda\xc8\xf7\xde\xf9\xee\xc2|~sv\x10\x04?\xf8\xe1\x8f\x06\xfe\xa9\x9f\ +\x9b\xb7n_\xbdz\xed\xdf\xfe\xe9\xf7\xc7\xec\xdaj\xbd\xfe\xe1G?u\x1d\xc7q\xec\ +8N\xa28\xfe\x93w\xbeS*\x95\xb2\xc7\xfc\xe5\xbb\xef]\xbe|I]\xff\xd6\x89n\xde*\ +\x95J\xb9#G_v\xfa\x91\xcf\xae|~\xf9\x8dK\xd9\x83\xd3Ap\x1cG\x8d\xde\xe8\x8e\ +\xecx\xf6a\xf4\x9fh\xb7-<;\x8d\xa0y\xf3\xe6\xad\x8b\x17\xce\xef\xff\xa9S\xaa\ +\xd33\t}bZ\xb2\x13\xb49\xe3\x88H\x00P\x02\xf6<.\xcf\xe87!0\xd8wc\x98\xc6h\ +\x9f\xce\xe4\xa2\xc5}\xf2P\xca~\xf9\xf2\x1b\xf5z}iiyaa\xfe\xe2\xc5\xf3\x1f~\ +\xf4qN\xdf\x97\x96\x96\xbf\xfd\xad?>w\xf6\x8c\xd2\xf4\xcbo\\\xfar\xf1\x86\ +\x92\x8f\xa5\xe5\x95+W>?w\xf6\xcc\xcd[\xb7\x1d\xc7\xfe\xde;\xdf\x8d\xe3\xf8\ +\x07?\xfc\xd1\x9b\x97/\xa9\x16\xfe\xeb\x7f\xf9\xcf#.\xe0\x97W\xaf\x95J\xa5\ +\xc5\xc5\xeb#\xc4\xfd\xfd\x0f\xfe\xea{\xef|\x17\x00\xc6\x99\x00R\x82 x\xff\ +\x83\x9f\xa4\x13\x0f\x00,-\xaf\xf4+\xe6\xe5\xcb\x97v\xd5\xec\xf8\x97\x9dE\rB\ +\x10\x04\xff\xe3\x83\x9f\x9c;{\xe6)\xce\x98\x0e\xc2\xaeN\xf4\x143\xc4\xa4\ +\x83\x06\x00\xe5\xddR}T\xfe.\x00X\ +]\xad\xff\xf8\xdd\xf7R\xbd\xfe\xec\xca\xe7\xea\xcd\x0f?\xfa\xb8\x11\x04\xd9A\ +XZ^\xb9z\xf5\x1a\x00,.^\xef\x9fZr\'\x02\x80\xf7?\xf8I\xa3\x11\x00\xc0\x87\ +\x1f\xfdT\xa9\xf3\x87\x1f\xfdT\x8d\x8f\x1a\x8d\xfe\xa1K\xc7\xc7\x1d4\xd47o\ +\xdd\xfe\xe4\x93\x9f\xa7\x97\x07\xbd\x1f\nQ\x14GQ\xac\xae\xfc\x05\x92$I\xcf\ +\xf9\x82\x89\xf0\x1b\x01\t\xeak\x9d\xf5\'\xcd\x8dV\xd0\xf1\x01\x9e\xd3j\'J\ +\xec"\xb7\xde\x13L\xb0\xe4\xf9\xb4\x7f\xc0\xd0n\x99\t&\x8e\xe3\x9c\x9f\xbd\ +\x1f%C\xbb\xf2\xe4\xfe\xc7\xff\xf0\xef\x1d\xc7\x89\xe3\xf8\xfd\x0f~\x92\x1a\ +\xfb)_.\xde\xf8\xf6\xb7\xbe\t\x00\x17/\x9e\x7f\xff\x83\x9f(O\xce\xd5\xab\xd7\ +\xbe\xfd\xado\xa6\xf3\xc4\xe57.\xfd\xd9\x9f\xff\x85\xf2H\xa4V\xe4\xeb\x17\ +\xcf\xdf\xbcyka\xfe\xc4\x97\x8b7^\xbfx>\x8ec5?\x01@\xd6\xeb\x9d\xeb\x91\x9a\ +\xb1\x94\xe4\xbdy\xf9R\xd6/\xacZ\xf8\x8f\xff\xe1\xdf\xab3\xfe\xe0\x87?\x1a\ +\xd1\xa9\x81\x97\xbd\xe3P\xdc\xbcy\xbbT*~\xef\x9d\xefd\xdf\xfc\xe5\xd5k\xfd\ +\xcb\x00\x00\xf0\xd5\xb7\xdfRc\xf5g\x7f\xfe\x17\xdf\xab\xd5\xbe\xf7\xcew\xd3\ +A\xb8\xfa\xc55\xc7\xb1\xe7\xe7O\x0c\xfb"\xb2\'\xbay\xebv\xa9TL\'\xb9\x9b7o9\ +\x8e\xadFI}|\xd8\xd0\xa5\xe3\x93\x1bj\x00\xb8z\xf5\xda\xe5\xcb\x97\x1c\xc7\ +\xa9\xd5j?\xfb\xe4\xd3 \x08\x94\x8fN\x1d_.\x97\xd4T\xf1\xa2\xb0\xdcR\x14>6\ +\x08\x00\x82a\x19\x96i\x0b\xc6\x04\x17@\x88k\x1b\x94R\x94\xe2Y\x9d3\x84\x80{\ +\x94\xdaU!\xa4!60\xea\x9a\x02\x04P\x8a\x04\xc0\x7f\x0e\xdd8`hq\x9f<\x16\x16\ +\xe6\x17\xaf\xdfx\xfd\xe2\xf9\xcf\xae|~\xee\xdc\xd9\x9b7o\x95\xcb\xa5z}-\x95\ +\x83\x94\x9f}\xf2i\xbd\xbe\x96jS\xa9TJM\xf5F\xd0,\x97\x8a\xea\x1d\x80\x13\ +\x00\xd0h\x04ss5\xe8\xc9\xab\xe38\xe7\xce\x9d\xc9\x99\x99\xca\x11\xa1\xd6`\ +\x157o\xdd\xbex\xe1\xfcj\xbd\xbe\xa3\xa7\xf8\xe2\x85\xf3\xff\xed\xbf\xff\xbf\ +_}\xfb\xad\xc5\xeb7\xfe\xdd\x9f~\x7f\xb5\xbe\x16\xc7\xb12o\x01\xa0\\*\xaa\ +\xae)U\x82\x8c\x96\xa5\xe4N\xb1Z_+g\xfc3\xd9\xd79\x86]\xf6\xe8\x0b\xbe\xfc\ +\xc6\xa5sg\xcf\xfc\xf8\xdd\xf7r\x93h\xee\xe7N\xfa\xfe\x88\xd9B\x9dKY\xdf\xfd\ +\x13C\xeeDA\x10\xac\xd6\xd7\xe2\xde\xc8\xd4j\xb5\xb9Z\xed\xcd\xcb\x97\xae^\ +\xbd\xf6\xb3O>\xfd\xc6\xd7\xbf\xa6\xa6\xde\xdc\xd0Af|rC\r\x00\xab\xf5\xfa\ +\xe2\xe2\xf5\xf4\xf8(\x8e\xeb\xf5zz\xc3\xbcp/\xbf_\x9am\xaf\xdf6\xa8\x00$&\ +\xb6\xca\x05\xcf\xf6J\\\x00rN\x92u\x1e\xb3gv\xbbc;\x9e\x92\xd27\x19\xa7\x94\ +\xc6\xa2l\x88\xb6mt\xd4\xc6\'\x9e\x84\x8e_y>=9Hhq\x9f<.^8\xff\xe1G\x1f\xbf\ +\xfd\xf6[\x00\xb0\xb8x}n\xae6?\x7f\xe2\x93O~\x9e30\x95\xcd\x9e\x8d\xeeP^u\ +\xb5\xa0\xea:N\xa9TZX\x98_\\\xbc~\xf1B\xd7\x8e\xfe\xea\xdbo--\xaf\xd4\xebu\ +\xa5\xaaKK\xcb\x17/^\xc8\xb6\xb9\xb8x\xe3\x1b_\xffZ*\x8b\x8b\xd7o\xfc\xf2\ +\xea\xb5\x8b\x17\xce\x9f;{fiyea\xfeD\xea\xd8\xe9\xbfl\xc7q\xd4\x95+\xf7H\xa9\ +Tr\x1cG-\x02\xc7q\xdc\x08\x02u\x85?~\xf7\xbdr9/\xeb\x03Y\x98?\xf1\xb3O>U\x82\ +\x18\xc7q\xea\x96\xb9y\xeb\xf6\xc2\xfc\x89\xec5\x0c\xbb\xec\x1dOQ*\x95\xde\ +\xbc|\xe9\xb3+\x9f\x7f\xfb[\x7f\x9c\x1d\xc6\xab_\\S\xd1G\xa9i\xbc#\x17/\x9c\ +\xbf\xfc\xc6\xa5\xcf\xae|\xae\xbe\x82\x11\'\x9a\x9f?\xb1\xb4\xb4\xacL\xfe\ +\xd5z\xbd\\*\xa9\xce^\xbcp\xfe\xe6\xad\xdb\x8b\x8b\xd7\xbf\xf7\xcew\xfb\x87.\ +Kn\xa8\xd55_\xbcxA\xcd\x9aK\xcb+s\xb5\xda\xc2\xc2|\xbd^W\xef\xd4{!\xa7*\xf6t\ +\xaeV\x1b\xa7G\xcf\x11\xd3r\xbc\xca\xc9\xa4q\xdbP\x9bN\xdb\x8fY\xb2I\rCr&\ +\xf8\xb3+;\x00\x10\xc7+4;1\x8b%\x01D4\xa6\x1c\x97\x90\x0e\xaa\x94b\xf4\x10\ +\x06\xb9\x83\x16\xf7ID=\xd8\x1f~\xf4q\xa9T\x9a\x9b\xab5\x1a\xc1\xd2\xd2\xf2\ +\xb7\xbf\xf5\xcd\xfeP\xc8\xf4\xbf\x00\xf0_\xff\xcb\x7f~\xfd\xe2\xf9\x1f\xbf\ +\xfb\xde\xd2\xd2\xb2\n\x85\x04\xa5SW\xaf\xfd\xe5\xbb\xefEq|\xf1\xc2y\xc7q\ +\xca\xa5\xe2\x87\x1f}\xbc\xb4\xb4\x1c\xc7I\xad6\x9b\xf5\xc9,-\xaf4\x82 \xfb\ +\xce\xb9\xb3g>\xbb\xf2\xf9\xd2\xf2\xca\xe5\xcb\x97\xde\xff\xe0\'s\xb5\xd9F\ +\xd0|\xfd\xe2\xf9\xcbo\\\x9a\xab\xd5\xfe\xf2\xdd\xf7.^<\x9f\xb5\n\xcf\x9d;\ +\xfb\xfe\x07\x7f\x95\n\xe5\x9b\x97/\xfd\xe0\x87?R\x9fz\xf3\xf2\xa5\xb9Z\xadT\ +*}\xef\x9d\xef|\xf8\xd1Oo\xde\xbc\xad|\x11K\xcb+\xeaR\x07\x92m!\xed\xbe\xf2n\ +g\xe3m\x86]\xf68\xa3\xad|\xf4\xd9\x83\xbf\xf1\xf5\xaf}\xf8\xd1\xc7\x9f]\xf9\ +\xbcT*\xcd\xd5fG|6\x1d\x848\x8e\xbf\\\xbc\xa1\xd69\xfed\xfb\x1c\xdc\x7f"\xa5\ +\xc8?\xf8\xe1\x8f\xd4\xf1\xdf\xfe\xd67\xe38\xf9\xf0\xa3\x8fU7U\xb8j\xff\xd0\ +\xe5Z\xcb\ru\xfa\x05\xa9\xafUM\x15\xef\x7f\xf0\x93\x9b7\xbb\x0b\x06j\xb4\xd5\ +?\xf7_\xdc\x01\xa0<\xbb\xb0\xcec\xd6zhRI\x80\x08\x16\x0b\x06\x00*t\x06\x80\ +\x00<\xc3\xaa*"\xdaf\xa7\\\x9d\x8b\x12@D\x8b0\x07C\xb5\x8c*\xc1:\x94f;\x00\ +\x90=\\\x89\xd6\xec1A\x10\xa4\xde\x951?\xa2,\xdc\xdcG\x96\x96W\x1c\xc7N\x1fi\ +uL\xf6\x9d\xa7hy\xe0\x89\xc6\xbc\x1e\x00X\xad\xd7\xe38\x19\xe7\x1a\xd4 \xcc\ +\xd5f\xc7\xf1\xa1?w>\xbb\xf2y\xb9\\\x1a\xf6# \xdb;\xd5\xa3\xf1\xaf3\xd7\xaf\ +\xfe\xefz\xcc\x11\xce\x92\xfb\xa2\x07\xbe\xf3bI\xa2v\xd4\xd9\x14I\x07\x90\ +\x0b\x16#\n\x90\x1c@J!\x08H\x00\x15\xf7\x8e\x84\x0c4\xe6I\xf7?\x83$\r\x11\r\ +\xdb\xa5\xd6\x94\x94\x88\xac\x89"\x01 B\x82?\xfb\xdaT\xf5\xd8\xde\xf6\xea\ +\x05\xa1\xc5]\xa3\xd9\x1d\x1f~\xf4\xf1\xdc\\\xadV\xab\x05A\xf0\xcb\xab\xd7\ +\xfe\xdd\x9f~\xff\x85\xcc+/\x0b\x88\x88R\x08\xc6;u\xd1y\xd0\x8cK,a\\JJ\x90\ +\x82\x04\x82\x04$\x01iP\xa4\xc0)\x05\x89\x06!j\xdf\xa9\xe85\xd0\xdd\xa5D\x89\ +\xf2\xc2\x00\x00\x91H\x90:\xfe\xf4\xe9\xa9\xca\xd1\x17\xd8\xb9=E\x8b\xbbF\ +\xb3;V\xeb\xf5\xc5\xc5\x1bjY\xf5\xcd\xcb\x97^\xf8j\xe4KB\x12\xdc\x83x\x15\ +\xcc\xb9\xb5\r\x16q0(\x11\xbd\x80F\x02x\xa4j\xc4\xf1F\xc1\xe2\xb2p\x86\x85\r\ +\x16\xae\xf3\xa4\x8d\x08\x94\x80\xef\x10\x04\x90f\x95\x83KP\x10\x02\x12\xa8\ +\xed\x95\xfd\xe2\x0c5\xac\x17\xda\xa7\xbdE\x8b\xbbF\xa3\x99\x00\x82\xd5\xdf\ +\xd8\xfc\x91\xe3\xd5\x82\xd0F\x80v\x84\x11CB\x08"\x9a\x94\x1c\x9f6\x9el\xd6}\ +\xb3#\x91\xf2^\x89\x0f\x04\x98r\xc0\xf3\x08 \x80Y\x86\xca\xef\xbe\xd8.\xec3z\ +\x13\x93F\xa3\x99\x00\x92$\x8e\x99\x94l\xdd\xb7y\xb9`Z\x96i\x1a\xc4\xa0\xe0\ +\xd9\xb4\\0\x92\x84I\x115C\xcc*\xbbA\xc0\xb5\tH\x00\x04`\r\xe8\xdcy\xb1]\xd8\ +gt\xb4\x8cF\xa3\x99\x00\x04g\xad\x0e\x98\x94!\xac\xb5\xa2J\xb9P\xf2,\x94(M\ +\x83\x08\x166\xdb\x1bR\nD\xb2UM\x1b\xc1u\x80\xd0\xcc\xfaj{\x19\xac\x19\xb0^\ +\x167\x9av\xcbh4\x9a\x03\nJ\x86\xac\x83\xbcIy\xe3\xd1\xea\x93(\x91&\x05\xdf\ +\x81\x84#\x80I\xa8\t\x84\xa0\xe4Rp\x00D$\x12\xc1w\x08\xf4\xcc\xf6\xeaT_\x11\ +\x0e\xc3\x87\xea\x1bp\x18\xb3\xb7\xf7\xa3-w\x8dFs\x80@\xc9\x90wd\xdc\x90I\ +\xd0\x8dY$\x80\x08B\xa0\x12\xea0\x01\x93\x12\x00\x0e\x92\x03\x00\x010\r\x02@\ +\x12\xbe\x95\xbb\x17\x11\xbc\x9c\xd9\xae\x10\x1dh\xdf\x85\xa9\xb3\xfb\xda\ +\xa5\x17\x84\x16w\x8dF\xf3BA\x81\x92#\xef\xc8\xa4!\x93&\xb2\x16J\xd6U\xe5\ +\x9e4K\xb9\x15\xd1\xa8\n\xa5\x1a\x84\xa4\xd1\xee\xb2{\x00RJ\x08\x01)\xc1\xa4\ +\xe0\xdad\xf0\xbe\xa7\xf0\x01x\xc7\xc08\x84\xc9drhq\xd7h4\xfb\x8eL\x80\xb7\ +\x91\x05DH\xf8\t\x13\xb1E\x04\xbe\xe8\x00\ -@\xf2\x8d\xb5\xd6z\x02\x00\xccl\t\x98\x19\xc9}\xe9#y\x8f\xb0\x00H\xba\xc3\ -\xfd\x8a\xbd\x9e0\xe8xn\x9b\x99*q[r\x01`\xfa\x8f?\x91\x86-\x07\x8d\x00Iww\ -\xf7\xce\xcc\xf0>\xbb\x01\xa8j)e\x80G\xa0\xb7[k\x00J)\xfdU\xd5\xd6Z\x87O_D\ -\x88\x88\x88dff>\x17"r\x02y\xd33\xb3E\xc4\xcb\xe3\xeb\xda\xbe\x9e\xf7\x0f\ -\xa0B\x86\xd5X\x16\xcc\xea\x00\x00\x00\x00IEND\xaeB`\x82' +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x017IDAT8\x8dcddbfh\x9f\xb3\xf3?\x03\x0e\xf0\xfc\xc5[\x0c\xb1\xfb\x0f\ +\x9f10000l\x9e]\xc2\xc8\x02\x13,Ot\xc6e\x06V\xe0\x9f1\x81\x81\x81\x81\x81\ +\x81\x05Y\xf0\xdc\x0b\x88C\x1e|\xfc\xc2\xf0\xe3\xf7\x01\x86{\x1fO20000(\xf1\ +\x9b3p\xb0:\xc0\xd5\x05\xa9\xf3\xc2\xd9L\xe8&\xa3kf```8\xfah-\xc3\xb57\x9d\ +\x0c?~\x1f\xc0p\t\x86\x01\xe8\x9aa\xe0\xf9\xc7\'X\xc5Q\x0c\x90\xe1c\xc4P\xf4\ +\xfc\xe3\x13\x14\xb6\x02?\x0f~\x17(\xf1\x9bc\xd5\xcc\xc0\xc0\xc0 \xc9/\x03g_\ +\xbbx\ta\x00,\xaa\xc4\xb8\x18\x18\x8c%\xd5\xb0j\x86\x19n$\xc1\x88"\xc6\x82\ +\xaeH]X\x9d!T#\x96\xe1\xec\xf3[\x0cG\x1f\xade````\xb0\x96\x0bf0\x96TcP\x17V\ +\xc70\x14\xc3\x00\x98!\xea\xc2\xea\x0c\xb7\x1a\x1a\x19\x18\x18\x18\x18\xa2\ +\xd6,\xc0\xa6\x0c\xe1\x05J\x00\x0b\x03\x03"iz,\xd3A\x91|l\xf2\x8a\x81\x81\ +\x81\x81au\x87\x18\x8a\xf8\xd5\x8aW\xc4\xb9@VN\x0c\x9f4v\x03\x94\x05LH2\x04%\ +\x10wD]!h#N\x03`\xb9\x0b\x06`\t\x85\x10\x00\x00\xe4\x0ecz\x94h\xf0\x8e\x00\ +\x00\x00\x00IEND\xaeB`\x82' def getImageBitmap(): diff --git a/wxPython/samples/ide/activegrid/tool/MessageService.py b/wxPython/samples/ide/activegrid/tool/MessageService.py index 288d40d5c9..1dd15ebd88 100644 --- a/wxPython/samples/ide/activegrid/tool/MessageService.py +++ b/wxPython/samples/ide/activegrid/tool/MessageService.py @@ -14,6 +14,35 @@ import wx import Service import STCTextEditor +#---------------------------------------------------------------------------- +# Utility +#---------------------------------------------------------------------------- + +def ClearMessages(): + messageService = wx.GetApp().GetService(MessageService) + view = messageService.GetView() + if view: + view.ClearLines() + + +def ShowMessages(messages, clear=False): + if ((messages != None) and (len(messages) > 0)): + messageService = wx.GetApp().GetService(MessageService) + messageService.ShowWindow(True) + view = messageService.GetView() + if view: + if (clear): + view.ClearLines() + for message in messages: + view.AddLines(message) + view.AddLines("\n") + + +#---------------------------------------------------------------------------- +# Classes +#---------------------------------------------------------------------------- + + class MessageView(Service.ServiceView): """ Reusable Message View for any document. When an item is selected, the document view is called back (with DoSelectCallback) to highlight and display the corresponding item in the document view. @@ -36,52 +65,52 @@ class MessageView(Service.ServiceView): txtCtrl.SetFontColor(wx.BLACK) txtCtrl.StyleClearAll() txtCtrl.UpdateStyles() + wx.EVT_SET_FOCUS(txtCtrl, self.OnFocus) return txtCtrl - -## def ProcessEvent(self, event): -## stcControl = self.GetControl() -## if not isinstance(stcControl, wx.stc.StyledTextCtrl): -## return wx.lib.docview.View.ProcessUpdateUIEvent(self, event) -## id = event.GetId() -## if id == wx.ID_CUT: -## stcControl.Cut() -## return True -## elif id == wx.ID_COPY: -## stcControl.Copy() -## return True -## elif id == wx.ID_PASTE: -## stcControl.Paste() -## return True -## elif id == wx.ID_CLEAR: -## stcControl.Clear() -## return True -## elif id == wx.ID_SELECTALL: -## stcControl.SetSelection(0, -1) -## return True -## -## -## def ProcessUpdateUIEvent(self, event): -## stcControl = self.GetControl() -## if not isinstance(stcControl, wx.stc.StyledTextCtrl): -## return wx.lib.docview.View.ProcessUpdateUIEvent(self, event) -## id = event.GetId() -## if id == wx.ID_CUT: -## event.Enable(stcControl.CanCut()) -## return True -## elif id == wx.ID_COPY: -## event.Enable(stcControl.CanCopy()) -## return True -## elif id == wx.ID_PASTE: -## event.Enable(stcControl.CanPaste()) -## return True -## elif id == wx.ID_CLEAR: -## event.Enable(True) # wxBug: should be stcControl.CanCut()) but disabling clear item means del key doesn't work in control as expected -## return True -## elif id == wx.ID_SELECTALL: -## event.Enable(stcControl.GetTextLength() > 0) -## return True + def GetDocument(self): + return None + + def OnFocus(self, event): + wx.GetApp().GetDocumentManager().ActivateView(self) + event.Skip() + + def ProcessEvent(self, event): + stcControl = self.GetControl() + if not isinstance(stcControl, wx.stc.StyledTextCtrl): + return wx.lib.docview.View.ProcessEvent(self, event) + id = event.GetId() + if id == wx.ID_COPY: + stcControl.Copy() + return True + elif id == wx.ID_CLEAR: + stcControl.Clear() + return True + elif id == wx.ID_SELECTALL: + stcControl.SetSelection(0, -1) + return True + + + def ProcessUpdateUIEvent(self, event): + stcControl = self.GetControl() + if not isinstance(stcControl, wx.stc.StyledTextCtrl): + return wx.lib.docview.View.ProcessUpdateUIEvent(self, event) + id = event.GetId() + if id == wx.ID_CUT or id == wx.ID_PASTE: + # I don't think cut or paste makes sense from a message/log window. + event.Enable(False) + return True + elif id == wx.ID_COPY: + hasSelection = (stcControl.GetSelectionStart() != stcControl.GetSelectionEnd()) + event.Enable(hasSelection) + return True + elif id == wx.ID_CLEAR: + event.Enable(True) # wxBug: should be stcControl.CanCut()) but disabling clear item means del key doesn't work in control as expected + return True + elif id == wx.ID_SELECTALL: + event.Enable(stcControl.GetTextLength() > 0) + return True #---------------------------------------------------------------------------- @@ -139,5 +168,3 @@ class MessageService(Service.Service): def _CreateView(self): return MessageView(self) - - diff --git a/wxPython/samples/ide/activegrid/tool/OutlineService.py b/wxPython/samples/ide/activegrid/tool/OutlineService.py index 573327db89..75fc67e0d2 100644 --- a/wxPython/samples/ide/activegrid/tool/OutlineService.py +++ b/wxPython/samples/ide/activegrid/tool/OutlineService.py @@ -321,7 +321,7 @@ class OutlineService(Service.Service): def __init__(self, serviceName, embeddedWindowLocation = wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM): Service.Service.__init__(self, serviceName, embeddedWindowLocation) - self._validTemplates = [] + self._validViewTypes = [] def _CreateView(self): @@ -493,9 +493,8 @@ class OutlineService(Service.Service): if self.GetView(): currView = wx.GetApp().GetDocumentManager().GetCurrentView() if currView: - for template in self._validTemplates: - type = template.GetViewType() - if isinstance(currView, type): + for viewType in self._validViewTypes: + if isinstance(currView, viewType): self.LoadOutline(currView) foundRegisteredView = True break @@ -506,14 +505,14 @@ class OutlineService(Service.Service): self._timer.Start(1000) # 1 second interval - def AddTemplateForBackgroundHandler(self, template): - self._validTemplates.append(template) + def AddViewTypeForBackgroundHandler(self, viewType): + self._validViewTypes.append(viewType) - def GetTemplatesForBackgroundHandler(self): - return self._validTemplates + def GetViewTypesForBackgroundHandler(self): + return self._validViewTypes - def RemoveTemplateForBackgroundHandler(self, template): - self._validTemplates.remove(template) + def RemoveViewTypeForBackgroundHandler(self, viewType): + self._validViewTypes.remove(viewType) diff --git a/wxPython/samples/ide/activegrid/tool/PHPEditor.py b/wxPython/samples/ide/activegrid/tool/PHPEditor.py index bd8fa06029..5e78d118f6 100644 --- a/wxPython/samples/ide/activegrid/tool/PHPEditor.py +++ b/wxPython/samples/ide/activegrid/tool/PHPEditor.py @@ -219,6 +219,10 @@ class PHPOptionsPanel(STCTextEditor.TextOptionsPanel): STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "PHP", label = "PHP", hasWordWrap = True, hasTabs = True) + def GetIcon(self): + return getPHPIcon() + + PHPKEYWORDS = [ "and", "or", "xor", "__FILE__", "exception", "__LINE__", "array", "as", "break", "case", "class", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", @@ -274,14 +278,22 @@ import cStringIO def getPHPData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00{IDAT8\x8dclh8\xf0\x9f\x81\x02\xc0D\x89f\xaa\x18\xc0\x82M0<\\\x1c\ -\xce^\xb9\xf2%y.\xd0\xd4\xd4$\xde\x05\xf8l\x0c\x0f\x17\x87\x8baS\xc7x\xfd\ -\xfa\xf5\xff\xc8\xb6]\xbf~\x1d\xc3\x05\xf8\xc4\x98\x90\x05\xae_\xbf\x8e\xa1\ -\x88\x90\xd8 \x8aF\x98\x93`~\xc3\x05\xd0\xd5\xc1\r\x80\t\xc0B\xf7\xfa\xf5\ -\xeb(l\\\xeaP\xbc\x80\x1c\x85\xb8\xd8\xe8|&b\x9c\x8dn;2`\x1c\xf0\xdc\x08\x00\ -\x8e\xf2S\xed\xb0\xbe\xaa\xbc\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x01GIDAT8\x8d\x8d\x931O\xc2@\x14\xc7\x7fW\xfa\x11\x1c\xe430\xb88\x18'\ +\x8c\x89\x0e\x0c\xc4\xd9\xdd\x85\xc9\xc5`\x82\x1b\t\x84\x98\x98\xe0\xa4_\x01\ +cd`t$\xb8h\xd0\xb8\xabD0\xd4\xd0\xb4%H $\xe7P\x0e{@\xa9\xff\xe4\r\xf7\xee~\ +\xff\xf7\xee^+\x1a\xcd\x8ed*\xab\xef\x02\xd0\xea\xda\x00\xb8\xce\x90\xb3\xa3\ +}\xc1*5\x9a\x1d\xf9\xf6#g\xf1\xea\xf9qyS\x97\xf5o)\x8f\xcfo\xa50b\x84\x85\ +\xb1\xca\xdc\x9b\xc0\xde\xe1\x01'\xa7U\x19v\xc6\xb4\xfa.\xeb\xc4\x01\x18L\ +\xfc\xa4;\xf2\xdb\x7f\xac\xdd\xd3s<\xda\x03+\xb4\x88\x19\x04\x15\x0c\xb0\x93\ +\xde\xc5\x9b\x80=\x86\xf6\xc5U\xa8\x81v\x05\x05\xab\xf6\xedq(\xf7\xd7A\xabk\ +\xb36\xd2\x93A\xd8\x1aF\x18\xcc\x83\xb0\x08\x7f\xbc\xb7\xc2\r\\g8\x03\x97\ +\xc1Q2{\x8e\xa7\x81/\xd7\xb5\x85C\xc9\xc46\xc9\x84>\xcaR!-`\xfa\x88\xab\xe0b\ +>\xb5\xb4\xb2\xfa6\xcc\xf6\xa7\xc5f\x00V\xc0\xc3\xf3\x17w\x95\xa7YN\xad\x83\ +\xfbP\x95\x06@un\xce\xd9\\\x8d\xad\x8d\xf8\xbf\xd6F\xa5\x9c\x11\x95rF\xfbaT\ +\xc50\x15\xf3)\xb29\xbfc!\x8c\x98v\xaf\xe0f\x14\\*\xa4\x85f\x10|\x9c(\xa9)\ +\xfc\x02?r\xb8\xfc~J.\xd0\x00\x00\x00\x00IEND\xaeB`\x82" def getPHPBitmap(): return BitmapFromImage(getPHPImage()) diff --git a/wxPython/samples/ide/activegrid/tool/PerlEditor.py b/wxPython/samples/ide/activegrid/tool/PerlEditor.py index aaab62a206..bc7c48f0c1 100644 --- a/wxPython/samples/ide/activegrid/tool/PerlEditor.py +++ b/wxPython/samples/ide/activegrid/tool/PerlEditor.py @@ -133,6 +133,10 @@ class PerlOptionsPanel(STCTextEditor.TextOptionsPanel): STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Perl", label = "Perl", hasWordWrap = True, hasTabs = True) + def GetIcon(self): + return getPerlIcon() + + PERLKEYWORDS = [ "abs", "accept", @@ -392,24 +396,22 @@ import cStringIO def getPerlData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x01\x81IDAT8\x8d\xa5S1n\xe30\x10\x1cJ\xf9\x80;U\x04\x04~\xc06\xdc\xa9\ -\x10\xd4\xb3K\xf2\x01\xf9\x01F\x92\xce\x8d:vI\x84\xdc\xd5\xaa\xdc%\xd1\x17\ -\x0c\x17ns\xa7\x07,\x16\xe0G6E@B\x91\x9c*\x0b\x10 \xb9\xe4\xecpg\xa8T\x92\ -\xe27q5^\xbc\xbf\xbd\n\x00\\\xdf\xdc\xaa\xb0\xf7\xfc\xf4(\xcc\x8c<\xcfqw\xff\ -\xa0\xa6\x00PI\x8aa\x18\xa4m[\xd9\xedvb\xad\x95a\x18D%)\xfa\xbe\x97\xc5b!\ -\xd6Z\xb1\xd6J\xdb\xb6\xa2\x92\x14\xe3\x91\x00\xc0r\xb5VZ\xeb\x08z<\x1e\xf1\ -\xfe\xf6*]\xd7\xc1\x18\x03c\x0c\xea\xba\x063\xe3\xff\xbf\x0f\xf9\xf1\tD\x14\ -\xe7\xce9\xec\xf7{\x00\x80\xf7\xfe\x1b\xf88\x920\xf1\xde\xc7j\xcc\x8c,\xcb\ -\xe2:\xe4\xeb\xba\x06\x80o,"\x03\xad5\x0e\x87C\xacz>\x9fAD\xb1\xba\xd6\x1aD\ -\x04f\x063\xcf\x19\\\xdf\xdc\xaa\xa2(p:\x9d\xe0\xbd\x07\x11\xc19\x07\xad5\ -\x98\x19\xce9l\xb7[\x10\x11\xf2<\x9f\x03\x00\xc0\xcb\x9f\xbf\xaa,\xcbX!\xcb2\ -t]\x17\xf3M\xd3\xc4\'\xc5\x98\xca\x12d\xddl6\x12d\x0c\x12\xab$\x85\xb5Vf2N\ -\x83\x88P\x14\x05\xbc\xf7h\x9a\x06UUE\xda\xc6\x98\xcbM\x1c\x871\x06\xde{TU\ -\x05\xe0\xcb\'\xe1RY\x96X\xae\xd6\xd1\x91\x17\x19\x00_]_\xae\xd6\x8a\x88\xf0\ -\xfc\xf4(\xe1\xd2\xb4\x07?\x02\x8c\x0f\x8e\x1d85\xd2\xc5\x06\xf6}?\xf3|\x18\ -\xb3\xdco\xbf\xf3\'`\xa6\xbc1\xa7\xd6\xcb\xbf\x00\x00\x00\x00IEND\xaeB`\x82'\ +\x00\x01CIDAT8\x8d\x95\x93\xbfN\x02A\x10\x87\xbf[\xef\x05\xach|\x02m}\x008\ +\x881Z\xd2\x1a\x13\x0bKx\x02{\xa3\xa13\xc6\xc6\xc6\xd2DZ+s\\\x83\x95\x1d\xa2\ +&V\x104\x01/p\x01\t\xa0\xe8X\xc0\x9d\x87\xdc^\xf0\x97Lfw3\xdf\xec\xcc\xfe1\ +\xca\x95\xba0\x95\xeb\xf5\x01h\xb4\xda\x00x\xde\x90\x83\xfd\r\x838\x95+u\xa9\ +\rDj\x03\x91\xe7\xbe\xc8}wb\xa7\xc5\xb2\xdc\xbe\x89\xe4\x8f\xae\xc4PK\xe8L\ +\xc5%\xef\x8da{7K\xee\xf0Rt1\xa6\xeb\xf5Y\x01>\xbea\xf45Y\xec\x8e&\xe5\xdf]\ +\xdb4\xdd\x0e\xaf/-\xed&&\x110\xc0\xfa\x96\xc5\xf1N\x06\x80\xe5\xb5\xac6\x81\ +\x82y\xb87\x9e\r\xeaT\x8b3s+\x95\x14+\x95\x14\x00\xd5h\xb5\xe9\x8e\xe6a\x7f\ +\xf70\x14\xf6\xfeXy\xde0\x08\xf2\xe1\xf6gt\xb9V*)v\xc9\t\xae\xd5.9\x86\x19\ +\x05\x9e\xefe\xe6i\x8dT\xd3\xed\xfc\x0b\x0e\xb7\x00\xd3C\xd4\x95\x1c'\xbf\ +\x15\x15\xbe\xe3\xc6;l\x9e\xdc\x00\xbf\xfe/`\x97\x1c#|\x0e&@\xb1p\x16\x04>U\ +\x1fI\x00\x17\xb9<\t\xa0\xc9*\t\x1e\xf4\xa5D\xbd\xeft:-q~\xe1\xbf\xb0\x88b\ +\x13\x84{\x8d\x9a\x03\xfc\x00\xea\x7f\xa9A\xa7\xc3Vo\x00\x00\x00\x00IEND\xae\ +B`\x82" def getPerlBitmap(): diff --git a/wxPython/samples/ide/activegrid/tool/ProjectEditor.py b/wxPython/samples/ide/activegrid/tool/ProjectEditor.py index 9934eaade7..af95b890d3 100644 --- a/wxPython/samples/ide/activegrid/tool/ProjectEditor.py +++ b/wxPython/samples/ide/activegrid/tool/ProjectEditor.py @@ -2,7 +2,7 @@ # Name: ProjectEditor.py # Purpose: IDE-style Project Editor for wx.lib.pydocview # -# Author: Peter Yared, Morgan Hua +# Author: Morgan Hua, Peter Yared # # Created: 8/15/03 # CVS-ID: $Id$ @@ -10,23 +10,41 @@ # License: wxWindows License #---------------------------------------------------------------------------- +import wx import wx.lib.docview import wx.lib.pydocview -import types -import os -import os.path -import wx +import wx.lib.buttons from wxPython.lib.rcsizer import RowColSizer -import time import Service +import copy +import os +import os.path +import sets import sys -import activegrid.util.xmlutils +import time +import types +import activegrid.util.appdirs as appdirs +import activegrid.util.fileutils as fileutils import UICommon import Wizard import SVNService +import project as projectlib +import ExtensionService + from IDE import ACTIVEGRID_BASE_IDE if not ACTIVEGRID_BASE_IDE: + import activegrid.server.deployment as deploymentlib import ProcessModelEditor + import DataModelEditor + import WsdlAgEditor + APP_LAST_LANGUAGE = "LastLanguage" + import activegrid.model.basedocmgr as basedocmgr + import activegrid.model.basemodel as basemodel + import PropertyService + from activegrid.server.toolsupport import GetTemplate + import activegrid.util.xmlutils as xmlutils + import activegrid.util.sysutils as sysutils + from SVNService import SVN_INSTALLED _ = wx.GetTranslation @@ -35,131 +53,241 @@ if wx.Platform == '__WXMSW__': _WINDOWS = True else: _WINDOWS = False - - + #---------------------------------------------------------------------------- # Constants #---------------------------------------------------------------------------- SPACE = 10 HALF_SPACE = 5 +PROJECT_EXTENSION = ".agp" + +# wxBug: the wxTextCtrl and wxChoice controls on Mac do not correctly size +# themselves with sizers, so we need to add a right border to the sizer to +# get the control to shrink itself to fit in the sizer. +MAC_RIGHT_BORDER = 0 +if wx.Platform == "__WXMAC__": + MAC_RIGHT_BORDER = 5 + + +PROJECT_KEY = "/AG_Projects" +PROJECT_DIRECTORY_KEY = "NewProjectDirectory" +NEW_PROJECT_DIRECTORY_DEFAULT = appdirs.documents_folder #---------------------------------------------------------------------------- -# XML Marshalling Methods +# Methods #---------------------------------------------------------------------------- -def load(fileObject): - return activegrid.util.xmlutils.defaultLoad(fileObject, knownTypes={"projectmodel" : ProjectModel}) +def getProjectKeyName(projectName, mode): + return "%s/%s/%s" % (PROJECT_KEY, projectName.replace(os.sep, '|'), mode) -def save(fileObject, projectModel): - activegrid.util.xmlutils.defaultSave(fileObject, projectModel, prettyPrint=True, knownTypes={"projectmodel" : ProjectModel}) + +def GetDocCallback(filepath): + """ Get the Document used by the IDE and the in-memory document model used by runtime engine """ + docMgr = wx.GetApp().GetDocumentManager() + + doc = docMgr.CreateDocument(filepath, docMgr.GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW) + if (doc == None): # already open + for d in docMgr.GetDocuments(): + if os.path.normcase(d.GetFilename()) == os.path.normcase(filepath): + doc = d + break + else: + projectService = wx.GetApp().GetService(ProjectService) + if projectService: + projectDocs = projectService.FindProjectByFile(filepath) + if projectDocs: + projectDoc = projectDocs[0] + projectService.AddProjectMapping(doc, projectDoc) + if hasattr(doc, "GetModel"): + projectService.AddProjectMapping(doc.GetModel(), projectDoc) + + + if doc and doc.GetDocumentTemplate().GetDocumentType() == WsdlAgEditor.WsdlAgDocument: + # get referenced wsdl doc instead + if os.path.isabs(doc.GetModel().filePath): # if absolute path, leave it alone + filepath = doc.GetModel().filePath + else: + filepath = doc.GetAppDocMgr().fullPath(doc.GetModel().filePath) # check relative to project homeDir + + if not os.path.isfile(filepath): + filepath = os.path.normpath(os.path.join(os.path.dirname(doc.GetFilename()), doc.GetModel().filePath)) # check relative to wsdlag file + + if not os.path.isfile(filepath): + filename = os.sep + os.path.basename(doc.GetModel().filePath) # check to see if in project file + filePaths = findDocumentMgr(doc).filePaths + for fp in filePaths: + if fp.endswith(filename): + filepath = fp + break + + doc = docMgr.CreateDocument(filepath, docMgr.GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW) + if (doc == None): # already open + for d in docMgr.GetDocuments(): + if os.path.normcase(d.GetFilename()) == os.path.normcase(filepath): + doc = d + break + else: + projectService = wx.GetApp().GetService(ProjectService) + if projectService: + projectDocs = projectService.FindProjectByFile(filepath) + if projectDocs: + projectDoc = projectDocs[0] + projectService.AddProjectMapping(doc, projectDoc) + if hasattr(doc, "GetModel"): + projectService.AddProjectMapping(doc.GetModel(), projectDoc) + + if doc: + docModel = doc.GetModel() + else: + docModel = None + + return doc, docModel + + +def findDocumentMgr(root): + projectService = wx.GetApp().GetService(ProjectService) + if projectService: + projectDoc = projectService.FindProjectFromMapping(root) + if projectDoc: + return projectDoc.GetModel() + + projectDoc = projectService.GetCurrentProject() + if not projectDoc: + return None + + if isinstance(root, wx.lib.docview.Document): + filepath = root.GetFilename() + elif hasattr(root, "fileName") and root.fileName: + filepath = root.fileName + else: + filepath = None + + if filepath: + if projectDoc.IsFileInProject(filepath): + return projectDoc.GetModel() + + projects = [] + openDocs = wx.GetApp().GetDocumentManager().GetDocuments() + for openDoc in openDocs: + if openDoc == projectDoc: + continue + if(isinstance(openDoc, ProjectDocument)): + if openDoc.IsFileInProject(filepath): + projects.append(openDoc) + + if projects: + if len(projects) == 1: + return projects[0].GetModel() + else: + choices = [os.path.basename(project.GetFilename()) for project in projects] + dlg = wx.SingleChoiceDialog(wx.GetApp().GetTopWindow(), _("'%s' found in more than one project.\nWhich project should be used for this operation?") % os.path.basename(filepath), _("Select Project"), choices, wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.OK|wx.CENTRE) + dlg.CenterOnParent() + projectDoc = None + if dlg.ShowModal() == wx.ID_OK: + i = dlg.GetSelection() + projectDoc = projects[i] + dlg.Destroy() + return projectDoc.GetModel() + return projectDoc.GetModel() + + return None + + +if not ACTIVEGRID_BASE_IDE: + basemodel.findGlobalDocumentMgr = findDocumentMgr #---------------------------------------------------------------------------- # Classes #---------------------------------------------------------------------------- -class ProjectModel: - __xmlname__ = "projectmodel" - __xmlrename__ = { "_files":"files"} - - - def __init__(self): - self._files = [] - - def initialize(self): - pass - - class ProjectDocument(wx.lib.docview.Document): - def __init__(self): + def __init__(self, model=None): wx.lib.docview.Document.__init__(self) - self._projectModel = ProjectModel() - + if model: + self.SetModel(model) + else: + self.SetModel(projectlib.Project()) # initial model used by "File | New... | Project" + self.GetModel().SetDocCallback(GetDocCallback) + + self._stageProjectFile = False + + + def __copy__(self): + model = copy.copy(self.GetModel()) + clone = ProjectDocument(model) + clone.SetFilename(self.GetFilename()) + return clone + + + def GetFirstView(self): + """ Bug: workaround. If user tries to open an already open project with main menu "File | Open...", docview.DocManager.OnFileOpen() silently returns None if project is already open. + And to the user, it appears as if nothing has happened. The user expects to see the open project. + This forces the project view to show the correct project. + """ + view = wx.lib.docview.Document.GetFirstView(self) + view.SetProject(self.GetFilename()) # ensure project is displayed in view + return view + def GetModel(self): return self._projectModel + + + def SetModel(self, model): + self._projectModel = model def OnCreate(self, path, flags): projectService = wx.GetApp().GetService(ProjectService) - if projectService.GetView(): + view = projectService.GetView() + if view: # view already exists, reuse # All project documents share the same view. - view = projectService.GetView() self.AddView(view) - if view.GetDocument(): + if view.GetDocument(): # All project documents need to share the same command processor, # to enable redo/undo of cross project document commands cmdProcessor = view.GetDocument().GetCommandProcessor() if cmdProcessor: self.SetCommandProcessor(cmdProcessor) - else: + else: # generate view view = self.GetDocumentTemplate().CreateView(self, flags) projectService.SetView(view) - return view def LoadObject(self, fileObject): - self._projectModel = activegrid.tool.ProjectEditor.load(fileObject) - self._projectModel._files = self.RelativeToAbsPath(self._projectModel._files) + self.SetModel(projectlib.load(fileObject)) + self.GetModel().SetDocCallback(GetDocCallback) return True def SaveObject(self, fileObject): - absPath = self._projectModel._files - self._projectModel._files = self.AbsToRelativePath(absPath) # temporarily change it to relative paths for saving - activegrid.tool.ProjectEditor.save(fileObject, self._projectModel) - self._projectModel._files = absPath # swap it back to absolute path + projectlib.save(fileObject, self.GetModel()) return True - def AbsToRelativePath(self, paths): - curPath = os.path.dirname(self.GetFilename()) - curPathLen = len(curPath) - - newFilePaths = [] - for path in paths: - if path.startswith(curPath): - path = "." + path[curPathLen:] # use relative path - if os.sep != '/': - path = path.replace(os.sep, '/', -1) # always save out with '/' as path separator for cross-platform compatibility. - else: - pass # use absolute path - newFilePaths.append(path) - return newFilePaths - - - def RelativeToAbsPath(self, paths): - newFilePaths = [] - for path in paths: - if path.startswith("."): # relative to project file - curPath = os.path.dirname(self.GetFilename()) - path = os.path.normpath(os.path.join(curPath, path)) - newFilePaths.append(path) - return newFilePaths - - - def OnOpenDocument(self, filename): - view = self.GetFirstView() - frame = view.GetFrame() + def OnOpenDocument(self, filePath): + projectService = wx.GetApp().GetService(ProjectService) + view = projectService.GetView() - if not os.path.exists(filename): + if not os.path.exists(filePath): wx.GetApp().CloseSplash() msgTitle = wx.GetApp().GetAppName() if not msgTitle: msgTitle = _("File Error") - wx.MessageBox(_("Could not find '%s'.") % filename, + wx.MessageBox(_("Could not find '%s'.") % filePath, msgTitle, wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP, - frame) + wx.GetApp().GetTopWindow()) return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed - fileObject = file(filename, 'r') + fileObject = file(filePath, 'r') try: self.LoadObject(fileObject) except: @@ -167,122 +295,644 @@ class ProjectDocument(wx.lib.docview.Document): msgTitle = wx.GetApp().GetAppName() if not msgTitle: msgTitle = _("File Error") - wx.MessageBox(_("Could not open '%s'. %s") % (wx.lib.docview.FileNameFromPath(filename), sys.exc_value), + wx.MessageBox(_("Could not open '%s'. %s") % (wx.lib.docview.FileNameFromPath(filePath), sys.exc_value), msgTitle, wx.OK | wx.ICON_EXCLAMATION | wx.STAY_ON_TOP, - frame) + wx.GetApp().GetTopWindow()) return True # if we return False, the Project View is destroyed, Service windows shouldn't be destroyed self.Modify(False) - self.SetFilename(filename, True) + self.SetFilename(filePath, True) view.AddProjectToView(self) self.SetDocumentModificationDate() self.UpdateAllViews() self._savedYet = True - view.Activate(True) + view.Activate() return True - - def AddFile(self, file): - return self.AddFiles([file]) + def AddFile(self, filePath, folderPath=None, type=None, name=None): + if type: + types = [type] + else: + types = None + if name: + names = [name] + else: + names = None + + return self.AddFiles([filePath], folderPath, types, names) - def AddFiles(self, files): - notAlreadyThereFiles = filter(lambda x: x not in self._projectModel._files, files) # Filter to the files that are not already in the project - if len(notAlreadyThereFiles) == 0: - self.UpdateAllViews(hint = ("select", self, files)) - return False + + def AddFiles(self, filePaths=None, folderPath=None, types=None, names=None, files=None): + # Filter out files that are not already in the project + if filePaths: + newFilePaths = [] + oldFilePaths = [] + for filePath in filePaths: + if self.GetModel().FindFile(filePath): + oldFilePaths.append(filePath) + else: + newFilePaths.append(filePath) + + projectService = wx.GetApp().GetService(ProjectService) + for i, filePath in enumerate(newFilePaths): + if types: + type = types[i] + else: + type = None + + if names: + name = names[i] + else: + name = projectService.FindNameDefault(filePath) + + if not folderPath: + folder = projectService.FindLogicalViewFolderDefault(filePath) + else: + folder = folderPath + + self.GetModel().AddFile(filePath, folder, type, name) + elif files: + newFilePaths = [] + oldFilePaths = [] + for file in files: + if self.GetModel().FindFile(file.filePath): + oldFilePaths.append(file.filePath) + else: + newFilePaths.append(file.filePath) + self.GetModel().AddFile(file=file) else: - self._projectModel._files = self._projectModel._files + notAlreadyThereFiles - self.UpdateAllViews(hint = ("add", self, notAlreadyThereFiles)) + return False + + self.AddNameSpaces(newFilePaths) + + self.UpdateAllViews(hint = ("add", self, newFilePaths, oldFilePaths)) + if len(newFilePaths): self.Modify(True) return True + else: + return False - def RemoveFile(self, file): - return self.RemoveFiles([file]) + def RemoveFile(self, filePath): + return self.RemoveFiles([filePath]) - def RemoveFiles(self, files): - for file in files: - self._projectModel._files.remove(file) - self.UpdateAllViews(hint = ("remove", self, files)) - self.Modify(True) - return True + def RemoveFiles(self, filePaths=None, files=None): + removedFiles = [] + + if files: + filePaths = [] + for file in files: + filePaths.append(file.filePath) + + for filePath in filePaths: + file = self.GetModel().FindFile(filePath) + if file: + self.GetModel().RemoveFile(file) + removedFiles.append(file.filePath) + + self.UpdateAllViews(hint = ("remove", self, removedFiles)) + if len(removedFiles): + self.Modify(True) + return True + else: + return False - def RenameFile(self, oldFile, newFile, isProject = False): + def RenameFile(self, oldFilePath, newFilePath, isProject = False): try: - if oldFile == newFile: + if oldFilePath == newFilePath: return False # projects don't have to exist yet, so not required to rename old file, # but files must exist, so we'll try to rename and allow exceptions to occur if can't. - if not isProject or (isProject and os.path.exists(oldFile)): - os.rename(oldFile, newFile) + if not isProject or (isProject and os.path.exists(oldFilePath)): + os.rename(oldFilePath, newFilePath) if isProject: documents = self.GetDocumentManager().GetDocuments() for document in documents: - if os.path.normcase(document.GetFilename()) == os.path.normcase(oldFile): # If the renamed document is open, update it - document.SetFilename(newFile) - document.SetTitle(wx.lib.docview.FileNameFromPath(newFile)) - document.UpdateAllViews(hint = ("rename", document, newFile)) + if os.path.normcase(document.GetFilename()) == os.path.normcase(oldFilePath): # If the renamed document is open, update it + document.SetFilename(newFilePath) + document.SetTitle(wx.lib.docview.FileNameFromPath(newFilePath)) + document.UpdateAllViews(hint = ("rename", self, oldFilePath, newFilePath)) else: - self.RemoveFile(oldFile) - self.AddFile(newFile) + self.UpdateFilePath(oldFilePath, newFilePath) documents = self.GetDocumentManager().GetDocuments() for document in documents: - if os.path.normcase(document.GetFilename()) == os.path.normcase(oldFile): # If the renamed document is open, update it - document.SetFilename(newFile, notifyViews = True) - document.UpdateAllViews(hint = ("rename", document, newFile)) + if os.path.normcase(document.GetFilename()) == os.path.normcase(oldFilePath): # If the renamed document is open, update it + document.SetFilename(newFilePath, notifyViews = True) + document.UpdateAllViews(hint = ("rename", self, oldFilePath, newFilePath)) return True except OSError, (code, message): msgTitle = wx.GetApp().GetAppName() if not msgTitle: msgTitle = _("File Error") - wx.MessageBox("Could not rename '%s'. '%s'" % (wx.lib.docview.FileNameFromPath(oldFile), message), + wx.MessageBox("Could not rename '%s'. '%s'" % (wx.lib.docview.FileNameFromPath(oldFilePath), message), msgTitle, wx.OK | wx.ICON_EXCLAMATION, - self.GetFirstView().GetFrame()) + wx.GetApp().GetTopWindow()) + return False + + + def MoveFile(self, file, newFolderPath): + return self.MoveFiles([file], newFolderPath) + + + def MoveFiles(self, files, newFolderPath): + filePaths = [] + isArray = isinstance(newFolderPath, type([])) + for i in range(len(files)): + if isArray: + files[i].logicalFolder = newFolderPath[i] + else: + files[i].logicalFolder = newFolderPath + filePaths.append(files[i].filePath) + + self.UpdateAllViews(hint = ("remove", self, filePaths)) + self.UpdateAllViews(hint = ("add", self, filePaths, [])) + self.Modify(True) + return True + + + def UpdateFilePath(self, oldFilePath, newFilePath): + file = self.GetModel().FindFile(oldFilePath) + self.RemoveFile(oldFilePath) + if file: + self.AddFile(newFilePath, file.logicalFolder, file.type, file.name) + else: + self.AddFile(newFilePath) + + + def RemoveInvalidPaths(self): + """Makes sure all paths project knows about are valid and point to existing files. Removes and returns list of invalid paths.""" + + invalidFileRefs = [] + + fileRefs = self.GetFileRefs() + + for fileRef in fileRefs: + if not os.path.exists(fileRef.filePath): + invalidFileRefs.append(fileRef) + + for fileRef in invalidFileRefs: + fileRefs.remove(fileRef) + + return [fileRef.filePath for fileRef in invalidFileRefs] + + def SetStageProjectFile(self): + self._stageProjectFile = True + + def ArchiveProject(self, zipdest, tmpdir=None, stagedir=None): + """Stages the application files in tmpdir, and zips the stagedir, creating a zipfile that has the projectname, in zipdest. Returns path to zipfile. Optionally, pass in stagedir and we assume the app is already staged at stagedir (we don't stage again in that case).""" + if not stagedir: + if not tmpdir: + raise AssertionError("'tmpdir' must be set when not passing 'stagedir' so we know where to stage the app") + stagedir = self.StageProject(tmpdir) + if os.path.exists(zipdest): + raise AssertionError("Cannot archive project, %s already exists" % zipdest) + fileutils.zip(zipdest, stagedir) + + return zipdest + + + def StageProject(self, tmpdir): + """ Copies all files that project knows about into staging location. Files that live outside of the project dir are copied into the root of the stage dir, and their recorded file path is updated. Files that live inside of the project dir keep their relative path. Generates .dpl file into staging dir. Returns path to staging dir.""" + + projname = self.GetProjectName() + stagedir = os.path.join(tmpdir, projname) + fileutils.remove(stagedir) + os.makedirs(stagedir) + + # remove invalid files from project + self.RemoveInvalidPaths() + + # required so relative paths are written correctly when .dpl file is + # generated below. + self.SetFilename(os.path.join(stagedir, + os.path.basename(self.GetFilename()))) + projectdir = self.GetModel().homeDir + + # Validate paths before actually copying, and populate a dict + # with src->dest so copying is easy. + # (fileDict: ProjectFile instance -> dest path (string)) + fileDict = self._ValidateFilePaths(projectdir, stagedir) + + # copy files to staging dir + self._StageFiles(fileDict) + + # it is unfortunate we require this. it would be nice if filepaths + # were only in the project + self._FixWsdlAgFiles(stagedir) + + # generate .dpl file + dplfilename = projname + deploymentlib.DEPLOYMENT_EXTENSION + dplfilepath = os.path.join(stagedir, dplfilename) + self.GenerateDeployment(dplfilepath, productionDeployment=True) + + if self._stageProjectFile: + # save project so we get the .agp file. not required for deployment + # but convenient if user wants to open the deployment in the IDE + agpfilename = projname + PROJECT_EXTENSION + agpfilepath = os.path.join(stagedir, agpfilename) + f = None + try: + f = open(agpfilepath, "w") + # setting homeDir correctly is required for the "figuring out + # relative paths" logic when saving the project + self.GetModel().homeDir = stagedir + projectlib.save(f, self.GetModel(), productionDeployment=True) + finally: + try: + f.close() + except: pass + + return stagedir + + + def _FixWsdlAgFiles(self, stagedir): + """For each wsdlag file in the stagedir: + Ensure the referenced wsdl file lives in root of stagedir. This + should be the case if wsdl is part of project (and staging has run). + If it is not at root of stagedir, copy it. Then update path in + wsdlag.""" + files = os.listdir(stagedir) + for f in files: + if f.endswith(WsdlAgEditor.WsdlAgDocument.WSDL_AG_EXT): + wsdlagpath = os.path.join(stagedir, f) + fileObject = None + mod = False + try: + fileObject = open(wsdlagpath) + serviceref = WsdlAgEditor.load(fileObject) + if hasattr(serviceref, "filePath") and serviceref.filePath: + mod = self.UpdateServiceRefFilePath(stagedir,serviceref) + finally: + try: + fileObject.close() + except: + pass + + # no need to save the file if we did not change anything + if not mod: continue + + # write the wsdlag file + fileObject = open(wsdlagpath) + try: + serviceref = WsdlAgEditor.save(fileObject, serviceref) + finally: + try: + fileObject.close() + except: + pass + + + def UpdateServiceRefFilePath(self, stagedir, serviceref): + """Returns True if serviceref.filePath has been updated, False otherwise.""" + if not os.path.exists(serviceref.filePath): + # should be an error? wrong place to + # validate that referenced file exists + # could print warning + return False + + # If the referenced file is in stagedir already, there's nothing to do + if fileutils.hasAncestorDir(serviceref.filePath, stagedir): return False + # The path points outside of stagedir. + + # Check if we already have the referenced wsdl file at root, should be + # the case if the referenced wsdl is part of project + # Copy it if we don't have it + relPath = os.path.basename(serviceref.filePath) + stagepath = os.path.join(stagedir, relPath) + if not os.path.exists(stagepath): + fileutils.copyFile(serviceref.filePath, stagepath) + + serviceref.filePath = relPath + + return True + + + def _StageFiles(self, fileDict): + """Copy files to staging directory, update filePath attr of project's ProjectFile instances.""" + + # fileDict: ProjectFile instance -> dest path (string) + + for fileRef, fileDest in fileDict.items(): + fileutils.copyFile(fileRef.filePath, fileDest) + fileRef.filePath = fileDest + + def _ValidateFilePaths(self, projectdir, stagedir): + """If paths validate, returns a dict mapping ProjectFile to destination path. Destination path is the path the file needs to be copied to for staging. If paths don't validate, throws an IOError. + With our current slightly simplistic staging algorithm, staging will not work iff the project has files outside of the projectdir with names (filename without path) that: + - match filenames of files living at the root of the project. + - are same as those of any other file that lives outside of the projectdir. + + We have this limitation because we move any file that lives outside of the project dir into the root of the stagedir (== copied project dir). We could make this smarter by either giving files unique names if we detect a collistion, or by creating some directory structure instead of putting all files from outside of the projectdir into the root of the stagedir (== copied projectdir).""" + + # ProjectFile instance -> dest path (string) + rtn = {} + + projectRootFiles = sets.Set() # live at project root + foreignFiles = sets.Set() # live outside of project + + fileRefsToDeploy = self.GetFileRefs() + + for fileRef in fileRefsToDeploy: + relPath = fileutils.getRelativePath(fileRef.filePath, projectdir) + filename = os.path.basename(fileRef.filePath) + if not relPath: # file lives outside of project dir... + + # do we have another file with the same name already? + if filename in foreignFiles: + raise IOError("More than one file with name \"%s\" lives outside of the project. These files need to have unique names" % filename) + foreignFiles.add(filename) + fileDest = os.path.join(stagedir, filename) + else: + # file lives somewhere within the project dir + fileDest = os.path.join(stagedir, relPath) + if not os.path.dirname(relPath): + projectRootFiles.add(filename) + + rtn[fileRef] = fileDest + + # make sure we won't collide with a file that lives at root of + # projectdir when moving files into project + for filename in foreignFiles: + if filename in projectRootFiles: + raise IOError("File outside of project, \"%s\", cannot have same name as file at project root" % filename) + + # REVIEW stoens@activegrid.com 19-Oct-05 -- + # We could also validate that user does not already have a .dpl file + # since we're going to generate one... + + return rtn + + + def RenameFolder(self, oldFolderPath, newFolderPath): + for file in self.GetModel()._files: + if file.logicalFolder == oldFolderPath: + file.logicalFolder = newFolderPath + self.UpdateAllViews(hint = ("rename folder", self, oldFolderPath, newFolderPath)) + self.Modify(True) + return True + def GetFiles(self): - return self._projectModel._files + return self.GetModel().filePaths + + + def GetFileRefs(self): + return self.GetModel().findAllRefs() + + + def SetFileRefs(self, fileRefs): + return self.GetModel().setRefs(fileRefs) def IsFileInProject(self, filename): - return filename in self.GetFiles() + return self.GetModel().FindFile(filename) + + + def GetAppInfo(self): + return self.GetModel().GetAppInfo() + + + def GetAppDocMgr(self): + return self.GetModel() + + + def GetProjectName(self): + return os.path.splitext(os.path.basename(self.GetFilename()))[0] + + + def GetDeploymentFilepath(self): + projectName = self.GetProjectName() + return os.path.join(self.GetModel().homeDir, projectName + "RunTime_tmp" + deploymentlib.DEPLOYMENT_EXTENSION) + + + def GenerateDeployment(self, deployFilepath=None, preview=False, productionDeployment=False): + if ACTIVEGRID_BASE_IDE: + return + + def FindOpenDoc(filePath): + openDocs = wx.GetApp().GetDocumentManager().GetDocuments() + for openDoc in openDocs: + if openDoc.GetFilename() == filePath: + return openDoc + return None + + if not deployFilepath: + deployFilepath = self.GetDeploymentFilepath() + + deployment = deploymentlib.Deployment(deployFilepath) + + defaultFlagsNoView = wx.GetApp().GetDocumentManager().GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW + self.GetAppInfo().CopyToDeployment(deployment) + + for file in self.GetModel()._files: + if not file.type: + continue + elif file.type == basedocmgr.FILE_TYPE_SERVICE: # set serviceRefs + doc = wx.GetApp().GetDocumentManager().CreateDocument(file.filePath, flags=defaultFlagsNoView) + if (doc == None): # already open + doc = FindOpenDoc(file.filePath) + if doc: + serviceRef = doc.GetModel() + if serviceRef: + documentRef = copy.copy(serviceRef) + deployment.serviceRefs.append(documentRef) + + if not productionDeployment: + # filePath should point to location of wsdl file + # wsdlag filePath points to relative path to wsdl file from wsdlag location + # but deployment needs relative path from deployment location, so here's the conversion + curDir = os.path.dirname(self.GetFilename()) + os.sep + filePath = file.document.fileName + if (filePath == None): + raise Exception("Cannot find file \"%s\"" % file.filePath) + if filePath.startswith(curDir): + filePath = filePath[len(curDir):] + if os.sep != '/': + filePath = filePath.replace(os.sep, "/") + documentRef.filePath = filePath + + documentRef.document = file.document + + if serviceRef.serviceType == deploymentlib.SERVICE_DATABASE and serviceRef.databaseService: + dataSourceService = wx.GetApp().GetService(DataModelEditor.DataSourceService) + ds = dataSourceService.getDataSource(serviceRef.databaseService.datasourceName) + if ds: + found = False + for d in deployment.dataSources: + if d.name == ds.name: + found = True + break + if not found: + deployment.dataSources.append(ds) + else: + curDir = os.path.dirname(self.GetFilename()) + os.sep + filePath = file.filePath + if filePath.startswith(curDir): + filePath = filePath[len(curDir):] + if os.sep != '/': + filePath = filePath.replace(os.sep, "/") + + if file.type == basedocmgr.FILE_TYPE_XFORM: + documentRef = deploymentlib.XFormRef() + deployment.xformRefs.append(documentRef) + elif file.type == basedocmgr.FILE_TYPE_PROCESS: + documentRef = deploymentlib.ProcessRef() + deployment.processRefs.append(documentRef) + elif file.type == basedocmgr.FILE_TYPE_SCHEMA: + # set schemaRefs + documentRef = deploymentlib.SchemaRef() + deployment.schemaRefs.append(documentRef) + + # set dataSources + doc = wx.GetApp().GetDocumentManager().CreateDocument(file.filePath, flags=defaultFlagsNoView) + if (doc == None): # already open + doc = FindOpenDoc(file.filePath) + if doc: + dataSourceService = wx.GetApp().GetService(DataModelEditor.DataSourceService) + ds = dataSourceService.getDataSource(doc.GetModel().getDefaultDataSourceName()) + if ds: + found = False + for d in deployment.dataSources: + if d.name == ds.name: + found = True + break + if not found: + deployment.dataSources.append(ds) + + # set keyServices + keyServices = doc.GetModel().keyServices + for keyService in keyServices: + # add default key service to deployment + if not productionDeployment: + mainModuleDir = sysutils.mainModuleDir + else: + mainModuleDir = sysutils.MAINMODULE_DIR_VAR + wsdlFullPath = os.path.join(mainModuleDir, "..", "wsdl", DataModelEditor.DEFAULT_KEYSERVICE_WSDL_FILENAME) + keyServiceRef = deploymentlib.ServiceRef(filePath=wsdlFullPath) + deployment.serviceRefs.append(keyServiceRef) + + keyServiceRef.name = keyService + keyServiceRef.serviceType = deploymentlib.SERVICE_LOCAL + keyServiceRef.localService = deploymentlib.LocalService() + if keyService == DataModelEditor.DEFAULT_KEYSERVICE: + keyServiceRef.filePath = wsdlFullPath + keyServiceRef.localServiceClassName = DataModelEditor.DEFAULT_KEYSERVICE_CLASSNAME + + + elif file.type == basedocmgr.FILE_TYPE_SKIN: + documentRef = deploymentlib.SkinRef(deployment) + deployment.skinref = documentRef + elif file.type == basedocmgr.FILE_TYPE_IDENTITY: + documentRef = deploymentlib.IdentityRef() + deployment.identityRefs.append(documentRef) + else: + continue + + documentRef.name = file.name + documentRef.filePath = filePath + doc = FindOpenDoc(file.filePath) + if doc and hasattr(doc, 'GetModel'): + documentRef.document = doc.GetModel() + if isinstance(documentRef, deploymentlib.XFormRef): + doc.GetModel().linkDeployment(deployment, deployment.loader) + + if preview: + deployment.initialize() # used in preview only + + if 0: # preview: # setPrototype not working, commented this out + deploymentlib._deploymentCache.setPrototype(deployment.fileName, deployment) + else: + deploymentlib.saveThroughCache(deployment.fileName, deployment) + + return deployFilepath + + + def AddNameSpaces(self, filePaths): + """ Add any new wsdl namespaces to bpel files """ + """ Add any new schema namespaces to wsdl files """ + if ACTIVEGRID_BASE_IDE: + return + + serviceRefs = self.GetAppDocMgr().allServiceRefs # wsdl + + processRefs = self.GetAppDocMgr().findRefsByFileType(basedocmgr.FILE_TYPE_PROCESS) # bpel + if processRefs and serviceRefs: + for processRef in processRefs: + processDoc = processRef._GetDoc() + process = processDoc.GetModel() + + modified = False + for serviceRef in serviceRefs: + wsdl = serviceRef.document + if (wsdl.fileName in filePaths + or serviceRef.filePath in filePaths): + wsdlLongNS = wsdl.targetNamespace + wsdlShortNS = self.GetAppDocMgr().findShortNS(wsdlLongNS) + if not wsdlShortNS: + wsdlShortNS = xmlutils.genShortNS(process, wsdlLongNS) + xmlutils.addNSAttribute(process, wsdlShortNS, wsdlLongNS) + modified = True + if modified: + processDoc.OnSaveDocument(processDoc.GetFilename()) + + schemaRefs = self.GetAppDocMgr().findRefsByFileType(basedocmgr.FILE_TYPE_SCHEMA) + if schemaRefs and serviceRefs: + for serviceRef in serviceRefs: + wsdl = serviceRef.document + wsdlDoc = serviceRef.ideDocument + + modified = False + for schemaRef in schemaRefs: + schema = schemaRef.document + if schema.fileName in filePaths: + schemaLongNS = schema.targetNamespace + schemaShortNS = self.GetAppDocMgr().findShortNS(schemaLongNS) + if not schemaShortNS: + schemaShortNS = xmlutils.genShortNS(process, schemaLongNS) + xmlutils.addNSAttribute(wsdl, schemaShortNS, schemaLongNS) + modified = True + if modified: + wsdlDoc.OnSaveDocument(wsdlDoc.GetFilename()) class NewProjectWizard(Wizard.BaseWizard): WIZTITLE = _("New Project Wizard") + def __init__(self, parent): self._parent = parent self._fullProjectPath = None Wizard.BaseWizard.__init__(self, parent, self.WIZTITLE) self._projectLocationPage = self.CreateProjectLocation(self) wx.wizard.EVT_WIZARD_PAGE_CHANGING(self, self.GetId(), self.OnWizPageChanging) - - - def CreateProjectLocation(self,wizard): + + + def CreateProjectLocation(self,wizard): page = Wizard.TitledWizardPage(wizard, _("Project File Location")) page.GetSizer().Add(wx.StaticText(page, -1, _("\nSelect the directory and filename for the project.\n\n"))) - self._projectName, self._dirCtrl, sizer, self._fileValidation = UICommon.CreateDirectoryControl(page, _("File Name:"), _("Directory:"), _("agp"), startingDirectory=os.getcwd()) + self._projectName, self._dirCtrl, sizer, self._fileValidation = UICommon.CreateDirectoryControl(page, fileExtension="agp", appDirDefaultStartDir=True) page.GetSizer().Add(sizer, 1, flag=wx.EXPAND) wizard.Layout() wizard.FitToPage(page) - return page + return page def RunWizard(self, existingTables = None, existingRelationships = None): status = wx.wizard.Wizard.RunWizard(self, self._projectLocationPage) if status: + wx.ConfigBase_Get().Write(PROJECT_DIRECTORY_KEY, self._dirCtrl.GetValue()) docManager = wx.GetApp().GetTopWindow().GetDocumentManager() if os.path.exists(self._fullProjectPath): # What if the document is already open and we're overwriting it? @@ -296,8 +946,9 @@ class NewProjectWizard(Wizard.BaseWizard): for template in docManager.GetTemplates(): if template.GetDocumentType() == ProjectDocument: doc = template.CreateDocument(self._fullProjectPath, flags = wx.lib.docview.DOC_NEW) - doc.OnSaveDocument(self._fullProjectPath) - view = doc.GetFirstView() + doc.OnSaveDocument(self._fullProjectPath) + projectService = wx.GetApp().GetService(ProjectService) + view = projectService.GetView() view.AddProjectToView(doc) break @@ -308,14 +959,13 @@ class NewProjectWizard(Wizard.BaseWizard): def OnWizPageChanging(self, event): if event.GetDirection(): # It's going forwards if event.GetPage() == self._projectLocationPage: - if not self._fileValidation(): + if not self._fileValidation(noFirstCharDigit=True): event.Veto() - return - self._fullProjectPath = os.path.join(self._dirCtrl.GetValue(),UICommon.MakeNameEndInExtension(self._projectName.GetValue(),'.agp')) - - - - def OnShowCreatePages(self): + return + self._fullProjectPath = os.path.join(self._dirCtrl.GetValue(),UICommon.MakeNameEndInExtension(self._projectName.GetValue(), PROJECT_EXTENSION)) + + + def OnShowCreatePages(self): self.Hide() import DataModelEditor requestedPos = self.GetPositionTuple() @@ -327,14 +977,17 @@ class NewProjectWizard(Wizard.BaseWizard): self._schemaName.SetValue(wiz.GetSchemaFileName()) wiz.Destroy() self.Show(True) - + class ProjectTemplate(wx.lib.docview.DocTemplate): def CreateDocument(self, path, flags): if path: - return wx.lib.docview.DocTemplate.CreateDocument(self, path, flags) + doc = wx.lib.docview.DocTemplate.CreateDocument(self, path, flags) + if path: + doc.GetModel()._projectDir = os.path.dirname(path) + return doc else: wiz = NewProjectWizard(wx.GetApp().GetTopWindow()) wiz.RunWizard() @@ -345,102 +998,198 @@ class ProjectTemplate(wx.lib.docview.DocTemplate): class ProjectAddFilesCommand(wx.lib.docview.Command): - def __init__(self, projectDoc, files): + def __init__(self, projectDoc, filePaths, folderPath=None, types=None, names=None): wx.lib.docview.Command.__init__(self, canUndo = True) self._projectDoc = projectDoc - self._files = files + self._allFilePaths = filePaths + self._folderPath = folderPath + self._types = types + self._names = names + + if not self._types: + self._types = [] + projectService = wx.GetApp().GetService(ProjectService) + for filePath in self._allFilePaths: + self._types.append(projectService.FindFileTypeDefault(filePath)) + + # list of files that will really be added + self._newFiles = [] + for filePath in self._allFilePaths: + if not projectDoc.GetModel().FindFile(filePath): + self._newFiles.append(filePath) def GetName(self): - if len(self._files) == 1: - return _("Add File %s") % os.path.basename(self._files[0]) + if len(self._allFilePaths) == 1: + return _("Add File %s") % os.path.basename(self._allFilePaths[0]) else: return _("Add Files") def Do(self): - return self._projectDoc.AddFiles(self._files) + return self._projectDoc.AddFiles(self._allFilePaths, self._folderPath, self._types, self._names) def Undo(self): - return self._projectDoc.RemoveFiles(self._files) + return self._projectDoc.RemoveFiles(self._newFiles) class ProjectRemoveFilesCommand(wx.lib.docview.Command): - def __init__(self, files): + def __init__(self, projectDoc, files): wx.lib.docview.Command.__init__(self, canUndo = True) + self._projectDoc = projectDoc self._files = files def GetName(self): if len(self._files) == 1: - return _("Remove File %s") % os.path.basename((self._files[0])[1]) + return _("Remove File %s") % os.path.basename(self._files[0].filePath) else: return _("Remove Files") def Do(self): - status = False - projects = [] - for data in self._files: - proj, filename = data - if proj not in projects: - projects.append(proj) - for project in projects: - files = [] - for data in self._files: - proj, filename = data - if project == proj: - files.append(filename) - status = project.RemoveFiles(files) or status - return status + return self._projectDoc.RemoveFiles(files=self._files) def Undo(self): - status = False - projects = [] - for data in self._files: - proj, filename = data - if proj not in projects: - projects.append(proj) - for project in projects: - files = [] - for data in self._files: - proj, filename = data - if project == proj: - files.append(filename) - status = project.AddFiles(files) or status - return status - + return self._projectDoc.AddFiles(files=self._files) + + class ProjectRenameFileCommand(wx.lib.docview.Command): - def __init__(self, projectDoc, oldFile, newFile, isProject = False): + def __init__(self, projectDoc, oldFilePath, newFilePath, isProject = False): wx.lib.docview.Command.__init__(self, canUndo = True) self._projectDoc = projectDoc - self._oldFile = oldFile - self._newFile = newFile + self._oldFilePath = oldFilePath + self._newFilePath = newFilePath self._isProject = isProject def GetName(self): - return _("Rename File %s to %s") % (os.path.basename(self._oldFile), os.path.basename(self._newFile)) + return _("Rename File %s to %s") % (os.path.basename(self._oldFilePath), os.path.basename(self._newFilePath)) def Do(self): - return self._projectDoc.RenameFile(self._oldFile, self._newFile, self._isProject) + return self._projectDoc.RenameFile(self._oldFilePath, self._newFilePath, self._isProject) def Undo(self): - return self._projectDoc.RenameFile(self._newFile, self._oldFile, self._isProject) + return self._projectDoc.RenameFile(self._newFilePath, self._oldFilePath, self._isProject) -class ProjectTreeCtrl(wx.TreeCtrl): +class ProjectRenameFolderCommand(wx.lib.docview.Command): + def __init__(self, doc, oldFolderPath, newFolderPath): + wx.lib.docview.Command.__init__(self, canUndo = True) + self._doc = doc + self._oldFolderPath = oldFolderPath + self._newFolderPath = newFolderPath + + + def GetName(self): + return _("Rename Folder %s to %s") % (os.path.basename(self._oldFolderPath), os.path.basename(self._newFolderPath)) + + + def Do(self): + return self._doc.RenameFolder(self._oldFolderPath, self._newFolderPath) + + + def Undo(self): + return self._doc.RenameFolder(self._newFolderPath, self._oldFolderPath) +class ProjectAddFolderCommand(wx.lib.docview.Command): + def __init__(self, view, doc, folderpath): + wx.lib.docview.Command.__init__(self, canUndo = True) + self._doc = doc + self._view = view + self._folderpath = folderpath + + + def GetName(self): + return _("Add Folder %s") % (os.path.basename(self._folderpath)) + + + def Do(self): + if self._view.GetDocument() != self._doc: + return True + status = self._view.AddFolder(self._folderpath) + if status: + self._view._treeCtrl.UnselectAll() + item = self._view._treeCtrl.FindFolder(self._folderpath) + self._view._treeCtrl.SelectItem(item) + return status + + + def Undo(self): + if self._view.GetDocument() != self._doc: + return True + return self._view.DeleteFolder(self._folderpath) + + +class ProjectRemoveFolderCommand(wx.lib.docview.Command): + def __init__(self, view, doc, folderpath): + wx.lib.docview.Command.__init__(self, canUndo = True) + self._doc = doc + self._view = view + self._folderpath = folderpath + + + def GetName(self): + return _("Remove Folder %s") % (os.path.basename(self._folderpath)) + + + def Do(self): + if self._view.GetDocument() != self._doc: + return True + return self._view.DeleteFolder(self._folderpath) + + + def Undo(self): + if self._view.GetDocument() != self._doc: + return True + status = self._view.AddFolder(self._folderpath) + if status: + self._view._treeCtrl.UnselectAll() + item = self._view._treeCtrl.FindFolder(self._folderpath) + self._view._treeCtrl.SelectItem(item) + return status + + +class ProjectMoveFilesCommand(wx.lib.docview.Command): + + def __init__(self, doc, files, folderPath): + wx.lib.docview.Command.__init__(self, canUndo = True) + self._doc = doc + self._files = files + self._newFolderPath = folderPath + + self._oldFolderPaths = [] + for file in self._files: + self._oldFolderPaths.append(file.logicalFolder) + + + def GetName(self): + if len(self._files) == 1: + return _("Move File %s") % os.path.basename(self._files[0].filePath) + else: + return _("Move Files") + + + def Do(self): + return self._doc.MoveFiles(self._files, self._newFolderPath) + + + def Undo(self): + return self._doc.MoveFiles(self._files, self._oldFolderPaths) + + +class ProjectTreeCtrl(wx.TreeCtrl): + #---------------------------------------------------------------------------- # Overridden Methods #---------------------------------------------------------------------------- @@ -461,7 +1210,7 @@ class ProjectTreeCtrl(wx.TreeCtrl): print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName iconIndex = iconList.AddIcon(icon) self._iconIndexLookup.append((template, iconIndex)) - + icon = getBlankIcon() if icon.GetHeight() != 16 or icon.GetWidth() != 16: icon.SetHeight(16) @@ -469,64 +1218,157 @@ class ProjectTreeCtrl(wx.TreeCtrl): if wx.GetApp().GetDebug(): print "Warning: getBlankIcon isn't 16x16, not crossplatform" self._blankIconIndex = iconList.AddIcon(icon) + + icon = getFolderClosedIcon() + if icon.GetHeight() != 16 or icon.GetWidth() != 16: + icon.SetHeight(16) + icon.SetWidth(16) + if wx.GetApp().GetDebug(): + print "Warning: getFolderIcon isn't 16x16, not crossplatform" + self._folderClosedIconIndex = iconList.AddIcon(icon) + + icon = getFolderOpenIcon() + if icon.GetHeight() != 16 or icon.GetWidth() != 16: + icon.SetHeight(16) + icon.SetWidth(16) + if wx.GetApp().GetDebug(): + print "Warning: getFolderIcon isn't 16x16, not crossplatform" + self._folderOpenIconIndex = iconList.AddIcon(icon) + self.AssignImageList(iconList) def OnCompareItems(self, item1, item2): - return cmp(self.GetItemText(item1).lower(), self.GetItemText(item2).lower()) + item1IsFolder = (self.GetPyData(item1) == None) + item2IsFolder = (self.GetPyData(item2) == None) + if (item1IsFolder == item2IsFolder): # if both are folders or both not + return cmp(self.GetItemText(item1).lower(), self.GetItemText(item2).lower()) + elif item1IsFolder and not item2IsFolder: # folders sort above non-folders + return -1 + elif not item1IsFolder and item2IsFolder: # folders sort above non-folders + return 1 + + def AppendFolder(self, parent, folderName): + item = wx.TreeCtrl.AppendItem(self, parent, folderName) + self.SetItemImage(item, self._folderClosedIconIndex, wx.TreeItemIcon_Normal) + self.SetItemImage(item, self._folderOpenIconIndex, wx.TreeItemIcon_Expanded) + self.SetPyData(item, None) + return item - def AppendItem(self, parent, filepath): - item = wx.TreeCtrl.AppendItem(self, parent, filepath) + + def AppendItem(self, parent, filename, file): + item = wx.TreeCtrl.AppendItem(self, parent, filename) found = False - template = wx.GetApp().GetDocumentManager().FindTemplateForPath(filepath) - if not template and parent == self.GetRootItem(): # If the parent is a root it's a new project - template = wx.GetApp().GetDocumentManager().FindTemplateForPath('.agp') + template = wx.GetApp().GetDocumentManager().FindTemplateForPath(filename) if template: for t, iconIndex in self._iconIndexLookup: if t is template: self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Normal) self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Expanded) - self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Selected) +## self.SetItemImage(item, iconIndex, wx.TreeItemIcon_Selected) found = True break if not found: self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Normal) self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Expanded) - self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Selected) +## self.SetItemImage(item, self._blankIconIndex, wx.TreeItemIcon_Selected) + self.SetPyData(item, file) + return item - #---------------------------------------------------------------------------- - # Client Data - #---------------------------------------------------------------------------- - - def SetData(self, item, longFilename, projectDoc=None): - self.SetPyData(item, (longFilename, projectDoc)) - - - def GetData(self, item): - """ returns longFilename and optional - """ - data = self.GetPyData(item) - if not data: - return (None, None) - return data + def AddFolder(self, folderPath): + folderItems = [] + + if folderPath != None: + folderTree = folderPath.split('/') + + item = self.GetRootItem() + for folderName in folderTree: + found = False + + (child, cookie) = self.GetFirstChild(item) + while child.IsOk(): + file = self.GetPyData(child) + if file: + pass + else: # folder + if self.GetItemText(child) == folderName: + item = child + found = True + break + (child, cookie) = self.GetNextChild(item, cookie) + + if not found: + item = self.AppendFolder(item, folderName) + folderItems.append(item) + return folderItems + - def GetLongFilename(self, item): - return self.GetData(item)[0] + def FindItem(self, filePath, parentItem=None): + if not parentItem: + parentItem = self.GetRootItem() + + (child, cookie) = self.GetFirstChild(parentItem) + while child.IsOk(): + file = self.GetPyData(child) + if file: + if file.filePath == filePath: + return child + else: # folder + result = self.FindItem(filePath, child) # do recursive call + if result: + return result + (child, cookie) = self.GetNextChild(parentItem, cookie) + + return None - def GetProjectDoc(self, item): - return self.GetData(item)[1] + def FindFolder(self, folderPath): + if folderPath != None: + folderTree = folderPath.split('/') + + item = self.GetRootItem() + for folderName in folderTree: + found = False + + (child, cookie) = self.GetFirstChild(item) + while child.IsOk(): + file = self.GetPyData(child) + if file: + pass + else: # folder + if self.GetItemText(child) == folderName: + item = child + found = True + break + (child, cookie) = self.GetNextChild(item, cookie) + + if found: + return item + + return None -class ProjectView(wx.lib.docview.View): + def FindClosestFolder(self, x, y): + item, flags = self.HitTest((x,y)) + if item: + file = self.GetPyData(item) + if file: + item = self.GetItemParent(item) + return item + return item + return None + +class ProjectView(wx.lib.docview.View): + LOGICAL_MODE = "logical" + PHYSICAL_MODE = "physical" #---------------------------------------------------------------------------- # Overridden methods @@ -534,10 +1376,18 @@ class ProjectView(wx.lib.docview.View): def __init__(self, service = None): wx.lib.docview.View.__init__(self) - self._service = service # not used, but kept to match other Services + # self._service = service # not used, but kept to match other Services + self._projectChoice = None + self._logicalBtn = None + self._physicalBtn = None self._treeCtrl = None self._editingSoDontKillFocus = False self._checkEditMenu = True + self._loading = False # flag to not to try to saving state of folders while it is loading + + + def GetDocumentManager(self): # Overshadow this since the superclass uses the view._viewDocument attribute directly, which the project editor doesn't use since it hosts multiple docs + return wx.GetApp().GetDocumentManager() def Destroy(self): @@ -548,43 +1398,15 @@ class ProjectView(wx.lib.docview.View): def GetDocument(self): - if not self._treeCtrl: + if not self._projectChoice: return None - - items = self._treeCtrl.GetSelections() - if not items: # No selection, so just return first project - item = self._treeCtrl.GetFirstVisibleItem() - if item.IsOk(): - return self._GetItemProject(item) - else: - return None - - for item in items: - project = self._GetItemProject(item) - if project: - return project - - return None - - - def GetDocumentManager(self): # Overshadow this since the superclass uses the view._viewDocument attribute directly, which the project editor doesn't use since it hosts multiple docs - return wx.GetApp().GetDocumentManager() + selItem = self._projectChoice.GetSelection() + if selItem == wx.NOT_FOUND: + return None - def OnChangeFilename(self): - if self.GetFrame(): - title = _("Projects") - if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI and wx.GetApp().GetAppName(): - title = title + " - " + wx.GetApp().GetAppName() - self.GetFrame().SetTitle(title) - project = self.GetDocument() - if project: - projectItem = self._GetProjectItem(project) - name = self._treeCtrl.GetItemText(self._GetProjectItem(project)) - name2 = self._MakeProjectName(project) - if name != name2: - self._treeCtrl.SetItemText(projectItem, name2) - self._treeCtrl.SortChildren(self._treeCtrl.GetRootItem()) + document = self._projectChoice.GetClientData(selItem) + return document def Activate(self, activate = True): @@ -604,6 +1426,7 @@ class ProjectView(wx.lib.docview.View): self._embeddedWindow = wx.GetApp().GetTopWindow().GetEmbeddedWindow(wx.lib.pydocview.EMBEDDED_WINDOW_TOPLEFT) self.SetFrame(self._embeddedWindow) frame = self._embeddedWindow + wx.EVT_SIZE(frame, self.OnSize) else: self._embeddedWindow = None pos = config.ReadInt("ProjectFrameXLoc", -1), config.ReadInt("ProjectFrameYLoc", -1) @@ -623,17 +1446,48 @@ class ProjectView(wx.lib.docview.View): if config.ReadInt("ProjectFrameMaximized", False): frame.Maximize(True) - sizer = wx.BoxSizer() - self._treeCtrl = ProjectTreeCtrl(frame, -1, style = wx.TR_HIDE_ROOT | wx.TR_HAS_BUTTONS | wx.TR_EDIT_LABELS | wx.TR_DEFAULT_STYLE | wx.TR_MULTIPLE) + panel = wx.Panel(frame, -1) + + sizer = wx.BoxSizer(wx.VERTICAL) + + butSizer = wx.BoxSizer(wx.HORIZONTAL) + + self._projectChoice = wx.Choice(panel, -1) + panel.Bind(wx.EVT_CHOICE, self.OnProjectSelect, self._projectChoice) + w, h = self._projectChoice.GetSize() + + self._logicalBtn = wx.lib.buttons.GenBitmapToggleButton(panel, -1, getLogicalModeOffBitmap(), size=(h,h)) + self._logicalBtn.SetBitmapSelected(getLogicalModeOnBitmap()) + self._logicalBtn.SetToggle(True) + self._logicalBtn.SetToolTipString(_("View Files by Logical Groups")) + panel.Bind(wx.EVT_BUTTON, self.OnSelectMode, self._logicalBtn) + self._physicalBtn = wx.lib.buttons.GenBitmapToggleButton(panel, -1, getPhysicalModeOffBitmap(), size=(h,h)) + self._physicalBtn.SetBitmapSelected(getPhysicalModeOnBitmap()) + self._physicalBtn.SetToolTipString(_("View Files by Physical Disk Layout")) + panel.Bind(wx.EVT_BUTTON, self.OnSelectMode, self._physicalBtn) + + butSizer.Add(self._projectChoice, 1, wx.EXPAND) + butSizer.Add(self._logicalBtn, 0) + butSizer.Add(self._physicalBtn, 0) + sizer.Add(butSizer, 0, wx.EXPAND) + + self._treeCtrl = ProjectTreeCtrl(panel, -1, style = wx.TR_HIDE_ROOT | wx.TR_HAS_BUTTONS | wx.TR_EDIT_LABELS | wx.TR_DEFAULT_STYLE | wx.TR_MULTIPLE | wx.TR_EXTENDED) self._treeCtrl.AddRoot(_("Projects")) wx.EVT_TREE_BEGIN_DRAG(self._treeCtrl, self._treeCtrl.GetId(), self.OnBeginDrag) wx.EVT_TREE_END_DRAG(self._treeCtrl, self._treeCtrl.GetId(), self.OnEndDrag) - if self._embeddedWindow: - sizer.Add(self._treeCtrl) - sizer.Fit(frame) + sizer.Add(self._treeCtrl, 1, wx.EXPAND|wx.BOTTOM, HALF_SPACE) # allow space for embedded window resize-sash + else: + sizer.Add(self._treeCtrl, 1, wx.EXPAND) + panel.SetSizer(sizer) + + sizer = wx.BoxSizer(wx.VERTICAL) + + if wx.GetApp().IsMDI(): + sizer.Add(panel, 1, wx.EXPAND|wx.BOTTOM, 1) # wx.Bug: without bottom margin, can't resize embedded window else: - sizer.Add(self._treeCtrl, 1, wx.EXPAND, 0) + sizer.Add(panel, 1, wx.EXPAND) + frame.SetSizer(sizer) frame.Layout() self.Activate() @@ -649,56 +1503,76 @@ class ProjectView(wx.lib.docview.View): wx.EVT_TREE_BEGIN_LABEL_EDIT(self._treeCtrl, self._treeCtrl.GetId(), self.OnBeginLabelEdit) wx.EVT_TREE_END_LABEL_EDIT(self._treeCtrl, self._treeCtrl.GetId(), self.OnEndLabelEdit) wx.EVT_RIGHT_DOWN(self._treeCtrl, self.OnRightClick) + wx.EVT_LEFT_DOWN(self._treeCtrl, self.OnLeftClick) wx.EVT_KEY_DOWN(self._treeCtrl, self.OnKeyPressed) + wx.EVT_TREE_ITEM_COLLAPSED(self._treeCtrl, self._treeCtrl.GetId(), self.SaveFolderState) + wx.EVT_TREE_ITEM_EXPANDED(self._treeCtrl, self._treeCtrl.GetId(), self.SaveFolderState) # wx.EVT_COMMAND_RIGHT_CLICK(self._treeCtrl, self._treeCtrl.GetId(), self.OnRightClick) # wxBug: This isn't working for some reason - # drag-and-drop support - dt = ProjectFileDropTarget(self) - self._treeCtrl.SetDropTarget(dt) + # drag-and-drop support + dt = ProjectFileDropTarget(self) + self._treeCtrl.SetDropTarget(dt) + + return True + + + def OnSelectMode(self, event): + btn = event.GetEventObject() + down = event.GetIsDown() + if btn == self._logicalBtn: + self._physicalBtn.SetToggle(not down) + else: # btn == self._physicalBtn: + self._logicalBtn.SetToggle(not down) + self.LoadProject(self.GetDocument()) + + + def GetMode(self): + if not self._physicalBtn.up: + return ProjectView.PHYSICAL_MODE + else: # elif self._logicalBtn.GetValue(): + return ProjectView.LOGICAL_MODE + - return True + def OnProjectSelect(self, event=None): + self.LoadProject(self.GetDocument()) + if self.GetDocument(): + filename = self.GetDocument().GetFilename() + else: + filename = '' + self._projectChoice.SetToolTipString(filename) + + + def OnSize(self, event): + event.Skip() + wx.CallAfter(self.GetFrame().Layout) def OnBeginDrag(self, event): + if self.GetMode() == ProjectView.PHYSICAL_MODE: + return + item = event.GetItem() if item.IsOk(): - if item == self._treeCtrl.GetRootItem(): - return - self._draggingItem = item - event.Allow() - + self._draggingItems = [] + for item in self._treeCtrl.GetSelections(): + if self._IsItemFile(item): + self._draggingItems.append(item) + if len(self._draggingItems): + event.Allow() + def OnEndDrag(self, event): item = event.GetItem() - if item.IsOk(): - # don't allow object to be dragged to itself - if item == self._draggingItem: - return - - rootItem = self._treeCtrl.GetRootItem() - - # don't let object replace root view - if item == rootItem: - wx.MessageBox(_("Cannot replace root view with item.")) - return - - # don't allow object to be dragged to a direct descendant - ancestor = self._treeCtrl.GetItemParent(item) - while ancestor != rootItem: - if ancestor == self._draggingItem: - wx.MessageBox(_("Cannot make item direct descendant of self.")) - return - else: - ancestor = self._treeCtrl.GetItemParent(ancestor) - - if self._treeCtrl.GetItemParent(item) == self._treeCtrl.GetItemParent(self._draggingItem): - # put it in same folder as it was originally, no-op. - return - if item == self._treeCtrl.GetItemParent(self._draggingItem): - # put it in same folder as it was originally, no-op. - return + if item.IsOk(): + files = [] + for ditem in self._draggingItems: + file = self._GetItemFile(ditem) + if file not in files: + files.append(file) - self.GetDocument().GetCommandProcessor().Submit(ProjectEditorMoveCommand(self, item, self._draggingItem)) + folderPath = self._GetItemFolderPath(item) + + self.GetDocument().GetCommandProcessor().Submit(ProjectMoveFilesCommand(self.GetDocument(), files, folderPath)) def WriteProjectConfig(self): @@ -714,32 +1588,47 @@ class ProjectView(wx.lib.docview.View): if config.ReadInt("ProjectSaveDocs", True): projectFileNames = [] - projectExpanded = [] - if self._treeCtrl: - for projectItem in self._GetChildItems(self._treeCtrl.GetRootItem()): - project = self._GetItemProject(projectItem) + curProject = None + + if self._projectChoice: + for i in range(self._projectChoice.GetCount()): + project = self._projectChoice.GetClientData(i) if not project.OnSaveModified(): return if project.GetDocumentSaved(): # Might be a new document and "No" selected to save it projectFileNames.append(str(project.GetFilename())) - projectExpanded.append(self._treeCtrl.IsExpanded(projectItem)) config.Write("ProjectSavedDocs", projectFileNames.__repr__()) - config.Write("ProjectExpandedSavedDocs", projectExpanded.__repr__()) + + document = None + if self._projectChoice.GetCount(): + i = self._projectChoice.GetSelection() + if i != wx.NOT_FOUND: + document = self._projectChoice.GetClientData(i) + if document: + config.Write("ProjectCurrent", document.GetFilename()) + else: + config.DeleteEntry("ProjectCurrent") def OnClose(self, deleteWindow = True): if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI: self.WriteProjectConfig() + project = self.GetDocument() if not project: return True - if not self.GetDocument().Close(): + if not project.Close(): return True - self.Activate(False) - if project: - projectItem = self._GetProjectItem(project) - if projectItem: - self._treeCtrl.Delete(projectItem) + + if not deleteWindow: + self.RemoveCurrentDocumentUpdate() + else: + # need this to accelerate closing down app if treeCtrl has lots of items + self._treeCtrl.Freeze() + rootItem = self._treeCtrl.GetRootItem() + self._treeCtrl.DeleteChildren(rootItem) + self._treeCtrl.Thaw() + # We don't need to delete the window since it is a floater/embedded return True @@ -750,59 +1639,168 @@ class ProjectView(wx.lib.docview.View): def OnUpdate(self, sender = None, hint = None): wx.lib.docview.View.OnUpdate(self, sender, hint) + if hint: if hint[0] == "add": - projectItem = self._GetProjectItem(hint[1]) - files = hint[2] + projectDoc = hint[1] + if self.GetDocument() != projectDoc: # project being updated isn't currently viewed project + return + + self._treeCtrl.Freeze() + + newFilePaths = hint[2] # need to be added and selected, and sorted + oldFilePaths = hint[3] # need to be selected self._treeCtrl.UnselectAll() - self._treeCtrl.Expand(projectItem) - item = None - for file in files: - item = self._treeCtrl.AppendItem(projectItem, os.path.basename(file)) - self._treeCtrl.SetData(item, file) - self._treeCtrl.SelectItem(item) - self._treeCtrl.EnsureVisible(item) - self._treeCtrl.SortChildren(projectItem) - if item: - self._treeCtrl.EnsureVisible(item) # need to be called after SortChildren + + mode = self.GetMode() + + project = projectDoc.GetModel() + projectDir = project.homeDir + rootItem = self._treeCtrl.GetRootItem() + + # add new folders and new items + addList = [] + for filePath in newFilePaths: + file = project.FindFile(filePath) + if file: + if mode == ProjectView.LOGICAL_MODE: + folderPath = file.logicalFolder + else: # ProjectView.PHYSICAL_MODE + folderPath = file.GetRelativeFolder(projectDir) + if folderPath: + self._treeCtrl.AddFolder(folderPath) + folder = self._treeCtrl.FindFolder(folderPath) + else: + folder = rootItem + item = self._treeCtrl.AppendItem(folder, os.path.basename(file.filePath), file) + addList.append(item) + + # sort folders with new items + parentList = [] + for item in addList: + parentItem = self._treeCtrl.GetItemParent(item) + if parentItem not in parentList: + parentList.append(parentItem) + for parentItem in parentList: + self._treeCtrl.SortChildren(parentItem) + + # select all the items user wanted to add + lastItem = None + for filePath in (oldFilePaths + newFilePaths): + item = self._treeCtrl.FindItem(filePath) + if item: + self._treeCtrl.SelectItem(item) + lastItem = item + + if lastItem: + self._treeCtrl.EnsureVisible(lastItem) + + self._treeCtrl.Thaw() + return + elif hint[0] == "remove": - projectItem = self._GetProjectItem(hint[1]) - files = hint[2] - self._treeCtrl.UnselectAll() - children = self._GetChildItems(projectItem) - for child in children: - if self._GetItemFile(child) in files: - self._treeCtrl.Delete(child) - elif hint[0] == "select": - projectItem = self._GetProjectItem(hint[1]) - files = hint[2] + projectDoc = hint[1] + if self.GetDocument() != projectDoc: # project being updated isn't currently viewed project + return + + self._treeCtrl.Freeze() + + filePaths = hint[2] self._treeCtrl.UnselectAll() - children = self._GetChildItems(projectItem) - for child in children: - if self._GetItemFile(child) in files: - self._treeCtrl.SelectItem(child) - self._treeCtrl.EnsureVisible(child) + + for filePath in filePaths: + item = self._treeCtrl.FindItem(filePath) + if item: + self._treeCtrl.Delete(item) + + self._treeCtrl.UnselectAll() # wxBug: even though we unselected earlier, an item still gets selected after the delete + + self._treeCtrl.Thaw() + return + elif hint[0] == "rename": - projectItem = self._GetProjectItem(hint[1]) - self._treeCtrl.SetItemText(projectItem, os.path.basename(hint[2])) + projectDoc = hint[1] + if self.GetDocument() != projectDoc: # project being updated isn't currently viewed project + return + + self._treeCtrl.Freeze() + item = self._treeCtrl.FindItem(hint[2]) + self._treeCtrl.SetItemText(item, os.path.basename(hint[3])) + self._treeCtrl.EnsureVisible(item) + self._treeCtrl.Thaw() + return + + elif hint[0] == "rename folder": + projectDoc = hint[1] + if self.GetDocument() != projectDoc: # project being updated isn't currently viewed project + return + + self._treeCtrl.Freeze() + item = self._treeCtrl.FindFolder(hint[2]) + if item: + self._treeCtrl.UnselectAll() + self._treeCtrl.SetItemText(item, os.path.basename(hint[3])) + self._treeCtrl.SortChildren(self._treeCtrl.GetItemParent(item)) + self._treeCtrl.SelectItem(item) + self._treeCtrl.EnsureVisible(item) + self._treeCtrl.Thaw() + return + + def RemoveProjectUpdate(self, projectDoc): + """ Called by service after deleting a project, need to remove from project choices """ + i = self._projectChoice.FindString(self._MakeProjectName(projectDoc)) + self._projectChoice.Delete(i) + + numProj = self._projectChoice.GetCount() + if i >= numProj: + i = numProj - 1 + if i >= 0: + self._projectChoice.SetSelection(i) + self.OnProjectSelect() + + + def RemoveCurrentDocumentUpdate(self, i=-1): + """ Called by service after deleting a project, need to remove from project choices """ + i = self._projectChoice.GetSelection() + self._projectChoice.Delete(i) + + numProj = self._projectChoice.GetCount() + if i >= numProj: + i = numProj - 1 + if i >= 0: + self._projectChoice.SetSelection(i) + self.OnProjectSelect() + def ProcessEvent(self, event): id = event.GetId() - if id == ProjectService.ADD_FILES_TO_PROJECT_ID: + if id == ProjectService.CLOSE_PROJECT_ID: + document = self.GetDocument() + if document: + if self.GetDocumentManager().CloseDocument(document, False): + self.RemoveCurrentDocumentUpdate() + return True + elif id == ProjectService.ADD_FILES_TO_PROJECT_ID: self.OnAddFileToProject(event) return True - elif id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID: + elif id == ProjectService.ADD_DIR_FILES_TO_PROJECT_ID: self.OnAddDirToProject(event) return True elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID: return False # Implement this one in the service + elif id == ProjectService.ADD_FOLDER_ID: + self.OnAddFolder(event) + return True elif id == ProjectService.RENAME_ID: self.OnRename(event) return True elif id == ProjectService.DELETE_FILE_ID: self.OnDeleteFile(event) - return True + return True + elif id == ProjectService.DELETE_PROJECT_ID: + self.OnDeleteProject(event) + return True elif id == wx.ID_CUT: self.OnCut(event) return True @@ -825,6 +1823,9 @@ class ProjectView(wx.lib.docview.View): elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID: self.OnProperties(event) return True + elif id == ProjectService.PROJECT_PROPERTIES_ID: + self.OnProjectProperties(event) + return True else: return False @@ -836,21 +1837,51 @@ class ProjectView(wx.lib.docview.View): if doc and not doc.GetCommandProcessor().GetEditMenu(): doc.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame())) self._checkEditMenu = False - + id = event.GetId() - if (id == wx.ID_CUT - or id == wx.ID_COPY - or id == ProjectService.RENAME_ID - or id == ProjectService.ADD_FILES_TO_PROJECT_ID - or id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID - or id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID): - event.Enable(self._HasSelection()) - return True - elif id == ProjectService.DELETE_FILE_ID: - event.Enable(len(self.GetSelectedFiles()) > 0) + if id == wx.ID_CLOSE: + # Too confusing, so disable closing from "File | Close" menu, must close from "Project | Close Current Project" menu + if self.ProjectHasFocus() or self.FilesHasFocus(): + event.Enable(False) + return True + else: + return False + elif (id == ProjectService.ADD_FILES_TO_PROJECT_ID + or id == ProjectService.ADD_DIR_FILES_TO_PROJECT_ID + or id == ProjectService.CLOSE_PROJECT_ID + or id == ProjectService.DELETE_PROJECT_ID): + event.Enable(self.GetDocument() != None) return True elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID: - event.Enable(False) + event.Enable(False) # Implement this one in the service + return True + elif id == ProjectService.ADD_FOLDER_ID: + event.Enable((self.GetDocument() != None) and (self.GetMode() == ProjectView.LOGICAL_MODE)) + return True + elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID: + status = False + if self.ProjectHasFocus(): + if self.GetDocument(): + status = True + elif self.FilesHasFocus(): + items = self._treeCtrl.GetSelections() + if items: + item = items[0] + if self._IsItemFile(item): + status = True + + event.Enable(status) + return True + elif (id == wx.ID_CUT + or id == wx.ID_COPY + or id == ProjectService.DELETE_FILE_ID + or id == ProjectService.REMOVE_FROM_PROJECT + or id == ProjectService.OPEN_SELECTION_ID): + event.Enable(self._HasFilesSelected()) + return True + elif (id == wx.ID_CLEAR + or id == ProjectService.RENAME_ID): + event.Enable(self._HasFilesSelected() or (self.GetDocument() != None and self.GetMode() == ProjectView.LOGICAL_MODE and self._HasFoldersSelected())) return True elif id == wx.ID_PASTE: event.Enable(self.CanPaste()) @@ -858,15 +1889,10 @@ class ProjectView(wx.lib.docview.View): elif id == wx.ID_SELECTALL: event.Enable(self._HasFiles()) return True - elif (id == wx.ID_CLEAR - or id == ProjectService.REMOVE_FROM_PROJECT - or id == ProjectService.OPEN_SELECTION_ID): - event.Enable(self._HasFilesSelected()) - return True elif (id == wx.ID_PREVIEW or id == wx.ID_PRINT): event.Enable(False) - return True + return True else: return False @@ -895,63 +1921,128 @@ class ProjectView(wx.lib.docview.View): # Methods for ProjectDocument and ProjectService to call #---------------------------------------------------------------------------- - def SetExpandedProjects(self, expandedProjects): - self._treeCtrl.UnselectAll() - firstItem = None - for i, item in enumerate(self._GetChildItems(self._treeCtrl.GetRootItem())): - if i == 0: - firstItem = item - - if expandedProjects[i]: - self._treeCtrl.Expand(item) - else: - self._treeCtrl.Collapse(item) - - if firstItem: - self._treeCtrl.EnsureVisible(firstItem) - + def SetProject(self, projectPath): + curSel = self._projectChoice.GetSelection() + for i in range(self._projectChoice.GetCount()): + document = self._projectChoice.GetClientData(i) + if document.GetFilename() == projectPath: + if curSel != i: # don't reload if already loaded + self._projectChoice.SetSelection(i) + self.LoadProject(document) + break + def GetSelectedFile(self): for item in self._treeCtrl.GetSelections(): - return self._GetItemFile(item) + filePath = self._GetItemFilePath(item) + if filePath: + return filePath + return None + - def GetSelectedFiles(self): - filenames = [] + filePaths = [] for item in self._treeCtrl.GetSelections(): - filename = self._GetItemFile(item) - if filename and filename not in filenames: - filenames.append(filename) - return filenames + filePath = self._GetItemFilePath(item) + if filePath and filePath not in filePaths: + filePaths.append(filePath) + return filePaths - def GetSelectedProjects(self): - filenames = [] - for item in self._treeCtrl.GetSelections(): - if self._IsItemProject(item): - filename = self._treeCtrl.GetLongFilename(item) - if filename and filename not in filenames: - filenames.append(filename) - return filenames + def GetSelectedPhysicalFolder(self): + if self.GetMode() == ProjectView.LOGICAL_MODE: + return None + else: + for item in self._treeCtrl.GetSelections(): + if not self._IsItemFile(item): + filePath = self._GetItemFolderPath(item) + if filePath: + return filePath + return None + + + def GetSelectedProject(self): + document = self.GetDocument() + if document: + return document.GetFilename() + else: + return None def AddProjectToView(self, document): + i = self._projectChoice.Append(self._MakeProjectName(document), document) + self._projectChoice.SetSelection(i) + self.OnProjectSelect() + + + def LoadProject(self, document): + wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) + self._treeCtrl.Freeze() + rootItem = self._treeCtrl.GetRootItem() - projectItem = self._treeCtrl.AppendItem(rootItem, self._MakeProjectName(document)) - self._treeCtrl.SetData(projectItem, document.GetFilename(), document) - for file in document.GetFiles(): - fileItem = self._treeCtrl.AppendItem(projectItem, os.path.basename(file)) - self._treeCtrl.SetData(fileItem, file) - self._treeCtrl.SortChildren(rootItem) - self._treeCtrl.SortChildren(projectItem) - self._treeCtrl.UnselectAll() - self._treeCtrl.Expand(projectItem) - self._treeCtrl.SelectItem(projectItem) - if self._embeddedWindow: - document.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame())) + self._treeCtrl.DeleteChildren(rootItem) + + if document: + mode = self.GetMode() + docFilePath = document.GetFilename() + + if mode == ProjectView.LOGICAL_MODE: + folders = document.GetModel().logicalFolders + else: + folders = document.GetModel().GetRelativeFolders() + + folders.sort() + folderItems = [] + for folderPath in folders: + folderItems = folderItems + self._treeCtrl.AddFolder(folderPath) + + for file in document.GetModel()._files: + if mode == ProjectView.LOGICAL_MODE: + folder = file.logicalFolder + else: + folder = file.GetRelativeFolder(document.GetModel().homeDir) + if folder: + folderTree = folder.split('/') + + item = rootItem + for folderName in folderTree: + found = False + (child, cookie) = self._treeCtrl.GetFirstChild(item) + while child.IsOk(): + if self._treeCtrl.GetItemText(child) == folderName: + item = child + found = True + break + (child, cookie) = self._treeCtrl.GetNextChild(item, cookie) + + if not found: + print "error folder '%s' not found for %s" % (folder, file.filePath) + break + else: + item = rootItem + + fileItem = self._treeCtrl.AppendItem(item, os.path.basename(file.filePath), file) + + self._treeCtrl.SortChildren(rootItem) + for item in folderItems: + self._treeCtrl.SortChildren(item) + + self.LoadFolderState() + + if self._embeddedWindow: + document.GetCommandProcessor().SetEditMenu(wx.GetApp().GetEditMenu(self._GetParentFrame())) + self._treeCtrl.Thaw() + wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) - def HasFocus(self): + + def ProjectHasFocus(self): + """ Does Project Choice have focus """ + return (wx.Window.FindFocus() == self._projectChoice) + + + def FilesHasFocus(self): + """ Does Project Tree have focus """ winWithFocus = wx.Window.FindFocus() if not winWithFocus: return False @@ -962,61 +2053,172 @@ class ProjectView(wx.lib.docview.View): return False + def SaveFolderState(self, event=None): + """ Save the open/close state of folders """ + + if self._loading: + return + + folderList = [] + folderItemList = self._GetFolderItems(self._treeCtrl.GetRootItem()) + for item in folderItemList: + if self._treeCtrl.IsExpanded(item): + folderList.append(self._GetItemFolderPath(item)) + + config = wx.ConfigBase_Get() + config.Write(getProjectKeyName(self.GetDocument().GetFilename(), self.GetMode()), repr(folderList)) + + + def LoadFolderState(self): + """ Load the open/close state of folders """ + self._loading = True + + config = wx.ConfigBase_Get() + openFolderData = config.Read(getProjectKeyName(self.GetDocument().GetFilename(), self.GetMode())) + if openFolderData: + folderList = eval(openFolderData) + + folderItemList = self._GetFolderItems(self._treeCtrl.GetRootItem()) + for item in folderItemList: + f = self._GetItemFolderPath(item) + if f in folderList: + self._treeCtrl.Expand(item) +## else: # not needed, initial state is collapsed +## self._treeCtrl.Collapse(item) + else: # default is to open all folders + folderItemList = self._GetFolderItems(self._treeCtrl.GetRootItem()) + for item in folderItemList: + self._treeCtrl.Expand(item) + + self._loading = False + + #---------------------------------------------------------------------------- # Control events #---------------------------------------------------------------------------- def OnProperties(self, event): - items = self._treeCtrl.GetSelections() - if not items: - return - item = items[0] - if self._IsItemProject(item): - projectPropertiesDialog = ProjectPropertiesDialog(wx.GetApp().GetTopWindow(), self._GetItemProject(item).GetFilename()) - if projectPropertiesDialog.ShowModal() == wx.ID_OK: - pass # Handle OK - projectPropertiesDialog.Destroy() - elif self._IsItemFile(item): - filePropertiesService = wx.GetApp().GetService(wx.lib.pydocview.FilePropertiesService) - filePropertiesService.ShowPropertiesDialog(self._GetItemFile(item)) + if self.ProjectHasFocus(): + self.OnProjectProperties(event) + elif self.FilesHasFocus(): + items = self._treeCtrl.GetSelections() + if not items: + return + item = items[0] + filePath = self._GetItemFilePath(item) + if filePath: + filePropertiesService = wx.GetApp().GetService(wx.lib.pydocview.FilePropertiesService) + filePropertiesService.ShowPropertiesDialog(filePath) + + + def OnProjectProperties(self, event): + if self.GetDocument(): + dlg = ProjectPropertiesDialog(wx.GetApp().GetTopWindow(), self.GetDocument()) + dlg.CenterOnParent() + finished = False + while not finished: + if dlg.ShowModal() == wx.ID_OK: + if hasattr(dlg, "_appInfoCtrl") and dlg._appInfoCtrl._grid.IsCellEditControlShown(): # for Linux + dlg._appInfoCtrl._grid.DisableCellEditControl() # If editor is still active, force it to finish the edit before setting the new model. + + homeDir = dlg._homeDirCtrl.GetValue() + if homeDir: + if homeDir == ProjectPropertiesDialog.RELATIVE_TO_PROJECT_FILE: + homeDir = None + if homeDir and not os.path.isdir(homeDir): + wx.MessageBox(_("Home Dir '%s' does not exist. Please specify a valid directory.") % homeDir, + _("Project Properties"), + wx.OK | wx.ICON_EXCLAMATION) + else: + if self.GetDocument().GetModel()._homeDir != homeDir: # don't set it if it hasn't changed + self.GetDocument().GetModel().homeDir = homeDir + self.GetDocument().Modify(True) + finished = True + else: + wx.MessageBox(_("Blank Home Dir. Please specify a valid directory."), + _("Project Properties"), + wx.OK | wx.ICON_EXCLAMATION) + else: # ID_CANCEL + finished = True + dlg.Destroy() + + + def OnAddFolder(self, event): + if self.GetDocument(): + items = self._treeCtrl.GetSelections() + if items: + item = items[0] + if self._IsItemFile(item): + item = self._treeCtrl.GetItemParent(item) + + folderDir = self._GetItemFolderPath(item) + else: + folderDir = "" + + if folderDir: + folderDir += "/" + folderPath = _("%sUntitled") % folderDir + i = 1 + while self._treeCtrl.FindFolder(folderPath): + i += 1 + folderPath = _("%sUntitled%s") % (folderDir, i) + self.GetDocument().GetCommandProcessor().Submit(ProjectAddFolderCommand(self, self.GetDocument(), folderPath)) + + self._treeCtrl.UnselectAll() + item = self._treeCtrl.FindFolder(folderPath) + self._treeCtrl.SelectItem(item) + self._treeCtrl.EnsureVisible(item) + self.OnRename() + + + def AddFolder(self, folderPath): + self._treeCtrl.AddFolder(folderPath) + return True + + + def DeleteFolder(self, folderPath): + item = self._treeCtrl.FindFolder(folderPath) + self._treeCtrl.Delete(item) + return True def OnAddFileToProject(self, event): if wx.Platform == "__WXMSW__" or wx.Platform == "__WXGTK__" or wx.Platform == "__WXMAC__": - allfilter = '' descr = '' for temp in self.GetDocumentManager()._templates: if temp.IsVisible(): if len(descr) > 0: descr = descr + _('|') - allfilter = allfilter + _(';') descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk - allfilter = allfilter + temp.GetFileFilter() - descr = _("All (%s)|%s|%s|Any (*.*) | *.*") % (allfilter, allfilter, descr) # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk + descr = _("All (*.*)|*.*|%s") % descr # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk else: descr = _("*.*") - - startDirectory = os.path.dirname(self.GetDocument().GetFilename()) - - if True or _WINDOWS: - dialog = wx.FileDialog(self.GetFrame(), _("Add Files"), startDirectory, "", descr, wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE) - if dialog.ShowModal() != wx.ID_OK: - return - paths = dialog.GetPaths() + + dialog = wx.FileDialog(self.GetFrame(), _("Add Files"), wildcard=descr, style=wx.OPEN|wx.HIDE_READONLY|wx.MULTIPLE|wx.CHANGE_DIR) + # dialog.CenterOnParent() # wxBug: caused crash with wx.FileDialog + if dialog.ShowModal() != wx.ID_OK: dialog.Destroy() - else: - paths = wx.FileSelector(_("Add Files"), startDirectory, "", wildcard = descr, flags = wx.OPEN | wx.HIDE_READONLY | wx.MULTIPLE, parent=self.GetFrame()) - if type(paths) == types.StringType: - paths = [paths] + return + paths = dialog.GetPaths() + dialog.Destroy() if len(paths): - self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), paths)) - self.Activate(True) # after add, should put focus on project editor + + folderPath = None + if self.GetMode() == ProjectView.LOGICAL_MODE: + selections = self._treeCtrl.GetSelections() + if selections: + item = selections[0] + if not self._IsItemFile(item): + folderPath = self._GetItemFolderPath(item) + + self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), paths, folderPath=folderPath)) + self.Activate() # after add, should put focus on project editor def OnAddDirToProject(self, event): - frame = wx.Dialog(None, -1, _("Add Directory Files to Project"), size= (320,200)) + frame = wx.Dialog(wx.GetApp().GetTopWindow(), -1, _("Add Directory Files to Project"), size= (320,200)) contentSizer = wx.BoxSizer(wx.VERTICAL) - + flexGridSizer = wx.FlexGridSizer(cols = 2, vgap=HALF_SPACE, hgap=HALF_SPACE) flexGridSizer.Add(wx.StaticText(frame, -1, _("Directory:")), 0, wx.ALIGN_CENTER_VERTICAL, 0) lineSizer = wx.BoxSizer(wx.HORIZONTAL) @@ -1026,17 +2228,17 @@ class ProjectView(wx.lib.docview.View): findDirButton = wx.Button(frame, -1, _("Browse...")) lineSizer.Add(findDirButton, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, HALF_SPACE) flexGridSizer.Add(lineSizer, 1, wx.EXPAND) - + def OnBrowseButton(event): dlg = wx.DirDialog(frame, _("Choose a directory:"), style=wx.DD_DEFAULT_STYLE) dir = dirCtrl.GetValue() if len(dir): dlg.SetPath(dir) + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: dirCtrl.SetValue(dlg.GetPath()) dirCtrl.SetToolTipString(dirCtrl.GetValue()) dirCtrl.SetInsertionPointEnd() - dlg.Destroy() wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton) @@ -1044,27 +2246,23 @@ class ProjectView(wx.lib.docview.View): for template in self.GetDocumentManager()._templates: if template.IsVisible(): visibleTemplates.append(template) - + choices = [] - allfilter = '' descr = '' for template in visibleTemplates: if len(descr) > 0: descr = descr + _('|') - allfilter = allfilter + _(';') descr = template.GetDescription() + _(" (") + template.GetFileFilter() + _(")") choices.append(descr) - allfilter = allfilter + template.GetFileFilter() - choices.insert(0, _("All (%s)") % allfilter) # first item - choices.append(_("Any (*.*)")) # last item + choices.insert(0, _("All (*.*)")) # first item filterChoice = wx.Choice(frame, -1, size=(250, -1), choices=choices) filterChoice.SetSelection(0) filterChoice.SetToolTipString(_("Select file type filter.")) flexGridSizer.Add(wx.StaticText(frame, -1, _("Files of type:")), 0, wx.ALIGN_CENTER_VERTICAL) flexGridSizer.Add(filterChoice, 1, wx.EXPAND) - + contentSizer.Add(flexGridSizer, 0, wx.ALL|wx.EXPAND, SPACE) - + subfolderCtrl = wx.CheckBox(frame, -1, _("Add files from subdirectories")) subfolderCtrl.SetValue(True) contentSizer.Add(subfolderCtrl, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, SPACE) @@ -1079,6 +2277,7 @@ class ProjectView(wx.lib.docview.View): frame.SetSizer(contentSizer) frame.Fit() + frame.CenterOnParent() status = frame.ShowModal() passedCheck = False @@ -1089,29 +2288,30 @@ class ProjectView(wx.lib.docview.View): _("Find in Directory"), wx.OK | wx.ICON_EXCLAMATION ) + dlg.CenterOnParent() dlg.ShowModal() dlg.Destroy() status = frame.ShowModal() else: passedCheck = True - - if status == wx.ID_OK: - frame.Destroy() + frame.Destroy() + + if status == wx.ID_OK: wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) - + doc = self.GetDocument() searchSubfolders = subfolderCtrl.IsChecked() dirString = dirCtrl.GetValue() - + if os.path.isfile(dirString): # If they pick a file explicitly, we won't prevent them from adding it even if it doesn't match the filter. # We'll assume they know what they're doing. paths = [dirString] else: paths = [] - + index = filterChoice.GetSelection() lastIndex = filterChoice.GetCount()-1 if index and index != lastIndex: # if not All or Any @@ -1121,13 +2321,13 @@ class ProjectView(wx.lib.docview.View): for root, dirs, files in os.walk(dirString): if not searchSubfolders and root != dirString: break - + for name in files: if index == 0: # All for template in visibleTemplates: if template.FileMatchesTemplate(name): filename = os.path.join(root, name) - + # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. if doc.IsFileInProject(filename): break @@ -1138,55 +2338,35 @@ class ProjectView(wx.lib.docview.View): filename = os.path.join(root, name) # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. if not doc.IsFileInProject(filename): - paths.append(filename) + paths.append(filename) else: # use selected filter if template.FileMatchesTemplate(name): filename = os.path.join(root, name) # if already in project, don't add it, otherwise undo will remove it from project even though it was already in it. if not doc.IsFileInProject(filename): - paths.append(filename) - - wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) - - doc.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc, paths)) - self.Activate(True) # after add, should put focus on project editor - else: - frame.Destroy() - - - def DoAddFilesToProject(self, filenames): - # method used by Drag-n-Drop to add files to current Project - self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), filenames)) - + paths.append(filename) - def DoSelectFiles(self, filenames): - # method used by Drag-n-Drop to select files in current Project - self._treeCtrl.UnselectAll() - for file in filenames: - item = self._GetFileItem(longFileName=file) - if item: - self._treeCtrl.SelectItem(item, True) - self._treeCtrl.EnsureVisible(item) + folderPath = None + if self.GetMode() == ProjectView.LOGICAL_MODE: + selections = self._treeCtrl.GetSelections() + if selections: + item = selections[0] + if not self._IsItemFile(item): + folderPath = self._GetItemFolderPath(item) + wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT)) - def DoSelectProject(self, x, y): - # method used by Drag-n-Drop to set current Project based on cursor position - item, flag = self._treeCtrl.HitTest((x,y)) - if not item: - return False + doc.GetCommandProcessor().Submit(ProjectAddFilesCommand(doc, paths, folderPath=folderPath)) + self.Activate() # after add, should put focus on project editor - project = self._GetItemProject(item) - if not project: - return False - projectItem = self._GetProjectItem(project) - self._treeCtrl.UnselectAll() - self._treeCtrl.SelectItem(projectItem) - return True + def DoAddFilesToProject(self, filePaths, folderPath): + # method used by Drag-n-Drop to add files to current Project + self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), filePaths, folderPath)) def OnFocus(self, event): - wx.GetApp().GetDocumentManager().ActivateView(self) + self.GetDocumentManager().ActivateView(self) event.Skip() @@ -1194,32 +2374,67 @@ class ProjectView(wx.lib.docview.View): # Get the top MDI window and "activate" it since it is already active from the perspective of the MDIParentFrame # wxBug: Would be preferable to call OnActivate, but have casting problem, so added Activate method to docview.DocMDIChildFrame if not self._editingSoDontKillFocus: # wxBug: This didn't used to happen, but now when you start to edit an item in a wxTreeCtrl it puts out a KILL_FOCUS event, so we need to detect it - childFrame = wx.GetApp().GetTopWindow().GetActiveChild() - if childFrame: - childFrame.Activate() + topWindow = wx.GetApp().GetTopWindow() + # wxBug: On Mac, this event can fire during shutdown, even after GetTopWindow() + # is set to NULL. So make sure we have a TLW before getting the active child. + if topWindow: + childFrame = topWindow.GetActiveChild() + if childFrame: + childFrame.Activate() + event.Skip() + + + def OnLeftClick(self, event): + """ wxBug: If tree has selection, but focus is in another window, single click in tree should do + single selection of item at mouse position. But what it does is just put focus back into the + window and all items go from inactive selection to active selection. Another click on the item + either activates double-click or edit for that item. This behavior is odd. + + This fix makes gives the tree view the focus and makes the item under the mouse position the + only active selection, as expected. + """ + if not self.ProjectHasFocus() and not self.FilesHasFocus() and not event.ShiftDown() and not event.ControlDown() and not event.MetaDown(): + self._treeCtrl.UnselectAll() + event.Skip() + item, flags = self._treeCtrl.HitTest(event.GetPosition()) + self._treeCtrl.SelectItem(item) + return + event.Skip() def OnRightClick(self, event): - self.Activate(True) - if not self._treeCtrl.GetSelections(): + self.Activate() + if not self.GetSelectedProject(): return - if len(self._treeCtrl.GetSelections()) == 1 and self._IsItemRoot(self._treeCtrl.GetSelections()[0]): - return # Don't do a menu if it's just the root item selected menu = wx.Menu() if self._HasFilesSelected(): # Files context menu.Append(ProjectService.OPEN_SELECTION_ID, _("&Open"), _("Opens the selection")) menu.Enable(ProjectService.OPEN_SELECTION_ID, True) wx.EVT_MENU(self._GetParentFrame(), ProjectService.OPEN_SELECTION_ID, self.OnOpenSelection) + + extService = wx.GetApp().GetService(ExtensionService.ExtensionService) + if extService and extService.GetExtensions(): + firstItem = True + for ext in extService.GetExtensions(): + if not ext.opOnSelectedFile: + continue + if firstItem: + menu.AppendSeparator() + firstItem = False + menu.Append(ext.id, ext.menuItemName) + wx.EVT_MENU(self._GetParentFrame(), ext.id, extService.ProcessEvent) + wx.EVT_UPDATE_UI(self._GetParentFrame(), ext.id, extService.ProcessUpdateUIEvent) + itemIDs = [None] for item in self._treeCtrl.GetSelections(): if self._IsItemProcessModelFile(item): itemIDs = [None, ProjectService.RUN_SELECTED_PM_ID, None] break else: # Project context - itemIDs = [wx.ID_CLOSE, wx.ID_SAVE, wx.ID_SAVEAS, None] + itemIDs = [] menuBar = self._GetParentFrame().GetMenuBar() - itemIDs = itemIDs + [ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, ProjectService.REMOVE_FROM_PROJECT] + itemIDs = itemIDs + [ProjectService.ADD_FILES_TO_PROJECT_ID, ProjectService.ADD_DIR_FILES_TO_PROJECT_ID, ProjectService.ADD_FOLDER_ID, ProjectService.REMOVE_FROM_PROJECT, None, ProjectService.CLOSE_PROJECT_ID, ProjectService.DELETE_PROJECT_ID, None, ProjectService.PROJECT_PROPERTIES_ID] svnIDs = [SVNService.SVNService.SVN_UPDATE_ID, SVNService.SVNService.SVN_CHECKIN_ID, SVNService.SVNService.SVN_REVERT_ID] if SVN_INSTALLED: itemIDs = itemIDs + [None, SVNService.SVNService.SVN_UPDATE_ID, SVNService.SVNService.SVN_CHECKIN_ID, SVNService.SVNService.SVN_REVERT_ID] @@ -1258,15 +2473,16 @@ class ProjectView(wx.lib.docview.View): projectService.OnRunProcessModel(event, runSelected=True) - def OnRename(self, event): - if self._treeCtrl.GetSelections(): - self._treeCtrl.EditLabel(self._treeCtrl.GetSelections()[0]) + def OnRename(self, event=None): + items = self._treeCtrl.GetSelections() + if items: + self._treeCtrl.EditLabel(items[0]) def OnBeginLabelEdit(self, event): self._editingSoDontKillFocus = True item = event.GetItem() - if not self._IsItemFile(item) and not self._IsItemProject(item): + if (self.GetMode() == ProjectView.PHYSICAL_MODE) and not self._IsItemFile(item): event.Veto() @@ -1274,25 +2490,35 @@ class ProjectView(wx.lib.docview.View): self._editingSoDontKillFocus = False item = event.GetItem() newName = event.GetLabel() - if not newName or (not self._IsItemFile(item) and not self._IsItemProject(item)): + if not newName: event.Veto() return if self._IsItemFile(item): - oldFile = self._GetItemFile(item) - newFile = os.path.join(os.path.split(oldFile)[0], newName) - project = self._GetItemProject(item) - if not project.GetCommandProcessor().Submit(ProjectRenameFileCommand(project, oldFile, newFile)): + oldFilePath = self._GetItemFilePath(item) + newFilePath = os.path.join(os.path.dirname(oldFilePath), newName) + doc = self.GetDocument() + if not doc.GetCommandProcessor().Submit(ProjectRenameFileCommand(doc, oldFilePath, newFilePath)): event.Veto() return - self._treeCtrl.SortChildren(self._treeCtrl.GetItemParent(self._treeCtrl.GetSelections()[0])) - elif self._IsItemProject(item): - oldFile = self._GetItemProject(item).GetFilename() - newFile = os.path.join(os.path.split(oldFile)[0], newName) - project = self._GetItemProject(item) - if not project.GetCommandProcessor().Submit(ProjectRenameFileCommand(project, oldFile, newFile, True)): + self._treeCtrl.SortChildren(self._treeCtrl.GetItemParent(item)) + else: + oldFolderPath = self._GetItemFolderPath(item) + newFolderPath = os.path.dirname(oldFolderPath) + if newFolderPath: + newFolderPath += "/" + newFolderPath += newName + if self._treeCtrl.FindFolder(newFolderPath): + wx.MessageBox(_("Folder '%s' already exists.") % newName, + "Rename Folder", + wx.OK | wx.ICON_EXCLAMATION, + self.GetFrame()) + event.Veto() + return + doc = self.GetDocument() + if not doc.GetCommandProcessor().Submit(ProjectRenameFolderCommand(doc, oldFolderPath, newFolderPath)): event.Veto() return - self._treeCtrl.SortChildren(self._treeCtrl.GetRootItem()) + self._treeCtrl.SortChildren(self._treeCtrl.GetItemParent(item)) def CanPaste(self): @@ -1318,9 +2544,9 @@ class ProjectView(wx.lib.docview.View): fileDataObject = wx.FileDataObject() items = self._treeCtrl.GetSelections() for item in items: - if self._IsItemFile(item): - file = self._treeCtrl.GetLongFilename(item) - fileDataObject.AddFile(file) + filePath = self._GetItemFilePath(item) + if filePath: + fileDataObject.AddFile(filePath) if len(fileDataObject.GetFilenames()) > 0 and wx.TheClipboard.Open(): wx.TheClipboard.SetData(fileDataObject) wx.TheClipboard.Close() @@ -1330,61 +2556,192 @@ class ProjectView(wx.lib.docview.View): if wx.TheClipboard.Open(): fileDataObject = wx.FileDataObject() if wx.TheClipboard.GetData(fileDataObject): - self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), fileDataObject.GetFilenames())) + folderPath = None + if self.GetMode() == ProjectView.LOGICAL_MODE: + items = self._treeCtrl.GetSelections() + if items: + item = items[0] + if item: + folderPath = self._GetItemFolderPath(item) + self.GetDocument().GetCommandProcessor().Submit(ProjectAddFilesCommand(self.GetDocument(), fileDataObject.GetFilenames(), folderPath)) wx.TheClipboard.Close() def OnClear(self, event): - items = self._treeCtrl.GetSelections() - files = [] - for item in items: - if self._IsItemFile(item): - files.append((self._GetItemProject(item), self._GetItemFile(item))) - self.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(files)) + if self._HasFilesSelected(): + items = self._treeCtrl.GetSelections() + files = [] + for item in items: + file = self._GetItemFile(item) + if file: + files.append(file) + self.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFilesCommand(self.GetDocument(), files)) + + elif self._HasFoldersSelected(): + items = self._treeCtrl.GetSelections() + item = items[0] + if self._treeCtrl.GetChildrenCount(item, False): + wx.MessageBox(_("Cannot remove folder '%s'. Folder is not empty.") % self._treeCtrl.GetItemText(item), + _("Remove Folder"), + wx.OK | wx.ICON_EXCLAMATION, + self.GetFrame()) + return + + folderPath = self._GetItemFolderPath(item) + self.GetDocument().GetCommandProcessor().Submit(ProjectRemoveFolderCommand(self, self.GetDocument(), folderPath)) def OnDeleteFile(self, event): yesNoMsg = wx.MessageDialog(self.GetFrame(), - _("Delete cannot be reversed.\n\nRemove the selected files from the\nprojects and file system permanently?"), + _("Delete cannot be reversed.\n\nRemove the selected files from the\nproject and file system permanently?"), _("Delete File"), wx.YES_NO|wx.ICON_QUESTION) - if yesNoMsg.ShowModal() == wx.ID_NO: + yesNoMsg.CenterOnParent() + status = yesNoMsg.ShowModal() + yesNoMsg.Destroy() + if status == wx.ID_NO: return - + items = self._treeCtrl.GetSelections() - files = [] delFiles = [] for item in items: - if self._IsItemFile(item): - filename = self._GetItemFile(item) - files.append((self._GetItemProject(item), filename)) - if filename not in delFiles: - delFiles.append(filename) - - # remove selected files from projects - projects = [] - for data in files: - proj, filename = data - if proj not in projects: - projects.append(proj) - for project in projects: - filenames = [] - for data in files: - proj, filename = data - if project == proj: - filenames.append(filename) - project.RemoveFiles(filenames) - + filePath = self._GetItemFilePath(item) + if filePath and filePath not in delFiles: + delFiles.append(filePath) + + # remove selected files from project + self.GetDocument().RemoveFiles(delFiles) + # remove selected files from file system - for filename in delFiles: - if os.path.exists(filename): + for filePath in delFiles: + if os.path.exists(filePath): try: - os.remove(filename) + os.remove(filePath) except: - wx.MessageBox("Could not delete '%s'. %s" % (os.path.basename(filename), sys.exc_value), + wx.MessageBox("Could not delete '%s'. %s" % (os.path.basename(filePath), sys.exc_value), _("Delete File"), - wx.OK | wx.ICON_EXCLAMATION) - + wx.OK | wx.ICON_EXCLAMATION, + self.GetFrame()) + + def OnDeleteProject(self, event=None, noPrompt=False, closeFiles=True, delFiles=True): + + class DeleteProjectDialog(wx.Dialog): + + def __init__(self, parent, doc): + wx.Dialog.__init__(self, parent, -1, _("Delete Project"), size = (310, 330)) + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(wx.StaticText(self, -1, _("Delete cannot be reversed.\nDeleted files are removed from the file system permanently.\n\nThe project file '%s' will be closed and deleted.") % os.path.basename(doc.GetFilename())), 0, wx.ALL, SPACE) + self._delFilesCtrl = wx.CheckBox(self, -1, _("Delete all files in project")) + self._delFilesCtrl.SetValue(True) + self._delFilesCtrl.SetToolTipString(_("Deletes files from disk, whether open or closed")) + sizer.Add(self._delFilesCtrl, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM, SPACE) + self._closeDeletedCtrl = wx.CheckBox(self, -1, _("Close open files belonging to project")) + self._closeDeletedCtrl.SetValue(True) + self._closeDeletedCtrl.SetToolTipString(_("Closes open editors for files belonging to project")) + sizer.Add(self._closeDeletedCtrl, 0, wx.LEFT|wx.RIGHT|wx.BOTTOM, SPACE) + + sizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0, wx.ALIGN_RIGHT|wx.RIGHT|wx.LEFT|wx.BOTTOM, SPACE) + + self.SetSizer(sizer) + sizer.Fit(self) + self.Layout() + + doc = self.GetDocument() + if not noPrompt: + dlg = DeleteProjectDialog(self.GetFrame(), doc) + dlg.CenterOnParent() + status = dlg.ShowModal() + delFiles = dlg._delFilesCtrl.GetValue() + closeFiles = dlg._closeDeletedCtrl.GetValue() + dlg.Destroy() + if status == wx.ID_CANCEL: + return + + if closeFiles or delFiles: + filesInProject = doc.GetFiles() + filesInProject.append(self.GetDocument().GetDeploymentFilepath()) # remove deployment file also. + + # don't remove self prematurely + filePath = doc.GetFilename() + if filePath in filesInProject: + filesInProject.remove(filePath) + + # don't close/delete files outside of project's directory + homeDir = doc.GetModel().homeDir + os.sep + for filePath in filesInProject[:]: + fileDir = os.path.dirname(filePath) + os.sep + if not fileDir.startswith(homeDir): + filesInProject.remove(filePath) + + if closeFiles: + # close any open views of documents in the project + openDocs = self.GetDocumentManager().GetDocuments()[:] # need copy or docs shift when closed + for d in openDocs: + if d.GetFilename() in filesInProject: + d.Modify(False) # make sure it doesn't ask to save the file + if isinstance(d.GetDocumentTemplate(), ProjectTemplate): # if project, remove from project list drop down + if self.GetDocumentManager().CloseDocument(d, True): + self.RemoveProjectUpdate(d) + else: # regular file + self.GetDocumentManager().CloseDocument(d, True) + + # remove files in project from file system + if delFiles: + dirPaths = [] + for filePath in filesInProject: + if os.path.isfile(filePath): + try: + dirPath = os.path.dirname(filePath) + if dirPath not in dirPaths: + dirPaths.append(dirPath) + + os.remove(filePath) + except: + wx.MessageBox("Could not delete file '%s'.\n%s" % (filePath, sys.exc_value), + _("Delete Project"), + wx.OK | wx.ICON_EXCLAMATION, + self.GetFrame()) + + filePath = doc.GetFilename() + + # close project + if doc: + doc.Modify(False) # make sure it doesn't ask to save the project + if self.GetDocumentManager().CloseDocument(doc, True): + self.RemoveCurrentDocumentUpdate() + + # remove project file + if delFiles: + dirPath = os.path.dirname(filePath) + if dirPath not in dirPaths: + dirPaths.append(dirPath) + if os.path.isfile(filePath): + try: + os.remove(filePath) + except: + wx.MessageBox("Could not delete project file '%s'.\n%s" % (filePath, sys.exc_value), + _("Delete Prjoect"), + wx.OK | wx.ICON_EXCLAMATION, + self.GetFrame()) + + # remove empty directories from file system + if delFiles: + dirPaths.sort() # sorting puts parent directories ahead of child directories + dirPaths.reverse() # remove child directories first + + for dirPath in dirPaths: + if os.path.isdir(dirPath): + files = os.listdir(dirPath) + if not files: + try: + os.rmdir(dirPath) + except: + wx.MessageBox("Could not delete empty directory '%s'.\n%s" % (dirPath, sys.exc_value), + _("Delete Project"), + wx.OK | wx.ICON_EXCLAMATION, + self.GetFrame()) + def OnKeyPressed(self, event): key = event.KeyCode() @@ -1397,9 +2754,17 @@ class ProjectView(wx.lib.docview.View): def OnSelectAll(self, event): project = self.GetDocument() if project: - self._treeCtrl.UnselectAll() - for child in self._GetChildItems(self._GetProjectItem(project)): + self.DoSelectAll(self._treeCtrl.GetRootItem()) + + + def DoSelectAll(self, parentItem): + (child, cookie) = self._treeCtrl.GetFirstChild(parentItem) + while child.IsOk(): + if self._IsItemFile(child): self._treeCtrl.SelectItem(child) + else: + self.DoSelectAll(child) + (child, cookie) = self._treeCtrl.GetNextChild(parentItem, cookie) def OnOpenSelectionSDI(self, event): @@ -1410,10 +2775,10 @@ class ProjectView(wx.lib.docview.View): def OnOpenSelection(self, event): doc = None try: - items = self._treeCtrl.GetSelections() + items = self._treeCtrl.GetSelections()[:] for item in items: - if self._IsItemFile(item): - filepath = self._GetItemFile(item) + filepath = self._GetItemFilePath(item) + if filepath: if not os.path.exists(filepath): msgTitle = wx.GetApp().GetAppName() if not msgTitle: @@ -1423,38 +2788,37 @@ class ProjectView(wx.lib.docview.View): msgTitle, wx.YES_NO|wx.ICON_QUESTION ) - if yesNoMsg.ShowModal() == wx.ID_NO: + yesNoMsg.CenterOnParent() + status = yesNoMsg.ShowModal() + yesNoMsg.Destroy() + if status == wx.ID_NO: continue - findFile = wx.FileDialog(self.GetFrame(), + findFileDlg = wx.FileDialog(self.GetFrame(), _("Choose a file"), - wx.lib.docview.PathOnly(filepath), - wx.lib.docview.FileNameFromPath(filepath), - style = wx.OPEN + defaultFile=wx.lib.docview.FileNameFromPath(filepath), + style=wx.OPEN|wx.FILE_MUST_EXIST|wx.CHANGE_DIR ) - if findFile.ShowModal() == wx.ID_OK and findFile.GetPath(): - newpath = findFile.GetPath() + # findFileDlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog + if findFileDlg.ShowModal() == wx.ID_OK: + newpath = findFileDlg.GetPath() else: newpath = None - findFile.Destroy() + findFileDlg.Destroy() if newpath: # update Project Model with new location - project = self._GetItemProject(item) - project.RemoveFile(filepath) - project.AddFile(newpath) + self.GetDocument().UpdateFilePath(filepath, newpath) filepath = newpath - doc = self.GetDocumentManager().CreateDocument(filepath, wx.lib.docview.DOC_SILENT) - if not doc: - shortFilename = self._treeCtrl.GetItemText(item) - if shortFilename.endswith(".agp"): - projItem = self._GetProjectItem(shortFilename=shortFilename) - self._treeCtrl.UnselectAll() - if not self._treeCtrl.IsExpanded(projItem): - self._treeCtrl.Expand(projItem) - if not self._treeCtrl.IsVisible(projItem): - self._treeCtrl.EnsureVisible(projItem) - if not self._treeCtrl.IsSelected(projItem): - self._treeCtrl.SelectItem(projItem) + doc = self.GetDocumentManager().CreateDocument(filepath, wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE) + if not doc and filepath.endswith(PROJECT_EXTENSION): # project already open + self.SetProject(filepath) + elif doc: + projectService = wx.GetApp().GetService(ProjectService) + if projectService: + projectService.AddProjectMapping(doc) + if hasattr(doc, "GetModel"): + projectService.AddProjectMapping(doc.GetModel()) + except IOError, (code, message): msgTitle = wx.GetApp().GetAppName() @@ -1476,25 +2840,26 @@ class ProjectView(wx.lib.docview.View): return self._treeCtrl.GetCount() > 1 # 1 item = root item, don't count as having files - def _HasSelection(self): + def _HasFilesSelected(self): if not self._treeCtrl: return False - items = self._treeCtrl.GetSelections() - if items: - return True - + if not items: + return False + for item in items: + if self._IsItemFile(item): + return True return False - def _HasFilesSelected(self): + def _HasFoldersSelected(self): if not self._treeCtrl: return False items = self._treeCtrl.GetSelections() if not items: return False for item in items: - if not self._IsItemFile(item): + if self._IsItemFile(item): return False return True @@ -1503,76 +2868,47 @@ class ProjectView(wx.lib.docview.View): return project.GetPrintableName() - # Return the tree item for a project - def _GetProjectItem(self, project=None, shortFilename=None): - rootItem = self._treeCtrl.GetRootItem() - (child, cookie) = self._treeCtrl.GetFirstChild(rootItem) - while child.IsOk(): - if project: - if self._treeCtrl.GetProjectDoc(child) == project: - return child - elif shortFilename: - if self._treeCtrl.GetItemText(child) == shortFilename: - return child - (child, cookie) = self._treeCtrl.GetNextChild(rootItem, cookie) - return None - - - # Returns the project for an item, either for a project item or a file that is part of a project - def _GetItemProject(self, item): - if self._IsItemRoot(item): - return None - if self._IsItemProject(item): - return self._treeCtrl.GetProjectDoc(item) - if self._IsItemFile(item): - return self._treeCtrl.GetProjectDoc(self._treeCtrl.GetItemParent(item)) - return None - - - def _GetItemFile(self, item): - if self._IsItemFile(item): - return self._treeCtrl.GetLongFilename(item) + def _GetItemFilePath(self, item): + file = self._GetItemFile(item) + if file: + return file.filePath else: return None - def _GetFileItem(self, shortFileName = None, longFileName = None): - """ Returns the tree item for a file given the short (display) or long (fullpath) file name. """ - + def _GetItemFolderPath(self, item): rootItem = self._treeCtrl.GetRootItem() - (project, cookie) = self._treeCtrl.GetFirstChild(rootItem) - while project.IsOk(): - (child, cookie2) = self._treeCtrl.GetFirstChild(project) - while child.IsOk(): - if shortFileName: - if self._treeCtrl.GetItemText(child) == shortFileName: - return child - else: - if self._treeCtrl.GetLongFilename(child) == longFileName: - return child - (child, cookie2) = self._treeCtrl.GetNextChild(project, cookie2) - (project, cookie) = self._treeCtrl.GetNextChild(rootItem, cookie) - return None - - - def _IsItemRoot(self, item): - return item == self._treeCtrl.GetRootItem() - + if item == rootItem: + return "" + + if self._IsItemFile(item): + item = self._treeCtrl.GetItemParent(item) + + folderPath = "" + while item != rootItem: + if folderPath: + folderPath = self._treeCtrl.GetItemText(item) + "/" + folderPath + else: + folderPath = self._treeCtrl.GetItemText(item) + item = self._treeCtrl.GetItemParent(item) + + return folderPath - def _IsItemProject(self, item): - return self._treeCtrl.GetProjectDoc(item) != None + + def _GetItemFile(self, item): + return self._treeCtrl.GetPyData(item) def _IsItemFile(self, item): - return self._treeCtrl.GetProjectDoc(item) == None + return self._GetItemFile(item) != None def _IsItemProcessModelFile(self, item): if ACTIVEGRID_BASE_IDE: return False - + if self._IsItemFile(item): - filename = self._treeCtrl.GetLongFilename(item) + filepath = self._GetItemFilePath(item) ext = None for template in self.GetDocumentManager().GetTemplates(): if template.GetDocumentType() == ProcessModelEditor.ProcessModelDocument: @@ -1581,7 +2917,7 @@ class ProjectView(wx.lib.docview.View): if not ext: return False - if filename.endswith(ext): + if filepath.endswith(ext): return True return False @@ -1594,8 +2930,17 @@ class ProjectView(wx.lib.docview.View): children.append(child) (child, cookie) = self._treeCtrl.GetNextChild(parentItem, cookie) return children - - + + + def _GetFolderItems(self, parentItem): + folderItems = [] + childrenItems = self._GetChildItems(parentItem) + for childItem in childrenItems: + if not self._IsItemFile(childItem): + folderItems.append(childItem) + folderItems += self._GetFolderItems(childItem) + return folderItems + class ProjectFileDropTarget(wx.FileDropTarget): @@ -1604,70 +2949,129 @@ class ProjectFileDropTarget(wx.FileDropTarget): self._view = view - def OnDropFiles(self, x, y, filenames): - if self._view.DoSelectProject(x, y): - self._view.DoAddFilesToProject(filenames) - self._view.DoSelectFiles(filenames) + def OnDropFiles(self, x, y, filePaths): + """ Do actual work of dropping files into project """ + if self._view.GetDocument(): + folderPath = None + if self._view.GetMode() == ProjectView.LOGICAL_MODE: + folderItem = self._view._treeCtrl.FindClosestFolder(x,y) + if folderItem: + folderPath = self._view._GetItemFolderPath(folderItem) + self._view.DoAddFilesToProject(filePaths, folderPath) return True return False def OnDragOver(self, x, y, default): - if self._view.DoSelectProject(x,y): + """ Feedback to show copy cursor if copy is allowed """ + if self._view.GetDocument(): # only allow drop if project exists return wx.DragCopy return wx.DragNone class ProjectPropertiesDialog(wx.Dialog): + RELATIVE_TO_PROJECT_FILE = _("relative to project file") - - def __init__(self, parent, filename): + def __init__(self, parent, document): wx.Dialog.__init__(self, parent, -1, _("Project Properties"), size = (310, 330)) filePropertiesService = wx.GetApp().GetService(wx.lib.pydocview.FilePropertiesService) notebook = wx.Notebook(self, -1) + tab = wx.Panel(notebook, -1) - - gridSizer = RowColSizer() - - gridSizer.Add(wx.StaticText(tab, -1, _("Filename:")), flag=wx.RIGHT, border=HALF_SPACE, row=0, col=0) + gridSizer = wx.FlexGridSizer(cols = 2, vgap = SPACE, hgap = SPACE) + gridSizer.AddGrowableCol(1) + gridSizer.Add(wx.StaticText(tab, -1, _("Filename:"))) + filename = document.GetFilename() if os.path.isfile(filename): - gridSizer.Add(wx.StaticText(tab, -1, os.path.split(filename)[1]), row=0, col=1) + gridSizer.Add(wx.StaticText(tab, -1, os.path.split(filename)[1])) - gridSizer.Add(wx.StaticText(tab, -1, _("Location:")), flag=wx.RIGHT, border=HALF_SPACE, row=1, col=0) - gridSizer.Add(wx.StaticText(tab, -1, filePropertiesService.chopPath(os.path.split(filename)[0])), flag=wx.BOTTOM, border=SPACE, row=1, col=1) + gridSizer.Add(wx.StaticText(tab, -1, _("Location:"))) + gridSizer.Add(wx.StaticText(tab, -1, filePropertiesService.chopPath(os.path.dirname(filename), length=50))) - gridSizer.Add(wx.StaticText(tab, -1, _("Size:")), flag=wx.RIGHT, border=HALF_SPACE, row=2, col=0) - gridSizer.Add(wx.StaticText(tab, -1, str(os.path.getsize(filename)) + ' ' + _("bytes")), row=2, col=1) + gridSizer.Add(wx.StaticText(tab, -1, _("Size:"))) + gridSizer.Add(wx.StaticText(tab, -1, str(os.path.getsize(filename)) + ' ' + _("bytes"))) lineSizer = wx.BoxSizer(wx.VERTICAL) # let the line expand horizontally without vertical expansion lineSizer.Add(wx.StaticLine(tab, -1, size = (10,-1)), 0, wx.EXPAND) - gridSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=HALF_SPACE, row=3, col=0, colspan=2) + gridSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP) - gridSizer.Add(wx.StaticText(tab, -1, _("Created:")), flag=wx.RIGHT, border=HALF_SPACE, row=4, col=0) - gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getctime(filename))), row=4, col=1) + lineSizer = wx.BoxSizer(wx.VERTICAL) # let the line expand horizontally without vertical expansion + lineSizer.Add(wx.StaticLine(tab, -1, size = (10,-1)), 0, wx.EXPAND) + gridSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP) - gridSizer.Add(wx.StaticText(tab, -1, _("Modified:")), flag=wx.RIGHT, border=HALF_SPACE, row=5, col=0) - gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getmtime(filename))), row=5, col=1) + gridSizer.Add(wx.StaticText(tab, -1, _("Created:"))) + gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getctime(filename)))) - gridSizer.Add(wx.StaticText(tab, -1, _("Accessed:")), flag=wx.RIGHT, border=HALF_SPACE, row=6, col=0) - gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getatime(filename))), row=6, col=1) + gridSizer.Add(wx.StaticText(tab, -1, _("Modified:"))) + gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getmtime(filename)))) + gridSizer.Add(wx.StaticText(tab, -1, _("Accessed:"))) + gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getatime(filename)))) else: - gridSizer.Add(wx.StaticText(tab, -1, os.path.split(filename)[1] + ' ' + _("[new project]")), row=0, col=1) - - # add a border around the inside of the tab - spacerGrid = wx.BoxSizer(wx.VERTICAL) - spacerGrid.Add(gridSizer, 0, wx.ALL, SPACE); + gridSizer.Add(wx.StaticText(tab, -1, os.path.split(filename)[1] + ' ' + _("[new project]"))) + spacerGrid = wx.BoxSizer(wx.HORIZONTAL) # add a border around the inside of the tab + spacerGrid.Add(gridSizer, 1, wx.ALL|wx.EXPAND, SPACE); tab.SetSizer(spacerGrid) notebook.AddPage(tab, _("General")) + + tab = wx.Panel(notebook, -1) + spacerGrid = wx.BoxSizer(wx.VERTICAL) # add a border around the inside of the tab + homePathLabel = wx.StaticText(tab, -1, _("Home Dir:")) + if document.GetModel().isDefaultHomeDir: + defaultHomeDir = ProjectPropertiesDialog.RELATIVE_TO_PROJECT_FILE + else: + defaultHomeDir = document.GetModel().homeDir + self._homeDirCtrl = wx.ComboBox(tab, -1, defaultHomeDir, size=(125,-1), choices=[ProjectPropertiesDialog.RELATIVE_TO_PROJECT_FILE, document.GetModel().homeDir]) + self._homeDirCtrl.SetToolTipString(self._homeDirCtrl.GetValue()) + if not document.GetModel().isDefaultHomeDir: + self._homeDirCtrl.SetInsertionPointEnd() + def OnDirChanged(event): + self._homeDirCtrl.SetToolTip(wx.ToolTip(self._homeDirCtrl.GetValue())) # wx.Bug: SetToolTipString only sets it for the dropdown control, not for the text edit control, so need to replace it completely + wx.EVT_COMBOBOX(self._homeDirCtrl, -1, OnDirChanged) + wx.EVT_TEXT(self._homeDirCtrl, -1, OnDirChanged) + choosePathButton = wx.Button(tab, -1, _("Browse...")) + def OnBrowseButton(event): + if self._homeDirCtrl.GetValue() == ProjectPropertiesDialog.RELATIVE_TO_PROJECT_FILE: + defaultHomeDir = document.GetModel().homeDir + else: + defaultHomeDir = self._homeDirCtrl.GetValue() + + dlg = wx.DirDialog(self, "Choose a directory:", defaultHomeDir, + style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON) + if dlg.ShowModal() == wx.ID_OK: + self._homeDirCtrl.SetValue(dlg.GetPath()) + self._homeDirCtrl.SetInsertionPointEnd() + self._homeDirCtrl.SetToolTip(wx.ToolTip(dlg.GetPath())) # wx.Bug: SetToolTipString only sets it for the dropdown control, not for the text edit control, so need to replace it completely + dlg.Destroy() + wx.EVT_BUTTON(choosePathButton, -1, OnBrowseButton) + pathSizer = wx.BoxSizer(wx.HORIZONTAL) + pathSizer.Add(homePathLabel, 0, wx.ALIGN_CENTER_VERTICAL) + pathSizer.Add(self._homeDirCtrl, 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND|wx.LEFT, HALF_SPACE) + pathSizer.Add(choosePathButton, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, SPACE) + spacerGrid.Add(pathSizer, 0, wx.ALL|wx.EXPAND, SPACE); + instructionText = wx.StaticText(tab, -1, _("The physical view shows files relative to Home Dir.\nThe Home Dir default is the project file's directory.\nSetting the Home Dir overrides the default directory.")) + spacerGrid.Add(instructionText, 0, wx.ALL, SPACE); + tab.SetSizer(spacerGrid) + notebook.AddPage(tab, _("Physical View")) + + if not ACTIVEGRID_BASE_IDE: + tab = wx.Panel(notebook, -1) + self._appInfoCtrl = PropertyService.PropertyCtrl(tab, header=False) + self._appInfoCtrl.SetDocument(document) + self._appInfoCtrl.SetModel(document.GetAppInfo()) + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(self._appInfoCtrl, 1, wx.EXPAND) + tab.SetSizer(sizer) + notebook.AddPage(tab, _("App Info")) + if wx.Platform == "__WXMSW__": - notebook.SetPageSize((310,200)) + notebook.SetPageSize((310,300)) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(notebook, 0, wx.ALL | wx.EXPAND, SPACE) - sizer.Add(self.CreateButtonSizer(wx.OK), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE) + sizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE) self.SetSizer(sizer) sizer.Fit(self) @@ -1689,12 +3093,22 @@ class ProjectOptionsPanel(wx.Panel): if not ACTIVEGRID_BASE_IDE: self._projShowWelcomeCheckBox = wx.CheckBox(self, -1, _("Show Welcome Dialog")) self._projShowWelcomeCheckBox.SetValue(config.ReadInt("RunWelcomeDialog", True)) - projectSizer.Add(self._projShowWelcomeCheckBox, 0, wx.ALL, HALF_SPACE) + projectSizer.Add(self._projShowWelcomeCheckBox, 0, wx.ALL, HALF_SPACE) + + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(wx.StaticText(self, -1, _("Default language for projects:")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, HALF_SPACE) + self._langCtrl = wx.Choice(self, -1, choices=deploymentlib.LANGUAGE_LIST) + self._langCtrl.SetStringSelection(config.Read(APP_LAST_LANGUAGE, deploymentlib.LANGUAGE_DEFAULT)) + self._langCtrl.SetToolTipString(_("Programming language to be used throughout the project.")) + sizer.Add(self._langCtrl, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, MAC_RIGHT_BORDER) + projectSizer.Add(sizer, 0, wx.ALL, HALF_SPACE) + projectBorderSizer.Add(projectSizer, 0, wx.ALL, SPACE) self.SetSizer(projectBorderSizer) self.Layout() parent.AddPage(self, _("Project")) + def OnUseSashSelect(self, event): if not self._useSashMessageShown: msgTitle = wx.GetApp().GetAppName() @@ -1712,6 +3126,11 @@ class ProjectOptionsPanel(wx.Panel): config.WriteInt("ProjectSaveDocs", self._projSaveDocsCheckBox.GetValue()) if not ACTIVEGRID_BASE_IDE: config.WriteInt("RunWelcomeDialog", self._projShowWelcomeCheckBox.GetValue()) + config.Write(APP_LAST_LANGUAGE, self._langCtrl.GetStringSelection()) + + + def GetIcon(self): + return getProjectIcon() class ProjectService(Service.Service): @@ -1720,16 +3139,19 @@ class ProjectService(Service.Service): # Constants #---------------------------------------------------------------------------- SHOW_WINDOW = wx.NewId() # keep this line for each subclass, need unique ID for each Service - RUNPM_ID = wx.NewId() RUN_SELECTED_PM_ID = wx.NewId() RUN_CURRENT_PM_ID = wx.NewId() - ADD_FILES_TO_PROJECT_ID = wx.NewId() - ADD_CURRENT_FILE_TO_PROJECT_ID = wx.NewId() RENAME_ID = wx.NewId() OPEN_SELECTION_ID = wx.NewId() REMOVE_FROM_PROJECT = wx.NewId() DELETE_FILE_ID = wx.NewId() - ADD_ALL_FILES_TO_PROJECT_ID = wx.NewId() + ADD_FILES_TO_PROJECT_ID = wx.NewId() + ADD_CURRENT_FILE_TO_PROJECT_ID = wx.NewId() + ADD_DIR_FILES_TO_PROJECT_ID = wx.NewId() + CLOSE_PROJECT_ID = wx.NewId() + PROJECT_PROPERTIES_ID = wx.NewId() + ADD_FOLDER_ID = wx.NewId() + DELETE_PROJECT_ID = wx.NewId() #---------------------------------------------------------------------------- @@ -1740,6 +3162,10 @@ class ProjectService(Service.Service): Service.Service.__init__(self, serviceName, embeddedWindowLocation) self._runHandlers = [] self._suppressOpenProjectMessages = False + self._logicalViewDefaults = [] + self._fileTypeDefaults = [] + self._nameDefaults = [] + self._mapToProject = dict() def _CreateView(self): @@ -1795,16 +3221,36 @@ class ProjectService(Service.Service): projectMenu.Append(ProjectService.ADD_FILES_TO_PROJECT_ID, _("Add &Files to Project..."), _("Adds a document to the current project")) wx.EVT_MENU(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessEvent) wx.EVT_UPDATE_UI(frame, ProjectService.ADD_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent) - if not menuBar.FindItemById(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID): - projectMenu.Append(ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project")) - wx.EVT_MENU(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessEvent) - wx.EVT_UPDATE_UI(frame, ProjectService.ADD_ALL_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent) + if not menuBar.FindItemById(ProjectService.ADD_DIR_FILES_TO_PROJECT_ID): + projectMenu.Append(ProjectService.ADD_DIR_FILES_TO_PROJECT_ID, _("Add Directory Files to Project..."), _("Adds a directory's documents to the current project")) + wx.EVT_MENU(frame, ProjectService.ADD_DIR_FILES_TO_PROJECT_ID, frame.ProcessEvent) + wx.EVT_UPDATE_UI(frame, ProjectService.ADD_DIR_FILES_TO_PROJECT_ID, frame.ProcessUpdateUIEvent) if not menuBar.FindItemById(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID): projectMenu.Append(ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, _("&Add Active File to Project..."), _("Adds the active document to a project")) wx.EVT_MENU(frame, ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, frame.ProcessEvent) wx.EVT_UPDATE_UI(frame, ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID, frame.ProcessUpdateUIEvent) - viewMenuIndex = menuBar.FindMenu(_("&View")) - menuBar.Insert(viewMenuIndex + 1, projectMenu, _("&Project")) + if not menuBar.FindItemById(ProjectService.ADD_FOLDER_ID): + projectMenu.Append(ProjectService.ADD_FOLDER_ID, _("Add Folder to Project"), _("Adds a new folder")) + wx.EVT_MENU(frame, ProjectService.ADD_FOLDER_ID, frame.ProcessEvent) + wx.EVT_UPDATE_UI(frame, ProjectService.ADD_FOLDER_ID, frame.ProcessUpdateUIEvent) + if not menuBar.FindItemById(ProjectService.CLOSE_PROJECT_ID): + projectMenu.AppendSeparator() + projectMenu.Append(ProjectService.CLOSE_PROJECT_ID, _("Close Project"), _("Closes currently open project")) + wx.EVT_MENU(frame, ProjectService.CLOSE_PROJECT_ID, frame.ProcessEvent) + wx.EVT_UPDATE_UI(frame, ProjectService.CLOSE_PROJECT_ID, frame.ProcessUpdateUIEvent) + if not menuBar.FindItemById(ProjectService.DELETE_PROJECT_ID): + projectMenu.Append(ProjectService.DELETE_PROJECT_ID, _("Delete Project..."), _("Delete currently open project and its files.")) + wx.EVT_MENU(frame, ProjectService.DELETE_PROJECT_ID, frame.ProcessEvent) + wx.EVT_UPDATE_UI(frame, ProjectService.DELETE_PROJECT_ID, frame.ProcessUpdateUIEvent) + if not menuBar.FindItemById(ProjectService.PROJECT_PROPERTIES_ID): + projectMenu.AppendSeparator() + projectMenu.Append(ProjectService.PROJECT_PROPERTIES_ID, _("Project Properties"), _("Project Properties")) + wx.EVT_MENU(frame, ProjectService.PROJECT_PROPERTIES_ID, frame.ProcessEvent) + wx.EVT_UPDATE_UI(frame, ProjectService.PROJECT_PROPERTIES_ID, frame.ProcessUpdateUIEvent) + index = menuBar.FindMenu(_("&Format")) + if index == -1: + index = menuBar.FindMenu(_("&View")) + menuBar.Insert(index + 1, projectMenu, _("&Project")) editMenu = menuBar.GetMenu(menuBar.FindMenu(_("&Edit"))) if not menuBar.FindItemById(ProjectService.RENAME_ID): editMenu.Append(ProjectService.RENAME_ID, _("&Rename"), _("Renames the active item")) @@ -1845,47 +3291,108 @@ class ProjectService(Service.Service): return True + #---------------------------------------------------------------------------- + # Document Manager Methods + #---------------------------------------------------------------------------- + + def FindProjectFromMapping(self, key): + """ Find which project a model or document belongs to """ + return self._mapToProject.get(key) + + + def AddProjectMapping(self, key, projectDoc=None): + """ Generate a mapping from model or document to project. If no project given, use current project. + e.g. Which project does this model or document belong to (when it was opened)? + """ + if not projectDoc: + projectDoc = self.GetCurrentProject() + self._mapToProject[key] = projectDoc + + + #---------------------------------------------------------------------------- + # Default Logical View Folder Methods + #---------------------------------------------------------------------------- + + def AddLogicalViewFolderDefault(self, pattern, folder): + self._logicalViewDefaults.append((pattern, folder)) + + + def FindLogicalViewFolderDefault(self, filename): + for (pattern, folder) in self._logicalViewDefaults: + if filename.endswith(pattern): + return folder + return None + + + #---------------------------------------------------------------------------- + # Default File Type Methods + #---------------------------------------------------------------------------- + + def AddFileTypeDefault(self, pattern, type): + self._fileTypeDefaults.append((pattern, type)) + + + def FindFileTypeDefault(self, filename): + for (pattern, type) in self._fileTypeDefaults: + if filename.endswith(pattern): + return type + return None + + + #---------------------------------------------------------------------------- + # Default Name Methods + #---------------------------------------------------------------------------- + + def AddNameDefault(self, pattern, method): + self._nameDefaults.append((pattern, method)) + + + def FindNameDefault(self, filename): + for (pattern, method) in self._nameDefaults: + if filename.endswith(pattern): + return method(filename) + return None + + + def GetDefaultNameCallback(self, filename): + """ A method for generating name from filepath for Project Service """ + return os.path.splitext(os.path.basename(filename))[0] + + #---------------------------------------------------------------------------- # Event Processing Methods #---------------------------------------------------------------------------- def ProcessEventBeforeWindows(self, event): id = event.GetId() - + if id == wx.ID_CLOSE_ALL: self.OnFileCloseAll(event) return True - - elif id == wx.ID_CLOSE: - document = self.GetDocumentManager().GetCurrentDocument() - if document and document.GetDocumentTemplate().GetDocumentType() == ProjectDocument: - self.OnProjectClose(event) - return True - else: - return False return False def ProcessUpdateUIEventBeforeWindows(self, event): id = event.GetId() - + if id == wx.ID_CLOSE_ALL: for document in self.GetDocumentManager().GetDocuments(): if document.GetDocumentTemplate().GetDocumentType() != ProjectDocument: event.Enable(True) return True - + event.Enable(False) return True - + elif id == wx.ID_CLOSE: + # "File | Close" is too confusing and hard to determine whether user wants to close a viewed file or the current project. + # Disallow "File | Close" if project is current document or active in project view. + # User must explicitly close project via "Project | Close Current Project". document = self.GetDocumentManager().GetCurrentDocument() if document and document.GetDocumentTemplate().GetDocumentType() == ProjectDocument: - projectFilenames = self.GetView().GetSelectedProjects() - if projectFilenames and len(projectFilenames): - event.Enable(True) - else: - event.Enable(False) + event.Enable(False) + return True + if self.GetView().ProcessUpdateUIEvent(event): return True return False @@ -1905,7 +3412,11 @@ class ProjectService(Service.Service): elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID: self.OnAddCurrentFileToProject(event) return True - elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID: + elif (id == ProjectService.PROJECT_PROPERTIES_ID + or id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID + or id == ProjectService.ADD_FOLDER_ID + or id == ProjectService.DELETE_PROJECT_ID + or id == ProjectService.CLOSE_PROJECT_ID): if self.GetView(): return self.GetView().ProcessEvent(event) else: @@ -1919,22 +3430,27 @@ class ProjectService(Service.Service): return True id = event.GetId() - if (id == ProjectService.RUNPM_ID - or id == ProjectService.RUN_SELECTED_PM_ID + if (id == ProjectService.RUN_SELECTED_PM_ID or id == ProjectService.RUN_CURRENT_PM_ID): - event.Enable(self._HasOpenedProjects() and self._HasProcessModel()) + event.Enable(True) return True elif id == ProjectService.ADD_CURRENT_FILE_TO_PROJECT_ID: event.Enable(self._CanAddCurrentFileToProject()) return True elif (id == ProjectService.ADD_FILES_TO_PROJECT_ID - or id == ProjectService.ADD_ALL_FILES_TO_PROJECT_ID + or id == ProjectService.ADD_DIR_FILES_TO_PROJECT_ID or id == ProjectService.RENAME_ID or id == ProjectService.OPEN_SELECTION_ID or id == ProjectService.DELETE_FILE_ID): event.Enable(False) return True - elif id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID: + elif id == ProjectService.PROJECT_PROPERTIES_ID: + event.Enable(self._HasOpenedProjects()) + return True + elif (id == wx.lib.pydocview.FilePropertiesService.PROPERTIES_ID + or id == ProjectService.ADD_FOLDER_ID + or id == ProjectService.DELETE_PROJECT_ID + or id == ProjectService.CLOSE_PROJECT_ID): if self.GetView(): return self.GetView().ProcessUpdateUIEvent(event) else: @@ -1944,7 +3460,33 @@ class ProjectService(Service.Service): def OnRunProcessModel(self, event, runSelected=False, runCurrentFile=False): - project = self.GetView().GetDocument() + project = self.GetCurrentProject() + + if runCurrentFile: + doc = self.GetDocumentManager().GetCurrentDocument() + if not doc or not hasattr(doc, "GetFilename"): + return + fileToRun = doc.GetFilename() + projects = self.FindProjectByFile(fileToRun) + if not projects: + return + elif project in projects: + # use current project + pass + elif len(projects) == 1: + # only one project, display it + project = projects[0] + self.GetView().SetProject(project.GetFilename()) + elif len(projects) > 1: + strings = map(lambda file: os.path.basename(file.GetFilename()), projects) + res = wx.GetSingleChoiceIndex(_("More than one project uses '%s'. Select project to run:") % os.path.basename(fileToRun), + _("Select Project"), + strings, + self.GetView()._GetParentFrame()) + if res == -1: + return + project = projects[res] + self.GetView().SetProject(project.GetFilename()) if project: ext = None @@ -1960,11 +3502,6 @@ class ProjectService(Service.Service): return docs = wx.GetApp().GetDocumentManager().GetDocuments() - for doc in docs: - if doc.GetFilename() in files and doc.GetDocumentTemplate().GetDocumentType() == ProcessModelEditor.ProcessModelDocument: - if not doc.GetProcessModel().beginProcess: - wx.MessageBox(_("Cannot run process. No begin action found."), _("Run Process")) - return filesModified = False for doc in docs: @@ -1972,15 +3509,18 @@ class ProjectService(Service.Service): filesModified = True break if filesModified: - frame = self.GetView().GetFrame() + frame = self.GetView().GetFrame() yesNoMsg = wx.MessageDialog(frame, _("Files have been modified. Process may not reflect your current changes.\n\nWould you like to save all files before running?"), _("Run Process"), wx.YES_NO|wx.ICON_QUESTION ) - if yesNoMsg.ShowModal() == wx.ID_YES: + yesNoMsg.CenterOnParent() + status = yesNoMsg.ShowModal() + yesNoMsg.Destroy() + if status == wx.ID_YES: wx.GetTopLevelParent(frame).OnFileSaveAll(None) - + if runCurrentFile: fileToRun = self.GetDocumentManager().GetCurrentDocument().GetFilename() elif runSelected: @@ -1991,19 +3531,20 @@ class ProjectService(Service.Service): res = wx.GetSingleChoiceIndex(_("Select a process to run:"), _("Run"), strings, - project.GetFirstView()._GetParentFrame()) + self.GetView()._GetParentFrame()) if res == -1: return fileToRun = files[res] else: fileToRun = files[0] - self.RunProcessModel(fileToRun) - + deployFilePath = project.GenerateDeployment() + self.RunProcessModel(fileToRun, project.GetAppInfo().language, deployFilePath) - def RunProcessModel(self, fileToRun): + + def RunProcessModel(self, fileToRun, language, deployFilePath): for runHandler in self.GetRunHandlers(): - if runHandler.RunProjectFile(fileToRun): + if runHandler.RunProjectFile(fileToRun, language, deployFilePath): return os.system('"' + fileToRun + '"') @@ -2037,11 +3578,6 @@ class ProjectService(Service.Service): return False - def _HasCurrentFile(self): - currentDoc = self.GetDocumentManager().GetCurrentDocument() - return currentDoc - - def _CanAddCurrentFileToProject(self): currentDoc = self.GetDocumentManager().GetCurrentDocument() if not currentDoc: @@ -2050,9 +3586,8 @@ class ProjectService(Service.Service): return False if not currentDoc._savedYet: return False - for document in self.GetDocumentManager().GetDocuments(): - if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument: - return True + if self.GetView().GetDocument(): # a project is open + return True return False # There are no documents open @@ -2070,58 +3605,32 @@ class ProjectService(Service.Service): if view: return view.GetDocument() return None - + + + def GetOpenProjects(self): + retval = [] + for document in self.GetDocumentManager().GetDocuments(): + if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument: + retval.append(document) + return retval + def FindProjectByFile(self, filename): + retval = [] for document in self.GetDocumentManager().GetDocuments(): if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument: if document.GetFilename() == filename: - return document + retval.append(document) elif document.IsFileInProject(filename): - return document - return None - + retval.append(document) + return retval - def GetCurrentProjectNames(self): - projects = [] - for document in self.GetDocumentManager().GetDocuments(): - if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument: - projects.append(document) - if not projects: - return - projects.sort(lambda a, b: cmp(a.GetPrintableName().lower(), b.GetPrintableName().lower())) - strings = map(lambda project: project.GetPrintableName(), projects) - return strings - def OnAddCurrentFileToProject(self, event): - if not self._CanAddCurrentFileToProject(): - return - projects = [] - for document in self.GetDocumentManager().GetDocuments(): - if document.GetDocumentTemplate().GetDocumentType() == ProjectDocument: - projects.append(document) - if not projects: - return - projects.sort(lambda a, b: cmp(a.GetPrintableName().lower(), b.GetPrintableName().lower())) - strings = map(lambda project: project.GetPrintableName(), projects) - res = wx.GetSingleChoiceIndex(_("Select a project to add the file to:"), - _("Add to Project"), - strings, - self.GetDocumentManager().FindSuitableParent()) - if res == -1: - return file = self.GetDocumentManager().GetCurrentDocument().GetFilename() - projects[res].GetCommandProcessor().Submit(ProjectAddFilesCommand(projects[res], [file])) - self.GetView().Activate(True) # after add, should put focus on project editor - - - def OnProjectClose(self, event): - projectFilenames = self.GetView().GetSelectedProjects() - for filename in projectFilenames: - doc = self.FindProjectByFile(filename) - if doc: - self.GetDocumentManager().CloseDocument(doc, False) + document = self.GetView().GetDocument() + document.GetCommandProcessor().Submit(ProjectAddFilesCommand(document, [file])) + self.GetView().Activate() # after add, should put focus on project editor def OnFileCloseAll(self, event): @@ -2139,52 +3648,20 @@ class ProjectService(Service.Service): docString = config.Read("ProjectSavedDocs") if docString: doc = None - for fileName in eval(docString): + docList = eval(docString) + for fileName in docList: if isinstance(fileName, types.StringTypes): if os.path.exists(fileName): - doc = self.GetDocumentManager().CreateDocument(fileName, wx.lib.docview.DOC_SILENT) + doc = self.GetDocumentManager().CreateDocument(fileName, wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE) if doc: openedDocs = True - expandedString = config.Read("ProjectExpandedSavedDocs") - if expandedString: - view = doc.GetFirstView() - view.SetExpandedProjects(eval(expandedString)) - return openedDocs - - -class ProjectEditorMoveCommand(wx.lib.docview.Command): - - def __init__(self, view, newPositionItem, item): - wx.lib.docview.Command.__init__(self, canUndo = True) - self._view = view - self._item = item - self._file = view._treeCtrl.GetLongFilename(item) - if view._IsItemFile(item): - self._projectOld = view._GetItemProject(item) - else: # view._IsItemProject(item): - self._projectOld = None - self._projectNew = view._GetItemProject(newPositionItem) - - - def GetName(self): - return _("Move File %s") % os.path.basename(self._file) - - def Do(self): - if self._projectOld: - self._projectOld.RemoveFile(self._file) - if self._projectNew: - self._projectNew.AddFile(self._file) - return True + currProject = config.Read("ProjectCurrent") + if currProject in docList: + self.GetView().SetProject(currProject) - - def Undo(self): - if self._projectNew: - self._projectNew.RemoveFile(self._file) - if self._projectOld: - self._projectOld.AddFile(self._file) - return True + return openedDocs #---------------------------------------------------------------------------- @@ -2198,10 +3675,22 @@ def getProjectData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00[IDAT8\x8d\xc5\x93\xc1\n\xc00\x08C\x8d\xf6\xff\xffX\xb3Sa-\xf6`;:O\n\ -\x12\x1fj\x0059\t\xed\t\xc3\xc9pn\x0b\x88\x88@\rU\x81\xf6.\x18N\xa8aE\x92\rh\ -YC\x85\xa4D\x90\x91\xdc%\xf8w\x07+\xd1\xfbW\x98\xc5\x8f\t\x86W\xee\x93+\xbe\ -\xc0gn\xdc\x8d\x07\xab"@p\xf7\x00($W\x8c\x8f&R\xa7\xa7\xa2u\xebL.\xef\xd9\x00\x97\ +\xa7\x87D\\er\x15\x95\xb9\xf5\x12\xa3\x81Y\x9bG\xfax0\xb3Z\x8d*\x95t\x92z\ +\xb5\x80yjhC\x83\x16\x96\x15\xdc\xc3AZ\x8d\xea{XN#g.,\xa6\xe0l\x9c\xde}\x89\ +\xb6\xc3\x9aR\xff\xe5\x01\x801}\x1c\x80\x9b\xcc\x05\xde\xb0\x9f\xd0t\x04oX\ +\xa6\xad4\xc9U\n\xc0&\x1e\xfd\xd6\x0e\x18\xd4Se\x00\xbca?m\xa5\xc9\x1d\xd0V\ +\x9a\x03\xa3\xd6\xadc\xa8\x8fv\xc0S\xa3H\xc8\x13\x01\xa2\x00\xc4V\x13\x94\ +\xb3)\xae\xae\x14\x8b\xd1\x17\x90laK\x03\xb3b\xab\t&\x02\xf7(\xf94\xf2k\x8c\ +\x8d\x8dy\xc7\xf0\xb7\x00\x80`t\x92`t\x87%\xa0\x9cM\xd1\xa8}\xce\xcc\xbf\xd1\ +\x11P\xce\xa6,\xe7\xaf\xdf\xd7,Ap\x89\x14\x92+\xc6_\x03\x8e\x80\xff\xc8\xf5\ +\xaf4\xf0\x06=\xf3\x8fJr]C\xd9\x00\x00\x00\x00IEND\xaeB`\x82' def getProjectBitmap(): return BitmapFromImage(getProjectImage()) @@ -2212,19 +3701,26 @@ def getProjectImage(): def getProjectIcon(): return wx.IconFromBitmap(getProjectBitmap()) - + #---------------------------------------------------------------------------- def getBlankData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\ -\xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\ -9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\ -\x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\ -\x00\x00IEND\xaeB`\x82' +\x00\x01\x04IDAT8\x8d\xa5\x93\xbdj\x02A\x10\xc7\x7f{gme\xe5c\xe4\t\x82\x85\ +\x85\x85oa\xe5+\xd8Z\xd8'e\xfa\x80\xd8\xd8X\x19R\xc4\x07\x90\x04\xd1J\x08\ +\x17\x0cr\\V\xe1\xe4\xfc\x80\xb58\xf7\xd8\xbd\x0f\xa280\xec\xec2\xbf\xff\xce\ +\xcc\xb2B8.\xf7X\xc9\xdc|L\x97J\xc7\xbe\x0c\x01\xf0\xd6\x01\x00RFtZu\x91Q\ +\x10\x8e\x9b\xf8\xe4\xf3[-w*\xf1\xafm\xec\xcf\x83\x89\x1a\xad\x94\xea\xbe\ +\x8c\x95\x99/\x1c\x17\xe7\xdaR\xcb%xh\xd4hw_\x95yn\xb5\xe0\xcb\x90\xea%\x0eO\ +\xf1\xba\xd9\xc7\xe5\xbf\x0f\xdfX]\xda)\x140A\r\x03<6klO\xf0w\x84~\xef\xc9\ +\xca/lA\xc3@\x02\xe7\x99U\x81\xb7\x0e\xa8\xec\xed\x04\x13\xde\x1c\xfe\x11\ +\x902\xb2@\xc8\xc2\x8b\xd9\xbcX\xc0\x045\xac\xc1 Jg\xe6\x08\xe8)\xa7o\xd5\ +\xb0\xbf\xcb\nd\x86x\x0b\x9c+p\x0b\x0c\xa9\x16~\xbc_\xeb\x9d\xd3\x03\xcb3q\ +\xefo\xbc\xfa/\x14\xd9\x19\x1f\xfb\x8aa\x87\xf2\xf7\x16\x00\x00\x00\x00IEND\ +\xaeB`\x82" def getBlankBitmap(): @@ -2236,4 +3732,184 @@ def getBlankImage(): def getBlankIcon(): return wx.IconFromBitmap(getBlankBitmap()) + + +#---------------------------------------------------------------------- +def getFolderClosedData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x00\xffIDAT8\x8d\xa5\x93?N\x02A\x14\x87\xbf\x19&\x10B\xb4A\x0b*iL0!$\ +\x06\x0f\xe0\x05lH\x88G\xe1\x0c\xdbx\x11ZN`,\xa5\x01\x8aM\xa4\x80\x84\xc4Fc\ +\xd0\xe8\xb0\xae\xbbc\x01\x0b,\x19\x16X~\xd5\x9b\xf7\xe7\x9by3o\x84\x90\x19\ +\x8e\x91\x8a\x0c\xed:\x06\xc0\xf7g\x00x\xde\x14\x80\xf3\x9b\x07\xb1\x13\xa0]\ +\xc7d\xcbw\x00d\x17\x81\x82\xff\x01\xc0\xb0\xd3\x9f\x83\x7f\xf5\xb2\xe8\xaa\ +\xf1\xb4\x84\n!3h\xd71\xef\xaf=\xeb\x0e\xc5R\xcd\xea\xcfWZ"\xd6\xc2\xb6\xc4\ +\xdc\xe5\xad\xd5?h\xd7M\xb5\xd9\x15\n\xe6}{\xde\x94\xe2\xf5\xbd59I\x12V\x17\ +\x96F\n \xfc\xfbD\xaaS\xc2\x9fI:@\x041\xdf\xa3\x8d\xb0Y\xb3\xed\xaf\xa9\x00\ +\xbe\xde\xc6\x9c\x9c]\x10\xea\xc3O #\xc3\xd7:)/\x19\xb0>$\x87J\x01\x04\xc1n\ +\xc0\xcb\xf3cl]mv\xe3\x83\xb4o\xc1\xa6D\xf4\x1b\x07\xed\xba\xd9\xa7`+ \xad\ +\xfe\x01\xd1\x03SV!\xfbHa\x00\x00\x00\x00IEND\xaeB`\x82' + +def getFolderClosedBitmap(): + return BitmapFromImage(getFolderClosedImage()) + +def getFolderClosedImage(): + stream = cStringIO.StringIO(getFolderClosedData()) + return ImageFromStream(stream) + +def getFolderClosedIcon(): + return wx.IconFromBitmap(getFolderClosedBitmap()) + + +#---------------------------------------------------------------------- +def getFolderOpenData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01>IDAT8\x8d\xa5\x93\xbdJ\x03A\x14\x85\xbfY\x03i\xac\x14\x92\xc2F\xad$\ +Z\xa4\x10\x11|\x01\xc1J\xdbt\xbe\x86\x9d\x85\x0f\xa0\xe0\x1b\x04,l\xc4J\x0b\ +\x0bA;a\x11\x13\xb1H\xc2\xc2\xca\x84@\x88n\xb2\xd9?\xcd\xd8d6.\x9b\x104\xa7\ +\xbas\xef=g\xce\x9d\xe1\na\xcc1\x0b\x8c\x99\xd8@F\x07_\xd6\xb9\n\xdd\x8f\xb8\ +\xd0s\x9a\x00\xe4\xb6O\xc5T\x81~\xf5D\x89\xdc\x0e\xd9_\x85,\xa0\xa2\x06\xefw\ +R\x01\x04\x9e\x03\xc0\xea\xde\x8dH\th\xa8\xa81:\xf8\x1e\x00\xf9\x8d\x03\x00\ +\xa4U\x07\xc0,\xdb\xaaX\xaa\xc4"\x99\x04\xd9\xf7\xe0\xfbs$\x12\x0e\x90\xad\ +\x0e\x00]\xeb*N\x9b\xe5u\x05P,UD\xc2\x81&K\xbb\r@\xd4\xba\x1f\x9a\xe9\xb0\ +\xb6\x7f\x96h}\xbe8\x1c9\xe89M\x16\xfc\x15\xa4\xdd\xc6\xe8\x9a\x18\xc3\x99\ +\x97w\x8f\x99\x86\xd8\x81\xb4\xea\x18]\x93\xfcf).\x0e\\9\x96\xf4r}\x84~\x87\ +\xc4\x08\x81\xe7\xa0\xfa\xb5\xa9\xb7\xa6\x1c\xf4\xdao\xcc/B\x04\x0c<\xfb\xef\ +\x02Zd\xa9P\x98\xd8\xf8\xfax\x1b\xc7\xa9o\xf4\xbdN\x8aP{z \x0c\xdc\xb1\xa4\ +\xdf\x10z\x99\xaa\x97[J\'\xc3\xc0\x9dH\x98(\xf0_\xcc\xbc\x8d?\xf2)\x7f\x8e|f\ +\xe54\x00\x00\x00\x00IEND\xaeB`\x82' + +def getFolderOpenBitmap(): + return BitmapFromImage(getFolderOpenImage()) + +def getFolderOpenImage(): + stream = cStringIO.StringIO(getFolderOpenData()) + return ImageFromStream(stream) + +def getFolderOpenIcon(): + return wx.IconFromBitmap(getFolderOpenBitmap()) + +#---------------------------------------------------------------------- +def getLogicalModeOnData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01\x83IDAT8\x8d\xa5\x93\xcbJ\xc3@\x14\x86\xbfI\x83buS\xabE+TE\x04\x17\ +\xde\xf0\x02\x82\xa0k\x17\n.\xdc\xf9\x1e.\xf4\x05\\\t\xfa\x18\x057\xe2\x0b\ +\x08ue@\xa4`\xb0\x84J\xd0(M\xa3"\xb65\x8d5.jcbS\x14\xfdW3\xe7\xfc\xe7\x9b9\ +\xc3\x19!\xa4\x08\xff\x91\xdcXT\x8d=\xb7\xf6\\\xa5\xe2\xd8\xf5\xfd\xab\t@\ +\xdf\xfc\x81\xf8\x11PQw\xddHl\x99H\x0c\xda\xbe\x19\xce\x0f\r\x17@\xae]{\xb1\ +\xf1\r\xc5\x83\n!E\xa8\xa8\xbb\xaeuw\x11zB\xbc\x7f24\xde1\xb6%\x02-\xb42\xbe\ +\xc5\x06\xd12i\x00&V\xb6\x11m\x0e\x00\xd9\xf4\xac;\xbe\xa1\x88z\x0b\x8eM\xf5\ +\xd5$1\xb3\xd9\x048\xde\xdf!%\xe5P4\x9b\x91\xc5+:{\x86\x03y\x19\xbe\x1e\xcc\ +\xafR1\x8f\x96Ic\xe6\xb34g\xbf\x01\xfcE\x00%=\x83~z\xd4dv\nW\x94\xc2\x00o/\ +\x0f\xc8]\xdd\xb4\xd7\xee\x00\xb8<="\x9a\x8c\xd37\x90"\x9a\xd4Qo\xba1\xf3Y\ +\x00\xcf\x13z\x03\xd7\xd6\x01\x88&\xe3\x00\xdc\xdf\xea\x94\r\x8b\x94da~\xb6\ +\xea\xda\x8f\x01\x80\x04\xf0TT\x91\x9d\x1b/8:\xb7D\xd9\xb0(\x1b\x16\x8af\xa3\ +h\xf5\xe1\x8a\xf5\x04\xcek\xbe\x81_Sk\xeb\x98\xd7\x05\xf4\xf7\x02\x00\x0b\ +\xd3\x89P_K\x00@\xefP\x82\xd5\xa1za\xee\xec\x84\xa7\xa2\xea\xe5\x1a\xd3\xd8\ +\x12\x90;;\t\xec\xfd\xe3\xeb\x97h\xfc\xc6lz\xd6\xfdMAK\xc0_\xf5\x01\xf4\x01\ +\x91\xdc\xfe\x86\x9e^\x00\x00\x00\x00IEND\xaeB`\x82' + +def getLogicalModeOnBitmap(): + return BitmapFromImage(getLogicalModeOnImage()) + +def getLogicalModeOnImage(): + stream = cStringIO.StringIO(getLogicalModeOnData()) + return ImageFromStream(stream) + +#---------------------------------------------------------------------- +def getLogicalModeOffData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01\x83IDAT8\x8d\xa5\x93\xcbJ\xc3@\x14\x86\xbfI\x83buS\xabE+TE\x04\x17\ +\xde\xf0\x02\x82\xa0k\x17\n.\xdc\xf9\x1e.\xf4\x05\\\t\xfa\x18\x057\xe2\x0b\ +\x08ue@\xa4`\xb0\x84J\xd0(M\xa3"\xb65\x8d5.jcbS\x14\xfdW3\xe7\xfc\xe7\x9b9\ +\xc3\x19!\xa4\x08\xff\x91\xdcXT\x8d=\xb7\xf6\\\xa5\xe2\xd8\xf5\xfd\xab\t@\ +\xdf\xfc\x81\xf8\x11PQw\xddHl\x99H\x0c\xda\xbe\x19\xce\x0f\r\x17@\xae]{\xb1\ +\xf1\r\xc5\x83\n!E\xa8\xa8\xbb\xaeuw\x11zB\xbc\x7f24\xde1\xb6%\x02-\xb42\xbe\ +\xc5\x06\xd12i\x00&V\xb6\x11m\x0e\x00\xd9\xf4\xac;\xbe\xa1\x88z\x0b\x8eM\xf5\ +\xd5$1\xb3\xd9\x048\xde\xdf!%\xe5P4\x9b\x91\xc5+:{\x86\x03y\x19\xbe\x1e\xcc\ +\xafR1\x8f\x96Ic\xe6\xb34g\xbf\x01\xfcE\x00%=\x83~z\xd4dv\nW\x94\xc2\x00o/\ +\x0f\xc8]\xdd\xb4\xd7\xee\x00\xb8<="\x9a\x8c\xd37\x90"\x9a\xd4Qo\xba1\xf3Y\ +\x00\xcf\x13z\x03\xd7\xd6\x01\x88&\xe3\x00\xdc\xdf\xea\x94\r\x8b\x94da~\xb6\ +\xea\xda\x8f\x01\x80\x04\xf0TT\x91\x9d\x1b/8:\xb7D\xd9\xb0(\x1b\x16\x8af\xa3\ +h\xf5\xe1\x8a\xf5\x04\xcek\xbe\x81_Sk\xeb\x98\xd7\x05\xf4\xf7\x02\x00\x0b\ +\xd3\x89P_K\x00@\xefP\x82\xd5\xa1za\xee\xec\x84\xa7\xa2\xea\xe5\x1a\xd3\xd8\ +\x12\x90;;\t\xec\xfd\xe3\xeb\x97h\xfc\xc6lz\xd6\xfdMAK\xc0_\xf5\x01\xf4\x01\ +\x91\xdc\xfe\x86\x9e^\x00\x00\x00\x00IEND\xaeB`\x82' + +def getLogicalModeOffBitmap(): + return BitmapFromImage(getLogicalModeOffImage()) + +def getLogicalModeOffImage(): + stream = cStringIO.StringIO(getLogicalModeOffData()) + return ImageFromStream(stream) + +#---------------------------------------------------------------------- +def getPhysicalModeOnData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01\xabIDAT8\x8d}\x931k\xdb@\x18\x86\x9f\xb3=\x98R\xb0\x06\xc7X\x01\x1d\ +\x14\x1c\xeaA4?\xa0\xa1\x8b\x9d\x04C\xe6N\xed\xd8\xad\xbf\xc0\xbf!c\xb6@\x9d\ +\xa1\xf4\'\xd4m\xd2l\x9dJ(\xb8R\x87\x90\x84\x80\xaeD\x8e\xad\xc1\xeePBIQ\x87\ +\x8b.:+\xc9\x0b\x82\xef\xee\xd3\xf3\xde{\x1f\x9c\x10\xa52\xf7)\x99N\xd2q\x1c\ +[{\xfe\xb3U\x91_\x8bE\x83E\xa8\xe9\xba\xa6\x1e\xc71*Rx\xd2\xa3\xe9\xba\xd4\ +\x97\x1a\xa2\x92L\'i\xd6\xbc\x0bZ\xecy\xd2CE\n\x15)\x00*Y\xf3!hQ\x9e\xf4\xf8\ +vt\xa4\r\xf2\xf0}\x90L|\xae\x93\xdb\xf5E;4uEE\xca\x184]\xd72\x91\x89\x0f\xc0\ +\xe3\xf6\xaee\xf8\xe7\x83\xcf\x06\x00e\xc4`o/\r\x83\x80\x96\xf4x\xf9\xea\xb5\ +I"\x13\xbf\x00ZJF\\\xec\xef >}\x1c\xa6\x00\x07\x87_hI\x8f\x17\x9d.*R<\x7f\ +\xd43\xffZF7\xa0\xb9\xc2\xf9\xc91OV\x9e\xb2\xde\xe9Z\x07\\\'\xe0\xacip\xf6\ +\xf5\xcdm\xfc\x08\x967\xde\xeaY\xec\xef\xe8!\x9e\x9f\x1c\x03\xf0[\xfe\x85\ +\xa8\x98\xd6Y\xdb\x85d\xa4\xeb60>\x03\xe0\xe7!\x94N#E\xb5\xe6P\xad9\x06\x88\ +\'\x97\x85\xfb\xea\xe1\x9c\x198Si\xbd\xd3%\x0c\x02\xae\xe63\x1a\xf3\x86\x15\ +\xd5\x82\xf3\x9a^\xea\x0f(\xf5\xb6\xb6D\xbf\xdf\xa7Zs\x08\x83\x00\x80\xab\ +\xf9\xac\x08g\'O\xedt\x15\x80\xfaRC\x00\x84?F\xe9\xbb\xc1\x80\x96\xf4t\xb7\ +\xbezw\x82\x9c\n\x8f)\xaf_\xdb\xffR\xb8\x99z.\xc1\xc1\xfb\xef\x00l\x0e\xcb\ +\xe2A\x83L\x9f{\xda(\xd3\xe6\xb0l\x9e\xf4\x7f\x85\x1d\xb2s\xbf\x8c\xaeh\x00\ +\x00\x00\x00IEND\xaeB`\x82' + +def getPhysicalModeOnBitmap(): + return BitmapFromImage(getPhysicalModeOnImage()) + +def getPhysicalModeOnImage(): + stream = cStringIO.StringIO(getPhysicalModeOnData()) + return ImageFromStream(stream) + +#---------------------------------------------------------------------- +def getPhysicalModeOffData(): + return \ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ +\x00\x01\xabIDAT8\x8d}\x931k\xdb@\x18\x86\x9f\xb3=\x98R\xb0\x06\xc7X\x01\x1d\ +\x14\x1c\xeaA4?\xa0\xa1\x8b\x9d\x04C\xe6N\xed\xd8\xad\xbf\xc0\xbf!c\xb6@\x9d\ +\xa1\xf4\'\xd4m\xd2l\x9dJ(\xb8R\x87\x90\x84\x80\xaeD\x8e\xad\xc1\xeePBIQ\x87\ +\x8b.:+\xc9\x0b\x82\xef\xee\xd3\xf3\xde{\x1f\x9c\x10\xa52\xf7)\x99N\xd2q\x1c\ +[{\xfe\xb3U\x91_\x8bE\x83E\xa8\xe9\xba\xa6\x1e\xc71*Rx\xd2\xa3\xe9\xba\xd4\ +\x97\x1a\xa2\x92L\'i\xd6\xbc\x0bZ\xecy\xd2CE\n\x15)\x00*Y\xf3!hQ\x9e\xf4\xf8\ +vt\xa4\r\xf2\xf0}\x90L|\xae\x93\xdb\xf5E;4uEE\xca\x184]\xd72\x91\x89\x0f\xc0\ +\xe3\xf6\xaee\xf8\xe7\x83\xcf\x06\x00e\xc4`o/\r\x83\x80\x96\xf4x\xf9\xea\xb5\ +I"\x13\xbf\x00ZJF\\\xec\xef >}\x1c\xa6\x00\x07\x87_hI\x8f\x17\x9d.*R<\x7f\ +\xd43\xffZF7\xa0\xb9\xc2\xf9\xc91OV\x9e\xb2\xde\xe9Z\x07\\\'\xe0\xacip\xf6\ +\xf5\xcdm\xfc\x08\x967\xde\xeaY\xec\xef\xe8!\x9e\x9f\x1c\x03\xf0[\xfe\x85\ +\xa8\x98\xd6Y\xdb\x85d\xa4\xeb60>\x03\xe0\xe7!\x94N#E\xb5\xe6P\xad9\x06\x88\ +\'\x97\x85\xfb\xea\xe1\x9c\x198Si\xbd\xd3%\x0c\x02\xae\xe63\x1a\xf3\x86\x15\ +\xd5\x82\xf3\x9a^\xea\x0f(\xf5\xb6\xb6D\xbf\xdf\xa7Zs\x08\x83\x00\x80\xab\ +\xf9\xac\x08g\'O\xedt\x15\x80\xfaRC\x00\x84?F\xe9\xbb\xc1\x80\x96\xf4t\xb7\ +\xbezw\x82\x9c\n\x8f)\xaf_\xdb\xffR\xb8\x99z.\xc1\xc1\xfb\xef\x00l\x0e\xcb\ +\xe2A\x83L\x9f{\xda(\xd3\xe6\xb0l\x9e\xf4\x7f\x85\x1d\xb2s\xbf\x8c\xaeh\x00\ +\x00\x00\x00IEND\xaeB`\x82' + +def getPhysicalModeOffBitmap(): + return BitmapFromImage(getPhysicalModeOffImage()) + +def getPhysicalModeOffImage(): + stream = cStringIO.StringIO(getPhysicalModeOffData()) + return ImageFromStream(stream) + diff --git a/wxPython/samples/ide/activegrid/tool/PythonEditor.py b/wxPython/samples/ide/activegrid/tool/PythonEditor.py index 6496f7f58a..ea5f6b71d1 100644 --- a/wxPython/samples/ide/activegrid/tool/PythonEditor.py +++ b/wxPython/samples/ide/activegrid/tool/PythonEditor.py @@ -25,6 +25,7 @@ import keyword # for GetAutoCompleteKeywordList import sys # for GetAutoCompleteKeywordList import MessageService # for OnCheckCode import OutlineService +from UICommon import CaseInsensitiveCompare try: import checker # for pychecker _CHECKER_INSTALLED = True @@ -69,8 +70,11 @@ class PythonView(CodeEditor.CodeView): def OnActivateView(self, activate, activeView, deactiveView): STCTextEditor.TextView.OnActivateView(self, activate, activeView, deactiveView) - if activate: - wx.CallAfter(self.LoadOutline) # need CallAfter because document isn't loaded yet + if activate and self.GetCtrl(): + if self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI: + self.LoadOutline() + else: + wx.CallAfter(self.LoadOutline) # need CallAfter because document isn't loaded yet def OnClose(self, deleteWindow = True): @@ -99,7 +103,7 @@ class PythonView(CodeEditor.CodeView): filterkw = filter(lambda item: item.lower().startswith(lowerHint), kw) # remove variables and methods that don't match hint kw = filterkw - kw.sort(self.CaseInsensitiveCompare) + kw.sort(CaseInsensitiveCompare) if hint: replaceLen = len(hint) @@ -119,6 +123,7 @@ class PythonView(CodeEditor.CodeView): # pychecker only works on files, doesn't take a stream or string input if self.GetDocument().IsModified(): dlg = wx.MessageDialog(self.GetFrame(), _("'%s' has been modfied and must be saved first. Save file and check code?") % filename, _("Check Code")) + dlg.CenterOnParent() val = dlg.ShowModal() dlg.Destroy() if val == wx.ID_OK: @@ -167,7 +172,7 @@ class PythonView(CodeEditor.CodeView): break if not foundView: - doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT) + doc = wx.GetApp().GetDocumentManager().CreateDocument(filename, wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE) foundView = doc.GetFirstView() if foundView: @@ -269,11 +274,29 @@ class PythonInterpreterView(wx.lib.docview.View): return True +class PythonInterpreterDocument(wx.lib.docview.Document): + """ Generate Unique Doc Type """ + pass + + class PythonService(CodeEditor.CodeService): def __init__(self): CodeEditor.CodeService.__init__(self) + docManager = wx.GetApp().GetDocumentManager() + pythonInterpreterTemplate = wx.lib.docview.DocTemplate(docManager, + _("Python Interpreter"), + "*.Foobar", + "Foobar", + ".Foobar", + _("Python Interpreter Document"), + _("Python Interpreter View"), + PythonInterpreterDocument, + PythonInterpreterView, + flags = wx.lib.docview.TEMPLATE_INVISIBLE, + icon = getPythonIcon()) + docManager.AssociateTemplate(pythonInterpreterTemplate) def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None): @@ -308,7 +331,7 @@ class PythonService(CodeEditor.CodeService): docManager = wx.GetApp().GetDocumentManager() event.Check(False) for doc in docManager.GetDocuments(): - if isinstance(doc.GetFirstView(), PythonInterpreterView): + if isinstance(doc, PythonInterpreterDocument): event.Check(True) break return True @@ -318,28 +341,20 @@ class PythonService(CodeEditor.CodeService): def OnViewPythonInterpreter(self, event): for doc in wx.GetApp().GetDocumentManager().GetDocuments(): - if isinstance(doc.GetFirstView(), PythonInterpreterView): - doc.GetFirstView().GetDocument().DeleteAllViews() + if isinstance(doc, PythonInterpreterDocument): + doc.DeleteAllViews() return - docManager = self.GetDocumentManager() - template = wx.lib.docview.DocTemplate(docManager, - _("Python Interpreter"), - "*.Foobar", - "Foobar", - ".Foobar", - _("Python Interpreter Document"), - _("Python Interpreter View"), - wx.lib.docview.Document, - PythonInterpreterView, - flags = wx.lib.docview.TEMPLATE_INVISIBLE) - newDoc = template.CreateDocument('', wx.lib.docview.DOC_SILENT) - if newDoc: - newDoc.SetDocumentName(template.GetDocumentName()) - newDoc.SetDocumentTemplate(template) - newDoc.OnNewDocument() - newDoc.SetWriteable(False) - newDoc.GetFirstView().GetFrame().SetTitle(_("Python Interpreter")) + for template in self.GetDocumentManager().GetTemplates(): + if template.GetDocumentType() == PythonInterpreterDocument: + newDoc = template.CreateDocument('', wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE) + if newDoc: + newDoc.SetDocumentName(template.GetDocumentName()) + newDoc.SetDocumentTemplate(template) + newDoc.OnNewDocument() + newDoc.SetWriteable(False) + newDoc.GetFirstView().GetFrame().SetTitle(_("Python Interpreter")) + break class PythonCtrl(CodeEditor.CodeCtrl): @@ -355,7 +370,7 @@ class PythonCtrl(CodeEditor.CodeCtrl): def SetViewDefaults(self): - CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Python", hasWordWrap = False, hasTabs = True) + CodeEditor.CodeCtrl.SetViewDefaults(self, configPrefix = "Python", hasWordWrap = True, hasTabs = True) def GetFontAndColorFromConfig(self): @@ -544,40 +559,56 @@ class PythonOptionsPanel(wx.Panel): choosePathButton = wx.Button(self, -1, _("Browse...")) pathSizer = wx.BoxSizer(wx.HORIZONTAL) HALF_SPACE = 5 - pathSizer.Add(pathLabel, 0, wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, HALF_SPACE) - pathSizer.Add(self._pathTextCtrl, 0, wx.ALIGN_LEFT | wx.EXPAND | wx.RIGHT, HALF_SPACE) - pathSizer.Add(choosePathButton, 0, wx.ALIGN_RIGHT | wx.LEFT, HALF_SPACE) + SPACE = 10 + pathSizer.Add(pathLabel, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.TOP, HALF_SPACE) + pathSizer.Add(self._pathTextCtrl, 1, wx.EXPAND|wx.LEFT|wx.TOP, HALF_SPACE) + pathSizer.Add(choosePathButton, 0, wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT|wx.TOP, HALF_SPACE) wx.EVT_BUTTON(self, choosePathButton.GetId(), self.OnChoosePath) mainSizer = wx.BoxSizer(wx.VERTICAL) - mainSizer.Add(pathSizer, 0, wx.LEFT | wx.RIGHT | wx.TOP, 10) + mainSizer.Add(pathSizer, 0, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, SPACE) - self._otherOptions = STCTextEditor.TextOptionsPanel(self, -1, configPrefix = "Python", label = "Python", hasWordWrap = False, hasTabs = True, addPage=False) - mainSizer.Add(self._otherOptions) + self._otherOptions = STCTextEditor.TextOptionsPanel(self, -1, configPrefix = "Python", label = "Python", hasWordWrap = True, hasTabs = True, addPage=False) + mainSizer.Add(self._otherOptions, 0, wx.EXPAND|wx.BOTTOM, SPACE) self.SetSizer(mainSizer) parent.AddPage(self, _("Python")) + def OnChoosePath(self, event): + defaultDir = os.path.dirname(self._pathTextCtrl.GetValue().strip()) + defaultFile = os.path.basename(self._pathTextCtrl.GetValue().strip()) if _WINDOWS: - wildcard = _("*.exe") + wildcard = _("Executable (*.exe)|*.exe|All (*.*)|*.*") + if not defaultFile: + defaultFile = "python.exe" else: wildcard = _("*") - path = wx.FileSelector(_("Select a File"), - _(""), - _(""), - wildcard = wildcard , - flags = wx.HIDE_READONLY, - parent = wx.GetApp().GetTopWindow()) - if path: - self._pathTextCtrl.SetValue(path) - self._pathTextCtrl.SetToolTipString(self._pathTextCtrl.GetValue()) - self._pathTextCtrl.SetInsertionPointEnd() + dlg = wx.FileDialog(wx.GetApp().GetTopWindow(), + _("Select a File"), + defaultDir=defaultDir, + defaultFile=defaultFile, + wildcard=wildcard, + style=wx.OPEN|wx.FILE_MUST_EXIST|wx.HIDE_READONLY) + # dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog + if dlg.ShowModal() == wx.ID_OK: + path = dlg.GetPath() + if path: + self._pathTextCtrl.SetValue(path) + self._pathTextCtrl.SetToolTipString(self._pathTextCtrl.GetValue()) + self._pathTextCtrl.SetInsertionPointEnd() + dlg.Destroy() + def OnOK(self, optionsDialog): - if len(self._pathTextCtrl.GetValue()) > 0: - config = wx.ConfigBase_Get() - config.Write("ActiveGridPythonLocation", self._pathTextCtrl.GetValue()) + config = wx.ConfigBase_Get() + config.Write("ActiveGridPythonLocation", self._pathTextCtrl.GetValue().strip()) self._otherOptions.OnOK(optionsDialog) + + + def GetIcon(self): + return getPythonIcon() + + #---------------------------------------------------------------------------- # Icon Bitmaps - generated by encode_bitmaps.py #---------------------------------------------------------------------------- @@ -587,18 +618,28 @@ import cStringIO def getPythonData(): return \ -"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00\xd5IDAT8\x8d\x8d\x93Y\x0e\xc3 \x0cD\x9fM\xcf\xddNr2.\x96\xb8\x1f\ -\x05\n\x84.#Y\x10\xa3\x19o\xb1\x99'*\xe2<\x82\x0e\xe6\xc9\xf8\x01\xef?\xa4\ -\xf7)]\x05\x970O\xcdr\xce!\x119\xe7\x00\x02\x88\xfe}i\xb5\x848\x8f\xa8\x19\ -\xcc\x19}+\xc5\xcc\xd3\x92\x18\x0f\xb8\xb7\x95a\xe9\xca\x0b:\x8e\xed\ +\xca\x01E\x1a\x00\x98\r\x89\x92\x91\xa1\xda\xd8\x87\x06ha\x1f\x1b\x80\xcd\ +\x9d%\xe0\xa5\x0f"[G\x87\x98\x8d\xde/ia\x05-\xac`\x996\xf9\\\x0b\xcb\xb4)\ +\x1bmOMn\xf7\xd5\xf0\'\\\x8b\xdces\xe7\x8d\xef\x80h\xd6\xc2\n\xf9\\\x0b]\xf5\ +\xab\xf2\xcdApR#\xf1kp4b\xc9 \xf9\\\x0b\x80\xe4\xcdE\xaf\xdeqlW\xaeVL\xaf`~\ +\xd9\x03@W\xd3\x00\xc4\x13\x0b\xc4\x92A\xcf\xd0\xf9\xe8:\x89\xebW\x01(|\xfd\ +\xe1\xbe-~F\xbas\xff\x91\xf75\x82n\x9d\x1c\xf0}\xfciw\xdd\xe7A<\xd1\x1b\xa8j\ +c\x9f\xb2\xd1F\x92\xe4\x80O\x12\xc0\xc6\xb3\x14\xf6Ta\xe0)g\x81\xba\x9a\xf6\ +\x9b(\x07\x14I@\x84lq\xb8?\xe6\xa3\xeb\x00\xdc\xba\x9d\xf4+\x10*~\xfem\xf3\ +\xf8\xe1\x06\xc7\xa7\xdb\xe8j\x9a\xf8\xdc\xa4\xb7\x1f[\\\xe5\xd2\x851/\xff\ +\x07\xac\x9b\xd1e\x12\x96\x0f\xfd\x00\x00\x00\x00IEND\xaeB`\x82' def getPythonBitmap(): diff --git a/wxPython/samples/ide/activegrid/tool/STCTextEditor.py b/wxPython/samples/ide/activegrid/tool/STCTextEditor.py index 549c708c23..fd9b84a91a 100644 --- a/wxPython/samples/ide/activegrid/tool/STCTextEditor.py +++ b/wxPython/samples/ide/activegrid/tool/STCTextEditor.py @@ -80,6 +80,13 @@ class TextDocument(wx.lib.docview.Document): pass +# Use this to override MultiClient.Select to prevent yellow background. +def MultiClientSelectBGNotYellow(a): + a.GetParent().multiView.UnSelect() + a.selected = True + #a.SetBackgroundColour(wx.Colour(255,255,0)) # Yellow + a.Refresh() + class TextView(wx.lib.docview.View): MARKER_NUM = 0 MARKER_MASK = 0x1 @@ -102,6 +109,12 @@ class TextView(wx.lib.docview.View): def GetCtrl(self): + if wx.Platform == "__WXMAC__": + # look for active one first + self._textEditor = self._GetActiveCtrl(self._dynSash) + if self._textEditor == None: # it is possible none are active + # look for any existing one + self._textEditor = self._FindCtrl(self._dynSash) return self._textEditor @@ -116,9 +129,19 @@ class TextView(wx.lib.docview.View): def OnCreate(self, doc, flags): frame = wx.GetApp().CreateDocumentFrame(self, doc, flags, style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE) - self._dynSash = wx.gizmos.DynamicSashWindow(frame, -1, style=wx.CLIP_CHILDREN) - self._dynSash._view = self - self._textEditor = self.GetCtrlClass()(self._dynSash, -1, style=wx.NO_BORDER) + # wxBug: DynamicSashWindow doesn't work on Mac, so revert to + # multisash implementation + if wx.Platform == "__WXMAC__": + wx.lib.multisash.MultiClient.Select = MultiClientSelectBGNotYellow + self._dynSash = wx.lib.multisash.MultiSash(frame, -1) + self._dynSash.SetDefaultChildClass(self.GetCtrlClass()) # wxBug: MultiSash instantiates the first TextCtrl with this call + + self._textEditor = self.GetCtrl() # wxBug: grab the TextCtrl from the MultiSash datastructure + else: + self._dynSash = wx.gizmos.DynamicSashWindow(frame, -1, style=wx.CLIP_CHILDREN) + self._dynSash._view = self + self._textEditor = self.GetCtrlClass()(self._dynSash, -1, style=wx.NO_BORDER) + wx.EVT_LEFT_DOWN(self._textEditor, self.OnLeftClick) self._CreateSizer(frame) self.Activate() frame.Show(True) @@ -130,14 +153,18 @@ class TextView(wx.lib.docview.View): sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(self._dynSash, 1, wx.EXPAND) frame.SetSizer(sizer) - frame.SetAutoLayout(True) + + + def OnLeftClick(self, event): + self.Activate() + event.Skip() def OnUpdate(self, sender = None, hint = None): if hint == "ViewStuff": self.GetCtrl().SetViewDefaults() elif hint == "Font": - font, color = self.GetFontAndColorFromConfig() + font, color = self.GetCtrl().GetFontAndColorFromConfig() self.GetCtrl().SetFont(font) self.GetCtrl().SetFontColor(color) @@ -195,7 +222,7 @@ class TextView(wx.lib.docview.View): self.GetCtrl().SetViewEOL(not self.GetCtrl().GetViewEOL()) return True elif id == VIEW_INDENTATION_GUIDES_ID: - self.GetCtrl().SetViewIndentationGuides(not self.GetCtrl().GetViewIndentationGuides()) + self.GetCtrl().SetIndentationGuides(not self.GetCtrl().GetIndentationGuides()) return True elif id == VIEW_RIGHT_EDGE_ID: self.GetCtrl().SetViewRightEdge(not self.GetCtrl().GetViewRightEdge()) @@ -352,6 +379,29 @@ class TextView(wx.lib.docview.View): def _GetParentFrame(self): return wx.GetTopLevelParent(self.GetFrame()) + def _GetActiveCtrl(self, parent): + """ Walk through the MultiSash windows and find the active Control """ + if isinstance(parent, wx.lib.multisash.MultiClient) and parent.selected: + return parent.child + if hasattr(parent, "GetChildren"): + for child in parent.GetChildren(): + found = self._GetActiveCtrl(child) + if found: + return found + return None + + + def _FindCtrl(self, parent): + """ Walk through the MultiSash windows and find the first TextCtrl """ + if isinstance(parent, self.GetCtrlClass()): + return parent + if hasattr(parent, "GetChildren"): + for child in parent.GetChildren(): + found = self._FindCtrl(child) + if found: + return found + return None + #---------------------------------------------------------------------------- # Methods for TextDocument to call @@ -401,6 +451,7 @@ class TextView(wx.lib.docview.View): data.SetInitialFont(self.GetCtrl().GetFont()) data.SetColour(self.GetCtrl().GetFontColor()) fontDialog = wx.FontDialog(self.GetFrame(), data) + fontDialog.CenterOnParent() if fontDialog.ShowModal() == wx.ID_OK: data = fontDialog.GetFontData() self.GetCtrl().SetFont(data.GetChosenFont()) @@ -614,7 +665,13 @@ class TextView(wx.lib.docview.View): else: return False - + def GetMarkerLines(self, mask=MARKER_MASK): + retval = [] + for lineNum in range(self.GetCtrl().GetLineCount()): + if self.GetCtrl().MarkerGet(lineNum) & mask: + retval.append(lineNum) + return retval + def GetMarkerCount(self): return self._markerCount @@ -807,9 +864,9 @@ class TextOptionsPanel(wx.Panel): textPanelSizer = wx.BoxSizer(wx.VERTICAL) textFontSizer = wx.BoxSizer(wx.HORIZONTAL) textFontSizer.Add(fontLabel, 0, wx.ALIGN_LEFT | wx.RIGHT | wx.TOP, HALF_SPACE) - textFontSizer.Add(self._sampleTextCtrl, 0, wx.ALIGN_LEFT | wx.EXPAND | wx.RIGHT, HALF_SPACE) + textFontSizer.Add(self._sampleTextCtrl, 1, wx.ALIGN_LEFT | wx.EXPAND | wx.RIGHT, HALF_SPACE) textFontSizer.Add(chooseFontButton, 0, wx.ALIGN_RIGHT | wx.LEFT, HALF_SPACE) - textPanelSizer.Add(textFontSizer, 0, wx.ALL, HALF_SPACE) + textPanelSizer.Add(textFontSizer, 0, wx.ALL|wx.EXPAND, HALF_SPACE) if self._hasWordWrap: textPanelSizer.Add(self._wordWrapCheckBox, 0, wx.ALL, HALF_SPACE) textPanelSizer.Add(self._viewWhitespaceCheckBox, 0, wx.ALL, HALF_SPACE) @@ -823,7 +880,7 @@ class TextOptionsPanel(wx.Panel): textIndentWidthSizer.Add(indentWidthLabel, 0, wx.ALIGN_LEFT | wx.RIGHT | wx.TOP, HALF_SPACE) textIndentWidthSizer.Add(self._indentWidthChoice, 0, wx.ALIGN_LEFT | wx.EXPAND, HALF_SPACE) textPanelSizer.Add(textIndentWidthSizer, 0, wx.ALL, HALF_SPACE) - textPanelBorderSizer.Add(textPanelSizer, 0, wx.ALL, SPACE) + textPanelBorderSizer.Add(textPanelSizer, 0, wx.ALL|wx.EXPAND, SPACE) ## styleButton = wx.Button(self, -1, _("Choose Style...")) ## wx.EVT_BUTTON(self, styleButton.GetId(), self.OnChooseStyle) ## textPanelBorderSizer.Add(styleButton, 0, wx.ALL, SPACE) @@ -856,6 +913,7 @@ class TextOptionsPanel(wx.Panel): ## #'HTML', 'html', ## #'XML', 'xml', ## config) +## dlg.CenterOnParent() ## try: ## dlg.ShowModal() ## finally: @@ -868,6 +926,7 @@ class TextOptionsPanel(wx.Panel): data.SetInitialFont(self._textFont) data.SetColour(self._textColor) fontDialog = wx.FontDialog(self, data) + fontDialog.CenterOnParent() if fontDialog.ShowModal() == wx.ID_OK: data = fontDialog.GetFontData() self._textFont = data.GetChosenFont() @@ -909,6 +968,10 @@ class TextOptionsPanel(wx.Panel): document.UpdateAllViews(hint = "ViewStuff") if doFontUpdate: document.UpdateAllViews(hint = "Font") + + + def GetIcon(self): + return getTextIcon() class TextCtrl(wx.stc.StyledTextCtrl): @@ -958,8 +1021,27 @@ class TextCtrl(wx.stc.StyledTextCtrl): self.SetFontColor(color) self.MarkerDefineDefault() + # for multisash initialization + if isinstance(parent, wx.lib.multisash.MultiClient): + while parent.GetParent(): + parent = parent.GetParent() + if hasattr(parent, "GetView"): + break + if hasattr(parent, "GetView"): + textEditor = parent.GetView()._textEditor + if textEditor: + doc = textEditor.GetDocPointer() + if doc: + self.SetDocPointer(doc) + def OnFocus(self, event): + # wxBug: On Mac, the STC control may fire a focus/kill focus event + # on shutdown even if the control is in an invalid state. So check + # before handling the event. + if self.IsBeingDeleted(): + return + self.SetSelBackground(1, "BLUE") self.SetSelForeground(1, "WHITE") if hasattr(self, "_dynSash"): @@ -968,6 +1050,11 @@ class TextCtrl(wx.stc.StyledTextCtrl): def OnKillFocus(self, event): + # wxBug: On Mac, the STC control may fire a focus/kill focus event + # on shutdown even if the control is in an invalid state. So check + # before handling the event. + if self.IsBeingDeleted(): + return self.SetSelBackground(0, "BLUE") self.SetSelForeground(0, "WHITE") self.SetSelBackground(1, "#C0C0C0") @@ -1328,13 +1415,21 @@ import cStringIO def getTextData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00`IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\xa7JU!$\x12\x1d\ -\xeb\t\t8n\x81\xb4\x86J\xfa]h\x0ee\x83\xb4\xc6\x14\x00\x00R\xcc \t\xcd\xa1\ -\x08\xd2\xa3\xe1\x08*\t$\x1d\xc4\x012\x0b\x00\xce\xe4\xc8\xe0\t}\xf7\x8f\rV\ -\xd9\x1a\xec\xe0\xbf\xc1\xd7\x06\xd9\xf5UX\xfdF+m\x03\xb8\x00\xe4\xc74B"x\ -\xf1\xf4\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x015IDAT8\x8d\xad\x90\xb1N\xc2P\x14\x86\xbf\x02/\xe0\xec#\x18g\xc3\xe6T\ +\x13':1\x18H\x98\x14\x12\x17G\x177\x17\x9c4a\xc5\xc0d0\xc2\xccdLx\x02^@+\t\ +\xc1\x90\xf6r\xdb\xc6\x94\xe5:\\\xdbP)\xc5DOr\x92\x9b{\xff\xfb\xfd\xff9\xc6h\ +l+\xbek.\x02\x00\xec\x99\x03\x80\xeb\xf8\\\x9d\x1d\x1bd\xd5hl\xab\xd7O\x15\ +\xf7x\xa1\xfb\xeeq\xa4^>\x94\xba\xb8yRF.\xcf\xa6.D\xa0Nw\x18C\xad\xb2\x19\ +\x9f\x0f\xca\x165\xd1V\xed\xebZj\x92\xc2\\\x04\xec\x02\xd5\x8a\x89\xb7\xd4\ +\x97n\xa8\xe3?\x0f\x86\x08\x19dNP\x00\xf0\x96\xd0\x7f\xd0\t\x84\x0c(U-\x0eK&\ +\xd3P\x8bz\xcdV6 \x8a\xed\x86\x99f\xe9\x00{\xe6\xb0\x13\xc2\xa0\xd3\xd7\t\ +\x84\x9f\x10\xec\x9dTp\x1d\xb1=A\xa9j\x01\xc4\xb1\x01&\xfe\x9a~\x1d\xe0:Zu\ +\x7f\xdb\x05@J/!(\xd6\x1bL\xde\xec\xcd\x00!\x03\xa6!\x1c\x9dVR\x9d\xdf\xe5\ +\x96\x04\xd1au\xd3\xab3\xef\x9f_f\x03\xa2\xa5\x15\xeb\x8d\xc4\xc36\xe7\x18 \ +\xa5G\xaf\xd9J\xb8f\xcd\xfc\xb3\x0c#\x97\xff\xb58\xadr\x7f\xfa\xfd\x1f\x80/\ +\x04\x1f\x8fW\x0e^\xc3\x12\x00\x00\x00\x00IEND\xaeB`\x82" def getTextBitmap(): @@ -1356,12 +1451,20 @@ def getZoomInData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00wIDAT8\x8d\xa5\x93Q\x12\x80 \x08D\xb5\xe9X\xee\xe9\xb7{\xd5Gc\xa9\ -\xacX\xca\x1f\xa0\x8fE0\x92<\xc3\x82\xed*\x08\xa0\xf2I~\x07\x000\x17T,\xdb\ -\xd6;\x08\xa4\x00\xa4GA\xab\xca\x00\xbc*\x1eD\xb4\x90\xa4O\x1e\xe3\x16f\xcc(\ -\xc8\x95F\x95\x8d\x02\xef\xa1n\xa0\xce\xc5v\x91zc\xacU\xbey\x03\xf0.\xa8\xb8\ -\x04\x8c\xac\x04MM\xa1lA\xfe\x85?\x90\xe5=X\x06\\\xebCA\xb3Q\xf34\x14\x00\ -\x00\x00\x00IEND\xaeB`\x82' +\x00\x01TIDAT8\x8d\x8d\x93\xbbJ\x03A\x14\x86\xbf\xd9,\xc6\xd8E%`)VF[{\xc1v\ +\xf1\x82\x8f\xb0\xb94\xda\xa5\x13\x11\x8b`\xa9h\x10F\xe3#H.\xa6\x15\xccKhg\ +\x10\xc1B\x8bTF\x90\xc0X\x8c3\xbb\xd9\xcdF\x7f\x18\xf6\xec\x9cs\xbe\xfd\xe70\ ++\x84\x93"\xacb\xc1W\xe1\xf7\xeb\xfa\x8d`\x82\xdcXcI\x8e\x02AM\x02\t\xe1\xa4\ +(\x16|uz)y\x19\xc0\xc9\xdd;\x99\xee!\x00\xd9\xbd\x00\xd6\xaf\x95\xc7B\xac\ +\x03\xd3\x1c\xd6\xc2t\x10\xf7\x13\x8e\xe0\x14\x0b\xbe\xa2$m\xf3\xca\xea\xacM\ +\xe6\xd2\xc1\xcaWdl>#\x0e\x8c\xed\xe7n\x90|\xa8\x96m\xbc~ y\x04Z\xcd\x86\xda\ +\xda\xde\xb1Gq\x00\xb2S\t\xfeB\x9aK\xa8\xb1\x0e\xf2\x15I.\xad\x0bo\x8f\xf4\ +\x97\xab\xe7z\x88\x1f\xdf\xf0\xfa9\x1e\xe0x\x9eG\xbf\x16X\xcd\xb8Ar\xc6\xd5\ +\x0b4\xd4\xf3\xbcd\x07F_\xc3 \x1e\x0c\xa3Y\x08\x9f\x1f~\xefA\xab\xd9P\x9dN\ +\x07\x80\xddcI\xc6\x85\xf9\xb4.8\xabhwK\xbd+6\x16\xf5\xdeZ=%F\x00\xa0\xa7\ +\x0b`@F\xc6\xf6\xd3\xc5&@\x0c"\xa2\xff\x82\x01\x85-\xb7\x9a\re\x00QH\x0c0N\ +\x06\x1a\x85\xbcym}\x0f\xfe\x92\x19\xdc\xf2~\xdb\xee\xdd\xf7\xf4\xf3_\x0e\ +\xa2N\xc2\xfa\x01MYp\xbc\xe4a\x0f\xa9\x00\x00\x00\x00IEND\xaeB`\x82' def getZoomInBitmap(): return BitmapFromImage(getZoomInImage()) @@ -1375,11 +1478,20 @@ def getZoomOutData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00qIDAT8\x8d\xa5\x92Q\x0e\xc0 \x08C-z\xff\x13O\xd9\xd7\x16"\x05\x8d\ -\xf6O\xa2\x8f"\x05\xa4\x96\x1b5V\xd4\xd1\xd5\x9e!\x15\xdb\x00\x1d]\xe7\x07\ -\xac\xf6Iv.B*fW\x0e\x90u\xc9 d\x84\x87v\x82\xb4\xf5\x08\'r\x0e\xa2N\x91~\x07\ -\xd9G\x95\xe2W\xeb\x00\x19\xc4\xd6\\FX\x12\xa3 \xb1:\x05\xacdAG[\xb0y9r`u\ -\x9d\x83k\xc0\x0b#3@0A\x0c"\x93\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x01RIDAT8\x8d\x8d\x93\xbbJ\x03A\x14\x86\xbf\xd9\x04\x93\x90J\x0cj#Dl\ +\xf4\x01\xec\x05\xdb\xc5\x0b>B\x92]\x1b+\xed,D\xb0\xb4\x08\x9afc|\x04\xc9\ +\x85\xb4>\x84\x95`\x93\x80`\x15\xd8*\x98\x84\xc0X\xcc\xce\xde7\xf8\xc30\x97=\ +\xf3\xcd\x7f\xce\xcc\na\xe4\x08\xabQ\xaf\xc9\xf0\xfc\xa5\xf3*X\xa1|b\xa3\xe5\ +D\x81 W\x81\x840r4\xea5\xf9\xf0\xe40Y@\xf3+\xf8\xb8\xbe\x16\x8c\xdd\x96\x9d\ +\n1\xf4\xc0\xdf\xdc\xb6\x01\xa8\xca\x19[\x05\xfc\x96%aY\x96\x0c\xdb\xae\xca\ +\x99\xea7\x8b\x91@w.\xf9x\xbcL\xb8\xf0k\xa0O\x1e{\xd31Q\x1d\xdd\xaaC\xfa\xbd\ +\xae<=;\xf7!F<\xd7,md\xc4\xf8\x0e\xf6\xaf\x1d\xb6\x8b*p\xa7\x0c\x95\xd0\x86\ +\xc9\x02\xbe\xa7\xe9\x00\xc34M\xdc\x96MA\xa8[,y\xc8r>h\x00ow6\xa6if;\x98K\ +\x95\xd6\xef\x12(\xc0t\x99~b8\x7f\xf0\xdeA\xbf\xd7\x95\xc3\xe1\x10\x80\x8b{\ +\x87R\x1e*\xde\xd55oTq\xf7Fm\x8ew\xd5\xdaa\'\'"\x00P\xd5\x05\xd0 -m\xfb\xf3\ +\xf9\x04 \x01\x11\xf1\x7fA\x83\xc2\x96\xfb\xbd\xae\xd4\x808$\x01H\x93\x86\ +\xc6!?\xe6 x\xca\xab\xa4\x0bwp5\xf0\xd7\xdeG\xaa\xff\x97\x83\xb8\x93\xb0\xfe\ +\x00\xc3\xa8ov\xfd\xe4\x9c\xa2\x00\x00\x00\x00IEND\xaeB`\x82' def getZoomOutBitmap(): diff --git a/wxPython/samples/ide/activegrid/tool/SVNService.py b/wxPython/samples/ide/activegrid/tool/SVNService.py index 9d35ad0ce9..785acf3866 100644 --- a/wxPython/samples/ide/activegrid/tool/SVNService.py +++ b/wxPython/samples/ide/activegrid/tool/SVNService.py @@ -99,6 +99,7 @@ class SVNService(wx.lib.pydocview.DocService): _("Comment"), _("SVN Log Message")) + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: retcode = True message = dlg.GetValue() @@ -141,11 +142,12 @@ class SVNService(wx.lib.pydocview.DocService): dlg.Fit() dlg.Layout() + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: retcode = True username = usernameTxt.GetValue().strip() password = passwordTxt.GetValue() - save = savePasswordCheckBox.IsChecked() + save = savePasswordCheckbox.IsChecked() else: retcode = False username = None @@ -195,6 +197,7 @@ class SVNService(wx.lib.pydocview.DocService): acceptedFailures = 0 save = False + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: cert = certRadio.GetStringSelection() if cert == _("Accept Always"): @@ -206,6 +209,7 @@ class SVNService(wx.lib.pydocview.DocService): acceptedFailures = trustDict.get('failures') save = False + dlg.Destroy() return retcode, acceptedFailures, save @@ -238,10 +242,11 @@ class SVNService(wx.lib.pydocview.DocService): dlg.Fit() dlg.Layout() + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: retcode = True password = passwordTxt.GetValue() - save = savePasswordCheckBox.IsChecked() + save = savePasswordCheckbox.IsChecked() else: retcode = False password = None @@ -253,10 +258,11 @@ class SVNService(wx.lib.pydocview.DocService): def SSLClientCert(self): dlg = wx.FileDialog(wx.GetApp().GetTopWindow(), - message="Choose certificate", defaultDir=os.getcwd(), - style=wx.OPEN|wx.CHANGE_DIR + message="Choose certificate", + style=wx.OPEN|wx.FILE_MUST_EXIST|wx.CHANGE_DIR ) + # dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog if dlg.ShowModal() == wx.ID_OK: retcode = True certfile = dlg.GetPath() @@ -321,8 +327,14 @@ class SVNService(wx.lib.pydocview.DocService): if id == SVNService.SVN_UPDATE_ID: wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) - filenames = self.GetCurrentDocuments()[:] - filenames.sort(self.BasenameCaseInsensitiveCompare) + filenames = self.GetCurrentDocuments() + if filenames: + filenames = filenames[:] + filenames.sort(self.BasenameCaseInsensitiveCompare) + else: + folderPath = self.GetCurrentFolder() + if folderPath: + filenames = [folderPath] messageService = wx.GetApp().GetService(MessageService.MessageService) messageService.ShowWindow() @@ -346,7 +358,10 @@ class SVNService(wx.lib.pydocview.DocService): _("Updated file '%s' is currently open. Close it?") % os.path.basename(filename), _("Close File"), wx.YES_NO|wx.ICON_QUESTION) - if yesNoMsg.ShowModal() == wx.ID_YES: + yesNoMsg.CenterOnParent() + status = yesNoMsg.ShowModal() + yesNoMsg.Destroy() + if status == wx.ID_YES: doc.DeleteAllViews() break else: @@ -377,8 +392,8 @@ class SVNService(wx.lib.pydocview.DocService): view.ClearLines() view.AddLines(_("SVN Update:\n")) - projects = self.GetCurrentProjects() - for project in projects: + project = self.GetCurrentProject() + if project: openDocs = wx.GetApp().GetDocumentManager().GetDocuments() for doc in openDocs: if doc.GetFilename() == project: @@ -400,7 +415,9 @@ class SVNService(wx.lib.pydocview.DocService): _("Updated file '%s' is currently open. Close it?") % os.path.basename(filename), _("Close File"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) + yesNoMsg.CenterOnParent() status = yesNoMsg.ShowModal() + yesNoMsg.Destroy() if status == wx.ID_YES: doc.DeleteAllViews() elif status == wx.ID_NO: @@ -428,8 +445,8 @@ class SVNService(wx.lib.pydocview.DocService): elif id == SVNService.SVN_CHECKIN_ALL_ID: filenames = [] - projects = self.GetCurrentProjects() - for project in projects: + project = self.GetCurrentProject() + if project: openDocs = wx.GetApp().GetDocumentManager().GetDocuments() for doc in openDocs: if doc.GetFilename() == project: @@ -447,7 +464,9 @@ class SVNService(wx.lib.pydocview.DocService): _("'%s' has unsaved modifications. Save it before commit?") % os.path.basename(filename), _("SVN Commit"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) + yesNoMsg.CenterOnParent() status = yesNoMsg.ShowModal() + yesNoMsg.Destroy() if status == wx.ID_YES: doc.Save() elif status == wx.ID_NO: @@ -474,11 +493,12 @@ class SVNService(wx.lib.pydocview.DocService): fileList.Check(i, True) sizer.Add(fileList, 0, wx.EXPAND|wx.TOP, HALF_SPACE) - buttonSizer = wx.BoxSizer(wx.HORIZONTAL) + buttonSizer = wx.StdDialogButtonSizer() okBtn = wx.Button(dlg, wx.ID_OK) okBtn.SetDefault() - buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE) - buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0) + buttonSizer.AddButton(okBtn) + buttonSizer.AddButton(wx.Button(dlg, wx.ID_CANCEL)) + buttonSizer.Realize() contentSizer = wx.BoxSizer(wx.VERTICAL) contentSizer.Add(sizer, 0, wx.ALL, SPACE) @@ -488,6 +508,7 @@ class SVNService(wx.lib.pydocview.DocService): dlg.Fit() dlg.Layout() + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) @@ -544,7 +565,9 @@ class SVNService(wx.lib.pydocview.DocService): _("'%s' has unsaved modifications. Save it before commit?") % os.path.basename(filename), _("SVN Commit"), wx.YES_NO|wx.CANCEL|wx.ICON_QUESTION) + yesNoMsg.CenterOnParent() status = yesNoMsg.ShowModal() + yesNoMsg.Destroy() if status == wx.ID_YES: doc.Save() elif status == wx.ID_NO: @@ -571,12 +594,13 @@ class SVNService(wx.lib.pydocview.DocService): fileList.Check(i, True) sizer.Add(fileList, 0, wx.EXPAND|wx.TOP, HALF_SPACE) - buttonSizer = wx.BoxSizer(wx.HORIZONTAL) + buttonSizer = wx.StdDialogButtonSizer() okBtn = wx.Button(dlg, wx.ID_OK) okBtn.SetDefault() - buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE) - buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0) - + buttonSizer.AddButton(okBtn) + buttonSizer.AddButton(wx.Button(dlg, wx.ID_CANCEL)) + buttonSizer.Realize() + contentSizer = wx.BoxSizer(wx.VERTICAL) contentSizer.Add(sizer, 0, wx.ALL, SPACE) contentSizer.Add(buttonSizer, 0, wx.ALL|wx.ALIGN_RIGHT, SPACE) @@ -585,6 +609,7 @@ class SVNService(wx.lib.pydocview.DocService): dlg.Fit() dlg.Layout() + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) @@ -654,11 +679,11 @@ class SVNService(wx.lib.pydocview.DocService): dir = localPath.GetValue() if len(dir): dirDlg.SetPath(dir) + dirDlg.CenterOnParent() if dirDlg.ShowModal() == wx.ID_OK: localPath.SetValue(dirDlg.GetPath()) localPath.SetToolTipString(localPath.GetValue()) localPath.SetInsertionPointEnd() - dirDlg.Destroy() wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton) @@ -667,11 +692,12 @@ class SVNService(wx.lib.pydocview.DocService): sizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE) gridSizer.Add(sizer, 0) - buttonSizer = wx.BoxSizer(wx.HORIZONTAL) + buttonSizer = wx.StdDialogButtonSizer() okBtn = wx.Button(dlg, wx.ID_OK) okBtn.SetDefault() - buttonSizer.Add(okBtn, 0, wx.RIGHT, HALF_SPACE) - buttonSizer.Add(wx.Button(dlg, wx.ID_CANCEL), 0) + buttonSizer.AddButton(okBtn) + buttonSizer.AddButton(wx.Button(dlg, wx.ID_CANCEL)) + buttonSizer.Realize() contentSizer = wx.BoxSizer(wx.VERTICAL) contentSizer.Add(gridSizer, 0, wx.ALL, SPACE) @@ -681,6 +707,7 @@ class SVNService(wx.lib.pydocview.DocService): dlg.Fit() dlg.Layout() + dlg.CenterOnParent() if dlg.ShowModal() == wx.ID_OK: wx.GetApp().GetTopWindow().SetCursor(wx.StockCursor(wx.CURSOR_WAIT)) @@ -737,7 +764,10 @@ class SVNService(wx.lib.pydocview.DocService): _("Reverted file '%s' is currently open. Close it?") % os.path.basename(doc.GetFilename()), _("Close File"), wx.YES_NO|wx.ICON_QUESTION) - if yesNoMsg.ShowModal() == wx.ID_YES: + yesNoMsg.CenterOnParent() + status = yesNoMsg.ShowModal() + yesNoMsg.Destroy() + if status == wx.ID_YES: doc.DeleteAllViews() except pysvn.ClientError, e: @@ -819,8 +849,7 @@ class SVNService(wx.lib.pydocview.DocService): def ProcessUpdateUIEvent(self, event): id = event.GetId() - if id in [SVNService.SVN_UPDATE_ID, - SVNService.SVN_CHECKIN_ID, + if id in [SVNService.SVN_CHECKIN_ID, SVNService.SVN_REVERT_ID, SVNService.SVN_ADD_ID, SVNService.SVN_DELETE_ID]: @@ -830,13 +859,20 @@ class SVNService(wx.lib.pydocview.DocService): event.Enable(False) return True + elif id == SVNService.SVN_UPDATE_ID: + if self.GetCurrentDocuments() or self.GetCurrentFolder(): + event.Enable(True) + else: + event.Enable(False) + return True + elif id == SVNService.SVN_CHECKOUT_ID: event.Enable(True) return True elif (id == SVNService.SVN_UPDATE_ALL_ID or id == SVNService.SVN_CHECKIN_ALL_ID): - if self.GetCurrentProjects(): + if self.GetCurrentProject(): event.Enable(True) else: event.Enable(False) @@ -845,27 +881,20 @@ class SVNService(wx.lib.pydocview.DocService): return False - def GetCurrentProjects(self): + def GetCurrentProject(self): projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) if projectService: projView = projectService.GetView() - - if projView.HasFocus(): - filenames = projView.GetSelectedProjects() - if len(filenames): - return filenames - else: - return None + return projView.GetSelectedProject() return None def GetCurrentDocuments(self): - projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) if projectService: projView = projectService.GetView() - if projView.HasFocus(): + if projView.FilesHasFocus(): filenames = projView.GetSelectedFiles() if len(filenames): return filenames @@ -881,6 +910,19 @@ class SVNService(wx.lib.pydocview.DocService): return filenames + def GetCurrentFolder(self): + projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) + if projectService: + projView = projectService.GetView() + + if projView.FilesHasFocus(): + folderPath = projView.GetSelectedPhysicalFolder() + if folderPath: + return folderPath + + return None + + def BasenameCaseInsensitiveCompare(self, s1, s2): s1L = os.path.basename(s1).lower() s2L = os.path.basename(s2).lower() @@ -903,6 +945,7 @@ class SVNOptionsPanel(wx.Panel): borderSizer = wx.BoxSizer(wx.VERTICAL) sizer = wx.FlexGridSizer(cols = 2, hgap = 5, vgap = 5) + sizer.AddGrowableCol(1, 1) sizer.Add(wx.StaticText(self, -1, _("SVN Config Dir:")), 0, wx.ALIGN_CENTER_VERTICAL) @@ -919,18 +962,18 @@ class SVNOptionsPanel(wx.Panel): dir = self._svnConfigDir.GetValue() if len(dir): dirDlg.SetPath(dir) + dirDlg.CenterOnParent() if dirDlg.ShowModal() == wx.ID_OK: self._svnConfigDir.SetValue(dirDlg.GetPath()) self._svnConfigDir.SetToolTipString(self._svnConfigDir.GetValue()) self._svnConfigDir.SetInsertionPointEnd() - dirDlg.Destroy() wx.EVT_BUTTON(findDirButton, -1, OnBrowseButton) hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.Add(self._svnConfigDir, 1, wx.EXPAND) hsizer.Add(findDirButton, 0, wx.LEFT, HALF_SPACE) - sizer.Add(hsizer, 0) + sizer.Add(hsizer, 0, wx.EXPAND) svnUrlList = ReadSvnUrlList() @@ -941,7 +984,7 @@ class SVNOptionsPanel(wx.Panel): self._svnURLCombobox.SetStringSelection(svnUrlList[0]) else: self._svnURLCombobox.SetToolTipString(_("Set Repository URL")) - sizer.Add(self._svnURLCombobox, 0) + sizer.Add(self._svnURLCombobox, 0, wx.EXPAND) sizer.Add(wx.StaticText(self, -1, _("SVN_SSH:")), 0, wx.ALIGN_CENTER_VERTICAL) @@ -956,6 +999,7 @@ class SVNOptionsPanel(wx.Panel): def OnBrowseFileButton(event): dirDlg = wx.FileDialog(self, _("Choose a file:"), style=wx.OPEN|wx.CHANGE_DIR) + # dirDlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog if dirDlg.ShowModal() == wx.ID_OK: self._svnSSH.SetValue(dirDlg.GetPath()) self._svnSSH.SetToolTipString(self._svnSSH.GetValue()) @@ -966,15 +1010,19 @@ class SVNOptionsPanel(wx.Panel): hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.Add(self._svnSSH, 1, wx.EXPAND) hsizer.Add(findSSHButton, 0, wx.LEFT, HALF_SPACE) - sizer.Add(hsizer, 0) + sizer.Add(hsizer, 0, wx.EXPAND) - borderSizer.Add(sizer, 0, wx.ALL, SPACE) + borderSizer.Add(sizer, 0, wx.ALL|wx.EXPAND, SPACE) self.SetSizer(borderSizer) self.Layout() parent.AddPage(self, _("SVN")) + def GetIcon(self): + return wx.NullIcon + + def OnOK(self, optionsDialog): config = wx.ConfigBase_Get() diff --git a/wxPython/samples/ide/activegrid/tool/Service.py b/wxPython/samples/ide/activegrid/tool/Service.py index 87e120bffa..b65f08d58e 100644 --- a/wxPython/samples/ide/activegrid/tool/Service.py +++ b/wxPython/samples/ide/activegrid/tool/Service.py @@ -106,6 +106,8 @@ class ServiceView(wx.EvtHandler): if (self._service.GetEmbeddedWindowLocation() == wx.lib.pydocview.EMBEDDED_WINDOW_BOTTOM): if ServiceView.bottomTab == None: ServiceView.bottomTab = wx.Notebook(frame, wx.NewId(), (0,0), (100,100), wx.LB_DEFAULT, "Bottom Tab") + wx.EVT_RIGHT_DOWN(ServiceView.bottomTab, self.OnNotebookRightClick) + wx.EVT_MIDDLE_DOWN(ServiceView.bottomTab, self.OnNotebookMiddleClick) sizer.Add(ServiceView.bottomTab, 1, wx.TOP|wx.EXPAND, 4) def OnFrameResize(event): ServiceView.bottomTab.SetSize(ServiceView.bottomTab.GetParent().GetSize()) @@ -125,10 +127,46 @@ class ServiceView(wx.EvtHandler): sizer.Add(self._control, 1, wx.EXPAND, 0) frame.SetSizer(sizer) frame.Layout() - + self.Activate() return True + def OnNotebookMiddleClick(self, event): + index, type = ServiceView.bottomTab.HitTest(event.GetPosition()) + # 0 tab is always message. This code assumes the rest are run/debug windows + if index > 0: + page = ServiceView.bottomTab.GetPage(index) + if hasattr(page, 'StopAndRemoveUI'): + page.StopAndRemoveUI(event) + + + def OnNotebookRightClick(self, event): + index, type = ServiceView.bottomTab.HitTest(event.GetPosition()) + menu = wx.Menu() + x, y = event.GetX(), event.GetY() + # 0 tab is always message. This code assumes the rest are run/debug windows + if index > 0: + page = ServiceView.bottomTab.GetPage(index) + id = wx.NewId() + menu.Append(id, _("Close")) + def OnRightMenuSelect(event): + if hasattr(page, 'StopAndRemoveUI'): + page.StopAndRemoveUI(event) + wx.EVT_MENU(ServiceView.bottomTab, id, OnRightMenuSelect) + if ServiceView.bottomTab.GetPageCount() > 1: + id = wx.NewId() + menu.Append(id, _("Close All but \"Message\"")) + def OnRightMenuSelect(event): + for i in range(ServiceView.bottomTab.GetPageCount()-1, 0, -1): # Go from len-1 to 1 + page = ServiceView.bottomTab.GetPage(i) + if hasattr(page, 'StopAndRemoveUI'): + page.StopAndRemoveUI(event) + wx.EVT_MENU(ServiceView.bottomTab, id, OnRightMenuSelect) + + ServiceView.bottomTab.PopupMenu(menu, wx.Point(x, y)) + menu.Destroy() + + def OnCloseWindow(self, event): frame = self.GetFrame() config = wx.ConfigBase_Get() diff --git a/wxPython/samples/ide/activegrid/tool/UICommon.py b/wxPython/samples/ide/activegrid/tool/UICommon.py index 98f863a9da..cb16f7bbf5 100644 --- a/wxPython/samples/ide/activegrid/tool/UICommon.py +++ b/wxPython/samples/ide/activegrid/tool/UICommon.py @@ -2,7 +2,7 @@ # Name: UICommon.py # Purpose: Shared UI stuff # -# Author: Matt Fryer +# Author: Matt Fryer, Morgan Hua # # Created: 3/10/05 # CVS-ID: $Id$ @@ -13,18 +13,67 @@ import os import os.path import wx +import string import ProjectEditor -import activegrid.util as utillib +import activegrid.util.sysutils as sysutils +import activegrid.util.strutils as strutils +import activegrid.util.appdirs as appdirs _ = wx.GetTranslation -def CreateDirectoryControl( parent, fileLabel, dirLabel, fileExtension, startingName="", startingDirectory=""): +def CreateDirectoryControl( parent, fileLabel=_("File Name:"), dirLabel=_("Directory"), fileExtension="*", startingName="", startingDirectory=None, choiceDirs=None, appDirDefaultStartDir=False, returnAll=False): + if not choiceDirs: + choiceDirs = [] + projectDirs = [] + + if appDirDefaultStartDir: + appDirectory = wx.ConfigBase_Get().Read(ProjectEditor.PROJECT_DIRECTORY_KEY, ProjectEditor.NEW_PROJECT_DIRECTORY_DEFAULT) + else: + appDirectory = wx.ConfigBase_Get().Read(ProjectEditor.PROJECT_DIRECTORY_KEY) + if appDirectory: + choiceDirs.append(appDirectory) + if appDirDefaultStartDir and not startingDirectory: + startingDirectory = appDirectory + + projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) + if projectService: + curProjectDoc = projectService.GetCurrentProject() + if curProjectDoc: + homeDir = curProjectDoc.GetAppDocMgr().homeDir + if homeDir and (homeDir not in choiceDirs): + choiceDirs.append(homeDir) + if not startingDirectory: + startingDirectory = homeDir + + for projectDoc in projectService.GetOpenProjects(): + if projectDoc == curProjectDoc: + continue + homeDir = projectDoc.GetAppDocMgr().homeDir + if homeDir and (homeDir not in projectDirs): + projectDirs.append(homeDir) + projectDirs.sort(CaseInsensitiveCompare) + for projectDir in projectDirs: + if projectDir not in choiceDirs: + choiceDirs.append(projectDir) + + if startingDirectory and (startingDirectory not in choiceDirs): + choiceDirs.insert(0, startingDirectory) + + if os.getcwd() not in choiceDirs: + choiceDirs.append(os.getcwd()) + if appdirs.documents_folder not in choiceDirs: + choiceDirs.append(appdirs.documents_folder) + + if not startingDirectory: + startingDirectory = os.getcwd() + nameControl = wx.TextCtrl(parent, -1, startingName, size=(-1,-1)) nameLabelText = wx.StaticText(parent, -1, fileLabel) dirLabelText = wx.StaticText(parent, -1, dirLabel) - dirControl = wx.TextCtrl(parent, -1, startingDirectory, size=(-1,-1)) + dirControl = wx.ComboBox(parent, -1, startingDirectory, size=(-1,-1), choices=choiceDirs) dirControl.SetToolTipString(startingDirectory) - button = wx.Button(parent, -1, _("Browse..."), size=(60,-1)) + button = wx.Button(parent, -1, _("Browse...")) + allControls = [nameControl, nameLabelText, dirLabelText, dirControl, button] def OnFindDirClick(event): name = "" @@ -35,54 +84,210 @@ def CreateDirectoryControl( parent, fileLabel, dirLabel, fileExtension, starting name = nameCtrlValue else: name = _("%s.%s") % (nameCtrlValue, fileExtension) - path = wx.FileSelector(_("Choose a filename and directory"), - "", - "%s" % name, - wildcard=_("*.%s") % fileExtension , - flags=wx.SAVE, - parent=parent) + + dlg = wx.FileDialog(parent, _("Choose a filename and directory"), + defaultDir = dirControl.GetValue().strip(), + defaultFile = name, + wildcard= "*.%s" % fileExtension, + style=wx.SAVE|wx.CHANGE_DIR) + if dlg.ShowModal() != wx.ID_OK: + dlg.Destroy() + return + path = dlg.GetPath() + dlg.Destroy() + if path: dir, filename = os.path.split(path) + if dirControl.FindString(dir) == wx.NOT_FOUND: + dirControl.Insert(dir, 0) dirControl.SetValue(dir) dirControl.SetToolTipString(dir) nameControl.SetValue(filename) parent.Bind(wx.EVT_BUTTON, OnFindDirClick, button) - def Validate(allowOverwriteOnPrompt=False): - if nameControl.GetValue() == "": - wx.MessageBox(_("Please provide a filename."), _("Provide a Filename")) + def Validate(allowOverwriteOnPrompt=False, infoString='', noFirstCharDigit=False): + projName = nameControl.GetValue().strip() + if projName == "": + wx.MessageBox(_("Please provide a %sfile name.") % infoString, _("Provide a File Name")) + return False + if noFirstCharDigit and projName[0].isdigit(): + wx.MessageBox(_("File name cannot start with a number. Please enter a different name."), _("Invalid File Name")) return False - if nameControl.GetValue().find(' ') != -1: - wx.MessageBox(_("Please provide a filename that does not contains spaces."), _("Spaces in Filename")) + if projName.find(' ') != -1: + wx.MessageBox(_("Please provide a %sfile name that does not contains spaces.") % infoString, _("Spaces in File Name")) return False if not os.path.exists(dirControl.GetValue()): - wx.MessageBox(_("That directory does not exist. Please choose an existing directory."), _("Provide a Valid Directory")) + wx.MessageBox(_("That %sdirectory does not exist. Please choose an existing directory.") % infoString, _("Provide a Valid Directory")) return False - filePath = os.path.join(dirControl.GetValue(), MakeNameEndInExtension(nameControl.GetValue(), "." + fileExtension)) + filePath = os.path.join(dirControl.GetValue(), MakeNameEndInExtension(projName, "." + fileExtension)) if os.path.exists(filePath): if allowOverwriteOnPrompt: - res = wx.MessageBox(_("That file already exists. Would you like to overwrite it."), "File Exists", style=wx.YES_NO|wx.NO_DEFAULT) + res = wx.MessageBox(_("That %sfile already exists. Would you like to overwrite it.") % infoString, "File Exists", style=wx.YES_NO|wx.NO_DEFAULT) return (res == wx.YES) else: - wx.MessageBox(_("That file already exists. Please choose a different name."), "File Exists") + wx.MessageBox(_("That %sfile already exists. Please choose a different name.") % infoString, "File Exists") return False return True HALF_SPACE = 5 flexGridSizer = wx.FlexGridSizer(cols = 3, vgap = HALF_SPACE, hgap = HALF_SPACE) flexGridSizer.AddGrowableCol(1,1) - flexGridSizer.Add(nameLabelText, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.TOP|wx.RIGHT, HALF_SPACE) + flexGridSizer.Add(nameLabelText, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) flexGridSizer.Add(nameControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) flexGridSizer.Add(button, flag=wx.ALIGN_RIGHT|wx.LEFT, border=HALF_SPACE) - flexGridSizer.Add(dirLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.TOP|wx.RIGHT, border=HALF_SPACE) - flexGridSizer.Add(dirControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border=HALF_SPACE) + flexGridSizer.Add(dirLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT) + flexGridSizer.Add(dirControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND) flexGridSizer.Add(wx.StaticText(parent, -1, ""), 0) - return nameControl, dirControl, flexGridSizer, Validate + if returnAll: + return nameControl, dirControl, flexGridSizer, Validate, allControls + else: + return nameControl, dirControl, flexGridSizer, Validate + + +def CreateDirectoryOnlyControl( parent, dirLabel=_("Location:"), startingDirectory=None, choiceDirs=None, appDirDefaultStartDir=False): + + if not choiceDirs: + choiceDirs = [] + projectDirs = [] + + if appDirDefaultStartDir: + appDirectory = wx.ConfigBase_Get().Read(ProjectEditor.PROJECT_DIRECTORY_KEY, ProjectEditor.NEW_PROJECT_DIRECTORY_DEFAULT) + else: + appDirectory = wx.ConfigBase_Get().Read(ProjectEditor.PROJECT_DIRECTORY_KEY) + if appDirectory: + choiceDirs.append(appDirectory) + if appDirDefaultStartDir and not startingDirectory: + startingDirectory = appDirectory + + projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) + if projectService: + curProjectDoc = projectService.GetCurrentProject() + if curProjectDoc: + homeDir = curProjectDoc.GetAppDocMgr().homeDir + if homeDir and (homeDir not in choiceDirs): + choiceDirs.append(homeDir) + if not startingDirectory: + startingDirectory = homeDir + + for projectDoc in projectService.GetOpenProjects(): + if projectDoc == curProjectDoc: + continue + homeDir = projectDoc.GetAppDocMgr().homeDir + if homeDir and (homeDir not in projectDirs): + projectDirs.append(homeDir) + projectDirs.sort(CaseInsensitiveCompare) + for projectDir in projectDirs: + if projectDir not in choiceDirs: + choiceDirs.append(projectDir) + + if startingDirectory and (startingDirectory not in choiceDirs): + choiceDirs.insert(0, startingDirectory) + + if os.getcwd() not in choiceDirs: + choiceDirs.append(os.getcwd()) + if appdirs.documents_folder not in choiceDirs: + choiceDirs.append(appdirs.documents_folder) + + + if not startingDirectory: + startingDirectory = os.getcwd() + + dirLabelText = wx.StaticText(parent, -1, dirLabel) + dirControl = wx.ComboBox(parent, -1, startingDirectory, size=(-1,-1), choices=choiceDirs) + dirControl.SetToolTipString(startingDirectory) + button = wx.Button(parent, -1, _("Browse...")) + + def OnFindDirClick(event): + dlg = wx.DirDialog(wx.GetApp().GetTopWindow(), + _("Choose a directory:"), + defaultPath=dirControl.GetValue().strip(), + style=wx.DD_DEFAULT_STYLE|wx.DD_NEW_DIR_BUTTON) + dlg.CenterOnParent() + if dlg.ShowModal() == wx.ID_OK: + dir = dlg.GetPath() + if dirControl.FindString(dir) == wx.NOT_FOUND: + dirControl.Insert(dir, 0) + dirControl.SetValue(dir) + dirControl.SetToolTipString(dir) + dlg.Destroy() + + parent.Bind(wx.EVT_BUTTON, OnFindDirClick, button) + + def Validate(allowOverwriteOnPrompt=False): + dirName = dirControl.GetValue().strip() + if dirName == "": + wx.MessageBox(_("Please provide a directory."), _("Provide a Directory")) + return False + if not os.path.exists(dirName): + wx.MessageBox(_("That directory does not exist. Please choose an existing directory."), _("Provide a Valid Directory")) + return False + return True + + HALF_SPACE = 5 + flexGridSizer = wx.FlexGridSizer(cols = 3, vgap = HALF_SPACE, hgap = HALF_SPACE) + flexGridSizer.AddGrowableCol(1,1) + flexGridSizer.Add(dirLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.RIGHT, border=HALF_SPACE) + flexGridSizer.Add(dirControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border=HALF_SPACE) + flexGridSizer.Add(button, flag=wx.ALIGN_RIGHT|wx.LEFT, border=HALF_SPACE) + + return dirControl, flexGridSizer, Validate + + +def CreateNameOnlyControl( parent, fileLabel, startingName="", startingDirectoryControl=None): + + fileLabelText = wx.StaticText(parent, -1, fileLabel) + nameControl = wx.TextCtrl(parent, -1, startingName, size=(-1,-1)) + + def Validate(allowOverwriteOnPrompt=False, noFirstCharDigit=False): + projName = nameControl.GetValue().strip() + if projName == "": + wx.MessageBox(_("Blank name. Please enter a valid name."), _("Project Name")) + return False + if noFirstCharDigit and projName[0].isdigit(): + wx.MessageBox(_("Name cannot start with a number. Please enter a valid name."), _("Project Name")) + return False + if projName.find(' ') != -1: + wx.MessageBox(_("Spaces in name. Name cannot have spaces.") % infoString, _("Project Name")) + return False + path = os.path.join(startingDirectoryControl.GetValue().strip(), projName) + if os.path.exists(path): + if os.path.isdir(path): + message = _("Project '%s' already exists. Would you like to overwrite the contents of the project?") % projName + else: # os.path.isfile(path): + message = _("'%s' already exists as a file. Would you like to replace it with the project?") % nameControl.GetValue().strip() + + yesNoMsg = wx.MessageDialog(wx.GetApp().GetTopWindow(), + message, + _("Project Directory Exists"), + wx.YES_NO|wx.ICON_QUESTION + ) + yesNoMsg.CenterOnParent() + status = yesNoMsg.ShowModal() + yesNoMsg.Destroy() + if status == wx.ID_NO: + return False + return True + + HALF_SPACE = 5 + flexGridSizer = wx.FlexGridSizer(cols = 2, vgap = HALF_SPACE, hgap = HALF_SPACE) + flexGridSizer.AddGrowableCol(1,1) + flexGridSizer.Add(fileLabelText, flag=wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_LEFT|wx.TOP|wx.RIGHT, border=HALF_SPACE) + flexGridSizer.Add(nameControl, 2, flag=wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, border=HALF_SPACE) + + return nameControl, flexGridSizer, Validate + -def AddFilesToCurrentProject(paths, save=False): +def GetCurrentProject(): + projectDocument = None + projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) + if projectService: + projectDocument = projectService.GetCurrentProject() + return projectDocument + +def AddFilesToCurrentProject(paths, folderPath=None, types=None, names=None, save=False): projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) if projectService: projectDocument = projectService.GetCurrentProject() @@ -92,11 +297,22 @@ def AddFilesToCurrentProject(paths, save=False): if path in files: paths.remove(path) if paths: - projectDocument.GetCommandProcessor().Submit(ProjectEditor.ProjectAddFilesCommand(projectDocument, paths)) - projectDocument.GetFirstView().DoSelectFiles([paths[0]]) + projectDocument.GetCommandProcessor().Submit(ProjectEditor.ProjectAddFilesCommand(projectDocument, paths, folderPath=folderPath, types=types, names=names)) if save: projectDocument.OnSaveDocument(projectDocument.GetFilename()) +def AddFilesToProject(projectDocument, paths, types=None, names=None, save=False): + if projectDocument: + files = projectDocument.GetFiles() + for path in paths: + if path in files: + paths.remove(path) + if paths: + projectDocument.GetCommandProcessor().Submit(ProjectEditor.ProjectAddFilesCommand(projectDocument, paths, types=types, names=names)) + if save: + projectDocument.OnSaveDocument(projectDocument.GetFilename()) + + def MakeNameEndInExtension(name, extension): if not name: return name @@ -106,23 +322,130 @@ def MakeNameEndInExtension(name, extension): else: return name + extension -# Lame -def PluralName(name): - if not name: - return name - if name.endswith('us'): - return name[0:-2] + 'ii' - elif name.endswith('s'): - return name - elif name.endswith('y'): - return name[0:-1] + 'ies' - else: - return name + 's' - + def GetPythonExecPath(): pythonExecPath = wx.ConfigBase_Get().Read("ActiveGridPythonLocation") if not pythonExecPath: - pythonExecPath = utillib.pythonExecPath + pythonExecPath = sysutils.pythonExecPath return pythonExecPath +def _DoRemoveRecursive(path, skipFile=None, skipped=False): + if path == skipFile: + skipped = True + elif os.path.isdir(path): + for file in os.listdir(path): + file_or_dir = os.path.join(path,file) + if skipFile == file_or_dir: + skipped = True + elif os.path.isdir(file_or_dir) and not os.path.islink(file_or_dir): + if _DoRemoveRecursive(file_or_dir, skipFile): # it's a directory recursive call to function again + skipped = True + else: + os.remove(file_or_dir) # it's a file, delete it + if not skipped: + os.rmdir(path) # delete the directory here + else: + os.remove(path) + + return skipped + + +def RemoveRecursive(path, skipFile=None): + _DoRemoveRecursive(path, skipFile) + + +def CaseInsensitiveCompare(s1, s2): + """ Method used by sort() to sort values in case insensitive order """ + return strutils.caseInsensitiveCompare(s1, s2) + + +def GetAnnotation(model, elementName): + """ Get an object's annotation used for tooltips """ + if hasattr(model, "__xsdcomplextype__"): + ct = model.__xsdcomplextype__ + if ct: + el = ct.findElement(elementName) + if el and el.annotation: + return el.annotation + + return "" + + +#---------------------------------------------------------------------------- +# Methods for finding application level info +#---------------------------------------------------------------------------- + +def GetProjectForDoc(doc): + """ Given a document find which project it belongs to. + Tries to intelligently resolve conflicts if it is in more than one open project. + """ + projectService = wx.GetApp().GetService(ProjectEditor.ProjectService) + + projectDoc = projectService.FindProjectFromMapping(doc) + if projectDoc: + return projectDoc + + projectDoc = projectService.GetCurrentProject() + if not projectDoc: + return None + if projectDoc.IsFileInProject(doc.GetFilename()): + return projectDoc + + projects = [] + openDocs = wx.GetApp().GetDocumentManager().GetDocuments() + for openDoc in openDocs: + if openDoc == projectDoc: + continue + if(isinstance(openDoc, ProjectEditor.ProjectDocument)): + if openDoc.IsFileInProject(doc.GetFilename()): + projects.append(openDoc) + + if projects: + if len(projects) == 1: + return projects[0] + else: + choices = [os.path.basename(project.GetFilename()) for project in projects] + dlg = wx.SingleChoiceDialog(wx.GetApp().GetTopWindow(), _("'%s' found in more than one project.\nWhich project should be used for this operation?") % os.path.basename(doc.GetFilename()), _("Select Project"), choices, wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.OK|wx.CENTRE) + dlg.CenterOnParent() + projectDoc = None + if dlg.ShowModal() == wx.ID_OK: + i = dlg.GetSelection() + projectDoc = projects[i] + dlg.Destroy() + return projectDoc + + return None + + +def GetAppInfoForDoc(doc): + """ Get the AppInfo for a given document """ + projectDoc = GetProjectForDoc(doc) + if projectDoc: + return projectDoc.GetAppInfo() + return None + + +def GetAppDocMgrForDoc(doc): + """ Get the AppDocMgr for a given document """ + projectDoc = GetProjectForDoc(doc) + if projectDoc: + return projectDoc.GetModel() + return None + + +def GetAppInfoLanguage(doc=None): + from activegrid.server.deployment import LANGUAGE_DEFAULT + if doc: + language = doc.GetAppInfo().language + else: + language = None + + if not language: + config = wx.ConfigBase_Get() + language = config.Read(ProjectEditor.APP_LAST_LANGUAGE, LANGUAGE_DEFAULT) + + if doc: + doc.GetAppInfo().language = language # once it is selected, it must be set. + + return language diff --git a/wxPython/samples/ide/activegrid/tool/Wizard.py b/wxPython/samples/ide/activegrid/tool/Wizard.py index 98d84eeb70..af2b9dad1b 100644 --- a/wxPython/samples/ide/activegrid/tool/Wizard.py +++ b/wxPython/samples/ide/activegrid/tool/Wizard.py @@ -39,7 +39,7 @@ class BaseWizard(wx.wizard.Wizard): class TitledWizardPage(wx.wizard.PyWizardPage): - def __init__(self, parent, title): + def __init__(self, parent, title=None): self._prev = None self._prevFunc = None self._next = None @@ -48,13 +48,22 @@ class TitledWizardPage(wx.wizard.PyWizardPage): self.SetSizer(wx.BoxSizer(wx.VERTICAL)) self.MakePageTitle(title) - + def SetTitle(self, title): + if not title: title = "" + self.title.SetLabel(title) + def MakePageTitle(self, title): sizer = wx.BoxSizer(wx.VERTICAL) - title = wx.StaticText(self, -1, title) - title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)) - sizer.Add(title, 0, wx.ALIGN_LEFT | wx.ALL, 5) - sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.ALL, 5) + if not title: title = "" + self.title = wx.StaticText(self, -1, title) + self.title.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)) + # the code below used to add a 5 pixel border in all directions + # but I found that the left margin was not aligned properly because + # only a few of the wizards made sure that pages themselves added + # the 5 pixel left border. If we still want to inset 5 more pixels, + # we should add a wx.HORIZONTAL sizer here to take care of it. + sizer.Add(self.title, 0, wx.ALIGN_LEFT | wx.TOP | wx.BOTTOM, 5) + sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) self.GetSizer().Add(sizer) @@ -115,689 +124,6 @@ import cStringIO def getWizardData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00}\x00\x00\x00\xfa\x08\x06\ -\x00\x00\x00\x8c5HE\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00 \ -\x00IDATx\x9c\xec\x9dy\x9cdUy\xf7\xbf\xe7\xdc\xbd\x96\xdegzVfe`\x86u\xd8WY\ -\x14\x90M\x10\x11D\x11W4\x89Fc\xe4M\xd4\xa8\xd1\x88\x91D\r\x1a\xb7\x98\x98\ -\xa8o\xd4\x08\xae\x08\x18EDE@\x04E\xf6}\xf6\xadgz\xaf\xae\xedn\xe7\xbc\x7f\ -\x9c[\xd5\xd53=\xc3$\x8c\xd0\xf3v\xff>\x9f\xea\xea\xbau\xebn\xbf\xf3<\xe79\ -\xcfr\x8e\xf8\xe4\'?\xa9\x99\xc1\xb4\xc15\xd7\\\x83\r\xf0\xc0\x03\x0f\xbc\ -\xd8\xd72\x83\x17\x00\xdf\xbe\xe1Fq\xcd5\xd7h\xbb\xb1\xe1[\xdf\xfa\xd6\x8by=\ -3x\x01\xf0\xed\x1bn\x04@\xbe\xc8\xd71\x83\x17\x013\xa4OC\xcc\x90>\r1C\xfa4\ -\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\ -\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\ -\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\ -\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\ -\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\ -\x103\xa4OC\xcc\x90>\ra?\xf7.S\x05j\xa7\xcf\xbb\xb6\xd7\xddM})P-\xbf\x97\xcd\ -w\xdd\xfc~\xb2\xe3\xb7\x9eG\x81V\xd9\x19D\xf6#9\xf1\x1aZO.&\xb9\x18\xd1\xf2\ -\xeb\xc9.\xb4\xe5\xd0\x8d\xf7\x89\x87T\x13\xf7\xc9\xce\xbd\xf3i\x9b\xf7\xa1\ -\x15\x88\xc9\xe9\xddOHW@\xda\xf2\xb9q\xe7r\xc2MON\x9bB\xa2\x10\xc4\xd9\x1e6`\ -\xa1\xb3o\xccQT\xd60tF\xae\xccN!\x18\'\xbd\xde\xf2\x9d\x95\x1dg\x92\x07\xaf[\ -64\xfe\x97\xa0\x859\xbbl\xec\xa3v\xfaa\xa4\xc1\x12\xe0\x8c\xef\x9ff\xbbY\x80\ -\xa5Ss\xfeD\x83\x10 ]\xb4\xcc\xae:\xdb\x14\x85u\xa4N\xf0<\x07t\x0c\xa20\xe9\ -\x13\xd9OH\x87]%u\xf2oa\\ 4*k\x1ez\xc2\x1e\r\xc2\xc7\x05G\xeet\x04\x05\xda\ -\xca\xa4\xb9\xf1\xbde\x9e,\xd2H\x90\xb0\x98\x8c;!\x0cI\xe6\xe0\x89aD\x02\x08\ -\xf4\xce\x8f\xbb\xd1(\x04`7~\xd8\xd0J\x12\x8d R \xe2\x98\xbcT 5H\x1b\xa4h^\ -\xb9\x06\x94\x80z\xa8\xf1\x1c\x1fGj\xd2$\xc4\x92\xbb\xef\xb9\xf7#\xd2w&f\xd7\ -o\x1bhH\x94yo\xfc\xc6\xa5\xf1\xe0\x1bD\xb5\xeegag\x92\xdc\xd0"v\x93M-$\xc8`\ -\xc2\xefZ\x05\xba\x01A\x82 F\x93"D\x84$E\x88\x86v\xf1\xb1\xd0\x08\xb2\xc6\ -\xd4P"\x8d\x83\xc8\x04D\n*F\xa5)JZ\xd8\xb6\x87\x94\x16\x96g\x83\xca$]+\xe2zJ\ -\xa4b\xb4t\xb0}\x1b\x04\xd8\x9e \x05R\x04\xca\xf2\xd1)\x14w\xc3\xfb~D:d\xca1\ -{\x9f\xfc\x8e\x04\x99\xc0\xa0\xb0\x9a\xf4\x8cKY\xabdN8\x82nl\x91\x93\xf6\xcf\ -\x91\x98\xd8\xc1\xec|U\x13\x8f\xdch\\2kt\x12\x81\x06\x92\x96\xe3\xb6\x9c]$\ -\xa8z\x19)\x15\xb8\x16\xd2\xb2\x91\xd84\x0c\x810V\xb8\xae\xd3<\x8b\xb0M/\xa0\ -Z\xce\xaa\x80zj4\x8d+\xd9#\xb3\xfb\r\xe9:\x93@\xb1\xd3\xf6\x9d?\x1b\x8e[\x1f\ -\x87\xc1\xcej\xb8\xf5\xf7\xb2\xf5\x0b\xbd\xd3;\xe6A\xb6jbh4\xac\xf1&(\xb2\ -\x06#qv9\x911\x0fB n\xd9\xa0\x0c\xf1\xd9Ae>\xa0A\xa3i0\xc6n\xd0\x02\x12GRJ \ -\x95`\xc9\xac\x8fo9\xbe\x02*U\xd8\xb8i\x1b###tuu1\xff\x80^\xda\xbcIn\x98\xfd\ -\x86\xf4\xbd\x18Y6\xc8n<\xd0\xe6\x937\xca\xbbU\x9dC\x0bY\x93\x11\xde\xd8\xa1\ -y\\\x1ar\xd7\xfc\x9d\xd5\xd8eg=\xbf\x13\xe1\xbaq,\xb1\xd3=\x08\x89F\xa2\x04\ -\xe6\x1d\x9b\x88\xc4\xd8iXXB \xb2k\x8e\x05Tm\xd3d$F_lZ\x17\xf3\xe4\xc3\x0f\ -\xf0\xd8\xc3\x0f\xd0\xb7e\x1d\xe5\x91!.\xbe\xe8B.\xbe\xf0\x02\xda\x0b\xd6n\ -\xb5\x12\xec7\xa4\xc3\xee\x89o\xe9\xe7w?f\x9b\xf0\xef8\xd9\x8d\xe1Mv\xfcV\ -\xb5\xa1\xc9\xfax@Il\xdd\xf2\xb0Z\x89nj\x95\x16\xa3O\xec\xfa\xafi<\x99\xf4\ -\xe24\xc7\x12\x8d\xf7\x10\x00;k\x04\x06\xe5\x10\xb6\xf7\xc1\xd6Q\xb8\xeb\xe9\ -ml\x19\x1ef\xe33O\xb2y\xcdcD#}\xcciw9b\xf9B\x0e?\xe4P\xae~\xc3\x15\xb4\x07\ -\x0e\xb6HI\xaa\x15r\xbe\x0f\xb2U\x1f\x8cc?"}o\xd1h\x04\xc20\xab\'6\x16\xa3\ -\x8a\x13 \x1d\'\xb59\xe6\xb6h\x92\'\x94y\xa9l\x18\xa7\xedI\x1aUf\x9d\x8bL\ -\xb34U\x819F\x9a\xd9\x01\xa6\x8b\xb5@\x0b\xb4\xb0\x891dG\x18\xb2\x13\xa0?\ -\x86M[S\x1e{\xeaY\x9exr-\x9b7\xf532P\xa1R\x8e\x18K,\xca\xb9"\xb1\x10\x88\xa8\ -\x84\xabl\x16.Z\xc6\xe9G\xaf\xe2\xd5\xe7\x9e\xc2\x91K\x0bx\x80\xd7\xb8\x7fK\ -\x82\xae\x01\xfb\xf9\x90m\x97\xbe{\xb7;\xecl\xc7\x9bm\xf5(\xc2w]\xc2p\x0c\ -\xdf\x95f\x1c\xab\x12P\nl\x1f\xa4\x83q\x81\x88\x89G\x91\nR\x05:1d\x8a\x86\ -\xd2m4\x18\xd5\xb4\xc6+\xd5\x1a^\xae\x8d\xc1J\x85B>O\x04\xd44\x14\x04\xe4\ -\x91\xa4\x11\x8cE\x1a\xbf(\xd8R\x82\xdf<\xd4\xc7\xedw\xdf\xc7#k\xd61X\xa9\ -\x93\x08\x9b0\x11D1\xd8V\x8e\xc0mC\xdb6\xd54\xc2\xb2]\x92h\x0cG\xa7\xac\\\ -\xb1\x8c\xd7]x&\x17\x9f\xd2C\x0e\xa8\xd7\xa0\x18`\xeeIG\xec\xde\xe44\xd8oH\ -\xdf\x1b(\x05J)\xb46"i\xdb6B\x18\xbb\xd9q]@\x19)\x17"s^\xa4\x18\tU\x90jb)QBd\ -t\n\xa4\x16\xc6\x95c\x8f\xabI\x9di\x84\xc68?\xd3\x19D@\x92\xf3\xa8\x01:\x9fg\ -\x04\xd8Q\x87\x8d\x9b\xca<\xf3\xd0\xef\x91\x03\x9bx\xd7\x9f\\I\xe0\x19\xe9\ -\x969\xf8\xc2W\xbf\xc3\xc6\xa1*\xa9\x97g8tHq\xb0\xfd\x80\xa0\xadH\x12\x0bv\ -\x94C\x84V\x14\x02\x97\xda\xe0f\x8a~\xc2KO9\x8e\xb7^y\x06\x07\xf7\x18\x034\ -\xaaAOn\x12\xaf\xe3\x1e\xa4d\xff!}\xa2\xcf\xb4e\xf3\xb8d\x0bI\xd3)\xd1\xb4\ -\xdf5\xa4\x99W,\xd2\x8a\x9c\xe7\xd3\xe8A\x8d\xd4\x02\xc2&\xc4%\x15\xb2\xd9\ -\xc7\x02XB\x90f\x8f(!#\x96\xf1.=e\\M?\xb5\x06\xd6m\x1e\xe0\xb1\'\xd7\xb1nc\ -\x1fO?\xb3\x1e\xe9\xfa(m1\xb8\xeea\xbe\xf0\x81\xd7S\xaaA)\x821\x05\xff\xf9\ -\x83\x87\xd98\x10\xe2v\x1f\xc0h\xa4\xc9\xe5<\xeaI\x8a\xd6\x82\x18\x1bK\x82\ -\xe3iD*\xf0\xa8q\xf8\x01\x05.;\xffd^~\xd6\xa1t\xb9\x868W\x80\x93\x83\xb8^\ -\xc7\xf62\x0f\xa1t\x19\xb7\\&\xc7\xfeCz\x03\x13\xfc\xcf\x06\n\xa8\xd5C\x10\ -\x16\x96ec\xb7v\xbfb\xdc\xa5\x19\'\x16\x81\x03B%\xe3\xbf\xb4l\xd2\xd4#\xb1lB\ -\xa0\x8e!\xb2q\x1a/{/\x01\xdb\x87a\xe3\x96:k7la\xdd\xc6\xed\xac\xd9\xb4\x95\ -\r\x9b\xfb\x19\x18.#\x1c\x9f(\x11X\xd2\xa3\xad\xb3\x8b\xb1\xb4\x83\x9c\xc8\ -\x11F1G\x1c\x7f&\xe7_p4\x0eP\x08`\xcdZ\xf8\xfe-?\x03\xa7H-\xb6(\x8d\x96!/\ -\xc0\xb2 \rI*#t\xe4\x02\x0e9\xf0\x00\x0e9\xe8 \x96\xcf\xf29\xe7\x88v\x96\xf4\ -@\xde5\xd7\x13\xd7S\xb4N\xb0\x02\xc78o\xa0\xe91L\x91\xa4\x18w\xd4d\xd8\xffH\ -\x87I\x89\xf7}\xaf\xe9\xa1\x0fS\x9a\x8d\xbd\xe1\xf4J\x00\x1c#E\x8e\xc8\x91VK\ -\xd8\xb9\x89zou\x89\xb6\xc6\xc0\xa45\xd1KU\x8f\xc1\xf1!V0:\xa2\x98\xdfe\x11\xe9\x1c\ -\xb6\xf6\x88\x04\x8c\xc5\xf0\xf1\xcf\xdc\xcc\x9a\xfe*Ol\x1ab\xdbp\x19\xa5\ -\x149\xd7\xa1\xe0YH\xe9\x93x\xb3I\x94G\xac\x04\x89\xb0H\xa5\x8d\xd2\xb69\xab\ -L\xa8%\x80\xeda\xb9\x16\xae\x15\x91ss\xc8\xa4\xca\xca\x15\x8b9s\xb5i|)p\xeb\ -\xed?\xe3\x91\'\x9e$\xd7s A\x10\xd0\xb3`\x01\x0b\x96-\xe3\xa4\x13\x172\xb0\ -\xbd\xca\x03\xf7\xdc\xc67o\xfb:g\x1e\xb7\x8a\xbf~\xeb\xe5,\xea4\x12\xab\xeb\ -\x11x\x127pH\xc3\x1a\x96e\xe1\xe5\xf3\x00\xd4jU\x82\\\xa1\xd9\xd5\xed\xd9a\ -\xbd?\x91\xfe\x1c\x08\x13\x8c\x07U\x8eG6c\x05\xa52\x8cU\xe1w\x8f\xad\'\xac\ -\xd5\xa9\xecX\xc7;\xdfr.\xb6\xef\x11i\xa3\xca\xcb\x11\xfc\xe0\'wSq\xbbH\xfcY\ -\x04\xdds\xf0\xfd\x00tB\xbdZ"\xac\x8d!\xdda\x12K\x92Z\x0e\xb1\xb4A8\x803\xee\ -t\x11\n\xe9(\xe2\xd2\x10\x92\x10\x9dT\xe8is\xb9\xf4\xa5\'\xe3c\xba\x89\xbb\ -\x1ex\x8a[~|\x0b\xc7\x1cw4+\x8fz)\x87\x1e\xb3\x98\xa7\xd6\xc1\x1f\x1e|\x8c\ -\xcf}\xea\xdf\x98\xdd&9\xf3\x84\x83\xf9\xf8\x9f}\x88\xc3\x16\xd8\x88z\r\xbfV\ -%\x08|\x94\xe3\x92*\x0b\xcb\x12X\xbe\xa1-M5B\x08\x82\\\x9b\xb9\x04\xc8\\\xcf\ -0\x1eQ\xdc\x15\x93lm\x98*\xd9a\xf4\xf3h\x17B\x8d\x8f\x93[%U\xb4^\xd8\xc4KiHh\ -CE5=ir|\xef\xc66\xd5\xb2\xef\xb3[C\xfa\x06\x86Y\xb3~\x0b\xeb\xd6of\xeb\xb6\ -\x1d\xf4\x0f\x8eR*U(\xd7b\x84\x9d#\x8d#t}\x84K_{.s\x03\x9a\x1e/\xed\x80\xdf9\ -\x87\x9ah\'T\x1e\xd5jL\xa9j\xa2Z\x16\x02\xcb\xf1\x11B\xa1\x85BK\xc5\xb8\x0f=\ -\xc9\x1c.\x1a\x92:mmyjcezr\x16A\xa4X>\xbb\xc0\xa5\xa7xh\x8c\xb17&:\xf9\xd8\ -\xa7?\xcb\x83\x0fo\xe4\xde\xdf=\xc1\xf7n\xfa\x11\xe5\xb1*s\xe6t\xf2\xfa\x0bN\ -\xe6e\xa7\x1c\xcaQK \x07\xb8h\x02_e!\xb42\xd2\x9fE\x9ay\xf0\x1b\xae i\x8dG\ -\xda&\xf4vZ\xed\xe4j\x9c\x88I\x18\xadS+\xf5\x13\xb4u\x9a\xa7\x11+\x90.qX\xc3\ -q\x1c\xb0\xed\x89$\xa6\xb1\x19+9\xce\xc4\xc34\x9d\x16\r\x96$$\nt\x089\x87zX\ -\xc6\xf7\xbd\xe6-\x84\xf5\x08\xcf\xcb14\x92\x90\xef4FU5\xfb6\x02b\r\xfd\x03\ -\xb0q\x8bb\xd3\xe6\xadl\xee\xdb\xce\x86-[\xd8\xb8e\x07\xdb\x07\x86I-3\xe4I\ -\x85\x8b\xd6\x0e\xa9\xf0Q\x14\x8cq\x17\x80\xadS|\x1f\xea\xf6\x08\x1b\xab0+\ -\x00\'5\xb6S\xa5\nc*\xa2\xee\x08\xa4c\x91\x92\xdd\xb7\xd2\xa4\x96\xc0q\x8b\ -\xe4,\x9fr\xb5N\x12\xa6\xe0f\x11\x0f\x9d\x00\t\xc2\xd1\x14r\x16#\x1b\x1ea\ -\xf9\xfcY8\xb5a\xda\xa9\xf1\xc1\xb7\xfc\x19\x1d\t\x945|\xe5\xc7\xdb\xb9\xfd\ -\xfe\x87x\xfa\xf1\xc7\xb1\x89\t\x1c\xc5\xbcN\x8fs^y\x06\xaf:\xefx\xe6w\x185\ -\xeeb\x0emi\r\xda5B\xe7\x18\x15&E\xab\xaf\x7fw\xd8\xf3pmr\xd2\xb5"h+\x00)i=F\ -Z\xdd\xa0\xc0\t\x82\xa6\xcb1\x8d\x12\x94RH)\x91\xb6\x8d\xd8\x99p\x1aWe\xa1\ -\xb5y6q\x15\xbc\xbc$J\x03,\x01\xa9\xe5\x91 \xb3\xc0\x81\x8d\xed;\x94cp:m\x1e\ -\xdb\n\xf7=\xbe\x9d5[w\xb0cd\x98\x07\x1f\x7f\x92\xa1\xe1\x1aa\xa2\x89\x12\r\ -\xc2A:>J:\x84\xa9K\x98\xce\xc6q\xf3(lt6\x866\xc1\x8c,\x14\xa2S<\x15\x92\x88\ -\x94\x9a\xcc1\x10\x92Y\xb7\x11\x12\xd7\xd8\x00\x96$L5:\x8a\xc0\xb5\x91\xb96\ -\xa4\x94\x88\xa4J\x12%\x0c\x8dV\x10\x96\x8b\x1bxX\x96&Ik\xc4\xe1($\x15$!\xb6\ -/9\xe2\xc0\xf9\x1c\xb2t!\xe7\x9dv*\xa7\xaf\x0ep1\xae\xd4k\xaf\xbf\x95\xef\ -\xdc\xfd4\xe4;\x11B\xe2\xdb\x92\xd3O<\x82\xab.=\x9bU\x0bhz\xd3LzG2\xae\xe2\ -\xb4e\x04O\xb4<\xd2=\x12\xdeB\xfc\xff\x88t,\xd2Ha9\x0e2(\xa2\xb4D\x0b(\x95\ -\xc6\xb0\x1d\x85\xeb{\xd8\x9e\x8bF6;\x82\x18\xe3\xc0L1\t J\x9b8\xbf\xc4\xb8"\ -\x95\x03\xa2\xc3\xec[Q\xc6C\xd8\x19\x04\xa4\x80EL\x14\xc3\xc3On\xe0o\xae\xfd\ -<\xc3\xaa\x8b2\x05\x06*\x11N\x90\xa3\xad\xdd\xa7\x16\xa6DV\x8e\xc4\x92h\xc7A\ -K\x0f!=\xb4\xf4A\xd9\xd8\xbe \x8e3/\x94H\x91$\x08\x1d\x9b+\x14)B$h\x99\x12\ -\x93\xa0\xec\x1aC\x95\x86\xf2\t1\x8a\x14t\x9cP\xc8\xe7\xf1\xbdv\xa2\xd4\xa6T\ -IH\xc2\x9a\xb1\x87\x1d\t\xf9<\xaeoc\'U\xc2\xd1\x1dX\xd1(+f\x179\xee\xf0\xc38\ -x\xd9B\x0e_u K\x96\xc0C\x8f\x86<\xfa\xd43\x14f\x1f\xca\xfc\xf9\xf0\x85o>\xc1\ --\xf7>\x86\xa5\x13\xba\x04\x9c\xf9\xd2\x13y\xcd\xabN`Yo\x96$\xa3L(t\xe7\xc8\ -\x19\x8d\x86\xfb\xdc\x0c\xff\x8f\xb1+\xe9J#\xdd\x80\x08\x9b\x14\x17%`\xf3vX\ -\xd0[\x04\x8c[\xa3\xc2\xf8P\xa8\xd1\xc35-h\x01\x89\x80\xb2\x82\xad\xdb\x15\ -\x1b\xd6od\xeb\x8e\n\x8f=1\xc4\xb6\xbe\x01|_Q\xf4k|\xfa#WR\x04\x02\x1c\\\x07\ -\x0e9l\x11\x1d\x0b\x0e\xe2\xee\xfb6RX\xb8\x84\xb0\xdd&\x12\x82\xca\xe8\x08\ -\x96\xe5!\xdc\x1cJ\xbahe\x11k\tI\x16\x96\xd4\x99w\xdbvi\xf8\xc2\x15`i\x85 \ -\xc5R\x86x-\x14\x89V`[\x0c\x8fVQ\xe4\x8c\xe7N@\x1c\xa6\xf8\xaeK-\xac18ZC%\ -\x0e\x8e_ \x97\x0f\xf0dB\xaa\xea\xa4n\x85\xf2\xd80\x9ecq\xd6)\xab\xb9\xf8\ -\x9ccY\xb5\x0c\xfa7\xc1\xe3\x0f\xaf\xe5_\xbf\xf4\x9fl\xdc\xbc\x89TH\xbe\xf4\ -\xd5\xf7\x91\xcb\xc3\'\xbft\x1f7\xdd\xfa\xdf\xf4\x14s\\\xf6\xb23\xb8\xfc\xdc\ -\x13Y2\xcf<\xbb\xb0\x06\xb9\xc0\x0c\xe3\x06\xb6\x0f1\xaf\xb7\xab%\xa6\xcfN\ -\xf1\xf6?6\xe9\x96c\xe2\xb3J"\xa5!\xb9\xad\x17\x06ScLI1\xee\x8d\x1a\xac\xc0\ -\xb6~\x18\x1c\x89x\xec\xc9g\xd9\xd6?\xc8\x9aM[\xd8\xda\xb7\x83R\xa5F\xaa\x05\ -\x08\x0b%|:\xe7\xae`\xc3\xfa!\xda\xf2\x1a/\x1d\xe0\xee\x87\x868\xfb\x88.\x12\ -m2\x85F+p\xe69\x17\xf2\xcbM?\xa6\xe6t\x91\xc6\x02\xb7\xad@4\x9c\x82NI*\x0eX\ -\xbe\xb1)l\x99\x89\x87\x00\xdb1\x07\xa8\xd6\xccU\xa5\xc6x\xd4\xa9m\xd4\xbbv\ -\x10J\x81%\xd0i\x88\xe3\nF\x86B$9,\xed\x9b\xe0G=\xa4^\x19\xc5o\xeb\xa43\x9f#\ -\x8e4\xb5x\x8c4\x1eF\x11\xe3\x881\xce;i5\xa7\x9dq\x11\xc7\x1d\xe2R\x03~~\'|\ -\xe8\x1f\xefe\xed\xba\xadDaB\x14\xa6X\xf4\xf0\xe9\x7f|\x1b\xddy\xf8\xfa\x7f\ -\xfd\x81_|\xf7\x8b\xbc\xf3u\x97p\xc5+_\xc1\xb2Nsyv\n\x8e\x05E\x17\xa2\xb1\ -\x18\xc7s\x987\xab\xab%N\xd4 }\\\x90\x1aMa_q\xbf\x0b\xe9\x89\x82XZHiS\x03\ -\x9e\xd8\x92\xc5o7E\x0c\x0e\x0c\xb1i\xcbV6n\xddF\xdf\xc00\xa3\xa5\n\x95zB=Q\ -\xe0\xfa$Z\x92`\xa1\xadnd\xe0\xa1\xb4 JS\xa2\x04J\x1b\x07 \xd7A)\xad\x90\x17\ -yn\xf8\xe1m\xbc\xec\x88\xd7\xe0d\xb1\xeaYy8\xf5\x84^\xe6\xfc\xb0\x9b5[F\xc0i\ -#\xaaE\x90@\xd0\xdeI\xb9&\xd1"\x1b\x17\xa7\n\x92\xba1 E\x96\x15\xe8f\xca13\ -\x1e\x95e\x11)3`\xb7\xb4\xc2C b\x85\xeb\xd9\x8c\x0c\x8c!\xe8D\xe2\x98\x04\n\ -\xad\t<\x97rRg\xa4RFk\xcd\xbc\xf9\x0b9\xe5\xe4\xe39\xeb\xb4y\xacZ`\x0e\xfd\ -\xdb\xdf\x0f\xf3\xc1\xeb~\xc6\x83\x8f\xaeed\xccBY9\x90\x05\xa4\xb0(\x14\xbb\ -\xb9\xfa\xaa\x0b9j\x05|\xee\xf3\xbfbx\xeb\xa3\xfc\xfc\x86\x7f\xa1\xb7\xd3\ -\xa1\xcdR\x08\xa5Qq\x8c%$\x8e4n57\xe7Ld\xb6\xa5\xd3\x9e,\xffn_a\x17\xd2\x85t\ -PH"`\xfd(\xfc\xf5G>\xc7\xe6\xed5\xea\xa9\x0b\xc2EH\x1b--\x94\xb4\xd0\xf8\xc4\ -Z\x92h\x89\'\x0b\xc4\x1ab%P\t\x90\xd8Y\x9fd\x81\xa3\xc0\xad\xd3\xde\x99\xa7V\ -\x95\xe4l\x87\x87\x1e\x7f\x96\xdb\xefz\x86\xd7\x9cr \xb6N\xb0\x84\xcd\x1c\ -\x17\xce>\xfe`\xbeq\xdb\x1fH\xf3\x01\xd50\x81(\xa4\x16V\xd1\xb6\x9b\r\x01\ -\x95I:\xd1\n\x07\x10Z R\x8d\xaa\'&\x94)e\xa6\x92\xa4\xe94\x85 M4Bid\x92`\xa5\ -\x16\xa5\xc1a,\x0e\xc0B\xa0\x05x\x8e\x8b\xef\xfb,]y8\'\x9dx<\xc7\x9f`3;\x075\ -\xe0\xae_\x0e\xf1o_\xb9\x83\xc7\xd7m\xa5\x16\x83\x14\x1e\xbe\xd7\x85\xdd&(\ -\x97*X\xc9 m\x81\xc79\'\x1c\xcf%g\xc2\xb3\x0f\xa7\xbc\xe9\x15\xa7r\xe0\xfc\ -\xd3(ZP/\xf7\xe1\x15r\xe6z\xbc,\xf6\x1a\xd7M\xc3u\xa3\x83\xfdP\xed\x03;bv.a\xc5\xbc\x0e\xce;\xedX\xce:\xed\ -\x10fw\x8d\xfb\x10"\xe0W\x8f\xc1\x8d?\xba\x87\xdf?\xfa,\x89r\xa8\x8e\x85($Aq\ -!\xdb\x06\x87\x19\tA\x97\x14\x85Y \xedxy\x9c EJA\xe2\xbbHO#=(\xcc\n\x08\x81\x07\ -\x1e~\x8c\xd9\xbd\x8bY\xbbf\x03\x859\xddx\xae\xe0\xd9\xbb\x7f\xcd\xf2\xa3\ -\x0f\xe6m\x7f\xfeA\xe6\xb5\xd9|\xea\x13\x1f\xe4\xedW]\xc1Y\xa7\x1d\x86\x0bX\ -\xda\xa4+\xd9\x1a\xe6u\xf7d\x9eA\x00\x0bK(\x92,\x99\xa1\x91\r\xeb\xd0\xda+7\ -\x8a\x1a`\xd7D\x81F\xdc`\'Z\xfe\x98\x92\x0e\nG(\x14\ty\xcb\xc6/\xc2\xe5\xaf<\ -\x87G\xff\xed&\xb6T\x07Qa\x8am\xe5\xb0\x1c\x974\x8e\xd1\x02l\' I\x9b\x01\xbf\ -\xf1\x8e\xaa\x19\xf1\xc9\x8a\xeetBQ\xc6\x04\x95>:u\x95\x9a\xb4\xa8\x8d\x0e\ -\xe2\x17\x8b\xf4\x0fo\xe4\xa6[\x9fb\xfe\xcb\x0fd\x9e\x1f\xe2j\xc9\xd9G\x1f\ -\xc0\x95\xe7\x1c\xc7X\x04\x17\x9dv$\x07-k\xa3\xb38\x9e\xabV\x05\xeez\x10~y\ -\xf7}\xfc\xea\xb7\x0f\x80\x93g\xb4\x962X\x8a\xc1q(\xf6\xf4\xa0\xb1)\x97J\xc4\ -\xb6\xe9`\xc3\xea(#NJ\x04F\xda]\xa8\xc51k7nd\xf6\xf2\xd5\xec\xd8\xb4\x16\xab\ -\x90\xe3o\xae\xfd(K\x0f\x80\x9f|\xffn~w\xe7\xcd|\xf5\x0b\x1fa\xc1,\x1f\x91\ -\x19\xdd\xae0\xde\xb5\xfah\x15\xdf\x91\xe0\xdb\x99\xa3H\x83L\xb1E:\xa1\x1a\ -\xc6\x82\xac\x05d\x01a\xd1Z\\\x99\xa59\xa5\xae1\xf02\x9d\xaf[\x98\x17z\xdf\r\ -\xde\'!]"\xb1HU\x8c+m\x12\r/?\xa5\x8b\x1f\xdd;\x0fwC?[\xfaJ\x08R\x84\xce\xa3\ -\x89A\xd9\xa4"\x1d\'\xba9\xe4hI\xfe\x97\x02\xa2\x14\xa4\x83\x1b\xe4\x18\xd9\ -\xb1\x81\xae \xcf\x9cb;\xcf\xec\xd8\x84Wpq\xd3*\xb7\xfc\xe0{\xbc\xf3\xdc\x0f\ - \x85G\x1aV\xe9\xf4=\xdeu\xe5K(\x16\xc1\xcd\xdc\x97\x03\x11\xdc\xf5\x871~r\ -\xd7\x03\xfc\xfe\xa9\r\xec\x18\xaaPM!\x16.\xda\xb6I\xed\x0eh\xb3@\xa5\x8c\ -\x95C\x10%\x84\'\xd1q\x82\xdd\xddER\xaf\xa0\x92~$&\xdf\xac\n\x0c\xf4\xef\xa0\ -\xa7}\x05\x95\xe1m\xbc\xfd\xea7q\xe1\x05\xf0\xb3\x1f\xc3_\xbf\xfb\xb3\x9c\ -\xb4j>\xdf\xf8\x97\xeb\x98?\xdb\x1c\xd6\xce\x08\xac\xd7\x14\x05W\xe2\xb7\xe5\ -ZF+\x13+kdV\x9c\xd4,F\xcd\xde\x13=IT\x92\xf1G\xa8\xb5I\x8e\x10b\xcf,k\xad\ -\x9b\x99\xbf\x8d\xfd\x1b\x9f\x1b\xdb\xf6\x92t\x07)-\xdc\xacO\xb1\x84\x91\xaa\ -\xbf\xfd\xcbsx\xc3\xbb>\x8f\x1d\r\xe1\x06s\x88\x1b\xe3M\xaf\x88\x96\x05\xa3\ -\xe6\xa3(;\x84c:\xb3\xd48lp\x02s*\x1d3\xa8\xa0\xadk\x01\xe5\xb0Dep\x0b\xb3\ -\xad\x84\xbcR\xac>d1\xe7\x9ev,\x96\x80\x10\xc9`I0\xdb\x87\xf9E\x18\x0ba\xc3\ -\xa0\xe6\xab\xdf\xbd\x9d\x1f\xde\xb3\x96\xedQ\x11\x95\xef!\xa1\x17\x9cQ\xa4]\ -G\x08H\xb5@[\x018y\xa8W\xa1:\x08N\x9d|\xb1H\x19\x1b\xe9\x17`\xc7v\xba\xba,\ -\xbc\x10\xda\x1d\xd8\xbc5&G\xca\xeaUs\xb9\xfa\xbd\xaf`\xf3\x08\xfc\xc5{oc\ -\xeb\x9aG9xn\x8e\xeb>p)\x07\xb4\x8d\x9755\x0c//\x90M\x12\x1b\xf9i;[\xd9\xa2\ -\xf5\x01?G\xdf\xfe\xbf\xc1d\r\xa3\xf1Y)\xf5?!\xdd\xa8\xe8V\xd5\xe4\x02\xdd\ -\x12\xde\xf7\xa7o\xe5\x9a\x0f\xff\x03a\x181T\x1e\x00\x7f\x16\x08\x1bj\x11\ -\xe4\xf2\xe0{\xc84E\xa5!\x12\x8d\xe5X(\x95\x92\xd6\x86 \x8d\xb0\xf3.V\xbdDyd\ -\x1b\xbd\x05\xc9KO_\xcd\xb9\xa7\x9f\xc8\xaa\x03\x1d|\x0b\xba\x0b0:\n\xbe\x07\ -\x1d\xb3\xf3$@R\x8fy\xe4\x91\xb5\xbc\xfd\xfd\x9f\xc5?\xe0\x18\xd6\x0f\x01\ -\x9d\x9d\xa0\x02\x88k\xa0$\x85\xf6N\xc2J\t)-T\x14\x9a\xc4\xb8\\\x80=g.Vm;\ -\xe5\x1d\x03P\x9cEt\xff\xfd\xc8\x85]ty\x92.\x17\xa8%T#\xc1G?\xf1i\x96\xac\ -\xb4\xf8\xd1m\xc3\\\xff\x95o\xe0\xb8\x16\x9d^\xcag\xae\xfd\x13:]c\xa6\xee6\ -\xe0\xb1oGS/\x08\xf6\xaa\xd1I\xa0\x08\x1c<\xc7\xe7\x03\xef|\x0f\x9f\xfa\xd27\ -\xb1;\xbb\x19S9\xac\\\x07\xa3\xa5\xbaIF\x93\x1a\xdbQ8D\xa4a\x15\x15W\xf1,(\ -\xfa)\xbe\x18\xa0\xd7s8\xe9\xd4c8\xef\xec\xd7pp\x16\xc4P\x98\x86\xa5\x81Q`\ -\xfd\xd0\x18\xbf\xbe\xff).~\xd91$qL\xbb/8\xfa\xd8\x83Xt\xe8\xa9\x05\x8c\xd5])W)\x14r\x93?\x9c\x0cS\x8d\xf4=\xd9\ -\x03{E\xba\x00t\xa5N[\xdeG\xe4\xe0]o:\x14%\xeb|\xf7\'\xbfF\xfb\x8ajT\x82J\ -\x8c\x9b\x96\x99U\xb09\xea\xf0e\xbc\xf4\xd4c9\xe6\xf0\x85\xcc\xca\x19\x97\ -\x8e\x93@:\x16\xe2\xe6=\xa4\x84\xa7\xfa\xe0\x87?\xbd\x97_?\xf0$\x83UM\xdfP\ -\x19\xcb\n\x08\xdc\x1c\xb3\x97\xcc\xe5[\xdf\xbb\x9b\xf3\xcf>\x9d@A\x90\x87Es\ -`\xd5\x8a\x05<\xf0\xf4:\x8a\xdd\xbd\x94\xab!i\x12\xa3}P\xbe&\xd6\n\xe9\xb8&\ -\xb9\xa2\x12\x82kS\xec\xca\xe1\xd6G\x18\xda\xbe\x91\xce\xce\x02VX\xe6\xeb_\ -\xf88g\x1cl\x0c\xe9\xba\x05Oo\xafR.\x0b\xe6,ZLi\xc3\x83\x9c\xba\xfa >\xf6\ -\xce\xb3\x08\x07\xab\xf8]\x86\xe8B~\xcf\x84\x03\xb8\xee\xeeJ\x0b\xa6\x1e\xf6\ -\xd2\xa6H\xf0\xac* \xc8I\x8f\x04x\xfb\x95\xc7\xb0f\xcd\x83\xfc\xfe\xf1g\x98\ -\xd3\xd9\xc51\xc7\x1c\xc5\x19/9\x91c\x0f)\xd0(\xaf\xf70\xaa\xb1\x86\xc9%\xac\ -[\x1ew\xdc\xb3\x9e[\x7f\xfe\x1b\x1e^\xbb\x9d\x92\xca1\x1c{\x0c\x0e\x878\x9d\ -\xf3q\x1c\x87\xc1\x91~FD\x9dy\xf96n\xfa\xc9\x1a^\x7f\xd12J5\xf0\x02\xf8\xdb\ -\xf7\x9c\xc5\x1b\xff\xfcK8Z\x10\n\x8f\xc4\xf1\x19\xacU!\x8e\xf1\xbb\xda\xa8\ -\x97\xab\xa0\x03hk\x87\xb0\xcc\xd8\xda\xa7\xc8\xbb\x15\x96\xf5\x16Y\xbct\x11\ -\x7f}\xcd\xd9\x04\xc0wnz\x94KO=\x948\x80{\x1f|\x0c\n\x05\xfa\xd6=\xc3l\'\xe1\ --W\\@\x00\xb4w\xb8\x10\x97Mq\xa30\xc9\xc5\xff\xbf`\xefH\x17\x1a|\tz\x8cz\xad\ -D.7\x0b\xe9\xc0\x97\xaf}+w>\xb8\x9e\x13\x8e\\\xdc\xdcUc\xaaE\x1c\x8c\x1a\xdf\ -0\x1a\xf3\xe8\xa3\xeb\xb9\xe5\xd6\xfbX\xbba\x98\xbe\x81\x11\xf0\xda\x91\xb9\ -\xd9Tt\x8e\x98<\xf4\x16\x89\xcb5b7 7\xbb\x8b\xb1\xcdOS\t$_\xfa\xfa\x0fY}\xd8\ -{9|\xb9)0=a>\x9cv\xc8B~\xfa\xbb\x8d\xa4\xb9y\x88\xf6N\xa8h\xc8\x07\xd4\x85\ -\x03\xaa\x0eR\xd1i\x01i\r\xe9\xa5\x1c\x7f\xc4R^z\xc6I\x9cs\xc6\\\xb6\x94\xe0\ -\xc3\x7f\x7f#\xb5\x81\x8d\xbc\xf9\xa2C\xd9T\x02t\x0c\x952\x8b\xe7\x15\xb8\ -\xf6\x1do\xe1\xa8\xa56n\xac!-\x83cS\x1d\x19!\xd7\xd9\xb3\xcf\x1f\xfc\x8b\x89\ -\xbd\x94ta\xf4\xa1\xed\x92\x0f\xac,\xc6+\t\xeb1g\x1f\xb9\x98jb\xb2\x98\x1aS`\ -\x85\x11\xdc\xf1\xc0Fn\xfd\xc5\xafy\xf8\x89\xb5\x94"\x97\xaa\xee@8=\xa8Ys\ -\x88\x12L$\xca\xce\x83]0\xc1\x89B\x11$TGFi_\xb0\x98\x91\xe1\r\xb4[\x01_\xf9\ -\xf6\x1d\\\xfbWg\xb2\xc0\x85\x91\x11\xc5\xbb\xdex\x01\x0f<\xfeyv81\xb5$6\xd3\ -4tuC\xdf&\x9c\x9ev\xfcz\x85\xe15O\xb0pV\x1b\xaf~\xf5\xb9\xbc\xf2\xc2\xe5\xcc\ -i\x87_\xfcA\xf3\x91\x8f\xff#\x96\x17\xb0\xa0\xab\xc3\x14\x1d>;\xcc\xf6\xf5O0\ -\xe7\x80\xa5\xbc\xf1\xbc\x938\xfbp;SK\xb1q\x19\xc7)\xb9\xce.j\xf5\x90 \xd8\ -\xcd\\\x1eS\x14\xa6\x06\x7fr\x7f\xc0^\x92n\x83\xdd\x91\x1dl\xdc\xad\xd8\xe3\ -\x9b\xa8[\xce2\xdd\xe8\x1f\x1e\xde\xc2\xb7~\xf83\xee{r3e\xab\x8b\xe1\xd4\xa7\ -"\x0fF\xe5\n\x10V\xc0r\x8c\xcbV\xa6\x99w*\x02Q6\xe3\xdbJ\x05:\xda\xc1\xae0Z\ -\x1d\xa5\xa7\xbb\xc0\xf6-\xfd\xdc\xbf\xf6\x19\xfe\xfb\xce\x83\xb8\xec\xc8\ -\xb9\xcc\xee\x94\xd0\x06\xab\x0f\x9f\xc5\x9dkK\xd4\x12\t\x85\x1e(\xa7`\xe7\ -\xc8\x87\x15D\xe9Y\x8e[\xd5\xce\xdb\xdf>^\xd7\xda\x00\x00 \x00IDATt%/9\xb6@\ -\x7f\x15\xfe\xe9+O\xf0\xfd\x9bo\xc2o\xefd\xc3\xf6\x11\x0e=\xec\x08"`\xa0o\ -\x0b\xf9h\x07\x97\x9e|\x0e\x7f~\xd1\x12\xda\x00\xdb\xcf&\x1a\xc0\x03O\xa2\ -\x85\xc4\xdd\xcf\x08\x070s\xdcLN\xfa^\x8d2\x1b\x89\x90\t&Hf\xf2\xce\xc0R\xe6\ -e+(H\xf8\xd5m\xbf`\xfd\x9a\xcdD\x91\xc7\xb6AEd-@yK\x81^(\xce1N\x1a!\xc1s\xc1\ -\xb3L.t}\x04\xc2a\xc8\t,+\x04\x99\x80\x8a\xa9#H\x82\x02\xcf\x0e\x96\xb9\xe1\ -\xc7?\xc7-Hv\xf4W\xd1\n\xfe\xeeo.G\xd6w\xd0\x11\xc4\xb0c\x1d\xae\x88\tt\rF\ -\xb6\xf0\x96W\x9f\xcd\x97\xaf\xffSN?\xb6\xc0\xe3\x1b\xe0\xef?\xf3[\xbe\xf3\ -\xdfw\xa3\xbdN\x06\xcb\t\x9d\xf3\x96!\x83NB\xe0\xee_\xde\xc6\x15\xe7\x9d\xca\ -\x9b/:\x9ev\xc0V\x15PY\xa2\x88\xb4\xb3\x18\xf8x\x1a\xfa\xfe\x85h\xb7\xdf\xec\ -\xb5k!my\xa9\xe6h`\xbc\xc4G\xa5\xf0\xa1\x0f\\\xc9Y/;\x83|>\xc7\xac\xd9s\x88\ -\xb4\x00\xe1A52\x81\xf2j\x19\xc6F\xa1V\xc6K*8I\x05WU\x08D\x84\x1dUp\xc3\xd0x\ -\xf0\xf0\x08S\x1f\xa7m>8\xb3\xb8\xef\xe9~\xae\xff\xd6]\xf8sr\xd4S\xe8\xb4\ -\xe1\xdc\x13V\xd3\x9d\x0c\xd0]\xac\xe0\x0e=\xcci+;\xf8\x8fO\xbe\x9b\xb7\\v\ -\x14\xed\x1e\xdcy\x7f\x85\xbf\xf9\xc4\xd7\xf8\xc9\xef\x9e\xa0\xec\xcfB\xe5\ -\xbb)G\x92r"\xb0\x1c\x17\x12hs\x15o\xb9\xf4\\\x0e\xea\x06K\x95AU\xcd\x1df^\ -\xc8\x98\xf1.k\x7fC\x9a\xec\x03\xd2\'B\x81\x88A\x86F\x8d\xc8\x1a\x8eg\xb4\ -\xe2\x9f\xbe\xf5d^{\xd9\xb9xv\x85\xb6\xa0\x0e\xd5\xcd\xe0\xa7Y\x0c\xde\x04\ -\x96e\xb5\x8a,W\xc8%\x8a\x82\xb0\xc9i\x0b]OH\xea1\x8e\x95\x03+O\\V\xc4*\xc0n\ -[\x88,\xce\xe5\xcb?\xf8\x19\x0fo59\xf5I\n\xef\xbb\xfa\xe5\xe8\xadOrX\xaf\xe4\ -\xcas\x8f\xe6C\xd7\x9c\xc3A\xcb\xa1\xe0\xc2\x7f}\xe7I\xde\xf3\xfe\xeb\xd88\ -\x10\xa2\xf2\xdd\xd4\xb1\x19\t5^{\x0fq\xa9B{!\xc0Vp\xc5\xc5\xe7q\xd8\xb26\ -\x920+\xc3\x990\x9b\x83\xc1\xfe\'\xe1\x06\xd2\xde\xfd0s/\xfbt\x85\xd5\xc8\ -\xf1\xca\x1e\x8a6s\x13fQ#\xb3\x8fR\x82j\xd5\xe3\xaaK\x96\xd2\xb5\xa0\x83\x8f\ -~\xf6k`\x07DI;I\x1a\xe0{yl\xcb!\xa9\x8c\x81\x8aq\xa5\x8bR\x16\xb5z\x8a\xe7uP\ -\x8b\x04\xe0\x99. \xac@\xaaIr\x16Z\xe4\x19\xf5\xba\xf8\xc4\x7f\xdc\xc4\xbf|\ -\xf0"\xf2\xc0\xac\x02\xbc\xeb\xf2\xf3Yr\xf8*\x8e:v\x11!\xd0W\x85\xbf\xfc\xe8\ -\x0fx\xe0\xa1\xb5\x14{\x0fg0\xc18k\xc6J$qJ\xd0\xdd\x89\xd0\x8a\xde\xbcC^\xc3\ -\xc9G\xaf\xa2\x02hG\x80\xf4\x8c6B\x820\x81\x92?V\n\xf2\x0b\x81\x88\x80\xddY"\ -{%\xe9f\x94\xaa\xb2)\xed$f\x1eDS0\xa8\xb3W\n\xb8\x96Ew\xce\xc2\x03.8\xae\x8b\ -\xaf\\\xf7.\x0e\xed\x8d\xe8T\xdbP\xd5a\xa2Z\x9d8J\xd1\xc2\xc1rrh\xdb\'\xc6\ -\xa1\xa6$\xd2+\xa2\x95DG\xb1\x89\xca\x15r&e8\xae\x91\x86!i~\x16\xf7<\xbe\x9e\ -\x1f\xfed\xa3\xb1\'\xca\xf0\xee7\x9d\xcbK\x8f]D\n\xdc\xfd\x84\xe6m\x7f\xf5\r\ -\xee||\x0b\x03\xa2\x8d-\xa5\x10\xa7\xd8\x8e\xaaW!\x08 \xdf\xc6\xd8H\t_\xa4\ -\xe4\xa8\x1b\xdf\xbb\x0e\xa9D&6\x14\x11\x80\xcc\x9b\x94m\xad\x10\x848Y\x94l\ -\x7fDy\x0f\xf2\xbcw\xea]KH\x1dH\x02P\x1eB{h>\xf1\x95o\xb3\xa9*Y\xb0\xf2\ -(F\x9fXKj\xe7\x19\x8b]\xb6\x95|>\xfd\xa5\xbb(\x01\x9dyx\xfdk\xcf\xa6>\xf2\ -\x0c\x9e+\x08\xc2\x98x\xb8\x9f\xee\xb6\x1cW\xbd\xf6X\xbes\xc3}\x1c|\xe0\x8aq\ -\xe9\xd4\x8dt\xe4\xd6\x9a\xb1q\x8c\x13\xbf\xf3cjH\xban\xaaxg\x1f\x97\x1e=_\ -\xa4{\x18O\xbc`Wj;f\xad\x11\xbf\xd8\x86\xeb{\x94+C\xc8$fQ\x0e\xe6\xc6\xf0\ -\xfeKN\xe0\'\xd7_\xcd\x812\xa4\x07S\xc40\x9a\xc2\xb5\xffz?\x1f\xfe\xd2\x0f\ -\x18t\xe7"f/a\xfd3\x1bpV\x1e\x86\x9b/\x10)\x8f\x8a\xe8\xe5\xee\xc7w\xf0\xc3_\ -\x0c1\x00\xbc\xe1\xc2U\x1c\x7fp7\xf3\x83\x145\xd8\x87\'SN9\xe9D\xe6v\xc2\xbd\ -\xf7\xdc\xc3\xa2E\x8b\x80\xcc6\xd3\x1a3\'\xba!\xbd\xd1\xaf\xef\xf2\x88Z;m\ -\xdd\xfa\xae\xa6\xec8\xde\xdb\'\xe3\xf4\xe7\tag\x05\nqL\xa8"\x8a\xf9\x00\xdf\ -V\x888\xc5\x93\xd0\xe1\x87XI\x8d\xd9\xb9\x1a\x05j\x08\r\x1f\xbf\xeek|\xe9\ -\xff~\x87E\x87\x9fD\x12t\x10\xd6\x12h\xef$V\x9ah\xd36\n]s(\xa7\x01\x9bG\x14\ -\xd7\xff\xeb\xd7\x19(\x19\xed\xf0\xb6\xd7\xbf\x8a\xda\x8eMty\x82\xae\xc0\xe6\ -\x95\xe7\x1f\xcd\x86m`9\x81\x99p7+\xb85\xde7\x9aD\x8a]\x94z\x86\ts\xc6\x8b\t\ -U\xb9\x12\x85T\x8a8\x8e\xff\x88O\xef\x7f\x0e\x97\xdd_\xcf\x0bB\xba\x16\xd9,S\ -\x12\x1c\xc7\xc3\x95.\xb2\x11\xa1\x93\xcad\xaf\x10\x9by\xc7t\x8cV!?\xff\xe9m\ -<\xf9\xe4\xe3\xd8\xb6M\xa9T2\x95\xa0(c\xaa\xc7\t\xcc\xea\xa5\\\xae\x83W\x00\ -\xbf\x00^\x9e/~\xf9\xbf\x18Tp\xf4\x81\x1d\x9cu\xfa\xc9x\xaa\xc6\xb1\x87.\xe3\ -\xb0\xc5\xf0\xe0\x83\x83l\xeb\xebg\xfe\xc2\xc5(\xc0u \tC\xe3o\xdf\xc3rV{k\ -\x9a;\x93M\xab\xf6"\xa2^\x19\xd8\xedw/\x98\xa47\xc2\xb1\xa6\x0f43?5EL\nSK\ -\xec\x14@\x06h\xe9s\xc6\x19g\xf0\xbew\xff\x19\xaf8\xed(j}O\xa1\x867c\xcb\x14\ -+\xe7\x9b\xf1V\xaa!\xc8\xe3\xe5\x1dR\x15R.Wx\xe4\xd1\xa7\xf9\xf5o\x9e \x01\ -\xdez\xf5\xc9\xb4\xb7\xb9\xbc\xee\x92\x97\x91\xc6p\xef\xbd\xf7\xa2\x84G\xef\ -\xfcN,a\xe4\xd4\xf6\xf2 mT\xad\x96]\xa5\x98\\]O\x14\xfb\xf1\xe2\x06hv\x08SM\ -\xd2\x0b\xf6\xee\xa9}\xc1\xe6\x86m\\\x82\xdd\x9c\x16_e\xb5\xba\xa6\x0e$\x05\ -\x12\x0b\x12<"\xa0\xcd\x83\xb3\x8fY\xcc\xbc \xcf\xc1\xbd>\xdf\xbc\xedN\x94\ -\xdb\xce\xa6\xda\x08\xa8"t\xcc\x81\xb1\x12\xe1\xf0\x00\xb3{}\xca\xfduB\x0b\ -\xbe\xf8\xd5\x9bYu\xf8J\x96\xf5\xc0\x9b\xdf\xf6\x06\x8e]\x01}\xa3\xf0\xe0\ -\x03\x0fPS6\xdb\xb6\xa7\x1c4\xcf\xa2\xd0\x1c\x8eI\xa3\x8a\xb4\xdc;\xa9n\x96m\ -\x99\xdfj\x00\xadQj\x8aE\xdd\xe5T\xe8\xd3i\xf8\xb8uK\r\xafefi\xb0\xa0\xa4\ -\x8d\xa5\x9e\xa51\x00\xc6\x87\x7f\xca!\xb3\xf8\xdb?\xbb\x80\xf7]u!\xc1\xd8V\ -\x18\xde\x82\xd7\x93\xb9X\xc3*N\xb7O\xa5\xbc\x83 \xc8\x13%\x01\xa3\x95\x80\ -\xf7\x7f\xe4\x87\xc4\xc09g\xe7q\x81;o\xfb5ZX\x08\xb7\xc0m\xbf\xbc\x8b0\xcb\ -\xd6\xaaE\x1a\xb0\x90\xb9\xfcs<\x8a\x9d\t5\x8e\xe6\xd6A\x9e\xe7M\xad\x94\xaa\ -ZR\xdc\xedw/\x98G\xae\xa1\xd6\r\xe1.\x86R\xb7\x99\xa5b\xd9\xe3\x93\xeb[\x8c\ -\xe7\xca\x0b]\xc3\xd55\xae:\xffT\xde\xf3\xba\x8bX>\'G\xb8\xe1qS\xd1\xd8\xe5\ -\x12G;PVB\xa8l\x84=\x0b\xd7_\xcc\x93\x0f\xae\xe5\x86\x1f\x0f`\x03C\x031w\xdc\ -\xfe3\xa4\x9b\xa3\xd09\x8b\x07\x1f~\x92j\x9c\x15]$\x98\xeb\xc1\x9e\xa0\xb2\'\ -b\'\xc2\x9b\xd5\xa3V6-\xe9\xc4B\xc2\xa9\x02\xb9\x07;\xe5\x05\x92t\x13\x9f\ -\xceRj1\xe1\x19\x0f\x84\x89\xc3\x0b\x146f\xdc\x9e\xc7\xe4\xdc\xb9\xdaT\xa9"\ -\x14Im\x8c\x9cT\xbc\xf1\xa2\xd5\xfc\xc5U\xafd^\xb7\x84\x91\x8dP\x1d\x00\xaa\ -\x90\xf7\xa8\xc9\x02\xb1\xecbxX3{\xc12n\xbe\xe9\xbfP@W\x8f\xc3\x8aU\x873:V\ -\xa5\x16C\x7f\xa9\xc2\xc3\x8f\xd5I\x01\'\x10\x99\x05\x9fi\x9f=\\\x7f#\x88d\ -\xd0\x90\xf4,\xc26\x05I\xdfS\xb5\xcd\x0bF\xba\x91c\x93O\x97\xca,\xedI\x98\ -\xef\\\xaa\xe4T?yJ\xe4SE!\xc2,b\x0cD\xe4!\xd7\x03R\x12\x8d\xc2e\xa7\xcf\xe6\ -\xb3\x1f|\x0b\xf3;\x81\xda\x00]\x8b\xe7S+WP\xf9\xb9TF-\xda\xf3\xb3\xa9\xf4\ -\x0f\xb0j\xe9,\x06\x06+\xa4\xc0\x85\x97]\xca\x8aC\x8ff\xb8TCaq\xcb\xad?\xa5\ -\x9a\xad\xdf\x93*\xcd\x1e\xe7`\x9d\x8cKm\xdc2\x8d\xcc\x9a\xc8q\xa6\\\x9f>\ -\x05$}\x1c-3\xd3\xb4\xcc\xc3\xa2\xcc?*\x06\x1d\x9a\xb5D]c\xf1\x9b\xc9\xb8$\ -\x90P\xc8k\\\r\'/\x83\xaf~\xfc\r\x1c\xbf\xa2\x97\xa1{\xee\xa0\xd8\xde\x85.\ -\x83\xd5>\x8f(L\xb1-X\xbet6\x0b\xba\xf3<\xb5\xb5F\xef\\x\xcd\x15\xe7\xe0\xd9\ -)\xbeg\xf3\x9b\xdf\xdeK\x98\x18)\x1d\x1e\x8b\xd0\xc2Fc\xd3X\x19a\xbc;\xca\ -\xd2\xa1[\'\x01\xda\xa9\x814#\x8dS\xa8\x8e\r\xa6\x04\xe9\x12\x13\xd6w\xccR\ -\xd3\xc2\x14\x96\x9a\x95\xd0$\xc6\xff\xd6\x06\xa2\x90\xe5\xc6\x9b\x9f4\xf2\ -\xeb]b\xb0\xca\xc4\xaa\x1ft\x8d\xc8\x81s\x8b8\xc0,[22\ -\xa8h\xebX\xc4\x1f\x1ez\x86\xcf|\xfe>.\xb9h1\x8b\x96\x1c\x08\xc2\xe2\xde\xfb\ -\xfbQ\xe9xL\\dG7v\x84m\x82\xa7\x99\x0by\x8f\xc6\xfd\x14\xc4\x9e\xea\xd3\xf7\ -\x13\xd2\x81T"\xa4\x83\xc4\xcc.\x12+\xc8\xe7l\\\x11"I9\xe1`x\xff;_\xc1\xca\ -\xb9\x82\xa3W\xcc\xc6\xc5t&]]\x07\xb0~\xf3\x08nn\x16?\xbb\xf3>~z\x17|\xf4\ -\xef\xff\x84HI~\xff\xc0\xc3\xc6\xed\xae\x1bj:\xcdV;\xd2\x13VWl]\x95q\xbf\x81\ -~\xd1\r\xb9\xe7\t\x8dYN"{\xf2\x96\x05\xa96\xf2n\x11b\xa9Qr\xc01\xcb\xe1\xba\ -\xf7_\xcd\xc5g\x1c\x83E\xcah\x05vl\x1f\xa2\xd81\x87\x9av)v\xcf\xe7\xba\xeb\ -\xff\x85\x91\x1a\\\xf2\x9a\xab\xf8\xcd\xef\x1e\xa4Z3\x06\xfax\xaaD\xd2X\x05\ -\x06\xd87\xd9\xae:s\xd36^i\x9a6_\r\x84aH\x9a\xa6\xcd1\x7f\xeb\xfe\x90\x90\ -\x00\xa126H\xe3\x15)\xbdk\xad]\xe3\xc3\x1e\xfc\x06\xfb\x07\xe9`\xae4m1\t-A-2\ -\xab9\x14\xa5\xc4\'!\x1d+s\xfc\xc1s9b\xc9\x1c\xda\xd1\xcc\xc9\xc3\xe6-\x1b\ -\xf1\x82\x1ca"\x19\xa8(B+\xcf\xbb\xfe\xfa\xffr\xd6+VP\x8e-\xd6o\xa9\xb5<\x85\ -F\\ \xc6"\xdeg\xb1\xf2\xc6T_\r\x95\xdb\x98\x15J\x08\x01\xf51\x08\xcbx\x0eX"A\ -\xc4uD\x1a"E\xb6\x18\xb0NM\xe1\r\x1aK\xea\tF\xb0Nc\x928B\x00a\xbd\x8eNU\xebI\ -\xf7\xf8(\xa7>\xb2j\'\x04\xd4\xc2\x908\x1b\\\xe5\xdd<\x16.\xa4\x1a\x11W\xe8-\ -z\xa4\xe5\x11\x02+!\xae\x0fa\x03\xed\x05\xc1Xe\x00\xcb\xcf\x91\x96cd\xd0I\ -\xea\x16\xf9\xcc\xbf<\xc2\xd5\xef\xfa\x0b~\xfc\x8b{vJa6K\xe9\n\xa2\xac\xa2g\ -\xdfX\xe7\x96e\x91\xa6)q\x1c7\xbdwJ)3\x8d\xba#\xcc\xf00\x8e\xb24\xf3F\x94\ -\xc2FH\x07!m\xacl\xe6Y\xadb\xd2$D\xa2\xf0\x1c\x1b\xcf\xb1\x89\xe3\x10\xdf\ -\xf3\x9b\xc3F\x9d$\xa8=D\xfd\xf6\x0f\xd2\xc1\x80\xaf\xebT\x06w0\xdc?\xc4\xdc\xa5\x07q\xed\xf5_\xc3\xeb\xceb\ -\x01\xd2\xf8\xff\xb0=\xd3p\xe2\x08a\t\x8c\x1e\xd8w\xf6{\xeb\xd4\x9e\xe6\x9f\ -\xec\xda\x85\xd5$|\xe7\xb3\x89\tY\xf6\xcd\x072\xfe\xd2r\x8f\x16{+\xf6\x0f\ -\xd2\x1b\x84\n;+\x97\xce\x86V\xad\x8d\xde2\x81\x1c\xe3\xb4i\xe4\x86\xa4\xf4\ -\x16\xe0\xb8e\xf0\xe1w\\\xce\x11\x8b\xdah\x17U,\xea89\x9fg\xd7oa\xb8\xa6\xf9\ -\xc4\xe7\xef\xa0?1\xd3\xcdTb\xcbx\x06\xa5o\xe6\xb3\xddG\xd3PL0\xdev\xda\xa6\ -\x11\xe8\xac\xd3j%\xbc\xb5\xa8\xa8\xf9\x1cv\x8a\xf7M [0\xf1}7\xd8OH7H1+I\x99\ -|\xf3\x16CE@$\xcd\xacV\xa1\x04-\xc7\x97\xd2\xc8\xbc\xfa\x9c\xbd\x12>\xf6g\ -\xaffA>bqO\x0e\x9d\xd6\xb1\x1d\x17\xa7m\x167\xff\xecn\xbeq\xd3\xd3\x0c\xa4\ -\xa0\x1c\x87\x94\x00\x84\x8f\x92\xbe\xe92\xb4\xb5\xd7R\xb4;\x08!\xcc2\x9e-\ -\xc47\xc3\xb1\xdaj\xe6\xe26\x08oPkgS\xbdL\xdc\xda\xf2j\x11~\xcd\xc4\xf7\xdda\ -\xbf \xbd\xb5:\x14\x1aFL\x16\xaa\xcdn\xd8\xd8\xdc\xe3\xce\x140\x99\xae"I\xc9\ -\xa5\x90\x8b\xe1\xb4\x83\x1d\xfe\xe9\x83o\xa5\xdd\x89\xe9\xca\xfb\xd8\x9eK\ -\xdf\xb6~f/]\xc9Wo\xb8\x99\xfb\x1e\xad\x9a\x86\x83\x99\xf5^\xfaEcX\xa9\xe7\ -\xdb\xa3\xef\xe1\xde\xb2\xbe\xbeU\xa14\x15y\xab\x86\xd1\xbbyg\xa22\x9a\xe4\ -\xeb]\xb0_\x90\x0e\xe3s\xbf\x98\xca\r\x05\x8d\tDE\x0cr\xe0`~t\xfb\xef\xf8\ -\xd1\xdd\x8f3\x02\xd4%D\x8d\xfc\xadf\x9e\xfb$\x8fu_\xf5\xf7{\xdca\xef\x8dH\ -\xb9\xd3\xfb\x9e\xf6\x99\xd2\x10\x98\xb5tl\x01\x0e\x0e\x16\x05 \xc8\xa2`f\ -\x98\xe6Ac\xab\x99\xb9\xd9\xf5Ll\xde\x96\xd9\xd87\x8f\xd76\x1b;IY\xe0\xc2\ -\x81\x12\xbe\xf6\xb7\x97q\xc9\x89+\xa8o\xde\xc8\x8e\x11\x8d\xbb\xe4\x04>\xfd\ -\xed\x9fs\xe3\x03\xb1I\xd0\x14\x1a\xc6v@2\x04\xba\x86\xd2!Ze\xae\x1c\x9d\x12\ -Gu\xb3@`\xc3\xa8\xcc\xd0\xe8\x8e\x1a.W\x98h\xc8M\xf6\x1a\x0f\xfa4\xfa\xeal\ -\x18\'\xadl8G3\xdc\xbc\xbb\x97\xdc\xe9}w\xd8/HG\x98\x11\x94\x91d\x89h\xa4.\ -\x88\xc6\xd2\x9eF\xa6\x1b\x8b\xceg\xae\x8f\xf1,\x17\x01\xb5\x84\xcc\xf6\xd1P\ -\x19&\x9f&\x1c\xde\x0b\xaf;\xef\x18\xde\xf0\xda\x97C8J\x14\'\xf8\xdd\x0b\xf9\ -\xf4\x17\xff\x93G\xb7\x82\xb0\x05\xe4\xf3P\xab\x80\x00)\xe4x\xb2\x84\x108\ -\xb2\xb1\xd2d\xb6m\xe7~6S\xe1\xad+5\xeci\xc5\x86\x89[[\xc8\xdfK\x9a\xf6\xd2x\ -\xdfOH\x7f\x9e\xd0\xc2\xcc[\xa8%\xa0ll\xa7\x13\xb4\x8d\xa3\xe1\xa8e\xf0\xce7\ -\x1e\xc6+_v \x0c?\x85]\x1dcd{\x89/|\xf9G\x8c\x01\xa1\x93G\x15g\xa3\x85G\xd2\ -\xacv\xcb\xe4\xd2r\xd0\xc2BO\xa2}\x05\xec\x91\xe0\x17\x13\xd3\x82t\x03E=\xa9\ -\x93&Y>\x9e\x06B\x85\xa7`\xb1\x0f\x7f\xf1\xfa\x97\xf0\xea3\x0e\xc5\xad\xf6\ -\xd3\x95\xcb\xf1\xe0Ck\xf8\xee\x1dCl\x03F,\x8f\n6\x89\xb2\x88\x12\x88\xb54\ -\x8e`\x01\xd2\xb6v\x89m4U\xecsH\xf6\x8b\x85iB\xba"%\xc6\xb1m,O\x1a\xc2\xe3\ -\x10\xcbI)\xc8\nAR\xe6\xb0N\xf8\xec{\xcf\xe3\xb4C\x17\x10\x8f\xf4\xd1\xd3;\ -\x87\xcf~\xf5F\x1e\x19\x82\x1dd\x0b\x13H\t\x96eV\xf2nt\xe3\xcdj\x97\x0c\xcdb\ -\xc8\x19\xd2_tX\x8dq\x97P`\xc5&jG\x08:&oC\x1b\x8a\x9c\x86/~\xec2.8c5\x03\xdb\ -\xd7SKS>\xfc\x0f7Sa\xbc\x10\xa3\x91I\xd5(\xa7\x9b4\xa3f\x1fy\xf1\xfeX\x98&\ -\xa4K\x046\xf50\xa4R\x1f\x05\x19\x82\x15\x9a\xc9\x7fc\x01\xa9G:Z\xa6M\x80\ -\x1d\xc2?\xbe\xefB\xce=\xf3p\xfa\xb7\xaf\xa7ZQ|\xeb\x07\xfd\x8cE\xe3\x1exM\ -\x96\x9e\xfd\\\xe4NQ\xe2\xa7\x05\xe9\x02H\xa2\x84\xbc\x17\xe0\xfb.!\x11\x91\ -\x8a\xc1\xf1\xc1\xc9\x93\x94\x13\xdc|\x1b\xd5\xe1Q\xba=\x93\xac}\xcd\x9f\x9e\ -\xcfU\x97\x9cM\xdf\xba\xa7\xf8\xc1\r\xdfah\x08\xc6j\xe3\xf9yM\xe2\x9f+\x7fn\ -\n\x12?-H\x07\xf0\\\x89@e\x91x\x0f%\x0b\x84\x04\xa4\xc2\xc6.\x06\xe8\x04\xf2\ -m\xed\x08B\x02\x14s\x1cx\xcf\x1b\xce\xe2\xeaW\xbe\x94\xea\x96g\xf8\xfb\xbf\ -\xbb\xaeIx\x98dCg\xb1\xc7\xac\xa4qL1\xe2\xa7\t\xe9\r_\xbd\xa9\xa5\xd3\x04\ -\xa4\x98!X\x8c\t\xd6\xa4\r\xef\x88\x12\xc84&\x07,*\xc0\xe5/;\x92\xf7\xbd\xf3\ -r\xb6\xac\x7f\x86o|\xf3\x87\xa4\xda\xe4:TjF\x83( \x8e\xf7A\xc0\xfd\x05\xc4\ -\x0bV\x9f\xfe\xe2"\xc5\x84Q$\x82B\x93\x9f\x863\xd5\xc2\xccLavu\xd1Q\x8a\xed\ -\x19g\xdeQ\x8b-\x96\xf5\x9e@2\xb6\x99\x9b\x7f|3\x87\x1dr\x10/9q%A\x00c\xd5\ -\x94\xf6\x9cE\xb5^\xc5u\xf2\x13\xdd\xa5\xcf3*\xf7\xc7\xc44!}\x1c\x96\x1e\x0f\ -X\x08\xc65\xafB\x91"\xb1$H\xcb2qZKa9u\xba\x02\x87\xab\xdf|)\x96\xedr\xe3\x8d\ -7\xb0\xfa\x88\x8f\xd0\x96\x83|\xce\x0c\xdf\xf2\xc5|\x16\xe7\xdf\t\xad\'\x98B\ -\x98\xba\xcdq\x9f\xa2Q\x80db\xec\xb66\x93\x15{\xda\x8c\xdcl\x14)\xa9\x19{\ -\x9bl\xa5,\x11Sd\xbe\xf5\x08O\xc2[\xde\xf8\n\x0e=t\x15\xd7_\xffO\x84Y\x0e\ -\xa3\xd2\x8d\xf8\x9f\xca\xca$\xc6O9\x05\xf9\x06\xa6\r\xe9\xa6B\x86\xc6j\xc6:\ -\x1b\xaek\xb0\xb5\xc2\xc5\x04rD\x16\x97O\x9b\x19\x0c\xc2,C\xa5m\xea\xa1i:oy\ -\xd3et\xb4\xb7\xf1\xc8#\x0fQ\xadG8V\xebr\x00\xc6\xd4\x9b\x10\xdf\x9e\x82\xd5\ -1\xd3\x83t\r\xba\x99V\x94`*\'J\xa0\xca\xa6"5\x95\xd8\n\xb3\xc4\xbb0C\xf7\xa4\ -\xe1bW9H=|\x0f\x12m\xfa\xf9w\xbf\xf3\xadl\xd8\xb0\x0e\xcb\x16\x94\xab\xa5\ -\x9dO\xd5Dk\x10v*I\xfd\xf4 \x1d&\x96\x80\x88\x14D\xe6j\xc9\xc4R%\xe3\x99*\ -\xa6+\xce\xe6\\\x94\xa2\x19\xd2lD\xf0\xd2\x04.\xbf\xe4b6\xad_G1W@L)J\x9f\x1b\ -\xd3\xc3\x90\x13-#*aaT}\xf6Yg\x81\xd8,\xc9f\\\n\xb2\x19\xa2\xb3\xe8\x89\x8b\ -\xd1\xf6`\x96\x10\x95\xc0\xca\xe5+\x1a\x87\xdf\t\xb2\xe5/\xbb\xd9\xe7\xc5\ -\xc3\xf4 \x1dZ\x9ezKB\xe1\x84\xed\xbb!F\x8c\xbf\xfdOgq\x99JD\xb7b\xfa\xa8\ -\xf7\x1941C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\ -\xd3\x103\xa4OC\xcc\x90>\r1C\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1C\ -\xfa4\xc4\x0c\xe9\xd3\x103\xa4OC\xcc\x90>\r1EH\xdf\xbfr\xcc\xf6wL\t\xd2\xe34\ -d\x86\xf8\x17\x0eS\x82\xf4hJ\xae\x82\xf2\xff/\xa6\x04\xe9\xbe\x9c\x91\xf2\ -\x17\x12S\x82t-\xfe\xb7\xb3\xf3M\xd5)\x1f\xa6\xe25\x8dcJ\xa4@\xdb\x93\xb5=\ -\xadI\x84\xc2V\x16J*\xd0\x12\x89&\x15\x02\x89"\xd5\x1a+M\x88\xa5\x8d\x14)\ -\xb60\xab\xbc\xbdX\xd0\xa9"\x15\x02\x91\xc6\xc4\x96\xc6\x93\xde\xa4W\xb3~\ -\xfdz\x1c\xc7a\xce\x9c9\x13\xb67\xe6\x8d}!0%$}2\xb2T\xa3\xd2@\x98\xd9^\x04)\ -\x1a\xcd\xffk\xef\xdc\x83\xa3\xaa\xee\x00\xfc\x9d{\xf6\xbd!\xbby@\x1e\xc4@B\ -\x91G\x84\x12\x9fT\xd1RPl3\xad\xb4\x96\xf1Q\x18t\xda\xd2Z\xb1\xd3\x8aN\xad:\ -\xe3L\x9d\xda\x87Z-\xed\xd4>\xa6\xd5"\x91\x82\x03\x96\xfa\xc0X\xa7(T#\x85\ -\x82$D\xb0\x89\x08I\x0c\xe4\x9d\x05\x93\xecn\xf6\xde{\xfa\xc7n\x96DQ\xab\xd3\ -Ml\xef\xf9f2\x9b=\xd9\xdc\xf3\xf8rN\xee9;\xfb\xfb\xc9\xd4g\xc5\x84er\xef\xd6\ -F\xae\xb9\xf7y\xdel\xef?\xed5\xc6\n\x05\xbc\xde;\xc0\xf7\xff\xb0\x93\x1d\x07\ -;pY\xa7\x17\x0eP]]MMM\r\'N\x9c\xe0\xd1G\x1f\xa5\xb1\xb1\x91G\x1ey\x84\xba\ -\xba\xba1k\xef\xc7D\xfa;IJN\xcem\x93\x96\x9e(\x1bw\x1de\xd3\xee\xa3\xe9\xb4\ -\x1b]\t\x17?\xdc\xf2\x1a[_\xf3\xf0\xa7\x1dM\xe3\xbe\xa0>\xb3\xfd ?\xdf.\xb8\ -\xfb\x99\x06\x94|\xff\xdd\x88\x10\x82p8Lqq1S\xa7N%\x1a\x8d\xd2\xd1\xd11fm\ -\xcd\xe8\xf2>\x94\xb0pK\x85e\x08\xa4J~TT\x90\n\xa5-\xe0T<\xae\x91\x03\x94\ -\x9c#B\xd9\x08\x1b,\xe1\xe2\x9fotp\xdd/^%\xe8J\xb0\xf4\xfc2\xfcJ\x91\xebMp\ -\xe3\xe5\xa5\xec>\x1c\xe1\xf3\x17\xccyG\xcd\n\xc5\xc8x\xab#\xeb\x19\xf98\xfc\ -\xddp\xfd\x1fm\xb5\x10(\x96]:\x8b!\xeb0\x8b\xcf\x9d\x82aI\xde/i\xfd0\x15\x15\ -\x15H)Y\xb6l\xd9\xa8\xccM\x99&\xa3\xd2=n\x89\xb2m\xa4\x82\x98ms\xe8\xf8 GZ"\ -\xc4\xf0p\xd6d?3J\xfc\xf8\x94\x1b%-\x94\xad\x88\x9a\x06\xbb\xdf\xec\xa3\xad;\ -BQ\xb6\x97\xca\x99\xc5\xf4\xf4D8\xdc\x97\xc06\x14\t\x95M}k\x07>\x9f\x0f\xc30\xd2\xe1>G\x86\xff\ -\xec\xee\xee&\x18\x0cR\x9a\x93\xc5\xf7\xae\x9e\x9b\\:\x85\xc0\xb6m\x84\x10$\ -\x12\t:::\x08\x04\x83\x84\xc2\xa1d\xfax\x92\xf9\\JJJ\x00(**\xca\xa4\x86w\x91\ -\xf1\x1b9\x05\xf4\x0f\xc6\xf9\xea\xda\xbfSS\xd7\x8de\xc0\x90p\x13\x182\xf8\ -\xe6US\xb8\xe7\xaasp+\x83W\x8e\xf6p\xd3\xaf^\xa6\xfe\x98\x00\x97\xc4P6\xb3\n\ -\x0f\x92\xe3\x1f\xa2\xf6\x88\x0b\x0bA,\xa1\xb8\xe8\xce\xed\x84d\x90\xa3\x0f/\ -e\xf9\x8f\x9f\xa2\xa5g\x90_\x7f\xe7\x12ZZ\x8e\xf1\xe3\'\xdb(\tK\xf6\xfe\xe2J\ -\xbcF\x82\x9e\x98\xe4\xf2;\x9f\xa6\'\xe1\xe1\xe9\xdb?E\xce\xec"\xee\xdf\xba\ -\x97\x9f<\xf9&\x03\xa6@*APD\xf9\xc1\xf2O\xf2\xed\xcf\xcd\xc1\xad\x12\xf4\x0f\ -Fyx\xddz\xfeQ[\x0b@ \x10\xe0\x8a+\xae`\xe3\xc6\x8d\xdcr\xcb-TVV\xb2v\xed\xda\ -t\x1e\xb5\x83\x07\x0f\xb2r\xe5J\x16/^\xccu\xd7]\xc7\xea\xd5\xab\x99?\x7f>\ -\x00555l\xde\xbc\x99h4\x8a\x90\x06\xf3\xe7\xcf\'\x1e\x8f\x8f{\xae\xf5\x8cK7\ -\x0c\x83`\xd0O\xc1\x14\x1f_\xcc\x9d\xcc\xf2\x85g\xd1u\xbc\x9b\x1b\xffX\xc7\ -\xef6\xb7q\xd3\xc2\x99d\x07\x13\\\xff\xc0v\x0e\xf7e1=4\xc8\xf9\xb3\xf2\xd9\ -\xd3\xd0\xca\xea+?M\x7fg;\x86g\x80\x17\x1bM|\x86\xc9\x17..\xa7\xc0\xb6\xf0\t\ -E\xdc\x08\x11w\x05\x10\x18\\\xb3\xe4l~\xba\xad\x87\xa3\'\xa0\xb6\xfe-.\x9dW\ -\xc2\xb6\xbdo\xd0\x13\xf70\xbb\xc4\xcf\xe2Y\x93x\xf8\xa5f\xee\xde|\x84)9n~p\ -\xd5\\ZNJ~\xb4\xe9\x00\xb7\xafo\xe2\xe2\x8aR\xce)\xf4\xf2\xf0\xba\xc7\xa8\ -\xab\xdb\xcf\r7\xdc\xc0\xec\xd9\xb3iiia\xdd\xbau\xa3\xfa$\x84\xe0\xc0\x81\ -\x03,X\xb0\x805k\xd6P\\\\\x9c\xce\xc04\x1c!r\xd7\xae]<\xf6\xd8c,Y\xb2\x84\ -\xcb.\xbb\x8ch<\xc6\x96-[8r\xe4\x08eee\x99\x1e\xf6\xf7e\x0c\xb6l\n\x03\xc1=_\ -\xba\x88\xed\rm\x1c\x8a\n\n1\xc6\xf9\xc89\xa3\xd2]\x98\xd8\xb8\xf9\xe5\xb6\xfd\ -4\xf5x\xa9\xaa\x94\xfc\xe6[K\x08\x05}|\xee\xee\xed\xbc\xf2F\x84!\xe1\xa6p\ -\x92\x1b0y\xbd\xb5\x9f\xe6\x9e(\xd3s\x0f\xd7.\x9e\xc07/=\x13\ -\x054\xf7\xbd\xcd\xe4\xf0\x04\xf2C\x01\xf2I\xe0\xb6\\tt\xb6\x02\xb3\xd2\x15\ -\xb4\xb5\xb5}\xe8\xbeggg\xd3\xde\xde\x9e~>\x9c\xd2\xa3\xa7\xa7\'}\x037^d|\ -\x9fn+\x85e&\x90v\x82\x81\xb8\xcd\xfe\xd6\x08\x0f=\xf9\x1a{\x9b\xdeF\xe1A\n\ -\x9b/\x9d\x13bj\xbe\x8bn\x95\xc7\xa5w>\xcb\xb2\x07j\xa9\xbc\xf9\x19~\xbb\xa3\ -\x19Sx\xc8\x91&\xca\x10\x0c\xaa +\xee\xdb\xcew\x7f\xb7sD\n\xdcTG\x0cI\x96\ -\x01+?3\x15\xa4E\xed\x1bCH\xcbdY\x1f\x03%\x00\x00\x04\xd0IDAT\xe5%e\xb8\x84\ -\x8d[%\xb8\xfe\xb3sq\xa9A\x9e\xd8\xd5\xc6\xb6=\xcd\xe8\n\xff\xb3dt\xed\xb1\x85L\x07\xe0\x1d=\xbc\x1fe\xc6\xbc\xdf\ -\x9c=\xddk?\xec\xb5\x9dCF\xa5\'l\xc5\xe8,\xb1\x9a\x8f\x03\x19]\xde}\xf2t\xeb\ -\xb8f\xbc\xf9\xf8\xddZj2\x8e\x96\xee@\xb4t\x07\xa2\xa5;\x10-\xdd\x81h\xe9\ -\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\xa5;\x10-\xdd\x81h\ -\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\xa5;\x10-\xdd\ -\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\xa5;\x10-\ -\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\xa5;\ -\x10-\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\xa2\ -\xa5;\x10-\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\x07\ -\xa2\xa5;\x10-\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x96\xee@\xb4t\ -\x07\xa2\xa5;\x10-\xdd\x81h\xe9\x0eDKw Z\xba\x03\xd1\xd2\x1d\x88\x0b`\xe3\ -\xa6\xc7\xc5\xc6M\x8f\x8fw[4c\x84PJ\xa9\xf1n\x84fl\xf97\x87\xba&\x9e\x12\xca\ -GT\x00\x00\x00\x00IEND\xaeB`\x82' - -def getWizardDataOld(): - return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00t\x00\x00\x01\x04\x08\x06\ \x00\x00\x00\xf9\xcf\x10R\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ \x00\x0f\xdfIDATx\x9c\xed]K\xb6\xe3(\x0cU\xf5\xa9MU\x86\xd9\xd6\xcb\xd0\xd9\ @@ -962,6 +288,6 @@ def getWizardBitmap(): def getWizardImage(): - stream = cStringIO.StringIO(getWizardDataOld()) # NOTE: This reverts us to the bitmap Peter likes. + stream = cStringIO.StringIO(getWizardData()) # NOTE: This reverts us to the bitmap Peter likes. return ImageFromStream(stream) diff --git a/wxPython/samples/ide/activegrid/tool/XmlEditor.py b/wxPython/samples/ide/activegrid/tool/XmlEditor.py index 0c27e51f15..66fd95cf1e 100644 --- a/wxPython/samples/ide/activegrid/tool/XmlEditor.py +++ b/wxPython/samples/ide/activegrid/tool/XmlEditor.py @@ -109,7 +109,7 @@ class XmlCtrl(CodeEditor.CodeCtrl): # Tag self.StyleSetSpec(wx.stc.STC_H_TAG, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces) # Attributes - self.StyleSetSpec(wx.stc.STC_H_ATTRIBUTE, "face:%(font)s,fore:#00007F,bold,size:%(size)d" % faces) + self.StyleSetSpec(wx.stc.STC_H_ATTRIBUTE, "face:%(font)s,fore:#007F7F,bold,size:%(size)d" % faces) class XmlOptionsPanel(STCTextEditor.TextOptionsPanel): @@ -118,13 +118,16 @@ class XmlOptionsPanel(STCTextEditor.TextOptionsPanel): STCTextEditor.TextOptionsPanel.__init__(self, parent, id, configPrefix = "Xml", label = "XML", hasWordWrap = True, hasTabs = True) + def GetIcon(self): + return getXMLIcon() + + XMLKEYWORDS = [ "ag:connectionstring", "ag:datasource", "ag:editorBounds", "ag:label", "ag:name", "ag:shortLabel", "ag:type", "element", "fractionDigits", "length", "minOccurs", "name", "objtype", "refer", "schema", "type", "xpath", "xmlns", "xs:complexType", "xs:element", "xs:enumeration", "xs:field", "xs:key", "xs:keyref", "xs:schema", "xs:selector" ] - #---------------------------------------------------------------------------- # Icon Bitmaps - generated by encode_bitmaps.py #---------------------------------------------------------------------------- @@ -136,19 +139,17 @@ def getXMLData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x01\x1aIDAT8\x8d\xed\x92?N\xc3P\x0c\xc6\x7fv\xf2\x924\xa8E*7\xe1\n\xbd\ -\x01G\xa8\xd8\x989\x05S/\xd0\x0110\xf4$\xa0J\xdd\x18\x18XY\x82\xa0\xad\xd2\ -\xfc\xe9{f\x08-\x02\xc1\xd4\x85\x01/\xb6l\xd9\xdf\xf7\xd9\x16\xd1\x88CL\x0f\ -\xea\xfe\x13\x03\xc4\xae\xcf\x8d\xb6\x84\xba\x84m\x83e\x03\xa8\x96\x88F`\x86\ -\xf5\x06\xc8\xba\x80\xf4\x08\xda\x1a\xf2cB04q\xcc\xe7\x0bb\xbb\xbf\x85\xd75\ -\xf2\xb1K\xc9\x12\xa8\x9aO\x84o\x88\xb6\x0bbxx\x04\xc5e\xe0:%\xe5\xd4\xa0j:\ -\x0f\xd4\x93\x82\xcd\xe9\x19\xf5\xa4\xd8\xd7\x97\xe2\x904\x82D\x89bA\xa5\xad\ -!\x85\xb0\x82|,\x94S#\x1fw\xb8\xbe?\xc4\x8d.\xf0\xfd\xe1\x9e\x81\x7fk\x91\ -\xd6\x83\x05\xcc\x0c\xf5\xea\xf0U@\xfb\xec\x9bw\x0c\x00\xe2\xab\xd1\x17\t\ -\xd9\xcc \x80o\xc1D\x11\xbb<1^\n\xf0\xbf\xacy\x03\xf4~\xc8g0{R\xe2\x9b\xc5\ -\x8aM\x03\xd4\xe0=\xb8\xb4;\x88\xc6 \nQ\x1e\xe1W\x1e\x89\xc1W\xe0\xb7\xa0=Hr\ -\xb8{\x0e\xc8\xff+\x1f>\xe0\x1d~\xafr\x13\x04HY"\x00\x00\x00\x00IEND\xaeB`\ -\x82' +\x00\x01\x08IDAT8\x8dc\xdc{\xf6\xde\x7f\x064p\xfb\xd1K\x06\x06\x06\x06\x86\ +\xd7o\xbf2\xd4\xa5\xb93\xa2\xcb\xa3\x80\xbdg\xef\xfd\xbf\xff\xed?\x1c_\xf9\ +\x04\xc13\xd6\x1f\xff\xbf\xeb\xf9\xff\xff\xcds\xf6\xfcgdbf\xc0\x85\x99\xb0\ +\x19\xfa\xe5\x17\x82m\xee\xed\xcc\x90Z\xb7\x08\xc3\x950\xc0\x82\xcc\xf9\xfa\ +\x07\xc1~\xfd\xf6+\xc3\xeb\xad{\x19\x1e?y\x89\xd7\x07,\xe8\x1aa\xb6\x9b{;300\ +00(\xfdb`88\x7f\x19N\x03\x98`\x01\x86\xac\xf9\xd3o\xa8+\xa0\xfc\x07\x0f\x1e\ +\xe3w\x01\xb2\x9f\xd15\xbf\xfa\x8e\xd7\x07\x0cL\xaf\xdf~%[3\xdc\x050\x8d\xa4\ +jf````LkX\xfa\x7f\x8a\xcdi\xe2T\xe3r\x01\x03\x03\x03\xc3\xa7#\x13H\xd6|\xea1\ +\x03jB\x12\xae\xffO\x14\x8d\x0cP\x0cx\xdb\xc8\xc8 \\\xff\x9f\xe1m#"\xf9c\xd3\ +\x84b\xc0\xec\xa68\xb8j\x98fdM\xc8\x86\xc1\xd4 \xcb32213\xfc\xdc\x95\xfb\x9f\ +\xdc0`A\xe6\x90\x03\x00\x11\x95\x8b;4e.A\x00\x00\x00\x00IEND\xaeB`\x82' def getXMLBitmap(): diff --git a/wxPython/samples/ide/activegrid/tool/project.py b/wxPython/samples/ide/activegrid/tool/project.py new file mode 100644 index 0000000000..babdadea42 --- /dev/null +++ b/wxPython/samples/ide/activegrid/tool/project.py @@ -0,0 +1,549 @@ +#---------------------------------------------------------------------------- +# Name: project.py +# Purpose: project model for wx.lib.pydocview +# +# Author: Morgan Hua +# +# Created: 8/25/05 +# CVS-ID: $Id$ +# Copyright: (c) 2005 ActiveGrid, Inc. +# License: wxWindows License +#---------------------------------------------------------------------------- + +import copy +import os +import os.path +import activegrid.util.xmlutils as xmlutils +from IDE import ACTIVEGRID_BASE_IDE +if not ACTIVEGRID_BASE_IDE: + import activegrid.model.basedocmgr as basedocmgr + import AppInfo + +#---------------------------------------------------------------------------- +# Constants +#---------------------------------------------------------------------------- +# Always add new versions, never edit the version number +# This allows you to upgrade the file by checking the version number +PROJECT_VERSION_050730 = '10' +PROJECT_VERSION_050826 = '11' + + +#---------------------------------------------------------------------------- +# XML Marshalling Methods +#---------------------------------------------------------------------------- + +def load(fileObject): + version = xmlutils.getAgVersion(fileObject.name) + # most current versions on top + if version == PROJECT_VERSION_050826: + fileObject.seek(0) + if ACTIVEGRID_BASE_IDE: + KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile} + else: + KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo} + project = xmlutils.load(fileObject.name, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES) + elif version == PROJECT_VERSION_050730: + fileObject.seek(0) + project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}) + project = project.upgradeVersion() + else: + # assume it is old version without version number + fileObject.seek(0) + project = xmlutils.load(fileObject.name, knownTypes={"project" : Project_10}) + if project: + project = project.upgradeVersion() + else: + print "Project, unknown version:", version + return None + + if project: + project._projectDir = os.path.dirname(fileObject.name) + project.RelativeToAbsPath() + + return project + + +def save(fileObject, project, productionDeployment=False): + if not project._projectDir: + project._projectDir = os.path.dirname(fileObject.name) + project.AbsToRelativePath() # temporarily change it to relative paths for saving + if ACTIVEGRID_BASE_IDE: + KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile} + else: + KNOWNTYPES = {"ag:project" : Project, "ag:file" : ProjectFile, "ag:appInfo" : AppInfo.AppInfo} + + savedHomeDir = project.homeDir + if productionDeployment: + # for deployments, we don't want an abs path in homeDir since that + # would tie the app to the current filesystem. So unset it. + project.homeDir = None + + xmlutils.save(fileObject.name, project, prettyPrint=True, knownTypes=KNOWNTYPES, knownNamespaces=xmlutils.KNOWN_NAMESPACES) + + if productionDeployment: + project.homeDir = savedHomeDir + + project.RelativeToAbsPath() # swap it back to absolute path + + +#---------------------------------------------------------------------------- +# Classes +#---------------------------------------------------------------------------- + +class BaseProject(object): + + __xmlname__ = "project" + __xmlexclude__ = ('fileName', '_projectDir', '_getDocCallback') + __xmlattributes__ = ("_homeDir", "version") + __xmlrename__ = { "_homeDir":"homeDir", "_appInfo":"appInfo" } + __xmlflattensequence__ = { "_files":("file",) } + __xmldefaultnamespace__ = xmlutils.AG_NS_URL + __xmlattrnamespaces__ = { "ag": ["version", "_homeDir"] } + + + def __init__(self): + self.__xmlnamespaces__ = { "ag" : xmlutils.AG_NS_URL } + self.version = PROJECT_VERSION_050826 + self._files = [] + self._projectDir = None # default for homeDir, set on load + self._homeDir = None # user set homeDir for use in calculating relative path + if not ACTIVEGRID_BASE_IDE: + self._appInfo = AppInfo.AppInfo() + + + def __copy__(self): + clone = Project() + clone._files = [copy.copy(file) for file in self._files] + clone._projectDir = self._projectDir + clone._homeDir = self._homeDir + if not ACTIVEGRID_BASE_IDE: + clone._appInfo = self._appInfo + return clone + + + def initialize(self): + """ Required method for xmlmarshaller """ + pass + + + def GetAppInfo(self): + return self._appInfo + + + def AddFile(self, filePath=None, logicalFolder=None, type=None, name=None, file=None): + """ Usage: self.AddFile(filePath, logicalFolder, type, name) # used for initial generation of object + self.AddFile(file=xyzFile) # normally used for redo/undo + Add newly created file object using filePath and logicalFolder or given file object + """ + if file: + self._files.append(file) + else: + self._files.append(ProjectFile(filePath, logicalFolder, type, name, getDocCallback=self._getDocCallback)) + + + def RemoveFile(self, file): + self._files.remove(file) + + + def FindFile(self, filePath): + if filePath: + for file in self._files: + if file.filePath == filePath: + return file + + return None + + + def _GetFilePaths(self): + return [file.filePath for file in self._files] + + + filePaths = property(_GetFilePaths) + + + def _GetLogicalFolders(self): + folders = [] + for file in self._files: + if file.logicalFolder and file.logicalFolder not in folders: + folders.append(file.logicalFolder) + return folders + + + logicalFolders = property(_GetLogicalFolders) + + + def _GetPhysicalFolders(self): + physicalFolders = [] + for file in self._files: + physicalFolder = file.physicalFolder + if physicalFolder and physicalFolder not in physicalFolders: + physicalFolders.append(physicalFolder) + return physicalFolders + + + physicalFolders = property(_GetPhysicalFolders) + + + def _GetHomeDir(self): + if self._homeDir: + return self._homeDir + else: + return self._projectDir + + + def _SetHomeDir(self, parentPath): + self._homeDir = parentPath + + + def _IsDefaultHomeDir(self): + return (self._homeDir == None) + + + isDefaultHomeDir = property(_IsDefaultHomeDir) + + + homeDir = property(_GetHomeDir, _SetHomeDir) + + + def GetRelativeFolders(self): + relativeFolders = [] + for file in self._files: + relFolder = file.GetRelativeFolder(self.homeDir) + if relFolder and relFolder not in relativeFolders: + relativeFolders.append(relFolder) + return relativeFolders + + + def AbsToRelativePath(self): + for file in self._files: + file.AbsToRelativePath(self.homeDir) + + + def RelativeToAbsPath(self): + for file in self._files: + file.RelativeToAbsPath(self.homeDir) + + + #---------------------------------------------------------------------------- + # BaseDocumentMgr methods + #---------------------------------------------------------------------------- + + + def fullPath(self, fileName): + fileName = super(BaseProject, self).fullPath(fileName) + + if os.path.isabs(fileName): + absPath = fileName + elif self.homeDir: + absPath = os.path.join(self.homeDir, fileName) + else: + absPath = os.path.abspath(fileName) + return os.path.normpath(absPath) + + + def documentRefFactory(self, name, fileType, filePath): + return ProjectFile(filePath=self.fullPath(filePath), type=fileType, name=name, getDocCallback=self._getDocCallback) + + + def findAllRefs(self): + return self._files + + + def GetXFormsDirectory(self): + forms = self.findRefsByFileType(basedocmgr.FILE_TYPE_XFORM) + filePaths = map(lambda form: form.filePath, forms) + xformdir = os.path.commonprefix(filePaths) + if not xformdir: + xformdir = self.homeDir + return xformdir + + + def setRefs(self, files): + self._files = files + + + def findRefsByFileType(self, fileType): + fileList = [] + for file in self._files: + if fileType == file.type: + fileList.append(file) + return fileList + + + def GenerateServiceRefPath(self, wsdlFilePath): + # HACK: temporary solution to getting wsdlag path from wsdl path. + import wx + from WsdlAgEditor import WsdlAgDocument + ext = WsdlAgDocument.WSDL_AG_EXT + for template in wx.GetApp().GetDocumentManager().GetTemplates(): + if template.GetDocumentType() == WsdlAgDocument: + ext = template.GetDefaultExtension() + break; + wsdlAgFilePath = os.path.splitext(wsdlFilePath)[0] + ext + return wsdlAgFilePath + + + def SetDocCallback(self, getDocCallback): + self._getDocCallback = getDocCallback + for file in self._files: + file._getDocCallback = getDocCallback + + +if ACTIVEGRID_BASE_IDE: + class Project(BaseProject): + pass +else: + class Project(BaseProject, basedocmgr.BaseDocumentMgr): + pass + + +class ProjectFile(object): + __xmlname__ = "file" + __xmlexclude__ = ('_getDocCallback', '_docCallbackCacheReturnValue', '_docModelCallbackCacheReturnValue', '_doc',) + __xmlattributes__ = ["filePath", "logicalFolder", "type", "name"] + __xmldefaultnamespace__ = xmlutils.AG_NS_URL + + + def __init__(self, filePath=None, logicalFolder=None, type=None, name=None, getDocCallback=None): + self.filePath = filePath + self.logicalFolder = logicalFolder + self.type = type + self.name = name + self._getDocCallback = getDocCallback + self._docCallbackCacheReturnValue = None + self._docModelCallbackCacheReturnValue = None + self._doc = None + + + def _GetDocumentModel(self): + # possible bug is if document gets replaced outside of IDE, where we'll return previous doc. + # originally added a timestamp check but that increased the time again to 4x + if self._docModelCallbackCacheReturnValue: # accelerator for caching document, got 4x speed up. + return self._docModelCallbackCacheReturnValue + + if self._getDocCallback: + self._docCallbackCacheReturnValue, self._docModelCallbackCacheReturnValue = self._getDocCallback(self.filePath) + return self._docModelCallbackCacheReturnValue + + return None + + + document = property(_GetDocumentModel) + + + def _GetDocument(self): + # Hack, just return the IDE document wrapper that corresponds to the runtime document model + # callers should have called ".document" before calling ".ideDocument" + if self._docCallbackCacheReturnValue: # accelerator for caching document, got 4x speed up. + return self._docCallbackCacheReturnValue + return None + + + ideDocument = property(_GetDocument) + + + def _typeEnumeration(self): + return basedocmgr.FILE_TYPE_LIST + + + def _GetPhysicalFolder(self): + dir = None + if self.filePath: + dir = os.path.dirname(self.filePath) + if os.sep != '/': + dir = dir.replace(os.sep, '/') # require '/' as delimiter + return dir + + + physicalFolder = property(_GetPhysicalFolder) + + + def GetRelativeFolder(self, parentPath): + parentPathLen = len(parentPath) + + dir = None + if self.filePath: + dir = os.path.dirname(self.filePath) + if dir.startswith(parentPath): + dir = "." + dir[parentPathLen:] # convert to relative path + if os.sep != '/': + dir = dir.replace(os.sep, '/') # always save out with '/' as path separator for cross-platform compatibility. + return dir + + + def AbsToRelativePath(self, parentPath): + """ Used to convert path to relative path for saving (disk format) """ + parentPathLen = len(parentPath) + + if self.filePath.startswith(parentPath): + self.filePath = "." + self.filePath[parentPathLen:] # convert to relative path + if os.sep != '/': + self.filePath = self.filePath.replace(os.sep, '/') # always save out with '/' as path separator for cross-platform compatibility. + else: + pass # not a decendant of project, use absolute path + + + def RelativeToAbsPath(self, parentPath): + """ Used to convert path to absolute path (for any necessary disk access) """ + if self.filePath.startswith("."): # relative to project file + self.filePath = os.path.normpath(os.path.join(parentPath, self.filePath)) + + + #---------------------------------------------------------------------------- + # BaseDocumentMgr methods + #---------------------------------------------------------------------------- + + def _GetDoc(self): + # HACK: temporary solution. + import wx + import wx.lib.docview + if not self._doc: + docMgr = wx.GetApp().GetDocumentManager() + + doc = docMgr.CreateDocument(self.filePath, docMgr.GetFlags()|wx.lib.docview.DOC_SILENT|wx.lib.docview.DOC_OPEN_ONCE|wx.lib.docview.DOC_NO_VIEW) + if (doc == None): # already open + docs = docMgr.GetDocuments() + for d in docs: + if d.GetFilename() == self.filePath: + doc = d + break + self._doc = doc + return self._doc + + + def _GetLocalServiceProcessName(self): + # HACK: temporary solution to getting process name from wsdlag file. + return self._GetDoc().GetModel().processName + + + processName = property(_GetLocalServiceProcessName) + + + def _GetStateful(self): + # HACK: temporary solution to getting stateful from wsdlag file. + return self._GetDoc().GetModel().stateful + + + def _SetStateful(self, stateful): + # HACK: temporary solution to setting stateful from wsdlag file. + self._GetDoc().GetModel().stateful = stateful + + + stateful = property(_GetStateful, _SetStateful) + + + def _GetLocalServiceCodeFile(self): + # HACK: temporary solution to getting class name from wsdlag file. + return self._GetDoc().GetModel().localServiceCodeFile + + + def _SetLocalServiceCodeFile(self, codefile): + # HACK: temporary solution to setting class name from wsdlag file. + self._GetDoc().GetModel().localServiceCodeFile = codefile + + + localServiceCodeFile = property(_GetLocalServiceCodeFile, _SetLocalServiceCodeFile) + + + def _GetLocalServiceClassName(self): + # HACK: temporary solution to getting class name from wsdlag file. + return self._GetDoc().GetModel().localServiceClassName + + + def _SetLocalServiceClassName(self, className): + # HACK: temporary solution to setting class name from wsdlag file. + self._GetDoc().GetModel().localServiceClassName = className + + + localServiceClassName = property(_GetLocalServiceClassName, _SetLocalServiceClassName) + + + +# only activate this code if we programatically need to access these values +## def _GetRssServiceBaseURL(self): +## return self._GetDoc().GetModel().rssServiceBaseURL +## +## +## def _SetRssServiceBaseURL(self, baseURL): +## self._GetDoc().GetModel().rssServiceBaseURL = baseURL +## +## +## rssServiceBaseURL = property(_GetRssServiceBaseURL, _SetRssServiceBaseURL) +## +## +## def _GetRssServiceRssVersion(self): +## return self._GetDoc().GetModel().rssServiceRssVersion +## +## +## def _SetRssServiceRssVersion(self, rssVersion): +## self._GetDoc().GetModel().rssServiceRssVersion = rssVersion +## +## +## rssServiceRssVersion = property(_GetRssServiceRssVersion, _SetRssServiceRssVersion) + + + def _GetServiceRefServiceType(self): + # HACK: temporary solution to getting service type from wsdlag file. + model = self._GetDoc().GetModel() + if hasattr(model, 'serviceType'): + return model.serviceType + else: + return None + + + def _SetServiceRefServiceType(self, serviceType): + # HACK: temporary solution to getting service type from wsdlag file. + self._GetDoc().GetModel().serviceType = serviceType + + + serviceType = property(_GetServiceRefServiceType, _SetServiceRefServiceType) + + + def getExternalPackage(self): + # HACK: temporary solution to getting custom code filename from wsdlag file. + import activegrid.server.deployment as deploymentlib + + appInfo = self._GetDoc().GetAppInfo() + + if appInfo.language == None: + language = deploymentlib.LANGUAGE_DEFAULT + else: + language = appInfo.language + + if language == deploymentlib.LANGUAGE_PYTHON: + suffix = ".py" + elif language == deploymentlib.LANGUAGE_PHP: + suffix = ".php" + pyFilename = self.name + suffix + return self._GetDoc().GetAppDocMgr().fullPath(pyFilename) + + +#---------------------------------------------------------------------------- +# Old Classes +#---------------------------------------------------------------------------- + +class Project_10: + """ Version 1.0, kept for upgrading to latest version. Over time, this should be deprecated. """ + __xmlname__ = "project" + __xmlrename__ = { "_files":"files"} + __xmlexclude__ = ('fileName',) + __xmlattributes__ = ["version"] + + + def __init__(self): + self.version = PROJECT_VERSION_050730 + self._files = [] + + + def initialize(self): + """ Required method for xmlmarshaller """ + pass + + + def upgradeVersion(self): + currModel = Project() + for file in self._files: + currModel._files.append(ProjectFile(file)) + return currModel + + diff --git a/wxPython/samples/ide/activegrid/util/__init__.py b/wxPython/samples/ide/activegrid/util/__init__.py index 943607976f..e69de29bb2 100644 --- a/wxPython/samples/ide/activegrid/util/__init__.py +++ b/wxPython/samples/ide/activegrid/util/__init__.py @@ -1,48 +0,0 @@ -#---------------------------------------------------------------------------- -# Name: __init__.py -# Purpose: Utilities -# -# Author: Joel Hare -# -# Created: 7/28/04 -# CVS-ID: $Id$ -# Copyright: (c) 2004-2005 ActiveGrid, Inc. -# License: wxWindows License -#---------------------------------------------------------------------------- - -import traceback -import sys -import os - -def isWindows(): - return os.name == 'nt' - -def _generateMainModuleDir(): - if sys.executable.find('python') != -1: - utilModuleDir = os.path.dirname(__file__) - if not os.path.isabs(utilModuleDir): - utilModuleDir = os.path.join(os.getcwd(), utilModuleDir) - mainModuleDir = os.path.normpath(os.path.join(utilModuleDir, os.path.join(os.path.pardir, os.path.pardir))) - if mainModuleDir.endswith('.zip'): - mainModuleDir = os.path.dirname(mainModuleDir) # Get rid of library.zip - else: - mainModuleDir = os.path.dirname(sys.executable) - return mainModuleDir - -mainModuleDir = _generateMainModuleDir() - - -def _generatePythonExecPath(): - if sys.executable.find('python') != -1: - pythonExecPath = sys.executable - else: - pythonExecPath = os.path.join(os.path.dirname(sys.executable), '3rdparty\python2.3\python') - return pythonExecPath - -pythonExecPath = _generatePythonExecPath() - -def getCommandNameForExecPath(execPath): - if isWindows(): - return '"%s"' % execPath - return execPath - diff --git a/wxPython/samples/ide/activegrid/util/aglogging.py b/wxPython/samples/ide/activegrid/util/aglogging.py index e4b5e7fd47..227e9726fa 100644 --- a/wxPython/samples/ide/activegrid/util/aglogging.py +++ b/wxPython/samples/ide/activegrid/util/aglogging.py @@ -15,7 +15,10 @@ import os import re import traceback import logging +import logging.config from activegrid.util.lang import * +import activegrid.util.objutils as objutils +import activegrid.util.sysutils as sysutils LEVEL_FATAL = logging.FATAL LEVEL_ERROR = logging.ERROR @@ -23,6 +26,90 @@ LEVEL_WARN = logging.WARN LEVEL_INFO = logging.INFO LEVEL_DEBUG = logging.DEBUG +EXCEPTION_INFO = 'exceptionInfo' + +LOG_MODE_IDE = 1 +LOG_MODE_TESTRUN = 2 +LOG_MODE_RUN = 3 +def initLogging(mode): + configFile = None + if (mode == LOG_MODE_IDE): + configFile = os.getenv("AG_LOGCONFIG_IDE") + elif (mode == LOG_MODE_TESTRUN): + configFile = os.getenv("AG_LOGCONFIG_TESTRUN") + else: + configFile = os.getenv("AG_LOGCONFIG_RUN") + if ((configFile == None) or not os.path.exists(configFile)): + if (mode == LOG_MODE_IDE): + configFile = "IDELog" + elif (mode == LOG_MODE_TESTRUN): + configFile = "TestRunLog" + else: + configFile = "RunLog" + configFile = sysutils.mainModuleDir + "/py" + configFile + ".ini" + if (os.path.exists(configFile)): + fileConfig(configFile) + else: + defaultStream = sys.stderr + if (mode == LOG_MODE_RUN): + defaultStream = sys.stdout + handler = logging.StreamHandler(defaultStream) + handler.setLevel(logging.INFO) + handler.setFormatter(logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s")) + logging.getLogger().addHandler(handler) + return configFile + +ag_debugLogger = logging.getLogger("activegrid.debug") + +def log(logger, level, msg, *params): + if (logger == None): + logger = ag_debugLogger + apply(logger.log, (level, msg) + params) + +def fatal(logger, msg, *params): + apply(logger.fatal, (msg,) + params) + +def error(logger, msg, *params): + apply(logger.error, (msg,) + params) + +def warn(logger, msg, *params): + apply(logger.warn, (msg,) + params) + +def info(logger, msg, *params): + apply(logger.info, (msg,) + params) + +def debug(logger, msg, *params): + if (logger == None): + logger = ag_debugLogger + apply(logger.debug, (msg,) + params) + +def setLevelFatal(logger): + logger.setLevel(LEVEL_FATAL) + +def setLevelError(logger): + logger.setLevel(LEVEL_ERROR) + +def setLevelWarn(logger): + logger.setLevel(LEVEL_WARN) + +def setLevelInfo(logger): + logger.setLevel(LEVEL_INFO) + +def setLevelDebug(logger): + logger.setLevel(LEVEL_DEBUG) + +def isEnabledForError(logger): + return logger.isEnabledFor(LEVEL_ERROR) + +def isEnabledForWarn(logger): + return logger.isEnabledFor(LEVEL_WARN) + +def isEnabledForInfo(logger): + return logger.isEnabledFor(LEVEL_INFO) + +def isEnabledForDebug(logger): + return logger.isEnabledFor(LEVEL_DEBUG) + TEST_MODE_NONE = 0 TEST_MODE_DETERMINISTIC = 1 TEST_MODE_NON_DETERMINISTIC = 2 @@ -38,8 +125,11 @@ def getTestMode(): global agTestMode return agTestMode -def testMode(normalObj, testObj=None): - if getTestMode() > TEST_MODE_NONE: +def testMode(normalObj, testObj=None, nonDeterministicObj=None): + testMode = getTestMode() + if testMode > TEST_MODE_NONE: + if ((nonDeterministicObj != None) and (testMode == TEST_MODE_NON_DETERMINISTIC)): + return nonDeterministicObj return testObj return normalObj @@ -68,18 +158,41 @@ def _fileNameReplacement(match): def _fileNameReplacementPHP(match): return "%s...%s" % (match.group(1), match.group(2).replace(os.sep, "/")) -def getTraceback(): - extype, val, tb = sys.exc_info() - tbs = "\n" - for s in traceback.format_tb(tb): - tbs += s +def formatTraceback(tb=None): + if (tb == None): + extype, val, tb = sys.exc_info() + tbs = "\n" + "".join(traceback.format_tb(tb)) return tbs +def formatExceptionCause(cause, stacktrace=False): + if (cause == None): + return "" + tbs = "" + if (stacktrace): + tbs = formatTraceback() + return "Caused by %s.%s: %s%s" % (cause.__module__, cause.__class__.__name__, str(cause), tbs) + +def addExceptionInfo(e, key, value): + if not hasattr(e, EXCEPTION_INFO): + try: + setattr(e, EXCEPTION_INFO, {}) + except: + return # Make sure we still report the real exception even if we can't add the extra info + if not e.exceptionInfo.has_key(key): # Never overwrite exception info since we assume earlier info is more specific + e.exceptionInfo[key] = value + def reportException(out=None, stacktrace=False, diffable=False, exception=None): - if (True): # exception == None): + exstr = exceptionToString(exception, stacktrace, diffable) + if (out == None): + print exstr + else: + print >> out, exstr + +def exceptionToString(exception=None, stacktrace=False, diffable=False): + if (exception == None): extype, val, t = sys.exc_info() else: - extype = type(exception) + extype = objutils.typeToString(exception) val = exception if (stacktrace): e,v,t = sys.exc_info() @@ -87,17 +200,169 @@ def reportException(out=None, stacktrace=False, diffable=False, exception=None): exstr = removeFileRefs(str(val)) else: exstr = str(val) - if (out == None): - print "Got Exception = %s: %s" % (extype, exstr) - else: - print >> out, "Got Exception = %s: %s" % (extype, exstr) + if hasattr(val, EXCEPTION_INFO): + firstTime = True + for infoKey, infoValue in getattr(val, EXCEPTION_INFO).items(): + if firstTime: + prefix = " EXTRA INFO:" + firstTime = False + else: + prefix = "," + exstr += ("%s %s=%s" % (prefix, infoKey, infoValue)) + result = "Got Exception = %s: %s" % (extype, exstr) if (stacktrace): fmt = traceback.format_exception(extype, val, t) for s in fmt: if (diffable): s = removeFileRefs(s) - if (out == None): - print s + result = result + "\n" + s + return result + +def fileConfig(fname, defaults=None): + """ + This is copied from logging.config so that we could fix the class lookup of + handlers. Previously handlers had to be defined in logging.handlers and we + need to be able to define our own. + """ + import ConfigParser, string + + cp = ConfigParser.ConfigParser(defaults) + if hasattr(cp, 'readfp') and hasattr(fname, 'readline'): + cp.readfp(fname) + else: + cp.read(fname) + #first, do the formatters... + flist = cp.get("formatters", "keys") + if len(flist): + flist = string.split(flist, ",") + formatters = {} + for form in flist: + sectname = "formatter_%s" % form + opts = cp.options(sectname) + if "format" in opts: + fs = cp.get(sectname, "format", 1) else: - print >> out, s - + fs = None + if "datefmt" in opts: + dfs = cp.get(sectname, "datefmt", 1) + else: + dfs = None + f = logging.Formatter(fs, dfs) + formatters[form] = f + #next, do the handlers... + #critical section... + logging._acquireLock() + try: +## try: + #first, lose the existing handlers... + logging._handlers.clear() + #now set up the new ones... + hlist = cp.get("handlers", "keys") + if len(hlist): + hlist = string.split(hlist, ",") + handlers = {} + fixups = [] #for inter-handler references + for hand in hlist: +## try: + sectname = "handler_%s" % hand + classname = cp.get(sectname, "class") + opts = cp.options(sectname) + if "formatter" in opts: + fmt = cp.get(sectname, "formatter") + else: + fmt = "" + klass = None + try: + klass = eval(classname, vars(logging)) + except: + pass + if (klass == None): + klass = objutils.classForName(classname) + args = cp.get(sectname, "args") + args = eval(args, vars(logging)) + h = apply(klass, args) + if "level" in opts: + level = cp.get(sectname, "level") + h.setLevel(logging._levelNames[level]) + if len(fmt): + h.setFormatter(formatters[fmt]) + #temporary hack for FileHandler and MemoryHandler. + if klass == logging.handlers.MemoryHandler: + if "target" in opts: + target = cp.get(sectname,"target") + else: + target = "" + if len(target): #the target handler may not be loaded yet, so keep for later... + fixups.append((h, target)) + handlers[hand] = h +## except Exception, e: #if an error occurs when instantiating a handler, too bad +## pass #this could happen e.g. because of lack of privileges + #now all handlers are loaded, fixup inter-handler references... + for fixup in fixups: + h = fixup[0] + t = fixup[1] + h.setTarget(handlers[t]) + #at last, the loggers...first the root... + llist = cp.get("loggers", "keys") + llist = string.split(llist, ",") + llist.remove("root") + sectname = "logger_root" + root = logging.root + log = root + opts = cp.options(sectname) + if "level" in opts: + level = cp.get(sectname, "level") + log.setLevel(logging._levelNames[level]) + for h in root.handlers[:]: + root.removeHandler(h) + hlist = cp.get(sectname, "handlers") + if len(hlist): + hlist = string.split(hlist, ",") + for hand in hlist: + log.addHandler(handlers[hand]) + #and now the others... + #we don't want to lose the existing loggers, + #since other threads may have pointers to them. + #existing is set to contain all existing loggers, + #and as we go through the new configuration we + #remove any which are configured. At the end, + #what's left in existing is the set of loggers + #which were in the previous configuration but + #which are not in the new configuration. + existing = root.manager.loggerDict.keys() + #now set up the new ones... + for log in llist: + sectname = "logger_%s" % log + qn = cp.get(sectname, "qualname") + opts = cp.options(sectname) + if "propagate" in opts: + propagate = cp.getint(sectname, "propagate") + else: + propagate = 1 + logger = logging.getLogger(qn) + if qn in existing: + existing.remove(qn) + if "level" in opts: + level = cp.get(sectname, "level") + logger.setLevel(logging._levelNames[level]) + for h in logger.handlers[:]: + logger.removeHandler(h) + logger.propagate = propagate + logger.disabled = 0 + hlist = cp.get(sectname, "handlers") + if len(hlist): + hlist = string.split(hlist, ",") + for hand in hlist: + logger.addHandler(handlers[hand]) + #Disable any old loggers. There's no point deleting + #them as other threads may continue to hold references + #and by disabling them, you stop them doing any logging. + for log in existing: + root.manager.loggerDict[log].disabled = 1 +## except: +## import traceback +## ei = sys.exc_info() +## traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr) +## del ei + finally: + logging._releaseLock() diff --git a/wxPython/samples/ide/activegrid/util/appdirs.py b/wxPython/samples/ide/activegrid/util/appdirs.py new file mode 100644 index 0000000000..7b73d5c4f4 --- /dev/null +++ b/wxPython/samples/ide/activegrid/util/appdirs.py @@ -0,0 +1,59 @@ +#---------------------------------------------------------------------------- +# Name: appdirs.py +# Purpose: Utilities for retrieving special application dirs +# +# Author: Kevin Ollivier +# +# Created: 8/27/05 +# CVS-ID: $Id$ +# Copyright: (c) 2004-2005 ActiveGrid, Inc. +# License: wxWindows License +#---------------------------------------------------------------------------- + +# NOTE: This was made a separate file because it depends upon the +# wx.StandardPaths module, and thus, on wxWidgets, unlike other +# utils modules. I wanted to ensure this module is never loaded +# from the web server, etc. + +import sys +import os +import string +import wx + +def isWindows(): + return os.name == 'nt' + +def _generateDocumentsDir(): + path = "" + if sys.platform == "win32": + from win32com.shell import shell, shellcon + path=shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0) + elif sys.platform == "darwin": + import macfs, MACFS + fsspec_disk, fsspec_desktop = macfs.FindFolder( MACFS.kOnSystemDisk, MACFS.kDocumentsFolderType, 0) + path = macfs.FSSpec((fsspec_disk, fsspec_desktop, '')).as_pathname() + + if path == "": + path = os.path.expanduser("~") + + return path + +documents_folder = _generateDocumentsDir() + +# NOTE: We don't set this at startup because wxStandardPaths needs a running +# application object. This makes sure the wxApp will always be created when +# we get the folder. +def getAppDataFolder(): + # wxStandardPaths requires a running app + if wx.GetApp() and wx.Platform != "__WXGTK__": + data_folder = wx.StandardPaths.Get().GetUserDataDir() + if not os.path.exists(data_folder): + os.mkdir(data_folder) + return data_folder + else: + # wxBug: on *nix, it wants to point to ~/.appname, but + # so does wxConfig... For now, redirect this to ~/.appbuilder + # when this is fixed, we'll migrate settings to the correct place + return os.path.join(os.path.expanduser("~"), ".appbuilder") + + return "" diff --git a/wxPython/samples/ide/activegrid/util/fileutils.py b/wxPython/samples/ide/activegrid/util/fileutils.py new file mode 100644 index 0000000000..2a75997aea --- /dev/null +++ b/wxPython/samples/ide/activegrid/util/fileutils.py @@ -0,0 +1,348 @@ +#---------------------------------------------------------------------------- +# Name: fileutils.py +# Purpose: Active grid miscellaneous utilities +# +# Author: Jeff Norton +# +# Created: 12/10/04 +# CVS-ID: $Id$ +# Copyright: (c) 2004-2005 ActiveGrid, Inc. +# License: wxWindows License +#---------------------------------------------------------------------------- + +import logging +import copy +import os +import shutil +import sys +import zipfile + +import activegrid.util.aglogging as aglogging +import activegrid.util.sysutils as sysutils +from activegrid.util.lang import * + +global fileutilsLogger +fileutilsLogger = logging.getLogger("activegrid.util.fileutils") +# FATAL : No logging +# ERROR : No logging +# WARN : No logging +# INFO : No logging +# DEBUG : debugging +aglogging.setLevelFatal(fileutilsLogger) +#logging.getLogger().addHandler(logging.StreamHandler(sys.stderr)) + + +def makeDirsForFile(filename): + d = os.path.dirname(filename) + if (not os.path.exists(d)): + os.makedirs(d) + +def createFile(filename, mode='w'): + f = None + if (not os.path.exists(filename)): + makeDirsForFile(filename) + f = file(filename, mode) + return f + +def compareFiles(file1, file2): +## result = filecmp.cmp(file1, file2) +## if result: +## return 0 +## return -1 + file1.seek(0) + file2.seek(0) + while True: + line1 = file1.readline() + line2 = file2.readline() + if (len(line1) == 0): + if (len(line2) == 0): + return 0 + else: + return -1 + elif (len(line2) == 0): + return -1 + elif (line1 != line2): + line1 = line1.replace(" ", "") + line2 = line2.replace(" ", "") + if (line1 != line2): + len1 = len(line1) + len2 = len(line2) + if ((abs(len1 - len2) == 1) and (len1 > 0) and (len2 > 0) + and (line1[-1] == "\n") and (line2[-1] == "\n")): + if (len1 > len2): + longer = line1 + shorter = line2 + else: + shorter = line1 + longer = line2 + if ((longer[-2] == "\r") and (longer[:-2] == shorter[:-1])): + continue + if ((longer[-2:] == shorter[-2:]) and (longer[-3] == "\r") and (longer[:-3] == shorter[:-2])): + continue + return -1 + +def expandVars(value): + """Syntax: ${myvar,default="default value"}""" + import activegrid.runtime as runtime + sx = value.find("${") + if (sx >= 0): + result = asString(value[:sx]) + endx = value.find("}") + if (endx > 1): + defaultValue = None + defsx = value.find(",default=\"") + if ((defsx > sx) and (defsx < endx)): + varname = value[sx+2:defsx] + if (value[endx-1] == '"'): + defaultValue = value[defsx+10:endx-1] + if (defaultValue == None): + varname = value[sx+2:endx] + if (varname == "AG_SYSTEM"): + varval = runtime.appInfo.getSystemDir() + elif (varname == "AG_SYSTEM_STATIC"): + varval = runtime.appInfo.getSystemStaticDir() + elif (varname == "AG_APP"): + varval = runtime.appInfo.getAppDir() + elif (varname == "AG_APP_STATIC"): + varval = runtime.appInfo.getAppStaticDir() + else: + varval = os.getenv(varname) + if ((varval == None) and (defaultValue != None)): + varval = defaultValue + if (varval == None): + result += value[sx:endx+1] + else: + result += varval + return result + expandVars(value[endx+1:]) + return value + +def toPHPpath(path, otherdir=None): + return convertSourcePath(path, "php", otherdir=otherdir) + +def toPythonpath(path, otherdir=None): + return convertSourcePath(path, "python", otherdir=otherdir) + +def toUnixPath(path): + if (path != None and os.sep != '/'): + path = path.replace(os.sep, '/') + return path + +def convertSourcePath(path, to, otherdir=None): + fromname = "python" + if (to == "python"): + fromname = "php" + pythonNode = os.sep + fromname + os.sep + ix = path.find(pythonNode) + if (ix < 0): + ix = path.find(fromname) - 1 + if ((ix < 0) or (len(path) <= ix+7) + or (path[ix] not in ("\\", "/")) or (path[ix+7] not in ("\\", "/"))): + raise Exception("Not in a %s source tree. Cannot create file name for %s." % (fromname, path)) + if (otherdir == None): + return path[:ix+1] + to + path[ix+7:] + else: + return otherdir + path[ix+7:] + if (otherdir == None): + return path.replace(pythonNode, os.sep + to + os.sep) + else: + return otherdir + path[ix+7:] + + +def visit(directory, files, extension): + testdirs = os.listdir(directory) + for thing in testdirs: + fullpath = os.path.join(directory, thing) + if (os.path.isdir(fullpath)): + visit(fullpath, files, extension) + elif thing.endswith(extension): + fullname = os.path.normpath(os.path.join(directory, thing)) + if not fullname in files: + files.append(fullname) + +def listFilesByExtensionInPath(path=[], extension='.lyt'): + #Collect input and output arguments into one bunch + retval = [] + for directory in path: + visit(directory, retval, extension) + return retval + +def getFileLastModificationTime(fileName): + return os.path.getmtime(fileName) + +def findFileLocation(location, fileName): + i = fileName.rfind(os.sep) + if i > 0: + fileName = fileName[:i] + while location[0:2] == '..' and location[2:3] == os.sep: + location = location[3:] + i = fileName.rfind(os.sep) + fileName = fileName[:i] + absPath = fileName + os.sep + location + return absPath + +def getAllExistingFiles(files, basepath=None, forceForwardSlashes=False): + """For each file in files, if it exists, adds its absolute path to the rtn list. If file is a dir, calls this function recursively on all child files in the dir. + If basepath is set, and if the file being processed is relative to basedir, adds that relative path to rtn list instead of the abs path. + Is this is Windows, and forceForwardSlashes is True, make sure returned paths only have forward slashes.""" + if isinstance(files, basestring): + files = [files] + rtn = [] + for file in files: + if os.path.exists(file): + if os.path.isfile(file): + if basepath and hasAncestorDir(file, basepath): + rtn.append(getRelativePath(file, basepath)) + else: + rtn.append(os.path.abspath(str(file))) + elif os.path.isdir(file): + dircontent = [os.path.join(file, f) for f in os.listdir(file)] + rtn.extend(getAllExistingFiles(dircontent, basepath)) + + if forceForwardSlashes and sysutils.isWindows(): + newRtn = [] + for f in rtn: + newRtn.append(f.replace("\\", "/")) + rtn = newRtn + + return rtn + +def hasAncestorDir(file, parent): + """Returns true if file has the dir 'parent' as some parent in its path.""" + return getRelativePath(file, parent) != None + +def getRelativePath(file, basedir): + """Returns relative path from 'basedir' to 'file', assuming 'file' lives beneath 'basedir'. If it doesn't, returns None.""" + file = os.path.abspath(file) + parent = os.path.abspath(basedir) + + if file == parent: + return None + + if file.startswith(parent): + return file[len(parent)+1:] + + return None + +def isEmptyDir(dir): + if not os.path.isdir(dir): + return False + return len(os.listdir(dir)) == 0 + +ifDefPy() +def zip(zipfilepath, basedir=None, files=None): + """Zip all files in files and save zip as zipfilepath. If files is None, zip all files in basedir. For all files to be zipped, if they are relative to basedir, include the relative path in the archive.""" + + if not files and not basedir: + raise AssertionError("Either 'basedir' or 'files' must be set") + + if not files: + aglogging.debug(fileutilsLogger,\ + "Looking for files to zip in %s" % basedir) + files = getAllExistingFiles(basedir) + else: + # removes files that don't exist and gets abs for each + files = getAllExistingFiles(files) + + if len(files) == 0: + aglogging.debug(fileutilsLogger, "No files to zip, nothing to do") + return + + z = zipfile.ZipFile(zipfilepath, mode="w", compression=zipfile.ZIP_DEFLATED) + + try: + for file in files: + arcname = None + if basedir: + arcname = getRelativePath(file, basedir) + if not arcname: + arcname = file + aglogging.debug(fileutilsLogger,\ + "%s: adding %s with arcname %s" %\ + (zipfilepath, file, arcname)) + z.write(file, arcname) + finally: + z.close() +endIfDef() + + +ifDefPy() +def unzip(zipfilepath, extractdir): + """Unzip zipfilepath into extractdir.""" + z = zipfile.ZipFile(zipfilepath, mode="r") + for info in z.infolist(): + filename = os.path.join(extractdir, info.filename) + try: + dir = os.path.dirname(filename) + aglogging.debug(fileutilsLogger, "Creating dir %s" % dir) + os.makedirs(dir) # do we have to worry about permissions? + except: + pass + if os.path.isdir(filename): + continue + aglogging.debug(fileutilsLogger,\ + ("Writing arcfile %s to %s" % (info.filename, filename))) + f = open(filename, "w") + f.write(z.read(info.filename)) + f.close() +endIfDef() + +ifDefPy() +def copyFile(src, dest): + """Copies file src to dest. Creates directories in 'dest' path if necessary.""" + destdir = os.path.dirname(dest) + if not os.path.exists(destdir): + os.makedirs(destdir) + shutil.copy(src, dest) +endIfDef() + +ifDefPy() +def copyDir(src, dest): + """Copies dir 'src' into dir 'dest'. Creates 'dest' if it does not exist.""" + shutil.copytree(src, dest) +endIfDef() + +ifDefPy() +def remove(file): + if not os.path.exists(file): + return + if os.path.isfile(file): + os.remove(file) + elif os.path.isdir(file): + shutil.rmtree(file) +endIfDef() + +ifDefPy() +import warnings +warnings.filterwarnings("ignore", message="tmpnam is a potential security risk to your program") +def getTmpFile(): + return os.tmpnam() +endIfDef() + +ifDefPy() +#@accepts str, dict, str, str, boolean +def replaceToken(infilepath, tokens={}, outfilepath=None, delim="@@",\ + useEnv=False): + """Replaces tokens of form 'delim''delim' in file at 'infilepath', using values in dict 'tokens'. If 'outfilepath' is set, writes output to 'outfilepath', if not set, overwrites original file. If 'useEnv' is True, adds os.environ to 'tokens'. This makes it possible to define an env var FOO=BLAH, and have @@FOO@@ be replaced with BLAH, without explicitly passing FOO=BLAH in 'tokens'. Note that entries in 'tokens' take precedence over entries in os.environ.""" + + if useEnv: + for key, val in os.environ.items(): + # passed in tokens take precedence + if not tokens.has_key(key): + tokens[key] = val + + f = open(infilepath, "r") + try: + content = f.read() + finally: + if f: f.close() + + for token, value in tokens.items(): + content = content.replace("%s%s%s" % (delim, token , delim), str(value)) + + if not outfilepath: outfilepath = infilepath + f = open(outfilepath, "w") + try: + f.write(content) + finally: + if f: f.close() +endIfDef() diff --git a/wxPython/samples/ide/activegrid/util/lang.py b/wxPython/samples/ide/activegrid/util/lang.py index 56777fa370..9519e174fa 100644 --- a/wxPython/samples/ide/activegrid/util/lang.py +++ b/wxPython/samples/ide/activegrid/util/lang.py @@ -65,3 +65,9 @@ def ifDefPy(comment=False): def endIfDef(): pass + +def ag_isPHP(): + return False + +def ag_isPython(): + return True diff --git a/wxPython/samples/ide/activegrid/util/objutils.py b/wxPython/samples/ide/activegrid/util/objutils.py index 9658aa2a2a..79cb02919e 100644 --- a/wxPython/samples/ide/activegrid/util/objutils.py +++ b/wxPython/samples/ide/activegrid/util/objutils.py @@ -14,36 +14,192 @@ import logging import traceback import sys import os +import __builtin__ +import types +import xml.sax.saxutils as saxutils from types import * +from activegrid.util.lang import * +FUNCTION_HAS_ATTR = '_hasAttr' +FUNCTION_GET_ATTR = '_getAttr' +FUNCTION_SET_ATTR = '_setAttr' +FUNCTION_DEL_ATTR = '_delAttr' + +def hasRawAttr(obj, name): + if obj == None: + return False + if name != FUNCTION_HAS_ATTR and hasattr(obj, FUNCTION_HAS_ATTR): + return obj._hasAttr(name) + return obj.__dict__.has_key(name) + +def getRawAttr(obj, name): + if name != FUNCTION_GET_ATTR and hasattr(obj, FUNCTION_GET_ATTR): + return obj._getAttr(name) + return obj.__dict__.get(name) + +def setRawAttr(obj, name, value): + if name != FUNCTION_SET_ATTR and hasattr(obj, FUNCTION_SET_ATTR): + obj._setAttr(name, value) + else: + obj.__dict__[name] = value + +def delRawAttr(obj, name): + if name != FUNCTION_DEL_ATTR and hasattr(obj, FUNCTION_DEL_ATTR): + obj._delAttr(name) + else: + del obj.__dict__[name] + +def getStaticAttr(obj, attr): + if (isinstance(obj, types.TypeType)): + classDesc = obj + else: + classDesc = obj.__class__ + if (hasattr(classDesc, attr)): + return getattr(classDesc, attr) + return None + +def setStaticAttr(obj, attr, value): + if (isinstance(obj, types.TypeType)): + classDesc = obj + else: + classDesc = obj.__class__ + setattr(classDesc, attr, value) + +def moduleForName(moduleName): + module = None + pathList = moduleName.split('.') + if (len(moduleName) > 0): + module = __import__(moduleName) + for name in pathList[1:]: + if (name in module.__dict__): + module = module.__dict__[name] + else: + module = None + break + return module + +def typeForName(typeName): + i = typeName.rfind('.') + if (i >= 0): + module = moduleForName(typeName[:i]) + if (module != None): + name = typeName[i+1:] + if (name in module.__dict__): + return module.__dict__[name] + elif __builtin__.__dict__.has_key(typeName): + return __builtin__.__dict__[typeName] + return None + +def functionForName(functionName): + ftype = typeForName(functionName) + if (isinstance(ftype, (types.FunctionType, types.MethodType, types.BuiltinFunctionType, types.BuiltinMethodType))): + return ftype + return None + def classForName(className): - pathList = className.split('.') - moduleName = '.'.join(pathList[:-1]) - code = __import__(moduleName) - for name in pathList[1:]: - code = code.__dict__[name] - return code + ctype = typeForName(className) + if (isinstance(ctype, (types.ClassType, types.TypeType))): + return ctype + return None -def hasPropertyValue(obj, attr): - hasProp = False - try: - prop = obj.__class__.__dict__[attr] - if (isinstance(prop, property)): - hasProp = hasattr(obj, attr) - if (hasProp): - # It's a property and it has a value but sometimes we don't want it. - # If there is a _hasattr method execute it and the - # result will tell us whether to include this value - try: - hasProp = obj._hasattr(attr) - except: - pass - except KeyError: - pass - return hasProp +def newInstance(className, objargs=None): + "dynamically create an object based on the className and return it." -def toDiffableString(value): - s = str(value) + if not isinstance(objargs, list): + objargs = [objargs] + + if className == "None": + return None + elif className == "bool": + if ((len(objargs) < 1) or (objargs[0].lower() == "false") or (not objargs[0])): + return False + return True + if className == "str" or className == "unicode": # don"t strip: blanks are significant + if len(objargs) > 0: + try: + return saxutils.unescape(objargs[0]).encode() + except: + return "?" + else: + return "" + + classtype = classForName(className) + if (classtype == None): + raise Exception("Could not find class %s" % className) + + if (len(objargs) > 0): + return classtype(*objargs) + else: + return classtype() + +def getClassProperty(classType, propertyName): + return getattr(classType, propertyName) + +def toDiffableRepr(value, exclude=None): + if (value == None): + return "None" +## elif (isinstance(value, ObjectType) and hasattr(value, "__dict__")): +## if (exclude == None): +## exclude = [] +## s = "%s(%s)" % (type(value), toDiffableString(value.__dict__, exclude)) + elif (not isinstance(value, (BooleanType, ClassType, ComplexType, DictType, DictionaryType, + FloatType, IntType, ListType, LongType, StringType, TupleType, + UnicodeType, BufferType, BuiltinFunctionType, BuiltinMethodType, + CodeType, FrameType, FunctionType, GeneratorType, InstanceType, + LambdaType, MethodType, ModuleType, SliceType, TracebackType, + TypeType, XRangeType))): + if (hasattr(value, "__str__")): + s = str(value) + elif (hasattr(value, "__dict__")): + s = "%s(%s)" % (type(value), toDiffableString(value.__dict__, exclude)) + else: + s = str(type(value)) + ix2 = s.find(" object at 0x") + if (ix2 > 0): + ix = s.rfind(".") + if (ix > 0): + s = "" %s[ix+1:ix2] + elif (isinstance(value, bool)): + if (value): + return "True" + else: + return "False" + elif (isinstance(value, (tuple, list))): + items = [] + for v in value: + if (isinstance(v, basestring)): + if (v.find("'") >= 0): + items.append('"%s"' % v) + else: + items.append("'%s'" % v) + else: + items.append(toDiffableString(v, exclude)) + s = "[" + ", ".join(items) + "]" + elif (isinstance(value, dict)): + if (exclude == None): + exclude = [] + items = [] + for key, val in value.iteritems(): + if (isinstance(val, UnicodeType)): + items.append("'%s': u'%s'" % (key, toDiffableString(val, exclude))) + elif (isinstance(val, basestring)): + items.append("'%s': '%s'" % (key, toDiffableString(val, exclude))) + else: + items.append("'%s': %s" % (key, toDiffableString(val, exclude))) + s = "{" + ", ".join(items) + "}" + else: + s = str(value) + return s + +def toDiffableString(value, exclude=None): + if (value == None): + return "None" + if ((exclude != None) and not isinstance(value, (basestring, int))): + for v in exclude: + if (v is value): + return "" + exclude.append(value) + s = toDiffableRepr(value) ds = "" i = s.find(" at 0x") start = 0 @@ -54,22 +210,43 @@ def toDiffableString(value): ds += s[start:i] start = j i = s.find(" at 0x", start) - return ds + s[start:] - + ds = ds + s[start:] + i = ds.find("\\src\\") + if (i < 0): + i = ds.find("/src/") + else: + ds = ds.replace("\\", "/") + if (i > 0): + i += 4 + if (ds[i:i+5] == "\\php\\"): + i += 4 + elif (ds[i:i+8] == "\\python\\"): + i += 7 + ds = "filepath: ..." + ds[i:] + return ds + def toString(value, options=0): if ((options & PRINT_OBJ_DIFFABLE) > 0): return toDiffableString(value) + elif (not isinstance(value, basestring)): + return str(value) return value -def toTypeString(obj): +def typeToString(obj, options=0): if (isinstance(obj, BooleanType)): return "bool" elif (isinstance(obj, UnicodeType)): + if ((options & PRINT_OBJ_DIFFABLE) > 0): + return "string" return "unicode" elif (isinstance(obj, basestring)): return "string" elif (isinstance(obj, IntType)): return "int" + elif (isinstance(obj, LongType)): + if ((options & PRINT_OBJ_DIFFABLE) > 0): + return "int" + return "long" elif (isinstance(obj, FloatType)): return "float" elif (type(obj) == ListType): @@ -79,18 +256,46 @@ def toTypeString(obj): elif (isinstance(obj, TupleType)): return "tuple" elif (isinstance(obj, InstanceType)): - return type(obj) +## ds = str(type(obj)) + ds = " " % (obj.__module__, obj.__class__.__name__) else: - return type(obj) + ds = str(type(obj)) + if (options == 0): + import activegrid.util.aglogging + options = activegrid.util.aglogging.testMode(0, PRINT_OBJ_DIFFABLE) + if ((options & PRINT_OBJ_DIFFABLE) > 0): + if (ds.startswith(" 0): + ix = name.find("__") + if ((ix > 1) and name.startswith("_")): + name = name[ix:] + return toDiffableString(name) + return name PRINT_OBJ_GETATTR = 1 PRINT_OBJ_HIDE_INTERNAL = 2 PRINT_OBJ_COMPACT = 4 PRINT_OBJ_NONONE = 8 PRINT_OBJ_DIFFABLE = 16 +PRINT_OBJ_HIDE_EXCLUDED = 32 PRINT_OBJ_INTERNAL = 512 -def printObject(out, object, name="", indent=0, flags=0, exclude=None, maxIndent=30): +def printObject(out, object, name=None, indent=0, flags=0, exclude=None, remove=None, maxIndent=30): + if (name == None): + name = "" +## elif (name.endswith("_") and not name.endswith("__")): +## name = name[:-1] + if ((remove != None) and (name in asDict(remove))): + return False if ((maxIndent != None) and (indent > maxIndent)): print >> out, " "*indent, "%s: %s" % (name, toString(str(object), flags)), if ((flags & PRINT_OBJ_INTERNAL) == 0): @@ -98,12 +303,11 @@ def printObject(out, object, name="", indent=0, flags=0, exclude=None, maxIndent return True finalNewLine = False printed = True -## if (exclude == None): -## exclude = [] - if ((flags & PRINT_OBJ_COMPACT) > 0): - if (exclude and object in exclude): + if ((flags & (PRINT_OBJ_COMPACT | PRINT_OBJ_HIDE_EXCLUDED)) > 0): + if ((exclude != None) and ((object in exclude) or (name in exclude))): return - indent = 0 + if ((flags & PRINT_OBJ_COMPACT) > 0): + indent = 0 if ((flags & PRINT_OBJ_INTERNAL) == 0): finalNewLine = True flags |= PRINT_OBJ_INTERNAL @@ -113,23 +317,23 @@ def printObject(out, object, name="", indent=0, flags=0, exclude=None, maxIndent else: finalNewLine = False printed = False - elif (name.startswith("_") and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0)): + elif (name.startswith("_") and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0) and not name.startswith("_v_")): finalNewLine = False printed = False elif (isinstance(object, (list, tuple))): if ((exclude != None) and object in exclude): - print >> out, " "*indent, name, " : ", toTypeString(object), " of length = ", len(object), " (already printed)", + print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = ", len(object), " (already printed)", elif ((exclude != None) and name in exclude): - print >> out, " "*indent, name, " : ", toTypeString(object), " of length = ", len(object), " (excluded)", + print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = ", len(object), " (excluded)", else: if ((exclude != None) and (len(object) > 0)): exclude.append(object) - print >> out, " "*indent, name, " : ", toTypeString(object), " of length = %d" % len(object), + print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = %d" % len(object), for i, o in enumerate(object): print >> out - printObject(out, o, name="[%d]" % i, indent=indent+2, flags=flags, exclude=exclude, maxIndent=maxIndent) + printObject(out, o, name="[%d]" % i, indent=indent+2, flags=flags, exclude=exclude, remove=remove, maxIndent=maxIndent) elif (isinstance(object, dict)): if ((exclude != None) and object in exclude): - print >> out, " "*indent, name, " : ", toTypeString(object), " (already printed)", + print >> out, " "*indent, name, " : ", typeToString(object, flags), " (already printed)", else: if ((exclude != None) and (len(object) > 0)): exclude.append(object) if (len(name) > 0): @@ -147,51 +351,62 @@ def printObject(out, object, name="", indent=0, flags=0, exclude=None, maxIndent n = key if (not (isinstance(n, basestring))): n = str(n) + else: + n = nameToString(n, flags) if ((not n.startswith("_") or ((flags & PRINT_OBJ_HIDE_INTERNAL) == 0))): - if printObject(out, object[key], name=n, indent=indent+2, flags=(flags | PRINT_OBJ_INTERNAL), exclude=exclude, maxIndent=maxIndent): + if printObject(out, object[key], name=n, indent=indent+2, flags=(flags | PRINT_OBJ_INTERNAL), exclude=exclude, remove=remove, maxIndent=maxIndent): if ((flags & PRINT_OBJ_COMPACT) == 0): print >> out else: print >> out, ",", print >> out, " "*indent, "}", elif (hasattr(object, "__dict__")): - if ((exclude != None) and object in exclude): - print >> out, " "*indent, name, " : ", toTypeString(object), " (already printed) = ", toDiffableString(object), + if (name.startswith("_")): ## and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0)): + print >> out, " "*indent, name, " : ", typeToString(object, flags), + elif ((exclude != None) and ((object in exclude) or (object.__dict__ in exclude))): + print >> out, " "*indent, name, " : ", typeToString(object, flags), " (already printed)", else: if (exclude != None): exclude.append(object) - if (name.startswith("_")): ## and ((flags & PRINT_OBJ_HIDE_INTERNAL) > 0)): - print >> out, " "*indent, name, " : ", toTypeString(object), - elif ((exclude != None) and object.__dict__ in exclude): - print >> out, " "*indent, name, " : ", toTypeString(object), " (already printed)", + print >> out, " "*indent, name, " : ", typeToString(object, flags), + if ((flags & PRINT_OBJ_GETATTR) == 0): + if ((flags & PRINT_OBJ_COMPACT) == 0): + print >> out + printObject(out, object.__dict__, indent=indent, flags=flags, exclude=exclude, remove=remove, maxIndent=maxIndent) else: - print >> out, " "*indent, name, " : ", toTypeString(object), - if ((flags & PRINT_OBJ_GETATTR) == 0): - if ((flags & PRINT_OBJ_COMPACT) == 0): + if ((flags & PRINT_OBJ_COMPACT) == 0): + print >> out +## indent += 2 + print >> out, " "*indent, "{", + keys = object.__dict__.keys() + keys.sort() + printed = True + for key in keys: + if ((exclude != None) and (key in exclude)): + continue + if (printed and ((flags & PRINT_OBJ_COMPACT) == 0)): print >> out - printObject(out, object.__dict__, indent=indent, flags=flags, exclude=exclude, maxIndent=maxIndent) - else: - keys = object.__dict__.keys() - keys.sort() - for n in keys: - if ((flags & PRINT_OBJ_COMPACT) == 0): - print >> out - printObject(out, getattr(object, n), name=n, indent=indent+2, flags=flags, exclude=exclude, maxIndent=maxIndent) + n = nameToString(key, flags) + printed = printObject(out, getattr(object, n), name=n, indent=indent+2, flags=flags, exclude=exclude, remove=remove, maxIndent=maxIndent) + if ((flags & PRINT_OBJ_COMPACT) == 0): + print >> out + print >> out, " "*indent, "}", elif (indent < 0): print >> out, object, elif isinstance(object, basestring): if ((exclude != None) and name in exclude): - print >> out, " "*indent, name, " : ", toTypeString(object), " of length = ", len(object), " (excluded)", + print >> out, " "*indent, name, " : ", typeToString(object, flags), " of length = ", len(object), " (excluded)", elif (len(object) > 100): - print >> out, " "*indent, name, ":", toTypeString(object), "[%d] = %s...%s" % (len(object), object[:50], object[-50:]), + object = toString(object, flags) + print >> out, " "*indent, name, ":", typeToString(object, flags), "[%d] = %s...%s" % (len(object), object[:50], object[-50:]), else: - print >> out, " "*indent, name, ":", toTypeString(object), "=", str(object), + print >> out, " "*indent, name, ":", typeToString(object, flags), "=", toString(object, flags), ## elif (isinstance(object, float)): ## val = str(object) ## if (len(val) > 17): ## val = val[:17] ## print >> out, " "*indent, name, ":", type(object), "=", val, else: - print >> out, " "*indent, name, ":", toTypeString(object), "=", str(object), + print >> out, " "*indent, name, ":", typeToString(object, flags), "=", toString(object, flags), if (finalNewLine): print >> out return printed diff --git a/wxPython/samples/ide/activegrid/util/strutils.py b/wxPython/samples/ide/activegrid/util/strutils.py new file mode 100644 index 0000000000..b79bd2a474 --- /dev/null +++ b/wxPython/samples/ide/activegrid/util/strutils.py @@ -0,0 +1,23 @@ +#---------------------------------------------------------------------------- +# Name: strutils.py +# Purpose: String Utilities +# +# Author: Morgan Hua +# +# Created: 11/3/05 +# CVS-ID: $Id$ +# Copyright: (c) 2005 ActiveGrid, Inc. +# License: wxWindows License +#---------------------------------------------------------------------------- + + +def caseInsensitiveCompare(s1, s2): + """ Method used by sort() to sort values in case insensitive order """ + s1L = s1.lower() + s2L = s2.lower() + if s1L == s2L: + return 0 + elif s1L < s2L: + return -1 + else: + return 1 diff --git a/wxPython/samples/ide/activegrid/util/sysutils.py b/wxPython/samples/ide/activegrid/util/sysutils.py new file mode 100644 index 0000000000..eb8bbf08f1 --- /dev/null +++ b/wxPython/samples/ide/activegrid/util/sysutils.py @@ -0,0 +1,87 @@ +#---------------------------------------------------------------------------- +# Name: sysutils.py +# Purpose: System Utilities +# +# Author: Joel Hare +# +# Created: 7/28/04 +# CVS-ID: $Id$ +# Copyright: (c) 2004-2005 ActiveGrid, Inc. +# License: wxWindows License +#---------------------------------------------------------------------------- + +import sys +import os + +# this will be set to true in IDE.py when we are running release builds. +isRelease = False + +# Commented out for now..... +# Required for Unicode support with python +# Put over here because of py2exe problems +# Python suggests modifying site.py +#if hasattr(sys,"setdefaultencoding"): +# sys.setdefaultencoding("UTF-8") + + +MAINMODULE_DIR = "AG_MAINMODULE_DIR" +IS_RELEASE = "AG_IS_RELEASE" + +def isRelease(): + return 'true' == (str(os.getenv(IS_RELEASE)).lower()) + +def setRelease(value): + if value: + os.environ[IS_RELEASE]= "TRUE" + else: + os.environ[IS_RELEASE]= "FALSE" + +def isWindows(): + return os.name == 'nt' + + +def _generateMainModuleDir(): + mainModuleDir = os.getenv(MAINMODULE_DIR) + if mainModuleDir: # if environment variable set, return it + return mainModuleDir + + # On Mac, the python executable sometimes has a capital "P" so we need to + # lower the string first + sysExecLower = sys.executable.lower() + if sysExecLower == "/" or sysExecLower.find('python') != -1 or sysExecLower.find('apache') != -1: + utilModuleDir = os.path.dirname(__file__) + if not os.path.isabs(utilModuleDir): + utilModuleDir = os.path.join(os.getcwd(), utilModuleDir) + mainModuleDir = os.path.normpath(os.path.join(utilModuleDir, os.path.join(os.path.pardir, os.path.pardir))) + if mainModuleDir.endswith('.zip'): + mainModuleDir = os.path.dirname(mainModuleDir) # Get rid of library.zip + else: + mainModuleDir = os.path.dirname(sys.executable) + + os.environ[MAINMODULE_DIR] = mainModuleDir # pythonBug: os.putenv doesn't work, set environment variable + + return mainModuleDir + +mainModuleDir = _generateMainModuleDir() + +def _generatePythonExecPath(): + # On Mac, the python executable sometimes has a capital "P" so we need to + # lower the string first + sysExecLower = sys.executable.lower() + if sysExecLower.find('python') != -1 or sysExecLower.find('apache') != -1: + pythonExecPath = sys.executable + else: + # this is where py2app puts the Python executable + if sys.platform == "darwin": + pythonExecPath = os.path.join(os.path.dirname(sys.executable), "../Frameworks/Python.Framework/Versions/2.4/Python/bin") + else: + pythonExecPath = os.path.join(os.path.dirname(sys.executable), '3rdparty\python2.4\python') + return pythonExecPath + +pythonExecPath = _generatePythonExecPath() + +def getCommandNameForExecPath(execPath): + if isWindows(): + return '"%s"' % execPath + return execPath + diff --git a/wxPython/samples/ide/activegrid/util/xmlmarshaller.py b/wxPython/samples/ide/activegrid/util/xmlmarshaller.py index 266418a1eb..6a74d2c486 100644 --- a/wxPython/samples/ide/activegrid/util/xmlmarshaller.py +++ b/wxPython/samples/ide/activegrid/util/xmlmarshaller.py @@ -2,21 +2,23 @@ # Name: xmlmarshaller.py # Purpose: # -# Author: John Spurling +# Authors: John Spurling, Joel Hare, Alan Mullendore # # Created: 7/28/04 # CVS-ID: $Id$ # Copyright: (c) 2004-2005 ActiveGrid, Inc. # License: wxWindows License #---------------------------------------------------------------------------- -import __builtin__ import sys from types import * +from activegrid.util.lang import * import logging +ifDefPy() import xml.sax import xml.sax.handler +endIfDef() import xml.sax.saxutils as saxutils -from activegrid.util.lang import * +import activegrid.util.objutils as objutils import activegrid.util.aglogging as aglogging MODULE_PATH = "__main__" @@ -96,6 +98,13 @@ within it. e.g. __xmlattrgroups__ = {"name": ["firstName", "lastName"], "address": ["addressLine1", "city", "state", "zip"]} +name: __xmlcdatacontent__ +type: string +description: value is the name of a string attribute that should be assigned CDATA content from the +source document and that should be marshalled as CDATA. + +__xmlcdatacontent__ = "messyContent" + """ global xmlMarshallerLogger @@ -104,8 +113,6 @@ xmlMarshallerLogger.setLevel(aglogging.LEVEL_WARN) # INFO : low-level info # DEBUG : debugging info -global knownGlobalTypes - ################################################################################ # # module exceptions @@ -139,6 +146,9 @@ class XMLAttributeIsNotStringType(Error): string.""" % (self.attrname, self.typename) class MarshallerException(Exception): + pass + +class UnmarshallerException(Exception): pass ################################################################################ @@ -150,6 +160,10 @@ class MarshallerException(Exception): XMLNS = "xmlns" XMLNS_PREFIX = XMLNS + ":" XMLNS_PREFIX_LENGTH = len(XMLNS_PREFIX) +DEFAULT_NAMESPACE_KEY = "__DEFAULTNS__" +TYPE_QNAME = "QName" +XMLSCHEMA_XSD_URL = "http://www.w3.org/2001/XMLSchema" +AG_URL = "http://www.activegrid.com/ag.xsd" BASETYPE_ELEMENT_NAME = "item" DICT_ITEM_NAME = "qqDictItem" @@ -183,69 +197,31 @@ def getComplexType(obj): return obj.__xsdcomplextype__ return None -def _objectfactory(objname, objargs=None, xsname=None): +def _objectfactory(objname, objargs=None, objclass=None): "dynamically create an object based on the objname and return it." - +## print "[objectfactory] objname [%s]" % (objname) if not isinstance(objargs, list): objargs = [objargs] - -## print "[objectfactory] xsname [%s]; objname [%s]" % (xsname, objname) - - # (a) deal with tagName:knownTypes mappings - if (xsname != None): - objclass = knownGlobalTypes.get(xsname) - if (objclass != None): - if (objargs != None): - return objclass(*objargs) - else: - return objclass() - - # (b) next with intrinisic types - if objname == "str" or objname == "unicode": # don"t strip: blanks are significant - if len(objargs) > 0: - return saxutils.unescape(objargs[0]).encode() - else: - return "" - elif objname == "bool": - return not objargs[0].lower() == "false" - elif objname in ("float", "int", "long"): -## objargs = [x.strip() for x in objargs] - return __builtin__.__dict__[objname](*objargs) - elif objname == "None": - return None - - # (c) objtype=path...module.class - # split the objname into the typename and module path, - # importing the module if need be. -## print "[objectfactory] creating an object of type %s and value %s, xsname=%s" % (objname, objargs, xsname) - objtype = objname.split(".")[-1] - pathlist = objname.split(".") - modulename = ".".join(pathlist[0:-1]) -## print "[objectfactory] object [%s] %s(%r)" % (objname, objtype, objargs) - - try: - if modulename: - module = __import__(modulename) - for name in pathlist[1:-1]: - module = module.__dict__[name] - elif __builtin__.__dict__.has_key(objname): - module = __builtin__ - else: - raise MarshallerException("Could not find class %s" % objname) - if objargs: - return module.__dict__[objtype](*objargs) + if (objclass != None): + if (len(objargs) > 0): + if (hasattr(objclass, "__xmlcdatacontent__")): + obj = objclass() + contentAttr = obj.__xmlcdatacontent__ + obj.__dict__[contentAttr] = str(objargs[0]) + return obj + return objclass(*objargs) else: - return module.__dict__[objtype]() - except KeyError: - raise MarshallerException("Could not find class %s" % objname) + return objclass() + return objutils.newInstance(objname, objargs) class Element: - - def __init__(self, name, attrs=None): + def __init__(self, name, attrs=None, xsname=None): self.name = name self.attrs = attrs self.content = "" self.children = [] + self.objclass = None + self.xsname = xsname def getobjtype(self): objtype = self.attrs.get("objtype") @@ -256,58 +232,177 @@ class Element: objtype = "str" return objtype - def __str__(self): - print " name = ", self.name, "; attrs = ", self.attrs, "number of children = ", len(self.children) - i = -1 - for child in self.children: - i = i + 1 - childClass = child.__class__.__name__ - print " Child ", i, " class: ",childClass - +class NsElement(object): + def __init__(self): + self.nsMap = {} + self.targetNS = None + self.defaultNS = None + self.prefix = None + + def isEmpty(self): + return ((self.nsMap == {}) and (self.targetNS == None) and (self.defaultNS == None)) + + def setKnownTypes(self, masterKnownTypes, masterKnownNamespaces, parentNSE): + # if we're a nested element, extend our parent element's mapping + if parentNSE != None: + self.knownTypes = parentNSE.knownTypes.copy() + # but if we have a different default namespace, replace the parent's default mappings + if parentNSE.defaultNS != self.defaultNS: + newKT = self.knownTypes.copy() + for tag in newKT: + if tag.find(':') < 0: + del self.knownTypes[tag] + newMap = parentNSE.nsMap.copy() + if self.nsMap != {}: + for k, v in self.nsMap.iteritems(): + newMap[k] = v + self.nsMap = newMap + else: + self.knownTypes = {} + reversedKNS = {} + # TODO: instead of starting with the knownNamespaces, start with the "xmlms" mappings + # for this element. Then we'd only process the namespaces and tags we need to. + # But for now, this works. + for long, short in masterKnownNamespaces.iteritems(): + reversedKNS[short] = long + mapLongs = self.nsMap.values() + for tag, mapClass in masterKnownTypes.iteritems(): + i = tag.rfind(':') + if i >= 0: # e.g. "wsdl:description" + knownTagShort = tag[:i] # "wsdl" + knownTagName = tag[i+1:] # "description" + knownTagLong = reversedKNS[knownTagShort] # e.g. "http://schemas.xmlsoap.org/wsdl" + if (knownTagLong in mapLongs): + for mShort, mLong in self.nsMap.iteritems(): + if mLong == knownTagLong: + actualShort = mShort # e.g. "ws" + actualTag = '%s:%s' % (actualShort, knownTagName) + self.knownTypes[actualTag] = mapClass + break + if self.defaultNS == knownTagLong: + self.knownTypes[knownTagName] = mapClass + else: # e.g. "ItemSearchRequest" + self.knownTypes[tag] = mapClass +## print 'mapping <%s> to class "%s"' % (tag, mapClass.__name__) + + def expandQName(self, eName, attrName, attrValue): + bigValue = attrValue + i = attrValue.rfind(':') + if (i < 0): + if self.defaultNS != None: + bigValue = '%s:%s' % (self.defaultNS, attrValue) + else: + attrNS = attrValue[:i] + attrNCName = attrValue[i+1:] + for shortNs, longNs in self.nsMap.iteritems(): + if shortNs == attrNS: + bigValue = '%s:%s' % (longNs, attrNCName) + break +## print '[expandQName] input attrName = "%s" and attrValue "%s"; output = "%s"' % (attrName, attrValue, bigValue) + return bigValue class XMLObjectFactory(xml.sax.ContentHandler): - def __init__(self): + def __init__(self, knownTypes=None, knownNamespaces=None): self.rootelement = None + if (knownTypes == None): + self.knownTypes = {} + else: + self.knownTypes = knownTypes + if (knownNamespaces == None): + self.knownNamespaces = {} + else: + self.knownNamespaces = knownNamespaces + self.skipper = False self.elementstack = [] + self.nsstack = [] + self.collectContent = None xml.sax.handler.ContentHandler.__init__(self) - def __str__(self): - print "-----XMLObjectFactory Dump-------------------------------" - if (self.rootelement == None): - print "rootelement is None" + def appendElementStack(self, newElement, newNS): + self.elementstack.append(newElement) + if (newNS.isEmpty()): + if (len(self.nsstack) > 0): + newNS = self.nsstack[-1] + else: + newNS.knownTypes = self.knownTypes.copy() else: - print "rootelement is an object" - i = -1 - print "length of elementstack is: ", len(self.elementstack) - for e in self.elementstack: - i = i + 1 - print "elementstack[", i, "]: " - str(e) - print "-----end XMLObjectFactory--------------------------------" + if (len(self.nsstack) > 0): + newNS.setKnownTypes(self.knownTypes, self.knownNamespaces, self.nsstack[-1]) + else: + newNS.setKnownTypes(self.knownTypes, self.knownNamespaces, None) + self.nsstack.append(newNS) + return newNS + + def popElementStack(self): + element = self.elementstack.pop() + nse = self.nsstack.pop() + return element, nse ## ContentHandler methods def startElement(self, name, attrs): -## print "startElement for name: ", name - if name.find(":") > -1: # Strip namespace prefixes for now until actually looking them up in xsd - name = name[name.find(":") + 1:] -## for attrname in attrs.getNames(): -## print "%s: %s" % (attrname, attrs.getValue(attrname)) - element = Element(name, attrs.copy()) - self.elementstack.append(element) -## print self.elementstack +## print '[startElement] <%s>' % (name) + if name == 'xs:annotation' or name == 'xsd:annotation': # should use namespace mapping here + self.skipper = True + self.appendElementStack(Element(name, attrs.copy()), NsElement()) + if self.skipper: + return + if self.collectContent != None: + strVal = '<%s' % (name) + for aKey, aVal in attrs.items(): + strVal += (' %s="%s"' % (aKey, aVal)) + strVal += '>' + self.collectContent.content += strVal + xsname = name + if name.find(':') > -1: # Strip namespace prefixes for now until actually looking them up in xsd + name = name[name.rfind(":") + 1:] + element = Element(name, attrs.copy(), xsname=xsname) + # if the element has namespace attributes, process them and add them to our stack + nse = NsElement() + for k in attrs.getNames(): + if k.startswith('xmlns'): + longNs = attrs[k] + eLongNs = longNs + '/' + if str(eLongNs) in asDict(self.knownNamespaces): + longNs = eLongNs + if k == 'xmlns': + nse.defaultNS = longNs + else: + shortNs = k[6:] + nse.nsMap[shortNs] = longNs + elif k == 'targetNamespace': + nse.targetNS = attrs.getValue(k) + nse = self.appendElementStack(element, nse) + element.objclass = nse.knownTypes.get(xsname) + if (hasattr(element.objclass, "__xmlcontent__")): + self.collectContent = element def characters(self, content): -## print "got content: %s (%s)" % (content, type(content)) +## print '[characters] "%s" (%s)' % (content, type(content)) if (content != None): - self.elementstack[-1].content += content + if self.collectContent != None: + self.collectContent.content += content + else: + self.elementstack[-1].content += content def endElement(self, name): -## print "[endElement] name of element we"re at the end of: %s" % name +## print "[endElement] " % name xsname = name if name.find(":") > -1: # Strip namespace prefixes for now until actually looking them up in xsd name = name[name.find(":") + 1:] + if self.skipper: + if xsname == "xs:annotation" or xsname == "xsd:annotation": # here too + self.skipper = False + self.popElementStack() + return + if self.collectContent != None: + if xsname != self.collectContent.xsname: + self.collectContent.content += ('' % (xsname)) + self.popElementStack() + return + else: + self.collectContent = None oldChildren = self.elementstack[-1].children - element = self.elementstack.pop() + element, nse = self.popElementStack() if ((len(self.elementstack) > 1) and (self.elementstack[-1].getobjtype() == "None")): parentElement = self.elementstack[-2] ## print "[endElement] %s: found parent with objtype==None: using its grandparent" % name @@ -323,8 +418,7 @@ class XMLObjectFactory(xml.sax.ContentHandler): strippedElementContent = element.content.strip() if (len(strippedElementContent) > 0): constructorarglist.append(element.content) -## print "[endElement] calling objectfactory" - obj = _objectfactory(objtype, constructorarglist, xsname) + obj = _objectfactory(objtype, constructorarglist, element.objclass) complexType = getComplexType(obj) if (obj != None): if (hasattr(obj, "__xmlname__") and getattr(obj, "__xmlname__") == "sequence"): @@ -338,13 +432,14 @@ class XMLObjectFactory(xml.sax.ContentHandler): ns = attrname[XMLNS_PREFIX_LENGTH:] else: ns = "" - if not hasattr(obj, "__xmlnamespaces__"): - obj.__xmlnamespaces__ = {ns:attr} - elif ns not in obj.__xmlnamespaces__: - if (hasattr(obj.__class__, "__xmlnamespaces__") - and (obj.__xmlnamespaces__ is obj.__class__.__xmlnamespaces__)): - obj.__xmlnamespaces__ = dict(obj.__xmlnamespaces__) - obj.__xmlnamespaces__[ns] = attr + if complexType != None: + if not hasattr(obj, "__xmlnamespaces__"): + obj.__xmlnamespaces__ = {ns:attr} + elif ns not in obj.__xmlnamespaces__: + if (hasattr(obj.__class__, "__xmlnamespaces__") + and (obj.__xmlnamespaces__ is obj.__class__.__xmlnamespaces__)): + obj.__xmlnamespaces__ = dict(obj.__xmlnamespaces__) + obj.__xmlnamespaces__[ns] = attr elif not attrname == "objtype": if attrname.find(":") > -1: # Strip namespace prefixes for now until actually looking them up in xsd attrname = attrname[attrname.find(":") + 1:] @@ -352,7 +447,10 @@ class XMLObjectFactory(xml.sax.ContentHandler): xsdElement = complexType.findElement(attrname) if (xsdElement != None): type = xsdElement.type +## print 'Unmarshalling element "%s", attribute "%s" with type "%s"' % (name, xsdElement.name, type) if (type != None): + if (type == TYPE_QNAME): + attr = nse.expandQName(name, attrname, attr) type = xsdToLangType(type) ### ToDO remove maxOccurs hack after bug 177 is fixed if attrname == "maxOccurs" and attr == "unbounded": @@ -361,15 +459,14 @@ class XMLObjectFactory(xml.sax.ContentHandler): try: setattrignorecase(obj, _toAttrName(obj, attrname), attr) except AttributeError: - raise MarshallerException("Error unmarshalling attribute \"%s\" of XML element \"%s\": object type not specified or known" % (attrname, name)) + errorString = 'Error unmarshalling XML document at line %i, column %i: The object type of attribute "%s" of XML element "%s": not specified or known' % (self._locator.getLineNumber(), self._locator.getColumnNumber(), attrname, name) + raise UnmarshallerException(errorString) ## obj.__dict__[_toAttrName(obj, attrname)] = attr # stuff any child attributes meant to be in a sequence via the __xmlflattensequence__ flattenDict = {} if hasattr(obj, "__xmlflattensequence__"): flatten = obj.__xmlflattensequence__ -## print "[endElement] %s: obj has __xmlflattensequence__" % name if (isinstance(flatten, dict)): -## print "[endElement] dict with flatten.items: ", flatten.items() for sequencename, xmlnametuple in flatten.items(): if (xmlnametuple == None): flattenDict[sequencename] = sequencename @@ -377,19 +474,17 @@ class XMLObjectFactory(xml.sax.ContentHandler): flattenDict[str(xmlnametuple)] = sequencename else: for xmlname in xmlnametuple: - ## print "[endElement]: adding flattenDict[%s] = %s" % (xmlname, sequencename) +## print "[endElement]: adding flattenDict[%s] = %s" % (xmlname, sequencename) flattenDict[xmlname] = sequencename else: - raise "Invalid type for __xmlflattensequence___ : it must be a dict" + raise Exception("Invalid type for __xmlflattensequence___ : it must be a dict") # reattach an object"s attributes to it for childname, child in element.children: ## print "[endElement] childname is: ", childname, "; child is: ", child if (childname in flattenDict): sequencename = _toAttrName(obj, flattenDict[childname]) -## print "[endElement] sequencename is: ", sequencename if (not hasattr(obj, sequencename)): -## print "[endElement] obj.__dict__ is: ", obj.__dict__ obj.__dict__[sequencename] = [] sequencevalue = getattr(obj, sequencename) if (sequencevalue == None): @@ -454,6 +549,7 @@ __typeMappingXsdToLang = { "boolean": "bool", "decimal": "float", # ToDO Does python have a better fixed point type? "int": "int", + "integer":"int", "long": "long", "float": "float", "bool": "bool", @@ -464,13 +560,25 @@ __typeMappingXsdToLang = { "datetime": "str", # see above (date) "time": "str", # see above (date) "double": "float", + "QName" : "str", + "blob" : "str", # ag:blob + "currency" : "str", # ag:currency } def xsdToLangType(xsdType): + if xsdType.startswith(XMLSCHEMA_XSD_URL): + xsdType = xsdType[len(XMLSCHEMA_XSD_URL)+1:] + elif xsdType.startswith(AG_URL): + xsdType = xsdType[len(AG_URL)+1:] langType = __typeMappingXsdToLang.get(xsdType) if (langType == None): raise Exception("Unknown xsd type %s" % xsdType) return langType + +def langToXsdType(langType): + if langType in asDict(__typeMappingXsdToLang): + return '%s:%s' % (XMLSCHEMA_XSD_URL, langType) + return langType def _getXmlValue(langValue): if (isinstance(langValue, bool)): @@ -480,19 +588,23 @@ def _getXmlValue(langValue): else: return str(langValue) -def unmarshal(xmlstr, knownTypes=None): - global knownGlobalTypes - if (knownTypes == None): - knownGlobalTypes = {} - else: - knownGlobalTypes = knownTypes - objectfactory = XMLObjectFactory() - xml.sax.parseString(xmlstr, objectfactory) +def unmarshal(xmlstr, knownTypes=None, knownNamespaces=None, xmlSource=None): + objectfactory = XMLObjectFactory(knownTypes, knownNamespaces) + try: + xml.sax.parseString(xmlstr, objectfactory) + except xml.sax.SAXParseException, errorData: + if xmlSource == None: + xmlSource = 'unknown' + errorString = 'SAXParseException ("%s") detected at line %d, column %d in XML document from source "%s" ' % (errorData.getMessage(), errorData.getLineNumber(), errorData.getColumnNumber(), xmlSource) + raise UnmarshallerException(errorString) return objectfactory.getRootObject() - -def marshal(obj, elementName=None, prettyPrint=False, indent=0, knownTypes=None, encoding=-1): - xmlstr = "".join(_marshal(obj, elementName, prettyPrint=prettyPrint, indent=indent, knownTypes=knownTypes)) +def marshal(obj, elementName=None, prettyPrint=False, marshalType=True, indent=0, knownTypes=None, knownNamespaces=None, encoding=-1): +## print '[marshal] entered with elementName = "%s"' % (elementName) + worker = XMLMarshalWorker(prettyPrint=prettyPrint, marshalType=marshalType, knownTypes=knownTypes, knownNamespaces=knownNamespaces) + if obj != None and hasattr(obj, '__xmldeepexclude__'): + worker.xmldeepexclude = obj.__xmldeepexclude__ + xmlstr = "".join(worker._marshal(obj, elementName, indent=indent)) if (isinstance(encoding, basestring)): return '\n%s' % (encoding, xmlstr.encode(encoding)) elif (encoding == None): @@ -500,271 +612,421 @@ def marshal(obj, elementName=None, prettyPrint=False, indent=0, knownTypes=None, else: return '\n%s' % (sys.getdefaultencoding(), xmlstr) -def _marshal(obj, elementName=None, nameSpacePrefix="", nameSpaces=None, prettyPrint=False, indent=0, knownTypes=None): - xmlMarshallerLogger.debug("--> _marshal: elementName=%s, type=%s, obj=%s" % (elementName, type(obj), str(obj))) - xmlString = None - if prettyPrint or indent: - prefix = " "*indent - newline = "\n" - increment = 4 - else: - prefix = "" - newline = "" - increment = 0 - - ## Determine the XML element name. If it isn"t specified in the - ## parameter list, look for it in the __xmlname__ Lang - ## attribute, else use the default generic BASETYPE_ELEMENT_NAME. - if not nameSpaces: nameSpaces = {} # Need to do this since if the {} is a default parameter it gets shared by all calls into the function - nameSpaceAttrs = "" - if knownTypes == None: - knownTypes = {} - if hasattr(obj, "__xmlnamespaces__"): - for nameSpaceKey, nameSpaceUrl in getattr(obj, "__xmlnamespaces__").items(): - if nameSpaceUrl in asDict(nameSpaces): - nameSpaceKey = nameSpaces[nameSpaceUrl] - else: -## # TODO: Wait to do this until there is shared for use when going through the object graph -## origNameSpaceKey = nameSpaceKey # Make sure there is no key collision, ie: same key referencing two different URL"s -## i = 1 -## while nameSpaceKey in nameSpaces.values(): -## nameSpaceKey = origNameSpaceKey + str(i) -## i += 1 - nameSpaces[nameSpaceUrl] = nameSpaceKey - if nameSpaceKey == "": - nameSpaceAttrs += ' xmlns="%s" ' % (nameSpaceUrl) - else: - nameSpaceAttrs += ' xmlns:%s="%s" ' % (nameSpaceKey, nameSpaceUrl) - nameSpaceAttrs = nameSpaceAttrs.rstrip() - if hasattr(obj, "__xmldefaultnamespace__"): - nameSpacePrefix = getattr(obj, "__xmldefaultnamespace__") + ":" - if not elementName: - if hasattr(obj, "__xmlname__"): - elementName = nameSpacePrefix + obj.__xmlname__ +class XMLMarshalWorker(object): + def __init__(self, marshalType=True, prettyPrint=False, knownTypes=None, knownNamespaces=None): + if knownTypes == None: + self.knownTypes = {} else: - elementName = nameSpacePrefix + BASETYPE_ELEMENT_NAME - else: - elementName = nameSpacePrefix + elementName - if hasattr(obj, "__xmlsequencer__"): - elementAdd = obj.__xmlsequencer__ - else: - elementAdd = None - -## print "marshal: entered with elementName: ", elementName - members_to_skip = [] - ## Add more members_to_skip based on ones the user has selected - ## via the __xmlexclude__ attribute. - if hasattr(obj, "__xmlexclude__"): -## print "marshal: found __xmlexclude__" - members_to_skip.extend(obj.__xmlexclude__) - # Marshal the attributes that are selected to be XML attributes. - objattrs = "" - className = ag_className(obj) - classNamePrefix = "_" + className - if hasattr(obj, "__xmlattributes__"): -## print "marshal: found __xmlattributes__" - xmlattributes = obj.__xmlattributes__ - members_to_skip.extend(xmlattributes) - for attr in xmlattributes: - internalAttrName = attr - ifDefPy() - if (attr.startswith("__") and not attr.endswith("__")): - internalAttrName = classNamePrefix + attr - endIfDef() - # Fail silently if a python attribute is specified to be - # an XML attribute but is missing. -## print "marshal: processing attribute ", internalAttrName - attrs = obj.__dict__ - value = attrs.get(internalAttrName) - xsdElement = None - complexType = getComplexType(obj) - if (complexType != None): -## print "marshal: found __xsdcomplextype__" - xsdElement = complexType.findElement(attr) - if (xsdElement != None): - default = xsdElement.default - if (default != None): - if ((default == value) or (default == _getXmlValue(value))): - continue + self.knownTypes = knownTypes + if knownNamespaces == None: + self.knownNamespaces = {} + else: + self.knownNamespaces = knownNamespaces + self.prettyPrint = prettyPrint + self.marshalType = marshalType + self.xmldeepexclude = [] + self.nsstack = [] + + def getNSPrefix(self): + if len(self.nsstack) > 0: + return self.nsstack[-1].prefix + return '' + + def isKnownType(self, elementName): + tagLongNs = None + nse = self.nsstack[-1] + i = elementName.rfind(':') + if i > 0: + prefix = elementName[:i] + name = elementName[i+1:] + else: + prefix = DEFAULT_NAMESPACE_KEY + name = elementName + for shortNs, longNs in nse.nameSpaces.iteritems(): + if shortNs == prefix: + tagLongNs = longNs + break + if tagLongNs == None: + knownTagName = elementName + else: + knownShortNs = self.knownNamespaces[tagLongNs] + knownTagName = knownShortNs + ':' + name + if (knownTagName in asDict(self.knownTypes)): + knownClass = self.knownTypes[knownTagName] + return True + return False + + def popNSStack(self): + self.nsstack.pop() + + def appendNSStack(self, obj): + nameSpaces = {} + defaultLongNS = None + for nse in self.nsstack: + for k, v in nse.nsMap.iteritems(): + nameSpaces[k] = v + if k == DEFAULT_NAMESPACE_KEY: + defaultLongNS = v + newNS = NsElement() + nameSpaceAttrs = "" + if hasattr(obj, "__xmlnamespaces__"): + ns = getattr(obj, "__xmlnamespaces__") + keys = ns.keys() + keys.sort() + for nameSpaceKey in keys: + nameSpaceUrl = ns[nameSpaceKey] + if nameSpaceUrl in nameSpaces.values(): + for k, v in nameSpaces.iteritems(): + if v == nameSpaceUrl: + nameSpaceKey = k + break else: - if (value == None): - continue - elif value == None: - continue - - # ToDO remove maxOccurs hack after bug 177 is fixed - if attr == "maxOccurs" and value == -1: - value = "unbounded" - - if isinstance(value, bool): - if value == True: - value = "true" - else: - value = "false" - - attrNameSpacePrefix = "" - if hasattr(obj, "__xmlattrnamespaces__"): -## print "marshal: found __xmlattrnamespaces__" - for nameSpaceKey, nameSpaceAttributes in getattr(obj, "__xmlattrnamespaces__").iteritems(): - if nameSpaceKey == nameSpacePrefix[:-1]: # Don't need to specify attribute namespace if it is the same as its element - continue - if attr in nameSpaceAttributes: - attrNameSpacePrefix = nameSpaceKey + ":" - break -## if attr.startswith("_"): -## attr = attr[1:] - if (hasattr(obj, "__xmlrename__") and attr in asDict(obj.__xmlrename__)): -## print "marshal: found __xmlrename__ (and its attribute)" - attr = obj.__xmlrename__[attr] - - objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, str(value)) -## print "marshal: new objattrs is: ", objattrs - - if (obj == None): - xmlString = [""] - elif isinstance(obj, bool): - xmlString = ['%s<%s objtype="bool">%s%s' % (prefix, elementName, obj, elementName, newline)] - elif isinstance(obj, int): - xmlString = ['%s<%s objtype="int">%s%s' % (prefix, elementName, str(obj), elementName, newline)] - elif isinstance(obj, long): - xmlString = ['%s<%s objtype="long">%s%s' % (prefix, elementName, str(obj), elementName, newline)] - elif isinstance(obj, float): - xmlString = ['%s<%s objtype="float">%s%s' % (prefix, elementName, str(obj), elementName, newline)] - elif isinstance(obj, unicode): # have to check before basestring - unicode is instance of base string - xmlString = ['%s<%s>%s%s' % (prefix, elementName, saxutils.escape(obj.encode()), elementName, newline)] - elif isinstance(obj, basestring): - xmlString = ['%s<%s>%s%s' % (prefix, elementName, saxutils.escape(obj), elementName, newline)] - elif isinstance(obj, list): - if len(obj) < 1: - xmlString = "" + if nameSpaceKey == "": + defaultLongNS = nameSpaceUrl + nameSpaces[DEFAULT_NAMESPACE_KEY] = nameSpaceUrl + newNS.nsMap[DEFAULT_NAMESPACE_KEY] = nameSpaceUrl + nameSpaceAttrs += ' xmlns="%s" ' % (nameSpaceUrl) + else: + nameSpaces[nameSpaceKey] = nameSpaceUrl + newNS.nsMap[nameSpaceKey] = nameSpaceUrl + nameSpaceAttrs += ' xmlns:%s="%s" ' % (nameSpaceKey, nameSpaceUrl) + nameSpaceAttrs = nameSpaceAttrs.rstrip() + if len(self.nsstack) > 0: + newNS.prefix = self.nsstack[-1].prefix else: - xmlString = ['%s<%s objtype="list">%s' % (prefix, elementName, newline)] - for item in obj: - xmlString.extend(_marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)) - xmlString.append("%s%s" % (prefix, elementName, newline)) - elif isinstance(obj, tuple): - if len(obj) < 1: - xmlString = "" + newNS.prefix = '' + if hasattr(obj, "__xmldefaultnamespace__"): + longPrefixNS = getattr(obj, "__xmldefaultnamespace__") + if longPrefixNS == defaultLongNS: + newNS.prefix = '' + else: + try: + for k, v in nameSpaces.iteritems(): + if v == longPrefixNS: + newNS.prefix = k + ':' + break; +## print '[appendNSStack] found longPrefixNS in nameSpaces = "%s"' % (newNS.prefix) + except: + if (longPrefixNS in asDict(self.knownNamespaces)): + newNS.prefix = self.knownNamespaces[longPrefixNS] + ':' + else: + raise MarshallerException('Error marshalling __xmldefaultnamespace__ ("%s") not defined in namespace stack' % (longPrefixNS)) + if hasattr(obj, "targetNamespace"): + newNS.targetNS = obj.targetNamespace + elif len(self.nsstack) > 0: + newNS.targetNS = self.nsstack[-1].targetNS + newNS.nameSpaces = nameSpaces + self.nsstack.append(newNS) + return nameSpaceAttrs + + def contractQName(self, value, obj, attr): + value = langToXsdType(value) + i = value.rfind(':') + if i >= 0: + longNS = value[:i] else: - xmlString = ['%s<%s objtype="list" mutable="false">%s' % (prefix, elementName, newline)] - for item in obj: - xmlString.extend(_marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)) - xmlString.append("%s%s" % (prefix, elementName, newline)) - elif isinstance(obj, dict): - xmlString = ['%s<%s objtype="dict">%s' % (prefix, elementName, newline)] - subprefix = prefix + " "*increment - subindent = indent + 2*increment - for key, val in obj.iteritems(): -## if (isinstance(key, basestring) and key is legal identifier): -## xmlString.extend(_marshal(val, elementName=key, nameSpaces=nameSpaces, indent=subindent, knownTypes=knownTypes)) -## else: - xmlString.append("%s<%s>%s" % (subprefix, DICT_ITEM_NAME, newline)) - xmlString.extend(_marshal(key, elementName=DICT_ITEM_KEY_NAME, indent=subindent, knownTypes=knownTypes)) - xmlString.extend(_marshal(val, elementName=DICT_ITEM_VALUE_NAME, nameSpaces=nameSpaces, indent=subindent, knownTypes=knownTypes)) - xmlString.append("%s%s" % (subprefix, DICT_ITEM_NAME, newline)) - xmlString.append("%s%s" % (prefix, elementName, newline)) - else: - # Only add the objtype if the element tag is unknown to us. - objname = knownTypes.get(elementName) - if (objname != None): - xmlString = ["%s<%s%s%s" % (prefix, elementName, nameSpaceAttrs, objattrs)] + # the value doesn't have a namespace and we couldn't map it to an XSD type...what to do? + # (a) just write it, as is, and hope it's in the default namespace (for now) + # (b) throw an exception so we can track down the bad code (later) + return value + if (longNS in self.nsstack[-1].nameSpaces.values()): + for kShort, vLong in self.nsstack[-1].nameSpaces.iteritems(): + if vLong == longNS: + shortNS = kShort + break + else: + shortNS = longNS # if we can't find the long->short mappping, just use longNS + if shortNS == DEFAULT_NAMESPACE_KEY: + value = value[i+1:] else: - xmlString = ['%s<%s%s%s objtype="%s.%s"' % (prefix, elementName, nameSpaceAttrs, objattrs, obj.__class__.__module__, className)] - # get the member, value pairs for the object, filtering out the types we don"t support - if (elementAdd != None): - prefix += increment*" " - indent += increment + value = shortNS + ':' + value[i+1:] + return value + + def _genObjTypeStr(self, typeString): + if self.marshalType: + return ' objtype="%s"' % typeString + return "" - xmlMemberString = [] - if hasattr(obj, "__xmlbody__"): - xmlbody = getattr(obj, obj.__xmlbody__) - if xmlbody != None: - xmlMemberString.append(xmlbody) + def _marshal(self, obj, elementName=None, nameSpacePrefix="", indent=0): + if (obj != None): + xmlMarshallerLogger.debug("--> _marshal: elementName=%s%s, type=%s, obj=%s, indent=%d" % (nameSpacePrefix, elementName, type(obj), str(obj), indent)) + else: + xmlMarshallerLogger.debug("--> _marshal: elementName=%s%s, obj is None, indent=%d" % (nameSpacePrefix, elementName, indent)) + excludeAttrs = [] + excludeAttrs.extend(self.xmldeepexclude) + if hasattr(obj, "__xmlexclude__"): + excludeAttrs.extend(obj.__xmlexclude__) + prettyPrint = self.prettyPrint + knownTypes = self.knownTypes + xmlString = None + if self.prettyPrint or indent: + prefix = " "*indent + newline = "\n" + increment = 2 else: - if hasattr(obj, "__xmlattrgroups__"): - attrGroups = obj.__xmlattrgroups__.copy() - if (not isinstance(attrGroups, dict)): - raise "__xmlattrgroups__ is not a dict, but must be" - for n in attrGroups.iterkeys(): - members_to_skip.extend(attrGroups[n]) + prefix = "" + newline = "" + increment = 0 + ## Determine the XML element name. If it isn"t specified in the + ## parameter list, look for it in the __xmlname__ Lang + ## attribute, else use the default generic BASETYPE_ELEMENT_NAME. + nameSpaceAttrs = self.appendNSStack(obj) + nameSpacePrefix = self.getNSPrefix() + if not elementName: + if hasattr(obj, "__xmlname__"): + elementName = nameSpacePrefix + obj.__xmlname__ else: - attrGroups = {} - # add the list of all attributes to attrGroups - eList = obj.__dict__.keys() - eList.sort() - attrGroups["__nogroup__"] = eList - - for eName, eList in attrGroups.iteritems(): - if (eName != "__nogroup__"): - prefix += increment*" " - indent += increment - xmlMemberString.append('%s<%s objtype="None">%s' % (prefix, eName, newline)) - for name in eList: - value = obj.__dict__[name] - if eName == "__nogroup__" and name in members_to_skip: continue - if name.startswith("__") and name.endswith("__"): continue - subElementNameSpacePrefix = nameSpacePrefix - if hasattr(obj, "__xmlattrnamespaces__"): - for nameSpaceKey, nameSpaceValues in getattr(obj, "__xmlattrnamespaces__").iteritems(): - if name in nameSpaceValues: - subElementNameSpacePrefix = nameSpaceKey + ":" - break - # handle sequences listed in __xmlflattensequence__ - # specially: instead of listing the contained items inside - # of a separate list, as God intended, list them inside - # the object containing the sequence. - if (hasattr(obj, "__xmlflattensequence__") and (value != None) and (name in asDict(obj.__xmlflattensequence__))): - xmlnametuple = obj.__xmlflattensequence__[name] - if (xmlnametuple == None): - xmlnametuple = [name] - elif (not isinstance(xmlnametuple, (tuple,list))): - xmlnametuple = [str(xmlnametuple)] - xmlname = None - if (len(xmlnametuple) == 1): - xmlname = xmlnametuple[0] -## ix = 0 - for seqitem in value: -## xmlname = xmlnametuple[ix] -## ix += 1 -## if (ix >= len(xmlnametuple)): -## ix = 0 - xmlMemberString.extend(_marshal(seqitem, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)) + elementName = nameSpacePrefix + BASETYPE_ELEMENT_NAME + else: + elementName = nameSpacePrefix + elementName +## print '[XMLMarshalWorker._marshal] elementName "%s"; nameSpaceAttrs is "%s"' % (elementName, nameSpaceAttrs) + + if (hasattr(obj, "__xmlsequencer__")) and (obj.__xmlsequencer__ != None): + if (XMLSCHEMA_XSD_URL in self.nsstack[-1].nameSpaces.values()): + for kShort, vLong in self.nsstack[-1].nameSpaces.iteritems(): + if vLong == XMLSCHEMA_XSD_URL: + xsdPrefix = kShort + ':' + break + else: + xsdPrefix = 'xs:' + elementAdd = xsdPrefix + obj.__xmlsequencer__ + else: + elementAdd = None + + ## print "marshal: entered with elementName: ", elementName + members_to_skip = [] + ## Add more members_to_skip based on ones the user has selected + ## via the __xmlexclude__ and __xmldeepexclude__ attributes. + members_to_skip.extend(excludeAttrs) + # Marshal the attributes that are selected to be XML attributes. + objattrs = "" + className = ag_className(obj) + classNamePrefix = "_" + className + if hasattr(obj, "__xmlattributes__"): + xmlattributes = obj.__xmlattributes__ + members_to_skip.extend(xmlattributes) + for attr in xmlattributes: +## print 'Processing element "%s"; attribute "%s"' % (elementName, attr) + internalAttrName = attr + ifDefPy() + if (attr.startswith("__") and not attr.endswith("__")): + internalAttrName = classNamePrefix + attr + endIfDef() + # Fail silently if a python attribute is specified to be + # an XML attribute but is missing. +## print "marshal: processing attribute ", internalAttrName + attrNameSpacePrefix = "" + if hasattr(obj, "__xmlattrnamespaces__"): + for nameSpaceKey, nameSpaceAttributes in getattr(obj, "__xmlattrnamespaces__").iteritems(): + if nameSpaceKey == nameSpacePrefix[:-1]: # Don't need to specify attribute namespace if it is the same as its element + continue + if attr in nameSpaceAttributes: + attrNameSpacePrefix = nameSpaceKey + ":" + break + attrs = obj.__dict__ + value = attrs.get(internalAttrName) + if (hasattr(obj, "__xmlrename__") and attr in asDict(obj.__xmlrename__)): + attr = obj.__xmlrename__[attr] + xsdElement = None + complexType = getComplexType(obj) + if (complexType != None): + xsdElement = complexType.findElement(attr) + if (xsdElement != None): + default = xsdElement.default + if (default != None): + if ((default == value) or (default == _getXmlValue(value))): + continue else: - if (hasattr(obj, "__xmlrename__") and name in asDict(obj.__xmlrename__)): - xmlname = obj.__xmlrename__[name] - else: - xmlname = name - xmlMemberString.extend(_marshal(value, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)) - if (eName != "__nogroup__"): - xmlMemberString.append("%s%s" % (prefix, eName, newline)) - prefix = prefix[:-increment] - indent -= increment - - # if we have nested elements, add them here, otherwise close the element tag immediately. - newList = [] - for s in xmlMemberString: - if (len(s) > 0): newList.append(s) - xmlMemberString = newList - if len(xmlMemberString) > 0: - xmlString.append(">") - if hasattr(obj, "__xmlbody__"): - xmlString.extend(xmlMemberString) - xmlString.append("%s" % (elementName, newline)) + if (value == None): + continue + elif xsdElement.type == TYPE_QNAME: + value = self.contractQName(value, obj, attr) + elif value == None: + continue + + # ToDO remove maxOccurs hack after bug 177 is fixed + if attr == "maxOccurs" and value == -1: + value = "unbounded" + + if isinstance(value, bool): + if value == True: + value = "true" + else: + value = "false" + else: + value = objutils.toDiffableRepr(value) + + objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, saxutils.escape(value)) + ## print "marshal: new objattrs is: ", objattrs + if (obj == None): + xmlString = [""] + elif isinstance(obj, bool): + objTypeStr = self._genObjTypeStr("bool") + xmlString = ['%s<%s%s>%s%s' % (prefix, elementName, objTypeStr, obj, elementName, newline)] + elif isinstance(obj, int): + objTypeStr = self._genObjTypeStr("int") + xmlString = ['%s<%s%s>%s%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] + elif isinstance(obj, long): + objTypeStr = self._genObjTypeStr("long") + xmlString = ['%s<%s%s>%s%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] + elif isinstance(obj, float): + objTypeStr = self._genObjTypeStr("float") + xmlString = ['%s<%s%s>%s%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] + elif isinstance(obj, unicode): # have to check before basestring - unicode is instance of base string + xmlString = ['%s<%s>%s%s' % (prefix, elementName, saxutils.escape(obj.encode()), elementName, newline)] + elif isinstance(obj, basestring): + xmlString = ['%s<%s>%s%s' % (prefix, elementName, saxutils.escape(obj), elementName, newline)] + elif isinstance(obj, list): + if len(obj) < 1: + xmlString = "" + else: + objTypeStr = self._genObjTypeStr("list") + xmlString = ['%s<%s%s>%s' % (prefix, elementName, objTypeStr, newline)] + for item in obj: + xmlString.extend(self._marshal(item, indent=indent+increment)) + xmlString.append("%s%s" % (prefix, elementName, newline)) + elif isinstance(obj, tuple): + if len(obj) < 1: + xmlString = "" else: - xmlString.append(newline) - if (elementAdd != None): - xmlString.append("%s<%s>%s" % (prefix, elementAdd, newline)) - xmlString.extend(xmlMemberString) - if (elementAdd != None): - xmlString.append("%s%s" % (prefix, elementAdd, newline)) - prefix = prefix[:-increment] - indent -= increment + objTypeStr = self._genObjTypeStr("list") + xmlString = ['%s<%s%s mutable="false">%s' % (prefix, elementName, objTypeStr, newline)] + for item in obj: + xmlString.extend(self._marshal(item, indent=indent+increment)) xmlString.append("%s%s" % (prefix, elementName, newline)) + elif isinstance(obj, dict): + objTypeStr = self._genObjTypeStr("dict") + xmlString = ['%s<%s%s>%s' % (prefix, elementName, objTypeStr, newline)] + subprefix = prefix + " "*increment + subindent = indent + 2*increment + keys = obj.keys() + keys.sort() + for key in keys: + xmlString.append("%s<%s>%s" % (subprefix, DICT_ITEM_NAME, newline)) + xmlString.extend(self._marshal(key, elementName=DICT_ITEM_KEY_NAME, indent=subindent)) + xmlString.extend(self._marshal(obj[key], elementName=DICT_ITEM_VALUE_NAME, indent=subindent)) + xmlString.append("%s%s" % (subprefix, DICT_ITEM_NAME, newline)) + xmlString.append("%s%s" % (prefix, elementName, newline)) + elif hasattr(obj, "__xmlcontent__"): + contentValue = getattr(obj, obj.__xmlcontent__) + if contentValue == None: + contentValue = '' + else: + contentValue = saxutils.escape(contentValue) + xmlString = ["%s<%s%s%s>%s%s" % (prefix, elementName, nameSpaceAttrs, objattrs, contentValue, elementName, newline)] else: - xmlString.append("/>%s" % newline) -## return xmlString - xmlMarshallerLogger.debug("<-- _marshal: %s" % str(xmlString)) - return xmlString + # Only add the objtype if the element tag is unknown to us. + if (self.isKnownType(elementName) == True): + objTypeStr = "" + else: + objTypeStr = self._genObjTypeStr("%s.%s" % (obj.__class__.__module__, className)) + xmlString = ['%s<%s%s%s%s' % (prefix, elementName, nameSpaceAttrs, objattrs, objTypeStr)] + # get the member, value pairs for the object, filtering out the types we don"t support + if (elementAdd != None): + prefix += increment*" " + indent += increment + xmlMemberString = [] + if hasattr(obj, "__xmlbody__"): + xmlbody = getattr(obj, obj.__xmlbody__) + if xmlbody != None: + xmlMemberString.append(xmlbody) + else: + if hasattr(obj, "__xmlattrgroups__"): + attrGroups = obj.__xmlattrgroups__.copy() + if (not isinstance(attrGroups, dict)): + raise "__xmlattrgroups__ is not a dict, but must be" + for n in attrGroups.iterkeys(): + members_to_skip.extend(attrGroups[n]) + else: + attrGroups = {} + # add the list of all attributes to attrGroups + eList = obj.__dict__.keys() + eList.sort() + attrGroups["__nogroup__"] = eList + + for eName, eList in attrGroups.iteritems(): + if (eName != "__nogroup__"): + prefix += increment*" " + indent += increment + objTypeStr = self._genObjTypeStr("None") + xmlMemberString.append('%s<%s%s>%s' % (prefix, eName, objTypeStr, newline)) + for name in eList: + value = obj.__dict__[name] + if eName == "__nogroup__" and name in members_to_skip: continue + if name.startswith("__") and name.endswith("__"): continue + if (hasattr(obj, "__xmlcdatacontent__") and (obj.__xmlcdatacontent__ == name)): + continue + subElementNameSpacePrefix = nameSpacePrefix + if hasattr(obj, "__xmlattrnamespaces__"): + for nameSpaceKey, nameSpaceValues in getattr(obj, "__xmlattrnamespaces__").iteritems(): + if name in nameSpaceValues: + subElementNameSpacePrefix = nameSpaceKey + ":" + break + # handle sequences listed in __xmlflattensequence__ + # specially: instead of listing the contained items inside + # of a separate list, as God intended, list them inside + # the object containing the sequence. + if (hasattr(obj, "__xmlflattensequence__") and (value != None) and (name in asDict(obj.__xmlflattensequence__))): + xmlnametuple = obj.__xmlflattensequence__[name] + if (xmlnametuple == None): + xmlnametuple = [name] + elif (not isinstance(xmlnametuple, (tuple,list))): + xmlnametuple = [str(xmlnametuple)] + xmlname = None + if (len(xmlnametuple) == 1): + xmlname = xmlnametuple[0] + ## ix = 0 + if not isinstance(value, (list, tuple)): + value = [value] + for seqitem in value: + ## xmlname = xmlnametuple[ix] + ## ix += 1 + ## if (ix >= len(xmlnametuple)): + ## ix = 0 + xmlMemberString.extend(self._marshal(seqitem, xmlname, subElementNameSpacePrefix, indent=indent+increment)) + else: + if (hasattr(obj, "__xmlrename__") and name in asDict(obj.__xmlrename__)): + xmlname = obj.__xmlrename__[name] + else: + xmlname = name + xmlMemberString.extend(self._marshal(value, xmlname, subElementNameSpacePrefix, indent=indent+increment)) + if (eName != "__nogroup__"): + xmlMemberString.append("%s%s" % (prefix, eName, newline)) + prefix = prefix[:-increment] + indent -= increment + + # if we have nested elements, add them here, otherwise close the element tag immediately. + newList = [] + for s in xmlMemberString: + if (len(s) > 0): newList.append(s) + xmlMemberString = newList + if len(xmlMemberString) > 0: + xmlString.append(">") + if hasattr(obj, "__xmlbody__"): + xmlString.extend(xmlMemberString) + xmlString.append("%s" % (elementName, newline)) + else: + xmlString.append(newline) + if (elementAdd != None): + xmlString.append("%s<%s>%s" % (prefix, elementAdd, newline)) + xmlString.extend(xmlMemberString) + if (elementAdd != None): + xmlString.append("%s%s" % (prefix, elementAdd, newline)) + prefix = prefix[:-increment] + indent -= increment + xmlString.append("%s%s" % (prefix, elementName, newline)) + else: + if hasattr(obj, "__xmlcdatacontent__"): + cdataAttr = obj.__xmlcdatacontent__ + cdataContent = obj.__dict__[cdataAttr] + xmlString.append(">%s" % (cdataContent, elementName, newline)) + else: + xmlString.append("/>%s" % newline) + ## return xmlString + xmlMarshallerLogger.debug("<-- _marshal: %s" % str(xmlString)) + #print "<-- _marshal: %s" % str(xmlString) + self.popNSStack() + return xmlString # A simple test, to be executed when the xmlmarshaller is run standalone class MarshallerPerson: diff --git a/wxPython/samples/ide/activegrid/util/xmlprettyprinter.py b/wxPython/samples/ide/activegrid/util/xmlprettyprinter.py index 97d74130cd..4290c71693 100644 --- a/wxPython/samples/ide/activegrid/util/xmlprettyprinter.py +++ b/wxPython/samples/ide/activegrid/util/xmlprettyprinter.py @@ -9,8 +9,10 @@ # Copyright: (c) 2004-2005 ActiveGrid, Inc. # License: wxWindows License #---------------------------------------------------------------------------- -import xml.sax from activegrid.util.lang import * +ifDefPy() +import xml.sax +endIfDef() class XMLPrettyPrinter(xml.sax.ContentHandler): def __init__(self, indentationChar=' ', newlineChar='\n'): diff --git a/wxPython/samples/ide/activegrid/util/xmlutils.py b/wxPython/samples/ide/activegrid/util/xmlutils.py index ac0ed7c6cf..02c0c8b2ca 100644 --- a/wxPython/samples/ide/activegrid/util/xmlutils.py +++ b/wxPython/samples/ide/activegrid/util/xmlutils.py @@ -10,80 +10,275 @@ # License: wxWindows License #---------------------------------------------------------------------------- +from activegrid.util.lang import * import os +import time +import urllib +import logging +from activegrid.util.lang import * import activegrid.util.objutils as objutils import activegrid.util.xmlmarshaller as xmlmarshaller +import activegrid.util.aglogging as aglogging -agKnownTypes = None +xmlLogger = logging.getLogger("activegrid.util.xml") + +def load(fileName, knownTypes=None, knownNamespaces=None): + loadedObject = None + fileObject = file(fileName) + timeStart = time.time() + try: + xml = fileObject.read() + loadedObject = unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=fileName) + loadedObject.fileName = os.path.abspath(fileName) + if hasattr(loadedObject, 'initialize'): + loadedObject.initialize() + finally: + fileObject.close() + timeDone = time.time() + aglogging.info(xmlLogger, ('Load statistics for file %s: elapsed time = %f secs' % (fileName, timeDone-timeStart))) + return loadedObject -def defaultLoad(fileObject, knownTypes=None): - xml = fileObject.read() - loadedObject = unmarshal(xml, knownTypes=knownTypes) - if hasattr(fileObject, 'name'): - loadedObject.fileName = os.path.abspath(fileObject.name) - loadedObject.initialize() +def loadURI(uri, knownTypes=None, knownNamespaces=None, xmlSource=None): + loadedObject = None + xml = urllib.urlopen(uri).read() + loadedObject = unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=xmlSource) + loadedObject.fileName = uri + if hasattr(loadedObject, 'initialize'): + loadedObject.initialize() return loadedObject -def unmarshal(xml, knownTypes=None): - if not knownTypes: knownTypes = getAgKnownTypes() - return xmlmarshaller.unmarshal(xml, knownTypes=knownTypes) +def unmarshal(xml, knownTypes=None, knownNamespaces=None, xmlSource=None): + if (knownTypes == None): + knownTypes, knownNamespaces = getAgKnownTypes() + return xmlmarshaller.unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces, xmlSource=xmlSource) -def defaultSave(fileObject, objectToSave, prettyPrint=True, knownTypes=None, encoding='utf-8'): - xml = marshal(objectToSave, prettyPrint=prettyPrint, knownTypes=knownTypes, encoding=encoding) - fileObject.write(xml) - fileObject.flush() +def save(fileName, objectToSave, prettyPrint=True, marshalType=True, knownTypes=None, knownNamespaces=None, encoding='utf-8'): + if hasattr(objectToSave, '_xmlReadOnly') and objectToSave._xmlReadOnly == True: + raise xmlmarshaller.MarshallerException('Error marshalling object to file "%s": object is marked "readOnly" and cannot be written' % (fileName)) + timeStart = time.time() + xml = marshal(objectToSave, prettyPrint=prettyPrint, marshalType=marshalType, knownTypes=knownTypes, knownNamespaces=knownNamespaces, encoding=encoding) + fileObject = file(fileName, 'w') + try: + fileObject.write(xml) + fileObject.flush() + except Exception, errorData: + fileObject.close() + raise xmlmarshaller.MarshallerException('Error marshalling object to file "%s": %s' % (fileName, str(errorData))) + fileObject.close() + timeDone = time.time() + aglogging.info(xmlLogger, ('Save statistics for file %s: elapsed time = %f secs' % (fileName, timeDone-timeStart))) + +def marshal(objectToSave, prettyPrint=True, marshalType=True, knownTypes=None, knownNamespaces=None, encoding='utf-8'): + if (knownTypes == None): + knownTypes, knownNamespaces = getAgKnownTypes() + return xmlmarshaller.marshal(objectToSave, prettyPrint=prettyPrint, marshalType=marshalType, knownTypes=knownTypes, knownNamespaces=knownNamespaces, encoding=encoding) + +def addNSAttribute(xmlDoc, shortNamespace, longNamespace): + if not hasattr(xmlDoc, "__xmlnamespaces__"): + xmlDoc.__xmlnamespaces__ = {shortNamespace:longNamespace} + elif shortNamespace not in xmlDoc.__xmlnamespaces__: + if (hasattr(xmlDoc.__class__, "__xmlnamespaces__") + and (xmlDoc.__xmlnamespaces__ is xmlDoc.__class__.__xmlnamespaces__)): + xmlDoc.__xmlnamespaces__ = dict(xmlDoc.__xmlnamespaces__) + xmlDoc.__xmlnamespaces__[shortNamespace] = longNamespace -def marshal(objectToSave, prettyPrint=True, knownTypes=None, encoding='utf-8'): - if not knownTypes: knownTypes = getAgKnownTypes() - return xmlmarshaller.marshal(objectToSave, prettyPrint=prettyPrint, knownTypes=knownTypes, encoding=encoding) +def genShortNS(xmlDoc, longNamespace=None): + if not hasattr(xmlDoc, "__xmlnamespaces__"): + return "ns1" + elif longNamespace != None and longNamespace in xmlDoc.__xmlnamespaces__.items(): + for key, value in xmlDoc.__xmlnamespaces__.iteritems(): + if value == longNamespace: + return key + i = 1 + while ("ns%d" % i) in xmlDoc.__xmlnamespaces__: + i += 1 + return ("ns%d" % i) -def cloneObject(objectToClone, knownTypes=None, encoding='utf-8'): - if not knownTypes: knownTypes = getAgKnownTypes() - xml = xmlmarshaller.marshal(objectToClone, prettyPrint=True, knownTypes=knownTypes, encoding=encoding) - clonedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes) +def genTargetNS(fileName, applicationName=None, type=None): + if (applicationName != None): + if (type != None): + tns = "urn:%s:%s:%s" % (applicationName, type, fileName) + else: + tns = "urn:%s:%s" % (applicationName, fileName) + else: + tns = "urn:%s" % fileName + return tns + +def splitType(typeName): + index = typeName.rfind(':') + if index != -1: + ns = typeName[:index] + complexTypeName = typeName[index+1:] + else: + ns = None + complexTypeName = typeName + return (ns, complexTypeName) + +def cloneObject(objectToClone, knownTypes=None, marshalType=True, knownNamespaces=None, encoding='utf-8'): + if (knownTypes == None): + knownTypes, knownNamespaces = getAgKnownTypes() + xml = xmlmarshaller.marshal(objectToClone, prettyPrint=True, marshalType=marshalType, knownTypes=knownTypes, knownNamespaces=knownNamespaces, encoding=encoding) + clonedObject = xmlmarshaller.unmarshal(xml, knownTypes=knownTypes, knownNamespaces=knownNamespaces) if hasattr(objectToClone, 'fileName'): clonedObject.fileName = objectToClone.fileName + if hasattr(objectToClone, "_parentDoc"): + clonedObject._parentDoc = objectToClone._parentDoc try: clonedObject.initialize() except AttributeError: pass return clonedObject -def getAgKnownTypes(): - import activegrid.model.processmodel - import activegrid.model.schema - import activegrid.data.dataservice - import activegrid.server.deployment - global agKnownTypes - if agKnownTypes == None: - tmpAgKnownTypes = {} - AG_TYPE_MAPPING = { +def getAgVersion(fileName): + fileObject = file(fileName) + try: + xml = fileObject.read() + finally: + fileObject.close() + i = xml.find(' ag:version=') + if i >= 0: + i += 12 + else: + i2 = xml.find('= 0: + i = xml.find(' version=', i2) + if i > 0: + i += 9 + elif xml.find('= 0: + return "10" + else: + return None + version = None + if xml[i:i+1] == '"': + j = xml.find('"', i+1) + if (j > i+1): + version = xml[i+1:j] + return version + +def escape(data): + """Escape ', ", &, <, and > in a string of data. + + Basically, everything that saxutils.escape does (and this calls that, at + least for now), but with " added as well. + + XXX TODO make this faster; saxutils.escape() is really slow + """ + + import xml.sax.saxutils as saxutils + + data=saxutils.escape(data) + data=data.replace("\"", """) + + # IE doesn't support ' + # data=data.replace("\'", "'") + data=data.replace("\'", "'") + + return data + +def unescape(data): + """Unescape ', ", &, <, and > in a string of data. + + Basically, everything that saxutils.unescape does (and this calls that, at + least for now), but with " added as well. + + XXX TODO make this faster; saxutils.unescape() is really slow + """ + + import xml.sax.saxutils as saxutils + + data=data.replace(""", "\"") + data=data.replace("'", "\'") + return saxutils.unescape(data) + + +AG_NS_URL = "http://www.activegrid.com/ag.xsd" +BPEL_NS_URL = "http://schemas.xmlsoap.org/ws/2003/03/business-process" +HTTP_WSDL_NS_URL = "http://schemas.xmlsoap.org/wsdl/http/" +MIME_WSDL_NS_URL = "http://schemas.xmlsoap.org/wsdl/mime/" +SOAP_NS_URL = "http://schemas.xmlsoap.org/wsdl/soap/" +SOAP12_NS_URL = "http://schemas.xmlsoap.org/wsdl/soap12/" +WSDL_NS_URL = "http://schemas.xmlsoap.org/wsdl/" +XFORMS_NS_URL = "http://www.w3c.org/xform.xsd" +XMLSCHEMA_NS_URL = "http://www.w3.org/2001/XMLSchema" +XSI_NS_URL = "http://www.w3.org/2001/XMLSchema-instance" +XACML_NS_URL = "urn:oasis:names:tc:xacml:2.0:policy:schema:os" + +KNOWN_NAMESPACES = { AG_NS_URL : "ag", + BPEL_NS_URL : "bpws", + HTTP_WSDL_NS_URL : "http", + MIME_WSDL_NS_URL : "mime", + SOAP_NS_URL : "soap", + SOAP12_NS_URL : "soap12", + WSDL_NS_URL : "wsdl", + XFORMS_NS_URL : "xforms", + XMLSCHEMA_NS_URL : "xs", + XACML_NS_URL : "xacml", + } + +global agXsdToClassName +agXsdToClassName = None +def getAgXsdToClassName(): + global agXsdToClassName + if (agXsdToClassName == None): + agXsdToClassName = { "ag:append" : "activegrid.model.processmodel.AppendOperation", + "ag:attribute" : "activegrid.model.identitymodel.Attribute", "ag:body" : "activegrid.model.processmodel.Body", + "ag:category_substitutions" : "activegrid.server.layoutrenderer.CategorySubstitutions", + "ag:command" : "activegrid.model.wsdl.Command", + "ag:css" : "activegrid.server.layoutrenderer.CSS", "ag:cssRule" : "activegrid.model.processmodel.CssRule", + "ag:databaseService" : "activegrid.server.deployment.DatabaseService", "ag:datasource" : "activegrid.data.dataservice.DataSource", + "ag:dataObjectList" : "activegrid.data.datalang.DataObjectList", "ag:debug" : "activegrid.model.processmodel.DebugOperation", "ag:deployment" : "activegrid.server.deployment.Deployment", - "ag:glue" : "activegrid.model.processmodel.Glue", + "ag:generator" : "activegrid.server.layoutrenderer.SerializableGenerator", + "ag:head" : "activegrid.server.layoutrenderer.Head", "ag:hr" : "activegrid.model.processmodel.HorizontalRow", + "ag:identity" : "activegrid.model.identitymodel.Identity", + "ag:identityref" : "activegrid.server.deployment.IdentityRef", "ag:image" : "activegrid.model.processmodel.Image", - "ag:inputs" : "activegrid.model.processmodel.Inputs", "ag:label" : "activegrid.model.processmodel.Label", - "ag:processmodel" : "activegrid.model.processmodel.ProcessModel", - "ag:processmodelref" : "activegrid.server.deployment.ProcessModelRef", + "ag:layout" : "activegrid.server.layoutrenderer.Layout", + "ag:layouts" : "activegrid.server.layoutrenderer.Layouts", + "ag:ldapsource" : "activegrid.model.identitymodel.LDAPSource", + "ag:localService" : "activegrid.server.deployment.LocalService", + "ag:parameter" : "activegrid.server.layoutrenderer.Parameter", + "ag:parameters" : "activegrid.server.layoutrenderer.Parameters", + "ag:processref" : "activegrid.server.deployment.ProcessRef", "ag:query" : "activegrid.model.processmodel.Query", - "ag:restParameter" : "activegrid.server.deployment.RestParameter", + "ag:soapService" : "activegrid.server.deployment.SoapService", + "ag:requiredFile" : "activegrid.server.layoutrenderer.RequiredFile", + "ag:resource" : "activegrid.model.identitymodel.IDResource", "ag:restService" : "activegrid.server.deployment.RestService", + "ag:rewrite" : "activegrid.model.wsdl.Rewrite", + "ag:role" : "activegrid.model.identitymodel.IDRole", + "ag:roledefn" : "activegrid.model.identitymodel.RoleDefn", + "ag:rssService" : "activegrid.server.deployment.RssService", + "ag:rule" : "activegrid.model.identitymodel.IDRule", "ag:schemaOptions" : "activegrid.model.schema.SchemaOptions", "ag:schemaref" : "activegrid.server.deployment.SchemaRef", + "ag:serviceCache" : "activegrid.server.deployment.ServiceCache", + "ag:serviceExtension": "activegrid.model.wsdl.ServiceExtension", + "ag:serviceExtensions": "activegrid.model.wsdl.ServiceExtensions", + "ag:serviceParameter": "activegrid.server.deployment.ServiceParameter", "ag:serviceref" : "activegrid.server.deployment.ServiceRef", "ag:set" : "activegrid.model.processmodel.SetOperation", + "ag:skinref" : "activegrid.server.deployment.SkinRef", + "ag:skin" : "activegrid.server.layoutrenderer.Skin", + "ag:skin_element_ref": "activegrid.server.layoutrenderer.SkinElementRef", + "ag:skin_element" : "activegrid.server.layoutrenderer.SkinElement", + "ag:skins" : "activegrid.server.layoutrenderer.Skins", + "ag:substitution" : "activegrid.server.layoutrenderer.Substitution", "ag:text" : "activegrid.model.processmodel.Text", "ag:title" : "activegrid.model.processmodel.Title", - "ag:view" : "activegrid.model.processmodel.View", + "ag:usertemplate" : "activegrid.model.identitymodel.UserTemplate", + "ag:xformref" : "activegrid.server.deployment.XFormRef", "bpws:case" : "activegrid.model.processmodel.BPELCase", "bpws:catch" : "activegrid.model.processmodel.BPELCatch", "bpws:faultHandlers" : "activegrid.model.processmodel.BPELFaultHandlers", + "bpws:flow" : "activegrid.model.processmodel.BPELFlow", "bpws:invoke" : "activegrid.model.processmodel.BPELInvoke", "bpws:onMessage" : "activegrid.model.processmodel.BPELOnMessage", "bpws:otherwise" : "activegrid.model.processmodel.BPELOtherwise", @@ -98,31 +293,117 @@ def getAgKnownTypes(): "bpws:variable" : "activegrid.model.processmodel.BPELVariable", "bpws:variables" : "activegrid.model.processmodel.BPELVariables", "bpws:while" : "activegrid.model.processmodel.BPELWhile", - "wsdl:message" : "activegrid.model.processmodel.WSDLMessage", - "wsdl:part" : "activegrid.model.processmodel.WSDLPart", + "http:address" : "activegrid.model.wsdl.HttpAddress", + "http:binding" : "activegrid.model.wsdl.HttpBinding", + "http:operation" : "activegrid.model.wsdl.HttpOperation", + "http:urlEncoded" : "activegrid.model.wsdl.HttpUrlEncoded", + "mime:content" : "activegrid.model.wsdl.MimeContent", + "mime:mimeXml" : "activegrid.model.wsdl.MimeMimeXml", + "soap:address" : "activegrid.model.wsdl.SoapAddress", + "soap:binding" : "activegrid.model.wsdl.SoapBinding", + "soap:body" : "activegrid.model.wsdl.SoapBody", + "soap:fault" : "activegrid.model.wsdl.SoapFault", + "soap:header" : "activegrid.model.wsdl.SoapHeader", + "soap:operation" : "activegrid.model.wsdl.SoapOperation", + "soap12:address" : "activegrid.model.wsdl.Soap12Address", + "soap12:binding" : "activegrid.model.wsdl.Soap12Binding", + "soap12:body" : "activegrid.model.wsdl.Soap12Body", + "soap12:fault" : "activegrid.model.wsdl.Soap12Fault", + "soap12:header" : "activegrid.model.wsdl.Soap12Header", + "soap12:operation" : "activegrid.model.wsdl.Soap12Operation", + "wsdl:binding" : "activegrid.model.wsdl.WsdlBinding", + "wsdl:definitions" : "activegrid.model.wsdl.WsdlDocument", + "wsdl:documentation" : "activegrid.model.wsdl.WsdlDocumentation", + "wsdl:fault" : "activegrid.model.wsdl.WsdlFault", + "wsdl:import" : "activegrid.model.wsdl.WsdlImport", + "wsdl:input" : "activegrid.model.wsdl.WsdlInput", + "wsdl:message" : "activegrid.model.wsdl.WsdlMessage", + "wsdl:operation" : "activegrid.model.wsdl.WsdlOperation", + "wsdl:output" : "activegrid.model.wsdl.WsdlOutput", + "wsdl:part" : "activegrid.model.wsdl.WsdlPart", + "wsdl:port" : "activegrid.model.wsdl.WsdlPort", + "wsdl:portType" : "activegrid.model.wsdl.WsdlPortType", + "wsdl:service" : "activegrid.model.wsdl.WsdlService", + "wsdl:types" : "activegrid.model.wsdl.WsdlTypes", + "xacml:Action" : "activegrid.model.identitymodel.XACMLAction", + "xacml:ActionAttributeDesignator" : "activegrid.model.identitymodel.XACMLActionAttributeDesignator", + "xacml:ActionMatch" : "activegrid.model.identitymodel.XACMLActionMatch", + "xacml:Actions" : "activegrid.model.identitymodel.XACMLActions", + "xacml:AttributeValue" : "activegrid.model.identitymodel.XACMLAttributeValue", + "xacml:Policy" : "activegrid.model.identitymodel.XACMLPolicy", + "xacml:Resource" : "activegrid.model.identitymodel.XACMLResource", + "xacml:ResourceAttributeDesignator" : "activegrid.model.identitymodel.XACMLResourceAttributeDesignator", + "xacml:ResourceMatch" : "activegrid.model.identitymodel.XACMLResourceMatch", + "xacml:Resources" : "activegrid.model.identitymodel.XACMLResources", + "xacml:Rule" : "activegrid.model.identitymodel.XACMLRule", + "xacml:Target" : "activegrid.model.identitymodel.XACMLTarget", + "xforms:copy" : "activegrid.model.processmodel.XFormsCopy", "xforms:group" : "activegrid.model.processmodel.XFormsGroup", + "xforms:include" : "activegrid.model.processmodel.XFormsInclude", "xforms:input" : "activegrid.model.processmodel.XFormsInput", + "xforms:item" : "activegrid.model.processmodel.XFormsItem", + "xforms:itemset" : "activegrid.model.processmodel.XFormsItemset", "xforms:label" : "activegrid.model.processmodel.XFormsLabel", + "xforms:model" : "activegrid.model.processmodel.XFormsModel", "xforms:output" : "activegrid.model.processmodel.XFormsOutput", "xforms:secret" : "activegrid.model.processmodel.XFormsSecret", + "xforms:select1" : "activegrid.model.processmodel.XFormsSelect1", + "xforms:submission" : "activegrid.model.processmodel.XFormsSubmission", "xforms:submit" : "activegrid.model.processmodel.XFormsSubmit", + "xforms:value" : "activegrid.model.processmodel.XFormsValue", + "xforms:xform" : "activegrid.model.processmodel.View", + "xforms:xforms" : "activegrid.model.processmodel.XFormsRoot", "xs:all" : "activegrid.model.schema.XsdSequence", + "xs:any" : "activegrid.model.schema.XsdAny", + "xs:attribute" : "activegrid.model.schema.XsdAttribute", + "xs:complexContent" : "activegrid.model.schema.XsdComplexContent", "xs:complexType" : "activegrid.model.schema.XsdComplexType", "xs:element" : "activegrid.model.schema.XsdElement", + "xs:enumeration" : "activegrid.model.schema.XsdEnumeration", + "xs:extension" : "activegrid.model.schema.XsdExtension", "xs:field" : "activegrid.model.schema.XsdKeyField", + "xs:import" : "activegrid.model.schema.XsdInclude", + "xs:include" : "activegrid.model.schema.XsdInclude", "xs:key" : "activegrid.model.schema.XsdKey", "xs:keyref" : "activegrid.model.schema.XsdKeyRef", + "xs:length" : "activegrid.model.schema.XsdLength", + "xs:list" : "activegrid.model.schema.XsdList", + "xs:maxLength" : "activegrid.model.schema.XsdMaxLength", + "xs:restriction" : "activegrid.model.schema.XsdRestriction", "xs:schema" : "activegrid.model.schema.Schema", "xs:selector" : "activegrid.model.schema.XsdKeySelector", "xs:sequence" : "activegrid.model.schema.XsdSequence", - } - - for keyName, className in AG_TYPE_MAPPING.iteritems(): - try: - tmpAgKnownTypes[keyName] = objutils.classForName(className) - except KeyError: - print "Error mapping knownType", className - pass - if len(tmpAgKnownTypes) > 0: - agKnownTypes = tmpAgKnownTypes - return agKnownTypes + "xs:simpleContent" : "activegrid.model.schema.XsdSimpleContent", + "xs:simpleType" : "activegrid.model.schema.XsdSimpleType", + "xs:totalDigits" : "activegrid.model.schema.XsdTotalDigits", + } + return agXsdToClassName + +global agKnownTypes +agKnownTypes = None +def getAgKnownTypes(): + global agKnownTypes + if agKnownTypes == None: + try: + tmpAgKnownTypes = {} + import activegrid.model.processmodel + import activegrid.model.schema + import activegrid.server.deployment + import activegrid.model.wsdl + ifDefPy() + import activegrid.data.dataservice + endIfDef() + for keyName, className in getAgXsdToClassName().iteritems(): + classType = objutils.classForName(className) + if (classType == None): + raise Exception("Cannot get class type for %s" % className) + else: + tmpAgKnownTypes[keyName] = classType + if len(tmpAgKnownTypes) > 0: + agKnownTypes = tmpAgKnownTypes + except ImportError: + agKnownTypes = {} + if len(agKnownTypes) == 0: # standalone IDE and XmlMarshaller don't contain known AG types + noKnownNamespaces = {} + return agKnownTypes, noKnownNamespaces + return agKnownTypes, KNOWN_NAMESPACES diff --git a/wxPython/samples/pydocview/PyDocViewDemo.py b/wxPython/samples/pydocview/PyDocViewDemo.py index aa0d2f02b6..a2a6d56684 100644 --- a/wxPython/samples/pydocview/PyDocViewDemo.py +++ b/wxPython/samples/pydocview/PyDocViewDemo.py @@ -12,12 +12,12 @@ import sys +import os.path import wx import wx.lib.docview as docview import wx.lib.pydocview as pydocview import TextEditor import FindService -import os.path _ = wx.GetTranslation @@ -90,7 +90,7 @@ class TextEditorApplication(pydocview.DocApp): if os.path.exists("tips.txt"): wx.CallAfter(self.ShowTip, wx.GetApp().GetTopWindow(), wx.CreateFileTipProvider("tips.txt", 0)) - wx.UpdateUIEvent.SetUpdateInterval(400) # Overhead of updating menus was too much. Change to update every 400 milliseconds. + wx.UpdateUIEvent.SetUpdateInterval(1000) # Overhead of updating menus was too much. Change to update every N milliseconds. # Tell the framework that everything is great return True diff --git a/wxPython/setup.py b/wxPython/setup.py index 6a1b7fe998..051bbdb6e8 100755 --- a/wxPython/setup.py +++ b/wxPython/setup.py @@ -34,8 +34,9 @@ import sys, os # We happen to be doing that here in this script, so make sure to # remove the build_options.py file, so that config.py will recreate it. -if os.path.exists("build_options.py"): - os.remove("build_options.py") +for bo_name in ["build_options.py", "build_options.pyc"]: + if os.path.exists(bo_name): + os.remove(bo_name) sys.setup_is_main = __name__ == "__main__" # an icky hack! from config import * diff --git a/wxPython/src/__core_rename.i b/wxPython/src/__core_rename.i index a440c6d8f7..0253f1abc6 100644 --- a/wxPython/src/__core_rename.i +++ b/wxPython/src/__core_rename.i @@ -91,6 +91,7 @@ %rename(SIZE_AUTO) wxSIZE_AUTO; %rename(SIZE_USE_EXISTING) wxSIZE_USE_EXISTING; %rename(SIZE_ALLOW_MINUS_ONE) wxSIZE_ALLOW_MINUS_ONE; +%rename(SIZE_FORCE) wxSIZE_FORCE; %rename(PORTRAIT) wxPORTRAIT; %rename(LANDSCAPE) wxLANDSCAPE; %rename(PRINT_QUALITY_HIGH) wxPRINT_QUALITY_HIGH; @@ -99,6 +100,7 @@ %rename(PRINT_QUALITY_DRAFT) wxPRINT_QUALITY_DRAFT; %rename(ID_ANY) wxID_ANY; %rename(ID_SEPARATOR) wxID_SEPARATOR; +%rename(ID_NONE) wxID_NONE; %rename(ID_LOWEST) wxID_LOWEST; %rename(ID_OPEN) wxID_OPEN; %rename(ID_CLOSE) wxID_CLOSE; @@ -476,8 +478,12 @@ %rename(MOD_NONE) wxMOD_NONE; %rename(MOD_ALT) wxMOD_ALT; %rename(MOD_CONTROL) wxMOD_CONTROL; +%rename(MOD_ALTGR) wxMOD_ALTGR; %rename(MOD_SHIFT) wxMOD_SHIFT; +%rename(MOD_META) wxMOD_META; %rename(MOD_WIN) wxMOD_WIN; +%rename(MOD_CMD) wxMOD_CMD; +%rename(MOD_ALL) wxMOD_ALL; %rename(UPDATE_UI_NONE) wxUPDATE_UI_NONE; %rename(UPDATE_UI_RECURSE) wxUPDATE_UI_RECURSE; %rename(UPDATE_UI_FROMIDLE) wxUPDATE_UI_FROMIDLE; @@ -554,6 +560,7 @@ %rename(IMAGE_ALPHA_THRESHOLD) wxIMAGE_ALPHA_THRESHOLD; %rename(IMAGE_ALPHA_OPAQUE) wxIMAGE_ALPHA_OPAQUE; %rename(ImageHandler) wxImageHandler; +%rename(PyImageHandler) wxPyImageHandler; %rename(ImageHistogram) wxImageHistogram; %rename(Image_RGBValue) wxImage_RGBValue; %rename(Image_HSVValue) wxImage_HSVValue; diff --git a/wxPython/src/_bitmap.i b/wxPython/src/_bitmap.i index 268743472d..48c940867e 100644 --- a/wxPython/src/_bitmap.i +++ b/wxPython/src/_bitmap.i @@ -283,10 +283,13 @@ the ``type`` parameter.", ""); #ifdef __WXMSW__ bool CopyFromCursor(const wxCursor& cursor); + // WXWIN_COMPATIBILITY_2_4 #if 0 int GetQuality(); void SetQuality(int q); + %pythoncode { GetQuality = wx._deprecated(GetQuality) } + %pythoncode { SetQuality = wx._deprecated(SetQuality) } #endif #endif diff --git a/wxPython/src/_choice.i b/wxPython/src/_choice.i index d50d06a3c2..365dda2c5a 100644 --- a/wxPython/src/_choice.i +++ b/wxPython/src/_choice.i @@ -73,6 +73,15 @@ public: List choices=EmptyList, long style=0, Validator validator=DefaultValidator, String name=ChoiceNameStr) -> bool", "Actually create the GUI Choice control for 2-phase creation", ""); + + DocDeclStr( + int , GetCurrentSelection() const, + "Unlike `GetSelection` which only returns the accepted selection value, +i.e. the selection in the control once the user closes the dropdown +list, this function returns the current selection. That is, while the +dropdown list is shown, it returns the currently selected item in +it. When it is not shown, its result is the same as for the other +function.", ""); static wxVisualAttributes diff --git a/wxPython/src/_clipbrd.i b/wxPython/src/_clipbrd.i index 1c262b3888..53a040abed 100644 --- a/wxPython/src/_clipbrd.i +++ b/wxPython/src/_clipbrd.i @@ -142,7 +142,8 @@ normal clipboard, if primary is True.", ""); self._instance = None def _checkInstance(self): if self._instance is None: - self._instance = self._initfunc(*self._args, **self._kwargs) + if wx.GetApp(): + self._instance = self._initfunc(*self._args, **self._kwargs) def __getattr__(self, name): self._checkInstance() return getattr(self._instance, name) diff --git a/wxPython/src/_combobox.i b/wxPython/src/_combobox.i index 9359f75dfb..d842914b93 100644 --- a/wxPython/src/_combobox.i +++ b/wxPython/src/_combobox.i @@ -166,6 +166,15 @@ the combobox text field.", "", GetMark); #endif + DocDeclStr( + int , GetCurrentSelection() const, + "Unlike `GetSelection` which only returns the accepted selection value, +i.e. the selection in the control once the user closes the dropdown +list, this function returns the current selection. That is, while the +dropdown list is shown, it returns the currently selected item in +it. When it is not shown, its result is the same as for the other +function.", ""); + DocDeclStr( bool , SetStringSelection(const wxString& string), "Select the item with the specifed string", ""); diff --git a/wxPython/src/_core_api.i b/wxPython/src/_core_api.i index 940ec32ba3..3ca6ae08f1 100644 --- a/wxPython/src/_core_api.i +++ b/wxPython/src/_core_api.i @@ -122,6 +122,33 @@ PyObject* wxPyMakeSwigPtr(void* ptr, const wxChar* className) { } +// Python's PyInstance_Check does not return True for instances of new-style +// classes. This should get close enough for both new and old classes but I +// should re-evaluate the need for doing instance checks... +bool wxPyInstance_Check(PyObject* obj) { + return PyObject_HasAttrString(obj, "__class__") != 0; +} + + + +// This one checks if the object is an instance of a SWIG proxy class (it has +// a .this attribute, and the .this attribute is a PySwigObject.) +bool wxPySwigInstance_Check(PyObject* obj) { + static PyObject* this_str = NULL; + if (this_str == NULL) + this_str = PyString_FromString("this"); + + PyObject* this_attr = PyObject_GetAttr(obj, this_str); + if (this_attr) { + bool retval = (PySwigObject_Check(this_attr) != 0); + Py_DECREF(this_attr); + return retval; + } + + PyErr_Clear(); + return false; +} + // Export a C API in a struct. Other modules will be able to load this from diff --git a/wxPython/src/_dataobj.i b/wxPython/src/_dataobj.i index 84ecb3802a..24296df053 100644 --- a/wxPython/src/_dataobj.i +++ b/wxPython/src/_dataobj.i @@ -248,8 +248,7 @@ in the given direction.", ""); for (size_t i=0; i bool + '''Check if this handler can read the image on the stream''' + + def LoadFile(self, image, stream, verbose, index) --> bool + '''Load image data from the stream and load it into image.''' + + def SaveFile(self, image, stream, verbose) --> bool + '''Save the iamge data in image to the stream using + this handler's image file format.''' + + def GetImageCount(self, stream) --> int + '''If this image format can hold more than one image, + how many does the image on the stream have?''' + +To activate your handler create an instance of it and pass it to +`wx.Image_AddHandler`. Be sure to call `SetName`, `SetType`, and +`SetExtension` from your constructor. +", ""); + +class wxPyImageHandler: public wxImageHandler { +public: + %pythonAppend wxPyImageHandler() "self._SetSelf(self)" + wxPyImageHandler(); + void _SetSelf(PyObject *self); +}; + + +//--------------------------------------------------------------------------- + + class wxImageHistogram /* : public wxImageHistogramBase */ { public: @@ -155,25 +192,41 @@ Unlike RGB data, not all images have an alpha channel and before using with `HasAlpha`. Note that currently only images loaded from PNG files with transparency information will have an alpha channel.", ""); + %{ // Pull the nested class out to the top level for SWIG's sake #define wxImage_RGBValue wxImage::RGBValue #define wxImage_HSVValue wxImage::HSVValue %} - + +DocStr(wxImage_RGBValue, +"An object that contains values for red, green and blue which represent +the value of a color. It is used by `wx.Image.HSVtoRGB` and +`wx.Image.RGBtoHSV`, which converts between HSV color space and RGB +color space.", ""); class wxImage_RGBValue { public: - wxImage_RGBValue(byte r=0, byte g=0, byte b=0); + DocCtorStr( + wxImage_RGBValue(byte r=0, byte g=0, byte b=0), + "Constructor.", ""); byte red; byte green; byte blue; }; - + + +DocStr(wxImage_HSVValue, +"An object that contains values for hue, saturation and value which +represent the value of a color. It is used by `wx.Image.HSVtoRGB` and +`wx.Image.RGBtoHSV`, which +converts between HSV color space and RGB +color space.", ""); class wxImage_HSVValue { public: - wxImage_HSVValue(double h=0.0, double s=0.0, double v=0.0); + DocCtorStr( + wxImage_HSVValue(double h=0.0, double s=0.0, double v=0.0), + "Constructor.", ""); double hue; double saturation; double value; @@ -919,8 +972,14 @@ MustHaveApp(ConvertToMonoBitmap); "Rotates the hue of each pixel of the image. Hue is a double in the range -1.0..1.0 where -1.0 is -360 degrees and 1.0 is 360 degrees", ""); - static wxImage_HSVValue RGBtoHSV(wxImage_RGBValue rgb); - static wxImage_RGBValue HSVtoRGB(wxImage_HSVValue hsv); + DocDeclStr( + static wxImage_HSVValue , RGBtoHSV(wxImage_RGBValue rgb), + "Converts a color in RGB color space to HSV color space.", ""); + + DocDeclStr( + static wxImage_RGBValue , HSVtoRGB(wxImage_HSVValue hsv), + "Converts a color in HSV color space to RGB color space.", ""); + %pythoncode { def __nonzero__(self): return self.Ok() } }; diff --git a/wxPython/src/_listctrl.i b/wxPython/src/_listctrl.i index dbb9a97143..0b88af7a3d 100644 --- a/wxPython/src/_listctrl.i +++ b/wxPython/src/_listctrl.i @@ -693,6 +693,9 @@ details in the second return value (see wx.LIST_HITTEST flags.)", ""); void SetItemBackgroundColour( long item, const wxColour &col); wxColour GetItemBackgroundColour( long item ) const; + // Font of an item. + void SetItemFont( long item, const wxFont &f); + wxFont GetItemFont( long item ) const; %pythoncode { %# diff --git a/wxPython/src/_sizers.i b/wxPython/src/_sizers.i index 1846e410d0..ae97bc0d15 100644 --- a/wxPython/src/_sizers.i +++ b/wxPython/src/_sizers.i @@ -318,14 +318,14 @@ static wxPySizerItemInfo wxPySizerItemTypeHelper(PyObject* item, bool checkSize, if ( !(info.window || info.sizer || (checkSize && info.gotSize) || (checkIdx && info.gotPos)) ) { // no expected type, figure out what kind of error message to generate if ( !checkSize && !checkIdx ) - PyErr_SetString(PyExc_TypeError, "wxWindow or wxSizer expected for item"); + PyErr_SetString(PyExc_TypeError, "wx.Window or wx.Sizer expected for item"); else if ( checkSize && !checkIdx ) - PyErr_SetString(PyExc_TypeError, "wxWindow, wxSizer, wxSize, or (w,h) expected for item"); + PyErr_SetString(PyExc_TypeError, "wx.Window, wx.Sizer, wx.Size, or (w,h) expected for item"); else if ( !checkSize && checkIdx) - PyErr_SetString(PyExc_TypeError, "wxWindow, wxSizer or int (position) expected for item"); + PyErr_SetString(PyExc_TypeError, "wx.Window, wx.Sizer or int (position) expected for item"); else // can this one happen? - PyErr_SetString(PyExc_TypeError, "wxWindow, wxSizer, wxSize, or (w,h) or int (position) expected for item"); + PyErr_SetString(PyExc_TypeError, "wx.Window, wx.Sizer, wx.Size, or (w,h) or int (position) expected for item"); } return info; diff --git a/wxPython/src/_statctrls.i b/wxPython/src/_statctrls.i index a22abfe080..240cc73877 100644 --- a/wxPython/src/_statctrls.i +++ b/wxPython/src/_statctrls.i @@ -114,6 +114,14 @@ public: long style = 0, const wxString& name = wxPyStaticTextNameStr); + DocDeclStr( + void , Wrap(int width), + "This functions wraps the control's label so that each of its lines +becomes at most ``width`` pixels wide if possible (the lines are +broken at words boundaries so it might not be the case if words are +too long). If ``width`` is negative, no wrapping is done.", ""); + + static wxVisualAttributes GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL); }; diff --git a/wxPython/src/_window.i b/wxPython/src/_window.i index ad60823e50..de89a749cf 100644 --- a/wxPython/src/_window.i +++ b/wxPython/src/_window.i @@ -436,13 +436,13 @@ window's *best size* values. Also set's the minsize for use with sizers.", ""); DocDeclStr( virtual void , Raise(), - "Raises the window to the top of the window hierarchy if it is a -managed window (dialog or frame).", ""); + "Raises the window to the top of the window hierarchy. In current +version of wxWidgets this works both for manage and child windows.", ""); DocDeclStr( virtual void , Lower(), - "Lowers the window to the bottom of the window hierarchy if it is a -managed window (dialog or frame).", ""); + "Lowers the window to the bottom of the window hierarchy. In current +version of wxWidgets this works both for manage and child windows.", ""); @@ -2060,7 +2060,8 @@ wxWindow* wxFindWindowByLabel( const wxString& label, WXHWND hWnd = (WXHWND)_hWnd; long id = wxGetWindowId(hWnd); wxWindow* win = new wxWindow; - parent->AddChild(win); + if (parent) + parent->AddChild(win); win->SetEventHandler(win); win->SetHWND(hWnd); win->SetId(id); diff --git a/wxPython/src/_xmlres.i b/wxPython/src/_xmlres.i index 79ffbc711a..e99138573a 100644 --- a/wxPython/src/_xmlres.i +++ b/wxPython/src/_xmlres.i @@ -91,6 +91,9 @@ public: } } + // Unload resource from the given XML file (wildcards not allowed) + bool Unload(const wxString& filename); + // Initialize handlers for all supported controls/windows. void InitAllHandlers(); diff --git a/wxPython/src/helpers.cpp b/wxPython/src/helpers.cpp index a1a20b66fa..13f89c15e6 100644 --- a/wxPython/src/helpers.cpp +++ b/wxPython/src/helpers.cpp @@ -701,21 +701,6 @@ PyObject* __wxPySetDictionary(PyObject* /* self */, PyObject* args) } -//--------------------------------------------------------------------------- - -// Python's PyInstance_Check does not return True for instances of new-style -// classes. This should get close enough for both new and old classes but I -// should re-evaluate the need for doing instance checks... -bool wxPyInstance_Check(PyObject* obj) { - return PyObject_HasAttrString(obj, "__class__") != 0; -} - - -// This one checks if the object is an instance of a SWIG proxy class (it has -// a .this attribute) -bool wxPySwigInstance_Check(PyObject* obj) { - return PyObject_HasAttrString(obj, "this") != 0; -} //--------------------------------------------------------------------------- @@ -2725,6 +2710,145 @@ PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) { } +//---------------------------------------------------------------------- +// wxPyImageHandler methods +// +// TODO: Switch these to use wxPython's standard macros and helper classes +// for calling callbacks. + +PyObject* wxPyImageHandler::m_DoCanRead_Name = NULL; +PyObject* wxPyImageHandler::m_GetImageCount_Name = NULL; +PyObject* wxPyImageHandler::m_LoadFile_Name = NULL; +PyObject* wxPyImageHandler::m_SaveFile_Name = NULL; + +PyObject* wxPyImageHandler::py_InputStream(wxInputStream* stream) { + return wxPyConstructObject(new wxPyInputStream(stream), + wxT("wxPyInputStream"), 0); +} + +PyObject* wxPyImageHandler::py_Image(wxImage* image) { + return wxPyConstructObject(image, wxT("wxImage"), 0); +} + +PyObject* wxPyImageHandler::py_OutputStream(wxOutputStream* stream) { + return wxPyConstructObject(stream, wxT("wxOutputStream"), 0); +} + +wxPyImageHandler::wxPyImageHandler(): + m_self(NULL) +{ + if (!m_DoCanRead_Name) { + m_DoCanRead_Name = PyString_FromString("DoCanRead"); + m_GetImageCount_Name = PyString_FromString("GetImageCount"); + m_LoadFile_Name = PyString_FromString("LoadFile"); + m_SaveFile_Name = PyString_FromString("SaveFile"); + } +} + +wxPyImageHandler::~wxPyImageHandler() { + if (m_self) { + Py_DECREF(m_self); + m_self = NULL; + } +} + +void wxPyImageHandler::_SetSelf(PyObject *self) { + // should check here for isinstance(PyImageHandler) ?? + m_self = self; + Py_INCREF(m_self); +} + +bool wxPyImageHandler::DoCanRead(wxInputStream& stream) { + // check if our object has this method + wxPyBlock_t blocked = wxPyBeginBlockThreads(); + if (!m_self || !PyObject_HasAttr(m_self, m_DoCanRead_Name)) { + wxPyEndBlockThreads(blocked); + return false; + } + + PyObject* res = PyObject_CallMethodObjArgs(m_self, m_DoCanRead_Name, + py_InputStream(&stream), NULL); + bool retval = false; + if (res) { + retval = PyInt_AsLong(res); + Py_DECREF(res); + PyErr_Clear(); + } + else + PyErr_Print(); + wxPyEndBlockThreads(blocked); + return retval; +} + +bool wxPyImageHandler::LoadFile( wxImage* image, wxInputStream& stream, + bool verbose, int index ) { + // check if our object has this method + wxPyBlock_t blocked = wxPyBeginBlockThreads(); + if (!m_self || !PyObject_HasAttr(m_self, m_LoadFile_Name)) { + wxPyEndBlockThreads(blocked); + return false; + } + PyObject* res = PyObject_CallMethodObjArgs(m_self, m_LoadFile_Name, + py_Image(image), + py_InputStream(&stream), + PyInt_FromLong(verbose), + PyInt_FromLong(index), + NULL); + bool retval = false; + if (res) { + retval = PyInt_AsLong(res); + Py_DECREF(res); + PyErr_Clear(); + } else + PyErr_Print(); + wxPyEndBlockThreads(blocked); + return retval; +} + +bool wxPyImageHandler::SaveFile( wxImage* image, wxOutputStream& stream, + bool verbose ) { + wxPyBlock_t blocked = wxPyBeginBlockThreads(); + if (!m_self || !PyObject_HasAttr(m_self, m_SaveFile_Name)) { + wxPyEndBlockThreads(blocked); + return false; + } + PyObject* res = PyObject_CallMethodObjArgs(m_self, m_SaveFile_Name, + py_Image(image), + py_OutputStream(&stream), + PyInt_FromLong(verbose), + NULL); + bool retval = false; + if(res) { + retval=PyInt_AsLong(res); + Py_DECREF(res); + PyErr_Clear(); + } else + PyErr_Print(); + wxPyEndBlockThreads(blocked); + return retval; +} + +int wxPyImageHandler::GetImageCount( wxInputStream& stream ) { + wxPyBlock_t blocked = wxPyBeginBlockThreads(); + if (!m_self || !PyObject_HasAttr(m_self, m_GetImageCount_Name)) { + wxPyEndBlockThreads(blocked); + return 1; + } + PyObject *res=PyObject_CallMethodObjArgs(m_self, m_GetImageCount_Name, + py_InputStream(&stream), + NULL); + int retval = 1; + if(res) { + retval=PyInt_AsLong(res); + Py_DECREF(res); + PyErr_Clear(); + } else + PyErr_Print(); + wxPyEndBlockThreads(blocked); + return retval; +} + + //---------------------------------------------------------------------- //---------------------------------------------------------------------- diff --git a/wxPython/src/media.i b/wxPython/src/media.i index d2db77b667..d811acb598 100644 --- a/wxPython/src/media.i +++ b/wxPython/src/media.i @@ -55,7 +55,15 @@ enum wxMediaState wxMEDIASTATE_PLAYING=0 }; +enum wxMediaCtrlPlayerControls +{ + wxMEDIACTRLPLAYERCONTROLS_NONE, + wxMEDIACTRLPLAYERCONTROLS_STEP, + wxMEDIACTRLPLAYERCONTROLS_VOLUME, + wxMEDIACTRLPLAYERCONTROLS_DEFAULT +}; + class wxMediaEvent : public wxNotifyEvent { public: @@ -89,9 +97,6 @@ public: bool Pause() { return false; } bool Stop() { return false; } - bool Load(const wxString& fileName) { return false; } - bool Load(const wxURI& location) { return false; } - wxMediaState GetState() { return wxMEDIASTATE_STOPPED; } double GetPlaybackRate() { return 0.0; } @@ -105,6 +110,14 @@ public: double GetVolume() { return 0.0; } bool SetVolume(double dVolume) { return false; } + + bool ShowPlayerControls( + wxMediaCtrlPlayerControls flags = wxMEDIACTRLPLAYERCONTROLS_DEFAULT) + { return false; } + + bool Load(const wxString& fileName) { return false; } + bool LoadURI(const wxString& fileName) { return false; } + bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy) { return false; } }; const wxEventType wxEVT_MEDIA_FINISHED = 0; @@ -180,16 +193,6 @@ public: bool Pause(); bool Stop(); - double GetVolume(); //DirectShow only - bool SetVolume(double dVolume); //DirectShow only - - bool Load(const wxString& fileName); - %extend { - bool LoadFromURI(const wxString& location) { - return self->Load(wxURI(location)); - } - } - wxMediaState GetState(); double GetPlaybackRate(); @@ -198,6 +201,17 @@ public: wxFileOffset Seek(wxFileOffset where, wxSeekMode mode = wxFromStart); wxFileOffset Tell(); wxFileOffset Length(); + + double GetVolume(); + bool SetVolume(double dVolume); + + bool ShowPlayerControls( + wxMediaCtrlPlayerControls flags = wxMEDIACTRLPLAYERCONTROLS_DEFAULT); + + bool Load(const wxString& fileName); + bool LoadURI(const wxString& fileName); + bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy); + %pythoncode { LoadFromURI = LoadURI } }; diff --git a/wxPython/wx/lib/calendar.py b/wxPython/wx/lib/calendar.py index 4c8c3b4a48..78071e666b 100644 --- a/wxPython/wx/lib/calendar.py +++ b/wxPython/wx/lib/calendar.py @@ -854,6 +854,7 @@ class Calendar( wx.PyControl ): def SetDayValue(self, day): self.set_day = day + self.day = day def SetMonth(self, month): if month >= 1 and month <= 12: diff --git a/wxPython/wx/lib/docview.py b/wxPython/wx/lib/docview.py index 075a373225..2c47b8d0cb 100644 --- a/wxPython/wx/lib/docview.py +++ b/wxPython/wx/lib/docview.py @@ -28,10 +28,12 @@ DOC_MDI = 2 DOC_NEW = 4 DOC_SILENT = 8 DOC_OPEN_ONCE = 16 +DOC_NO_VIEW = 32 DEFAULT_DOCMAN_FLAGS = DOC_SDI & DOC_OPEN_ONCE TEMPLATE_VISIBLE = 1 TEMPLATE_INVISIBLE = 2 +TEMPLATE_NO_CREATE = (4 | TEMPLATE_VISIBLE) DEFAULT_TEMPLATE_FLAGS = TEMPLATE_VISIBLE MAX_FILE_HISTORY = 9 @@ -680,8 +682,10 @@ class Document(wx.EvtHandler): """ The default implementation calls DeleteContents (an empty implementation) sets the modified flag to false. Override this to - supply additional behaviour when the document is closed with Close. + supply additional behaviour when the document is opened with Open. """ + if flags & DOC_NO_VIEW: + return True return self.GetDocumentTemplate().CreateView(self, flags) @@ -1193,6 +1197,16 @@ class DocTemplate(wx.Object): return (self._flags & TEMPLATE_VISIBLE) == TEMPLATE_VISIBLE + def IsNewable(self): + """ + Returns true if the document template can be shown in "New" dialogs, + false otherwise. + + This method has been added to wxPython and is not in wxWindows. + """ + return (self._flags & TEMPLATE_NO_CREATE) != TEMPLATE_NO_CREATE + + def GetDocumentName(self): """ Returns the document type name, as passed to the document template @@ -1250,8 +1264,9 @@ class DocTemplate(wx.Object): """ ext = FindExtension(path) if not ext: return False - return ext in self.GetFileFilter() - # return self.GetDefaultExtension() == FindExtension(path) + + extList = self.GetFileFilter().replace('*','').split(';') + return ext in extList class DocManager(wx.EvtHandler): @@ -1802,7 +1817,13 @@ class DocManager(wx.EvtHandler): will delete the oldest currently loaded document before creating a new one. - wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE flag. + wxPython version supports the document manager's wx.lib.docview.DOC_OPEN_ONCE + and wx.lib.docview.DOC_NO_VIEW flag. + + if wx.lib.docview.DOC_OPEN_ONCE is present, trying to open the same file multiple + times will just return the same document. + if wx.lib.docview.DOC_NO_VIEW is present, opening a file will generate the document, + but not generate a corresponding view. """ templates = [] for temp in self._templates: @@ -1817,16 +1838,13 @@ class DocManager(wx.EvtHandler): return None if flags & DOC_NEW: + for temp in templates[:]: + if not temp.IsNewable(): + templates.remove(temp) if len(templates) == 1: temp = templates[0] - newDoc = temp.CreateDocument(path, flags) - if newDoc: - newDoc.SetDocumentName(temp.GetDocumentName()) - newDoc.SetDocumentTemplate(temp) - newDoc.OnNewDocument() - return newDoc - - temp = self.SelectDocumentType(templates) + else: + temp = self.SelectDocumentType(templates) if temp: newDoc = temp.CreateDocument(path, flags) if newDoc: @@ -1865,7 +1883,12 @@ class DocManager(wx.EvtHandler): document.SetDocumentModificationDate() firstView = document.GetFirstView() - if firstView and firstView.GetFrame(): + if not firstView and not (flags & DOC_NO_VIEW): + document.GetDocumentTemplate().CreateView(document, flags) + document.UpdateAllViews() + firstView = document.GetFirstView() + + if firstView and firstView.GetFrame() and not (flags & DOC_NO_VIEW): firstView.GetFrame().SetFocus() # Not in wxWindows code but useful nonetheless if hasattr(firstView.GetFrame(), "IsIconized") and firstView.GetFrame().IsIconized(): # Not in wxWindows code but useful nonetheless firstView.GetFrame().Iconize(False) @@ -1878,7 +1901,9 @@ class DocManager(wx.EvtHandler): newDoc.SetDocumentTemplate(temp) if not newDoc.OnOpenDocument(path): newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews - newDoc.GetFirstView().GetFrame().Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it. + frame = newDoc.GetFirstView().GetFrame() + if frame: + Destroy() # DeleteAllViews doesn't get rid of the frame, so we'll explicitly destroy it. return None self.AddFileToHistory(path) return newDoc @@ -2117,41 +2142,32 @@ class DocManager(wx.EvtHandler): This function is used in wxDocManager.CreateDocument. """ if wx.Platform == "__WXMSW__" or wx.Platform == "__WXGTK__" or wx.Platform == "__WXMAC__": - allfilter = '' descr = '' for temp in templates: if temp.IsVisible(): if len(descr) > 0: descr = descr + _('|') - allfilter = allfilter + _(';') descr = descr + temp.GetDescription() + _(" (") + temp.GetFileFilter() + _(") |") + temp.GetFileFilter() # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk - allfilter = allfilter + temp.GetFileFilter() - descr = _("All (%s)|%s|%s|Any (*.*) | *.*") % (allfilter, allfilter, descr) # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk + descr = _("All (*.*)|*.*|%s") % descr # spacing is important, make sure there is no space after the "|", it causes a bug on wx_gtk else: descr = _("*.*") - path = wx.FileSelector(_("Select a File"), - self._lastDirectory, - _(""), - wildcard = descr, - flags = wx.HIDE_READONLY, - parent = self.FindSuitableParent()) - if path: - if not FileExists(path): - msgTitle = wx.GetApp().GetAppName() - if not msgTitle: - msgTitle = _("File Error") - wx.MessageBox("Could not open '%s'." % FileNameFromPath(path), - msgTitle, - wx.OK | wx.ICON_EXCLAMATION, - parent) - return (None, None) - self._lastDirectory = PathOnly(path) - + dlg = wx.FileDialog(self.FindSuitableParent(), + _("Select a File"), + wildcard=descr, + style=wx.OPEN|wx.FILE_MUST_EXIST|wx.CHANGE_DIR) + # dlg.CenterOnParent() # wxBug: caused crash with wx.FileDialog + if dlg.ShowModal() == wx.ID_OK: + path = dlg.GetPath() + else: + path = None + dlg.Destroy() + + if path: theTemplate = self.FindTemplateForPath(path) return (theTemplate, path) - - return (None, None) + + return (None, None) def OnOpenFileFailure(self): @@ -3151,8 +3167,10 @@ class CommandProcessor(wx.Object): the history list. """ done = command.Do() - if done and storeIt: - self._commands.append(command) + if done: + del self._redoCommands[:] + if storeIt: + self._commands.append(command) if self._maxCommands > -1: if len(self._commands) > self._maxCommands: del self._commands[0] diff --git a/wxPython/wx/lib/filebrowsebutton.py b/wxPython/wx/lib/filebrowsebutton.py index ca3338f462..0620161d11 100644 --- a/wxPython/wx/lib/filebrowsebutton.py +++ b/wxPython/wx/lib/filebrowsebutton.py @@ -242,8 +242,8 @@ class FileBrowseButtonWithHistory( FileBrowseButton ): textControl.SetToolTipString( self.toolTip ) textControl.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) if self.changeCallback: - textControl.Bind(wx.EVT_TEXT, self.changeCallback) - textControl.Bind(wx.EVT_COMBOBOX, self.changeCallback) + textControl.Bind(wx.EVT_TEXT, self.OnChanged) + textControl.Bind(wx.EVT_COMBOBOX, self.OnChanged) if self.history: history=self.history self.history=None diff --git a/wxPython/wx/lib/foldpanelbar.py b/wxPython/wx/lib/foldpanelbar.py index 4cc6c907e2..66a5ab2a15 100644 --- a/wxPython/wx/lib/foldpanelbar.py +++ b/wxPython/wx/lib/foldpanelbar.py @@ -3,7 +3,7 @@ # Ported From Jorgen Bodde & Julian Smart (Extended Demo) C++ Code By: # # Andrea Gavana, @ 23 Mar 2005 -# Latest Revision: 28 Mar 2005, 22.30 CET +# Latest Revision: 05 Nov 2005, 23.30 CET # # # TODO List @@ -30,9 +30,14 @@ # TODO: A Smart Way To Check Wether The Old - New Width Of The # Panel Changed, If So No Need To Resize The Fold Panel Items # -# 5. Implementing Styles Like FPB_SINGLE_FOLD and FPB_EXCLUSIVE_FOLD -# TODO: Jorgen Has Left Undone These Jobs. I Don't Really Get What They -# Should Supposed To Do, So If Someone Could Enlight Me, Please Let Me Know. +# +# DONE List: +# +# 1. Implemented Styles Like FPB_SINGLE_FOLD and FPB_EXCLUSIVE_FOLD +# Thanks To E. A. Tacao For His Nice Suggestions. +# +# 2. Added Some Maquillage To FoldPanelBar: When The Mouse Enters The Icon +# Region, It Is Changed To wx.CURSOR_HAND. # # # For The Original TODO List From Jorgen, Please Refer To: @@ -106,7 +111,7 @@ FoldPanelBar is supported on the following platforms: * Mac OSX (Thanks To Robin Dunn For The CaptionBar Size Patch) -Latest Revision: Andrea Gavana @ 30 Mar 2005, 22.30 CET +Latest Revision: Andrea Gavana @ 05 Nov 2005, 23.30 CET """ @@ -179,7 +184,7 @@ FPB_EXTRA_Y = 4 # pixels of the bmp to be aligned from the right filled with space FPB_BMP_RIGHTSPACE = 2 -# Not yet supported but added for future reference. Single fold forces +# Now supported! Single fold forces # other panels to close when they are open, and only opens the current panel. # This will allow the open panel to gain the full size left in the client area FPB_SINGLE_FOLD = 0x0001 @@ -188,9 +193,9 @@ FPB_SINGLE_FOLD = 0x0001 # show up at the top FPB_COLLAPSE_TO_BOTTOM = 0x0002 -# Not yet supported, but added for future reference. Single fold plus panels +# Now supported! Single fold plus panels # will be stacked at the bottom -FPB_EXCLUSIVE_FOLD = FPB_SINGLE_FOLD | FPB_COLLAPSE_TO_BOTTOM +FPB_EXCLUSIVE_FOLD = 0x0004 # Orientation Flag FPB_HORIZONTAL = wx.HORIZONTAL @@ -669,12 +674,13 @@ class CaptionBar(wx.Window): dc = wx.PaintDC(self) wndRect = self.GetRect() vertical = self.IsVertical() - + # TODO: Maybe first a memory DC should draw all, and then paint it on # the caption. This way a flickering arrow during resize is not visible self.FillCaptionBackground(dc) dc.SetFont(self._style.GetCaptionFont()) + dc.SetTextForeground(self._style.GetCaptionColour()) if vertical: dc.DrawText(self._caption, 4, FPB_EXTRA_Y/2) @@ -734,27 +740,52 @@ class CaptionBar(wx.Window): """ Catches the mouse click-double click. - If clicked on the arrow (single) or double on the caption we - change state and an event must be fired to let this panel - collapse or expand. + If clicked on the arrow (single) or double on the caption we change state + and an event must be fired to let this panel collapse or expand. """ - - send_event = False + send_event = False + vertical = self.IsVertical() + if event.LeftDown() and self._foldIcons: pt = event.GetPosition() rect = self.GetRect() - vertical = self.IsVertical() - + drw = (rect.GetWidth() - self._iconWidth - self._rightIndent) if vertical and pt.x > drw or not vertical and \ pt.y < (self._iconHeight + self._rightIndent): send_event = True elif event.LeftDClick(): + self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) send_event = True + elif event.Entering() and self._foldIcons: + pt = event.GetPosition() + rect = self.GetRect() + + drw = (rect.GetWidth() - self._iconWidth - self._rightIndent) + if vertical and pt.x > drw or not vertical and \ + pt.y < (self._iconHeight + self._rightIndent): + self.SetCursor(wx.StockCursor(wx.CURSOR_HAND)) + else: + self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) + + elif event.Leaving(): + self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) + + elif event.Moving(): + pt = event.GetPosition() + rect = self.GetRect() + + drw = (rect.GetWidth() - self._iconWidth - self._rightIndent) + if vertical and pt.x > drw or not vertical and \ + pt.y < (self._iconHeight + self._rightIndent): + self.SetCursor(wx.StockCursor(wx.CURSOR_HAND)) + else: + self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW)) + # send the collapse, expand event to the parent if send_event: @@ -1172,7 +1203,7 @@ class FoldPanelBar(wx.Panel): self._foldPanel.SetSize(foldrect[2:]) - if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM: + if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM or self._extraStyle & FPB_EXCLUSIVE_FOLD: rect = self.RepositionCollapsedToBottom() vertical = self.IsVertical() if vertical and rect.GetHeight() > 0 or not vertical and rect.GetWidth() > 0: @@ -1212,7 +1243,7 @@ class FoldPanelBar(wx.Panel): # should be drawn at the bottom. All panels that are expanded # are drawn on top. The last expanded panel gets all the extra space - if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM: + if self._extraStyle & FPB_COLLAPSE_TO_BOTTOM or self._extraStyle & FPB_EXCLUSIVE_FOLD: offset = 0 @@ -1353,9 +1384,22 @@ class FoldPanelBar(wx.Panel): the bottom and the order where the panel originally was placed is restored. """ + + fpbextrastyle = 0 + if self._extraStyle & FPB_SINGLE_FOLD or self._extraStyle & FPB_EXCLUSIVE_FOLD: + fpbextrastyle = 1 + for panel in self._panels: + panel.Collapse() + foldpanel.Expand() - self.RefreshPanelsFrom(foldpanel) + + if fpbextrastyle: + if self._extraStyle & FPB_EXCLUSIVE_FOLD: + self.RepositionCollapsedToBottom() + self.RefreshPanelsFrom(self._panels[0]) + else: + self.RefreshPanelsFrom(foldpanel) def ApplyCaptionStyle(self, foldpanel, cbstyle): diff --git a/wxPython/wx/lib/hyperlink.py b/wxPython/wx/lib/hyperlink.py index adc746316d..1795e46c6f 100644 --- a/wxPython/wx/lib/hyperlink.py +++ b/wxPython/wx/lib/hyperlink.py @@ -3,7 +3,7 @@ # Ported From Angelo Mandato C++ Code By: # # Andrea Gavana, @ 27 Mar 2005 -# Latest Revision: 27 Apr 2005, 22.30 CET +# Latest Revision: 05 Nov 2005, 22.30 CET # # # Original Web Site (For The C++ Code): @@ -11,6 +11,8 @@ # http://www.spaceblue.com/codedetail.php?CodeID=7 # # +# Thanks to E. A. Tacao for his nice suggestions and improvements of the code. +# # For all kind of problems, requests of enhancements and bug reports, please # write to me at: # @@ -33,7 +35,7 @@ browser window. Special thanks to Robin Dunn for the event binder for the 3 mouse buttons. -Latest Revision: Andrea Gavana @ 11 May 2005, 21.00 CET +Latest Revision: Andrea Gavana @ 05 Nov 2005, 22.30 CET """ @@ -212,15 +214,24 @@ class HyperLinkCtrl(StaticText): self.SetCursor(self._CursorHand) if self._EnableRollover: - self.SetForegroundColour(self._LinkRolloverColor) fontTemp = self.GetFont() fontTemp.SetUnderlined(self._RolloverUnderline) if self._Bold: fontTemp.SetWeight(wx.BOLD) + + needRefresh = False + + if self.GetFont() != fontTemp: + self.SetFont(fontTemp) + needRefresh = True - self.SetFont(fontTemp) - self.Refresh() + if self.GetForegroundColour() != self._LinkRolloverColor: + self.SetForegroundColour(self._LinkRolloverColor) + needRefresh = True + if needRefresh: + self.Refresh() + else: # Restore The Original Cursor self.SetCursor(wx.NullCursor) @@ -301,12 +312,12 @@ class HyperLinkCtrl(StaticText): self.SetForegroundColour(self._LinkColour) fontTemp.SetUnderlined(self._LinkUnderline) - if self._Bold: fontTemp.SetWeight(wx.BOLD) - self.SetFont(fontTemp) - self.Refresh(OnRefresh) + if self.GetFont() != fontTemp: + self.SetFont(fontTemp) + self.Refresh(OnRefresh) def DisplayError(self, ErrorMessage, ReportErrors=True): diff --git a/wxPython/wx/lib/masked/maskededit.py b/wxPython/wx/lib/masked/maskededit.py index be2753eb8b..d2be65e91d 100644 --- a/wxPython/wx/lib/masked/maskededit.py +++ b/wxPython/wx/lib/masked/maskededit.py @@ -696,6 +696,8 @@ Event Handling self._SetKeycodeHandler(WXK_UP, self.IncrementValue) self._SetKeyHandler('-', self._OnChangeSign) + (Setting a func of None removes any keyhandler for the given key.) + "Navigation" keys are assumed to change the cursor position, and therefore don't cause automatic motion of the cursor as insertable characters do. @@ -2106,7 +2108,10 @@ class MaskedEditMixin: used by the control. should take the event as argument and return False if no further action on the key is necessary. """ - self._keyhandlers[keycode] = func + if func: + self._keyhandlers[keycode] = func + elif self._keyhandlers.has_key(keycode): + del self._keyhandlers[keycode] def _SetKeyHandler(self, char, func): @@ -2126,6 +2131,9 @@ class MaskedEditMixin: self._nav.append(keycode) if handler: self._keyhandlers[keycode] = handler + elif self.keyhandlers.has_key(keycode): + del self._keyhandlers[keycode] + def _AddNavKey(self, char, handler=None): @@ -2154,6 +2162,8 @@ class MaskedEditMixin: self._nav.append(keycode) if func: self._keyhandlers[keycode] = func + elif self.keyhandlers.has_key(keycode): + del self._keyhandlers[keycode] def _processMask(self, mask): @@ -2611,6 +2621,12 @@ class MaskedEditMixin: keycode = ord(key) if not self._keyhandlers.has_key(keycode): self._SetKeyHandler(key, self._OnChangeSign) + elif self._isInt or self._isFloat: + signkeys = ['-', '+', ' ', '(', ')'] + for key in signkeys: + keycode = ord(key) + if self._keyhandlers.has_key(keycode) and self._keyhandlers[keycode] == self._OnChangeSign: + self._SetKeyHandler(key, None) @@ -2674,14 +2690,15 @@ class MaskedEditMixin: 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 cusor after decimal point if floating point, otherwise at 0. - if not self._keyhandlers.has_key(ord(self._decimalChar)): + # leaves cursor after decimal point if floating point, otherwise at 0. + if not self._keyhandlers.has_key(ord(self._decimalChar)) or self._keyhandlers[ord(self._decimalChar)] != self._OnDecimalPoint: self._SetKeyHandler(self._decimalChar, self._OnDecimalPoint) - if not self._keyhandlers.has_key(ord(self._shiftDecimalChar)): + + if not self._keyhandlers.has_key(ord(self._shiftDecimalChar)) or self._keyhandlers[ord(self._shiftDecimalChar)] != self._OnChangeField: self._SetKeyHandler(self._shiftDecimalChar, self._OnChangeField) # (Shift-'.' == '>' on US keyboards) # Allow selective insert of groupchar in numbers: - if not self._keyhandlers.has_key(ord(self._fields[0]._groupChar)): + if not self._keyhandlers.has_key(ord(self._fields[0]._groupChar)) or self._keyhandlers[ord(self._fields[0]._groupChar)] != self._OnGroupChar: self._SetKeyHandler(self._fields[0]._groupChar, self._OnGroupChar) ## dbg(indent=0, suspend=0) @@ -3784,13 +3801,17 @@ class MaskedEditMixin: value = self._eraseSelection() integer = self._fields[0] start, end = integer._extent + sel_start, sel_to = self._GetSelection() #### dbg('adjusted pos:', pos) if chr(key) in ('-','+','(', ')') or (chr(key) == " " and pos == self._signpos): cursign = self._isNeg ## dbg('cursign:', cursign) if chr(key) in ('-','(', ')'): - self._isNeg = (not self._isNeg) ## flip value + if sel_start <= self._signpos: + self._isNeg = True + else: + self._isNeg = (not self._isNeg) ## flip value else: self._isNeg = False ## dbg('isNeg?', self._isNeg) @@ -4098,7 +4119,7 @@ class MaskedEditMixin: # first space for sign, and last one if using parens. if( self._signOk and ((pos == self._signpos and key in (ord('-'), ord('+'), ord(' ')) ) - or self._useParens and pos == self._masklength -1)): + or (self._useParens and pos == self._masklength -1))): ## dbg('adjusted pos:', pos, indent=0) return pos @@ -4106,6 +4127,7 @@ class MaskedEditMixin: field = self._FindField(pos) ## dbg('field._insertRight?', field._insertRight) +## if self._signOk: dbg('self._signpos:', self._signpos) if field._insertRight: # if allow right-insert start, end = field._extent slice = self._GetValue()[start:end].strip() @@ -4140,12 +4162,14 @@ class MaskedEditMixin: ## # restore selection ## self._SetSelection(sel_start, pos) - elif self._signOk and sel_start == 0: # if selected to beginning and signed, + # if selected to beginning and signed, and not changing sign explicitly: + elif self._signOk and sel_start == 0 and key not in (ord('-'), ord('+'), ord(' ')): # adjust to past reserved sign position: pos = self._fields[0]._extent[0] +## dbg('adjusting field to ', pos) self._SetInsertionPoint(pos) - # restore selection - self._SetSelection(pos, sel_to) + # but keep original selection, to allow replacement of any sign: + self._SetSelection(0, sel_to) else: pass # leave position/selection alone @@ -4526,11 +4550,11 @@ class MaskedEditMixin: if self._signOk: text, signpos, right_signpos = self._getSignedValue() ## dbg('text: "%s", signpos:' % text, signpos) + if text and signpos != self._signpos: + self._signpos = signpos if not text or text[signpos] not in ('-','('): self._isNeg = False ## dbg('no valid sign found; new sign:', self._isNeg) - if text and signpos != self._signpos: - self._signpos = signpos elif text and self._valid and not self._isNeg and text[signpos] in ('-', '('): ## dbg('setting _isNeg to True') self._isNeg = True @@ -5352,6 +5376,8 @@ class MaskedEditMixin: field = self._FindField(self._GetInsertionPoint()) edit_start, edit_end = field._extent if field._selectOnFieldEntry: + if self._isFloat or self._isInt and field == self._fields[0]: + edit_start = 0 self._SetInsertionPoint(edit_start) self._SetSelection(edit_start, edit_end) @@ -5368,8 +5394,8 @@ class MaskedEditMixin: if integer._selectOnFieldEntry: ## dbg('select on field entry:') - self._SetInsertionPoint(edit_start) - self._SetSelection(edit_start, edit_end) + self._SetInsertionPoint(0) + self._SetSelection(0, edit_end) elif integer._insertRight: ## dbg('moving insertion point to end') @@ -6546,6 +6572,22 @@ __i=0 ## CHANGELOG: ## ==================== +## Version 1.9 +## 1. Now ignores kill focus events when being destroyed. +## 2. Added missing call to set insertion point on changing fields. +## 3. Modified SetKeyHandler() to accept None as means of removing one. +## 4. Fixed keyhandler processing for group and decimal character changes. +## 5. Fixed a problem that prevented input into the integer digit of a +## integerwidth=1 numctrl, if the current value was 0. +## 6. Fixed logic involving processing of "_signOk" flag, to remove default +## sign key handlers if false, so that SetAllowNegative(False) in the +## NumCtrl works properly. +## 7. Fixed selection logic for numeric controls so that if selectOnFieldEntry +## is true, and the integer portion of an integer format control is selected +## and the sign position is selected, the sign keys will always result in a +## negative value, rather than toggling the previous sign. +## +## ## Version 1.8 ## 1. Fixed bug involving incorrect variable name, causing combobox autocomplete to fail. ## 2. Added proper support for unicode version of wxPython diff --git a/wxPython/wx/lib/masked/numctrl.py b/wxPython/wx/lib/masked/numctrl.py index e48eacd7b7..1256ee0780 100644 --- a/wxPython/wx/lib/masked/numctrl.py +++ b/wxPython/wx/lib/masked/numctrl.py @@ -762,12 +762,6 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): if maskededit_kwargs.keys(): self.SetCtrlParameters(**maskededit_kwargs) - # Record end of integer and place cursor there: - integerEnd = self._fields[0]._extent[1] - self.SetInsertionPoint(0) - self.SetInsertionPoint(integerEnd) - self.SetSelection(integerEnd, integerEnd) - # Go ensure all the format codes necessary are present: orig_intformat = intformat = self.GetFieldParameter(0, 'formatcodes') if 'r' not in intformat: @@ -780,6 +774,17 @@ class NumCtrl(BaseMaskedTextCtrl, NumCtrlAccessorsMixin): else: self.SetCtrlParameters(formatcodes=intformat) + # Record end of integer and place cursor there unless selecting, or select entire field: + integerStart, integerEnd = self._fields[0]._extent + if not self._fields[0]._selectOnFieldEntry: + self.SetInsertionPoint(0) + self.SetInsertionPoint(integerEnd) + self.SetSelection(integerEnd, integerEnd) + else: + self.SetInsertionPoint(0) # include any sign + self.SetSelection(0, integerEnd) + + # Set min and max as appropriate: if kwargs.has_key('min'): min = kwargs['min'] diff --git a/wxPython/wx/lib/mixins/grid.py b/wxPython/wx/lib/mixins/grid.py index f24b65058f..586d24eee5 100644 --- a/wxPython/wx/lib/mixins/grid.py +++ b/wxPython/wx/lib/mixins/grid.py @@ -1,5 +1,5 @@ #---------------------------------------------------------------------------- -# Name: wxPython.lib.mixins.grid +# Name: wx.lib.mixins.grid # Purpose: Helpful mix-in classes for wx.Grid # # Author: Robin Dunn @@ -34,20 +34,15 @@ class GridAutoEditMixin: """ def __init__(self): - self.__enableEdit = 0 - self.Bind(wx.EVT_IDLE, self.__OnIdle) self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.__OnSelectCell) - def __OnIdle(self, evt): - if self.__enableEdit: - if self.CanEnableCellControl(): - self.EnableCellEditControl() - self.__enableEdit = 0 - evt.Skip() + def __DoEnableEdit(self): + if self.CanEnableCellControl(): + self.EnableCellEditControl() def __OnSelectCell(self, evt): - self.__enableEdit = 1 + wx.CallAfter(self.__DoEnableEdit) evt.Skip() diff --git a/wxPython/wx/lib/ogl/_basic.py b/wxPython/wx/lib/ogl/_basic.py index 69028630a8..5ebf3287ca 100644 --- a/wxPython/wx/lib/ogl/_basic.py +++ b/wxPython/wx/lib/ogl/_basic.py @@ -289,8 +289,7 @@ class Shape(ShapeEvtHandler): def Delete(self): if self._parent: - i = self._parent.GetChildren().index(self) - self._parent.GetChildren(i).remove(self) + self._parent.GetChildren().remove(self) self.ClearText() self.ClearRegions() @@ -301,7 +300,8 @@ class Shape(ShapeEvtHandler): if self._canvas: self.RemoveFromCanvas(self._canvas) - self.GetEventHandler().OnDelete() + if self.GetEventHandler(): + self.GetEventHandler().OnDelete() self._eventHandler = None def __del__(self): diff --git a/wxPython/wx/lib/printout.py b/wxPython/wx/lib/printout.py index 086a6c1fc0..32f3eac88c 100644 --- a/wxPython/wx/lib/printout.py +++ b/wxPython/wx/lib/printout.py @@ -15,14 +15,15 @@ # add index to data list after parsing total pages for paging #---------------------------------------------------------------------------- # 12/10/2003 - Jeff Grimmett (grimmtooth@softhome.net) -# # o 2.5 compatability update. -# - +#---------------------------------------------------------------------------- +# 11/23/2004 - Vernon Cole (wnvcole@peppermillcas.com) +# o Generalize for non-2-dimensional sequences and non-text data +# (can use as a simple text printer by supplying a list of strings.) +# o Add a small _main_ for self test + import copy -import os -import sys - +import types import wx class PrintBase: @@ -268,10 +269,47 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): pos_x = self.left_margin * self.pwidth + self.horizontal_offset # left margin self.column.append(pos_x) + #module logic expects two dimensional data -- fix input if needed + if isinstance(self.data,types.StringTypes): + self.data = [[copy.copy(self.data)]] # a string becomes a single cell + try: + rows = len(self.data) + except TypeError: + self.data = [[str(self.data)]] # a non-iterable becomes a single cell + rows = 1 + first_value = self.data[0] + + if isinstance(first_value, types.StringTypes): # a sequence of strings + if self.label == [] and self.set_column == []: + data = [] + for x in self.data: #becomes one column + data.append([x]) + else: + data = [self.data] #becames one row + self.data = data + first_value = data[0] + try: + column_total = len(first_value) + except TypeError: # a sequence of non-iterables + if self.label == [] and self.set_column == []: + data = [] #becomes one column + for x in self.data: + data.append([str(x)]) + column_total = 1 + else: + data = [self.data] #becomes one row + column_total = len(self.data) + self.data = data + first_value = data[0] + if self.set_column == []: table_width = self.page_width - self.left_margin - self.right_margin - width = table_width/(len(self.label)) - for val in self.label: + if self.label == []: + temp = first_value + else: + temp = self.label + width = table_width/(len(temp)) + for val in temp: column_width = width * self.pwidth pos_x = pos_x + column_width self.column.append(pos_x) # position of each column @@ -290,13 +328,10 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): print "Column Settings Incorrect", "\nColumn Value: " + str(self.column), "\nLabel Value: " + str(self.label) return - first_value = self.data[0] - column_total = len(first_value) if column_total != len(self.column) -1: - print "Column Settings Incorrect", first_value, self.column + print "Cannot fit", first_value, 'in', len(self.column)-1, 'columns.' return - col = 0 for col in range(column_total): try: align = set_column_align[col] # check if custom column alignment @@ -314,10 +349,8 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): colour = set_column_txtcolour[col] # check if custom column text colour except: colour = self.GetFontColour(self.parent.text_font) - self.column_txtcolour.append(colour) - col = col + 1 def SetPointAdjust(self): f = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL) # setup using 10 point @@ -526,12 +559,14 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): self.col = 0 max_y = 0 for vtxt in row_val: + if not isinstance(vtxt,types.StringTypes): + vtxt = str(vtxt) self.region = self.column[self.col+1] - self.column[self.col] self.indent = self.column[self.col] self.align = self.column_align[self.col] fcolour = self.column_txtcolour[self.col] # set font colour - celltext = self.GetCellText(self.data_cnt, self.col) + celltext = self.GetCellTextColour(self.data_cnt, self.col) if celltext is not None: fcolour = celltext # override the column colour @@ -554,7 +589,7 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): except: return None - def GetCellText(self, row, col): # check if custom colour defined for the cell text + def GetCellTextColour(self, row, col): # check if custom colour defined for the cell text try: set = self.cell_text[row] except: @@ -570,7 +605,8 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): self.DrawColumns() # draw all vertical lines def DrawGridLine(self): - if self.draw == True: + if self.draw == True \ + and len(self.column) > 2: #supress grid lines if only one column try: size = self.row_line_size[self.data_cnt] except: @@ -588,7 +624,8 @@ class PrintTableDraw(wx.ScrolledWindow, PrintBase): self.DC.DrawLine(self.column[0], y_out, self.end_x, y_out) def DrawColumns(self): - if self.draw == True: + if self.draw == True \ + and len(self.column) > 2: #surpress grid line if only one column col = 0 for val in self.column: try: @@ -720,8 +757,8 @@ class PrintTable: self.footer_type = "Pageof" def SetMargins(self): - self.left_margin = 1.0 - self.right_margin = 1.0 # only used if no column sizes + self.left_margin = 0.5 + self.right_margin = 0.5 # only used if no column sizes self.top_margin = 0.8 self.bottom_margin = 1.0 @@ -869,15 +906,15 @@ class PrintTable: self.footer.append(set) def Preview(self): + data = wx.PrintDialogData(self.printData) printout = SetPrintout(self) printout2 = SetPrintout(self) - self.preview = wx.PrintPreview(printout, printout2, self.printData) + self.preview = wx.PrintPreview(printout, printout2, data) if not self.preview.Ok(): wxMessageBox("There was a problem printing!", "Printing", wx.OK) return self.preview.SetZoom(60) # initial zoom value - frame = wx.PreviewFrame(self.preview, self.parentFrame, "Print preview") frame.Initialize() @@ -887,14 +924,13 @@ class PrintTable: frame.Show(True) def Print(self): - pdd = wx.PrintDialogData() - pdd.SetPrintData(self.printData) + pdd = wx.PrintDialogData(self.printData) printer = wx.Printer(pdd) printout = SetPrintout(self) if not printer.Print(self.parentFrame, printout): wx.MessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wx.OK) else: - self.printData = printer.GetPrintDialogData().GetPrintData() + self.printData = wx.PrintData( printer.GetPrintDialogData().GetPrintData() ) printout.Destroy() def DoDrawing(self, DC): @@ -1091,8 +1127,23 @@ class SetPrintout(wx.Printout): self.canvas.DoDrawing(dc) return True - - - - - +if __name__ == '__main__': + app = wx.PySimpleApp() + frame = wx.Frame(None, -1, "Dummy wx frame for testing printout.py") + frame.Show(True) + ptbl = PrintTable(frame) + ptbl.SetHeader('This is the test HEADER') + # a single sequence will print out as a single column with no borders ... + ptbl.data = ( + 'This is the first line of text.', + 'This is the second line\nand the third. The fourth will be the number "4.0".', + 04.00, + 'This is the fifth line, but by design it is too long to fit in the width of a standard'\ + ' page, so it will be forced to wrap around in order to fit without having '\ + 'some of its verbose verbage truncated.', + 'Here we have the final line.' + ) + #... but, if labels or columns are defined, a single sequence will print out as a single row + ##ptbl.label = ('One','Two','Three','Four','5') + ptbl.Preview() + app.MainLoop() diff --git a/wxPython/wx/lib/pydocview.py b/wxPython/wx/lib/pydocview.py index 7c9f8e00c0..2ac99a3e6b 100644 --- a/wxPython/wx/lib/pydocview.py +++ b/wxPython/wx/lib/pydocview.py @@ -194,8 +194,16 @@ class DocFrameMixIn: Saves all of the currently open documents. """ docs = wx.GetApp().GetDocumentManager().GetDocuments() + + # save child documents first + for doc in docs: + if isinstance(doc, wx.lib.pydocview.ChildDocument): + doc.Save() + + # save parent and other documents later for doc in docs: - doc.Save() + if not isinstance(doc, wx.lib.pydocview.ChildDocument): + doc.Save() def OnAbout(self, event): @@ -371,12 +379,13 @@ class DocMDIParentFrameMixIn: Create the specified embedded windows around the edges of the frame. """ frameSize = self.GetSize() # TODO: GetClientWindow.GetSize is still returning 0,0 since the frame isn't fully constructed yet, so using full frame size - defaultHSize = int(frameSize[0] / 6) - defaultVSize = int(frameSize[1] / 7) + MIN_SIZE = 20 + defaultHSize = max(MIN_SIZE, int(frameSize[0] / 6)) + defaultVSize = max(MIN_SIZE, int(frameSize[1] / 7)) defaultSubVSize = int(frameSize[1] / 2) config = wx.ConfigBase_Get() if windows & (EMBEDDED_WINDOW_LEFT | EMBEDDED_WINDOW_TOPLEFT | EMBEDDED_WINDOW_BOTTOMLEFT): - self._leftEmbWindow = self._CreateEmbeddedWindow(self, (config.ReadInt("MDIEmbedLeftSize", defaultHSize), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_LEFT, visible = config.ReadInt("MDIEmbedLeftVisible", 1), sash = wx.SASH_RIGHT) + self._leftEmbWindow = self._CreateEmbeddedWindow(self, (max(MIN_SIZE,config.ReadInt("MDIEmbedLeftSize", defaultHSize)), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_LEFT, visible = config.ReadInt("MDIEmbedLeftVisible", 1), sash = wx.SASH_RIGHT) else: self._leftEmbWindow = None if windows & EMBEDDED_WINDOW_TOPLEFT: @@ -388,7 +397,7 @@ class DocMDIParentFrameMixIn: else: self._bottomLeftEmbWindow = None if windows & (EMBEDDED_WINDOW_RIGHT | EMBEDDED_WINDOW_TOPRIGHT | EMBEDDED_WINDOW_BOTTOMRIGHT): - self._rightEmbWindow = self._CreateEmbeddedWindow(self, (config.ReadInt("MDIEmbedRightSize", defaultHSize), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_RIGHT, visible = config.ReadInt("MDIEmbedRightVisible", 1), sash = wx.SASH_LEFT) + self._rightEmbWindow = self._CreateEmbeddedWindow(self, (max(MIN_SIZE,config.ReadInt("MDIEmbedRightSize", defaultHSize)), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_RIGHT, visible = config.ReadInt("MDIEmbedRightVisible", 1), sash = wx.SASH_LEFT) else: self._rightEmbWindow = None if windows & EMBEDDED_WINDOW_TOPRIGHT: @@ -400,11 +409,11 @@ class DocMDIParentFrameMixIn: else: self._bottomRightEmbWindow = None if windows & EMBEDDED_WINDOW_TOP: - self._topEmbWindow = self._CreateEmbeddedWindow(self, (-1, config.ReadInt("MDIEmbedTopSize", defaultVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopVisible", 1), sash = wx.SASH_BOTTOM) + self._topEmbWindow = self._CreateEmbeddedWindow(self, (-1, max(MIN_SIZE,config.ReadInt("MDIEmbedTopSize", defaultVSize))), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopVisible", 1), sash = wx.SASH_BOTTOM) else: self._topEmbWindow = None if windows & EMBEDDED_WINDOW_BOTTOM: - self._bottomEmbWindow = self._CreateEmbeddedWindow(self, (-1, config.ReadInt("MDIEmbedBottomSize", defaultVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomVisible", 1), sash = wx.SASH_TOP) + self._bottomEmbWindow = self._CreateEmbeddedWindow(self, (-1, max(MIN_SIZE,config.ReadInt("MDIEmbedBottomSize", defaultVSize))), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomVisible", 1), sash = wx.SASH_TOP) else: self._bottomEmbWindow = None @@ -572,11 +581,11 @@ class DocMDIParentFrameMixIn: self._LayoutFrame() - def HideEmbeddedWindow(self): + def HideEmbeddedWindow(self, window): """ Hides the embedded window specified by the embedded window location constant. """ - self.ShowEmbeddedWindow(show = False) + self.ShowEmbeddedWindow(window, show=False) class DocTabbedChildFrame(wx.Panel): @@ -645,7 +654,7 @@ class DocTabbedChildFrame(wx.Panel): """ Returns the frame's title. """ - wx.GetApp().GetTopWindow().GetNotebookPageTitle(self) + return wx.GetApp().GetTopWindow().GetNotebookPageTitle(self) def SetTitle(self, title): @@ -769,11 +778,22 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn): """ Creates the notebook to use for the tabbed document interface. """ - self._notebook = wx.Notebook(self, wx.NewId()) + if wx.Platform != "__WXMAC__": + self._notebook = wx.Notebook(self, wx.NewId()) + else: + self._notebook = wx.Listbook(self, wx.NewId(), style=wx.LB_LEFT) # self._notebook.SetSizer(wx.NotebookSizer(self._notebook)) - wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged) + if wx.Platform != "__WXMAC__": + wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged) + else: + wx.EVT_LISTBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged) wx.EVT_RIGHT_DOWN(self._notebook, self.OnNotebookRightClick) - wx.EVT_MOTION(self._notebook, self.OnNotebookMouseOver) + wx.EVT_MIDDLE_DOWN(self._notebook, self.OnNotebookMiddleClick) + + # wxBug: wx.Listbook does not implement HitTest the same way wx.Notebook + # does, so for now don't fire MouseOver events. + if wx.Platform != "__WXMAC__": + wx.EVT_MOTION(self._notebook, self.OnNotebookMouseOver) templates = wx.GetApp().GetDocumentManager().GetTemplates() iconList = wx.ImageList(16, 16, initialCount = len(templates)) @@ -829,6 +849,7 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn): def OnNotebookMouseOver(self, event): # wxBug: On Windows XP the tooltips don't automatically disappear when you move the mouse and it is on a notebook tab, has nothing to do with this code!!! index, type = self._notebook.HitTest(event.GetPosition()) + if index > -1: doc = self._notebook.GetPage(index).GetView().GetDocument() self._notebook.SetToolTip(wx.ToolTip(doc.GetFilename())) @@ -837,6 +858,17 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn): event.Skip() + def OnNotebookMiddleClick(self, event): + """ + Handles middle clicks for the notebook, closing the document whose tab was + clicked on. + """ + index, type = self._notebook.HitTest(event.GetPosition()) + if index > -1: + doc = self._notebook.GetPage(index).GetView().GetDocument() + if doc: + doc.DeleteAllViews() + def OnNotebookRightClick(self, event): """ Handles right clicks for the notebook, enabling users to either close @@ -902,9 +934,19 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn): break if not found: self._notebook.SetPageImage(index, self._blankIconIndex) + + # wxBug: the wxListbook used on Mac needs its tabs list resized + # whenever a new tab is added, but the only way to do this is + # to resize the entire control + if wx.Platform == "__WXMAC__": + content_size = self._notebook.GetSize() + self._notebook.SetSize((content_size.x+2, -1)) + self._notebook.SetSize((content_size.x, -1)) + self._notebook.Layout() + def RemoveNotebookPage(self, panel): """ Removes a document page from the notebook. @@ -925,7 +967,7 @@ class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn): def GetNotebookPageTitle(self, panel): - self._notebook.GetPageText(self.GetNotebookPageIndex(panel)) + return self._notebook.GetPageText(self.GetNotebookPageIndex(panel)) def SetNotebookPageTitle(self, panel, title): @@ -1296,7 +1338,7 @@ class DocOptionsService(DocService): DocService.__init__(self) self.ClearOptionsPanels() self._supportedModes = supportedModes - self._toolOptionsID = wx.NewId() + self._toolOptionsID = wx.ID_PREFERENCES if showGeneralOptions: self.AddOptionsPanel(GeneralOptionsPanel) @@ -1370,6 +1412,7 @@ class DocOptionsService(DocService): if len(self._optionsPanels) == 0: return optionsDialog = OptionsDialog(wx.GetApp().GetTopWindow(), self._optionsPanels, self._docManager) + optionsDialog.CenterOnParent() if optionsDialog.ShowModal() == wx.ID_OK: optionsDialog.OnOK(optionsDialog) # wxBug: wxDialog should be calling this automatically but doesn't optionsDialog.Destroy() @@ -1386,8 +1429,8 @@ class OptionsDialog(wx.Dialog): """ Initializes the options dialog with a notebook page that contains new instances of the passed optionsPanelClasses. - """ - wx.Dialog.__init__(self, parent, -1, _("Options"), size = (570, 365)) + """ + wx.Dialog.__init__(self, parent, -1, _("Options")) self._optionsPanels = [] self._docManager = docManager @@ -1397,16 +1440,54 @@ class OptionsDialog(wx.Dialog): sizer = wx.BoxSizer(wx.VERTICAL) - optionsNotebook = wx.Notebook(self, -1, size=(560, 325)) + if wx.Platform == "__WXMAC__": + optionsNotebook = wx.Listbook(self, wx.NewId(), style=wx.LB_DEFAULT) + else: + optionsNotebook = wx.Notebook(self, wx.NewId(), style=wx.NB_MULTILINE) # NB_MULTILINE is windows platform only sizer.Add(optionsNotebook, 0, wx.ALL | wx.EXPAND, SPACE) - for optionsPanelClass in optionsPanelClasses: - optionsPanel = optionsPanelClass(optionsNotebook, -1) - self._optionsPanels.append(optionsPanel) + + if wx.Platform == "__WXMAC__": + iconList = wx.ImageList(16, 16, initialCount = len(optionsPanelClasses)) + self._iconIndexLookup = [] + + for optionsPanelClass in optionsPanelClasses: + optionsPanel = optionsPanelClass(optionsNotebook, -1) + self._optionsPanels.append(optionsPanel) + + # We need to populate the image list before setting notebook images + if hasattr(optionsPanel, "GetIcon"): + icon = optionsPanel.GetIcon() + else: + icon = None + if icon: + if icon.GetHeight() != 16 or icon.GetWidth() != 16: + icon.SetHeight(16) + icon.SetWidth(16) + if wx.GetApp().GetDebug(): + print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName + iconIndex = iconList.AddIcon(icon) + self._iconIndexLookup.append((optionsPanel, iconIndex)) + + else: + # use -1 to represent that this panel has no icon + self._iconIndexLookup.append((optionsPanel, -1)) + + optionsNotebook.AssignImageList(iconList) + + # Add icons to notebook + for index in range(0, len(optionsPanelClasses)-1): + iconIndex = self._iconIndexLookup[index][1] + if iconIndex >= 0: + optionsNotebook.SetPageImage(index, iconIndex) + else: + for optionsPanelClass in optionsPanelClasses: + optionsPanel = optionsPanelClass(optionsNotebook, -1) + self._optionsPanels.append(optionsPanel) + sizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE) self.SetSizer(sizer) self.Layout() - if wx.Platform != '__WXMAC__' or len(optionsPanelClasses) < 6: # wxBug: Notebook tabs are truncated and user can't get to them on the Mac - self.Fit() + self.Fit() wx.CallAfter(self.DoRefresh) @@ -1512,6 +1593,11 @@ class GeneralOptionsPanel(wx.Panel): config.WriteInt("UseWinMDI", (self._documentRadioBox.GetStringSelection() == self._winMdiChoice)) + def GetIcon(self): + """ Return icon for options panel on the Mac. """ + return wx.GetApp().GetDefaultIcon() + + class DocApp(wx.PySimpleApp): """ The DocApp class serves as the base class for pydocview applications and offers @@ -1587,7 +1673,16 @@ class DocApp(wx.PySimpleApp): frame = wx.lib.pydocview.DocMDIParentFrame(docManager, None, -1, self.GetAppName()) frame.Show(True) - + def MacOpenFile(self, filename): + self.GetDocumentManager().CreateDocument(os.path.normpath(filename), wx.lib.docview.DOC_SILENT) + + # force display of running app + topWindow = wx.GetApp().GetTopWindow() + if topWindow.IsIconized(): + topWindow.Iconize(False) + else: + topWindow.Raise() + def DoBackgroundListenAndLoad(self): """ Open any files specified in the given command line argument passed in via shared memory @@ -1602,7 +1697,7 @@ class DocApp(wx.PySimpleApp): self._sharedMemory.flush() args = pickle.loads(data) for arg in args: - if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg): + if (wx.Platform != "__WXMSW__" or arg[0] != "/") and arg[0] != '-' and os.path.exists(arg): self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT) # force display of running app @@ -1623,7 +1718,7 @@ class DocApp(wx.PySimpleApp): """ args = sys.argv[1:] for arg in args: - if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg): + if (wx.Platform != "__WXMSW__" or arg[0] != "/") and arg[0] != '-' and os.path.exists(arg): self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT) @@ -2022,7 +2117,7 @@ class DocApp(wx.PySimpleApp): splash_bmp = image else: splash_bmp = wx.Image(image).ConvertToBitmap() - self._splash = wx.SplashScreen(splash_bmp,wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_NO_TIMEOUT,0, None, -1) + self._splash = wx.SplashScreen(splash_bmp, wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_NO_TIMEOUT, 0, None, -1, style=wx.SIMPLE_BORDER|wx.FRAME_NO_TASKBAR) self._splash.Show() @@ -2351,7 +2446,7 @@ class AboutService(DocService): dlg = self._dlg(wx.GetApp().GetTopWindow(), self._image) else: dlg = self._dlg(wx.GetApp().GetTopWindow()) - dlg.CenterOnScreen() + dlg.CenterOnParent() dlg.ShowModal() dlg.Destroy() @@ -2384,7 +2479,6 @@ class AboutDialog(wx.Dialog): sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5) self.SetSizer(sizer) - self.SetAutoLayout(True) sizer.Fit(self) @@ -2457,6 +2551,7 @@ class FilePropertiesService(DocService): filename = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename() filePropertiesDialog = FilePropertiesDialog(wx.GetApp().GetTopWindow(), filename) + filePropertiesDialog.CenterOnParent() if filePropertiesDialog.ShowModal() == wx.ID_OK: pass # Handle OK filePropertiesDialog.Destroy() @@ -2928,13 +3023,20 @@ import cStringIO #---------------------------------------------------------------------- def getNewData(): return \ -'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00[IDAT8\x8d\xed\x93\xb1\n\x001\x08C\x13{\xff\xff\xc7mn\xb8El\x91\x16\ -\x97\x0e\x97M\x90\x97\x88JZCE\x8f/4\xba\xb2fZc\n\x00\x00i\xcd \t\x8d\xae\x08\ -\xb1\xad\x9c\x0e\x1eS\x1e\x01\xc8\xcf\xdcC\xa6\x112\xf7\x08:N\xb0\xd2\x0f\ -\xb8\x010\xdd\x81\xdf\xf1\x8eX\xfd\xc6\xf2\x08/D\xbd\x19(\xc8\xa5\xd9\xfa\ -\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x01\x04IDAT8\x8d\xa5\x93\xbdj\x02A\x10\xc7\x7f{gme\xe5c\xe4\t\x82\x85\ +\x85\x85oa\xe5+\xd8Z\xd8'e\xfa\x80\xd8\xd8X\x19R\xc4\x07\x90\x04\xd1J\x08\ +\x17\x0cr\\V\xe1\xe4\xfc\x80\xb58\xf7\xd8\xbd\x0f\xa280\xec\xec2\xbf\xff\xce\ +\xcc\xb2B8.\xf7X\xc9\xdc|L\x97J\xc7\xbe\x0c\x01\xf0\xd6\x01\x00RFtZu\x91Q\ +\x10\x8e\x9b\xf8\xe4\xf3[-w*\xf1\xafm\xec\xcf\x83\x89\x1a\xad\x94\xea\xbe\ +\x8c\x95\x99/\x1c\x17\xe7\xdaR\xcb%xh\xd4hw_\x95yn\xb5\xe0\xcb\x90\xea%\x0eO\ +\xf1\xba\xd9\xc7\xe5\xbf\x0f\xdfX]\xda)\x140A\r\x03<6klO\xf0w\x84~\xef\xc9\ +\xca/lA\xc3@\x02\xe7\x99U\x81\xb7\x0e\xa8\xec\xed\x04\x13\xde\x1c\xfe\x11\ +\x902\xb2@\xc8\xc2\x8b\xd9\xbcX\xc0\x045\xac\xc1 Jg\xe6\x08\xe8)\xa7o\xd5\ +\xb0\xbf\xcb\nd\x86x\x0b\x9c+p\x0b\x0c\xa9\x16~\xbc_\xeb\x9d\xd3\x03\xcb3q\ +\xefo\xbc\xfa/\x14\xd9\x19\x1f\xfb\x8aa\x87\xf2\xf7\x16\x00\x00\x00\x00IEND\ +\xaeB`\x82" def getNewBitmap(): return BitmapFromImage(getNewImage()) @@ -2948,13 +3050,21 @@ def getOpenData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00\x95IDAT8\x8d\xa5\x92\xc1\x12\x03!\x08C\x13\xec\x87\xfb\xe3B\x0f.]\ -\xb0\x8e[m.\xea\x0c/\x06\x06R\n\xfe\xd1\xeb\xd7B\xd5f~\x17)\xdc2Pm\x16!\x7f\ -\xab6\xe3i\x0b\x9e\xe8\x93\xc0BD\x86\xdfV0\x00\x90R`\xda\xcc\x0c\x00\x0c\x00\ -\xc1\x05>\x9a\x87\x19t\x180\x981\xbd\xfd\xe4\xc4Y\x82\xf7\x14\xca\xe7\xb7\ -\xa6\t\xee6\x1c\xba\xe18\xab\xc1 \xc3\xb5N?L\xaa5\xb5\xd0\x8dw`JaJ\xb0\x0b\ -\x03!\xc1\t\xdc\xb9k\x0f\x9e\xd1\x0b\x18\xf6\xe0x\x95]\xf2\\\xb2\xd6\x1b}\ -\x14BL\xb9{t\xc7\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x01gIDAT8\x8d\xa5\x93=KBQ\x18\xc7\x7fWo)5\x1594DC\x04!\xd1\x0bM-\xd1\ +\xd0T\x81\xba\xb7\xf8\x01Z\x9a\xdb\xfa\x08AC\x10\x0e\xb5\x86\xbaDC`CMaN\xd9\ +\x0bQF7\xe2z\xc1kz\xcd\xc4\x97\xd3\xa0\xde\xbc\\oE\xfd\xa7s\xce\xf3\xfc\x7f\ +\xe7y\xce\x8b$\xb9\xdc\xfcG2@\xf1bC\x00\x18%\xcd\x12\x1c^\xdc\x97~\x04\x18\ +\xe7K\xa2of\x05\x80\xfe\x8e@\xc3\xc8\xf2zJ\x13\xac+\xe6\xfax(a\x81\xca\xa2w\ +\x8a\x86\x91\x85\xaanE\xf7\x0c\xe0\xf3\xcf\x03P}|3\x97\x93\x11U\xcc\x85\xd3&\ +D\xee\xf4\x88\xb2\xfa5)\xab(\x99"\x00\xb9\x87c\x0b;\x19\xf1\x0b\x80\xb9pZ\ +\xb2\x00\x00\xd3T\xcb\xa5\x00(\xe4Uf\xd7\xb6m\xbd\xa7\x0e\xd6\x89\xc7\xa2\ +\xc2\x04<_\xdf\xe3\x15\x1a\xb5V\xbfc\xab\x9b6S7\xc9FIC\xbf\xcb\xe0\x15\x1a\ +\xbe\xe9e|\xad@C\xbfu4\x9d\xecnQ\x99\xdci\x02\x00\xea\x1f\x1a\x15]a\xa8pcK\ +\xae\xbf?9\x82\x02\xc1\x90$\x1b\xba\x82<\xe8\xeb\x9a\\\xcb)\xdd|\x14r\x15<\ +\xad\xb1\xab\x99\x98bdb\xd4q\xa7\xefd\xbb\x05\xa7\xdd\x8f\x0e/\x9d\x01\x85\ +\xbc\nX+8K\\\x99\xe5\x02x\x16\xf6\xba\x02$\xc9\xe56\x1fF[\xda\x8bn\x9er\xa7\ +\x02\xc1\x90\xedoH\xed\xdf\x18\x8fE\xc5o\x0c\x8e\x80\xbf\xea\x13\xa8\x18\x89\ +5\xe7L\xb3:\x00\x00\x00\x00IEND\xaeB`\x82' def getOpenBitmap(): return BitmapFromImage(getOpenImage()) @@ -2968,13 +3078,20 @@ def getCopyData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00\x9fIDAT8\x8d\xa5\x93\xdb\x0e\x830\x0cC\xed\x84\xdfF\xeb\xb4\xef\xa6\ -\xde\x030z\t\x94\tK\x91z\xcb\x01\xbb*i\x8e\'\x9a\x00@yQ\xb4Is\x8e\x00\xb6\ -\x0f$Uu\x05\x0e\x01\x91$\r!\xa49\x94\x17I\x02\xc9_\xe3:Nq\x93}XL|\xeb\xe9\ -\x05\xa4p\rH\xa29h^[ Y\xd5\xb9\xb5\x17\x94gu\x19DA\x96\xe0c\xfe^\xcf\xe7Y\ -\x95\x05\x00M\xf5\x16Z;\x7f\xfdAd\xcf\xee\x1cj\xc1%|\xdan"LL\x19\xda\xe1}\ -\x90:\x00#\x95_l5\x04\xec\x89\x9f\xef?|\x8d\x97o\xe1\x8e\xbeJ\xfc\xb1\xde\ -\xea\xf8\xb9\xc4\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x01_IDAT8\x8d\x8d\x92\xbfK\x02a\x18\xc7?w\xfa\'\xd8\xd0\xa0\xe4v\xd0$M\ +\x8dB\x11\x11\xa5B\x7f@C\xd0RC{k8E\x834\xb45\n\x15\xfd\x80hhh\xd2\xadI\x82\ +\xa4!\xb8\x84\xca\xd4;\xa5\xf2R\xe1m\xd0\xfb\xf5^\x1e~\xe1\xe5^\x9e{\xbe\x9f\ +\xf7\xfb\xbcwJ\xa9\xa2\x0bFj\x98\xdf\x00\xd4\xea\x06\x00f\xdbbosQ!L\xa5\x8a.\ +\xaa_"\xb0\x8e\xce\xcb\xa2\xfc)\xc4N\xfeT(j\x84\xb1\xabT\xd1E,\x19w\x80\x8d\ +\x97Ww?A"\xd5n\xf2*\x96\x8c\x13K\xc6\xd1R\x1aZJcai\x1e\x80\xf4j\x9a\xed\xfd\ +\xa2\xf0\x01B\xe7\x1b\xa9\xd9\x1d>;\x03X\xd9X\xf7AToC\xb3\xeb\xc6\x96e\xb6-\ +\x1en\xef\xb999\x03\xe0\xea\xf2B\x00Dku\x83)\xcd\x85\x8c;}n9\r\x80\xd1\x87b\ +\xbe\x00\xb33\xc3\x04f\xdbr\x9a;\x03\xbfI\x86\x1a\xfd\xe0\x01\xaam\xec\x0c\ +\x86\r\xf6\x8d{\xcd\xf6;\x00\xb3\'\x01\xde?\x9a>\xba\x9cH6\xb7,x~\xaa:=Q\x9f\ +\xb9\xe7\x1fE\xae\xb7\\\xb6\x1f\xe0\x8d\x15H$\x99\x1b?\x12@\xd7\xdf\xd0\x0f\ +\nN!\x91\x98\x9e\xd8\x0c\x10\xbd>\xdeU\xeco\np\xf7\xf8\xebK\x14fvF\xc8ds\xce\ +\xff\xbd\xb6u(\xbc\x89\xbc\x17\xf6\x9f\x14E\x8d\x04\x8a\xdeDa\xcads\xca\x1f\ +\x0cI\xd4\xda\x88E\x9d\xc4\x00\x00\x00\x00IEND\xaeB`\x82' def getCopyBitmap(): return BitmapFromImage(getCopyImage()) @@ -2988,13 +3105,22 @@ def getPasteData(): return \ "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00\xa1IDAT8\x8d\xa5\x93\xd9\x0e\xc3 \x0c\x04\xc7\xa6\xbf]\xc5U\xbf\xbb\ -\xd9>$4\\9\xaa\xacd\t\x0c\x1e/H6\xf3\xc4\x1d=FI\xcd\x1f\x95{\xf3d{\x003O]\ -\x01\x80\x94/\x0c\x8a\n\xa0\x01\x8a\x88\xdfaD m\x85y\xdd\xde\xc9\x10/\xc9\ -\xf9\xc0S2\xf3%\xf2\xba\x04\x94\xea\xfe`\xf4\x9c#U\x80\xbd.\x97\x015\xec&\ -\x00@\x9a\xba\x9c\xd9\x0b\x08\xe0\r4\x9fxU\xd2\x84\xe6\xa7N\x1dl\x1dkGe\xee\ -\x14\xd0>\xa3\x85\xfc\xe5`\x08]\x87I}\x84\x8e\x04!\xf3\xb48\x18\r\x8bf4\xea\ -\xde;\xbc9\xce_!\\\\T\xf75'\xd6\x00\x00\x00\x00IEND\xaeB`\x82" +\x00\x01\x90IDAT8\x8d\x8d\x93?H\x02a\x18\x87\x9fSw\xb1\xa9!q\xc8\xb0?B\xd0\ +\x98\x10DS\x10\x98\x82C\xd1\x12\x1a\xcd\rb&\xad\x1a\x144F`[\xd4 hBPKC\x83P\ +\x8b4\xe4\xa9tP\x82\x98\x88`$\x82\x8b\xd8p\xddu\xa7\xa5\xfd\x96{\xbf\xef\xfd\ +\xbd\xcf\xf7~w\xf7\n\x82\xc1\x08@M\xect\xd1(x\x12ef\xcaN./\x11\\\xdc\xd3\xa6\ +pz\x8d\x82\x12\x0b\x82\xc1HM\xect-c\xf7\xaa!\x10\xc9\xe0]rR\xac\xb4\x01\xc8\ +\xe5%\xe2\xbbF5_|\x0c\xa9\x10\x03=\nD2\x00$\xef\x9e\xc9\xe5%ryI\xde?\xe8\xe8\ +|\xe9\xabT\x17\xc0\xd4\x0b\xd8\nl\xa8q\xfd\xa3%\xb7\xd9x\xe1\xad=\xc2q\xba\ +\xc2\x8e\xfbU\xe7\xef\x03\x00\x98m\xd6\xef\xa7\xb23\xc9\xdbm\x06\xfb\x8a\x8f\ +\xe0y\x8a\xc0\xc4\x10\x00\xc0\xcdEB\x8d\x97\xd7}j\xbc\xb0\xe6!~\x99d\xd11\ +\x04\xa0-R$]'\xa84M4\xca\x05p8\x7f\x07\xd4?Z\x98mr\x07\x95\xa6\x9c\xf6o{\xb0\ +\xce\xbb\x00\xb0\x03\xe9\xc3\xd8\xf0+h;x\xf9\xfc\xcb\xd5\x0bh>Pzw1>\x0bg\xa7\ +)]\xaaQ.\x00`\xdb\x0c\x0f\x00hN\xf4o{~=\xf9\xa9\x0eY\xb1\x8awI\xf3\x0ej\x05\ +\xb0\x98\x1f\x00x-\xd5\xb0\xce\xc3\xd1~LW\x98\x15\xab\xccM\x8f\xfe\xaf\x03\ +\x00w0\xccS\xfdgm\xfb\xc3\xd7\xf7++w\xd5\x16\x0f\x92\t\xe4\xe9zN\x86\xbe\xa7\ +1\xaa\xfbLY\xb1:\x10 (\xe3\x0c?\x03\xf2_\xb9W=\xc2\x17\x1c\xf8\x87\x9a\x03\ +\x12\xd7\xb9\x00\x00\x00\x00IEND\xaeB`\x82" def getPasteBitmap(): return BitmapFromImage(getPasteImage()) @@ -3008,11 +3134,19 @@ def getSaveData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00lIDAT8\x8d\xc5\x93\xe1\n\xc0 \x08\x84=\xed\xc1}\xf1\xcd\xfd\x18B\x98\ -mX\x83\x1d\x04\x11\xfayV\x02,\xb4#\xde\xca&\xa2\xe6\x1b;\x0f\xab$\x82\x05\ -\x83\x03U\xbdaf\xe9\xea\x13]\xe5\x16\xa2\xd32\xc0].\x03\xa2Z\x8d\x17\x18\xfd(\xb72\xc2\x06\x00\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x01\x1dIDAT8\x8d\x9d\x93=N\xc3@\x10\x85\xbf\xf5\xa2-\xf1\x11\xa0\x8dC\ +\x8f\x82\xa0\xe5\xa7\xa6\xe2\x04\xb4p\x00\x1a\xfb\x02\x11T\xf4\xa4\xa0\xc1\ +\xc1\\\x01\x90R"\xc5\xa4\x89RD\x14\x04$\xa2@\x01\xb1\x04C\xe1\xc8\xb1`\x1dC^\ +5;?\xef\xcd\x8cv\x94r4\xf1\xc5\xa7P\x82a\xff\xb7o\xfd@+\x94\xa3\xb9o"2\xa8K\ +\x18\x86R\x84\xc1\x87\xc8\xdd\xf3X|\xdf\x17\x11\x91\x9bc$\x8a"q\xf2\x8cZk\ +\xab\xfa\xd3\x18\x1e\xdf\x12\xba\xef\x06\x80\xdb\x13\x95\xc5\x1ckE\t\xd6\xb6\ +\xf7\xec\x04I\x92\x94\xaa\xff\xc4\\\x1d\xf0\xd2\xfd\x1bA\x99:\xc0B\xfe\xb1\ +\xbb\xf1@\x10\x043\xc5\x8f6\xaf\x00\xe8u\xc0]\x9e\x10\x0c\xfb@m\x92\xb0\xbf8\ +\xcd\x1e\xb5\xacm\xdb;\x18\xb5\xc0]%8}\xcd\x85+\x99\xd5\x8e\xbf2\xfb\xfc\xb0\ +g\x1f!U\xac\xe0y^\xe62\xc6p\xd6h\x14\x8e4s\x89\xc6\xa4\xcb[\xa9V\xffG\xa0\ +\xb5\xce\x8a\x97j[\xb4\xe3\xb8\x90@)\'\xfd\xbe\xd7\xf5\xe2\x83\xeau\xec~w\'\ +\x9a\x12\x00\\6\xc3\xd2\xab,\xec`^|\x03\xb6\xdf|Q.\xa7\x15\x89\x00\x00\x00\ +\x00IEND\xaeB`\x82' def getSaveBitmap(): return BitmapFromImage(getSaveImage()) @@ -3026,17 +3160,20 @@ def getSaveAllData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x01\tIDAT8\x8d\xa5\x93\xe1m\x830\x10\x85\xdfA\xd7H\x827\xf0\x02\xado\ -\x04\x8f`Fh\xfb\xb7\xad\xcd&$Y\x80\x11\xcc\x06\x8c\xe0E\xd2\xeb\x8f\x16\x04!\ -8R\xf3\xa4\x93Nw\xd2\xf3\xa7g\x9b\xa8(\xf1\x88\x9er\xcb\xc3~\')%x\xef\xa7Y\ -\x8c\x11J)\x00\xc0\xf1t&PQn\x163\x0b\x00\x99\xcb{/\x00\xc49\'T\x94(\xfe\x83\ -\x1dB\x98\xfa\x95\xc1a\xbf\x13\xf9\xbe\xc8\xd7\xe7\x87\x18c\xe0\xbd\x073\xa3\ -\xaek\x10\x11\xfa\xbe\xcfgPU\x15RJ\x8bSB\x08h\x9af1\xdb$\xc8aw]\x87\xae\xeb\ -\xd6\x04\xd7i\x1bc\xc0\xccPJ\xa1m[03\x98\x19Z\xeb\x951QQ\xc2\xbc\ -\x92\xcb\xbc\xdd\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x01UIDAT8\x8d\x9d\x93\xbfK\xc3@\x1c\xc5\xdf%\x01g\xeb \x1d\x8a\x8b\x83M\ +\x11\xe9\x16\x8a\x8b\xff@\xa0\xdd\x14\'\x17\x17A2\xe9,\x08\xc9\x14\x82n.nn\ +\x9a\xde?\xe0R;\xb88\x99v\xe8`\x86\n."\x81\xb6\xb4\xb4~\x1d\xd2\xc4^\x92j\ +\xf5\x03\xc7\xfd~\xf7\xeeq\xc7<\x17\x84)\xa3\x1e\x04\x863\xfd\xf10\xac\xb7\ +\x8fe&,\xf2\\\x10\xf9\x06q\xce)I\x7fL\xf4\xda\'2M\x93\x88\x88\x1e.@\x9csb\ +\x92\x8c\xb8x.\xa8X6\xd0z\xb2c\xd1?9\x89\x1c\xfc\xd7\x89\x82\x04\xeb\x9f:Z\ +\xf5l\';9\xe0\xf1\xea\x14\xca\x12\xb0\xe2\xebh8 ))\x00\x00\xc5\xb2\x81\x8e\ +\xc4\xb1\xb5GB\xd9< \x14\xf6\t\xf7\xef&*Ga\xf6\x99\x02Y\x0c&\xc0\xc7\x08x\ +\xe9\x01A\x10\xa0y\xc9\x16\x17\x98\xdd\x1cQ\xd1\x8d\x9f\x05<\xcf\x136\xcf#\ +\x15b\xc4\xc9\xee\x1b,\xcb\x8a\xfbA\x10\xc4\xed\xf3\xc3\x01\x00\xc0o\x03J\ +\xa9&\xb3\x86c\xd3r![\xe47\x14 |\x14\xcf\xb7\x13JNZ7\xab\xc2\xe9\xddn7\x9e\ +\xbb>\xcb\x01\x98\xc9\xa0T\x93Y\x93\xdbH\xa2\xaa*4MC\xb5Z\xcdt \x84\x98\xfa(\ +S\xf2\xf9\xfc\xdc+0&\xc9\xa9\xc1\x86\xf3}\x1d\xbf\r\xacm\x84\xf5\xc2\x02\x00\ +Pw\xefR\x99d\xf1\x05z\x94\xd0b\xcb S\xf3\x00\x00\x00\x00IEND\xaeB`\x82' def getSaveAllBitmap(): return BitmapFromImage(getSaveAllImage()) @@ -3048,16 +3185,25 @@ def getSaveAllImage(): #---------------------------------------------------------------------- def getPrintData(): return \ -"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00\xa1IDAT8\x8d\xa5S[\x0e\x02!\x0c\xec\xd0\xbd\xb6\x1a\xf5\xda\x96\xd9\ -\x0f\xa1V\x96\x00\xbaMHI\xd3y\xf0(\x90T\xce\xc4\xd6+2\x1bg@$E\x97\x80\xd9H\ -\x8e\xf1\x00\xc6\x0e\xda&''\x05\x80\xab\x1f\x08\xa2\xfa\xcc\xc5\xd0\xc1H\xbd\ -\n\x89\xbc\xef\xc1\tV\xd5\x91\x14\xcc\xc6\x9a\xa5<#WV\xed\x8d\x18\x94\xc2\ -\xd1s'\xa2\xb2\xe7\xc2\xf4STAf\xe3\x16\x0bm\xdc\xae\x17'\xbf?\x9e\x0e\x8an\ -\x86G\xc8\xf6\xf9\x91I\xf5\x8b\xa0\n\xff}\x04w\x80\xa4ng\x06l/QD\x04u\x1aW\ -\x06(:\xf0\xfd\x99q\xce\xf6\xe2\x0e\xa5\xa2~.\x00=\xb5t\x00\x00\x00\x00IEND\ -\xaeB`\x82" +\x00\x01\xa7IDAT8\x8d\xa5S=K\xc3P\x14=\xef\xb5 \x0e\xf6\x17\xb8$X\x10\xa7\ +\x82\xb4\n]\x05A\x07\xebd%\xfe\x02\x97\x82\xe0\xa0\x83\xa3\x88\xb5E\xfd\x07j\ +\x0bq\xea\x07\x18(8:5\x16\xa2H\xf1\x8bN\x12\tt\xe9\x8b\xddZ\x9eC|i\x93\xd4\ +\x0f\xf0\xc0\xe1\xe6\xbe\xdc{\xde\xb9\xc9{\x84\xd0\x10\xfe\x83\xb0x8m\xf6\ +\xb8i\xf7=/\xfb\xad\x07O\x9e]\x9f%\x01\x05BC 4\x84\x1d\xbd\xc7\xfdx\xb2\x1d^\ +\x99\x9c\x1f\xe6\x8ey\xb5Z\xe5\xa2^\x90\n\xa1\x83\xb91\xb2{;p\xf0\xfc\xe1\ +\xc4W\xdb\x89\xe3\xcb\x19\xa8\xaa\x8aJ\xb9\xc4\x87\r\xd0\xe1\xc4o\xf9/\x08\ +\x03\xc0\xc5\xf9\x19\x07\x80\xfb\xaf\x9d\xc5\xae-6(4\xed>\x9aoA\x01zq~\xc6\ +\x15E\x81\xa2(\xee\xe2\xd4\x84\x13\xe5H\xb0\xc1?\x06\x05\x80b\xb1\xe8\x16\ +\xbc\xda\x0e[\xcc\xa1i\xf71\xfcw\xf2\xf9\xbcG\x84\x14\n\x05\x1e\x8b\xc5\xa0\ +\xd5\xae\xb1\xbd\x95\x81eY#gm\xb7\xdb\x9e|cs\x1fw7\x97$lZm\xc4\x00,-. \x9b?\ +\xc1tT\x1e)\xc0\x18C$\x12\x01c\xce\x87\xe9\xbe\xeb\xa8\x94K\x9cNGeh\xb5k\x00\ +\x80\xd1\xa8#\x91H@\x96\xe5\x00%I\xc2\xe3K\x0b\x9a\xa6A\x92$W8\xbc\x92Z%\xeb\ +\xe95n4\xea\x01\xab\x9dN\xc7\xe3"9\x1fGr>\xeeYs\x8fr:\x9d\x06c\x0c\x86ax\nL\ +\xcb;\xbb\x1f\x84\xd0\x10*\xe5\x12WU\x15\xcd7`f\xf2\xc7z\x00\x80\xae\xeb\xc8\ +\xe5rXI\xad\x12"nc\xa5\\\xe2{G*\xba\xef\xfa\xaf\x02\xa2\xd9u \xe0?\xe7\xdfA4\ +\x03\xc0\'\xe3\x82\xc9\x18g\x90\x8e]\x00\x00\x00\x00IEND\xaeB`\x82' def getPrintBitmap(): return BitmapFromImage(getPrintImage()) @@ -3071,14 +3217,20 @@ def getPrintPreviewData(): return \ '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00\xa8IDAT8\x8d\x9d\x93K\x0e\xc30\x08Dg \xd7n\xcd\xc1\x9b\xd2E\x83E\\\ -\xffT$/\x82\xc5\x83\x19\x13\x02p,\x82\xa2\x1c\xde\x01p\xf71\x83\xe4\x14"\xab\ -\xeeQ\xec\xef\xb3\xdbe{\x82\x0c\xcb\xdf\xc7\xaa{\x86\xb7\xb0-@\xaf(\xc7\xd4\ -\x03\x9203P\x94\x14\xa5\x99\xa1\xf5b\x08\x88b+\x05~\xbejQ\x0f\xe2\xbd\x00\ -\xe0\x14\x05\xdc\x9d\xa2\xa0(\xcc\xec\x9b\xbb\xee(\xba~F\xea15a\n(\xcfG\x1d5\ -d\xe4\xdcTB\xc8\x88\xb1CB\x9b\x9b\x02\x02\x92O@\xaa\x0fXl\xe2\xcd\x0f\xf2g\ -\xad\x89\x8d\xbf\xf1\x06\xb9V9 \x0c\x1d\xff\xc6\x07\x8aF\x9e\x04\x12\xb5\xf9\ -O\x00\x00\x00\x00IEND\xaeB`\x82' +\x00\x01mIDAT8\x8d\x8d\x92\xbdK\x02a\x1c\xc7?w\x1a\x85E\x04588XHa\xd1\x14!AB\ +\r.\xbd\x07m-By.M\xfe\x03N\x05\x0e\xed\xf9\x124\x045\x04\x15\xdc\xda&4\xb5DC\ +J\x8a\x81E\t.\x82\x918\xd8\xf0pOw\xde\x19}\xe1\xe1w\xf7;>\xdf\xdf\xcbs\xca\ +\xddC\xb9C\x97\x1e\x8bU\xf9\x9c\xd8]V\xba\xbf\x9b\xa5\x02\xf8\xa6\xc6-ge=\ +\x0c@p)\xcc\xc1\xe1\xa5\xad\x80\xcd\xa0\x97\x86\xfb`5\xba\xf3\xa7\x89\xdb)Y\ +\xff\x16\xf1"{%s\xb77\xd7\x9d\xcd\xadm\xdb86\x03\x03\x0eE\xc2\x04\xdbPk\xc1y\ +2Edf\xday\x84\xe6\xdb\x93\x84\x8c\xd8h\x8bSk\xf5j\xdcdPj\x8eX`C\x06\x9c?\x8a\ +\xe3\xef/\xa3\xeb:\xb1\xfd=\xdb.,#4\xdav\x18-m\x01b\xd0\xc9\xe6N\xe5.Ts\xcbN\ +pz\x0e\xa2~\x91\x0bx\x00-m\xe9D-W>%h\xc0\x1f_\xbf\x15\xef\xeb\x90\xaf\xc1\ +\xe2\x18x="\x82\xb8\x15\xd9\x81yYf\x18\xe0\xac"\xc0\xc0\x10\x84\xc6D4\xcb\ +\xf2#u\xc3\xb2m`t\x00&\x07E4\xcb]x.QH\xa6\xec$\x13\xf83q^\xb44^\x8f\xb8\xa5"\ +p\x9c\x88\xa3\x91\xe1\x9d5\x00\x14Eu\xc9y\x9c\xa4\xeb\xba\xe5}\xb6\x9a\x01`\ +\xc1\x07\xf39\x97\xa2(\xaa\xab\x17+\xd5]\xe0\xf5dC\x9a\xfc\xcb\xc0\xc9\xd00\ +\xf9\x011\xc9\x87\xf3\xb4\xd1t\xaf\x00\x00\x00\x00IEND\xaeB`\x82' def getPrintPreviewBitmap(): return BitmapFromImage(getPrintPreviewImage()) @@ -3090,13 +3242,22 @@ def getPrintPreviewImage(): #---------------------------------------------------------------------- def getCutData(): return \ -"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ +'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00rIDAT8\x8d\xad\x93\xc1\x0e\xc0 \x08CW\xdco{\xf2\xbb';\xb18\x07\x9d\ -\x0b\xe3\xa2\x98\xe6\xb5$\x02H\xd92%\xde\xa3\xf6CY\xff\nH'\xf8\x05`\xb1Y\xfc\ -\x10\x00)`\xfdR\x82\x15w\n0W\xe6N\x01\xda\xab\x8e\xe7g\xc0\xe8\xae\xbdj\x04\ -\xda#\xe7;\xa8] \xbb\xbb\tL0\x8bX\xa5?\xd2c\x84\xb9 \r6\x96\x97\x0c\xf362\ -\xb1k\x90]\xe7\x13\x85\xca7&\xcf\xda\xcdU\x00\x00\x00\x00IEND\xaeB`\x82" +\x00\x01HIDAT8\x8d\x85\x92OK\x02Q\x14\xc5\x7f\xa3\x05}\x1b\xa1\xc0\x9d\xb4\ +\xaaf6\x93a\x10\xe3^\x83l\xdf\xc6\xa5\x1bIA\xb4\xa0\x9cM\xe5"\x84\x18\xff\ +\x108\xbb\xf0\x93\xb4v\x15h\xa9\xaf\x16\xaf\x85\xbcat^\xd3\x81\xb79\xf7\xdc\ +\xf3\xce{\xf7b$\x92\x84O\xa7\xd3\x91\x9b\\\xf8\xd4\xeb\xb5\xb5z\x02\r\x9e\ +\x1e\x1f\xa4\x8eo5\x1b\x12`\xd0\xef\x05u\xadA.\x97\xc3u\xef\xd7LZ\xcd\x86\ +\xb4\xedlD\xab5\xd0A\x08\xc1l6e>_\xc4\x1b\x88o\x01@\xde\xc9\x07\x91k\xd7Ui\ +\x9a\x96\xd6xk\x93(\x14\xce\r@\x1e\x1e\x1cE\xc4\x9e\xe7\x91J\xa58\xce\x9e\ +\x18\x7f\x1a\x00,\x17\xab\x98\xb6\x9dE\x08!M\xd3\x8aDW0\x8cDR[P\xb1U\xa3\xef\ +\x8f"\xb7C\xcc\'\xee\xbdw\xf1\x10\x80\x1fC[\x9eH\x05UH\x17\xa2r\x13\xac\x9d_Pq\x8f\x01(96\ +\xdf\x16\xd7X\xff\xb8\xaf\x02\x05\x066\xa0+5\xe6\xb3\x0b\x1c\xeeW\x00x\xd1\ +\xf3\x14\x80\xaf\x93\xbf\xd8\xcb\xb8\xeaN\x05\xd3\xd7\xbc\x9a\xd1\xdf\x19\ +\x8cL@\xa4~\x9f\x9a\xec\xa3\xb3\xa7\r\x80|.+>\xc1\xfb\xd5\xe72\xf0\xf2-U\xa7\ +\xec\x83c\xf1\x84\xd79\x9f\xcbJj\xa9/\xf8\x13\xcb\xe7U.\xaf\xcep\xa5\x06P\ +\x8f\x1d\xf1'\x8c\xc5\x13*\x9f\xcb\x8a'\xe8_l\x17\x80\xe57\x1b\xea\xd4\xae\ +\xc7w\xfe9\x94\x1c\xdb\x83\x1e\x0f4\t\xc0^\xc6UFb\xee\xacS\xdba\xf8\xd5\x08\ +\xdd\xd3O\xc4t7\xab\xb8m\x93Z\xf2w\xbe\xfdgJk-\xb3\xc5\x11\xc6\xde\x8dS\x95\ +\x8a\xd7\xbf\xe4\xd8\xec\x9c\xecr\xb2Sfm\xf9\x0f3\xc9\x15\xdf\xcb^\x82X<\xa1\ +\x06#\x13\x0c}\x1a\x06 \xdc\xfc\xc87\xf0?\xb8\x1e\xc1\n\xa1\xac\x10Zk\xe9\ +\x18k\x95\x9fGS\xf2\xa58*\x9f7S\xd2\x92\x0c\x8b\xd6Z\xccL\xd0\xf6\x1d\xb4\ +\xd6\xd2\x92\x0c\xcb\xea\xdf\x0f\r\xc1w\x047%\x8d\xc0\x81\x02#i\x04VV\x88k\ +\x82\xbe\xde\xc2\xb0\xb2\xea\xa7\x00\x00\x00\x00IEND\xaeB`\x82" def getUndoBitmap(): return BitmapFromImage(getUndoImage()) @@ -3129,12 +3302,22 @@ def getRedoData(): return \ "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\ \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\ -\x00\x00jIDAT8\x8d\xed\x92\xcd\n\xc0 \x0c\x83\x9bv\xaf\xed\x16\xf0\xbd\xd7]&\ -\xf8\x8f\xe0e\x87\t9$\xb6\x1f\xb5\x08\xa8\xc9\xce\xd1\xad\xeeO\x00\x8e\xdc\\\ -gp\xb2,\x80FL\tP\x13\xa8\tI\x17\xa1'\x9f$\xd2\xe6\xb9\xef\x86=\xa5\xfb\x1a\ -\xb8\xbc\x03h\x84\xdf\xc1\xeb|\x19\xd0k.\x00\xe4\xb8h\x94\xbf\xa3\x95\xef$\ -\xe7\xbbh\xf4\x7f\xe5}\xc0\x03&\x1b&\xe5\xc2\x03!\xa6\x00\x00\x00\x00IEND\ -\xaeB`\x82" +\x00\x01\x88IDAT8\x8d\xa5\x92\xc1K\x02A\x14\xc6\xbfQ\t\xbc\x14tJ\xfb\x0f2\ +\x08\xbaD\xdd:\xe5!\xd2\xad$/\x82FP\x06\x99\x87\x04\xa1\x83D\x10\x0b\x85\xd4\ +\xa9\x8c (\x82<\xad\xce\xa9\xff\xc0[\xd2)\xbcu\t\xb2\xd0\xa5\xb5\x94\x14z\ +\x1dd\x87]\x1bBh\xe0\xc1\xf0\xde\xfb~3\xef\x9ba\xcc\xe1\xc4\x7f\x96K\x96\xdc\ +\xd6\xfcd\xeeO\x94;\xd67\xc0\x14Fg\xd7E\xae~\xa5S\xe3\xd3@!\xfe(\x051s\x84m\ +\xcdOV!\x004\xbf\r\x00\x80\xde\xae\xe2B\xbb\x94B\\\x00\x10\xb9\x9a\x12\xe2,W\ +Eqc~S\xec\xd7\x94\x18\xaa\xafY*e^l\x10\x87\xf5\xb4,W\xb1<\x98\x16q\x98W\xa1\ +\xb7\xab\x00\x80F\xa7\x0e\x00(\x164\xb2\x02\xc0\x1cN(\xb9qRr\xe3\xc49'\xe6p\ +\xc2\x1a3\xfb\xa3t\xfb\xbcK\xe7O[\xa4V\xc2\xe4K\x0e\xdb\xfa\\\x00\x10\xf3\ +\x1c\x00\x00\x02AEj\x94\xd11P\xffz\x93\x95\xba\x80^\xe1\xf4\xde\x08\x01@)\ +\xf3\xc2\xdek-!\xae5u\xe8\xcf-\x00\x80gi\x80l\x1e\xf4\xae\xc4j\x14c\x89!1o\ +\xad\xa9\x8b\xda\xc6\xf5\n\x16v&\xbb\x16\xc8~b\xb1\xa0\x91\xfa\x10G4\xb2h;\ +\xbd\xd1\xfe\x10=\xfc\xe8\x1eg\x91\xbc\xfc\x06\x81\xa0\xc2\xd2\x13\xa789\xbe\ +\x91\xde\xce\x14\x07\x82\nC\xaf\xeb\xd6\xe0\x9c\x93/9Lj%L\xa9\xf2\x1c\xa5\ +\xcas\xe4\r\xb9m\xaf\xf0'\xc0\x84xCnR+\xe1_\xe2\xbe\x00V\x88\xec\x9f\xf4\x05\ +0!\xb2\xfc\x0f\xe0\xc4\xb6\xad\x97R\xe5z\x00\x00\x00\x00IEND\xaeB`\x82" def getRedoBitmap(): return BitmapFromImage(getRedoImage()) diff --git a/wxPython/wx/lib/throbber.py b/wxPython/wx/lib/throbber.py index 5a5b073f3f..2812cdd969 100644 --- a/wxPython/wx/lib/throbber.py +++ b/wxPython/wx/lib/throbber.py @@ -59,7 +59,12 @@ class Throbber(wx.PyPanel): overlay = None, # optional image to overlay on animation reverse = 0, # reverse direction at end of animation style = 0, # window style - name = "throbber"): + name = "throbber", + rest = 0, + current = 0, + direction = 1, + sequence = None + ): wx.PyPanel.__init__(self, parent, id, pos, size, style, name) self.name = name self.label = label @@ -89,8 +94,9 @@ class Throbber(wx.PyPanel): self.labelX = (width - extentX)/2 self.labelY = (height - extentY)/2 self.frameDelay = frameDelay - self.current = 0 - self.direction = 1 + self.rest = rest + self.current = current + self.direction = direction self.autoReverse = reverse self.overlay = overlay if overlay is not None: @@ -116,14 +122,14 @@ class Throbber(wx.PyPanel): # while the throbber is running. self.sequence[0] should always # refer to whatever frame is to be shown when 'resting' and be sure # that no item in self.sequence >= self.frames or < 0!!! - self.sequence = range(self.frames) + self.SetSequence(sequence) self.SetClientSize((width, height)) timerID = wx.NewId() self.timer = wx.Timer(self, timerID) - self.Bind(EVT_UPDATE_THROBBER, self.Rotate) + self.Bind(EVT_UPDATE_THROBBER, self.Update) self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroyWindow) @@ -157,18 +163,21 @@ class Throbber(wx.PyPanel): event.Skip() - def Rotate(self, event): - self.current += self.direction + def Update(self, event): + self.Next() + + + def Wrap(self): if self.current >= len(self.sequence): if self.autoReverse: self.Reverse() self.current = len(self.sequence) - 1 else: - self.current = 1 - if self.current < 1: + self.current = 0 + if self.current < 0: if self.autoReverse: self.Reverse() - self.current = 1 + self.current = 0 else: self.current = len(self.sequence) - 1 self.Draw(wx.ClientDC(self)) @@ -185,7 +194,7 @@ class Throbber(wx.PyPanel): def Rest(self): """Stop the animation and return to frame 0""" self.Stop() - self.current = 0 + self.current = self.rest self.Draw(wx.ClientDC(self)) @@ -213,6 +222,65 @@ class Throbber(wx.PyPanel): self.running = not self.running + def SetCurrent(self, current): + """Set current image""" + running = self.Running() + if not running: + #FIXME: need to make sure value is within range!!! + self.current = current + self.Draw(wx.ClientDC(self)) + + + def SetRest(self, rest): + """Set rest image""" + self.rest = rest + + + def SetSequence(self, sequence = None): + """Order to display images""" + + # self.sequence can be changed, but it's not recommended doing it + # while the throbber is running. self.sequence[0] should always + # refer to whatever frame is to be shown when 'resting' and be sure + # that no item in self.sequence >= self.frames or < 0!!! + + running = self.Running() + self.Stop() + + if sequence is not None: + #FIXME: need to make sure values are within range!!! + self.sequence = sequence + else: + self.sequence = range(self.frames) + + if running: + self.Start() + + + def Increment(self): + """Display next image in sequence""" + self.current += 1 + self.Wrap() + + + def Decrement(self): + """Display previous image in sequence""" + self.current -= 1 + self.Wrap() + + + def Next(self): + """Display next image in sequence according to direction""" + self.current += self.direction + self.Wrap() + + + def Previous(self): + """Display previous image in sequence according to direction""" + self.current -= self.direction + self.Wrap() + + def SetFrameDelay(self, frameDelay = 0.05): """Delay between each frame""" self.frameDelay = frameDelay diff --git a/wxPython/wx/py/CHANGES.txt b/wxPython/wx/py/CHANGES.txt index d92d1ae041..e6929aa727 100644 --- a/wxPython/wx/py/CHANGES.txt +++ b/wxPython/wx/py/CHANGES.txt @@ -1,3 +1,81 @@ +0.9.5 (12/23/2005) +------------------- + +Applied a series of enhancments by Franz Steinaeusler, Adi Sieker, and +Sebastian Haase, up until their 7-31-2005 version. (Their next +version broke some existing functionality, and added some confusing +hacks, and I didn't feel that the incremental gains were worth the +loss at that point so I stopped at 7-31-2005.) + +Their changes include the following: + +* The Autocomplete and Calltip windows can now be opened manually with + Ctrl-Space and Ctrl-Shift-Space. + +* In the stand alone PyCrust app the various option settings, window + size and position, and etc. are saved and restored at the next run. + +* Added a help dialog bound to the F1 key that shows the key bindings. + +* Added a new text completion function that suggests words from the + history. Bound to Shift-Return. + +* F11 will toggle the maximized state of the frame. + +* switched to Bind() from wx.EVT_*(). + +* Display of line numbers can be toggled. + +* F12 toggles a "free edit" mode of the shell buffer. This mode is + useful, for example, if you would like to remove some output or + errors or etc. from the buffer before doing a copy/paste. The free + edit mode is designated by the use of a red, non-flashing caret. + +* Ctrl-H will fold/unfold (hide/show) the selected lines. + + + +On top of these changes I (Robin Dunn) added the following: + +* General code cleanup and fixes. + +* Use wx.StandardPaths to determine the location of the config files. + +* Remove Orbtech attributions from the UI, they've been there long + enough. + +* Use wx.SP_LIVE_UPDATE on crust and filling windows. + +* Extended the saving of the config info and other new features to the + PyShell app too. Additionally, other apps that embed a PyCrust or a + PyShell can pass their own wx.Config object and have the Py code + save/restore its settings to/from there. + +* All of the classes with config info get an opportunity to save/load + their own settings instead of putting all the save/load code in one + place that then has to reach all over the place to do anything. + +* Enable editing of the startup python code, which will either be the + file pointed to by PYTHONSTARTUP or a file in the config dir if + PYTHONSTARTUP is not set in the environment. + +* Added an option to skip the running of the startup code when + PyShell or PyCrust starts. + +* PyCrust adds a pp(item) function to the shell's namespace that + pretty prints the item in the Display tab of the notebook. Added + code to raise that tab when pp() is called. + +* Added an option for whether to insert text for function parameters + when popping up the call tip. + +* Added Find and Find-Next functions that use the wx.FindReplaceDialog. + + + + + + 0.9.4 (1/25/2004 to //2004) ------------------------------ diff --git a/wxPython/wx/py/PyCrust.py b/wxPython/wx/py/PyCrust.py index b9a222763e..95975d0d00 100644 --- a/wxPython/wx/py/PyCrust.py +++ b/wxPython/wx/py/PyCrust.py @@ -17,15 +17,26 @@ class App(wx.App): """PyCrust standalone application.""" def OnInit(self): + import os import wx from wx import py - wx.InitAllImageHandlers() - self.frame = py.crust.CrustFrame() - self.frame.SetSize((800, 600)) + + self.SetAppName("pycrust") + confDir = wx.StandardPaths.Get().GetUserDataDir() + if not os.path.exists(confDir): + os.mkdir(confDir) + fileName = os.path.join(confDir, 'config') + self.config = wx.FileConfig(localFilename=fileName) + self.config.SetRecordDefaults(True) + + self.frame = py.crust.CrustFrame(config=self.config, dataDir=confDir) +## self.frame.startupFileName = os.path.join(confDir,'pycrust_startup') +## self.frame.historyFileName = os.path.join(confDir,'pycrust_history') self.frame.Show() self.SetTopWindow(self.frame) return True - + + ''' The main() function needs to handle being imported, such as with the pycrust script that wxPython installs: diff --git a/wxPython/wx/py/PyShell.py b/wxPython/wx/py/PyShell.py index c800dc4d9c..2af5143ecd 100644 --- a/wxPython/wx/py/PyShell.py +++ b/wxPython/wx/py/PyShell.py @@ -17,14 +17,21 @@ class App(wx.App): """PyShell standalone application.""" def OnInit(self): + import os import wx from wx import py - wx.InitAllImageHandlers() - self.frame = py.shell.ShellFrame() - self.frame.SetSize((750, 525)) + + self.SetAppName("pyshell") + confDir = wx.StandardPaths.Get().GetUserDataDir() + if not os.path.exists(confDir): + os.mkdir(confDir) + fileName = os.path.join(confDir, 'config') + self.config = wx.FileConfig(localFilename=fileName) + self.config.SetRecordDefaults(True) + + self.frame = py.shell.ShellFrame(config=self.config, dataDir=confDir) self.frame.Show() self.SetTopWindow(self.frame) - self.frame.shell.SetFocus() return True ''' diff --git a/wxPython/wx/py/crust.py b/wxPython/wx/py/crust.py index 2a26da1c5c..cd78c8c907 100644 --- a/wxPython/wx/py/crust.py +++ b/wxPython/wx/py/crust.py @@ -8,6 +8,7 @@ import wx import os import pprint +import re import sys import dispatcher @@ -23,55 +24,95 @@ class Crust(wx.SplitterWindow): name = 'Crust' revision = __revision__ + sashoffset = 300 - def __init__(self, parent, id=-1, pos=wx.DefaultPosition, - size=wx.DefaultSize, style=wx.SP_3D, + def __init__(self, parent, id=-1, pos=wx.DefaultPosition, + size=wx.DefaultSize, style=wx.SP_3D|wx.SP_LIVE_UPDATE, name='Crust Window', rootObject=None, rootLabel=None, - rootIsNamespace=True, intro='', locals=None, - InterpClass=None, *args, **kwds): + rootIsNamespace=True, intro='', locals=None, + InterpClass=None, + startupScript=None, execStartupScript=True, + *args, **kwds): """Create Crust instance.""" wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name) - self.shell = Shell(parent=self, introText=intro, - locals=locals, InterpClass=InterpClass, + self.shell = Shell(parent=self, introText=intro, + locals=locals, InterpClass=InterpClass, + startupScript=startupScript, + execStartupScript=execStartupScript, *args, **kwds) self.editor = self.shell if rootObject is None: rootObject = self.shell.interp.locals self.notebook = wx.Notebook(parent=self, id=-1) self.shell.interp.locals['notebook'] = self.notebook - self.filling = Filling(parent=self.notebook, - rootObject=rootObject, - rootLabel=rootLabel, + self.filling = Filling(parent=self.notebook, + rootObject=rootObject, + rootLabel=rootLabel, rootIsNamespace=rootIsNamespace) # Add 'filling' to the interpreter's locals. self.shell.interp.locals['filling'] = self.filling self.notebook.AddPage(page=self.filling, text='Namespace', select=True) + self.display = Display(parent=self.notebook) self.notebook.AddPage(page=self.display, text='Display') # Add 'pp' (pretty print) to the interpreter's locals. self.shell.interp.locals['pp'] = self.display.setItem + self.display.nbTab = self.notebook.GetPageCount()-1 + self.calltip = Calltip(parent=self.notebook) self.notebook.AddPage(page=self.calltip, text='Calltip') + self.sessionlisting = SessionListing(parent=self.notebook) self.notebook.AddPage(page=self.sessionlisting, text='Session') + self.dispatcherlisting = DispatcherListing(parent=self.notebook) self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher') -## from wxd import wx_ -## self.wxdocs = Filling(parent=self.notebook, -## rootObject=wx_, -## rootLabel='wx', -## rootIsNamespace=False, -## static=True) -## self.notebook.AddPage(page=self.wxdocs, text='wxPython Docs') -## from wxd import stc_ -## self.stcdocs = Filling(parent=self.notebook, -## rootObject=stc_.StyledTextCtrl, -## rootLabel='StyledTextCtrl', -## rootIsNamespace=False, -## static=True) -## self.notebook.AddPage(page=self.stcdocs, text='StyledTextCtrl Docs') - self.SplitHorizontally(self.shell, self.notebook, 300) - self.SetMinimumPaneSize(1) + + self.SplitHorizontally(self.shell, self.notebook, -self.sashoffset) + self.SetMinimumPaneSize(100) + + self.Bind(wx.EVT_SIZE, self.SplitterOnSize) + self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnChanged) + + + def OnChanged(self, event): + """update sash offset from the bottom of the window""" + self.sashoffset = self.GetSize().height - event.GetSashPosition() + event.Skip() + + + # Make the splitter expand the top window when resized + def SplitterOnSize(self, event): + splitter = event.GetEventObject() + sz = splitter.GetSize() + splitter.SetSashPosition(sz.height - self.sashoffset, True) + event.Skip() + + + def LoadSettings(self, config): + self.shell.LoadSettings(config) + self.filling.LoadSettings(config) + + pos = config.ReadInt('Sash/CrustPos', 400) + wx.CallAfter(self.SetSashPosition, pos) + def _updateSashPosValue(): + sz = self.GetSize() + self.sashoffset = sz.height - self.GetSashPosition() + wx.CallAfter(_updateSashPosValue) + zoom = config.ReadInt('View/Zoom/Display', -99) + if zoom != -99: + self.display.SetZoom(zoom) + + + def SaveSettings(self, config): + self.shell.SaveSettings(config) + self.filling.SaveSettings(config) + + config.WriteInt('Sash/CrustPos', self.GetSashPosition()) + config.WriteInt('View/Zoom/Display', self.display.GetZoom()) + + + class Display(editwindow.EditWindow): @@ -105,15 +146,20 @@ class Display(editwindow.EditWindow): """Set item to pretty print in the notebook Display tab.""" self.item = item self.Refresh() + if self.GetParent().GetSelection() != self.nbTab: + focus = wx.Window.FindFocus() + self.GetParent().SetSelection(self.nbTab) + wx.CallAfter(focus.SetFocus) + - +# TODO: Switch this to a editwindow.EditWindow class Calltip(wx.TextCtrl): """Text control containing the most recent shell calltip.""" def __init__(self, parent=None, id=-1): style = (wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH2) wx.TextCtrl.__init__(self, parent, id, style=style) - self.SetBackgroundColour(wx.Colour(255, 255, 232)) + self.SetBackgroundColour(wx.Colour(255, 255, 208)) dispatcher.connect(receiver=self.display, signal='Shell.calltip') def display(self, calltip): @@ -123,6 +169,7 @@ class Calltip(wx.TextCtrl): self.AppendText(calltip) +# TODO: Switch this to a editwindow.EditWindow class SessionListing(wx.TextCtrl): """Text control containing all commands for session.""" @@ -161,44 +208,58 @@ class DispatcherListing(wx.TextCtrl): self.AppendText(text + '\n') -class CrustFrame(frame.Frame): + +class CrustFrame(frame.Frame, frame.ShellFrameMixin): """Frame containing all the PyCrust components.""" name = 'CrustFrame' revision = __revision__ + def __init__(self, parent=None, id=-1, title='PyCrust', pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, rootObject=None, rootLabel=None, rootIsNamespace=True, - locals=None, InterpClass=None, *args, **kwds): + locals=None, InterpClass=None, + config=None, dataDir=None, + *args, **kwds): """Create CrustFrame instance.""" frame.Frame.__init__(self, parent, id, title, pos, size, style) + frame.ShellFrameMixin.__init__(self, config, dataDir) + + if size == wx.DefaultSize: + self.SetSize((800, 600)) + intro = 'PyCrust %s - The Flakiest Python Shell' % VERSION - intro += '\nSponsored by Orbtech - ' - intro += 'Your source for Python programming expertise.' self.SetStatusText(intro.replace('\n', ', ')) self.crust = Crust(parent=self, intro=intro, rootObject=rootObject, rootLabel=rootLabel, rootIsNamespace=rootIsNamespace, locals=locals, - InterpClass=InterpClass, *args, **kwds) + InterpClass=InterpClass, + startupScript=self.startupScript, + execStartupScript=self.execStartupScript, + *args, **kwds) self.shell = self.crust.shell + # Override the filling so that status messages go to the status bar. self.crust.filling.tree.setStatusText = self.SetStatusText + # Override the shell so that status messages go to the status bar. self.shell.setStatusText = self.SetStatusText - # Fix a problem with the sash shrinking to nothing. - self.crust.filling.SetSashPosition(200) - # Set focus to the shell editor. + self.shell.SetFocus() + self.LoadSettings() + def OnClose(self, event): """Event handler for closing.""" + self.SaveSettings() self.crust.shell.destroy() self.Destroy() + def OnAbout(self, event): """Display an About window.""" title = 'About PyCrust' @@ -211,8 +272,33 @@ class CrustFrame(frame.Frame): 'Platform: %s\n' % sys.platform + \ 'Python Version: %s\n' % sys.version.split()[0] + \ 'wxPython Version: %s\n' % wx.VERSION_STRING + \ - ('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:])) + ('\t(%s)\n' % ", ".join(wx.PlatformInfo[1:])) dialog = wx.MessageDialog(self, text, title, wx.OK | wx.ICON_INFORMATION) dialog.ShowModal() dialog.Destroy() + + + + def LoadSettings(self): + if self.config is not None: + frame.ShellFrameMixin.LoadSettings(self) + frame.Frame.LoadSettings(self, self.config) + self.crust.LoadSettings(self.config) + + + def SaveSettings(self): + if self.config is not None: + frame.ShellFrameMixin.SaveSettings(self) + if self.autoSaveSettings: + frame.Frame.SaveSettings(self, self.config) + self.crust.SaveSettings(self.config) + + + def DoSaveSettings(self): + if self.config is not None: + self.SaveSettings() + self.config.Flush() + + + diff --git a/wxPython/wx/py/editor.py b/wxPython/wx/py/editor.py index be2f521b9c..8dc8981798 100644 --- a/wxPython/wx/py/editor.py +++ b/wxPython/wx/py/editor.py @@ -30,7 +30,7 @@ class EditorFrame(frame.Frame): self._defaultText = title + ' - the tastiest Python editor.' self._statusText = self._defaultText self.SetStatusText(self._statusText) - wx.EVT_IDLE(self, self.OnIdle) + self.Bind(wx.EVT_IDLE, self.OnIdle) self._setup() if filename: self.bufferCreate(filename) @@ -137,7 +137,7 @@ class EditorFrame(frame.Frame): self.bufferDestroy() buffer = Buffer() self.panel = panel = wx.Panel(parent=self, id=-1) - wx.EVT_ERASE_BACKGROUND(panel, lambda x: x) + panel.Bind (wx.EVT_ERASE_BACKGROUND, lambda x: x) editor = Editor(parent=panel) panel.editor = editor sizer = wx.BoxSizer(wx.VERTICAL) @@ -318,7 +318,7 @@ class EditorNotebookFrame(EditorFrame): """Create new buffer.""" buffer = Buffer() panel = wx.Panel(parent=self.notebook, id=-1) - wx.EVT_ERASE_BACKGROUND(panel, lambda x: x) + panel.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: x) editor = Editor(parent=panel) panel.editor = editor sizer = wx.BoxSizer(wx.VERTICAL) @@ -366,11 +366,9 @@ class EditorNotebook(wx.Notebook): def __init__(self, parent): """Create EditorNotebook instance.""" wx.Notebook.__init__(self, parent, id=-1, style=wx.CLIP_CHILDREN) - wx.EVT_NOTEBOOK_PAGE_CHANGING(self, self.GetId(), - self.OnPageChanging) - wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), - self.OnPageChanged) - wx.EVT_IDLE(self, self.OnIdle) + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging, id=self.GetId()) + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=self.GetId()) + self.Bind(wx.EVT_IDLE, self.OnIdle) def OnIdle(self, event): """Event handler for idle time.""" @@ -552,7 +550,7 @@ class EditorShellNotebook(wx.Notebook): self.AddPage(page=self.editor.window, text='Editor', select=True) self.AddPage(page=self.shell, text='Shell') self.editor.setFocus() - wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self.GetId(), self.OnPageChanged) + self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=self.GetId()) def OnPageChanged(self, event): """Page changed event handler.""" @@ -583,8 +581,8 @@ class Editor: self.id = self.window.GetId() self.buffer = None # Assign handlers for keyboard events. - wx.EVT_CHAR(self.window, self.OnChar) - wx.EVT_KEY_DOWN(self.window, self.OnKeyDown) + self.window.Bind(wx.EVT_CHAR, self.OnChar) + self.window.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) def _setBuffer(self, buffer, text): """Set the editor to a buffer. Private callback called by buffer.""" diff --git a/wxPython/wx/py/editwindow.py b/wxPython/wx/py/editwindow.py index 90aebf5953..78b75f5ccf 100644 --- a/wxPython/wx/py/editwindow.py +++ b/wxPython/wx/py/editwindow.py @@ -92,11 +92,10 @@ class EditWindow(stc.StyledTextCtrl): size = 0 self.SetZoom(size) - def __config(self): - """Configure shell based on user preferences.""" - self.SetMarginType(1, stc.STC_MARGIN_NUMBER) - self.SetMarginWidth(1, 40) + def __config(self): + self.setDisplayLineNumbers(False) + self.SetLexer(stc.STC_LEX_PYTHON) self.SetKeyWords(0, ' '.join(keyword.kwlist)) @@ -116,6 +115,7 @@ class EditWindow(stc.StyledTextCtrl): self.AutoCompStops(' .,;:([)]}\'"\\<>%^&+-=*/|`') # Do we want to automatically pop up command argument help? self.autoCallTip = True + self.callTipInsert = True self.CallTipSetBackground(FACES['calltipbg']) self.CallTipSetForeground(FACES['calltipfg']) self.SetWrapMode(False) @@ -124,6 +124,16 @@ class EditWindow(stc.StyledTextCtrl): except AttributeError: pass + def setDisplayLineNumbers(self, state): + self.lineNumbers = state + if state: + self.SetMarginType(1, stc.STC_MARGIN_NUMBER) + self.SetMarginWidth(1, 40) + else: + # Leave a small margin so the feature hidden lines marker can be seen + self.SetMarginType(1, 0) + self.SetMarginWidth(1, 10) + def setStyles(self, faces): """Configure font size, typeface and color for lexer.""" @@ -136,7 +146,7 @@ class EditWindow(stc.StyledTextCtrl): # Built in styles self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, - "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces) + "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % FACES) self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces) self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, @@ -223,3 +233,65 @@ class EditWindow(stc.StyledTextCtrl): def CanPaste(self): """Return True if pasting should succeed.""" return stc.StyledTextCtrl.CanPaste(self) and self.CanEdit() + + + def GetLastPosition(self): + return self.GetLength() + + def GetRange(self, start, end): + return self.GetTextRange(start, end) + + def GetSelection(self): + return self.GetAnchor(), self.GetCurrentPos() + + def SetSelection(self, start, end): + self.SetSelectionStart(start) + self.SetSelectionEnd(end) + + def ShowPosition(self, pos): + line = self.LineFromPosition(pos) + #self.EnsureVisible(line) + self.GotoLine(line) + + def DoFindNext(self, findData, findDlg=None): + backward = not (findData.GetFlags() & wx.FR_DOWN) + matchcase = findData.GetFlags() & wx.FR_MATCHCASE + end = self.GetLastPosition() + textstring = self.GetRange(0, end) + findstring = findData.GetFindString() + if not matchcase: + textstring.lower() + findstring.lower() + if backward: + start = self.GetSelection()[0] + loc = textstring.rfind(findstring, 0, start) + else: + start = self.GetSelection()[1] + loc = textstring.find(findstring, start) + + # if it wasn't found then restart at begining + if loc == -1 and start != 0: + if backward: + start = end + loc = textstring.rfind(findstring, 0, start) + else: + start = 0 + loc = textstring.find(findstring, start) + + # was it still not found? + if loc == -1: + dlg = wx.MessageDialog(self, 'Unable to find the search text.', + 'Not found!', + wx.OK | wx.ICON_INFORMATION) + dlg.ShowModal() + dlg.Destroy() + if findDlg: + if loc == -1: + wx.CallAfter(findDlg.SetFocus) + return + else: + findDlg.Close() + + # show and select the found text + self.ShowPosition(loc) + self.SetSelection(loc, loc + len(findstring)) diff --git a/wxPython/wx/py/filling.py b/wxPython/wx/py/filling.py index f34bbf0153..56b6c7cf41 100644 --- a/wxPython/wx/py/filling.py +++ b/wxPython/wx/py/filling.py @@ -61,10 +61,10 @@ class FillingTree(wx.TreeCtrl): rootData = wx.TreeItemData(rootObject) self.item = self.root = self.AddRoot(rootLabel, -1, -1, rootData) self.SetItemHasChildren(self.root, self.objHasChildren(rootObject)) - wx.EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding) - wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed) - wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged) - wx.EVT_TREE_ITEM_ACTIVATED(self, self.GetId(), self.OnItemActivated) + self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding, id=self.GetId()) + self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=self.GetId()) + self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=self.GetId()) + self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated, id=self.GetId()) if not static: dispatcher.connect(receiver=self.push, signal='Interpreter.push') @@ -277,24 +277,49 @@ class Filling(wx.SplitterWindow): revision = __revision__ def __init__(self, parent, id=-1, pos=wx.DefaultPosition, - size=wx.DefaultSize, style=wx.SP_3D, + size=wx.DefaultSize, style=wx.SP_3D|wx.SP_LIVE_UPDATE, name='Filling Window', rootObject=None, rootLabel=None, rootIsNamespace=False, static=False): """Create a Filling instance.""" wx.SplitterWindow.__init__(self, parent, id, pos, size, style, name) + self.tree = FillingTree(parent=self, rootObject=rootObject, rootLabel=rootLabel, rootIsNamespace=rootIsNamespace, static=static) self.text = FillingText(parent=self, static=static) - self.SplitVertically(self.tree, self.text, 130) + + wx.FutureCall(1, self.SplitVertically, self.tree, self.text, 200) + self.SetMinimumPaneSize(1) + # Override the filling so that descriptions go to FillingText. self.tree.setText = self.text.SetText + # Display the root item. -## self.tree.SelectItem(self.tree.root) + self.tree.SelectItem(self.tree.root) self.tree.display() + self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnChanged) + + def OnChanged(self, event): + #this is important: do not evaluate this event=> otherwise, splitterwindow behaves strange + #event.Skip() + pass + + + def LoadSettings(self, config): + pos = config.ReadInt('Sash/FillingPos', 200) + wx.FutureCall(250, self.SetSashPosition, pos) + zoom = config.ReadInt('View/Zoom/Filling', -99) + if zoom != -99: + self.text.SetZoom(zoom) + + def SaveSettings(self, config): + config.WriteInt('Sash/FillingPos', self.GetSashPosition()) + config.WriteInt('View/Zoom/Filling', self.text.GetZoom()) + + class FillingFrame(wx.Frame): """Frame containing the namespace tree component.""" diff --git a/wxPython/wx/py/frame.py b/wxPython/wx/py/frame.py index 600f2bd1b9..e716fb7492 100644 --- a/wxPython/wx/py/frame.py +++ b/wxPython/wx/py/frame.py @@ -5,8 +5,9 @@ __cvsid__ = "$Id$" __revision__ = "$Revision$"[11:-2] import wx +import os from version import VERSION - +import editwindow ID_NEW = wx.ID_NEW ID_OPEN = wx.ID_OPEN @@ -23,7 +24,9 @@ ID_COPY = wx.ID_COPY ID_PASTE = wx.ID_PASTE ID_CLEAR = wx.ID_CLEAR ID_SELECTALL = wx.ID_SELECTALL +ID_EMPTYBUFFER = wx.NewId() ID_ABOUT = wx.ID_ABOUT +ID_HELP = wx.NewId() ID_AUTOCOMP = wx.NewId() ID_AUTOCOMP_SHOW = wx.NewId() ID_AUTOCOMP_MAGIC = wx.NewId() @@ -31,11 +34,25 @@ ID_AUTOCOMP_SINGLE = wx.NewId() ID_AUTOCOMP_DOUBLE = wx.NewId() ID_CALLTIPS = wx.NewId() ID_CALLTIPS_SHOW = wx.NewId() +ID_CALLTIPS_INSERT = wx.NewId() ID_COPY_PLUS = wx.NewId() ID_NAMESPACE = wx.NewId() ID_PASTE_PLUS = wx.NewId() ID_WRAP = wx.NewId() +ID_TOGGLE_MAXIMIZE = wx.NewId() ID_USEAA = wx.NewId() +ID_SHOW_LINENUMBERS = wx.NewId() +ID_AUTO_SAVESETTINGS = wx.NewId() +ID_SAVEHISTORY = wx.NewId() +ID_SAVESETTINGS = wx.NewId() +ID_DELSETTINGSFILE = wx.NewId() +ID_EDITSTARTUPSCRIPT = wx.NewId() +ID_EXECSTARTUPSCRIPT = wx.NewId() +ID_STARTUP = wx.NewId() +ID_SETTINGS = wx.NewId() +ID_FIND = wx.ID_FIND +ID_FINDNEXT = wx.NewId() + class Frame(wx.Frame): @@ -53,13 +70,28 @@ class Frame(wx.Frame): import images self.SetIcon(images.getPyIcon()) self.__createMenus() - wx.EVT_CLOSE(self, self.OnClose) + + self.iconized = False + self.findDlg = None + self.findData = wx.FindReplaceData() + self.findData.SetFlags(wx.FR_DOWN) + + self.Bind(wx.EVT_CLOSE, self.OnClose) + self.Bind(wx.EVT_ICONIZE, self.OnIconize) + + + def OnIconize(self, event): + """Event handler for Iconize.""" + self.iconized = event.Iconized() + def OnClose(self, event): """Event handler for closing.""" self.Destroy() + def __createMenus(self): + # File Menu m = self.fileMenu = wx.Menu() m.Append(ID_NEW, '&New \tCtrl+N', 'New file') @@ -73,17 +105,18 @@ class Frame(wx.Frame): m.AppendSeparator() m.Append(ID_SAVE, '&Save... \tCtrl+S', 'Save file') - m.Append(ID_SAVEAS, 'Save &As \tShift+Ctrl+S', + m.Append(ID_SAVEAS, 'Save &As \tCtrl+Shift+S', 'Save file with new name') m.AppendSeparator() m.Append(ID_PRINT, '&Print... \tCtrl+P', 'Print file') m.AppendSeparator() - m.Append(ID_NAMESPACE, '&Update Namespace \tShift+Ctrl+N', + m.Append(ID_NAMESPACE, '&Update Namespace \tCtrl+Shift+N', 'Update namespace for autocompletion and calltips') m.AppendSeparator() - m.Append(ID_EXIT, 'E&xit', 'Exit Program') + m.Append(ID_EXIT, 'E&xit\tCtrl+Q', 'Exit Program') + # Edit m = self.editMenu = wx.Menu() m.Append(ID_UNDO, '&Undo \tCtrl+Z', 'Undo the last action') @@ -94,105 +127,175 @@ class Frame(wx.Frame): 'Cut the selection') m.Append(ID_COPY, '&Copy \tCtrl+C', 'Copy the selection') - m.Append(ID_COPY_PLUS, 'Cop&y Plus \tShift+Ctrl+C', + m.Append(ID_COPY_PLUS, 'Cop&y Plus \tCtrl+Shift+C', 'Copy the selection - retaining prompts') m.Append(ID_PASTE, '&Paste \tCtrl+V', 'Paste from clipboard') - m.Append(ID_PASTE_PLUS, 'Past&e Plus \tShift+Ctrl+V', + m.Append(ID_PASTE_PLUS, 'Past&e Plus \tCtrl+Shift+V', 'Paste and run commands') m.AppendSeparator() m.Append(ID_CLEAR, 'Cle&ar', 'Delete the selection') m.Append(ID_SELECTALL, 'Select A&ll \tCtrl+A', 'Select all text') + m.AppendSeparator() + m.Append(ID_EMPTYBUFFER, 'E&mpty Buffer', + 'Delete all the contents of the edit buffer') + m.Append(ID_FIND, '&Find Text \tCtrl+F', + 'Search for text in the edit buffer') + m.Append(ID_FINDNEXT, 'Find &Next \tF3', + 'Find next/previous instance of the search text') + + # View + m = self.viewMenu = wx.Menu() + m.Append(ID_WRAP, '&Wrap Lines\tCtrl+Shift+W', + 'Wrap lines at right edge', wx.ITEM_CHECK) + m.Append(ID_SHOW_LINENUMBERS, '&Show Line Numbers\tCtrl+Shift+L', 'Show Line Numbers', wx.ITEM_CHECK) + m.Append(ID_TOGGLE_MAXIMIZE, '&Toggle Maximize\tF11', 'Maximize/Restore Application') + # Options m = self.autocompMenu = wx.Menu() - m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion', + m.Append(ID_AUTOCOMP_SHOW, 'Show &Auto Completion\tCtrl+Shift+A', 'Show auto completion list', wx.ITEM_CHECK) - m.Append(ID_AUTOCOMP_MAGIC, 'Include Magic Attributes', + m.Append(ID_AUTOCOMP_MAGIC, 'Include &Magic Attributes\tCtrl+Shift+M', 'Include attributes visible to __getattr__ and __setattr__', wx.ITEM_CHECK) - m.Append(ID_AUTOCOMP_SINGLE, 'Include Single Underscores', + m.Append(ID_AUTOCOMP_SINGLE, 'Include Single &Underscores\tCtrl+Shift+U', 'Include attibutes prefixed by a single underscore', wx.ITEM_CHECK) - m.Append(ID_AUTOCOMP_DOUBLE, 'Include Double Underscores', + m.Append(ID_AUTOCOMP_DOUBLE, 'Include &Double Underscores\tCtrl+Shift+D', 'Include attibutes prefixed by a double underscore', wx.ITEM_CHECK) - m = self.calltipsMenu = wx.Menu() - m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips', + m.Append(ID_CALLTIPS_SHOW, 'Show Call &Tips\tCtrl+Shift+T', 'Show call tips with argument signature and docstring', wx.ITEM_CHECK) + m.Append(ID_CALLTIPS_INSERT, '&Insert Call Tips\tCtrl+Shift+I', + '&Insert Call Tips', wx.ITEM_CHECK) m = self.optionsMenu = wx.Menu() m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu, 'Auto Completion Options') m.AppendMenu(ID_CALLTIPS, '&Call Tips', self.calltipsMenu, 'Call Tip Options') - m.Append(ID_WRAP, '&Wrap Lines', - 'Wrap lines at right edge', wx.ITEM_CHECK) + if wx.Platform == "__WXMAC__": - m.Append(ID_USEAA, '&Use AntiAliasing', + m.Append(ID_USEAA, '&Use AntiAliasing\tCtrl+Shift+A', 'Use anti-aliased fonts', wx.ITEM_CHECK) + + m.AppendSeparator() + m.Append(ID_SAVEHISTORY, '&Save History\tAlt+Ctrl+A', 'Automatically save history on close', wx.ITEM_CHECK) + self.startupMenu = wx.Menu() + self.startupMenu.Append(ID_EXECSTARTUPSCRIPT, 'E&xecute Startup Script\tAlt+Ctrl+X', 'Execute Startup Script', wx.ITEM_CHECK) + self.startupMenu.Append(ID_EDITSTARTUPSCRIPT, '&Edit Startup Script\tAlt+Ctrl+E', 'Edit Startup Script') + m.AppendMenu(ID_STARTUP, '&Startup', self.startupMenu, 'Startup Options') + + self.settingsMenu = wx.Menu() + self.settingsMenu.Append(ID_AUTO_SAVESETTINGS, '&Auto Save Settings\tAlt+Ctrl+A', 'Automatically save settings on close', wx.ITEM_CHECK) + self.settingsMenu.Append(ID_SAVESETTINGS, '&Save Settings\tAlt+Ctrl+S', 'Save settings now') + self.settingsMenu.Append(ID_DELSETTINGSFILE, '&Revert to default\tAlt+Ctrl+R', 'Revert to the default settings') + m.AppendMenu(ID_SETTINGS, '&Settings', self.settingsMenu, 'Settings Options') m = self.helpMenu = wx.Menu() + m.Append(ID_HELP, '&Help\tF1', 'Help!') m.AppendSeparator() - m.Append(ID_ABOUT, '&About...', 'About this program') + m.Append(ID_ABOUT, '&About...\tAlt+A', 'About this program') b = self.menuBar = wx.MenuBar() b.Append(self.fileMenu, '&File') b.Append(self.editMenu, '&Edit') + b.Append(self.viewMenu, '&View') b.Append(self.optionsMenu, '&Options') b.Append(self.helpMenu, '&Help') self.SetMenuBar(b) - wx.EVT_MENU(self, ID_NEW, self.OnFileNew) - wx.EVT_MENU(self, ID_OPEN, self.OnFileOpen) - wx.EVT_MENU(self, ID_REVERT, self.OnFileRevert) - wx.EVT_MENU(self, ID_CLOSE, self.OnFileClose) - wx.EVT_MENU(self, ID_SAVE, self.OnFileSave) - wx.EVT_MENU(self, ID_SAVEAS, self.OnFileSaveAs) - wx.EVT_MENU(self, ID_NAMESPACE, self.OnFileUpdateNamespace) - wx.EVT_MENU(self, ID_PRINT, self.OnFilePrint) - wx.EVT_MENU(self, ID_EXIT, self.OnExit) - wx.EVT_MENU(self, ID_UNDO, self.OnUndo) - wx.EVT_MENU(self, ID_REDO, self.OnRedo) - wx.EVT_MENU(self, ID_CUT, self.OnCut) - wx.EVT_MENU(self, ID_COPY, self.OnCopy) - wx.EVT_MENU(self, ID_COPY_PLUS, self.OnCopyPlus) - wx.EVT_MENU(self, ID_PASTE, self.OnPaste) - wx.EVT_MENU(self, ID_PASTE_PLUS, self.OnPastePlus) - wx.EVT_MENU(self, ID_CLEAR, self.OnClear) - wx.EVT_MENU(self, ID_SELECTALL, self.OnSelectAll) - wx.EVT_MENU(self, ID_ABOUT, self.OnAbout) - wx.EVT_MENU(self, ID_AUTOCOMP_SHOW, self.OnAutoCompleteShow) - wx.EVT_MENU(self, ID_AUTOCOMP_MAGIC, self.OnAutoCompleteMagic) - wx.EVT_MENU(self, ID_AUTOCOMP_SINGLE, self.OnAutoCompleteSingle) - wx.EVT_MENU(self, ID_AUTOCOMP_DOUBLE, self.OnAutoCompleteDouble) - wx.EVT_MENU(self, ID_CALLTIPS_SHOW, self.OnCallTipsShow) - wx.EVT_MENU(self, ID_WRAP, self.OnWrap) - wx.EVT_MENU(self, ID_USEAA, self.OnUseAA) - - wx.EVT_UPDATE_UI(self, ID_NEW, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_OPEN, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_REVERT, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_CLOSE, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_SAVE, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_SAVEAS, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_NAMESPACE, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_PRINT, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_UNDO, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_REDO, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_CUT, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_COPY, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_COPY_PLUS, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_PASTE, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_PASTE_PLUS, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_CLEAR, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_SELECTALL, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SHOW, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_MAGIC, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SINGLE, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_DOUBLE, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_CALLTIPS_SHOW, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_WRAP, self.OnUpdateMenu) - wx.EVT_UPDATE_UI(self, ID_USEAA, self.OnUpdateMenu) + self.Bind(wx.EVT_MENU, self.OnFileNew, id=ID_NEW) + self.Bind(wx.EVT_MENU, self.OnFileOpen, id=ID_OPEN) + self.Bind(wx.EVT_MENU, self.OnFileRevert, id=ID_REVERT) + self.Bind(wx.EVT_MENU, self.OnFileClose, id=ID_CLOSE) + self.Bind(wx.EVT_MENU, self.OnFileSave, id=ID_SAVE) + self.Bind(wx.EVT_MENU, self.OnFileSaveAs, id=ID_SAVEAS) + self.Bind(wx.EVT_MENU, self.OnFileUpdateNamespace, id=ID_NAMESPACE) + self.Bind(wx.EVT_MENU, self.OnFilePrint, id=ID_PRINT) + self.Bind(wx.EVT_MENU, self.OnExit, id=ID_EXIT) + self.Bind(wx.EVT_MENU, self.OnUndo, id=ID_UNDO) + self.Bind(wx.EVT_MENU, self.OnRedo, id=ID_REDO) + self.Bind(wx.EVT_MENU, self.OnCut, id=ID_CUT) + self.Bind(wx.EVT_MENU, self.OnCopy, id=ID_COPY) + self.Bind(wx.EVT_MENU, self.OnCopyPlus, id=ID_COPY_PLUS) + self.Bind(wx.EVT_MENU, self.OnPaste, id=ID_PASTE) + self.Bind(wx.EVT_MENU, self.OnPastePlus, id=ID_PASTE_PLUS) + self.Bind(wx.EVT_MENU, self.OnClear, id=ID_CLEAR) + self.Bind(wx.EVT_MENU, self.OnSelectAll, id=ID_SELECTALL) + self.Bind(wx.EVT_MENU, self.OnEmptyBuffer, id=ID_EMPTYBUFFER) + self.Bind(wx.EVT_MENU, self.OnAbout, id=ID_ABOUT) + self.Bind(wx.EVT_MENU, self.OnHelp, id=ID_HELP) + self.Bind(wx.EVT_MENU, self.OnAutoCompleteShow, id=ID_AUTOCOMP_SHOW) + self.Bind(wx.EVT_MENU, self.OnAutoCompleteMagic, id=ID_AUTOCOMP_MAGIC) + self.Bind(wx.EVT_MENU, self.OnAutoCompleteSingle, id=ID_AUTOCOMP_SINGLE) + self.Bind(wx.EVT_MENU, self.OnAutoCompleteDouble, id=ID_AUTOCOMP_DOUBLE) + self.Bind(wx.EVT_MENU, self.OnCallTipsShow, id=ID_CALLTIPS_SHOW) + self.Bind(wx.EVT_MENU, self.OnCallTipsInsert, id=ID_CALLTIPS_INSERT) + self.Bind(wx.EVT_MENU, self.OnWrap, id=ID_WRAP) + self.Bind(wx.EVT_MENU, self.OnUseAA, id=ID_USEAA) + self.Bind(wx.EVT_MENU, self.OnToggleMaximize, id=ID_TOGGLE_MAXIMIZE) + self.Bind(wx.EVT_MENU, self.OnShowLineNumbers, id=ID_SHOW_LINENUMBERS) + self.Bind(wx.EVT_MENU, self.OnAutoSaveSettings, id=ID_AUTO_SAVESETTINGS) + self.Bind(wx.EVT_MENU, self.OnSaveHistory, id=ID_SAVEHISTORY) + self.Bind(wx.EVT_MENU, self.OnSaveSettings, id=ID_SAVESETTINGS) + self.Bind(wx.EVT_MENU, self.OnDelSettingsFile, id=ID_DELSETTINGSFILE) + self.Bind(wx.EVT_MENU, self.OnEditStartupScript, id=ID_EDITSTARTUPSCRIPT) + self.Bind(wx.EVT_MENU, self.OnExecStartupScript, id=ID_EXECSTARTUPSCRIPT) + self.Bind(wx.EVT_MENU, self.OnFindText, id=ID_FIND) + self.Bind(wx.EVT_MENU, self.OnFindNext, id=ID_FINDNEXT) + + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_NEW) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_OPEN) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_REVERT) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CLOSE) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVE) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEAS) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_NAMESPACE) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_PRINT) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_UNDO) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_REDO) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CUT) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_COPY) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_COPY_PLUS) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_PASTE) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_PASTE_PLUS) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CLEAR) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SELECTALL) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EMPTYBUFFER) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_SHOW) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_MAGIC) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_SINGLE) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTOCOMP_DOUBLE) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CALLTIPS_SHOW) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CALLTIPS_INSERT) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_WRAP) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_USEAA) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SHOW_LINENUMBERS) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_AUTO_SAVESETTINGS) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVESETTINGS) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_DELSETTINGSFILE) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EXECSTARTUPSCRIPT) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEHISTORY) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EDITSTARTUPSCRIPT) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FIND) + self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FINDNEXT) + + self.Bind(wx.EVT_ACTIVATE, self.OnActivate) + self.Bind(wx.EVT_FIND, self.OnFindNext) + self.Bind(wx.EVT_FIND_NEXT, self.OnFindNext) + self.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose) + + + + def OnShowLineNumbers(self, event): + win = wx.Window.FindFocus() + if hasattr(win, 'lineNumbers'): + win.lineNumbers = event.IsChecked() + win.setDisplayLineNumbers(win.lineNumbers) + + def OnToggleMaximize(self, event): + self.Maximize(not self.IsMaximized()) def OnFileNew(self, event): self.bufferNew() @@ -222,39 +325,52 @@ class Frame(wx.Frame): self.Close(False) def OnUndo(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.Undo() def OnRedo(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.Redo() def OnCut(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.Cut() def OnCopy(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.Copy() def OnCopyPlus(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.CopyWithPrompts() def OnPaste(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.Paste() def OnPastePlus(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.PasteAndRun() def OnClear(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.Clear() + + def OnEmptyBuffer(self, event): + win = wx.Window.FindFocus() + d = wx.MessageDialog(self, + "Are you sure you want to clear the edit buffer,\n" + "deleting all the text?", + "Empty Buffer", wx.OK | wx.CANCEL | wx.ICON_QUESTION) + answer = d.ShowModal() + d.Destroy() + if (answer == wx.ID_OK): + win.ClearAll() + if hasattr(win,'prompt'): + win.prompt() def OnSelectAll(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.SelectAll() def OnAbout(self, event): @@ -266,38 +382,102 @@ class Frame(wx.Frame): dialog.ShowModal() dialog.Destroy() + def OnHelp(self, event): + """Display a Help window.""" + title = 'Help' + text = "Type 'shell.help()' in the shell window." + dialog = wx.MessageDialog(self, text, title, + wx.OK | wx.ICON_INFORMATION) + dialog.ShowModal() + dialog.Destroy() + def OnAutoCompleteShow(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.autoComplete = event.IsChecked() def OnAutoCompleteMagic(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.autoCompleteIncludeMagic = event.IsChecked() def OnAutoCompleteSingle(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.autoCompleteIncludeSingle = event.IsChecked() def OnAutoCompleteDouble(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.autoCompleteIncludeDouble = event.IsChecked() def OnCallTipsShow(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.autoCallTip = event.IsChecked() + def OnCallTipsInsert(self, event): + win = wx.Window.FindFocus() + win.callTipInsert = event.IsChecked() + def OnWrap(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.SetWrapMode(event.IsChecked()) + wx.FutureCall(1, self.shell.EnsureCaretVisible) def OnUseAA(self, event): - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() win.SetUseAntiAliasing(event.IsChecked()) + + def OnSaveHistory(self, event): + self.saveHistory = event.IsChecked() + + def OnAutoSaveSettings(self, event): + self.autoSaveSettings = event.IsChecked() + + def OnSaveSettings(self, event): + self.DoSaveSettings() + + def OnDelSettingsFile(self, event): + if self.config is not None: + d = wx.MessageDialog( + self, "Do you want to revert to the default settings?\n" + + "A restart is needed for the change to take effect", + "Warning", wx.OK | wx.CANCEL | wx.ICON_QUESTION) + answer = d.ShowModal() + d.Destroy() + if (answer == wx.ID_OK): + self.config.DeleteAll() + self.LoadSettings() + + + def OnEditStartupScript(self, event): + if hasattr(self, 'EditStartupScript'): + self.EditStartupScript() + + def OnExecStartupScript(self, event): + self.execStartupScript = event.IsChecked() + + + def OnFindText(self, event): + if self.findDlg is not None: + return + win = wx.Window.FindFocus() + self.findDlg = wx.FindReplaceDialog(win, self.findData, "Find", + wx.FR_NOWHOLEWORD) + self.findDlg.Show() + def OnFindNext(self, event): + if isinstance(event, wx.FindDialogEvent): + win = self.findDlg.GetParent() + else: + win = wx.Window.FindFocus() + win.DoFindNext(self.findData, self.findDlg) + + def OnFindClose(self, event): + self.findDlg.Destroy() + self.findDlg = None + + def OnUpdateMenu(self, event): """Update menu items based on current status and context.""" - win = wx.Window_FindFocus() + win = wx.Window.FindFocus() id = event.GetId() event.Enable(True) try: @@ -341,6 +521,8 @@ class Frame(wx.Frame): event.Enable(win.CanCut()) elif id == ID_SELECTALL: event.Enable(hasattr(win, 'SelectAll')) + elif id == ID_EMPTYBUFFER: + event.Enable(hasattr(win, 'ClearAll') and not win.GetReadOnly()) elif id == ID_AUTOCOMP_SHOW: event.Check(win.autoComplete) elif id == ID_AUTOCOMP_MAGIC: @@ -351,12 +533,273 @@ class Frame(wx.Frame): event.Check(win.autoCompleteIncludeDouble) elif id == ID_CALLTIPS_SHOW: event.Check(win.autoCallTip) + elif id == ID_CALLTIPS_INSERT: + event.Check(win.callTipInsert) elif id == ID_WRAP: event.Check(win.GetWrapMode()) elif id == ID_USEAA: event.Check(win.GetUseAntiAliasing()) + + elif id == ID_SHOW_LINENUMBERS: + event.Check(win.lineNumbers) + elif id == ID_AUTO_SAVESETTINGS: + event.Check(self.autoSaveSettings) + elif id == ID_SAVESETTINGS: + event.Enable(self.config is not None and + hasattr(self, 'DoSaveSettings')) + elif id == ID_DELSETTINGSFILE: + event.Enable(self.config is not None) + + elif id == ID_EXECSTARTUPSCRIPT: + event.Check(self.execStartupScript) + + elif id == ID_SAVEHISTORY: + event.Check(self.saveHistory and self.dataDir is not None) + elif id == ID_EDITSTARTUPSCRIPT: + event.Enable(hasattr(self, 'EditStartupScript')) + + elif id == ID_FIND: + event.Enable(hasattr(win, 'DoFindNext')) + elif id == ID_FINDNEXT: + event.Enable(hasattr(win, 'DoFindNext') and + self.findData.GetFindString() != '') + else: event.Enable(False) except AttributeError: # This menu option is not supported in the current context. event.Enable(False) + + + def OnActivate(self, event): + """ + Event Handler for losing the focus of the Frame. Should close + Autocomplete listbox, if shown. + """ + if not event.GetActive(): + # If autocomplete active, cancel it. Otherwise, the + # autocomplete list will stay visible on top of the + # z-order after switching to another application + win = wx.Window.FindFocus() + if hasattr(win, 'AutoCompActive') and win.AutoCompActive(): + win.AutoCompCancel() + event.Skip() + + + + def LoadSettings(self, config): + """Called be derived classes to load settings specific to the Frame""" + 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) + + + def SaveSettings(self, config): + """Called by derived classes to save Frame settings to a wx.Config object""" + + # TODO: track position/size so we can save it even if the + # frame is maximized or iconized. + if not self.iconized 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) + + + + +class ShellFrameMixin: + """ + A mix-in class for frames that will have a Shell or a Crust window + and that want to add history, startupScript and other common + functionality. + """ + def __init__(self, config, dataDir): + self.config = config + self.dataDir = dataDir + self.startupScript = os.environ.get('PYTHONSTARTUP') + if not self.startupScript and self.dataDir: + self.startupScript = os.path.join(self.dataDir, 'startup') + + self.autoSaveSettings = False + self.saveHistory = False + + # We need this one before we have a chance to load the settings... + self.execStartupScript = True + if self.config: + self.execStartupScript = self.config.ReadBool('Options/ExecStartupScript', True) + + + def OnHelp(self, event): + """Display a Help window.""" + import wx.lib.dialogs + title = 'Help on key bindings' + + text = wx.py.shell.HELP_TEXT + + dlg = wx.lib.dialogs.ScrolledMessageDialog(self, text, title, size = ((700, 540))) + fnt = wx.Font(10, wx.TELETYPE, wx.NORMAL, wx.NORMAL) + dlg.GetChildren()[0].SetFont(fnt) + dlg.GetChildren()[0].SetInsertionPoint(0) + dlg.ShowModal() + dlg.Destroy() + + + def LoadSettings(self): + if self.config is not None: + self.autoSaveSettings = self.config.ReadBool('Options/AutoSaveSettings', False) + self.execStartupScript = self.config.ReadBool('Options/ExecStartupScript', True) + self.saveHistory = self.config.ReadBool('Options/SaveHistory', False) + self.LoadHistory() + + + def SaveSettings(self): + if self.config is not None: + # always save this one + self.config.WriteBool('Options/AutoSaveSettings', self.autoSaveSettings) + if self.autoSaveSettings: + self.config.WriteBool('Options/SaveHistory', self.saveHistory) + self.config.WriteBool('Options/ExecStartupScript', self.execStartupScript) + self.SaveHistory() + + + + def SaveHistory(self): + if self.dataDir: + try: + # always open the file so that when we are not + # saving the history, the old file is emptied. + name = os.path.join(self.dataDir, 'history') + f = file(name, 'w') + if self.saveHistory: + hist = '\n'.join(self.shell.history) + f.write(hist) + f.close() + except: + d = wx.MessageDialog(self, "Error saving history file.", + "Error", wx.ICON_EXCLAMATION) + d.ShowModal() + d.Destroy() + + + def LoadHistory(self): + if self.dataDir: + name = os.path.join(self.dataDir, 'history') + if os.path.exists(name): + try: + f = file(name, 'U') + hist = f.read() + f.close() + self.shell.history = hist.split('\n') + except: + d = wx.MessageDialog(self, "Error loading history file.", + "Error", wx.ICON_EXCLAMATION) + d.ShowModal() + d.Destroy() + + + def bufferHasChanged(self): + # the shell buffers can always be saved + return True + + def bufferSave(self): + import time + appname = wx.GetApp().GetAppName() + default = appname + '-' + time.strftime("%Y%m%d-%H%M.py") + fileName = wx.FileSelector("Save File As", "Saving", + default_filename=default, + default_extension="py", + wildcard="*.py", + flags = wx.SAVE | wx.OVERWRITE_PROMPT) + if not fileName: + return + + text = self.shell.GetText() + +## This isn't working currently... +## d = wx.MessageDialog(self,u'Save source code only?\nAnswering yes will only save lines starting with >>> and ...',u'Question', wx.YES_NO | wx.ICON_QUESTION) +## yes_no = d.ShowModal() +## if yes_no == wx.ID_YES: +## m = re.findall('^[>\.]{3,3} (.*)\r', text, re.MULTILINE | re.LOCALE) +## text = '\n'.join(m) +## d.Destroy() + + try: + f = open(fileName, "w") + f.write(text) + f.close() + except: + d = wx.MessageDialog(self, u'Error saving session',u'Error', + wx.OK | wx.ICON_ERROR) + d.ShowModal() + d.Destroy() + + + def EditStartupScript(self): + if os.path.exists(self.startupScript): + text = file(self.startupScript, 'U').read() + else: + text = '' + + dlg = EditStartupScriptDialog(self, self.startupScript, text) + if dlg.ShowModal() == wx.ID_OK: + text = dlg.GetText() + try: + f = file(self.startupScript, 'w') + f.write(text) + f.close() + except: + d = wx.MessageDialog(self, "Error saving startup file.", + "Error", wx.ICON_EXCLAMATION) + d.ShowModal() + d.Destroy() + + + +class EditStartupScriptDialog(wx.Dialog): + def __init__(self, parent, fileName, text): + wx.Dialog.__init__(self, parent, size=(425,350), + title="Edit Startup Script", + style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER) + + pst = wx.StaticText(self, -1, "Path:") + ptx = wx.TextCtrl(self, -1, fileName, style=wx.TE_READONLY) + self.editor = editwindow.EditWindow(self) + self.editor.SetText(text) + wx.CallAfter(self.editor.SetFocus) + + ok = wx.Button(self, wx.ID_OK) + cancel = wx.Button(self, wx.ID_CANCEL) + + mainSizer = wx.BoxSizer(wx.VERTICAL) + + pthSizer = wx.BoxSizer(wx.HORIZONTAL) + pthSizer.Add(pst, flag=wx.ALIGN_CENTER_VERTICAL) + pthSizer.Add((5,5)) + pthSizer.Add(ptx, 1) + mainSizer.Add(pthSizer, 0, wx.EXPAND|wx.ALL, 10) + + mainSizer.Add(self.editor, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 10) + + btnSizer = wx.BoxSizer(wx.HORIZONTAL) + btnSizer.Add((5,5), 1) + btnSizer.Add(ok) + btnSizer.Add((5,5), 1) + btnSizer.Add(cancel) + btnSizer.Add((5,5), 1) + mainSizer.Add(btnSizer, 0, wx.EXPAND|wx.ALL, 10) + + self.SetSizer(mainSizer) + self.Layout() + + + def GetText(self): + return self.editor.GetText() diff --git a/wxPython/wx/py/interpreter.py b/wxPython/wx/py/interpreter.py index 112344ad3f..4eef617272 100644 --- a/wxPython/wx/py/interpreter.py +++ b/wxPython/wx/py/interpreter.py @@ -42,7 +42,8 @@ class Interpreter(InteractiveInterpreter): self.more = 0 # List of lists to support recursive push(). self.commandBuffer = [] - self.startupScript = os.environ.get('PYTHONSTARTUP') + self.startupScript = None + def push(self, command): """Send command to the interpreter to be executed. diff --git a/wxPython/wx/py/shell.py b/wxPython/wx/py/shell.py index 8e1b0474f3..da3f2751d2 100644 --- a/wxPython/wx/py/shell.py +++ b/wxPython/wx/py/shell.py @@ -31,7 +31,7 @@ NAVKEYS = (wx.WXK_END, wx.WXK_LEFT, wx.WXK_RIGHT, wx.WXK_UP, wx.WXK_DOWN, wx.WXK_PRIOR, wx.WXK_NEXT) -class ShellFrame(frame.Frame): +class ShellFrame(frame.Frame, frame.ShellFrameMixin): """Frame containing the shell component.""" name = 'Shell Frame' @@ -40,19 +40,31 @@ class ShellFrame(frame.Frame): def __init__(self, parent=None, id=-1, title='PyShell', pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, locals=None, - InterpClass=None, *args, **kwds): + InterpClass=None, + config=None, dataDir=None, + *args, **kwds): """Create ShellFrame instance.""" frame.Frame.__init__(self, parent, id, title, pos, size, style) + frame.ShellFrameMixin.__init__(self, config, dataDir) + + if size == wx.DefaultSize: + self.SetSize((750, 525)) + intro = 'PyShell %s - The Flakiest Python Shell' % VERSION - intro += '\nSponsored by Orbtech - ' + \ - 'Your source for Python programming expertise.' self.SetStatusText(intro.replace('\n', ', ')) self.shell = Shell(parent=self, id=-1, introText=intro, locals=locals, InterpClass=InterpClass, + startupScript=self.startupScript, + execStartupScript=self.execStartupScript, *args, **kwds) + # Override the shell so that status messages go to the status bar. self.shell.setStatusText = self.SetStatusText + self.shell.SetFocus() + self.LoadSettings() + + def OnClose(self, event): """Event handler for closing.""" # This isn't working the way I want, but I'll leave it for now. @@ -60,6 +72,7 @@ class ShellFrame(frame.Frame): if event.CanVeto(): event.Veto(True) else: + self.SaveSettings() self.shell.destroy() self.Destroy() @@ -82,21 +95,28 @@ class ShellFrame(frame.Frame): dialog.Destroy() -class ShellFacade: - """Simplified interface to all shell-related functionality. + def LoadSettings(self): + if self.config is not None: + frame.ShellFrameMixin.LoadSettings(self) + frame.Frame.LoadSettings(self, self.config) + self.shell.LoadSettings(self.config) - This is a semi-transparent facade, in that all attributes of other - are accessible, even though only some are visible to the user.""" + def SaveSettings(self): + if self.config is not None: + frame.ShellFrameMixin.SaveSettings(self) + if self.autoSaveSettings: + frame.Frame.SaveSettings(self, self.config) + self.shell.SaveSettings(self.config) - name = 'Shell Interface' - revision = __revision__ + def DoSaveSettings(self): + if self.config is not None: + self.SaveSettings() + self.config.Flush() + - def __init__(self, other): - """Create a ShellFacade instance.""" - d = self.__dict__ - d['other'] = other - d['helpText'] = \ -""" + + +HELP_TEXT = """\ * Key bindings: Home Go to the beginning of the command or line. Shift+Home Select to the beginning of the command or line. @@ -104,6 +124,7 @@ Shift+End Select to the end of the line. End Go to the end of the line. Ctrl+C Copy selected text, removing prompts. Ctrl+Shift+C Copy selected text, retaining prompts. +Alt+C Copy to the clipboard, including prefixed prompts. Ctrl+X Cut selected text. Ctrl+V Paste from clipboard. Ctrl+Shift+V Paste and run multiple commands from clipboard. @@ -119,8 +140,31 @@ Ctrl+Enter Insert new line into multiline command. Ctrl+] Increase font size. Ctrl+[ Decrease font size. Ctrl+= Default font size. +Ctrl-Space Show Auto Completion. +Ctrl-Alt-Space Show Call Tip. +Alt+Shift+C Clear Screen. +Shift+Enter Complete Text from History. +Ctrl+F Search (backwards) TODO: regexp-wholeWords-... +Ctrl+G Search next +Ctrl+H "hide" lines containing selection / "unhide" +F12 on/off "free-edit" mode """ +class ShellFacade: + """Simplified interface to all shell-related functionality. + + This is a semi-transparent facade, in that all attributes of other + are accessible, even though only some are visible to the user.""" + + name = 'Shell Interface' + revision = __revision__ + + def __init__(self, other): + """Create a ShellFacade instance.""" + d = self.__dict__ + d['other'] = other + d['helpText'] = HELP_TEXT + def help(self): """Display some useful information about how to use the shell.""" self.write(self.helpText) @@ -151,6 +195,7 @@ Ctrl+= Default font size. 'autoCompleteIncludeDouble', 'autoCompleteIncludeMagic', 'autoCompleteIncludeSingle', + 'callTipInsert', 'clear', 'pause', 'prompt', @@ -167,6 +212,7 @@ Ctrl+= Default font size. return list + class Shell(editwindow.EditWindow): """Shell based on StyledTextCtrl.""" @@ -175,26 +221,32 @@ class Shell(editwindow.EditWindow): def __init__(self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.CLIP_CHILDREN, - introText='', locals=None, InterpClass=None, *args, **kwds): + introText='', locals=None, InterpClass=None, + startupScript=None, execStartupScript=True, + *args, **kwds): """Create Shell instance.""" editwindow.EditWindow.__init__(self, parent, id, pos, size, style) self.wrap() if locals is None: import __main__ locals = __main__.__dict__ + # Grab these so they can be restored by self.redirect* methods. self.stdin = sys.stdin self.stdout = sys.stdout self.stderr = sys.stderr + # Import a default interpreter class if one isn't provided. if InterpClass == None: from interpreter import Interpreter else: Interpreter = InterpClass + # Create a replacement for stdin. self.reader = PseudoFileIn(self.readline, self.readlines) self.reader.input = '' self.reader.isreading = False + # Set up the interpreter. self.interp = Interpreter(locals=locals, rawin=self.raw_input, @@ -202,15 +254,20 @@ class Shell(editwindow.EditWindow): stdout=PseudoFileOut(self.writeOut), stderr=PseudoFileErr(self.writeErr), *args, **kwds) + # Set up the buffer. self.buffer = Buffer() + # Find out for which keycodes the interpreter will autocomplete. self.autoCompleteKeys = self.interp.getAutoCompleteKeys() + # Keep track of the last non-continuation prompt positions. self.promptPosStart = 0 self.promptPosEnd = 0 + # Keep track of multi-line commands. self.more = False + # Create the command history. Commands are added into the # front of the list (ie. at index 0) as they are entered. # self.historyIndex is the current position in the history; it @@ -220,23 +277,46 @@ class Shell(editwindow.EditWindow): # command, not in the history. self.history = [] self.historyIndex = -1 + + #seb add mode for "free edit" + self.noteMode = 0 + self.MarkerDefine(0,stc.STC_MARK_ROUNDRECT) # marker for hidden + self.searchTxt = "" + # Assign handlers for keyboard events. - wx.EVT_CHAR(self, self.OnChar) - wx.EVT_KEY_DOWN(self, self.OnKeyDown) + self.Bind(wx.EVT_CHAR, self.OnChar) + self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown) + # Assign handler for idle time. self.waiting = False - wx.EVT_IDLE(self, self.OnIdle) + self.Bind(wx.EVT_IDLE, self.OnIdle) + # Display the introductory banner information. self.showIntro(introText) + # Assign some pseudo keywords to the interpreter's namespace. self.setBuiltinKeywords() + # Add 'shell' to the interpreter's local namespace. self.setLocalShell() + + ## NOTE: See note at bottom of this file... + ## #seb: File drag and drop + ## self.SetDropTarget( FileDropTarget(self) ) + # Do this last so the user has complete control over their # environment. They can override anything they want. - self.execStartupScript(self.interp.startupScript) + if execStartupScript: + if startupScript is None: + startupScript = os.environ.get('PYTHONSTARTUP') + self.execStartupScript(startupScript) + else: + self.prompt() + wx.CallAfter(self.ScrollToLine, 0) + + def destroy(self): del self.interp @@ -270,29 +350,32 @@ class Shell(editwindow.EditWindow): __builtin__.close = __builtin__.exit = __builtin__.quit = \ 'Click on the close button to leave the application.' + def quit(self): """Quit the application.""" - # XXX Good enough for now but later we want to send a close event. - # In the close event handler we can make sure they want to # quit. Other applications, like PythonCard, may choose to # hide rather than quit so we should just post the event and # let the surrounding app decide what it wants to do. self.write('Click on the close button to leave the application.') + def setLocalShell(self): """Add 'shell' to locals as reference to ShellFacade instance.""" self.interp.locals['shell'] = ShellFacade(other=self) + def execStartupScript(self, startupScript): """Execute the user's PYTHONSTARTUP script if they have one.""" if startupScript and os.path.isfile(startupScript): text = 'Startup script executed: ' + startupScript self.push('print %r; execfile(%r)' % (text, startupScript)) + self.interp.startupScript = startupScript else: self.push('') + def about(self): """Display information about Py.""" text = """ @@ -302,17 +385,24 @@ Py Shell Revision: %s Py Interpreter Revision: %s Python Version: %s wxPython Version: %s +wxPython PlatformInfo: %s Platform: %s""" % \ (__author__, VERSION, self.revision, self.interp.revision, - sys.version.split()[0], wx.VERSION_STRING, sys.platform) + sys.version.split()[0], wx.VERSION_STRING, str(wx.PlatformInfo), + sys.platform) self.write(text.strip()) + def OnChar(self, event): """Keypress event handler. Only receives an event if OnKeyDown calls event.Skip() for the corresponding event.""" + if self.noteMode: + event.Skip() + return + # Prevent modification of previously submitted # commands/responses. if not self.CanEdit(): @@ -343,11 +433,12 @@ Platform: %s""" % \ self.ReplaceSelection('') command = self.GetTextRange(stoppos, currpos) + '(' self.write('(') - self.autoCallTipShow(command) + self.autoCallTipShow(command, self.GetCurrentPos() == self.GetTextLength()) else: # Allow the normal event handling to take place. event.Skip() + def OnKeyDown(self, event): """Key down event handler.""" @@ -364,12 +455,64 @@ Platform: %s""" % \ currpos = self.GetCurrentPos() endpos = self.GetTextLength() selecting = self.GetSelectionStart() != self.GetSelectionEnd() + + if controlDown and key in (ord('H'), ord('h')): + li = self.GetCurrentLine() + m = self.MarkerGet(li) + if m & 1<<0: + startP = self.PositionFromLine(li) + self.MarkerDelete(li, 0) + maxli = self.GetLineCount() + li += 1 # li stayed visible as header-line + li0 = li + while li 1 (mix out "trash") + thlist = [] + for i in newlist: + if len (i) > 1: + thlist.append (i) + + #unique (no duplicate words + #oneliner from german python forum => unique list + unlist = [thlist[i] for i in xrange(len(thlist)) if thlist[i] not in thlist[:i]] + + #sort lowercase + unlist.sort(lambda a, b: cmp(a.lower(), b.lower())) + + #this is more convenient, isn't it? + self.AutoCompSetIgnoreCase(True) + + #join again together in a string + stringlist = " ".join(unlist) + + #pos von 0 noch ausrechnen + + #how big is the offset? + cpos = self.GetCurrentPos() - 1 + while chr (self.GetCharAt (cpos)).isalnum(): + cpos -= 1 + + #the most important part + self.AutoCompShow(self.GetCurrentPos() - cpos -1, stringlist) + + def clearCommand(self): """Delete the current, unexecuted command.""" startpos = self.promptPosEnd @@ -589,6 +778,7 @@ Platform: %s""" % \ self.write(os.linesep) else: self.push(command) + wx.FutureCall(1, self.EnsureCaretVisible) # Or replace the current command with the other command. else: # If the line contains a command (even an invalid one). @@ -665,9 +855,10 @@ Platform: %s""" % \ text = text[ps2size:] return text - def push(self, command): + def push(self, command, silent = False): """Send command to the interpreter for execution.""" - self.write(os.linesep) + if not silent: + self.write(os.linesep) busy = wx.BusyCursor() self.waiting = True self.more = self.interp.push(command) @@ -675,7 +866,8 @@ Platform: %s""" % \ del busy if not self.more: self.addHistory(command.rstrip()) - self.prompt() + if not silent: + self.prompt() def addHistory(self, command): """Add command to the command history.""" @@ -817,7 +1009,7 @@ Platform: %s""" % \ finally: file.close() - def autoCompleteShow(self, command): + def autoCompleteShow(self, command, offset = 0): """Display auto-completion popup list.""" self.AutoCompSetAutoHide(self.autoCompleteAutoHide) self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive) @@ -827,19 +1019,19 @@ Platform: %s""" % \ includeDouble=self.autoCompleteIncludeDouble) if list: options = ' '.join(list) - offset = 0 + #offset = 0 self.AutoCompShow(offset, options) - def autoCallTipShow(self, command): + def autoCallTipShow(self, command, insertcalltip = True, forceCallTip = False): """Display argument spec and docstring in a popup window.""" if self.CallTipActive(): self.CallTipCancel() (name, argspec, tip) = self.interp.getCallTip(command) if tip: dispatcher.send(signal='Shell.calltip', sender=self, calltip=tip) - if not self.autoCallTip: + if not self.autoCallTip and not forceCallTip: return - if argspec: + if argspec and insertcalltip and self.callTipInsert: startpos = self.GetCurrentPos() self.write(argspec + ')') endpos = self.GetCurrentPos() @@ -852,6 +1044,53 @@ Platform: %s""" % \ # fallback. tippos = max(tippos, fallback) self.CallTipShow(tippos, tip) + + def OnCallTipAutoCompleteManually (self, shiftDown): + """AutoComplete and Calltips manually.""" + if self.AutoCompActive(): + self.AutoCompCancel() + currpos = self.GetCurrentPos() + stoppos = self.promptPosEnd + + cpos = currpos + #go back until '.' is found + pointavailpos = -1 + while cpos >= stoppos: + if self.GetCharAt(cpos) == ord ('.'): + pointavailpos = cpos + break + cpos -= 1 + + #word from non whitespace until '.' + if pointavailpos != -1: + #look backward for first whitespace char + textbehind = self.GetTextRange (pointavailpos + 1, currpos) + pointavailpos += 1 + + if not shiftDown: + #call AutoComplete + stoppos = self.promptPosEnd + textbefore = self.GetTextRange(stoppos, pointavailpos) + self.autoCompleteShow(textbefore, len (textbehind)) + else: + #call CallTips + cpos = pointavailpos + begpos = -1 + while cpos > stoppos: + if chr(self.GetCharAt(cpos)).isspace(): + begpos = cpos + break + cpos -= 1 + if begpos == -1: + begpos = cpos + ctips = self.GetTextRange (begpos, currpos) + ctindex = ctips.find ('(') + if ctindex != -1 and not self.CallTipActive(): + #insert calltip, if current pos is '(', otherwise show it only + self.autoCallTipShow(ctips[:ctindex + 1], \ + self.GetCharAt(currpos - 1) == ord('(') and self.GetCurrentPos() == self.GetTextLength(),\ + True) + def writeOut(self, text): """Replacement for stdout.""" @@ -1034,3 +1273,101 @@ Platform: %s""" % \ This number of points is added to the size of all fonts. It may be positive to magnify or negative to reduce.""" self.SetZoom(points) + + + + def LoadSettings(self, config): + self.autoComplete = config.ReadBool('Options/AutoComplete', True) + self.autoCompleteIncludeMagic = config.ReadBool('Options/AutoCompleteIncludeMagic', True) + self.autoCompleteIncludeSingle = config.ReadBool('Options/AutoCompleteIncludeSingle', True) + self.autoCompleteIncludeDouble = config.ReadBool('Options/AutoCompleteIncludeDouble', True) + + self.autoCallTip = config.ReadBool('Options/AutoCallTip', True) + self.callTipInsert = config.ReadBool('Options/CallTipInsert', True) + self.SetWrapMode(config.ReadBool('View/WrapMode', True)) + + useAA = config.ReadBool('Options/UseAntiAliasing', self.GetUseAntiAliasing()) + self.SetUseAntiAliasing(useAA) + self.lineNumbers = config.ReadBool('View/ShowLineNumbers', True) + self.setDisplayLineNumbers (self.lineNumbers) + zoom = config.ReadInt('View/Zoom/Shell', -99) + if zoom != -99: + self.SetZoom(zoom) + + + + def SaveSettings(self, config): + config.WriteBool('Options/AutoComplete', self.autoComplete) + config.WriteBool('Options/AutoCompleteIncludeMagic', self.autoCompleteIncludeMagic) + config.WriteBool('Options/AutoCompleteIncludeSingle', self.autoCompleteIncludeSingle) + config.WriteBool('Options/AutoCompleteIncludeDouble', self.autoCompleteIncludeDouble) + config.WriteBool('Options/AutoCallTip', self.autoCallTip) + config.WriteBool('Options/CallTipInsert', self.callTipInsert) + config.WriteBool('Options/UseAntiAliasing', self.GetUseAntiAliasing()) + config.WriteBool('View/WrapMode', self.GetWrapMode()) + config.WriteBool('View/ShowLineNumbers', self.lineNumbers) + config.WriteInt('View/Zoom/Shell', self.GetZoom()) + + + +## NOTE: The DnD of file names is disabled until I can figure out how +## best to still allow DnD of text. + + +## #seb : File drag and drop +## class FileDropTarget(wx.FileDropTarget): +## def __init__(self, obj): +## wx.FileDropTarget.__init__(self) +## self.obj = obj +## def OnDropFiles(self, x, y, filenames): +## if len(filenames) == 1: +## txt = 'r\"%s\"' % filenames[0] +## else: +## txt = '( ' +## for f in filenames: +## txt += 'r\"%s\" , ' % f +## txt += ')' +## self.obj.AppendText(txt) +## pos = self.obj.GetCurrentPos() +## self.obj.SetCurrentPos( pos ) +## self.obj.SetSelection( pos, pos ) + + + +## class TextAndFileDropTarget(wx.DropTarget): +## def __init__(self, shell): +## wx.DropTarget.__init__(self) +## self.shell = shell +## self.compdo = wx.DataObjectComposite() +## self.textdo = wx.TextDataObject() +## self.filedo = wx.FileDataObject() +## self.compdo.Add(self.textdo) +## self.compdo.Add(self.filedo, True) + +## self.SetDataObject(self.compdo) + +## def OnDrop(self, x, y): +## return True + +## def OnData(self, x, y, result): +## self.GetData() +## if self.textdo.GetTextLength() > 1: +## text = self.textdo.GetText() +## # *** Do somethign with the dragged text here... +## self.textdo.SetText('') +## else: +## filenames = str(self.filename.GetFilenames()) +## if len(filenames) == 1: +## txt = 'r\"%s\"' % filenames[0] +## else: +## txt = '( ' +## for f in filenames: +## txt += 'r\"%s\" , ' % f +## txt += ')' +## self.shell.AppendText(txt) +## pos = self.shell.GetCurrentPos() +## self.shell.SetCurrentPos( pos ) +## self.shell.SetSelection( pos, pos ) + +## return result + diff --git a/wxPython/wx/py/version.py b/wxPython/wx/py/version.py index 76a8cd87dc..c0a5f5d4c1 100644 --- a/wxPython/wx/py/version.py +++ b/wxPython/wx/py/version.py @@ -6,4 +6,4 @@ __author__ = "Patrick K. O'Brien " __cvsid__ = "$Id$" __revision__ = "$Revision$"[11:-2] -VERSION = '0.9.4' +VERSION = '0.9.5' diff --git a/wxPython/wxPython/_core.py b/wxPython/wxPython/_core.py index d1bf8af940..980c02a6c2 100644 --- a/wxPython/wxPython/_core.py +++ b/wxPython/wxPython/_core.py @@ -107,6 +107,7 @@ wxSIZE_AUTO_HEIGHT = wx._core.SIZE_AUTO_HEIGHT wxSIZE_AUTO = wx._core.SIZE_AUTO wxSIZE_USE_EXISTING = wx._core.SIZE_USE_EXISTING wxSIZE_ALLOW_MINUS_ONE = wx._core.SIZE_ALLOW_MINUS_ONE +wxSIZE_FORCE = wx._core.SIZE_FORCE wxPORTRAIT = wx._core.PORTRAIT wxLANDSCAPE = wx._core.LANDSCAPE wxPRINT_QUALITY_HIGH = wx._core.PRINT_QUALITY_HIGH @@ -115,6 +116,7 @@ wxPRINT_QUALITY_LOW = wx._core.PRINT_QUALITY_LOW wxPRINT_QUALITY_DRAFT = wx._core.PRINT_QUALITY_DRAFT wxID_ANY = wx._core.ID_ANY wxID_SEPARATOR = wx._core.ID_SEPARATOR +wxID_NONE = wx._core.ID_NONE wxID_LOWEST = wx._core.ID_LOWEST wxID_OPEN = wx._core.ID_OPEN wxID_CLOSE = wx._core.ID_CLOSE @@ -619,8 +621,12 @@ wxHT_MAX = wx._core.HT_MAX wxMOD_NONE = wx._core.MOD_NONE wxMOD_ALT = wx._core.MOD_ALT wxMOD_CONTROL = wx._core.MOD_CONTROL +wxMOD_ALTGR = wx._core.MOD_ALTGR wxMOD_SHIFT = wx._core.MOD_SHIFT +wxMOD_META = wx._core.MOD_META wxMOD_WIN = wx._core.MOD_WIN +wxMOD_CMD = wx._core.MOD_CMD +wxMOD_ALL = wx._core.MOD_ALL wxUPDATE_UI_NONE = wx._core.UPDATE_UI_NONE wxUPDATE_UI_RECURSE = wx._core.UPDATE_UI_RECURSE wxUPDATE_UI_FROMIDLE = wx._core.UPDATE_UI_FROMIDLE @@ -732,6 +738,8 @@ wxIMAGE_ALPHA_THRESHOLD = wx._core.IMAGE_ALPHA_THRESHOLD wxIMAGE_ALPHA_OPAQUE = wx._core.IMAGE_ALPHA_OPAQUE wxImageHandler = wx._core.ImageHandler wxImageHandlerPtr = wx._core.ImageHandlerPtr +wxPyImageHandler = wx._core.PyImageHandler +wxPyImageHandlerPtr = wx._core.PyImageHandlerPtr wxImageHistogram = wx._core.ImageHistogram wxImageHistogramPtr = wx._core.ImageHistogramPtr wxImageHistogram_MakeKey = wx._core.ImageHistogram_MakeKey -- 2.45.2