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