]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Main.py
Changed (again) how the GIL is aquired and the tstate restored. This
[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 if hasattr(self, "tbicon"):
827 del self.tbicon
828 self.Destroy()
829
830
831 #---------------------------------------------
832 def OnIdle(self, event):
833 if self.otherWin:
834 self.otherWin.Raise()
835 self.window = self.otherWin
836 self.otherWin = None
837
838
839 #---------------------------------------------
840 def ShowTip(self):
841 try:
842 showTipText = open(opj("data/showTips")).read()
843 showTip, index = eval(showTipText)
844 except IOError:
845 showTip, index = (1, 0)
846 if showTip:
847 tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index)
848 ##tp = MyTP(0)
849 showTip = wx.ShowTip(self, tp)
850 index = tp.GetCurrentTip()
851 open(opj("data/showTips"), "w").write(str( (showTip, index) ))
852
853
854 #---------------------------------------------
855 def OnDemoMenu(self, event):
856 try:
857 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
858 except:
859 selectedDemo = None
860 if selectedDemo:
861 self.tree.SelectItem(selectedDemo)
862 self.tree.EnsureVisible(selectedDemo)
863
864
865 #---------------------------------------------
866 def OnTaskBarActivate(self, evt):
867 if self.IsIconized():
868 self.Iconize(False)
869 if not self.IsShown():
870 self.Show(True)
871 self.Raise()
872
873 #---------------------------------------------
874
875 TBMENU_RESTORE = 1000
876 TBMENU_CLOSE = 1001
877
878 def OnTaskBarMenu(self, evt):
879 menu = wx.Menu()
880 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
881 menu.Append(self.TBMENU_CLOSE, "Close")
882 self.tbicon.PopupMenu(menu)
883 menu.Destroy()
884
885 #---------------------------------------------
886 def OnTaskBarClose(self, evt):
887 self.Close()
888
889 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
890 # prod the main idle handler a bit to get the window to actually close
891 wx.GetApp().ProcessIdle()
892
893
894 #---------------------------------------------
895 def OnIconfiy(self, evt):
896 wx.LogMessage("OnIconfiy")
897 evt.Skip()
898
899 #---------------------------------------------
900 def OnMaximize(self, evt):
901 wx.LogMessage("OnMaximize")
902 evt.Skip()
903
904
905
906
907 #---------------------------------------------------------------------------
908 #---------------------------------------------------------------------------
909
910 class MySplashScreen(wx.SplashScreen):
911 def __init__(self):
912 bmp = wx.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
913 wx.SplashScreen.__init__(self, bmp,
914 wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
915 3000, None, -1)
916 self.Bind(wx.EVT_CLOSE, self.OnClose)
917
918 def OnClose(self, evt):
919 self.Hide()
920 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
921 frame.Show()
922 evt.Skip() # Make sure the default handler runs too...
923
924
925 class MyApp(wx.App):
926 def OnInit(self):
927 """
928 Create and show the splash screen. It will then create and show
929 the main frame when it is time to do so.
930 """
931
932 wx.InitAllImageHandlers()
933
934 # Normally when using a SplashScreen you would create it, show
935 # it and then continue on with the applicaiton's
936 # initialization, finally creating and showing the main
937 # application window(s). In this case we have nothing else to
938 # do so we'll delay showing the main frame until later (see
939 # OnClose above) so the users can see the SplashScrren effect.
940 splash = MySplashScreen()
941 splash.Show()
942
943 return True
944
945
946
947 #---------------------------------------------------------------------------
948
949 def main():
950 try:
951 demoPath = os.path.dirname(__file__)
952 os.chdir(demoPath)
953 except:
954 pass
955 app = MyApp(0) ##wx.Platform == "__WXMAC__")
956 app.MainLoop()
957
958
959 #---------------------------------------------------------------------------
960
961
962
963 overview = """<html><body>
964 <h2>wxPython</h2>
965
966 <p> wxPython is a <b>GUI toolkit</b> for the <a
967 href="http://www.python.org/">Python</a> programming language. It
968 allows Python programmers to create programs with a robust, highly
969 functional graphical user interface, simply and easily. It is
970 implemented as a Python extension module (native code) that wraps the
971 popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
972 platform GUI library, which is written in C++.
973
974 <p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
975 means that it is free for anyone to use and the source code is
976 available for anyone to look at and modify. Or anyone can contribute
977 fixes or enhancements to the project.
978
979 <p> wxPython is a <b>cross-platform</b> toolkit. This means that the
980 same program will run on multiple platforms without modification.
981 Currently supported platforms are 32-bit Microsoft Windows, most Unix
982 or unix-like systems, and Macintosh OS X. Since the language is
983 Python, wxPython programs are <b>simple, easy</b> to write and easy to
984 understand.
985
986 <p> <b>This demo</b> is not only a collection of test cases for
987 wxPython, but is also designed to help you learn about and how to use
988 wxPython. Each sample is listed in the tree control on the left.
989 When a sample is selected in the tree then a module is loaded and run
990 (usually in a tab of this notebook,) and the source code of the module
991 is loaded in another tab for you to browse and learn from.
992
993 """
994
995
996 #----------------------------------------------------------------------------
997 #----------------------------------------------------------------------------
998
999 if __name__ == '__main__':
1000 main()
1001
1002 #----------------------------------------------------------------------------
1003
1004
1005
1006
1007
1008
1009