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