]> git.saurik.com Git - wxWidgets.git/blame - wxPython/demo/Main.py
Some wxCollapsiblePane tweaks:
[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
08ecc920
RD
14# FIXME List:
15# * Problems with flickering related to ERASE_BACKGROUND
16# and the splitters. Might be a problem with this 2.5 beta...?
17# UPDATE: can't see on 2.5.2 GTK - maybe just a faster machine :)
18# * Demo Code menu?
19# * Annoying switching between tabs and resulting flicker
20# how to replace a page in the notebook without deleting/adding?
21# Where is SetPage!? tried freeze...tried reparent of dummy panel....
22
23# TODO List:
24# * UI design more prefessional
25# * save file positions (new field in demoModules) (@ LoadDemoSource)
26# * Update main overview
27
28# * Why don't we move _treeList into a separate module
29
30import sys, os, time, traceback, types
cf694132 31
1fded56b
RD
32import wx # This module uses the new wx namespace
33import wx.html
606d919c 34
96bfd053
RD
35import images
36
d14a1e28
RD
37# For debugging
38##wx.Trap();
a0676188
RD
39##print "wx.VERSION_STRING = %s (%s)" % (wx.VERSION_STRING, wx.USE_UNICODE and 'unicode' or 'ansi')
40##print "pid:", os.getpid()
ef8b9c3e 41##raw_input("Press Enter...")
6fa68946 42
1e4a197e 43
cf694132
RD
44#---------------------------------------------------------------------------
45
46
47_treeList = [
9c67cbec 48 # new stuff
77d4f443 49 ('Recent Additions/Updates', [
23a02364 50 'AnalogClock',
1c976bff
RD
51 'AUI_DockingWindowMgr',
52 'AUI_Notebook',
23a02364 53 'CheckListCtrlMixin',
4f708f05 54 'ComboTreeBox',
febb39df 55 'Pickers',
7e664d85 56 'PseudoDC',
30fc5e8f 57 'RichTextCtrl',
6aabc8da
RD
58 'Treebook',
59 'Toolbook',
ecc0e221
RD
60 'BitmapFromBuffer',
61 'RawBitmapAccess',
f77c79d0 62 'DragScroller',
8bbd1bbf 63 'DelayedResult',
ac9d5e95 64 'ExpandoTextCtrl',
66dae888 65 'ButtonPanel',
6cb4f153 66 'FlatNotebook',
c8f129d0 67 'CustomTreeCtrl',
f541d829 68 'AboutBox',
e19b9131 69 'AnimateCtrl',
2c7816ff 70 'AlphaDrawing',
51aad6d3 71 'GraphicsContext',
9c67cbec
RD
72 ]),
73
1e4a197e 74 # managed windows == things with a (optional) caption you can close
03a604a6 75 ('Frames and Dialogs', [
1c976bff 76 'AUI_DockingWindowMgr',
299647ac
RD
77 'Dialog',
78 'Frame',
79 'MDIWindows',
80 'MiniFrame',
81 'Wizard',
9c67cbec
RD
82 ]),
83
84 # the common dialogs
85 ('Common Dialogs', [
f541d829 86 'AboutBox',
299647ac
RD
87 'ColourDialog',
88 'DirDialog',
89 'FileDialog',
299647ac
RD
90 'FindReplaceDialog',
91 'FontDialog',
92 'MessageDialog',
89eb18ec 93 'MultiChoiceDialog',
299647ac
RD
94 'PageSetupDialog',
95 'PrintDialog',
96 'ProgressDialog',
97 'SingleChoiceDialog',
98 'TextEntryDialog',
9c67cbec
RD
99 ]),
100
af83019e 101 # dialogs from libraries
9c67cbec 102 ('More Dialogs', [
9c67cbec 103 'ImageBrowser',
299647ac 104 'ScrolledMessageDialog',
9c67cbec
RD
105 ]),
106
107 # core controls
108 ('Core Windows/Controls', [
8b7fa2d9 109 'BitmapButton',
299647ac
RD
110 'Button',
111 'CheckBox',
112 'CheckListBox',
113 'Choice',
114 'ComboBox',
115 'Gauge',
116 'Grid',
117 'Grid_MegaExample',
118 'ListBox',
119 'ListCtrl',
120 'ListCtrl_virtual',
15513a80 121 'ListCtrl_edit',
299647ac 122 'Menu',
1fded56b 123 'PopupMenu',
299647ac
RD
124 'PopupWindow',
125 'RadioBox',
126 'RadioButton',
127 'SashWindow',
128 'ScrolledWindow',
129 'Slider',
130 'SpinButton',
131 'SpinCtrl',
132 'SplitterWindow',
133 'StaticBitmap',
e79c8a7c 134 'StaticBox',
299647ac
RD
135 'StaticText',
136 'StatusBar',
f2b4a4ea 137 'StockButtons',
299647ac
RD
138 'TextCtrl',
139 'ToggleButton',
140 'ToolBar',
141 'TreeCtrl',
142 'Validator',
9c67cbec 143 ]),
6aabc8da
RD
144
145 ('"Book" Controls', [
1c976bff 146 'AUI_Notebook',
6aabc8da
RD
147 'Choicebook',
148 'Listbook',
149 'Notebook',
150 'Toolbook',
151 'Treebook',
152 ]),
9c67cbec 153
d14a1e28 154 ('Custom Controls', [
23a02364 155 'AnalogClock',
66dae888 156 'ButtonPanel',
d14a1e28 157 'ColourSelect',
4f708f05 158 'ComboTreeBox',
c8f129d0 159 'CustomTreeCtrl',
299647ac 160 'Editor',
6cb4f153 161 'FlatNotebook',
d14a1e28 162 'GenericButtons',
299647ac
RD
163 'GenericDirCtrl',
164 'LEDNumberCtrl',
165 'MultiSash',
166 'PopupControl',
167 'PyColourChooser',
168 'TreeListCtrl',
d14a1e28
RD
169 ]),
170
8b9a4190 171 # controls coming from other libraries
9c67cbec 172 ('More Windows/Controls', [
b7c75283
RD
173 'ActiveX_FlashWindow',
174 'ActiveX_IEHtmlWindow',
175 'ActiveX_PDFWindow',
299647ac
RD
176 #'RightTextCtrl', deprecated as we have wxTE_RIGHT now.
177 'Calendar',
178 'CalendarCtrl',
23a02364 179 'CheckListCtrlMixin',
9c67cbec 180 'ContextHelp',
91334b48 181 'DatePickerCtrl',
299647ac
RD
182 'DynamicSashWindow',
183 'EditableListBox',
ac9d5e95 184 'ExpandoTextCtrl',
9c67cbec
RD
185 'FancyText',
186 'FileBrowseButton',
299647ac
RD
187 'FloatBar',
188 'FloatCanvas',
42f5333f 189 'FoldPanelBar',
299647ac 190 'HtmlWindow',
a6987674 191 'HyperLinkCtrl',
299647ac
RD
192 'IntCtrl',
193 'MVCTree',
1fded56b 194 'MaskedEditControls',
299647ac 195 'MaskedNumCtrl',
486afba9
RD
196 'MediaCtrl',
197 'MultiSplitterWindow',
d211a853 198 'Pickers',
9c67cbec 199 'PyCrust',
80b27b4e 200 'PyPlot',
299647ac 201 'PyShell',
30fc5e8f 202 'RichTextCtrl',
299647ac 203 'ScrolledPanel',
9c67cbec 204 'SplitTree',
299647ac
RD
205 'StyledTextCtrl_1',
206 'StyledTextCtrl_2',
9c67cbec 207 'TablePrint',
1e4a197e 208 'Throbber',
cccce1a6 209 'Ticker',
299647ac
RD
210 'TimeCtrl',
211 'VListBox',
9c67cbec
RD
212 ]),
213
214 # How to lay out the controls in a frame/dialog
215 ('Window Layout', [
299647ac 216 'GridBagSizer',
9c67cbec 217 'LayoutAnchors',
299647ac 218 'LayoutConstraints',
9c67cbec
RD
219 'Layoutf',
220 'RowColSizer',
299647ac 221 'ScrolledPanel',
9c67cbec 222 'Sizers',
299647ac
RD
223 'XmlResource',
224 'XmlResourceHandler',
225 'XmlResourceSubclass',
9c67cbec
RD
226 ]),
227
228 # ditto
229 ('Process and Events', [
8bbd1bbf 230 'DelayedResult',
1e4a197e 231 'EventManager',
299647ac 232 'KeyEvents',
299647ac 233 'Process',
9c67cbec
RD
234 'PythonEvents',
235 'Threads',
299647ac 236 'Timer',
c163da42 237 ##'infoframe', # needs better explanation and some fixing
9c67cbec
RD
238 ]),
239
240 # Clipboard and DnD
241 ('Clipboard and DnD', [
242 'CustomDragAndDrop',
243 'DragAndDrop',
244 'URLDragAndDrop',
245 ]),
246
247 # Images
1e4a197e 248 ('Using Images', [
2c7816ff 249 'AlphaDrawing',
c35bf68e 250 'AnimateCtrl',
299647ac 251 'ArtProvider',
0dcc6f22 252 'BitmapFromBuffer',
76343679 253 'Cursor',
299647ac
RD
254 'DragImage',
255 'Image',
8a88769e 256 'ImageAlpha',
299647ac
RD
257 'ImageFromStream',
258 'Mask',
ecc0e221 259 'RawBitmapAccess',
1e4a197e 260 'Throbber',
9c67cbec
RD
261 ]),
262
263 # Other stuff
264 ('Miscellaneous', [
2c7816ff 265 'AlphaDrawing',
9c67cbec 266 'ColourDB',
c163da42 267 ##'DialogUnits', # needs more explanations
f77c79d0 268 'DragScroller',
9c67cbec 269 'DrawXXXList',
299647ac 270 'FileHistory',
9c67cbec 271 'FontEnumerator',
51aad6d3 272 'GraphicsContext',
486afba9 273 'GLCanvas',
299647ac 274 'Joystick',
486afba9 275 'MimeTypesManager',
51c5e1f2 276 'MouseGestures',
299647ac 277 'OGL',
9c67cbec 278 'PrintFramework',
7e664d85 279 'PseudoDC',
3628e088 280 'ShapedWindow',
78862f24 281 'Sound',
62038e59 282 'StandardPaths',
9c67cbec 283 'Unicode',
9c67cbec
RD
284 ]),
285
70a357c2 286
9c67cbec
RD
287 ('Check out the samples dir too', [
288 ]),
289
9c67cbec
RD
290]
291
292
cf694132
RD
293
294#---------------------------------------------------------------------------
8b9a4190 295# Show how to derive a custom wxLog class
cf694132 296
1fded56b 297class MyLog(wx.PyLog):
76bfdc78 298 def __init__(self, textCtrl, logTime=0):
1fded56b 299 wx.PyLog.__init__(self)
76bfdc78
RD
300 self.tc = textCtrl
301 self.logTime = logTime
302
303 def DoLogString(self, message, timeStamp):
62038e59
RD
304 #print message, timeStamp
305 #if self.logTime:
306 # message = time.strftime("%X", time.localtime(timeStamp)) + \
307 # ": " + message
1e4a197e
RD
308 if self.tc:
309 self.tc.AppendText(message + '\n')
76bfdc78
RD
310
311
1fded56b 312class MyTP(wx.PyTipProvider):
861a0196
RD
313 def GetTip(self):
314 return "This is my tip"
315
c4ef95da
RD
316#---------------------------------------------------------------------------
317# A class to be used to simply display a message in the demo pane
318# rather than running the sample itself.
319
320class MessagePanel(wx.Panel):
321 def __init__(self, parent, message, caption='', flags=0):
322 wx.Panel.__init__(self, parent)
323
324 # Make widgets
325 if flags:
326 artid = None
327 if flags & wx.ICON_EXCLAMATION:
328 artid = wx.ART_WARNING
329 elif flags & wx.ICON_ERROR:
330 artid = wx.ART_ERROR
331 elif flags & wx.ICON_QUESTION:
332 artid = wx.ART_QUESTION
333 elif flags & wx.ICON_INFORMATION:
334 artid = wx.ART_INFORMATION
335
336 if artid is not None:
337 bmp = wx.ArtProvider.GetBitmap(artid, wx.ART_MESSAGE_BOX, (32,32))
338 icon = wx.StaticBitmap(self, -1, bmp)
339 else:
340 icon = (32,32) # make a spacer instead
341
342 if caption:
343 caption = wx.StaticText(self, -1, caption)
344 caption.SetFont(wx.Font(28, wx.SWISS, wx.NORMAL, wx.BOLD))
345
346 message = wx.StaticText(self, -1, message)
347
348 # add to sizers for layout
349 tbox = wx.BoxSizer(wx.VERTICAL)
350 if caption:
351 tbox.Add(caption)
352 tbox.Add((10,10))
353 tbox.Add(message)
354
355 hbox = wx.BoxSizer(wx.HORIZONTAL)
356 hbox.Add((10,10), 1)
357 hbox.Add(icon)
358 hbox.Add((10,10))
359 hbox.Add(tbox)
360 hbox.Add((10,10), 1)
361
362 box = wx.BoxSizer(wx.VERTICAL)
363 box.Add((10,10), 1)
364 box.Add(hbox, 0, wx.EXPAND)
365 box.Add((10,10), 2)
366
367 self.SetSizer(box)
a7593631 368 self.Fit()
c4ef95da 369
08ecc920 370
1fded56b
RD
371#---------------------------------------------------------------------------
372# A class to be used to display source code in the demo. Try using the
299647ac 373# wxSTC in the StyledTextCtrl_2 sample first, fall back to wxTextCtrl
1fded56b 374# if there is an error, such as the stc module not being present.
8b9a4190 375#
1fded56b
RD
376
377try:
4638eaea 378 ##raise ImportError # for testing the alternate implementation
1fded56b 379 from wx import stc
299647ac 380 from StyledTextCtrl_2 import PythonSTC
08ecc920
RD
381
382 class DemoCodeEditor(PythonSTC):
383 def __init__(self, parent):
2e839e96 384 PythonSTC.__init__(self, parent, -1, style=wx.BORDER_NONE)
80b27b4e 385 self.SetUpEditor()
1fded56b
RD
386
387 # Some methods to make it compatible with how the wxTextCtrl is used
388 def SetValue(self, value):
6c7d1792
RD
389 if wx.USE_UNICODE:
390 value = value.decode('iso8859_1')
1fded56b 391 self.SetText(value)
08ecc920
RD
392 self.EmptyUndoBuffer()
393 self.SetSavePoint()
394
395 def IsModified(self):
396 return self.GetModify()
1fded56b
RD
397
398 def Clear(self):
399 self.ClearAll()
400
401 def SetInsertionPoint(self, pos):
402 self.SetCurrentPos(pos)
08ecc920 403 self.SetAnchor(pos)
1fded56b
RD
404
405 def ShowPosition(self, pos):
08ecc920 406 line = self.LineFromPosition(pos)
887a1bd9
RD
407 #self.EnsureVisible(line)
408 self.GotoLine(line)
1fded56b
RD
409
410 def GetLastPosition(self):
411 return self.GetLength()
412
08ecc920
RD
413 def GetPositionFromLine(self, line):
414 return self.PositionFromLine(line)
415
1fded56b
RD
416 def GetRange(self, start, end):
417 return self.GetTextRange(start, end)
418
419 def GetSelection(self):
420 return self.GetAnchor(), self.GetCurrentPos()
421
422 def SetSelection(self, start, end):
423 self.SetSelectionStart(start)
424 self.SetSelectionEnd(end)
425
08ecc920
RD
426 def SelectLine(self, line):
427 start = self.PositionFromLine(line)
428 end = self.GetLineEndPosition(line)
429 self.SetSelection(start, end)
430
80b27b4e
RD
431 def SetUpEditor(self):
432 """
433 This method carries out the work of setting up the demo editor.
434 It's seperate so as not to clutter up the init code.
435 """
436 import keyword
437
438 self.SetLexer(stc.STC_LEX_PYTHON)
439 self.SetKeyWords(0, " ".join(keyword.kwlist))
440
441 # Enable folding
442 self.SetProperty("fold", "1" )
443
444 # Highlight tab/space mixing (shouldn't be any)
445 self.SetProperty("tab.timmy.whinge.level", "1")
446
447 # Set left and right margins
448 self.SetMargins(2,2)
449
450 # Set up the numbers in the margin for margin #1
451 self.SetMarginType(1, wx.stc.STC_MARGIN_NUMBER)
452 # Reasonable value for, say, 4-5 digits using a mono font (40 pix)
453 self.SetMarginWidth(1, 40)
454
455 # Indentation and tab stuff
456 self.SetIndent(4) # Proscribed indent size for wx
457 self.SetIndentationGuides(True) # Show indent guides
458 self.SetBackSpaceUnIndents(True)# Backspace unindents rather than delete 1 space
459 self.SetTabIndents(True) # Tab key indents
460 self.SetTabWidth(4) # Proscribed tab size for wx
461 self.SetUseTabs(False) # Use spaces rather than tabs, or
462 # TabTimmy will complain!
463 # White space
464 self.SetViewWhiteSpace(False) # Don't view white space
465
887a1bd9
RD
466 # EOL: Since we are loading/saving ourselves, and the
467 # strings will always have \n's in them, set the STC to
468 # edit them that way.
469 self.SetEOLMode(wx.stc.STC_EOL_LF)
470 self.SetViewEOL(False)
471
80b27b4e
RD
472 # No right-edge mode indicator
473 self.SetEdgeMode(stc.STC_EDGE_NONE)
474
475 # Setup a margin to hold fold markers
476 self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
477 self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
478 self.SetMarginSensitive(2, True)
479 self.SetMarginWidth(2, 12)
480
481 # and now set up the fold markers
482 self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, stc.STC_MARK_BOXPLUSCONNECTED, "white", "black")
483 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, stc.STC_MARK_BOXMINUSCONNECTED, "white", "black")
484 self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, stc.STC_MARK_TCORNER, "white", "black")
485 self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, stc.STC_MARK_LCORNER, "white", "black")
486 self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, stc.STC_MARK_VLINE, "white", "black")
487 self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, "white", "black")
488 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, "white", "black")
489
490 # Global default style
491 if wx.Platform == '__WXMSW__':
492 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
493 'fore:#000000,back:#FFFFFF,face:Courier New,size:9')
1f2b9015
KO
494 elif wx.Platform == '__WXMAC__':
495 # TODO: if this looks fine on Linux too, remove the Mac-specific case
496 # and use this whenever OS != MSW.
497 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
498 'fore:#000000,back:#FFFFFF,face:Courier')
80b27b4e
RD
499 else:
500 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
27eac64c 501 'fore:#000000,back:#FFFFFF,face:Courier,size:9')
80b27b4e
RD
502
503 # Clear styles and revert to default.
504 self.StyleClearAll()
505
506 # Following style specs only indicate differences from default.
507 # The rest remains unchanged.
508
509 # Line numbers in margin
e44b5196 510 self.StyleSetSpec(wx.stc.STC_STYLE_LINENUMBER,'fore:#000000,back:#99A9C2')
80b27b4e
RD
511 # Highlighted brace
512 self.StyleSetSpec(wx.stc.STC_STYLE_BRACELIGHT,'fore:#00009D,back:#FFFF00')
513 # Unmatched brace
514 self.StyleSetSpec(wx.stc.STC_STYLE_BRACEBAD,'fore:#00009D,back:#FF0000')
515 # Indentation guide
516 self.StyleSetSpec(wx.stc.STC_STYLE_INDENTGUIDE, "fore:#CDCDCD")
517
518 # Python styles
519 self.StyleSetSpec(wx.stc.STC_P_DEFAULT, 'fore:#000000')
520 # Comments
a253aa20
RD
521 self.StyleSetSpec(wx.stc.STC_P_COMMENTLINE, 'fore:#008000,back:#F0FFF0')
522 self.StyleSetSpec(wx.stc.STC_P_COMMENTBLOCK, 'fore:#008000,back:#F0FFF0')
80b27b4e
RD
523 # Numbers
524 self.StyleSetSpec(wx.stc.STC_P_NUMBER, 'fore:#008080')
525 # Strings and characters
526 self.StyleSetSpec(wx.stc.STC_P_STRING, 'fore:#800080')
527 self.StyleSetSpec(wx.stc.STC_P_CHARACTER, 'fore:#800080')
528 # Keywords
529 self.StyleSetSpec(wx.stc.STC_P_WORD, 'fore:#000080,bold')
530 # Triple quotes
531 self.StyleSetSpec(wx.stc.STC_P_TRIPLE, 'fore:#800080,back:#FFFFEA')
532 self.StyleSetSpec(wx.stc.STC_P_TRIPLEDOUBLE, 'fore:#800080,back:#FFFFEA')
533 # Class names
534 self.StyleSetSpec(wx.stc.STC_P_CLASSNAME, 'fore:#0000FF,bold')
535 # Function names
536 self.StyleSetSpec(wx.stc.STC_P_DEFNAME, 'fore:#008080,bold')
537 # Operators
538 self.StyleSetSpec(wx.stc.STC_P_OPERATOR, 'fore:#800000,bold')
539 # Identifiers. I leave this as not bold because everything seems
540 # to be an identifier if it doesn't match the above criterae
541 self.StyleSetSpec(wx.stc.STC_P_IDENTIFIER, 'fore:#000000')
542
543 # Caret color
544 self.SetCaretForeground("BLUE")
545 # Selection background
546 self.SetSelBackground(1, '#66CCFF')
547
548 self.SetSelBackground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT))
549 self.SetSelForeground(True, wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT))
550
08ecc920
RD
551 def RegisterModifiedEvent(self, eventHandler):
552 self.Bind(wx.stc.EVT_STC_CHANGE, eventHandler)
553
1fded56b
RD
554
555except ImportError:
08ecc920
RD
556 class DemoCodeEditor(wx.TextCtrl):
557 def __init__(self, parent):
2e839e96
RD
558 wx.TextCtrl.__init__(self, parent, -1, style =
559 wx.TE_MULTILINE | wx.HSCROLL | wx.TE_RICH2 | wx.TE_NOHIDESEL)
1fded56b 560
08ecc920
RD
561 def RegisterModifiedEvent(self, eventHandler):
562 self.Bind(wx.EVT_TEXT, eventHandler)
563
564 def SetReadOnly(self, flag):
565 self.SetEditable(not flag)
566 # NOTE: STC already has this method
567
568 def GetText(self):
569 return self.GetValue()
570
b6176ab7 571 def GetPositionFromLine(self, line):
08ecc920
RD
572 return self.XYToPosition(0,line)
573
574 def GotoLine(self, line):
b6176ab7
RD
575 pos = self.GetPositionFromLine(line)
576 self.SetInsertionPoint(pos)
577 self.ShowPosition(pos)
08ecc920
RD
578
579 def SelectLine(self, line):
580 start = self.GetPositionFromLine(line)
581 end = start + self.GetLineLength(line)
582 self.SetSelection(start, end)
583
584
585#---------------------------------------------------------------------------
586# Constants for module versions
587
588modOriginal = 0
589modModified = 1
590modDefault = modOriginal
591
592#---------------------------------------------------------------------------
593
594class DemoCodePanel(wx.Panel):
595 """Panel for the 'Demo Code' tab"""
596 def __init__(self, parent, mainFrame):
2e839e96 597 wx.Panel.__init__(self, parent, size=(1,1))
e0465cbd
RD
598 if 'wxMSW' in wx.PlatformInfo:
599 self.Hide()
08ecc920
RD
600 self.mainFrame = mainFrame
601 self.editor = DemoCodeEditor(self)
602 self.editor.RegisterModifiedEvent(self.OnCodeModified)
603
604 self.btnSave = wx.Button(self, -1, "Save Changes")
605 self.btnRestore = wx.Button(self, -1, "Delete Modified")
606 self.btnSave.Enable(False)
607 self.btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
608 self.btnRestore.Bind(wx.EVT_BUTTON, self.OnRestore)
609
610 self.radioButtons = { modOriginal: wx.RadioButton(self, -1, "Original", style = wx.RB_GROUP),
611 modModified: wx.RadioButton(self, -1, "Modified") }
612
613 self.controlBox = wx.BoxSizer(wx.HORIZONTAL)
614 self.controlBox.Add(wx.StaticText(self, -1, "Active Version:"), 0,
615 wx.RIGHT | wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 5)
616 for modID, radioButton in self.radioButtons.items():
617 self.controlBox.Add(radioButton, 0, wx.EXPAND | wx.RIGHT, 5)
618 radioButton.modID = modID # makes it easier for the event handler
619 radioButton.Bind(wx.EVT_RADIOBUTTON, self.OnRadioButton)
620
621 self.controlBox.Add(self.btnSave, 0, wx.RIGHT, 5)
622 self.controlBox.Add(self.btnRestore, 0)
623
624 self.box = wx.BoxSizer(wx.VERTICAL)
625 self.box.Add(self.controlBox, 0, wx.EXPAND)
887a1bd9 626 self.box.Add(wx.StaticLine(self), 0, wx.EXPAND)
08ecc920
RD
627 self.box.Add(self.editor, 1, wx.EXPAND)
628
629 self.box.Fit(self)
630 self.SetSizer(self.box)
631
632
633 # Loads a demo from a DemoModules object
634 def LoadDemo(self, demoModules):
635 self.demoModules = demoModules
636 if (modDefault == modModified) and demoModules.Exists(modModified):
637 demoModules.SetActive(modModified)
638 else:
639 demoModules.SetActive(modOriginal)
640 self.radioButtons[demoModules.GetActiveID()].Enable(True)
641 self.ActiveModuleChanged()
642
643
644 def ActiveModuleChanged(self):
645 self.LoadDemoSource(self.demoModules.GetSource())
646 self.UpdateControlState()
a6780fa2 647 self.ReloadDemo()
08ecc920
RD
648
649
650 def LoadDemoSource(self, source):
651 self.editor.Clear()
652 self.editor.SetValue(source)
653 self.JumpToLine(0)
654 self.btnSave.Enable(False)
655
656
657 def JumpToLine(self, line, highlight=False):
658 self.editor.GotoLine(line)
659 self.editor.SetFocus()
660 if highlight:
661 self.editor.SelectLine(line)
662
663
664 def UpdateControlState(self):
665 active = self.demoModules.GetActiveID()
666 # Update the radio/restore buttons
667 for moduleID in self.radioButtons:
668 btn = self.radioButtons[moduleID]
669 if moduleID == active:
670 btn.SetValue(True)
671 else:
672 btn.SetValue(False)
673
674 if self.demoModules.Exists(moduleID):
675 btn.Enable(True)
676 if moduleID == modModified:
677 self.btnRestore.Enable(True)
678 else:
679 btn.Enable(False)
680 if moduleID == modModified:
681 self.btnRestore.Enable(False)
682
683
684 def OnRadioButton(self, event):
685 radioSelected = event.GetEventObject()
686 modSelected = radioSelected.modID
687 if modSelected != self.demoModules.GetActiveID():
688 busy = wx.BusyInfo("Reloading demo module...")
689 self.demoModules.SetActive(modSelected)
690 self.ActiveModuleChanged()
691
692
693 def ReloadDemo(self):
694 if self.demoModules.name != __name__:
a6780fa2 695 self.mainFrame.RunModule()
08ecc920
RD
696
697
698 def OnCodeModified(self, event):
699 self.btnSave.Enable(self.editor.IsModified())
700
701
702 def OnSave(self, event):
703 if self.demoModules.Exists(modModified):
704 if self.demoModules.GetActiveID() == modOriginal:
705 overwriteMsg = "You are about to overwrite an already existing modified copy\n" + \
706 "Do you want to continue?"
707 dlg = wx.MessageDialog(self, overwriteMsg, "wxPython Demo",
708 wx.YES_NO | wx.NO_DEFAULT| wx.ICON_EXCLAMATION)
709 result = dlg.ShowModal()
710 if result == wx.ID_NO:
711 return
712 dlg.Destroy()
713
714 self.demoModules.SetActive(modModified)
715 modifiedFilename = GetModifiedFilename(self.demoModules.name)
716
717 # Create the demo directory if one doesn't already exist
718 if not os.path.exists(GetModifiedDirectory()):
719 try:
720 os.makedirs(GetModifiedDirectory())
721 if not os.path.exists(GetModifiedDirectory()):
c163da42 722 wx.LogMessage("BUG: Created demo directory but it still doesn't exist")
08ecc920
RD
723 raise AssetionError
724 except:
725 wx.LogMessage("Error creating demo directory: %s" % GetModifiedDirectory())
726 return
727 else:
728 wx.LogMessage("Created directory for modified demos: %s" % GetModifiedDirectory())
729
730 # Save
887a1bd9 731 f = open(modifiedFilename, "wt")
08ecc920
RD
732 source = self.editor.GetText()
733 try:
734 f.write(source)
735 finally:
736 f.close()
737
738 busy = wx.BusyInfo("Reloading demo module...")
739 self.demoModules.LoadFromFile(modModified, modifiedFilename)
740 self.ActiveModuleChanged()
741
742
743 def OnRestore(self, event): # Handles the "Delete Modified" button
744 modifiedFilename = GetModifiedFilename(self.demoModules.name)
745 self.demoModules.Delete(modModified)
746 os.unlink(modifiedFilename) # Delete the modified copy
747 busy = wx.BusyInfo("Reloading demo module...")
748 self.ActiveModuleChanged()
749
1fded56b 750
6c5ae2d2
RD
751#---------------------------------------------------------------------------
752
753def opj(path):
754 """Convert paths to the platform-specific separator"""
08ecc920
RD
755 str = apply(os.path.join, tuple(path.split('/')))
756 # HACK: on Linux, a leading / gets lost...
757 if path.startswith('/'):
758 str = '/' + str
759 return str
760
761
762def GetModifiedDirectory():
763 """
764 Returns the directory where modified versions of the demo files
765 are stored
766 """
767 return opj(wx.GetHomeDir() + "/.wxPyDemo/modified/")
768
769
770def GetModifiedFilename(name):
771 """
772 Returns the filename of the modified version of the specified demo
773 """
774 if not name.endswith(".py"):
775 name = name + ".py"
776 return GetModifiedDirectory() + name
777
778
779def GetOriginalFilename(name):
780 """
781 Returns the filename of the original version of the specified demo
782 """
783 if not name.endswith(".py"):
784 name = name + ".py"
785 return name
786
787
788def DoesModifiedExist(name):
789 """Returns whether the specified demo has a modified copy"""
790 if os.path.exists(GetModifiedFilename(name)):
791 return True
792 else:
793 return False
794
795
796#---------------------------------------------------------------------------
797
798class ModuleDictWrapper:
799 """Emulates a module with a dynamically compiled __dict__"""
800 def __init__(self, dict):
801 self.dict = dict
802
803 def __getattr__(self, name):
804 if name in self.dict:
805 return self.dict[name]
806 else:
807 raise AttributeError
808
809class DemoModules:
810 """
811 Dynamically manages the original/modified versions of a demo
812 module
813 """
814 def __init__(self, name):
815 self.modActive = -1
816 self.name = name
817
818 # (dict , source , filename , description , error information )
819 # ( 0 , 1 , 2 , 3 , 4 )
820 self.modules = [[None, "" , "" , "<original>" , None],
821 [None, "" , "" , "<modified>" , None]]
822
823 # load original module
824 self.LoadFromFile(modOriginal, GetOriginalFilename(name))
317a64e5 825 self.SetActive(modOriginal)
08ecc920
RD
826
827 # load modified module (if one exists)
828 if DoesModifiedExist(name):
829 self.LoadFromFile(modModified, GetModifiedFilename(name))
830
831
832 def LoadFromFile(self, modID, filename):
833 self.modules[modID][2] = filename
887a1bd9 834 file = open(filename, "rt")
08ecc920
RD
835 self.LoadFromSource(modID, file.read())
836 file.close()
837
838
839 def LoadFromSource(self, modID, source):
840 self.modules[modID][1] = source
841 self.LoadDict(modID)
842
843
844 def LoadDict(self, modID):
845 if self.name != __name__:
846 source = self.modules[modID][1]
02b800ce
RD
847 #description = self.modules[modID][3]
848 description = self.modules[modID][2]
08ecc920
RD
849
850 try:
851 self.modules[modID][0] = {}
852 code = compile(source, description, "exec")
853 exec code in self.modules[modID][0]
854 except:
855 self.modules[modID][4] = DemoError(sys.exc_info())
856 self.modules[modID][0] = None
857 else:
858 self.modules[modID][4] = None
859
860
861 def SetActive(self, modID):
862 if modID != modOriginal and modID != modModified:
863 raise LookupError
864 else:
865 self.modActive = modID
866
867
868 def GetActive(self):
869 dict = self.modules[self.modActive][0]
870 if dict is None:
871 return None
872 else:
873 return ModuleDictWrapper(dict)
874
875
876 def GetActiveID(self):
877 return self.modActive
878
879
880 def GetSource(self, modID = None):
881 if modID is None:
882 modID = self.modActive
883 return self.modules[modID][1]
884
885
886 def GetFilename(self, modID = None):
887 if modID is None:
888 modID = self.modActive
889 return self.modules[self.modActive][2]
890
891
892 def GetErrorInfo(self, modID = None):
893 if modID is None:
894 modID = self.modActive
895 return self.modules[self.modActive][4]
896
897
898 def Exists(self, modID):
899 return self.modules[modID][1] != ""
900
901
902 def UpdateFile(self, modID = None):
903 """Updates the file from which a module was loaded
904 with (possibly updated) source"""
905 if modID is None:
906 modID = self.modActive
907
908 source = self.modules[modID][1]
909 filename = self.modules[modID][2]
910
911 try:
887a1bd9 912 file = open(filename, "wt")
08ecc920
RD
913 file.write(source)
914 finally:
915 file.close()
916
917
918 def Delete(self, modID):
919 if self.modActive == modID:
920 self.SetActive(0)
921
922 self.modules[modID][0] = None
923 self.modules[modID][1] = ""
924 self.modules[modID][2] = ""
925
926
08ecc920
RD
927#---------------------------------------------------------------------------
928
929class DemoError:
930 """Wraps and stores information about the current exception"""
931 def __init__(self, exc_info):
932 import copy
933
934 excType, excValue = exc_info[:2]
935 # traceback list entries: (filename, line number, function name, text)
936 self.traceback = traceback.extract_tb(exc_info[2])
937
938 # --Based on traceback.py::format_exception_only()--
939 if type(excType) == types.ClassType:
940 self.exception_type = excType.__name__
941 else:
942 self.exception_type = excType
943
944 # If it's a syntax error, extra information needs
945 # to be added to the traceback
946 if excType is SyntaxError:
947 try:
948 msg, (filename, lineno, self.offset, line) = excValue
949 except:
950 pass
951 else:
952 if not filename:
953 filename = "<string>"
954 line = line.strip()
955 self.traceback.append( (filename, lineno, "", line) )
956 excValue = msg
957 try:
958 self.exception_details = str(excValue)
959 except:
960 self.exception_details = "<unprintable %s object>" & type(excValue).__name__
961
962 del exc_info
963
964 def __str__(self):
965 ret = "Type %s \n \
966 Traceback: %s \n \
967 Details : %s" % ( str(self.exception_type), str(self.traceback), self.exception_details )
968 return ret
969
970#---------------------------------------------------------------------------
971
972class DemoErrorPanel(wx.Panel):
973 """Panel put into the demo tab when the demo fails to run due to errors"""
974
975 def __init__(self, parent, codePanel, demoError, log):
976 wx.Panel.__init__(self, parent, -1)#, style=wx.NO_FULL_REPAINT_ON_RESIZE)
977 self.codePanel = codePanel
978 self.nb = parent
979 self.log = log
980
981 self.box = wx.BoxSizer(wx.VERTICAL)
982
983 # Main Label
d6922577 984 self.box.Add(wx.StaticText(self, -1, "An error has occurred while trying to run the demo")
08ecc920
RD
985 , 0, wx.ALIGN_CENTER | wx.TOP, 10)
986
987 # Exception Information
988 boxInfo = wx.StaticBox(self, -1, "Exception Info" )
989 boxInfoSizer = wx.StaticBoxSizer(boxInfo, wx.VERTICAL ) # Used to center the grid within the box
990 boxInfoGrid = wx.FlexGridSizer(0, 2, 0, 0)
991 textFlags = wx.ALIGN_RIGHT | wx.LEFT | wx.RIGHT | wx.TOP
992 boxInfoGrid.Add(wx.StaticText(self, -1, "Type: "), 0, textFlags, 5 )
993 boxInfoGrid.Add(wx.StaticText(self, -1, demoError.exception_type) , 0, textFlags, 5 )
994 boxInfoGrid.Add(wx.StaticText(self, -1, "Details: ") , 0, textFlags, 5 )
995 boxInfoGrid.Add(wx.StaticText(self, -1, demoError.exception_details) , 0, textFlags, 5 )
996 boxInfoSizer.Add(boxInfoGrid, 0, wx.ALIGN_CENTRE | wx.ALL, 5 )
997 self.box.Add(boxInfoSizer, 0, wx.ALIGN_CENTER | wx.ALL, 5)
998
999 # Set up the traceback list
1000 # This one automatically resizes last column to take up remaining space
1001 from ListCtrl import TestListCtrl
1002 self.list = TestListCtrl(self, -1, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
1003 self.list.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
1004 self.list.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
1005 self.list.InsertColumn(0, "Filename")
1006 self.list.InsertColumn(1, "Line", wx.LIST_FORMAT_RIGHT)
1007 self.list.InsertColumn(2, "Function")
1008 self.list.InsertColumn(3, "Code")
1009 self.InsertTraceback(self.list, demoError.traceback)
1010 self.list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
1011 self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
1012 self.box.Add(wx.StaticText(self, -1, "Traceback:")
1013 , 0, wx.ALIGN_CENTER | wx.TOP, 5)
1014 self.box.Add(self.list, 1, wx.GROW | wx.ALIGN_CENTER | wx.ALL, 5)
1015 self.box.Add(wx.StaticText(self, -1, "Entries from the demo module are shown in blue\n"
1016 + "Double-click on them to go to the offending line")
1017 , 0, wx.ALIGN_CENTER | wx.BOTTOM, 5)
1018
1019 self.box.Fit(self)
1020 self.SetSizer(self.box)
1021
1022
1023 def InsertTraceback(self, list, traceback):
1024 #Add the traceback data
1025 for x in range(len(traceback)):
1026 data = traceback[x]
1027 list.InsertStringItem(x, os.path.basename(data[0])) # Filename
1028 list.SetStringItem(x, 1, str(data[1])) # Line
1029 list.SetStringItem(x, 2, str(data[2])) # Function
1030 list.SetStringItem(x, 3, str(data[3])) # Code
1031
1032 # Check whether this entry is from the demo module
1033 if data[0] == "<original>" or data[0] == "<modified>": # FIXME: make more generalised
1034 self.list.SetItemData(x, int(data[1])) # Store line number for easy access
1035 # Give it a blue colour
1036 item = self.list.GetItem(x)
1037 item.SetTextColour(wx.BLUE)
1038 self.list.SetItem(item)
1039 else:
1040 self.list.SetItemData(x, -1) # Editor can't jump into this one's code
1041
1042
1043 def OnItemSelected(self, event):
1044 # This occurs before OnDoubleClick and can be used to set the
1045 # currentItem. OnDoubleClick doesn't get a wxListEvent....
1046 self.currentItem = event.m_itemIndex
1047 event.Skip()
1048
1049
1050 def OnDoubleClick(self, event):
1051 # If double-clicking on a demo's entry, jump to the line number
1052 line = self.list.GetItemData(self.currentItem)
1053 if line != -1:
1054 self.nb.SetSelection(1) # Switch to the code viewer tab
1055 wx.CallAfter(self.codePanel.JumpToLine, line-1, True)
1056 event.Skip()
1057
6c5ae2d2 1058
76bfdc78
RD
1059#---------------------------------------------------------------------------
1060
1cc18e15
RD
1061class DemoTaskBarIcon(wx.TaskBarIcon):
1062 TBMENU_RESTORE = wx.NewId()
1063 TBMENU_CLOSE = wx.NewId()
1064 TBMENU_CHANGE = wx.NewId()
1065 TBMENU_REMOVE = wx.NewId()
1066
1067 def __init__(self, frame):
1068 wx.TaskBarIcon.__init__(self)
1069 self.frame = frame
1070
1071 # Set the image
8596dc0b 1072 icon = self.MakeIcon(images.getWXPdemoImage())
1cc18e15 1073 self.SetIcon(icon, "wxPython Demo")
8596dc0b 1074 self.imgidx = 1
1cc18e15
RD
1075
1076 # bind some events
1077 self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
1078 self.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=self.TBMENU_RESTORE)
1079 self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=self.TBMENU_CLOSE)
1080 self.Bind(wx.EVT_MENU, self.OnTaskBarChange, id=self.TBMENU_CHANGE)
1081 self.Bind(wx.EVT_MENU, self.OnTaskBarRemove, id=self.TBMENU_REMOVE)
1082
1083
1084 def CreatePopupMenu(self):
1085 """
1086 This method is called by the base class when it needs to popup
1087 the menu for the default EVT_RIGHT_DOWN event. Just create
1088 the menu how you want it and return it from this function,
1089 the base class takes care of the rest.
1090 """
1091 menu = wx.Menu()
1092 menu.Append(self.TBMENU_RESTORE, "Restore wxPython Demo")
1093 menu.Append(self.TBMENU_CLOSE, "Close wxPython Demo")
1094 menu.AppendSeparator()
1095 menu.Append(self.TBMENU_CHANGE, "Change the TB Icon")
1096 menu.Append(self.TBMENU_REMOVE, "Remove the TB Icon")
1097 return menu
1098
1099
1100 def MakeIcon(self, img):
1101 """
1102 The various platforms have different requirements for the
1103 icon size...
1104 """
1105 if "wxMSW" in wx.PlatformInfo:
8596dc0b 1106 img = img.Scale(16, 16)
1cc18e15 1107 elif "wxGTK" in wx.PlatformInfo:
8596dc0b
RD
1108 img = img.Scale(22, 22)
1109 # wxMac can be any size upto 128x128, so leave the source img alone....
1cc18e15
RD
1110 icon = wx.IconFromBitmap(img.ConvertToBitmap() )
1111 return icon
1112
1113
1114 def OnTaskBarActivate(self, evt):
1115 if self.frame.IsIconized():
1116 self.frame.Iconize(False)
1117 if not self.frame.IsShown():
1118 self.frame.Show(True)
1119 self.frame.Raise()
1120
1121
1122 def OnTaskBarClose(self, evt):
1123 self.frame.Close()
1124
1cc18e15
RD
1125
1126 def OnTaskBarChange(self, evt):
6c75a4cf 1127 names = [ "WXPdemo", "Mondrian", "Pencil", "Carrot" ]
8596dc0b
RD
1128 name = names[self.imgidx]
1129
1130 getFunc = getattr(images, "get%sImage" % name)
1131 self.imgidx += 1
1132 if self.imgidx >= len(names):
1133 self.imgidx = 0
1134
1135 icon = self.MakeIcon(getFunc())
1136 self.SetIcon(icon, "This is a new icon: " + name)
1cc18e15
RD
1137
1138
1139 def OnTaskBarRemove(self, evt):
1140 self.RemoveIcon()
1141
1142
1143#---------------------------------------------------------------------------
1fded56b 1144class wxPythonDemo(wx.Frame):
e9159fe8 1145 overviewText = "wxPython Overview"
c368d904 1146
08ecc920 1147 def __init__(self, parent, title):
8ee202f3 1148 wx.Frame.__init__(self, parent, -1, title, size = (950, 720),
08ecc920 1149 style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
2f90df85 1150
f290d1c7
RD
1151 self.SetMinSize((640,480))
1152
08ecc920 1153 self.loaded = False
694759cf 1154 self.cwd = os.getcwd()
3ca6a5f0 1155 self.curOverview = ""
08ecc920
RD
1156 self.demoPage = None
1157 self.codePage = None
887a1bd9 1158 self.shell = None
a6780fa2 1159 self.firstTime = True
df5204e0 1160 self.finddlg = None
694759cf 1161
8596dc0b 1162 icon = images.getWXPdemoIcon()
96bfd053 1163 self.SetIcon(icon)
c368d904 1164
8bbd1bbf
RD
1165 try:
1166 self.tbicon = DemoTaskBarIcon(self)
1167 except:
1168 self.tbicon = None
1169
1fded56b 1170 wx.CallAfter(self.ShowTip)
cf694132
RD
1171
1172 self.otherWin = None
80b27b4e
RD
1173 self.Bind(wx.EVT_IDLE, self.OnIdle)
1174 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
1175 self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)
1176 self.Bind(wx.EVT_MAXIMIZE, self.OnMaximize)
cf694132 1177
1fded56b
RD
1178 self.Centre(wx.BOTH)
1179 self.CreateStatusBar(1, wx.ST_SIZEGRIP)
5a7823f5 1180
0c8f2860
RD
1181 splitter = wx.SplitterWindow(self, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D)
1182 splitter2 = wx.SplitterWindow(splitter, -1, style=wx.CLIP_CHILDREN | wx.SP_LIVE_UPDATE | wx.SP_3D)
5a7823f5 1183
d56cebe7 1184 def EmptyHandler(evt): pass
80b27b4e
RD
1185 #splitter.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
1186 #splitter2.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
cf694132 1187
1e4a197e
RD
1188 # Prevent TreeCtrl from displaying all items after destruction when True
1189 self.dying = False
cf694132 1190
08ecc920
RD
1191 # Create a Notebook
1192 self.nb = wx.Notebook(splitter2, -1, style=wx.CLIP_CHILDREN)
1193
cf694132 1194 # Make a File menu
1fded56b
RD
1195 self.mainmenu = wx.MenuBar()
1196 menu = wx.Menu()
330af869
RD
1197 item = menu.Append(-1, '&Redirect Output',
1198 'Redirect print statements to a window',
1199 wx.ITEM_CHECK)
1200 self.Bind(wx.EVT_MENU, self.OnToggleRedirect, item)
08ecc920 1201
c8000995
RD
1202 item = menu.Append(-1, 'E&xit\tAlt-X', 'Get the heck outta here!')
1203 self.Bind(wx.EVT_MENU, self.OnFileExit, item)
05871e13 1204 wx.App.SetMacExitMenuItemId(item.GetId())
cf694132
RD
1205 self.mainmenu.Append(menu, '&File')
1206
ec3e670f 1207 # Make a Demo menu
1fded56b 1208 menu = wx.Menu()
ec3e670f 1209 for item in _treeList:
1fded56b 1210 submenu = wx.Menu()
ec3e670f 1211 for childItem in item[1]:
c8000995
RD
1212 mi = submenu.Append(-1, childItem)
1213 self.Bind(wx.EVT_MENU, self.OnDemoMenu, mi)
1fded56b 1214 menu.AppendMenu(wx.NewId(), item[0], submenu)
ec3e670f
RD
1215 self.mainmenu.Append(menu, '&Demo')
1216
1217
cf694132 1218 # Make a Help menu
1fded56b 1219 menu = wx.Menu()
c8000995
RD
1220 findItem = menu.Append(-1, '&Find\tCtrl-F', 'Find in the Demo Code')
1221 findnextItem = menu.Append(-1, 'Find &Next\tF3', 'Find Next')
1e4a197e 1222 menu.AppendSeparator()
887a1bd9
RD
1223
1224 shellItem = menu.Append(-1, 'Open Py&Shell Window\tF5',
1225 'An interactive interpreter window with the demo app and frame objects in the namesapce')
1226 menu.AppendSeparator()
3764716d 1227 helpItem = menu.Append(-1, '&About wxPython Demo', 'wxPython RULES!!!')
05871e13 1228 wx.App.SetMacAboutMenuItemId(helpItem.GetId())
887a1bd9
RD
1229
1230 self.Bind(wx.EVT_MENU, self.OnOpenShellWindow, shellItem)
c8000995
RD
1231 self.Bind(wx.EVT_MENU, self.OnHelpAbout, helpItem)
1232 self.Bind(wx.EVT_MENU, self.OnHelpFind, findItem)
1233 self.Bind(wx.EVT_MENU, self.OnFindNext, findnextItem)
df5204e0
RD
1234 self.Bind(wx.EVT_FIND, self.OnFind)
1235 self.Bind(wx.EVT_FIND_NEXT, self.OnFind)
1236 self.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose)
1237 self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateFindItems, findItem)
1238 self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateFindItems, findnextItem)
cf694132
RD
1239 self.mainmenu.Append(menu, '&Help')
1240 self.SetMenuBar(self.mainmenu)
1241
1fded56b 1242 self.finddata = wx.FindReplaceData()
02b800ce 1243 self.finddata.SetFlags(wx.FR_DOWN)
1e4a197e
RD
1244
1245 if 0:
1246 # This is another way to set Accelerators, in addition to
1247 # using the '\t<key>' syntax in the menu items.
1fded56b
RD
1248 aTable = wx.AcceleratorTable([(wx.ACCEL_ALT, ord('X'), exitID),
1249 (wx.ACCEL_CTRL, ord('H'), helpID),
1250 (wx.ACCEL_CTRL, ord('F'), findID),
1251 (wx.ACCEL_NORMAL, WXK_F3, findnextID)
1252 ])
1e4a197e 1253 self.SetAcceleratorTable(aTable)
2f90df85 1254
bb0054cd 1255
cf694132 1256 # Create a TreeCtrl
1fded56b 1257 tID = wx.NewId()
f6bcfd97 1258 self.treeMap = {}
3628e088
RD
1259 self.tree = wx.TreeCtrl(splitter, tID, style =
1260 wx.TR_DEFAULT_STYLE #| wx.TR_HAS_VARIABLE_ROW_HEIGHT
eb0f373c 1261 )
afb810d9 1262
e9159fe8 1263 root = self.tree.AddRoot("wxPython Overview")
f6bcfd97
BP
1264 firstChild = None
1265 for item in _treeList:
1266 child = self.tree.AppendItem(root, item[0])
1267 if not firstChild: firstChild = child
1268 for childItem in item[1]:
1269 theDemo = self.tree.AppendItem(child, childItem)
1270 self.treeMap[childItem] = theDemo
1271
1272 self.tree.Expand(root)
1273 self.tree.Expand(firstChild)
80b27b4e
RD
1274 self.tree.Bind(wx.EVT_TREE_ITEM_EXPANDED, self.OnItemExpanded, id=tID)
1275 self.tree.Bind(wx.EVT_TREE_ITEM_COLLAPSED, self.OnItemCollapsed, id=tID)
1276 self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=tID)
1277 self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnTreeLeftDown)
cf694132 1278
1fded56b 1279 # Set up a wx.html.HtmlWindow on the Overview Notebook page
0bdca46d
RD
1280 # we put it in a panel first because there seems to be a
1281 # refresh bug of some sort (wxGTK) when it is directly in
1282 # the notebook...
1283 if 0: # the old way
1fded56b 1284 self.ovr = wx.html.HtmlWindow(self.nb, -1, size=(400, 400))
0bdca46d
RD
1285 self.nb.AddPage(self.ovr, self.overviewText)
1286
1fded56b
RD
1287 else: # hopefully I can remove this hacky code soon, see SF bug #216861
1288 panel = wx.Panel(self.nb, -1, style=wx.CLIP_CHILDREN)
1289 self.ovr = wx.html.HtmlWindow(panel, -1, size=(400, 400))
0bdca46d
RD
1290 self.nb.AddPage(panel, self.overviewText)
1291
1292 def OnOvrSize(evt, ovr=self.ovr):
1293 ovr.SetSize(evt.GetSize())
80b27b4e
RD
1294 panel.Bind(wx.EVT_SIZE, OnOvrSize)
1295 panel.Bind(wx.EVT_ERASE_BACKGROUND, EmptyHandler)
0bdca46d 1296
08ecc920 1297 if "gtk2" in wx.PlatformInfo:
385721a8 1298 self.ovr.SetStandardFonts()
08ecc920 1299 self.SetOverview(self.overviewText, mainOverview)
c368d904 1300
cf694132 1301
08ecc920
RD
1302 # Set up a log window
1303 self.log = wx.TextCtrl(splitter2, -1,
1304 style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
1305
1306 # Set the wxWindows log target to be this textctrl
1307 #wx.Log_SetActiveTarget(wx.LogTextCtrl(self.log))
cf694132 1308
08ecc920
RD
1309 # But instead of the above we want to show how to use our own wx.Log class
1310 wx.Log_SetActiveTarget(MyLog(self.log))
1311
1312 # for serious debugging
1313 #wx.Log_SetActiveTarget(wx.LogStderr())
1314 #wx.Log_SetTraceMask(wx.TraceMessages)
cf694132
RD
1315
1316
e44b5196
RD
1317 self.Bind(wx.EVT_ACTIVATE, self.OnActivate)
1318 wx.GetApp().Bind(wx.EVT_ACTIVATE_APP, self.OnAppActivate)
1319
f6bcfd97 1320 # add the windows to the splitter and split it.
08ecc920
RD
1321 splitter2.SplitHorizontally(self.nb, self.log, -160)
1322 splitter.SplitVertically(self.tree, splitter2, 200)
afb810d9 1323
f290d1c7
RD
1324 splitter.SetMinimumPaneSize(120)
1325 splitter2.SetMinimumPaneSize(60)
afb810d9 1326
11926a78 1327 # Make the splitter on the right expand the top window when resized
2f0f3b0f
RD
1328 def SplitterOnSize(evt):
1329 splitter = evt.GetEventObject()
1330 sz = splitter.GetSize()
08ecc920 1331 splitter.SetSashPosition(sz.height - 160, False)
2f0f3b0f 1332 evt.Skip()
80b27b4e
RD
1333
1334 splitter2.Bind(wx.EVT_SIZE, SplitterOnSize)
2f0f3b0f 1335
bb0054cd
RD
1336 # select initial items
1337 self.nb.SetSelection(0)
f6bcfd97 1338 self.tree.SelectItem(root)
ec3e670f 1339
08ecc920
RD
1340 # Load 'Main' module
1341 self.LoadDemo(self.overviewText)
1342 self.loaded = True
1343
1344 # select some other initial module?
1345 if len(sys.argv) > 1:
1346 arg = sys.argv[1]
1347 if arg.endswith('.py'):
1348 arg = arg[:-3]
1349 selectedDemo = self.treeMap.get(arg, None)
f6bcfd97 1350 if selectedDemo:
ec3e670f
RD
1351 self.tree.SelectItem(selectedDemo)
1352 self.tree.EnsureVisible(selectedDemo)
1353
bb0054cd 1354
cf694132
RD
1355 #---------------------------------------------
1356 def WriteText(self, text):
f6bcfd97
BP
1357 if text[-1:] == '\n':
1358 text = text[:-1]
1fded56b 1359 wx.LogMessage(text)
f6bcfd97 1360
cf694132
RD
1361 def write(self, txt):
1362 self.WriteText(txt)
1363
1364 #---------------------------------------------
1365 def OnItemExpanded(self, event):
1366 item = event.GetItem()
1fded56b 1367 wx.LogMessage("OnItemExpanded: %s" % self.tree.GetItemText(item))
c368d904 1368 event.Skip()
cf694132
RD
1369
1370 #---------------------------------------------
1371 def OnItemCollapsed(self, event):
1372 item = event.GetItem()
1fded56b 1373 wx.LogMessage("OnItemCollapsed: %s" % self.tree.GetItemText(item))
c368d904 1374 event.Skip()
f6bcfd97
BP
1375
1376 #---------------------------------------------
1377 def OnTreeLeftDown(self, event):
08ecc920 1378 # reset the overview text if the tree item is clicked on again
f6bcfd97
BP
1379 pt = event.GetPosition();
1380 item, flags = self.tree.HitTest(pt)
1381 if item == self.tree.GetSelection():
d975da9b 1382 self.SetOverview(self.tree.GetItemText(item)+" Overview", self.curOverview)
185d7c3e 1383 event.Skip()
cf694132
RD
1384
1385 #---------------------------------------------
1386 def OnSelChanged(self, event):
08ecc920 1387 if self.dying or not self.loaded:
cf694132
RD
1388 return
1389
5a7823f5
RD
1390 item = event.GetItem()
1391 itemText = self.tree.GetItemText(item)
08ecc920 1392 self.LoadDemo(itemText)
5a7823f5
RD
1393
1394 #---------------------------------------------
08ecc920
RD
1395 def LoadDemo(self, demoName):
1396 try:
1397 wx.BeginBusyCursor()
1398
1399 os.chdir(self.cwd)
1400 self.ShutdownDemoModule()
1401
1402 if demoName == self.overviewText:
1403 # User selected the "wxPython Overview" node
1404 # ie: _this_ module
1405 # Changing the main window at runtime not yet supported...
1406 self.demoModules = DemoModules(__name__)
1407 self.SetOverview(self.overviewText, mainOverview)
1408 self.LoadDemoSource()
1409 self.UpdateNotebook(0)
1410 else:
1411 if os.path.exists(GetOriginalFilename(demoName)):
1412 wx.LogMessage("Loading demo %s.py..." % demoName)
1413 self.demoModules = DemoModules(demoName)
a6780fa2 1414 self.LoadDemoSource()
08ecc920
RD
1415 self.tree.Refresh()
1416 else:
1417 self.SetOverview("wxPython", mainOverview)
1418 self.codePage = None
1419 self.UpdateNotebook(0)
1420 finally:
1421 wx.EndBusyCursor()
cf694132 1422
08ecc920
RD
1423 #---------------------------------------------
1424 def LoadDemoSource(self):
1425 self.codePage = None
1426 self.codePage = DemoCodePanel(self.nb, self)
1427 self.codePage.LoadDemo(self.demoModules)
1428
1429 #---------------------------------------------
a6780fa2 1430 def RunModule(self):
08ecc920 1431 """Runs the active module"""
cf694132 1432
08ecc920
RD
1433 module = self.demoModules.GetActive()
1434 self.ShutdownDemoModule()
1435 overviewText = ""
1436
8412feb0
RD
1437 # o The RunTest() for all samples must now return a window that can
1438 # be palced in a tab in the main notebook.
d6922577 1439 # o If an error occurs (or has occurred before) an error tab is created.
08ecc920
RD
1440
1441 if module is not None:
1442 wx.LogMessage("Running demo module...")
1443 if hasattr(module, "overview"):
1444 overviewText = module.overview
cf694132 1445
08ecc920
RD
1446 try:
1447 self.demoPage = module.runTest(self, self.nb, self)
08ecc920 1448 except:
317a64e5 1449 self.demoPage = DemoErrorPanel(self.nb, self.codePage,
7d0f8766
RD
1450 DemoError(sys.exc_info()), self)
1451
1452 assert self.demoPage is not None, "runTest must return a window!"
1453
08ecc920
RD
1454 else:
1455 # There was a previous error in compiling or exec-ing
317a64e5
RD
1456 self.demoPage = DemoErrorPanel(self.nb, self.codePage,
1457 self.demoModules.GetErrorInfo(), self)
a6780fa2 1458
08ecc920 1459 self.SetOverview(self.demoModules.name + " Overview", overviewText)
a6780fa2
RD
1460
1461 if self.firstTime:
1462 # cahnge to the demo page the first time a module is run
1463 self.UpdateNotebook(2)
1464 self.firstTime = False
1465 else:
1466 # otherwise just stay on the same tab in case the user has changed to another one
1467 self.UpdateNotebook()
cf694132
RD
1468
1469 #---------------------------------------------
08ecc920
RD
1470 def ShutdownDemoModule(self):
1471 if self.demoPage:
1472 # inform the window that it's time to quit if it cares
1473 if hasattr(self.demoPage, "ShutdownDemo"):
1474 self.demoPage.ShutdownDemo()
1475 wx.YieldIfNeeded() # in case the page has pending events
1476 self.demoPage = None
1477
1478 #---------------------------------------------
1479 def UpdateNotebook(self, select = -1):
1480 nb = self.nb
1481 debug = False
1482
1483 def UpdatePage(page, pageText):
1484 pageExists = False
1485 pagePos = -1
1486 for i in range(nb.GetPageCount()):
1487 if nb.GetPageText(i) == pageText:
1488 pageExists = True
1489 pagePos = i
1490 break
1491
1492 if page:
1493 if not pageExists:
1494 # Add a new page
08ecc920
RD
1495 nb.AddPage(page, pageText)
1496 if debug: wx.LogMessage("DBG: ADDED %s" % pageText)
1497 else:
08ecc920
RD
1498 if nb.GetPage(pagePos) != page:
1499 # Reload an existing page
1500 nb.Freeze()
08ecc920
RD
1501 nb.DeletePage(pagePos)
1502 nb.InsertPage(pagePos, page, pageText)
1503 nb.Thaw()
1504 if debug: wx.LogMessage("DBG: RELOADED %s" % pageText)
1505 else:
1506 # Excellent! No redraw/flicker
1507 if debug: wx.LogMessage("DBG: SAVED from reloading %s" % pageText)
1508 elif pageExists:
1509 # Delete a page
1510 nb.DeletePage(pagePos)
1511 if debug: wx.LogMessage("DBG: DELETED %s" % pageText)
1512 else:
1513 if debug: wx.LogMessage("DBG: STILL GONE - %s" % pageText)
1514
1515 if select == -1:
1516 select = nb.GetSelection()
cf694132 1517
08ecc920
RD
1518 UpdatePage(self.codePage, "Demo Code")
1519 UpdatePage(self.demoPage, "Demo")
cf694132 1520
887a1bd9 1521 if select >= 0 and select < nb.GetPageCount():
08ecc920
RD
1522 nb.SetSelection(select)
1523
cf694132
RD
1524 #---------------------------------------------
1525 def SetOverview(self, name, text):
f6bcfd97
BP
1526 self.curOverview = text
1527 lead = text[:6]
1528 if lead != '<html>' and lead != '<HTML>':
1e4a197e 1529 text = '<br>'.join(text.split('\n'))
6c7d1792
RD
1530 if wx.USE_UNICODE:
1531 text = text.decode('iso8859_1')
f6bcfd97 1532 self.ovr.SetPage(text)
cf694132 1533 self.nb.SetPageText(0, name)
cf694132
RD
1534
1535 #---------------------------------------------
1536 # Menu methods
c368d904 1537 def OnFileExit(self, *event):
cf694132
RD
1538 self.Close()
1539
330af869
RD
1540 def OnToggleRedirect(self, event):
1541 app = wx.GetApp()
1542 if event.Checked():
1543 app.RedirectStdio()
1544 print "Print statements and other standard output will now be directed to this window."
1545 else:
1546 app.RestoreStdio()
1547 print "Print statements and other standard output will now be sent to the usual location."
08ecc920 1548
cf694132 1549 def OnHelpAbout(self, event):
e166644c 1550 from About import MyAboutBox
ec3e670f 1551 about = MyAboutBox(self)
cf694132
RD
1552 about.ShowModal()
1553 about.Destroy()
1554
1e4a197e 1555 def OnHelpFind(self, event):
df5204e0
RD
1556 if self.finddlg != None:
1557 return
1558
1e4a197e 1559 self.nb.SetSelection(1)
1fded56b 1560 self.finddlg = wx.FindReplaceDialog(self, self.finddata, "Find",
02b800ce 1561 wx.FR_NOMATCHCASE | wx.FR_NOWHOLEWORD)
1e4a197e
RD
1562 self.finddlg.Show(True)
1563
df5204e0
RD
1564
1565 def OnUpdateFindItems(self, evt):
1566 evt.Enable(self.finddlg == None)
1567
1568
1e4a197e 1569 def OnFind(self, event):
08ecc920 1570 editor = self.codePage.editor
1e4a197e 1571 self.nb.SetSelection(1)
08ecc920
RD
1572 end = editor.GetLastPosition()
1573 textstring = editor.GetRange(0, end).lower()
1e4a197e 1574 findstring = self.finddata.GetFindString().lower()
02b800ce
RD
1575 backward = not (self.finddata.GetFlags() & wx.FR_DOWN)
1576 if backward:
1577 start = editor.GetSelection()[0]
1578 loc = textstring.rfind(findstring, 0, start)
1579 else:
1580 start = editor.GetSelection()[1]
1581 loc = textstring.find(findstring, start)
1e4a197e
RD
1582 if loc == -1 and start != 0:
1583 # string not found, start at beginning
02b800ce
RD
1584 if backward:
1585 start = end
1586 loc = textstring.rfind(findstring, 0, start)
1587 else:
1588 start = 0
1589 loc = textstring.find(findstring, start)
1e4a197e 1590 if loc == -1:
1fded56b 1591 dlg = wx.MessageDialog(self, 'Find String Not Found',
1e4a197e 1592 'Find String Not Found in Demo File',
1fded56b 1593 wx.OK | wx.ICON_INFORMATION)
1e4a197e
RD
1594 dlg.ShowModal()
1595 dlg.Destroy()
1596 if self.finddlg:
1597 if loc == -1:
1598 self.finddlg.SetFocus()
1599 return
1600 else:
1601 self.finddlg.Destroy()
df5204e0 1602 self.finddlg = None
08ecc920
RD
1603 editor.ShowPosition(loc)
1604 editor.SetSelection(loc, loc + len(findstring))
1e4a197e
RD
1605
1606
1607
1608 def OnFindNext(self, event):
1609 if self.finddata.GetFindString():
1610 self.OnFind(event)
1611 else:
1612 self.OnHelpFind(event)
1613
1614 def OnFindClose(self, event):
1615 event.GetDialog().Destroy()
df5204e0 1616 self.finddlg = None
1e4a197e 1617
cf694132 1618
887a1bd9
RD
1619 def OnOpenShellWindow(self, evt):
1620 if self.shell:
1621 # if it already exists then just make sure it's visible
1622 s = self.shell
1623 if s.IsIconized():
1624 s.Iconize(False)
1625 s.Raise()
1626 else:
1627 # Make a PyShell window
1628 from wx import py
1629 namespace = { 'wx' : wx,
1630 'app' : wx.GetApp(),
1631 'frame' : self,
1632 }
1633 self.shell = py.shell.ShellFrame(None, locals=namespace)
1634 self.shell.SetSize((640,480))
1635 self.shell.Show()
1636
1637 # Hook the close event of the main frame window so that we
1638 # close the shell at the same time if it still exists
1639 def CloseShell(evt):
1640 if self.shell:
1641 self.shell.Close()
1642 evt.Skip()
1643 self.Bind(wx.EVT_CLOSE, CloseShell)
1644
1645
cf694132
RD
1646 #---------------------------------------------
1647 def OnCloseWindow(self, event):
1e4a197e 1648 self.dying = True
08ecc920
RD
1649 self.demoPage = None
1650 self.codePage = None
26197023 1651 self.mainmenu = None
8bbd1bbf
RD
1652 if self.tbicon is not None:
1653 self.tbicon.Destroy()
cf694132
RD
1654 self.Destroy()
1655
c368d904 1656
cf694132
RD
1657 #---------------------------------------------
1658 def OnIdle(self, event):
1659 if self.otherWin:
1660 self.otherWin.Raise()
08ecc920 1661 self.demoPage = self.otherWin
cf694132
RD
1662 self.otherWin = None
1663
ccf691a4
RD
1664
1665 #---------------------------------------------
1666 def ShowTip(self):
1667 try:
1668 showTipText = open(opj("data/showTips")).read()
1669 showTip, index = eval(showTipText)
1670 except IOError:
1671 showTip, index = (1, 0)
1672 if showTip:
1fded56b 1673 tp = wx.CreateFileTipProvider(opj("data/tips.txt"), index)
861a0196 1674 ##tp = MyTP(0)
1fded56b 1675 showTip = wx.ShowTip(self, tp)
ccf691a4
RD
1676 index = tp.GetCurrentTip()
1677 open(opj("data/showTips"), "w").write(str( (showTip, index) ))
1678
1679
ec3e670f
RD
1680 #---------------------------------------------
1681 def OnDemoMenu(self, event):
f6bcfd97
BP
1682 try:
1683 selectedDemo = self.treeMap[self.mainmenu.GetLabel(event.GetId())]
1684 except:
1685 selectedDemo = None
1686 if selectedDemo:
1687 self.tree.SelectItem(selectedDemo)
1688 self.tree.EnsureVisible(selectedDemo)
ec3e670f 1689
c368d904 1690
c368d904 1691
f3d9dc1d
RD
1692 #---------------------------------------------
1693 def OnIconfiy(self, evt):
8412feb0 1694 wx.LogMessage("OnIconfiy: %s" % evt.Iconized())
f3d9dc1d
RD
1695 evt.Skip()
1696
1697 #---------------------------------------------
1698 def OnMaximize(self, evt):
1fded56b 1699 wx.LogMessage("OnMaximize")
f3d9dc1d
RD
1700 evt.Skip()
1701
8412feb0
RD
1702 #---------------------------------------------
1703 def OnActivate(self, evt):
1704 wx.LogMessage("OnActivate: %s" % evt.GetActive())
1705 evt.Skip()
f3d9dc1d 1706
8412feb0
RD
1707 #---------------------------------------------
1708 def OnAppActivate(self, evt):
1709 wx.LogMessage("OnAppActivate: %s" % evt.GetActive())
1710 evt.Skip()
f3d9dc1d 1711
cf694132
RD
1712#---------------------------------------------------------------------------
1713#---------------------------------------------------------------------------
1714
1fded56b 1715class MySplashScreen(wx.SplashScreen):
b5a5d647 1716 def __init__(self):
6c75a4cf 1717 bmp = wx.Image(opj("bitmaps/splash.png")).ConvertToBitmap()
1fded56b 1718 wx.SplashScreen.__init__(self, bmp,
a253aa20 1719 wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT,
6c75a4cf 1720 5000, None, -1)
80b27b4e 1721 self.Bind(wx.EVT_CLOSE, self.OnClose)
6f696172
RD
1722 self.fc = wx.FutureCall(2000, self.ShowMain)
1723
b5a5d647
RD
1724
1725 def OnClose(self, evt):
6f696172
RD
1726 # Make sure the default handler runs too so this window gets
1727 # destroyed
1728 evt.Skip()
8eca4fef 1729 self.Hide()
6f696172
RD
1730
1731 # if the timer is still running then go ahead and show the
1732 # main frame now
1733 if self.fc.IsRunning():
1734 self.fc.Stop()
1735 self.ShowMain()
1736
cf694132 1737
6c75a4cf
RD
1738 def ShowMain(self):
1739 frame = wxPythonDemo(None, "wxPython: (A Demonstration)")
1740 frame.Show()
6f696172
RD
1741 if self.fc.IsRunning():
1742 self.Raise()
6c75a4cf 1743
b5a5d647 1744
1fded56b 1745class MyApp(wx.App):
b5a5d647
RD
1746 def OnInit(self):
1747 """
68320e40 1748 Create and show the splash screen. It will then create and show
b5a5d647
RD
1749 the main frame when it is time to do so.
1750 """
1e4a197e 1751
7b85d630
RD
1752 wx.SystemOptions.SetOptionInt("mac.window-plain-transition", 1)
1753
35ee3288
RD
1754 # For debugging
1755 #self.SetAssertMode(wx.PYAPP_ASSERT_DIALOG)
1756
a253aa20
RD
1757 # Normally when using a SplashScreen you would create it, show
1758 # it and then continue on with the applicaiton's
1759 # initialization, finally creating and showing the main
1760 # application window(s). In this case we have nothing else to
1761 # do so we'll delay showing the main frame until later (see
6c75a4cf 1762 # ShowMain above) so the users can see the SplashScreen effect.
b5a5d647
RD
1763 splash = MySplashScreen()
1764 splash.Show()
a253aa20 1765
1e4a197e 1766 return True
b5a5d647
RD
1767
1768
1769
cf694132
RD
1770#---------------------------------------------------------------------------
1771
1772def main():
e02c03a4 1773 try:
d56cebe7 1774 demoPath = os.path.dirname(__file__)
e02c03a4
RD
1775 os.chdir(demoPath)
1776 except:
1777 pass
03a604a6 1778 app = MyApp(False)
cf694132
RD
1779 app.MainLoop()
1780
cf694132
RD
1781#---------------------------------------------------------------------------
1782
1783
08ecc920 1784mainOverview = """<html><body>
1fded56b
RD
1785<h2>wxPython</h2>
1786
f6063c19
RD
1787<p> wxPython is a <b>GUI toolkit</b> for the Python programming
1788language. It allows Python programmers to create programs with a
1789robust, highly functional graphical user interface, simply and easily.
1790It is implemented as a Python extension module (native code) that
1791wraps the popular wxWindows cross platform GUI library, which is
1792written in C++.
1fded56b
RD
1793
1794<p> Like Python and wxWindows, wxPython is <b>Open Source</b> which
1795means that it is free for anyone to use and the source code is
1796available for anyone to look at and modify. Or anyone can contribute
8b9a4190 1797fixes or enhancements to the project.
1fded56b
RD
1798
1799<p> wxPython is a <b>cross-platform</b> toolkit. This means that the
1800same program will run on multiple platforms without modification.
1801Currently supported platforms are 32-bit Microsoft Windows, most Unix
1802or unix-like systems, and Macintosh OS X. Since the language is
1803Python, wxPython programs are <b>simple, easy</b> to write and easy to
1804understand.
1805
1806<p> <b>This demo</b> is not only a collection of test cases for
1807wxPython, but is also designed to help you learn about and how to use
1808wxPython. Each sample is listed in the tree control on the left.
1809When a sample is selected in the tree then a module is loaded and run
1810(usually in a tab of this notebook,) and the source code of the module
1811is loaded in another tab for you to browse and learn from.
1812
1813"""
cf694132
RD
1814
1815
1816#----------------------------------------------------------------------------
1817#----------------------------------------------------------------------------
1818
1819if __name__ == '__main__':
08ecc920 1820 __name__ = 'Main'
cf694132
RD
1821 main()
1822
1823#----------------------------------------------------------------------------
1824
1825
1826
1827
1828
1829
1830