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