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