]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Main.py
update from herbert breunung
[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 if wx.USE_UNICODE:
265 value = value.decode('iso8859_1')
266 self.SetReadOnly(False)
267 self.SetText(value)
268 self.SetReadOnly(True)
269
270 def Clear(self):
271 self.ClearAll()
272
273 def SetInsertionPoint(self, pos):
274 self.SetCurrentPos(pos)
275
276 def ShowPosition(self, pos):
277 self.GotoPos(pos)
278
279 def GetLastPosition(self):
280 return self.GetLength()
281
282 def GetRange(self, start, end):
283 return self.GetTextRange(start, end)
284
285 def GetSelection(self):
286 return self.GetAnchor(), self.GetCurrentPos()
287
288 def SetSelection(self, start, end):
289 self.SetSelectionStart(start)
290 self.SetSelectionEnd(end)
291
292 def SetUpEditor(self):
293 """
294 This method carries out the work of setting up the demo editor.
295 It's seperate so as not to clutter up the init code.
296 """
297 import keyword
298
299 self.SetLexer(stc.STC_LEX_PYTHON)
300 self.SetKeyWords(0, " ".join(keyword.kwlist))
301
302 # Enable folding
303 self.SetProperty("fold", "1" )
304
305 # Highlight tab/space mixing (shouldn't be any)
306 self.SetProperty("tab.timmy.whinge.level", "1")
307
308 # Set left and right margins
309 self.SetMargins(2,2)
310
311 # Set up the numbers in the margin for margin #1
312 self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
313 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
314 self.SetMarginWidth(1, 40)
315
316 # Indentation and tab stuff
317 self.SetIndent(4) # Proscribed indent size for wx
318 self.SetIndentationGuides(True) # Show indent guides
319 self.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
320 self.SetTabIndents(True) # Tab key indents
321 self.SetTabWidth(4) # Proscribed tab size for wx
322 self.SetUseTabs(False) # Use spaces rather than tabs, or
323 # TabTimmy will complain!
324 # White space
325 self.SetViewWhiteSpace(False) # Don't view white space
326
327 # EOL
328 #self.SetEOLMode(wx.stc.STC_EOL_CRLF) # Just leave it at the default (autosense)
329 self.SetViewEOL(False)
330 # No right-edge mode indicator
331 self.SetEdgeMode(stc.STC_EDGE_NONE)
332
333 # Setup a margin to hold fold markers
334 self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
335 self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
336 self.SetMarginSensitive(2, True)
337 self.SetMarginWidth(2, 12)
338
339 # and now set up the fold markers
340 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "black")
341 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "black")
342 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "black")
343 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "black")
344 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "black")
345 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "black")
346 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "black")
347
348 # Global default style
349 if wx.Platform == '__WXMSW__':
350 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
351 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
352 else:
353 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
354 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
355
356 # Clear styles and revert to default.
357 self.StyleClearAll()
358
359 # Following style specs only indicate differences from default.
360 # The rest remains unchanged.
361
362 # Line numbers in margin
363 self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
364
365 # Highlighted brace
366 self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
367 # Unmatched brace
368 self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
369 # Indentation guide
370 self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
371
372 # Python styles
373 self.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
374 # Comments
375 self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
376 self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
377 # Numbers
378 self.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
379 # Strings and characters
380 self.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
381 self.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
382 # Keywords
383 self.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
384 # Triple quotes
385 self.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
386 self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
387 # Class names
388 self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
389 # Function names
390 self.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
391 # Operators
392 self.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
393 # Identifiers. I leave this as not bold because everything seems
394 # to be an identifier if it doesn't match the above criterae
395 self.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
396
397 # Caret color
398 self.SetCaretForeground("BLUE")
399 # Selection background
400 self.SetSelBackground(1, '#66CCFF')
401
402 self.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
403 self.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
404
405
406 except ImportError:
407 class DemoCodeViewer(wx.TextCtrl):
408 def __init__(self, parent, ID):
409 wx.TextCtrl.__init__(self, parent, ID, style =
410 wx.TE_MULTILINE | wx.TE_READONLY |
411 wx.HSCROLL | wx.TE_RICH2 | wx.TE_NOHIDESEL)
412
413
414 #---------------------------------------------------------------------------
415
416 def opj(path):
417 """Convert paths to the platform-specific separator"""
418 return apply(os.path.join, tuple(path.split('/')))
419
420
421 #---------------------------------------------------------------------------
422
423 class wxPythonDemo(wx.Frame):
424 overviewText = "wxPython Overview"
425
426 def __init__(self, parent, id, title):
427 wx.Frame.__init__(self, parent, -1, title, size = (800, 600),
428 style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
429
430
431 self.cwd = os.getcwd()
432 self.curOverview = ""
433 self.window = None
434
435 icon = images.getMondrianIcon()
436 self.SetIcon(icon)
437
438 if wx.Platform != '__WXMAC__':
439 # setup a taskbar icon, and catch some events from it
440 dim = 16 # (may want to use 22 on wxGTK...)
441 icon = wx.IconFromBitmap(
442 images.getMondrianImage().Scale(dim,dim).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 if wx.USE_UNICODE:
742 text = text.decode('iso8859_1')
743 self.ovr.SetPage(text)
744 self.nb.SetPageText(0, name)
745
746 #---------------------------------------------
747 # Menu methods
748 def OnFileExit(self, *event):
749 self.Close()
750
751 def OnToggleRedirect(self, event):
752 app = wx.GetApp()
753 if event.Checked():
754 app.RedirectStdio()
755 print "Print statements and other standard output will now be directed to this window."
756 else:
757 app.RestoreStdio()
758 print "Print statements and other standard output will now be sent to the usual location."
759
760 def OnHelpAbout(self, event):
761 from About import MyAboutBox
762 about = MyAboutBox(self)
763 about.ShowModal()
764 about.Destroy()
765
766 def OnHelpFind(self, event):
767 self.nb.SetSelection(1)
768 self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find",
769 wx.FR_NOUPDOWN |
770 wx.FR_NOMATCHCASE |
771 wx.FR_NOWHOLEWORD)
772 self.finddlg.Show(True)
773
774 def OnFind(self, event):
775 self.nb.SetSelection(1)
776 end = self.txt.GetLastPosition()
777 textstring = self.txt.GetRange(0, end).lower()
778 start = self.txt.GetSelection()[1]
779 findstring = self.finddata.GetFindString().lower()
780 loc = textstring.find(findstring, start)
781 if loc == -1 and start != 0:
782 # string not found, start at beginning
783 start = 0
784 loc = textstring.find(findstring, start)
785 if loc == -1:
786 dlg = wx.MessageDialog(self, 'Find String Not Found',
787 'Find String Not Found in Demo File',
788 wx.OK | wx.ICON_INFORMATION)
789 dlg.ShowModal()
790 dlg.Destroy()
791 if self.finddlg:
792 if loc == -1:
793 self.finddlg.SetFocus()
794 return
795 else:
796 self.finddlg.Destroy()
797 self.txt.ShowPosition(loc)
798 self.txt.SetSelection(loc, loc + len(findstring))
799
800
801
802 def OnFindNext(self, event):
803 if self.finddata.GetFindString():
804 self.OnFind(event)
805 else:
806 self.OnHelpFind(event)
807
808 def OnFindClose(self, event):
809 event.GetDialog().Destroy()
810
811
812 #---------------------------------------------
813 def OnCloseWindow(self, event):
814 self.dying = True
815 self.window = None
816 self.mainmenu = None
817 self.Destroy()
818
819
820 #---------------------------------------------
821 def OnIdle(self, event):
822 if self.otherWin:
823 self.otherWin.Raise()
824 self.window = self.otherWin
825 self.otherWin = None
826
827
828 #---------------------------------------------
829 def ShowTip(self):
830 try:
831 showTipText = open(opj("data/showTips")).read()
832 showTip, index = eval(showTipText)
833 except IOError:
834 showTip, index = (1, 0)
835 if showTip:
836 tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index)
837 ##tp = MyTP(0)
838 showTip = wx.ShowTip(self, tp)
839 index = tp.GetCurrentTip()
840 open(opj("data/showTips"), "w").write(str( (showTip, index) ))
841
842
843 #---------------------------------------------
844 def OnDemoMenu(self, event):
845 try:
846 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
847 except:
848 selectedDemo = None
849 if selectedDemo:
850 self.tree.SelectItem(selectedDemo)
851 self.tree.EnsureVisible(selectedDemo)
852
853
854 #---------------------------------------------
855 def OnTaskBarActivate(self, evt):
856 if self.IsIconized():
857 self.Iconize(False)
858 if not self.IsShown():
859 self.Show(True)
860 self.Raise()
861
862 #---------------------------------------------
863
864 TBMENU_RESTORE = 1000
865 TBMENU_CLOSE = 1001
866
867 def OnTaskBarMenu(self, evt):
868 menu = wx.Menu()
869 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
870 menu.Append(self.TBMENU_CLOSE, "Close")
871 self.tbicon.PopupMenu(menu)
872 menu.Destroy()
873
874 #---------------------------------------------
875 def OnTaskBarClose(self, evt):
876 self.Close()
877
878 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
879 # prod the main idle handler a bit to get the window to actually close
880 wx.GetApp().ProcessIdle()
881
882
883 #---------------------------------------------
884 def OnIconfiy(self, evt):
885 wx.LogMessage("OnIconfiy")
886 evt.Skip()
887
888 #---------------------------------------------
889 def OnMaximize(self, evt):
890 wx.LogMessage("OnMaximize")
891 evt.Skip()
892
893
894
895
896 #---------------------------------------------------------------------------
897 #---------------------------------------------------------------------------
898
899 class MySplashScreen(wx.SplashScreen):
900 def __init__(self):
901 bmp = wx.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
902 wx.SplashScreen.__init__(self, bmp,
903 wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
904 3000, None, -1)
905 self.Bind(wx.EVT_CLOSE, self.OnClose)
906
907 def OnClose(self, evt):
908 self.Hide()
909 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
910 frame.Show()
911 evt.Skip() # Make sure the default handler runs too...
912
913
914 class MyApp(wx.App):
915 def OnInit(self):
916 """
917 Create and show the splash screen. It will then create and show
918 the main frame when it is time to do so.
919 """
920
921 # Normally when using a SplashScreen you would create it, show
922 # it and then continue on with the applicaiton's
923 # initialization, finally creating and showing the main
924 # application window(s). In this case we have nothing else to
925 # do so we'll delay showing the main frame until later (see
926 # OnClose above) so the users can see the SplashScreen effect.
927 splash = MySplashScreen()
928 splash.Show()
929
930 return True
931
932
933
934 #---------------------------------------------------------------------------
935
936 def main():
937 try:
938 demoPath = os.path.dirname(__file__)
939 os.chdir(demoPath)
940 except:
941 pass
942 app = MyApp(0) ##wx.Platform == "__WXMAC__")
943 app.MainLoop()
944
945
946 #---------------------------------------------------------------------------
947
948
949
950 overview = """<html><body>
951 <h2>wxPython</h2>
952
953 <p> wxPython is a <b>GUI toolkit</b> for the Python programming
954 language. It allows Python programmers to create programs with a
955 robust, highly functional graphical user interface, simply and easily.
956 It is implemented as a Python extension module (native code) that
957 wraps the popular wxWindows cross platform GUI library, which is
958 written in C++.
959
960 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
961 means that it is free for anyone to use and the source code is
962 available for anyone to look at and modify. Or anyone can contribute
963 fixes or enhancements to the project.
964
965 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
966 same program will run on multiple platforms without modification.
967 Currently supported platforms are 32-bit Microsoft Windows, most Unix
968 or unix-like systems, and Macintosh OS X. Since the language is
969 Python, wxPython programs are <b>simple, easy</b> to write and easy to
970 understand.
971
972 <p> <b>This demo</b> is not only a collection of test cases for
973 wxPython, but is also designed to help you learn about and how to use
974 wxPython. Each sample is listed in the tree control on the left.
975 When a sample is selected in the tree then a module is loaded and run
976 (usually in a tab of this notebook,) and the source code of the module
977 is loaded in another tab for you to browse and learn from.
978
979 """
980
981
982 #----------------------------------------------------------------------------
983 #----------------------------------------------------------------------------
984
985 if __name__ == '__main__':
986 main()
987
988 #----------------------------------------------------------------------------
989
990
991
992
993
994
995