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