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