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