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