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