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