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