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