]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Main.py
Reworked how stock objects are initialized. They now have an
[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 'wxVListBox',
33 'wxListbook',
34 'wxMaskedNumCtrl',
35 'FloatCanvas',
36 'wxXmlResourceSubclass',
37 'wxGridBagSizer',
38 'Cursor',
39 'PyPlot',
40 ]),
41
42 # managed windows == things with a (optional) caption you can close
43 ('Base Frames and Dialogs', [
44 'wxDialog',
45 'wxFrame',
46 'wxMDIWindows',
47 'wxMiniFrame',
48 'wxWizard',
49 ]),
50
51 # the common dialogs
52 ('Common Dialogs', [
53 'wxColourDialog',
54 'wxDirDialog',
55 'wxFileDialog',
56 'wxFileDialog_Save',
57 'wxFindReplaceDialog',
58 'wxFontDialog',
59 'wxMessageDialog',
60 'wxPageSetupDialog',
61 'wxPrintDialog',
62 'wxProgressDialog',
63 'wxSingleChoiceDialog',
64 'wxTextEntryDialog',
65 ]),
66
67 # dialogs from libraries
68 ('More Dialogs', [
69 'ErrorDialogs',
70 'ImageBrowser',
71 'wxMultipleChoiceDialog',
72 'wxScrolledMessageDialog',
73 ]),
74
75 # core controls
76 ('Core Windows/Controls', [
77 'PopupMenu',
78 'wxButton',
79 'wxCheckBox',
80 'wxCheckListBox',
81 'wxChoice',
82 'wxComboBox',
83 'wxGauge',
84 'wxGrid',
85 'wxGrid_MegaExample',
86 'wxListbook',
87 'wxListBox',
88 'wxListCtrl',
89 'wxListCtrl_virtual',
90 'wxMenu',
91 'wxNotebook',
92 'wxPopupWindow',
93 'wxRadioBox',
94 'wxRadioButton',
95 'wxSashWindow',
96 'wxScrolledWindow',
97 'wxSlider',
98 'wxSpinButton',
99 'wxSpinCtrl',
100 'wxSplitterWindow',
101 'wxStaticBitmap',
102 'wxStaticText',
103 'wxStatusBar',
104 'wxTextCtrl',
105 'wxToggleButton',
106 'wxToolBar',
107 'wxTreeCtrl',
108 'wxValidator',
109 ]),
110
111 ('Custom Controls', [
112 'AnalogClockWindow',
113 'ColourSelect',
114 'GenericButtons',
115 'wxEditor',
116 'wxGenericDirCtrl',
117 'wxLEDNumberCtrl',
118 'wxMultiSash',
119 'wxPopupControl',
120 'wxPyColourChooser',
121 'wxTreeListCtrl',
122 ]),
123
124 # controls coming from other libraries
125 ('More Windows/Controls', [
126 #'wxFloatBar', deprecated
127 #'wxMVCTree', deprecated
128 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
129 'ContextHelp',
130 'FancyText',
131 'FloatCanvas',
132 'FileBrowseButton',
133 'MaskedEditControls',
134 'PyShell',
135 'PyCrust',
136 'PyPlot',
137 'SplitTree',
138 'TablePrint',
139 'Throbber',
140 'wxCalendar',
141 'wxCalendarCtrl',
142 'wxDynamicSashWindow',
143 'wxEditableListBox',
144 'wxHtmlWindow',
145 'wxIEHtmlWin',
146 'wxIntCtrl',
147 'wxMimeTypesManager',
148 'wxMaskedNumCtrl',
149 'wxScrolledPanel',
150 'wxStyledTextCtrl_1',
151 'wxStyledTextCtrl_2',
152 'wxTimeCtrl',
153 'wxVListBox',
154 ]),
155
156 # How to lay out the controls in a frame/dialog
157 ('Window Layout', [
158 'LayoutAnchors',
159 'Layoutf',
160 'RowColSizer',
161 'Sizers',
162 'wxGridBagSizer',
163 'wxLayoutConstraints',
164 'wxScrolledPanel',
165 'wxXmlResource',
166 'wxXmlResourceHandler',
167 'wxXmlResourceSubclass',
168 ]),
169
170 # ditto
171 ('Process and Events', [
172 'EventManager',
173 'infoframe',
174 'OOR',
175 'PythonEvents',
176 'Threads',
177 'wxKeyEvents',
178 'wxProcess',
179 'wxTimer',
180 ]),
181
182 # Clipboard and DnD
183 ('Clipboard and DnD', [
184 'CustomDragAndDrop',
185 'DragAndDrop',
186 'URLDragAndDrop',
187 ]),
188
189 # Images
190 ('Using Images', [
191 'Cursor',
192 'Throbber',
193 'wxArtProvider',
194 'wxDragImage',
195 'wxImage',
196 'wxImageFromStream',
197 'wxMask',
198 ]),
199
200 # Other stuff
201 ('Miscellaneous', [
202 'ColourDB',
203 'DialogUnits',
204 'DrawXXXList',
205 'FontEnumerator',
206 'NewNamespace',
207 'PrintFramework',
208 'ShapedWindow',
209 'Throbber',
210 'Unicode',
211 'wxFileHistory',
212 'wxJoystick',
213 'wxOGL',
214 'wxWave',
215 ]),
216
217 # need libs not coming with the demo
218 ('Objects using an external library', [
219 'ActiveXWrapper_Acrobat',
220 'ActiveXWrapper_IE',
221 'wxGLCanvas',
222 #'wxPlotCanvas', # 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 wxStyledTextCtrl_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 wxStyledTextCtrl_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:#00CC00,back:#F0FFF0')
381 self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#00CC00,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 == '__WXMSW__':
443 # setup a taskbar icon, and catch some events from it
444 self.tbicon = wx.TaskBarIcon()
445 self.tbicon.SetIcon(icon, "wxPython Demo")
446 self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
447 self.tbicon.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.OnTaskBarMenu)
448 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
449 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
450
451 wx.CallAfter(self.ShowTip)
452
453 self.otherWin = None
454 self.Bind(wx.EVT_IDLE, self.OnIdle)
455 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
456 self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)
457 self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize)
458
459 self.Centre(wx.BOTH)
460 self.CreateStatusBar(1, wx.ST_SIZEGRIP)
461
462 splitter = wx.SplitterWindow(self, -1)
463 splitter2 = wx.SplitterWindow(splitter, -1)
464
465 def EmptyHandler(evt): pass
466 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
467 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
468
469 # Prevent TreeCtrl from displaying all items after destruction when True
470 self.dying = False
471
472 # Make a File menu
473 self.mainmenu = wx.MenuBar()
474 menu = wx.Menu()
475 exitID = wx.NewId()
476 menu.Append(exitID, 'E&xit\tAlt-X', 'Get the heck outta here!')
477 self.Bind(wx.EVT_MENU, self.OnFileExit, id=exitID)
478 wx.App_SetMacExitMenuItemId(exitID)
479 self.mainmenu.Append(menu, '&File')
480
481 # Make a Demo menu
482 menu = wx.Menu()
483 for item in _treeList:
484 submenu = wx.Menu()
485 for childItem in item[1]:
486 mID = wx.NewId()
487 submenu.Append(mID, childItem)
488 self.Bind(wx.EVT_MENU, self.OnDemoMenu, id=mID)
489 menu.AppendMenu(wx.NewId(), item[0], submenu)
490 self.mainmenu.Append(menu, '&Demo')
491
492
493 # Make a Help menu
494 helpID = wx.NewId()
495 findID = wx.NewId()
496 findnextID = wx.NewId()
497 menu = wx.Menu()
498 menu.Append(findID, '&Find\tCtrl-F', 'Find in the Demo Code')
499 menu.Append(findnextID, 'Find &Next\tF3', 'Find Next')
500 menu.AppendSeparator()
501 menu.Append(helpID, '&About\tCtrl-H', 'wxPython RULES!!!')
502 wx.App_SetMacAboutMenuItemId(helpID)
503 self.Bind(wx.EVT_MENU, self.OnHelpAbout, id=helpID)
504 self.Bind(wx.EVT_MENU, self.OnHelpFind, id=findID)
505 self.Bind(wx.EVT_MENU, self.OnFindNext, id=findnextID)
506 self.Bind(wx.EVT_COMMAND_FIND, self.OnFind)
507 self.Bind(wx.EVT_COMMAND_FIND_NEXT, self.OnFind)
508 self.Bind(wx.EVT_COMMAND_FIND_CLOSE, self.OnFindClose)
509 self.mainmenu.Append(menu, '&Help')
510 self.SetMenuBar(self.mainmenu)
511
512 self.finddata = wx.FindReplaceData()
513
514 if 0:
515 # This is another way to set Accelerators, in addition to
516 # using the '\t<key>' syntax in the menu items.
517 aTable = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), exitID),
518 (wx.ACCEL_CTRL, ord('H'), helpID),
519 (wx.ACCEL_CTRL, ord('F'), findID),
520 (wx.ACCEL_NORMAL, WXK_F3, findnextID)
521 ])
522 self.SetAcceleratorTable(aTable)
523
524
525 # Create a TreeCtrl
526 tID = wx.NewId()
527 self.treeMap = {}
528 self.tree = wx.TreeCtrl(splitter, tID, style =
529 wx.TR_DEFAULT_STYLE #| wx.TR_HAS_VARIABLE_ROW_HEIGHT
530 )
531
532 root = self.tree.AddRoot("wxPython Overview")
533 firstChild = None
534 for item in _treeList:
535 child = self.tree.AppendItem(root, item[0])
536 if not firstChild: firstChild = child
537 for childItem in item[1]:
538 theDemo = self.tree.AppendItem(child, childItem)
539 self.treeMap[childItem] = theDemo
540
541 self.tree.Expand(root)
542 self.tree.Expand(firstChild)
543 self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, id=tID)
544 self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=tID)
545 self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=tID)
546 self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
547
548 # Create a Notebook
549 self.nb = wx.Notebook(splitter2, -1, style=wx.CLIP_CHILDREN)
550
551 # Set up a wx.html.HtmlWindow on the Overview Notebook page
552 # we put it in a panel first because there seems to be a
553 # refresh bug of some sort (wxGTK) when it is directly in
554 # the notebook...
555 if 0: # the old way
556 self.ovr = wx.html.HtmlWindow(self.nb, -1, size=(400, 400))
557 self.nb.AddPage(self.ovr, self.overviewText)
558
559 else: # hopefully I can remove this hacky code soon, see SF bug #216861
560 panel = wx.Panel(self.nb, -1, style=wx.CLIP_CHILDREN)
561 self.ovr = wx.html.HtmlWindow(panel, -1, size=(400, 400))
562 self.nb.AddPage(panel, self.overviewText)
563
564 def OnOvrSize(evt, ovr=self.ovr):
565 ovr.SetSize(evt.GetSize())
566
567 panel.Bind(wx.EVT_SIZE, OnOvrSize)
568 panel.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
569
570
571 self.SetOverview(self.overviewText, overview)
572
573
574 # Set up a notebook page for viewing the source code of each sample
575 self.txt = DemoCodeViewer(self.nb, -1)
576 self.nb.AddPage(self.txt, "Demo Code")
577 self.LoadDemoSource('Main.py')
578
579
580 # Set up a log on the View Log Notebook page
581 self.log = wx.TextCtrl(splitter2, -1,
582 style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
583
584 # Set the wxWindows log target to be this textctrl
585 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
586
587 # But instead of the above we want to show how to use our own wx.Log class
588 wx.Log_SetActiveTarget(MyLog(self.log))
589
590 # for serious debugging
591 #wx.Log_SetActiveTarget(wx.LogStderr())
592 #wx.Log_SetTraceMask(wx.TraceMessages)
593
594 self.Show(True)
595
596
597 # add the windows to the splitter and split it.
598 splitter2.SplitHorizontally(self.nb, self.log, -120)
599 splitter.SplitVertically(self.tree, splitter2, 180)
600
601 splitter.SetMinimumPaneSize(20)
602 splitter2.SetMinimumPaneSize(20)
603
604
605 # Make the splitter on the right expand the top wind when resized
606 def SplitterOnSize(evt):
607 splitter = evt.GetEventObject()
608 sz = splitter.GetSize()
609 splitter.SetSashPosition(sz.height - 120, False)
610 evt.Skip()
611
612 splitter2.Bind(wx.EVT_SIZE, SplitterOnSize)
613
614
615 # select initial items
616 self.nb.SetSelection(0)
617 self.tree.SelectItem(root)
618
619 if len(sys.argv) == 2:
620 try:
621 selectedDemo = self.treeMap[sys.argv[1]]
622 except:
623 selectedDemo = None
624 if selectedDemo:
625 self.tree.SelectItem(selectedDemo)
626 self.tree.EnsureVisible(selectedDemo)
627
628
629 wx.LogMessage('window handle: %s' % self.GetHandle())
630
631
632 #---------------------------------------------
633 def WriteText(self, text):
634 if text[-1:] == '\n':
635 text = text[:-1]
636 wx.LogMessage(text)
637
638
639 def write(self, txt):
640 self.WriteText(txt)
641
642 #---------------------------------------------
643 def OnItemExpanded(self, event):
644 item = event.GetItem()
645 wx.LogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
646 event.Skip()
647
648 #---------------------------------------------
649 def OnItemCollapsed(self, event):
650 item = event.GetItem()
651 wx.LogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
652 event.Skip()
653
654 #---------------------------------------------
655 def OnTreeLeftDown(self, event):
656 pt = event.GetPosition();
657 item, flags = self.tree.HitTest(pt)
658 if item == self.tree.GetSelection():
659 self.SetOverview(self.tree.GetItemText(item)+" Overview", self.curOverview)
660 event.Skip()
661
662 #---------------------------------------------
663 def OnSelChanged(self, event):
664 if self.dying:
665 return
666
667 item = event.GetItem()
668 itemText = self.tree.GetItemText(item)
669 self.RunDemo(itemText)
670
671
672 #---------------------------------------------
673 def RunDemo(self, itemText):
674 os.chdir(self.cwd)
675 if self.nb.GetPageCount() == 3:
676 if self.nb.GetSelection() == 2:
677 self.nb.SetSelection(0)
678 # inform the window that it's time to quit if it cares
679 if self.window is not None:
680 if hasattr(self.window, "ShutdownDemo"):
681 self.window.ShutdownDemo()
682 wx.SafeYield() # in case the page has pending events
683 self.nb.DeletePage(2)
684
685 if itemText == self.overviewText:
686 self.LoadDemoSource('Main.py')
687 self.SetOverview(self.overviewText, overview)
688 self.nb.Refresh();
689 self.window = None
690
691 else:
692 if os.path.exists(itemText + '.py'):
693 wx.BeginBusyCursor()
694 wx.LogMessage("Running demo %s.py..." % itemText)
695 try:
696 self.LoadDemoSource(itemText + '.py')
697
698 if (sys.modules.has_key(itemText)):
699 reload(sys.modules[itemText])
700
701 module = __import__(itemText, globals())
702 self.SetOverview(itemText + " Overview", module.overview)
703 finally:
704 wx.EndBusyCursor()
705 self.tree.Refresh()
706
707 # in case runTest is modal, make sure things look right...
708 self.nb.Refresh();
709 wx.SafeYield()
710
711 self.window = module.runTest(self, self.nb, self) ###
712 if self.window is not None:
713 self.nb.AddPage(self.window, 'Demo')
714 self.nb.SetSelection(2)
715 self.nb.Refresh() # without this wxMac has troubles showing the just added page
716
717 else:
718 self.ovr.SetPage("")
719 self.txt.Clear()
720 self.window = None
721
722
723
724 #---------------------------------------------
725 # Get the Demo files
726 def LoadDemoSource(self, filename):
727 self.txt.Clear()
728 try:
729 self.txt.SetValue(open(filename).read())
730 except IOError:
731 self.txt.SetValue("Cannot open %s file." % filename)
732
733 self.txt.SetInsertionPoint(0)
734 self.txt.ShowPosition(0)
735
736 #---------------------------------------------
737 def SetOverview(self, name, text):
738 self.curOverview = text
739 lead = text[:6]
740 if lead != '<html>' and lead != '<HTML>':
741 text = '<br>'.join(text.split('\n'))
742 self.ovr.SetPage(text)
743 self.nb.SetPageText(0, name)
744
745 #---------------------------------------------
746 # Menu methods
747 def OnFileExit(self, *event):
748 self.Close()
749
750 def OnHelpAbout(self, event):
751 from About import MyAboutBox
752 about = MyAboutBox(self)
753 about.ShowModal()
754 about.Destroy()
755
756 def OnHelpFind(self, event):
757 self.nb.SetSelection(1)
758 self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find",
759 wx.FR_NOUPDOWN |
760 wx.FR_NOMATCHCASE |
761 wx.FR_NOWHOLEWORD)
762 self.finddlg.Show(True)
763
764 def OnFind(self, event):
765 self.nb.SetSelection(1)
766 end = self.txt.GetLastPosition()
767 textstring = self.txt.GetRange(0, end).lower()
768 start = self.txt.GetSelection()[1]
769 findstring = self.finddata.GetFindString().lower()
770 loc = textstring.find(findstring, start)
771 if loc == -1 and start != 0:
772 # string not found, start at beginning
773 start = 0
774 loc = textstring.find(findstring, start)
775 if loc == -1:
776 dlg = wx.MessageDialog(self, 'Find String Not Found',
777 'Find String Not Found in Demo File',
778 wx.OK | wx.ICON_INFORMATION)
779 dlg.ShowModal()
780 dlg.Destroy()
781 if self.finddlg:
782 if loc == -1:
783 self.finddlg.SetFocus()
784 return
785 else:
786 self.finddlg.Destroy()
787 self.txt.ShowPosition(loc)
788 self.txt.SetSelection(loc, loc + len(findstring))
789
790
791
792 def OnFindNext(self, event):
793 if self.finddata.GetFindString():
794 self.OnFind(event)
795 else:
796 self.OnHelpFind(event)
797
798 def OnFindClose(self, event):
799 event.GetDialog().Destroy()
800
801
802 #---------------------------------------------
803 def OnCloseWindow(self, event):
804 self.dying = True
805 self.window = None
806 self.mainmenu = None
807 if hasattr(self, "tbicon"):
808 del self.tbicon
809 self.Destroy()
810
811
812 #---------------------------------------------
813 def OnIdle(self, event):
814 if self.otherWin:
815 self.otherWin.Raise()
816 self.window = self.otherWin
817 self.otherWin = None
818
819
820 #---------------------------------------------
821 def ShowTip(self):
822 try:
823 showTipText = open(opj("data/showTips")).read()
824 showTip, index = eval(showTipText)
825 except IOError:
826 showTip, index = (1, 0)
827 if showTip:
828 tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index)
829 ##tp = MyTP(0)
830 showTip = wx.ShowTip(self, tp)
831 index = tp.GetCurrentTip()
832 open(opj("data/showTips"), "w").write(str( (showTip, index) ))
833
834
835 #---------------------------------------------
836 def OnDemoMenu(self, event):
837 try:
838 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
839 except:
840 selectedDemo = None
841 if selectedDemo:
842 self.tree.SelectItem(selectedDemo)
843 self.tree.EnsureVisible(selectedDemo)
844
845
846 #---------------------------------------------
847 def OnTaskBarActivate(self, evt):
848 if self.IsIconized():
849 self.Iconize(False)
850 if not self.IsShown():
851 self.Show(True)
852 self.Raise()
853
854 #---------------------------------------------
855
856 TBMENU_RESTORE = 1000
857 TBMENU_CLOSE = 1001
858
859 def OnTaskBarMenu(self, evt):
860 menu = wx.Menu()
861 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
862 menu.Append(self.TBMENU_CLOSE, "Close")
863 self.tbicon.PopupMenu(menu)
864 menu.Destroy()
865
866 #---------------------------------------------
867 def OnTaskBarClose(self, evt):
868 self.Close()
869
870 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
871 # prod the main idle handler a bit to get the window to actually close
872 wx.GetApp().ProcessIdle()
873
874
875 #---------------------------------------------
876 def OnIconfiy(self, evt):
877 wx.LogMessage("OnIconfiy")
878 evt.Skip()
879
880 #---------------------------------------------
881 def OnMaximize(self, evt):
882 wx.LogMessage("OnMaximize")
883 evt.Skip()
884
885
886
887
888 #---------------------------------------------------------------------------
889 #---------------------------------------------------------------------------
890
891 class MySplashScreen(wx.SplashScreen):
892 def __init__(self):
893 bmp = wx.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
894 wx.SplashScreen.__init__(self, bmp,
895 wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_TIMEOUT,
896 4000, None, -1,
897 style = wx.SIMPLE_BORDER|wx.FRAME_NO_TASKBAR|wx.STAY_ON_TOP)
898 self.Bind(wx.EVT_CLOSE, self.OnClose)
899
900 def OnClose(self, evt):
901 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
902 frame.Show()
903 evt.Skip() # Make sure the default handler runs too...
904
905
906 class MyApp(wx.App):
907 def OnInit(self):
908 """
909 Create and show the splash screen. It will then create and show
910 the main frame when it is time to do so.
911 """
912
913 #import locale
914 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
915 #locale.setlocale(locale.LC_ALL, 'fr')
916
917 wx.InitAllImageHandlers()
918 splash = MySplashScreen()
919 splash.Show()
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