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