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