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