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