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