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