]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Main.py
ba79bc8e44e569b45694afc0eb4e3f10fdc5c753
[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/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 # for testing the alternate implementation
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 dim = 16 # (may want to use 22 on wxGTK...)
439 icon = wx.IconFromBitmap(
440 images.getMondrianImage().Scale(dim,dim).ConvertToBitmap() )
441 #icon = wx.Icon('bmp_source/mondrian.ico', wx.BITMAP_TYPE_ICO)
442 #icon = images.getMondrianIcon()
443 self.tbicon = wx.TaskBarIcon()
444 self.tbicon.SetIcon(icon, "wxPython Demo")
445 self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
446 self.tbicon.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.OnTaskBarMenu)
447 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
448 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
449
450 wx.CallAfter(self.ShowTip)
451
452 self.otherWin = None
453 self.Bind(wx.EVT_IDLE, self.OnIdle)
454 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
455 self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)
456 self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize)
457
458 self.Centre(wx.BOTH)
459 self.CreateStatusBar(1, wx.ST_SIZEGRIP)
460
461 splitter = wx.SplitterWindow(self, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D)
462 splitter2 = wx.SplitterWindow(splitter, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D)
463
464 # Set up a log on the View Log Notebook page
465 self.log = wx.TextCtrl(splitter2, -1,
466 style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
467
468 # Set the wxWindows log target to be this textctrl
469 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
470
471 # But instead of the above we want to show how to use our own wx.Log class
472 wx.Log_SetActiveTarget(MyLog(self.log))
473
474 # for serious debugging
475 #wx.Log_SetActiveTarget(wx.LogStderr())
476 #wx.Log_SetTraceMask(wx.TraceMessages)
477
478
479
480 def EmptyHandler(evt): pass
481 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
482 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
483
484 # Prevent TreeCtrl from displaying all items after destruction when True
485 self.dying = False
486
487 # Make a File menu
488 self.mainmenu = wx.MenuBar()
489 menu = wx.Menu()
490 item = menu.Append(-1, '&Redirect Output',
491 'Redirect print statements to a window',
492 wx.ITEM_CHECK)
493 self.Bind(wx.EVT_MENU, self.OnToggleRedirect, item)
494
495 item = menu.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
496 self.Bind(wx.EVT_MENU, self.OnFileExit, item)
497 wx.App_SetMacExitMenuItemId(item.GetId())
498
499 self.mainmenu.Append(menu, '&File')
500
501 # Make a Demo menu
502 menu = wx.Menu()
503 for item in _treeList:
504 submenu = wx.Menu()
505 for childItem in item[1]:
506 mi = submenu.Append(-1, childItem)
507 self.Bind(wx.EVT_MENU, self.OnDemoMenu, mi)
508 menu.AppendMenu(wx.NewId(), item[0], submenu)
509 self.mainmenu.Append(menu, '&Demo')
510
511
512 # Make a Help menu
513 helpID = wx.NewId()
514 findID = wx.NewId()
515 findnextID = wx.NewId()
516 menu = wx.Menu()
517 findItem = menu.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
518 findnextItem = menu.Append(-1, 'Find &Next\tF3', 'Find Next')
519 menu.AppendSeparator()
520 helpItem = menu.Append(-1, '&About\tCtrl-H', 'wxPython RULES!!!')
521 wx.App_SetMacAboutMenuItemId(helpItem.GetId())
522 self.Bind(wx.EVT_MENU, self.OnHelpAbout, helpItem)
523 self.Bind(wx.EVT_MENU, self.OnHelpFind, findItem)
524 self.Bind(wx.EVT_MENU, self.OnFindNext, findnextItem)
525 self.Bind(wx.EVT_COMMAND_FIND, self.OnFind)
526 self.Bind(wx.EVT_COMMAND_FIND_NEXT, self.OnFind)
527 self.Bind(wx.EVT_COMMAND_FIND_CLOSE, self.OnFindClose)
528 self.mainmenu.Append(menu, '&Help')
529 self.SetMenuBar(self.mainmenu)
530
531 self.finddata = wx.FindReplaceData()
532
533 if 0:
534 # This is another way to set Accelerators, in addition to
535 # using the '\t<key>' syntax in the menu items.
536 aTable = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), exitID),
537 (wx.ACCEL_CTRL, ord('H'), helpID),
538 (wx.ACCEL_CTRL, ord('F'), findID),
539 (wx.ACCEL_NORMAL, WXK_F3, findnextID)
540 ])
541 self.SetAcceleratorTable(aTable)
542
543
544 # Create a TreeCtrl
545 tID = wx.NewId()
546 self.treeMap = {}
547 self.tree = wx.TreeCtrl(splitter, tID, style =
548 wx.TR_DEFAULT_STYLE #| wx.TR_HAS_VARIABLE_ROW_HEIGHT
549 )
550
551 root = self.tree.AddRoot("wxPython Overview")
552 firstChild = None
553 for item in _treeList:
554 child = self.tree.AppendItem(root, item[0])
555 if not firstChild: firstChild = child
556 for childItem in item[1]:
557 theDemo = self.tree.AppendItem(child, childItem)
558 self.treeMap[childItem] = theDemo
559
560 self.tree.Expand(root)
561 self.tree.Expand(firstChild)
562 self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, id=tID)
563 self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=tID)
564 self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=tID)
565 self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
566
567 # Create a Notebook
568 self.nb = wx.Notebook(splitter2, -1, style=wx.CLIP_CHILDREN)
569
570 # Set up a wx.html.HtmlWindow on the Overview Notebook page
571 # we put it in a panel first because there seems to be a
572 # refresh bug of some sort (wxGTK) when it is directly in
573 # the notebook...
574 if 0: # the old way
575 self.ovr = wx.html.HtmlWindow(self.nb, -1, size=(400, 400))
576 self.nb.AddPage(self.ovr, self.overviewText)
577
578 else: # hopefully I can remove this hacky code soon, see SF bug #216861
579 panel = wx.Panel(self.nb, -1, style=wx.CLIP_CHILDREN)
580 self.ovr = wx.html.HtmlWindow(panel, -1, size=(400, 400))
581 self.nb.AddPage(panel, self.overviewText)
582
583 def OnOvrSize(evt, ovr=self.ovr):
584 ovr.SetSize(evt.GetSize())
585
586 panel.Bind(wx.EVT_SIZE, OnOvrSize)
587 panel.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
588
589
590 self.SetOverview(self.overviewText, overview)
591
592
593 # Set up a notebook page for viewing the source code of each sample
594 self.txt = DemoCodeViewer(self.nb, -1)
595 self.nb.AddPage(self.txt, "Demo Code")
596 self.LoadDemoSource('Main.py')
597
598
599 # add the windows to the splitter and split it.
600 splitter2.SplitHorizontally(self.nb, self.log, -120)
601 splitter.SplitVertically(self.tree, splitter2, 180)
602
603 splitter.SetMinimumPaneSize(20)
604 splitter2.SetMinimumPaneSize(20)
605
606
607 # Make the splitter on the right expand the top window when resized
608 def SplitterOnSize(evt):
609 splitter = evt.GetEventObject()
610 sz = splitter.GetSize()
611 splitter.SetSashPosition(sz.height - 120, False)
612 evt.Skip()
613
614 splitter2.Bind(wx.EVT_SIZE, SplitterOnSize)
615
616
617 # select initial items
618 self.nb.SetSelection(0)
619 self.tree.SelectItem(root)
620
621 if len(sys.argv) == 2:
622 try:
623 selectedDemo = self.treeMap[sys.argv[1]]
624 except:
625 selectedDemo = None
626 if selectedDemo:
627 self.tree.SelectItem(selectedDemo)
628 self.tree.EnsureVisible(selectedDemo)
629
630
631 ## wx.LogMessage('window handle: %s' % self.GetHandle())
632
633
634 #---------------------------------------------
635 def WriteText(self, text):
636 if text[-1:] == '\n':
637 text = text[:-1]
638 wx.LogMessage(text)
639
640
641 def write(self, txt):
642 self.WriteText(txt)
643
644 #---------------------------------------------
645 def OnItemExpanded(self, event):
646 item = event.GetItem()
647 wx.LogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
648 event.Skip()
649
650 #---------------------------------------------
651 def OnItemCollapsed(self, event):
652 item = event.GetItem()
653 wx.LogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
654 event.Skip()
655
656 #---------------------------------------------
657 def OnTreeLeftDown(self, event):
658 pt = event.GetPosition();
659 item, flags = self.tree.HitTest(pt)
660 if item == self.tree.GetSelection():
661 self.SetOverview(self.tree.GetItemText(item)+" Overview", self.curOverview)
662 event.Skip()
663
664 #---------------------------------------------
665 def OnSelChanged(self, event):
666 if self.dying:
667 return
668
669 item = event.GetItem()
670 itemText = self.tree.GetItemText(item)
671 self.RunDemo(itemText)
672
673
674 #---------------------------------------------
675 def RunDemo(self, itemText):
676 os.chdir(self.cwd)
677 if self.nb.GetPageCount() == 3:
678 if self.nb.GetSelection() == 2:
679 self.nb.SetSelection(0)
680 # inform the window that it's time to quit if it cares
681 if self.window is not None:
682 if hasattr(self.window, "ShutdownDemo"):
683 self.window.ShutdownDemo()
684 wx.SafeYield() # in case the page has pending events
685 self.nb.DeletePage(2)
686
687 if itemText == self.overviewText:
688 self.LoadDemoSource('Main.py')
689 self.SetOverview(self.overviewText, overview)
690 self.window = None
691
692 else:
693 if os.path.exists(itemText + '.py'):
694 wx.BeginBusyCursor()
695 wx.LogMessage("Running demo %s.py..." % itemText)
696 try:
697 self.LoadDemoSource(itemText + '.py')
698
699 if (sys.modules.has_key(itemText)):
700 reload(sys.modules[itemText])
701
702 module = __import__(itemText, globals())
703 self.SetOverview(itemText + " Overview", module.overview)
704 finally:
705 wx.EndBusyCursor()
706 self.tree.Refresh()
707
708 self.window = module.runTest(self, self.nb, self) ###
709 if self.window is not None:
710 self.nb.AddPage(self.window, 'Demo')
711 self.nb.SetSelection(2)
712
713 else:
714 self.ovr.SetPage("")
715 self.txt.Clear()
716 self.window = None
717
718 self.tree.SetFocus()
719
720
721 #---------------------------------------------
722 # Get the Demo files
723 def LoadDemoSource(self, filename):
724 self.txt.Clear()
725 try:
726 self.txt.SetValue(open(filename).read())
727 except IOError:
728 self.txt.SetValue("Cannot open %s file." % filename)
729
730 self.txt.SetInsertionPoint(0)
731 self.txt.ShowPosition(0)
732
733 #---------------------------------------------
734 def SetOverview(self, name, text):
735 self.curOverview = text
736 lead = text[:6]
737 if lead != '<html>' and lead != '<HTML>':
738 text = '<br>'.join(text.split('\n'))
739 self.ovr.SetPage(text)
740 self.nb.SetPageText(0, name)
741
742 #---------------------------------------------
743 # Menu methods
744 def OnFileExit(self, *event):
745 self.Close()
746
747 def OnToggleRedirect(self, event):
748 app = wx.GetApp()
749 if event.Checked():
750 app.RedirectStdio()
751 print "Print statements and other standard output will now be directed to this window."
752 else:
753 app.RestoreStdio()
754 print "Print statements and other standard output will now be sent to the usual location."
755
756 def OnHelpAbout(self, event):
757 from About import MyAboutBox
758 about = MyAboutBox(self)
759 about.ShowModal()
760 about.Destroy()
761
762 def OnHelpFind(self, event):
763 self.nb.SetSelection(1)
764 self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find",
765 wx.FR_NOUPDOWN |
766 wx.FR_NOMATCHCASE |
767 wx.FR_NOWHOLEWORD)
768 self.finddlg.Show(True)
769
770 def OnFind(self, event):
771 self.nb.SetSelection(1)
772 end = self.txt.GetLastPosition()
773 textstring = self.txt.GetRange(0, end).lower()
774 start = self.txt.GetSelection()[1]
775 findstring = self.finddata.GetFindString().lower()
776 loc = textstring.find(findstring, start)
777 if loc == -1 and start != 0:
778 # string not found, start at beginning
779 start = 0
780 loc = textstring.find(findstring, start)
781 if loc == -1:
782 dlg = wx.MessageDialog(self, 'Find String Not Found',
783 'Find String Not Found in Demo File',
784 wx.OK | wx.ICON_INFORMATION)
785 dlg.ShowModal()
786 dlg.Destroy()
787 if self.finddlg:
788 if loc == -1:
789 self.finddlg.SetFocus()
790 return
791 else:
792 self.finddlg.Destroy()
793 self.txt.ShowPosition(loc)
794 self.txt.SetSelection(loc, loc + len(findstring))
795
796
797
798 def OnFindNext(self, event):
799 if self.finddata.GetFindString():
800 self.OnFind(event)
801 else:
802 self.OnHelpFind(event)
803
804 def OnFindClose(self, event):
805 event.GetDialog().Destroy()
806
807
808 #---------------------------------------------
809 def OnCloseWindow(self, event):
810 self.dying = True
811 self.window = None
812 self.mainmenu = None
813 self.Destroy()
814
815
816 #---------------------------------------------
817 def OnIdle(self, event):
818 if self.otherWin:
819 self.otherWin.Raise()
820 self.window = self.otherWin
821 self.otherWin = None
822
823
824 #---------------------------------------------
825 def ShowTip(self):
826 try:
827 showTipText = open(opj("data/showTips")).read()
828 showTip, index = eval(showTipText)
829 except IOError:
830 showTip, index = (1, 0)
831 if showTip:
832 tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index)
833 ##tp = MyTP(0)
834 showTip = wx.ShowTip(self, tp)
835 index = tp.GetCurrentTip()
836 open(opj("data/showTips"), "w").write(str( (showTip, index) ))
837
838
839 #---------------------------------------------
840 def OnDemoMenu(self, event):
841 try:
842 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
843 except:
844 selectedDemo = None
845 if selectedDemo:
846 self.tree.SelectItem(selectedDemo)
847 self.tree.EnsureVisible(selectedDemo)
848
849
850 #---------------------------------------------
851 def OnTaskBarActivate(self, evt):
852 if self.IsIconized():
853 self.Iconize(False)
854 if not self.IsShown():
855 self.Show(True)
856 self.Raise()
857
858 #---------------------------------------------
859
860 TBMENU_RESTORE = 1000
861 TBMENU_CLOSE = 1001
862
863 def OnTaskBarMenu(self, evt):
864 menu = wx.Menu()
865 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
866 menu.Append(self.TBMENU_CLOSE, "Close")
867 self.tbicon.PopupMenu(menu)
868 menu.Destroy()
869
870 #---------------------------------------------
871 def OnTaskBarClose(self, evt):
872 self.Close()
873
874 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
875 # prod the main idle handler a bit to get the window to actually close
876 wx.GetApp().ProcessIdle()
877
878
879 #---------------------------------------------
880 def OnIconfiy(self, evt):
881 wx.LogMessage("OnIconfiy")
882 evt.Skip()
883
884 #---------------------------------------------
885 def OnMaximize(self, evt):
886 wx.LogMessage("OnMaximize")
887 evt.Skip()
888
889
890
891
892 #---------------------------------------------------------------------------
893 #---------------------------------------------------------------------------
894
895 class MySplashScreen(wx.SplashScreen):
896 def __init__(self):
897 bmp = wx.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
898 wx.SplashScreen.__init__(self, bmp,
899 wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
900 3000, None, -1)
901 self.Bind(wx.EVT_CLOSE, self.OnClose)
902
903 def OnClose(self, evt):
904 self.Hide()
905 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
906 frame.Show()
907 evt.Skip() # Make sure the default handler runs too...
908
909
910 class MyApp(wx.App):
911 def OnInit(self):
912 """
913 Create and show the splash screen. It will then create and show
914 the main frame when it is time to do so.
915 """
916
917 # Normally when using a SplashScreen you would create it, show
918 # it and then continue on with the applicaiton's
919 # initialization, finally creating and showing the main
920 # application window(s). In this case we have nothing else to
921 # do so we'll delay showing the main frame until later (see
922 # OnClose above) so the users can see the SplashScreen effect.
923 splash = MySplashScreen()
924 splash.Show()
925
926 return True
927
928
929
930 #---------------------------------------------------------------------------
931
932 def main():
933 try:
934 demoPath = os.path.dirname(__file__)
935 os.chdir(demoPath)
936 except:
937 pass
938 app = MyApp(0) ##wx.Platform == "__WXMAC__")
939 app.MainLoop()
940
941
942 #---------------------------------------------------------------------------
943
944
945
946 overview = """<html><body>
947 <h2>wxPython</h2>
948
949 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
950 language. It allows Python programmers to create programs with a
951 robust, highly functional graphical user interface, simply and easily.
952 It is implemented as a Python extension module (native code) that
953 wraps the popular wxWindows cross platform GUI library, which is
954 written in C++.
955
956 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
957 means that it is free for anyone to use and the source code is
958 available for anyone to look at and modify. Or anyone can contribute
959 fixes or enhancements to the project.
960
961 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
962 same program will run on multiple platforms without modification.
963 Currently supported platforms are 32-bit Microsoft Windows, most Unix
964 or unix-like systems, and Macintosh OS X. Since the language is
965 Python, wxPython programs are <b>simple, easy</b> to write and easy to
966 understand.
967
968 <p> <b>This demo</b> is not only a collection of test cases for
969 wxPython, but is also designed to help you learn about and how to use
970 wxPython. Each sample is listed in the tree control on the left.
971 When a sample is selected in the tree then a module is loaded and run
972 (usually in a tab of this notebook,) and the source code of the module
973 is loaded in another tab for you to browse and learn from.
974
975 """
976
977
978 #----------------------------------------------------------------------------
979 #----------------------------------------------------------------------------
980
981 if __name__ == '__main__':
982 main()
983
984 #----------------------------------------------------------------------------
985
986
987
988
989
990
991