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