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