]> git.saurik.com Git - wxWidgets.git/blame - wxPython/demo/Main.py
fixed restoration of global cursor
[wxWidgets.git] / wxPython / demo / Main.py
CommitLineData
cf694132
RD
1#!/bin/env python
2#----------------------------------------------------------------------------
3# Name: Main.py
4# Purpose: Testing lots of stuff, controls, window types, etc.
5#
f6bcfd97 6# Author: Robin Dunn
cf694132 7#
f6bcfd97 8# Created: A long time ago, in a galaxy far, far away...
cf694132
RD
9# RCS-ID: $Id$
10# Copyright: (c) 1999 by Total Control Software
11# Licence: wxWindows license
12#----------------------------------------------------------------------------
13
76bfdc78 14import sys, os, time
cf694132 15from wxPython.wx import *
9fb56e0c 16from wxPython.lib.splashscreen import SplashScreen
f6bcfd97 17from wxPython.html import wxHtmlWindow
cf694132 18
96bfd053
RD
19import images
20
cf694132
RD
21#---------------------------------------------------------------------------
22
23
24_treeList = [
4f3449b4 25 ('New since last release', ['ContextHelp',
c7e7022c 26 'PyCrust',
fea018f8 27 'PyCrustWithFilling',
6d19860f
RD
28 'VirtualListCtrl',
29 'wxListCtrl',
53fe40ba 30 'TablePrint',
0122b7e3
RD
31 'OOR',
32 'wxFindReplaceDialog',
33 ##'wxPopupWindow',
f6bcfd97 34 ]),
e395c057 35
6d19860f 36 ('Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame',
6d19860f
RD
37 'wxGrid', 'wxSashWindow',
38 'wxScrolledWindow', 'wxSplitterWindow',
39 'wxStatusBar', 'wxNotebook',
40 'wxHtmlWindow',
0122b7e3
RD
41 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',
42 ##'wxPopupWindow',
43 ]),
cf694132
RD
44
45 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
46 'wxSingleChoiceDialog', 'wxTextEntryDialog',
47 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
0122b7e3
RD
48 'wxMessageDialog', 'wxProgressDialog', 'wxFindReplaceDialog',
49 ]),
cf694132
RD
50
51 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
52 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl',
f6bcfd97
BP
53 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
54 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
d1679124 55 'wxCalendarCtrl', 'wxToggleButton',
6999b0d8 56 ]),
cf694132 57
4f3449b4 58 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']),
cf694132 59
b1462dfa
RD
60 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'FontEnumerator',
61 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
9b3d3bc4 62 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
f6bcfd97
BP
63 'PythonEvents', 'Threads',
64 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
493f1553 65 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
ac346f50 66 'wxJoystick',
f6bcfd97 67 ]),
cf694132 68
e0473f5f 69 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
f0261a72 70 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
c7e7022c 71 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
c368d904 72 'FileBrowseButton', 'GenericButtons', 'wxEditor',
c7e7022c 73 'ColourSelect', 'ImageBrowser',
53fe40ba 74 'infoframe', 'ColourDB', 'PyCrust', 'TablePrint',
c368d904 75 ]),
cf694132 76
8bf5d46e 77 ('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']),
cf694132
RD
78
79 ]
80
81#---------------------------------------------------------------------------
82
76bfdc78
RD
83class MyLog(wxPyLog):
84 def __init__(self, textCtrl, logTime=0):
85 wxPyLog.__init__(self)
86 self.tc = textCtrl
87 self.logTime = logTime
88
89 def DoLogString(self, message, timeStamp):
90 if self.logTime:
91 message = time.strftime("%X", time.localtime(timeStamp)) + \
92 ": " + message
93 self.tc.AppendText(message + '\n')
94
95
96#---------------------------------------------------------------------------
97
cf694132 98class wxPythonDemo(wxFrame):
c368d904 99
cf694132 100 def __init__(self, parent, id, title):
f6bcfd97
BP
101 wxFrame.__init__(self, parent, -1, title, size = (800, 600),
102 style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
2f90df85 103
694759cf 104 self.cwd = os.getcwd()
3ca6a5f0 105 self.curOverview = ""
694759cf 106
b6962846
RD
107 if 1:
108 icon = wxIconFromXPMData(images.getMondrianData())
109 else:
110 # another way to do it
111 bmp = images.getMondrianBitmap()
112 icon = wxEmptyIcon()
113 icon.CopyFromBitmap(bmp)
114
96bfd053 115 self.SetIcon(icon)
c368d904 116
96bfd053 117 if wxPlatform == '__WXMSW__':
c368d904
RD
118 # setup a taskbar icon, and catch some events from it
119 self.tbicon = wxTaskBarIcon()
120 self.tbicon.SetIcon(icon, "wxPython Demo")
121 EVT_TASKBAR_LEFT_DCLICK(self.tbicon, self.OnTaskBarActivate)
122 EVT_TASKBAR_RIGHT_UP(self.tbicon, self.OnTaskBarMenu)
123 EVT_MENU(self.tbicon, self.TBMENU_RESTORE, self.OnTaskBarActivate)
124 EVT_MENU(self.tbicon, self.TBMENU_CLOSE, self.OnTaskBarClose)
125
cf694132
RD
126
127 self.otherWin = None
128 EVT_IDLE(self, self.OnIdle)
f6bcfd97 129 EVT_CLOSE(self, self.OnCloseWindow)
f3d9dc1d
RD
130 EVT_ICONIZE(self, self.OnIconfiy)
131 EVT_MAXIMIZE(self, self.OnMaximize)
cf694132
RD
132
133 self.Centre(wxBOTH)
134 self.CreateStatusBar(1, wxST_SIZEGRIP)
5a7823f5 135
f6bcfd97
BP
136 splitter = wxSplitterWindow(self, -1, style=wxNO_3D|wxSP_3D)
137 splitter2 = wxSplitterWindow(splitter, -1, style=wxNO_3D|wxSP_3D)
5a7823f5 138
d56cebe7
RD
139 def EmptyHandler(evt): pass
140 EVT_ERASE_BACKGROUND(splitter, EmptyHandler)
141 EVT_ERASE_BACKGROUND(splitter2, EmptyHandler)
cf694132 142
b1cfebd9 143 # Prevent TreeCtrl from displaying all items after destruction when true
cf694132
RD
144 self.dying = false
145
146 # Make a File menu
147 self.mainmenu = wxMenuBar()
148 menu = wxMenu()
2f90df85 149 exitID = wxNewId()
f0261a72 150 menu.Append(exitID, 'E&xit\tAlt-X', 'Get the heck outta here!')
2f90df85 151 EVT_MENU(self, exitID, self.OnFileExit)
cf694132
RD
152 self.mainmenu.Append(menu, '&File')
153
ec3e670f
RD
154 # Make a Demo menu
155 menu = wxMenu()
156 for item in _treeList:
157 submenu = wxMenu()
158 for childItem in item[1]:
159 mID = wxNewId()
160 submenu.Append(mID, childItem)
161 EVT_MENU(self, mID, self.OnDemoMenu)
162 menu.AppendMenu(wxNewId(), item[0], submenu)
163 self.mainmenu.Append(menu, '&Demo')
164
165
cf694132 166 # Make a Help menu
2f90df85 167 helpID = wxNewId()
cf694132 168 menu = wxMenu()
2f90df85
RD
169 menu.Append(helpID, '&About\tCtrl-H', 'wxPython RULES!!!')
170 EVT_MENU(self, helpID, self.OnHelpAbout)
cf694132
RD
171 self.mainmenu.Append(menu, '&Help')
172 self.SetMenuBar(self.mainmenu)
173
2f90df85 174 # set the menu accellerator table...
f0261a72 175 aTable = wxAcceleratorTable([(wxACCEL_ALT, ord('X'), exitID),
2f90df85
RD
176 (wxACCEL_CTRL, ord('H'), helpID)])
177 self.SetAcceleratorTable(aTable)
178
bb0054cd 179
cf694132 180 # Create a TreeCtrl
f6bcfd97
BP
181 tID = wxNewId()
182 self.treeMap = {}
183 self.tree = wxTreeCtrl(splitter, tID,
184 style=wxTR_HAS_BUTTONS |
185 wxTR_EDIT_LABELS |
186 wxTR_HAS_VARIABLE_ROW_HEIGHT |
187 wxSUNKEN_BORDER)
188 #self.tree.SetBackgroundColour(wxNamedColour("Pink"))
189 root = self.tree.AddRoot("Overview")
190 firstChild = None
191 for item in _treeList:
192 child = self.tree.AppendItem(root, item[0])
193 if not firstChild: firstChild = child
194 for childItem in item[1]:
195 theDemo = self.tree.AppendItem(child, childItem)
196 self.treeMap[childItem] = theDemo
197
198 self.tree.Expand(root)
199 self.tree.Expand(firstChild)
200 EVT_TREE_ITEM_EXPANDED (self.tree, tID, self.OnItemExpanded)
201 EVT_TREE_ITEM_COLLAPSED (self.tree, tID, self.OnItemCollapsed)
202 EVT_TREE_SEL_CHANGED (self.tree, tID, self.OnSelChanged)
203 EVT_LEFT_DOWN (self.tree, self.OnTreeLeftDown)
cf694132 204
cf694132 205 # Create a Notebook
d56cebe7 206 self.nb = wxNotebook(splitter2, -1, style=wxCLIP_CHILDREN)
cf694132 207
c368d904
RD
208 # Set up a wxHtmlWindow on the Overview Notebook page
209 # we put it in a panel first because there seems to be a
210 # refresh bug of some sort (wxGTK) when it is directly in
211 # the notebook...
212 if 0: # the old way
213 self.ovr = wxHtmlWindow(self.nb, -1, size=(400, 400))
214 self.nb.AddPage(self.ovr, "Overview")
215
e87269a7 216 else: # hopefully I can remove this hacky code soon, see bug #216861
d56cebe7 217 panel = wxPanel(self.nb, -1, style=wxCLIP_CHILDREN)
c368d904
RD
218 self.ovr = wxHtmlWindow(panel, -1, size=(400, 400))
219 self.nb.AddPage(panel, "Overview")
220
221 def OnOvrSize(evt, ovr=self.ovr):
222 ovr.SetSize(evt.GetSize())
223
224 EVT_SIZE(panel, OnOvrSize)
d56cebe7
RD
225 EVT_ERASE_BACKGROUND(panel, EmptyHandler)
226
c368d904
RD
227
228 self.SetOverview("Overview", overview)
cf694132
RD
229
230
231 # Set up a TextCtrl on the Demo Code Notebook page
efc5f224
RD
232 self.txt = wxTextCtrl(self.nb, -1,
233 style = wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL)
cf694132
RD
234 self.nb.AddPage(self.txt, "Demo Code")
235
236
cf694132 237 # Set up a log on the View Log Notebook page
f6bcfd97 238 self.log = wxTextCtrl(splitter2, -1,
efc5f224 239 style = wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL)
f6bcfd97 240 # Set the wxWindows log target to be this textctrl
76bfdc78
RD
241 #wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
242 wxLog_SetActiveTarget(MyLog(self.log))
cf694132
RD
243
244
5a7823f5 245
f6bcfd97 246 self.Show(true)
5a7823f5 247
f6bcfd97
BP
248 # add the windows to the splitter and split it.
249 splitter2.SplitHorizontally(self.nb, self.log)
250 splitter2.SetSashPosition(450, true)
251 splitter2.SetMinimumPaneSize(20)
cf694132 252
f6bcfd97
BP
253 splitter.SplitVertically(self.tree, splitter2)
254 splitter.SetSashPosition(180, true)
255 splitter.SetMinimumPaneSize(20)
cf694132 256
cf694132 257
bb0054cd
RD
258 # select initial items
259 self.nb.SetSelection(0)
f6bcfd97 260 self.tree.SelectItem(root)
ec3e670f
RD
261
262 if len(sys.argv) == 2:
263 try:
264 selectedDemo = self.treeMap[sys.argv[1]]
265 except:
266 selectedDemo = None
f6bcfd97 267 if selectedDemo:
ec3e670f
RD
268 self.tree.SelectItem(selectedDemo)
269 self.tree.EnsureVisible(selectedDemo)
270
bb0054cd 271
f6bcfd97 272 wxLogMessage('window handle: %s' % self.GetHandle())
2abc0a0f
RD
273
274
cf694132
RD
275 #---------------------------------------------
276 def WriteText(self, text):
f6bcfd97
BP
277 if text[-1:] == '\n':
278 text = text[:-1]
279 wxLogMessage(text)
280
cf694132
RD
281
282 def write(self, txt):
283 self.WriteText(txt)
284
285 #---------------------------------------------
286 def OnItemExpanded(self, event):
287 item = event.GetItem()
f6bcfd97 288 wxLogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
c368d904 289 event.Skip()
cf694132
RD
290
291 #---------------------------------------------
292 def OnItemCollapsed(self, event):
293 item = event.GetItem()
f6bcfd97 294 wxLogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
c368d904 295 event.Skip()
f6bcfd97
BP
296
297 #---------------------------------------------
298 def OnTreeLeftDown(self, event):
299 pt = event.GetPosition();
300 item, flags = self.tree.HitTest(pt)
301 if item == self.tree.GetSelection():
302 self.SetOverview(self.tree.GetItemText(item), self.curOverview)
185d7c3e 303 event.Skip()
cf694132
RD
304
305 #---------------------------------------------
306 def OnSelChanged(self, event):
307 if self.dying:
308 return
309
5a7823f5
RD
310 item = event.GetItem()
311 itemText = self.tree.GetItemText(item)
312 self.RunDemo(itemText)
313
314
315 #---------------------------------------------
316 def RunDemo(self, itemText):
694759cf 317 os.chdir(self.cwd)
cf694132
RD
318 if self.nb.GetPageCount() == 3:
319 if self.nb.GetSelection() == 2:
320 self.nb.SetSelection(0)
321 self.nb.DeletePage(2)
322
cf694132
RD
323 if itemText == 'Overview':
324 self.GetDemoFile('Main.py')
325 self.SetOverview('Overview', overview)
cf694132 326 self.nb.Refresh();
e91a9dfc 327 self.window = None
cf694132
RD
328
329 else:
330 if os.path.exists(itemText + '.py'):
9d8bd15f 331 wxBeginBusyCursor()
f6bcfd97
BP
332 wxLogMessage("Running demo %s.py..." % itemText)
333 try:
334 self.GetDemoFile(itemText + '.py')
335 module = __import__(itemText, globals())
336 self.SetOverview(itemText, module.overview)
337 finally:
338 wxEndBusyCursor()
cf694132
RD
339
340 # in case runTest is modal, make sure things look right...
341 self.nb.Refresh();
342 wxYield()
343
f6bcfd97 344 self.window = module.runTest(self, self.nb, self) ###
e91a9dfc
RD
345 if self.window:
346 self.nb.AddPage(self.window, 'Demo')
dcd38683 347 wxYield()
cf694132 348 self.nb.SetSelection(2)
cf694132
RD
349
350 else:
f6bcfd97 351 self.ovr.SetPage("")
cf694132 352 self.txt.Clear()
e91a9dfc 353 self.window = None
cf694132 354
2f90df85 355
cf694132
RD
356
357 #---------------------------------------------
358 # Get the Demo files
359 def GetDemoFile(self, filename):
360 self.txt.Clear()
bb0054cd
RD
361 try:
362 self.txt.SetValue(open(filename).read())
8bf5d46e 363 except IOError:
cf694132
RD
364 self.txt.WriteText("Cannot open %s file." % filename)
365
366 self.txt.SetInsertionPoint(0)
367 self.txt.ShowPosition(0)
368
369 #---------------------------------------------
370 def SetOverview(self, name, text):
f6bcfd97
BP
371 self.curOverview = text
372 lead = text[:6]
373 if lead != '<html>' and lead != '<HTML>':
374 text = string.join(string.split(text, '\n'), '<br>')
375 #text = '<font size="-1"><pre>' + text + '</pre></font>'
376 self.ovr.SetPage(text)
cf694132 377 self.nb.SetPageText(0, name)
cf694132
RD
378
379 #---------------------------------------------
380 # Menu methods
c368d904 381 def OnFileExit(self, *event):
cf694132
RD
382 self.Close()
383
384
385 def OnHelpAbout(self, event):
e166644c 386 from About import MyAboutBox
ec3e670f 387 about = MyAboutBox(self)
cf694132
RD
388 about.ShowModal()
389 about.Destroy()
390
391
392 #---------------------------------------------
393 def OnCloseWindow(self, event):
394 self.dying = true
e91a9dfc 395 self.window = None
26197023 396 self.mainmenu = None
c368d904
RD
397 if hasattr(self, "tbicon"):
398 del self.tbicon
cf694132
RD
399 self.Destroy()
400
c368d904 401
cf694132
RD
402 #---------------------------------------------
403 def OnIdle(self, event):
404 if self.otherWin:
405 self.otherWin.Raise()
e91a9dfc 406 self.window = self.otherWin
cf694132
RD
407 self.otherWin = None
408
ec3e670f
RD
409 #---------------------------------------------
410 def OnDemoMenu(self, event):
f6bcfd97
BP
411 try:
412 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
413 except:
414 selectedDemo = None
415 if selectedDemo:
416 self.tree.SelectItem(selectedDemo)
417 self.tree.EnsureVisible(selectedDemo)
ec3e670f 418
c368d904
RD
419
420 #---------------------------------------------
421 def OnTaskBarActivate(self, evt):
422 if self.IsIconized():
423 self.Iconize(false)
424 if not self.IsShown():
425 self.Show(true)
426 self.Raise()
427
428 #---------------------------------------------
429
430 TBMENU_RESTORE = 1000
431 TBMENU_CLOSE = 1001
432
433 def OnTaskBarMenu(self, evt):
434 menu = wxMenu()
435 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
436 menu.Append(self.TBMENU_CLOSE, "Close")
437 self.tbicon.PopupMenu(menu)
438 menu.Destroy()
439
440 #---------------------------------------------
441 def OnTaskBarClose(self, evt):
442 self.Close()
443
444 # because of the way wxTaskBarIcon.PopupMenu is implemented we have to
445 # prod the main idle handler a bit to get the window to actually close
446 wxGetApp().ProcessIdle()
447
448
f3d9dc1d
RD
449 #---------------------------------------------
450 def OnIconfiy(self, evt):
451 wxLogMessage("OnIconfiy")
452 evt.Skip()
453
454 #---------------------------------------------
455 def OnMaximize(self, evt):
456 wxLogMessage("OnMaximize")
457 evt.Skip()
458
459
460
461
cf694132
RD
462#---------------------------------------------------------------------------
463#---------------------------------------------------------------------------
464
465class MyApp(wxApp):
466 def OnInit(self):
f6bcfd97 467 wxInitAllImageHandlers()
9fb56e0c
RD
468
469 self.splash = SplashScreen(None, bitmapfile='bitmaps/splash.gif',
470 duration=4000, callback=self.AfterSplash)
471 self.splash.Show(true)
472 wxYield()
473 return true
474
f6bcfd97 475
9fb56e0c
RD
476 def AfterSplash(self):
477 self.splash.Close(true)
478 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
cf694132
RD
479 frame.Show(true)
480 self.SetTopWindow(frame)
f6bcfd97
BP
481 self.ShowTip(frame)
482
483
484 def ShowTip(self, frame):
485 try:
486 showTipText = open("data/showTips").read()
487 showTip, index = eval(showTipText)
488 except IOError:
489 showTip, index = (1, 0)
c368d904 490 #print showTip, index
f6bcfd97
BP
491 if showTip:
492 tp = wxCreateFileTipProvider("data/tips.txt", index)
493 showTip = wxShowTip(frame, tp)
494 index = tp.GetCurrentTip()
495 open("data/showTips", "w").write(str( (showTip, index) ))
496
cf694132
RD
497
498#---------------------------------------------------------------------------
499
500def main():
e02c03a4 501 try:
d56cebe7 502 demoPath = os.path.dirname(__file__)
e02c03a4
RD
503 os.chdir(demoPath)
504 except:
505 pass
cf694132
RD
506 app = MyApp(0)
507 app.MainLoop()
508
509
510#---------------------------------------------------------------------------
511
512
513
f6bcfd97
BP
514overview = """<html><body>
515 <h2>Python</h2>
516
517 Python is an interpreted, interactive, object-oriented programming
518 language often compared to Tcl, Perl, Scheme, or Java.
519
520 <p> Python combines remarkable power with very clear syntax. It has
521 modules, classes, exceptions, very high level dynamic data types, and
522 dynamic typing. There are interfaces to many system calls and
523 libraries, and new built-in modules are easily written in C or
524 C++. Python is also usable as an extension language for applications
525 that need a programmable interface. <p>
526
527 <h2>wxWindows</h2>
528
529 wxWindows is a free C++ framework designed to make cross-platform
530 programming child's play. Well, almost. wxWindows 2 supports Windows
531 3.1/95/98/NT, Unix with GTK/Motif/Lesstif, with a Mac version
532 underway. Other ports are under consideration. <p>
533
534 wxWindows is a set of libraries that allows C++ applications to
535 compile and run on several different types of computers, with minimal
536 source code changes. There is one library per supported GUI (such as
537 Motif, or Windows). As well as providing a common API (Application
538 Programming Interface) for GUI functionality, it provides
539 functionality for accessing some commonly-used operating system
540 facilities, such as copying or deleting files. wxWindows is a
541 'framework' in the sense that it provides a lot of built-in
542 functionality, which the application can use or replace as required,
543 thus saving a great deal of coding effort. Basic data structures such
544 as strings, linked lists and hash tables are also supported.
545
546 <p>
547 <h2>wxPython</h2>
548
549 wxPython is a Python extension module that encapsulates the wxWindows
550 GUI classes. Currently it is only available for the Win32 and GTK
551 ports of wxWindows, but as soon as the other ports are brought up to
552 the same level as Win32 and GTK, it should be fairly trivial to
553 enable wxPython to be used with the new GUI.
554
555 <p>
556
557 The wxPython extension module attempts to mirror the class heiarchy
558 of wxWindows as closely as possible. This means that there is a
559 wxFrame class in wxPython that looks, smells, tastes and acts almost
560 the same as the wxFrame class in the C++ version. Unfortunately,
561 because of differences in the languages, wxPython doesn't match
562 wxWindows exactly, but the differences should be easy to absorb
563 because they are natural to Python. For example, some methods that
564 return multiple values via argument pointers in C++ will return a
565 tuple of values in Python.
566
567 <p>
568
569 There is still much to be done for wxPython, many classes still need
570 to be mirrored. Also, wxWindows is still somewhat of a moving target
571 so it is a bit of an effort just keeping wxPython up to date. On the
572 other hand, there are enough of the core classes completed that
573 useful applications can be written.
574
575 <p>
576
577 wxPython is close enough to the C++ version that the majority of
578 the wxPython documentation is actually just notes attached to the C++
579 documents that describe the places where wxPython is different. There
580 is also a series of sample programs included, and a series of
581 documentation pages that assist the programmer in getting started
582 with wxPython.
583
584 """
cf694132
RD
585
586
587#----------------------------------------------------------------------------
588#----------------------------------------------------------------------------
589
590if __name__ == '__main__':
591 main()
592
593#----------------------------------------------------------------------------
594
595
596
597
598
599
600