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