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