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