]> git.saurik.com Git - wxWidgets.git/blob - wxPython/demo/Main.py
Added wxWizard and the wizard page classes, as well as a wizard sample
[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, string
15 from wxPython.wx import *
16 from wxPython.html import wxHtmlWindow
17
18 ##from wxPython.stc import *
19
20 import images
21
22 #---------------------------------------------------------------------------
23
24
25 _treeList = [
26 # new stuff
27 ('New since last release', [
28 'RowColSizer',
29 'Unicode',
30 'wxFileHistory',
31 'wxGenericDirCtrl',
32 'wxImageFromStream',
33 'wxArtProvider',
34 'ScrolledPanel',
35 'wxMenu',
36 'wxIEHtmlWin',
37 'wxKeyEvents',
38 'wxWizard',
39 ]),
40
41 # managed windows == things with a caption you can close
42 ('Base Frames and Dialogs', [
43 'wxDialog',
44 'wxFrame',
45 'wxMDIWindows',
46 'wxMiniFrame',
47 'wxWizard',
48 ]),
49
50 # the common dialogs
51 ('Common Dialogs', [
52 'wxColourDialog',
53 'wxDirDialog',
54 'wxFileDialog',
55 'wxFindReplaceDialog',
56 'wxFontDialog',
57 'wxMessageDialog',
58 'wxPageSetupDialog',
59 'wxPrintDialog',
60 'wxProgressDialog',
61 'wxSingleChoiceDialog',
62 'wxTextEntryDialog',
63 ]),
64
65 # dialogs from libraries
66 ('More Dialogs', [
67 'ErrorDialogs',
68 'ImageBrowser',
69 'wxMultipleChoiceDialog',
70 'wxScrolledMessageDialog',
71 ]),
72
73 # core controls
74 ('Core Windows/Controls', [
75 'wxButton',
76 'wxCheckBox',
77 'wxCheckListBox',
78 'wxChoice',
79 'wxComboBox',
80 'wxGauge',
81 'wxGenericDirCtrl',
82 'wxGrid',
83 'wxListBox',
84 'wxListCtrl',
85 'wxListCtrl_virtual',
86 'wxMenu',
87 'wxNotebook',
88 'wxPopupWindow',
89 'wxRadioBox',
90 'wxSashWindow',
91 'wxSlider',
92 'wxScrolledWindow',
93 'wxSplitterWindow',
94 'wxSpinButton',
95 'wxSpinCtrl',
96 'wxStaticText',
97 'wxStaticBitmap',
98 'wxStatusBar',
99 'wxTextCtrl',
100 'wxToggleButton',
101 'wxToolBar',
102 'wxTreeCtrl',
103 'wxValidator',
104 ]),
105
106 # controls coming from other librairies
107 ('More Windows/Controls', [
108 'ColourSelect',
109 'ContextHelp',
110 'FancyText',
111 'FileBrowseButton',
112 'GenericButtons',
113 'PyCrust',
114 'PyCrustWithFilling',
115 'SplitTree',
116 'TablePrint',
117 'wxCalendar',
118 'wxCalendarCtrl',
119 'wxDynamicSashWindow',
120 'wxEditableListBox',
121 'wxEditor',
122 #'wxFloatBar', deprecated
123 'wxHtmlWindow',
124 'wxIEHtmlWin',
125 'wxLEDNumberCtrl',
126 'wxMimeTypesManager',
127 #'wxMVCTree', deprecated
128 'wxRightTextCtrl',
129 'wxStyledTextCtrl_1',
130 'wxStyledTextCtrl_2',
131 ]),
132
133 # How to lay out the controls in a frame/dialog
134 ('Window Layout', [
135 'LayoutAnchors',
136 'Layoutf',
137 'RowColSizer',
138 'ScrolledPanel',
139 'Sizers',
140 'wxLayoutConstraints',
141 'XML_Resource',
142 ]),
143
144 # ditto
145 ('Process and Events', [
146 'infoframe',
147 'OOR',
148 'PythonEvents',
149 'Threads',
150 'wxProcess',
151 'wxTimer',
152 'wxKeyEvents',
153 ]),
154
155 # Clipboard and DnD
156 ('Clipboard and DnD', [
157 'CustomDragAndDrop',
158 'DragAndDrop',
159 'URLDragAndDrop',
160 ]),
161
162 # Images
163 ('Images', [
164 'wxDragImage',
165 'wxImage',
166 'wxImageFromStream',
167 'wxMask',
168 'wxArtProvider',
169 ]),
170
171 # Other stuff
172 ('Miscellaneous', [
173 'ColourDB',
174 'DialogUnits',
175 'DrawXXXList',
176 'FontEnumerator',
177 'PrintFramework',
178 'Unicode',
179 'wxFileHistory',
180 'wxJoystick',
181 'wxOGL',
182 'wxWave',
183 ]),
184
185 # need libs not coming with the demo
186 ('Objects using an external library', [
187 'ActiveXWrapper_Acrobat',
188 'ActiveXWrapper_IE',
189 'wxGLCanvas',
190 'wxPlotCanvas',
191 ]),
192
193
194 ('Check out the samples dir too', [
195 ]),
196
197 ]
198
199
200
201 #---------------------------------------------------------------------------
202
203 class MyLog(wxPyLog):
204 def __init__(self, textCtrl, logTime=0):
205 wxPyLog.__init__(self)
206 self.tc = textCtrl
207 self.logTime = logTime
208
209 def DoLogString(self, message, timeStamp):
210 if self.logTime:
211 message = time.strftime("%X", time.localtime(timeStamp)) + \
212 ": " + message
213 self.tc.AppendText(message + '\n')
214
215
216 class MyTP(wxPyTipProvider):
217 def GetTip(self):
218 return "This is my tip"
219
220 #---------------------------------------------------------------------------
221
222 def opj(path):
223 """Convert paths to the platform-specific separator"""
224 return apply(os.path.join, tuple(string.split(path, '/')))
225
226
227 #---------------------------------------------------------------------------
228
229 class wxPythonDemo(wxFrame):
230 overviewText = "wxPython Overview"
231
232 def __init__(self, parent, id, title):
233 wxFrame.__init__(self, parent, -1, title, size = (800, 600),
234 style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
235
236 self.cwd = os.getcwd()
237 self.curOverview = ""
238
239 icon = images.getMondrianIcon()
240 self.SetIcon(icon)
241
242 if wxPlatform == '__WXMSW__':
243 # setup a taskbar icon, and catch some events from it
244 self.tbicon = wxTaskBarIcon()
245 self.tbicon.SetIcon(icon, "wxPython Demo")
246 EVT_TASKBAR_LEFT_DCLICK(self.tbicon, self.OnTaskBarActivate)
247 EVT_TASKBAR_RIGHT_UP(self.tbicon, self.OnTaskBarMenu)
248 EVT_MENU(self.tbicon, self.TBMENU_RESTORE, self.OnTaskBarActivate)
249 EVT_MENU(self.tbicon, self.TBMENU_CLOSE, self.OnTaskBarClose)
250
251
252 self.otherWin = None
253 self.showTip = true
254 EVT_IDLE(self, self.OnIdle)
255 EVT_CLOSE(self, self.OnCloseWindow)
256 EVT_ICONIZE(self, self.OnIconfiy)
257 EVT_MAXIMIZE(self, self.OnMaximize)
258
259 self.Centre(wxBOTH)
260 self.CreateStatusBar(1, wxST_SIZEGRIP)
261
262 splitter = wxSplitterWindow(self, -1, style=wxNO_3D|wxSP_3D)
263 splitter2 = wxSplitterWindow(splitter, -1, style=wxNO_3D|wxSP_3D)
264
265 def EmptyHandler(evt): pass
266 EVT_ERASE_BACKGROUND(splitter, EmptyHandler)
267 EVT_ERASE_BACKGROUND(splitter2, EmptyHandler)
268
269 # Prevent TreeCtrl from displaying all items after destruction when true
270 self.dying = false
271
272 # Make a File menu
273 self.mainmenu = wxMenuBar()
274 menu = wxMenu()
275 exitID = wxNewId()
276 menu.Append(exitID, 'E&xit\tAlt-X', 'Get the heck outta here!')
277 EVT_MENU(self, exitID, self.OnFileExit)
278 self.mainmenu.Append(menu, '&File')
279
280 # Make a Demo menu
281 menu = wxMenu()
282 for item in _treeList:
283 submenu = wxMenu()
284 for childItem in item[1]:
285 mID = wxNewId()
286 submenu.Append(mID, childItem)
287 EVT_MENU(self, mID, self.OnDemoMenu)
288 menu.AppendMenu(wxNewId(), item[0], submenu)
289 self.mainmenu.Append(menu, '&Demo')
290
291
292 # Make a Help menu
293 helpID = wxNewId()
294 menu = wxMenu()
295 menu.Append(helpID, '&About\tCtrl-H', 'wxPython RULES!!!')
296 EVT_MENU(self, helpID, self.OnHelpAbout)
297 self.mainmenu.Append(menu, '&Help')
298 self.SetMenuBar(self.mainmenu)
299
300 # set the menu accellerator table...
301 aTable = wxAcceleratorTable([(wxACCEL_ALT, ord('X'), exitID),
302 (wxACCEL_CTRL, ord('H'), helpID)])
303 self.SetAcceleratorTable(aTable)
304
305
306 # Create a TreeCtrl
307 tID = wxNewId()
308 self.treeMap = {}
309 self.tree = wxTreeCtrl(splitter, tID,
310 style=wxTR_HAS_BUTTONS |
311 wxTR_HAS_VARIABLE_ROW_HEIGHT
312 )
313
314 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
315 root = self.tree.AddRoot("wxPython Overview")
316 firstChild = None
317 for item in _treeList:
318 child = self.tree.AppendItem(root, item[0])
319 if not firstChild: firstChild = child
320 for childItem in item[1]:
321 theDemo = self.tree.AppendItem(child, childItem)
322 self.treeMap[childItem] = theDemo
323
324 self.tree.Expand(root)
325 self.tree.Expand(firstChild)
326 EVT_TREE_ITEM_EXPANDED (self.tree, tID, self.OnItemExpanded)
327 EVT_TREE_ITEM_COLLAPSED (self.tree, tID, self.OnItemCollapsed)
328 EVT_TREE_SEL_CHANGED (self.tree, tID, self.OnSelChanged)
329 EVT_LEFT_DOWN (self.tree, self.OnTreeLeftDown)
330
331 # Create a Notebook
332 self.nb = wxNotebook(splitter2, -1, style=wxCLIP_CHILDREN)
333
334 # Set up a wxHtmlWindow on the Overview Notebook page
335 # we put it in a panel first because there seems to be a
336 # refresh bug of some sort (wxGTK) when it is directly in
337 # the notebook...
338 if 0: # the old way
339 self.ovr = wxHtmlWindow(self.nb, -1, size=(400, 400))
340 self.nb.AddPage(self.ovr, self.overviewText)
341
342 else: # hopefully I can remove this hacky code soon, see bug #216861
343 panel = wxPanel(self.nb, -1, style=wxCLIP_CHILDREN)
344 self.ovr = wxHtmlWindow(panel, -1, size=(400, 400))
345 self.nb.AddPage(panel, self.overviewText)
346
347 def OnOvrSize(evt, ovr=self.ovr):
348 ovr.SetSize(evt.GetSize())
349
350 EVT_SIZE(panel, OnOvrSize)
351 EVT_ERASE_BACKGROUND(panel, EmptyHandler)
352
353
354 self.SetOverview(self.overviewText, overview)
355
356
357 # Set up a TextCtrl on the Demo Code Notebook page
358 self.txt = wxTextCtrl(self.nb, -1,
359 style = wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL)
360 self.nb.AddPage(self.txt, "Demo Code")
361
362
363 # Set up a log on the View Log Notebook page
364 self.log = wxTextCtrl(splitter2, -1,
365 style = wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL)
366
367 # Set the wxWindows log target to be this textctrl
368 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
369
370 # But instead of the above we want to show how to use our own wxLog class
371 wxLog_SetActiveTarget(MyLog(self.log))
372
373 # for serious debugging
374 #wxLog_SetActiveTarget(wxLogStderr())
375 #wxLog_SetTraceMask(wxTraceMessages)
376
377 self.Show(true)
378
379
380 # add the windows to the splitter and split it.
381 splitter2.SplitHorizontally(self.nb, self.log)
382 splitter.SplitVertically(self.tree, splitter2)
383
384 splitter.SetSashPosition(180, true)
385 splitter.SetMinimumPaneSize(20)
386 splitter2.SetSashPosition(450, true)
387 splitter2.SetMinimumPaneSize(20)
388
389
390
391 # select initial items
392 self.nb.SetSelection(0)
393 self.tree.SelectItem(root)
394
395 if len(sys.argv) == 2:
396 try:
397 selectedDemo = self.treeMap[sys.argv[1]]
398 except:
399 selectedDemo = None
400 if selectedDemo:
401 self.tree.SelectItem(selectedDemo)
402 self.tree.EnsureVisible(selectedDemo)
403
404
405 wxLogMessage('window handle: %s' % self.GetHandle())
406
407
408 #---------------------------------------------
409 def WriteText(self, text):
410 if text[-1:] == '\n':
411 text = text[:-1]
412 wxLogMessage(text)
413
414
415 def write(self, txt):
416 self.WriteText(txt)
417
418 #---------------------------------------------
419 def OnItemExpanded(self, event):
420 item = event.GetItem()
421 wxLogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
422 event.Skip()
423
424 #---------------------------------------------
425 def OnItemCollapsed(self, event):
426 item = event.GetItem()
427 wxLogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
428 event.Skip()
429
430 #---------------------------------------------
431 def OnTreeLeftDown(self, event):
432 pt = event.GetPosition();
433 item, flags = self.tree.HitTest(pt)
434 if item == self.tree.GetSelection():
435 self.SetOverview(self.tree.GetItemText(item)+" Overview", self.curOverview)
436 event.Skip()
437
438 #---------------------------------------------
439 def OnSelChanged(self, event):
440 if self.dying:
441 return
442
443 item = event.GetItem()
444 itemText = self.tree.GetItemText(item)
445 self.RunDemo(itemText)
446
447
448 #---------------------------------------------
449 def RunDemo(self, itemText):
450 os.chdir(self.cwd)
451 if self.nb.GetPageCount() == 3:
452 if self.nb.GetSelection() == 2:
453 self.nb.SetSelection(0)
454 self.nb.DeletePage(2)
455
456 if itemText == self.overviewText:
457 self.GetDemoFile('Main.py')
458 self.SetOverview(self.overviewText, overview)
459 self.nb.Refresh();
460 self.window = None
461
462 else:
463 if os.path.exists(itemText + '.py'):
464 wxBeginBusyCursor()
465 wxLogMessage("Running demo %s.py..." % itemText)
466 try:
467 self.GetDemoFile(itemText + '.py')
468 module = __import__(itemText, globals())
469 self.SetOverview(itemText + " Overview", module.overview)
470 finally:
471 wxEndBusyCursor()
472 self.tree.Refresh()
473
474 # in case runTest is modal, make sure things look right...
475 self.nb.Refresh();
476 wxSafeYield()
477
478 self.window = module.runTest(self, self.nb, self) ###
479 if self.window:
480 self.nb.AddPage(self.window, 'Demo')
481 self.nb.SetSelection(2)
482 self.nb.Refresh() # without this wxMac has troubles showing the just added page
483
484 else:
485 self.ovr.SetPage("")
486 self.txt.Clear()
487 self.window = None
488
489
490
491 #---------------------------------------------
492 # Get the Demo files
493 def GetDemoFile(self, filename):
494 self.txt.Clear()
495 try:
496 self.txt.SetValue(open(filename).read())
497 except IOError:
498 self.txt.WriteText("Cannot open %s file." % filename)
499
500 self.txt.SetInsertionPoint(0)
501 self.txt.ShowPosition(0)
502
503 #---------------------------------------------
504 def SetOverview(self, name, text):
505 self.curOverview = text
506 lead = text[:6]
507 if lead != '<html>' and lead != '<HTML>':
508 text = string.join(string.split(text, '\n'), '<br>')
509 self.ovr.SetPage(text)
510 self.nb.SetPageText(0, name)
511
512 #---------------------------------------------
513 # Menu methods
514 def OnFileExit(self, *event):
515 self.Close()
516
517
518 def OnHelpAbout(self, event):
519 from About import MyAboutBox
520 about = MyAboutBox(self)
521 about.ShowModal()
522 about.Destroy()
523
524
525 #---------------------------------------------
526 def OnCloseWindow(self, event):
527 self.dying = true
528 self.window = None
529 self.mainmenu = None
530 if hasattr(self, "tbicon"):
531 del self.tbicon
532 self.Destroy()
533
534
535 #---------------------------------------------
536 def OnIdle(self, event):
537 if self.otherWin:
538 self.otherWin.Raise()
539 self.window = self.otherWin
540 self.otherWin = None
541
542 if self.showTip:
543 self.ShowTip()
544 self.showTip = false
545
546
547 #---------------------------------------------
548 def ShowTip(self):
549 try:
550 showTipText = open(opj("data/showTips")).read()
551 showTip, index = eval(showTipText)
552 except IOError:
553 showTip, index = (1, 0)
554 if showTip:
555 tp = wxCreateFileTipProvider(opj("data/tips.txt"), index)
556 ##tp = MyTP(0)
557 showTip = wxShowTip(self, tp)
558 index = tp.GetCurrentTip()
559 open(opj("data/showTips"), "w").write(str( (showTip, index) ))
560
561
562 #---------------------------------------------
563 def OnDemoMenu(self, event):
564 try:
565 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
566 except:
567 selectedDemo = None
568 if selectedDemo:
569 self.tree.SelectItem(selectedDemo)
570 self.tree.EnsureVisible(selectedDemo)
571
572
573 #---------------------------------------------
574 def OnTaskBarActivate(self, evt):
575 if self.IsIconized():
576 self.Iconize(false)
577 if not self.IsShown():
578 self.Show(true)
579 self.Raise()
580
581 #---------------------------------------------
582
583 TBMENU_RESTORE = 1000
584 TBMENU_CLOSE = 1001
585
586 def OnTaskBarMenu(self, evt):
587 menu = wxMenu()
588 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
589 menu.Append(self.TBMENU_CLOSE, "Close")
590 self.tbicon.PopupMenu(menu)
591 menu.Destroy()
592
593 #---------------------------------------------
594 def OnTaskBarClose(self, evt):
595 self.Close()
596
597 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
598 # prod the main idle handler a bit to get the window to actually close
599 wxGetApp().ProcessIdle()
600
601
602 #---------------------------------------------
603 def OnIconfiy(self, evt):
604 wxLogMessage("OnIconfiy")
605 evt.Skip()
606
607 #---------------------------------------------
608 def OnMaximize(self, evt):
609 wxLogMessage("OnMaximize")
610 evt.Skip()
611
612
613
614
615 #---------------------------------------------------------------------------
616 #---------------------------------------------------------------------------
617
618 class MySplashScreen(wxSplashScreen):
619 def __init__(self):
620 bmp = wxImage(opj("bitmaps/splash.gif")).ConvertToBitmap()
621 wxSplashScreen.__init__(self, bmp,
622 wxSPLASH_CENTRE_ON_SCREEN|wxSPLASH_TIMEOUT,
623 4000, None, -1,
624 style = wxSIMPLE_BORDER|wxFRAME_NO_TASKBAR|wxSTAY_ON_TOP)
625 EVT_CLOSE(self, self.OnClose)
626
627 def OnClose(self, evt):
628 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
629 frame.Show(true)
630 evt.Skip() # Make sure the default handler runs too...
631
632
633 class MyApp(wxApp):
634 def OnInit(self):
635 """
636 Create and show the splash screen. It will then create and show
637 the main frame when it is time to do so.
638 """
639 wxInitAllImageHandlers()
640 splash = MySplashScreen()
641 splash.Show()
642 return true
643
644
645
646 #---------------------------------------------------------------------------
647
648 def main():
649 try:
650 demoPath = os.path.dirname(__file__)
651 os.chdir(demoPath)
652 except:
653 pass
654 app = MyApp(wxPlatform == "__WXMAC__")
655 app.MainLoop()
656
657
658 #---------------------------------------------------------------------------
659
660
661
662 overview = """<html><body>
663 <h2>Python</h2>
664
665 Python is an interpreted, interactive, object-oriented programming
666 language often compared to Tcl, Perl, Scheme, or Java.
667
668 <p> Python combines remarkable power with very clear syntax. It has
669 modules, classes, exceptions, very high level dynamic data types, and
670 dynamic typing. There are interfaces to many system calls and
671 libraries, and new built-in modules are easily written in C or
672 C++. Python is also usable as an extension language for applications
673 that need a programmable interface. <p>
674
675 <h2>wxWindows</h2>
676
677 wxWindows is a free C++ framework designed to make cross-platform
678 programming child's play. Well, almost. wxWindows 2 supports Windows
679 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
680 underway. Other ports are under consideration. <p>
681
682 wxWindows is a set of libraries that allows C++ applications to
683 compile and run on several different types of computers, with minimal
684 source code changes. There is one library per supported GUI (such as
685 Motif, or Windows). As well as providing a common API (Application
686 Programming Interface) for GUI functionality, it provides
687 functionality for accessing some commonly-used operating system
688 facilities, such as copying or deleting files. wxWindows is a
689 'framework' in the sense that it provides a lot of built-in
690 functionality, which the application can use or replace as required,
691 thus saving a great deal of coding effort. Basic data structures such
692 as strings, linked lists and hash tables are also supported.
693
694 <p>
695 <h2>wxPython</h2>
696
697 wxPython is a Python extension module that encapsulates the wxWindows
698 GUI classes. Currently it is only available for the Win32 and GTK
699 ports of wxWindows, but as soon as the other ports are brought up to
700 the same level as Win32 and GTK, it should be fairly trivial to
701 enable wxPython to be used with the new GUI.
702
703 <p>
704
705 The wxPython extension module attempts to mirror the class heiarchy
706 of wxWindows as closely as possible. This means that there is a
707 wxFrame class in wxPython that looks, smells, tastes and acts almost
708 the same as the wxFrame class in the C++ version. Unfortunately,
709 because of differences in the languages, wxPython doesn't match
710 wxWindows exactly, but the differences should be easy to absorb
711 because they are natural to Python. For example, some methods that
712 return multiple values via argument pointers in C++ will return a
713 tuple of values in Python.
714
715 <p>
716
717 There is still much to be done for wxPython, many classes still need
718 to be mirrored. Also, wxWindows is still somewhat of a moving target
719 so it is a bit of an effort just keeping wxPython up to date. On the
720 other hand, there are enough of the core classes completed that
721 useful applications can be written.
722
723 <p>
724
725 wxPython is close enough to the C++ version that the majority of
726 the wxPython documentation is actually just notes attached to the C++
727 documents that describe the places where wxPython is different. There
728 is also a series of sample programs included, and a series of
729 documentation pages that assist the programmer in getting started
730 with wxPython.
731
732 """
733
734
735 #----------------------------------------------------------------------------
736 #----------------------------------------------------------------------------
737
738 if __name__ == '__main__':
739 main()
740
741 #----------------------------------------------------------------------------
742
743
744
745
746
747
748