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