]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Main.py
use Bind
[wxWidgets.git] / wxPython / demo / Main.py
1 #!/bin/env python
2 #----------------------------------------------------------------------------
3 # Name: Main.py
4 # Purpose: Testing lots of stuff, controls, window types, etc.
5 #
6 # Author: Robin Dunn
7 #
8 # Created: A long time ago, in a galaxy far, far away...
9 # RCS-ID: $Id$
10 # Copyright: (c) 1999 by Total Control Software
11 # Licence: wxWindows license
12 #----------------------------------------------------------------------------
13
14 import sys, os, time
15
16 import wx # This module uses the new wx namespace
17 import wx.html
18
19 import images
20
21 # For debugging
22 ##wx.Trap();
23 ##print os.getpid(); raw_input("Press a key...")
24
25
26 #---------------------------------------------------------------------------
27
28
29 _treeList = [
30 # new stuff
31 ('Recent Additions', [
32 'VListBox',
33 'Listbook',
34 'MaskedNumCtrl',
35 'FloatCanvas',
36 'XmlResourceSubclass',
37 'GridBagSizer',
38 'Cursor',
39 'PyPlot',
40 ]),
41
42 # managed windows == things with a (optional) caption you can close
43 ('Base Frames and Dialogs', [
44 'Dialog',
45 'Frame',
46 'MDIWindows',
47 'MiniFrame',
48 'Wizard',
49 ]),
50
51 # the common dialogs
52 ('Common Dialogs', [
53 'ColourDialog',
54 'DirDialog',
55 'FileDialog',
56 'FileDialog_Save',
57 'FindReplaceDialog',
58 'FontDialog',
59 'MessageDialog',
60 'PageSetupDialog',
61 'PrintDialog',
62 'ProgressDialog',
63 'SingleChoiceDialog',
64 'TextEntryDialog',
65 ]),
66
67 # dialogs from libraries
68 ('More Dialogs', [
69 'ErrorDialogs',
70 'ImageBrowser',
71 'MultipleChoiceDialog',
72 'ScrolledMessageDialog',
73 ]),
74
75 # core controls
76 ('Core Windows/Controls', [
77 'Button',
78 'CheckBox',
79 'CheckListBox',
80 'Choice',
81 'ComboBox',
82 'Gauge',
83 'Grid',
84 'Grid_MegaExample',
85 'ListBox',
86 'ListCtrl',
87 'ListCtrl_virtual',
88 'Listbook',
89 'Menu',
90 'Notebook',
91 'PopupMenu',
92 'PopupWindow',
93 'RadioBox',
94 'RadioButton',
95 'SashWindow',
96 'ScrolledWindow',
97 'Slider',
98 'SpinButton',
99 'SpinCtrl',
100 'SplitterWindow',
101 'StaticBitmap',
102 'StaticText',
103 'StatusBar',
104 'TextCtrl',
105 'ToggleButton',
106 'ToolBar',
107 'TreeCtrl',
108 'Validator',
109 ]),
110
111 ('Custom Controls', [
112 'AnalogClockWindow',
113 'ColourSelect',
114 'Editor',
115 'GenericButtons',
116 'GenericDirCtrl',
117 'LEDNumberCtrl',
118 'MultiSash',
119 'PopupControl',
120 'PyColourChooser',
121 'TreeListCtrl',
122 ]),
123
124 # controls coming from other libraries
125 ('More Windows/Controls', [
126 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
127 'Calendar',
128 'CalendarCtrl',
129 'ContextHelp',
130 'DynamicSashWindow',
131 'EditableListBox',
132 'FancyText',
133 'FileBrowseButton',
134 'FloatBar',
135 'FloatCanvas',
136 'HtmlWindow',
137 'IEHtmlWin',
138 'IntCtrl',
139 'MVCTree',
140 'MaskedEditControls',
141 'MaskedNumCtrl',
142 'MimeTypesManager',
143 'PyCrust',
144 'PyPlot',
145 'PyShell',
146 'ScrolledPanel',
147 'SplitTree',
148 'StyledTextCtrl_1',
149 'StyledTextCtrl_2',
150 'TablePrint',
151 'Throbber',
152 'TimeCtrl',
153 'VListBox',
154 ]),
155
156 # How to lay out the controls in a frame/dialog
157 ('Window Layout', [
158 'GridBagSizer',
159 'LayoutAnchors',
160 'LayoutConstraints',
161 'Layoutf',
162 'RowColSizer',
163 'ScrolledPanel',
164 'Sizers',
165 'XmlResource',
166 'XmlResourceHandler',
167 'XmlResourceSubclass',
168 ]),
169
170 # ditto
171 ('Process and Events', [
172 'EventManager',
173 'KeyEvents',
174 'OOR',
175 'Process',
176 'PythonEvents',
177 'Threads',
178 'Timer',
179 'infoframe',
180 ]),
181
182 # Clipboard and DnD
183 ('Clipboard and DnD', [
184 'CustomDragAndDrop',
185 'DragAndDrop',
186 'URLDragAndDrop',
187 ]),
188
189 # Images
190 ('Using Images', [
191 'ArtProvider',
192 'Cursor',
193 'DragImage',
194 'Image',
195 'ImageFromStream',
196 'Mask',
197 'Throbber',
198 ]),
199
200 # Other stuff
201 ('Miscellaneous', [
202 'ColourDB',
203 'DialogUnits',
204 'DrawXXXList',
205 'FileHistory',
206 'FontEnumerator',
207 'Joystick',
208 'NewNamespace',
209 'OGL',
210 'PrintFramework',
211 'ShapedWindow',
212 'Unicode',
213 'Wave',
214 ]),
215
216 # need libs not coming with the demo
217 ('Objects using an external library', [
218 'ActiveXWrapper_Acrobat',
219 'ActiveXWrapper_IE',
220 'GLCanvas',
221 #'PlotCanvas', # deprecated, use PyPlot
222 ]),
223
224
225 ('Check out the samples dir too', [
226 ]),
227
228 ]
229
230
231
232 #---------------------------------------------------------------------------
233 # Show how to derive a custom wxLog class
234
235 class MyLog(wx.PyLog):
236 def __init__(self, textCtrl, logTime=0):
237 wx.PyLog.__init__(self)
238 self.tc = textCtrl
239 self.logTime = logTime
240
241 def DoLogString(self, message, timeStamp):
242 if self.logTime:
243 message = time.strftime("%X", time.localtime(timeStamp)) + \
244 ": " + message
245 if self.tc:
246 self.tc.AppendText(message + '\n')
247
248
249 class MyTP(wx.PyTipProvider):
250 def GetTip(self):
251 return "This is my tip"
252
253 #---------------------------------------------------------------------------
254 # A class to be used to display source code in the demo. Try using the
255 # wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
256 # if there is an error, such as the stc module not being present.
257 #
258
259 try:
260 ##raise ImportError
261 from wx import stc
262 from StyledTextCtrl_2 import PythonSTC
263 class DemoCodeViewer(PythonSTC):
264 def __init__(self, parent, ID):
265 PythonSTC.__init__(self, parent, ID)
266 self.SetUpEditor()
267
268 # Some methods to make it compatible with how the wxTextCtrl is used
269 def SetValue(self, value):
270 self.SetReadOnly(False)
271 self.SetText(value)
272 self.SetReadOnly(True)
273
274 def Clear(self):
275 self.ClearAll()
276
277 def SetInsertionPoint(self, pos):
278 self.SetCurrentPos(pos)
279
280 def ShowPosition(self, pos):
281 self.GotoPos(pos)
282
283 def GetLastPosition(self):
284 return self.GetLength()
285
286 def GetRange(self, start, end):
287 return self.GetTextRange(start, end)
288
289 def GetSelection(self):
290 return self.GetAnchor(), self.GetCurrentPos()
291
292 def SetSelection(self, start, end):
293 self.SetSelectionStart(start)
294 self.SetSelectionEnd(end)
295
296 def SetUpEditor(self):
297 """
298 This method carries out the work of setting up the demo editor.
299 It's seperate so as not to clutter up the init code.
300 """
301 import keyword
302
303 self.SetLexer(stc.STC_LEX_PYTHON)
304 self.SetKeyWords(0, " ".join(keyword.kwlist))
305
306 # Enable folding
307 self.SetProperty("fold", "1" )
308
309 # Highlight tab/space mixing (shouldn't be any)
310 self.SetProperty("tab.timmy.whinge.level", "1")
311
312 # Set left and right margins
313 self.SetMargins(2,2)
314
315 # Set up the numbers in the margin for margin #1
316 self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
317 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
318 self.SetMarginWidth(1, 40)
319
320 # Indentation and tab stuff
321 self.SetIndent(4) # Proscribed indent size for wx
322 self.SetIndentationGuides(True) # Show indent guides
323 self.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
324 self.SetTabIndents(True) # Tab key indents
325 self.SetTabWidth(4) # Proscribed tab size for wx
326 self.SetUseTabs(False) # Use spaces rather than tabs, or
327 # TabTimmy will complain!
328 # White space
329 self.SetViewWhiteSpace(False) # Don't view white space
330
331 # EOL
332 #self.SetEOLMode(wx.stc.STC_EOL_CRLF) # Just leave it at the default (autosense)
333 self.SetViewEOL(False)
334 # No right-edge mode indicator
335 self.SetEdgeMode(stc.STC_EDGE_NONE)
336
337 # Setup a margin to hold fold markers
338 self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
339 self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
340 self.SetMarginSensitive(2, True)
341 self.SetMarginWidth(2, 12)
342
343 # and now set up the fold markers
344 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "black")
345 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "black")
346 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "black")
347 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "black")
348 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "black")
349 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "black")
350 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "black")
351
352 # Global default style
353 if wx.Platform == '__WXMSW__':
354 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
355 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
356 else:
357 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
358 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
359
360 # Clear styles and revert to default.
361 self.StyleClearAll()
362
363 # Following style specs only indicate differences from default.
364 # The rest remains unchanged.
365
366 # Line numbers in margin
367 self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
368
369 # Highlighted brace
370 self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
371 # Unmatched brace
372 self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
373 # Indentation guide
374 self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
375
376 # Python styles
377 self.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
378 # Comments
379 self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
380 self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
381 # Numbers
382 self.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
383 # Strings and characters
384 self.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
385 self.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
386 # Keywords
387 self.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
388 # Triple quotes
389 self.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
390 self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
391 # Class names
392 self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
393 # Function names
394 self.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
395 # Operators
396 self.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
397 # Identifiers. I leave this as not bold because everything seems
398 # to be an identifier if it doesn't match the above criterae
399 self.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
400
401 # Caret color
402 self.SetCaretForeground("BLUE")
403 # Selection background
404 self.SetSelBackground(1, '#66CCFF')
405
406 self.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
407 self.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
408
409
410 except ImportError:
411 class DemoCodeViewer(wx.TextCtrl):
412 def __init__(self, parent, ID):
413 wx.TextCtrl.__init__(self, parent, ID, style =
414 wx.TE_MULTILINE | wx.TE_READONLY |
415 wx.HSCROLL | wx.TE_RICH2 | wx.TE_NOHIDESEL)
416
417
418 #---------------------------------------------------------------------------
419
420 def opj(path):
421 """Convert paths to the platform-specific separator"""
422 return apply(os.path.join, tuple(path.split('/')))
423
424
425 #---------------------------------------------------------------------------
426
427 class wxPythonDemo(wx.Frame):
428 overviewText = "wxPython Overview"
429
430 def __init__(self, parent, id, title):
431 wx.Frame.__init__(self, parent, -1, title, size = (800, 600),
432 style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
433
434 self.cwd = os.getcwd()
435 self.curOverview = ""
436 self.window = None
437
438 icon = images.getMondrianIcon()
439 self.SetIcon(icon)
440
441 if wx.Platform != '__WXMAC__':
442 # setup a taskbar icon, and catch some events from it
443 icon = wx.IconFromBitmap(
444 images.getMondrianImage().Scale(16,16).ConvertToBitmap() )
445 self.tbicon = wx.TaskBarIcon()
446 self.tbicon.SetIcon(icon, "wxPython Demo")
447 self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
448 self.tbicon.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.OnTaskBarMenu)
449 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
450 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
451
452 wx.CallAfter(self.ShowTip)
453
454 self.otherWin = None
455 self.Bind(wx.EVT_IDLE, self.OnIdle)
456 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
457 self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)
458 self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize)
459
460 self.Centre(wx.BOTH)
461 self.CreateStatusBar(1, wx.ST_SIZEGRIP)
462
463 splitter = wx.SplitterWindow(self, -1)
464 splitter2 = wx.SplitterWindow(splitter, -1)
465
466 def EmptyHandler(evt): pass
467 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
468 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
469
470 # Prevent TreeCtrl from displaying all items after destruction when True
471 self.dying = False
472
473 # Make a File menu
474 self.mainmenu = wx.MenuBar()
475 menu = wx.Menu()
476 exitID = wx.NewId()
477 menu.Append(exitID, 'E&xit\tAlt-X', 'Get the heck outta here!')
478 self.Bind(wx.EVT_MENU, self.OnFileExit, id=exitID)
479 wx.App_SetMacExitMenuItemId(exitID)
480 self.mainmenu.Append(menu, '&File')
481
482 # Make a Demo menu
483 menu = wx.Menu()
484 for item in _treeList:
485 submenu = wx.Menu()
486 for childItem in item[1]:
487 mID = wx.NewId()
488 submenu.Append(mID, childItem)
489 self.Bind(wx.EVT_MENU, self.OnDemoMenu, id=mID)
490 menu.AppendMenu(wx.NewId(), item[0], submenu)
491 self.mainmenu.Append(menu, '&Demo')
492
493
494 # Make a Help menu
495 helpID = wx.NewId()
496 findID = wx.NewId()
497 findnextID = wx.NewId()
498 menu = wx.Menu()
499 menu.Append(findID, '&Find\tCtrl-F', 'Find in the Demo Code')
500 menu.Append(findnextID, 'Find &Next\tF3', 'Find Next')
501 menu.AppendSeparator()
502 menu.Append(helpID, '&About\tCtrl-H', 'wxPython RULES!!!')
503 wx.App_SetMacAboutMenuItemId(helpID)
504 self.Bind(wx.EVT_MENU, self.OnHelpAbout, id=helpID)
505 self.Bind(wx.EVT_MENU, self.OnHelpFind, id=findID)
506 self.Bind(wx.EVT_MENU, self.OnFindNext, id=findnextID)
507 self.Bind(wx.EVT_COMMAND_FIND, self.OnFind)
508 self.Bind(wx.EVT_COMMAND_FIND_NEXT, self.OnFind)
509 self.Bind(wx.EVT_COMMAND_FIND_CLOSE, self.OnFindClose)
510 self.mainmenu.Append(menu, '&Help')
511 self.SetMenuBar(self.mainmenu)
512
513 self.finddata = wx.FindReplaceData()
514
515 if 0:
516 # This is another way to set Accelerators, in addition to
517 # using the '\t<key>' syntax in the menu items.
518 aTable = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), exitID),
519 (wx.ACCEL_CTRL, ord('H'), helpID),
520 (wx.ACCEL_CTRL, ord('F'), findID),
521 (wx.ACCEL_NORMAL, WXK_F3, findnextID)
522 ])
523 self.SetAcceleratorTable(aTable)
524
525
526 # Create a TreeCtrl
527 tID = wx.NewId()
528 self.treeMap = {}
529 self.tree = wx.TreeCtrl(splitter, tID, style =
530 wx.TR_DEFAULT_STYLE #| wx.TR_HAS_VARIABLE_ROW_HEIGHT
531 )
532
533 root = self.tree.AddRoot("wxPython Overview")
534 firstChild = None
535 for item in _treeList:
536 child = self.tree.AppendItem(root, item[0])
537 if not firstChild: firstChild = child
538 for childItem in item[1]:
539 theDemo = self.tree.AppendItem(child, childItem)
540 self.treeMap[childItem] = theDemo
541
542 self.tree.Expand(root)
543 self.tree.Expand(firstChild)
544 self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, id=tID)
545 self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=tID)
546 self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=tID)
547 self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
548
549 # Create a Notebook
550 self.nb = wx.Notebook(splitter2, -1, style=wx.CLIP_CHILDREN)
551
552 # Set up a wx.html.HtmlWindow on the Overview Notebook page
553 # we put it in a panel first because there seems to be a
554 # refresh bug of some sort (wxGTK) when it is directly in
555 # the notebook...
556 if 0: # the old way
557 self.ovr = wx.html.HtmlWindow(self.nb, -1, size=(400, 400))
558 self.nb.AddPage(self.ovr, self.overviewText)
559
560 else: # hopefully I can remove this hacky code soon, see SF bug #216861
561 panel = wx.Panel(self.nb, -1, style=wx.CLIP_CHILDREN)
562 self.ovr = wx.html.HtmlWindow(panel, -1, size=(400, 400))
563 self.nb.AddPage(panel, self.overviewText)
564
565 def OnOvrSize(evt, ovr=self.ovr):
566 ovr.SetSize(evt.GetSize())
567
568 panel.Bind(wx.EVT_SIZE, OnOvrSize)
569 panel.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
570
571
572 self.SetOverview(self.overviewText, overview)
573
574
575 # Set up a notebook page for viewing the source code of each sample
576 self.txt = DemoCodeViewer(self.nb, -1)
577 self.nb.AddPage(self.txt, "Demo Code")
578 self.LoadDemoSource('Main.py')
579
580
581 # Set up a log on the View Log Notebook page
582 self.log = wx.TextCtrl(splitter2, -1,
583 style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
584
585 # Set the wxWindows log target to be this textctrl
586 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
587
588 # But instead of the above we want to show how to use our own wx.Log class
589 wx.Log_SetActiveTarget(MyLog(self.log))
590
591 # for serious debugging
592 #wx.Log_SetActiveTarget(wx.LogStderr())
593 #wx.Log_SetTraceMask(wx.TraceMessages)
594
595
596 # add the windows to the splitter and split it.
597 splitter2.SplitHorizontally(self.nb, self.log, -120)
598 splitter.SplitVertically(self.tree, splitter2, 180)
599
600 splitter.SetMinimumPaneSize(20)
601 splitter2.SetMinimumPaneSize(20)
602
603
604 # Make the splitter on the right expand the top wind when resized
605 def SplitterOnSize(evt):
606 splitter = evt.GetEventObject()
607 sz = splitter.GetSize()
608 splitter.SetSashPosition(sz.height - 120, False)
609 evt.Skip()
610
611 splitter2.Bind(wx.EVT_SIZE, SplitterOnSize)
612
613
614 # select initial items
615 self.nb.SetSelection(0)
616 self.tree.SelectItem(root)
617
618 if len(sys.argv) == 2:
619 try:
620 selectedDemo = self.treeMap[sys.argv[1]]
621 except:
622 selectedDemo = None
623 if selectedDemo:
624 self.tree.SelectItem(selectedDemo)
625 self.tree.EnsureVisible(selectedDemo)
626
627
628 wx.LogMessage('window handle: %s' % self.GetHandle())
629
630
631 #---------------------------------------------
632 def WriteText(self, text):
633 if text[-1:] == '\n':
634 text = text[:-1]
635 wx.LogMessage(text)
636
637
638 def write(self, txt):
639 self.WriteText(txt)
640
641 #---------------------------------------------
642 def OnItemExpanded(self, event):
643 item = event.GetItem()
644 wx.LogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
645 event.Skip()
646
647 #---------------------------------------------
648 def OnItemCollapsed(self, event):
649 item = event.GetItem()
650 wx.LogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
651 event.Skip()
652
653 #---------------------------------------------
654 def OnTreeLeftDown(self, event):
655 pt = event.GetPosition();
656 item, flags = self.tree.HitTest(pt)
657 if item == self.tree.GetSelection():
658 self.SetOverview(self.tree.GetItemText(item)+" Overview", self.curOverview)
659 event.Skip()
660
661 #---------------------------------------------
662 def OnSelChanged(self, event):
663 if self.dying:
664 return
665
666 item = event.GetItem()
667 itemText = self.tree.GetItemText(item)
668 self.RunDemo(itemText)
669
670
671 #---------------------------------------------
672 def RunDemo(self, itemText):
673 os.chdir(self.cwd)
674 if self.nb.GetPageCount() == 3:
675 if self.nb.GetSelection() == 2:
676 self.nb.SetSelection(0)
677 # inform the window that it's time to quit if it cares
678 if self.window is not None:
679 if hasattr(self.window, "ShutdownDemo"):
680 self.window.ShutdownDemo()
681 wx.SafeYield() # in case the page has pending events
682 self.nb.DeletePage(2)
683
684 if itemText == self.overviewText:
685 self.LoadDemoSource('Main.py')
686 self.SetOverview(self.overviewText, overview)
687 self.nb.Refresh();
688 self.window = None
689
690 else:
691 if os.path.exists(itemText + '.py'):
692 wx.BeginBusyCursor()
693 wx.LogMessage("Running demo %s.py..." % itemText)
694 try:
695 self.LoadDemoSource(itemText + '.py')
696
697 if (sys.modules.has_key(itemText)):
698 reload(sys.modules[itemText])
699
700 module = __import__(itemText, globals())
701 self.SetOverview(itemText + " Overview", module.overview)
702 finally:
703 wx.EndBusyCursor()
704 self.tree.Refresh()
705
706 # in case runTest is modal, make sure things look right...
707 self.nb.Refresh();
708 wx.SafeYield()
709
710 self.window = module.runTest(self, self.nb, self) ###
711 if self.window is not None:
712 self.nb.AddPage(self.window, 'Demo')
713 self.nb.SetSelection(2)
714 self.nb.Refresh() # without this wxMac has troubles showing the just added page
715
716 else:
717 self.ovr.SetPage("")
718 self.txt.Clear()
719 self.window = None
720
721
722
723 #---------------------------------------------
724 # Get the Demo files
725 def LoadDemoSource(self, filename):
726 self.txt.Clear()
727 try:
728 self.txt.SetValue(open(filename).read())
729 except IOError:
730 self.txt.SetValue("Cannot open %s file." % filename)
731
732 self.txt.SetInsertionPoint(0)
733 self.txt.ShowPosition(0)
734
735 #---------------------------------------------
736 def SetOverview(self, name, text):
737 self.curOverview = text
738 lead = text[:6]
739 if lead != '<html>' and lead != '<HTML>':
740 text = '<br>'.join(text.split('\n'))
741 self.ovr.SetPage(text)
742 self.nb.SetPageText(0, name)
743
744 #---------------------------------------------
745 # Menu methods
746 def OnFileExit(self, *event):
747 self.Close()
748
749 def OnHelpAbout(self, event):
750 from About import MyAboutBox
751 about = MyAboutBox(self)
752 about.ShowModal()
753 about.Destroy()
754
755 def OnHelpFind(self, event):
756 self.nb.SetSelection(1)
757 self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find",
758 wx.FR_NOUPDOWN |
759 wx.FR_NOMATCHCASE |
760 wx.FR_NOWHOLEWORD)
761 self.finddlg.Show(True)
762
763 def OnFind(self, event):
764 self.nb.SetSelection(1)
765 end = self.txt.GetLastPosition()
766 textstring = self.txt.GetRange(0, end).lower()
767 start = self.txt.GetSelection()[1]
768 findstring = self.finddata.GetFindString().lower()
769 loc = textstring.find(findstring, start)
770 if loc == -1 and start != 0:
771 # string not found, start at beginning
772 start = 0
773 loc = textstring.find(findstring, start)
774 if loc == -1:
775 dlg = wx.MessageDialog(self, 'Find String Not Found',
776 'Find String Not Found in Demo File',
777 wx.OK | wx.ICON_INFORMATION)
778 dlg.ShowModal()
779 dlg.Destroy()
780 if self.finddlg:
781 if loc == -1:
782 self.finddlg.SetFocus()
783 return
784 else:
785 self.finddlg.Destroy()
786 self.txt.ShowPosition(loc)
787 self.txt.SetSelection(loc, loc + len(findstring))
788
789
790
791 def OnFindNext(self, event):
792 if self.finddata.GetFindString():
793 self.OnFind(event)
794 else:
795 self.OnHelpFind(event)
796
797 def OnFindClose(self, event):
798 event.GetDialog().Destroy()
799
800
801 #---------------------------------------------
802 def OnCloseWindow(self, event):
803 self.dying = True
804 self.window = None
805 self.mainmenu = None
806 if hasattr(self, "tbicon"):
807 del self.tbicon
808 self.Destroy()
809
810
811 #---------------------------------------------
812 def OnIdle(self, event):
813 if self.otherWin:
814 self.otherWin.Raise()
815 self.window = self.otherWin
816 self.otherWin = None
817
818
819 #---------------------------------------------
820 def ShowTip(self):
821 try:
822 showTipText = open(opj("data/showTips")).read()
823 showTip, index = eval(showTipText)
824 except IOError:
825 showTip, index = (1, 0)
826 if showTip:
827 tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index)
828 ##tp = MyTP(0)
829 showTip = wx.ShowTip(self, tp)
830 index = tp.GetCurrentTip()
831 open(opj("data/showTips"), "w").write(str( (showTip, index) ))
832
833
834 #---------------------------------------------
835 def OnDemoMenu(self, event):
836 try:
837 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
838 except:
839 selectedDemo = None
840 if selectedDemo:
841 self.tree.SelectItem(selectedDemo)
842 self.tree.EnsureVisible(selectedDemo)
843
844
845 #---------------------------------------------
846 def OnTaskBarActivate(self, evt):
847 if self.IsIconized():
848 self.Iconize(False)
849 if not self.IsShown():
850 self.Show(True)
851 self.Raise()
852
853 #---------------------------------------------
854
855 TBMENU_RESTORE = 1000
856 TBMENU_CLOSE = 1001
857
858 def OnTaskBarMenu(self, evt):
859 menu = wx.Menu()
860 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
861 menu.Append(self.TBMENU_CLOSE, "Close")
862 self.tbicon.PopupMenu(menu)
863 menu.Destroy()
864
865 #---------------------------------------------
866 def OnTaskBarClose(self, evt):
867 self.Close()
868
869 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
870 # prod the main idle handler a bit to get the window to actually close
871 wx.GetApp().ProcessIdle()
872
873
874 #---------------------------------------------
875 def OnIconfiy(self, evt):
876 wx.LogMessage("OnIconfiy")
877 evt.Skip()
878
879 #---------------------------------------------
880 def OnMaximize(self, evt):
881 wx.LogMessage("OnMaximize")
882 evt.Skip()
883
884
885
886
887 #---------------------------------------------------------------------------
888 #---------------------------------------------------------------------------
889
890 class MySplashScreen(wx.SplashScreen):
891 def __init__(self):
892 bmp = wx.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
893 wx.SplashScreen.__init__(self, bmp,
894 wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
895 3000, None, -1)
896 self.Bind(wx.EVT_CLOSE, self.OnClose)
897
898 def OnClose(self, evt):
899 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
900 frame.Show()
901 evt.Skip() # Make sure the default handler runs too...
902
903
904 class MyApp(wx.App):
905 def OnInit(self):
906 """
907 Create and show the splash screen. It will then create and show
908 the main frame when it is time to do so.
909 """
910
911 wx.InitAllImageHandlers()
912
913 # Normally when using a SplashScreen you would create it, show
914 # it and then continue on with the applicaiton's
915 # initialization, finally creating and showing the main
916 # application window(s). In this case we have nothing else to
917 # do so we'll delay showing the main frame until later (see
918 # OnClose above) so the users can see the SplashScrren effect.
919 splash = MySplashScreen()
920 splash.Show()
921
922 return True
923
924
925
926 #---------------------------------------------------------------------------
927
928 def main():
929 try:
930 demoPath = os.path.dirname(__file__)
931 os.chdir(demoPath)
932 except:
933 pass
934 app = MyApp(0) #wx.Platform == "__WXMAC__")
935 app.MainLoop()
936
937
938 #---------------------------------------------------------------------------
939
940
941
942 overview = """<html><body>
943 <h2>wxPython</h2>
944
945 <p> wxPython is a <b>GUI toolkit</b> for the <a
946 href="http://www.python.org/">Python</a> programming language. It
947 allows Python programmers to create programs with a robust, highly
948 functional graphical user interface, simply and easily. It is
949 implemented as a Python extension module (native code) that wraps the
950 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
951 platform GUI library, which is written in C++.
952
953 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
954 means that it is free for anyone to use and the source code is
955 available for anyone to look at and modify. Or anyone can contribute
956 fixes or enhancements to the project.
957
958 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
959 same program will run on multiple platforms without modification.
960 Currently supported platforms are 32-bit Microsoft Windows, most Unix
961 or unix-like systems, and Macintosh OS X. Since the language is
962 Python, wxPython programs are <b>simple, easy</b> to write and easy to
963 understand.
964
965 <p> <b>This demo</b> is not only a collection of test cases for
966 wxPython, but is also designed to help you learn about and how to use
967 wxPython. Each sample is listed in the tree control on the left.
968 When a sample is selected in the tree then a module is loaded and run
969 (usually in a tab of this notebook,) and the source code of the module
970 is loaded in another tab for you to browse and learn from.
971
972 """
973
974
975 #----------------------------------------------------------------------------
976 #----------------------------------------------------------------------------
977
978 if __name__ == '__main__':
979 main()
980
981 #----------------------------------------------------------------------------
982
983
984
985
986
987
988