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