--- /dev/null
+import wx
+
+class App(wx.App):
+
+ def OnInit(self):
+ frame = wx.Frame(parent=None, title='Bare')
+ frame.Show()
+ return True
+
+app = App()
+app.MainLoop()
--- /dev/null
+#!/usr/bin/env python
+
+"""Hello, wxPython! program."""
+
+import wx
+
+class Frame(wx.Frame):
+ """Frame class that displays an image."""
+
+ def __init__(self, image, parent=None, id=-1,
+ pos=wx.DefaultPosition, title='Hello, wxPython!'):
+ """Create a Frame instance and display image."""
+ temp = image.ConvertToBitmap()
+ size = temp.GetWidth(), temp.GetHeight()
+ wx.Frame.__init__(self, parent, id, title, pos, size)
+ panel = wx.Panel(self)
+ self.bmp = wx.StaticBitmap(parent=panel, bitmap=temp)
+ self.SetClientSize(size)
+
+class App(wx.App):
+ """Application class."""
+
+ def OnInit(self):
+ image = wx.Image('wxPython.jpg', wx.BITMAP_TYPE_JPEG)
+ self.frame = Frame(image)
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+def main():
+ app = App()
+ app.MainLoop()
+
+if __name__ == '__main__':
+ main()
+
--- /dev/null
+import wx
+
+class MyApp(wx.App):
+
+ def OnInit(self):
+ frame = MyFrame("Hello World", (50, 60), (450, 340))
+ frame.Show()
+ self.SetTopWindow(frame)
+ return True
+
+class MyFrame(wx.Frame):
+
+ def __init__(self, title, pos, size):
+ wx.Frame.__init__(self, None, -1, title, pos, size)
+ menuFile = wx.Menu()
+ menuFile.Append(1, "&About...")
+ menuFile.AppendSeparator()
+ menuFile.Append(2, "E&xit")
+ menuBar = wx.MenuBar()
+ menuBar.Append(menuFile, "&File")
+ self.SetMenuBar(menuBar)
+ self.CreateStatusBar()
+ self.SetStatusText("Welcome to wxPython!")
+ self.Bind(wx.EVT_MENU, self.OnAbout, id=1)
+ self.Bind(wx.EVT_MENU, self.OnQuit, id=2)
+
+ def OnQuit(self, event):
+ self.Close()
+
+ def OnAbout(self, event):
+ wx.MessageBox("This is a wxPython Hello world sample",
+ "About Hello World", wx.OK | wx.ICON_INFORMATION, self)
+
+if __name__ == '__main__':
+ app = MyApp(False)
+ app.MainLoop()
--- /dev/null
+#!/bin/env python
+import wx
+
+class MyFrame(wx.Frame):
+
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "My Frame", size=(300, 300))
+ panel = wx.Panel(self, -1)
+ panel.Bind(wx.EVT_MOTION, self.OnMove)
+ wx.StaticText(panel, -1, "Pos:", pos=(10, 12))
+ self.posCtrl = wx.TextCtrl(panel, -1, "", pos=(40, 10))
+
+ def OnMove(self, event):
+ pos = event.GetPosition()
+ self.posCtrl.SetValue("%s, %s" % (pos.x, pos.y))
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show(True)
+ app.MainLoop()
--- /dev/null
+#!/usr/bin/env python
+
+"""Spare.py is a starting point for simple wxPython programs."""
+
+import wx
+
+class Frame(wx.Frame):
+ pass
+
+class App(wx.App):
+
+ def OnInit(self):
+ self.frame = Frame(parent=None, title='Spare')
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+if __name__ == '__main__':
+ app = App()
+ app.MainLoop()
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+import images
+
+class App(wx.App):
+
+ def __init__(self, redirect=True, filename=None):
+ wx.App.__init__(self, redirect, filename)
+
+ def OnInit(self):
+ dlg = wx.MessageDialog(None, 'Is this the coolest thing ever!',
+ 'MessageDialog', wx.YES_NO | wx.ICON_QUESTION)
+ result = dlg.ShowModal()
+ dlg.Destroy()
+
+ dlg = wx.TextEntryDialog(None, "Who is buried in Grant's tomb?",
+ 'A Question', 'Cary Grant')
+ if dlg.ShowModal() == wx.ID_OK:
+ response = dlg.GetValue()
+ dlg.Destroy()
+
+ dlg = wx.SingleChoiceDialog(None,
+ 'What version of Python are you using?', 'Single Choice',
+ ['1.5.2', '2.0', '2.1.3', '2.2', '2.3.1'])
+ if dlg.ShowModal() == wx.ID_OK:
+ response = dlg.GetStringSelection()
+ dlg.Destroy()
+
+ return True
+
+
+if __name__ == '__main__':
+ app = App(False, "output")
+ fred = app.MainLoop()
+
--- /dev/null
+#----------------------------------------------------------------------
+# This file was generated by encode_bitmaps.py
+#
+from wx import ImageFromStream, BitmapFromImage
+from wx import EmptyIcon
+import cStringIO
+
+def getNewData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x0f\x08\x06\
+\x00\x00\x00\xedsO/\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
+\x00YIDATx\x9c\xed\xd31\n@!\x0c\x03\xd0\xa4\xfe\xfb\xdfX\xe3\xf0\x97R\xa5(.\
+\x0ef\x13\xe45\xa2\x92Vp\x92\xcf/\xd4\xaa\xb2\xcd\xb4\xc2\x14\x00\x00in\x90\
+\x84ZUDl\xa9\xa7\xc3c\xcb-\x80\xfc\x87{d8B6=B\xdb\rfy\xc0\r\xc0\xf0\x0e\xfc\
+\x1d\xaf\x84\xa7\xbf\xb1\x03\xe1,\x19&\x93\x9a\xd2\x97\x00\x00\x00\x00IEND\
+\xaeB`\x82'
+
+def getNewBitmap():
+ return BitmapFromImage(getNewImage())
+
+def getNewImage():
+ stream = cStringIO.StringIO(getNewData())
+ return ImageFromStream(stream)
+
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+
+class InsertFrame(wx.Frame):
+
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Frame With Button',
+ size=(300, 100))
+ panel = wx.Panel(self)
+ button = wx.Button(panel, label="Close", pos=(125, 10),
+ size=(50, 50))
+ self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ def OnCloseMe(self, event):
+ self.Close(True)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = InsertFrame(parent=None, id=-1)
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+import sys
+
+class Frame(wx.Frame):
+
+ def __init__(self, parent, id, title):
+ print "Frame __init__"
+ wx.Frame.__init__(self, parent, id, title)
+
+class App(wx.App):
+
+ def __init__(self, redirect=True, filename=None):
+ print "App __init__"
+ wx.App.__init__(self, redirect, filename)
+
+ def OnInit(self):
+ print "OnInit"
+ self.frame = Frame(parent=None, id=-1, title='Startup')
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ print >> sys.stderr, "A pretend error message"
+ print "app name: <", self.GetVendorName(), ">"
+ return True
+
+ def OnExit(self):
+ print "OnExit"
+
+if __name__ == '__main__':
+ app = App(redirect=True)
+ print "before MainLoop"
+ fred = app.MainLoop()
+ print "after MainLoop", fred
+
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+import images
+
+class ToolbarFrame(wx.Frame):
+
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Toolbars',
+ size=(300, 200))
+ panel = wx.Panel(self)
+ panel.SetBackgroundColour('White')
+ statusBar = self.CreateStatusBar()
+ toolbar = self.CreateToolBar()
+ toolbar.AddSimpleTool(wx.NewId(), images.getNewBitmap(),
+ "New", "Long help for 'New'")
+ toolbar.Realize()
+ menuBar = wx.MenuBar()
+ menu1 = wx.Menu()
+ menuBar.Append(menu1, "&File")
+ menu2 = wx.Menu()
+ menu2.Append(wx.NewId(), "&Copy", "Copy in status bar")
+ menu2.Append(wx.NewId(), "C&ut", "")
+ menu2.Append(wx.NewId(), "Paste", "")
+ menu2.AppendSeparator()
+ menu2.Append(wx.NewId(), "&Options...", "Display Options")
+ menuBar.Append(menu2, "&Edit")
+ self.SetMenuBar(menuBar)
+
+ def OnCloseMe(self, event):
+ self.Close(True)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = ToolbarFrame(parent=None, id=-1)
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+import wx
+
+class TwoButtonEvent(wx.PyCommandEvent):
+ def __init__(self, evtType, id):
+ wx.PyCommandEvent.__init__(self, evtType, id)
+ self.clickCount = 0
+
+ def GetClickCount(self):
+ return self.clickCount
+
+ def SetClickCount(self, count):
+ self.clickCount = count
+
+myEVT_TWO_BUTTON = wx.NewEventType()
+EVT_TWO_BUTTON = wx.PyEventBinder(myEVT_TWO_BUTTON, 1)
+
+class TwoButtonPanel(wx.Panel):
+ def __init__(self, parent, id=-1, leftText="Left",
+ rightText="Right"):
+ wx.Panel.__init__(self, parent, id)
+ self.leftButton = wx.Button(self, label=leftText)
+ self.rightButton = wx.Button(self, label=rightText,
+ pos=(100,0))
+ self.leftClick = False
+ self.rightClick = False
+ self.clickCount = 0
+ self.leftButton.Bind(wx.EVT_LEFT_DOWN, self.OnLeftClick)
+ self.rightButton.Bind(wx.EVT_LEFT_DOWN, self.OnRightClick)
+
+ def OnLeftClick(self, event):
+ self.leftClick = True
+ self.OnClick()
+ event.Skip()
+
+ def OnRightClick(self, event):
+ self.rightClick = True
+ self.OnClick()
+ event.Skip()
+
+ def OnClick(self):
+ self.clickCount += 1
+ if self.leftClick and self.rightClick:
+ self.leftClick = False
+ self.rightClick = False
+ evt = TwoButtonEvent(myEVT_TWO_BUTTON, self.GetId())
+ evt.SetClickCount(self.clickCount)
+ self.GetEventHandler().ProcessEvent(evt)
+
+
+class CustomEventFrame(wx.Frame):
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Click Count: 0',
+ size=(300, 100))
+ panel = TwoButtonPanel(self)
+ self.Bind(EVT_TWO_BUTTON, self.OnTwoClick, panel)
+
+ def OnTwoClick(self, event):
+ self.SetTitle("Click Count: %s" % event.GetClickCount())
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = CustomEventFrame(parent=None, id=-1)
+ frame.Show()
+ app.MainLoop()
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+
+class DoubleEventFrame(wx.Frame):
+
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Frame With Button',
+ size=(300, 100))
+ self.panel = wx.Panel(self, -1)
+ self.button = wx.Button(self.panel, -1, "Click Me", pos=(100, 15))
+ self.Bind(wx.EVT_BUTTON, self.OnButtonClick, self.button)
+ self.button.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
+
+ def OnButtonClick(self, event):
+ self.panel.SetBackgroundColour('Green')
+ self.panel.Refresh()
+
+ def OnMouseDown(self, event):
+ self.button.SetLabel("Again!")
+ event.Skip()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = DoubleEventFrame(parent=None, id=-1)
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+
+class MenuEventFrame(wx.Frame):
+
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Menus', size=(300, 200))
+ menuBar = wx.MenuBar()
+ menu1 = wx.Menu()
+ menuItem = menu1.Append(-1, "&Exit...")
+ menuBar.Append(menu1, "&File")
+ self.SetMenuBar(menuBar)
+ self.Bind(wx.EVT_MENU, self.OnCloseMe, menuItem)
+
+ def OnCloseMe(self, event):
+ self.Close(True)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = MenuEventFrame(parent=None, id=-1)
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+
+class MouseEventFrame(wx.Frame):
+
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Frame With Button',
+ size=(300, 100))
+ self.panel = wx.Panel(self)
+ self.button = wx.Button(self.panel, label="Not Over", pos=(100, 15))
+ self.Bind(wx.EVT_BUTTON, self.OnButtonClick, self.button)
+ self.button.Bind(wx.EVT_ENTER_WINDOW, self.OnEnterWindow)
+ self.button.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow)
+
+ def OnButtonClick(self, event):
+ self.panel.SetBackgroundColour('Green')
+ self.panel.Refresh()
+
+ def OnEnterWindow(self, event):
+ self.button.SetLabel("Over Me!")
+ event.Skip()
+
+ def OnLeaveWindow(self, event):
+ self.button.SetLabel("Not Over")
+ event.Skip()
+
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = MouseEventFrame(parent=None, id=-1)
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+"""PyWrap is a command line utility that runs a wxPython program with
+additional runtime-tools, such as PyCrust."""
+
+__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
+__cvsid__ = "$Id$"
+__revision__ = "$Revision$"[11:-2]
+
+import wx
+from wx import py
+
+import os
+import sys
+
+def wrap(app):
+ wx.InitAllImageHandlers()
+ frame = py.crust.CrustFrame()
+ frame.SetSize((750, 525))
+ frame.Show(True)
+ frame.shell.interp.locals['app'] = app
+ app.MainLoop()
+
+def main(modulename=None):
+ sys.path.insert(0, os.curdir)
+ if not modulename:
+ if len(sys.argv) < 2:
+ print "Please specify a module name."
+ raise SystemExit
+ modulename = sys.argv[1]
+ if modulename.endswith('.py'):
+ modulename = modulename[:-3]
+ module = __import__(modulename)
+ # Find the App class.
+ App = None
+ d = module.__dict__
+ for item in d.keys():
+ try:
+ if issubclass(d[item], wx.App):
+ App = d[item]
+ except (NameError, TypeError):
+ pass
+ if App is None:
+ print "No App class was found."
+ raise SystemExit
+ app = App()
+ wrap(app)
+
+if __name__ == '__main__':
+ main()
--- /dev/null
+#----------------------------------------------------------------------
+# This file was generated by encode_bitmaps.py
+#
+from wx import ImageFromStream, BitmapFromImage
+from wx import EmptyIcon
+import cStringIO
+
+def getNewData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x0f\x08\x06\
+\x00\x00\x00\xedsO/\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\
+\x00YIDATx\x9c\xed\xd31\n@!\x0c\x03\xd0\xa4\xfe\xfb\xdfX\xe3\xf0\x97R\xa5(.\
+\x0ef\x13\xe45\xa2\x92Vp\x92\xcf/\xd4\xaa\xb2\xcd\xb4\xc2\x14\x00\x00in\x90\
+\x84ZUDl\xa9\xa7\xc3c\xcb-\x80\xfc\x87{d8B6=B\xdb\rfy\xc0\r\xc0\xf0\x0e\xfc\
+\x1d\xaf\x84\xa7\xbf\xb1\x03\xe1,\x19&\x93\x9a\xd2\x97\x00\x00\x00\x00IEND\
+\xaeB`\x82'
+
+def getNewBitmap():
+ return BitmapFromImage(getNewImage())
+
+def getNewImage():
+ stream = cStringIO.StringIO(getNewData())
+ return ImageFromStream(stream)
+
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+from wx.py.shell import ShellFrame
+from wx.py.filling import FillingFrame
+import images
+
+class ToolbarFrame(wx.Frame):
+
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Toolbars',
+ size=(300, 200))
+ panel = wx.Panel(self, -1)
+ panel.SetBackgroundColour('White')
+ statusBar = self.CreateStatusBar()
+ toolbar = self.CreateToolBar()
+ toolbar.AddSimpleTool(wx.NewId(), images.getNewBitmap(),
+ "New", "Long help for 'New'")
+ toolbar.Realize()
+ menuBar = wx.MenuBar()
+ menu1 = wx.Menu()
+ menuBar.Append(menu1, "&File")
+ menu2 = wx.Menu()
+ menu2.Append(wx.NewId(), "&Copy", "Copy in status bar")
+ menu2.Append(wx.NewId(), "C&ut", "")
+ menu2.Append(wx.NewId(), "Paste", "")
+ menu2.AppendSeparator()
+ menu2.Append(wx.NewId(), "&Options...", "Display Options")
+ menuBar.Append(menu2, "&Edit")
+
+ menu3 = wx.Menu()
+ shell = menu3.Append(-1, "&Python shell",
+ "Open Python shell frame")
+ filling = menu3.Append(-1, "&Namespace viewer",
+ "Open namespace viewer frame")
+ menuBar.Append(menu3, "&Debug")
+ self.Bind(wx.EVT_MENU, self.OnShell, shell)
+ self.Bind(wx.EVT_MENU, self.OnFilling, filling)
+
+ self.SetMenuBar(menuBar)
+
+ def OnCloseMe(self, event):
+ self.Close(True)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+ def OnShell(self, event):
+ frame = ShellFrame(parent=self)
+ frame.Show()
+
+ def OnFilling(self, event):
+ frame = FillingFrame(parent=self)
+ frame.Show()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ app.frame = ToolbarFrame(parent=None, id=-1)
+ app.frame.Show()
+ app.MainLoop()
--- /dev/null
+#!/usr/bin/env python
+
+from wx.py.PyWrap import main
+main()
--- /dev/null
+#!/usr/bin/env python
+
+"""Spare.py is a starting point for simple wxPython programs."""
+
+import wx
+
+class Frame(wx.Frame):
+ pass
+
+class App(wx.App):
+
+ def OnInit(self):
+ self.frame = Frame(parent=None, id=-1, title='Spare')
+ self.frame.Show()
+ self.SetTopWindow(self.frame)
+ return True
+
+if __name__ == '__main__':
+ app = App()
+ app.MainLoop()
--- /dev/null
+class AbstractModel(object):
+
+ def __init__(self):
+ self.listeners = []
+
+ def addListener(self, listenerFunc):
+ self.listeners.append(listenerFunc)
+
+ def removeListener(self, listenerFunc):
+ self.listeners.remove(listenerFunc)
+
+ def update(self):
+ for eachFunc in self.listeners:
+ eachFunc(self)
+
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+
+class RefactorExample(wx.Frame):
+
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Refactor Example',
+ size=(340, 200))
+ panel = wx.Panel(self, -1)
+ panel.SetBackgroundColour("White")
+ prevButton = wx.Button(panel, -1, "<< PREV", pos=(80, 0))
+ self.Bind(wx.EVT_BUTTON, self.OnPrev, prevButton)
+ nextButton = wx.Button(panel, -1, "NEXT >>", pos=(160, 0))
+ self.Bind(wx.EVT_BUTTON, self.OnNext, nextButton)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ menuBar = wx.MenuBar()
+ menu1 = wx.Menu()
+ openMenuItem = menu1.Append(-1, "&Open", "Copy in status bar")
+ self.Bind(wx.EVT_MENU, self.OnOpen, openMenuItem)
+ quitMenuItem = menu1.Append(-1, "&Quit", "Quit")
+ self.Bind(wx.EVT_MENU, self.OnCloseWindow, quitMenuItem)
+ menuBar.Append(menu1, "&File")
+ menu2 = wx.Menu()
+ copyItem = menu2.Append(-1, "&Copy", "Copy")
+ self.Bind(wx.EVT_MENU, self.OnCopy, copyItem)
+ cutItem = menu2.Append(-1, "C&ut", "Cut")
+ self.Bind(wx.EVT_MENU, self.OnCut, cutItem)
+ pasteItem = menu2.Append(-1, "Paste", "Paste")
+ self.Bind(wx.EVT_MENU, self.OnPaste, pasteItem)
+ menuBar.Append(menu2, "&Edit")
+ self.SetMenuBar(menuBar)
+
+ static = wx.StaticText(panel, wx.NewId(), "First Name",
+ pos=(10, 50))
+ static.SetBackgroundColour("White")
+ text = wx.TextCtrl(panel, wx.NewId(), "", size=(100, -1),
+ pos=(80, 50))
+
+ static2 = wx.StaticText(panel, wx.NewId(), "Last Name",
+ pos=(10, 80))
+ static2.SetBackgroundColour("White")
+ text2 = wx.TextCtrl(panel, wx.NewId(), "", size=(100, -1),
+ pos=(80, 80))
+
+ firstButton = wx.Button(panel, -1, "FIRST")
+ self.Bind(wx.EVT_BUTTON, self.OnFirst, firstButton)
+
+ menu2.AppendSeparator()
+ optItem = menu2.Append(-1, "&Options...", "Display Options")
+ self.Bind(wx.EVT_MENU, self.OnOptions, optItem)
+
+ lastButton = wx.Button(panel, -1, "LAST", pos=(240, 0))
+ self.Bind(wx.EVT_BUTTON, self.OnLast, lastButton)
+
+
+ # Just grouping the empty event handlers together
+ def OnPrev(self, event): pass
+ def OnNext(self, event): pass
+ def OnLast(self, event): pass
+ def OnFirst(self, event): pass
+ def OnOpen(self, event): pass
+ def OnCopy(self, event): pass
+ def OnCut(self, event): pass
+ def OnPaste(self, event): pass
+ def OnOptions(self, event): pass
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = RefactorExample(parent=None, id=-1)
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+import wx
+import wx.grid
+
+class GenericTable(wx.grid.PyGridTableBase):
+
+ def __init__(self, data, rowLabels=None, colLabels=None):
+ wx.grid.PyGridTableBase.__init__(self)
+ self.data = data
+ self.rowLabels = rowLabels
+ self.colLabels = colLabels
+
+ def GetNumberRows(self):
+ return len(self.data)
+
+ def GetNumberCols(self):
+ return len(self.data[0])
+
+ def GetColLabelValue(self, col):
+ if self.colLabels:
+ return self.colLabels[col]
+
+ def GetRowLabelValue(self, row):
+ if self.rowLabels:
+ return self.rowLabels[row]
+
+ def IsEmptyCell(self, row, col):
+ return False
+
+ def GetValue(self, row, col):
+ return self.data[row][col]
+
+ def SetValue(self, row, col, value):
+ pass
+
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+
+class RefactorExample(wx.Frame):
+
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Refactor Example',
+ size=(340, 200))
+ panel = wx.Panel(self, -1)
+ panel.SetBackgroundColour("White")
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.createMenuBar()
+ self.createButtonBar(panel)
+ self.createTextFields(panel)
+
+ def menuData(self):
+ return (("&File",
+ ("&Open", "Open in status bar", self.OnOpen),
+ ("&Quit", "Quit", self.OnCloseWindow)),
+ ("&Edit",
+ ("&Copy", "Copy", self.OnCopy),
+ ("C&ut", "Cut", self.OnCut),
+ ("&Paste", "Paste", self.OnPaste),
+ ("", "", ""),
+ ("&Options...", "DisplayOptions", self.OnOptions)))
+
+ def createMenuBar(self):
+ menuBar = wx.MenuBar()
+ for eachMenuData in self.menuData():
+ menuLabel = eachMenuData[0]
+ menuItems = eachMenuData[1:]
+ menuBar.Append(self.createMenu(menuItems), menuLabel)
+ self.SetMenuBar(menuBar)
+
+ def createMenu(self, menuData):
+ menu = wx.Menu()
+ for eachLabel, eachStatus, eachHandler in menuData:
+ if not eachLabel:
+ menu.AppendSeparator()
+ continue
+ menuItem = menu.Append(-1, eachLabel, eachStatus)
+ self.Bind(wx.EVT_MENU, eachHandler, menuItem)
+ return menu
+
+ def buttonData(self):
+ return (("First", self.OnFirst),
+ ("<< PREV", self.OnPrev),
+ ("NEXT >>", self.OnNext),
+ ("Last", self.OnLast))
+
+ def createButtonBar(self, panel, yPos = 0):
+ xPos = 0
+ for eachLabel, eachHandler in self.buttonData():
+ pos = (xPos, yPos)
+ button = self.buildOneButton(panel, eachLabel, eachHandler, pos)
+ xPos += button.GetSize().width
+
+ def buildOneButton(self, parent, label, handler, pos=(0,0)):
+ button = wx.Button(parent, -1, label, pos)
+ self.Bind(wx.EVT_BUTTON, handler, button)
+ return button
+
+ def textFieldData(self):
+ return (("First Name", (10, 50)),
+ ("Last Name", (10, 80)))
+
+ def createTextFields(self, panel):
+ for eachLabel, eachPos in self.textFieldData():
+ self.createCaptionedText(panel, eachLabel, eachPos)
+
+ def createCaptionedText(self, panel, label, pos):
+ static = wx.StaticText(panel, wx.NewId(), label, pos)
+ static.SetBackgroundColour("White")
+ textPos = (pos[0] + 75, pos[1])
+ wx.TextCtrl(panel, wx.NewId(), "", size=(100, -1), pos=textPos)
+
+ # Just grouping the empty event handlers together
+ def OnPrev(self, event): pass
+ def OnNext(self, event): pass
+ def OnLast(self, event): pass
+ def OnFirst(self, event): pass
+ def OnOpen(self, event): pass
+ def OnCopy(self, event): pass
+ def OnCut(self, event): pass
+ def OnPaste(self, event): pass
+ def OnOptions(self, event): pass
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = RefactorExample(parent=None, id=-1)
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+import wx
+import wx.grid
+import generictable
+
+
+data = (("Bob", "Dernier"), ("Ryne", "Sandberg"),
+ ("Gary", "Matthews"), ("Leon", "Durham"),
+ ("Keith", "Moreland"), ("Ron", "Cey"),
+ ("Jody", "Davis"), ("Larry", "Bowa"),
+ ("Rick", "Sutcliffe"))
+
+colLabels = ("Last", "First")
+rowLabels = ("CF", "2B", "LF", "1B", "RF", "3B", "C", "SS", "P")
+
+
+class SimpleGrid(wx.grid.Grid):
+ def __init__(self, parent):
+ wx.grid.Grid.__init__(self, parent, -1)
+ tableBase = generictable.GenericTable(data, rowLabels,
+ colLabels)
+ self.SetTable(tableBase)
+
+class TestFrame(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, "A Grid",
+ size=(275, 275))
+ grid = SimpleGrid(self)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = TestFrame(None)
+ frame.Show(True)
+ app.MainLoop()
+
--- /dev/null
+import wx
+import wx.grid
+
+class LineupTable(wx.grid.PyGridTableBase):
+
+ data = (("CF", "Bob", "Dernier"), ("2B", "Ryne", "Sandberg"),
+ ("LF", "Gary", "Matthews"), ("1B", "Leon", "Durham"),
+ ("RF", "Keith", "Moreland"), ("3B", "Ron", "Cey"),
+ ("C", "Jody", "Davis"), ("SS", "Larry", "Bowa"),
+ ("P", "Rick", "Sutcliffe"))
+
+ colLabels = ("Last", "First")
+
+ def __init__(self):
+ wx.grid.PyGridTableBase.__init__(self)
+
+ def GetNumberRows(self):
+ return len(self.data)
+
+ def GetNumberCols(self):
+ return len(self.data[0]) - 1
+
+ def GetColLabelValue(self, col):
+ return self.colLabels[col]
+
+ def GetRowLabelValue(self, row):
+ return self.data[row][0]
+
+ def IsEmptyCell(self, row, col):
+ return False
+
+ def GetValue(self, row, col):
+ return self.data[row][col + 1]
+
+ def SetValue(self, row, col, value):
+ pass
+
+class SimpleGrid(wx.grid.Grid):
+ def __init__(self, parent):
+ wx.grid.Grid.__init__(self, parent, -1)
+ self.SetTable(LineupTable())
+
+class TestFrame(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, "A Grid",
+ size=(275, 275))
+ grid = SimpleGrid(self)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = TestFrame(None)
+ frame.Show(True)
+ app.MainLoop()
+
--- /dev/null
+import wx
+import wx.grid
+
+class SimpleGrid(wx.grid.Grid):
+ def __init__(self, parent):
+ wx.grid.Grid.__init__(self, parent, -1)
+ self.CreateGrid(9, 2)
+ self.SetColLabelValue(0, "First")
+ self.SetColLabelValue(1, "Last")
+ self.SetRowLabelValue(0, "CF")
+ self.SetCellValue(0, 0, "Bob")
+ self.SetCellValue(0, 1, "Dernier")
+ self.SetRowLabelValue(1, "2B")
+ self.SetCellValue(1, 0, "Ryne")
+ self.SetCellValue(1, 1, "Sandberg")
+ self.SetRowLabelValue(2, "LF")
+ self.SetCellValue(2, 0, "Gary")
+ self.SetCellValue(2, 1, "Matthews")
+ self.SetRowLabelValue(3, "1B")
+ self.SetCellValue(3, 0, "Leon")
+ self.SetCellValue(3, 1, "Durham")
+ self.SetRowLabelValue(4, "RF")
+ self.SetCellValue(4, 0, "Keith")
+ self.SetCellValue(4, 1, "Moreland")
+ self.SetRowLabelValue(5, "3B")
+ self.SetCellValue(5, 0, "Ron")
+ self.SetCellValue(5, 1, "Cey")
+ self.SetRowLabelValue(6, "C")
+ self.SetCellValue(6, 0, "Jody")
+ self.SetCellValue(6, 1, "Davis")
+ self.SetRowLabelValue(7, "SS")
+ self.SetCellValue(7, 0, "Larry")
+ self.SetCellValue(7, 1, "Bowa")
+ self.SetRowLabelValue(8, "P")
+ self.SetCellValue(8, 0, "Rick")
+ self.SetCellValue(8, 1, "Sutcliffe")
+
+class TestFrame(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, "A Grid",
+ size=(275, 275))
+ grid = SimpleGrid(self)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = TestFrame(None)
+ frame.Show(True)
+ app.MainLoop()
+
--- /dev/null
+import wx
+import wx.grid
+
+class LineupEntry:
+
+ def __init__(self, pos, first, last):
+ self.pos = pos
+ self.first = first
+ self.last = last
+
+class LineupTable(wx.grid.PyGridTableBase):
+
+ colLabels = ("First", "Last")
+ colAttrs = ("first", "last")
+
+ def __init__(self, entries):
+ wx.grid.PyGridTableBase.__init__(self)
+ self.entries = entries
+
+ def GetNumberRows(self):
+ return len(self.entries)
+
+ def GetNumberCols(self):
+ return 2
+
+ def GetColLabelValue(self, col):
+ return self.colLabels[col]
+
+ def GetRowLabelValue(self, col):
+ return self.entries[row].pos
+
+ def IsEmptyCell(self, row, col):
+ return False
+
+ def GetValue(self, row, col):
+ entry = self.entries[row]
+ return getattr(entry, self.colAttrs[col])
+
+ def SetValue(self, row, col, value):
+ pass
+
--- /dev/null
+#!/usr/bin/env python
+
+import wx
+import abstractmodel
+
+class SimpleName(abstractmodel.AbstractModel):
+
+ def __init__(self, first="", last=""):
+ abstractmodel.AbstractModel.__init__(self)
+ self.set(first, last)
+
+ def set(self, first, last):
+ self.first = first
+ self.last = last
+ self.update()
+
+class ModelExample(wx.Frame):
+
+ def __init__(self, parent, id):
+ wx.Frame.__init__(self, parent, id, 'Flintstones',
+ size=(340, 200))
+ panel = wx.Panel(self)
+ panel.SetBackgroundColour("White")
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+ self.textFields = {}
+ self.createTextFields(panel)
+ self.model = SimpleName()
+ self.model.addListener(self.OnUpdate)
+ self.createButtonBar(panel)
+
+ def buttonData(self):
+ return (("Fredify", self.OnFred),
+ ("Wilmafy", self.OnWilma),
+ ("Barnify", self.OnBarney),
+ ("Bettify", self.OnBetty))
+
+ def createButtonBar(self, panel, yPos = 0):
+ xPos = 0
+ for eachLabel, eachHandler in self.buttonData():
+ pos = (xPos, yPos)
+ button = self.buildOneButton(panel, eachLabel, eachHandler, pos)
+ xPos += button.GetSize().width
+
+ def buildOneButton(self, parent, label, handler, pos=(0,0)):
+ button = wx.Button(parent, -1, label, pos)
+ self.Bind(wx.EVT_BUTTON, handler, button)
+ return button
+
+ def textFieldData(self):
+ return (("First Name", (10, 50)),
+ ("Last Name", (10, 80)))
+
+ def createTextFields(self, panel):
+ for eachLabel, eachPos in self.textFieldData():
+ self.createCaptionedText(panel, eachLabel, eachPos)
+
+ def createCaptionedText(self, panel, label, pos):
+ static = wx.StaticText(panel, wx.NewId(), label, pos)
+ static.SetBackgroundColour("White")
+ textPos = (pos[0] + 75, pos[1])
+ self.textFields[label] = wx.TextCtrl(panel, wx.NewId(),
+ "", size=(100, -1), pos=textPos,
+ style=wx.TE_READONLY)
+
+ def OnUpdate(self, model):
+ self.textFields["First Name"].SetValue(model.first)
+ self.textFields["Last Name"].SetValue(model.last)
+
+ def OnFred(self, event):
+ self.model.set("Fred", "Flintstone")
+
+ def OnBarney(self, event):
+ self.model.set("Barney", "Rubble")
+
+ def OnWilma(self, event):
+ self.model.set("Wilma", "Flintstone")
+
+ def OnBetty(self, event):
+ self.model.set("Betty", "Rubble")
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = ModelExample(parent=None, id=-1)
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+import unittest
+import modelExample
+import wx
+
+class TestExample(unittest.TestCase):
+
+ def setUp(self):
+ self.app = wx.PySimpleApp()
+ self.frame = modelExample.ModelExample(parent=None, id=-1)
+
+ def tearDown(self):
+ self.frame.Destroy()
+
+ def testModel(self):
+ self.frame.OnBarney(None)
+ self.assertEqual("Barney", self.frame.model.first,
+ msg="First is wrong")
+ self.assertEqual("Rubble", self.frame.model.last)
+
+ def testEvent(self):
+ panel = self.frame.GetChildren()[0]
+ for each in panel.GetChildren():
+ if each.GetLabel() == "Wilmafy":
+ wilma = each
+ break
+ event = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, wilma.GetId())
+ wilma.GetEventHandler().ProcessEvent(event)
+ self.assertEqual("Wilma", self.frame.model.first)
+ self.assertEqual("Flintstone", self.frame.model.last)
+
+def suite():
+ suite = unittest.makeSuite(TestExample, 'test')
+ return suite
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
+
--- /dev/null
+import unittest
+import modelExample
+import wx
+
+class TestExample(unittest.TestCase):
+
+ def setUp(self):
+ self.app = wx.PySimpleApp()
+ self.frame = modelExample.ModelExample(parent=None, id=-1)
+
+ def tearDown(self):
+ self.frame.Destroy()
+
+ def testModel(self):
+ self.frame.OnBarney(None)
+ self.assertEqual("Barney", self.frame.model.first,
+ msg="First is wrong")
+ self.assertEqual("Rubble", self.frame.model.last)
+
+def suite():
+ suite = unittest.makeSuite(TestExample, 'test')
+ return suite
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
+
--- /dev/null
+import wx
+
+
+class SketchWindow(wx.Window):
+ def __init__(self, parent, ID):
+ wx.Window.__init__(self, parent, ID)
+ self.SetBackgroundColour("White")
+ self.color = "Black"
+ self.thickness = 1
+ self.pen = wx.Pen(self.color, self.thickness, wx.SOLID)
+ self.lines = []
+ self.curLine = []
+ self.pos = (0, 0)
+ self.InitBuffer()
+
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ def InitBuffer(self):
+ size = self.GetClientSize()
+ #self.buffer = wx.EmptyBitmap(max(1, size.width), max(1, size.height))
+ self.buffer = wx.EmptyBitmap(size.width, size.height)
+ if self.buffer.Ok():
+ dc = wx.BufferedDC(None, self.buffer)
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ dc.Clear()
+ self.DrawLines(dc)
+ self.reInitBuffer = False
+
+ def GetLinesData(self):
+ return self.lines[:]
+
+ def SetLinesData(self, lines):
+ self.lines = lines[:]
+ self.InitBuffer()
+ self.Refresh()
+
+ def OnLeftDown(self, event):
+ self.curLine = []
+ self.pos = event.GetPositionTuple()
+ self.CaptureMouse()
+
+ def OnLeftUp(self, event):
+ if self.HasCapture():
+ self.lines.append((self.color,
+ self.thickness,
+ self.curLine))
+ self.curLine = []
+ self.ReleaseMouse()
+
+ def OnMotion(self, event):
+ if event.Dragging() and event.LeftIsDown():
+ dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
+ self.drawMotion(dc, event)
+ event.Skip()
+
+ def drawMotion(self, dc, event):
+ dc.SetPen(self.pen)
+ newPos = event.GetPositionTuple()
+ coords = self.pos + newPos
+ self.curLine.append(coords)
+ dc.DrawLine(*coords)
+ self.pos = newPos
+
+ def OnSize(self, event):
+ self.reInitBuffer = True
+
+ def OnIdle(self, event):
+ if self.reInitBuffer:
+ self.InitBuffer()
+ self.Refresh(False)
+
+ def OnPaint(self, event):
+ dc = wx.BufferedPaintDC(self, self.buffer)
+
+ def DrawLines(self, dc):
+ for colour, thickness, line in self.lines:
+ pen = wx.Pen(colour, thickness, wx.SOLID)
+ dc.SetPen(pen)
+ for coords in line:
+ dc.DrawLine(*coords)
+
+ def SetColor(self, color):
+ self.color = color
+ self.pen = wx.Pen(self.color, self.thickness, wx.SOLID)
+
+ def SetThickness(self, num):
+ self.thickness = num
+ self.pen = wx.Pen(self.color, self.thickness, wx.SOLID)
+
+
+class SketchFrame(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, "Sketch Frame",
+ size=(800,600))
+ self.sketch = SketchWindow(self, -1)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = SketchFrame(None)
+ frame.Show(True)
+ app.MainLoop()
--- /dev/null
+import wx
+from example1 import SketchWindow
+
+
+class SketchFrame(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, "Sketch Frame",
+ size=(800,600))
+ self.sketch = SketchWindow(self, -1)
+ self.sketch.Bind(wx.EVT_MOTION, self.OnSketchMotion)
+ self.statusbar = self.CreateStatusBar()
+
+ def OnSketchMotion(self, event):
+ self.statusbar.SetStatusText(str(event.GetPositionTuple()))
+ event.Skip()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = SketchFrame(None)
+ frame.Show(True)
+ app.MainLoop()
--- /dev/null
+import wx
+from example1 import SketchWindow
+
+class SketchFrame(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, "Sketch Frame",
+ size=(800,600))
+ self.sketch = SketchWindow(self, -1)
+ self.sketch.Bind(wx.EVT_MOTION, self.OnSketchMotion)
+ self.statusbar = self.CreateStatusBar()
+ self.statusbar.SetFieldsCount(3)
+ self.statusbar.SetStatusWidths([-1, -2, -3])
+
+ def OnSketchMotion(self, event):
+ self.statusbar.SetStatusText("Pos: %s" %
+ str(event.GetPositionTuple()), 0)
+ self.statusbar.SetStatusText("Current Pts: %s" %
+ len(self.sketch.curLine), 1)
+ self.statusbar.SetStatusText("Line Count: %s" %
+ len(self.sketch.lines), 2)
+ event.Skip()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = SketchFrame(None)
+ frame.Show(True)
+ app.MainLoop()
--- /dev/null
+import wx
+from example1 import SketchWindow
+
+
+class SketchFrame(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, "Sketch Frame",
+ size=(800,600))
+ self.sketch = SketchWindow(self, -1)
+ self.sketch.Bind(wx.EVT_MOTION, self.OnSketchMotion)
+ self.initStatusBar()
+ self.createMenuBar()
+
+ def initStatusBar(self):
+ self.statusbar = self.CreateStatusBar()
+ self.statusbar.SetFieldsCount(3)
+ self.statusbar.SetStatusWidths([-1, -2, -3])
+
+ def OnSketchMotion(self, event):
+ self.statusbar.SetStatusText("Pos: %s" %
+ str(event.GetPositionTuple()), 0)
+ self.statusbar.SetStatusText("Current Pts: %s" %
+ len(self.sketch.curLine), 1)
+ self.statusbar.SetStatusText("Line Count: %s" %
+ len(self.sketch.lines), 2)
+ event.Skip()
+
+ def menuData(self):
+ return [("&File", (
+ ("&New", "New Sketch file", self.OnNew),
+ ("&Open", "Open sketch file", self.OnOpen),
+ ("&Save", "Save sketch file", self.OnSave),
+ ("", "", ""),
+ ("&Color", (
+ ("&Black", "", self.OnColor,
+ wx.ITEM_RADIO),
+ ("&Red", "", self.OnColor,
+ wx.ITEM_RADIO),
+ ("&Green", "", self.OnColor,
+ wx.ITEM_RADIO),
+ ("&Blue", "", self.OnColor,
+ wx.ITEM_RADIO))),
+ ("", "", ""),
+ ("&Quit", "Quit", self.OnCloseWindow)))]
+
+ def createMenuBar(self):
+ menuBar = wx.MenuBar()
+ for eachMenuData in self.menuData():
+ menuLabel = eachMenuData[0]
+ menuItems = eachMenuData[1]
+ menuBar.Append(self.createMenu(menuItems), menuLabel)
+ self.SetMenuBar(menuBar)
+
+ def createMenu(self, menuData):
+ menu = wx.Menu()
+ for eachItem in menuData:
+ if len(eachItem) == 2:
+ label = eachItem[0]
+ subMenu = self.createMenu(eachItem[1])
+ menu.AppendMenu(wx.NewId(), label, subMenu)
+ else:
+ self.createMenuItem(menu, *eachItem)
+ return menu
+
+ def createMenuItem(self, menu, label, status, handler,
+ kind=wx.ITEM_NORMAL):
+ if not label:
+ menu.AppendSeparator()
+ return
+ menuItem = menu.Append(-1, label, status, kind)
+ self.Bind(wx.EVT_MENU, handler, menuItem)
+
+ def OnNew(self, event): pass
+ def OnOpen(self, event): pass
+ def OnSave(self, event): pass
+
+ def OnColor(self, event):
+ menubar = self.GetMenuBar()
+ itemId = event.GetId()
+ item = menubar.FindItemById(itemId)
+ color = item.GetLabel()
+ self.sketch.SetColor(color)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = SketchFrame(None)
+ frame.Show(True)
+ app.MainLoop()
--- /dev/null
+import wx
+from example1 import SketchWindow
+
+
+class SketchFrame(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, -1, "Sketch Frame",
+ size=(800,600))
+ self.sketch = SketchWindow(self, -1)
+ self.sketch.Bind(wx.EVT_MOTION, self.OnSketchMotion)
+ self.initStatusBar()
+ self.createMenuBar()
+ self.createToolBar()
+
+ def initStatusBar(self):
+ self.statusbar = self.CreateStatusBar()
+ self.statusbar.SetFieldsCount(3)
+ self.statusbar.SetStatusWidths([-1, -2, -3])
+
+ def OnSketchMotion(self, event):
+ self.statusbar.SetStatusText("Pos: %s" %
+ str(event.GetPositionTuple()), 0)
+ self.statusbar.SetStatusText("Current Pts: %s" %
+ len(self.sketch.curLine), 1)
+ self.statusbar.SetStatusText("Line Count: %s" %
+ len(self.sketch.lines), 2)
+ event.Skip()
+
+ def menuData(self):
+ return [("&File", (
+ ("&New", "New Sketch file", self.OnNew),
+ ("&Open", "Open sketch file", self.OnOpen),
+ ("&Save", "Save sketch file", self.OnSave),
+ ("", "", ""),
+ ("&Color", (
+ ("&Black", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Red", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Green", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Blue", "", self.OnColor, wx.ITEM_RADIO))),
+ ("", "", ""),
+ ("&Quit", "Quit", self.OnCloseWindow)))]
+
+ def createMenuBar(self):
+ menuBar = wx.MenuBar()
+ for eachMenuData in self.menuData():
+ menuLabel = eachMenuData[0]
+ menuItems = eachMenuData[1]
+ menuBar.Append(self.createMenu(menuItems), menuLabel)
+ self.SetMenuBar(menuBar)
+
+ def createMenu(self, menuData):
+ menu = wx.Menu()
+ for eachItem in menuData:
+ if len(eachItem) == 2:
+ label = eachItem[0]
+ subMenu = self.createMenu(eachItem[1])
+ menu.AppendMenu(wx.NewId(), label, subMenu)
+ else:
+ self.createMenuItem(menu, *eachItem)
+ return menu
+
+ def createMenuItem(self, menu, label, status, handler, kind=wx.ITEM_NORMAL):
+ if not label:
+ menu.AppendSeparator()
+ return
+ menuItem = menu.Append(-1, label, status, kind)
+ self.Bind(wx.EVT_MENU, handler, menuItem)
+
+ def createToolBar(self):
+ toolbar = self.CreateToolBar()
+ for each in self.toolbarData():
+ self.createSimpleTool(toolbar, *each)
+ toolbar.AddSeparator()
+ for each in self.toolbarColorData():
+ self.createColorTool(toolbar, each)
+ toolbar.Realize()
+
+ def createSimpleTool(self, toolbar, label, filename, help, handler):
+ if not label:
+ toolbar.AddSeparator()
+ return
+ bmp = wx.Image(filename, wx.BITMAP_TYPE_BMP).ConvertToBitmap()
+ tool = toolbar.AddSimpleTool(-1, bmp, label, help)
+ self.Bind(wx.EVT_MENU, handler, tool)
+
+ def toolbarData(self):
+ return (("New", "new.bmp", "Create new sketch", self.OnNew),
+ ("", "", "", ""),
+ ("Open", "open.bmp", "Open existing sketch", self.OnOpen),
+ ("Save", "save.bmp", "Save existing sketch", self.OnSave))
+
+ def createColorTool(self, toolbar, color):
+ bmp = self.MakeBitmap(color)
+ tool = toolbar.AddRadioTool(-1, bmp, shortHelp=color)
+ self.Bind(wx.EVT_MENU, self.OnColor, tool)
+
+ def MakeBitmap(self, color):
+ bmp = wx.EmptyBitmap(16, 15)
+ dc = wx.MemoryDC()
+ dc.SelectObject(bmp)
+ dc.SetBackground(wx.Brush(color))
+ dc.Clear()
+ dc.SelectObject(wx.NullBitmap)
+ return bmp
+
+ def toolbarColorData(self):
+ return ("Black", "Red", "Green", "Blue")
+
+ def OnNew(self, event): pass
+ def OnOpen(self, event): pass
+ def OnSave(self, event): pass
+
+ def OnColor(self, event):
+ menubar = self.GetMenuBar()
+ itemId = event.GetId()
+ item = menubar.FindItemById(itemId)
+ if not item:
+ toolbar = self.GetToolBar()
+ item = toolbar.FindById(itemId)
+ color = item.GetShortHelp()
+ else:
+ color = item.GetLabel()
+ self.sketch.SetColor(color)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = SketchFrame(None)
+ frame.Show(True)
+ app.MainLoop()
--- /dev/null
+import wx
+import cPickle
+import os
+
+from example1 import SketchWindow
+
+
+class SketchFrame(wx.Frame):
+ def __init__(self, parent):
+ self.title = "Sketch Frame"
+ wx.Frame.__init__(self, parent, -1, self.title,
+ size=(800,600))
+ self.filename = ""
+ self.sketch = SketchWindow(self, -1)
+ self.sketch.Bind(wx.EVT_MOTION, self.OnSketchMotion)
+ self.initStatusBar()
+ self.createMenuBar()
+ self.createToolBar()
+
+ def initStatusBar(self):
+ self.statusbar = self.CreateStatusBar()
+ self.statusbar.SetFieldsCount(3)
+ self.statusbar.SetStatusWidths([-1, -2, -3])
+
+ def OnSketchMotion(self, event):
+ self.statusbar.SetStatusText("Pos: %s" %
+ str(event.GetPositionTuple()), 0)
+ self.statusbar.SetStatusText("Current Pts: %s" %
+ len(self.sketch.curLine), 1)
+ self.statusbar.SetStatusText("Line Count: %s" %
+ len(self.sketch.lines), 2)
+ event.Skip()
+
+ def menuData(self):
+ return [("&File", (
+ ("&New", "New Sketch file", self.OnNew),
+ ("&Open", "Open sketch file", self.OnOpen),
+ ("&Save", "Save sketch file", self.OnSave),
+ ("", "", ""),
+ ("&Color", (
+ ("&Black", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Red", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Green", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Blue", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Other...", "", self.OnOtherColor, wx.ITEM_RADIO))),
+ ("", "", ""),
+ ("&Quit", "Quit", self.OnCloseWindow)))]
+
+ def createMenuBar(self):
+ menuBar = wx.MenuBar()
+ for eachMenuData in self.menuData():
+ menuLabel = eachMenuData[0]
+ menuItems = eachMenuData[1]
+ menuBar.Append(self.createMenu(menuItems), menuLabel)
+ self.SetMenuBar(menuBar)
+
+ def createMenu(self, menuData):
+ menu = wx.Menu()
+ for eachItem in menuData:
+ if len(eachItem) == 2:
+ label = eachItem[0]
+ subMenu = self.createMenu(eachItem[1])
+ menu.AppendMenu(wx.NewId(), label, subMenu)
+ else:
+ self.createMenuItem(menu, *eachItem)
+ return menu
+
+ def createMenuItem(self, menu, label, status, handler, kind=wx.ITEM_NORMAL):
+ if not label:
+ menu.AppendSeparator()
+ return
+ menuItem = menu.Append(-1, label, status, kind)
+ self.Bind(wx.EVT_MENU, handler, menuItem)
+
+ def createToolBar(self):
+ toolbar = self.CreateToolBar()
+ for each in self.toolbarData():
+ self.createSimpleTool(toolbar, *each)
+ toolbar.AddSeparator()
+ for each in self.toolbarColorData():
+ self.createColorTool(toolbar, each)
+ toolbar.Realize()
+
+ def createSimpleTool(self, toolbar, label, filename, help, handler):
+ if not label:
+ toolbar.AddSeparator()
+ return
+ bmp = wx.Image(filename, wx.BITMAP_TYPE_BMP).ConvertToBitmap()
+ tool = toolbar.AddSimpleTool(-1, bmp, label, help)
+ self.Bind(wx.EVT_MENU, handler, tool)
+
+ def toolbarData(self):
+ return (("New", "new.bmp", "Create new sketch", self.OnNew),
+ ("", "", "", ""),
+ ("Open", "open.bmp", "Open existing sketch", self.OnOpen),
+ ("Save", "save.bmp", "Save existing sketch", self.OnSave))
+
+ def createColorTool(self, toolbar, color):
+ bmp = self.MakeBitmap(color)
+ tool = toolbar.AddRadioTool(-1, bmp, shortHelp=color)
+ self.Bind(wx.EVT_MENU, self.OnColor, tool)
+
+ def MakeBitmap(self, color):
+ bmp = wx.EmptyBitmap(16, 15)
+ dc = wx.MemoryDC()
+ dc.SelectObject(bmp)
+ dc.SetBackground(wx.Brush(color))
+ dc.Clear()
+ dc.SelectObject(wx.NullBitmap)
+ return bmp
+
+ def toolbarColorData(self):
+ return ("Black", "Red", "Green", "Blue")
+
+ def OnNew(self, event): pass
+
+ def OnColor(self, event):
+ menubar = self.GetMenuBar()
+ itemId = event.GetId()
+ item = menubar.FindItemById(itemId)
+ if not item:
+ toolbar = self.GetToolBar()
+ item = toolbar.FindById(itemId)
+ color = item.GetShortHelp()
+ else:
+ color = item.GetLabel()
+ self.sketch.SetColor(color)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+ def SaveFile(self):
+ if self.filename:
+ data = self.sketch.GetLinesData()
+ f = open(self.filename, 'w')
+ cPickle.dump(data, f)
+ f.close()
+
+ def ReadFile(self):
+ if self.filename:
+ try:
+ f = open(self.filename, 'r')
+ data = cPickle.load(f)
+ f.close()
+ self.sketch.SetLinesData(data)
+ except cPickle.UnpicklingError:
+ wx.MessageBox("%s is not a sketch file." % self.filename,
+ "oops!", style=wx.OK|wx.ICON_EXCLAMATION)
+
+ wildcard = "Sketch files (*.sketch)|*.sketch|All files (*.*)|*.*"
+
+ def OnOpen(self, event):
+ dlg = wx.FileDialog(self, "Open sketch file...", os.getcwd(),
+ style=wx.OPEN, wildcard=self.wildcard)
+ if dlg.ShowModal() == wx.ID_OK:
+ self.filename = dlg.GetPath()
+ self.ReadFile()
+ self.SetTitle(self.title + ' -- ' + self.filename)
+ dlg.Destroy()
+
+ def OnSave(self, event):
+ if not self.filename:
+ self.OnSaveAs(event)
+ else:
+ self.SaveFile()
+
+ def OnSaveAs(self, event):
+ dlg = wx.FileDialog(self, "Save sketch as...", os.getcwd(),
+ style=wx.SAVE | wx.OVERWRITE_PROMPT,
+ wildcard = self.wildcard)
+ if dlg.ShowModal() == wx.ID_OK:
+ filename = dlg.GetPath()
+ if not os.path.splitext(filename)[1]:
+ filename = filename + '.sketch'
+ self.filename = filename
+ self.SaveFile()
+ self.SetTitle(self.title + ' -- ' + self.filename)
+ dlg.Destroy()
+
+ def OnOtherColor(self, event):
+ dlg = wx.ColourDialog(frame)
+ dlg.GetColourData().SetChooseFull(True)
+ if dlg.ShowModal() == wx.ID_OK:
+ self.sketch.SetColor(dlg.GetColourData().GetColour())
+ dlg.Destroy()
+
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = SketchFrame(None)
+ frame.Show(True)
+ app.MainLoop()
--- /dev/null
+import wx
+import wx.html
+import cPickle
+import os
+from wx.lib import buttons
+
+from example1 import SketchWindow
+
+class SketchFrame(wx.Frame):
+ def __init__(self, parent):
+ self.title = "Sketch Frame"
+ wx.Frame.__init__(self, parent, -1, self.title,
+ size=(800,600))
+ self.filename = ""
+ self.sketch = SketchWindow(self, -1)
+ wx.EVT_MOTION(self.sketch, self.OnSketchMotion)
+ self.initStatusBar()
+ self.createMenuBar()
+ self.createToolBar()
+ self.createPanel()
+
+ def createPanel(self):
+ controlPanel = ControlPanel(self, -1, self.sketch)
+ box = wx.BoxSizer(wx.HORIZONTAL)
+ box.Add(controlPanel, 0, wx.EXPAND)
+ box.Add(self.sketch, 1, wx.EXPAND)
+ self.SetSizer(box)
+
+ def initStatusBar(self):
+ self.statusbar = self.CreateStatusBar()
+ self.statusbar.SetFieldsCount(3)
+ self.statusbar.SetStatusWidths([-1, -2, -3])
+
+ def OnSketchMotion(self, event):
+ self.statusbar.SetStatusText("Pos: %s" %
+ str(event.GetPositionTuple()), 0)
+ self.statusbar.SetStatusText("Current Pts: %s" %
+ len(self.sketch.curLine), 1)
+ self.statusbar.SetStatusText("Line Count: %s" %
+ len(self.sketch.lines), 2)
+ event.Skip()
+
+ def menuData(self):
+ return [("&File", (
+ ("&New", "New Sketch file", self.OnNew),
+ ("&Open", "Open sketch file", self.OnOpen),
+ ("&Save", "Save sketch file", self.OnSave),
+ ("", "", ""),
+ ("&Color", (
+ ("&Black", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Red", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Green", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Blue", "", self.OnColor, wx.ITEM_RADIO),
+ ("&Other...", "", self.OnOtherColor, wx.ITEM_RADIO))),
+ ("", "", ""),
+ ("About...", "Show about window", self.OnAbout),
+ ("&Quit", "Quit", self.OnCloseWindow)))]
+
+ def createMenuBar(self):
+ menuBar = wx.MenuBar()
+ for eachMenuData in self.menuData():
+ menuLabel = eachMenuData[0]
+ menuItems = eachMenuData[1]
+ menuBar.Append(self.createMenu(menuItems), menuLabel)
+ self.SetMenuBar(menuBar)
+
+ def createMenu(self, menuData):
+ menu = wx.Menu()
+ for eachItem in menuData:
+ if len(eachItem) == 2:
+ label = eachItem[0]
+ subMenu = self.createMenu(eachItem[1])
+ menu.AppendMenu(wx.NewId(), label, subMenu)
+ else:
+ self.createMenuItem(menu, *eachItem)
+ return menu
+
+ def createMenuItem(self, menu, label, status, handler, kind=wx.ITEM_NORMAL):
+ if not label:
+ menu.AppendSeparator()
+ return
+ menuItem = menu.Append(-1, label, status, kind)
+ self.Bind(wx.EVT_MENU, handler, menuItem)
+
+ def createToolBar(self):
+ toolbar = self.CreateToolBar()
+ for each in self.toolbarData():
+ self.createSimpleTool(toolbar, *each)
+ toolbar.AddSeparator()
+ for each in self.toolbarColorData():
+ self.createColorTool(toolbar, each)
+ toolbar.Realize()
+
+ def createSimpleTool(self, toolbar, label, filename, help, handler):
+ if not label:
+ toolbar.AddSeparator()
+ return
+ bmp = wx.Image(filename, wx.BITMAP_TYPE_BMP).ConvertToBitmap()
+ tool = toolbar.AddSimpleTool(-1, bmp, label, help)
+ self.Bind(wx.EVT_MENU, handler, tool)
+
+ def toolbarData(self):
+ return (("New", "new.bmp", "Create new sketch", self.OnNew),
+ ("", "", "", ""),
+ ("Open", "open.bmp", "Open existing sketch", self.OnOpen),
+ ("Save", "save.bmp", "Save existing sketch", self.OnSave))
+
+ def createColorTool(self, toolbar, color):
+ bmp = self.MakeBitmap(color)
+ tool = toolbar.AddRadioTool(-1, bmp, shortHelp=color)
+ self.Bind(wx.EVT_MENU, self.OnColor, tool)
+
+ def MakeBitmap(self, color):
+ bmp = wx.EmptyBitmap(16, 15)
+ dc = wx.MemoryDC()
+ dc.SelectObject(bmp)
+ dc.SetBackground(wx.Brush(color))
+ dc.Clear()
+ dc.SelectObject(wx.NullBitmap)
+ return bmp
+
+ def toolbarColorData(self):
+ return ("Black", "Red", "Green", "Blue")
+
+ def OnNew(self, event): pass
+
+ def OnColor(self, event):
+ menubar = self.GetMenuBar()
+ itemId = event.GetId()
+ item = menubar.FindItemById(itemId)
+ if not item:
+ toolbar = self.GetToolBar()
+ item = toolbar.FindById(itemId)
+ color = item.GetShortHelp()
+ else:
+ color = item.GetLabel()
+ self.sketch.SetColor(color)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+ def SaveFile(self):
+ if self.filename:
+ data = self.sketch.GetLinesData()
+ f = open(self.filename, 'w')
+ cPickle.dump(data, f)
+ f.close()
+
+ def ReadFile(self):
+ if self.filename:
+ try:
+ f = open(self.filename, 'r')
+ data = cPickle.load(f)
+ f.close()
+ self.sketch.SetLinesData(data)
+ except cPickle.UnpicklingError:
+ wx.MessageBox("%s is not a sketch file." % self.filename,
+ "oops!", style=wx.OK|wx.ICON_EXCLAMATION)
+
+ wildcard = "Sketch files (*.sketch)|*.sketch|All files (*.*)|*.*"
+
+ def OnOpen(self, event):
+ dlg = wx.FileDialog(self, "Open sketch file...", os.getcwd(),
+ style=wx.OPEN, wildcard=self.wildcard)
+ if dlg.ShowModal() == wx.ID_OK:
+ self.filename = dlg.GetPath()
+ self.ReadFile()
+ self.SetTitle(self.title + ' -- ' + self.filename)
+ dlg.Destroy()
+
+ def OnSave(self, event):
+ if not self.filename:
+ self.OnSaveAs(event)
+ else:
+ self.SaveFile()
+
+ def OnSaveAs(self, event):
+ dlg = wx.FileDialog(self, "Save sketch as...", os.getcwd(),
+ style=wx.SAVE | wx.OVERWRITE_PROMPT,
+ wildcard = self.wildcard)
+ if dlg.ShowModal() == wx.ID_OK:
+ filename = dlg.GetPath()
+ if not os.path.splitext(filename)[1]:
+ filename = filename + '.sketch'
+ self.filename = filename
+ self.SaveFile()
+ self.SetTitle(self.title + ' -- ' + self.filename)
+ dlg.Destroy()
+
+ def OnOtherColor(self, event):
+ dlg = wx.ColourDialog(frame)
+ dlg.GetColourData().SetChooseFull(True)
+ if dlg.ShowModal() == wx.ID_OK:
+ self.sketch.SetColor(dlg.GetColourData().GetColour())
+ dlg.Destroy()
+
+ def OnAbout(self, event):
+ dlg = SketchAbout(self)
+ dlg.ShowModal()
+ dlg.Destroy()
+
+
+class SketchAbout(wx.Dialog):
+ text = '''
+<html>
+<body bgcolor="#ACAA60">
+<center><table bgcolor="#455481" width="100%" cellspacing="0"
+cellpadding="0" border="1">
+<tr>
+ <td align="center"><h1>Sketch!</h1></td>
+</tr>
+</table>
+</center>
+<p><b>Sketch</b> is a demonstration program for <b>wxPython In Action</b>
+Chapter 7. It is based on the SuperDoodle demo included with wxPython,
+available at http://www.wxpython.org/
+</p>
+
+<p><b>SuperDoodle</b> and <b>wxPython</b> are brought to you by
+<b>Robin Dunn</b> and <b>Total Control Software</b>, Copyright
+© 1997-2006.</p>
+</body>
+</html>
+'''
+
+ def __init__(self, parent):
+ wx.Dialog.__init__(self, parent, -1, 'About Sketch',
+ size=(440, 400) )
+
+ html = wx.html.HtmlWindow(self)
+ html.SetPage(self.text)
+ button = wx.Button(self, wx.ID_OK, "Okay")
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(html, 1, wx.EXPAND|wx.ALL, 5)
+ sizer.Add(button, 0, wx.ALIGN_CENTER|wx.ALL, 5)
+
+ self.SetSizer(sizer)
+ self.Layout()
+
+
+
+class ControlPanel(wx.Panel):
+
+ BMP_SIZE = 16
+ BMP_BORDER = 3
+ NUM_COLS = 4
+ SPACING = 4
+
+ colorList = ('Black', 'Yellow', 'Red', 'Green', 'Blue', 'Purple',
+ 'Brown', 'Aquamarine', 'Forest Green', 'Light Blue',
+ 'Goldenrod', 'Cyan', 'Orange', 'Navy', 'Dark Grey',
+ 'Light Grey')
+ maxThickness = 16
+
+ def __init__(self, parent, ID, sketch):
+ wx.Panel.__init__(self, parent, ID, style=wx.RAISED_BORDER)
+ self.sketch = sketch
+ buttonSize = (self.BMP_SIZE + 2 * self.BMP_BORDER,
+ self.BMP_SIZE + 2 * self.BMP_BORDER)
+ colorGrid = self.createColorGrid(parent, buttonSize)
+ thicknessGrid = self.createThicknessGrid(buttonSize)
+ self.layout(colorGrid, thicknessGrid)
+
+ def createColorGrid(self, parent, buttonSize):
+ self.colorMap = {}
+ self.colorButtons = {}
+ colorGrid = wx.GridSizer(cols=self.NUM_COLS, hgap=2, vgap=2)
+ for eachColor in self.colorList:
+ bmp = parent.MakeBitmap(eachColor)
+ b = buttons.GenBitmapToggleButton(self, -1, bmp, size=buttonSize)
+ b.SetBezelWidth(1)
+ b.SetUseFocusIndicator(False)
+ self.Bind(wx.EVT_BUTTON, self.OnSetColour, b)
+ colorGrid.Add(b, 0)
+ self.colorMap[b.GetId()] = eachColor
+ self.colorButtons[eachColor] = b
+ self.colorButtons[self.colorList[0]].SetToggle(True)
+ return colorGrid
+
+ def createThicknessGrid(self, buttonSize):
+ self.thicknessIdMap = {}
+ self.thicknessButtons = {}
+ thicknessGrid = wx.GridSizer(cols=self.NUM_COLS, hgap=2, vgap=2)
+ for x in range(1, self.maxThickness + 1):
+ b = buttons.GenToggleButton(self, -1, str(x), size=buttonSize)
+ b.SetBezelWidth(1)
+ b.SetUseFocusIndicator(False)
+ self.Bind(wx.EVT_BUTTON, self.OnSetThickness, b)
+ thicknessGrid.Add(b, 0)
+ self.thicknessIdMap[b.GetId()] = x
+ self.thicknessButtons[x] = b
+ self.thicknessButtons[1].SetToggle(True)
+ return thicknessGrid
+
+ def layout(self, colorGrid, thicknessGrid):
+ box = wx.BoxSizer(wx.VERTICAL)
+ box.Add(colorGrid, 0, wx.ALL, self.SPACING)
+ box.Add(thicknessGrid, 0, wx.ALL, self.SPACING)
+ self.SetSizer(box)
+ box.Fit(self)
+
+ def OnSetColour(self, event):
+ color = self.colorMap[event.GetId()]
+ if color != self.sketch.color:
+ self.colorButtons[self.sketch.color].SetToggle(False)
+ self.sketch.SetColor(color)
+
+ def OnSetThickness(self, event):
+ thickness = self.thicknessIdMap[event.GetId()]
+ if thickness != self.sketch.thickness:
+ self.thicknessButtons[self.sketch.thickness].SetToggle(False)
+ self.sketch.SetThickness(thickness)
+
+
+class SketchApp(wx.App):
+
+ def OnInit(self):
+ bmp = wx.Image("splash.png").ConvertToBitmap()
+ wx.SplashScreen(bmp, wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
+ 1000, None, -1)
+ wx.Yield()
+
+ frame = SketchFrame(None)
+ frame.Show(True)
+ self.SetTopWindow(frame)
+ return True
+
+if __name__ == '__main__':
+ app = SketchApp(False)
+ app.MainLoop()
--- /dev/null
+import wx
+
+class BitmapButtonFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Bitmap Button Example',
+ size=(200, 150))
+ panel = wx.Panel(self, -1)
+ bmp = wx.Image("bitmap.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
+ self.button = wx.BitmapButton(panel, -1, bmp, pos=(10, 20))
+ self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)
+ self.button.SetDefault()
+ self.button2 = wx.BitmapButton(panel, -1, bmp, pos=(100, 20),
+ style=0)
+ self.Bind(wx.EVT_BUTTON, self.OnClick, self.button2)
+
+ def OnClick(self, event):
+ self.Destroy()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = BitmapButtonFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class ButtonFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Button Example',
+ size=(300, 100))
+ panel = wx.Panel(self, -1)
+ self.button = wx.Button(panel, -1, "Hello", pos=(50, 20))
+ self.Bind(wx.EVT_BUTTON, self.OnClick, self.button)
+ self.button.SetDefault()
+
+ def OnClick(self, event):
+ self.button.SetLabel("Clicked")
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = ButtonFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class CheckBoxFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Checkbox Example',
+ size=(150, 200))
+ panel = wx.Panel(self, -1)
+ wx.CheckBox(panel, -1, "Alpha", (35, 40), (150, 20))
+ wx.CheckBox(panel, -1, "Beta", (35, 60), (150, 20))
+ wx.CheckBox(panel, -1, "Gamma", (35, 80), (150, 20))
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ CheckBoxFrame().Show()
+ app.MainLoop()
+
--- /dev/null
+import wx
+
+class ChoiceFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Choice Example',
+ size=(250, 200))
+ panel = wx.Panel(self, -1)
+ sampleList = ['zero', 'one', 'two', 'three', 'four', 'five',
+ 'six', 'seven', 'eight']
+ wx.StaticText(panel, -1, "Select one:", (15, 20))
+ wx.Choice(panel, -1, (85, 18), choices=sampleList)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ ChoiceFrame().Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class ComboBoxFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Combo Box Example',
+ size=(350, 300))
+ panel = wx.Panel(self, -1)
+ sampleList = ['zero', 'one', 'two', 'three', 'four', 'five',
+ 'six', 'seven', 'eight']
+ wx.StaticText(panel, -1, "Select one:", (15, 15))
+ wx.ComboBox(panel, -1, "default value", (15, 30), wx.DefaultSize,
+ sampleList, wx.CB_DROPDOWN)
+ wx.ComboBox(panel, -1, "default value", (150, 30), wx.DefaultSize,
+ sampleList, wx.CB_SIMPLE)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ ComboBoxFrame().Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class GaugeFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Gauge Example',
+ size=(350, 150))
+ panel = wx.Panel(self, -1)
+ self.count = 0
+ self.gauge = wx.Gauge(panel, -1, 50, (20, 50), (250, 25))
+ self.gauge.SetBezelFace(3)
+ self.gauge.SetShadowWidth(3)
+ self.Bind(wx.EVT_IDLE, self.OnIdle)
+
+ def OnIdle(self, event):
+ self.count = self.count + 1
+ if self.count >= 50:
+ self.count = 0
+ self.gauge.SetValue(self.count)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ GaugeFrame().Show()
+ app.MainLoop()
--- /dev/null
+import wx
+import wx.lib.buttons as buttons
+
+class GenericButtonFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Generic Button Example',
+ size=(500, 350))
+ panel = wx.Panel(self, -1)
+
+ sizer = wx.FlexGridSizer(1, 3, 20, 20)
+ b = wx.Button(panel, -1, "A wx.Button")
+ b.SetDefault()
+ sizer.Add(b)
+
+ b = wx.Button(panel, -1, "non-default wx.Button")
+ sizer.Add(b)
+ sizer.Add((10,10))
+
+ b = buttons.GenButton(panel, -1, 'Generic Button')
+ sizer.Add(b)
+
+ b = buttons.GenButton(panel, -1, 'disabled Generic')
+ b.Enable(False)
+ sizer.Add(b)
+
+ b = buttons.GenButton(panel, -1, 'bigger')
+ b.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.BOLD, False))
+ b.SetBezelWidth(5)
+ b.SetBackgroundColour("Navy")
+ b.SetForegroundColour("white")
+ b.SetToolTipString("This is a BIG button...")
+ sizer.Add(b)
+
+ bmp = wx.Image("bitmap.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
+ b = buttons.GenBitmapButton(panel, -1, bmp)
+ sizer.Add(b)
+
+ b = buttons.GenBitmapToggleButton(panel, -1, bmp)
+ sizer.Add(b)
+
+ b = buttons.GenBitmapTextButton(panel, -1, bmp, "Bitmapped Text",
+ size=(175, 75))
+ b.SetUseFocusIndicator(False)
+ sizer.Add(b)
+
+ b = buttons.GenToggleButton(panel, -1, "Toggle Button")
+ sizer.Add(b)
+
+ panel.SetSizer(sizer)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = GenericButtonFrame()
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+import wx
+
+class ListBoxFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'List Box Example',
+ size=(250, 200))
+ panel = wx.Panel(self, -1)
+
+ sampleList = ['zero', 'one', 'two', 'three', 'four', 'five',
+ 'six', 'seven', 'eight', 'nine', 'ten', 'eleven',
+ 'twelve', 'thirteen', 'fourteen']
+
+ listBox = wx.ListBox(panel, -1, (20, 20), (80, 120), sampleList,
+ wx.LB_SINGLE)
+ listBox.SetSelection(3)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ ListBoxFrame().Show()
+ app.MainLoop()
+
--- /dev/null
+import wx
+
+class RadioButtonFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Radio Example',
+ size=(200, 200))
+ panel = wx.Panel(self, -1)
+ radio1 = wx.RadioButton(panel, -1, "Elmo", pos=(20, 50), style=wx.RB_GROUP)
+ radio2 = wx.RadioButton(panel, -1, "Ernie", pos=(20, 80))
+ radio3 = wx.RadioButton(panel, -1, "Bert", pos=(20, 110))
+ text1 = wx.TextCtrl(panel, -1, "", pos=(80, 50))
+ text2 = wx.TextCtrl(panel, -1, "", pos=(80, 80))
+ text3 = wx.TextCtrl(panel, -1, "", pos=(80, 110))
+ self.texts = {"Elmo": text1, "Ernie": text2, "Bert": text3}
+ for eachText in [text2, text3]:
+ eachText.Enable(False)
+ for eachRadio in [radio1, radio2, radio3]:
+ self.Bind(wx.EVT_RADIOBUTTON, self.OnRadio, eachRadio)
+ self.selectedText = text1
+
+ def OnRadio(self, event):
+ if self.selectedText:
+ self.selectedText.Enable(False)
+ radioSelected = event.GetEventObject()
+ text = self.texts[radioSelected.GetLabel()]
+ text.Enable(True)
+ self.selectedText = text
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ RadioButtonFrame().Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class RadioBoxFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Radio Box Example',
+ size=(350, 200))
+ panel = wx.Panel(self, -1)
+ sampleList = ['zero', 'one', 'two', 'three', 'four', 'five',
+ 'six', 'seven', 'eight']
+ wx.RadioBox(panel, -1, "A Radio Box", (10, 10), wx.DefaultSize,
+ sampleList, 2, wx.RA_SPECIFY_COLS)
+
+ wx.RadioBox(panel, -1, "", (150, 10), wx.DefaultSize,
+ sampleList, 3, wx.RA_SPECIFY_COLS | wx.NO_BORDER)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ RadioBoxFrame().Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class SliderFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Slider Example',
+ size=(300, 350))
+ panel = wx.Panel(self, -1)
+ self.count = 0
+ slider = wx.Slider(panel, 100, 25, 1, 100, pos=(10, 10),
+ size=(250, -1),
+ style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS )
+ slider.SetTickFreq(5, 1)
+ slider = wx.Slider(panel, 100, 25, 1, 100, pos=(125, 70),
+ size=(-1, 250),
+ style=wx.SL_VERTICAL | wx.SL_AUTOTICKS | wx.SL_LABELS )
+ slider.SetTickFreq(20, 1)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = SliderFrame()
+ frame.Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class SpinnerFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Spinner Example',
+ size=(100, 100))
+ panel = wx.Panel(self, -1)
+ sc = wx.SpinCtrl(panel, -1, "", (30, 20), (80, -1))
+ sc.SetRange(1,100)
+ sc.SetValue(5)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ SpinnerFrame().Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class StaticTextFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Static Text Example',
+ size=(400, 300))
+ panel = wx.Panel(self, -1)
+ wx.StaticText(panel, -1, "This is an example of static text",
+ (100, 10))
+ rev = wx.StaticText(panel, -1, "Static Text With Reversed Colors",
+ (100, 30))
+ rev.SetForegroundColour('white')
+ rev.SetBackgroundColour('black')
+ center = wx.StaticText(panel, -1, "align center", (100, 50),
+ (160, -1), wx.ALIGN_CENTER)
+ center.SetForegroundColour('white')
+ center.SetBackgroundColour('black')
+ right = wx.StaticText(panel, -1, "align right", (100, 70),
+ (160, -1), wx.ALIGN_RIGHT)
+ right.SetForegroundColour('white')
+ right.SetBackgroundColour('black')
+ str = "You can also change the font."
+ text = wx.StaticText(panel, -1, str, (20, 100))
+ font = wx.Font(18, wx.DECORATIVE, wx.ITALIC, wx.NORMAL)
+ text.SetFont(font)
+ wx.StaticText(panel, -1, "Your text\ncan be split\n"
+ "over multiple lines\n\neven blank ones", (20,150))
+ wx.StaticText(panel, -1, "Multi-line text\ncan also\n"
+ "be right aligned\n\neven with a blank", (220,150),
+ style=wx.ALIGN_RIGHT)
+
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = StaticTextFrame()
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+import wx
+
+class TextFrame(wx.Frame):
+
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Text Entry Example',
+ size=(300, 100))
+ panel = wx.Panel(self, -1)
+ basicLabel = wx.StaticText(panel, -1, "Basic Control:")
+ basicText = wx.TextCtrl(panel, -1, "I've entered some text!",
+ size=(175, -1))
+ basicText.SetInsertionPoint(0)
+
+ pwdLabel = wx.StaticText(panel, -1, "Password:")
+ pwdText = wx.TextCtrl(panel, -1, "password", size=(175, -1),
+ style=wx.TE_PASSWORD)
+ sizer = wx.FlexGridSizer(cols=2, hgap=6, vgap=6)
+ sizer.AddMany([basicLabel, basicText, pwdLabel, pwdText])
+ panel.SetSizer(sizer)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = TextFrame()
+ frame.Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class TextFrame(wx.Frame):
+
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Text Entry Example',
+ size=(300, 250))
+ panel = wx.Panel(self, -1)
+ multiLabel = wx.StaticText(panel, -1, "Multi-line")
+ multiText = wx.TextCtrl(panel, -1,
+ "Here is a looooooooooooooong line of text set in the control.\n\n"
+ "See that it wrapped, and that this line is after a blank",
+ size=(200, 100), style=wx.TE_MULTILINE)
+ multiText.SetInsertionPoint(0)
+
+ richLabel = wx.StaticText(panel, -1, "Rich Text")
+ richText = wx.TextCtrl(panel, -1,
+ "If supported by the native control, this is reversed, and this is a different font.",
+ size=(200, 100), style=wx.TE_MULTILINE|wx.TE_RICH2)
+ richText.SetInsertionPoint(0)
+ richText.SetStyle(44, 52, wx.TextAttr("white", "black"))
+ points = richText.GetFont().GetPointSize()
+ f = wx.Font(points + 3, wx.ROMAN, wx.ITALIC, wx.BOLD, True)
+ richText.SetStyle(68, 82, wx.TextAttr("blue", wx.NullColour, f))
+ sizer = wx.FlexGridSizer(cols=2, hgap=6, vgap=6)
+ sizer.AddMany([multiLabel, multiText, richLabel, richText])
+ panel.SetSizer(sizer)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = TextFrame()
+ frame.Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class SubclassFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Frame Subclass',
+ size=(300, 100))
+ panel = wx.Panel(self, -1)
+ button = wx.Button(panel, -1, "Close Me", pos=(15, 15))
+ self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ def OnCloseMe(self, event):
+ self.Close(True)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ SubclassFrame().Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class HelpFrame(wx.Frame):
+
+ def __init__(self):
+ pre = wx.PreFrame()
+ pre.SetExtraStyle(wx.FRAME_EX_CONTEXTHELP)
+ pre.Create(None, -1, "Help Context", size=(300, 100),
+ style=wx.DEFAULT_FRAME_STYLE ^
+ (wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX))
+ self.PostCreate(pre)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ HelpFrame().Show()
+ app.MainLoop()
--- /dev/null
+#----------------------------------------------------------------------
+# This file was generated by encode_bitmaps.py
+#
+from wx import ImageFromStream, BitmapFromImage
+from wx import EmptyIcon
+import cStringIO
+
+
+def getVippiData():
+ return \
+'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01^\x00\x00\x01O\x08\x06\x00\
+\x00\x00\x05\xa1\xa6$\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00 \
+\x00IDATx\x9c\xec\x9dy`T\xd5\xd9\xff?\xe7\xced%!\x0b\x81@ \x10@\xf6M\x84\x80\
+"(\xae\x05\x14\x85\xba\xaf\xa8m\xad\xbb\xb5\xaf\xbe\xb6\xda\xfe\xaa]\xb4X\
+\xdf\xd6\xd6\xd6\x05\xad\xadR\xb7\x96\x8a\xe2\x8e; \n\x02\x82 \n\xc8\x1e aMH\
+B\x96\x99{\xcf\xef\x8fsg\xcdd\x9b\xcc\x96\xe4|tH\xe6n\xe7\xdc\x9b\xb9\xdfy\
+\xees\x9e\xe79B\x18\x0e:\x13\xd22\xa5\xff{a8D\xac\xda\x8cE[\x1a\x8d&\xf1q\
+\xc6\xbb\x03\xb1"Xp!\xf6B\xa8\x05X\xa3\xd1@\'\x10\xdeD\x10\xdc`\xb4\x00k4\
+\x9d\x1b\xd1Q]\r\x89,\xb8\xfe\xc4\xbbO\x1a\x8d&\xf6t8\xe1\r%n\x908\x02\xa7\
+\xc5W\xa3\xd1t\x18\xe1Mt\xc1\r&\x1e\x83|\x1a\x8d&1\xe8\x10\xc2\xdb^\xadH-\
+\xbe\x1aM\xe7\xa4]\x0bo{\xb3rC\xa1\xc5W\xa3\xe9|\xb4[\xe1m\xafVn(:\xd2\xb9h4\
+\x9a\xe6iw\xc2\xdb\x11\xac\xdc\xc6\xd0\xd6\xafF\xd390\xe2\xdd\x81\xd6\xd0\
+\x91E\x17\x1a\x9eGc\xe7\xab\xd1h\xda7\xedFx;\xba\xe8z\xd0\xe2\xab\xd1t|\xda\
+\x8d\xf0\x06#\x0c\x87\xe8h\xa2\xeb\xa1\xa3\x9e\x97F\xa3Q\xb4\x0b\xe1\xed\x8c\
+\xbeO\xffs\xd4V\xafF\xd3\xb1hW\xb5\x1a:\x83\xe0\xfa\xe39_-\xbc\x1aM\xc7\xa2\
+\xddE5h4\x1aM{\xa7]Y\xbc\xe1\xd2\x1a\x8b1ZVug\x19\x1c\xd4h4\xcd\xd3\xa1-\xde\
+\xb6>\xa2\x87#\x8a\x91v\x0bha\xd6h:\x1e\x1dNx\xa3\xe5\x0fmJ\x00c\xe9\x83\xd5\
+B\xac\xd1\xb4\x7f:\x8c\xf0\xb6D\xfcrss\xb9\xf8\xe2\x8b9\xfd\xf4\xd3\xc9\xc9\
+\xc9\x01\xa0\xb6\xb6\x96g\x9f}\x96\xf7\xde{\x8f\x8a\x8a\x8a&\xf7O\xb4\x18[-\
+\xc2\x1aM\xfb\xa4\xdd\x0bos\xe2\x97\x9b\x9b\xcb\xe5\x97_\xce\xa9\xa7\x9e\xca\
+I\'\x9dDAA\x01\x00B(\xcd\x92R\xed~\xe8\xd0!^~\xf9e^x\xe1\x05V\xacX\x81i\x9a\
+\x11\xebcff&III\x8c\x1e=\x9a^\xbdz1b\xc4\x08\x00\n\n\n(**b\xd7\xae]\x94\x94\
+\x94\xb0y\xf3fv\xed\xda\xc5\xa1C\x87\xd8\xb2e\x0b\xb5\xb5\xb5-:\xbe\x16`\x8d\
+\xa6}\xd1n\x85\xb7)\xc1\x15B0f\xcc\x18\xae\xbb\xee:\xe6\xcc\x99Cff\xa6wy\xa3\
+\xc7\xb3\x05\xd8\xb2,\xbe\xf9\xe6\x1b\x96.]\xca\xd2\xa5Ky\xff\xfd\xf79p\xe0@\
+\x8b\xfb\x95\x9c\x9cLZZ\x1a\x93&Mb\xca\x94)\x9cz\xea\xa9\x1c\x7f\xfc\xf1\x18\
+\x86AJJJ@\x1f\xa5\x94\r~\x02\x98\xa6Iii)\x1b7nd\xd1\xa2E,[\xb6\x8c\r\x1b6\
+\xb4\xe8\xcb@\x8b\xb0F\x93\xf8\xb4;\xe1mNp\xc7\x8f\x1f\xcf/~\xf1\x0b\xa6O\
+\x9f\x8e\xd3\xe9lRl\x9bl\xc7\x16\xc1\xd2\xd2R\xa6O\x9f\xce\xbau\xeb\x9a\xdc>\
+%%\x85K.\xb9\x84{\xee\xb9\x87\xa2\xa2"\x92\x93\x93\xbd}j\x0bRJL\xd3d\xd5\xaa\
+U,]\xba\x94\xf9\xf3\xe7\xb3~\xfd\xfa&\xf7\xd1\xe2\xab\xd1$6\xedFx\x9b\x13\
+\xdc\xe2\xe2b\x1e|\xf0AN9\xe5\x14\x1c\x0eG\x9b\x05\xcf\xdb\xae\x94\xbc\xf0\
+\xc2\x0b\\y\xe5\x95!\xd7\xf7\xef\xdf\x9f\x193fp\xf3\xcd73t\xe8Po\x7f\xa2\x81\
+\x94\x12\x97\xcb\xc5\x92%Kx\xe3\x8d7\xf8\xe4\x93O\xd8\xb0a\x03n\xb7\xbb\xc1\
+\xb6Z|5\x9a\xc4\xa5]\x08oS\xa2[TT\xc4}\xf7\xdd\xc7\xe5\x97_\xde&\x0b\xb7)v\
+\xef\xde\xcd\xa8Q\xa3\x1a\x0c\xbe\x15\x17\x17\xf3\xe6\x9bo\x92\x97\x97\x07DO\
+p\x83\xf1wI,^\xbc\x98\x9f\xfc\xe4\'l\xd9\xb2\xa5\xc1vZ|5\x9a\xc4$\xe1k54&\
+\xbaIII\xfc\xf0\x87?d\xe5\xca\x95\\}\xf5\xd5$%%EM\xf8\xfa\xf4\xe9\xc3\x85\
+\x17^\xd8`\xf9\x19g\x9cA^^\x1eB\x88\x98\x89.\xe0m\xcf\xe9t2}\xfat>\xff\xfcsf\
+\xcd\x9a\xd5`;i\x992\xde\x91\x17\x1a\x8d\xa6!\t+\xbcM\x89FQQ\x11\x0b\x17.\
+\xe4\xc9\'\x9f\xf4\n_\xb49\xfb\xec\xb3\x1b,[\xbdzuL\x057\x14B\x08rrrx\xfe\
+\xf9\xe7\x99={v\\\xfb\xa2\xd1hZFB\no\xa3\xe9\xb5Bp\xe5\x95W\xb2b\xc5\nf\xcc\
+\x98\x81a\x181\x11>!\x8472!xy" \x84 --\x8d\x7f\xfd\xeb_\x8dZ\xbeq\xe8\x96F\
+\xa3i\x84\x84\x13\xde\xc6D\xc20\x0c\xfe\xfa\xd7\xbf\xf2\xcc3\xcf\xd0\xbd{\
+\xf7\x98\x8b^QQ\x11\x85\x85\x85\x01\xcb,\xcb\xf2\xfa[\xe3\x8dG|\x9f\x7f\xfey\
+-\xbe\x1aM\x82\x93P\xc2\xdb\x988\xe4\xe4\xe4\xb0h\xd1"n\xbc\xf1\xc6\x88\xf9r\
+\x83\x05SJ\xd9\xa4\x88\x86\x8a\x94X\xb9re\x8b\x93\x1cb\x81\xbf\xf8N\x9d:5\
+\xde\xdd\xd1h4\x8d\x900\xd5\xc9\x1a\x13\xdd\xdc\xdc\\^\x7f\xfduN:\xe9\xa46\t\
+\xae\x94\x12\xb7\xdb\xcd\x8a\x15+8z\xf4(G\x8e\x1c\xe1\x9bo\xbe\xf1\xaeOKKc\
+\xec\xd8\xb1\x0c\x1e<\x98\xfe\xfd\xfb{\xdd\nM\xb5\x99H\x16\xaf\x07\x8f\xf8>\
+\xf9\xe4\x93L\x980! \x12CZ\xa6\xd4\x91\x0e\x1aM\xfcI\x08\xe1mLt\xfb\xf4\xe9\
+\xc3\xe2\xc5\x8b\x19:th\x9bE\xf7\xe0\xc1\x83\xdcu\xd7]\xcc\x9f?\x1f\xcb\xb2\
+\x1a\xdd6%%\x85Q\xa3F1c\xc6\x0cf\xcd\x9a\xc5\x88\x11#HJJ\xc20\x0cF\x8e\x1c\
+\xc9\x8e\x1d;\xc2\xeeG\xac\x10B0h\xd0 ~\xf3\x9b\xdfp\xdbm\xb7\x05\xac\xd3\
+\xe2\xab\xd1\xc4\x9f\xb8\xbb\x1a\x1a\x13\xdd!C\x86\xb0p\xe1\xc26\x8b.@EE\x05\
+3f\xcc\xe0\xd9g\x9fmRt\x01\xea\xea\xeaX\xb5j\x15\xbf\xfe\xf5\xaf\x19?~<g\x9d\
+u\x16\x1f~\xf8!\xd5\xd5\xd5ddd\xb4\xa9\x1f\xb1D\x08\xc1\x8f~\xf4#\xedr\xd0h\
+\x12\x90\xb8&P4\xe5^X\xb4h\x11\x93&M\x8aH\xca\xed\xef~\xf7;~\xf9\xcb_\x86}\
+\x0c!\x04\xfd\xfb\xf7G\x08\xc1\xd6\xad[\xbd\xcb322(++#==\xdd\xdbVEE\x05\x07\
+\x0e\x1c\xe0\x9bo\xbea\xf8\xf0\xe1\xe4\xe4\xe4\x90\x9b\x9b\x1b\xb7\x08\x88M\
+\x9b61f\xcc\x18\xea\xea\xea\x02\x96k\xabW\xa3\x89\x1fq\x13\xde\xc6D7--\x8d\
+\xc5\x8b\x17s\xf2\xc9\'GD\xacV\xae\\\xc9\xa4I\x93\x1a\x14\x98\x11N\'\x99\xe3\
+\xc7\xd3e\xf8p2\'L\xc0HK\xe3\xd8\xc6\x8d\xd4l\xdbF\xf9G\x1f\xe1:x\xb0\xd9c\
+\x7f\xef{\xdf\xe3\xad\xb7\xdeB\x08A}}=\x8b\x16-\xe2\xbe\xfb\xeec\xd3\xa6M\
+\x98\xa6\x89\xc3\xe1 ++\x8b\xf3\xcf?\x9f\xdbo\xbf\x9d\x91#G\xc6,\x04\xce\x83\
+eYL\x9d:\x95\xa5K\x97\x06,\xd7\xc2\xab\xd1\xc4\x8f\x84\xf0\xf1\xfa\xf3\x9b\
+\xdf\xfc&b\xa2+\xa5\xe4\xb9\xe7\x9e\x0b\x14]\xc3\xa0\xdb9\xe70`\xee\\\xd2\
+\x07\x0f\x06\xc3\xc0\xf3\r\xe0i\xd1]^\xce\xe1\xb7\xde\xa2l\xfe|\x0e/^\x0c\
+\x8d\x0c\xa0\x95\x95\x95\xf1\xf8\xe3\x8f\xe3r\xb9\x98?\x7f>k\xd6\xac\tXo\x9a\
+&\x87\x0f\x1f\xe6\x1f\xff\xf8\x07\xcf=\xf7\x1c\xb3f\xcd\xe2\x81\x07\x1e`\xd0\
+\xa0A1\x13_\x8f\xcb!Xx5\x1aM\xfc\x88\x8b\xc5\xdb\x98\xb5{\xd5UW\xf1\xf4\xd3O\
+{+{\xb5\xa9\r\xfb\xb1\x7f\xc8\x90!\xec\xdf\xbf\x1f\x00Gf&C\x9e~\x9a\xbc\x0b/\
+\x84f\xd2|\xa5\x94`Y\x1c]\xbe\x9cm?\xfb\x19G\x97/o]\x07\xec\xf03\t\xe0W\xc4&\
+55\x95\xb9s\xe7r\xeb\xad\xb7\x02\xb1I\xc2X\xb3f\r\xe3\xc6\x8d\x0bX\xa6-^\x8d\
+&~\xc4\xdc\xe2mLt\xc7\x8d\x1b\xc7\xbcy\xf3""\xba\x1e\xe6\xcd\x9b\xe7\x15]\
+\x84`\xc8\xbcy\xe4]tQ\x80\xd8I)\xc1\xed\xa6f\xebV\xac\xba:\xd2\x07\x0eD\xa4\
+\xa6*\xe1t8\xe8:y2c>\xfc\x90\x83\x0b\x16\xb0\xf5\xee\xbb\xa9\xdf\xb3\'d[\x8e\
+\xae]\xe9>{6\xa9\x03\x07\x929v,\xe9\xc3\x86\xe1\xcc\xcd\x05\xb7\x9b\xc3\xef\
+\xbe\xcb\x81\x05\x0b8\xf4\xd6[\xd4\xd6\xd6r\xc7\x1dw\x00p\xcb-\xb7\xc4\xcd\
+\xf7\xab\xa3\x1b4\x9a\xf8\x11s\x8b7\x94\xf0&\'\'\xb3d\xc9\x12&L\x98\x101!\
+\xaa\xad\xade\xd4\xa8Q|\xf7\xddw\x00\xa4\r\x1aD\xf1\x86\r\x08?a\x97Rb\x1e9\
+\xc27W\\\xc1\x91\x0f>@\x9a&\x8e\xccL\xba\x0c\x1dJ\xc1\x8d7\xd2\xfd\x92K\x10)\
+)\xde"\xe5\xdf^~9\xfb_z\xa9A[\xd9\xa7\x9f\xce\xf0\xe7\x9f\xc7\x99\x9f\xdfh\
+\xff\xa5eq\xe4\xed\xb7\xf9\xfa\xd2K\xb1\xaa\xaap8\x1c<\xf2\xc8#\xdc|\xf3\xcd\
+Q\x17\xdf\x92\x92\x12\x06\x0f\x1eLMMM\xc0r-\xbc\x1aM|\x88i8Yc\xd6\xee\x9dw\
+\xde\x19Q\xd1\x95R\xf2\xdf\xff\xfe7 \x02!\xb9\xa0\x00\x91\x94\x14\xb0\x9du\
+\xec\x18\xdf^s\r\x87\xdfy\x07\xe9r\x81eaVTpt\xc5\n\xbe\xbd\xe6\x1a\xd6\x9dy&\
+\xa6\x9d\x80`VTP\xb9zu\xc0\xfe"%\x85\x01\x0f=\xc4\xa8\xb7\xdejRt\x01\x84a\
+\x903c\x06\xc3\xff\xf5/\x10\x02\xd34\xb9\xf7\xde{\xd9\xb0aC\xd4\x930z\xf4\
+\xe8\xe1\x8d\xbc\xd0h4\xf1\'\xeeq\xbc\xc7\x1dw\x9c\xf7\xd1;\x12H)\xd9\xb3g\
+\x0fw\xdduW\x80\xa0\xf5\xb8\xf0Bd\xd0v{\xff\xfaW\x0e\xbd\xfez\xa3\xc7:\xfa\
+\xe9\xa7\x1cy\xfbm\xa4\xdb\xcd\xf6{\xee\xa1&\xa8\xe6m\xf6\x94)\x14\xdey\'\
+\x86m\x157\x87\x10\x82n3g\xd2e\xe4Hu\xfc\xa3G\x993gN\xd4\xd3\x8e\x1d\x0eG\
+\x83:\x13\x1a\x8d&~\xc4=\xaa\xe1\xfa\xeb\xaf\xa7[\xb7n\x11}\xdc\xbe\xf7\xde{\
+\xd9\xb7o\x9fo\x81\xc3A\xde\xf9\xe7\x07\xb6Q_\xcf\xde\xa7\x9ej\xf6X{\x9fx\
+\x02wy9{\x9fx\xa2\xc1\xba\xa4\xee\xdd\x01;\x1d\xb9\xac\x8c\n\xbf\xc8\x01##\
+\x83\xec\xd3N\xf3\xba*<H!\xe8~\xd1ET\xdb\xd3\xf7\xac[\xb7\x8e\xf5\xeb\xd7S\\\
+\\\x1c5\x97\x83\xc3\xe1\xa0g\xcf\x9eQ9\xb6F\xa3i=1\x13\xdePn\x86A\x83\x06q\
+\xd3M7E\xbc-\x8f_7\x80\xa0\x01\xb5\xd2\x7f\xfc\x83\xdam\xdb\x9a=V\xf9\xf2\
+\xe5\x1c]\xb92dHY\xb7s\xcf\xc5\xac\xa9\xa1\xec\xd9g\xd9\xfe\xff\xfe\x1f\xee\
+\xa0\xd8\xdf.\xa3F1\xe0\xc1\x07\xc9\x99>\x1d\xe1WR\xb2\xf0\xa7?\xe5\xe0+\xaf\
+P\xb5v-\x96e\xf1\xd5W_Q\\\\\xdc\x8a3\xd4h4\xed\x99\xb8\xba\x1a\xee\xbc\xf3N\
+\xd2\xd3\xd3#n\xe9\xf5\xe8\xd1#\xe0}r\xcf\x9e8sr\xbc\xef\x05\xb0\xff\xe5\x97\
+\x1b\x8d\xcf\r\xc0\xed\xc6\n\xe1\nH\xee\xdd\x9b\xdc\x193\xd8q\xcf=l\xb9\xe9\
+\xa6\x06\xa2\x0bP\xbd~=\xeb\xcf?\x9f\xefn\xbe\x19\xeb\xd81\xefl\xc2"=\x9d\
+\xc1\x8f?\xae\xa2\'\x80\x8f>\xfa\xa8u\'\xa8\xd1h\xda5q\x13\xde\xc2\xc2B\xae\
+\xb8\xe2\x8a\x88\x8b\xae\x10\x82\x81\x03\x07\x06,\xeb:a\x02\x86\xdf\xe0\x924\
+M\xdcA\xf3\xa7\xb5\xb2\x11\x06>\xf4\x10\xae\xfd\xfb\xd9\xf3\xb7\xbf5\xbd\xad\
+i\xb2\xf7\x89\'\xd8v\xcf=\xde\x04\r!\x04\x19c\xc7\xe2\xb4k?\x94\x95\x95\x85\
+\xdf\x17\x8dF\xd3\xee\x88\x89\xf0\x86r3\\u\xd5UQ\x19i\x97R2j\xd4\xa8\x80e\
+\x8e\xf4\xf4\x80\x815WY\x19\xd5\x1b7\x86\xddF\xd6\xe4\xc9\xf4\xb8\xf4R\xf6\
+\xbf\xf4\x122\xc4\x0c\xbf\xa1\xa8\xdf\xb3\'\xc0\xdd\xe1:t\x083(\xbcK\xa3\xd1\
+t\x0e\xe2b\xf1\x1a\x86\xc1Yg\x9d\x15\x95c\x0b!\xc8\xcf\xcf\x0fXV\xb1|9\xd4\
+\xd7\xfb\xdaOM\xc5\x91\x99\x19^\x03\x0e\x07\xfd~\xf1\x0b\x10\x82\xaa\xb5k[\
+\xbc[\xfa\xb0a^\xd7\x86\x94\x92#\xef\xbf\x8fU]\xad\xfac\xc4=\xb8D\xa3\xd1\
+\xc4\x90\xb8\xdc\xf13f\xcc`\xca\x94)Q\x1b\xc5?\xf1\xc4\x13)((\xf0\xbe\xaf\
+\xdd\xbe\x9dC\xaf\xbf\xee\r/s\xe4\xe62p\xee\\p\xb4>y\xa4\xf7\r7\x90}\xe6\x99\
+\x00-\xb6v\x01\x92\xf2\xf2\xc0N\xc4\xb0\xaa\xab\xd9\xf3\xe8\xa3\x01\xfd\x8d&\
+\x96eQYY\x19\xb0L\'Oh4\xf1#.\xc2{\xc6\x19g\xe0\x08C\xf4ZJVV\x16\x17]tQ\xc0\
+\xb2\x9d\x0f>\x88\xb4\x1f\xed\x85\x10\xe4_s\r\x03\xff\xf0\x07h\x85\xb5\xe9\
+\xc8\xca\xa2\xdf/\x7f\xa9\x04\x14\xe89gN\x8b\xf6K\xe9\xd3\x87<\xbfy\xd0\xca?\
+\xfc\x90\xcaU\xab\xd41\x1d\x8e\xa8\xd7\xcc\xad\xa8\xa8`\xbd\x1d\xbe\xa6\xd1h\
+\xe2O\xd4\x857\xd8\xbfk\x18\x06\xe7\x9e{nT\xdb\x14Bp\xcb-\xb7\x04\xd4}\xa8Z\
+\xb3\x86]\x0f>\x88\xb4\x0b\xa1\x0b\xc3\xa0\xf7\xed\xb7\xb7J|\xb3&M\xc2iO\xb4\
+)\x84 w\xe6L\xf2\x9a\x99R=\xb9woF\xbd\xf5\x16\xc9v\x02\x83\x00\xb6\xfd\xfc\
+\xe7\xde\xf5\xf9\xf9\xf9L\x9c81j\xd6\xbf\x94\x92\xc5\x8b\x17s\xf4\xe8\xd1\
+\xa8\x1c_\xa3\xd1\xb4\x9e\x98[\xbc\x85\x85\x85\x14\x15\x15E\xbd\x9d\x01\x03\
+\x060c\xc6\x8c\x80e\xbb\xe6\xce\xa5|\xf1b\xaf\xcbA\x08A\xef\x9f\xfc\xa4\xc5\
+\xe2\x9b\x92\x9f\x1f0@&\x92\x92\x18\xfc\xe4\x93dM\x9e\xdc\xc0m\xe1\xc8\xca"o\
+\xf6lN\xf8\xec3\xd2G\x8e\xf4\xd6{\xa8\\\xb5\x8a\x9a\xcd\x9b\xbd\xdb\xfd\xe2\
+\x17\xbf\x88j:\xaf\xcb\xe5\xe2\xf7\xbf\xff}\xd4\x8e\xaf\xd1hZO\xd4\x8b\xe4\
+\x04[\xbcW_}5\xff\xfc\xe7?\xa3^\x18FJ\xc9\xae]\xbb\x18=zt\x80\xb5\xe7\xc8\
+\xc8`\xf8\xcb/\x933m\x9a\xb74\xa4\x94\x92\x8d\xb3gs\xf0\xb5\xd7\x9a<f\xfa\
+\xb0a\x14\xaf_\x1f \xb2RJ\x04P\xb3y3\x96\xdf,\x0f\xa9\xfd\xfaat\xed\xaaB\xc8\
+\xfc|\xbbk\xa7L\xf1\x0e\xca\r\x1f>\x9c\xd5\xabW\x93j\xc7\xf3F\x1a)%O?\xfd4\
+\xd7_\x7f}\xc0r\xed\xdf\xd5h\xe2K\xcc-\xdeh\x0f$y\x10B\xd0\xb7o_n\xbc\xf1\
+\xc6\x80\xe5fU\x15\xeb\xcf;\x8f\xefn\xbd\x15\xf3\xf0a\xafp\x1aii\xcd\x1e\xb3\
+f\xdb6\xca?\xfe8\xa0\x06\x84\x10\x02\x84 m\xc8\x10\xba\x8c\x1e\xed}9\xb2\xb2\
+\xbc\xeb<\xa2\xbb\xfdg?\xf3\x8anAA\x01/\xbd\xf4\x12)))\x11=o\x0f\x9ez\xc4\
+\xf7\xdf\x7f\x7fT\x8e\xaf\xd1h\xc2\'\xe6\xc2\x9b\x96\x96\x16\xd3\xd9\x17~\
+\xfb\xdb\xdfr\xce9\xe7\x04\xae0M\xf6>\xf6\x18+G\x8c`\xef_\xfeB\xe9\xd3OS\xbe\
+dI\xb3\xc7\x93uul\xbb\xfbn\xcc#GZ\\QLJI\xf5\x9a5|5m\x9a7\xd9"55\x95\xc7\x1e{\
+\x8c\x91\xb6\x0b"\x1a\xb8\\.\xee\xb8\xe3\x0e\xf6\x04\xd5\x0f\xd6\xd6\xaeF\
+\x13\x7fb\xeejX\xb7n\x1d\xa3G\x8f\x8ej\x9b\x01\xedK\xc9\x81\x03\x07\xb8\xf9\
+\xe6\x9bY\xb0`AD\x8e\x99;c\x06\xc3\x9e}\x16G#\xc5}\xa4\x94 %\xf5{\xf6P\xfa\
+\xcc3\xec\xfc\xfd\xef\x91v\xdaqrr2\xf3\xe7\xcf\xe7\xa2\xa0\x82\xec\x91\xc44M\
+\x1e{\xec1n\xbf\xfd\xf6@\xeb\\\x8b\xaeF\x93\x10tx\xe1\x05%\x84\xc7\x8e\x1d\
+\xe3o\x7f\xfb\x1b\xf7\xde{/\xeeV\xc4\xdf\xa6w\x07\xc3\x01U\xa5\x81\xcbS\xfa\
+\xf4\xa1\xe8W\xbf"\xef\x82\x0bpfg\x83\x94X\xf5\xf5X\xb5\xb5\x1cz\xf5U*>\xfd\
+\x94\xb2\x17_\xf4&I\x00\xa4\xa4\xa4\xf0\xec\xb3\xcfr\xf1\xc5\x17GEt\xa5\x94H\
+)y\xf8\xe1\x87\xb9\xe7\x9e{\x1aN\xf0\xa9\x85W\xa3I\x08b.\xbcK\x97.e\xf2\xe4\
+\xc9Qm3d?lQ\x9a7o\x1e\xb7\xdezk\x8b\xc4\xf7\xb8\xb3`\xf6\xb3p\xec \xcc\x9b\
+\x08\xae\x10\x19\xbe)}\xfb\xd2e\xe8P,\x97\x8b\xaa\xf5\xeb\x91n7fyy\x83\xed\n\
+\n\nx\xfc\xf1\xc7\x999sf\xd4D\xf7\xf0\xe1\xc3\xdcw\xdf}<\xf1\xc4\x13\r\xceO\
+\x8b\xaeF\x9388\x84\x88\xb2\x9bW\xca\xfb\xfc\xdf\x16\x17\x17\xc7\xa5\x04\xa2\
+\'\xf6\xf6\x84\x13N\xa0[\xb7n\xbc\xfb\xee\xbb\x8d\xfai\r\'L\xfb?\xf8\xde#\
+\x90\xd4UY\xbd\xd9\x05\xf0m\x88\x9a\xe9fE\x055[\xb7R\xbbc\x87\xaa@\x16\xa2\
+\x92\xd9\xa4I\x93x\xf1\xc5\x17\xa3\x96\xad\'\xa5d\xcb\x96-\xcc\x9e=\x9b\xd7^\
+{\r\xcb\x8eU\xf6\xa0EW\xa3I,b>\xb8\xb6}\xfb\xf6\xa8Ou\x13\n)%\x96e\xf1\xe9\
+\xa7\x9f\xf2\xa7?\xfd\xa9\x818yH\xef\x0eW\xbf\x03\xc5\xb7\x83\x91\xa4\xc2v\
+\x85\x01\xa3\xae\x81\xd3~\x89o\x0e\xf8\x16\xe0p8\xb8\xf5\xd6[\xf9\xe4\x93O\
+\x185jTDE\xd7c\xc1\x97\x96\x96r\xc7\x1dw0q\xe2DV\x07MM\x04Zt5\x9aD$\xe6\xae\
+\x86\xd1\xa3G\xb3l\xd922\xc3-R\xd3\xda\xf6m\x91?x\xf0 \xf3\xe6\xcd\xe3\xfe\
+\xfb\xef\xc7\xe5r\x85\xdc\xb6\xe0\x04\xb8\xe8e\xc8\x1a\x18\x90\'\xe1;\x96\
+\x1b\xde\xff_X\xfeg \xb4n{),,d\xfe\xfc\xf9L\x992%\xa2Ep<\x82\xbbw\xef^\xfe\
+\xf0\x87?\xf0\xc2\x0b/p0D-`\x0fZx5\x9a\xc4#\xe6\xc2\x0b\xf0\xcb_\xfe\x92\xfb\
+\xef\xbf?\xaaae\x1e\xc1\xdd\xb7o\x1f\x0f?\xfc0\x0b\x17.d\xc7\x8e\x1d\x8dn?h:\
+\xccz\x06\xd2\xf2C\x8b\xae\xf7\xb8\x16|\xbb\x00\x16^\x07\xae\xea\xc6\xb7\x1b\
+0`\x00\'\x9ex"c\xc6\x8ca\xea\xd4\xa9\x8c\x1f?\xde\xeb\xeeh\xedy\xf8[\xb7\xaf\
+\xbe\xfa*\x8b\x16-b\xe9\xd2\xa5\rf\r\x0e\x85\x16^\x8d&\xf1\x88\x8b\xf0&\'\'\
+\xf3\xd4SOq\xe5\x95W\x86%FM\xb6g\x0b\xee\x17_|\xc1\x03\x0f<\xc0\x92%K8r\xe4H\
+\xa3\xdb\'g\xc0\xe4\xbb\xe0\xe4\x9f\x81HjZt}\x8d\xc0\x81\xaf\xe0?\x97\xc1\
+\x81o\x9a\xdf<))\x89\xef\x7f\xff\xfbL\x9b6\x8d\xc9\x93\'\x93\x94\x94D\x9f>}\
+\x1a\x9cwUU\x15\xfb\xf7\xef\x07`\xcb\x96-\x1c:t\x88\xca\xcaJ^}\xf5Uv\xed\xda\
+EII\tUUU-\xe8\xa0\x0f-\xbc\x1aM\xe2\x11\x17\xe1\x05%Fs\xe6\xcc\xe1\xc6\x1bod\
+\xec\xd8\xb1vg\xc2\xd7\x08\xcb\xb2p\xb9\\|\xf8\xe1\x87<\xf1\xc4\x13\xbc\xfb\
+\xee\xbb\xd4\xf9\xa5\xf0\x86\xa2\xc7\x08\x98\xf9$\xf4\x9e\xd4B\xc1\xf5CJpU\
+\xc2;\xb7\xc1\xfa\x7f\x83\xbb\x855\xcd\r\xc3\xf0\no0\xd5\xd5\xd5\xde\xd9(\
+\xc2\xf5\x83\x0f<\x13z\x8d\x85e\x7f\xf0-\xd3\xe2\xab\xd1$\x16a\x0b\xaf\xbf\
+\xa06uc7&\xbc\x1eRSS\xb9\xfc\xf2\xcb9\xed\xb4\xd38\xf3\xcc3\xbdE\xcc\x9b\x12\
+a\x8f(Y\x96EII\t\x1b7n\xe4\xa5\x97^\xe2\xfd\xf7\xdf\xa7\xb4\xb4\xb4\xd1\x813\
+o\x7f\x9d0\xf5^8\xf1\x0e\x15\xb5\x10\xae\xdeK\tB\xc2\xfe\xaf\xe0\xb5\x1f\xc0\
+\xde/\x81\xd8\x8f\x1b\x02\x90\xdc\x05&\xdd\x01\'\xdf\x03X\xf0\xe4x8\xf8\xado\
+}c\x7f\xa3\xe0\xbf\x8f\x16i\x8d&\xfa\x84%\xbc\xa1\xc44\xd4\r\xdb\x9c\xe8\x06\
+\x93\x95\x95\xc5)\xa7\x9c\xc2\xc4\x89\x139\xfe\xf8\xe3\x1b\xcc$\x01\xb0c\xc7\
+\x0e\xb6o\xdf\xce\xb2e\xcb\xf8\xf2\xcb/9p\xe0\x00\xb5!B\xb8B!\x9c\xd0o2\x9c\
+\xf7\x04d\x0fR\xd1\n\x91@J\xc0\r\xbb>\x81O\x1e\x80\xed\x1f\x133\x016\x9cp\
+\xf2\xff\xc0\xb8\x1fC\xd7"\xf5%"%|\xf5\x0c\xbc\xfaC\xdfv\xad\xfd\xfbh\x01\
+\xd6h\xa2G\xab\x84\xb757jkE7\x9a\x08\x07\xf4;\x19\xa6\xfe\n\xfaM\x05)\xc2\
+\xb7rC\x11\xe0\x150a\xdfJX\xf5$|\xfb\x06\xd4\x1c\x8e\\;\x1e\x8c$\xe81\x0c\
+\xc6^\x0b\x83\xcfQQ\x18\x04\x9dS\xdda\xf8\xcb`8v\xc8\xb7,\x9c\xbf\x91\x16`\
+\x8d&\xf2\xb4Hx[{\x83\x86\xda\xbe\xd7\tP\xba\x0e\xa4\x19\xbc&z\x08\x07\x14\
+\x9d\x02\xa7\xfc\x1c\x8a\xce\x88\xbc\xe0z0k\xa1t\x15\xe4\x1f\x0f\xce.\xca\
+\xd8\x15\xc0\xb1\xfd\xb0\xf2/\xb0}\t\x94\xae\x05\xd71\x15\x15\xd1\x1a\x8c$p$\
+A\xd7B\xe8{\x12\xf4?\x15\n\xa7\xa8\xf7M\r\x06J\tK\xfe\x1f|\xfc[\xdf\xb2\xb6|\
+9j\x01\xd6h"G\x93\xc2\x1b\x8eE\x14j\x9f\xa2S\xe0\xaaw`\xf5S\xf0\xfe\xbdP\xdf\
+\xba\x81\xf9\xd6! \xbb\x1f\x8c\xbd\x1a\x86_\x08y#\xa2\'\xb8^$\xb8\x8e\xc2\
+\xaeeP\xf2\x19d\xf6\x86>\'A\xee p\xa6\xab\xf5f\r\xec\xdf\x08\xbb\x96\xc2\xbe\
+5P\xd5\xc4\x8c\xee\xdd\x87BFOu\x9c\xc2\x93\xd4O#Y\x89pk\x128\x0e}\rO\x8c\x07\
+\xb7\xed\x89\x89\x84;H\x0b\xb0F\xd3vB\noKo\xc6\x96\xdc\xc8\xce4\xb8i\xad\xf2\
+\xa9\x02T\xee\x84\xb7o\x87-\xef\x80Y\x1f\xbcw\xf8\xa4d\xc3\x90\xe90\xf6:(<\
+\x19\x8c\xd4(\x8bm\x08<\xbe\xde\xef\xde\x86es\xe1\xe8^8\xeeL\xe8w\n\xf4\x9d\
+\xa2\x04\x14\xa7\xad\x9dM\xf5M6\xb3\xbe\xc5\x1d\x82E\xd7\xc0\x97\xcf\xf9\x16\
+\xb5t\x90\xad%h\x11\xd6h\xc2#@x\xdb\xfa\xe8\xd9`\x7f\x013\xff\x06co\xf0\x89\
+\xa0\'\x12`\xcfr\xf8\xf4a5\x10U[\x11^\xe73\xf2!o(\x8c\xba\x04\x86_\x0c\xa9\
+\xb9\xb6f\xc5Y\x0e<\x02\xbc\xf5\x1d\xf8\xf2\x9f\xb0\xe9\r\xb5,w\x00\x8c\xb9\
+\x12\xc6^\x03\xe9\xf9j\xb0/\xda\xfd=\xfc\r<6\x16L\xbf\xc8:-\xbe\x1aM|\x11\
+\xc2pD\xec\x86\x0b>\xce\x84\x1b\xe0{\x7f\xb1\x1f\x91\x830\xeb\xd4\xe3\xb94\
+\x95\xf8~\xf5/(\xdd\x00\x08\xa8\xdc\x03VPVoJ\x16\xa4f\xabQ\xfc!\xd3a\xc8\xf9\
+\xd0\xe7Dp\xa4\xa9\xe8\x04O\xc3\x06P{\x18\xea* %WY\xc2\xb1FJe\xb0J\xd4?G6\
+\xc3\xf6\x8f\xe0\xdb\x85\xb0\xed#\xd5\xc9\x9c\xfe\xd0s\x84\x8a\xb9\xcd\x1f\
+\x0b=\x867u@H\xef\xa5\x9e\x1eZ\xdf\x19\x95\xe6\xfc\xe9\xc3\xbeE\x91\x12^-\
+\xba\x1aMxx\xf5\xa1U;\xb5@t3{\xc3u\x1fC\xf6q\xa1\x8fa\xd6\xc2\xe2\x9fB\xd9\
+\x06(\x18\xab\x92\x19\x0c\xa1\x1e\xc9\xabJ\xc1rC\xd7\xdeJh\x01R\xba*\xe1\x05\
+\x90\x0e\xf5\x18o\xd5+\x9f\xaa\xbbNe\x90\xd5\x1c\x84\x9d\x9f\x82#YY\x95\'\
+\xfc\x08RrZ{v\x11@\xc2\xe2\x9f\xc0\xa0\x19jP\x0f\xfb\xa1BH\xa8,\x81\xfd\xeba\
+\xdfZ([\x07{\xbe\x80\x8a=\xca\xea\xb5\x9a\x18x\xbc\xe6}\xe8;5\xbc\xee\x1c\
+\xda\x00\x7f\x1b\xe3\x1b\xd8k\xad\xf0\n\xc3!Z\x1aB\xa8\xd1h\x9a\'j\xc2{\xe9\
+\x02\x18\xfc\xfd\xa6G\xdd\xad:\xf8t.|\xfck\x7fQ\xf0m\x93\xd1SE&\x04\x93\x92\
+\xa5\xc4\xd5r\xa9\xe3\x14\x8eW#\xff\x00\xbd\xc6\xc3\xf0\x8b 9;\x8e.\x07\t/\
+\x9d\x0b\x9b\xdeVq\xc3g\xfe\x0e\xfaL\x0er+x\xae\x96\x05\x95\xf6\x97\xc8\x9e/\
+\xa0\xba\x14\x0el\x84\xca28\xb4U}\x99T\x95\xc1\xb5\x1fB\xdf\xd3\xc2\xec\x8e\
+\t\xf3\xcfRV\xb7\x87\xd6D8x\xb6mi\xd2\x8cF\xa3i\x9aF]\r\xad\xb1r\x82\xb7\xeb\
+9\x16~\xfc\x05^K\xafI,\xd8\xf91\xd4\x1e\x81\xd4\x1c\xe8\xde\xd4#\xb7\x8d3%\
+\xd0\x85 \xc1;\x18%eb\xf8x\xb7\xbd\xa5"8<\xb5\x1cF^\x08\x13o\x87\x9e\'\xd8_&\
+M|!\t\xfb\xebP\xa0\n\xf1\xd4W)\xcb\xdd\x11\xe6\xbc\x98R\xc2\x9a\'\xe0\x8d\
+\x9b|\xcbZ*\xbcZ`5\x9a\xc8\xe3\x1d\\\xf3\xdcx\xcd\xdd\x90\xcd\xde\xb0\xc2\
+\xb6vg\xc7V\x00=I\x0c\xf1\x16]\x0fR*\x7f\xf3\x91m\xb0\xe4\xb7\xb0\xf5}\xe5\
+\x1e\xe9S\x0c=G\xc3\xe8+\xa0\xdb\x90\xe6\xab\xa1E\x8a}+`^\xd0\x04\xcf\xcd\
+\xc5^\x07o\xa3\xd1h"C\xb3\t\x14\xad\x15\xde\xfcQp\xc3\x97\xb4\xcc\xda\r\x13\
+\xaf\xc8\x02\xeej(\xf9\x1c\xa4\x0b\xfaO#2aX\x11\xc43\xd0V\x7f\x14>\xfb?\x15\
+\xe5P\xb1[\xadK\xee\n#fCA1\x8c\xb8\x10\xd2z\xf8<\x10\x91\x16c\xab\x16\x9e\
+\x1c\xa7b\x89=4\'\xbcZt5\x9a\xe8\xd0j\xe1\x85\xd0>?\x0f\x97\xfe7\xf2\xd6\xae\
+G\xbc\xdc5P]\xa6\x8a\xbf\xec\xfe\x14\xf6\xaeV)\xb1\x13o\x81\x91\x97\xab\xf0\
+\xac\x84F*\x01\xde\xf2&\xec\\\x02_>\xebKnH\xce\x80>\x13a\xd8L\x188\x1dr\x06\
+\x824"w\x1d\xa5\x84O\x7f\x03\x1f\xfc*pyc.%\xcf\xba\xc8\xb4\xae\xd1h\xfc\x89\
+\xa8\xf0\xe6\r\x85\x1f\xafRi\xb3\x91BZ\xb0\xeb#8\xf05\x1c\xfa\x0e*K\x95\x00\
+\xa7w\x87\xa2)0\xecBpf$\x8e\x8b\xa1\xc5H8\xf4\x8d\xf2m\xef^\xae&\xd4\xf4X\
+\xa3\xceT(\x18\x07C\xce\x83\xdca\x9197)a\xcf\xa7\xf0\xf7)\x81\xcbu\xc4\x82F\
+\x13{\xc2\xaa\xd5\xd0\xd8\xcdz\xea=0\xf5\xb7D\xf4q\xdfc\xed\x86\\\xe7\xe9O;\
+\x96\x08\xff\xc1\xb4\x90\xeb\x89\xdc\xf9\xb9*\xe0\x8f\xfd\x95\xd87\x85\x16]\
+\x8d&\xbaDl20\xe1\x80\xa1\xb3\x89\xb8\x8fU\x08\xfb\x98!^"\xda5\x18b\x80\xb7\
+\xffM\x9cc\xa4H\xea\xaab\xa65\x1aM|\tKxCY\xbb=F\xa8\xea\\\x9a\xc4E\x02\xfd\
+\x9b\x89\x05\xd6\xd6\xaeF\x13}Z$\xbc-\xb9\x19O\xb86t\xb2\x83&q\x10\x02z\x8f\
+\x8fw/4\x1aMD\\\r]z\xc0\xa8+H\xb8P.MCz\x8e\x0b\xb3\xe6\x83F\xa3\x89\x18-\x16\
+\xde\xa6\xac\xde\xe1\xb3!-/2\x1d\xd2D\x97\xb4nj\xf6\x8aPh7\x83F\x13\x1b\xdal\
+\xf1:S\xe1\xc4\xdb\xe36\xc7\xa3\xa6\xb5\x08U\x11M\xa3\xd1\xc4\x8f6\x0bo\xd1\
+\x14\xc8\x19\xd4\xfe\xa3\x0b:\x0b\x12-\xbc\x1aM\xbci\xb3\xf0\x1e?\x87\xa8\
+\xa6\x07k"\x8b\x10\x90= \xc4r\xedf\xd0hbF\x9b\x84\xb7\xdb`\x959\xa6\xad\xdd\
+\xf6E\xaf\xe3UYM\x8dF\x13\x1f\xda$\xbc\xc7_\xad&a\xd4\xb4/\xd2\xf2 7\xa8@}8\
+\xb3\x90h4\x9a\xf0\x08[x\xbb\xf4\x80\xf17\xe8A\xb5\xf6\x88\x91\xa4\x06E5\x1a\
+M|\x08[xO\xbcU\xcdi\xa6\xdd\x0c\xed\x0f)\xb5\xf0j4\xf1$,\xe1M\xef\x0e\xc57i\
+\xd1m\xafH\xa0\xf7\t\xf1\xee\x85F\xd3y\tKxG\xcc\x86\xe4xL"\xa9\x89\x08\xfa\
+\x0bS\xa3\x89/a\to\xd1\xe9\x91\xee\x86F\xa3\xd1t\x1eZ/\xbc\x86\x9a\xdeG[M\
+\x1a\x8dF\x13\x1e\xad\x16^\x01\xa4fE\xa1\'\x1a\x8dF\xd3Ih\xb1\xf0\xea8O\x8dF\
+\xa3\x89\x0c\xad\xb6x\xa5T\x13Lj4\x1a\x8d&<Z\xef\xe3\x95phK\x14z\xa2\x89+\
+\xbaV\x83F\x13;\xc2N\xa0\x90\xda\xf1\xa0\xd1h4a\x11\x96\xf0\xee\xfeTO6\xa1\
+\xd1h4\xe1\x12\xd6\x0c\x14f-qQ^)A\xba@\xd6\x834c\xdf~GA?\xadh4\xf1%\xbcY\x86\
+e|n\xde\x9a\xfd\xf0\x97!\xf0P>\xac{&\xf6\xedw\x14\x0c\x01\xbbV\xc4\xbb\x17\
+\x1aM\xe7%,\xe1\xdd\xb5"B\xb3d\xb6\x02)a\xd7\x12(\xdf\x0e\xd2\x82\xc2I\r\xd7\
+K\x89*D\x10\xeb/\x06\xbf6\xdb\x835)-\xb0\\\xf1\xee\x85F\xd3yq\x86\xb3\x93\
+\xb4"\xdd\x8d\xe6\xb1\\\xb0n\xbe\xaa\xaau\xfe<\xc8\x1d\xee\xd7\x1f\t\xfb\xd7\
+\xc2\xc6\x97a\xf7J\xc8\x1f\x01\x03\xcf\x86\xfeg\x82\x91\x1a\xfd,;\xb3\x0e\
+\xde\xff\x19$\xa7\xc1\xf1\xd7A\xf6q\x89\x9d\xd9Ws\x00\x0e~\xeb{\xaf#\x1a4\
+\x9a\xd8"\x84\xd1\xf2y{<I\x149\x03\xe0\xd6o@\xc4\xa8\x08\xba\x94\xf0\xdd\xeb\
+\xf0\xc2\xf9\xaa\x1c\xe5\xd9\x7f\xf6\t\x9bGt\xe7O\x83\xea\xfd\x81\xfb\xf5\
+\x18\x01g\xfc\x16\x06\xcd\x04\x11\xc5\xe9\x89\xa4\x84\xaa\xdd0\x7f:\xb8k\xe1\
+\x9a\x0f\xa0kQ\xf4\xdak+\xd5%\xf0\xa7\x81`\xd6\xab\xf7Zx5\x9a\xd8\x12\x96\
+\xc7\xa0|\x07\xd4WF\xb8\'M`\xd6\xc0G\xbfR\xbf\x8f\xb8$\xd0\x9a\xac=\x08\xaf\
+\\\xd5Pt\x01\xf6\x7f\r/]\x00+\x1fi{\x1f\xa4\x04w\x15\x1c\xd9\x04\x9b\x16\xc2\
+\xe6W\xa1\xa6\x0c\x90\xaa?\x19\x85p\xd5\xdb\x90\xd2\x15\x96>@BW\x88\xdf\xb7\
+\xce\'\xba\x1a\x8d&\xf6\x84\xe5j\x80\xd8\xdd\xb8R\xc2\x8e\x0fa\xdfZH\xea\x02\
+\xdd\x87\x05\xae\xdb\xf0\xa2\x12\xd8F\xf7\xb7\xe0\xd0f\xb5m8\x8f\xff\x9eH\
+\x8a\x0f\xee\x86\r\x0b\xa0\xaa\x14,\xb7Z\x97\x92\x05\xe3\xae\x85\xd3\x1f\x04\
+#E\x89\xef\x0f\x96\xc1k\xd7\xaa\x81\xc0\xb4\xfc\xd6\xb7\x17m\xa4\x84\xea\xb2\
+x\xf7B\xa3\xe9\xdc\x84\x17\xd5`AI\x8cF\xc5\x05\xb0\xe9U\xf5{\xc1\t\x90\x92\
+\x1d\xb8n\xcf\x17\xcd\x1f\xa3\xe4\x8b\xb6\r\x06.{\x00\x96?\x02GK|\xa2\x0bPW\
+\xa1\x96\xbfx\x1eT\xefU\xcb\x1c\xe9p\xf6\xff\xc1\x91mmh0\x8a\x08\xa0\xf4K\
+\xbf\xf7\xda\xcd\xa0\xd1\xc4\x9c\xb0\xf5(fi\xc3\x02*\xf7\xa9_\xfbM&0~\xd8\
+\x82\xdd\x9f7\x7f\x08w\x98q\xc7R\xc2\xce\xf7\xe1\x93\x07\x9a\xden\xeb{\xf0\
+\xaf\xe9P_\xae\xdeg\xf4\x81\xae\x85\xado/&H(Y\x19\xefNh4\x9d\x9bV\t\xaf\xbfu\
+T\xbe\x9d\xd8\xf81%t\xed\xa3~u\xa6\xd0@@\xcd\xba\xe85m\xd6\xc0\xe2\xbb[\x16z\
+U\xb6\x1e\xde\xbc\x19\xacz\xdb\xe7\xdb\'z\xfdj\x0b\xd5eP\xd6\x84kF\xa3\xd1D\
+\x9f\xb0-\xde\x92\x151J^\x13\xd0\xd3\x9e\x1f\xac\xf0\xe4\x86\xeb\xba\xb6@\
+\xe0\xba\xf6n}|\xad\xc7\x7f\xbc\xef\xcb\xe6\xb7\xf5\xb0\xfe%8V\xa6\xf6-\xdfJ\
+B\x0e\xb0\x95~\t\xaej\xf5\xbbv3h4\xf1!l\xe1=\xb2\x13\xea\xab"\xd9\x95\xc6\
+\xe9;I\x85\x839\x92\x82V\x08(:\xa5\x99\x9d\x05\x8c\xb9\xaa\xf5\x1a(\xeba\xed\
+?[\xb7O\xff\xa9\x90Q\xa0~\xff\xfa\xc5\xe8Z\xe3aa\xc1\xd7\xff\x8ew\'4\x1aM\
+\xd8\xc2[W\x01\x15;c\x93\xa9\x957\x1c\xfaLP\xd6Z@{\x02\x8ao\x86\xe3\xce\x06#\
+D|\x86\xe1\x84\xa9\xbf\x80QW\xb6>\xa2\xa1\xae\n\x8c`\xa1o\x02a\xc0)?\x07\x1c\
+*\xa6w\xf9\x9f\x13Kx\xa5\x84\xbd+a\xfd\xcb\xf1\xee\x89F\xa3i\xfd\xd4?\xf6\
+\xe3\xa9\xe5\x86o\x17F\xbeC!\xb1\xe7y\xfb\xe6u (k.\xa3\x0f\\\xf6:\xfc`\t\x14\
+_\xafB\xbc\x8c$\x18\xfe}\xf8\xd1r8\xe5W\x84\xf5\xf5\x92\x9a\x0bW\xbe\r\xa7\
+\xdc\xd3\x82\xe4\x0b\x01\'\\\x0b\xfdNW\xee\x97\xcf\xfe\x0f\xea\xab[\xdff4\
+\x11\x12\xbex\xcc\x1ehD\xbb\x194\x9ax\xd2\xaa\xcc5\x0f\x9e\x0c\xb6~\xa7\xc2\
+\xb5\x1f\x81\x8c\xf2-,%\xacy\x0c\xde\xbc\r\xae|\x03\xfaOkh\xc1J\xa9D\xaf\xee\
+\xb0J\xa6\xc8\x19\x02\x88\xb6\xa5\xeezj?\x94\xad\x86\xa5sa\xd3\x1b\xa1\xad\
+\xd8a\xb3\xe0\xa2\x7f\x03N\xd8\xfb\x19<3U\r\x04\xfe\xcf\x1eH\xee\x1a~\xfb\
+\x91BJ\xd8\xfe.\xfc\xeb\\_U7-\xbc\x1aM\xfchS\xad\x9b\xf2\x1d\xb1y\x9c\x16\
+\x02F_\xad\x92\'^\xbf\x11J\x96\x02V\xa0\xdbA\x08@@J7\xc8\x1d\xa6\x1e\xfd\xfd\
+E\xd7#\xa2\xadq\x8dx\x8e\xd9s<\\\xf82\xdc\xf4%\x8c\x9d\x03\x8e\x14\xdf6\x85\
+\'\xc19\x8f\x01NpW\xc2\x7f.SQ\x10\xdd\x87AJf\x9bN;"H\xa92\xec\xde\xbcE\x8b\
+\xaeF\x93(\xb4\xc9\xe2E\xc0e\xaf\xc0\xa0\xf3\xa3_\x14FJ8\xb2\x19^\xb9\x12\
+\xf6~\tc\xae\x84\xf1?\x86^\'\xd8\xbe\xd8\xe0\xaf\x10\x89\xd7-ql\xbf\xca|\x93\
+.8n&\xad\n\xc70ka\xf9\x83\x907\x12\x86\x9c\xaf\xda\xaa*\x81\x83\x9bTB\xc5\
+\xf0\x8b\xc1\x91\x06\xd2\ro\xdf\x02\xab\xe6\xa9\xfdz\x17\xc3\x8fV\xc6?\xb0\
+\xc1\xaa\x83\xe7g\xc0\xb6\x0f}\xcb\xb4\xf0j4\xf1%\xac\x94aa8\x84\xb4L\x89\
+\x84\r/\xc3\xe0\xf3#\xdd\xad\x10m\n\xc8\x19\x0c\xd7|\x0c\xab\x1e\x83/\xe6\
+\xc1\xda\xe7 \xabP\xbdr\xfa\x07no\xb9\xa0d\x15 \x95?z\xfc\x8f`\xe2O\x94\x10\
+\xb6Fu\x8c\x14\xe83\t\x9e?\x1f\x06}\x0ff<\n\x99\x85*=\xd8\x83\x94\xb0\xf1EX\
+\xf5\x94oYf/\xdb\xba\x8e\xa3\xc4I\t_>\x15(\xba\x1a\x8d&\xfe\x84e\xf1\x82\xcf\
+\xeaM\xeb\x06\xb7m\x82\xd4n\x11\xedW\xd3mK0\x8f\xc1\x96\xd7a\xd9\xc3*yA\xa2\
+\x92\x17@E3\x08\x03\xb2\xfa\xc2\xc4\x9ba\xe4\xa5\x90\x9eo\x8bn8B(\xe1\xc3\
+\x9f+?oF>\x9c\xf5\x00\x8c\xba\n\xef\xd7VM\x19<u"\x94\xefT\xef\x93\xd2\xe1\
+\x9a\x0f\xa1\xd7\x84\xf8\x95\x87\x94\x12*\xbe\x83\'\'@m\xb9o\xb9\xb6v5\x9a\
+\xf8\xd3f\xe1\x05\xb8\xf8E\x18zI\xecEFJpWC}\x85\xfa\xbdt-X\xa6\xf2\xaf&wQ\
+\x11\x0e\x8e.\x91\xe9\x97\xbb\x1a^\x9d\x03\x9b\xdeT\x05\x82\x8a\xa6\xc0\x90\
+\x99\xaa\xbd\xcf\x1fUn\x07\x00\x04L\xff#\x14\xdf\x1e\xdf\x9a\xbc\xd2\x84\x85\
+W4\x0c\x1f\xd3\xc2\xab\xd1\xc4\x9f\xb0\x85\x17\x02\x04\xa8\x7fV\x00\x00 \x00\
+IDAT\xeb\xf3\xde\xb0\x1a\x92\xb3\x9b\xdb\xa3\xfd"\xa5\xf2\x97\xba\x8f\xc1\
+\xc1o\x94\x95]\xb1\x0b\xf6\xae\x86:\xbbDf\xc5.(<\x11.x9\xba\xf5\x7f[\xd2\xd7\
+o^\x82\x05W\x05\xceM\xa7EW\xa3I\x0c""\xbc\x00\x97\xfc\x07\x86\\\x90\xd83/D\
+\x12Ot\x84\xff\xe9\x9a5 \x9c \x92\xe2\xebb\xa8\xde\x03O\x16\xab\x12\x96\x1e\
+\xb4\xe8j4\x89C\x9b\xc2\xc9\xfco\xe6/\x1e\x07:\xd1\xcc\xbf\xc2\x13#\xec\xf7r\
+\xa4\x83\x91\x1c\xdf/\x1f!\xe1\xbd\xbb\x03EW\xa3\xd1$\x16m\x9e\xb3\xd2#\xbe\
+\xdb>\x84M\xaf\xb5\x8f\xc9\x1e;*R\xc2\xc6\x97\xe0\xab\x17\x03\x97kkW\xa3I,":\
+Y\xf0\xc7\xf7A\xed!-\xbe\xf1@J\xd8\xff%\xbc\xf6c\x02\x82\x87\xb5\xe8j4\x89GD\
+\x84\xd7ss\x97m\x80\xa5\xbf\x8dk\xe8j\xa7\xc5U\t\x0b.\x8b]\xc58\x8dF\x13>\
+\x11\xb5x\x01V<\x06[\xdf\xd2Vo,q\x1f\x83\x0f~\x06\x077\x07.\xd7\xd6\xaeF\x93\
+\x98D\\x-\x17\xbcr\r\x94~\xa1\xc57\x16HK\xcd\t\xb7\xf2\xf1\xc0\xe5Zt5\x9a\
+\xc4%\xe2\xc2\x0bp\xec \xfc\xeb\x1c8\xbcQ\x8boT\xb1S\x95\x97>\x14\xb8X\x8b\
+\xaeF\x93\xd8\xb4)\x8e\xd7\x83\x7f<\xaf?\x99\xbd\xe0\xf2E\x90?\xae\xf3\xc4\
+\xf7\xc6\n)a\xcf2xn\xbao*\x1f\x0f\x1dMx/\xbau\xa1\xdc\xb9\xe7(i\xe9\xc9`\x97\
+\xff\x94\xc2\x1eK\x90~\xa9\xe0R"\x85\xb0\x17H\x04\xeawO\xd9R\x81\xdf\xb8\xa3\
+\xf4[\xd0\x8e\xaf\x96\x90 \x85D\n\x89a\t\x84pP~\xa0\x84\xe21\xb9\xcc{\xe8\
+\xdav|f\x1d\x9b\xb0\x8a\xe4\xb4\x94\xca}\xf0\x9fK\xe0\xc2\x17\xa1g\xb1Z\xa6\
+\x058\x02H8\xb4^\xd5\xd7\xed\xe8\xa2\x0b\xf0\xedw\x87\xd8\xbc\xed0)\x19\xaa\
+\x1e\xa7\x12\\\x89D \x84\x92Ri\xab\xa7\xf0\x08\xa9\x00\x89\xaa\x05*,\xb5@z\
+\xfe\xf5\\!)}\x01\xd9\xed\xf9\xc9\xcc>Wa\x810\x9cT\xee\xddKN\xd7\xfax\xf7J\
+\xd3\x04Q\x15^\x80\xc3\xdb\xe0\xf9sa\xe6\x130dv\xb4[\xeb\xf8H\t\x876\xc2\xfc\
+s\xa0\xeeh\xe0\xba\x8e(\xba\x00i\x19\xc9\xa4uM%3C\xcd\xc5$\x10H\x0b\xdb\xaa\
+\xb5\x0b-\xe3\x00\x0c\x90\x16RX\x08\xfb\x1b\xdeS _Y\x86\xc2+\xc6\x08\xe1\x95\
+b\x84\x9f\xc7\xad\xddY\x06\x96:})@Z\x08\xc3I]u\x1a\xe9]R\xe3\xdd1M\x13D\xd4\
+\xc7\xdb\xb3gO\xfe\xfb\xdf\xffr\xddu\xd7\x91\x93\x93\xe3]^}\x00^\xfd\x01\xac\
+{F\r\xbei\xbfoxH\t\x15[\xe1\x85\xf3\xfc\x8a\xf2\xd8tT\xd1\xf5G\xd8\xff\x81\
+\xd2G\x03\x10\x9e\x0f\x93\x04,\x894l+W\x82\x90\x06\x02\xbb"\xbe\x90\x08\xbb@\
+\xb3\x94\x1e\x0b\xd7@\x99\x8b\xaaB~P"b;y\x19\x08a\xa8Sl\xcf>\x93NFD\x85799\
+\x99\x993g\xf2\xf4\xd3O\xb3~\xfdzn\xb9\xe5\x16\xaf\xe5Q[\x0e\xaf]\x0fo\xdd\
+\xa8\xa6\xe7\xd1\xb4\x0e)a\xffjx\xee{pd[\xe0\xba\xce \xba\r\x91\x08)\x10\xc2\
+\xc0\xb2\x0c\xea]\x165\xaez\xea\xea\xdd\xb8\xdc M\xa1\xdc\x0e\xb6\x85+\xa5\
+\xb0\xbf\xf0%\xc2P\xeb\xa4E\x03\x17C\xfc\x854\xfc\x97\xa6\xfd\xd0f\xe1\xf5\
+\x1fX\x1b=z4N\xa7\x13!\x04\xbd{\xf7\xe6\x91G\x1e\xe1\x7f\xff\xf7\x7f\xfd\xb6\
+\x85\xd5\x7f\x87\xe7\xceVs\x80\xc9VN\xc5\xd3Y\x91\x12v}\xa0\x06\xd2\x82E\xb7\
+s\xa2T\xd3\x14\x92:\x0b\x10\x82\xf44\']\xbb\xa4\x90\x99\x9aLJ\xb2\x03SH\\\
+\xd2Bb!\xa5\xc7\xf5`\xd8\n\xa5,_C\x80D\xa9\xafhw.\x06M{&\xa2\x16\xef\x80\x01\
+\x03\x02\xde;\x1c\x0e\xee\xba\xeb.\xbat\xe9\x12\xb0|\xdf\x1ax\xfe<X\xf6k\xc0\
+\xd4\xe2\xdb\x14\xd2\x82\xcd\xaf\xc0\xbf/Uaz\x1a\x00\x81\x14\x02KJ\xaa\x8f\
+\xb9\xe9\xd5-\x8d\xabf\x0c\xe0\xfe\x1b\xc6q\xef\x8f\xc7q\xf1\xd9\xfd)\xe8\
+\x91\x8a\xcb4\xb1l\xabX"l\xbf\xae\xed\xefE \xa5\xf4\xbat\xf5gP\x13K":\xb86|\
+\xf8\xf0\x06\xcb\xa4\x94\xc8\x10\x9fj\xb3\x1e>\xbc\x1fv,\x83s\x1eU\xb3\x02k\
+\xa3\xc3\x87\x94 ,X\xfd\x18\xbc\xf5\x13\xfb\xb1X\xe3\x8b\xfe2\x05\x96e2\xeb\
+\xb4\xbe\\z\xd6@\xc6\x0c\xce!;;\x15i\xc1\x81\xc3\xf9\x9cQ\xdc\x87\xff,\xfe\
+\x8ew>\xdd\x8d\xc4\x890,\xe5U\x90\xf6\x83\xb9@]T)\xf4\x07O\x13s"*\xbc\x83\
+\x07\x0f\x0exd\x93R\xb2r\xe5J\x8e\x1d;\x16z\x07\t\xdb\xde\x87\x7f\x9c\x0e\
+\xdf{\x08F\\\xa2z\xd4\xd9\xef\x03\xcf\xd4F\x0b\xaf\x86\x8d\x0bi\xdf\xa1NQ\
+\xc02%N\x03\x86\r\xe8\xc6\x0fg\rc\xd2\x84B\x844\xc1TB\xda\xb7o\x1a\x85}\xbb\
+\x93\x9e\xe2d\xdf\xfe\x1a\xd6o+\xc74M\x1c\x0e\x03p\xa8\xc8\x06\xff\xb83\xf4g\
+N\x13["\xe6j\x10B\xd0\xad[\xe0\xc4k\xa6i\xf2\xf8\xe3\x8f7\xb2\x87\x8f\xaa}\
+\xf0\xdf\xab\xe0\xef\x93\xa0l\x95m\x88tR\xb1\x91\x12*w\xc0\xbf/\x84\x8d\xaf\
+\x10 \xba\xc9\xc9\xc9\x0c\x1a4(^]K\x08\x04\xe02-\x9c\xc9\x823N\xea\xcd\x90\
+\xbeY\x08\xcb\xc4\xacuc\xd5K\xa4\xcbB\xd6\xba\x11f=\xc7\x0f\xcbc\xe6\xe9\x03\
+\x11\x02\xdcn%\xb4\x86m\xec\xaap^\x87WqC=\x95i4\xd1"b\xc2\xdb\xa3G\x8f\x00Q\
+\x90R\xf2\xe7?\xff\x997\xdex\xa3\xc5\xc7\xd8\xb3\n\x9e:\x19\x16\\d\x0bp\'*\
+\xac\x0e*\xd4\xee\xabg\xe0\xf1q\xb0\xe5\x9d\xc0u\xa7\x9ez*K\x97.\xe5\xb9\xe7\
+\x9e\x8bO\xe7\x12\x08K\x82\xc3\xe9\xa4o~\x172\xbb8\xc1\x94\x18R\x00\x12)\xd4\
+`\x99\xe52I\xcfLe\xd8\xc0\xae\xb6uk\xd8\xf37Y\xbe\xfc\t\xcf\xb7\x9a@\x0f\xae\
+ibJ\x9b\x84\xd7?\xa2!;;\x1b\xa7Sy.\xa4\x94|\xf5\xd5W\xfc\xeaW\xbfj\xf51-\x97\
+\xb2\xf4\x9e:\x19\xde\xbd\r\x8e\xeeD\rbw`\x83DJ\xa8\xdc\r/\xcf\x86W\x7f\x04\
+\xb5G\x02\xd7\xff\xf4\xa7?e\xf1\xe2\xc5\x14\x17\x173|\xf8p\xf2\xf3\xf3\xe3\
+\xd3\xd1\x04B\xc5(x\xc4R%M\xe0\xcdb\xb3\xecm\x0c\x1c~\xb1\xbf``\x19\xc2\x9bB\
+\xec{\xb4\xf2\xb8\x1b\xb4\xf8jbC\xc4,\xde\xe1\xc3\x87\xe3t:\x91RRRR\xc2\x8c\
+\x193\xa8\xae\xaent\xfb\xff\x9d<\x99\xc5s\xe6P\x94\x1dz\x86L\xcb\xa5JL>6\x06\
+\xde\xfb\xa9J\x1c\xb0\xea;\x98\x00\xdb\xb1\xa4\xbb?\x86\xf9\xd3`\xf3\x9b4\
+\xf0\xe7\x9ew\xdey<\xf8\xe0\x83$\'\'#\x84 33\x93\xf1\xe3\xc7\xc7\xa3\xb7\t\
+\x83\xc7U`y\x92\xd6<\x0b\r?_\xad\xfd\xd3\xf2/\n/|\x1bx2\xdet\x1c\xac&\x1eDLx\
+\xfb\xf7\xef\x0f@yy9W\\q\x05{\xf7\xee\xf5\xae\x0b\x0e\xf0\xef\x99\x91\xc1\
+\xcf&O\xe6\xcc~\xfdX\xfa\x83\x1fp\xf1\xc8\x91\x8d\x1e\xb7\xae\x02\x96?\x02\
+\x8f\x0e\x87gOW.\x08wU\x07\x10`\t\xc7\xca\xe0\xbd;\xe0\xd9\xef\xc1\x81\x8d\
+\xa17+..&99\xd9\xfb^\x08AAAA\x8c:\xd9~Pv\xad\x01\xc2\xc00\x8c\x16dq\x89\x80\
+\x1f\x1aM,\x89XTCAA\x01\xe5\xe5\xe5\x9c\x7f\xfe\xf9,]\xba\xd4\xbb<Xt\xd3\x9c\
+N\xde\x9d3\x87l\xdb\x82\xeb\xdd\xa5\x0b/|\xff\xfb\x9c7t(w\xbd\xfb.\xfb*+C\
+\x1e\xdfr\xc1\xaeOa\xdeI\x90\xd5\x07N\xbc\x15\xfa\x9f\x01\xf9\xa3\xc1\xf2\
+\xdcC\t|\x13yj\x06H7\xec\xfa\x046\xbf\x05_\xbd\x00UeM\xef\xb7u\xebV;\xde\xd4\
+7\x08\xd4\xd9\x07\xd8\x1a#\x81\xff\xfc\x1aM\x00\x11\x13\xde\x13O<\x91[o\xbd5\
+\xa4\xe8\xfa\xfb\x82\x7f}\xc6\x19\x8c\xca\xcb\xf3\xde$B\x08\x1c\xc0\xe5\xc3\
+\x87sZQ\x11\xb7\xbd\xfd6\xff\xfd\xfa\xebF\xdb\x91&\x94\xef\x84w\xee\x04#\tz\
+\x0c\x87\xa2)0\xe6j\xc8\x1b\x0e\xcet\xcf\x81#uf\xe1\xe1\x11Z\x80\xda\x83P\
+\xba\x0e\xb6.\x86\r\x0b\xa0|{\xcb\x8f\xf3\xca+\xaf0w\xee\\\xbaw\xef\xee\x15\
+\xdf\xe0D\x15\x8dF\xd3\xbe\x88\x88\xf0\x1a\x86\xc1\xea\xd5\xab\xf9\xcf\x7f\
+\xfe\xe3]\x16\xaa~\xc0\xf8\x82\x02n).\x0e\xa9\x89B\x08z\xa5\xa7\xf3\xfc\xf7\
+\xbfO\x97\xa4$\x9e[\xbb\xd6{\x9c\xc6\xea\xfdZ.%h\xa5\xeb\xe0\xf3\xbfB\x97|(\
+\x9c\x00\xfd\xa6@\xaf\x13\xa0\xe7XH\xe9\n8\xfcj\xb6F\x01\x7f\x91\xc5\rU\xfba\
+\xcfg\xb0\xe3\x13\xd5\xb7}_)\x97I8\x1c=z\x94\xb9s\xe7\xf2\xd0C\x0f\xa9Gh!\
+\x18?~<\x0e\x87\x03\xd3Ta\x1f\xd22e\xe7\xac\xd7\xa0\xd1\xb4O""\xbc\xd9\xd9\
+\xd9\xbc\xfc\xf2\xcb\xd4\xd7\xab\x1a\xa0\xfe"\xe0\x11\xcdT\xa7\x93\xe7/\xba\
+\x88\x14#\xb4[YJ\xc9\xa1\xba:\xae}\xf5U\xde\xd8\xb4)\xe0\x18\xa1,\xe7PT\x97\
+\xc1\xb7\xaf\xab\x17@J\x16\xa4\xe5\xc0\x80\xa9P0\x1e\xf2\x86BZ7\xe8\xd2\x1d\
+\xd2\xf2\xd46F2\x81\xd6\xb1_al\xaf\xa0\xfa\xaf\xb7\x94\xe0\xbb\x8eA\xc5N\xf5\
+\xfb\x9e/\xe0\xd0fUG\xa1d\x95\x8aJp\xd76}\xcd\x9a\xc3\xff\x0b\xe7\x8f\x7f\
+\xfc#}\xfb\xf6\xe5\xb6\xdbn\x03 \'\'\x87\xee\xdd\xbbSZZ\xda\xb6F4\x1aM\\\x08\
+[x\xfdE\xf0\xf0\xe1\xc3,_\xbe\xbc\xc9\xed/\x1f=\x9a\xe3\xb2\xb2B\x86\xecH\
+\xe0@m-\xb3^|\x91\xcfv\xefn\xb4\xdaV(Ao\x8a\xba\n\xf5Z\xf3O\xf5\xf2\x90\x9c\
+\t\xc9\x19`8\xa1\xe0\xf8\xc0}\xb2\xfa@\xceqv{\xa8\xd8b\xff\x99{]\xc7\xa0l\
+\xa3Jy\xae9\xd4\\\x0f\x9a\'5\x1b2\xf2\xe1\xe0\xa6\x86\xeb\xfc\xc5\xf7\xee\
+\xbb\xef\xa6o\xdf\xbe\xcc\x9a5\x8b\xf4\xf4t\xd2\xd3\xd3\x1b\xee\xa0\xd1h\xda\
+\x05\x11/\x84\x1eJ\x1c\xbbw\xe9\xc2\xdd\x93\'\x87t1\xb8,\x8b?\xaf\\\xc9#\xcb\
+\x97\xb3\xa7\xb2\xb2\xc5%\x0e\x83\xb7k\x89\x10{\xa8\xafT/\x80\xa3\xbb[\xbaW\
+\xe40\x92\xa0\xfb\x10\x18q!\x1c\x7f-`\xc1\x9f\x87\x82Y\xd7\xf8>uuu\xdcr\xcb-\
+\x14\x17\x17SPP@\xbf~\xfd\xd8\xb6M\x97*\xd3h\xda#\x11\x15\xde\xc6Ds\xee\xd9g\
+3(;\xbb\x81\xb5[Y_\xcf\xcf>\xf8\x80\xc7W\xaeTO\xf8m\xf0S\x86\xda\xb75b\x1c\
+\x0b\xba\x0f\x87\x11\x17\xc0\x88\x8b w\x08\x88$\xdb\xefl)\x9ft\xc9g\xbem=~[\
+\x7f\xabw\xef\xde\xbd\xfc\xf4\xa7?\xe5\xe5\x97_f\xc0\x80\x01|\xf4\xd1Gq:\x13\
+\x8dF\xd3\x16"&\xbc\x8dY\xa0C\xf3\xf2\xb8t\xc4\x88\x06\xa2\xeb\x96\x92{?\xfa\
+\x88\xc7V\xae\x0c\xb9\x7f\xa4\xfa\x14o\xf1u\xa6B\xe1D\x18u\x19\x8c\xbc\x1c\
+\x9c\x19v\xdf\xfc\xceV\n\x18:=Px\x1b\xe3\xb5\xd7^c\xf5\xea\xd5\xba\xb6\x80F\
+\xd3\x8e\x89\xea\x9ckI\x86\xc1o\xce8\x83\xd4\xa0\x015\t<\xfa\xc5\x17<\xfa\
+\xf9\xe7\xd1l\xbeQ\x84\x80\xd1\xa3\xbb\xb0m[-\x95\x95*2 )\x03\x1cI-?Fj\x16\
+\xf4\n\xf2\x0fw\x1b\x04]z\xf8m\xd3\x15\x06N\x83\x8c>\xd8\xf5\x00\x1a?\xde\
+\xe8\xab\xe1\xe3\x07B\x0f\xca\xf9\x7f\x81\xd4\xd7\xd7\xf3\xfb\xdf\xff\x9e\
+\xd1\xa3G\xb7\xbc\xb3\x1a\x8d&\xa1\x88\x88\xf06f\xed\x9eu\xdcq\\0th`\xd0\x80\
+\x94\xfcg\xd3&\xee~\xf7\xddF\xf7\x8f$\xa1\xac^!\xe0\xef\x7f\x1fJ~~2#G\xae\
+\xa4\xa2\xc2\xe4\xfc\xc7\xed\xb2\x94->0j~\xc5F""Z\xd5G\x01\x99}a\xc8\xb9\xf0\
+\xf5\x82F\xb6\xf1;\x8fO>\xf9\x84\t\x13&\xb4\xbe!\x8dF\x93\x10\xb49e\xb81\xd1\
+4\x84\xe0\x8e\x93Nj \xba\x9b\x8e\x1c\xe1\xf67\xdf\xc4eYx|\x98m\xedCk\xfbhY\
+\xb0~}5\xbd{\'SX\xa8\xa6\x0cw\xd7\x83t\x02I-|9i(\xb2m9\x13\x01\xbd\xc6\x06.j\
+\xccMr\xf0\xe0A\x1e}\xf4\xd164\xa6\xd1h\xe2IX\xc2\xeb\x11\x84\xa6\x06\xb4N-*\
+\xe2\xb4~\xfd\x02\xd6\x1d\xae\xab\xe3\xbaW_\xa5\xb4\xaa*x\xb7\x98\xb3`\xc1\
+\x81\x80z\x0f%\x9f\xc5?\xe5x\xccUM\xaf\xf7\xbf\xde%%%Mm\xaa\xd1h\x12\x98\xb0\
+-\xde\xe6,\xd5[&N\x0c8\xb8KJnx\xe3\r>\xdb\xbd\xbbE\xfbG\x9b\xcf>\xab\xa0\xce\
+/|\xab\xb2\x94\xb8\xcf\xf4\x90\xde]\xf9\x895\x1aM\xc7&,\xe1mL4\xfd#\x19\xa6\
+\x1fw\\@a\x97\xdf/[\xc6\x02\xbb\x06C\xbcE\x17\xd4\x8c\x04\xb5\xb5\xbeJ\xeb\
+\x87\xb7\x11w\xe1\x15)0\xe0\xb4f\xb6I\x80k\xa7\xd1h\xdaFDg\x19\xf6p\xc3\x84\
+\t\xdeH\x06)%+KKy`\xc9\x12 ~\xc2\x11\xdc\xee\xd1\xa3&;v\xd4&T\xf1k!\xec\x01\
+\xbef\xba\xa4\xc5W\xa3i\xdfD\\x\x05pB\xcf\x9e>A\x13\x82\xbf\xae\\I\xad\xdb\
+\x1d\xe9\xa6\xda\x8c\x10\x92\t\x13\xba\xc6\xbb\x1b\x01t\x1f\x06Ii\xad\xdf/\
+\xde\xf1\xca\x1a\x8d\xa6\xe5DLx=7\xfe\xe9\x03\x06pra\xa1Z&%\xefm\xdf\xceK_}\
+\x05$\xa6\xa5\xe6H\xb0.\xa5\xe7CVa\xbc{\xa1\xd1h\xa2I\xc4-\xde\x9f\x9fr\n\
+\xc2\x0e\x17pI\xc9\x1d\xef\xbc\x83\xdb\x0e\x1d\x8bt[m\xc5\xe5J@#Q\xc0\xe0\
+\x19\xbe\xb7\x8dY\xb2\x89x=5\x1aM\xcb\x88\xa8\xf0\xa69\x9d\x0c\xcb\xcbC\x08\
+\x81\x94\x92\xa5\xbbw\xb3\xe9\xc0\x81H6\x11Q>\xfd\xf4h\xbc\xbb\xd0\x00\t\x14\
+\x9d\x1a\xef^h4\x9ah\x12\x11\xe1\xf5XeW\x8c\x19C\xcf.]\xd4B!\xf8\xdb\xca\x95\
+\x98R&\xacu&\xa5\xa4\xb883\xce\x9dP\xb3jH\xb7za\xaab:-I\xc6H\xd4\xeb\xaa\xd1\
+h\x9a&\xa2\xb5\x1a\xa6\x0f\x1a\xa4\xdc\x0cBp\xa0\xa6\x86\xf7\xbe\xfb.\x92\
+\x87\x8f\n\x19\x19\x8e\x98\xb6\xe7I\xda\xb0j\xa1d\xb9\x9aG\xee\x9b\xd7\xa0\
+\xce\xcf\xf8\xb6\\\xc4=\xb4M\xa3\xd1D\x8f\x88\tozR\x12\xe3\n\n\xbcn\x86\x0f\
+\xb6o\xa7\xca\x9e\x91B\xe3\x9b\xcd\xa2\xfe0,\xfb=\xac\xff7T\xec\xa6\xcd\x02\
+\x9b\x08\x15\xd84\x1aM\xeb\x88\x98\xf0vMI\xa1\x97\x9f\x9b\xe1\xa5\xf5\xeb\
+\xd5\xaf\xfaq\x18)\xa1f?,\xfd\x1dl\xf8w\xd0\xcc\xc2)@\x010\x04\xb0\x80\x15@+\
+\xe7g\xd3\xd7X\xa3i_\xb4Yx=\xd6VA\xd7\xae\x18v\xec\xee\xc1\x9a\x1a>\xde\xde\
+\x8a\xa9t\xe3\xc8\xd1\xa3*\xbe89\x83\xa8\xccL,%l~\x05\xde\xbf\x07\x0en\xb6\
+\x17\n`$0\x1e\xe8\t$\xfb\xed0\x04x\x1a\xa8\x89|_4\x89\x81r7\xb5\xfe!\xa5\xa9\
+d\x1f\xfd\xc8\xd3\xbe\x88\x98\xc5{r\xdf\xbe8\xec\x0f\xc6\xfec\xc78Z\xd7\xc4<\
+6\t\xc4\xaaU\xaa`O\xaf\xd1aWu\x0c\x89\x94 ]\xb0\xfa\tx\xe7\x7f\xc0\xf2\xe4\
+\x8f\xf4\x02f\xda?C5\x98\x03L\x00>\x89PG4\x89\x85\x04\xa4D\n\xcf\x1bT%|\xfb\
+\xbd\xe7\xe3 \xfd?\x1b\xb2)\xd1\x95\xde\x9f\xd2o\x7fMb\x131\xe1\xed\x97\x9d\
+\xed\xfd\xa3\xaf/+kr\xdbDAJ\xc1\xee\xdd\xbe\xca\xe3\x91\xca\x1e\x96R\r\x9e\
+\xbd};\xac~\xca^\xe8\x04\xce\x03F\xe0\xbb\xa1\xfcn\xac\x80e\xb9\x91\xe9\x87&\
+\xf1\x90\xf6+\xa04\x1e\xd2\xa7\xc1A\x1bK)\xfcD\xb8)\xbbV\x80%\x10\x18HK \xa5\
+\x96\xe0D&b\xc2;0\'\x07P!Z;\xca\xcb\x81\xf6\xe1{,)\xb1\x857\x82\xcfj\xd2\x05\
+\xf3\xcf\x86\x9d\xcb\xec\x05N\xe0B\x94\x1b!`C\xc0\r\xec\x06\xf6\x02\xf5@\x17\
+\xa0[\xe4\xfa\xa2I0\x84\xb4\x7f\xa8Ah\x89\x85\x10\x12\xa4\x01\x18 L\xdbru\
+\xe2\x90\x82c\xf5I\xd4[\x0eD\xb3\x1fP\x89\xb0\x04\xc2pb\x1eK\xa2\xbe.5\xea\
+\xa7\xa2\t\x9f\xc8Y\xbcYY\x80z$Z\xbf\x7f\x7f\xa4\x0e\x1bU\x06\r\xf2\x15E((\
+\xb6#\x0f\xda\xf0U!%\xb8*\xe1\xdd\xdb\xfdD7\x19\xb8\x14(\xf2\xdf\x10e\xc1|\
+\x07\xbc\x05\x94\x03\xd9(q>\x0f(\x04^@;\xee:,\xb6\xf8\x02\x12\x03\xa4\xa5\
+\xdc\x0fH\x04\x02!\xc0m\x9a\xb8j+8e\xf4&\x8a\n\x0eSW\x9f\x14\xda\x0f&\x95\
+\x93\x01a!L\x03!\x04U\xd5G\xe9\xdb3\x8d\x87>\xbfG\xa6\xa4\xa5\xe02-\x84\xc7\
+\r\x91\xf0\xa6P\xdb\xb0\xccZ\x92\x92\xb2\x19>\xe6\x9e\x84>\xd3\x88\x08o\x97\
+\xa4$\xf232"q\xa8\x98\xd2\xa7O\x8a\xf7\xf7\xe4\xcc\xb6\x8b\xaet\xc3\xe2\xff\
+\x815\xff\xb4\x17:\x81\xef\x03\xfd\xfd7DE/\xbc\x03\xacAE5<\n\\\x04\xf4@\xdd\
+\x18/\x12 \xba\x9e\x19\x87\xc3\xef\x9d&\xb1\x10J,m\xa4-\xb6\xea\x0fl \x10\
+\x98\xee:\xcc\xba\x83\xcc:i\x153F\x97QS\x99\xd2\xd8\xc1\x1a\xe0\x90\x0e\\\
+\x98\xec?\xfa!UU\x16\x864pZ\x06\xf5N\x17)\xeedD\x07V\xdfzj \xb5w\xbc\xbb\xd1\
+,\x11\x11\xdeT\xa7\x93\x9c\xb40Jj\xc5\x90\xe0X\xd7\xe4dAr\xb2Ay\xb9\x1b\xe1h\
+8\xedN\xab\x8e-\xa1\xf6\x10,\xfa!|\xfb\x9a\xdf\x8aSh\xe8^\x10(\xc1]\x85\x8aj\
+x\x08\x98J\xa0%R\x1d~_4\x89\x8e\xf0\xca\xae\xf4z|\xa5_\xedj\xd4`\x9b%0\x04\
+\xe4d\xa4\x93v\xb4+\xa94\x1d\xd5\x10\xd4\x04R:\xe9\xe6\xc8\xf7\xbe\xf7\xe6\
+\xa8:\xe9\xd0\xc2+\x85\x05\xddz\x02\xdb\xe2\xdd\x95&i\x93\xf06\x17\xb8\x9f\
+\xc8\x96ZF\x86\x83\x8c\x0c\x07%%\xf58R\xecp\xb20\x11\x12\xde\xba9Ht\x8f\x03N\
+\x0e\xdaP\x02\xfb\x80\xf7\x80\xd3\x80\x85@W:\xfc\xe3\x9f\xc6\x1fi\x0b\xae\
+\xb0\x9f\xb0\xa4zZ\xb2$R(W\x03\xc2P.\x08\xcb\x89e)\xc5lm\xdd\xe8D\xaa3\x1dK\
+\x04\x06X\xb1\xcdF\r\x87\xb0k5\xf8\x8b\xee\xc5\xa3F\x91\xe2\xf9\xc6F\xb9\x1e\
+\x12\x9d\xf1\xe3\xbb\xe2v[\x00t\xed\x05]\xfb\x84w\x1c)\xa1b\x87J\xfb\xf5\x92\
+\x8d\xf2\xd5\xfa_]\tT\x02\xff\x02n\x03\xdeD\x8bn\'FH\xc0\xf2H\xb0C\xcd\xb4*\
+\x1d |n\x07)eP\xf4\x83\xa6%\xb4\x87+\xd6\xa6\xc9.\x01r\xd3\xd2\xf8\xe9I\'y\
+\x93\'\x90\x92\xe2\x82\x82\xc8\xf4.\x8a\xf4\xef\x9f\xca\x9a5*\x867\xabP\xb9]\
+\xc3e\xdd\xb3`\xfa\x87-\x9f\x01\x04[\xd0\x02\xf8\x0c\x95\xa5\xf6\x1b \r-\xba\
+\x9d\x12\x81gX\xcd\x8e\x17C\x19\xb9\xc2+\xb6\x16\xca\xfa\xc5\x90\xde(\x08MkH\
+\xfck\xd6jWC\xb0\xe8\xbe~\xc5\x15\x0c\xb4#\x1a@=\xe2\xf4\xee\x9aX\xb3:\x84b\
+\xe0\xc0T\x96/W\xb9\xb9E\xa7\x86\x9f<a\x1e\x83/\xe7\xfb-\xc8\x06\x82\xab\x8b\
+I`\x0f\xf0%\xf0\x1c\xa0#}:5^\xd9\x15\x1e\x97\x80\x04L\x10\x96\x1a\xe1\x95\
+\xea%\xbc[kZG\xe2_\xb3VY\xbc\xfe\xa2\xeb\x10\x82g/\xb8\x80\x93\xec\xc28\xfe\
+\x14\xe5\xe4$\xd4\xa9\x87\xf2EO\x9c\x98\xc5\x92%*\xde8\xabo\xf8\x11\rU{\xe1\
+\xa8\xffL\xeb\xe3h(\xba\xc7\x80E@1*\xca\xa1\xa9\xb6\x12\xff\xcb:nx\x93\x0f\
+\xda\xf1E\x12\xfe\xbf\xf8M\x06+\xed,\ta\x0f}\x19\x00\xd2\xe8\xd0\x03aQ\xa1\
+\x9d\xb8fZ,\xbc\xc1\xe2u\xed\xb8q\x9c3p`H\'\xfe\xe0\x9c\x1c\x86v\xef\x1er\
+\xbfD ;\xdbA\xef\xde\xc9l\xdbV\x830\xa0`|x\xc7\x91\x12\xf6\x7fm\x97q\x04HB\
+\xd5`\xf0G\x00\xcb\x81\x03\xc0\xef\x81\x96\xf8\xfdw\x86\xd7\x9f\x8e\x8e\xb0}\
+\x9e\x12\xd1\x1e\x8c\x9a\x90xDV\x08%\xb1*\xc3L\r\xa8!\x0c\xdb\xdam}\xfa\xaf\
+\x94\x12i\x08df\xba\xfa\xd9N\x04(\xd2H\x87\x05\x86\xd9\xfc\x86q&\xac\xa8\x86\
+\xac\x94\x14\xee\x9f:\xb5\xd1\x0f\x86C\x08\x86\xe7\xe7\xf3M\x82\xce>q\xfc\
+\xf1\x99t\xe9\xe2\xa0\xa6\xc6"\xab/\xf4\x18\x15\xdeq\x84\x80\x92\xcf\xfd\x16\
+d\xa2\\\r\xfeT\xa2\xc2\xc7r\x81\xd14/\x18\x02\xe5\x96\xd0x1<!Wv\x82\x81\x8c\
+\xce\xe4\xd81C\x08_\x1e\x9a\x81PZk;\xbb\x0cO\x96\x83w\xb0\xbai\x01\x95RBj*F\
+\xde\x00d\xb7Q\xe0\xccE\xba\xf6B\xd9:\xe4\xe1=\xe0ru\xae\x08\x07K\xd8Y\x80\
+\x89M\x8b\x847\xd8j\x9d5|\xb8\xaf\x04d#xR\x88\x13\x91\xc1\x83\xd3y\xfb\xed\
+\xc3\xd4\xd5I\x06O\xa0eVhc\xf8_\x99^!\xd6\xaf\x07jQ\xe1cM_2M#H\xa1\xea\x15H\
+\xa1\xfeP\xc2r\x81L\xfc\xc8\x99P(\xd1U\xb5\x19\x84-\xb0Bx\\\r\x12%\xc5x\xc7\
+\xe0\x9ar5H)!\xa3+\xc6q\x97c8O\xc1\x12y\x08\x1c\x18\xc9&\xb2O\tV\xde\xdbX[^C\
+\xd6\xd7w\x1a\xf1\x15\x18\xed\xc2\xdb\x10\xd6W\xc3%#G6\xe9K\x11\xc0\xe9EEav)\
+\xba\x08\x01\x17_\xdc\x9do\xbe9\x06@F\xcf\x08\x1e<\x94\xf0\xee\xb3\x7fv\xa1e\
+W\xdb\x02\xb6D\xacG\x1d\x02C$aH\x89\x94\x16RZ\x08\xa3\x1d\xdcYM"\xbc/_m$\xd1\
+\xa4\xc8\x06#\xa5\x84\xa4$\x8c\x01\xb30\x9c\x97\x81\x18\x83!\n0\xe8\x81\xa4\
+\x00i\x9c\x88\x91v\x15\x0c8=r\xd5\x9f4\x11\xa3\xd5\xae\x86\xe3\xbau\xe3\x8c\
+\xfe\xfd}\x8fKR\x86\xfc6\xed\x95\x19\xe7\xb9\xcc\x1a\xa1K\x17\x83\xf1\xe33y\
+\xee\xb9R\x00\x86\x9c\x17\xc1r\x90\xa1\x8c\xfcJ\xfb\xa7\xc7\xa0iIC\xa5m\xef\
+\xca\xb7\x8f\xffY\xba*\x8fb$%\xa3\xec\x00\xe1\r]J\xe4\x10%\xcb\xee\xa7\x030\
+\x9c\x92\r\x95I\xfczI9\xce\x94T\xbcY^\xed\xd8\xc7\xdb*|\xa3\x89!\x11\x85\xc7\
+#\x92g!E7\x04u\x08TT\x84\x14\x12\x89\x13A_\x9c]fa\xf6\xd8\x88,\xdb\xd5i\xac\
+\xde\xf6@\xab\x85wT~>IB`I\xc9\x1fW\xac`h^\x1e\xd3\x06\x0e\xc4\x19\xf4G\x1d\
+\x98\x9bKvj*\xe5\xb5\xb5\x8d\x1c)>L\x98\xa0B\xdd\xde{\xef\x08)]\xa1\xd7\t\
+\x112\x08\x04\xa1-^Od\xddJ\xc0E`\xd1\xf3PT\x02A\x93\x1f\x87\x93\xfd\xb7\xeb\
+\xc1\x07\xa9\xdd[\x86\xd3ax\xbb\x17\xd1\x82\xc3Q\xc2\xa33I@\x95e\xb1\xd2\x99\
+M\xed\xe8;02\xfb\x81\xbbF}\x81XV{\x0elh9\x1e\xc38\xe4:\x81\xcc\x1c\x88t\xf6C\
+Xuv\x9a\xb1\x81\x14\x02\x84\x85!M\xa4\x14\x08\xe38DfOd\xd9\xaeX\xf6\\\xd3\
+\x0c\xad\x16\xde\xc9\xfd\xfa\x01\xf0eY\x19?\x7f\xef=L\xcb\xe2\xee)S\xf8\xedi\
+\xa7a\xe0KUt\x1a\x86\xb70z<S\x87\x83\xfd\xd3\x17\\\xd0\x9dM\x9b\x8eQVVO\xbf)\
+\x90\x1c<\x18\xd6\xaa\x83C]e\xd3\xeb\xe9\x85\xf2\xf3\xeeA\x157?\x93\xa6\xc5\
+\xef\x08p\xb0\r}\xb2\x19\x9d\xe4\xc0t\x98\x8845@#\xa4\xc4\x90\xca\xa2\x94\
+\x01\xdf4\x89\xa3\xc4\xc2\xae $\xa4 I\x08\x8e\xbaL\xf6\';q:\x1dj\xb6j)A\x18X\
+\x9d\xc1r\xf3|j\x9bx:\x91"\x15d2\x86e\xda\xc1\xc1&H\x0ba\x08T\xd13\x07\x82\
+\xaeH\x91\x1e\x93.kZN\xab\x84\xd7\x10\x82\xa9\xfd\xfa!\x81\xdf-]\x8a\xdbR\
+\xf9^s\x97.e{y9\x7f8\xfbl\xfat\xe9\x82\x10\x02\x07\xd0;+\x8bC5\x893\x87MJ\
+\x8a`\xda\xb4\\\xfe\xf9\xcf2,\x0b\x86\xccl\xdb\xf1\xa4\t;\x97z\xde\x00\xc1\
+\x93n\x08\xa0\xaf\xfd\xbb\x05<\x00\x9cN\xd3\x83y{\x89\x885\x97$\x04I\x86\x01\
+\x86\x03\x0b\xa9\xacz)\xb1\xf0>\xac\xd3\xb4I\x15K\xfc\xfc0\xd2\x81\x10\xe04 \
+YZ$\x1b\x867\x99@\x08\x81%\xa4\xb7\xdaA\x87\xc6\x9b\x08\xda\xf8\xdfGH\x07\
+\x86%\xec\x1a\xe8n\x84a <e"%8\x84T\xc5\xd1e\xf3\xd5|5\xb1\xa5U\x83k\xd9\xa9\
+\xa9\x14eg\xb3\xa6\xb4\x94\xd7\xbf\xfd\xd6\xbb\\\x02/\xaf_\xcf\xa9\xcf<\xc3!\
+{\xca\x1f\xa7\x10\xf4\xcfn\x8b9\x19yN8!\x93>}RX\xb6\xac\x1c\xc3\t\xc7Mo\x9b\
+\xc6U\x97\xfa\xcd\xa3\x06\xb0\x9f\x86\x07\xec\x85O|\x97\x00\x1f\x87\xd8\xc6\
+\x9fO\x9aY\xdfB,!pKpK\x81\x89\xaa\xb7nJ\xc3N\x8d\xf6\xccx [\xf1\x8a&\xc2O{\r\
+,\x04nia\xaa2\xe1\xde\xae\n\t\x0e\x8f\x9b:H\x8f<\xf1\xb1\xbeW\xa8v\x1a.\x94\
+\x01?\x13L\x9e\x9a\xb9\xf4*\xa3\xd8.\xa6\x0e\xca\xb7k\x00\x9e\xf8`\xe99L\x82\
+\x9d\x97\xa6u\xc2\x9b\x95\x9aJfJ\n\x0f\xfaY\xbb\xfel?r\x845\xfb\xf6%l\xf0\
+\xf6\xb9\xe7v\xc30\xa0\xbc\xdcMV_\xc8\x1d\xd86\xff\xee\xd1\x12\xbf\xb9\xd4@E\
+0\x04\x1fO\xa0\xcaC\x1a(\xab\xf7\x87\xa8\x8au\xa1.\x91D\xc5\xfcF\x08K\xd89\
+\xffvM\x00)\xecY\x0e\xbc\xb1\xa3 \xf1Y\x90\xb2\xd1\xffZ\'\xd1a\xbd\xecLY\xcf\
+\x85\t\x1c\x03\x14HCb\tK\xb9M\x84\xbf\xa8\xf8]>?\xe1\rP-\x8f\xf5h_\x87\x80\
+\xfd\xbc\xd6`cb\x1d\'\xec\x07\x80&?\x9f\xc2\xb2\xaf\x99@H\xc3\xbe^R\x85\xdfy\
+N\xda\x90m(\x85\xa5\x89\x16\xad\xfa\x938\r\x83\xd5\xa5\xa5\xbc\xe1g\xed\n\
+\xc3!\xfc\xfd\xb7Kv\xeeL\x98\xf0\x15\x7f\xff\xae\xd3)\xb8\xec\xb2\x1el\xd9R\
+\xcb\xd7_W3\xe4\x1c\x10\xcd\rt5C\xaf\xf10|\xb6\xdf\x82#!6\x12\xc0@T*1\xc0\
+\x0eT\xe5\xb2P\xe2[\x8f\x9a\xde=\x12\xf8\xdd\xb8\x06\x86\xfaC\xdb\xb5\x00$ \
+\xa5\x05.7\xb2\xd6\x85U\xe3\xc2\xaaw\xa9p-a\x8b\xb2\x90>q\x16\xb1{y\n\xc4\
+\x18\x08e\xd1y\xaf\xa3\xf0\xaeo\xf0\x95\xef\xd9\xc8\x16Q\xff\xcb*\xa4DX\x9e\
+\x8d\xfc\x0f\xe8\xc9\x80\xb3\xbf\x94\xda\xe1\x1ce\xde/+\xf5\x07\xf5~Y\t\xa4J\
+\xc4\xb0\x97k\x12\x8fV\t\xef\x84\xc2B\x1eZ\xb2\x84z\xdb\xda\xf5\x17\\\xcf\
+\xef\x1f\xd9\xd3\xba\x07|\xf8\x13\xa0&\xef\xc4\x89\xca\xcd\xf0\xee\xbb\x87\
+\xa9\xaf\x97\xf4;\x85\xb6\xbb7\x1d0\xfd/~\xb1\xc0e4\xfeh8\r8\xc1ns#0\x06x\
+\x15\xa8\x00L\xd4\xf4?\xabQ\xf3\xafE\x00ik\x8aa)+\xd7\x12\x80t\x83e\x82i\x82\
+\xcb\xc4HI\xc6\xd1\xbd\x07\x8e\xfc\x1e\x88\xae]\x90\xa6\x84z\x0bC\xaa\xfc0\
+\x7f\x83Q\x88(\xbe\x90\x08)\x94hx\x85\x10{\x84^\x89\x88\x90\x02\x03\x87\xaa\
+\xb7\xea\xb1Z\x85e\xfb\xae=\x16\xb0\xf0\xfc\x1f\x80\xd2 \xdb\x92\x0e\xf8`z\
+\xd5)2\x17=\x92\xb4\xa4k\xb6\xfbEY\xbe\xbe\xa7\x13\x95Zm\xf9.K\x02\x9e^g\xa7\
+U\x83k\xfb++y\x7f\xeb\xd6&\xb7\xd9|\xf0 Un7\xa9\x0e\x07\xdf\x1d>\xdc\xa6\xce\
+E\x92i\xd3\xba\xe1p\xc0\xe2\xc5\x87I\xcf\x83\xfeg\xb4\xfd\x98B@z/\x98\xfd\
+\x0c\xcc?\x07%\x9ee@>\xa1\xef\xfe\x99\xa8\xb2\x90o\xa1f\x99\xb8\x00\xc8\x03\
+\xba\xa3\xfc\xc3\x11\xbc\\\x12\x15\x0b+\x84i\xfbJ%\x06j0Fb r\xb31F\x8f\xc69f\
+,"\xc9\x89\xb9{\x07\xf5+V\xc2\xce\xdd\x08S"\x1dN\xfc\x8beF\xf5\x9b\xd3\xef\t\
+\xc9\xa3\x9fM\x89\x85\xf0l)P\x96\xaa\xe5\xb4\xad?\x13\xc32T&\x18\x00\x06\xd2\
+0\x94\x15\x8d\x89\x90\x86\xaa\x93\x80z\n\xb0\x0c\xec\xba\t\t\xf3\x90\x16\x82\
+\xa6;\xa6\xbc.\rS/\xbc\x0f\x01Zt\x13\x92\x16\x0boVj*\x0e\x87\xc3{?4f\xc5\x1e\
+<v\x8cg\xd7\xae\xe5\x87\xe3\xc6QZ\xd9T\xacUt\t\xa8\xa4\xe6\x80\xcb.\xebAy\
+\xb9\xc9g\x9fU\xd0g\x12\xa4Dh\xdcO\x08(:\x0bF\\\x08_\xff\x07\xf8\x1a%\xbc\r6\
+\xb4\x7f\x8eC\xcdN\xb1\x11\xe5\xcf\xf5X\xbb}PQ\x11A\x97,\xdc\xa7\x05\x01X\
+\xb6KS\x1a\xe0@\x80iaI\x81s\xd0\x10\xd2\xae\x98\x83\xf3\xcc\xb3\x91]3U-\xe5\
+\xda:RJvS\xf7\xe4\xdf\xa8_\xf4&V\x9a\x1b!b\xe8\x1c\x14\xde\x7fZd\xa1)\xab\
+\xdc\x00$\xd2\xe1FH\x0ba\t[i<n\x12[\x9c\x11\x18\x18\xf6\xac\xbe\x800\xec\xb6\
+L\xaf\xe0\xb6u\xa2\xd3x\xa2\x9eH\x9a\xe8|;=\xaf\x8eL\x8b\x85\xb7\xa2\xb6\x96\
+w6onr\x1ba8\x84\xb4L\xf9YI\t\xa7\xf7\xef\xcf\x91\x04I\x9e8\xf9\xe4,\xfa\xf5K\
+a\xd1\xa2C\x94\x97\x9b\x9cx\xba\xd7\x05\x1a\x11\x84\x03\xce}\x0c*\xf7\xc0\
+\xae\xb5\xc0$T\xa1\xf3\xc6\xc8\x02N\x04N\xf2[&\x81\xcd\xc0K\x11\xea\x13J\xd3\
+\x11B\x89\x94\xb4\xb0,\t\x19Y\xa4\\\xf3\x03\x92\xaf\xba\x16\xd2\xd3m\xc3Q]\
+\x89\xe4\xa2\x01\x88$\x07\xb2\xf6\x18u\x1f|\x04NK\xc5u%\x18\x02@B]\x9d\x89%-\
+\x84P\xe7&0\x90\x86m\xd1\x1a\x02\xcb\xed\xe6py\x8d\xcfQ-\xf0\x05PH\xcb\xef\
+\xef\x1f\xc2?\xa1\xd1D\x91\xa8\xdcUk\xf7\xee\xa5\xbc\xae\x0e+N\xcf9\xc1I\x13\
+s\xe6\xf4B\x08x\xf8\xe1\xdd*\x8clZd\xad\x1b! \xa5\x1b\x9c\xff4\xa4\x18\xc0\
+\xeb4?\xa5EhGd\xe4\xfad\xcb\xa9\x1ap\x11\xe0\xb6 %\x99\xe4\xe2\xe3I>\xed\x0c\
+\xe8\x92\x81\xac\xad\x81\xdaZ\xa8\xab\x85\xdaZ\xa4\xe5&i\xc2\xc9\xa4\\r\x15"\
++[\x99\x81V\xe2=\xab:\x1c\x82\x1a\x97\xc9\xd2/K)=T\x0b\x8e\x14\x8c$\xc3v\x19\
+Hp\x1a\x88\x94T\xf6\xec\xad\xe0\x9d\xa5;\xb1\xa4\xc4\xe1TWCH\xdfu\xf1\x0b\
+\xa5\xd0hbJX\xc2\xdb\xdc\xe3\xef\xee\x8a\n\xde\xb5\x07\xd9\xe2Mv\xb6\x83\x99\
+3s\xd9\xb6\xad\x8e\xd5\xab+\xc9\xea\x07\xd9\x03#\xdf\x8e\x10\x903\x14\xae\
+\xfd\x102\xcaQ1\xbbqDY\xf4\x12\xb0\xd4\xcc\xab\xa6\x84\xd4t\x1c\xa3\x8fG\xa4\
+\xa5#,K\r\xbcIC\r\xca\x18\x12Q\xefB\x18\x0e\x8c\xc2B\x1c\x85\xf9\xe00Tzn\x02\
+!\x00\x87\xc3\xa0\xce4\xf9\xf0\x8b\xbd\xbc\xf2\xfevv\xee<\x8c\xcbeB\x92\x81p\
+&Q_\x0f%{+\xf8\xcf\xe2\xad\xbc\xff\xd9\x1e\xa4\x00\xc3\x93:-\x85\x8at@\xda\
+\xa2\xeb\xf5\x86\xc6\xeb\x944\x9d\x90\x16\xb9\x1a<.\x84\x96\x1e\xb4\xda\xe5b\
+\xc3\x9e\xf8\x14\x95\r\xee\xe7\x15W\xf4$/\xcf\xc9\xdbo\xabh\x86\xe3\xbf\x07\
+\x8e\x94\xe8\xb4-\x04\xf48\x01\xae~\x07\x9e\x9e\x02\xf5\xe9\xa8)\xdc\xfd\xef\
+\xef\x18a\xa1J\x93:\xd4\xfc2*\xaa\xc1\x92Xu\x12\xe9\xb1b\r\x8f\xa1m`Y\x12\
+\xc3[\x92\xd0B\xa4$\xc7\xde\xe9\x19\xe0hm\xfc\xe3f\x08\xf5\xaaw\x99<\xf5\xea\
+\xb7l\xd9y\x94YS\xfb\xd1\xbf(\x8b\xa4$\'\xdbvU\xf0\xca\x07\xdbY\xb2j/5\xf5\
+\x12G\x92\xfd8a\x1b\xb8\x9e8s\x87!\xb0\xec\t\'\r?\xf7\xb2\x7f\x0f\xfc\xaf\
+\x80\x7f|z\xdb\x0b\xceh\xa1\xef\xcc\xb4iz\xf7\xc6\xb0\xa4\xf4\x86\x95\xc5\
+\x93\xd4T\x83\x1bnP\x13o.\\x\x10\xe1\x801WE\xd6\xbf\x1b\x8c\x10\x907\n~\xb8\
+\x04\x16]\x0f%\xaf\xa0|\xbe=h\xf5\xd5n[\x18\x9e\xb4\xbd\x04\xca\xc7\xeb\t\
+\x11sX.<\x05\xc5-$`\xaa\x9c~\xe1\'z\x16j\xa0*\x1e\x8e\xcff,l{\xe8\x0c\x90\
+\x18\x86\xc1\xb1z7\x1f\xac)\xe1\x8bo\xf7\x93\x92\xec@ \xa8s\xb99ZUG]\xbd\x85\
+\xd3)\xfc4Nz\x13\x0e\xc0\xf2M*\xe9u\xfe\xfa\x92E\x02\xdb\x94\xfeo"*\xba\x9ec\
+\xcb\xe0\xd8\x04\xad\xcb\x1d\x9a\xa8\x08/\x10\x97\x81\xb5`kw\xc8\x904\x86\rK\
+\xe3\xe8Q\x8be\xcb\xca\xc9\xec\t\xdd\x87G\xdf\x90\x13\x02\xf2F\xc3\x15o\xc2\
+\xab\xd7\xc0\xa6\xa7Q\xf5x\x8f\x03\xfa\x01\x83\x81t\xa2\xfb\r\x80\xaa\xad!\
+\xd4<\xe2 $\x96\x10H\xe17\x9f\x83}!\x84\xb0\xb3\xc1\xbcaX1\xce\xed\xf7\xc4\
+\xe5J\x19\xb2]\xd9\xe0\x17O\xbfUM\x90\xdaZ\x93\xa3U\xd5\x98\xa6\n\x19\x13\
+\x0eIr\x92\x83$\x87C\x15\x8b\x91\x02\x95,-T\x88\x87\xb2q\xbdS\xf0x\xdan\xd0\
+\xa0\x08\xeaOD/\x8ag\xce\t\xdf4=>\xf7\x90o P\xd31\x89\x9a\xf0z\x88g\xf2\xc4m\
+\xb7\xf5\xc10\xe0\x83\x0f\x8ep\xf0\xa0\x9bS~\x0e\xce\x18\x95\t\xf6\x0c\xb8]\
+\xbc\x10\xbe\xfa\'|x\x1fT\xae\x05\xd6\xa2JC\xf6GM\x07$\x80B\xfb\xe7\xde\x08\
+\xf7\xc1\xfb\x9b\x9d\xed%|b\xeb\x95\x14i\xf8\xa2\xb8<\xbe\xcf\x18\xdf\xf4R\
+\x08\xb0,;\xd4\xcb\x1bv\x80O\x9c\xf0%s\x08\xec\x08\x05[|\x11$;\x1d$%\x19\xa8\
+\x8f\xb3g\x94\xd2>\t\xe1\x8b\xf7\xf5/;\xee\xfb\x17oz\xad@\x82\xe5\xab{\x80\
+\x9f\xd5\xef\x9d9\xa2\xad\xe7\xea7\xa6\x03\xab\x9d\x00\x00 \x00IDAT\xe7\x9aD\
+\x15wG\xa8A?<\xa7\x06\xeazxS\x9f5\x1d\x8d\x16\x0bok\xfd\xbc\xb1&\xb8o\xa9\
+\xa9\x06g\x9c\x91\x83\x94\x82\xb9sw!\x1c0\xf2\xd2\xd8\xba-\x85\x00\x91\x04\
+\xc7\xff\x10\x86]\x08K\x1f\x80\xcf\xfe\x0cV=\xb0)\xcam#\xb0\xa4\xcf\x87\x0b\
+\x96\xa7J\x83\xbd^\xda\x05V\x14\xc1\xa2\x12\xeb\xa2\xd9^#\x13\x8f\x10\xfa\
+\xd5\x8f\xb03\xd9L!1\xf0I\xab\xaf\x9f\xd2\x8e\xe9\xf5\x1c\xc9c\xd5J\x8fk\x17\
+5s\x9b\x0c\xb2\xe5=\xd6\xae\xe5{/\x95\xe8z\x8e*\xed\xf40\xe1\x11\xfb\x08\\\
+\x16!\x84_L\xb1\xf0\xa6\xf9J{\xc0\xcf\xdf\xc2O\xd8\x1bN\xd3&\xa2n\xf1\xc6\
+\x8bK.\xe9Aaa2{\xf7\xaah\x86n\x83\x95\x9b!.\x08U\xf7\xf7\xcc\x87\xa0\xf8\x06\
+\xd8\xfd\x19\xec\xf8\x08\xccz\xb5\xbat\x1d\x94\xae\x0f\xda\xa5\xcdO\nJq<7y\
+\xe8~\x85\x9al&\xf6\x0f(\xc2\x13`\xa04N\t\x8ea\xf8"\xbd<\xc6\xa7\xb4ly20\xa4\
+\xc7\x12\r\xees\xa0U\xeb\xaf\xe8\r\xceVz\x9d\x0e*\xd1\x04\x810\x04>C\xd3\xd7\
+!\xf5\xcc\xe0\xa0\xcd\x11\x98B\xf8\xd2\xc9\xec\xac9i\xff\x1e\xe0\xda\x10\x0e\
+\xedj\xe8\xc0\xb4Jx[b\xf5\xfao\x13O7\xc3\r7\xa8\xd8\xddw\xde9\x82i\xc2\xa8\
+\x8bi\xdb\xa4\x96m\xc4c@f\r\x84\xae\x03`\xe4\x95\xf6\n\t\xef\xdf\xd9Px\xa3E\
+\xf0\x1f\xcf\xdf\xb2\x8dWU9\x9fCA\xda\xb5\x83\xd5#\xbe\x9d\x12\x81\x1a \xb4p\
+X\xa6\x8a\xd0\xf0\x96k\x10~\x83e\x8d\xd0\xd4\'P`\x1fHxS\x89\x85\x10*$D\xa8\
+\xb6\x0cK\rBZ\xc2\x81\xd1P\xba\xc3<[\xdf\xd4\xedRJ\x0c\xc3\xa1\xeadH\xcbv\
+\x8dXHa\x92\xc8S4i\xdaF\xab\xbf\xbe\x13\xa1\xe0M0\xc1_\x06C\x87\xa63zt\x06 X\
+\xb0\xe0\x00\xce4\x18qI\xe2<\xb6\x05<\xc5[\xb0#\xce1\xbf\xf1F\xf8U\xccQ\x95$\
+L\x04\xa6]8L\xd8\x95,\x05R8\x91\xd2iW\x1b\xc3+\xaam)\xd0\xe3\xf1[\x08!0\x0c\
+\x81\xe1\xf1\xcf\x08\x81\x90\x0e\x10\x06"\xe4\x93A\x9b\xcf\xda\xfe)\x91\x16\
+\xb6\xaf\xdd\xe1k\xcb\x12:\xb9\xc3\xc6[\xea\xd3\x90|\xbd\xab\x0e\x97)\xe3f$D\
+\x02i\x99\xed`\x02\xfa0\xb8\xfb\xee\xbe\xa4\xa5\tV\xac\xa8\xe4\xfd\xf7\x0f\
+\x93?\x12\xf2\x86\xc6\xd6\xbf\xdbR\xea\xab\x82\x8a\xa9wJ|\x83HB*\x83\xd3\xf7\
+\xb8\xaf|\xa0\x86\xf2\x9b4\xd0"\x11\x81\x97\xc7\xba\xb6\xa4\xb2\xb8=cr \xb1\
+\x84\xc4\x14>\xdf\xb0\xd7\'.\xc3\x7f\xd9\xa3}>\x0b\x1bSY\xd8\x98\xb6\x87\xc8\
+P\xb6\xbe\x16^\xa4\x94\xd4\x9b\x92G\x17\x1ea\xf4U;\x187g\x07\xcf\xbc]\x1e\
+\xefn\x85\x8d\xc7H\x8c\x8a\x8f7\x96Vq\xb0\xb5\x9b\x96f0yr\x16\x00\x8b\x16\
+\x1d\xc44a\xec\xd5x\x82\x89\x12\x8e\xfd\xeb\xa0.\x02\x93[\xb6k\xa4\x00,{`\
+\xcb\xf0\x8a\x9ba\x1b}\xfeC\x80\xca\x0f\xaa\x12=\x84\x9dp\xd1f\xebGH\xb0\xa4\
+\xb7\x0c\xa5\xea\x87\xb2~\x85\xf4\x84\xe5\xf9\x15L\x0f\x18\xde\x0b\x0f\xcf\
+\x10\'\xa8\x88b\x87]\xff\x18\xe9\xf1#\xbb\xc10\xdb\xdcN\xbbG\xc0\x9c\xdf\xee\
+c\xe1\xc7U\xdeE\x7fz\xe1\x08W\x9d\x9dEzr\xfb\xbdM:\xdc\xe0\xdae\x97\xe53p`*\
+\xe5\xe5n\xfe\xfb\xdf\x03\xa4f\xc3\xc8\xcb\x13\xd3\xda\x95R\r\xacuzl\xdd\xf5\
+\xfc.,\xa1\xe6\x0b\x13\x127Pc\xa4p\xcc\x91nOr\xd9 \xd5\xa0\xcdH,\x8c$\x01u.\
+\\G\xab\xb0\xecd\x12C\n\x84\xa5DX\x1aQ\x10@\xe9\xb3\xf5\r\xe5\xefP~^\xe9\xc6\
+U_G\xaai6[\xf2\xa3c#\xf9h\xdd1\xdeXZ\x15\xb0t\xfb^\x17o}^\xc5\x05S2c\x1e}\
+\xd3\x16\xfc\xc7\xbe\xda\xb5\xf0\x06[\xbb\x86\x017\xddT\x80\x10\xb0x\xf1\x11\
+6o\xaea\xf8\x05\x90\x92\x13\xaf\x1e6\x8d\x00v|\x12\xef^\xc4\x1f\xdf\xd0\x9a_\
+\x94\x01\x80\x10d\xe2\xa6\xf7\xb1=8\xa5\x8b4\xcb\xa5\x02\xe3\xa4\x8c\xec\xe3\
+\x8b\x90\xb8\xdcn\x9c\x19Yd\r\xed\x830\xdc\xca\xef*\x8c\x80v"9\xd6%\xedA=o|\
+\xb0\'\xb6\xd7\xd6\xdfc5uT\x94\x1e\xc4i\xb4\x1fa\x89\x06+6\xd4\xe22\x1b.\x9f\
+\xfb\xdca\xa6M\xcc #\xa5}\\\x9f\xe0\x80\x83v-\xbc\xc1\x9cyf\x0ec\xc6tAJx\xe1\
+\x852\x00\xc6\\\xe9\xbb\xb1\x13\r\xab\x1e\xca\xbe\x0e\\\xd6\xe9\xdc\x0c\xf8\
+\\\x06H\xe9\x15U\x13\x13\x87!\x18aVs\xf3\xb6g\xa9\x16\x02\x87\x1d\x91\x1c\
+\xd1\x04\x0f\tN\t[+k\xc9=g:7\xbd\xb0 a\xae\xff_\xfe4O\xf6\xc9\xfc(a?\xbf\xd1\
+FJ\x98:6\x1d\xa7\x03\xdcA\xe2\xfb\xd5wu,\xfe\xa2\x9a\xd9\'g\xb4\x1b\xab\xd7\
+\xff\xde\xeeP\xc2{\xfd\xf5\x058\x1cp\xf8\xb0\x9b\x95+U%\xb2\x81g\'\xa6\x9b\
+\x01\xa0\xe6\x10TDh\xaa\x9f\xf6\x8c/\x9bN\x89\xb0\x85J\xf70\x84\xa0\x07.\xba\
+\x99\x07\x03\x12,"\xecg \t\xe8\xe9\xb6p\xa4\xd4D\xf0\xc0m\xe7\xb6;\xae\x17\
+\xe5\x9b.\x93\xec\xd9o[\xc2\t\xfaA\x8e\x12B\x08N\x1c\x9e\xca_\xee\xcc\xe7\
+\xb6\x87\xcb\x1a\x88\xef?^/g\xd6\xe4\x8c\x84\xffR\x92\x96)\x83\r\xaav+\xbc\
+\xc1n\x86\x1e=\x92\x98:UM+\xf1\xdak\x87(-\xadg\xea/\xc1h\xaa y\x9c\xd9\xbb\n\
+\\\xd5\xf1\xeeE\xfc\xf1\x1f\xaa\x12\x9e\x18]\xbb\xa6\x82\xd3\x80d\x873(\xc97\
+x\xef6 !\tI\x86QG}\x02N\xc7\x9b\x9e\x91\x8d;\xc9\x85\xa8o\xe3\xcc\xac\xed\
+\x14\x81\xe0\xba\xe9Y\xac\xdd\\\xc7\xbc\x85\x81\xd1\x0cK\xbf\xaca\xefa\x93>\
+\xb9\x89-c\xa1\x9eb\x13\xbb\xc7\xad\xe0\xf6\xdb\xfb\x90\x9b\xeb\xa0\xaeN\xf2\
+\xc8#\xbb\x11\x0e\x18pVl\xad]\xaf\xeb\xd1\x84#\xdb`\xd72\x90~\xdf\xd2}N\x84\
+\xbc\xe1\xb6\xa6\x00\x077\xc6\xaeo\x89\x8e\'\xb4J\xe2\xff7S\xefC\xb8\xf8"\
+\x8e\x0b\xb0\x120|\xcb\xb2\xdc\x9dVt\xbdH\xf8\xd3\xad=p\x9b\x92g\x16Ux\x17\
+\xd7\xd4K\xfe\xba\xe00\x0f^\xdf=\xc2\xc3\xad\x91#\x94\xb5\x0b\xedTxCe\xcf\
+\x9du\x96\x1aA\xdb\xb1\xa3\x8eo\xbf=F\xcfQPxR\x83]\xa3\xd3\x1f\tXP\xb2L\xcd\
+\xbb\xb6s\x19\x94~E\x83H \xe1\x80\x9ec`\xe4E0x\x06\xecY\x15\xb4\xbe\x13\xfaw\
+\x83\xf1\xde@1\xba\x12\xd2\xdf\xdcND\xbcI"\x9d\xf7\xa3!\x84\xc0)\xe0\x0f7\
+\xf7`\xed\xe6Z\xd6|[\xe7]\xb7\xf0\xe3*~1\'\xaf\xdd\x0c\xb2yh\x97\xc2\x1b\xcc\
+\xb4i\xb9\x8c\x1b\xf7\xff\xd9;\xef8)\xaa\xac\r?\xb7\xbb\'\x07`\x98!\xe7\x9cs\
+\x10\x04\x04\x13( *\x86UQW\x17\xd6\x0c\xba\xba\xabkZPw\xd7\xb4&\xf4\x13P\x8c\
+\xa0\xae\x19Ae1\xa1\x02*9J\xce0C\x9c\x1c;\xdd\xef\x8fS5\xd3\xdd\xd3=\x01&t\
+\x0f\xfd\xfel\x99\xae\xae\xae\xbaU}\xef[\xe7\x9e{\xce{\xe2\x01x\xf3\xcd#8\
+\x1c\x9a^\xd7JHdu\xff\x1cZC^*,\xbe\x1b~\xff\xcc\xdb\xc2-\xb5\xaf\x0b\xd2\xd6\
+\xca\xeb\x9b\x07\t\xee\x01\x1fF\x18A\x86\xb8H\xc5\x9c\x07\x9a2\xe6\xee\x83\
+\x9c\xc8\x94\x81\xb6/\xd5\xc1\xbc%Y\xdc2\xae\xbe\x87\xc4gm\xb6\xd2\x1b\x81\
+\x8c\xa9\xe0sj\x9d\x02n\xba\xa9\t\x16\x8b\xa2\xb0P3o\xde\x11\xa2\xeaA\xaf\
+\xeb\xaa\xdf\xcd\xa05l\xff\x08f\x0f\x84-\x1f{\x90\xae\xcd\xe7\x15\x0ft\x01F\
+\x02\x7f\x00\x86!%\xdd\xc3\x08#\x8c\nC)E\x8f6\x91<;\xb5\x116\x0f\xdd\x95\xe7\
+\xdfK\'\xcf\x1e|i\xc4e\xe9\xda\x84\x9c\xc5\xeb{1M\x9aDr\xfe\xf9\r\xd0Z\xf3\
+\xeb\xaf\xd9\x1c=j\xa7\xc3\x18\x88\xf1Wb\xbd\n\xe1\xb6\xc3\xaa\x97a\xc9\xfd\
+\xe0v\x1a\x1b\x9b\x02\xe7\x01\xcd\xf0~\xa4Y\x90\xa5s\xb3\xe5\x9d\x80Q\xc0;\
+\xc0\xfe\xeamg\x18a\xd4%(\x14W\x8dJ\xe0\x8d\x85\x99\xfc\xb4N\xa2P\xf6\xa59\
+\x99\xf9I\x06\x0f\\\x93t\xda\xc7\x0f\xe4\x93\xadj\x84\xbc\xc5{\xe9\xa5\xc94h\
+`\x05\x14\xaf\xbe\x9a\x8a\xcb\r}\xfeH\xb5^\x99\xdb\x01_\xde\x0e\x8b\xef5H7\
+\x02!\xd2\x9b\x80vHi\xf7(\x8fW\x84\xf1EO\x81\x00\x0b\x10]r\xcc\xb0\x7f7\x8c0\
+*\x06\x0b0\xfb\xfe&\xc4z\xf8u_\xfd8\x03\x8a\x87PpY\xbe\xfe\x10\xd2\xc4\x1b\
+\x17g\xe1\xe6\x9b\x9b\x00p\xfc\xb8\x83\xa5K3\x89I\xaa\xfa\xf2\xed\x9e\xd0\
+\x1a\x96\xff\x1b\xd6\xce564\x01n\x06F \x04[\xd1\xf3\xba\x81\xd0\xd5\xfa\x08#\
+\x8cZ\x83R\x8a\xb6M"\x18;,\xbex\xdb\xd1t\x17s\xbe\xc8\xc0\xad\\`\xa9\xfdD\
+\xeb\xf2\xe4sC\x8ax}/\xa6{\xf78\xfa\xf5\x93|\xed\x15+\xb29~\xdc\xc1\x80\x9b\
+\xc1\x16WM\xe7\xd7pl-\xfc\xf4ocC=\xe0J\xc0\xd7\xada\xb6\xd2\xac4\x91\x01\x14\
+\xe1M\xcak\x80\xa3\xd5\xd3\xce0\xc2\xa8\xf3\xd0\xf0\xe2=\x8di\xd2\xb0\xc4\
+\xd9\xbb\xe0\xa7\\\\\x16\xd7i\xe9nWe\xa5\x9d\xb2f\xb1!\xe7\xe3\xf5\xc4\x88\
+\x11\xf5\xb1X\xa4z\xc0\xff\xfd_*\xca\n]&R-\xa1\x0cZ\x83=\x13\x16L\x01g!r\xe7\
+\xae\x06\x1a\xf89\x9f\x1b\xf8\x0e\xd8\x08\xe4\x19\x9fG\x02\x89\x94\x90rz\xd5\
+\xb71\x8c0\xce\x14(\xa5H\x8a\xb70nX<\xaf/\x90\xd8\xde\xefV\xe6\xb3tC>\xe7\
+\x9e\x1fv5T\x1b\x92\x93#\xb8\xe7\x9e\x16\x00\x14\x15\xc1o\xbfe\xd1\xb474\xe9\
+[M\'\xd4\xf0\xe3\x0cH[g\xbc?\x07YLS\xde\xfb\xe0\x02~\x04~AH\xd7\xdc^\x04\x1c\
+\x07N\x18/\x8f\xd9P\xd8\xbf\x1bF\x18\x95\x87B\xf1\xa7K\xeac\xf5`\xb1\xe5\x1b\
+\x0b\xaa\xa6NH5\xd7\x97\x0c\x19\xe2\xf5\xbd\x11C\x87&\xd2\xa4\x89\xacZ}\xf6\
+\xd9q\xb2\xb3]\xf4\xbb\tT\x84\xdf\xaf\x9f\xde\xb95\xa4\xfe\x02\xbf\xbdbl\xe8\
+\x0f\x9c\xed\xbb\x13B\xa6\x0b\x80\x9f\x8dm6\xa4\x9apo\xe0\xcf\xc0\xad\xc0uU\
+\xdf\xbe0\xc28S\xd1\xbb]\x14\xe7\r*\xf1-~\xbf:\xbf\xd6\xc5Y*B\xda!\xe9jP\n\
+\xee\xbe\xbbEq\xdd\xc0\xaf\xbeJG\xd9\xa0\xe5\xb0\xea\xb9\xe7\nX\xff\xb6\x11\
+\xc1`\x01\xce\r\xb0\xe3\x97\xc0& \x16\xb8\x0b\xb8\x01\x89r\x880\xbe\xa7\x10\
+\xf7\xc3\xfc\xaaoc\x18a\x9c\x89\xb0\x00\x93\xc6$\xf2\xcd\xafyh`\xcdF\'k\x7f\
+\xb7\xd7v\xb3\xcaEH\x12o\x83\x066\xfa\xf4\x119\xb8\xbc<\x17_\x7f}\x92f}!\xb9\
+{\xf5\x9c/\xe7\x10l[d\xbc\xe9\x86\x84\x8b\xf9\xba\x18V\x02\xeb\x81^\xc0k\xc0\
+@J\xfb~5\xb0\xaaz\xda\x18F\x18g"\x94R\x8c\x1d\x12O\xe3\x86V\x8e\x9ct\xe1t\
+\xc2\xdb_\xe6T\xc9\xb1\xab3\xa67$\\\r\xbe\xa6\xfbu\xd75\xa6~}+Zk6m\xca#=\xdd\
+I\x9f\xeb\xa1Zd\xdd5\xecX\x08\xb9i@\x1cpA\xe9\xcf\xd9\x0f,\x01\x92\x80\xcf\
+\xf0O\xba&VTC\x1b\xc3\x08\xe3\x0cF\\\xa4\xe2\xb2\x91\t\xc5\xef\x7f\xf8\xb1\
+\xf6\xc3\x85\xca#\xec\x90 ^_\xdcxc\x93\xe2\xbf\xdf~\xfb(ZC\xa7q\xd5\xe7\xda\
+\xd9o\xfal\xdb#\x91\t\x9eq\xdaN\xe0s\xe3\xefg\x10\x9fnY\xed\xf0)\xf5\x13^X\
+\x0b#\x8c\xd3\x83R\x8a\x8b\x87\x96\xc4\xf4\xee\xdd\x9bQ\x8b\xad\xa9\x18B\x8e\
+x\x1b7\x8e\xa0{\xf7X\x94R8\x9d\xf0\xd5W\'I\xee\n\t-\xab\xe7|\x19\xbb`\xdb\
+\x17\x08\x99\x0e\xa2tR\xcc\xaf@\x160\t\xb8\x91\xb2I7\x03\xd8[\x1d\xad\x0c\
+\xa3\xce\xa2"k\xeb\xba\xa4\x04\xba\xf7\x0b\xcf\x02\xceu\x1ag\xf7\x8a!\xb9\
+\xbe\x04\xf0:\x9dU\x97@Q]\xd1\rAO\xbc\xbe\x17>hP"QQ\x16\xb4\xd6\xec\xdcY\xc0\
+\xe1\xc3E\xf4\xbc\x8a\xd3\n\x9a.\x0b\xc76\x83#\x1fH\x06\x9a\xe3M\xac.\xc4u\
+\x10\r\xfc\x8d\xf2\xe3\x87O"\xe4\x1bF\x18U\x82\x92\xea\xcbf\xdd6\x8d\x0f\xf1\
+\xc2\x19Q7(.\xd2B\xff.Q\xb5\xdd\x8c\n#\xe8\x89\xd7\x17\xe7\x9e\xdb\x00\xb3\
+\xc3\xcd\x9f\x7f\x0c\xb7\x866#\xab\xc7\xcd\xa05\xe4\x99\xee\xa2N\x94\xb6\x1c\
+\xd2\x80B$\xa6\xb7;ewp\r,\xf7s\x8c0\xc2(\x0bF\x9f\xf2\xa7\xbce\xc6\xabj\xad\
+\xc0m\x88\xc8k\xd9.\xe3\xc1\xa8\xd6v\x06\xf49\xed\xd6L\x18\x91\xe0\xf1\xbez\
+\xe3pO\x17!E\xbc\x16\x0b\x0c\x1bV\xcf\xa8\xc6\xaa\xf8\xe9\xa7L\x12\x9aB\xb3\
+\x01\xd5s>\x05l\xfb\xdcx\xe3O\xc6\xd1T%\x1bU\xc1\x83\xfdV\x15\xad\n\xe3\xcc\
+\x82F\xc7\x14\x96\xf1\xb9\xa8.\x15W\xad\xd3%\x95@\x15b<\xe83\x80y\x95R\x8c\
+\xe8\x13KD\x88\xc4i\x055\xf1\xfa>\xb5\xda\xb5\x8b\xa1gO\t\x96>q\xc2\xc1\xe6\
+\xcdyt\xb8\x10\xac\xd5\xa4\xcd\xa0\x80\xdcc>\x1b\xfc\xe1\xec2>3\xe1\xa7\xef\
+\x87\x17\xd6\xc2\xa8\x10\x02\x94$2\xdd\n(\x8dV\x86_S\x95X\xc1Z[\x82B0\xa6\
+\xa6\xd0\xa1y\x04\x1d[V}\x99\xa4S\xb1\x9e\xeb\x94H\xce\xd0\xa1\x89DF*\xb4\
+\xd6\xac[\x97KV\x96S\x94\xc8j\xaa\x01\xbe\xb7\xb2)\xe2[\xde\xe4\xe73\x7f\xd8\
+R\xfe.a\x84\xe1\x05\xad\xc0\xea\xbfs)\x14\xf2\x9fa\xe5j#KG\x99i\x94\xa0\xdc\
+\x16Th\r\xf3S\x87\x86\x8b\xcf\x8e/\x7f\xbf @H\xfd"#F\xd4\xc7\xf4[-[\x96\x855\
+\x1aZ\x8f\xa0\xda\x98\xd7\xed\x00{\xae\xf1\xe6\x98\x9f\xf3D!\xb2\x90\xdfW\
+\xe0`\x1a\xd1j\x08#\x8c\xca@iT^\x80E#mA\x19\xae\x05\xa5-(e\xae0k)\x83\xa34\
+\xfaLXY3\xa1\xe1\x12\x0f\xa9\xc8`\xf6\xf3\x86\x88GD\xd0\xa1C\x8c\xe1\xdf\xd5\
+\xec\xd9S@bs\x88kT}\xe7\xb3D@\xa4\xf9;\xe6\xfb\xd9A!q\xbb\xdf\x00G\x10\x12\
+\x0e\xd4\xcf\x1d\xc8B\\\x18\xb5\x02\xadK(\xc8\xd42\xd2@\xa1\xd6\xecpj\x0eip\
+\x9d\x0cF\xc98\x83X\xfd\xac\x1ek\xe5F+-\x06\xae\x92\xb81\x8d\x1b\xb92\xb1\
+\xa9\x94r\xe3\xa5\xc8T\x87\xa1\x94\xa2[\xdb(\x92\xebY8\x91U{\xd7\\\x11\x17b\
+\xd0\x12\xaf\xef\xd3\xcaf\x83\xe6\xcd\xc5\x7fST\xa4Y\xb1"\x9bN\xe3\xa89\x9b}\
+/\xb2\x98\xe6y\xc74\xd0\x11X\x06\xfc\x15)\xe5\x13\xe8\x96g\x00\x87J\xde\x86\
+\xfd\xbb\xd5\x0f\xe1#\xa1\xa2\xbd.\xcd*\x87\x9bT\x97f\xadS\xb3\xd2\xe1\xa6H\
+\x0b%\x15?\x0f\xbf\xfd\xd1\xfcZ\xb9\xa8\xb1\xdfO\x03\x167\xdam)E\xbeJic\x01M\
+\x1b\xe1\x0cN\xa3\xf5\xb2\xf8\xac\xb42|\xbegNW\x8b\x8fR\x9c;(\x8e\x0f\xbf\
+\xa9\x9a\xb4\xe1\xeaB\xd0\x12\xaf/Z\xb5\x8a\xa6uk\xa9\x95s\xfc\xb8\x83\xc3\
+\x87\x8b\x18r^q\xc0L\xb5@\x03\xcd\xfa\x19R\x90Y@*\xd0\xd2\xe3\x84\nh\x01\xb4\
+\x06\x16\x02;\x91\xb0\xb3@\r:s\xfa\x7f\xadAk\x8d\x05\xc8\xd3\xb0\xde\xe9fq\
+\x91\x9b\xe5\x0e7\xbf;uq\x10J\x95\x9c\xc7\xc70\xa8>"vCL\x11\xe4\xc5\x94\xfaD\
+i\x9b\xf7\xc2\x9b\xd9"\xb7EB\xca\xcc(\x07\x1dR\x1e\xc5\xd3\x83\x86\x8b\x87\
+\xd5;e\xe2\xad)\xf7D\xc8\xfc"\xc3\x86\xd5\xc7f<&V\xad\xca\xc1\xe9\xd64\xea^\
+\xbd\np\x1a\x18p+%\x84\xb9\x8d\xd2\xe4\xa9\x80\xb1\x88\xde\xee\xb3\x1e_\x0c\
+\xa3\xc6\xa0\xb5$\x0f\xb8\xb5f\xb7K\xf3\xa7l\x07\x03O\x161!\xd3\xc1\xab\x05.\
+6V1\xe9\xfam\x83\xdb\xa5\xcdW\x95\x1f;`T\x83\x1b\xb46,_\x0bJY(\x91\xc13}\xbc\
+\x85\xa0\x1cU\xdd\xa4\xa0\x85R\x8a\xb3\x06\xa5\x10\x1dm\xab\xd2\x87aU\xff\
+\xaeAi\xf1\xfa\xbb\xc8V\xad\xa2\x8a\xa7Z;v\x88\x7f\xb7^\xeb\xeam\x87R\xd0\
+\xa8\x17\xb4\x19\x01\xfb~\x04V\x03C\x80\x04\xcf\x9d\x90\x18\xdf\x11\xc0\xbbH\
+\xa4\xc3 D:\xd2W\xc5,\x8c*\x87\xd2\x9al\xad\x99\x99\xef\xe2\x7fEnv\xba\xaa\
+\x9fd\xcb\x83g\xff=\xed\xc1\xaf\xac\xa8\xfch?\x1fh\xdc:\x17e)\xc0\xe2\xb6\
+\xa1\x95<|\xe4;n\x14\x16\xb4v\xe2\xb4\xa4\x81\xf3\xcc*\xee\xd7\xbaE"E\xf6\
+\x00O\xab A\xc8X\xbc\xed\xdb\xcbTKk\xcd\xbe}\x85\xb4\x1aR=\xa2\xe7\xbeP\x110\
+\xfa?`\x8dD\x16\xc8\xd6\x06\xd8q0\xd0\x05x\x1c\x18\x0f\x0c\x00\xfe\x89D2\xb8\
+\x91\xa8\x883c\x8d\xa3\xdaa\xa6\xc4\xeer\xba\xb9%\xdb\xc1\xe0\x93v^\xc8w\xb1\
+5\x08H\xd7\x17\xa7o\t\xcb\xd7J\xf9w5\x90\xb1\x0e\xad\xd7\x81%\x02\xad\xac`\
+\xb8z\xb5\xd2\xb8\xb1\x89\xff\xd7\xf93\x1c\xdduz\x17\x11b\xa8e\x1d\xf4\n!$\
+\x887"B1th" \x1dp\xf5\xealZ\x0f\xaf\x99\x19\xbdR\xd0\xb8/\xf4\x9edlXO\xc9\
+\x92\xb8\',\xc0\x85@3\xe3\xfdV\xe0\x11\xc4\xe7{>0\xd5\xf8^\x18\xa7\x0c\xad5\
+\xb9n\xcd\xec|\'C\xd2\x8b\x18\x96n\xe7\x93"7\'B\xc4\xb5S\xa5\xae\x08\xa5\xe0\
+\xd0.\xdc9\xf3p\xebu\xa0\xdd(b\x80\x18\xf9W\x15\xe2\xd4+Pi_B~\x81\xdf\xa8\
+\x880j\x0fA\xe9j\xf0E\xbbv\xd1\xb4i#\xd3-m\xac\xa6%w\xab\xc1\'\x9b\x82\x91\
+\xd3a\xfb\x97\x86v\xc3/\xc0\xb0\xd2\xfb\x10\x83\xa8\x94\xbdNI1\xcbL\xe0\x87\
+\x1ajg\x1d\x84\x06\xd0\x9a|\r\xef\x168y\xa5\xc0\xc5\x91\xea\x9a9\x98\x01\x00\
+V\xa0s\x80}N \xb3\x17\xcf\x06V\x92JM\xf2\xad\xb0\x1b\xc2H\xfb-m\xf5j\xf4\x8e\
+\xe5\xb8\xda\xe4a\xab\x7f)X\xda\xa1u\x04\xb8\n\x81M\xb8S?A\x1d\xd9\x17\xf6v\
+\x05!B\x82x\x87\x0c\xa9GD\x84t\x9f\x93\'\x9d\xec\xda\x97\xcf\xc8N5w~\xa5 \
+\xbe\x05\x9c\xf3 |5\r!\xde\xb3(}\xf7\x14\xa2Tv#\xa2\xcb\x10\x85\xa8\x9a}\x8a\
+\x97\xb5\x1b\x0e%\xab \xb4\xe6\xb0[\xf3j\xbe\x93\xf7\x0b\xdd\xe4T\x90\xe0,\
+\x11\x90\xd2\t\xdcn8\xbe\xd5\xd8\xd8\x07\x89>\xf9\x1a\xb0#i\xde\x93\x003\x0e\
+\\#\xb5\xf1\xea#\xbfc\x12\xfe\xfd\xf3y@\x81\xc7\xfb\x1dH\x0c\xb7Y]\xe4\x17\
+\xe0\xa7\n^^E*\x1ch\x8d\x8e)B\x15\xfaI\xa2PJ\xc8w\xefZ\x9c\xd1[QQ\xf1\x10\
+\x19\x8d.\xca\x83\xc2\\T\x91\xddH\xa4\x08w\xb7`C\xd0\x11\xaf\xbf\xa9\xd8\xa5\
+\x97&c\x06\x8e\xb9\xdd`\x8d\xd1\xc4\xf9\x13\xad\xa9F(\x05\xfdo\x85\r\xf3\xe0\
+\xf0*`)\xe2B(\xb5#"\x96nV\xaa\xb0\x13^`\xab\x04L\x15\xae\xc3n\xcd\xac|\'\xf3\
+\n\xdc\xc5\xc5\x9a\xfd\xc1\x1a%!\x7f\r\xda@\x93\xde\xd0\xb8\x97,\xba6\xec\
+\x04[?\x82\x0f\xafEb\xad/A~\x87c\x089Z\x91\x02\xa4\x95u\xb6\xc5\x19/\x13\xc9\
+\x1e\x7f_\x0e<D\x85\x89\x17*f\xfd\xfa%]\xcf\xcfQPX(/<\xba[\x98p\x83\x16AG\
+\xbc\xbe\x88\x8cT\x0c\x1e\x9cX<\xcd\xda\xbe=\x8f\xa4\xce\xbaVZ\xae"\xe0\xe2\
+\x17`\xee9\xe0^\x0bt@\xac(\x08\x93kU@k\x8e\xba53\xf3\x9d\xcc/t\x93\xe7\xc7\
+\xc2\xb5\xc5B\xd3\x9e\xd0\xb4/t\xbe\x04R\xba\x19"\xf8\x1e\xea\x87f\x11\xd4\
+\x02s1\xdf3\xfae0R\x1fo%\x12\x1e\xd8\x95\xaa\xfb\xed\\H\xc1S\x90\x82\xa7\x8d\
+\x90\xc5\xd5\xb2\x9e\x1c\x06\x02\x13\xb0\xa14\x16&\xd1:\x85\xa0\'\xde.]bi\
+\xd4\xa8\xa4\x9999.\x1a\xf5\xaa\x9d\x87\xb9R\xd0\xf4,\xe8s#\xac\x9d\x8bd\xaa\
+5\x07z z\xbc\xb1\x94\xf8\t\xc3\xa80\xb4\xd6\xe4j\x98\x1f\xc0\x87[\xbf5t\xbaX\
+,\xda\xf6\x17Bbk\xfc\xdeg\xe5\xf3\xf7\x11\xb3\xccRc\x8f\x0f\x13\x11+\xf5(\
+\xf0\x14\xf0V\x15^\xc8\xef\xc8\xa2*\xc0EH\xbf\xb0#\xa5\xa1\xb6\x06\xfa\x927J\
+\xb9\x1f\xc2\x84[c\xa8Im\x87\xa0\'\xde\x94\x94\x88\xe2\xa7\xbd\xd6\x9a\xdd\
+\xbb\x0b\xa8\xd7\x82Z#7e\x81\x0b\xff\x03\x19\xbba\xefR$\r\xf8\x10\xf0-\x12\
+\xdf\xdb\x19\xd1lh\x0c\xd4C\x16\xd9\x828\x8c\xcc\x9f\xc0vM\x9e;\xcf\x83p\xd3\
+<\xee\x93I\xb6]/\x87\x96C\xc1\x1ac8\x9b*\xf8\xbbk7\x1cYo\xbe\xf1\xf8@!3\x95\
+\xa3H\xf5\x90\xaaJ}\xd4\xc0\x1bH\xc8a<\xe2\xde\x00\x88\xc4\xdb5Q\x91Cy\x91\
+\xaf\xdc\x14\xadK/\xae\x85\x11\xba\x08z\xe2\x1d7\xae\xc4\xbf\xab\x94\xe2\xc0\
+\x81"\x9a\x8e\xab\xdd6E&\xc2\x1f>\x87\x0f.5\xc8\x17D\xc7!\x03\xa9\xc1\x06%\
+\x16Y-\xd5\xbc\xd2~\xfe\x02o\x8e\x11\xce\xd5^\x1f\xaab&\xaa\xe6A\xae5\x07\\\
+\x9a\xeb\xb2\x1cl\xf7ch\xf4\xbd\x01F\xcc\xf0&\xdbJ\xb5\xc8\r\xb9\xa6\x1a\x9c\
+g\x18\x9f\x06z"\xbf\xd3A\xc4J-\xafzHE\x90\x01|d\xfc=\x04!\\\x13\xf9\xa0\xacp\
+\xc3\x97pd\x13\xac\x9a\r\xe9\xe5\x84\xd6j\xb7K\x0f\x18\xd0\x83\xc2B\x07\x91\
+\xd1\x01\x16\xd7\xc2\x08Y\x04u\x1c\xaf\xd5\n\xc3\x87\xd7\xf3\xb0xa\xd7\xae\
+\x02"\xabI\xf8\xbc\xa2P\n"\x0c\xf2\xed0\xc6H\xae\xf0\x85\xa6\xd6HW N\xcf\xd2\
+\x06\xad\x17\xf5z\x7fd\x08\xac\xc8\x03\xa3z\xcct\xad5\xa9.7\x0f\xe48\x18\x91\
+n\xf7K\xba\x00??\x0b\xbb\xbf>\xf5\xf3(\x1b\xb4\x1cd\xbcI\xc5\xc3\x01\x8c\xcc\
+F: i\xde\xff>\xf5s\x14C\x03K\x8c\xf3\xa4 \xc93\x9e\x9f\x1d\x85\xb8\x14h>\x14\
+\x06\xdf\x0b\xb7\xad\x87\xd1OCR\xfb\xb2\x0f\xbbz\xf5fn\xbec!En\x17"|#\x17a\
+\xd6S\x93\x97\xc7\xfd\x93r\x13\x1eo\xb5\xd7>\xbe\xef\xeb\x1a\xb4\xd6h\x8b\
+\x13l\xf6\xdanJ\xb9\x08j\x8b\xb7I\x93(:w\xf6\x16\x07\xc9\xc8\xb7\xd3\xb1E-5\
+\xc8\x03&\xf9N\xfa\n2\xf7\xc2\x81e\xbe;@\x8b\xc1\xb0\xfb\x7f\xf0\xe5\xd4Zh\
+\x1fP\xcc\xfcfD\x91[\xa3\xedE\xf2\xafR\xb8\r\x11m\xd1tu\xa3\xb4\x96\xfd\xec\
+\x0e\xdc\'\xd3\xc1\xed\xaa2\x1f\xa3\xe9\xc7\x9dW\xe0\xe4\xd9|\x17\xd9\xfe\
+\x12P\x86\x00}\x81\xfd\xe0\xfc\x06\x16\xde\x0e7,\x86\x06\x9dO\xa1\x19\x9eF\
+\xfbAJ?o\x06!\xa2F_!B\xf6=95\xabW\x03\xbb\x81;\x8c\xef_\x01Dx\x1c+\x0f\xc8\
+\x80\xa8\xf6\x10a\xac\x01\xd8\xe2`\xf0}0\xe0\x0e\xd8\xff#\xfc\xf0\x08\x1c^\
+\xe3\xff\xf0\x9f|}\x9c\x84$\x0b/\xdc\xd5\x8ehWt\xb1&\x8e\x8e-\x04\x87\x15e\
+\x8f,~^buI\xea\x9a\xd3VL\xc0:\xd2!\xfb(\x8f\xf7\x0e\x9bT\xa7\xa8\x83\xd0\t\
+\x19\xa0\n\xca\xdf\xd1\xf7{5\xac\xdd\x1bT\xc4\xeb{\xf1\x89\x89VbbJ\xca\x07\
+\xdb\xedn2s\x1dD7\xa8\xf1\xa6\xf9\x852V\xd2\xeb\xb5\x83\x9e\xed\xfc\xef\xd3\
+\xd1\n\x96\xfb\xc0]\x1b\x0fa%\xa4\xaaP\xb8m\x1a\nrp\xae\xfa\r\x9d\x9e\x8ej\
+\xd7\x1e\x8b\xd5\x06\x0e\x17\xe0F+\x85\x8a\x89\xc1\x9d\x93\x8d}\xd5\xaf\xb8\
+\x8e\x9eD\xbb5\xcazz\x03\xd4\xb4\xae\xd69\xdc\xfc1\xdb\xe1\xe5\xc7-i\'\x12\
+\x8a\xd5\xcdx\x9f\x04\xd4\x87\xacy\xf0\xf1\xb50\xf9\x17P\x95\x9cik\r\xcd\x07\
+\xc1\xc6\xf7\x11K\xd4S\xd2S\x01\xed\x80\xe1\xc0\x8f\xc0\x18$\xc9\xa5,e9\xbf\
+\'A|\xc5W"\xbe\xfchJ\xfbs\xa3\x81xh{\x0e^\xf3K\xa5$B\xa3\xdd\x18h5\x02v.\x84\
+\xc5\xf7BNj\xe9\xd3\xbc5\xdfMna\x0co\xbe~7\xd11\x1ey\xf2\x9eV|\xa0\xf6\x9din\
+a\x97\x1dT<p]m\xb7\xa4L\x04\x15\xf1\xfab\xc8\x90zX,%\xbdg\xdf\xbe"\xf6\xed\
+\x0b-5\xf1\x84\x96\xd0\xb0\xbdG \x7fMC\xb9\xd1\xda\x82\xb6\xd8\xd0N;l\xdd\
+\x86\xfd\x83\xb7 *\x12k\x97\xeeXb"\x8db\x88\nwN\x0eE\xf3\xdf\xa4\xe8\xfd\xb7\
+\xc1\x9e\x8f\xb2\x9e^\xf0\xbd\xd6\x9a\x83.\xcd\xcb\xf9N>(t\x13\xd0\x0ei\x84\
+\x90\xae\xe7\xa9\xda\x02\xed\xe0\xe8&\xd8\xf1\x05t\xbe\xa2rMQ\n\xda_ \xc9\
+\x14n;\x12:\xe6\xe9\xcb\xd5\x88\xb0\xd1\x01Dky4\xf0\np1\x15#+\x8d\xb8*\xa6!i\
+\xe4\x18\xef\xb7R\xe2j\xd0`\xea\x92\xb7\x1f\xed\x9f\x07\x95\x82\x888\xe8z\
+\xb5\xb8\xad\xb6\xfc\x17\xbe\x9f\x0e\xb9G\xbc\xf7\xfb\xf8\x93M|\xf2\xd9\x9f\
+\xcf4\x1a\xad\x15\xd4k\rY\xfb\xab\xf7\x1cA=\xdf\x18>\xbc^\xf1\xdfZk\x96/\xcf\
+"\xb1\xb5F\x05\xf5\xe3\xc2\x1b\x96\x08H\xac%\xd7H\xb1`\x8a\xc5\x18\xfdV\x1b\
+\xb8\x0b)\xfc`>\xf9O=N\xd1g\x1f\xe2X\xb9\x0c\xe7\xba\xd58\x97\xfdH\xe1k\xb3(\
+|}6\xee-\xbbQ\x11V)\xeb|\nC\xdd\x14\xb1\xf9\xb0\xd0\xc5\xf0t;o\x96E\xba Z\
+\xc7\x19\x94\xf6\x87\x8f\x10o\xc7\xe2\xfb@\x9f\xc2\xf3\xb6a7\xe84\xc6x\xf3\
+\xb3\xcf\xf1MW\xc4U\x88\xc6\xf2~`"\xa2\xa9\xb1\x87\xf2\xfd\xf3v`2\xf0\xa1\
+\xf1>\nI\xa8\xe9\x8f\xb7%\xfa\rD[\xa5DUY\x0f\x0e\xa5 \xb2>\xf4\xf93\xdc\xba\
+\x06\x06\xdd\x06\x16\x9f~\x1e\xcc\xa5lB\x19\xa5\x8a.\xf8\x13\x83\xabb\x045\
+\x85%%\xd9\xbcBh\xf6\xec)$\xba\x9e\xac\x10\x87\n4\xd0\xb4\x17\xec\xfe\xa6f\
+\xcf\xeb\xc6-\xdc\xa2\xadh\xa5\r\xd9@\x0bX\xa2\xd0\xf6"\x9c_\x7f\x8d\xf3\xa7\
+\x9f\xa1YC,\t\xf5q\xa7\x1e\xc1}2\x13\xe5(\xc0\x12g\xc5\x8d\x0b\xb0\x80V\x95"\
+_\xad5\xbf;\xdd<\x9e\xebd\xa9C\x97\xd6\x05R\x88/\xf7\x1c\xc4\xda\xfc\x10)\
+\x01\xf15p\xad\xcf~-\x81f\x90u\x00\x8em\x86\xc6\x03*g\xf5j\xa0\xef\xcd\xb0m!\
+\x92\xb1\xf6\x03"\xd7i\x1eC!\x84y\x050\x17\xc8\x06^Fb{G\x00\x03\x81\xa1\x88\
+\xbb\xc0\x17s\x80\xf9H\x06\xdc\x10c\xdf\x04\xbc\xef\xd5j`\r4\x19\x011\xc9\
+\xa5\x0f\xe1\x0fJAlS\xb8\xe8eh\xd2\x0b\xbe\xbe\x17\x1c\x1ee\xa7*\x94f\x1c\
+\xc6)#\xaa\x1e\x14\x9c\xac\xfe\xf3\x04-\xf1Z\xad\xd0\xbd\xbb\xa7\xc3L\xb1|y\
+\x96\xffA\x10\xe4\xa8\xdf\xb6v\xce\xabQ(m\xc5\xa2\xdd\xc2\xa1\x16\xc0\xedFk\
+\x85\x1b\ryY\xb0+\x03m\xb1\x81\xcbm\xac\n\x83\xc5\xaa\xb0\xa0*\x15~\xac\xb5\
+\x90\xec{\x05.\x1e\xcau\xfa//\xa7\x80\x7f\x01\xf7\x177P\x08\xee\x0e`\x172\
+\xe5o\x8b71\x1a\xbfw\xeaj!\xde\xca@)\xe8p1\xb4\x1e\x0e\xfb\x7f\x06\x96#q\xb6\
+\xa3}\xce\x91\x00\xdc\x8a$:\xec\x00r\x91E\xb7\xaf\xca8x"\xa2\xd7a\xea3\xfb.\
+\xde\x19\xb1\xddJ\xc1\x05\xff\xae\xdc\xf3\xcb\xac\xd6\xd3\xe7\x16\xe8p\x11|p\
+\x85\\\x7f\xf1\xe1\xc3\xe4[mh\xd2\x0bNl\xab\xfe\xf3\x04\xad\xab!&\xc6Jl\xacw\
+\xf3\xdcA\x9c\x88P\x16Z\x0e+=m\xacnX\x8c\x88\\\xb1v\xc1\xed\xd6\xf2\xb2\xb8\
+\xd1\x16\r\x11\ne\xb5b\xd5\n\x8b\xcb\x89\xb2\x80\xc5f5\x16\xd3L\x96F\xfc\x15\
+e@\x1b\x95\x1fV:\xdc\x8cJ\xb7so \xd2\x8dDH\xf7o\xc6{%\xa7a\x8a\xb1\x1d`\x9f\
+\x9f\xef5\x91\x7f\xb6/\xac\xf8\xb5{BE\xc0\xf8W\xc1\x16\x83\x10\xe2o\x08\xa1\
+\x16\xe1\xed\x12\x88\x06\xaeF\xa2\x1d\xa2}^fbLg\x84l\'#\x0f\x8b\xd1\xf8\'\
+\xdd\xc3\xc0\xdbr\x8eVgC\xd3JZ\xea\xc5mW\x10\xdf\nn\xfe\tz\xfd\xc1\xfb\xb3\
+\xb0\xdb\xa1j\xe0{\x1f\x1b\xb4\x81\xfc\x8c\xd2\xfbU\xf5\x83.h-\xde\xc6\x8d#h\
+\xdc\xd8_\x80lhA)\xd1\x13H\xe9\x06G7\xca\xb6\x9a\xb3X4\x1a\x17n\xa5\x01\xabD\
+8h\x85.\xae<\xab\xd0V+XTq2\x852\n%VD\xbf\xdf\xcc<\xfbw\x9e\x839\x05e<\x15;#S\
+\xf9\xa1\xf8Y]\x02n\x07f#\x0bS\xe7\xe1\xed[5\xa2\x19\x0e\xae\x04\xe5\xa2\xd2\
+=V)H\xea\x06\x17\xfc\x13\xbe\xfe\x8b\xb1q5\xe2z\xb8\x140#d\xccv\x8dA\xd2}}a\
+\xae\x8c\xf9\xae\x90\xf9#\xdd\xf9\x80K\xe2\xbb\xcf\xffg\xe5\xdb\\|8\x89\x04$\
+c\x0fd\x1d\xf2\xf3y\xd8\xf2\xadR(\x0b$4\x01]\x03j\xfaAk\xf1B\x1dJS\xb7A\xef\
+\x1a\x8enQ\xc6\xff4R\xfe\xdb\x02R\x9bK\x83\xc2\x82\x05)\x88\xe8V\xe06\xe2\
+\x1a\xc0\x0c?\xc3(\x13\x8e\xdf\x05&\xb3\xc6\xd9*\x87\x9b\xd1\x19\xf6\xc0\xa4\
+\xab\x10\x12[\x8c\x7f\xd25\x11\x0b\xdc\x80,X\x05\x80#\x0fr\x0e\x97w\xd5\x811\
+\xe0vh\xef\xa9&w\x00\xf1\xd3\xae\xc6\xdb\xf2\r\xd4F\xe5\xf3\xaf/4\xe2*y\x17(\
+\x94\x05\x9a\x91\x0fC\xf3a\xa7\xd1\x8f\xdd\xb0\xec\x9f0g\x10\xec\xf7\x8d\x13\
+7O\x1b\xb6|\xab\x0cq)\xe2j\xa8\t\x045\xf1zBk(,\x0cM_\x83R0\xf0N\xe8ws\xc9\
+\xb6j\x1f0\xda$_+\n+\xca\xb0~\xb5\xc5\x83e\x94l\xd5\xb8\xb1\xa0\x8dD\n\x0b\
+\xaa8u\x18/\xd60\xa3\x15~w\xba\x99\x9a\xe3\xe0\xf2L\x07;\x02]F\n\xf0\x01\xf0\
+1\xa2\x0eV\x1e\xf9t/\xfbcg!\x14\xa4\x97\xbdO (\x05*\x12\xae\xfa\x18:\x8d\xf5\
+hK!\xa2&\xf6-\xa7\x9eahF?l@R\x86\r\x19\xd0\xf3\x1e\x83a\x0f\x9f\x06\xe9jX\
+\xf7\x1a|\xf7\xa8\xf7\xe2\x9a\xdf]\xc3\xe4[%hq\x16\xa4\x06Hd\xa9j\x84\x0c\
+\xf1\x16\x15i6n\xcc\xad\xedf\x9c2\xac10v\x16\x0c\xba\xbdd[u\x0e\x18\xad\x0c\
+\xd5\x05mP\xab\x02\xb0\xa0\xdc\x92\xf5\xe1\xd6n#\xf2A\xa1\xb4\x057\xe0Vn\xdc\
+\xca%\x0boX\x0cn6\x18\xdc\xa8\xe0{w\x8e\x83\xf32\x1c\xbc_\xe8\xa6\xc8\xdf\
+\x89-\xc8\x14\xfew$\xb1\xc0Tl\xabe\x14\xa7y\x7f\x06c_\x02\x9bgB\xc6\n\x84\
+\x80\x0f\x03\'\x91\xe8\x86\x8a\xc2\x0e,\x02\x16\x02\x85\x10\x19/\xd2\xa1\x83\
+\xef\xe5\xb4\xae\xdb\x9e\x05??\x89\xff\x108?\x08\x93o\xe5\xe1y\xcf\xac\x910\
+\xfc\xaf\x90\xb6\xb1f\xce\x1d\xb4>^_X\xad\x18>\xdf\xd0J\xa00\xa1\x14`\x85\
+\xb6#a\xe5\xff\xd5\xc0\xf9\xb4\x067X\xdcF,\xaf\x06\x0b\x16\xdc\xda\xed?\xe3\
+\xc9s\x9b\x87?S\xf2\x044\xef\x14\xbay*\xdf\x15\xb8\n\x84B\x08\xf7.$R\xc1\xac\
+2^Q\x04\x98JW%\x94\x02"\xa0\xff\x1d\x90\xd8\x1c\xbe\xf9;\x9c\xdci\xc8R\xac1^\
+\xc6\xef\x84\x99\xa9nE\xa4?\x03\xe1(R\x0e\x08\x89\x9e\x18\xff\xaa\xc4\x0f\
+\x9f\x0e\x0bj\r?>\x06\x99\xfb\x81\x86@+$\xda\xc3\xd0\x1d&\r\x89}^\x82\x97\
+\xf2]\xd8\xe7{\xeah\xda\x07\x1a\xf5\x94\xfeP\x13\x08\x19\xe2\x8d\x88P\xb4n\
+\x1dMZ\x88\x12\xaf\xab\x08V\xbe\x08\xdf<\xe8\xbd\xbd\xba\x06\x8b\xbb\xb0\x08\
+\xb7]\xa3\x9c\x0eSJ\xdb\x88\xcd\xd5~y\xb74\x14\x0e4\xffqj\xde\xd6\x92\xdf\
+\x10\x10]\x81\x07\x908\\k\xb9\x07\xf6w*\t\xf3\xf2\x85\x99\x1d\x86D\x85\xd8b\
+\xfc\xecs\nP\n:^\n\xedF\xc3\xd1u\xf0\xcb\x0b\xf0\xfbg\xa0\xcd"\xa6N \xc7\xe3\
+\x0beTGW\x16H\xea n\xa4\x81w\x82-^\xae\xe7\x94=\x0c\x1a\xf2Sa\xcd\xbbHB\xc6Y\
+\xc8=\xf5\\\xdc\x8bE\xdc8~<oa\xf2\xad\x18<\xad]e\x81\xa1\x7f\x81\xdcc\x90\
+\x93V3\xe7\x0f\x19\xe25\xa1 \xa4r\xd0\xb5\x86\xbc4\xf8\xf2v\xd8\xb6\xa0\xe6\
+\xce\x1b{\xf74tf&*\xcaf\xdc*\x0bn\xb3`\xa2.\xfb\x16\xba5|\xbal9O,]\xc6.G\x80\
+\x15/\x85$#\xdc\x80d\x7fE\x95q\xc0\xf2\xa0\xf1?\xbd7-Q$\xfb/\xa9\xc3)\x1e\
+\xdf\x0fL\xad\x84fC\xe1\xf2\xc10j\x07\xecX$\xc1\xf3;\x17\xc3q#\x96\xd3\xed\
+\xa4D\xa8M\x81\xd5\x90Jh\xd4\x03\xda\x9d\x0b=\xae\x16KIE\x96\x1c\xf7t\xb1{\t\
+\x14\xf5F\xea\xc2\xf9\xceD2\x11\xbfy\x0eb\r\xfb\t\xf6\x0f\x93o\xe5\x90\xd4\
+\x11\xba\\\x0e\x9b\xde\x93\xdf\xdb\x17\xd5q/\x83\x96x33\x9ddd8IJ\xf2n\xe2\
+\xf1\xed\xe0v\x80%\x04"\xcd\xb4\x86\xf4\xad"\xf4R\\\r\xc1\xdf~\xd50P\x12\xee\
+{\xf8\x94\x8f\x17\x15a\xd3v\xbb\x1d\xb7?\xf9\xc0(\xe0\x0f\xc0\x9d\x88\x92Xe]\
+\n\xfe`G\xf4q\xbb`F\xb9\t6P\xecYj\xda\x13\xb1\xfc\xaa\x18J\x81\xb2ARW\x18\
+\xd2U\xb8m\xd4?\x8dB\xbd@\xe6>\xc87\xc8-2\x0eR\xba\xc8>\xb6\x18$\xdc\x99\xaa\
+\x8d\xbeQ\xdapE\x99U\x8e\xcdc\x9b\x0f\xa7\xd7\x81|Dt=\t\xc9\xba\xf3C\xde\xa9\
+({\x00\x00 \x00IDAT\x16a\xf2\xad8.|\x12\xb0y\x08\xe7\xd7\x00B\x8ax\xadVEQ.\
+\xa7\xe7@\xab\x01\x98|\x95\xba\x02\xe6_\xe2\xb3\x1a\x1f\x85\x0c\x14\x9f\\\
+\xda`\x18(\xe6\xf4\xab\xb0\xa8T\xa2\xaf\xa0;\xb2r\xdf\xc5x_\x15\xad\xd5H\xe2\
+\xc4^\x84\xc8\xcdm\xd9\xc0w%\xbb\xf5\xbe\xb1z\':^b\xeb6\xc3e\x00$\xf7(\xe7{U\
+\xdc\x8e\xcc\xdd\x90\xb6\x01\xef\xf2\xf2\x1a\xb1p\xdfFH\xb7\x15\xa2+\x11\x87\
+\x14\xec\x0c\xb0f\x10\x0c}*\x18\xe1\xe9fh\xd8I\xc4\x89\xb4\x03v\x9e\x86\xfes\
+e\x112Q\r\xa0\x196,\x11W\x11\x14e\xd5v[\xca\xc7\x96y\x1e\xa4\xab\x10?\xe8-\
+\xc0}Hz\xaa\x9fism\xaeLW\xe8\xdc\x99\x80Yv\xa9\xaa\x86\xb3\x06f e\x92\xccr9\
+\n\x8940\xc2\xa8\x9a\xf5\x87N\x97\xd4\xa1\xb8\xee\x00\xd0\x1a\x8em\x91\x19])\
+\xac\xa1\xc4\xd1\xfe\x18\x921gE\x84\xdc\xef$\xa0\t\x15\x8ev(\x1b\x03&\x83\
+\x8a\x82\x03?\xc1\x89\x1d5w\xde\xa0"^\xcf\xa7\xb3\xcb\x05\x1b6x\x86\x8f)\xa2\
+\xa2,\x14eC\xf6\x81Zh\\E\xa1a\xdd,\xf8\xf4&\x0fKw\x0c\x12Z\xd5\x18\x19 \r\
+\x11\xbf\xa8\x1f\xdd\x89\x9a\x1c(\xda\xed\xd2\xe6\xabB_HE\xc2\xae\xaa\xaa\
+\x85\x1aI\xdf\xfd\x18\x11"7\xc9\xe3\x00\x92\xd8\x00\xa0`\xf8\x03\x04\xf1\xdc\
+\xac\xea\xa0\x08\x90\x1a\xad(^d\xa4%\x12=b\x8e\x94D\xe0\x05D\xd8\'\xc5\xffq\
+\xc3\xe4[\x02_k\xb7\xcf\x9f\xe4Vn\xfe\x80\x1a\x9dI\x07\x15\xf1\xfa"#\xc3\xe9\
+Q\xa6D3`@\x02Ps!\x1f\x95\x85\xd6\xb0\xf6U\xa98\xa1\xcd\xd9\xba\xa9reZ\x89\
+\xe6\xe5\x1c\xc2\xafo\x0e\xaa\x7f\xa0T\x8al\x13\x90\xf6_\x8cXX\xffB\xa6\xbd\
+\xa7\xdbB\x8d(\x92]\x83X\xbb\xe6B\x92\x19\x17k,h5\xeb\x0b\x9d\xc6\xd7}k\xd7\
+\x84\xa3\xbcP\xf5\xf1\x08\xd9z\xc2\x8aD\x94|\r\x04\xc8\xbc\n\x93oi\\\xf0/\
+\x88j \xfe\xfc\x9d\x8b\xfd\xefS]\xae\x9a\xa0&\xdeU\xab\xb21\x1f\xedJ)\xda\
+\xb7\x8f!"B\x91{\xb4\xc4\x8f\x1a,\xd0\x1av.\x80/\xa7y\xac\x8c6\xa4\x84t\x8bw\
+\x04\xbeARK\xcb\xc8\t\xaf\x8e\x81R)\xc2\x05\x11\xa8\xb9\x05!\xdd\x01H<\xeb&\
+\xe0\xe9\xd3i\x04P\x80,\x0e]\x8d\x84\x91\x8dC,Z\r\xfc\x0f0\x8aT\xc67\x81+\
+\xde+\x89\x18\xa8\xf3p\xc3\xa1\xd5~\xb6{:\xb7\x87\xe3\xdf\xcd\xa3\x80~H\x16\
+\xde=\xf8\x9d!\x9c\xe9\xe4\xeby\xfd-\x06A\xfb\x8b\xe4\x81\x9e\xb6\x06\xb2O#\
+\x1d\xfdT\x10\xd4\xc4\xfb\xfb\xef\xf9^\x85\xf9\x9a4\x89 >\xde\xca\xa1\xdf\
+\x82+\x9aLk\xc8\xd9\x0f\x0b&\xfb\x84\xa3\\\x80w)\x18\x8dL\xd7\x7fAb1gP"\xd2\
+\xe2\xef\xb8U0P*\xeaN\x88\x88\x85^\xd7\xc2\xe5o#\xa5\x95b\x80\x9b\x8cv\x9a8\
+\x1f\xa9\'\xf6\x1f\xe0U\xc0\x8c{\xadPC\x8c\xd7\xaf\x88\xdbe2R\x8f\xec<$\xa5X\
+\x03\x9b\x81u%\xed\x99\xf0\x1a4\xe8t\xe6X\xbbhp\xfaK\x07\xb4 B\xed\t\xc8o\
+\x10\x08\nHF~\x9f\xcf\x8d\xbf}Oq\x86\x93/\x805\n.xZ\xb2I\xd15\xbb\xa8f"\xa8\
+\x89w\xe7\xce\x02rsK\xa2\xc4\xe3\xe2\xact\xee\x1c\xcb\x91\r5\xa3 TQ(\r?\xfc\
+\xa3$\xec\x08\x80f\x94\xae\xe1\xe5F\xa6\x83 \x19^\x8f Ds#\xd0\xd4\xff\xb1+m\
+\xa5Rq\xb2\x05);3`\n\xdc\xbe\x1e.\x9b\x07\xbd\xae\x87\xc6]\x11k\xdc\xe1\xd1~\
+\x85X\xbc\xd7#\xbe\xe9;\x10\x01\x9c\x1d\x14\x97\xb7\xf1K\xc2\x9e\x84{#0\n\
+\xf1\x13+\xe0BdF`>\x90\xcc\xe9\x9e\x82\xf1\xff\x07\x1d<u\x15\xcet\xb8\x90\
+\x87x|9\xfb\x99.\xad\x8b\x11\x97M\x9b\xd2\xbb\x9c\x89\xe4\xeby\xcd=\xaf\x92:\
+wJ\t\x8f\xfc\xfei\xcd\xb7\'\xa8\x97,\x8e\x1d\xb3\xb3m[>\x03\x07\xc6\x17W\xa2\
+\xe8\xd93\x8e\xdf\xde\xc8&}\xa7\xa4f\x06\x054\x1c^\xe9\xb3\xcd\xb7t\xb7F\xa6\
+\xe9f\t\xf0\xbf"\x03\xa45\xf0&\xe27}\x14\x99\x82\xe7P\n\xde\x996\xa5\xfdN\
+\x95\x19L\xca\x02\xc9]\xa0\xff\xcd\xd0s\x12\xc46\xc2;^\xd4\x82\x90n.\xdeZ\
+\x0b\n\x89j\xb8\x03X\t\xacB\xa6\xb7\x03\x10\xcb\xfd,\xfc\x13\xe5N$\x0c\xcdL\
+\x92\x88D|\xbb\xa6\xa5\x9b\x8bH)\x16\xc8\xf7G=\n=\xae\x0fp\xac3\x19G\x10\xe9\
+\xcc>\x94\x7fo\x14\xa2-\xfc+\xf2\x80\\\xe7\xfd\xf1\x99\x1ajf\x8b\x81\xb3\xff\
+f\xd8\x08\x1a\xd6\xbfQ3\xc2\xe7\xa5\xdaQ\xf3\xa7\xac8\xdcn\xf8\xf1\xc7,\x06\
+\x0eL0\xb6h\xc6\x8fo\xc8k\xaf\xa7\x91\xb9W\x82\xde\x83a\x1a\x9aw\x0c\xd2\xf7\
+xlPx\x17V4\xb7\x99\xfb\\\x80\xb7\x8bA!\x0b&\xcf#\xfe\xb9\xe7(\t\x94\xf7\x83S\
+\xb5X"\x13\xa0\xdb\xa5\xd0\xf7&hq6\xa8\x88\xd2\xf7\xcf\r\xf4\xba\xce\x90!\
+\xdcH\xe9\xa9\xadBz\xcdP\x84hw \x95z\x8f\x03\x15\xc9\xccK\x06&P\xa2\x7f\x90\
+\x81\x94\xff1\x8a\xb2\x8d|\x18\x86?*\x0f\x870\xfc\xe0\x01Jf\x06\xe5A!\x85D\
+\x17#\xbf\xe3&\xef\x8f\xcf\x14\xf2\xf5\x1c/=&B\xb2YXU\xc3\xd6\xcf\x02\x7f\
+\xaf:\xefM\xd0w\xef\x9f\x7f.I\x94WJ\xd1\xa3G\x1cQ\x91\x8am\x0b\x82\xc8 \xd2>\
+\x8b}\x8d\x8d\x97\'\xdcH\x98\x14\x08\xf1\x06Z i\x8d\x84\x07}`\xfc]\x05\x88K\
+\x81Q\xd3a\xdav\x98\xf06\xb4\x1c)\x99\x7f\xfe\x1eZJA\x97\t\x10\xd3\x10\t\xe9\
+\xca+\xe3\xc0\x16$\xd0\xff\xcf\xc0mH\nq\x1b\xc4\x15\xe1\xd9\xb3l\xc84y8\xf0G\
+JH7\x1f\t%;*o;\x8d\x85\xb3\xff\x1e&]@\x84pJ\x02z$K\r\xe47\xd9\x85\x7f\xb7\
+\x8e?(d\x865\x973\xd2\xe7\xeby}\r\xda\xc1\xc8\x19\x14\x8b\xfc\x17\x9e\x84\
+\xfd+j\xa7]Am\xf1\x02\xacZ\x95Cn\xae\x8b\x84\x04\xc9\x17m\xdd:\x8a\xe1\xc3\
+\xeb\xb3}s\x06\xdaMP\x14\xbe\x8cL\x80\xb8\x86\x90c\x96\xe4n\xe6g\xa7<J\\\x08\
+\xbe\xa4\xec\x0b\x85\xac\xf4\x8f@\xe23\xdfE\xac\x952\x84\xc2\x03\xa1Io\x98\
+\xb4\x08\xe2\x9aSL\xf6\xe5=\xb0b\x9b@\xe7\x8ba\xfd\xbb\xc8\x14uX\x19_2\xb77D\
+\x88u8\xe2\x8f\xcc\xf4ho\x02\xe2\xb20\t\xd5\xf4\xe9~L\xb1\x00M\x87\x0b\xe1\
+\x8a\x0f\xc0\x1a\x825\xf5\xaa\x0cJ\nA\x032\x93\x18\xee\xf1\x99Yp;\x1d\xb8\
+\x19\x89\x8c\xa9\xe8\xbdR\x88;\xe8yD[\xc3\x87j\xcf\x04\xcb7\xba>\xdc\xf05$\
+\xb65|\xbb\x1a\xf6~\x07v?n\xbd\x9a@\xd0\xdb\x16G\x8f\x8a\x9f\xd7\x8cnP\n\xfa\
+\xf4\x89\xe7\xd8f8\xb9\xb5\x96\x1bg "\xce\x88\x040\xe1\xcfRM\xa5DM\xaa"*\xf7\
+\n\x19lS\x11?\xdd\x0fH\x04\x80\xe7\xe2\x8a\x8d2I<\xae\x11L\xfa\x12b=H\xb7"\
+\xd0\xc0\x85\xff\x81\x16\x83\x11\x0b\xab\xb2\xbd\xc4\x8a\x10qS\xe3\x15o\x1c\
+\xc3\x0c\x8b:\x88\xf8t\r\xd2\x8dn\x00c\xff\x0flq\xc1\xe1:\xaa-h\x0bt\x1ek\
+\xbc9\x82\xf8\xc4\xcd\xc5I\xcf\xe8\x98e\xc0,*\x17K\xad\x90\xf0\xbd\xce\xfe?\
+\xae\x8b\x96\xaf\xe75\x9d\xf3 \xd4\xefX\xd2\xbf\xdcvX3\xb7\xb6Z\x16\x84\xc4\
+\xeb\xfb\xe4\xd5\x1a\x16,(\t\x17PJ1n\\C\xec\xb9\xb0i^\xf0\xc4\xf3\x16\x0bk+\
+\x8a\x0b4z\xc1lg2%\xd6KE`\xfaT\x87 \xfa\xab;\x81\xed\xc6k\x07\xb2r\xedy\xc7\
+\xceF\xace\x84\xd0\xe2\x9aT\x9e\xcc\x94\x82\xe8d\x98\xf8.\xb4\xee\r\xbc\x88D\
+clF\xdc%\xa6\xefY{\xbc|\xe1\xfbY!2E~\x13\xd1\x1c(\x00,\xd0u\x02\\\xb7\x00\
+\xea\xb5;\xb3I\xd7D\xdf\x9b\rW\x8b\x13y\xe0\x9a\xf7d\x00\x92vn\xbe\x7f\x10Y\
+\x07pRq\x02\xb6Q\xa6\x95\\\x97\xc8\xd7\xf3ZzO*-L\x7f\xf0\'\xd8\xfdM\xe0\xefW\
+\xf7\x0c \xe8]\r\x00\xdf~\x9b\xce\x8c\x19\xad\xb1\x1an\x85!C\x12\xe9\xd0!\
+\x86\xad\x8b\n\x18\xf5O\xaaE\xb5\xaaRP\xd0r\x08\xa4\x99\xeaF\xfeB~\xcc\x00\
+\xed\x04\xbc\xad\x97J\x9c\xa3\x98\xd4=\x89\xddS\xb7\xa2\x0f\xb2\x88\xb2\xeb\
+\x14\x8e\xef{:\x05\xf5:\xc0\r\xdf\xc2\xe6y\xb0\xf2U8\xfc\x89\xf1\xa1\r\xf1\
+\x1b6F\xae%@\xaa*\x99\xc6+\x1d\xf1\xe3\x9a1\xaa\n\xda\x9c#\x0bi\xadF!\xc5.\
+\xc2\xa4\x8bR\xd0\xb8/\xb4\x1d\x05{\xbe\x03\xd6"\xe1v\xf5\x11\xc2\xbc\nq\xfd\
+,F\x1e\\\xb7 \x95/\xfe\r\x98\x0bF\x81`JJ\x96S>\xa9.\xb8\x1d<I\xb7\xf38\x187\
+\x8bRIL\xfb\x7f\xaa\xf9vy"$\x88w\xcd\x9a\x1cv\xec(\xa4kWQ\xc2\x8e\x88\x80)S\
+\x9a\xf2\xc0C{\xc8\xd8-A\xf6\xb5\x8a\x8at\xd3\x00\x82_\xa7\x8d\xe5\xc8\xa0JD\
+HW#\xd3\xfb*\x98\xcb\x98\xb5\xcaz\xde\x04=&\x89h\xf8\xb6/`\xdd[\x90\x93\x8a,\
+\x00U\xe6xVh}6\x8c|\x14Z\x8d$L\xb8~\xa0\x15\x8c{\x05^\xe9-\xe2\xf9,Bd8\xcd\
+\x91\xda\x07y\xf0~\x8eTJ^\x88\xcc\x84nC\xac\xe0dJ\xf7G\x93t\xefA\x08z0\x12M\
+\xf2=uNL\xdd\x8bt\xc7\xc3\x15\xef\x835\xd6\xbb\x9fi\x97\xf4\xe3@\xa8\x89k\
+\x0f:W\x83?8\x9d\xf0\xc6\x1bi\x1e~^\xc5\x981IDGX\xd8\xfai\x10\xb8\x1b4$\x04H\
+\x80\xa8\xee\xf3\x16\x87\xa8\r\xa3$\xe6\xb6\x8a\xef\x87R\x12\x05\xd1t0\x8c|\
+\x02\xee\xda\n\xd7|\n\xe7<$\x9d;\xbe\x89d\x03\xf9{\xa5t\x85\xfe\x93a\xecL\
+\xb8m-\xdc\xf0=\xb4:WH8L\xba\xa5\xa1\x14\xd4\xef\x04c\x9e1\x16\x8e\xf7 \xe4j\
+\xba\x14\xccY\xcf\x8d\x94\xf8k\x8b\x90H\x98.\x88\xf5\xbb\x9c\x12=\x8dl\x84`\
+\x9fA\x04v\x06#\xe4{6\xde\x8bw>\x08E\xb7\x83?\xd2-\xb5n\xa0a\xf7b8\xba\xa5\
+\x16\x1a\xe8\x01\xa5,\xb5=O\xf7\x0f\xdf\x1f>%%\x82\xfd\xfb\xcf"&F\x9e\x15Zkn\
+\xbcq;Kw\x1d\xe5\xe6\x9f\xa9uw\xc3\xb1u0k\xa0!\x8e\xf3GJ/\xb0-AR\x85\x93\x90\
+\xe9\xa2Y?\xebtP\x84H)\x1eD\x92\x1a\xccp\xa1\\\xe0yh\xda\x17\xfe\xbc\x92j{\
+\xbcj-\x97\xe0\xc8\x01g\x81\xff}\xa2\x1bH\xbcp\xf0\xc4\xfe\x95<\xa8\xcbk\x92\
+\xa6\xf6\x1e\x0e\xda\t\xf3F\xc3\x9e\xef\x8d\r]\x10W\x03\x944\xdc\x05\xfc\x86\
+\xff*\xc9\xc9\x88_8\n\xd1\xefm@\xe9\x0b^\x8dd\x11\x96\x83P\xb0~}Iw\xe2{\xfe\
+\x17k\xb5\x0b\xe6]\x08\'V[\xc9\xce\xf6?\r\xad\x89\xeb\r\tW\x03\xc0\xf1\xe3\
+\x0e\xbe\xfb.\x93\xb1c\x1b\x14g\xb1M\x9e\xdc\x94\x8f/:\xc6\xf6\xcf5\x9d\'\
+\xd6n\xfb\x92:Iy\x9a\xac\xfd\x88\xb0\xb7/\xf1\x9a\x8bo\xe9\x88\x06\xc2B\xbcu\
+\x10*\x0b\r|\x82\xa8\x9c\xd5\xa3$\xceSSl\xed4\xe9!S\xd7\xea\xeaEf\xa7\x8eH\
+\x94W0\xa3\xf8!\x91+\xe5}v/\x81\xcc=px\xad\xff\xfd\x9b\xf6\x91\x07W\xfd\xb6\
+\x92\xe5\x17\x99\x08\xa8\x1a$c+\\>\x0f\xe6\x8d\x81#\x1b\x81m\xc0\x7f\x91\x85\
+\xd38i\x0bV$\x91%\n!_\xb3\x1ca\x14\xd2\':!\x84\xeb)\xb2c\xc2\x14+\xaa\x00\
+\x82\xd9\xf5\xe0e\xa0)\xe8u\r\x8c\x9fS\xda\xbd\x00\xd2\x07Nn\x85\x83\xbfB\
+\x97\xf6\xd1l\xdaT:H\xbd\xa6\xae3d\x88\x17`\xee\xdc4\xc6\x8e\x95\xb8-\xa5\
+\x14g\x9f]\x8f\x8e\x1dbY\xf7v\x1e\x9d/\xa7V\xad*k,t\xbb\x04~\x99\x89\x7f\xdf\
+g\x1bJ\xdc\x00\xdf\x03\xd3\x80\x97)!\xe4\xca@#YbS\x8c\xbf[\xe2m\xd5n\'p\xb4\
+\xc1\x99\x06-d\xbb\xef\x1bP\xdb\xe3\xe8\x18\x91D\xefv\xf1\\\xde-J\xa6\xdc\
+\xe3Jv\xdd\xbb\xb7\x90={d\x05\xf0\xe4I;\x8b\xff\x91\xce\xfe\x03\x85\xa8hM\
+\xa3.\x12\x80\xdf\xe52hw>D\xd5\xaf^\x12VJ\xe2\xa9/\x99\x03\xef\x8e\x95\x87\
+\x05\xdb\x91\x0c\xc1K\xf0~\xb0\xf7G\xfa\xd7\xefH\xa6Z;\xbcGv \x9f\xafG\xf2@r\
+\'\x99\x9d\x1c^EI\x8d9\xcf\xaf\x18\x04\x17L\x04\xec;+\x1e\xf5\x88d=\x06Z;P\
+\xc0\xd2\xc7 \xb9~$\x19\x19\xfe\xd4\xe6k\x0eA\xebj\x80\xd276:Z\xb1i\xd3 :t\
+\x90\x98\x18\xad5\x0b\x16\xa4\xf3\x87\xeb7s\xcf~\x88J\xf2{\x98\x1a\x81\xd6\
+\x90\xb1\x1df\x0f\x02{.B\x8a\xbe~\xdf/(\xc9\x99WH\xaa\xecD*\xf7\xc00I\xf7ZJ,\
+\x96K\xf0\xce\xdf\xff\x0c\xd8\x08\xe7N\x87a\x8f\x9ey\xbeT\xad\x01\x17\xec\\\
+\x08\xe9?Gr\xe5\xc0\xd6\x0c\xeeY\x9f\xce\x9dc\xb0\x19\x84\xa4\xfc\xdc\x14\
+\xadu\xf1v\xad5\x0e\x87\x90\xf1g\x9f\x9d`\xce\x9cT\xf6\xee\x15\x932"VJ\xb9\
+\xf7\x9f"\xd1\x19\xd1\r\xa9\xb6\x87\xbe\xd6\x90\xf6\x1b\xbcw\x19\xe4\x99\t:\
+\x11\x88F\xc6PJ\xb4yM\xab\xd6\x9fu\xebu@\xc4E\xf5!Rn\th\xd8\x11&\xaf\x10m\
+\xda\xfd\xdf\xc1\'7B\xee\x91\xc0\x87\xa8m\xf2\xf5\xe5\x05k$\x8cx\x00F\xfc\
+\xc3\x98\xe1\x05h\x9d+\x1f^\xea\x02c\x86\xa4\xb0`\xc1\t\x8a\x8aJ[&5umV\x15\
+\xcc\xf9\x99ZO\xf7|\xebtJ\xdd\xb5\xd1\xa3\xc5\xdd\xa0\x94\xa2c\xc7\x18\xd6\
+\xac\xcce\xf3\xda\x02:\\D\xadY\xbdJ\x19\x03\xd0\x01{\x97"\x99j\x9e\xf5\xba4\
+\xe2\x8f-\xa2$\xb4l=B\x9a\xf5\xa8X\xbb5B\xde\x9e\xa4\xdb\x00\xb1\xda\xcc\x12\
+\xe0vD\xd3\xd6\x0e}n\x80&}\xfd\x1d\xa8nBk\xf17ox\x03\xd6<mcBJ{\xfeq[\'\x86\
+\x0eL\xa4q\xe3H\xacVU\xdco\xfc\xc1s\xbbR\n\xabU\x91\x9c\x1c\xc1\xd9g\'\xf2\
+\xa7?5e\xf0\xe0D\x06\x0eL\xc0Q\x04\xeb\xbe/d\xd3\x7f\xe1\xb7W \xf7\x00$6\x83\
+\x98$)C_\x95P\n\xe2\x9bC\x9fk\xe1\xe8F\xc8\xd8\x83D"\x1cF\xc2\xcd\xf2\x91\
+\xf0\xc5D\xfc\x93\xaeB\xfa\xca!$\xa4\xef \xf0)\x92\xa0\x81$\xd9\\\xfb\x85\
+\x91\xd1e\x91x\xea~\x7f\x04W\x81\xd4~\xd3\xfe\xdc\xa0ZOG\xeb\xe9JYfT\xed\xd5\
+\x96\r\xedvi_NHl\x01\x13\xdf\x81>S\x802HWkX\xf3*\xec\xff\xda\xca\xc0\x81\x89\
+\xac\\Y:e\xad&\x1f(!e\xf1\x82,\xb2m\xde<\x90F\x8d\xa4\xce\xb6\xd6\x9aU\xabr9\
+\x7f\xc2Z\xa6\xfc\x06\t\xadj\xbc\x99^(<\t\xaf\r6Ds\xaeET\xca\xcc\x9f\xd3\x1c\
+\x18{\x90E\x8dt$\x06\xf6]D"\x11\x02\x13\xb0\x06\xb6 \xab\xd2f\x02\x83\x15I\
+\x1fmJ\x89\xb5\xf3\x03\xf0\xb3\x10\xc0m\xeb!\xb9{\x15^\\\x90\xc2\xd3\xc2]\
+\xf6\x14t\x8ao\xc0\xec\xd9\x9dh\xd7.* \xc9\x06>\x96\xfcH\xe6\xd7\xb4\xf6\tE\
+\xd2\x1a\xad\x15\xfb\xf7\x17\xb2iS\x1e\xaf\xbd\x96\xc6\x0f?d\x90\x97\xef\xa6\
+\xe5Yp\xf6}"\xb0m\x8d\xae\xda\x99\x86\xd6\xa0\x1d\xf0\xf3\x13\xf0\xe3\xbf|\
+\x08Q!\x8bim\xf1v/e\x03\'\x90\xd01?\xee\x83\xc6=\xe0\xf2w \xa5\x8f\xef5\xca!\
+\x8f\xae\x81/n\x81\xd4\x00~\xf0\xe2\xd3W3a\xf9\xe3\x01e\x914\xf3\x8b_\xaeX\
+\xf2\x8d=K\xc6\xe5E\x83\x9a\xb0kW>\xbf\xfc\x92]j\x9f0\xf1\x1a\x08\x14\xd22}z\
+\x1b\x1e}\xb4\xb5\xd7\xe0\x189r=jX\x16\xe7<Q\xbbSk\xad\xe1\xe0\x8f\xf0\xde\
+\x04(\xd2\x081\xfaZ\xb4\xa6e\xfa="\xad\x18\x8d\x84\x07=\x84\xe8<(?\xfb/B"\
+\x17\x0e\x1a\xdb\xac\x88\xb5\xec\x99~\xec\x06^\x01\xd2\xa1\xf9\x00\x98\xfc+\
+\xb5\x1e\xedQ\x9d\xd0\x86\x1f\xfb\xc0\x0f\xb0\xe4\x01\xb0\xef\x8f\xe0o\x7fm\
+\xc9\xd4\xa9\xcd\x89\x8a\n<\x933\xc3\x12].\xb0\xdb5\x87\x0e\x15q\xf8p\x11\
+\xfb\xf7\x8b\x7fw\xf5\xea\x1crr\x84\xd9\x9a6\x8d\xa4K\x97X\x9a7\x8fd\xe4\xc8\
+\xfa\xd8l\xaa\x14I\xed\xdd[\xc8{\xef\x1d\xe3\xd5W\x0f\x93\x96f\xa7\xc5Y0\xec\
+oR\xb2HWq\xac\xb2\xd6px\x05\xacz\x05\xb6-4\xdcZ\x95\x85\x82.\xe3\xe1\x92\xb9\
+2K+\xcbJt\x17\xc1\xfa\xd7\xe0\x87\x7fB\xde\xd1\n\x1c\xba\x8a\xc8\xab\xacp\
+\xb6F=a\xd4\xc3\xd0y"\x15\xd2j\xd1\x1a\xd6\xbd\n\x07\xe6\xc43gN\'\x86\x0f_\
+\x87\xdd^{n\x06\x08r\xe2\x05\xff?@\xfb\xf61\xfc\xf2K_RR"\x8a\xb7m\xd9\x92\
+\xcfY#V3y\xb5\xa6^\xdb\x1amb)h\r\xbb\x17\x89_NG"2\x88f\x92\x87\xa7\xf5\x0b\
+\xe2g3\xad\xdf8Djq\x18\xde\x1a\x0c\x07\x80\x97(\xb1tS\x10\xd2\xf5\xd4`\xd0\
+\x88\xff\xd8(\x96x\xc3bhsa\xdd\xf4\xefj\rJ\xc3\xe1_a\xf5l\xd8\xf4\x1e\\1\xb1\
+\x11\xcf<\xd3\x8e\x16-"\x03\xfao\xb5\x86\xa3G\x1d\xacZ\x95\xc3\xa2E\'Y\xba4\
+\x93\x9c\x1c\x17\xc7\x8e\xd9\xc5\xa2,c1R)\x18<8\x91\x91#\xebs\xce9\xf5\xe9\
+\xd7/\x9e\x94\x14\x9b\x97O8;\xdb\xc5\x9c9i<\xfb\xecA\x8e\x9fp\xd0v\x14\\\xfc\
+\x124\xf4L\xf5\xad\xaa\xebG|\xbe\x1b\xdf\x85\r\xf3\xe0\xd8\xef\x01\xdc\x02^\
+\x17!\t,\xe7<\x0c\xad\xcf\x05e\xabX\xff\xd0\x1ar\x0f\xc2\x92\xfb`\xcb\xa7\
+\x158\x8f\xe7)+If\x15\x89\x1f\xfe\xc3G\xd0ib\xc5\xfb\xb63\x17fv\x85\xe7\xa6w\
+\xc6\xe1\xd0\xdcv[\xe9r\xc25\xed\xb7\x0eI\xe2\x05\xf8\xc7?\xda\xf0\x8f\x7f\
+\xb4*\xee\xf8n\xb7\xe6\x81\x07\xf6\xf2\xdd\xc9\x83\x8c\x9b-\x9d\xaaV\xe1\x86\
+\xdf^\x80\xff\xfd\xcdX%n\x8d\xa8\x8d\x99\xd3AO\xc2\xb4#\xe1@k(;\x12!\x16!\
+\xe5\xb3\x8c\xf7\xbe\xc7x\x038\x06\xad\x87\xc1\xf5\xdfJ\x02C]\x83I\x02?<\n\
+\x9b\xfe\x0bqQV\x1ez\xa85\xf7\xde\xdbB2\xed<F\xa3\xd6\x1a\xbb\x1d~\xff=\x8f\
+\xaf\xbeJ\xe7\xfb\xef3X\xb92\xdb\xab\xaa\xc9\xa9")\xc9\xc6\x94)\xcd\x181\xa2\
+\x1e\xfd\xfb\'\xd0\xa8\x91\x90\xb0\xd6\x9a\xac,\x17\xb3g\xa7\xf1\xaf\x7f\xed\
+\xa7\x08\x17\x83o\x87\xfe\xb7AB\xcb\xaa\x7f\x10j\r\xeeBH\xdf\x05\xe9;\x01\r\
+\x07\x7f\x01\xa7\x11Z\x16\x95\x08\xcd\x06\xc8\xdf\xd1\xf5\xa1\xe50\xfc\xea0W\
+\xe4<J\xc3\xa1\xe5\xf0\xfd\xa3\xb0\xf7Gj-j\xa6a\'\xb8m\x9dD\x12\x95\x0b\rkf\
+\xc1\xae\x97bY\xb2\xa47\xa3Go`\xeb\xd6\xd2B\xd7a\xe2\xf5\x03\x7f\xe4\x9b\x98\
+he\xd3\xa6\x81\xb4lYb\xe1\x1c;\xe6\xe0\xac!k\x19\xfcL!\x9d.\xab}\x97\x03\x1a\
+\xb6\x7f\n\x0b\xfe\x0c\x85\x19\x08Q\xf6B2\x86\x1az\xeel\xfc\x9b\x8a\x08\xd1\
+\x1c\xc4\x1b\xf5\x11\x81\x94\x0e\xf8\x0f?\xd3H\x85\x87\xad`\x89\x80[WAr\xaf\
+\xbag\xedj\'\xec\xfb\x0e\xbe\xfe\x0b\x9c\xd8\n\x97\\\x92\xcc\xec\xd9\x9d\x8a\
+I\xcf\x84\xdb\xadIKs\xb0re6\x8f<\xb2\x8f\xad[\xf3p\x9f>\xd7\x06D\xa3F\x11\
+\xdcyg\x0b\xae\xbe:\x85\x8e\x1d\xa3\x8b\tx\xf7\xee"f\xcfN\xe5\xf9\xe7\x0f\
+\x12\xddP\xaa\xda\xf6\x98\x14X\x0b\xb9*P\x9c\x1c\xa2\xfc\xbf\xaf\x8a\xe3\xbb\
+s\xe1\xe5^\x90\xb9\xafj\x8eY."\x11\r\xeb_(\xd6\x9a\xb8\xf4u\xe8us\xf9\xd7\
+\xe5.\x84Wz\xc2u\x175g\xec\xd8\x86\x8c\x19\xb3\xb1\xd4>\xb5\x11\xa5\x11\xb2\
+\xc4\x0b\x92@1gNG\xaf\xe9\xde\xfc\xf9\xc7y\xf4\xf5\xad\xfc\xe1\x0b#\xe8\xbd\
+\x96\xa15d\xef\x85E\xb7\xc3\xae\xff\x19\x1b\xa3\x10\xab\xb5\x0b%.\x85\xf2B\
+\x81\xca\xfal=\xc5\xd5\x1f:\x8f\x87\xab?\xab\x98\xef+d\xa0!\xff(,\xbe\x076\
+\x7f\x08\xb11\x16f\xcf\xee\xcc\x95W&\x13\x11\xa1\x8a\x89NkX\xbd:\x97\xf7\xdf\
+?\xc6\xec\xd9\xa9\x14\x14T#\xdb\xfaA\x83\x066\xa6Nm\xc1\xf8\xf1\r\xe9\xd3\'\
+\x0e\x8bE~\xff\r\x1b\xf2x\xf0\xc1\xbd\xfc\xef\x7f\xe9\xb49\x07\xc6\xbd\n\r:\
+\x87\xe6\x83Qk\xd8\xf46|v3\xd5k\xf1Z\x90Yb\x1fd\x9cD \x95N~\x94\x8f\x9b\xf6\
+\x85)+\xcb\x9e\xd9j\r\xab^\x84uOE\xb2a\xc3\x00\xa6L\xd9\xce\x17_\x9c,\xb5_\
+\x98x\xcb\x80?\xf2\x8d\x89\xb1\xb0jU\x7f\xbau\x8b)&_\x87C3q\xe2\x16\xec\xc3O\
+r\xd6}\x04M\xaa\xaa3_\\\x0f?\xfe\x0b\x1cf\xc2\x8cB\x02\xdfG I\x10\x95\xf9)\
+\xcc\xbb\xf1;\x12\xb7\xeb\x12\xcd\x84)\xbf@B\xeb\xd0\x1c\xd4\xbe0}\x99kg\xc3\
+\xb7\x0fK\x12\xc1y\xe75\xe0\xc9\'\xdb\xd2\xbf\x7f|1\xe1\x82b\xc5\x8alf\xce<\
+\xccG\x1f\x1d;%\xeb6\xd0\xe0;\x15\xcd\x02\xab\x15&Nl\xc4c\x8f\xb5\xa1S\'\x89\
+9\xb7\xdb5O=u\x90W_M\xa50\xd2\xce\x95\x1f@\xd3\xb3B\xefw\xca9\x08\xaf\xf6\
+\x85\x82\x91\x94\xc4\x10\x83\xd4\x82\xfb\x15IS~\x10)\x1be7\xb6\x81\x08\xfa\
+\xecCB\xdb|}\xc4Q\x08\xb9\x0e\x03v#\xeakC\x90H\x1fO\x83#\r\x98#\x7fZ#\xc5\
+\xddPV\xdd\xc5\x8c\xed\xf0\x7f}\xe1\xf1G\xdbq\xc5\x15\xc9t\xeb\xb6\n\x87\xc3\
+\xfb\xe7\xac\xad\x98\xe4\x90&^\x80+\xaeH\xe1\x83\x0f\xbab\xb5\x96X\xbd\xbbv\
+\x15r\xd55[\x1883/h:\xb79\xe5;\xbcL\\\x0f\xa5\n\xec\xc5"\xa1b\x1d\x91\xc5\
+\xb3\xb2|\xd4\x99H\x16\xd3Z\xa4C#.\x86k>\x81\xf6\xe3\x82\xe3zO\x17ZC\x81i\
+\xe5~\x04\xd1\x91\x16\x1e~\xb85\x7f\xfb[\xcbbyP\x80%K2y\xe1\x85C|\xfbm\x06Ng\
+\xc59\xf2T\x07\\e\x8882R\xf1\xc0\x03\xad\xb9\xf3\xcef$\'\xcb\x0f\xbacG\x01S\
+\xa6\xec`\xf9/Y\x0c\xfb\x1b\x9c\xf3\x8fS\xf3\xb9\xd6\x06\xb4\x865/\xc3\x97w\
+\x03\xb7#i\xeaf\xbb\x17#\xba\x11\x0f\x03\x8fQ2\x833\xe1F\x08w;\xdeR\xa6 \xc6\
+\x87\xa9\xa8\xf7<p/\xa2\xc8\xe6+\xda\x9e\x89hC\x1b\xb8a1\xb4\x1d\x1d\xa8\xb1\
+\xb0p2DlI\xe4\xeb\xaf{2m\xda.\xde}\xb7tXF\x98x+\x80@\x9d\xfe\x9dw\xba2iR\x8a\
+\x97\xcba\xd9\xb2l\xae\x98\xbc\x81\x9b\x96k\xa2\xca\x08\x99\xa9ih-\x194\x1b\
+\xde\x82\x1f\x1e\x93B\x99\xa5\x10G\x895\x11\x85\x84\x98\x15P\x1c\xf4\xce\t\
+\xa4\n\xb0\x01K\x04\\\xf6&\xf4\xb8\x96\xa0\xb1\xf0O\x15Z\x83r\xc3\xda\xd7$&7\
+c\x9f\x94{\xfa\xf8\xe3\x1e\xf4\xef_"d\x9c\x96\xe6`\xc6\x8c\xfd\xbc\xf1FZ\x8d\
+\x10\xae\xdf\xb6V\x90\x84[\xb4\x88\xe2\x85\x17:0aBC\xacV\xc8\xcdu3{v\x1a\x0f\
+?\xbc\x87\xb6c4\xe3gCL\xa3\xe0\xe9\xa3\x81\xa04\xbc1\x1c\x0e,\x07\xc6"\xd6-\
+\x08\xc1\xbe\x83X\xb4_ \t=\xa7z-\xcf!\xc4{%\x92\xd2\xed\t\x0b\xf0\x14\xc5\
+\xd1=\xa3\x1e\x85\x11~R8\xb4\x86\xcc\x1d0{\x00,\xf9\xb2\x0fM\x9bF\xd2\xb7\
+\xefj\xf2\xf2\xbc\xa7B\xb5\x99\x81\x17\xc4ik\x15\xc7C\x0f\xed!3\xd3\xe5%\x1b\
+9lX"\x93\xc6\xb5`\xe1\x9f\xa9>-\xdcS\x80R\xa2\x9a\xd4\xefv\x98\xb6S\xea\xa1\
+\xf5\xbfI2\x88\x8a\x93\x08\xf3\x90iU\x1a\xd2\x99W \xa1b\xe66\x0f\xd2\x8dL\
+\x80\xcb\xde\xa8;\xa4[x\x12\xbe{\x00\x16\xdd\t\x99\xfb\xe1\xc2\x0b\x1b\xb0dI\
+\xefb\xd2\xcd\xcbs3}\xfa~z\xf6\\\xc5\x9c9\xa9\x15"]e\xb1*\xf3U\x95\xed\xad\
+\xe81\x0f\x1d*\xe2\xaa\xab\xb6p\xe3\x8d\xdb\xc8\xcar\x11\x1fo\xe1\xde{\x9b\
+\xb3`AO\xec\x9b\xa2y\xed,\xd8\xfa>\x94*\x9a\x1adp\x16A\xf6!?\x1f\xd8\x91\xac\
+8\x85\x7f\x15\xb4S\xc1\t?\xdb\xf2\xa8P\xddAw!|\xfaG\x98|cs\x86\x0eM\xe4\xc9\
+\'\x0f\x96"\xdd\xdaFm\x07]U\n\xcabU\xfe\xac\x8c\x83\x07\x8b\xb8\xe5\x96\x1d|\
+\xf0A7/\xab\xe1\xfe\xfb[\xf2\xe5\x88\x13\xacz\xa9\x80A\xf7\x10T\xc4\xa4\x94(\
+z\xb5\xbbX^\xa3s 7\x15R\xd7\xc8j\xf1\t\xa3\x8a\x84=\x1b\xd2\x02)h\xf5\x87Q3\
+\x0c?W\x10]\xdb)A\xc3\xd1\xb5\xb0\xe0fQ\xe3\x8a\x8cT\xdcs_K\x9ex\xa2M\xb1ka\
+\xdd\xba<\xa6N\xdd\xc9\xf2\xe5\xa5\xb3\x8e\xfc\xa1\xa6,\x1a\xcf\xf3\x04\xb2\
+\x82\xddnx\xef\xbdc\xacY\x93\xc3\xacY\x9d\x191"\x91\x0b/\xac\xcf\xaaU\xfd\
+\xb9\xf4\xd2\xcd|\xf2\xc7,\x8em\x11\xbd\x01\x82\xd4\xf5`\xcf\x81\xbc\xe3\xc6\
+\x9b\x86\x94\xf8_#\x90\x99\x99\x85\xd2V\xea\xa9\xc2\xdf\xf5\x17"\xba\xc4\x06\
+l~\xca\x18i\r[?\x06\xc7\xde\x08\xfe\xf1Ekv\xee,\xe0\xa3\x8fJO+k[o"\xa4\x88\
+\x17\x02\x93\xef\x82\x05\'x\xe9\xa5\xc3L\x9b\xd6\xac8\x1f?%\xc5\xc6\x92%\xbd\
+\x19<t\r-\x868\x82\xc6\xdf\xeb\tOi\xc5\x06\x89\xd0\xa0\x0b\xde\x0b\nn\xfc\
+\xaaE\x01\xd2\xd1\xcb\xc8O\x0f\x15\xb8\x1d\x92G\xff\xe3?\xc5\xf5\x92\x94d\
+\xe3\x95W:q\xd5U\xc9(%S\xf3\xb9s\x8f\xf0\xf7\xbf\xef\xa1\xb0\xb0|\xcb\xa56\
+\x07Uy$\xbc}{\x01c\xc6l\xe0\xde{[2cF\x1b\x1a4\xb0\xf2\xe5\x97=\xf9\xfb\xdf\
+\xf7\xf2\xca\xbf\x0fs`\x05\\\xfe6\xc4UC\xcc\xef\xe9\xc2\xab9\xf1\x1e\x1b,\
+\x88\x8f\xf6\xc0i\x9e@S\xe2N\xf3-\x8f\xa5\x01\x8f\x80\x04e\x81V>B\xeeZC\xd6n\
+\xf8\xfa\x1e\x98~\x7fK\xa2\xa3-L\x9a\xb4\xb58\x0b\xb1\xe4\xbb\xb5\xaf\xb0V\'\
+\\\r \xab\xc6O?}\x80\x8c\x8c\x92\x9b\xac\x94\xa2e\xcbH\x9ey\xb2\x03\x0bnV\
+\x14\xf9\x9b\xbe\x04#<\xbb\x85\xc5\xc80\xf2\xf7\n\xf1\xd29ZK\xb5\xd7%\xf7\
+\xc0W\xd3\xa0\xe0\x04\\}u#6o\x1e\xc8\xd5W\x0b\xe9\x1e>l\xe7\xce;wr\xcf=\xbb\
+\xca%\xdd\xeap\'\x9c\x0e\x02\xb5\xa7\xa8H\xf3\xef\x7f\x1f\xa0\x7f\xff5\xec\
+\xdcYH|\xbc\x85\x17^h\xcf=w\xb7\xe0\xd0r\xc5\xcb=a\xc3\xeb\xf2@\n&D$@\x9cY_\
+\xcf\xacpa\xa2*\xb2E]H\xb8\x98\x05\x89\xf2\xf1\x84\x9b\x92\x08\t\xa0^+h\xda\
+\xcfg\x97"\xf8\xe6~\x18\xda\xb7\x01\xf7\xdc\xd3\x82\xaf\xbeJg\xed\xdaS\xc9\
+\xa9\xae~\x84$\xf1\x06\x1a\\iiv\xe6\xcc))\x11\x04B\xbe\xd7]\x97\xc2\xdd7\xb4\
+e\xd1\xed\xd2\x99\x83\xd9\x8fv&@kI;M\xdf"U\x16~{\x05\xfa\xf5\x8bg\xf1\xe2^\
+\xcc\x9b\xd7\x85&M$\x15\xfc\xd7_s\x18:t\x1d\xef\xbcS\xb6H@\xb0\x11\xae/\xfc\
+\xb5Mk\xd8\xb81\x8f\x8b.\xda\xc8\xa2E\x19X,\xf0\xec\xb3\xedX\xb4\xa8\'\xcd\
+\x93\xa3Yp\x0b\xfc4C\\M\xc1\xd2_\xadQ\xd0\xe1\x02\xe3\xcdJ\xbc\r\x84\x9e\x88\
+\x15\xbc\xf7\x14\x0f\xae\x91\xea\xd3\xab\x90\xd8\xddd\x9f\xcfR\x91P3\x03C\
+\xa6\x81%\xc6c\x17\r+_\x82\xb4\x1fl\xcc\x9c\xd9\x91\xdd\xbb\x0b\xb8\xff~\x8f\
+/\x18\x08\x96~\x12\x92\xc4\x0b\x81o\xe0\x0b/\x1cd\xd3\xa6\xfcR\xe4{\xef\xbd-\
+\xe8\x15\xd1\x88\xef\xfe\x86L\xdf\x83\xa43\x9fI0\xb3\xf92\xb6\xc3;\xe7I\x8c\
+\xe5\xde\xa50zt\x03\x96,\xe9\xc5\xf9\xe7\xd7\xc7j\x15\x7f\xe8\xcb/\xa7r\xd9e\
+[8x\xb0\xa8\xccc\x06\xcb@*\x0f\x81\x1e\x0e{\xf6\x142a\xc2&\x1e\x7f\xfc\x00.\
+\x17\\pA}V\xae\xec\xc7\x9dw4g\xc5\xd3\x8ayc }+\xb5\x96\x9e\xeb\t\r\xb4=\xd7x\
+\xb3\x1dY\xf85\xdb\x15\x85h\x92\xa4R\xf9\xb6j`\x130\xd5\xf8\xbb\x0b\xde\xe9\
+\xf0\xb9\x14k\x90\x00$\xb6\x84\xbe\x7f\xf2\xce\xce\xcb;\x04\xcb\x9f\x83;\xef\
+lN\xb3f\x91\\s\xcd\xd6b\xd1\xa3`D\xc8\x12/\xf8\x1ftG\x8f:\xb8\xe8\xa2\x8d\
+\x1c<h\xf7"\xdf\x88\x08x\xe3\x8d\xce\xd8\xd6\xd5\xe3\xeb;\xf0+\x93\x17F\xf5A\
+k\xc0\r?=\x06o\x8e\x82}?\x82\xdb\t\xb7\xde\xda\x8c\x85\x0b{\x92\x94$\xcb\rv;\
+\xdcu\xd7.\xa6N\xdd\xc5\xd1\xa3\x81\x97\xb0\x83\xdd\xca\r\x84@\xd6\xef\x8c\
+\x19\xfb\x988q\x0b\xd9\xd9n\x92\x92l\xbc\xf4R\x07f\xcd\xeaD\xee6\x1bo\x8e\
+\x82=\x8b\xa9u\xf2U\n\xda\x8c\x82\xfa\xad\x8d\r\xbfz~\x88\x14\xe1\xdc\x89\
+\xa4\xbd\x17R\xb1\xf6j\xc4\x92\xbd\x1c\t\x13\xeb\x8f\xc4\xb2\x9b\x9f\xb9\x90\
+\xac\xcc\xe3%_\x19v/\xd8\xe2=N\xada\xd1m\x10\xe3\xb2q\xf7\xdd-\x989\xf30\xeb\
+\xd6\x95v1\x04S\x7f\ti\xe2\r\x84\xd4T;\xd7]\xb7\x95\xecl\xb7W\x88YT\x94\xe2\
+\x93\x8f\xbb\xa36$\xb0\xe1-\xcaU\xa4\n\xa3j`\n\x94\x7fr5\xfc0C\xaa\x1b\xd8l\
+\x8a\xbf\xfe\xb5%/\xbe\xd8\x9e\x88\x08\x19\x0f\x87\x0f\xdb\x990a\x13\xb3f\
+\xa5\x06<V\xa8\x12\xae\'\x02\x91\xef\xc2\x85\'\x19<x\rK\x97f\x01\x9a\x9bnj\
+\xccW_\xf5"\xc1\x12\xc1\x07W\xc0\xd2G\x8c\x92\xef\xb5\x88\x98\xc6\xa29\x0c\
+\x88\xd5\xbb\x8a\x12\x82U\x88\x06\xf0|\xa4\xe0\xebs\x88\x05\xec\xc4?\t\x9b\
+\x8azc\x10\xf2\xed\x08\\\xe4\xf1\x99\x0b)c\xef\xe11hy\x16\xf4\xbb\xc5\xdb\
+\xda]\xf7\x1a\xec\xfb^\xf1\xf6\xdb]\xb1\xd9\x14\xaf\xbf^\xba\xf6V\xb0\xf5\
+\x99\x90J\xa0\x08\x84@!<\xa3G7`\xfe\xfc\xae$%Ex\xfcP\x9a\r\x1b\xf2\x18w\xc9&\
+zN\xb33p\xaa$ \x84Q=\xd0\x1a2v\xc0\x87W\xc2\xd1M\xb2-%%\x82\xd9\xb3;q\xe9\
+\xa5\r\x8b\xd3~w\xec(\xe0O\x7f\xda\xc1\xf2\xe5\xbeiM%\x08\xb6\xc1S\x15\xf0\
+\xd7w\xe3\xe3\xad|\xfcqw.\xbc\xb0>\x00G\x8e8\xb8\xfc\xf2-\xfc\xfa[6\xdd\'\
+\xc2\xf8\xd7E\x87\xa4\xb6\x16V]E\xf0\xc5M\xb0\xf1}Dk\xfa\x06J\xc7\xef\xba\
+\x90*\xc6?"\x84\xda\x1b\xc9\xc8\xf4\xc5\x02\x84X\x1b\x03\x93(\x89f\xc8B\xe4R\
+w\x95\xec\xda\xb8\'\\\xbf\x18b\x9b\xca\xb5k\r\x8e,\x11\xc19\x7fP2\x1f}\xd4\
+\x9d\xc7\x1e\xdb\xcf\x8c\x19\xfbJ\x9d&\xd8\xfaN\x9d&^\x80\x9bnj\xc2\x9c9\x9d\
+\xb0\xd9\xbc\xe5\x02\xd7\xad\xcbc\xec\xd8\x8d\xf4\xbc\xdb\xc1\xd0\xbfRf\xad\
+\xa60N\rZC\xea\n\xf8\xe4z\xc80\x16]\x9a7\x8f\xe4\xbb\xef\xfa\xd0\xa9S\x89\
+\x8a\xd7\xe6\xcd\xf9L\x98\xb0\xb9\xb8\xa6\x99?\x04\xdb\xc0\xa9J\xf8\xeb\xbfq\
+q\x16\x1ey\xa4\rw\xdf\xdd\x9c\xc8HEa\xa1\xe6\xd6[w\xf0\xce;Gi9\x04.\x7f\xb7b\
+\x95\x17\xaa\x0b\xb9\x86fC\xfeI\x84|/F\x8alZ\xf1\xf6\xcfn\x03\xbeB\xfc\xb4\
+\x81\xd0\xd5\xf8\xbeI\xba\xb9\xc0\x9bH\xe5\x0c\x03\x8d{\xc2\xa4\xaf!\xaeY\
+\xc95\xbb\xed0\xef"\xb0\x1d\x8ca\xd9\xb2\xbel\xd8\x90\xcb\xf8\xf1\x9bJ\xd5R\
+\x0b\xc6\xbeS\'\x88\x17\xca&\xdf;\xefl\xce\xf3\xcf\xb7\xc7j\xc5+\xad\xf8\xdb\
+o3\xb9\xe4\xd2M\xf4\xfe\xa3\xe6\xc2\x17\xa8\xb00t\x18\xe5C\xbb`\xe3\xdb\xf0\
+\xe5]\xe00R</\xbe8\x89\xb9s;\xd3\xb8\xb1L1\xdcnX\xba4\x8bI\x93\xb6r\xe4\x88\
+\x7f\x7fn0\x0e\x9a\xea\x82o\x1fV\n&NL\xe1\xad\xb7\xba\x10\x1b\xabp8Dsz\xe6\
+\xccC\xb4\x1a\x0e\xe3gC\xbd\x0e\xb5\xd3g\xb5\x86\xb4\x950\x7f\x1c\xe4\x9f@\
+\xc8\xb6\x110\n)we\x12\xb0F2\xce~DJW\x99\xcf\xd6h\xc4J\xeek\xbc,\xc6\xbe\xdb\
+)E\xd4\xbe\xa4k\x8a\'\xfd\xf24|\xf70\xfc\xb8\xb4/]\xbb\xc6r\xdey\x1bX\xbf\
+\xde\x9b\xe1\x83\xb5\xff\xd4\x19\xe2\x85\x8a\x91\xaf\xaf\xe5\xfb\xe1\x87\'\
+\x98:m\'\xad&8\xb8\xe0\x19\x89U\x0c\x93\xef\xe9\xc1\x99\x0f\xdf?\x04\xbf\xbc\
+\x08hQ\xeb\x9a1\xa3-\x7f\xfdk\x8bb\x7f\xee\xd6\xad\x05<\xf9\xe4\x01\xe6\xcf?\
+\x1aPM,X\x07Mu\xc2_\x1f\xee\xdb7\x9e\x05\x0bz\xd0\xa2E$Z\xc3\x0f?dq\xc7\x1d;\
+8ZX\xc0\r\x8b\xa1~-ILj\r9\xfb\xe0\x83\xcb!m\xbd\xc7\x07-\x11\xed\xe8zH\x95\
+\x94\x14(.\xbai\x16i\x8dF"!L\xbf\xf0&\xa4\x10\x80\x87\x95\x0b\xd0\xfe|\xb8\
+\xf4M\x88k\xee\xe1\xd7u\x8b\xdc\xe3w\x8f\xc2\xed\x93[\xf0\xc4\x13m\x193f#\
+\xcb\x96\x95vS\x05k\x1f\xaaS\xc4\x0b\xa7f\xf9\xae_/\xf1\x94\x91m\x1d\\\xbb\
+\x08\xa2=U\x97\xc2\xa80\xb4\x86\x93\xbf\xc3\x17S\xa4\n\x02\xc0\x80\x01\t<\
+\xfahQ\xd2\x80\x9d\x00\x00\r\xe4IDATk\xc6\x8eM\xc2b\x11\xd7\xc2\xff\xfe\x97\
+\xc9\x15Wl\x0e\x98?\x1f\xac\x83\xa5\xa6\xe0\xaf\x0fw\xe9\x12\xcb\xe2\xc5\xbd\
+h\xd5*\x12\x80C\x87\xec\x8c\x1e\xbd\x91\xbd\xa9\xf9\\\xfe6t\xbc\x84Z\xe9\xb3\
+ZC\xc11X\xf6$\xacy\xddO\r8\x0b\xe2B\xd0\x88\x1f7\x16!\xddFH{w!>^\x9fd\x91\
+\xa8z0a\x16t\xbe\xdc[\xbdMk\xd8\xbb\x18\xde\xbb\x14.87\x89\x0f?\xec&Y\x7f\
+\xaf\x1c\xc6\x17\xc1\xdc\x8f\xea\x1c\xf1B\xd9\xe4\xfb\xc4\x13my\xf0\xc1\x96\
+\xa5J\xc4l\xdf^\xc8\x95Wn\xe1\xa8;\x8f\x91\x0fA\xb7k\x8c\xcc\xdd\xa0\xfd\xe9\
+\x82\x07f\x95\xdfU/\x8bn\xae#\x0f\x12\x12\xac\xdc\x7f\x7f+\xee\xbb\xaf\x05\
+\x91\x91\xaax\xbf\xa7\x9e:\xc8\xf4\xe9\xfb\xfc\x16\x1b\x84\xe0\x1e,5\t\xff\
+\x8bn\x16\x1e{\xac-w\xdf\xdd\x1c\x90\x0c\xb8\x9bo\xde\xceG\x9f\x1f\xe3\xaa\
+\xf7\xa0\xc3%\x1eBK5\r\r\xc77\xc2\xd2\xc7a\xebge\xa4\xb9W\x00\xcd\x07\xc2\
+\x95\xefC\xa2\x8f\x0f[k\x91U}\xe7"\xe8\xd0*\x96E\x8bz\xf2\xdcs\x87B\x8et\x01\
+\xac\xaa\xd6~\xa9\xea\x83R\x96\x19h=\xdd\xdfg\xcb\x96e\xd1\xb6m,={\xc6\x16\
+\x93\xafR\x8a\x86\rm\x9cuV=\xfe\xfb\xe6IV\xbd\xe7\xc2]\x08\xcd\xfaW}\x99\xee\
+\xba\x06\xad\xe1\xe4fY\xe4\xd8\xf0.\xb8\xecR\x89\xe1\x8b/z2iRc\xa3*\xaf\xc2\
+\xe9\x84\xa7\x9f>\xc8#\x8f\xec\xc5\xe9\xf4\x7f\xac`\x1f,5\t\x7f}\xd8n\xd7|\
+\xf3M\x06QQV\x06\x0eL :\xda\xc2\xd8\xb1\r\xc9\xcbv\xf3\xceC9D\xc4@\xf3A\xb5D\
+\xbe\n\xe2\x9a@\xf7+\xa0\xddy\x90\xd4V\xb6\xc57\x82\x888\x11\xd8)\xabH\xa6-\
+\x06:]\x04c_\x81\x913 :\xb94\xe9\x9e\xd8\x04\x1f]\x03\x11v+K\x97\xf6\xe5\xeb\
+\xaf\xd3C"\x82\xc1\x1f\xea\xa4\xc5k"\x90\xe5\x1b\x19\xa9x\xe1\x85\x8eL\x9e\
+\xdc\x04\x9b\xcd\xdb\xedp\xe4\x88\x83?\xfeq\x1bK\x96d\xd0z\xb8T\x89M\xe9\x1d\
+&__\x98E\x16\x7f{\x01~z\n\x8a\xb2\xc0b\x81\xa9S[\xf0\x97\xbf\xb4(\xae\xf6\
+\xab\xb5f\xcf\x9e"\xee\xbak\'\x8b\x17\xa7\xfb\x8d\x9b\x0e\x85\x81R[\x08\xd4\
+\x87\xaf\xb9\xa6\x11s\xe7v&:Zn\xdd\xf7\xdfgq\xf3\x9f\xb6\xd1xL\x11\x17>\x07\
+\xd6\x98\xda\xed\xb3Z\x1bI\x02J\x1e\xc6Y\xfb s\xaf\xc8Jf\xfa\x88\xe94\xeb\
+\x0b-\x86BL\xb2\xff\xe8"\xd3\x97\xfc\xe6\xb9\xa03\xac|\xf2I\x0f\xb2\xb3]\xfc\
+\xe1\x0f[J\xcd\x9cB\xa5/\xd5i\xe2\x85\xb2\xdd\x0ew\xdd\xd5\x9c\xe7\x9e+\xed\
+\xf3u8`\xea\xd4\x9d\xbc\xf5\xd6\x11\x9ch\x86\xde\x03\xc3\xee\x87\xc8z\x9c\
+\xf1\xbe_sE\xf9\xd02\xf8\xe6\x018\xb0B\xb6\'&Z\x99>\xbd-\xd3\xa65+\xf6\xe5:\
+\x1c\xf0\xca+\x87y\xfc\xf1\xfddd\xf87sCe\xa0\xd46\xfc\xf5\xe3\xb3\xcf\xae\
+\xc7\xb3\xcf\xb6c\xf0\xe0\x04\x00\x0e\x1c\xb03\xe9\xfa\xadd7\xcbb\xdck\x92\
+\xdd\x15\xf2\x06\x83\x86\xcc=\xf0\xc5d\xd8\xff\x13\xcc\x9a\xd5\x89\xf3\xcek\
+\xc0\xd9g\xaf\xe5\xc8\x91\xd2*B\xa1\xd2\x9f\xea<\xf1B\xf9\xe4\xfb\xe4\x93\
+\xed\x88\x89Q^\xe4\xebv\xc3\xaaU9\xdcx\xe36v\xec( \xa9\x83T\x89\xed8\x0e,g\
+\xa8\xfbAk\xc8;\x0c\xbf\xbe\x00+^\x90\xa9\xa3\xc5"\x04\xf0\xf2\xcb\x1d\xe9\
+\xd9\xd3\\E\x81\xb5k\xf3\x986m\'+Vd\x07\xcc\x0e\x0c\x95A\x12,\xf0\xd7\x8fM\
+\xb7\xce\xd9g\x0b\xf9\xba\\\xf0\xec\xb3\x07\xf9\xef\xe6\xbd\\\xfcjh\x93\xaf\
+\xd6\xb0\xff[\x115\xcfI\x85\'\x9fl\xc7\xb4i\xcd\xb9\xf0\xc2\x8d\xfc\xfcs\xe8\
+D0\xf8\xc3\x19A\xbcP6\xf9\x9esN=>\xff\xbc\'\xf5\xeaYJ-\xba\x1d;\xe6\xe0\xce;\
+w\xf1\xf1\xc7\xc7QVh\xd4\x1d\xce\xff\'\xb4\xbb\x00T5\x96\xe9\x0e&\x04*W\xd4\
+\xaaU\x14\xcf=WR\xd2\x06\xa4B\xc4\x8b/\x1ef\xfa\xf4}\x01\xabC\x84\xd2\x00\tF\
+\xf8\xf6\xe5\xa4$\x1b\x8f>\xda\x86\xdboo\x86\xcd&\xf1\xd1O?s\x909\x0b\xf6q\
+\xd5\x02MtJ\x08\xf6S\r\xe9\xdb$N8}\x0f\\ye\no\xbe\xd9\x85{\xee\xd9\xc5k\xaf\
+\x05\x7fJpy8c\x88\x17\xca&\xdf\x8e\x1dcx\xff\xfdn\xf4\xeb\x17W\x8a|\x1d\x0eI\
+\xb6\x98<y;iivP\xd0\xa8\x1b\\\xf84\xb4\x1fS\xb7\xb3\xde\xdcN\xf8\xfd\x03X\
+\xfe\x8cT\x860\xd1\xb5\xab\xac*\xb7m\x1bU\xec\xcb]\xb4(\x9d\x07\x1f\xdc\xcb\
+\xe6\xcdy\x01\x8f\x17j\x03$X\xe1\xaf/\xdfxccf\xce\xecH|\xbc\xac\xae\xadX\x91\
+\xc3\xbd\xff\xdcF\xafG\x0bh:8t\xfa\xa8v\xc3\xeeE\xf0\xd1u\x12\x9ev\xe5\x95)\
+\xbc\xf1Fg\xfe\xf2\x97\xddu\x82t\xe1\x0c#^\x13\x81\x088*J\xf1\xe8\xa3m\x8a+\
+\xd9\xfa\x12pf\xa6\x8b\xe9\xd3\xf71wn\x9a\xc4\xa0*\x89|\x180Ed\xea\xcc\x8a\
+\x10\xa1\x0e3<l\xf7b\xf8\xed%\xd8\xf5\x8dl\xb7X\xa0G\x8f8f\xcd\xeaL\xef\xdeq\
+\xc4\xc4\xc8\xc5\x1e8`\xe7\xee\xbbw\xb1h\xd1\x89\x80\x11\x0b\x10\x9a\x03$\
+\x98\xe1\xaf\x1f\xf7\xeb\x17\xcf\x9bov\xa1g\xcfX\x00~\xfe9\x9b\tWld\xfc;n\
+\xda\x8d&\xa8\xfb\xa7\xb9`\xbbx*\xac\x9e\x0bh!\xdd\xb9s;s\xdf}\xbb\x993\xa7n\
+\x90.\x9c\xa1\xc4\x0b\x81\xc9W)\x18=ZR[\x9b6\x8d(E\xbe \xb5\xbf>\xf8\xe0\x18\
+o\xbf}\x84c\xc7\x1c(\x0b4\xe9\r].\x81\xde\xd7K\x0e}(\xc6\x00k\r\xda\x0e\xfb\
+\xbe\x87\xe5\xcf\xc2\x9e\xefe{\xf3\xe6QL\x98\xd0\x90)S\x9a\xd2\xa3G\\\xb1[\
+\xe1\xe4I\'O<q\x80\xb9sS\xc9\xcd\r\x1c\xb8\x19\xaa\x83#\x14\x10H\xe7\xe1\xf9\
+\xe7;0yr\x13\x00V\xae\xcc\xe5\xc6?m\xa5\xe55\x05\x0c\xfd;\x04c\xb9(\xad!\xe7\
+\x00|z=\xec\xffY\xb6]ye\n\xd3\xa7\xb7\xe1\xfe\xfb\xf7\xb0h\xd1\xc9R\xdf\t\
+\xe5~u\xc6\x12/\x94\xedz\xa8W\xcf\xca\x93O\xb6g\xca\x94&X,\xde\xd6/\x08\t\
+\x1f:dg\xe6\xcc\xc3|\xfe\xf9\tv\xed*@k\x89Y\xec2\x1e\xba_\t\xcd\x06@|s\xa4|O\
+\x90v\x113J\xc1\x9e\r\x9b\xe6\xc3\xaf/\xc1\x89\x1d\x80\x16\x1f\xeeM75\xe5\
+\xaf\x7fmIl\xac*v)\xd8\xed\x9aY\xb3\xd2x\xee\xb9\x83\x1c8P7\x84\xcaC\x19\xfe\
+\xfa\xb1\xcd\xa6\xb8\xf2\xca\x14^z\xa9\x03\r\x1b\xda\xd8\xbb\xb7\x88\x8b.\
+\xde\x88\xa5S\x01c^\x80\xc4\xb6\xc1\xd3\'\xb5\x1bv-\x94Zi\x19{efu\xfd\xf5M\
+\x982\xa5)\xb7\xde\xba\xc3\xaf\xeb*\xd4\xfb\xd5\x19M\xbcP6\xf9*\x05\x17\\\
+\xd0\x80\xbb\xeej\xc1\xc5\x177@\xa9\xd2\xee\x07\x80\xc2B\xcd\xdbo\x1f\xe5\
+\xad\xb7\xd2X\xb7.\xb78\xb60"\x16:\x8e\x81\xe1\x7f\x87\xe4.R:E\xd9\x08\x8e\
+\xe9\x9e\x06\xed\x84\x13\xbf\xc3\xba7`\xe3\x07\xb2h\x16\x19\xa9\x18>\xbc>S\
+\xa64e\xec\xd8\x86\xc4\xc5\x954\xb6\xb0P\xf3\xfe\xfb\xc7x\xea\xa9\x03\xec\
+\xd8QP\xc6\xc1C\x7f`\x84\x1a\x02\xf5\xe3A\x83\x12x\xe4\x916\x8c\x1d\xdb\x80\
+\xbd{\x8b\x183f#\x873\n\x18\xfd\x0c\xf4\xbc\xa1\x163\xdd(\x89\x92Y\xf6$\xac\
+\x9c%Q2\xf1\xf1V\xfe\xf3\x9f\x0e\xec\xdbW\xc8\xcc\x99\x07\xfd\xce\xa4\xeaB\
+\xdf:\xe3\x89\x17\xca&_\x90\'\xf0\xf9\xe77\xe0\x81\x07Z1lX=\xaf\xa4\x8b\xe2c\
+\x18!h\xbbv\x15\xf2\xe5\x97\xe9|\xf4\xd1Q\xd6\xaf\xcf\x93\x02\x8d\n\xa2\xeb\
+\x89r\x7f\xeba\xd0\xf9\x12\xb1\x86#\xe2\xc0\x12I\x8d\x10\xb1i\xd9\xba\xed\
+\x12\x17\xb9q\x1e\xec\\\x0cG7C\x84E\xd1\xaf_\x02\xc3\x86\xd5\xe3\xfa\xeb\x9b\
+\xd0\xad[,J\xe9b\x0b77\xd7\xcd\xfc\xf9\xc7x\xfe\xf9\x83\xec\xdcYP\xaex|]\x18\
+\x18\xa1\n\x7f}9"Bq\xef\xbd-\xb9\xef\xbe\x16de\xb9\x183f#\xbbv\x170\xf4\x1e\
+\x18\xf1\x88h\xfb\xd6\xb41\xa05\xa4\xfd\n\x0b\xfe\x0c\xc76\xcb\xb6\x0b.h\xc0\
+\xfd\xf7\xb7\xe6\xc5\x17\x0f\xb2pai\xd7\x02\xd4\x9d\xbe\x15&^\x03\xe5\x91/\
+\x885\xd8\xbf\x7f\x02O=\xd5\x8e\x81\x03\x13\x88\x8aR\xa5\x08\x18\x84\x84].)C\
+\xb4xq:\xf3\xe6\x1de\xd5\xaal/Q\x98\xc8\x04\x88o\x0c-\x07C\x83\xb6\xd0l \xb4\
+\x1e\x01\xd6\x08\xb0\xc5\x1a\xc7\x81S\x1e\x10\x9eD\x9b\xb5\x0f\x0e\xae\x80\
+\xbd?\xc0\xc1_%s(&\xc2\xc2\xa0A\xf58\xe7\x9cz\xdcpC\x13Z\xb5\x8a\xf4\xb0\xe8\
+5ZCf\xa6\x8b\xcf>;\xc1\xb3\xcf\x1ed\xeb\xd6\xfcr\xcfYW\x06E(\xa3\xac~|\xd6Y\
+\x89<\xf4P+\xbav\x8d\xe3\x96[v\xf0\xddw\x19\xc45\x82K_\x87\x0e\xe3jf]\xc2\\\
+\xb8\xdd\xf2>|9\r\n3d\r\xe1\xbe\xfbZR\xaf\x9e\x8d\x87\x1f\xdeCjj\xdd\x97\x08\
+\r\x13\xaf\x07*B\xbe \x9d\xb3M\x9bh\x9ex\xa2-\xa3G\'\x19\xf5\xc2t@\x12\xd6\
+\x1a\x8e\x1ds\xf0\xd1G\xc7Y\xba4\x8bM\x9br\xd9\xb7\xaf\x10\x87\xc3\xfbt\xd6H\
+\x88I\x82\x06\xed\xe4}J\x17\x88K\x86\x96C\xc1b\x93\x92\xd6\xf1\xcd\x02\xb7\
+\xab(\x0bNl\x85\xfc\xe3pl\x0b\x9c\xdc%\xff\xa6\xef\x81\xa8\x08E\xbf~\x89\xf4\
+\xe9\x13G\x9f>\xf1\x8c\x19\x93D\x8b\x16Qf+\x8b\xad[\xad\x15\xfb\xf7\x172s\
+\xe6a\xdex#\x8d\xac\xac2\x12\xec=\xefI\x1d\x1a\x14u\x01eE\xee\\\x7f}\x13\x1e\
+~\xb85S\xa7\xee\x14\xcb\xd2\x02\xed\xcf\x83s\x1e\x86\xe6g\x01\xd5\xa0K\xad5\
+\xe0\x84\xdf?\x84eFhb\x84M1aB2\xe3\xc6%\xf3\xfe\xfbG\xf9\xe6\x9b\xf43F"4L\
+\xbc~PQ\x02\x06\x88\x89\xb10th=.\xbb,\x99+\xaeH\xa1Q#)\xda\x18\x88\x84A\xe1t\
+j\x0e\x1c(b\xf3\xe6<\xd6\xac\xc9a\xcb\x96<\xd6\xaf\xcf%\'\xc7Ez\xba\x03W\x00\
+\xaeSV\x08\xf8s)\xc0\r\tq6l6\xc5\x80\x01\t\xf4\xea\x15G\xa3F\x91\xf4\xec\x19\
+G\xd7\xae\xb14k\x16\x89\xc5\xf0\xe9yf\xe9\x81X\xb7_}\x95\xcek\xaf\xa5\xf1\
+\xcb/Y\x01\xd5\xc3J\x9d\xb6\x8e\r\x88\xba\x86@}9%%\x82\xc7\x1fo\xc7\xde\xbd\
+\x85<\xf7\xdc\x01\x1c\x0e\x8d\xb2BJW8\xe7A\xe8<A\xf4\x1eN\xc7\n6\xc3\xc3\xd2\
+w\xc2\xf6/`\xf3\x7f\xe1\xe8\x16@K\xdc\xfc\xfd\xf7\xb7f\xd3\xa6\\f\xce<\x14\
+\x90p\xa1n\xf6\xb10\xf1\x96\x81\xca\x100@\xd3\xa6\x91\xdczk3\xbat\x89\xa5s\
+\xe7X\xbaw\x8f-\x15\x0f\\\xea\x1c\x06\xf1i\xad\xd0\x1av\xef.\xa0\xa8Hz\xe1\
+\xb6m\xf9\xa4\xa7\x97\x11\x18k >\xdeJ\xaf^R7\xa5m\xdb\x18bb,X,r\xdc\xb2\x1e\
+\x00\xb9\xb9.V\xaf\xce\xe1\xbd\xf7\x8e\xf1\xd1G\xc7*l\xddB\xdd\x1c\x0cu\x15e\
+\xf5\xe3n\xddb\x998\xb11\xef\xbf\x7f\x84]\xbbJ\x16L\x13\x9aC\xd7\xf1\xd0\xe3\
+\x0f\xd0\xb4?\xd8\xe2\xca\'a\xd3\xbd\x85\x1brSa\xefR\xf8\xf5EH]\x8b\x99INT\
+\x94\xe2\xd2KS\x88\x8f\xb7\xf1\xfe\xfbG\xc8\xcf?3\xc3\x10\xc3\xc4[\x0e*K\xbe\
+&,\x16\xa9\x1c0~|2\x13&4\xa4A\x03\x1b-ZDa\xb1\xa8Z\xaa\x16 \x97\x91\x9e\xeed\
+\xed\xda<\x16-:\xc1\xa2E\'\xd9\xb3\'p\x9d3\x7f\xa8\xcb\x83\xa1.\xa3\xac~\x1c\
+\x13ca\xf0\xe0D\x92\x93#\xf8\xf6\xdb\x0c23\xbd\x1f\xf6\x89-\xa0\xeb\x04h\xd6\
+\x0f\xea\xb7\x83\xc4V\x12\xb1\x13\x97,\x9fg\x1f\x06\xb7\x0b\xb2\x0f\x88e\xbb\
+\xffg\xb1l\x9d\x1e\x81/\xf1\xf1\x16:t\x88!3\xd3\xc9\xf1\xe3\x8e\x80"\xf8&\
+\xeaz?\x0b\x13o\x05q\xaa\x04\x0cB\xc2V\xab\xa2W\xafx&LhH\x93&\x91\x0c\x1c\
+\x98HB\x82\x95V\xad\xa2\x0c\xab\xb8l\xcb\xb8Rm5H\xd6\xe5\x82\x8c\x0c\'\x1b6\
+\xe4\xb2aC\x1eK\x97f\xb2lY\x16YY\xceJ\x97\xb5\xaf\xeb\x03\xe1LAY\xfd8!\xc1\
+\xca\x88\x11\xf5IM-b\xf7\xee\x02\xb2\xb3\xfd\xcc\x80\x8c\xe4\x8b\x88X\x88m(\
+\x9b\xb2S%\x14Lk\xf0,\xe3\x1e\x15\xa5\x185\xaa\x01n\xb7f\xe7\xce|\xf6\xed+\
+\xaaP\xbf;\x13\xfaZ\x98x+\x81\xd3!_\x7f\x88\x8cT4n\x1cI\xd7\xae\xb1\x8c\x18Q\
+\x9f\x86\r#\x182$\x11\xad\xe5\xb3\xf6\xedc\xd0Zc\xb1(\xfe\xbf\x9d\xbbWM\x18\
+\x8c\xc28\xfe\x18\x89\xa6Z\x89kwQ\x10\x15\x17\xaf\xc7\xdb\x14\\3(^\x80 \xf8\
+\xb5k\xd1P\x8d%\x89\xe9\x10\n\xd6Z\x13\xbfj\xce{\xce\x7f\x16\xcc\xf0\xf3\xe1\
+%\t\xea\xfa\xef\x93r\x10\x00\x9e\x17\xc0\xf7\x038\xce\x1e\xf3\xf9\'f3\x07\
+\xe3\xf1\x0e\xbd\x9e\x8d\xc9\xc4\xc1t\xba\xfb\xf3/\x19\xa3\xe2\xf0\x03\xe0X\
+\x1c\xc7\x95\xca\x0b\x0cC\x83\xe3\xec\xb1X\xb8\xb1nye\xb3)\x94J94\x9b\x05T\
+\xab9x\x1e`Y+t\xbb\xef\xb1\xaf\x8d\x8b9\x19\xde+\xba\xf7\x00\x1f\xf6=\xae\
+\xe9t\n\xc5b\xf8\xa0\xce4\xd3\xa8\xd7_O~~8\xdcb\xb9t\xe1\xba{\xd8\xb6\x7f\
+\xf1I\xf6\xc7w3A/\xc57\\.\xe7\xd0h\xe4aY+\xd4jy\xac\xd7\x1e\x06\x83\x0f\xe8z\
+\n\xed\xf6\x1b\x0cC\x83ah\xc8d4\xb4Z\x05\x8cF[t:K\xf4\xfb\xf6\xd9\xfb\xb7\
+\xc7q\xb3\'\xc3{\xd0#\x075\xe9q\x83\xcf\xbd[\xadk\x1a`\x9a\xe1\xc1`\xb3\xf1c\
+\xbf\x05\x13\x15\x17\x87\xac\x87\x97\xf3\xd0\x1e\xc7\x05<\xd7([W\xd1&\xbb\
+\xe1\xa5\x0c\xf0?S\x11;\xa7TwN\xdd\xa7\x0c\xaftU\xd4\xe1\xab\x94\x98\x0e\xa3\
+d\x92\xdd\xf0\x02\x02\xf5\x91Q\xc2O=q|\xbe$[d9\xbc\xe7\x12\xcc\xb7\x95d\xec\
+\x9c\xe2\xee8\xe9\x0eex/\x88;\xe6\xa8\x92\x8e]\nS\xd91\x15\x832\xbcwLU\xd0T0\
+K\xf7\x8d\x82g\xaa6ex\x9f\xdc3pS\xc5*\xd1\xe9V\xd7\xaa\x1b\xfd\x028\xc0\xaeS\
+5\x9dLZ\x00\x00\x00\x00IEND\xaeB`\x82'
+
+def getVippiBitmap():
+ return BitmapFromImage(getVippiImage())
+
+def getVippiImage():
+ stream = cStringIO.StringIO(getVippiData())
+ return ImageFromStream(stream)
+
--- /dev/null
+import wx
+
+class MDIFrame(wx.MDIParentFrame):
+ def __init__(self):
+ wx.MDIParentFrame.__init__(self, None, -1, "MDI Parent",
+ size=(600,400))
+ menu = wx.Menu()
+ menu.Append(5000, "&New Window")
+ menu.Append(5001, "E&xit")
+ menubar = wx.MenuBar()
+ menubar.Append(menu, "&File")
+ self.SetMenuBar(menubar)
+ self.Bind(wx.EVT_MENU, self.OnNewWindow, id=5000)
+ self.Bind(wx.EVT_MENU, self.OnExit, id=5001)
+
+ def OnExit(self, evt):
+ self.Close(True)
+
+ def OnNewWindow(self, evt):
+ win = wx.MDIChildFrame(self, -1, "Child Window")
+ win.Show(True)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = MDIFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class MiniFrame(wx.MiniFrame):
+ def __init__(self):
+ wx.MiniFrame.__init__(self, None, -1, 'Mini Frame',
+ size=(300, 100))
+ panel = wx.Panel(self, -1, size=(300, 100))
+ button = wx.Button(panel, -1, "Close Me", pos=(15, 15))
+ self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ def OnCloseMe(self, event):
+ self.Close(True)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ MiniFrame().Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class ScrollbarFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, 'Scrollbar Example',
+ size=(300, 200))
+ self.scroll = wx.ScrolledWindow(self, -1)
+ self.scroll.SetScrollbars(1, 1, 600, 400)
+ self.button = wx.Button(self.scroll, -1, "Scroll Me", pos=(50, 20))
+ self.Bind(wx.EVT_BUTTON, self.OnClickTop, self.button)
+ self.button2 = wx.Button(self.scroll, -1, "Scroll Back", pos=(500, 350))
+ self.Bind(wx.EVT_BUTTON, self.OnClickBottom, self.button2)
+
+ def OnClickTop(self, event):
+ self.scroll.Scroll(600, 400)
+
+ def OnClickBottom(self, event):
+ self.scroll.Scroll(1, 1)
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = ScrollbarFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+import images
+
+class ShapedFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "Shaped Window",
+ style = wx.FRAME_SHAPED | wx.SIMPLE_BORDER |
+ wx.FRAME_NO_TASKBAR)
+ self.hasShape = False
+ self.bmp = images.getVippiBitmap()
+ self.SetClientSize((self.bmp.GetWidth(), self.bmp.GetHeight()))
+ dc = wx.ClientDC(self)
+ dc.DrawBitmap(self.bmp, 0,0, True)
+ self.SetWindowShape()
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
+ self.Bind(wx.EVT_RIGHT_UP, self.OnExit)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
+
+ def SetWindowShape(self, evt=None):
+ r = wx.RegionFromBitmap(self.bmp)
+ self.hasShape = self.SetShape(r)
+
+ def OnDoubleClick(self, evt):
+ if self.hasShape:
+ self.SetShape(wx.Region())
+ self.hasShape = False
+ else:
+ self.SetWindowShape()
+
+ def OnPaint(self, evt):
+ dc = wx.PaintDC(self)
+ dc.DrawBitmap(self.bmp, 0,0, True)
+
+ def OnExit(self, evt):
+ self.Close()
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ ShapedFrame().Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+import images
+
+class ShapedFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "Shaped Window",
+ style = wx.FRAME_SHAPED | wx.SIMPLE_BORDER )
+ self.hasShape = False
+ self.delta = wx.Point(0,0)
+ self.bmp = images.getVippiBitmap()
+ self.SetClientSize((self.bmp.GetWidth(), self.bmp.GetHeight()))
+ dc = wx.ClientDC(self)
+ dc.DrawBitmap(self.bmp, 0,0, True)
+ self.SetWindowShape()
+ self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+ self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
+ self.Bind(wx.EVT_MOTION, self.OnMouseMove)
+ self.Bind(wx.EVT_RIGHT_UP, self.OnExit)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_WINDOW_CREATE, self.SetWindowShape)
+
+ def SetWindowShape(self, evt=None):
+ r = wx.RegionFromBitmap(self.bmp)
+ self.hasShape = self.SetShape(r)
+
+ def OnDoubleClick(self, evt):
+ if self.hasShape:
+ self.SetShape(wx.Region())
+ self.hasShape = False
+ else:
+ self.SetWindowShape()
+
+ def OnPaint(self, evt):
+ dc = wx.PaintDC(self)
+ dc.DrawBitmap(self.bmp, 0,0, True)
+
+ def OnExit(self, evt):
+ self.Close()
+
+ def OnLeftDown(self, evt):
+ self.CaptureMouse()
+ pos = self.ClientToScreen(evt.GetPosition())
+ origin = self.GetPosition()
+ self.delta = wx.Point(pos.x - origin.x, pos.y - origin.y)
+
+ def OnMouseMove(self, evt):
+ if evt.Dragging() and evt.LeftIsDown():
+ pos = self.ClientToScreen(evt.GetPosition())
+ newPos = (pos.x - self.delta.x, pos.y - self.delta.y)
+ self.Move(newPos)
+
+ def OnLeftUp(self, evt):
+ if self.HasCapture():
+ self.ReleaseMouse()
+
+
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ ShapedFrame().Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ frame = wx.Frame(None, -1, "A Frame", style=wx.DEFAULT_FRAME_STYLE,
+ size=(200, 100))
+ frame.Show()
+ app.MainLoop()
--- /dev/null
+import wx
+
+class SplitterExampleFrame(wx.Frame):
+ def __init__(self, parent, title):
+ wx.Frame.__init__(self, parent, title=title)
+ self.MakeMenuBar()
+ self.minpane = 0
+ self.initpos = 0
+ self.sp = wx.SplitterWindow(self)
+ self.p1 = wx.Panel(self.sp, style=wx.SUNKEN_BORDER)
+ self.p2 = wx.Panel(self.sp, style=wx.SUNKEN_BORDER)
+ self.p1.SetBackgroundColour("pink")
+ self.p2.SetBackgroundColour("sky blue")
+ self.p1.Hide()
+ self.p2.Hide()
+
+ self.sp.Initialize(self.p1)
+
+ self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGING,
+ self.OnSashChanging, self.sp)
+ self.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED,
+ self.OnSashChanged, self.sp)
+
+
+ def MakeMenuBar(self):
+ menu = wx.Menu()
+ item = menu.Append(-1, "Split horizontally")
+ self.Bind(wx.EVT_MENU, self.OnSplitH, item)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanSplit, item)
+ item = menu.Append(-1, "Split vertically")
+ self.Bind(wx.EVT_MENU, self.OnSplitV, item)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanSplit, item)
+ item = menu.Append(-1, "Unsplit")
+ self.Bind(wx.EVT_MENU, self.OnUnsplit, item)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnCheckCanUnsplit, item)
+
+ menu.AppendSeparator()
+ item = menu.Append(-1, "Set initial sash position")
+ self.Bind(wx.EVT_MENU, self.OnSetPos, item)
+ item = menu.Append(-1, "Set minimum pane size")
+ self.Bind(wx.EVT_MENU, self.OnSetMin, item)
+
+ menu.AppendSeparator()
+ item = menu.Append(wx.ID_EXIT, "E&xit")
+ self.Bind(wx.EVT_MENU, self.OnExit, item)
+
+ mbar = wx.MenuBar()
+ mbar.Append(menu, "Splitter")
+ self.SetMenuBar(mbar)
+
+
+ def OnSashChanging(self, evt):
+ print "OnSashChanging:", evt.GetSashPosition()
+
+ def OnSashChanged(self, evt):
+ print "OnSashChanged:", evt.GetSashPosition()
+
+
+ def OnSplitH(self, evt):
+ self.sp.SplitHorizontally(self.p1, self.p2, self.initpos)
+
+ def OnSplitV(self, evt):
+ self.sp.SplitVertically(self.p1, self.p2, self.initpos)
+
+ def OnCheckCanSplit(self, evt):
+ evt.Enable(not self.sp.IsSplit())
+
+ def OnCheckCanUnsplit(self, evt):
+ evt.Enable(self.sp.IsSplit())
+
+ def OnUnsplit(self, evt):
+ self.sp.Unsplit()
+
+ def OnSetMin(self, evt):
+ minpane = wx.GetNumberFromUser(
+ "Enter the minimum pane size",
+ "", "Minimum Pane Size", self.minpane,
+ 0, 1000, self)
+ if minpane != -1:
+ self.minpane = minpane
+ self.sp.SetMinimumPaneSize(self.minpane)
+
+ def OnSetPos(self, evt):
+ initpos = wx.GetNumberFromUser(
+ "Enter the initial sash position (to be used in the Split call)",
+ "", "Initial Sash Position", self.initpos,
+ -1000, 1000, self)
+ if initpos != -1:
+ self.initpos = initpos
+
+
+ def OnExit(self, evt):
+ self.Close()
+
+
+app = wx.PySimpleApp(redirect=True)
+frm = SplitterExampleFrame(None, "Splitter Example")
+frm.SetSize((600,500))
+frm.Show()
+app.SetTopWindow(frm)
+app.MainLoop()
--- /dev/null
+import wx
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ choices = ["Alpha", "Baker", "Charlie", "Delta"]
+ dialog = wx.SingleChoiceDialog(None, "Pick A Word", "Choices",
+ choices)
+ if dialog.ShowModal() == wx.ID_OK:
+ print "You selected: %s\n" % dialog.GetStringSelection()
+
+ dialog.Destroy()
+
--- /dev/null
+import wx
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ dialog = wx.ColourDialog(None)
+ dialog.GetColourData().SetChooseFull(True)
+ if dialog.ShowModal() == wx.ID_OK:
+ data = dialog.GetColourData()
+ print 'You selected: %s\n' % str(data.GetColour().Get())
+ dialog.Destroy()
--- /dev/null
+import wx
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ dialog = wx.DirDialog(None, "Choose a directory:",
+ style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
+ if dialog.ShowModal() == wx.ID_OK:
+ print dialog.GetPath()
+ dialog.Destroy()
+
+
+
--- /dev/null
+import wx
+import os
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ wildcard = "Python source (*.py)|*.py|" \
+ "Compiled Python (*.pyc)|*.pyc|" \
+ "All files (*.*)|*.*"
+ dialog = wx.FileDialog(None, "Choose a file", os.getcwd(),
+ "", wildcard, wx.OPEN)
+ if dialog.ShowModal() == wx.ID_OK:
+ print dialog.GetPath()
+
+ dialog.Destroy()
+
+
+
--- /dev/null
+import wx
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ dialog = wx.FontDialog(None, wx.FontData())
+ if dialog.ShowModal() == wx.ID_OK:
+ data = dialog.GetFontData()
+ font = data.GetChosenFont()
+ colour = data.GetColour()
+ print 'You selected: "%s", %d points\n' % (
+ font.GetFaceName(), font.GetPointSize())
+ dialog.Destroy()
+
+
+
+
--- /dev/null
+import wx
+import wx.lib.imagebrowser as imagebrowser
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ dialog = imagebrowser.ImageDialog(None)
+ if dialog.ShowModal() == wx.ID_OK:
+ print "You Selected File: " + dialog.GetFile()
+ dialog.Destroy()
+
+
--- /dev/null
+import wx
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ dlg = wx.MessageDialog(None, "Is this explanation OK?",
+ 'A Message Box',
+ wx.YES_NO | wx.ICON_QUESTION)
+ retCode = dlg.ShowModal()
+ if (retCode == wx.ID_YES):
+ print "yes"
+ else:
+ print "no"
+ dlg.Destroy()
+
+ retCode = wx.MessageBox("Is this way easier?", "Via Function",
+ wx.YES_NO | wx.ICON_QUESTION)
--- /dev/null
+import wx
+
+class SubclassDialog(wx.Dialog):
+ def __init__(self):
+ wx.Dialog.__init__(self, None, -1, 'Dialog Subclass',
+ size=(300, 100))
+ okButton = wx.Button(self, wx.ID_OK, "OK", pos=(15, 15))
+ okButton.SetDefault()
+ cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel",
+ pos=(115, 15))
+
+if __name__ == '__main__':
+ app = wx.PySimpleApp()
+ app.MainLoop()
+ dialog = SubclassDialog()
+ result = dialog.ShowModal()
+ if result == wx.ID_OK:
+ print "OK"
+ else:
+ print "Cancel"
+ dialog.Destroy()
--- /dev/null
+import wx
+
+class Frame(wx.Frame):
+ def __init__(self, parent):
+ wx.Frame.__init__(self, parent, title="ProgressDialog sample")
+ self.progressMax = 100
+ self.count = 0
+ self.dialog = None
+ self.timer = wx.Timer(self)
+ self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
+ self.timer.Start(1000)
+
+ def OnTimer(self, evt):
+ if not self.dialog:
+ self.dialog = wx.ProgressDialog("A progress box", "Time remaining",
+ self.progressMax,
+ style=wx.PD_CAN_ABORT
+ | wx.PD_ELAPSED_TIME
+ | wx.PD_REMAINING_TIME)
+
+ self.count += 1
+ keepGoing = self.dialog.Update(self.count)
+ if not keepGoing or self.count == self.progressMax:
+ self.dialog.Destroy()
+ self.timer.Stop()
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = Frame(None)
+ frame.Show()
+ app.MainLoop()
+
--- /dev/null
+import wx
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ provider = wx.CreateFileTipProvider("tips.txt", 0)
+ wx.ShowTip(None, provider, True)
+
+
--- /dev/null
+import wx
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ dialog = wx.TextEntryDialog(None,
+ "What kind of text would you like to enter?",
+ "Text Entry", "Default Value", style=wx.OK|wx.CANCEL)
+ if dialog.ShowModal() == wx.ID_OK:
+ print "You entered: %s" % dialog.GetValue()
+
+ dialog.Destroy()
--- /dev/null
+You can do startup tips very easily.
+Feel the force, Luke.
--- /dev/null
+import wx
+
+about_txt = """\
+The validator used in this example will ensure that the text
+controls are not empty when you press the Ok button, and
+will not let you leave if any of the Validations fail."""
+
+
+class NotEmptyValidator(wx.PyValidator):
+ def __init__(self):
+ wx.PyValidator.__init__(self)
+
+ def Clone(self):
+ """
+ Note that every validator must implement the Clone() method.
+ """
+ return NotEmptyValidator()
+
+ def Validate(self, win):
+ textCtrl = self.GetWindow()
+ text = textCtrl.GetValue()
+
+ if len(text) == 0:
+ wx.MessageBox("This field must contain some text!", "Error")
+ textCtrl.SetBackgroundColour("pink")
+ textCtrl.SetFocus()
+ textCtrl.Refresh()
+ return False
+ else:
+ textCtrl.SetBackgroundColour(
+ wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
+ textCtrl.Refresh()
+ return True
+
+ def TransferToWindow(self):
+ return True
+
+ def TransferFromWindow(self):
+ return True
+
+
+
+class MyDialog(wx.Dialog):
+ def __init__(self):
+ wx.Dialog.__init__(self, None, -1, "Validators: validating")
+
+ # Create the text controls
+ about = wx.StaticText(self, -1, about_txt)
+ name_l = wx.StaticText(self, -1, "Name:")
+ email_l = wx.StaticText(self, -1, "Email:")
+ phone_l = wx.StaticText(self, -1, "Phone:")
+
+ name_t = wx.TextCtrl(self, validator=NotEmptyValidator())
+ email_t = wx.TextCtrl(self, validator=NotEmptyValidator())
+ phone_t = wx.TextCtrl(self, validator=NotEmptyValidator())
+
+ # Use standard button IDs
+ okay = wx.Button(self, wx.ID_OK)
+ okay.SetDefault()
+ cancel = wx.Button(self, wx.ID_CANCEL)
+
+ # Layout with sizers
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(about, 0, wx.ALL, 5)
+ sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
+
+ fgs = wx.FlexGridSizer(3, 2, 5, 5)
+ fgs.Add(name_l, 0, wx.ALIGN_RIGHT)
+ fgs.Add(name_t, 0, wx.EXPAND)
+ fgs.Add(email_l, 0, wx.ALIGN_RIGHT)
+ fgs.Add(email_t, 0, wx.EXPAND)
+ fgs.Add(phone_l, 0, wx.ALIGN_RIGHT)
+ fgs.Add(phone_t, 0, wx.EXPAND)
+ fgs.AddGrowableCol(1)
+ sizer.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)
+
+ btns = wx.StdDialogButtonSizer()
+ btns.AddButton(okay)
+ btns.AddButton(cancel)
+ btns.Realize()
+ sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
+
+ self.SetSizer(sizer)
+ sizer.Fit(self)
+
+
+app = wx.PySimpleApp()
+
+dlg = MyDialog()
+dlg.ShowModal()
+dlg.Destroy()
+
+app.MainLoop()
--- /dev/null
+import wx
+import pprint
+
+about_txt = """\
+The validator used in this example shows how the validator
+can be used to transfer data to and from each text control
+automatically when the dialog is shown and dismissed."""
+
+
+class DataXferValidator(wx.PyValidator):
+ def __init__(self, data, key):
+ wx.PyValidator.__init__(self)
+ self.data = data
+ self.key = key
+
+ def Clone(self):
+ """
+ Note that every validator must implement the Clone() method.
+ """
+ return DataXferValidator(self.data, self.key)
+
+ def Validate(self, win):
+ return True
+
+ def TransferToWindow(self):
+ textCtrl = self.GetWindow()
+ textCtrl.SetValue(self.data.get(self.key, ""))
+ return True
+
+ def TransferFromWindow(self):
+ textCtrl = self.GetWindow()
+ self.data[self.key] = textCtrl.GetValue()
+ return True
+
+
+
+class MyDialog(wx.Dialog):
+ def __init__(self, data):
+ wx.Dialog.__init__(self, None, -1, "Validators: data transfer")
+
+ # Create the text controls
+ about = wx.StaticText(self, -1, about_txt)
+ name_l = wx.StaticText(self, -1, "Name:")
+ email_l = wx.StaticText(self, -1, "Email:")
+ phone_l = wx.StaticText(self, -1, "Phone:")
+
+ name_t = wx.TextCtrl(self, validator=DataXferValidator(data, "name"))
+ email_t = wx.TextCtrl(self, validator=DataXferValidator(data, "email"))
+ phone_t = wx.TextCtrl(self, validator=DataXferValidator(data, "phone"))
+
+ # Use standard button IDs
+ okay = wx.Button(self, wx.ID_OK)
+ okay.SetDefault()
+ cancel = wx.Button(self, wx.ID_CANCEL)
+
+ # Layout with sizers
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(about, 0, wx.ALL, 5)
+ sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
+
+ fgs = wx.FlexGridSizer(3, 2, 5, 5)
+ fgs.Add(name_l, 0, wx.ALIGN_RIGHT)
+ fgs.Add(name_t, 0, wx.EXPAND)
+ fgs.Add(email_l, 0, wx.ALIGN_RIGHT)
+ fgs.Add(email_t, 0, wx.EXPAND)
+ fgs.Add(phone_l, 0, wx.ALIGN_RIGHT)
+ fgs.Add(phone_t, 0, wx.EXPAND)
+ fgs.AddGrowableCol(1)
+ sizer.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)
+
+ btns = wx.StdDialogButtonSizer()
+ btns.AddButton(okay)
+ btns.AddButton(cancel)
+ btns.Realize()
+ sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
+
+ self.SetSizer(sizer)
+ sizer.Fit(self)
+
+
+app = wx.PySimpleApp()
+
+data = { "name" : "Jordyn Dunn" }
+dlg = MyDialog(data)
+dlg.ShowModal()
+dlg.Destroy()
+
+wx.MessageBox("You entered these values:\n\n" +
+ pprint.pformat(data))
+
+app.MainLoop()
--- /dev/null
+import wx
+import string
+
+about_txt = """\
+The validator used in this example will validate the input on the fly
+instead of waiting until the okay button is pressed. The first field
+will not allow digits to be typed, the second will allow anything
+and the third will not allow alphabetic characters to be entered.
+"""
+
+
+class CharValidator(wx.PyValidator):
+ def __init__(self, flag):
+ wx.PyValidator.__init__(self)
+ self.flag = flag
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+
+ def Clone(self):
+ """
+ Note that every validator must implement the Clone() method.
+ """
+ return CharValidator(self.flag)
+
+ def Validate(self, win):
+ return True
+
+ def TransferToWindow(self):
+ return True
+
+ def TransferFromWindow(self):
+ return True
+
+ def OnChar(self, evt):
+ key = chr(evt.GetKeyCode())
+ if self.flag == "no-alpha" and key in string.letters:
+ return
+ if self.flag == "no-digit" and key in string.digits:
+ return
+ evt.Skip()
+
+
+class MyDialog(wx.Dialog):
+ def __init__(self):
+ wx.Dialog.__init__(self, None, -1, "Validators: behavior modification")
+
+ # Create the text controls
+ about = wx.StaticText(self, -1, about_txt)
+ name_l = wx.StaticText(self, -1, "Name:")
+ email_l = wx.StaticText(self, -1, "Email:")
+ phone_l = wx.StaticText(self, -1, "Phone:")
+
+ name_t = wx.TextCtrl(self, validator=CharValidator("no-digit"))
+ email_t = wx.TextCtrl(self, validator=CharValidator("any"))
+ phone_t = wx.TextCtrl(self, validator=CharValidator("no-alpha"))
+
+ # Use standard button IDs
+ okay = wx.Button(self, wx.ID_OK)
+ okay.SetDefault()
+ cancel = wx.Button(self, wx.ID_CANCEL)
+
+ # Layout with sizers
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(about, 0, wx.ALL, 5)
+ sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
+
+ fgs = wx.FlexGridSizer(3, 2, 5, 5)
+ fgs.Add(name_l, 0, wx.ALIGN_RIGHT)
+ fgs.Add(name_t, 0, wx.EXPAND)
+ fgs.Add(email_l, 0, wx.ALIGN_RIGHT)
+ fgs.Add(email_t, 0, wx.EXPAND)
+ fgs.Add(phone_l, 0, wx.ALIGN_RIGHT)
+ fgs.Add(phone_t, 0, wx.EXPAND)
+ fgs.AddGrowableCol(1)
+ sizer.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)
+
+ btns = wx.StdDialogButtonSizer()
+ btns.AddButton(okay)
+ btns.AddButton(cancel)
+ btns.Realize()
+ sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
+
+ self.SetSizer(sizer)
+ sizer.Fit(self)
+
+
+app = wx.PySimpleApp()
+
+dlg = MyDialog()
+dlg.ShowModal()
+dlg.Destroy()
+
+app.MainLoop()
--- /dev/null
+import wx
+import wx.wizard
+
+class TitledPage(wx.wizard.WizardPageSimple):
+ def __init__(self, parent, title):
+ wx.wizard.WizardPageSimple.__init__(self, parent)
+ self.sizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.sizer)
+ titleText = wx.StaticText(self, -1, title)
+ titleText.SetFont(
+ wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
+ self.sizer.Add(titleText, 0,
+ wx.ALIGN_CENTRE | wx.ALL, 5)
+ self.sizer.Add(wx.StaticLine(self, -1), 0,
+ wx.EXPAND | wx.ALL, 5)
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ wizard = wx.wizard.Wizard(None, -1, "Simple Wizard")
+ page1 = TitledPage(wizard, "Page 1")
+ page2 = TitledPage(wizard, "Page 2")
+ page3 = TitledPage(wizard, "Page 3")
+ page4 = TitledPage(wizard, "Page 4")
+ page1.sizer.Add(wx.StaticText(page1, -1,
+ "Testing the wizard"))
+ page4.sizer.Add(wx.StaticText(page4, -1,
+ "This is the last page."))
+ wx.wizard.WizardPageSimple_Chain(page1, page2)
+ wx.wizard.WizardPageSimple_Chain(page2, page3)
+ wx.wizard.WizardPageSimple_Chain(page3, page4)
+ wizard.FitToPage(page1)
+
+ if wizard.RunWizard(page1):
+ print "Success"
+
+ wizard.Destroy()
+
+
+
--- /dev/null
+import wx
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Add Menu Items")
+ p = wx.Panel(self)
+ self.txt = wx.TextCtrl(p, -1, "new item")
+ btn = wx.Button(p, -1, "Add Menu Item")
+ self.Bind(wx.EVT_BUTTON, self.OnAddItem, btn)
+
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(self.txt, 0, wx.ALL, 20)
+ sizer.Add(btn, 0, wx.TOP|wx.RIGHT, 20)
+ p.SetSizer(sizer)
+
+ self.menu = menu = wx.Menu()
+ simple = menu.Append(-1, "Simple menu item")
+ menu.AppendSeparator()
+ exit = menu.Append(-1, "Exit")
+ self.Bind(wx.EVT_MENU, self.OnSimple, simple)
+ self.Bind(wx.EVT_MENU, self.OnExit, exit)
+
+ menuBar = wx.MenuBar()
+ menuBar.Append(menu, "Menu")
+ self.SetMenuBar(menuBar)
+
+
+ def OnSimple(self, event):
+ wx.MessageBox("You selected the simple menu item")
+
+ def OnExit(self, event):
+ self.Close()
+
+ def OnAddItem(self, event):
+ item = self.menu.Append(-1, self.txt.GetValue())
+ self.Bind(wx.EVT_MENU, self.OnNewItemSelected, item)
+
+ def OnNewItemSelected(self, event):
+ wx.MessageBox("You selected a new item")
+
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "Simple Menu Example")
+ p = wx.Panel(self)
+ menuBar = wx.MenuBar()
+ menu = wx.Menu()
+ menuBar.Append(menu, "Left Menu")
+ menu2 = wx.Menu()
+ menuBar.Append(menu2, "Middle Menu")
+ menu3 = wx.Menu()
+ menuBar.Append(menu3, "Right Menu")
+ self.SetMenuBar(menuBar)
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "Simple Menu Example")
+ p = wx.Panel(self)
+ menu = wx.Menu()
+ simple = menu.Append(-1, "Simple menu item")
+ menu.AppendSeparator()
+ exit = menu.Append(-1, "Exit")
+ self.Bind(wx.EVT_MENU, self.OnSimple, simple)
+ self.Bind(wx.EVT_MENU, self.OnExit, exit)
+ menuBar = wx.MenuBar()
+ menuBar.Append(menu, "Simple Menu")
+ self.SetMenuBar(menuBar)
+
+ def OnSimple(self, event):
+ wx.MessageBox("You selected the simple menu item")
+
+ def OnExit(self, event):
+ self.Close()
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+ID_SIMPLE = wx.NewId()
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Enable/Disable Menu Example")
+ p = wx.Panel(self)
+ self.btn = wx.Button(p, -1, "Disable Item", (20,20))
+ self.Bind(wx.EVT_BUTTON, self.OnToggleItem, self.btn)
+
+ menu = wx.Menu()
+ menu.Append(ID_SIMPLE, "Simple menu item")
+ self.Bind(wx.EVT_MENU, self.OnSimple, id=ID_SIMPLE)
+
+ menu.AppendSeparator()
+ menu.Append(wx.ID_EXIT, "Exit")
+ self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)
+
+ menuBar = wx.MenuBar()
+ menuBar.Append(menu, "Menu")
+ self.SetMenuBar(menuBar)
+
+
+ def OnSimple(self, event):
+ wx.MessageBox("You selected the simple menu item")
+
+ def OnExit(self, event):
+ self.Close()
+
+ def OnToggleItem(self, event):
+ menubar = self.GetMenuBar()
+ enabled = menubar.IsEnabled(ID_SIMPLE)
+ menubar.Enable(ID_SIMPLE, not enabled)
+ self.btn.SetLabel(
+ (enabled and "Enable" or "Disable") + " Item")
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Fancier Menu Example")
+ p = wx.Panel(self)
+ menu = wx.Menu()
+
+ bmp = wx.Bitmap("open.png", wx.BITMAP_TYPE_PNG)
+ item = wx.MenuItem(menu, -1, "Has Open Bitmap")
+ item.SetBitmap(bmp)
+ menu.AppendItem(item)
+
+ if True or 'wxMSW' in wx.PlatformInfo:
+ font = wx.SystemSettings.GetFont(
+ wx.SYS_DEFAULT_GUI_FONT)
+ font.SetWeight(wx.BOLD)
+ item = wx.MenuItem(menu, -1, "Has Bold Font")
+ item.SetFont(font)
+ menu.AppendItem(item)
+
+ item = wx.MenuItem(menu, -1, "Has Red Text")
+ item.SetTextColour("red")
+ menu.AppendItem(item)
+
+
+ menu.AppendSeparator()
+ exit = menu.Append(-1, "Exit")
+ self.Bind(wx.EVT_MENU, self.OnExit, exit)
+
+ menuBar = wx.MenuBar()
+ menuBar.Append(menu, "Menu")
+ self.SetMenuBar(menuBar)
+
+
+ def OnExit(self, event):
+ self.Close()
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Find Item Example")
+ p = wx.Panel(self)
+ self.txt = wx.TextCtrl(p, -1, "new item")
+ btn = wx.Button(p, -1, "Add Menu Item")
+ self.Bind(wx.EVT_BUTTON, self.OnAddItem, btn)
+
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(self.txt, 0, wx.ALL, 20)
+ sizer.Add(btn, 0, wx.TOP|wx.RIGHT, 20)
+ p.SetSizer(sizer)
+
+ self.menu = menu = wx.Menu()
+ simple = menu.Append(-1, "Simple menu item")
+ menu.AppendSeparator()
+ exit = menu.Append(-1, "Exit")
+ self.Bind(wx.EVT_MENU, self.OnSimple, simple)
+ self.Bind(wx.EVT_MENU, self.OnExit, exit)
+
+ menuBar = wx.MenuBar()
+ menuBar.Append(menu, "Menu")
+ self.SetMenuBar(menuBar)
+
+
+ def OnSimple(self, event):
+ wx.MessageBox("You selected the simple menu item")
+
+ def OnExit(self, event):
+ self.Close()
+
+ def OnAddItem(self, event):
+ item = self.menu.Append(-1, self.txt.GetValue())
+ self.Bind(wx.EVT_MENU, self.OnNewItemSelected, item)
+
+ def OnNewItemSelected(self, event):
+ item = self.GetMenuBar().FindItemById(event.GetId())
+ text = item.GetText()
+ wx.MessageBox("You selected the '%s' item" % text)
+
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Popup Menu Example")
+ self.panel = p = wx.Panel(self)
+ menu = wx.Menu()
+ exit = menu.Append(-1, "Exit")
+ self.Bind(wx.EVT_MENU, self.OnExit, exit)
+
+ menuBar = wx.MenuBar()
+ menuBar.Append(menu, "Menu")
+ self.SetMenuBar(menuBar)
+
+ wx.StaticText(p, -1,
+ "Right-click on the panel to show a popup menu",
+ (25,25))
+
+ self.popupmenu = wx.Menu()
+ for text in "one two three four five".split():
+ item = self.popupmenu.Append(-1, text)
+ self.Bind(wx.EVT_MENU, self.OnPopupItemSelected, item)
+ p.Bind(wx.EVT_CONTEXT_MENU, self.OnShowPopup)
+
+
+ def OnShowPopup(self, event):
+ pos = event.GetPosition()
+ pos = self.panel.ScreenToClient(pos)
+ self.panel.PopupMenu(self.popupmenu, pos)
+
+
+ def OnPopupItemSelected(self, event):
+ item = self.popupmenu.FindItemById(event.GetId())
+ text = item.GetText()
+ wx.MessageBox("You selected item '%s'" % text)
+
+
+ def OnExit(self, event):
+ self.Close()
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Sub-menu Example")
+ p = wx.Panel(self)
+ menu = wx.Menu()
+
+ submenu = wx.Menu()
+ submenu.Append(-1, "Sub-item 1")
+ submenu.Append(-1, "Sub-item 2")
+ menu.AppendMenu(-1, "Sub-menu", submenu)
+
+ menu.AppendSeparator()
+ exit = menu.Append(-1, "Exit")
+ self.Bind(wx.EVT_MENU, self.OnExit, exit)
+
+ menuBar = wx.MenuBar()
+ menuBar.Append(menu, "Menu")
+ self.SetMenuBar(menuBar)
+
+
+ def OnExit(self, event):
+ self.Close()
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Toggle Items Example")
+ p = wx.Panel(self)
+ menuBar = wx.MenuBar()
+ menu = wx.Menu()
+ exit = menu.Append(-1, "Exit")
+ self.Bind(wx.EVT_MENU, self.OnExit, exit)
+ menuBar.Append(menu, "Menu")
+
+ menu = wx.Menu()
+ menu.AppendCheckItem(-1, "Check Item 1")
+ menu.AppendCheckItem(-1, "Check Item 2")
+ menu.AppendCheckItem(-1, "Check Item 3")
+ menu.AppendSeparator()
+ menu.AppendRadioItem(-1, "Radio Item 1")
+ menu.AppendRadioItem(-1, "Radio Item 2")
+ menu.AppendRadioItem(-1, "Radio Item 3")
+ menuBar.Append(menu, "Toggle Items")
+
+ self.SetMenuBar(menuBar)
+
+ def OnExit(self, event):
+ self.Close()
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+ID_SIMPLE = wx.NewId()
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "UPDATE_UI Menu Example")
+ p = wx.Panel(self)
+ self.btn = wx.Button(p, -1, "Disable Item", (20,20))
+ self.Bind(wx.EVT_BUTTON, self.OnToggleItem, self.btn)
+
+ menu = wx.Menu()
+ menu.Append(ID_SIMPLE, "Simple menu item")
+ self.enabled = True
+ self.Bind(wx.EVT_MENU, self.OnSimple, id=ID_SIMPLE)
+ self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateSimple, id=ID_SIMPLE)
+
+ menu.AppendSeparator()
+ menu.Append(wx.ID_EXIT, "Exit")
+ self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)
+
+ menuBar = wx.MenuBar()
+ menuBar.Append(menu, "Menu")
+ self.SetMenuBar(menuBar)
+
+
+ def OnSimple(self, event):
+ wx.MessageBox("You selected the simple menu item")
+
+ def OnExit(self, event):
+ self.Close()
+
+ def OnToggleItem(self, event):
+ self.btn.SetLabel(
+ (self.enabled and "Enable" or "Disable") + " Item")
+ self.enabled = not self.enabled
+
+ def OnUpdateSimple(self, event):
+ event.Enable(self.enabled)
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Accelerator Example")
+ p = wx.Panel(self)
+ menu = wx.Menu()
+ simple = menu.Append(-1, "Simple &menu item") # with mnemonic
+ accel = menu.Append(-1, "&Accelerated\tCtrl-A") # with accelerator
+
+ menu.AppendSeparator()
+ exit = menu.Append(-1, "E&xit")
+
+ self.Bind(wx.EVT_MENU, self.OnSimple, simple)
+ self.Bind(wx.EVT_MENU, self.OnAccelerated, accel)
+ self.Bind(wx.EVT_MENU, self.OnExit, exit)
+
+ menuBar = wx.MenuBar()
+ menuBar.Append(menu, "&Menu")
+ self.SetMenuBar(menuBar)
+
+ # An alternate way to make accelerators
+ acceltbl = wx.AcceleratorTable( [
+ (wx.ACCEL_CTRL, ord('Q'), exit.GetId())
+ ])
+ self.SetAcceleratorTable(acceltbl)
+
+
+ def OnSimple(self, event):
+ wx.MessageBox("You selected the simple menu item")
+
+ def OnAccelerated(self, event):
+ wx.MessageBox("You selected the accelerated menu item")
+
+
+ def OnExit(self, event):
+ self.Close()
+
+
+if __name__ == "__main__":
+ app = wx.PySimpleApp()
+ frame = MyFrame()
+ frame.Show()
+ app.MainLoop()
+
+
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four five six seven eight nine".split()
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "FlexGridSizer")
+ sizer = wx.FlexGridSizer(rows=3, cols=3, hgap=5, vgap=5)
+ for label in labels:
+ bw = BlockWindow(self, label=label)
+ sizer.Add(bw, 0, 0)
+ center = self.FindWindowByName("five")
+ center.SetMinSize((150,50))
+ self.SetSizer(sizer)
+ self.Fit()
+
+app = wx.PySimpleApp()
+TestFrame().Show()
+app.MainLoop()
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four five six seven eight nine".split()
+
+class GridSizerFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "Basic Grid Sizer")
+ sizer = wx.GridSizer(rows=3, cols=3, hgap=5, vgap=5)
+ for label in labels:
+ bw = BlockWindow(self, label=label)
+ sizer.Add(bw, 0, 0)
+ self.SetSizer(sizer)
+ self.Fit()
+
+app = wx.PySimpleApp()
+GridSizerFrame().Show()
+app.MainLoop()
--- /dev/null
+import wx
+
+class BlockWindow(wx.Panel):
+ def __init__(self, parent, ID=-1, label="",
+ pos=wx.DefaultPosition, size=(100, 25)):
+ wx.Panel.__init__(self, parent, ID, pos, size,
+ wx.RAISED_BORDER, label)
+ self.label = label
+ self.SetBackgroundColour("white")
+ self.SetMinSize(size)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+ def OnPaint(self, evt):
+ sz = self.GetClientSize()
+ dc = wx.PaintDC(self)
+ w,h = dc.GetTextExtent(self.label)
+ dc.SetFont(self.GetFont())
+ dc.DrawText(self.label, (sz.width-w)/2, (sz.height-h)/2)
+
+
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four five six seven eight nine".split()
+flags = {"one": wx.BOTTOM, "two": wx.ALL, "three": wx.TOP,
+ "four": wx.LEFT, "five": wx.ALL, "six": wx.RIGHT,
+ "seven": wx.BOTTOM | wx.TOP, "eight": wx.ALL,
+ "nine": wx.LEFT | wx.RIGHT}
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "GridSizer Borders")
+ sizer = wx.GridSizer(rows=3, cols=3, hgap=5, vgap=5)
+ for label in labels:
+ bw = BlockWindow(self, label=label)
+ flag = flags.get(label, 0)
+ sizer.Add(bw, 0, flag, 10)
+ self.SetSizer(sizer)
+ self.Fit()
+
+app = wx.PySimpleApp()
+TestFrame().Show()
+app.MainLoop()
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four".split()
+
+class TestFrame(wx.Frame):
+ title = "none"
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, self.title)
+ sizer = self.CreateSizerAndWindows()
+ self.SetSizer(sizer)
+ self.Fit()
+
+class VBoxSizerFrame(TestFrame):
+ title = "Vertical BoxSizer"
+
+ def CreateSizerAndWindows(self):
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ for label in labels:
+ bw = BlockWindow(self, label=label, size=(200,30))
+ sizer.Add(bw, flag=wx.EXPAND)
+ return sizer
+
+
+class HBoxSizerFrame(TestFrame):
+ title = "Horizontal BoxSizer"
+
+ def CreateSizerAndWindows(self):
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ for label in labels:
+ bw = BlockWindow(self, label=label, size=(75,30))
+ sizer.Add(bw, flag=wx.EXPAND)
+ return sizer
+
+class VBoxSizerStretchableFrame(TestFrame):
+ title = "Stretchable BoxSizer"
+
+ def CreateSizerAndWindows(self):
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ for label in labels:
+ bw = BlockWindow(self, label=label, size=(200,30))
+ sizer.Add(bw, flag=wx.EXPAND)
+
+ # Add an item that takes all the free space
+ bw = BlockWindow(self, label="gets all free space", size=(200,30))
+ sizer.Add(bw, 1, flag=wx.EXPAND)
+ return sizer
+
+class VBoxSizerMultiProportionalFrame(TestFrame):
+ title = "Proportional BoxSizer"
+
+ def CreateSizerAndWindows(self):
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ for label in labels:
+ bw = BlockWindow(self, label=label, size=(200,30))
+ sizer.Add(bw, flag=wx.EXPAND)
+
+ # Add an item that takes one share of the free space
+ bw = BlockWindow(self,
+ label="gets 1/3 of the free space",
+ size=(200,30))
+ sizer.Add(bw, 1, flag=wx.EXPAND)
+
+ # Add an item that takes 2 shares of the free space
+ bw = BlockWindow(self,
+ label="gets 2/3 of the free space",
+ size=(200,30))
+ sizer.Add(bw, 2, flag=wx.EXPAND)
+ return sizer
+
+app = wx.PySimpleApp()
+frameList = [VBoxSizerFrame, HBoxSizerFrame,
+ VBoxSizerStretchableFrame,
+ VBoxSizerMultiProportionalFrame]
+for klass in frameList:
+ frame = klass()
+ frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four five six seven eight nine".split()
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "GridBagSizer Test")
+ sizer = wx.GridBagSizer(hgap=5, vgap=5)
+ for col in range(3):
+ for row in range(3):
+ bw = BlockWindow(self, label=labels[row*3 + col])
+ sizer.Add(bw, pos=(row,col))
+
+ # add a window that spans several rows
+ bw = BlockWindow(self, label="span 3 rows")
+ sizer.Add(bw, pos=(0,3), span=(3,1), flag=wx.EXPAND)
+
+ # add a window that spans all columns
+ bw = BlockWindow(self, label="span all columns")
+ sizer.Add(bw, pos=(3,0), span=(1,4), flag=wx.EXPAND)
+
+ # make the last row and col be stretchable
+ sizer.AddGrowableCol(3)
+ sizer.AddGrowableRow(3)
+
+ self.SetSizer(sizer)
+ self.Fit()
+
+
+app = wx.PySimpleApp()
+TestFrame().Show()
+
+app.MainLoop()
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four five six seven eight nine".split()
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "GridSizer Test")
+ sizer = wx.GridSizer(rows=3, cols=3, hgap=5, vgap=5)
+ for label in labels:
+ bw = BlockWindow(self, label=label)
+ sizer.Add(bw, 0, 0)
+ center = self.FindWindowByName("five")
+ center.SetMinSize((150,50))
+ self.SetSizer(sizer)
+ self.Fit()
+app = wx.PySimpleApp()
+TestFrame().Show()
+app.MainLoop()
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four five six seven eight nine".split()
+
+class GridSizerFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "Prepend Grid Sizer")
+ sizer = wx.GridSizer(rows=3, cols=3, hgap=5, vgap=5)
+ for label in labels:
+ bw = BlockWindow(self, label=label)
+ sizer.Prepend(bw, 0, 0)
+ self.SetSizer(sizer)
+ self.Fit()
+
+app = wx.PySimpleApp()
+GridSizerFrame().Show()
+app.MainLoop()
--- /dev/null
+import wx
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "Real World Test")
+ panel = wx.Panel(self)
+
+ # First create the controls
+ topLbl = wx.StaticText(panel, -1, "Account Information")
+ topLbl.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
+
+ nameLbl = wx.StaticText(panel, -1, "Name:")
+ name = wx.TextCtrl(panel, -1, "");
+
+ addrLbl = wx.StaticText(panel, -1, "Address:")
+ addr1 = wx.TextCtrl(panel, -1, "");
+ addr2 = wx.TextCtrl(panel, -1, "");
+
+ cstLbl = wx.StaticText(panel, -1, "City, State, Zip:")
+ city = wx.TextCtrl(panel, -1, "", size=(150,-1));
+ state = wx.TextCtrl(panel, -1, "", size=(50,-1));
+ zip = wx.TextCtrl(panel, -1, "", size=(70,-1));
+
+ phoneLbl = wx.StaticText(panel, -1, "Phone:")
+ phone = wx.TextCtrl(panel, -1, "");
+
+ emailLbl = wx.StaticText(panel, -1, "Email:")
+ email = wx.TextCtrl(panel, -1, "");
+
+ saveBtn = wx.Button(panel, -1, "Save")
+ cancelBtn = wx.Button(panel, -1, "Cancel")
+
+ # Now do the layout.
+
+ # mainSizer is the top-level one that manages everything
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ mainSizer.Add(topLbl, 0, wx.ALL, 5)
+ mainSizer.Add(wx.StaticLine(panel), 0,
+ wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
+
+ # addrSizer is a grid that holds all of the address info
+ addrSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
+ addrSizer.AddGrowableCol(1)
+ addrSizer.Add(nameLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(name, 0, wx.EXPAND)
+ addrSizer.Add(addrLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(addr1, 0, wx.EXPAND)
+ addrSizer.Add((10,10)) # some empty space
+ addrSizer.Add(addr2, 0, wx.EXPAND)
+
+ addrSizer.Add(cstLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+
+ # the city, state, zip fields are in a sub-sizer
+ cstSizer = wx.BoxSizer(wx.HORIZONTAL)
+ cstSizer.Add(city, 1)
+ cstSizer.Add(state, 0, wx.LEFT|wx.RIGHT, 5)
+ cstSizer.Add(zip)
+ addrSizer.Add(cstSizer, 0, wx.EXPAND)
+
+ addrSizer.Add(phoneLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(phone, 0, wx.EXPAND)
+ addrSizer.Add(emailLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(email, 0, wx.EXPAND)
+
+ # now add the addrSizer to the mainSizer
+ mainSizer.Add(addrSizer, 0, wx.EXPAND|wx.ALL, 10)
+
+ # The buttons sizer will put them in a row with resizeable
+ # gaps between and on either side of the buttons
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ btnSizer.Add((20,20), 1)
+ btnSizer.Add(saveBtn)
+ btnSizer.Add((20,20), 1)
+ btnSizer.Add(cancelBtn)
+ btnSizer.Add((20,20), 1)
+
+ mainSizer.Add(btnSizer, 0, wx.EXPAND|wx.BOTTOM, 10)
+
+ panel.SetSizer(mainSizer)
+
+ # Fit the frame to the needs of the sizer. The frame will
+ # automatically resize the panel as needed. Also prevent the
+ # frame from getting smaller than this size.
+ mainSizer.Fit(self)
+ mainSizer.SetSizeHints(self)
+
+
+app = wx.PySimpleApp()
+TestFrame().Show()
+app.MainLoop()
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four five six seven eight nine".split()
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "Resizing Flex Grid Sizer")
+ sizer = wx.FlexGridSizer(rows=3, cols=3, hgap=5, vgap=5)
+ for label in labels:
+ bw = BlockWindow(self, label=label)
+ sizer.Add(bw, 0, 0)
+ center = self.FindWindowByName("five")
+ center.SetMinSize((150,50))
+ sizer.AddGrowableCol(0, 1)
+ sizer.AddGrowableCol(1, 2)
+ sizer.AddGrowableCol(2, 1)
+ sizer.AddGrowableRow(0, 1)
+ sizer.AddGrowableRow(1, 5)
+ sizer.AddGrowableRow(2, 1)
+ self.SetSizer(sizer)
+ self.Fit()
+
+app = wx.PySimpleApp()
+TestFrame().Show()
+app.MainLoop()
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four five six seven eight nine".split()
+flags = {"one": wx.ALIGN_BOTTOM, "two": wx.ALIGN_CENTER,
+ "four": wx.ALIGN_RIGHT, "six": wx.EXPAND, "seven": wx.EXPAND,
+ "eight": wx.SHAPED}
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "GridSizer Resizing")
+ sizer = wx.GridSizer(rows=3, cols=3, hgap=5, vgap=5)
+ for label in labels:
+ bw = BlockWindow(self, label=label)
+ flag = flags.get(label, 0)
+ sizer.Add(bw, 0, flag)
+ self.SetSizer(sizer)
+ self.Fit()
+
+app = wx.PySimpleApp()
+TestFrame().Show()
+app.MainLoop()
--- /dev/null
+import wx
+from blockwindow import BlockWindow
+
+labels = "one two three four five six seven eight nine".split()
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "StaticBoxSizer Test")
+ self.panel = wx.Panel(self)
+
+ # make three static boxes with windows positioned inside them
+ box1 = self.MakeStaticBoxSizer("Box 1", labels[0:3])
+ box2 = self.MakeStaticBoxSizer("Box 2", labels[3:6])
+ box3 = self.MakeStaticBoxSizer("Box 3", labels[6:9])
+
+ # We can also use a sizer to manage the placement of other
+ # sizers (and therefore the windows and sub-sizers that they
+ # manage as well.)
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(box1, 0, wx.ALL, 10)
+ sizer.Add(box2, 0, wx.ALL, 10)
+ sizer.Add(box3, 0, wx.ALL, 10)
+
+ self.panel.SetSizer(sizer)
+ sizer.Fit(self)
+
+
+ def MakeStaticBoxSizer(self, boxlabel, itemlabels):
+ # first the static box
+ box = wx.StaticBox(self.panel, -1, boxlabel)
+
+ # then the sizer
+ sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
+
+ # then add items to it like normal
+ for label in itemlabels:
+ bw = BlockWindow(self.panel, label=label)
+ sizer.Add(bw, 0, wx.ALL, 2)
+
+ return sizer
+
+
+app = wx.PySimpleApp()
+TestFrame().Show()
+app.MainLoop()
--- /dev/null
+# This one shows how to draw images on a DC.
+
+import wx
+import random
+random.seed()
+
+class RandomImagePlacementWindow(wx.Window):
+ def __init__(self, parent, image):
+ wx.Window.__init__(self, parent)
+ self.photo = image.ConvertToBitmap()
+
+ # choose some random positions to draw the image at:
+ self.positions = [(10,10)]
+ for x in range(50):
+ x = random.randint(0, 1000)
+ y = random.randint(0, 1000)
+ self.positions.append( (x,y) )
+
+ # Bind the Paint event
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def OnPaint(self, evt):
+ # create and clear the DC
+ dc = wx.PaintDC(self)
+ brush = wx.Brush("sky blue")
+ dc.SetBackground(brush)
+ dc.Clear()
+
+ # draw the image in random locations
+ for x,y in self.positions:
+ dc.DrawBitmap(self.photo, x, y, True)
+
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Loading Images",
+ size=(640,480))
+ img = wx.Image("masked-portrait.png")
+ win = RandomImagePlacementWindow(self, img)
+
+
+app = wx.PySimpleApp()
+frm = TestFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+
+filenames = ["image.bmp", "image.gif", "image.jpg", "image.png" ]
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Loading Images")
+ p = wx.Panel(self)
+
+ fgs = wx.FlexGridSizer(cols=2, hgap=10, vgap=10)
+ for name in filenames:
+ # load the image from the file
+ img1 = wx.Image(name, wx.BITMAP_TYPE_ANY)
+
+ # Scale the original to another wx.Image
+ w = img1.GetWidth()
+ h = img1.GetHeight()
+ img2 = img1.Scale(w/2, h/2)
+
+ # turn them into static bitmap widgets
+ sb1 = wx.StaticBitmap(p, -1, wx.BitmapFromImage(img1))
+ sb2 = wx.StaticBitmap(p, -1, wx.BitmapFromImage(img2))
+
+ # and put them into the sizer
+ fgs.Add(sb1)
+ fgs.Add(sb2)
+
+ p.SetSizerAndFit(fgs)
+ self.Fit()
+
+
+app = wx.PySimpleApp()
+frm = TestFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import math
+import random
+
+class RadarGraph(wx.Window):
+ """
+ A simple radar graph that plots a collection of values in the
+ range of 0-100 onto a polar coordinate system designed to easily
+ show outliers, etc. You might use this kind of graph to monitor
+ some sort of resource allocation metrics, and a quick glance at
+ the graph can tell you when conditions are good (within some
+ accepted tolerance level) or approaching critical levels (total
+ resource consumption).
+ """
+ def __init__(self, parent, title, labels):
+ wx.Window.__init__(self, parent)
+ self.title = title
+ self.labels = labels
+ self.data = [0.0] * len(labels)
+ self.titleFont = wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD)
+ self.labelFont = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL)
+
+ self.InitBuffer()
+
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+
+
+ def OnSize(self, evt):
+ # When the window size changes we need a new buffer.
+ self.InitBuffer()
+
+
+ def OnPaint(self, evt):
+ # This automatically Blits self.buffer to a wx.PaintDC when
+ # the dc is destroyed, and so nothing else needs done.
+ dc = wx.BufferedPaintDC(self, self.buffer)
+
+
+ def InitBuffer(self):
+ # Create the buffer bitmap to be the same size as the window,
+ # then draw our graph to it. Since we use wx.BufferedDC
+ # whatever is drawn to the buffer is also drawn to the window.
+ w, h = self.GetClientSize()
+ self.buffer = wx.EmptyBitmap(w, h)
+ dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
+ self.DrawGraph(dc)
+
+
+ def GetData(self):
+ return self.data
+
+ def SetData(self, newData):
+ assert len(newData) == len(self.data)
+ self.data = newData[:]
+
+ # The data has changed, so update the buffer and the window
+ dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
+ self.DrawGraph(dc)
+
+
+ def PolarToCartesian(self, radius, angle, cx, cy):
+ x = radius * math.cos(math.radians(angle))
+ y = radius * math.sin(math.radians(angle))
+ return (cx+x, cy-y)
+
+
+ def DrawGraph(self, dc):
+ spacer = 10
+ scaledmax = 150.0
+
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ dc.Clear()
+ dw, dh = dc.GetSize()
+
+ # Find out where to draw the title and do it
+ dc.SetFont(self.titleFont)
+ tw, th = dc.GetTextExtent(self.title)
+ dc.DrawText(self.title, (dw-tw)/2, spacer)
+
+ # find the center of the space below the title
+ th = th + 2*spacer
+ cx = dw/2
+ cy = (dh-th)/2 + th
+
+ # calculate a scale factor to use for drawing the graph based
+ # on the minimum available width or height
+ mindim = min(cx, (dh-th)/2)
+ scale = mindim/scaledmax
+
+ # draw the graph axis and "bulls-eye" with rings at scaled 25,
+ # 50, 75 and 100 positions
+ dc.SetPen(wx.Pen("black", 1))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ dc.DrawCircle(cx,cy, 25*scale)
+ dc.DrawCircle(cx,cy, 50*scale)
+ dc.DrawCircle(cx,cy, 75*scale)
+ dc.DrawCircle(cx,cy, 100*scale)
+
+ dc.SetPen(wx.Pen("black", 2))
+ dc.DrawLine(cx-110*scale, cy, cx+110*scale, cy)
+ dc.DrawLine(cx, cy-110*scale, cx, cy+110*scale)
+
+ # Now find the coordinates for each data point, draw the
+ # labels, and find the max data point
+ dc.SetFont(self.labelFont)
+ maxval = 0
+ angle = 0
+ polypoints = []
+ for i, label in enumerate(self.labels):
+ val = self.data[i]
+ point = self.PolarToCartesian(val*scale, angle, cx, cy)
+ polypoints.append(point)
+ x, y = self.PolarToCartesian(125*scale, angle, cx,cy)
+ dc.DrawText(label, x, y)
+ if val > maxval:
+ maxval = val
+ angle = angle + 360/len(self.labels)
+
+ # Set the brush color based on the max value (green is good,
+ # red is bad)
+ c = "forest green"
+ if maxval > 70:
+ c = "yellow"
+ if maxval > 95:
+ c = "red"
+
+ # Finally, draw the plot data as a filled polygon
+ dc.SetBrush(wx.Brush(c))
+ dc.SetPen(wx.Pen("navy", 3))
+ dc.DrawPolygon(polypoints)
+
+
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Double Buffered Drawing",
+ size=(480,480))
+ self.plot = RadarGraph(self, "Sample 'Radar' Plot",
+ ["A", "B", "C", "D", "E", "F", "G", "H"])
+
+ # Set some random initial data values
+ data = []
+ for d in self.plot.GetData():
+ data.append(random.randint(0, 75))
+ self.plot.SetData(data)
+
+ # Create a timer to update the data values
+ self.Bind(wx.EVT_TIMER, self.OnTimeout)
+ self.timer = wx.Timer(self)
+ self.timer.Start(500)
+
+
+ def OnTimeout(self, evt):
+ # simulate the positive or negative growth of each data value
+ data = []
+ for d in self.plot.GetData():
+ val = d + random.uniform(-5, 5)
+ if val < 0:
+ val = 0
+ if val > 110:
+ val = 110
+ data.append(val)
+ self.plot.SetData(data)
+
+
+app = wx.PySimpleApp()
+frm = TestFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+
+# Just some simple data structures for the report mode listctrl examples
+
+columns = ["Request ID", "Summary", "Date", "Submitted By"]
+
+rows = [
+ ("987441", "additions to RTTI?", "2004-07-08 10:22", "g00fy"),
+ ("846368", "wxTextCtrl - disable auto-scrolling", "2003-11-20 21:25", "ryannpcs"),
+ ("846367", "Less flicker when resizing a window", "2003-11-20 21:24", "ryannpcs"),
+ ("846366", "Wishlist - wxDbGetConnection return value", "2003-11-20 21:23", "ryannpcs"),
+ ("846364", "wxPostscriptDC with floating point coordinates", "2003-11-20 21:22", "ryannpcs"),
+ ("846363", "Wishlist - Better wxString Formatting", "2003-11-20 21:22", "ryannpcs"),
+ ("846362", "Wishlist - Crossplatform wxRichText Widget", "2003-11-20 21:20", "ryannpcs"),
+ ("953341", "Support for paper trays when printing", "2004-05-13 08:01", "tonye"),
+ ("952466", "mac menu - Window menu", "2004-05-12 03:19", "pimbuur"),
+ ("928899", "FloatCanvas demo should work with numarray", "2004-04-03 08:30", "glchapman"),
+ ("912714", "wxGrid: Support for Search / Replace", "2004-03-09 05:46", "rclund"),
+ ("901061", "wxComboBox - add small icons as in MSW CComboBoxEx ", "2004-02-20 04:04", "tomash"),
+ ("900768", "Please add more codepages support to your source built", "2004-02-19 15:49", "jsat66"),
+ ("894921", "trigger on event-system creation", "2004-02-11 08:10", "g00fy"),
+ ("869808", "HitTest in wxCheckListBox", "2004-01-03 01:22", "dickkniep"),
+ ("863306", "wxGrid - Thaw/Freeze column/row", "2003-12-19 17:54", "zinit"),
+ ("975435", "wxMenu anchor right position in wxMenuBar", "2004-06-18 08:44", "jmt2715"),
+ ("969811", "wxColourEnumerator", "2004-06-09 11:41", "wyo"),
+ ("959849", "wx.Grid gridlines past max row/col", "2004-05-24 19:39", "dodywijaya"),
+ ("959158", "wxGrid: Arbitrary controls in the grid", "2004-05-23 16:56", "somecoder"),
+ ("953824", "mac menu - Window menu", "2004-05-14 02:06", "pimbuur"),
+ ("863301", "wxTextCtrl - edit mode", "2003-12-19 17:48", "zinit"),
+ ("855902", "virtual window classes", "2003-12-07 12:39", "cursorstar"),
+ ("852379", "wxGrid row/col size limits", "2003-12-01 15:47", "jbrouwers"),
+ ("846375", "wxGraphicsPath", "2003-11-20 21:30", "ryannpcs"),
+ ("846374", "wxToolBar - return tool at position", "2003-11-20 21:29", "ryannpcs"),
+ ("846373", "Scrolling improvements", "2003-11-20 21:28", "ryannpcs"),
+ ("846372", "Hooks for standard remote events", "2003-11-20 21:27", "ryannpcs"),
+ ("846370", "wxDial - dial widget", "2003-11-20 21:27", "ryannpcs"),
+ ("846369", "wxGird - auto-scrolling", "2003-11-20 21:26", "ryannpcs"),
+ ("846361", "Wishlist - wxStaticText that takes fonts, colors, etc.", "2003-11-20 21:19", "ryannpcs"),
+ ("819559", "wxListCtrl column widths in wxLC_ICON mode ", "2003-10-07 13:34", "nwmoriarty"),
+ ("817429", "OS X wheel mouse", "2003-10-03 14:05", "mdcowles"),
+]
+
--- /dev/null
+import wx
+import sys, glob
+
+class DemoFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "wx.ListCtrl in wx.LC_ICON mode",
+ size=(600,400))
+
+ # load some images into an image list
+ il = wx.ImageList(32,32, True)
+ for name in glob.glob("icon??.png"):
+ bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)
+ il_max = il.Add(bmp)
+
+ # create the list control
+ self.list = wx.ListCtrl(self, -1,
+ style=wx.LC_ICON | wx.LC_AUTOARRANGE)
+
+ # assign the image list to it
+ self.list.AssignImageList(il, wx.IMAGE_LIST_NORMAL)
+
+ # create some items for the list
+ for x in range(25):
+ img = x % (il_max+1)
+ self.list.InsertImageStringItem(x,
+ "This is item %02d" % x, img)
+
+app = wx.PySimpleApp()
+frame = DemoFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import sys, glob
+
+class DemoFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "wx.ListCtrl in wx.LC_LIST mode",
+ size=(600,400))
+
+ # load some images into an image list
+ il = wx.ImageList(16,16, True)
+ for name in glob.glob("smicon??.png"):
+ bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)
+ il_max = il.Add(bmp)
+
+ # create the list control
+ self.list = wx.ListCtrl(self, -1, style=wx.LC_LIST)
+
+ # assign the image list to it
+ self.list.AssignImageList(il, wx.IMAGE_LIST_SMALL)
+
+ # create some items for the list
+ for x in range(25):
+ img = x % (il_max+1)
+ self.list.InsertImageStringItem(x,
+ "This is item %02d" % x,
+ img)
+
+
+
+app = wx.PySimpleApp()
+frame = DemoFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import sys, glob, random
+import data
+
+class DemoFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "wx.ListCtrl in wx.LC_REPORT mode",
+ size=(600,400))
+
+ il = wx.ImageList(16,16, True)
+ for name in glob.glob("smicon??.png"):
+ bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)
+ il_max = il.Add(bmp)
+ self.list = wx.ListCtrl(self, -1, style=wx.LC_REPORT)
+ self.list.AssignImageList(il, wx.IMAGE_LIST_SMALL)
+
+ # Add some columns
+ for col, text in enumerate(data.columns):
+ self.list.InsertColumn(col, text)
+
+ # add the rows
+ for item in data.rows:
+ index = self.list.InsertStringItem(sys.maxint, item[0])
+ for col, text in enumerate(item[1:]):
+ self.list.SetStringItem(index, col+1, text)
+
+ # give each item a random image
+ img = random.randint(0, il_max)
+ self.list.SetItemImage(index, img, img)
+
+ # set the width of the columns in various ways
+ self.list.SetColumnWidth(0, 120)
+ self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+ self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
+ self.list.SetColumnWidth(3, wx.LIST_AUTOSIZE_USEHEADER)
+
+
+app = wx.PySimpleApp()
+frame = DemoFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.lib.mixins.listctrl
+import sys, glob, random
+import data
+
+class DemoFrame(wx.Frame, wx.lib.mixins.listctrl.ColumnSorterMixin):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "wx.ListCtrl with ColumnSorterMixin",
+ size=(600,400))
+
+ # load some images into an image list
+ il = wx.ImageList(16,16, True)
+ for name in glob.glob("smicon??.png"):
+ bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)
+ il_max = il.Add(bmp)
+
+ # add some arrows for the column sorter
+ self.up = il.AddWithColourMask(
+ wx.Bitmap("sm_up.bmp", wx.BITMAP_TYPE_BMP), "blue")
+ self.dn = il.AddWithColourMask(
+ wx.Bitmap("sm_down.bmp", wx.BITMAP_TYPE_BMP), "blue")
+
+ # create the list control
+ self.list = wx.ListCtrl(self, -1, style=wx.LC_REPORT)
+
+ # assign the image list to it
+ self.list.AssignImageList(il, wx.IMAGE_LIST_SMALL)
+
+ # Add some columns
+ for col, text in enumerate(data.columns):
+ self.list.InsertColumn(col, text)
+
+ # add the rows
+ self.itemDataMap = {}
+ for item in data.rows:
+ index = self.list.InsertStringItem(sys.maxint, item[0])
+ for col, text in enumerate(item[1:]):
+ self.list.SetStringItem(index, col+1, text)
+
+ # give each item a data value, and map it back to the
+ # item values, for the column sorter
+ self.list.SetItemData(index, index)
+ self.itemDataMap[index] = item
+
+ # give each item a random image
+ img = random.randint(0, il_max)
+ self.list.SetItemImage(index, img, img)
+
+ # set the width of the columns in various ways
+ self.list.SetColumnWidth(0, 120)
+ self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+ self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
+ self.list.SetColumnWidth(3, wx.LIST_AUTOSIZE_USEHEADER)
+
+ # initialize the column sorter
+ wx.lib.mixins.listctrl.ColumnSorterMixin.__init__(self,
+ len(data.columns))
+
+ def GetListCtrl(self):
+ return self.list
+
+ def GetSortImages(self):
+ return (self.dn, self.up)
+
+
+app = wx.PySimpleApp()
+frame = DemoFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import sys, glob, random
+import data
+
+class DemoFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Other wx.ListCtrl Stuff",
+ size=(700,500))
+ self.list = None
+ self.editable = False
+ self.MakeMenu()
+ self.MakeListCtrl()
+
+
+ def MakeListCtrl(self, otherflags=0):
+ # if we already have a listctrl then get rid of it
+ if self.list:
+ self.list.Destroy()
+
+ if self.editable:
+ otherflags |= wx.LC_EDIT_LABELS
+
+ # load some images into an image list
+ il = wx.ImageList(16,16, True)
+ for name in glob.glob("smicon??.png"):
+ bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)
+ il_max = il.Add(bmp)
+
+ # create the list control
+ self.list = wx.ListCtrl(self, -1, style=wx.LC_REPORT|otherflags)
+
+ # assign the image list to it
+ self.list.AssignImageList(il, wx.IMAGE_LIST_SMALL)
+
+ # Add some columns
+ for col, text in enumerate(data.columns):
+ self.list.InsertColumn(col, text)
+
+ # add the rows
+ for row, item in enumerate(data.rows):
+ index = self.list.InsertStringItem(sys.maxint, item[0])
+ for col, text in enumerate(item[1:]):
+ self.list.SetStringItem(index, col+1, text)
+
+ # give each item a random image
+ img = random.randint(0, il_max)
+ self.list.SetItemImage(index, img, img)
+
+ # set the data value for each item to be its position in
+ # the data list
+ self.list.SetItemData(index, row)
+
+
+ # set the width of the columns in various ways
+ self.list.SetColumnWidth(0, 120)
+ self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+ self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
+ self.list.SetColumnWidth(3, wx.LIST_AUTOSIZE_USEHEADER)
+
+ # bind some interesting events
+ self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self.list)
+ self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected, self.list)
+ self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, self.list)
+
+ # in case we are recreating the list tickle the frame a bit so
+ # it will redo the layout
+ self.SendSizeEvent()
+
+
+ def MakeMenu(self):
+ mbar = wx.MenuBar()
+ menu = wx.Menu()
+ item = menu.Append(-1, "E&xit\tAlt-X")
+ self.Bind(wx.EVT_MENU, self.OnExit, item)
+ mbar.Append(menu, "&File")
+
+ menu = wx.Menu()
+ item = menu.Append(-1, "Sort ascending")
+ self.Bind(wx.EVT_MENU, self.OnSortAscending, item)
+ item = menu.Append(-1, "Sort descending")
+ self.Bind(wx.EVT_MENU, self.OnSortDescending, item)
+ item = menu.Append(-1, "Sort by submitter")
+ self.Bind(wx.EVT_MENU, self.OnSortBySubmitter, item)
+
+ menu.AppendSeparator()
+ item = menu.Append(-1, "Show selected")
+ self.Bind(wx.EVT_MENU, self.OnShowSelected, item)
+ item = menu.Append(-1, "Select all")
+ self.Bind(wx.EVT_MENU, self.OnSelectAll, item)
+ item = menu.Append(-1, "Select none")
+ self.Bind(wx.EVT_MENU, self.OnSelectNone, item)
+
+ menu.AppendSeparator()
+ item = menu.Append(-1, "Set item text colour")
+ self.Bind(wx.EVT_MENU, self.OnSetTextColour, item)
+ item = menu.Append(-1, "Set item background colour")
+ self.Bind(wx.EVT_MENU, self.OnSetBGColour, item)
+
+ menu.AppendSeparator()
+ item = menu.Append(-1, "Enable item editing", kind=wx.ITEM_CHECK)
+ self.Bind(wx.EVT_MENU, self.OnEnableEditing, item)
+ item = menu.Append(-1, "Edit current item")
+ self.Bind(wx.EVT_MENU, self.OnEditItem, item)
+ mbar.Append(menu, "&Demo")
+
+ self.SetMenuBar(mbar)
+
+
+
+ def OnExit(self, evt):
+ self.Close()
+
+
+ def OnItemSelected(self, evt):
+ item = evt.GetItem()
+ print "Item selected:", item.GetText()
+
+ def OnItemDeselected(self, evt):
+ item = evt.GetItem()
+ print "Item deselected:", item.GetText()
+
+ def OnItemActivated(self, evt):
+ item = evt.GetItem()
+ print "Item activated:", item.GetText()
+
+ def OnSortAscending(self, evt):
+ # recreate the listctrl with a sort style
+ self.MakeListCtrl(wx.LC_SORT_ASCENDING)
+
+ def OnSortDescending(self, evt):
+ # recreate the listctrl with a sort style
+ self.MakeListCtrl(wx.LC_SORT_DESCENDING)
+
+ def OnSortBySubmitter(self, evt):
+ def compare_func(row1, row2):
+ # compare the values in the 4th col of the data
+ val1 = data.rows[row1][3]
+ val2 = data.rows[row2][3]
+ if val1 < val2: return -1
+ if val1 > val2: return 1
+ return 0
+
+ self.list.SortItems(compare_func)
+
+
+
+ def OnShowSelected(self, evt):
+ print "These items are selected:"
+ index = self.list.GetFirstSelected()
+ if index == -1:
+ print "\tNone"
+ return
+ while index != -1:
+ item = self.list.GetItem(index)
+ print "\t%s" % item.GetText()
+ index = self.list.GetNextSelected(index)
+
+ def OnSelectAll(self, evt):
+ for index in range(self.list.GetItemCount()):
+ self.list.Select(index, True)
+
+ def OnSelectNone(self, evt):
+ index = self.list.GetFirstSelected()
+ while index != -1:
+ self.list.Select(index, False)
+ index = self.list.GetNextSelected(index)
+
+
+ def OnSetTextColour(self, evt):
+ dlg = wx.ColourDialog(self)
+ if dlg.ShowModal() == wx.ID_OK:
+ colour = dlg.GetColourData().GetColour()
+ index = self.list.GetFirstSelected()
+ while index != -1:
+ self.list.SetItemTextColour(index, colour)
+ index = self.list.GetNextSelected(index)
+ dlg.Destroy()
+
+ def OnSetBGColour(self, evt):
+ dlg = wx.ColourDialog(self)
+ if dlg.ShowModal() == wx.ID_OK:
+ colour = dlg.GetColourData().GetColour()
+ index = self.list.GetFirstSelected()
+ while index != -1:
+ self.list.SetItemBackgroundColour(index, colour)
+ index = self.list.GetNextSelected(index)
+ dlg.Destroy()
+
+
+ def OnEnableEditing(self, evt):
+ self.editable = evt.IsChecked()
+ self.MakeListCtrl()
+
+ def OnEditItem(self, evt):
+ index = self.list.GetFirstSelected()
+ if index != -1:
+ self.list.EditLabel(index)
+
+
+class DemoApp(wx.App):
+ def OnInit(self):
+ frame = DemoFrame()
+ self.SetTopWindow(frame)
+ print "Program output appears here..."
+ frame.Show()
+ return True
+
+app = DemoApp(redirect=True)
+app.MainLoop()
--- /dev/null
+import wx
+import sys, glob, random
+import data
+
+class DataSource:
+ """
+ A simple data source class that just uses our sample data items.
+ A real data source class would manage fetching items from a
+ database or similar.
+ """
+ def GetColumnHeaders(self):
+ return data.columns
+
+ def GetCount(self):
+ return len(data.rows)
+
+ def GetItem(self, index):
+ return data.rows[index]
+
+ def UpdateCache(self, start, end):
+ pass
+
+
+class VirtualListCtrl(wx.ListCtrl):
+ """
+ A generic virtual listctrl that fetches data from a DataSource.
+ """
+ def __init__(self, parent, dataSource):
+ wx.ListCtrl.__init__(self, parent,
+ style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VIRTUAL)
+ self.dataSource = dataSource
+ self.Bind(wx.EVT_LIST_CACHE_HINT, self.DoCacheItems)
+ self.SetItemCount(dataSource.GetCount())
+
+ columns = dataSource.GetColumnHeaders()
+ for col, text in enumerate(columns):
+ self.InsertColumn(col, text)
+
+
+ def DoCacheItems(self, evt):
+ self.dataSource.UpdateCache(
+ evt.GetCacheFrom(), evt.GetCacheTo())
+
+ def OnGetItemText(self, item, col):
+ data = self.dataSource.GetItem(item)
+ return data[col]
+
+ def OnGetItemAttr(self, item): return None
+ def OnGetItemImage(self, item): return -1
+
+
+
+class DemoFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "Virtual wx.ListCtrl",
+ size=(600,400))
+
+ self.list = VirtualListCtrl(self, DataSource())
+
+
+
+app = wx.PySimpleApp()
+frame = DemoFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import sys, glob
+
+class DemoFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1,
+ "wx.ListCtrl in wx.LC_SMALL_ICON mode",
+ size=(600,400))
+
+ # load some images into an image list
+ il = wx.ImageList(16,16, True)
+ for name in glob.glob("smicon??.png"):
+ bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG)
+ il_max = il.Add(bmp)
+
+ # create the list control
+ self.list = wx.ListCtrl(self, -1,
+ style=wx.LC_SMALL_ICON
+ | wx.LC_AUTOARRANGE
+ )
+
+ # assign the image list to it
+ self.list.AssignImageList(il, wx.IMAGE_LIST_SMALL)
+
+ # create some items for the list
+ for x in range(25):
+ img = x % (il_max+1)
+ self.list.InsertImageStringItem(x,
+ "This is item %02d" % x,
+ img)
+
+app = wx.PySimpleApp()
+frame = DemoFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.grid
+
+class TestFrame(wx.Frame):
+
+
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Grid Attributes",
+ size=(600,300))
+ grid = wx.grid.Grid(self)
+ grid.CreateGrid(10,6)
+ for row in range(10):
+ for col in range(6):
+ grid.SetCellValue(row, col, "(%s,%s)" % (row, col))
+
+ grid.SetCellTextColour(1, 1, "red")
+ grid.SetCellFont(1,1, wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
+ grid.SetCellBackgroundColour(2, 2, "light blue")
+
+ attr = wx.grid.GridCellAttr()
+ attr.SetTextColour("navyblue")
+ attr.SetBackgroundColour("pink")
+ attr.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
+
+ grid.SetAttr(4, 0, attr)
+ grid.SetAttr(5, 1, attr)
+ grid.SetRowAttr(8, attr)
+
+
+app = wx.PySimpleApp()
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.grid
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Simple Grid",
+ size=(640,480))
+ grid = wx.grid.Grid(self)
+ grid.CreateGrid(50,50)
+ for row in range(20):
+ for col in range(6):
+ grid.SetCellValue(row, col,
+ "cell (%d,%d)" % (row, col))
+
+app = wx.PySimpleApp()
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.grid
+import string
+
+class UpCaseCellEditor(wx.grid.PyGridCellEditor):
+ def __init__(self):
+ wx.grid.PyGridCellEditor.__init__(self)
+
+ def Create(self, parent, id, evtHandler):
+ """
+ Called to create the control, which must derive from wx.Control.
+ *Must Override*
+ """
+ self._tc = wx.TextCtrl(parent, id, "")
+ self._tc.SetInsertionPoint(0)
+ self.SetControl(self._tc)
+
+ if evtHandler:
+ self._tc.PushEventHandler(evtHandler)
+
+ self._tc.Bind(wx.EVT_CHAR, self.OnChar)
+
+ def SetSize(self, rect):
+ """
+ Called to position/size the edit control within the cell rectangle.
+ If you don't fill the cell (the rect) then be sure to override
+ PaintBackground and do something meaningful there.
+ """
+ self._tc.SetDimensions(rect.x, rect.y, rect.width+2, rect.height+2,
+ wx.SIZE_ALLOW_MINUS_ONE)
+
+ def BeginEdit(self, row, col, grid):
+ """
+ Fetch the value from the table and prepare the edit control
+ to begin editing. Set the focus to the edit control.
+ *Must Override*
+ """
+ self.startValue = grid.GetTable().GetValue(row, col)
+ self._tc.SetValue(self.startValue)
+ self._tc.SetInsertionPointEnd()
+ self._tc.SetFocus()
+ self._tc.SetSelection(0, self._tc.GetLastPosition())
+
+ def EndEdit(self, row, col, grid):
+ """
+ Complete the editing of the current cell. Returns True if the value
+ has changed. If necessary, the control may be destroyed.
+ *Must Override*
+ """
+ changed = False
+
+ val = self._tc.GetValue()
+
+ if val != self.startValue:
+ changed = True
+ grid.GetTable().SetValue(row, col, val) # update the table
+
+ self.startValue = ''
+ self._tc.SetValue('')
+ return changed
+
+ def Reset(self):
+ """
+ Reset the value in the control back to its starting value.
+ *Must Override*
+ """
+ self._tc.SetValue(self.startValue)
+ self._tc.SetInsertionPointEnd()
+
+ def Clone(self):
+ """
+ Create a new object which is the copy of this one
+ *Must Override*
+ """
+ return UpCaseCellEditor()
+
+ def StartingKey(self, evt):
+ """
+ If the editor is enabled by pressing keys on the grid, this will be
+ called to let the editor do something about that first key if desired.
+ """
+ self.OnChar(evt)
+ if evt.GetSkipped():
+ self._tc.EmulateKeyPress(evt)
+
+ def OnChar(self, evt):
+ key = evt.GetKeyCode()
+ if key > 255:
+ evt.Skip()
+ return
+ char = chr(key)
+ if char in string.letters:
+ char = char.upper()
+ self._tc.WriteText(char)
+ else:
+ evt.Skip()
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Grid Editor",
+ size=(640,480))
+
+ grid = wx.grid.Grid(self)
+ grid.CreateGrid(50,50)
+ grid.SetDefaultEditor(UpCaseCellEditor())
+
+
+app = wx.PySimpleApp()
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.grid
+
+class TestFrame(wx.Frame):
+
+ rowLabels = ["uno", "dos", "tres", "quatro", "cinco"]
+ colLabels = ["homer", "marge", "bart", "lisa", "maggie"]
+
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Grid Headers",
+ size=(500,200))
+ grid = wx.grid.Grid(self)
+ grid.CreateGrid(5,5)
+ for row in range(5):
+ grid.SetRowLabelValue(row, self.rowLabels[row])
+ grid.SetColLabelValue(row, self.colLabels[row])
+ for col in range(5):
+ grid.SetCellValue(row, col,
+ "(%s,%s)" % (self.rowLabels[row], self.colLabels[col]))
+
+app = wx.PySimpleApp()
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.grid
+import random
+
+class RandomBackgroundRenderer(wx.grid.PyGridCellRenderer):
+ def __init__(self):
+ wx.grid.PyGridCellRenderer.__init__(self)
+
+
+ def Draw(self, grid, attr, dc, rect, row, col, isSelected):
+ text = grid.GetCellValue(row, col)
+ hAlign, vAlign = attr.GetAlignment()
+ dc.SetFont( attr.GetFont() )
+ if isSelected:
+ bg = grid.GetSelectionBackground()
+ fg = grid.GetSelectionForeground()
+ else:
+ bg = random.choice(["pink", "sky blue", "cyan", "yellow", "plum"])
+ fg = attr.GetTextColour()
+
+ dc.SetTextBackground(bg)
+ dc.SetTextForeground(fg)
+ dc.SetBrush(wx.Brush(bg, wx.SOLID))
+ dc.SetPen(wx.TRANSPARENT_PEN)
+ dc.DrawRectangleRect(rect)
+ grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign)
+
+
+ def GetBestSize(self, grid, attr, dc, row, col):
+ text = grid.GetCellValue(row, col)
+ dc.SetFont(attr.GetFont())
+ w, h = dc.GetTextExtent(text)
+ return wx.Size(w, h)
+
+ def Clone(self):
+ return RandomBackgroundRenderer()
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Grid Renderer",
+ size=(640,480))
+
+ grid = wx.grid.Grid(self)
+ grid.CreateGrid(50,50)
+
+ # Set this custom renderer just for row 4
+ attr = wx.grid.GridCellAttr()
+ attr.SetRenderer(RandomBackgroundRenderer())
+ grid.SetRowAttr(4, attr)
+
+ for row in range(10):
+ for col in range(10):
+ grid.SetCellValue(row, col,
+ "cell (%d,%d)" % (row, col))
+
+app = wx.PySimpleApp()
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.grid
+
+class TestFrame(wx.Frame):
+
+
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Grid Sizes",
+ size=(600,300))
+ grid = wx.grid.Grid(self)
+ grid.CreateGrid(5,5)
+ for row in range(5):
+ for col in range(5):
+ grid.SetCellValue(row, col, "(%s,%s)" % (row, col))
+
+ grid.SetCellSize(2, 2, 2, 3)
+ grid.SetColSize(1, 125)
+ grid.SetRowSize(1, 100)
+
+app = wx.PySimpleApp()
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.grid
+
+class TestTable(wx.grid.PyGridTableBase):
+ def __init__(self):
+ wx.grid.PyGridTableBase.__init__(self)
+ self.data = { (1,1) : "Here",
+ (2,2) : "is",
+ (3,3) : "some",
+ (4,4) : "data",
+ }
+
+ self.odd=wx.grid.GridCellAttr()
+ self.odd.SetBackgroundColour("sky blue")
+ self.odd.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
+
+ self.even=wx.grid.GridCellAttr()
+ self.even.SetBackgroundColour("sea green")
+ self.even.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
+
+
+ # these five are the required methods
+ def GetNumberRows(self):
+ return 50
+
+ def GetNumberCols(self):
+ return 50
+
+ def IsEmptyCell(self, row, col):
+ return self.data.get((row, col)) is not None
+
+ def GetValue(self, row, col):
+ value = self.data.get((row, col))
+ if value is not None:
+ return value
+ else:
+ return ''
+
+ def SetValue(self, row, col, value):
+ self.data[(row,col)] = value
+
+
+ # the table can also provide the attribute for each cell
+ def GetAttr(self, row, col, kind):
+ attr = [self.even, self.odd][row % 2]
+ attr.IncRef()
+ return attr
+
+
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Grid Table",
+ size=(640,480))
+
+ grid = wx.grid.Grid(self)
+
+ table = TestTable()
+ grid.SetTable(table, True)
+
+
+app = wx.PySimpleApp()
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.grid
+
+class TestTable(wx.grid.PyGridTableBase):
+ def __init__(self):
+ wx.grid.PyGridTableBase.__init__(self)
+ self.rowLabels = ["uno", "dos", "tres", "quatro", "cinco"]
+ self.colLabels = ["homer", "marge", "bart", "lisa", "maggie"]
+
+ def GetNumberRows(self):
+ return 5
+
+ def GetNumberCols(self):
+ return 5
+
+ def IsEmptyCell(self, row, col):
+ return False
+
+ def GetValue(self, row, col):
+ return "(%s,%s)" % (self.rowLabels[row], self.colLabels[col])
+
+ def SetValue(self, row, col, value):
+ pass
+
+ def GetColLabelValue(self, col):
+ return self.colLabels[col]
+
+ def GetRowLabelValue(self, row):
+ return self.rowLabels[row]
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Grid Table",
+ size=(500,200))
+ grid = wx.grid.Grid(self)
+ table = TestTable()
+ grid.SetTable(table, True)
+
+app = wx.PySimpleApp()
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.grid
+
+class TestTable(wx.grid.PyGridTableBase):
+ def __init__(self):
+ wx.grid.PyGridTableBase.__init__(self)
+ self.data = { (1,1) : "Here",
+ (2,2) : "is",
+ (3,3) : "some",
+ (4,4) : "data",
+ }
+
+ self.odd=wx.grid.GridCellAttr()
+ self.odd.SetBackgroundColour("sky blue")
+ self.odd.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
+
+ self.even=wx.grid.GridCellAttr()
+ self.even.SetBackgroundColour("sea green")
+ self.even.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
+
+
+ # these five are the required methods
+ def GetNumberRows(self):
+ return 50
+
+ def GetNumberCols(self):
+ return 50
+
+ def IsEmptyCell(self, row, col):
+ return self.data.get((row, col)) is not None
+
+ def GetValue(self, row, col):
+ value = self.data.get((row, col))
+ if value is not None:
+ return value
+ else:
+ return ''
+
+ def SetValue(self, row, col, value):
+ self.data[(row,col)] = value
+
+
+ # the table can also provide the attribute for each cell
+ def GetAttr(self, row, col, kind):
+ attr = [self.even, self.odd][row % 2]
+ attr.IncRef()
+ return attr
+
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Grid Table",
+ size=(640,480))
+
+ grid = wx.grid.Grid(self)
+
+ table = TestTable()
+ grid.SetTable(table, True)
+
+
+app = wx.PySimpleApp()
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
--- /dev/null
+
+# Some sample data for the treectrl samples
+
+tree = [
+ "wx.AcceleratorTable",
+ "wx.BrushList",
+ "wx.BusyInfo",
+ "wx.Clipboard",
+ "wx.Colour",
+ "wx.ColourData",
+ "wx.ColourDatabase",
+ "wx.ContextHelp",
+ ["wx.DC", [
+ "wx.ClientDC",
+ ["wx.MemoryDC", [
+ "wx.lib.colourchooser.canvas.BitmapBuffer",
+ ["wx.BufferedDC", [
+ "wx.BufferedPaintDC", ]]]],
+
+ "wx.MetaFileDC",
+ "wx.MirrorDC",
+ "wx.PaintDC",
+ "wx.PostScriptDC",
+ "wx.PrinterDC",
+ "wx.ScreenDC",
+ "wx.WindowDC",]],
+ "wx.DragImage",
+ "wx.Effects",
+ "wx.EncodingConverter",
+ ["wx.Event", [
+ "wx.ActivateEvent",
+ "wx.CalculateLayoutEvent",
+ "wx.CloseEvent",
+ ["wx.CommandEvent", [
+ "wx.calendar.CalendarEvent",
+ "wx.ChildFocusEvent",
+ "wx.ContextMenuEvent",
+ "wx.gizmos.DynamicSashSplitEvent",
+ "wx.gizmos.DynamicSashUnifyEvent",
+ "wx.FindDialogEvent",
+ "wx.grid.GridEditorCreatedEvent",
+ "wx.HelpEvent",
+ ["wx.NotifyEvent",[
+ ["wx.BookCtrlEvent", [
+ "wx.ListbookEvent",
+ "wx.NotebookEvent ",]],
+ "wx.grid.GridEvent",
+ "wx.grid.GridRangeSelectEvent",
+ "wx.grid.GridSizeEvent",
+ "wx.ListEvent",
+ "wx.SpinEvent",
+ "wx.SplitterEvent",
+ "wx.TreeEvent",
+ "wx.wizard.WizardEvent ",]],
+ ["wx.PyCommandEvent", [
+ "wx.lib.colourselect.ColourSelectEvent",
+ "wx.lib.buttons.GenButtonEvent",
+ "wx.lib.gridmovers.GridColMoveEvent",
+ "wx.lib.gridmovers.GridRowMoveEvent",
+ "wx.lib.intctrl.IntUpdatedEvent",
+ "wx.lib.masked.combobox.MaskedComboBoxSelectEvent",
+ "wx.lib.masked.numctrl.NumberUpdatedEvent",
+ "wx.lib.masked.timectrl.TimeUpdatedEvent ",]],
+ "wx.SashEvent",
+ "wx.ScrollEvent",
+ "wx.stc.StyledTextEvent",
+ "wx.TextUrlEvent",
+ "wx.UpdateUIEvent",
+ "wx.WindowCreateEvent",
+ "wx.WindowDestroyEvent ",]],
+ "wx.DisplayChangedEvent",
+ "wx.DropFilesEvent",
+ "wx.EraseEvent",
+ "wx.FocusEvent",
+ "wx.IconizeEvent",
+ "wx.IdleEvent",
+ "wx.InitDialogEvent",
+ "wx.JoystickEvent",
+ "wx.KeyEvent",
+ "wx.MaximizeEvent",
+ "wx.MenuEvent",
+ "wx.MouseCaptureChangedEvent",
+ "wx.MouseEvent",
+ "wx.MoveEvent",
+ "wx.NavigationKeyEvent",
+ "wx.NcPaintEvent",
+ "wx.PaintEvent",
+ "wx.PaletteChangedEvent",
+ "wx.ProcessEvent",
+ ["wx.PyEvent", [
+ "wx.lib.throbber.UpdateThrobberEvent ",]],
+ "wx.QueryLayoutInfoEvent",
+ "wx.QueryNewPaletteEvent",
+ "wx.ScrollWinEvent",
+ "wx.SetCursorEvent",
+ "wx.ShowEvent",
+ "wx.SizeEvent",
+ "wx.SysColourChangedEvent",
+ "wx.TaskBarIconEvent",
+ "wx.TimerEvent ",]],
+ ["wx.EvtHandler", [
+ "wx.lib.gridmovers.GridColMover",
+ "wx.lib.gridmovers.GridRowMover",
+ "wx.html.HtmlHelpController",
+ "wx.Menu",
+ "wx.Process",
+ ["wx.PyApp", [
+ ["wx.App", [
+ "wx.py.PyAlaCarte.App",
+ "wx.py.PyAlaMode.App",
+ "wx.py.PyAlaModeTest.App",
+ "wx.py.PyCrust.App",
+ "wx.py.PyShell.App",
+ ["wx.py.filling.App", [
+ "wx.py.PyFilling.App ",]],
+ ["wx.PySimpleApp", [
+ "wx.lib.masked.maskededit.test",]],
+ "wx.PyWidgetTester ",]]]],
+
+ "wx.TaskBarIcon",
+ ["wx.Timer", [
+ "wx.PyTimer ",]],
+ ["wx.Validator", [
+ ["wx.PyValidator",[
+ "wx.lib.intctrl.IntValidator",]]]],
+ ["wx.Window", [
+ ["wx.lib.colourchooser.canvas.Canvas", [
+ "wx.lib.colourchooser.pycolourslider.PyColourSlider",
+ "wx.lib.colourchooser.pypalette.PyPalette",]],
+ "wx.lib.gridmovers.ColDragWindow",
+ ["wx.Control",[
+ ["wx.BookCtrl", [
+ "wx.Listbook",
+ ["wx.Notebook",[
+ "wx.py.editor.EditorNotebook",
+ "wx.py.editor.EditorShellNotebook",]] ]],
+ ["wx.Button", [
+ ["wx.BitmapButton",[
+ "wx.lib.colourselect.ColourSelect",
+ "wx.ContextHelpButton",
+ "wx.lib.foldmenu.FoldOutMenu ",]] ]],
+ "wx.calendar.CalendarCtrl",
+ "wx.CheckBox",
+ ["wx.ComboBox",[
+ ["wx.lib.masked.combobox.BaseMaskedComboBox", [
+ "wx.lib.masked.combobox.ComboBox",
+ "wx.lib.masked.combobox.PreMaskedComboBox",]] ]],
+ ["wx.ControlWithItems", [
+ ["wx.Choice",[
+ "wx.DirFilterListCtrl ",]],
+ "wx.ListBox",
+ "wx.CheckListBox ",]],
+ "wx.Gauge",
+ "wx.GenericDirCtrl",
+ "wx.gizmos.LEDNumberCtrl",
+ ["wx.ListCtrl",[
+ "wx.ListView ",]],
+ ["wx.PyControl",[
+ "wx.lib.calendar.Calendar",
+ ["wx.lib.buttons.GenButton",[
+ ["wx.lib.buttons.GenBitmapButton",[
+ ["wx.lib.buttons.GenBitmapTextButton",[
+ "wx.lib.buttons.GenBitmapTextToggleButton ",]],
+ "wx.lib.buttons.GenBitmapToggleButton ",]],
+ "wx.lib.buttons.GenToggleButton ",]],
+ "wx.lib.statbmp.GenStaticBitmap",
+ "wx.lib.stattext.GenStaticText",
+ "wx.lib.popupctl.PopButton",
+ "wx.lib.popupctl.PopupControl",
+ "wx.lib.ticker.Ticker ",]],
+ "wx.RadioBox",
+ "wx.RadioButton",
+ "wx.ScrollBar",
+ "wx.Slider",
+ "wx.SpinButton",
+ "wx.SpinCtrl",
+ ["wx.StaticBitmap",[
+ "wx.lib.fancytext.StaticFancyText ",]],
+ "wx.StaticBox",
+ "wx.StaticLine",
+ "wx.StaticText",
+ ["wx.stc.StyledTextCtrl",[
+ ["wx.py.editwindow.EditWindow",[
+ "wx.py.crust.Display",
+ "wx.py.editor.EditWindow",
+ "wx.py.filling.FillingText",
+ "wx.py.shell.Shell",]],
+ "wx.lib.pyshell.PyShellWindow ",]],
+ ["wx.TextCtrl", [
+ ["wx.lib.masked.textctrl.BaseMaskedTextCtrl",[
+ "wx.lib.masked.ipaddrctrl.IpAddrCtrl",
+ "wx.lib.masked.numctrl.NumCtrl",
+ "wx.lib.masked.textctrl.PreMaskedTextCtrl",
+ "wx.lib.masked.textctrl.TextCtrl",
+ "wx.lib.masked.timectrl.TimeCtrl ",]],
+ "wx.py.crust.Calltip",
+ "wx.lib.sheet.CTextCellEditor",
+ "wx.py.crust.DispatcherListing",
+ "wx.lib.intctrl.IntCtrl",
+ "wx.lib.rightalign.RightTextCtrl",
+ "wx.py.crust.SessionListing",]],
+ "wx.ToggleButton",
+ "wx.ToolBar",
+ ["wx.TreeCtrl",[
+ "wx.py.filling.FillingTree",
+ "wx.gizmos.RemotelyScrolledTreeCtrl ",]],
+ "wx.gizmos.TreeListCtrl ",]],
+ "wx.gizmos.DynamicSashWindow",
+ "wx.lib.multisash.EmptyChild",
+ "wx.glcanvas.GLCanvas",
+ "wx.lib.imagebrowser.ImageView",
+ "wx.MDIClientWindow",
+ "wx.MenuBar",
+ "wx.lib.multisash.MultiClient",
+ "wx.lib.multisash.MultiCloser",
+ "wx.lib.multisash.MultiCreator",
+ "wx.lib.multisash.MultiSash",
+ "wx.lib.multisash.MultiSizer",
+ "wx.lib.multisash.MultiSplit",
+ "wx.lib.multisash.MultiViewLeaf",
+ ["wx.Panel",[
+ "wx.gizmos.EditableListBox",
+ ["wx.lib.filebrowsebutton.FileBrowseButton",[
+ "wx.lib.filebrowsebutton.DirBrowseButton",
+ "wx.lib.filebrowsebutton.FileBrowseButtonWithHistory",]],
+ "wx.lib.floatcanvas.FloatCanvas.FloatCanvas",
+ "wx.lib.floatcanvas.NavCanvas.NavCanvas",
+ "wx.NotebookPage",
+ ["wx.PreviewControlBar",[
+ "wx.PyPreviewControlBar ",]],
+ "wx.lib.colourchooser.pycolourbox.PyColourBox",
+ "wx.lib.colourchooser.pycolourchooser.PyColourChooser",
+ ["wx.PyPanel",[
+ "wx.lib.throbber.Throbber",]],
+ "wx.lib.shell.PyShell",
+ "wx.lib.shell.PyShellInput",
+ "wx.lib.shell.PyShellOutput",
+ ["wx.ScrolledWindow",[
+ "wx.lib.editor.editor.Editor",
+ ["wx.grid.Grid",[
+ "wx.lib.sheet.CSheet ",]],
+ ["wx.html.HtmlWindow",[
+ "wx.lib.ClickableHtmlWindow.PyClickableHtmlWindow",]],
+ "wx.PreviewCanvas",
+ "wx.lib.printout.PrintTableDraw",
+ ["wx.PyScrolledWindow",[
+ "wx.lib.scrolledpanel.ScrolledPanel",]],
+ "wx.lib.ogl.ShapeCanvas",
+ "wx.gizmos.SplitterScrolledWindow ",]],
+ ["wx.VScrolledWindow",[
+ ["wx.VListBox", [
+ "wx.HtmlListBox ",]] ]],
+ ["wx.wizard.WizardPage", [
+ "wx.wizard.PyWizardPage",
+ "wx.wizard.WizardPageSimple ",]],
+ "wx.lib.plot.PlotCanvas",
+ "wx.lib.wxPlotCanvas.PlotCanvas",
+ ["wx.PopupWindow",[
+ "wx.lib.foldmenu.FoldOutWindow",
+ ["wx.PopupTransientWindow",[
+ "wx.TipWindow ",]] ]],
+ ["wx.PyWindow", [
+ "wx.lib.analogclock.AnalogClockWindow",]],
+ "wx.lib.gridmovers.RowDragWindow",
+ ["wx.SashWindow",[
+ "wx.SashLayoutWindow ",]],
+ "wx.SplashScreenWindow",
+ ["wx.SplitterWindow",[
+ "wx.py.crust.Crust",
+ "wx.py.filling.Filling",
+ "wx.gizmos.ThinSplitterWindow ",]],
+ "wx.StatusBar",
+ ["wx.TopLevelWindow",[
+ ["wx.Dialog",[
+ "wx.lib.calendar.CalenDlg",
+ "wx.ColourDialog",
+ "wx.DirDialog",
+ "wx.FileDialog",
+ "wx.FindReplaceDialog",
+ "wx.FontDialog",
+ "wx.lib.imagebrowser.ImageDialog",
+ "wx.MessageDialog",
+ "wx.MultiChoiceDialog",
+ "wx.lib.dialogs.MultipleChoiceDialog",
+ "wx.PageSetupDialog",
+ "wx.lib.popupctl.PopupDialog",
+ "wx.PrintDialog",
+ "wx.lib.dialogs.ScrolledMessageDialog",
+ "wx.SingleChoiceDialog",
+ "wx.TextEntryDialog",
+ "wx.wizard.Wizard ",]],
+ ["wx.Frame", [
+ "wx.lib.analogclockopts.ACCustomizationFrame",
+ "wx.py.filling.FillingFrame",
+ ["wx.py.frame.Frame",[
+ "wx.py.crust.CrustFrame",
+ ["wx.py.editor.EditorFrame",[
+ "wx.py.editor.EditorNotebookFrame",]],
+ "wx.py.shell.ShellFrame",]],
+ "wx.html.HtmlHelpFrame",
+ "wx.MDIChildFrame",
+ "wx.MDIParentFrame",
+ "wx.MiniFrame",
+ ["wx.PreviewFrame",[
+ "wx.PyPreviewFrame ",]],
+ "wx.ProgressDialog",
+ "wx.SplashScreen",
+ "wx.lib.splashscreen.SplashScreen",
+ "wx.lib.masked.maskededit.test2",
+ "wx.lib.plot.TestFrame ",]] ]],
+ "wx.gizmos.TreeCompanionWindow ",]] ]] ]],
+ "wx.FileHistory",
+ "wx.FileSystem",
+ "wx.FindReplaceData",
+ "wx.FontData",
+ "wx.FontList",
+ "wx.FSFile",
+ ["wx.GDIObject",[
+ "wx.Bitmap",
+ "wx.Brush",
+ "wx.Cursor",
+ "wx.Font",
+ "wx.Icon",
+ "wx.Palette",
+ "wx.Pen",
+ "wx.Region ",]],
+ "wx.glcanvas.GLContext",
+ ["wx.grid.GridTableBase", [
+ "wx.grid.GridStringTable",
+ "wx.grid.PyGridTableBase ",]],
+ ["wx.html.HtmlCell", [
+ "wx.html.HtmlColourCell",
+ "wx.html.HtmlContainerCell",
+ "wx.html.HtmlFontCell",
+ "wx.html.HtmlWidgetCell",
+ "wx.html.HtmlWordCell ",]],
+ "wx.html.HtmlDCRenderer",
+ "wx.html.HtmlEasyPrinting",
+ "wx.html.HtmlFilter",
+ "wx.html.HtmlLinkInfo",
+ ["wx.html.HtmlParser", [
+ "wx.html.HtmlWinParser ",]],
+ "wx.html.HtmlTag",
+ ["wx.html.HtmlTagHandler", [
+ ["wx.html.HtmlWinTagHandler", [
+ "wx.lib.wxpTag.wxpTagHandler ",]] ]],
+ "wx.Image",
+ ["wx.ImageHandler", [
+ ["wx.BMPHandler", [
+ ["wx.ICOHandler", [
+ ["wx.CURHandler", [
+ "wx.ANIHandler ",]] ]] ]],
+ "wx.GIFHandler",
+ "wx.JPEGHandler",
+ "wx.PCXHandler",
+ "wx.PNGHandler",
+ "wx.PNMHandler",
+ "wx.TIFFHandler",
+ "wx.XPMHandler ",]],
+ "wx.ImageList",
+ "wx.IndividualLayoutConstraint",
+ "wx.LayoutAlgorithm",
+ ["wx.LayoutConstraints", [
+ "wx.lib.anchors.LayoutAnchors",
+ "wx.lib.layoutf.Layoutf",]],
+ "wx.ListItem",
+ "wx.Mask",
+ "wx.MenuItem",
+ "wx.MetaFile",
+ "wx.PageSetupDialogData",
+ "wx.PenList",
+ "wx.PrintData",
+ "wx.PrintDialogData",
+ "wx.Printer",
+ ["wx.Printout", [
+ "wx.html.HtmlPrintout",
+ "wx.lib.plot.PlotPrintout",
+ "wx.lib.printout.SetPrintout ",]],
+ ["wx.PrintPreview", [
+ "wx.PyPrintPreview ",]],
+ "wx.RegionIterator",
+ ["wx.Sizer", [
+ "wx.BookCtrlSizer",
+ ["wx.BoxSizer", [
+ "wx.StaticBoxSizer", ]],
+ ["wx.GridSizer", [
+ ["wx.FlexGridSizer", [
+ "wx.GridBagSizer",]] ]],
+ "wx.NotebookSizer",
+ "wx.PySizer",]],
+ ["wx.SizerItem", [
+ "wx.GBSizerItem",]],
+ "wx.SystemOptions",
+ "wx.ToolBarToolBase",
+ "wx.ToolTip",
+ "wx.gizmos.TreeListColumnInfo",
+ "wx.xrc.XmlDocument",
+ "wx.xrc.XmlResource",
+ "wx.xrc.XmlResourceHandler ",
+]
+
+
+
--- /dev/null
+import wx
+import data
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None,
+ title="simple tree with icons", size=(400,500))
+
+ # Create an image list
+ il = wx.ImageList(16,16)
+
+ # Get some standard images from the art provider and add them
+ # to the image list
+ self.fldridx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_FOLDER,
+ wx.ART_OTHER, (16,16)))
+ self.fldropenidx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN,
+ wx.ART_OTHER, (16,16)))
+ self.fileidx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE,
+ wx.ART_OTHER, (16,16)))
+
+
+ # Create the tree
+ self.tree = wx.TreeCtrl(self)
+ # Give it the image list
+ self.tree.AssignImageList(il)
+ root = self.tree.AddRoot("wx.Object")
+ self.tree.SetItemImage(root, self.fldridx,
+ wx.TreeItemIcon_Normal)
+ self.tree.SetItemImage(root, self.fldropenidx,
+ wx.TreeItemIcon_Expanded)
+
+ self.AddTreeNodes(root, data.tree)
+ self.tree.Expand(root)
+
+
+ def AddTreeNodes(self, parentItem, items):
+ for item in items:
+ if type(item) == str:
+ newItem = self.tree.AppendItem(parentItem, item)
+ self.tree.SetItemImage(newItem, self.fileidx,
+ wx.TreeItemIcon_Normal)
+ else:
+ newItem = self.tree.AppendItem(parentItem, item[0])
+ self.tree.SetItemImage(newItem, self.fldridx,
+ wx.TreeItemIcon_Normal)
+ self.tree.SetItemImage(newItem, self.fldropenidx,
+ wx.TreeItemIcon_Expanded)
+
+ self.AddTreeNodes(newItem, item[1])
+
+
+ def GetItemText(self, item):
+ if item:
+ return self.tree.GetItemText(item)
+ else:
+ return ""
+
+app = wx.PySimpleApp(redirect=True)
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
+
--- /dev/null
+import wx
+import data
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="tree: misc tests", size=(400,500))
+
+ # Create an image list
+ il = wx.ImageList(16,16)
+
+ # Get some standard images from the art provider and add them
+ # to the image list
+ self.fldridx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16,16)))
+ self.fldropenidx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, (16,16)))
+ self.fileidx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, (16,16)))
+
+
+ # Create the tree
+ self.tree = wx.TreeCtrl(self, style=wx.TR_DEFAULT_STYLE | wx.TR_EDIT_LABELS)
+
+ # Give it the image list
+ self.tree.AssignImageList(il)
+
+
+ # Add a root node and assign it some images
+ root = self.tree.AddRoot("wx.Object")
+ self.tree.SetItemPyData(root, None)
+ self.tree.SetItemImage(root, self.fldridx,
+ wx.TreeItemIcon_Normal)
+ self.tree.SetItemImage(root, self.fldropenidx,
+ wx.TreeItemIcon_Expanded)
+
+ # Add nodes from our data set
+ self.AddTreeNodes(root, data.tree)
+
+ # Bind some interesting events
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, self.tree)
+ self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, self.tree)
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.tree)
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivated, self.tree)
+
+ self.Bind(wx.EVT_TREE_BEGIN_LABEL_EDIT, self.OnBeginEdit, self.tree)
+
+
+ # Expand the first level
+ self.tree.Expand(root)
+
+
+ menu = wx.Menu()
+ mi = menu.Append(-1, "Edit Item")
+ self.Bind(wx.EVT_MENU, self.OnEditItem, mi)
+ mi = menu.Append(-1, "Sort Children")
+ self.Bind(wx.EVT_MENU, self.OnSortChildren, mi)
+ mi = menu.Append(-1, "Delete Children")
+ self.Bind(wx.EVT_MENU, self.OnDeleteChildren, mi)
+ mi = menu.Append(-1, "Find all Children")
+ self.Bind(wx.EVT_MENU, self.OnFindChildren, mi)
+ mb = wx.MenuBar()
+ mb.Append(menu, "Tests")
+ self.SetMenuBar(mb)
+
+
+ def AddTreeNodes(self, parentItem, items):
+ """
+ Recursively traverses the data structure, adding tree nodes to
+ match it.
+ """
+ for item in items:
+ if type(item) == str:
+ newItem = self.tree.AppendItem(parentItem, item)
+ self.tree.SetItemPyData(newItem, None)
+ self.tree.SetItemImage(newItem, self.fileidx,
+ wx.TreeItemIcon_Normal)
+ else:
+ newItem = self.tree.AppendItem(parentItem, item[0])
+ self.tree.SetItemPyData(newItem, None)
+ self.tree.SetItemImage(newItem, self.fldridx,
+ wx.TreeItemIcon_Normal)
+ self.tree.SetItemImage(newItem, self.fldropenidx,
+ wx.TreeItemIcon_Expanded)
+
+ self.AddTreeNodes(newItem, item[1])
+
+
+ def GetItemText(self, item):
+ if item:
+ return self.tree.GetItemText(item)
+ else:
+ return ""
+
+ def OnItemExpanded(self, evt):
+ print "OnItemExpanded: ", self.GetItemText(evt.GetItem())
+
+ def OnItemCollapsed(self, evt):
+ print "OnItemCollapsed:", self.GetItemText(evt.GetItem())
+
+ def OnSelChanged(self, evt):
+ print "OnSelChanged: ", self.GetItemText(evt.GetItem())
+
+ def OnActivated(self, evt):
+ print "OnActivated: ", self.GetItemText(evt.GetItem())
+
+
+ def OnBeginEdit(self, evt):
+ print "OnBeginEdit: ", self.GetItemText(evt.GetItem())
+ # we can prevent nodes from being edited, for example let's
+ # not let the root node be edited...
+ item = evt.GetItem()
+ if item == self.tree.GetRootItem():
+ evt.Veto()
+ print "*** Edit was vetoed!"
+
+
+ def OnEditItem(self, evt):
+ item = self.tree.GetSelection()
+ if item:
+ self.tree.EditLabel(item)
+
+ def OnSortChildren(self, evt):
+ item = self.tree.GetSelection()
+ if item:
+ self.tree.SortChildren(item)
+
+ def OnDeleteChildren(self, evt):
+ item = self.tree.GetSelection()
+ if item:
+ self.tree.DeleteChildren(item)
+
+ def OnFindChildren(self, evt):
+ item = self.tree.GetSelection()
+ if item:
+ self.PrintAllItems(item)
+
+ def PrintAllItems(self, parent, indent=0):
+ text = self.tree.GetItemText(parent)
+ print ' ' * indent, text
+ indent += 4
+ item, cookie = self.tree.GetFirstChild(parent)
+ while item:
+ if self.tree.ItemHasChildren(item):
+ self.PrintAllItems(item, indent)
+ else:
+ text = self.tree.GetItemText(item)
+ print ' ' * indent, text
+ item, cookie = self.tree.GetNextChild(parent, cookie)
+
+
+app = wx.PySimpleApp(redirect=True)
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
+
--- /dev/null
+import wx
+import data
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="simple tree", size=(400,500))
+
+ # Create the tree
+ self.tree = wx.TreeCtrl(self)
+
+ # Add a root node
+ root = self.tree.AddRoot("wx.Object")
+
+ # Add nodes from our data set
+ self.AddTreeNodes(root, data.tree)
+
+ # Bind some interesting events
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, self.tree)
+ self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, self.tree)
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.tree)
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivated, self.tree)
+
+ # Expand the first level
+ self.tree.Expand(root)
+
+
+ def AddTreeNodes(self, parentItem, items):
+ """
+ Recursively traverses the data structure, adding tree nodes to
+ match it.
+ """
+ for item in items:
+ if type(item) == str:
+ self.tree.AppendItem(parentItem, item)
+ else:
+ newItem = self.tree.AppendItem(parentItem, item[0])
+ self.AddTreeNodes(newItem, item[1])
+
+ def GetItemText(self, item):
+ if item:
+ return self.tree.GetItemText(item)
+ else:
+ return ""
+
+ def OnItemExpanded(self, evt):
+ print "OnItemExpanded: ", self.GetItemText(evt.GetItem())
+
+ def OnItemCollapsed(self, evt):
+ print "OnItemCollapsed:", self.GetItemText(evt.GetItem())
+
+ def OnSelChanged(self, evt):
+ print "OnSelChanged: ", self.GetItemText(evt.GetItem())
+
+ def OnActivated(self, evt):
+ print "OnActivated: ", self.GetItemText(evt.GetItem())
+
+
+app = wx.PySimpleApp(redirect=True)
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
+
--- /dev/null
+import wx
+import wx.gizmos
+import data
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="TreeListCtrl", size=(400,500))
+
+ # Create an image list
+ il = wx.ImageList(16,16)
+
+ # Get some standard images from the art provider and add them
+ # to the image list
+ self.fldridx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16,16)))
+ self.fldropenidx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, (16,16)))
+ self.fileidx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, (16,16)))
+
+
+ # Create the tree
+ self.tree = wx.gizmos.TreeListCtrl(self, style =
+ wx.TR_DEFAULT_STYLE
+ | wx.TR_FULL_ROW_HIGHLIGHT)
+
+ # Give it the image list
+ self.tree.AssignImageList(il)
+
+
+ # create some columns
+ self.tree.AddColumn("Class Name")
+ self.tree.AddColumn("Description")
+ self.tree.SetMainColumn(0) # the one with the tree in it...
+ self.tree.SetColumnWidth(0, 200)
+ self.tree.SetColumnWidth(1, 200)
+
+ # Add a root node and assign it some images
+ root = self.tree.AddRoot("wx.Object")
+ self.tree.SetItemText(root, "A description of wx.Object", 1)
+ self.tree.SetItemImage(root, self.fldridx,
+ wx.TreeItemIcon_Normal)
+ self.tree.SetItemImage(root, self.fldropenidx,
+ wx.TreeItemIcon_Expanded)
+
+ # Add nodes from our data set
+ self.AddTreeNodes(root, data.tree)
+
+ # Bind some interesting events
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, self.tree)
+ self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, self.tree)
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.tree)
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivated, self.tree)
+
+ # Expand the first level
+ self.tree.Expand(root)
+
+
+ def AddTreeNodes(self, parentItem, items):
+ """
+ Recursively traverses the data structure, adding tree nodes to
+ match it.
+ """
+ for item in items:
+ if type(item) == str:
+ newItem = self.tree.AppendItem(parentItem, item)
+ self.tree.SetItemText(newItem, "A description of %s" % item, 1)
+ self.tree.SetItemImage(newItem, self.fileidx,
+ wx.TreeItemIcon_Normal)
+ else:
+ newItem = self.tree.AppendItem(parentItem, item[0])
+ self.tree.SetItemText(newItem, "A description of %s" % item[0], 1)
+ self.tree.SetItemImage(newItem, self.fldridx,
+ wx.TreeItemIcon_Normal)
+ self.tree.SetItemImage(newItem, self.fldropenidx,
+ wx.TreeItemIcon_Expanded)
+
+ self.AddTreeNodes(newItem, item[1])
+
+
+ def GetItemText(self, item):
+ if item:
+ return self.tree.GetItemText(item)
+ else:
+ return ""
+
+ def OnItemExpanded(self, evt):
+ print "OnItemExpanded: ", self.GetItemText(evt.GetItem())
+
+ def OnItemCollapsed(self, evt):
+ print "OnItemCollapsed:", self.GetItemText(evt.GetItem())
+
+ def OnSelChanged(self, evt):
+ print "OnSelChanged: ", self.GetItemText(evt.GetItem())
+
+ def OnActivated(self, evt):
+ print "OnActivated: ", self.GetItemText(evt.GetItem())
+
+
+app = wx.PySimpleApp(redirect=True)
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
+
--- /dev/null
+import wx
+import data
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="virtual tree with icons", size=(400,500))
+ il = wx.ImageList(16,16)
+ self.fldridx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, (16,16)))
+ self.fldropenidx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, (16,16)))
+ self.fileidx = il.Add(
+ wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, (16,16)))
+ self.tree = wx.TreeCtrl(self)
+ self.tree.AssignImageList(il)
+ root = self.tree.AddRoot("wx.Object")
+ self.tree.SetItemImage(root, self.fldridx,
+ wx.TreeItemIcon_Normal)
+ self.tree.SetItemImage(root, self.fldropenidx,
+ wx.TreeItemIcon_Expanded)
+
+ # Instead of adding nodes for the whole tree, just attach some
+ # data to the root node so that it can find and add its child
+ # nodes when it is expanded, and mark it as having children so
+ # it will be expandable.
+ self.tree.SetItemPyData(root, data.tree)
+ self.tree.SetItemHasChildren(root, True)
+
+ # Bind some interesting events
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, self.tree)
+ self.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, self.tree)
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.tree)
+ self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivated, self.tree)
+
+ self.Bind(wx.EVT_TREE_ITEM_EXPANDING, self.OnItemExpanding, self.tree)
+ self.tree.Expand(root)
+
+
+ def AddTreeNodes(self, parentItem):
+ """
+ Add nodes for just the children of the parentItem
+ """
+ items = self.tree.GetItemPyData(parentItem)
+ for item in items:
+ if type(item) == str:
+ # a leaf node
+ newItem = self.tree.AppendItem(parentItem, item)
+ self.tree.SetItemImage(newItem, self.fileidx,
+ wx.TreeItemIcon_Normal)
+ else:
+ # this item has children
+ newItem = self.tree.AppendItem(parentItem, item[0])
+ self.tree.SetItemImage(newItem, self.fldridx,
+ wx.TreeItemIcon_Normal)
+ self.tree.SetItemImage(newItem, self.fldropenidx,
+ wx.TreeItemIcon_Expanded)
+ self.tree.SetItemPyData(newItem, item[1])
+ self.tree.SetItemHasChildren(newItem, True)
+
+
+
+ def GetItemText(self, item):
+ if item:
+ return self.tree.GetItemText(item)
+ else:
+ return ""
+
+ def OnItemExpanded(self, evt):
+ print "OnItemExpanded: ", self.GetItemText(evt.GetItem())
+
+ def OnItemExpanding(self, evt):
+ # When the item is about to be expanded add the first level of child nodes
+ print "OnItemExpanding:", self.GetItemText(evt.GetItem())
+ self.AddTreeNodes(evt.GetItem())
+
+ def OnItemCollapsed(self, evt):
+ print "OnItemCollapsed:", self.GetItemText(evt.GetItem())
+ # And remove them when collapsed as we don't need them any longer
+ self.tree.DeleteChildren(evt.GetItem())
+
+ def OnSelChanged(self, evt):
+ print "OnSelChanged: ", self.GetItemText(evt.GetItem())
+
+ def OnActivated(self, evt):
+ print "OnActivated: ", self.GetItemText(evt.GetItem())
+
+
+app = wx.PySimpleApp(redirect=True)
+frame = TestFrame()
+frame.Show()
+app.MainLoop()
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+<HEAD>
+<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+<UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="1">
+ <param name="Local" value="book1.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Untitled: d:\HELPS\testing\main.htm">
+ <param name="Local" value="main.htm">
+ </OBJECT>
+ <UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Nested 1">
+ <param name="Local" value="book1.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Nested 2">
+ <param name="Local" value="book2.htm">
+ </OBJECT>
+ <UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="MoreNested 1">
+ <param name="Local" value="book1.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="MoreNested 2">
+ <param name="Local" value="book2.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="MoreNested 3">
+ <param name="Local" value="book1.htm">
+ </OBJECT>
+ </UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Nested 3">
+ <param name="Local" value="book1.htm">
+ </OBJECT>
+ </UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="2">
+ <param name="Local" value="book2.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="multiple">
+ <param name="Local" value="book2.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="multiple">
+ <param name="Local" value="book1.htm">
+ </OBJECT>
+ <UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Nested under multiple">
+ <param name="Local" value="book1.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Nested under multiple 2">
+ <param name="Local" value="book1.htm">
+ </OBJECT>
+ </UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="multiple">
+ <param name="Local" value="main.htm">
+ </OBJECT>
+</UL>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD>
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+<OBJECT type="text/site properties">
+ <param name="ImageType" value="Folder">
+</OBJECT>
+<UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Project file">
+ <param name="Local" value="another.hhp">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Contents file">
+ <param name="Local" value="another.hhc">
+ </OBJECT>
+</UL>
+</BODY></HTML>
--- /dev/null
+[OPTIONS]
+Compatibility=1.1
+Contents file=another.hhc
+Display compile progress=No
+Title=Another book
+Default topic=another.htm
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+ <head>
+ <title>Another HTML Help book</title>
+ </head>
+
+ <body>
+ <h1>Another book...</h1>
+ Here's another book to demonstrate that
+ <UL>
+ <LI> You can display multiple books in a help controller
+ <LI> You can selectively search books. Try it!
+ <LI> Index files are optional. This book doesn't supply an index, but it does supply
+ a contents (.hhc) file. You must always supply a contents file because
+ <UL>
+ <LI> Contents trees rule :-)
+ <LI> The search algorithm uses the contents tree to find out which pages are
+ available.
+ </UL>
+ Wanna know what a contents file looks like? Click <a href="another.hhc">here</a>
+ </UL>
+ You can also view the <a href="another.hhp">project file</a> for this book.
+ </body>
+</html>
--- /dev/null
+<html><title>Book 1</title><body>
+<h2>Book 1.</h2>
+How do you enjoy <i> book one</i>??
+</body></html>
--- /dev/null
+<html><title>Book 1</title><body>
+<h2>Book 2.</h2>
+How do you enjoy <i> book two</i>??
+<p>Please click <a href="page2-b.htm">HERE</a>
+</body></html>
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<HTML>
+<HEAD>
+<meta name="GENERATOR" content="Microsoft® HTML Help Workshop 4.1">
+<!-- Sitemap 1.0 -->
+</HEAD><BODY>
+<OBJECT type="text/site properties">
+ <param name="ImageType" value="Folder">
+</OBJECT>
+<UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Book 1">
+ <param name="Local" value="book1.htm">
+ </OBJECT>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="Book 2">
+ <param name="ID" value=34>
+ <param name="Local" value="book2.htm">
+ </OBJECT>
+ <UL>
+ <LI> <OBJECT type="text/sitemap">
+ <param name="Name" value="sub book">
+ <param name="Local" value="page2-b.htm">
+ </OBJECT>
+ </UL>
+</UL>
+</BODY></HTML>
+
--- /dev/null
+<html><body>
+<h2>This is main page.</h2>
+<a href="book1.htm">Book 1</a><br>
+<a href="book2.htm">Book 2</a><br>
+</body></html>
--- /dev/null
+<html><body>
+<font color="#FF0000" size=+4 face="Tahoma">
+Hello, you're on sub page of page 2 !!!
+</font>
+</body></html>
--- /dev/null
+[OPTIONS]
+Compatibility=1.1
+Compiled file=testing.chm
+Contents file=contents.hhc
+Display compile progress=No
+Index file=Index.hhk
+Language=0x405 Èesky
+Title=Test HELPFILE
+Default topic=main.htm
+
+[FILES]
+main.htm
+book1.htm
+book2.htm
+page2-b.htm
+
--- /dev/null
+"""
+wxPython can use html files for online help or other forms of
+documentation for your application. The help can be organized as a
+collection of books, and there is a help viewer available that enables
+the user to browse by book, via an index or full text search. The
+format of the contents and index files are similar to Microsoft
+HtmlHelp.
+"""
+
+import wx
+import wx.html
+
+class MyHtmlFrame(wx.Frame):
+ def __init__(self, parent, title):
+ wx.Frame.__init__(self, parent, -1, title)
+ p = wx.Panel(self)
+ b1 = wx.Button(p, -1, "Show Help Contents")
+ b2 = wx.Button(p, -1, "Show Help Index")
+ b3 = wx.Button(p, -1, "Show Specific Help")
+ self.Bind(wx.EVT_BUTTON, self.OnShowHelpContents, b1)
+ self.Bind(wx.EVT_BUTTON, self.OnShowHelpIndex, b2)
+ self.Bind(wx.EVT_BUTTON, self.OnShowSpecificHelp, b3)
+
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add((10,10))
+ sizer.Add(b1, 0, wx.ALL, 10)
+ sizer.Add(b2, 0, wx.ALL, 10)
+ sizer.Add(b3, 0, wx.ALL, 10)
+ p.SetSizer(sizer)
+
+ self.InitHelp()
+
+
+ def InitHelp(self):
+ def _addBook(filename):
+ if not self.help.AddBook(filename):
+ wx.MessageBox("Unable to open: " + filename,
+ "Error", wx.OK|wx.ICON_EXCLAMATION)
+
+ self.help = wx.html.HtmlHelpController()
+
+ _addBook("helpfiles/testing.hhp")
+ _addBook("helpfiles/another.hhp")
+
+
+ def OnShowHelpContents(self, evt):
+ self.help.DisplayContents()
+
+ def OnShowHelpIndex(self, evt):
+ self.help.DisplayIndex()
+
+ def OnShowSpecificHelp(self, evt):
+ self.help.Display("sub book")
+
+
+app = wx.PySimpleApp()
+frm = MyHtmlFrame(None, "HTML Help")
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.html
+
+page = """<html><body>
+
+This silly example shows how custom tags can be defined and used in a
+wx.HtmlWindow. We've defined a new tag, <blue> that will change
+the <blue>foreground color</blue> of the portions of the document that
+it encloses to some shade of blue. The tag handler can also use
+parameters specifed in the tag, for example:
+
+<ul>
+<li> <blue shade='sky'>Sky Blue</blue>
+<li> <blue shade='midnight'>Midnight Blue</blue>
+<li> <blue shade='dark'>Dark Blue</blue>
+<li> <blue shade='navy'>Navy Blue</blue>
+</ul>
+
+</body></html>
+"""
+
+
+class BlueTagHandler(wx.html.HtmlWinTagHandler):
+ def __init__(self):
+ wx.html.HtmlWinTagHandler.__init__(self)
+
+ def GetSupportedTags(self):
+ return "BLUE"
+
+ def HandleTag(self, tag):
+ old = self.GetParser().GetActualColor()
+ clr = "#0000FF"
+ if tag.HasParam("SHADE"):
+ shade = tag.GetParam("SHADE")
+ if shade.upper() == "SKY":
+ clr = "#3299CC"
+ if shade.upper() == "MIDNIGHT":
+ clr = "#2F2F4F"
+ elif shade.upper() == "DARK":
+ clr = "#00008B"
+ elif shade.upper == "NAVY":
+ clr = "#23238E"
+
+ self.GetParser().SetActualColor(clr)
+ self.GetParser().GetContainer().InsertCell(wx.html.HtmlColourCell(clr))
+
+ self.ParseInner(tag)
+
+ self.GetParser().SetActualColor(old)
+ self.GetParser().GetContainer().InsertCell(wx.html.HtmlColourCell(old))
+
+ return True
+
+
+wx.html.HtmlWinParser_AddTagHandler(BlueTagHandler)
+
+
+
+class MyHtmlFrame(wx.Frame):
+ def __init__(self, parent, title):
+ wx.Frame.__init__(self, parent, -1, title)
+ html = wx.html.HtmlWindow(self)
+ if "gtk2" in wx.PlatformInfo:
+ html.SetStandardFonts()
+ html.SetPage(page)
+
+
+app = wx.PySimpleApp()
+frm = MyHtmlFrame(None, "Custom HTML Tag Handler")
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.html
+
+class MyHtmlFrame(wx.Frame):
+ def __init__(self, parent, title):
+ wx.Frame.__init__(self, parent, -1, title)
+ html = wx.html.HtmlWindow(self)
+ if "gtk2" in wx.PlatformInfo:
+ html.SetStandardFonts()
+
+ html.SetPage(
+ "Here is some <b>formatted</b> <i><u>text</u></i> "
+ "loaded from a <font color=\"red\">string</font>.")
+
+
+app = wx.PySimpleApp()
+frm = MyHtmlFrame(None, "Simple HTML")
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.html
+
+class MyHtmlFrame(wx.Frame):
+ def __init__(self, parent, title):
+ wx.Frame.__init__(self, parent, -1, title, size=(600,400))
+ html = wx.html.HtmlWindow(self)
+ if "gtk2" in wx.PlatformInfo:
+ html.SetStandardFonts()
+
+ wx.CallAfter(
+ html.LoadPage, "http://wxwidgets.org/manuals/2.6.2/wx_wxbutton.html")
+
+app = wx.PySimpleApp()
+frm = MyHtmlFrame(None, "Simple HTML Browser")
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import wx.html
+
+class MyHtmlFrame(wx.Frame):
+ def __init__(self, parent, title):
+ wx.Frame.__init__(self, parent, -1, title, size=(600,400))
+ self.CreateStatusBar()
+
+ html = wx.html.HtmlWindow(self)
+ if "gtk2" in wx.PlatformInfo:
+ html.SetStandardFonts()
+ html.SetRelatedFrame(self, self.GetTitle() + " -- %s")
+ html.SetRelatedStatusBar(0)
+
+ wx.CallAfter(
+ html.LoadPage, "http://wxwidgets.org/manuals/2.6.2/wx_wxbutton.html")
+
+app = wx.PySimpleApp()
+frm = MyHtmlFrame(None, "Simple HTML Browser")
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import os
+
+FONTSIZE = 10
+
+class TextDocPrintout(wx.Printout):
+ """
+ A printout class that is able to print simple text documents.
+ Does not handle page numbers or titles, and it assumes that no
+ lines are longer than what will fit within the page width. Those
+ features are left as an exercise for the reader. ;-)
+ """
+ def __init__(self, text, title, margins):
+ wx.Printout.__init__(self, title)
+ self.lines = text.split('\n')
+ self.margins = margins
+
+
+ def HasPage(self, page):
+ return page <= self.numPages
+
+ def GetPageInfo(self):
+ return (1, self.numPages, 1, self.numPages)
+
+
+ def CalculateScale(self, dc):
+ # Scale the DC such that the printout is roughly the same as
+ # the screen scaling.
+ ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
+ ppiScreenX, ppiScreenY = self.GetPPIScreen()
+ logScale = float(ppiPrinterX)/float(ppiScreenX)
+
+ # Now adjust if the real page size is reduced (such as when
+ # drawing on a scaled wx.MemoryDC in the Print Preview.) If
+ # page width == DC width then nothing changes, otherwise we
+ # scale down for the DC.
+ pw, ph = self.GetPageSizePixels()
+ dw, dh = dc.GetSize()
+ scale = logScale * float(dw)/float(pw)
+
+ # Set the DC's scale.
+ dc.SetUserScale(scale, scale)
+
+ # Find the logical units per millimeter (for calculating the
+ # margins)
+ self.logUnitsMM = float(ppiPrinterX)/(logScale*25.4)
+
+
+ def CalculateLayout(self, dc):
+ # Determine the position of the margins and the
+ # page/line height
+ topLeft, bottomRight = self.margins
+ dw, dh = dc.GetSize()
+ self.x1 = topLeft.x * self.logUnitsMM
+ self.y1 = topLeft.y * self.logUnitsMM
+ self.x2 = dc.DeviceToLogicalXRel(dw) - bottomRight.x * self.logUnitsMM
+ self.y2 = dc.DeviceToLogicalYRel(dh) - bottomRight.y * self.logUnitsMM
+
+ # use a 1mm buffer around the inside of the box, and a few
+ # pixels between each line
+ self.pageHeight = self.y2 - self.y1 - 2*self.logUnitsMM
+ font = wx.Font(FONTSIZE, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
+ dc.SetFont(font)
+ self.lineHeight = dc.GetCharHeight()
+ self.linesPerPage = int(self.pageHeight/self.lineHeight)
+
+
+ def OnPreparePrinting(self):
+ # calculate the number of pages
+ dc = self.GetDC()
+ self.CalculateScale(dc)
+ self.CalculateLayout(dc)
+ self.numPages = len(self.lines) / self.linesPerPage
+ if len(self.lines) % self.linesPerPage != 0:
+ self.numPages += 1
+
+
+ def OnPrintPage(self, page):
+ dc = self.GetDC()
+ self.CalculateScale(dc)
+ self.CalculateLayout(dc)
+
+ # draw a page outline at the margin points
+ dc.SetPen(wx.Pen("black", 0))
+ dc.SetBrush(wx.TRANSPARENT_BRUSH)
+ r = wx.RectPP((self.x1, self.y1),
+ (self.x2, self.y2))
+ dc.DrawRectangleRect(r)
+ dc.SetClippingRect(r)
+
+ # Draw the text lines for this page
+ line = (page-1) * self.linesPerPage
+ x = self.x1 + self.logUnitsMM
+ y = self.y1 + self.logUnitsMM
+ while line < (page * self.linesPerPage):
+ dc.DrawText(self.lines[line], x, y)
+ y += self.lineHeight
+ line += 1
+ if line >= len(self.lines):
+ break
+ return True
+
+
+class PrintFrameworkSample(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, size=(640, 480),
+ title="Print Framework Sample")
+ self.CreateStatusBar()
+
+ # A text widget to display the doc and let it be edited
+ self.tc = wx.TextCtrl(self, -1, "",
+ style=wx.TE_MULTILINE|wx.TE_DONTWRAP)
+ self.tc.SetFont(wx.Font(FONTSIZE, wx.TELETYPE, wx.NORMAL, wx.NORMAL))
+ filename = os.path.join(os.path.dirname(__file__), "sample-text.txt")
+ self.tc.SetValue(open(filename).read())
+ self.tc.Bind(wx.EVT_SET_FOCUS, self.OnClearSelection)
+ wx.CallAfter(self.tc.SetInsertionPoint, 0)
+
+ # Create the menu and menubar
+ menu = wx.Menu()
+ item = menu.Append(-1, "Page Setup...\tF5",
+ "Set up page margins and etc.")
+ self.Bind(wx.EVT_MENU, self.OnPageSetup, item)
+ item = menu.Append(-1, "Print Preview...\tF6",
+ "View the printout on-screen")
+ self.Bind(wx.EVT_MENU, self.OnPrintPreview, item)
+ item = menu.Append(-1, "Print...\tF7", "Print the document")
+ self.Bind(wx.EVT_MENU, self.OnPrint, item)
+ menu.AppendSeparator()
+## item = menu.Append(-1, "Test other stuff...\tF9", "")
+## self.Bind(wx.EVT_MENU, self.OnPrintTest, item)
+## menu.AppendSeparator()
+ item = menu.Append(wx.ID_EXIT, "E&xit\tCtrl-Q", "Close this application")
+ self.Bind(wx.EVT_MENU, self.OnExit, item)
+
+ menubar = wx.MenuBar()
+ menubar.Append(menu, "&File")
+ self.SetMenuBar(menubar)
+
+ # initialize the print data and set some default values
+ self.pdata = wx.PrintData()
+ self.pdata.SetPaperId(wx.PAPER_LETTER)
+ self.pdata.SetOrientation(wx.PORTRAIT)
+ self.margins = (wx.Point(15,15), wx.Point(15,15))
+
+
+ def OnExit(self, evt):
+ self.Close()
+
+
+ def OnClearSelection(self, evt):
+ evt.Skip()
+ wx.CallAfter(self.tc.SetInsertionPoint,
+ self.tc.GetInsertionPoint())
+
+
+ def OnPageSetup(self, evt):
+ data = wx.PageSetupDialogData()
+ data.SetPrintData(self.pdata)
+
+ data.SetDefaultMinMargins(True)
+ data.SetMarginTopLeft(self.margins[0])
+ data.SetMarginBottomRight(self.margins[1])
+
+ dlg = wx.PageSetupDialog(self, data)
+ if dlg.ShowModal() == wx.ID_OK:
+ data = dlg.GetPageSetupData()
+ self.pdata = wx.PrintData(data.GetPrintData()) # force a copy
+ self.pdata.SetPaperId(data.GetPaperId())
+ self.margins = (data.GetMarginTopLeft(),
+ data.GetMarginBottomRight())
+ dlg.Destroy()
+
+
+ def OnPrintPreview(self, evt):
+ data = wx.PrintDialogData(self.pdata)
+ text = self.tc.GetValue()
+ printout1 = TextDocPrintout(text, "title", self.margins)
+ printout2 = None #TextDocPrintout(text, "title", self.margins)
+ preview = wx.PrintPreview(printout1, printout2, data)
+ if not preview.Ok():
+ wx.MessageBox("Unable to create PrintPreview!", "Error")
+ else:
+ # create the preview frame such that it overlays the app frame
+ frame = wx.PreviewFrame(preview, self, "Print Preview",
+ pos=self.GetPosition(),
+ size=self.GetSize())
+ frame.Initialize()
+ frame.Show()
+
+
+ def OnPrint(self, evt):
+ data = wx.PrintDialogData(self.pdata)
+ printer = wx.Printer(data)
+ text = self.tc.GetValue()
+ printout = TextDocPrintout(text, "title", self.margins)
+ useSetupDialog = True
+ if not printer.Print(self, printout, useSetupDialog) \
+ and printer.GetLastError() == wx.PRINTER_ERROR:
+ wx.MessageBox(
+ "There was a problem printing.\n"
+ "Perhaps your current printer is not set correctly?",
+ "Printing Error", wx.OK)
+ else:
+ data = printer.GetPrintDialogData()
+ self.pdata = wx.PrintData(data.GetPrintData()) # force a copy
+ printout.Destroy()
+
+
+ def OnPrintTest(self, evt):
+ data = wx.PrintDialogData(self.pdata)
+ dlg = wx.PrintDialog(self, data)
+ if dlg.ShowModal() == wx.ID_OK:
+ data = dlg.GetPrintDialogData()
+ print
+ print "GetFromPage:", data.GetFromPage()
+ print "GetToPage:", data.GetToPage()
+ print "GetMinPage:", data.GetMinPage()
+ print "GetMaxPage:", data.GetMaxPage()
+ print "GetNoCopies:", data.GetNoCopies()
+ print "GetAllPages:", data.GetAllPages()
+ print "GetSelection:", data.GetSelection()
+ print "GetCollate:", data.GetCollate()
+ print "GetPrintToFile:", data.GetPrintToFile()
+
+ self.pdata = wx.PrintData(data.GetPrintData())
+ print
+ print "GetPrinterName:", self.pdata.GetPrinterName()
+
+ dlg.Destroy()
+
+
+app = wx.PySimpleApp()
+frm = PrintFrameworkSample()
+frm.Show()
+app.MainLoop()
--- /dev/null
+THE BROTHERS GRIMM
+FAIRY TALES
+
+
+
+THE GOLDEN BIRD
+
+A certain king had a beautiful garden, and in the garden stood a tree
+which bore golden apples. These apples were always counted, and about
+the time when they began to grow ripe it was found that every night
+one of them was gone. The king became very angry at this, and ordered
+the gardener to keep watch all night under the tree. The gardener set
+his eldest son to watch; but about twelve o'clock he fell asleep, and
+in the morning another of the apples was missing. Then the second son
+was ordered to watch; and at midnight he too fell asleep, and in the
+morning another apple was gone. Then the third son offered to keep
+watch; but the gardener at first would not let him, for fear some harm
+should come to him: however, at last he consented, and the young man
+laid himself under the tree to watch. As the clock struck twelve he
+heard a rustling noise in the air, and a bird came flying that was of
+pure gold; and as it was snapping at one of the apples with its beak,
+the gardener's son jumped up and shot an arrow at it. But the arrow
+did the bird no harm; only it dropped a golden feather from its tail,
+and then flew away. The golden feather was brought to the king in the
+morning, and all the council was called together. Everyone agreed that
+it was worth more than all the wealth of the kingdom: but the king
+said, 'One feather is of no use to me, I must have the whole bird.'
+
+Then the gardener's eldest son set out and thought to find the golden
+bird very easily; and when he had gone but a little way, he came to a
+wood, and by the side of the wood he saw a fox sitting; so he took his
+bow and made ready to shoot at it. Then the fox said, 'Do not shoot
+me, for I will give you good counsel; I know what your business is,
+and that you want to find the golden bird. You will reach a village in
+the evening; and when you get there, you will see two inns opposite to
+each other, one of which is very pleasant and beautiful to look at: go
+not in there, but rest for the night in the other, though it may
+appear to you to be very poor and mean.' But the son thought to
+himself, 'What can such a beast as this know about the matter?' So he
+shot his arrow at the fox; but he missed it, and it set up its tail
+above its back and ran into the wood. Then he went his way, and in the
+evening came to the village where the two inns were; and in one of
+these were people singing, and dancing, and feasting; but the other
+looked very dirty, and poor. 'I should be very silly,' said he, 'if I
+went to that shabby house, and left this charming place'; so he went
+into the smart house, and ate and drank at his ease, and forgot the
+bird, and his country too.
+
+Time passed on; and as the eldest son did not come back, and no
+tidings were heard of him, the second son set out, and the same thing
+happened to him. He met the fox, who gave him the good advice: but
+when he came to the two inns, his eldest brother was standing at the
+window where the merrymaking was, and called to him to come in; and he
+could not withstand the temptation, but went in, and forgot the golden
+bird and his country in the same manner.
+
+Time passed on again, and the youngest son too wished to set out into
+the wide world to seek for the golden bird; but his father would not
+listen to it for a long while, for he was very fond of his son, and
+was afraid that some ill luck might happen to him also, and prevent
+his coming back. However, at last it was agreed he should go, for he
+would not rest at home; and as he came to the wood, he met the fox,
+and heard the same good counsel. But he was thankful to the fox, and
+did not attempt his life as his brothers had done; so the fox said,
+'Sit upon my tail, and you will travel faster.' So he sat down, and
+the fox began to run, and away they went over stock and stone so quick
+that their hair whistled in the wind.
+
+When they came to the village, the son followed the fox's counsel, and
+without looking about him went to the shabby inn and rested there all
+night at his ease. In the morning came the fox again and met him as he
+was beginning his journey, and said, 'Go straight forward, till you
+come to a castle, before which lie a whole troop of soldiers fast
+asleep and snoring: take no notice of them, but go into the castle and
+pass on and on till you come to a room, where the golden bird sits in
+a wooden cage; close by it stands a beautiful golden cage; but do not
+try to take the bird out of the shabby cage and put it into the
+handsome one, otherwise you will repent it.' Then the fox stretched
+out his tail again, and the young man sat himself down, and away they
+went over stock and stone till their hair whistled in the wind.
+
+Before the castle gate all was as the fox had said: so the son went in
+and found the chamber where the golden bird hung in a wooden cage, and
+below stood the golden cage, and the three golden apples that had been
+lost were lying close by it. Then thought he to himself, 'It will be a
+very droll thing to bring away such a fine bird in this shabby cage';
+so he opened the door and took hold of it and put it into the golden
+cage. But the bird set up such a loud scream that all the soldiers
+awoke, and they took him prisoner and carried him before the king. The
+next morning the court sat to judge him; and when all was heard, it
+sentenced him to die, unless he should bring the king the golden horse
+which could run as swiftly as the wind; and if he did this, he was to
+have the golden bird given him for his own.
+
+So he set out once more on his journey, sighing, and in great despair,
+when on a sudden his friend the fox met him, and said, 'You see now
+what has happened on account of your not listening to my counsel. I
+will still, however, tell you how to find the golden horse, if you
+will do as I bid you. You must go straight on till you come to the
+castle where the horse stands in his stall: by his side will lie the
+groom fast asleep and snoring: take away the horse quietly, but be
+sure to put the old leathern saddle upon him, and not the golden one
+that is close by it.' Then the son sat down on the fox's tail, and
+away they went over stock and stone till their hair whistled in the
+wind.
+
+All went right, and the groom lay snoring with his hand upon the
+golden saddle. But when the son looked at the horse, he thought it a
+great pity to put the leathern saddle upon it. 'I will give him the
+good one,' said he; 'I am sure he deserves it.' As he took up the
+golden saddle the groom awoke and cried out so loud, that all the
+guards ran in and took him prisoner, and in the morning he was again
+brought before the court to be judged, and was sentenced to die. But
+it was agreed, that, if he could bring thither the beautiful princess,
+he should live, and have the bird and the horse given him for his own.
+
+Then he went his way very sorrowful; but the old fox came and said,
+'Why did not you listen to me? If you had, you would have carried away
+both the bird and the horse; yet will I once more give you counsel. Go
+straight on, and in the evening you will arrive at a castle. At twelve
+o'clock at night the princess goes to the bathing-house: go up to her
+and give her a kiss, and she will let you lead her away; but take care
+you do not suffer her to go and take leave of her father and mother.'
+Then the fox stretched out his tail, and so away they went over stock
+and stone till their hair whistled again.
+
+As they came to the castle, all was as the fox had said, and at twelve
+o'clock the young man met the princes going to the bath and gave her
+the kiss, and she agreed to run away with him, but begged with many
+tears that he would let her take leave of her father. At first he
+refused, but she wept still more and more, and fell at his feet, till
+at last he consented; but the moment she came to her father's house
+the guards awoke and he was taken prisoner again.
+
+Then he was brought before the king, and the king said, 'You shall
+never have my daughter unless in eight days you dig away the hill that
+stops the view from my window.' Now this hill was so big that the
+whole world could not take it away: and when he had worked for seven
+days, and had done very little, the fox came and said. 'Lie down and
+go to sleep; I will work for you.' And in the morning he awoke and the
+hill was gone; so he went merrily to the king, and told him that now
+that it was removed he must give him the princess.
+
+Then the king was obliged to keep his word, and away went the young
+man and the princess; and the fox came and said to him, 'We will have
+all three, the princess, the horse, and the bird.' 'Ah!' said the
+young man, 'that would be a great thing, but how can you contrive it?'
+
+'If you will only listen,' said the fox, 'it can be done. When you
+come to the king, and he asks for the beautiful princess, you must
+say, "Here she is!" Then he will be very joyful; and you will mount
+the golden horse that they are to give you, and put out your hand to
+take leave of them; but shake hands with the princess last. Then lift
+her quickly on to the horse behind you; clap your spurs to his side,
+and gallop away as fast as you can.'
+
+All went right: then the fox said, 'When you come to the castle where
+the bird is, I will stay with the princess at the door, and you will
+ride in and speak to the king; and when he sees that it is the right
+horse, he will bring out the bird; but you must sit still, and say
+that you want to look at it, to see whether it is the true golden
+bird; and when you get it into your hand, ride away.'
+
+This, too, happened as the fox said; they carried off the bird, the
+princess mounted again, and they rode on to a great wood. Then the fox
+came, and said, 'Pray kill me, and cut off my head and my feet.' But
+the young man refused to do it: so the fox said, 'I will at any rate
+give you good counsel: beware of two things; ransom no one from the
+gallows, and sit down by the side of no river.' Then away he went.
+'Well,' thought the young man, 'it is no hard matter to keep that
+advice.'
+
+He rode on with the princess, till at last he came to the village
+where he had left his two brothers. And there he heard a great noise
+and uproar; and when he asked what was the matter, the people said,
+'Two men are going to be hanged.' As he came nearer, he saw that the
+two men were his brothers, who had turned robbers; so he said, 'Cannot
+they in any way be saved?' But the people said 'No,' unless he would
+bestow all his money upon the rascals and buy their liberty. Then he
+did not stay to think about the matter, but paid what was asked, and
+his brothers were given up, and went on with him towards their home.
+
+And as they came to the wood where the fox first met them, it was so
+cool and pleasant that the two brothers said, 'Let us sit down by the
+side of the river, and rest a while, to eat and drink.' So he said,
+'Yes,' and forgot the fox's counsel, and sat down on the side of the
+river; and while he suspected nothing, they came behind, and threw him
+down the bank, and took the princess, the horse, and the bird, and
+went home to the king their master, and said. 'All this have we won by
+our labour.' Then there was great rejoicing made; but the horse would
+not eat, the bird would not sing, and the princess wept.
+
+The youngest son fell to the bottom of the river's bed: luckily it was
+nearly dry, but his bones were almost broken, and the bank was so
+steep that he could find no way to get out. Then the old fox came once
+more, and scolded him for not following his advice; otherwise no evil
+would have befallen him: 'Yet,' said he, 'I cannot leave you here, so
+lay hold of my tail and hold fast.' Then he pulled him out of the
+river, and said to him, as he got upon the bank, 'Your brothers have
+set watch to kill you, if they find you in the kingdom.' So he dressed
+himself as a poor man, and came secretly to the king's court, and was
+scarcely within the doors when the horse began to eat, and the bird to
+sing, and princess left off weeping. Then he went to the king, and
+told him all his brothers' roguery; and they were seized and punished,
+and he had the princess given to him again; and after the king's death
+he was heir to his kingdom.
+
+A long while after, he went to walk one day in the wood, and the old
+fox met him, and besought him with tears in his eyes to kill him, and
+cut off his head and feet. And at last he did so, and in a moment the
+fox was changed into a man, and turned out to be the brother of the
+princess, who had been lost a great many many years.
+
--- /dev/null
+import wx
+
+t1_text = """\
+The whole contents of this control
+will be placed in the system's
+clipboard when you click the copy
+button below.
+"""
+
+t2_text = """\
+If the clipboard contains a text
+data object then it will be placed
+in this control when you click
+the paste button below. Try
+copying to and pasting from
+other applications too!
+"""
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Clipboard",
+ size=(500,300))
+ p = wx.Panel(self)
+
+ # create the controls
+ self.t1 = wx.TextCtrl(p, -1, t1_text,
+ style=wx.TE_MULTILINE|wx.HSCROLL)
+ self.t2 = wx.TextCtrl(p, -1, t2_text,
+ style=wx.TE_MULTILINE|wx.HSCROLL)
+ copy = wx.Button(p, -1, "Copy")
+ paste = wx.Button(p, -1, "Paste")
+
+ # setup the layout with sizers
+ fgs = wx.FlexGridSizer(2, 2, 5, 5)
+ fgs.AddGrowableRow(0)
+ fgs.AddGrowableCol(0)
+ fgs.AddGrowableCol(1)
+ fgs.Add(self.t1, 0, wx.EXPAND)
+ fgs.Add(self.t2, 0, wx.EXPAND)
+ fgs.Add(copy, 0, wx.EXPAND)
+ fgs.Add(paste, 0, wx.EXPAND)
+ border = wx.BoxSizer()
+ border.Add(fgs, 1, wx.EXPAND|wx.ALL, 5)
+ p.SetSizer(border)
+
+ # Bind events
+ self.Bind(wx.EVT_BUTTON, self.OnDoCopy, copy)
+ self.Bind(wx.EVT_BUTTON, self.OnDoPaste, paste)
+
+ def OnDoCopy(self, evt):
+ data = wx.TextDataObject()
+ data.SetText(self.t1.GetValue())
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.SetData(data)
+ wx.TheClipboard.Close()
+ else:
+ wx.MessageBox("Unable to open the clipboard", "Error")
+
+ def OnDoPaste(self, evt):
+ success = False
+ data = wx.TextDataObject()
+ if wx.TheClipboard.Open():
+ success = wx.TheClipboard.GetData(data)
+ wx.TheClipboard.Close()
+
+ if success:
+ self.t2.SetValue(data.GetText())
+ else:
+ wx.MessageBox(
+ "There is no data in the clipboard in the required format",
+ "Error")
+
+
+app = wx.PySimpleApp()
+frm = MyFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+"""
+This sample shows how to put multiple objects in the clipboard, one of
+which uses a custom data format. In this case we use a Python
+dictionary of values for our custom format, and we also put a textual
+representation of the dictionary. To test this, run two instances of
+this program, enter data in one and click the copy button. Then click
+the paste button in the other instance. Also paste into a text editor
+to see the data in the standard text format.
+"""
+
+
+import wx
+import cPickle
+import pprint
+
+class TestFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, -1, "Copy/Paste Test")
+ panel = wx.Panel(self)
+
+ # First create the controls
+ topLbl = wx.StaticText(panel, -1, "Account Information")
+ topLbl.SetFont(wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
+
+ nameLbl = wx.StaticText(panel, -1, "Name:")
+ self.name = wx.TextCtrl(panel, -1, "");
+
+ addrLbl = wx.StaticText(panel, -1, "Address:")
+ self.addr1 = wx.TextCtrl(panel, -1, "");
+ self.addr2 = wx.TextCtrl(panel, -1, "");
+
+ cstLbl = wx.StaticText(panel, -1, "City, State, Zip:")
+ self.city = wx.TextCtrl(panel, -1, "", size=(150,-1));
+ self.state = wx.TextCtrl(panel, -1, "", size=(50,-1));
+ self.zip = wx.TextCtrl(panel, -1, "", size=(70,-1));
+
+ phoneLbl = wx.StaticText(panel, -1, "Phone:")
+ self.phone = wx.TextCtrl(panel, -1, "");
+
+ emailLbl = wx.StaticText(panel, -1, "Email:")
+ self.email = wx.TextCtrl(panel, -1, "");
+
+ copyBtn = wx.Button(panel, -1, "Copy")
+ pasteBtn = wx.Button(panel, -1, "Paste")
+ self.Bind(wx.EVT_BUTTON, self.OnCopy, copyBtn)
+ self.Bind(wx.EVT_BUTTON, self.OnPaste, pasteBtn)
+
+ # Now do the layout.
+
+ # mainSizer is the top-level one that manages everything
+ mainSizer = wx.BoxSizer(wx.VERTICAL)
+ mainSizer.Add(topLbl, 0, wx.ALL, 5)
+ mainSizer.Add(wx.StaticLine(panel), 0,
+ wx.EXPAND|wx.TOP|wx.BOTTOM, 5)
+
+ # addrSizer is a grid that holds all of the address info
+ addrSizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)
+ addrSizer.AddGrowableCol(1)
+ addrSizer.Add(nameLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(self.name, 0, wx.EXPAND)
+ addrSizer.Add(addrLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(self.addr1, 0, wx.EXPAND)
+ addrSizer.Add((10,10)) # some empty space
+ addrSizer.Add(self.addr2, 0, wx.EXPAND)
+
+ addrSizer.Add(cstLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+
+ # the city, state, zip fields are in a sub-sizer
+ cstSizer = wx.BoxSizer(wx.HORIZONTAL)
+ cstSizer.Add(self.city, 1)
+ cstSizer.Add(self.state, 0, wx.LEFT|wx.RIGHT, 5)
+ cstSizer.Add(self.zip)
+ addrSizer.Add(cstSizer, 0, wx.EXPAND)
+
+ addrSizer.Add(phoneLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(self.phone, 0, wx.EXPAND)
+ addrSizer.Add(emailLbl, 0,
+ wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
+ addrSizer.Add(self.email, 0, wx.EXPAND)
+
+ # now add the addrSizer to the mainSizer
+ mainSizer.Add(addrSizer, 0, wx.EXPAND|wx.ALL, 10)
+
+ # The buttons sizer will put them in a row with resizeable
+ # gaps between and on either side of the buttons
+ btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+ btnSizer.Add((20,20), 1)
+ btnSizer.Add(copyBtn)
+ btnSizer.Add((20,20), 1)
+ btnSizer.Add(pasteBtn)
+ btnSizer.Add((20,20), 1)
+
+ mainSizer.Add(btnSizer, 0, wx.EXPAND|wx.BOTTOM, 10)
+
+ panel.SetSizer(mainSizer)
+
+ # Fit the frame to the needs of the sizer. The frame will
+ # automatically resize the panel as needed. Also prevent the
+ # frame from getting smaller than this size.
+ mainSizer.Fit(self)
+ self.SetMinSize(self.GetSize())
+
+
+ fieldNames = ["name", "addr1", "addr2",
+ "city", "state", "zip", "phone", "email"]
+
+ def OnCopy(self, evt):
+ # make a dictionary of values
+ fieldData = {}
+ for name in self.fieldNames:
+ tc = getattr(self, name)
+ fieldData[name] = tc.GetValue()
+
+ # pickle it and put in a custom data object
+ cdo = wx.CustomDataObject("ContactDictFormat")
+ cdo.SetData(cPickle.dumps(fieldData))
+
+ # also make a text representaion
+ tdo = wx.TextDataObject(pprint.pformat(fieldData))
+
+ # and put them both in the clipboard
+ dataobj = wx.DataObjectComposite()
+ dataobj.Add(cdo)
+ dataobj.Add(tdo)
+ if wx.TheClipboard.Open():
+ wx.TheClipboard.SetData(dataobj)
+ wx.TheClipboard.Close()
+
+
+ def OnPaste(self, evt):
+ # Get the custom format object and put it into
+ # the entry fields
+ cdo = wx.CustomDataObject("ContactDictFormat")
+ if wx.TheClipboard.Open():
+ success = wx.TheClipboard.GetData(cdo)
+ wx.TheClipboard.Close()
+ if success:
+ data = cdo.GetData()
+ fieldData = cPickle.loads(data)
+ for name in self.fieldNames:
+ tc = getattr(self, name)
+ tc.SetValue(fieldData[name])
+
+
+
+app = wx.PySimpleApp()
+TestFrame().Show()
+app.MainLoop()
--- /dev/null
+import wx
+
+class DragController(wx.Control):
+ """
+ Just a little control to handle dragging the text from a text
+ control. We use a separate control so as to not interfere with
+ the native drag-select functionality of the native text control.
+ """
+ def __init__(self, parent, source, size=(25,25)):
+ wx.Control.__init__(self, parent, -1, size=size,
+ style=wx.SIMPLE_BORDER)
+ self.source = source
+ self.SetMinSize(size)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+
+ def OnPaint(self, evt):
+ # draw a simple arrow
+ dc = wx.BufferedPaintDC(self)
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ dc.Clear()
+ w, h = dc.GetSize()
+ y = h/2
+ dc.SetPen(wx.Pen("dark blue", 2))
+ dc.DrawLine(w/8, y, w-w/8, y)
+ dc.DrawLine(w-w/8, y, w/2, h/4)
+ dc.DrawLine(w-w/8, y, w/2, 3*h/4)
+
+ def OnLeftDown(self, evt):
+ text = self.source.GetValue()
+ data = wx.TextDataObject(text)
+ dropSource = wx.DropSource(self)
+ dropSource.SetData(data)
+ result = dropSource.DoDragDrop(wx.Drag_AllowMove)
+
+ # if the user wants to move the data then we should delete it
+ # from the source
+ if result == wx.DragMove:
+ self.source.SetValue("")
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Drop Source")
+ p = wx.Panel(self)
+
+ # create the controls
+ label1 = wx.StaticText(p, -1, "Put some text in this control:")
+ label2 = wx.StaticText(p, -1,
+ "Then drag from the neighboring bitmap and\n"
+ "drop in an application that accepts dropped\n"
+ "text, such as MS Word.")
+ text = wx.TextCtrl(p, -1, "Some text")
+ dragctl = DragController(p, text)
+
+ # setup the layout with sizers
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(label1, 0, wx.ALL, 5)
+ hrow = wx.BoxSizer(wx.HORIZONTAL)
+ hrow.Add(text, 1, wx.RIGHT, 5)
+ hrow.Add(dragctl, 0)
+ sizer.Add(hrow, 0, wx.EXPAND|wx.ALL, 5)
+ sizer.Add(label2, 0, wx.ALL, 5)
+ p.SetSizer(sizer)
+ sizer.Fit(self)
+
+
+app = wx.PySimpleApp()
+frm = MyFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+
+class MyFileDropTarget(wx.FileDropTarget):
+ def __init__(self, window):
+ wx.FileDropTarget.__init__(self)
+ self.window = window
+
+ def OnDropFiles(self, x, y, filenames):
+ self.window.AppendText("\n%d file(s) dropped at (%d,%d):\n" %
+ (len(filenames), x, y))
+ for file in filenames:
+ self.window.AppendText("\t%s\n" % file)
+
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Drop Target",
+ size=(500,300))
+ p = wx.Panel(self)
+
+ # create the controls
+ label = wx.StaticText(p, -1, "Drop some files here:")
+ text = wx.TextCtrl(p, -1, "",
+ style=wx.TE_MULTILINE|wx.HSCROLL)
+
+ # setup the layout with sizers
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(label, 0, wx.ALL, 5)
+ sizer.Add(text, 1, wx.EXPAND|wx.ALL, 5)
+ p.SetSizer(sizer)
+
+ # make the text control be a drop target
+ dt = MyFileDropTarget(text)
+ text.SetDropTarget(dt)
+
+
+app = wx.PySimpleApp()
+frm = MyFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+from wx.lib.filebrowsebutton import FileBrowseButton
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="wx.Sound",
+ size=(500,100))
+ p = wx.Panel(self)
+
+ # create the controls
+ self.fbb = FileBrowseButton(p,
+ labelText="Select WAV file:",
+ fileMask="*.wav")
+ btn = wx.Button(p, -1, "Play")
+ self.Bind(wx.EVT_BUTTON, self.OnPlaySound, btn)
+
+ # setup the layout with sizers
+ sizer = wx.BoxSizer(wx.HORIZONTAL)
+ sizer.Add(self.fbb, 1, wx.ALIGN_CENTER_VERTICAL)
+ sizer.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL)
+ border = wx.BoxSizer(wx.VERTICAL)
+ border.Add(sizer, 0, wx.EXPAND|wx.ALL, 15)
+ p.SetSizer(border)
+
+
+ def OnPlaySound(self, evt):
+ filename = self.fbb.GetValue()
+ self.sound = wx.Sound(filename)
+ if self.sound.IsOk():
+ self.sound.Play(wx.SOUND_ASYNC)
+ else:
+ wx.MessageBox("Invalid sound file", "Error")
+
+
+app = wx.PySimpleApp()
+frm = MyFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import time
+
+class ClockWindow(wx.Window):
+ def __init__(self, parent):
+ wx.Window.__init__(self, parent)
+ self.Bind(wx.EVT_PAINT, self.OnPaint)
+ self.timer = wx.Timer(self)
+ self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
+ self.timer.Start(1000)
+
+ def Draw(self, dc):
+ t = time.localtime(time.time())
+ st = time.strftime("%I:%M:%S", t)
+ w, h = self.GetClientSize()
+ dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+ dc.Clear()
+ dc.SetFont(wx.Font(30, wx.SWISS, wx.NORMAL, wx.NORMAL))
+ tw, th = dc.GetTextExtent(st)
+ dc.DrawText(st, (w-tw)/2, (h)/2 - th/2)
+
+ def OnTimer(self, evt):
+ dc = wx.BufferedDC(wx.ClientDC(self))
+ self.Draw(dc)
+
+ def OnPaint(self, evt):
+ dc = wx.BufferedPaintDC(self)
+ self.Draw(dc)
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="wx.Timer")
+ ClockWindow(self)
+
+
+app = wx.PySimpleApp()
+frm = MyFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+import wx
+import threading
+import random
+
+class WorkerThread(threading.Thread):
+ """
+ This just simulates some long-running task that periodically sends
+ a message to the GUI thread.
+ """
+ def __init__(self, threadNum, window):
+ threading.Thread.__init__(self)
+ self.threadNum = threadNum
+ self.window = window
+ self.timeToQuit = threading.Event()
+ self.timeToQuit.clear()
+ self.messageCount = random.randint(10,20)
+ self.messageDelay = 0.1 + 2.0 * random.random()
+
+ def stop(self):
+ self.timeToQuit.set()
+
+ def run(self):
+ msg = "Thread %d iterating %d times with a delay of %1.4f\n" \
+ % (self.threadNum, self.messageCount, self.messageDelay)
+ wx.CallAfter(self.window.LogMessage, msg)
+
+ for i in range(1, self.messageCount+1):
+ self.timeToQuit.wait(self.messageDelay)
+ if self.timeToQuit.isSet():
+ break
+ msg = "Message %d from thread %d\n" % (i, self.threadNum)
+ wx.CallAfter(self.window.LogMessage, msg)
+ else:
+ wx.CallAfter(self.window.ThreadFinished, self)
+
+
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="Multi-threaded GUI")
+ self.threads = []
+ self.count = 0
+
+ panel = wx.Panel(self)
+ startBtn = wx.Button(panel, -1, "Start a thread")
+ stopBtn = wx.Button(panel, -1, "Stop all threads")
+ self.tc = wx.StaticText(panel, -1, "Worker Threads: 00")
+ self.log = wx.TextCtrl(panel, -1, "",
+ style=wx.TE_RICH|wx.TE_MULTILINE)
+
+ inner = wx.BoxSizer(wx.HORIZONTAL)
+ inner.Add(startBtn, 0, wx.RIGHT, 15)
+ inner.Add(stopBtn, 0, wx.RIGHT, 15)
+ inner.Add(self.tc, 0, wx.ALIGN_CENTER_VERTICAL)
+ main = wx.BoxSizer(wx.VERTICAL)
+ main.Add(inner, 0, wx.ALL, 5)
+ main.Add(self.log, 1, wx.EXPAND|wx.ALL, 5)
+ panel.SetSizer(main)
+
+ self.Bind(wx.EVT_BUTTON, self.OnStartButton, startBtn)
+ self.Bind(wx.EVT_BUTTON, self.OnStopButton, stopBtn)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ self.UpdateCount()
+
+ def OnStartButton(self, evt):
+ self.count += 1
+ thread = WorkerThread(self.count, self)
+ self.threads.append(thread)
+ self.UpdateCount()
+ thread.start()
+
+ def OnStopButton(self, evt):
+ self.StopThreads()
+ self.UpdateCount()
+
+ def OnCloseWindow(self, evt):
+ self.StopThreads()
+ self.Destroy()
+
+ def StopThreads(self):
+ while self.threads:
+ thread = self.threads[0]
+ thread.stop()
+ self.threads.remove(thread)
+
+ def UpdateCount(self):
+ self.tc.SetLabel("Worker Threads: %d" % len(self.threads))
+
+ def LogMessage(self, msg):
+ self.log.AppendText(msg)
+
+ def ThreadFinished(self, thread):
+ self.threads.remove(thread)
+ self.UpdateCount()
+
+
+app = wx.PySimpleApp()
+frm = MyFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+"""
+XRC is an XML-based resource format for wxPython. With it you can
+define the layout of widgets, and then load that XRC at runtime to
+create the layout. There are several GUI designers available that
+understand the XRC format, a simple one called XRCed comes with
+wxPython.
+"""
+
+import wx
+import wx.xrc
+
+
+class MyFrame(wx.Frame):
+ def __init__(self):
+ wx.Frame.__init__(self, None, title="XRC Sample",
+ size=(400,225))
+ res = wx.xrc.XmlResource("xrcsample.xrc")
+ panel = res.LoadPanel(self, "ID_PANEL")
+
+ self.Bind(wx.EVT_BUTTON, self.OnOk,
+ wx.xrc.XRCCTRL(self, "ID_OK"))
+ self.Bind(wx.EVT_BUTTON, self.OnCancel,
+ wx.xrc.XRCCTRL(self, "ID_CANCEL"))
+
+
+ def OnOk(self, evt):
+ namectrl = wx.xrc.XRCCTRL(self, "ID_NAME")
+ name = namectrl.GetValue()
+ emailctrl = wx.xrc.XRCCTRL(self, "ID_EMAIL")
+ email = emailctrl.GetValue()
+ phonectrl = wx.xrc.XRCCTRL(self, "ID_PHONE")
+ phone = phonectrl.GetValue()
+ print "You entered:\n name: %s\n email: %s\n phone: %s\n" \
+ % (name, email, phone)
+
+ def OnCancel(self, evt):
+ self.Close()
+
+
+app = wx.PySimpleApp(redirect=True)
+frm = MyFrame()
+frm.Show()
+app.MainLoop()
--- /dev/null
+<?xml version="1.0" encoding="iso-8859-1"?>
+<resource>
+ <object class="wxPanel" name="ID_PANEL">
+ <object class="wxGridBagSizer">
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>Name:</label>
+ </object>
+ <flag>wxALIGN_RIGHT</flag>
+ <cellpos>1,1</cellpos>
+ </object>
+ <vgap>5</vgap>
+ <hgap>5</hgap>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="ID_NAME">
+ <size>200,-1</size>
+ </object>
+ <flag>wxEXPAND</flag>
+ <cellpos>1,2</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>Email:</label>
+ </object>
+ <flag>wxALIGN_RIGHT</flag>
+ <cellpos>2,1</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="ID_EMAIL"/>
+ <flag>wxEXPAND</flag>
+ <cellpos>2,2</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxStaticText">
+ <label>Phone:</label>
+ </object>
+ <flag>wxALIGN_RIGHT</flag>
+ <cellpos>3,1</cellpos>
+ </object>
+ <object class="sizeritem">
+ <object class="wxTextCtrl" name="ID_PHONE"/>
+ <flag>wxEXPAND</flag>
+ <cellpos>3,2</cellpos>
+ </object>
+ <growablecols>2</growablecols>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <object class="wxStaticLine">
+ <style>wxLI_HORIZONTAL</style>
+ </object>
+ <flag>wxEXPAND|wxALIGN_CENTRE_VERTICAL</flag>
+ </object>
+ </object>
+ <flag>wxEXPAND</flag>
+ <cellpos>5,0</cellpos>
+ <cellspan>1,4</cellspan>
+ </object>
+ <object class="sizeritem">
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="spacer">
+ <size>10,10</size>
+ <option>1</option>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="ID_OK">
+ <label>OK</label>
+ <default>1</default>
+ </object>
+ </object>
+ <object class="spacer">
+ <size>10,10</size>
+ <option>1</option>
+ <flag></flag>
+ </object>
+ <object class="sizeritem">
+ <object class="wxButton" name="ID_CANCEL">
+ <label>Cancel</label>
+ </object>
+ </object>
+ <object class="spacer">
+ <size>10,10</size>
+ <option>1</option>
+ </object>
+ </object>
+ <flag>wxEXPAND</flag>
+ <cellpos>6,0</cellpos>
+ <cellspan>1,4</cellspan>
+ </object>
+ </object>
+ </object>
+</resource>
--- /dev/null
+This directory contains the sample programs that were printed in the
+wxPython In Action book. For details and explainations of each,
+please see the coresponding chapter in the book.
+
+http://www.manning.com/affiliate/idevaffiliate.php?id=189_23
+