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