]> git.saurik.com Git - wxWidgets.git/blame_incremental - wxPython/demo/Main.py
added a few encoding convenience methods for pc-mac encoding and string handling...
[wxWidgets.git] / wxPython / demo / Main.py
... / ...
CommitLineData
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
14import sys, os
15from wxPython.wx import *
16from wxPython.lib.splashscreen import SplashScreen
17from wxPython.html import wxHtmlWindow
18
19import images
20
21#---------------------------------------------------------------------------
22
23
24_treeList = [
25 ('New since last release', ['ContextHelp',
26 'PyCrust',
27 'VirtualListCtrl'
28 ]),
29
30 ('Managed Windows', ['wxFrame', 'wxDialog', 'wxMiniFrame']),
31
32 ('Non-Managed Windows', ['wxGrid', 'wxSashWindow',
33 'wxScrolledWindow', 'wxSplitterWindow',
34 'wxStatusBar', 'wxNotebook',
35 'wxHtmlWindow',
36 'wxStyledTextCtrl_1', 'wxStyledTextCtrl_2',]),
37
38 ('Common Dialogs', ['wxColourDialog', 'wxDirDialog', 'wxFileDialog',
39 'wxSingleChoiceDialog', 'wxTextEntryDialog',
40 'wxFontDialog', 'wxPageSetupDialog', 'wxPrintDialog',
41 'wxMessageDialog', 'wxProgressDialog']),
42
43 ('Controls', ['wxButton', 'wxCheckBox', 'wxCheckListBox', 'wxChoice',
44 'wxComboBox', 'wxGauge', 'wxListBox', 'wxListCtrl', 'wxTextCtrl',
45 'wxTreeCtrl', 'wxSpinButton', 'wxSpinCtrl', 'wxStaticText',
46 'wxStaticBitmap', 'wxRadioBox', 'wxSlider', 'wxToolBar',
47 'wxCalendarCtrl', 'wxToggleButton',
48 ]),
49
50 ('Window Layout', ['wxLayoutConstraints', 'LayoutAnchors', 'Sizers', 'XML_Resource']),
51
52 ('Miscellaneous', [ 'DragAndDrop', 'CustomDragAndDrop', 'FontEnumerator',
53 'wxTimer', 'wxValidator', 'wxGLCanvas', 'DialogUnits',
54 'wxImage', 'wxMask', 'PrintFramework', 'wxOGL',
55 'PythonEvents', 'Threads',
56 'ActiveXWrapper_Acrobat', 'ActiveXWrapper_IE',
57 'wxDragImage', "wxProcess", "FancyText", "OOR", "wxWave",
58 'wxJoystick',
59 ]),
60
61 ('wxPython Library', ['Layoutf', 'wxScrolledMessageDialog',
62 'wxMultipleChoiceDialog', 'wxPlotCanvas', 'wxFloatBar',
63 'wxCalendar', 'wxMVCTree', 'wxVTKRenderWindow',
64 'FileBrowseButton', 'GenericButtons', 'wxEditor',
65 'ColourSelect', 'ImageBrowser',
66 'infoframe', 'ColourDB', 'PyCrust',
67 ]),
68
69 ('Cool Contribs', ['pyTree', 'hangman', 'SlashDot', 'XMLtreeview']),
70
71 ]
72
73#---------------------------------------------------------------------------
74
75class wxPythonDemo(wxFrame):
76
77 def __init__(self, parent, id, title):
78 wxFrame.__init__(self, parent, -1, title, size = (800, 600),
79 style=wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
80
81 self.cwd = os.getcwd()
82 self.curOverview = ""
83
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
92 self.SetIcon(icon)
93
94 if wxPlatform == '__WXMSW__':
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
103
104 self.otherWin = None
105 EVT_IDLE(self, self.OnIdle)
106 EVT_CLOSE(self, self.OnCloseWindow)
107 EVT_ICONIZE(self, self.OnIconfiy)
108 EVT_MAXIMIZE(self, self.OnMaximize)
109
110 self.Centre(wxBOTH)
111 self.CreateStatusBar(1, wxST_SIZEGRIP)
112
113 splitter = wxSplitterWindow(self, -1, style=wxNO_3D|wxSP_3D)
114 splitter2 = wxSplitterWindow(splitter, -1, style=wxNO_3D|wxSP_3D)
115
116 def EmptyHandler(evt): pass
117 EVT_ERASE_BACKGROUND(splitter, EmptyHandler)
118 EVT_ERASE_BACKGROUND(splitter2, EmptyHandler)
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()
126 exitID = wxNewId()
127 menu.Append(exitID, 'E&xit\tAlt-X', 'Get the heck outta here!')
128 EVT_MENU(self, exitID, self.OnFileExit)
129 self.mainmenu.Append(menu, '&File')
130
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
143 # Make a Help menu
144 helpID = wxNewId()
145 menu = wxMenu()
146 menu.Append(helpID, '&About\tCtrl-H', 'wxPython RULES!!!')
147 EVT_MENU(self, helpID, self.OnHelpAbout)
148 self.mainmenu.Append(menu, '&Help')
149 self.SetMenuBar(self.mainmenu)
150
151 # set the menu accellerator table...
152 aTable = wxAcceleratorTable([(wxACCEL_ALT, ord('X'), exitID),
153 (wxACCEL_CTRL, ord('H'), helpID)])
154 self.SetAcceleratorTable(aTable)
155
156
157 # Create a TreeCtrl
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)
181
182 # Create a Notebook
183 self.nb = wxNotebook(splitter2, -1, style=wxCLIP_CHILDREN)
184
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
193 else: # hopefully I can remove this hacky code soon, see bug #216861
194 panel = wxPanel(self.nb, -1, style=wxCLIP_CHILDREN)
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)
202 EVT_ERASE_BACKGROUND(panel, EmptyHandler)
203
204
205 self.SetOverview("Overview", overview)
206
207
208 # Set up a TextCtrl on the Demo Code Notebook page
209 self.txt = wxTextCtrl(self.nb, -1,
210 style = wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL)
211 self.txt.SetFont(wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false))
212 self.nb.AddPage(self.txt, "Demo Code")
213
214
215 # Set up a log on the View Log Notebook page
216 self.log = wxTextCtrl(splitter2, -1,
217 style = wxTE_MULTILINE|wxTE_READONLY|wxHSCROLL)
218 # Set the wxWindows log target to be this textctrl
219 wxLog_SetActiveTarget(wxLogTextCtrl(self.log))
220
221
222
223 self.Show(true)
224
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)
229
230 splitter.SplitVertically(self.tree, splitter2)
231 splitter.SetSashPosition(180, true)
232 splitter.SetMinimumPaneSize(20)
233
234
235 # select initial items
236 self.nb.SetSelection(0)
237 self.tree.SelectItem(root)
238
239 if len(sys.argv) == 2:
240 try:
241 selectedDemo = self.treeMap[sys.argv[1]]
242 except:
243 selectedDemo = None
244 if selectedDemo:
245 self.tree.SelectItem(selectedDemo)
246 self.tree.EnsureVisible(selectedDemo)
247
248
249 wxLogMessage('window handle: %s' % self.GetHandle())
250
251
252 #---------------------------------------------
253 def WriteText(self, text):
254 if text[-1:] == '\n':
255 text = text[:-1]
256 wxLogMessage(text)
257
258
259 def write(self, txt):
260 self.WriteText(txt)
261
262 #---------------------------------------------
263 def OnItemExpanded(self, event):
264 item = event.GetItem()
265 wxLogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
266 event.Skip()
267
268 #---------------------------------------------
269 def OnItemCollapsed(self, event):
270 item = event.GetItem()
271 wxLogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
272 event.Skip()
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)
280 event.Skip()
281
282 #---------------------------------------------
283 def OnSelChanged(self, event):
284 if self.dying:
285 return
286
287 item = event.GetItem()
288 itemText = self.tree.GetItemText(item)
289 self.RunDemo(itemText)
290
291
292 #---------------------------------------------
293 def RunDemo(self, itemText):
294 os.chdir(self.cwd)
295 if self.nb.GetPageCount() == 3:
296 if self.nb.GetSelection() == 2:
297 self.nb.SetSelection(0)
298 self.nb.DeletePage(2)
299
300 if itemText == 'Overview':
301 self.GetDemoFile('Main.py')
302 self.SetOverview('Overview', overview)
303 self.nb.Refresh();
304 self.window = None
305
306 else:
307 if os.path.exists(itemText + '.py'):
308 wxBeginBusyCursor()
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()
316
317 # in case runTest is modal, make sure things look right...
318 self.nb.Refresh();
319 wxYield()
320
321 self.window = module.runTest(self, self.nb, self) ###
322 if self.window:
323 self.nb.AddPage(self.window, 'Demo')
324 wxYield()
325 self.nb.SetSelection(2)
326
327 else:
328 self.ovr.SetPage("")
329 self.txt.Clear()
330 self.window = None
331
332
333
334 #---------------------------------------------
335 # Get the Demo files
336 def GetDemoFile(self, filename):
337 self.txt.Clear()
338 try:
339 self.txt.SetValue(open(filename).read())
340 except IOError:
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):
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)
354 self.nb.SetPageText(0, name)
355
356 #---------------------------------------------
357 # Menu methods
358 def OnFileExit(self, *event):
359 self.Close()
360
361
362 def OnHelpAbout(self, event):
363 from About import MyAboutBox
364 about = MyAboutBox(self)
365 about.ShowModal()
366 about.Destroy()
367
368
369 #---------------------------------------------
370 def OnCloseWindow(self, event):
371 self.dying = true
372 self.window = None
373 self.mainmenu = None
374 if hasattr(self, "tbicon"):
375 del self.tbicon
376 self.Destroy()
377
378
379 #---------------------------------------------
380 def OnIdle(self, event):
381 if self.otherWin:
382 self.otherWin.Raise()
383 self.window = self.otherWin
384 self.otherWin = None
385
386 #---------------------------------------------
387 def OnDemoMenu(self, event):
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)
395
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
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
439#---------------------------------------------------------------------------
440#---------------------------------------------------------------------------
441
442class MyApp(wxApp):
443 def OnInit(self):
444 wxInitAllImageHandlers()
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
452
453 def AfterSplash(self):
454 self.splash.Close(true)
455 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
456 frame.Show(true)
457 self.SetTopWindow(frame)
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)
467 #print showTip, index
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
474
475#---------------------------------------------------------------------------
476
477def main():
478 try:
479 demoPath = os.path.dirname(__file__)
480 os.chdir(demoPath)
481 except:
482 pass
483 app = MyApp(0)
484 app.MainLoop()
485
486
487#---------------------------------------------------------------------------
488
489
490
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 """
562
563
564#----------------------------------------------------------------------------
565#----------------------------------------------------------------------------
566
567if __name__ == '__main__':
568 main()
569
570#----------------------------------------------------------------------------
571
572
573
574
575
576
577