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