]> git.saurik.com Git - wxWidgets.git/blame - wxPython/demo/Main.py
1.
[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
1e4a197e 14import sys, os, time
cf694132 15
1fded56b
RD
16import wx # This module uses the new wx namespace
17import wx.html
606d919c 18
96bfd053
RD
19import images
20
d14a1e28
RD
21# For debugging
22##wx.Trap();
23##print os.getpid(); raw_input("Press a key...")
6fa68946 24
1e4a197e 25
cf694132
RD
26#---------------------------------------------------------------------------
27
28
29_treeList = [
9c67cbec 30 # new stuff
1e4a197e 31 ('Recent Additions', [
3628e088 32 'wxVListBox',
2f0f3b0f 33 'wxListbook',
8b9a4190
RD
34 'wxMaskedNumCtrl',
35 'FloatCanvas',
6fa68946 36 'wxXmlResourceSubclass',
d14a1e28 37 'wxGridBagSizer',
76343679 38 'Cursor',
80b27b4e 39 'PyPlot',
9c67cbec
RD
40 ]),
41
1e4a197e 42 # managed windows == things with a (optional) caption you can close
9c67cbec
RD
43 ('Base Frames and Dialogs', [
44 'wxDialog',
45 'wxFrame',
46 'wxMDIWindows',
47 'wxMiniFrame',
af83019e 48 'wxWizard',
9c67cbec
RD
49 ]),
50
51 # the common dialogs
52 ('Common Dialogs', [
53 'wxColourDialog',
54 'wxDirDialog',
55 'wxFileDialog',
1fded56b 56 'wxFileDialog_Save',
9c67cbec
RD
57 'wxFindReplaceDialog',
58 'wxFontDialog',
59 'wxMessageDialog',
60 'wxPageSetupDialog',
61 'wxPrintDialog',
62 'wxProgressDialog',
63 'wxSingleChoiceDialog',
64 'wxTextEntryDialog',
65 ]),
66
af83019e 67 # dialogs from libraries
9c67cbec
RD
68 ('More Dialogs', [
69 'ErrorDialogs',
70 'ImageBrowser',
71 'wxMultipleChoiceDialog',
72 'wxScrolledMessageDialog',
73 ]),
74
75 # core controls
76 ('Core Windows/Controls', [
1fded56b 77 'PopupMenu',
9c67cbec
RD
78 'wxButton',
79 'wxCheckBox',
80 'wxCheckListBox',
81 'wxChoice',
82 'wxComboBox',
83 'wxGauge',
9c67cbec 84 'wxGrid',
1fded56b 85 'wxGrid_MegaExample',
2f0f3b0f 86 'wxListbook',
9c67cbec
RD
87 'wxListBox',
88 'wxListCtrl',
6f48b1b5 89 'wxListCtrl_virtual',
3115ef3e 90 'wxMenu',
9c67cbec
RD
91 'wxNotebook',
92 'wxPopupWindow',
93 'wxRadioBox',
1e4a197e 94 'wxRadioButton',
9c67cbec 95 'wxSashWindow',
9c67cbec 96 'wxScrolledWindow',
1e4a197e 97 'wxSlider',
9c67cbec
RD
98 'wxSpinButton',
99 'wxSpinCtrl',
1e4a197e 100 'wxSplitterWindow',
9c67cbec 101 'wxStaticBitmap',
1e4a197e 102 'wxStaticText',
9c67cbec
RD
103 'wxStatusBar',
104 'wxTextCtrl',
9c67cbec
RD
105 'wxToggleButton',
106 'wxToolBar',
107 'wxTreeCtrl',
108 'wxValidator',
109 ]),
110
d14a1e28
RD
111 ('Custom Controls', [
112 'AnalogClockWindow',
113 'ColourSelect',
114 'GenericButtons',
115 'wxEditor',
116 'wxGenericDirCtrl',
117 'wxLEDNumberCtrl',
118 'wxMultiSash',
119 'wxPopupControl',
120 'wxPyColourChooser',
121 'wxTreeListCtrl',
122 ]),
123
8b9a4190 124 # controls coming from other libraries
9c67cbec 125 ('More Windows/Controls', [
1e4a197e
RD
126 #'wxFloatBar', deprecated
127 #'wxMVCTree', deprecated
1fded56b 128 #'wxRightTextCtrl', deprecated as we have wxTE_RIGHT now.
9c67cbec
RD
129 'ContextHelp',
130 'FancyText',
8b9a4190 131 'FloatCanvas',
9c67cbec 132 'FileBrowseButton',
1fded56b
RD
133 'MaskedEditControls',
134 'PyShell',
9c67cbec 135 'PyCrust',
80b27b4e 136 'PyPlot',
9c67cbec
RD
137 'SplitTree',
138 'TablePrint',
1e4a197e 139 'Throbber',
9c67cbec
RD
140 'wxCalendar',
141 'wxCalendarCtrl',
142 'wxDynamicSashWindow',
143 'wxEditableListBox',
9c67cbec 144 'wxHtmlWindow',
c731eb47 145 'wxIEHtmlWin',
1e4a197e 146 'wxIntCtrl',
9c67cbec 147 'wxMimeTypesManager',
8b9a4190 148 'wxMaskedNumCtrl',
fd3f2efe 149 'wxScrolledPanel',
9c67cbec
RD
150 'wxStyledTextCtrl_1',
151 'wxStyledTextCtrl_2',
1e4a197e 152 'wxTimeCtrl',
3628e088 153 'wxVListBox',
9c67cbec
RD
154 ]),
155
156 # How to lay out the controls in a frame/dialog
157 ('Window Layout', [
158 'LayoutAnchors',
159 'Layoutf',
160 'RowColSizer',
161 'Sizers',
d14a1e28 162 'wxGridBagSizer',
9c67cbec 163 'wxLayoutConstraints',
1e4a197e 164 'wxScrolledPanel',
628c7f79
RD
165 'wxXmlResource',
166 'wxXmlResourceHandler',
6fa68946 167 'wxXmlResourceSubclass',
9c67cbec
RD
168 ]),
169
170 # ditto
171 ('Process and Events', [
1e4a197e 172 'EventManager',
9c67cbec
RD
173 'infoframe',
174 'OOR',
175 'PythonEvents',
176 'Threads',
1e4a197e 177 'wxKeyEvents',
9c67cbec
RD
178 'wxProcess',
179 'wxTimer',
180 ]),
181
182 # Clipboard and DnD
183 ('Clipboard and DnD', [
184 'CustomDragAndDrop',
185 'DragAndDrop',
186 'URLDragAndDrop',
187 ]),
188
189 # Images
1e4a197e 190 ('Using Images', [
76343679 191 'Cursor',
1e4a197e
RD
192 'Throbber',
193 'wxArtProvider',
9c67cbec
RD
194 'wxDragImage',
195 'wxImage',
196 'wxImageFromStream',
197 'wxMask',
198 ]),
199
200 # Other stuff
201 ('Miscellaneous', [
202 'ColourDB',
203 'DialogUnits',
204 'DrawXXXList',
205 'FontEnumerator',
3628e088 206 'NewNamespace',
9c67cbec 207 'PrintFramework',
3628e088 208 'ShapedWindow',
1e4a197e 209 'Throbber',
9c67cbec
RD
210 'Unicode',
211 'wxFileHistory',
212 'wxJoystick',
213 'wxOGL',
214 'wxWave',
215 ]),
216
217 # need libs not coming with the demo
218 ('Objects using an external library', [
219 'ActiveXWrapper_Acrobat',
220 'ActiveXWrapper_IE',
221 'wxGLCanvas',
80b27b4e 222 #'wxPlotCanvas', # deprecated, use PyPlot
9c67cbec
RD
223 ]),
224
70a357c2 225
9c67cbec
RD
226 ('Check out the samples dir too', [
227 ]),
228
9c67cbec
RD
229]
230
231
cf694132
RD
232
233#---------------------------------------------------------------------------
8b9a4190 234# Show how to derive a custom wxLog class
cf694132 235
1fded56b 236class MyLog(wx.PyLog):
76bfdc78 237 def __init__(self, textCtrl, logTime=0):
1fded56b 238 wx.PyLog.__init__(self)
76bfdc78
RD
239 self.tc = textCtrl
240 self.logTime = logTime
241
242 def DoLogString(self, message, timeStamp):
243 if self.logTime:
244 message = time.strftime("%X", time.localtime(timeStamp)) + \
245 ": " + message
1e4a197e
RD
246 if self.tc:
247 self.tc.AppendText(message + '\n')
76bfdc78
RD
248
249
1fded56b 250class MyTP(wx.PyTipProvider):
861a0196
RD
251 def GetTip(self):
252 return "This is my tip"
253
1fded56b
RD
254#---------------------------------------------------------------------------
255# A class to be used to display source code in the demo. Try using the
256# wxSTC in the wxStyledTextCtrl_2 sample first, fall back to wxTextCtrl
257# if there is an error, such as the stc module not being present.
8b9a4190 258#
1fded56b
RD
259
260try:
261 ##raise ImportError
262 from wx import stc
263 from wxStyledTextCtrl_2 import PythonSTC
264 class DemoCodeViewer(PythonSTC):
265 def __init__(self, parent, ID):
266 PythonSTC.__init__(self, parent, ID)
80b27b4e 267 self.SetUpEditor()
1fded56b
RD
268
269 # Some methods to make it compatible with how the wxTextCtrl is used
270 def SetValue(self, value):
271 self.SetReadOnly(False)
272 self.SetText(value)
273 self.SetReadOnly(True)
274
275 def Clear(self):
276 self.ClearAll()
277
278 def SetInsertionPoint(self, pos):
279 self.SetCurrentPos(pos)
280
281 def ShowPosition(self, pos):
282 self.GotoPos(pos)
283
284 def GetLastPosition(self):
285 return self.GetLength()
286
287 def GetRange(self, start, end):
288 return self.GetTextRange(start, end)
289
290 def GetSelection(self):
291 return self.GetAnchor(), self.GetCurrentPos()
292
293 def SetSelection(self, start, end):
294 self.SetSelectionStart(start)
295 self.SetSelectionEnd(end)
296
80b27b4e
RD
297 def SetUpEditor(self):
298 """
299 This method carries out the work of setting up the demo editor.
300 It's seperate so as not to clutter up the init code.
301 """
302 import keyword
303
304 self.SetLexer(stc.STC_LEX_PYTHON)
305 self.SetKeyWords(0, " ".join(keyword.kwlist))
306
307 # Enable folding
308 self.SetProperty("fold", "1" )
309
310 # Highlight tab/space mixing (shouldn't be any)
311 self.SetProperty("tab.timmy.whinge.level", "1")
312
313 # Set left and right margins
314 self.SetMargins(2,2)
315
316 # Set up the numbers in the margin for margin #1
317 self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
318 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
319 self.SetMarginWidth(1, 40)
320
321 # Indentation and tab stuff
322 self.SetIndent(4) # Proscribed indent size for wx
323 self.SetIndentationGuides(True) # Show indent guides
324 self.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
325 self.SetTabIndents(True) # Tab key indents
326 self.SetTabWidth(4) # Proscribed tab size for wx
327 self.SetUseTabs(False) # Use spaces rather than tabs, or
328 # TabTimmy will complain!
329 # White space
330 self.SetViewWhiteSpace(False) # Don't view white space
331
332 # EOL
333 #self.SetEOLMode(wx.stc.STC_EOL_CRLF) # Just leave it at the default (autosense)
334 self.SetViewEOL(False)
335 # No right-edge mode indicator
336 self.SetEdgeMode(stc.STC_EDGE_NONE)
337
338 # Setup a margin to hold fold markers
339 self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
340 self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
341 self.SetMarginSensitive(2, True)
342 self.SetMarginWidth(2, 12)
343
344 # and now set up the fold markers
345 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "black")
346 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "black")
347 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "black")
348 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "black")
349 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "black")
350 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "black")
351 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "black")
352
353 # Global default style
354 if wx.Platform == '__WXMSW__':
355 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
356 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
357 else:
358 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
359 'fore:#000000,back:#FFFFFF,face:Courier,size:12')
360
361 # Clear styles and revert to default.
362 self.StyleClearAll()
363
364 # Following style specs only indicate differences from default.
365 # The rest remains unchanged.
366
367 # Line numbers in margin
368 self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
369
370 # Highlighted brace
371 self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
372 # Unmatched brace
373 self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
374 # Indentation guide
375 self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
376
377 # Python styles
378 self.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
379 # Comments
380 self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#00CC00,back:#F0FFF0')
381 self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#00CC00,back:#F0FFF0')
382 # Numbers
383 self.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
384 # Strings and characters
385 self.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
386 self.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
387 # Keywords
388 self.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
389 # Triple quotes
390 self.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
391 self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
392 # Class names
393 self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
394 # Function names
395 self.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
396 # Operators
397 self.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
398 # Identifiers. I leave this as not bold because everything seems
399 # to be an identifier if it doesn't match the above criterae
400 self.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
401
402 # Caret color
403 self.SetCaretForeground("BLUE")
404 # Selection background
405 self.SetSelBackground(1, '#66CCFF')
406
407 self.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
408 self.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
409
1fded56b
RD
410
411except ImportError:
412 class DemoCodeViewer(wx.TextCtrl):
413 def __init__(self, parent, ID):
414 wx.TextCtrl.__init__(self, parent, ID, style =
415 wx.TE_MULTILINE | wx.TE_READONLY |
416 wx.HSCROLL | wx.TE_RICH2 | wx.TE_NOHIDESEL)
417
418
6c5ae2d2
RD
419#---------------------------------------------------------------------------
420
421def opj(path):
422 """Convert paths to the platform-specific separator"""
1e4a197e 423 return apply(os.path.join, tuple(path.split('/')))
6c5ae2d2
RD
424
425
76bfdc78
RD
426#---------------------------------------------------------------------------
427
1fded56b 428class wxPythonDemo(wx.Frame):
e9159fe8 429 overviewText = "wxPython Overview"
c368d904 430
cf694132 431 def __init__(self, parent, id, title):
1fded56b
RD
432 wx.Frame.__init__(self, parent, -1, title, size = (800, 600),
433 style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
2f90df85 434
694759cf 435 self.cwd = os.getcwd()
3ca6a5f0 436 self.curOverview = ""
1e4a197e 437 self.window = None
694759cf 438
afb810d9 439 icon = images.getMondrianIcon()
96bfd053 440 self.SetIcon(icon)
c368d904 441
1fded56b 442 if wx.Platform == '__WXMSW__':
c368d904 443 # setup a taskbar icon, and catch some events from it
1fded56b 444 self.tbicon = wx.TaskBarIcon()
c368d904 445 self.tbicon.SetIcon(icon, "wxPython Demo")
80b27b4e
RD
446 self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
447 self.tbicon.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.OnTaskBarMenu)
448 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
449 self.tbicon.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
c368d904 450
1fded56b 451 wx.CallAfter(self.ShowTip)
cf694132
RD
452
453 self.otherWin = None
80b27b4e
RD
454 self.Bind(wx.EVT_IDLE, self.OnIdle)
455 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
456 self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)
457 self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize)
cf694132 458
1fded56b
RD
459 self.Centre(wx.BOTH)
460 self.CreateStatusBar(1, wx.ST_SIZEGRIP)
5a7823f5 461
8a12f92d
RD
462 splitter = wx.SplitterWindow(self, -1)
463 splitter2 = wx.SplitterWindow(splitter, -1)
5a7823f5 464
d56cebe7 465 def EmptyHandler(evt): pass
80b27b4e
RD
466 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
467 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
cf694132 468
1e4a197e
RD
469 # Prevent TreeCtrl from displaying all items after destruction when True
470 self.dying = False
cf694132
RD
471
472 # Make a File menu
1fded56b
RD
473 self.mainmenu = wx.MenuBar()
474 menu = wx.Menu()
475 exitID = wx.NewId()
f0261a72 476 menu.Append(exitID, 'E&xit\tAlt-X', 'Get the heck outta here!')
80b27b4e 477 self.Bind(wx.EVT_MENU, self.OnFileExit, id=exitID)
1fded56b 478 wx.App_SetMacExitMenuItemId(exitID)
cf694132
RD
479 self.mainmenu.Append(menu, '&File')
480
ec3e670f 481 # Make a Demo menu
1fded56b 482 menu = wx.Menu()
ec3e670f 483 for item in _treeList:
1fded56b 484 submenu = wx.Menu()
ec3e670f 485 for childItem in item[1]:
1fded56b 486 mID = wx.NewId()
ec3e670f 487 submenu.Append(mID, childItem)
80b27b4e 488 self.Bind(wx.EVT_MENU, self.OnDemoMenu, id=mID)
1fded56b 489 menu.AppendMenu(wx.NewId(), item[0], submenu)
ec3e670f
RD
490 self.mainmenu.Append(menu, '&Demo')
491
492
cf694132 493 # Make a Help menu
1fded56b
RD
494 helpID = wx.NewId()
495 findID = wx.NewId()
496 findnextID = wx.NewId()
497 menu = wx.Menu()
1e4a197e
RD
498 menu.Append(findID, '&Find\tCtrl-F', 'Find in the Demo Code')
499 menu.Append(findnextID, 'Find &Next\tF3', 'Find Next')
500 menu.AppendSeparator()
2f90df85 501 menu.Append(helpID, '&About\tCtrl-H', 'wxPython RULES!!!')
1fded56b 502 wx.App_SetMacAboutMenuItemId(helpID)
80b27b4e
RD
503 self.Bind(wx.EVT_MENU, self.OnHelpAbout, id=helpID)
504 self.Bind(wx.EVT_MENU, self.OnHelpFind, id=findID)
505 self.Bind(wx.EVT_MENU, self.OnFindNext, id=findnextID)
506 self.Bind(wx.EVT_COMMAND_FIND, self.OnFind)
507 self.Bind(wx.EVT_COMMAND_FIND_NEXT, self.OnFind)
508 self.Bind(wx.EVT_COMMAND_FIND_CLOSE, self.OnFindClose)
cf694132
RD
509 self.mainmenu.Append(menu, '&Help')
510 self.SetMenuBar(self.mainmenu)
511
1fded56b 512 self.finddata = wx.FindReplaceData()
1e4a197e
RD
513
514 if 0:
515 # This is another way to set Accelerators, in addition to
516 # using the '\t<key>' syntax in the menu items.
1fded56b
RD
517 aTable = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), exitID),
518 (wx.ACCEL_CTRL, ord('H'), helpID),
519 (wx.ACCEL_CTRL, ord('F'), findID),
520 (wx.ACCEL_NORMAL, WXK_F3, findnextID)
521 ])
1e4a197e 522 self.SetAcceleratorTable(aTable)
2f90df85 523
bb0054cd 524
cf694132 525 # Create a TreeCtrl
1fded56b 526 tID = wx.NewId()
f6bcfd97 527 self.treeMap = {}
3628e088
RD
528 self.tree = wx.TreeCtrl(splitter, tID, style =
529 wx.TR_DEFAULT_STYLE #| wx.TR_HAS_VARIABLE_ROW_HEIGHT
eb0f373c 530 )
afb810d9 531
e9159fe8 532 root = self.tree.AddRoot("wxPython Overview")
f6bcfd97
BP
533 firstChild = None
534 for item in _treeList:
535 child = self.tree.AppendItem(root, item[0])
536 if not firstChild: firstChild = child
537 for childItem in item[1]:
538 theDemo = self.tree.AppendItem(child, childItem)
539 self.treeMap[childItem] = theDemo
540
541 self.tree.Expand(root)
542 self.tree.Expand(firstChild)
80b27b4e
RD
543 self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, id=tID)
544 self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=tID)
545 self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=tID)
546 self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
cf694132 547
cf694132 548 # Create a Notebook
1fded56b 549 self.nb = wx.Notebook(splitter2, -1, style=wx.CLIP_CHILDREN)
cf694132 550
1fded56b 551 # Set up a wx.html.HtmlWindow on the Overview Notebook page
0bdca46d
RD
552 # we put it in a panel first because there seems to be a
553 # refresh bug of some sort (wxGTK) when it is directly in
554 # the notebook...
555 if 0: # the old way
1fded56b 556 self.ovr = wx.html.HtmlWindow(self.nb, -1, size=(400, 400))
0bdca46d
RD
557 self.nb.AddPage(self.ovr, self.overviewText)
558
1fded56b
RD
559 else: # hopefully I can remove this hacky code soon, see SF bug #216861
560 panel = wx.Panel(self.nb, -1, style=wx.CLIP_CHILDREN)
561 self.ovr = wx.html.HtmlWindow(panel, -1, size=(400, 400))
0bdca46d
RD
562 self.nb.AddPage(panel, self.overviewText)
563
564 def OnOvrSize(evt, ovr=self.ovr):
565 ovr.SetSize(evt.GetSize())
566
80b27b4e
RD
567 panel.Bind(wx.EVT_SIZE, OnOvrSize)
568 panel.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
0bdca46d 569
c368d904 570
e9159fe8 571 self.SetOverview(self.overviewText, overview)
cf694132
RD
572
573
1fded56b
RD
574 # Set up a notebook page for viewing the source code of each sample
575 self.txt = DemoCodeViewer(self.nb, -1)
cf694132 576 self.nb.AddPage(self.txt, "Demo Code")
80b27b4e 577 self.LoadDemoSource('Main.py')
cf694132
RD
578
579
cf694132 580 # Set up a log on the View Log Notebook page
1fded56b
RD
581 self.log = wx.TextCtrl(splitter2, -1,
582 style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
342639eb 583
f6bcfd97 584 # Set the wxWindows log target to be this textctrl
1fded56b 585 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
342639eb 586
1fded56b
RD
587 # But instead of the above we want to show how to use our own wx.Log class
588 wx.Log_SetActiveTarget(MyLog(self.log))
cf694132 589
f9b24f07 590 # for serious debugging
1fded56b
RD
591 #wx.Log_SetActiveTarget(wx.LogStderr())
592 #wx.Log_SetTraceMask(wx.TraceMessages)
5a7823f5 593
1e4a197e 594 self.Show(True)
5a7823f5 595
f9b24f07 596
f6bcfd97 597 # add the windows to the splitter and split it.
2f0f3b0f 598 splitter2.SplitHorizontally(self.nb, self.log, -120)
1e4a197e 599 splitter.SplitVertically(self.tree, splitter2, 180)
afb810d9 600
f6bcfd97 601 splitter.SetMinimumPaneSize(20)
afb810d9
RD
602 splitter2.SetMinimumPaneSize(20)
603
cf694132 604
2f0f3b0f
RD
605 # Make the splitter on the right expand the top wind when resized
606 def SplitterOnSize(evt):
607 splitter = evt.GetEventObject()
608 sz = splitter.GetSize()
609 splitter.SetSashPosition(sz.height - 120, False)
610 evt.Skip()
80b27b4e
RD
611
612 splitter2.Bind(wx.EVT_SIZE, SplitterOnSize)
2f0f3b0f 613
cf694132 614
bb0054cd
RD
615 # select initial items
616 self.nb.SetSelection(0)
f6bcfd97 617 self.tree.SelectItem(root)
ec3e670f
RD
618
619 if len(sys.argv) == 2:
620 try:
621 selectedDemo = self.treeMap[sys.argv[1]]
622 except:
623 selectedDemo = None
f6bcfd97 624 if selectedDemo:
ec3e670f
RD
625 self.tree.SelectItem(selectedDemo)
626 self.tree.EnsureVisible(selectedDemo)
627
bb0054cd 628
1fded56b 629 wx.LogMessage('window handle: %s' % self.GetHandle())
2abc0a0f
RD
630
631
cf694132
RD
632 #---------------------------------------------
633 def WriteText(self, text):
f6bcfd97
BP
634 if text[-1:] == '\n':
635 text = text[:-1]
1fded56b 636 wx.LogMessage(text)
f6bcfd97 637
cf694132
RD
638
639 def write(self, txt):
640 self.WriteText(txt)
641
642 #---------------------------------------------
643 def OnItemExpanded(self, event):
644 item = event.GetItem()
1fded56b 645 wx.LogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
c368d904 646 event.Skip()
cf694132
RD
647
648 #---------------------------------------------
649 def OnItemCollapsed(self, event):
650 item = event.GetItem()
1fded56b 651 wx.LogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
c368d904 652 event.Skip()
f6bcfd97
BP
653
654 #---------------------------------------------
655 def OnTreeLeftDown(self, event):
656 pt = event.GetPosition();
657 item, flags = self.tree.HitTest(pt)
658 if item == self.tree.GetSelection():
d975da9b 659 self.SetOverview(self.tree.GetItemText(item)+" Overview", self.curOverview)
185d7c3e 660 event.Skip()
cf694132
RD
661
662 #---------------------------------------------
663 def OnSelChanged(self, event):
664 if self.dying:
665 return
666
5a7823f5
RD
667 item = event.GetItem()
668 itemText = self.tree.GetItemText(item)
669 self.RunDemo(itemText)
670
671
672 #---------------------------------------------
673 def RunDemo(self, itemText):
694759cf 674 os.chdir(self.cwd)
cf694132
RD
675 if self.nb.GetPageCount() == 3:
676 if self.nb.GetSelection() == 2:
677 self.nb.SetSelection(0)
1e4a197e
RD
678 # inform the window that it's time to quit if it cares
679 if self.window is not None:
680 if hasattr(self.window, "ShutdownDemo"):
681 self.window.ShutdownDemo()
1fded56b 682 wx.SafeYield() # in case the page has pending events
cf694132
RD
683 self.nb.DeletePage(2)
684
e9159fe8 685 if itemText == self.overviewText:
80b27b4e 686 self.LoadDemoSource('Main.py')
e9159fe8 687 self.SetOverview(self.overviewText, overview)
cf694132 688 self.nb.Refresh();
e91a9dfc 689 self.window = None
cf694132
RD
690
691 else:
692 if os.path.exists(itemText + '.py'):
1fded56b
RD
693 wx.BeginBusyCursor()
694 wx.LogMessage("Running demo %s.py..." % itemText)
f6bcfd97 695 try:
80b27b4e
RD
696 self.LoadDemoSource(itemText + '.py')
697
698 if (sys.modules.has_key(itemText)):
699 reload(sys.modules[itemText])
700
f6bcfd97 701 module = __import__(itemText, globals())
e9159fe8 702 self.SetOverview(itemText + " Overview", module.overview)
f6bcfd97 703 finally:
1fded56b 704 wx.EndBusyCursor()
5a1eefc7 705 self.tree.Refresh()
cf694132
RD
706
707 # in case runTest is modal, make sure things look right...
708 self.nb.Refresh();
1fded56b 709 wx.SafeYield()
cf694132 710
f6bcfd97 711 self.window = module.runTest(self, self.nb, self) ###
1e4a197e 712 if self.window is not None:
e91a9dfc 713 self.nb.AddPage(self.window, 'Demo')
cf694132 714 self.nb.SetSelection(2)
eb28fd47 715 self.nb.Refresh() # without this wxMac has troubles showing the just added page
cf694132
RD
716
717 else:
f6bcfd97 718 self.ovr.SetPage("")
cf694132 719 self.txt.Clear()
e91a9dfc 720 self.window = None
cf694132 721
2f90df85 722
cf694132
RD
723
724 #---------------------------------------------
725 # Get the Demo files
80b27b4e 726 def LoadDemoSource(self, filename):
cf694132 727 self.txt.Clear()
bb0054cd
RD
728 try:
729 self.txt.SetValue(open(filename).read())
8bf5d46e 730 except IOError:
1fded56b 731 self.txt.SetValue("Cannot open %s file." % filename)
cf694132
RD
732
733 self.txt.SetInsertionPoint(0)
734 self.txt.ShowPosition(0)
735
736 #---------------------------------------------
737 def SetOverview(self, name, text):
f6bcfd97
BP
738 self.curOverview = text
739 lead = text[:6]
740 if lead != '<html>' and lead != '<HTML>':
1e4a197e 741 text = '<br>'.join(text.split('\n'))
f6bcfd97 742 self.ovr.SetPage(text)
cf694132 743 self.nb.SetPageText(0, name)
cf694132
RD
744
745 #---------------------------------------------
746 # Menu methods
c368d904 747 def OnFileExit(self, *event):
cf694132
RD
748 self.Close()
749
cf694132 750 def OnHelpAbout(self, event):
e166644c 751 from About import MyAboutBox
ec3e670f 752 about = MyAboutBox(self)
cf694132
RD
753 about.ShowModal()
754 about.Destroy()
755
1e4a197e
RD
756 def OnHelpFind(self, event):
757 self.nb.SetSelection(1)
1fded56b
RD
758 self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find",
759 wx.FR_NOUPDOWN |
760 wx.FR_NOMATCHCASE |
761 wx.FR_NOWHOLEWORD)
1e4a197e
RD
762 self.finddlg.Show(True)
763
764 def OnFind(self, event):
765 self.nb.SetSelection(1)
766 end = self.txt.GetLastPosition()
767 textstring = self.txt.GetRange(0, end).lower()
768 start = self.txt.GetSelection()[1]
769 findstring = self.finddata.GetFindString().lower()
770 loc = textstring.find(findstring, start)
771 if loc == -1 and start != 0:
772 # string not found, start at beginning
773 start = 0
774 loc = textstring.find(findstring, start)
775 if loc == -1:
1fded56b 776 dlg = wx.MessageDialog(self, 'Find String Not Found',
1e4a197e 777 'Find String Not Found in Demo File',
1fded56b 778 wx.OK | wx.ICON_INFORMATION)
1e4a197e
RD
779 dlg.ShowModal()
780 dlg.Destroy()
781 if self.finddlg:
782 if loc == -1:
783 self.finddlg.SetFocus()
784 return
785 else:
786 self.finddlg.Destroy()
1e4a197e 787 self.txt.ShowPosition(loc)
1fded56b 788 self.txt.SetSelection(loc, loc + len(findstring))
1e4a197e
RD
789
790
791
792 def OnFindNext(self, event):
793 if self.finddata.GetFindString():
794 self.OnFind(event)
795 else:
796 self.OnHelpFind(event)
797
798 def OnFindClose(self, event):
799 event.GetDialog().Destroy()
800
cf694132
RD
801
802 #---------------------------------------------
803 def OnCloseWindow(self, event):
1e4a197e 804 self.dying = True
e91a9dfc 805 self.window = None
26197023 806 self.mainmenu = None
c368d904
RD
807 if hasattr(self, "tbicon"):
808 del self.tbicon
cf694132
RD
809 self.Destroy()
810
c368d904 811
cf694132
RD
812 #---------------------------------------------
813 def OnIdle(self, event):
814 if self.otherWin:
815 self.otherWin.Raise()
e91a9dfc 816 self.window = self.otherWin
cf694132
RD
817 self.otherWin = None
818
ccf691a4
RD
819
820 #---------------------------------------------
821 def ShowTip(self):
822 try:
823 showTipText = open(opj("data/showTips")).read()
824 showTip, index = eval(showTipText)
825 except IOError:
826 showTip, index = (1, 0)
827 if showTip:
1fded56b 828 tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index)
861a0196 829 ##tp = MyTP(0)
1fded56b 830 showTip = wx.ShowTip(self, tp)
ccf691a4
RD
831 index = tp.GetCurrentTip()
832 open(opj("data/showTips"), "w").write(str( (showTip, index) ))
833
834
ec3e670f
RD
835 #---------------------------------------------
836 def OnDemoMenu(self, event):
f6bcfd97
BP
837 try:
838 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
839 except:
840 selectedDemo = None
841 if selectedDemo:
842 self.tree.SelectItem(selectedDemo)
843 self.tree.EnsureVisible(selectedDemo)
ec3e670f 844
c368d904
RD
845
846 #---------------------------------------------
847 def OnTaskBarActivate(self, evt):
848 if self.IsIconized():
1e4a197e 849 self.Iconize(False)
c368d904 850 if not self.IsShown():
1e4a197e 851 self.Show(True)
c368d904
RD
852 self.Raise()
853
854 #---------------------------------------------
855
856 TBMENU_RESTORE = 1000
857 TBMENU_CLOSE = 1001
858
859 def OnTaskBarMenu(self, evt):
1fded56b 860 menu = wx.Menu()
c368d904
RD
861 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
862 menu.Append(self.TBMENU_CLOSE, "Close")
863 self.tbicon.PopupMenu(menu)
864 menu.Destroy()
865
866 #---------------------------------------------
867 def OnTaskBarClose(self, evt):
868 self.Close()
869
1fded56b 870 # because of the way wx.TaskBarIcon.PopupMenu is implemented we have to
c368d904 871 # prod the main idle handler a bit to get the window to actually close
1fded56b 872 wx.GetApp().ProcessIdle()
c368d904
RD
873
874
f3d9dc1d
RD
875 #---------------------------------------------
876 def OnIconfiy(self, evt):
1fded56b 877 wx.LogMessage("OnIconfiy")
f3d9dc1d
RD
878 evt.Skip()
879
880 #---------------------------------------------
881 def OnMaximize(self, evt):
1fded56b 882 wx.LogMessage("OnMaximize")
f3d9dc1d
RD
883 evt.Skip()
884
885
886
887
cf694132
RD
888#---------------------------------------------------------------------------
889#---------------------------------------------------------------------------
890
1fded56b 891class MySplashScreen(wx.SplashScreen):
b5a5d647 892 def __init__(self):
1fded56b
RD
893 bmp = wx.Image(opj("bitmaps/splash.gif")).ConvertToBitmap()
894 wx.SplashScreen.__init__(self, bmp,
895 wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_TIMEOUT,
40c4c5a3 896 4000, None, -1,
1fded56b 897 style = wx.SIMPLE_BORDER|wx.FRAME_NO_TASKBAR|wx.STAY_ON_TOP)
80b27b4e 898 self.Bind(wx.EVT_CLOSE, self.OnClose)
b5a5d647
RD
899
900 def OnClose(self, evt):
9fb56e0c 901 frame = wxPythonDemo(None, -1, "wxPython: (A Demonstration)")
1e4a197e 902 frame.Show()
ccf691a4 903 evt.Skip() # Make sure the default handler runs too...
cf694132 904
b5a5d647 905
1fded56b 906class MyApp(wx.App):
b5a5d647
RD
907 def OnInit(self):
908 """
68320e40 909 Create and show the splash screen. It will then create and show
b5a5d647
RD
910 the main frame when it is time to do so.
911 """
1e4a197e
RD
912
913 #import locale
1fded56b 914 #self.locale = wx.Locale(wx.LANGUAGE_FRENCH)
1e4a197e
RD
915 #locale.setlocale(locale.LC_ALL, 'fr')
916
1fded56b 917 wx.InitAllImageHandlers()
b5a5d647
RD
918 splash = MySplashScreen()
919 splash.Show()
1e4a197e 920 return True
b5a5d647
RD
921
922
923
cf694132
RD
924#---------------------------------------------------------------------------
925
926def main():
e02c03a4 927 try:
d56cebe7 928 demoPath = os.path.dirname(__file__)
e02c03a4
RD
929 os.chdir(demoPath)
930 except:
931 pass
d14a1e28 932 app = MyApp(0) #wx.Platform == "__WXMAC__")
cf694132
RD
933 app.MainLoop()
934
935
936#---------------------------------------------------------------------------
937
938
939
f6bcfd97 940overview = """<html><body>
1fded56b
RD
941<h2>wxPython</h2>
942
943<p> wxPython is a <b>GUI toolkit</b> for the <a
944href="http://www.python.org/">Python</a> programming language. It
945allows Python programmers to create programs with a robust, highly
946functional graphical user interface, simply and easily. It is
947implemented as a Python extension module (native code) that wraps the
948popular <a href="http://wxwindows.org/front.htm">wxWindows</a> cross
949platform GUI library, which is written in C++.
950
951<p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
952means that it is free for anyone to use and the source code is
953available for anyone to look at and modify. Or anyone can contribute
8b9a4190 954fixes or enhancements to the project.
1fded56b
RD
955
956<p> wxPython is a <b>cross-platform</b> toolkit. This means that the
957same program will run on multiple platforms without modification.
958Currently supported platforms are 32-bit Microsoft Windows, most Unix
959or unix-like systems, and Macintosh OS X. Since the language is
960Python, wxPython programs are <b>simple, easy</b> to write and easy to
961understand.
962
963<p> <b>This demo</b> is not only a collection of test cases for
964wxPython, but is also designed to help you learn about and how to use
965wxPython. Each sample is listed in the tree control on the left.
966When a sample is selected in the tree then a module is loaded and run
967(usually in a tab of this notebook,) and the source code of the module
968is loaded in another tab for you to browse and learn from.
969
970"""
cf694132
RD
971
972
973#----------------------------------------------------------------------------
974#----------------------------------------------------------------------------
975
976if __name__ == '__main__':
977 main()
978
979#----------------------------------------------------------------------------
980
981
982
983
984
985
986