]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/pydocview.py
Copy about.htm
[wxWidgets.git] / wxPython / wx / lib / pydocview.py
1 #----------------------------------------------------------------------------
2 # Name: pydocview.py
3 # Purpose: Python extensions to the wxWindows docview framework
4 #
5 # Author: Peter Yared, Morgan Hua
6 #
7 # Created: 5/15/03
8 # CVS-ID: $Id$
9 # Copyright: (c) 2003-2005 ActiveGrid, Inc.
10 # License: wxWindows license
11 #----------------------------------------------------------------------------
12
13
14 import wx
15 import wx.lib.docview
16 import sys
17 import getopt
18 from wxPython.lib.rcsizer import RowColSizer
19 import os
20 import os.path
21 import time
22 import string
23 import pickle
24 import tempfile
25 import mmap
26 _ = wx.GetTranslation
27 if wx.Platform == '__WXMSW__':
28 _WINDOWS = True
29 else:
30 _WINDOWS = False
31
32 #----------------------------------------------------------------------------
33 # Constants
34 #----------------------------------------------------------------------------
35
36 VIEW_TOOLBAR_ID = wx.NewId()
37 VIEW_STATUSBAR_ID = wx.NewId()
38
39 EMBEDDED_WINDOW_TOP = 1
40 EMBEDDED_WINDOW_BOTTOM = 2
41 EMBEDDED_WINDOW_LEFT = 4
42 EMBEDDED_WINDOW_RIGHT = 8
43 EMBEDDED_WINDOW_TOPLEFT = 16
44 EMBEDDED_WINDOW_BOTTOMLEFT = 32
45 EMBEDDED_WINDOW_TOPRIGHT = 64
46 EMBEDDED_WINDOW_BOTTOMRIGHT = 128
47 EMBEDDED_WINDOW_ALL = EMBEDDED_WINDOW_TOP | EMBEDDED_WINDOW_BOTTOM | EMBEDDED_WINDOW_LEFT | EMBEDDED_WINDOW_RIGHT | \
48 EMBEDDED_WINDOW_TOPLEFT | EMBEDDED_WINDOW_BOTTOMLEFT | EMBEDDED_WINDOW_TOPRIGHT | EMBEDDED_WINDOW_BOTTOMRIGHT
49
50 SAVEALL_ID = wx.NewId()
51
52 WINDOW_MENU_NUM_ITEMS = 9
53
54
55 class DocFrameMixIn:
56 """
57 Class with common code used by DocMDIParentFrame, DocTabbedParentFrame, and
58 DocSDIFrame.
59 """
60
61
62 def GetDocumentManager(self):
63 """
64 Returns the document manager associated with the DocMDIParentFrame.
65 """
66 return self._docManager
67
68
69 def InitializePrintData(self):
70 """
71 Initializes the PrintData that is used when printing.
72 """
73 self._printData = wx.PrintData()
74 self._printData.SetPaperId(wx.PAPER_LETTER)
75
76
77 def CreateDefaultMenuBar(self, sdi=False):
78 """
79 Creates the default MenuBar. Contains File, Edit, View, Tools, and Help menus.
80 """
81 menuBar = wx.MenuBar()
82
83 fileMenu = wx.Menu()
84 fileMenu.Append(wx.ID_NEW, _("&New...\tCtrl+N"), _("Creates a new document"))
85 fileMenu.Append(wx.ID_OPEN, _("&Open...\tCtrl+O"), _("Opens an existing document"))
86 fileMenu.Append(wx.ID_CLOSE, _("&Close"), _("Closes the active document"))
87 if not sdi:
88 fileMenu.Append(wx.ID_CLOSE_ALL, _("Close A&ll"), _("Closes all open documents"))
89 fileMenu.AppendSeparator()
90 fileMenu.Append(wx.ID_SAVE, _("&Save\tCtrl+S"), _("Saves the active document"))
91 fileMenu.Append(wx.ID_SAVEAS, _("Save &As..."), _("Saves the active document with a new name"))
92 fileMenu.Append(SAVEALL_ID, _("Save All\tCtrl+Shift+A"), _("Saves the all active documents"))
93 wx.EVT_MENU(self, SAVEALL_ID, self.ProcessEvent)
94 wx.EVT_UPDATE_UI(self, SAVEALL_ID, self.ProcessUpdateUIEvent)
95 fileMenu.AppendSeparator()
96 fileMenu.Append(wx.ID_PRINT, _("&Print\tCtrl+P"), _("Prints the active document"))
97 fileMenu.Append(wx.ID_PREVIEW, _("Print Pre&view"), _("Displays full pages"))
98 fileMenu.Append(wx.ID_PRINT_SETUP, _("Page Set&up"), _("Changes page layout settings"))
99 fileMenu.AppendSeparator()
100 if wx.Platform == '__WXMAC__':
101 fileMenu.Append(wx.ID_EXIT, _("&Quit"), _("Closes this program"))
102 else:
103 fileMenu.Append(wx.ID_EXIT, _("E&xit"), _("Closes this program"))
104 self._docManager.FileHistoryUseMenu(fileMenu)
105 self._docManager.FileHistoryAddFilesToMenu()
106 menuBar.Append(fileMenu, _("&File"));
107
108 editMenu = wx.Menu()
109 editMenu.Append(wx.ID_UNDO, _("&Undo\tCtrl+Z"), _("Reverses the last action"))
110 editMenu.Append(wx.ID_REDO, _("&Redo\tCtrl+Y"), _("Reverses the last undo"))
111 editMenu.AppendSeparator()
112 #item = wxMenuItem(self.editMenu, wxID_CUT, _("Cu&t\tCtrl+X"), _("Cuts the selection and puts it on the Clipboard"))
113 #item.SetBitmap(getCutBitmap())
114 #editMenu.AppendItem(item)
115 editMenu.Append(wx.ID_CUT, _("Cu&t\tCtrl+X"), _("Cuts the selection and puts it on the Clipboard"))
116 wx.EVT_MENU(self, wx.ID_CUT, self.ProcessEvent)
117 wx.EVT_UPDATE_UI(self, wx.ID_CUT, self.ProcessUpdateUIEvent)
118 editMenu.Append(wx.ID_COPY, _("&Copy\tCtrl+C"), _("Copies the selection and puts it on the Clipboard"))
119 wx.EVT_MENU(self, wx.ID_COPY, self.ProcessEvent)
120 wx.EVT_UPDATE_UI(self, wx.ID_COPY, self.ProcessUpdateUIEvent)
121 editMenu.Append(wx.ID_PASTE, _("&Paste\tCtrl+V"), _("Inserts Clipboard contents"))
122 wx.EVT_MENU(self, wx.ID_PASTE, self.ProcessEvent)
123 wx.EVT_UPDATE_UI(self, wx.ID_PASTE, self.ProcessUpdateUIEvent)
124 editMenu.Append(wx.ID_CLEAR, _("Cle&ar"), _("Erases the selection"))
125 wx.EVT_MENU(self, wx.ID_CLEAR, self.ProcessEvent)
126 wx.EVT_UPDATE_UI(self, wx.ID_CLEAR, self.ProcessUpdateUIEvent)
127 editMenu.AppendSeparator()
128 editMenu.Append(wx.ID_SELECTALL, _("Select A&ll\tCtrl+A"), _("Selects all available data"))
129 wx.EVT_MENU(self, wx.ID_SELECTALL, self.ProcessEvent)
130 wx.EVT_UPDATE_UI(self, wx.ID_SELECTALL, self.ProcessUpdateUIEvent)
131 menuBar.Append(editMenu, _("&Edit"))
132 if sdi:
133 if self.GetDocument() and self.GetDocument().GetCommandProcessor():
134 self.GetDocument().GetCommandProcessor().SetEditMenu(editMenu)
135
136 viewMenu = wx.Menu()
137 viewMenu.AppendCheckItem(VIEW_TOOLBAR_ID, _("&Toolbar"), _("Shows or hides the toolbar"))
138 wx.EVT_MENU(self, VIEW_TOOLBAR_ID, self.OnViewToolBar)
139 wx.EVT_UPDATE_UI(self, VIEW_TOOLBAR_ID, self.OnUpdateViewToolBar)
140 viewMenu.AppendCheckItem(VIEW_STATUSBAR_ID, _("&Status Bar"), _("Shows or hides the status bar"))
141 wx.EVT_MENU(self, VIEW_STATUSBAR_ID, self.OnViewStatusBar)
142 wx.EVT_UPDATE_UI(self, VIEW_STATUSBAR_ID, self.OnUpdateViewStatusBar)
143 menuBar.Append(viewMenu, _("&View"))
144
145 helpMenu = wx.Menu()
146 helpMenu.Append(wx.ID_ABOUT, _("&About" + " " + wx.GetApp().GetAppName()), _("Displays program information, version number, and copyright"))
147 wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
148 menuBar.Append(helpMenu, _("&Help"))
149
150 wx.EVT_UPDATE_UI(self, wx.ID_ABOUT, self.ProcessUpdateUIEvent) # Using ID_ABOUT to update the window menu, the window menu items are not triggering
151
152 if sdi: # TODO: Is this really needed?
153 wx.EVT_COMMAND_FIND_CLOSE(self, -1, self.ProcessEvent)
154
155 return menuBar
156
157
158 def CreateDefaultStatusBar(self):
159 """
160 Creates the default StatusBar.
161 """
162 wx.Frame.CreateStatusBar(self)
163 self.GetStatusBar().Show(wx.ConfigBase_Get().ReadInt("ViewStatusBar", True))
164 self.UpdateStatus()
165 return self.GetStatusBar()
166
167
168 def CreateDefaultToolBar(self):
169 """
170 Creates the default ToolBar.
171 """
172 self._toolBar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT)
173 self._toolBar.AddSimpleTool(wx.ID_NEW, getNewBitmap(), _("New"), _("Creates a new document"))
174 self._toolBar.AddSimpleTool(wx.ID_OPEN, getOpenBitmap(), _("Open"), _("Opens an existing document"))
175 self._toolBar.AddSimpleTool(wx.ID_SAVE, getSaveBitmap(), _("Save"), _("Saves the active document"))
176 self._toolBar.AddSimpleTool(SAVEALL_ID, getSaveAllBitmap(), _("Save All"), _("Saves all the active documents"))
177 self._toolBar.AddSeparator()
178 self._toolBar.AddSimpleTool(wx.ID_PRINT, getPrintBitmap(), _("Print"), _("Displays full pages"))
179 self._toolBar.AddSimpleTool(wx.ID_PREVIEW, getPrintPreviewBitmap(), _("Print Preview"), _("Prints the active document"))
180 self._toolBar.AddSeparator()
181 self._toolBar.AddSimpleTool(wx.ID_CUT, getCutBitmap(), _("Cut"), _("Cuts the selection and puts it on the Clipboard"))
182 self._toolBar.AddSimpleTool(wx.ID_COPY, getCopyBitmap(), _("Copy"), _("Copies the selection and puts it on the Clipboard"))
183 self._toolBar.AddSimpleTool(wx.ID_PASTE, getPasteBitmap(), _("Paste"), _("Inserts Clipboard contents"))
184 self._toolBar.AddSimpleTool(wx.ID_UNDO, getUndoBitmap(), _("Undo"), _("Reverses the last action"))
185 self._toolBar.AddSimpleTool(wx.ID_REDO, getRedoBitmap(), _("Redo"), _("Reverses the last undo"))
186 self._toolBar.Realize()
187 self._toolBar.Show(wx.ConfigBase_Get().ReadInt("ViewToolBar", True))
188
189 return self._toolBar
190
191
192 def OnFileSaveAll(self, event):
193 """
194 Saves all of the currently open documents.
195 """
196 docs = wx.GetApp().GetDocumentManager().GetDocuments()
197 for doc in docs:
198 doc.Save()
199
200
201 def OnAbout(self, event):
202 """
203 Invokes the about dialog.
204 """
205 aboutService = wx.GetApp().GetService(AboutService)
206 if aboutService:
207 aboutService.ShowAbout()
208
209
210 def OnViewToolBar(self, event):
211 """
212 Toggles whether the ToolBar is visible.
213 """
214 self._toolBar.Show(not self._toolBar.IsShown())
215 self._LayoutFrame()
216
217
218 def OnUpdateViewToolBar(self, event):
219 """
220 Updates the View ToolBar menu item.
221 """
222 event.Check(self.GetToolBar().IsShown())
223
224
225 def OnViewStatusBar(self, event):
226 """
227 Toggles whether the StatusBar is visible.
228 """
229 self.GetStatusBar().Show(not self.GetStatusBar().IsShown())
230 self._LayoutFrame()
231
232
233 def OnUpdateViewStatusBar(self, event):
234 """
235 Updates the View StatusBar menu item.
236 """
237 event.Check(self.GetStatusBar().IsShown())
238
239
240 def UpdateStatus(self, message = _("Ready")):
241 """
242 Updates the StatusBar.
243 """
244 # wxBug: Menubar and toolbar help strings don't pop the status text back
245 if self.GetStatusBar().GetStatusText() != message:
246 self.GetStatusBar().PushStatusText(message)
247
248
249 class DocMDIParentFrameMixIn:
250 """
251 Class with common code used by DocMDIParentFrame and DocTabbedParentFrame.
252 """
253
254
255 def _GetPosSizeFromConfig(self, pos, size):
256 """
257 Adjusts the position and size of the frame using the saved config position and size.
258 """
259 config = wx.ConfigBase_Get()
260 if pos == wx.DefaultPosition and size == wx.DefaultSize and config.ReadInt("MDIFrameMaximized", False):
261 pos = [0, 0]
262 size = wx.DisplaySize()
263 # wxBug: Need to set to fill screen to get around bug where maximize is leaving shadow of statusbar, check out maximize call at end of this function
264 else:
265 if pos == wx.DefaultPosition:
266 pos = config.ReadInt("MDIFrameXLoc", -1), config.ReadInt("MDIFrameYLoc", -1)
267
268 if wx.Display_GetFromPoint(pos) == -1: # Check if the frame position is offscreen
269 pos = wx.DefaultPosition
270
271 if size == wx.DefaultSize:
272 size = wx.Size(config.ReadInt("MDIFrameXSize", 450), config.ReadInt("MDIFrameYSize", 300))
273 return pos, size
274
275
276 def _InitFrame(self, embeddedWindows):
277 """
278 Initializes the frame and creates the default menubar, toolbar, and status bar.
279 """
280 self._embeddedWindows = []
281 self.SetDropTarget(_DocFrameFileDropTarget(self._docManager, self))
282
283 if wx.GetApp().GetDefaultIcon():
284 self.SetIcon(wx.GetApp().GetDefaultIcon())
285
286 wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
287 wx.EVT_SIZE(self, self.OnSize)
288
289 self.InitializePrintData()
290
291 toolBar = self.CreateDefaultToolBar()
292 self.SetToolBar(toolBar)
293 menuBar = self.CreateDefaultMenuBar()
294 statusBar = self.CreateDefaultStatusBar()
295
296 config = wx.ConfigBase_Get()
297 if config.ReadInt("MDIFrameMaximized", False):
298 # wxBug: On maximize, statusbar leaves a residual that needs to be refereshed, happens even when user does it
299 self.Maximize()
300
301 self.CreateEmbeddedWindows(embeddedWindows)
302 self._LayoutFrame()
303
304 wx.GetApp().SetTopWindow(self) # Need to do this here in case the services are looking for wx.GetApp().GetTopWindow()
305 for service in wx.GetApp().GetServices():
306 service.InstallControls(self, menuBar = menuBar, toolBar = toolBar, statusBar = statusBar)
307 if hasattr(service, "ShowWindow"):
308 service.ShowWindow() # instantiate service windows for correct positioning, we'll hide/show them later based on user preference
309
310 self.SetMenuBar(menuBar) # wxBug: Have to set the menubar at the very end or the automatic MDI "window" menu doesn't get put in the right place when the services add new menus to the menubar
311
312
313 def ProcessEvent(self, event):
314 """
315 Processes an event, searching event tables and calling zero or more
316 suitable event handler function(s). Note that the ProcessEvent
317 method is called from the wxPython docview framework directly since
318 wxPython does not have a virtual ProcessEvent function.
319 """
320 id = event.GetId()
321 if id == SAVEALL_ID:
322 self.OnFileSaveAll(event)
323 return True
324
325 return wx.GetApp().ProcessEvent(event)
326
327
328 def ProcessUpdateUIEvent(self, event):
329 """
330 Processes a UI event, searching event tables and calling zero or more
331 suitable event handler function(s). Note that the ProcessEvent
332 method is called from the wxPython docview framework directly since
333 wxPython does not have a virtual ProcessEvent function.
334 """
335 id = event.GetId()
336 if id == wx.ID_CUT:
337 event.Enable(False)
338 return True
339 elif id == wx.ID_COPY:
340 event.Enable(False)
341 return True
342 elif id == wx.ID_PASTE:
343 event.Enable(False)
344 return True
345 elif id == wx.ID_CLEAR:
346 event.Enable(False)
347 return True
348 elif id == wx.ID_SELECTALL:
349 event.Enable(False)
350 return True
351 elif id == SAVEALL_ID:
352 filesModified = False
353 docs = wx.GetApp().GetDocumentManager().GetDocuments()
354 for doc in docs:
355 if doc.IsModified():
356 filesModified = True
357 break
358
359 event.Enable(filesModified)
360 return True
361 else:
362 return wx.GetApp().ProcessUpdateUIEvent(event)
363
364
365 def CreateEmbeddedWindows(self, windows = 0):
366 """
367 Create the specified embedded windows around the edges of the frame.
368 """
369 frameSize = self.GetSize() # TODO: GetClientWindow.GetSize is still returning 0,0 since the frame isn't fully constructed yet, so using full frame size
370 defaultHSize = int(frameSize[0] / 6)
371 defaultVSize = int(frameSize[1] / 7)
372 defaultSubVSize = int(frameSize[1] / 2)
373 config = wx.ConfigBase_Get()
374 if windows & (EMBEDDED_WINDOW_LEFT | EMBEDDED_WINDOW_TOPLEFT | EMBEDDED_WINDOW_BOTTOMLEFT):
375 self._leftEmbWindow = self._CreateEmbeddedWindow(self, (config.ReadInt("MDIEmbedLeftSize", defaultHSize), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_LEFT, visible = config.ReadInt("MDIEmbedLeftVisible", 1), sash = wx.SASH_RIGHT)
376 else:
377 self._leftEmbWindow = None
378 if windows & EMBEDDED_WINDOW_TOPLEFT:
379 self._topLeftEmbWindow = self._CreateEmbeddedWindow(self._leftEmbWindow, (-1, config.ReadInt("MDIEmbedTopLeftSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopLeftVisible", 1), sash = wx.SASH_BOTTOM)
380 else:
381 self._topLeftEmbWindow = None
382 if windows & EMBEDDED_WINDOW_BOTTOMLEFT:
383 self._bottomLeftEmbWindow = self._CreateEmbeddedWindow(self._leftEmbWindow, (-1, config.ReadInt("MDIEmbedBottomLeftSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomLeftVisible", 1))
384 else:
385 self._bottomLeftEmbWindow = None
386 if windows & (EMBEDDED_WINDOW_RIGHT | EMBEDDED_WINDOW_TOPRIGHT | EMBEDDED_WINDOW_BOTTOMRIGHT):
387 self._rightEmbWindow = self._CreateEmbeddedWindow(self, (config.ReadInt("MDIEmbedRightSize", defaultHSize), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_RIGHT, visible = config.ReadInt("MDIEmbedRightVisible", 1), sash = wx.SASH_LEFT)
388 else:
389 self._rightEmbWindow = None
390 if windows & EMBEDDED_WINDOW_TOPRIGHT:
391 self._topRightEmbWindow = self._CreateEmbeddedWindow(self._rightEmbWindow, (-1, config.ReadInt("MDIEmbedTopRightSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopRightVisible", 1), sash = wx.SASH_BOTTOM)
392 else:
393 self._topRightEmbWindow = None
394 if windows & EMBEDDED_WINDOW_BOTTOMRIGHT:
395 self._bottomRightEmbWindow = self._CreateEmbeddedWindow(self._rightEmbWindow, (-1, config.ReadInt("MDIEmbedBottomRightSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomRightVisible", 1))
396 else:
397 self._bottomRightEmbWindow = None
398 if windows & EMBEDDED_WINDOW_TOP:
399 self._topEmbWindow = self._CreateEmbeddedWindow(self, (-1, config.ReadInt("MDIEmbedTopSize", defaultVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopVisible", 1), sash = wx.SASH_BOTTOM)
400 else:
401 self._topEmbWindow = None
402 if windows & EMBEDDED_WINDOW_BOTTOM:
403 self._bottomEmbWindow = self._CreateEmbeddedWindow(self, (-1, config.ReadInt("MDIEmbedBottomSize", defaultVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomVisible", 1), sash = wx.SASH_TOP)
404 else:
405 self._bottomEmbWindow = None
406
407
408 def SaveEmbeddedWindowSizes(self):
409 """
410 Saves the sizes of the embedded windows.
411 """
412 config = wx.ConfigBase_Get()
413 if not self.IsMaximized():
414 config.WriteInt("MDIFrameXLoc", self.GetPositionTuple()[0])
415 config.WriteInt("MDIFrameYLoc", self.GetPositionTuple()[1])
416 config.WriteInt("MDIFrameXSize", self.GetSizeTuple()[0])
417 config.WriteInt("MDIFrameYSize", self.GetSizeTuple()[1])
418 config.WriteInt("MDIFrameMaximized", self.IsMaximized())
419 config.WriteInt("ViewToolBar", self._toolBar.IsShown())
420 config.WriteInt("ViewStatusBar", self.GetStatusBar().IsShown())
421
422 if self._leftEmbWindow:
423 config.WriteInt("MDIEmbedLeftSize", self._leftEmbWindow.GetSize()[0])
424 config.WriteInt("MDIEmbedLeftVisible", self._leftEmbWindow.IsShown())
425 if self._topLeftEmbWindow:
426 if self._topLeftEmbWindow._sizeBeforeHidden:
427 size = self._topLeftEmbWindow._sizeBeforeHidden[1]
428 else:
429 size = self._topLeftEmbWindow.GetSize()[1]
430 config.WriteInt("MDIEmbedTopLeftSize", size)
431 config.WriteInt("MDIEmbedTopLeftVisible", self._topLeftEmbWindow.IsShown())
432 if self._bottomLeftEmbWindow:
433 if self._bottomLeftEmbWindow._sizeBeforeHidden:
434 size = self._bottomLeftEmbWindow._sizeBeforeHidden[1]
435 else:
436 size = self._bottomLeftEmbWindow.GetSize()[1]
437 config.WriteInt("MDIEmbedBottomLeftSize", size)
438 config.WriteInt("MDIEmbedBottomLeftVisible", self._bottomLeftEmbWindow.IsShown())
439 if self._rightEmbWindow:
440 config.WriteInt("MDIEmbedRightSize", self._rightEmbWindow.GetSize()[0])
441 config.WriteInt("MDIEmbedRightVisible", self._rightEmbWindow.IsShown())
442 if self._topRightEmbWindow:
443 if self._topRightEmbWindow._sizeBeforeHidden:
444 size = self._topRightEmbWindow._sizeBeforeHidden[1]
445 else:
446 size = self._topRightEmbWindow.GetSize()[1]
447 config.WriteInt("MDIEmbedTopRightSize", size)
448 config.WriteInt("MDIEmbedTopRightVisible", self._topRightEmbWindow.IsShown())
449 if self._bottomRightEmbWindow:
450 if self._bottomRightEmbWindow._sizeBeforeHidden:
451 size = self._bottomRightEmbWindow._sizeBeforeHidden[1]
452 else:
453 size = self._bottomRightEmbWindow.GetSize()[1]
454 config.WriteInt("MDIEmbedBottomRightSize", size)
455 config.WriteInt("MDIEmbedBottomRightVisible", self._bottomRightEmbWindow.IsShown())
456 if self._topEmbWindow:
457 config.WriteInt("MDIEmbedTopSize", self._topEmbWindow.GetSize()[1])
458 config.WriteInt("MDIEmbedTopVisible", self._topEmbWindow.IsShown())
459 if self._bottomEmbWindow:
460 config.WriteInt("MDIEmbedBottomSize", self._bottomEmbWindow.GetSize()[1])
461 config.WriteInt("MDIEmbedBottomVisible", self._bottomEmbWindow.IsShown())
462
463
464 def GetEmbeddedWindow(self, loc):
465 """
466 Returns the instance of the embedded window specified by the embedded window location constant.
467 """
468 if loc == EMBEDDED_WINDOW_TOP:
469 return self._topEmbWindow
470 elif loc == EMBEDDED_WINDOW_BOTTOM:
471 return self._bottomEmbWindow
472 elif loc == EMBEDDED_WINDOW_LEFT:
473 return self._leftEmbWindow
474 elif loc == EMBEDDED_WINDOW_RIGHT:
475 return self._rightEmbWindow
476 elif loc == EMBEDDED_WINDOW_TOPLEFT:
477 return self._topLeftEmbWindow
478 elif loc == EMBEDDED_WINDOW_BOTTOMLEFT:
479 return self._bottomLeftEmbWindow
480 elif loc == EMBEDDED_WINDOW_TOPRIGHT:
481 return self._topRightEmbWindow
482 elif loc == EMBEDDED_WINDOW_BOTTOMRIGHT:
483 return self._bottomRightEmbWindow
484 return None
485
486
487 def _CreateEmbeddedWindow(self, parent, size, orientation, alignment, visible = True, sash = None):
488 """
489 Creates the embedded window with the specified size, orientation, and alignment. If the
490 window is not visible it will retain the size with which it was last viewed.
491 """
492 window = wx.SashLayoutWindow(parent, wx.NewId(), style = wx.NO_BORDER | wx.SW_3D)
493 window.SetDefaultSize(size)
494 window.SetOrientation(orientation)
495 window.SetAlignment(alignment)
496 if sash != None: # wx.SASH_TOP is 0 so check for None instead of just doing "if sash:"
497 window.SetSashVisible(sash, True)
498 ####
499 def OnEmbeddedWindowSashDrag(event):
500 if event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE:
501 return
502 sashWindow = event.GetEventObject()
503 if sashWindow.GetAlignment() == wx.LAYOUT_TOP or sashWindow.GetAlignment() == wx.LAYOUT_BOTTOM:
504 size = wx.Size(-1, event.GetDragRect().height)
505 else:
506 size = wx.Size(event.GetDragRect().width, -1)
507 event.GetEventObject().SetDefaultSize(size)
508 self._LayoutFrame()
509 sashWindow.Refresh()
510 if isinstance(sashWindow.GetParent(), wx.SashLayoutWindow):
511 sashWindow.Show()
512 parentSashWindow = sashWindow.GetParent() # Force a refresh
513 parentSashWindow.Layout()
514 parentSashWindow.Refresh()
515 parentSashWindow.SetSize((parentSashWindow.GetSize().width + 1, parentSashWindow.GetSize().height + 1))
516 ####
517 wx.EVT_SASH_DRAGGED(window, window.GetId(), OnEmbeddedWindowSashDrag)
518 window._sizeBeforeHidden = None
519 if not visible:
520 window.Show(False)
521 if isinstance(parent, wx.SashLayoutWindow): # It's a window embedded in another sash window so remember its actual size to show it again
522 window._sizeBeforeHidden = size
523 return window
524
525
526 def ShowEmbeddedWindow(self, window, show = True):
527 """
528 Shows or hides the embedded window specified by the embedded window location constant.
529 """
530 window.Show(show)
531 if isinstance(window.GetParent(), wx.SashLayoutWindow): # It is a parent sashwindow with multiple embedded sashwindows
532 parentSashWindow = window.GetParent()
533 if show: # Make sure it is visible in case all of the subwindows were hidden
534 parentSashWindow.Show()
535 if show and window._sizeBeforeHidden:
536 if window._sizeBeforeHidden[1] == parentSashWindow.GetClientSize()[1]:
537 if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).IsShown():
538 window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).GetSize()[1]))
539 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).IsShown():
540 window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).GetSize()[1]))
541 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).IsShown():
542 window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).GetSize()[1]))
543 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).IsShown():
544 window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).GetSize()[1]))
545 else:
546 window.SetDefaultSize(window._sizeBeforeHidden)
547 # If it is not the size of the full parent sashwindow set the other window's size so that if it gets shown it will have a cooresponding size
548 if window._sizeBeforeHidden[1] < parentSashWindow.GetClientSize()[1]:
549 otherWindowSize = (-1, parentSashWindow.GetClientSize()[1] - window._sizeBeforeHidden[1])
550 if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT):
551 self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).SetDefaultSize(otherWindowSize)
552 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT):
553 self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).SetDefaultSize(otherWindowSize)
554 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT):
555 self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).SetDefaultSize(otherWindowSize)
556 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT):
557 self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).SetDefaultSize(otherWindowSize)
558
559 if not show:
560 if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).IsShown() \
561 or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).IsShown() \
562 or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).IsShown() \
563 or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).IsShown():
564 parentSashWindow.Hide() # Hide the parent sashwindow if all of the children are hidden
565 parentSashWindow.Layout() # Force a refresh
566 parentSashWindow.Refresh()
567 parentSashWindow.SetSize((parentSashWindow.GetSize().width + 1, parentSashWindow.GetSize().height + 1))
568 self._LayoutFrame()
569
570
571 def HideEmbeddedWindow(self):
572 """
573 Hides the embedded window specified by the embedded window location constant.
574 """
575 self.ShowEmbeddedWindow(show = False)
576
577
578 class DocTabbedChildFrame(wx.Panel):
579 """
580 The wxDocMDIChildFrame class provides a default frame for displaying
581 documents on separate windows. This class can only be used for MDI child
582 frames.
583
584 The class is part of the document/view framework supported by wxWindows,
585 and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
586 classes.
587 """
588
589
590 def __init__(self, doc, view, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"):
591 """
592 Constructor. Note that the event table must be rebuilt for the
593 frame since the EvtHandler is not virtual.
594 """
595 wx.Panel.__init__(self, frame.GetNotebook(), id)
596 self._childDocument = doc
597 self._childView = view
598 frame.AddNotebookPage(self, doc.GetPrintableName())
599 if view:
600 view.SetFrame(self)
601
602
603 def GetIcon(self):
604 """
605 Dummy method since the icon of tabbed frames are managed by the notebook.
606 """
607 return None
608
609
610 def SetIcon(self, icon):
611 """
612 Dummy method since the icon of tabbed frames are managed by the notebook.
613 """
614 pass
615
616
617 def Destroy(self):
618 """
619 Removes the current notebook page.
620 """
621 wx.GetApp().GetTopWindow().RemoveNotebookPage(self)
622
623
624 def SetFocus(self):
625 """
626 Activates the current notebook page.
627 """
628 wx.GetApp().GetTopWindow().ActivateNotebookPage(self)
629
630
631 def Activate(self): # Need this in case there are embedded sash windows and such, OnActivate is not getting called
632 """
633 Activates the current view.
634 """
635 # Called by Project Editor
636 if self._childView:
637 self._childView.Activate(True)
638
639
640 def GetTitle(self):
641 """
642 Returns the frame's title.
643 """
644 wx.GetApp().GetTopWindow().GetNotebookPageTitle(self)
645
646
647 def SetTitle(self, title):
648 """
649 Sets the frame's title.
650 """
651 wx.GetApp().GetTopWindow().SetNotebookPageTitle(self, title)
652
653
654 def ProcessEvent(event):
655 """
656 Processes an event, searching event tables and calling zero or more
657 suitable event handler function(s). Note that the ProcessEvent
658 method is called from the wxPython docview framework directly since
659 wxPython does not have a virtual ProcessEvent function.
660 """
661 if not self._childView or not self._childView.ProcessEvent(event):
662 if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
663 return False
664 else:
665 return True
666 else:
667 return True
668
669
670 def GetDocument(self):
671 """
672 Returns the document associated with this frame.
673 """
674 return self._childDocument
675
676
677 def SetDocument(self, document):
678 """
679 Sets the document for this frame.
680 """
681 self._childDocument = document
682
683
684 def GetView(self):
685 """
686 Returns the view associated with this frame.
687 """
688 return self._childView
689
690
691 def SetView(self, view):
692 """
693 Sets the view for this frame.
694 """
695 self._childView = view
696
697
698 class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
699 """
700 The DocTabbedParentFrame class provides a default top-level frame for
701 applications using the document/view framework. This class can only be
702 used for MDI parent frames that use a tabbed interface.
703
704 It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
705 classes.
706 """
707
708
709 def __init__(self, docManager, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "DocTabbedParentFrame", embeddedWindows = 0):
710 """
711 Constructor. Note that the event table must be rebuilt for the
712 frame since the EvtHandler is not virtual.
713 """
714 pos, size = self._GetPosSizeFromConfig(pos, size)
715 wx.Frame.__init__(self, frame, id, title, pos, size, style, name)
716
717 # From docview.MDIParentFrame
718 self._docManager = docManager
719
720 wx.EVT_CLOSE(self, self.OnCloseWindow)
721
722 wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
723 wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
724
725 wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
726 wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
727 wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
728 wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
729 wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
730 wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
731 wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
732 wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
733 wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
734 wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
735 wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
736 wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
737 wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
738
739 wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
740 wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
741 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
742 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
743 wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
744 wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
745 wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
746 wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
747 wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
748 wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
749 wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
750 wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
751 # End From docview.MDIParentFrame
752
753 self.CreateNotebook()
754 self._InitFrame(embeddedWindows)
755
756
757 def _LayoutFrame(self):
758 """
759 Lays out the frame.
760 """
761 wx.LayoutAlgorithm().LayoutFrame(self, self._notebook)
762
763
764 def CreateNotebook(self):
765 """
766 Creates the notebook to use for the tabbed document interface.
767 """
768 self._notebook = wx.Notebook(self, wx.NewId())
769 # self._notebook.SetSizer(wx.NotebookSizer(self._notebook))
770 wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
771 wx.EVT_RIGHT_DOWN(self._notebook, self.OnNotebookRightClick)
772
773 templates = wx.GetApp().GetDocumentManager().GetTemplates()
774 iconList = wx.ImageList(16, 16, initialCount = len(templates))
775 self._iconIndexLookup = []
776 for template in templates:
777 icon = template.GetIcon()
778 if icon:
779 if icon.GetHeight() != 16:
780 icon.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
781 if icon.GetWidth() != 16:
782 icon.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
783 iconIndex = iconList.AddIcon(icon)
784 self._iconIndexLookup.append((template, iconIndex))
785
786 icon = getBlankIcon()
787 if icon.GetHeight() != 16:
788 icon.SetHeight(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
789 if icon.GetWidth() != 16:
790 icon.SetWidth(16) # wxBug: img2py.py uses EmptyIcon which is 32x32
791 self._blankIconIndex = iconList.AddIcon(icon)
792 self._notebook.AssignImageList(iconList)
793
794
795 def GetNotebook(self):
796 """
797 Returns the notebook used by the tabbed document interface.
798 """
799 return self._notebook
800
801
802 def GetActiveChild(self):
803 """
804 Returns the active notebook page, which to the framework is treated as
805 a document frame.
806 """
807 index = self._notebook.GetSelection()
808 if index == -1:
809 return None
810 return self._notebook.GetPage(index)
811
812
813 def OnNotebookPageChanged(self, event):
814 """
815 Activates a notebook page's view when it is selected.
816 """
817 index = self._notebook.GetSelection()
818 if index > -1:
819 self._notebook.GetPage(index).GetView().Activate()
820
821
822 def OnNotebookRightClick(self, event):
823 """
824 Handles right clicks for the notebook, enabling users to either close
825 a tab or select from the available documents if the user clicks on the
826 notebook's white space.
827 """
828 index, type = self._notebook.HitTest(event.GetPosition())
829 menu = wx.Menu()
830 x, y = event.GetX(), event.GetY()
831 if index > -1:
832 doc = self._notebook.GetPage(index).GetView().GetDocument()
833 id = wx.NewId()
834 menu.Append(id, _("Close"))
835 def OnRightMenuSelect(event):
836 doc.DeleteAllViews()
837 wx.EVT_MENU(self, id, OnRightMenuSelect)
838 if self._notebook.GetPageCount() > 1:
839 menu.AppendSeparator()
840 tabsMenu = wx.Menu()
841 menu.AppendMenu(wx.NewId(), _("Select Tab"), tabsMenu)
842 else:
843 y = y - 25 # wxBug: It is offsetting click events in the blank notebook area
844 tabsMenu = menu
845
846 if self._notebook.GetPageCount() > 1:
847 selectIDs = {}
848 for i in range(0, self._notebook.GetPageCount()):
849 id = wx.NewId()
850 selectIDs[id] = i
851 tabsMenu.Append(id, self._notebook.GetPageText(i))
852 def OnRightMenuSelect(event):
853 self._notebook.SetSelection(selectIDs[event.GetId()])
854 wx.EVT_MENU(self, id, OnRightMenuSelect)
855
856 self._notebook.PopupMenu(menu, wx.Point(x, y))
857 menu.Destroy()
858
859
860 def AddNotebookPage(self, panel, title):
861 """
862 Adds a document page to the notebook.
863 """
864 self._notebook.AddPage(panel, title)
865 index = self._notebook.GetPageCount() - 1
866 self._notebook.SetSelection(index)
867
868 found = False # Now set the icon
869 template = panel.GetDocument().GetDocumentTemplate()
870 if template:
871 for t, iconIndex in self._iconIndexLookup:
872 if t is template:
873 self._notebook.SetPageImage(index, iconIndex)
874 found = True
875 break
876 if not found:
877 self._notebook.SetPageImage(index, self._blankIconIndex)
878 self._notebook.Layout()
879
880
881 def RemoveNotebookPage(self, panel):
882 """
883 Removes a document page from the notebook.
884 """
885 index = self.GetNotebookPageIndex(panel)
886 if index > -1:
887 self._notebook.DeletePage(index)
888
889
890 def ActivateNotebookPage(self, panel):
891 """
892 Sets the notebook to the specified panel.
893 """
894 index = self.GetNotebookPageIndex(panel)
895 if index > -1:
896 self._notebook.SetSelection(index)
897
898
899 def GetNotebookPageTitle(self, panel):
900 self._notebook.GetPageText(self.GetNotebookPageIndex(panel))
901
902
903 def SetNotebookPageTitle(self, panel, title):
904 self._notebook.SetPageText(self.GetNotebookPageIndex(panel), title)
905
906
907 def GetNotebookPageIndex(self, panel):
908 """
909 Returns the index of particular notebook panel.
910 """
911 index = -1
912 for i in range(self._notebook.GetPageCount()):
913 if self._notebook.GetPage(i) == panel:
914 index = i
915 break
916 return index
917
918
919 def ProcessEvent(self, event):
920 """
921 Processes an event, searching event tables and calling zero or more
922 suitable event handler function(s). Note that the ProcessEvent
923 method is called from the wxPython docview framework directly since
924 wxPython does not have a virtual ProcessEvent function.
925 """
926 if wx.GetApp().ProcessEventBeforeWindows(event):
927 return True
928 if self._docManager and self._docManager.ProcessEvent(event):
929 return True
930 return DocMDIParentFrameMixIn.ProcessEvent(self, event)
931
932
933 def ProcessUpdateUIEvent(self, event):
934 """
935 Processes a UI event, searching event tables and calling zero or more
936 suitable event handler function(s). Note that the ProcessEvent
937 method is called from the wxPython docview framework directly since
938 wxPython does not have a virtual ProcessEvent function.
939 """
940 if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
941 return True
942 if self._docManager and self._docManager.ProcessUpdateUIEvent(event):
943 return True
944 return DocMDIParentFrameMixIn.ProcessUpdateUIEvent(self, event)
945
946
947 def OnExit(self, event):
948 """
949 Called when File/Exit is chosen and closes the window.
950 """
951 self.Close()
952
953
954 def OnMRUFile(self, event):
955 """
956 Opens the appropriate file when it is selected from the file history
957 menu.
958 """
959 n = event.GetId() - wx.ID_FILE1
960 filename = self._docManager.GetHistoryFile(n)
961 if filename:
962 self._docManager.CreateDocument(filename, wx.lib.docview.DOC_SILENT)
963 else:
964 self._docManager.RemoveFileFromHistory(n)
965 msgTitle = wx.GetApp().GetAppName()
966 if not msgTitle:
967 msgTitle = _("File Error")
968 wx.MessageBox("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list" % FileNameFromPath(file),
969 msgTitle,
970 wx.OK | wx.ICON_EXCLAMATION,
971 self)
972
973
974 def OnSize(self, event):
975 """
976 Called when the frame is resized and lays out the client window.
977 """
978 # Needed in case there are splitpanels around the mdi frame
979 self._LayoutFrame()
980
981
982 def OnCloseWindow(self, event):
983 """
984 Called when the frame is closed. Remembers the frame size.
985 """
986 self.SaveEmbeddedWindowSizes()
987
988 # save and close services last
989 for service in wx.GetApp().GetServices():
990 if not service.OnCloseFrame(event):
991 return
992
993 # From docview.MDIParentFrame
994 if self._docManager.Clear(not event.CanVeto()):
995 self.Destroy()
996 else:
997 event.Veto()
998
999
1000 class DocMDIChildFrame(wx.MDIChildFrame):
1001 """
1002 The wxDocMDIChildFrame class provides a default frame for displaying
1003 documents on separate windows. This class can only be used for MDI child
1004 frames.
1005
1006 The class is part of the document/view framework supported by wxWindows,
1007 and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
1008 classes.
1009 """
1010
1011
1012 def __init__(self, doc, view, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "frame"):
1013 """
1014 Constructor. Note that the event table must be rebuilt for the
1015 frame since the EvtHandler is not virtual.
1016 """
1017 wx.MDIChildFrame.__init__(self, frame, id, title, pos, size, style, name)
1018 self._childDocument = doc
1019 self._childView = view
1020 if view:
1021 view.SetFrame(self)
1022 # self.Create(doc, view, frame, id, title, pos, size, style, name)
1023 self._activeEvent = None
1024 self._activated = 0
1025 wx.EVT_ACTIVATE(self, self.OnActivate)
1026 wx.EVT_CLOSE(self, self.OnCloseWindow)
1027
1028 if frame: # wxBug: For some reason the EVT_ACTIVATE event is not getting triggered for the first mdi client window that is opened so we have to do it manually
1029 mdiChildren = filter(lambda x: isinstance(x, wx.MDIChildFrame), frame.GetChildren())
1030 if len(mdiChildren) == 1:
1031 self.Activate()
1032
1033
1034 ## # Couldn't get this to work, but seems to work fine with single stage construction
1035 ## def Create(self, doc, view, frame, id, title, pos, size, style, name):
1036 ## self._childDocument = doc
1037 ## self._childView = view
1038 ## if wx.MDIChildFrame.Create(self, frame, id, title, pos, size, style, name):
1039 ## if view:
1040 ## view.SetFrame(self)
1041 ## return True
1042 ## return False
1043
1044
1045
1046 def Activate(self): # Need this in case there are embedded sash windows and such, OnActivate is not getting called
1047 """
1048 Activates the current view.
1049 """
1050 if self._childView:
1051 self._childView.Activate(True)
1052
1053
1054 def ProcessEvent(event):
1055 """
1056 Processes an event, searching event tables and calling zero or more
1057 suitable event handler function(s). Note that the ProcessEvent
1058 method is called from the wxPython docview framework directly since
1059 wxPython does not have a virtual ProcessEvent function.
1060 """
1061 if self._activeEvent == event:
1062 return False
1063
1064 self._activeEvent = event # Break recursion loops
1065
1066 if self._childView:
1067 self._childView.Activate(True)
1068
1069 if not self._childView or not self._childView.ProcessEvent(event):
1070 if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
1071 ret = False
1072 else:
1073 ret = True
1074 else:
1075 ret = True
1076
1077 self._activeEvent = None
1078 return ret
1079
1080
1081 def OnActivate(self, event):
1082 """
1083 Sets the currently active view to be the frame's view. You may need to
1084 override (but still call) this function in order to set the keyboard
1085 focus for your subwindow.
1086 """
1087 if self._activated != 0:
1088 return True
1089 self._activated += 1
1090 wx.MDIChildFrame.Activate(self)
1091 if event.GetActive() and self._childView:
1092 self._childView.Activate(event.GetActive())
1093 self._activated = 0
1094
1095
1096 def OnCloseWindow(self, event):
1097 """
1098 Closes and deletes the current view and document.
1099 """
1100 if self._childView:
1101 ans = False
1102 if not event.CanVeto():
1103 ans = True
1104 else:
1105 ans = self._childView.Close(deleteWindow = False)
1106
1107 if ans:
1108 self._childView.Activate(False)
1109 self._childView.Destroy()
1110 self._childView = None
1111 if self._childDocument:
1112 self._childDocument.Destroy() # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
1113 self._childDocument = None
1114 self.Destroy()
1115 else:
1116 event.Veto()
1117 else:
1118 event.Veto()
1119
1120
1121 def GetDocument(self):
1122 """
1123 Returns the document associated with this frame.
1124 """
1125 return self._childDocument
1126
1127
1128 def SetDocument(self, document):
1129 """
1130 Sets the document for this frame.
1131 """
1132 self._childDocument = document
1133
1134
1135 def GetView(self):
1136 """
1137 Returns the view associated with this frame.
1138 """
1139 return self._childView
1140
1141
1142 def SetView(self, view):
1143 """
1144 Sets the view for this frame.
1145 """
1146 self._childView = view
1147
1148
1149
1150
1151
1152 class DocService(wx.EvtHandler):
1153 """
1154 An abstract class used to add reusable services to a docview application.
1155 """
1156
1157
1158 def __init__(self):
1159 """Initializes the DocService."""
1160 pass
1161
1162
1163 def GetDocumentManager(self):
1164 """Returns the DocManager for the docview application."""
1165 return self._docManager
1166
1167
1168 def SetDocumentManager(self, docManager):
1169 """Sets the DocManager for the docview application."""
1170 self._docManager = docManager
1171
1172
1173 def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
1174 """Called to install controls into the menubar and toolbar of a SDI or MDI window. Override this method for a particular service."""
1175 pass
1176
1177
1178 def ProcessEventBeforeWindows(self, event):
1179 """
1180 Processes an event before the main window has a chance to process the window.
1181 Override this method for a particular service.
1182 """
1183 return False
1184
1185
1186 def ProcessUpdateUIEventBeforeWindows(self, event):
1187 """
1188 Processes a UI event before the main window has a chance to process the window.
1189 Override this method for a particular service.
1190 """
1191 return False
1192
1193
1194 def ProcessEvent(self, event):
1195 """
1196 Processes an event, searching event tables and calling zero or more
1197 suitable event handler function(s). Note that the ProcessEvent
1198 method is called from the wxPython docview framework directly since
1199 wxPython does not have a virtual ProcessEvent function.
1200 """
1201 return False
1202
1203
1204 def ProcessUpdateUIEvent(self, event):
1205 """
1206 Processes a UI event, searching event tables and calling zero or more
1207 suitable event handler function(s). Note that the ProcessEvent
1208 method is called from the wxPython docview framework directly since
1209 wxPython does not have a virtual ProcessEvent function.
1210 """
1211 return False
1212
1213
1214 def OnCloseFrame(self, event):
1215 """
1216 Called when the a docview frame is being closed. Override this method
1217 so a service can either do cleanup or veto the frame being closed by
1218 returning false.
1219 """
1220 return True
1221
1222
1223 def OnExit(self):
1224 """
1225 Called when the the docview application is being closed. Override this method
1226 so a service can either do cleanup or veto the frame being closed by
1227 returning false.
1228 """
1229 pass
1230
1231
1232 def GetMenuItemPos(self, menu, id):
1233 """
1234 Utility method used to find the position of a menu item so that services can
1235 easily find where to insert a menu item in InstallControls.
1236 """
1237 menuItems = menu.GetMenuItems()
1238 for i, menuItem in enumerate(menuItems):
1239 if menuItem.GetId() == id:
1240 return i
1241 return i
1242
1243
1244 def GetView(self):
1245 """
1246 Called by WindowMenuService to get views for services that don't
1247 have dedicated documents such as the Outline Service.
1248 """
1249 return None
1250
1251
1252 class DocOptionsService(DocService):
1253 """
1254 A service that implements an options menu item and an options dialog with
1255 notebook tabs. New tabs can be added by other services by calling the
1256 "AddOptionsPanel" method.
1257 """
1258
1259
1260 def __init__(self, showGeneralOptions=True, allowModeChanges=True):
1261 """
1262 Initializes the options service with the option of suppressing the default
1263 general options pane that is included with the options service by setting
1264 showGeneralOptions to False. It allowModeChanges is set to False, the
1265 default general options pane will allow users to change the document
1266 interface mode between SDI and MDI modes.
1267 """
1268 DocService.__init__(self)
1269 self.ClearOptionsPanels()
1270 self._allowModeChanges = allowModeChanges
1271 self._toolOptionsID = wx.NewId()
1272 if showGeneralOptions:
1273 self.AddOptionsPanel(GeneralOptionsPanel)
1274
1275
1276 def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
1277 """
1278 Installs a "Tools" menu with an "Options" menu item.
1279 """
1280 toolsMenuIndex = menuBar.FindMenu(_("&Tools"))
1281 if toolsMenuIndex > -1:
1282 toolsMenu = menuBar.GetMenu(toolsMenuIndex)
1283 else:
1284 toolsMenu = wx.Menu()
1285 if toolsMenuIndex == -1:
1286 formatMenuIndex = menuBar.FindMenu(_("&Format"))
1287 menuBar.Insert(formatMenuIndex + 1, toolsMenu, _("&Tools"))
1288 if toolsMenu:
1289 if toolsMenu.GetMenuItemCount():
1290 toolsMenu.AppendSeparator()
1291 toolsMenu.Append(self._toolOptionsID, _("&Options..."), _("Sets options"))
1292 wx.EVT_MENU(frame, self._toolOptionsID, frame.ProcessEvent)
1293
1294
1295 def ProcessEvent(self, event):
1296 """
1297 Checks to see if the "Options" menu item has been selected.
1298 """
1299 id = event.GetId()
1300 if id == self._toolOptionsID:
1301 self.OnOptions(event)
1302 return True
1303 else:
1304 return False
1305
1306
1307 def GetAllowModeChanges(self):
1308 """
1309 Return true if the default general options pane should allow users to
1310 change the document interface mode between SDI and MDI modes.
1311 """
1312 return self._allowModeChanges
1313
1314
1315 def SetAllowModeChanges(self, allowModeChanges):
1316 """
1317 Set to true if the default general options pane should allow users to
1318 change the document interface mode between SDI and MDI modes.
1319 """
1320 self._allowModeChanges = allowModeChanges
1321
1322
1323 def ClearOptionsPanels(self):
1324 """
1325 Clears all of the options panels that have been added into the
1326 options dialog.
1327 """
1328 self._optionsPanels = []
1329
1330
1331 def AddOptionsPanel(self, optionsPanel):
1332 """
1333 Adds an options panel to the options dialog.
1334 """
1335 self._optionsPanels.append(optionsPanel)
1336
1337
1338 def OnOptions(self, event):
1339 """
1340 Shows the options dialog, called when the "Options" menu item is selected.
1341 """
1342 if len(self._optionsPanels) == 0:
1343 return
1344 optionsDialog = OptionsDialog(wx.GetApp().GetTopWindow(), self._optionsPanels, self._docManager)
1345 if optionsDialog.ShowModal() == wx.ID_OK:
1346 optionsDialog.OnOK(optionsDialog) # wxBug: wxDialog should be calling this automatically but doesn't
1347 optionsDialog.Destroy()
1348
1349
1350 class OptionsDialog(wx.Dialog):
1351 """
1352 A default options dialog used by the OptionsService that hosts a notebook
1353 tab of options panels.
1354 """
1355
1356
1357 def __init__(self, parent, optionsPanelClasses, docManager):
1358 """
1359 Initializes the options dialog with a notebook page that contains new
1360 instances of the passed optionsPanelClasses.
1361 """
1362 wx.Dialog.__init__(self, parent, -1, _("Options"), size = (310, 400))
1363
1364 self._optionsPanels = []
1365 self._docManager = docManager
1366
1367 HALF_SPACE = 5
1368 SPACE = 10
1369
1370 sizer = wx.BoxSizer(wx.VERTICAL)
1371
1372 optionsNotebook = wx.Notebook(self, -1, size = (310, 375))
1373 sizer.Add(optionsNotebook, 0, wx.ALL | wx.EXPAND, SPACE)
1374 for optionsPanelClass in optionsPanelClasses:
1375 optionsPanel = optionsPanelClass(optionsNotebook, -1)
1376 self._optionsPanels.append(optionsPanel)
1377 sizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
1378 self.SetSizer(sizer)
1379 self.Layout()
1380 self.Fit()
1381 wx.CallAfter(self.DoRefresh)
1382
1383
1384 def DoRefresh(self):
1385 """
1386 wxBug: On Windows XP when using a multiline notebook the default page doesn't get
1387 drawn, but it works when using a single line notebook.
1388 """
1389 self.Refresh()
1390
1391
1392 def GetDocManager(self):
1393 """
1394 Returns the document manager passed to the OptionsDialog constructor.
1395 """
1396 return self._docManager
1397
1398
1399 def OnOK(self, event):
1400 """
1401 Calls the OnOK method of all of the OptionDialog's embedded panels
1402 """
1403 for optionsPanel in self._optionsPanels:
1404 optionsPanel.OnOK(event)
1405
1406
1407 class GeneralOptionsPanel(wx.Panel):
1408 """
1409 A general options panel that is used in the OptionDialog to configure the
1410 generic properties of a pydocview application, such as "show tips at startup"
1411 and whether to use SDI or MDI for the application.
1412 """
1413
1414
1415 def __init__(self, parent, id):
1416 """
1417 Initializes the panel by adding an "Options" folder tab to the parent notebook and
1418 populating the panel with the generic properties of a pydocview application.
1419 """
1420 wx.Panel.__init__(self, parent, id)
1421 SPACE = 10
1422 HALF_SPACE = 5
1423 config = wx.ConfigBase_Get()
1424 self._showTipsCheckBox = wx.CheckBox(self, -1, _("Show tips at start up"))
1425 self._showTipsCheckBox.SetValue(config.ReadInt("ShowTipAtStartup", True))
1426 if wx.GetApp().GetService(DocOptionsService).GetAllowModeChanges():
1427 choices = [_("Show each document in its own window"), _("Show all documents in a single window with tabs")]
1428 if wx.Platform == "__WXMSW__":
1429 choices.append(_("Show all documents in a single window with child windows"))
1430 self._documentRadioBox = wx.RadioBox(self, -1, _("Document Interface"),
1431 choices = choices,
1432 majorDimension=1,
1433 )
1434 if config.ReadInt("UseWinMDI", False):
1435 self._documentRadioBox.SetSelection(2)
1436 elif config.ReadInt("UseMDI", True):
1437 self._documentRadioBox.SetSelection(1)
1438 else:
1439 self._documentRadioBox.SetSelection(0)
1440 def OnDocumentInterfaceSelect(event):
1441 if not self._documentInterfaceMessageShown:
1442 msgTitle = wx.GetApp().GetAppName()
1443 if not msgTitle:
1444 msgTitle = _("Document Options")
1445 wx.MessageBox("Document interface changes will not appear until the application is restarted.",
1446 msgTitle,
1447 wx.OK | wx.ICON_INFORMATION,
1448 self.GetParent())
1449 self._documentInterfaceMessageShown = True
1450 wx.EVT_RADIOBOX(self, self._documentRadioBox.GetId(), OnDocumentInterfaceSelect)
1451 optionsBorderSizer = wx.BoxSizer(wx.VERTICAL)
1452 optionsSizer = wx.BoxSizer(wx.VERTICAL)
1453 if wx.GetApp().GetService(DocOptionsService).GetAllowModeChanges():
1454 optionsSizer.Add(self._documentRadioBox, 0, wx.ALL, HALF_SPACE)
1455 optionsSizer.Add(self._showTipsCheckBox, 0, wx.ALL, HALF_SPACE)
1456 optionsBorderSizer.Add(optionsSizer, 0, wx.ALL, SPACE)
1457 self.SetSizer(optionsBorderSizer)
1458 self.Layout()
1459 self._documentInterfaceMessageShown = False
1460 parent.AddPage(self, _("Options"))
1461
1462
1463 def OnOK(self, optionsDialog):
1464 """
1465 Updates the config based on the selections in the options panel.
1466 """
1467 config = wx.ConfigBase_Get()
1468 config.WriteInt("ShowTipAtStartup", self._showTipsCheckBox.GetValue())
1469 if wx.GetApp().GetService(DocOptionsService).GetAllowModeChanges():
1470 config.WriteInt("UseMDI", (self._documentRadioBox.GetSelection() == 1))
1471 config.WriteInt("UseWinMDI", (self._documentRadioBox.GetSelection() == 2))
1472
1473
1474 class DocApp(wx.PySimpleApp):
1475 """
1476 The DocApp class serves as the base class for pydocview applications and offers
1477 functionality such as services, creation of SDI and MDI frames, show tips,
1478 and a splash screen.
1479 """
1480
1481
1482 def OnInit(self):
1483 """
1484 Initializes the DocApp.
1485 """
1486 self._services = []
1487 self._defaultIcon = None
1488 self._registeredCloseEvent = False
1489 self._useTabbedMDI = True
1490
1491 if not hasattr(self, "_debug"): # only set if not already initialized
1492 self._debug = False
1493 if not hasattr(self, "_singleInstance"): # only set if not already initialized
1494 self._singleInstance = True
1495
1496 # if _singleInstance is TRUE only allow one single instance of app to run.
1497 # When user tries to run a second instance of the app, abort startup,
1498 # But if user also specifies files to open in command line, send message to running app to open those files
1499 if self._singleInstance:
1500 # create shared memory temporary file
1501 if wx.Platform == '__WXMSW__':
1502 tfile = tempfile.TemporaryFile(prefix="ag", suffix="tmp")
1503 fno = tfile.fileno()
1504 self._sharedMemory = mmap.mmap(fno, 1024, "shared_memory")
1505 else:
1506 tfile = file(os.path.join(tempfile.gettempdir(), tempfile.gettempprefix() + self.GetAppName() + '-' + wx.GetUserId() + "AGSharedMemory"), 'w+b')
1507 tfile.write("*")
1508 tfile.seek(1024)
1509 tfile.write(" ")
1510 tfile.flush()
1511 fno = tfile.fileno()
1512 self._sharedMemory = mmap.mmap(fno, 1024)
1513
1514 self._singleInstanceChecker = wx.SingleInstanceChecker(self.GetAppName() + '-' + wx.GetUserId(), tempfile.gettempdir())
1515 if self._singleInstanceChecker.IsAnotherRunning():
1516 # have running single instance open file arguments
1517 data = pickle.dumps(sys.argv[1:])
1518 while 1:
1519 self._sharedMemory.seek(0)
1520 marker = self._sharedMemory.read_byte()
1521 if marker == '\0' or marker == '*': # available buffer
1522 self._sharedMemory.seek(0)
1523 self._sharedMemory.write_byte('-') # set writing marker
1524 self._sharedMemory.write(data) # write files we tried to open to shared memory
1525 self._sharedMemory.seek(0)
1526 self._sharedMemory.write_byte('+') # set finished writing marker
1527 self._sharedMemory.flush()
1528 break
1529 else:
1530 time.sleep(1) # give enough time for buffer to be available
1531
1532 return False
1533 else:
1534 self._timer = wx.PyTimer(self.DoBackgroundListenAndLoad)
1535 self._timer.Start(250)
1536
1537 return True
1538
1539
1540 def OpenMainFrame(self):
1541 docManager = self.GetDocumentManager()
1542 if docManager.GetFlags() & wx.lib.docview.DOC_MDI:
1543 if self.GetUseTabbedMDI():
1544 frame = wx.lib.pydocview.DocTabbedParentFrame(docManager, None, -1, self.GetAppName())
1545 else:
1546 frame = wx.lib.pydocview.DocMDIParentFrame(docManager, None, -1, self.GetAppName())
1547 frame.Show(True)
1548
1549
1550 def DoBackgroundListenAndLoad(self):
1551 """
1552 Open any files specified in the given command line argument passed in via shared memory
1553 """
1554 self._timer.Stop()
1555
1556 self._sharedMemory.seek(0)
1557 if self._sharedMemory.read_byte() == '+': # available data
1558 data = self._sharedMemory.read(1024-1)
1559 self._sharedMemory.seek(0)
1560 self._sharedMemory.write_byte("*") # finished reading, set buffer free marker
1561 self._sharedMemory.flush()
1562 args = pickle.loads(data)
1563 for arg in args:
1564 if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg):
1565 self.GetDocumentManager().CreateDocument(arg, wx.lib.docview.DOC_SILENT)
1566
1567 # force display of running app
1568 topWindow = wx.GetApp().GetTopWindow()
1569 if topWindow.IsIconized():
1570 topWindow.Iconize(False)
1571 else:
1572 topWindow.Raise()
1573
1574
1575 self._timer.Start(1000) # 1 second interval
1576
1577
1578 def OpenCommandLineArgs(self):
1579 """
1580 Called to open files that have been passed to the application from the
1581 command line.
1582 """
1583 args = sys.argv[1:]
1584 for arg in args:
1585 if arg[0] != '/' and arg[0] != '-' and os.path.exists(arg):
1586 self.GetDocumentManager().CreateDocument(arg, wx.lib.docview.DOC_SILENT)
1587
1588
1589 def GetDocumentManager(self):
1590 """
1591 Returns the document manager associated to the DocApp.
1592 """
1593 return self._docManager
1594
1595
1596 def SetDocumentManager(self, docManager):
1597 """
1598 Sets the document manager associated with the DocApp and loads the
1599 DocApp's file history into the document manager.
1600 """
1601 self._docManager = docManager
1602 config = wx.ConfigBase_Get()
1603 self.GetDocumentManager().FileHistoryLoad(config)
1604
1605
1606 def ProcessEventBeforeWindows(self, event):
1607 """
1608 Enables services to process an event before the main window has a chance to
1609 process the window.
1610 """
1611 for service in self._services:
1612 if service.ProcessEventBeforeWindows(event):
1613 return True
1614 return False
1615
1616
1617 def ProcessUpdateUIEventBeforeWindows(self, event):
1618 """
1619 Enables services to process a UI event before the main window has a chance
1620 to process the window.
1621 """
1622 for service in self._services:
1623 if service.ProcessUpdateUIEventBeforeWindows(event):
1624 return True
1625 return False
1626
1627
1628 def ProcessEvent(self, event):
1629 """
1630 Processes an event, searching event tables and calling zero or more
1631 suitable event handler function(s). Note that the ProcessEvent
1632 method is called from the wxPython docview framework directly since
1633 wxPython does not have a virtual ProcessEvent function.
1634 """
1635 for service in self._services:
1636 if service.ProcessEvent(event):
1637 return True
1638 return False
1639
1640
1641 def ProcessUpdateUIEvent(self, event):
1642 """
1643 Processes a UI event, searching event tables and calling zero or more
1644 suitable event handler function(s). Note that the ProcessEvent
1645 method is called from the wxPython docview framework directly since
1646 wxPython does not have a virtual ProcessEvent function.
1647 """
1648 for service in self._services:
1649 if service.ProcessUpdateUIEvent(event):
1650 return True
1651 return False
1652
1653
1654 def InstallService(self, service):
1655 """
1656 Installs an instance of a DocService into the DocApp.
1657 """
1658 service.SetDocumentManager(self._docManager)
1659 self._services.append(service)
1660 return service
1661
1662
1663 def GetServices(self):
1664 """
1665 Returns the DocService instances that have been installed into the DocApp.
1666 """
1667 return self._services
1668
1669
1670 def GetService(self, type):
1671 """
1672 Returns the instance of a particular type of service that has been installed
1673 into the DocApp. For example, "wx.GetApp().GetService(pydocview.OptionsService)"
1674 returns the isntance of the OptionsService that is running within the DocApp.
1675 """
1676 for service in self._services:
1677 if isinstance(service, type):
1678 return service
1679 return None
1680
1681
1682 def OnExit(self):
1683 """
1684 Called when the DocApp is exited, enables the installed DocServices to exit
1685 and saves the DocManager's file history.
1686 """
1687 for service in self._services:
1688 service.OnExit()
1689 config = wx.ConfigBase_Get()
1690 self._docManager.FileHistorySave(config)
1691
1692 if hasattr(self, "_singleInstanceChecker"):
1693 del self._singleInstanceChecker
1694
1695
1696 def GetDefaultDocManagerFlags(self):
1697 """
1698 Returns the default flags to use when creating the DocManager.
1699 """
1700 config = wx.ConfigBase_Get()
1701 if config.ReadInt("UseMDI", True) or config.ReadInt("UseWinMDI", False):
1702 flags = wx.lib.docview.DOC_MDI | wx.lib.docview.DOC_OPEN_ONCE
1703 if config.ReadInt("UseWinMDI", False):
1704 self.SetUseTabbedMDI(False)
1705 else:
1706 flags = wx.lib.docview.DOC_SDI | wx.lib.docview.DOC_OPEN_ONCE
1707 return flags
1708
1709
1710 def ShowTip(self, frame, tipProvider):
1711 """
1712 Shows the tip window, generally this is called when an application starts.
1713 A wx.TipProvider must be passed.
1714 """
1715 config = wx.ConfigBase_Get()
1716 showTip = config.ReadInt("ShowTipAtStartup", 1)
1717 if showTip:
1718 index = config.ReadInt("TipIndex", 0)
1719 showTipResult = wx.ShowTip(wx.GetApp().GetTopWindow(), tipProvider, showAtStartup = showTip)
1720 if showTipResult != showTip:
1721 config.WriteInt("ShowTipAtStartup", showTipResult)
1722
1723
1724 def GetEditMenu(self, frame):
1725 """
1726 Utility method that finds the Edit menu within the menubar of a frame.
1727 """
1728 menuBar = frame.GetMenuBar()
1729 if not menuBar:
1730 return None
1731 editMenuIndex = menuBar.FindMenu(_("&Edit"))
1732 if editMenuIndex == -1:
1733 return None
1734 return menuBar.GetMenu(editMenuIndex)
1735
1736
1737 def GetUseTabbedMDI(self):
1738 """
1739 Returns True if Windows MDI should use folder tabs instead of child windows.
1740 """
1741 return self._useTabbedMDI
1742
1743
1744 def SetUseTabbedMDI(self, useTabbedMDI):
1745 """
1746 Set to True if Windows MDI should use folder tabs instead of child windows.
1747 """
1748 self._useTabbedMDI = useTabbedMDI
1749
1750
1751 def CreateDocumentFrame(self, view, doc, flags, id = -1, title = "", pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
1752 """
1753 Called by the DocManager to create and return a new Frame for a Document.
1754 Chooses whether to create an MDIChildFrame or SDI Frame based on the
1755 DocManager's flags.
1756 """
1757 docflags = self.GetDocumentManager().GetFlags()
1758 if docflags & wx.lib.docview.DOC_SDI:
1759 frame = self.CreateSDIDocumentFrame(doc, view, id, title, pos, size, style)
1760 frame.Show()
1761
1762 # wxBug: operating system bug, first window is set to the position of last window closed, ignoring passed in position on frame creation
1763 # also, initial size is incorrect for the same reasons
1764 if frame.GetPosition() != pos:
1765 frame.Move(pos)
1766 if frame.GetSize() != size:
1767 frame.SetSize(size)
1768
1769 if doc and doc.GetCommandProcessor():
1770 doc.GetCommandProcessor().SetEditMenu(self.GetEditMenu(frame))
1771 elif docflags & wx.lib.docview.DOC_MDI:
1772 if self.GetUseTabbedMDI():
1773 frame = self.CreateTabbedDocumentFrame(doc, view, id, title, pos, size, style)
1774 else:
1775 frame = self.CreateMDIDocumentFrame(doc, view, id, title, pos, size, style)
1776 if doc:
1777 if doc.GetDocumentTemplate().GetIcon():
1778 frame.SetIcon(doc.GetDocumentTemplate().GetIcon())
1779 elif wx.GetApp().GetTopWindow().GetIcon():
1780 frame.SetIcon(wx.GetApp().GetTopWindow().GetIcon())
1781 if doc and doc.GetCommandProcessor():
1782 doc.GetCommandProcessor().SetEditMenu(self.GetEditMenu(wx.GetApp().GetTopWindow()))
1783 if not frame.GetIcon() and self._defaultIcon:
1784 frame.SetIcon(self.GetDefaultIcon())
1785 view.SetFrame(frame)
1786 return frame
1787
1788
1789 def CreateSDIDocumentFrame(self, doc, view, id = -1, title = "", pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
1790 """
1791 Creates and returns an SDI Document Frame.
1792 """
1793 frame = DocSDIFrame(doc, view, None, id, title, pos, size, style)
1794 return frame
1795
1796
1797 def CreateTabbedDocumentFrame(self, doc, view, id = -1, title = "", pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
1798 """
1799 Creates and returns an MDI Document Frame for a Tabbed MDI view
1800 """
1801 frame = DocTabbedChildFrame(doc, view, wx.GetApp().GetTopWindow(), id, title, pos, size, style)
1802 return frame
1803
1804
1805 def CreateMDIDocumentFrame(self, doc, view, id = -1, title = "", pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
1806 """
1807 Creates and returns an MDI Document Frame.
1808 """
1809 # if any child windows are maximized, then user must want any new children maximized
1810 # if no children exist, then use the default value from registry
1811 # wxBug: Only current window is maximized, so need to check every child frame
1812 parentFrame = wx.GetApp().GetTopWindow()
1813 childrenMaximized = filter(lambda child: isinstance(child, wx.MDIChildFrame) and child.IsMaximized(), parentFrame.GetChildren())
1814 if childrenMaximized:
1815 maximize = True
1816 else:
1817 children = filter(lambda child: isinstance(child, wx.MDIChildFrame), parentFrame.GetChildren())
1818 if children:
1819 # other windows exist and none are maximized
1820 maximize = False
1821 else:
1822 # get default setting from registry
1823 maximize = wx.ConfigBase_Get().ReadInt("MDIChildFrameMaximized", False)
1824
1825 frame = wx.lib.docview.DocMDIChildFrame(doc, view, wx.GetApp().GetTopWindow(), id, title, pos, size, style)
1826 if maximize: # wxBug: Should already be maximizing new child frames if one is maximized but it's not so we have to force it to
1827 frame.Maximize(True)
1828
1829 ## wx.EVT_MAXIMIZE(frame, self.OnMaximize) # wxBug: This doesn't work, need to save MDIChildFrameMaximized state on close of windows instead
1830 wx.EVT_CLOSE(frame, self.OnCloseChildWindow)
1831 if not self._registeredCloseEvent:
1832 wx.EVT_CLOSE(parentFrame, self.OnCloseMainWindow) # need to check on this, but only once
1833 self._registeredCloseEvent = True
1834
1835 return frame
1836
1837
1838 def SaveMDIDocumentFrameMaximizedState(self, maximized):
1839 """
1840 Remember in the config whether the MDI Frame is maximized so that it can be restored
1841 on open.
1842 """
1843 config = wx.ConfigBase_Get()
1844 maximizeFlag = config.ReadInt("MDIChildFrameMaximized", False)
1845 if maximized != maximizeFlag:
1846 config.WriteInt("MDIChildFrameMaximized", maximized)
1847
1848
1849 def OnCloseChildWindow(self, event):
1850 """
1851 Called when an MDI Child Frame is closed. Calls SaveMDIDocumentFrameMaximizedState to
1852 remember whether the MDI Frame is maximized so that it can be restored on open.
1853 """
1854 self.SaveMDIDocumentFrameMaximizedState(event.GetEventObject().IsMaximized())
1855 event.Skip()
1856
1857
1858 def OnCloseMainWindow(self, event):
1859 """
1860 Called when the MDI Parent Frame is closed. Remembers whether the MDI Parent Frame is
1861 maximized.
1862 """
1863 children = event.GetEventObject().GetChildren()
1864 childrenMaximized = filter(lambda child: isinstance(child, wx.MDIChildFrame)and child.IsMaximized(), children)
1865 if childrenMaximized:
1866 self.SaveMDIDocumentFrameMaximizedState(True)
1867 else:
1868 childrenNotMaximized = filter(lambda child: isinstance(child, wx.MDIChildFrame), children)
1869
1870 if childrenNotMaximized:
1871 # other windows exist and none are maximized
1872 self.SaveMDIDocumentFrameMaximizedState(False)
1873
1874 event.Skip()
1875
1876
1877 def GetDefaultIcon(self):
1878 """
1879 Returns the application's default icon.
1880 """
1881 return self._defaultIcon
1882
1883
1884 def SetDefaultIcon(self, icon):
1885 """
1886 Sets the application's default icon.
1887 """
1888 self._defaultIcon = icon
1889
1890
1891 def GetDebug(self):
1892 """
1893 Returns True if the application is in debug mode.
1894 """
1895 return self._debug
1896
1897
1898 def SetDebug(self, debug):
1899 """
1900 Sets the application's debug mode.
1901 """
1902 self._debug = debug
1903
1904
1905 def GetSingleInstance(self):
1906 """
1907 Returns True if the application is in single instance mode. Used to determine if multiple instances of the application is allowed to launch.
1908 """
1909 return self._singleInstance
1910
1911
1912 def SetSingleInstance(self, singleInstance):
1913 """
1914 Sets application's single instance mode.
1915 """
1916 self._singleInstance = singleInstance
1917
1918
1919
1920 def CreateChildDocument(self, parentDocument, documentType, objectToEdit, path = ''):
1921 """
1922 Creates a child window of a document that edits an object. The child window
1923 is managed by the parent document frame, so it will be prompted to close if its
1924 parent is closed, etc. Child Documents are useful when there are complicated
1925 Views of a Document and users will need to tunnel into the View.
1926 """
1927 for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1928 if isinstance(document, ChildDocument) and document.GetParentDocument() == parentDocument:
1929 if document.GetData() == objectToEdit:
1930 if hasattr(document.GetFirstView().GetFrame(), "SetFocus"):
1931 document.GetFirstView().GetFrame().SetFocus()
1932 return document
1933 for temp in wx.GetApp().GetDocumentManager().GetTemplates():
1934 if temp.GetDocumentType() == documentType:
1935 break
1936 temp = None
1937 newDoc = temp.CreateDocument(path, 0, data = objectToEdit, parentDocument = parentDocument)
1938 newDoc.SetDocumentName(temp.GetDocumentName())
1939 newDoc.SetDocumentTemplate(temp)
1940 if path == '':
1941 newDoc.OnNewDocument()
1942 else:
1943 if not newDoc.OnOpenDocument(path):
1944 newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews
1945 return None
1946 return newDoc
1947
1948
1949 def CloseChildDocuments(self, parentDocument):
1950 """
1951 Closes the child windows of a Document.
1952 """
1953 for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
1954 if isinstance(document, ChildDocument) and document.GetParentDocument() == parentDocument:
1955 if document.GetFirstView().GetFrame():
1956 document.GetFirstView().GetFrame().SetFocus()
1957 if document.GetFirstView().OnClose(deleteWindow = False):
1958 if document.GetFirstView().GetFrame():
1959 document.GetFirstView().GetFrame().Close() # wxBug: Need to do this for some random reason
1960 else:
1961 return False
1962 return True
1963
1964
1965 def IsMDI(self):
1966 """
1967 Returns True if the application is in MDI mode.
1968 """
1969 return self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_MDI
1970
1971
1972 def IsSDI(self):
1973 """
1974 Returns True if the application is in SDI mode.
1975 """
1976 return self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI
1977
1978
1979 def ShowSplash(self, image):
1980 """
1981 Shows a splash window with the given image. Input parameter 'image' can either be a wx.Bitmap or a filename.
1982 """
1983 if isinstance(image, wx.Bitmap):
1984 splash_bmp = image
1985 else:
1986 splash_bmp = wx.Image(image).ConvertToBitmap()
1987 self._splash = wx.SplashScreen(splash_bmp,wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_NO_TIMEOUT,0, None, -1)
1988 self._splash.Show()
1989
1990
1991 def CloseSplash(self):
1992 """
1993 Closes the splash window.
1994 """
1995 if self._splash:
1996 self._splash.Close(True)
1997
1998
1999 class _DocFrameFileDropTarget(wx.FileDropTarget):
2000 """
2001 Class used to handle drops into the document frame.
2002 """
2003
2004 def __init__(self, docManager, docFrame):
2005 """
2006 Initializes the FileDropTarget class with the active docManager and the docFrame.
2007 """
2008 wx.FileDropTarget.__init__(self)
2009 self._docManager = docManager
2010 self._docFrame = docFrame
2011
2012
2013 def OnDropFiles(self, x, y, filenames):
2014 """
2015 Called when files are dropped in the drop target and tells the docManager to open
2016 the files.
2017 """
2018 try:
2019 for file in filenames:
2020 self._docManager.CreateDocument(file, wx.lib.docview.DOC_SILENT)
2021 except:
2022 msgTitle = wx.GetApp().GetAppName()
2023 if not msgTitle:
2024 msgTitle = _("File Error")
2025 wx.MessageBox("Could not open '%s'. '%s'" % (docview.FileNameFromPath(file), sys.exc_value),
2026 msgTitle,
2027 wx.OK | wx.ICON_EXCLAMATION,
2028 self._docManager.FindSuitableParent())
2029
2030
2031 class DocMDIParentFrame(wx.lib.docview.DocMDIParentFrame, DocFrameMixIn, DocMDIParentFrameMixIn):
2032 """
2033 The DocMDIParentFrame is the primary frame which the DocApp uses to host MDI child windows. It offers
2034 features such as a default menubar, toolbar, and status bar, and a mechanism to manage embedded windows
2035 on the edges of the DocMDIParentFrame.
2036 """
2037
2038
2039 def __init__(self, docManager, parent, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "DocMDIFrame", embeddedWindows = 0):
2040 """
2041 Initializes the DocMDIParentFrame with the default menubar, toolbar, and status bar. Use the
2042 optional embeddedWindows parameter with the embedded window constants to create embedded
2043 windows around the edges of the DocMDIParentFrame.
2044 """
2045 pos, size = self._GetPosSizeFromConfig(pos, size)
2046 wx.lib.docview.DocMDIParentFrame.__init__(self, docManager, parent, id, title, pos, size, style, name)
2047 self._InitFrame(embeddedWindows)
2048
2049
2050 def _LayoutFrame(self):
2051 """
2052 Lays out the frame.
2053 """
2054 wx.LayoutAlgorithm().LayoutMDIFrame(self)
2055 self.GetClientWindow().Refresh()
2056
2057
2058 def ProcessEvent(self, event):
2059 """
2060 Processes an event, searching event tables and calling zero or more
2061 suitable event handler function(s). Note that the ProcessEvent
2062 method is called from the wxPython docview framework directly since
2063 wxPython does not have a virtual ProcessEvent function.
2064 """
2065 if wx.GetApp().ProcessEventBeforeWindows(event):
2066 return True
2067 if wx.lib.docview.DocMDIParentFrame.ProcessEvent(self, event):
2068 return True
2069 return DocMDIParentFrameMixIn.ProcessEvent(self, event)
2070
2071
2072 def ProcessUpdateUIEvent(self, event):
2073 """
2074 Processes a UI event, searching event tables and calling zero or more
2075 suitable event handler function(s). Note that the ProcessEvent
2076 method is called from the wxPython docview framework directly since
2077 wxPython does not have a virtual ProcessEvent function.
2078 """
2079 if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
2080 return True
2081 if wx.lib.docview.DocMDIParentFrame.ProcessUpdateUIEvent(self, event): # Let the views handle the event before the services
2082 return True
2083 if event.GetId() == wx.ID_ABOUT: # Using ID_ABOUT to update the window menu, the window menu items are not triggering
2084 self.UpdateWindowMenu()
2085 return True
2086 return DocMDIParentFrameMixIn.ProcessUpdateUIEvent(self, event)
2087
2088
2089 def UpdateWindowMenu(self):
2090 """
2091 Updates the WindowMenu on Windows platforms.
2092 """
2093 if wx.Platform == '__WXMSW__':
2094 children = filter(lambda child: isinstance(child, wx.MDIChildFrame), self.GetChildren())
2095 windowCount = len(children)
2096 hasWindow = windowCount >= 1
2097 has2OrMoreWindows = windowCount >= 2
2098
2099 windowMenu = self.GetWindowMenu()
2100 if windowMenu:
2101 windowMenu.Enable(wx.IDM_WINDOWTILE, hasWindow)
2102 windowMenu.Enable(wx.IDM_WINDOWTILEHOR, hasWindow)
2103 windowMenu.Enable(wx.IDM_WINDOWCASCADE, hasWindow)
2104 windowMenu.Enable(wx.IDM_WINDOWICONS, hasWindow)
2105 windowMenu.Enable(wx.IDM_WINDOWTILEVERT, hasWindow)
2106 wx.IDM_WINDOWPREV = 4006 # wxBug: Not defined for some reason
2107 windowMenu.Enable(wx.IDM_WINDOWPREV, has2OrMoreWindows)
2108 windowMenu.Enable(wx.IDM_WINDOWNEXT, has2OrMoreWindows)
2109
2110
2111
2112 def OnSize(self, event):
2113 """
2114 Called when the DocMDIParentFrame is resized and lays out the MDI client window.
2115 """
2116 # Needed in case there are splitpanels around the mdi frame
2117 self._LayoutFrame()
2118
2119
2120 def OnCloseWindow(self, event):
2121 """
2122 Called when the DocMDIParentFrame is closed. Remembers the frame size.
2123 """
2124 self.SaveEmbeddedWindowSizes()
2125
2126 # save and close services last.
2127 for service in wx.GetApp().GetServices():
2128 if not service.OnCloseFrame(event):
2129 return
2130
2131 # save and close documents
2132 # documents with a common view, e.g. project view, should save the document, but not close the window
2133 # and let the service close the window.
2134 wx.lib.docview.DocMDIParentFrame.OnCloseWindow(self, event)
2135
2136
2137 class DocSDIFrame(wx.lib.docview.DocChildFrame, DocFrameMixIn):
2138 """
2139 The DocSDIFrame host DocManager Document windows. It offers features such as a default menubar,
2140 toolbar, and status bar.
2141 """
2142
2143
2144 def __init__(self, doc, view, parent, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "DocSDIFrame"):
2145 """
2146 Initializes the DocSDIFrame with the default menubar, toolbar, and status bar.
2147 """
2148 wx.lib.docview.DocChildFrame.__init__(self, doc, view, parent, id, title, pos, size, style, name)
2149 self._fileMenu = None
2150 if doc:
2151 self._docManager = doc.GetDocumentManager()
2152 else:
2153 self._docManager = None
2154 self.SetDropTarget(_DocFrameFileDropTarget(self._docManager, self))
2155
2156 wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
2157 wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
2158 wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
2159
2160 self.InitializePrintData()
2161
2162 menuBar = self.CreateDefaultMenuBar(sdi=True)
2163 toolBar = self.CreateDefaultToolBar()
2164 self.SetToolBar(toolBar)
2165 statusBar = self.CreateDefaultStatusBar()
2166
2167 for service in wx.GetApp().GetServices():
2168 service.InstallControls(self, menuBar = menuBar, toolBar = toolBar, statusBar = statusBar, document = doc)
2169
2170 self.SetMenuBar(menuBar) # wxBug: Need to do this in SDI to mimic MDI... because have to set the menubar at the very end or the automatic MDI "window" menu doesn't get put in the right place when the services add new menus to the menubar
2171
2172
2173 def _LayoutFrame(self):
2174 """
2175 Lays out the Frame.
2176 """
2177 self.Layout()
2178
2179
2180 def OnExit(self, event):
2181 """
2182 Called when the application is exitting.
2183 """
2184 if self._childView.GetDocumentManager().Clear(force = False):
2185 self.Destroy()
2186 else:
2187 event.Veto()
2188
2189
2190 def OnMRUFile(self, event):
2191 """
2192 Opens the appropriate file when it is selected from the file history
2193 menu.
2194 """
2195 n = event.GetId() - wx.ID_FILE1
2196 filename = self._docManager.GetHistoryFile(n)
2197 if filename:
2198 self._docManager.CreateDocument(filename, wx.lib.docview.DOC_SILENT)
2199 else:
2200 self._docManager.RemoveFileFromHistory(n)
2201 msgTitle = wx.GetApp().GetAppName()
2202 if not msgTitle:
2203 msgTitle = _("File Error")
2204 wx.MessageBox("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list" % docview.FileNameFromPath(file),
2205 msgTitle,
2206 wx.OK | wx.ICON_EXCLAMATION,
2207 self)
2208
2209
2210 def ProcessEvent(self, event):
2211 """
2212 Processes an event, searching event tables and calling zero or more
2213 suitable event handler function(s). Note that the ProcessEvent
2214 method is called from the wxPython docview framework directly since
2215 wxPython does not have a virtual ProcessEvent function.
2216 """
2217 if wx.GetApp().ProcessEventBeforeWindows(event):
2218 return True
2219 if self._childView:
2220 self._childView.Activate(True)
2221
2222 id = event.GetId()
2223 if id == SAVEALL_ID:
2224 self.OnFileSaveAll(event)
2225 return True
2226
2227 if hasattr(self._childView, "GetDocumentManager") and self._childView.GetDocumentManager().ProcessEvent(event): # Need to call docmanager here since super class relies on DocParentFrame which we are not using
2228 return True
2229 else:
2230 return wx.GetApp().ProcessEvent(event)
2231
2232
2233 def ProcessUpdateUIEvent(self, event):
2234 """
2235 Processes a UI event, searching event tables and calling zero or more
2236 suitable event handler function(s). Note that the ProcessEvent
2237 method is called from the wxPython docview framework directly since
2238 wxPython does not have a virtual ProcessEvent function.
2239 """
2240 if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
2241 return True
2242 if self._childView:
2243 if hasattr(self._childView, "GetDocumentManager"):
2244 docMgr = self._childView.GetDocumentManager()
2245 if docMgr:
2246 if docMgr.GetCurrentDocument() != self._childView.GetDocument():
2247 return False
2248 if docMgr.ProcessUpdateUIEvent(event): # Let the views handle the event before the services
2249 return True
2250 id = event.GetId()
2251 if id == wx.ID_CUT:
2252 event.Enable(False)
2253 return True
2254 elif id == wx.ID_COPY:
2255 event.Enable(False)
2256 return True
2257 elif id == wx.ID_PASTE:
2258 event.Enable(False)
2259 return True
2260 elif id == wx.ID_CLEAR:
2261 event.Enable(False)
2262 return True
2263 elif id == wx.ID_SELECTALL:
2264 event.Enable(False)
2265 return True
2266 elif id == SAVEALL_ID:
2267 filesModified = False
2268 docs = wx.GetApp().GetDocumentManager().GetDocuments()
2269 for doc in docs:
2270 if doc.IsModified():
2271 filesModified = True
2272 break
2273
2274 event.Enable(filesModified)
2275 return True
2276 else:
2277 return wx.GetApp().ProcessUpdateUIEvent(event)
2278
2279
2280 def OnCloseWindow(self, event):
2281 """
2282 Called when the window is saved. Enables services to help close the frame.
2283 """
2284 for service in wx.GetApp().GetServices():
2285 service.OnCloseFrame(event)
2286 wx.lib.docview.DocChildFrame.OnCloseWindow(self, event)
2287 if self._fileMenu and self._docManager:
2288 self._docManager.FileHistoryRemoveMenu(self._fileMenu)
2289
2290
2291 class AboutService(DocService):
2292 """
2293 About Dialog Service that installs under the Help menu to show the properties of the current application.
2294 """
2295
2296 def __init__(self, aboutDialog=None, image=None):
2297 """
2298 Initializes the AboutService.
2299 """
2300 if aboutDialog:
2301 self._dlg = aboutDialog
2302 self._image = None
2303 else:
2304 self._dlg = AboutDialog # use default AboutDialog
2305 self._image = image
2306
2307
2308 def ShowAbout(self):
2309 """
2310 Show the AboutDialog
2311 """
2312 if self._image:
2313 dlg = self._dlg(wx.GetApp().GetTopWindow(), self._image)
2314 else:
2315 dlg = self._dlg(wx.GetApp().GetTopWindow())
2316 dlg.CenterOnScreen()
2317 dlg.ShowModal()
2318 dlg.Destroy()
2319
2320
2321 def SetAboutDialog(self, dlg):
2322 """
2323 Customize the AboutDialog
2324 """
2325 self._dlg = dlg
2326
2327
2328 class AboutDialog(wx.Dialog):
2329 """
2330 Opens an AboutDialog. Shared by DocMDIParentFrame and DocSDIFrame.
2331 """
2332
2333 def __init__(self, parent, image=None):
2334 """
2335 Initializes the about dialog.
2336 """
2337 wx.Dialog.__init__(self, parent, -1, _("About ") + wx.GetApp().GetAppName(), style = wx.DEFAULT_DIALOG_STYLE)
2338
2339 sizer = wx.BoxSizer(wx.VERTICAL)
2340 if image:
2341 imageItem = wx.StaticBitmap(self, -1, image.ConvertToBitmap(), (0,0), (image.GetWidth(), image.GetHeight()))
2342 sizer.Add(imageItem, 0, wx.ALIGN_CENTER|wx.ALL, 0)
2343 sizer.Add(wx.StaticText(self, -1, wx.GetApp().GetAppName()), 0, wx.ALIGN_CENTRE|wx.ALL, 5)
2344
2345 btn = wx.Button(self, wx.ID_OK)
2346 sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
2347
2348 self.SetSizer(sizer)
2349 self.SetAutoLayout(True)
2350 sizer.Fit(self)
2351
2352
2353
2354 class FilePropertiesService(DocService):
2355 """
2356 Service that installs under the File menu to show the properties of the file associated
2357 with the current document.
2358 """
2359
2360 PROPERTIES_ID = wx.NewId()
2361
2362
2363 def __init__(self):
2364 """
2365 Initializes the PropertyService.
2366 """
2367 self._customEventHandlers = []
2368
2369
2370 def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
2371 """
2372 Installs a File/Properties menu item.
2373 """
2374 fileMenu = menuBar.GetMenu(menuBar.FindMenu(_("&File")))
2375 exitMenuItemPos = self.GetMenuItemPos(fileMenu, wx.ID_EXIT)
2376 fileMenu.InsertSeparator(exitMenuItemPos)
2377 fileMenu.Insert(exitMenuItemPos, FilePropertiesService.PROPERTIES_ID, _("&Properties"), _("Show file properties"))
2378 wx.EVT_MENU(frame, FilePropertiesService.PROPERTIES_ID, self.ProcessEvent)
2379 wx.EVT_UPDATE_UI(frame, FilePropertiesService.PROPERTIES_ID, self.ProcessUpdateUIEvent)
2380
2381
2382 def ProcessEvent(self, event):
2383 """
2384 Detects when the File/Properties menu item is selected.
2385 """
2386 id = event.GetId()
2387 if id == FilePropertiesService.PROPERTIES_ID:
2388 for eventHandler in self._customEventHandlers:
2389 if eventHandler.ProcessEvent(event):
2390 return True
2391
2392 self.ShowPropertiesDialog()
2393 return True
2394 else:
2395 return False
2396
2397
2398 def ProcessUpdateUIEvent(self, event):
2399 """
2400 Updates the File/Properties menu item.
2401 """
2402 id = event.GetId()
2403 if id == FilePropertiesService.PROPERTIES_ID:
2404 for eventHandler in self._customEventHandlers:
2405 if eventHandler.ProcessUpdateUIEvent(event):
2406 return True
2407
2408 event.Enable(wx.GetApp().GetDocumentManager().GetCurrentDocument() != None)
2409 return True
2410 else:
2411 return False
2412
2413
2414 def ShowPropertiesDialog(self, filename = None):
2415 """
2416 Shows the PropertiesDialog for the specified file.
2417 """
2418 if not filename:
2419 filename = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
2420
2421 filePropertiesDialog = FilePropertiesDialog(wx.GetApp().GetTopWindow(), filename)
2422 if filePropertiesDialog.ShowModal() == wx.ID_OK:
2423 pass # Handle OK
2424 filePropertiesDialog.Destroy()
2425
2426
2427 def GetCustomEventHandlers(self):
2428 """
2429 Returns the custom event handlers for the PropertyService.
2430 """
2431 return self._customEventHandlers
2432
2433
2434 def AddCustomEventHandler(self, handler):
2435 """
2436 Adds a custom event handlers for the PropertyService. A custom event handler enables
2437 a different dialog to be provided for a particular file.
2438 """
2439 self._customEventHandlers.append(handler)
2440
2441
2442 def RemoveCustomEventHandler(self, handler):
2443 """
2444 Removes a custom event handler from the PropertyService.
2445 """
2446 self._customEventHandlers.remove(handler)
2447
2448
2449 def chopPath(self, text, length = 36):
2450 """
2451 Simple version of textwrap. textwrap.fill() unfortunately chops lines at spaces
2452 and creates odd word boundaries. Instead, we will chop the path without regard to
2453 spaces, but pay attention to path delimiters.
2454 """
2455 chopped = ""
2456 textLen = len(text)
2457 start = 0
2458
2459 while start < textLen:
2460 end = start + length
2461 if end > textLen:
2462 end = textLen
2463
2464 # see if we can find a delimiter to chop the path
2465 if end < textLen:
2466 lastSep = text.rfind(os.sep, start, end + 1)
2467 if lastSep != -1 and lastSep != start:
2468 end = lastSep
2469
2470 if len(chopped):
2471 chopped = chopped + '\n' + text[start:end]
2472 else:
2473 chopped = text[start:end]
2474
2475 start = end
2476
2477 return chopped
2478
2479
2480 class FilePropertiesDialog(wx.Dialog):
2481 """
2482 Dialog that shows the properties of a file. Invoked by the PropertiesService.
2483 """
2484
2485
2486 def __init__(self, parent, filename):
2487 """
2488 Initializes the properties dialog.
2489 """
2490 wx.Dialog.__init__(self, parent, -1, _("File Properties"), size = (310, 330))
2491
2492 HALF_SPACE = 5
2493 SPACE = 10
2494
2495 filePropertiesService = wx.GetApp().GetService(FilePropertiesService)
2496
2497 fileExists = os.path.exists(filename)
2498
2499 notebook = wx.Notebook(self, -1)
2500 tab = wx.Panel(notebook, -1)
2501
2502 gridSizer = RowColSizer()
2503
2504 gridSizer.Add(wx.StaticText(tab, -1, _("Filename:")), flag=wx.RIGHT, border=HALF_SPACE, row=0, col=0)
2505 gridSizer.Add(wx.StaticText(tab, -1, os.path.basename(filename)), row=0, col=1)
2506
2507 gridSizer.Add(wx.StaticText(tab, -1, _("Location:")), flag=wx.RIGHT, border=HALF_SPACE, row=1, col=0)
2508 gridSizer.Add(wx.StaticText(tab, -1, filePropertiesService.chopPath(os.path.dirname(filename))), flag=wx.BOTTOM, border=SPACE, row=1, col=1)
2509
2510 gridSizer.Add(wx.StaticText(tab, -1, _("Size:")), flag=wx.RIGHT, border=HALF_SPACE, row=2, col=0)
2511 if fileExists:
2512 gridSizer.Add(wx.StaticText(tab, -1, str(os.path.getsize(filename)) + ' ' + _("bytes")), row=2, col=1)
2513
2514 lineSizer = wx.BoxSizer(wx.VERTICAL) # let the line expand horizontally without vertical expansion
2515 lineSizer.Add(wx.StaticLine(tab, -1, size = (10,-1)), 0, wx.EXPAND)
2516 gridSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=HALF_SPACE, row=3, col=0, colspan=2)
2517
2518 gridSizer.Add(wx.StaticText(tab, -1, _("Created:")), flag=wx.RIGHT, border=HALF_SPACE, row=4, col=0)
2519 if fileExists:
2520 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getctime(filename))), row=4, col=1)
2521
2522 gridSizer.Add(wx.StaticText(tab, -1, _("Modified:")), flag=wx.RIGHT, border=HALF_SPACE, row=5, col=0)
2523 if fileExists:
2524 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getmtime(filename))), row=5, col=1)
2525
2526 gridSizer.Add(wx.StaticText(tab, -1, _("Accessed:")), flag=wx.RIGHT, border=HALF_SPACE, row=6, col=0)
2527 if fileExists:
2528 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getatime(filename))), row=6, col=1)
2529
2530 # add a border around the inside of the tab
2531 spacerGrid = wx.BoxSizer(wx.VERTICAL)
2532 spacerGrid.Add(gridSizer, 0, wx.ALL, SPACE);
2533 tab.SetSizer(spacerGrid)
2534 notebook.AddPage(tab, _("General"))
2535
2536 sizer = wx.BoxSizer(wx.VERTICAL)
2537 sizer.Add(notebook, 0, wx.ALL | wx.EXPAND, SPACE)
2538 sizer.Add(self.CreateButtonSizer(wx.OK), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
2539
2540 sizer.Fit(self)
2541 self.SetDimensions(-1, -1, 310, -1, wx.SIZE_USE_EXISTING)
2542 self.SetSizer(sizer)
2543 self.Layout()
2544
2545
2546 class ChildDocument(wx.lib.docview.Document):
2547 """
2548 A ChildDocument is a document that represents a portion of a Document. The child
2549 document is managed by the parent document, so it will be prompted to close if its
2550 parent is closed, etc. Child Documents are useful when there are complicated
2551 Views of a Document and users will need to tunnel into the View.
2552 """
2553
2554
2555 def GetData(self):
2556 """
2557 Returns the data that the ChildDocument contains.
2558 """
2559 return self._data
2560
2561
2562 def SetData(self, data):
2563 """
2564 Sets the data that the ChildDocument contains.
2565 """
2566 self._data = data
2567
2568
2569 def GetParentDocument(self):
2570 """
2571 Returns the parent Document of the ChildDocument.
2572 """
2573 return self._parentDocument
2574
2575
2576 def SetParentDocument(self, parentDocument):
2577 """
2578 Sets the parent Document of the ChildDocument.
2579 """
2580 self._parentDocument = parentDocument
2581
2582
2583 def OnSaveDocument(self, filename):
2584 """
2585 Called when the ChildDocument is saved and does the minimum such that the
2586 ChildDocument looks like a real Document to the framework.
2587 """
2588 self.SetFilename(filename, True)
2589 self.Modify(False)
2590 self.SetDocumentSaved(True)
2591 return True
2592
2593
2594 def OnOpenDocument(self, filename):
2595 """
2596 Called when the ChildDocument is opened and does the minimum such that the
2597 ChildDocument looks like a real Document to the framework.
2598 """
2599 self.SetFilename(filename, True)
2600 self.Modify(False)
2601 self.SetDocumentSaved(True)
2602 self.UpdateAllViews()
2603 return True
2604
2605
2606 def Save(self):
2607 """
2608 Called when the ChildDocument is saved and does the minimum such that the
2609 ChildDocument looks like a real Document to the framework.
2610 """
2611 return self.OnSaveDocument(self._documentFile)
2612
2613
2614 def SaveAs(self):
2615 """
2616 Called when the ChildDocument is saved and does the minimum such that the
2617 ChildDocument looks like a real Document to the framework.
2618 """
2619 return self.OnSaveDocument(self._documentFile)
2620
2621
2622 class ChildDocTemplate(wx.lib.docview.DocTemplate):
2623 """
2624 A ChildDocTemplate is a DocTemplate subclass that enables the creation of ChildDocuments
2625 that represents a portion of a Document. The child document is managed by the parent document,
2626 so it will be prompted to close if its parent is closed, etc. Child Documents are useful
2627 when there are complicated Views of a Document and users will need to tunnel into the View.
2628 """
2629
2630
2631 def __init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags = wx.lib.docview.TEMPLATE_INVISIBLE, icon = None):
2632 """
2633 Initializes the ChildDocTemplate.
2634 """
2635 wx.lib.docview.DocTemplate.__init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags = flags, icon = icon)
2636
2637
2638 def CreateDocument(self, path, flags, data = None, parentDocument = None):
2639 """
2640 Called when a ChildDocument is to be created and does the minimum such that the
2641 ChildDocument looks like a real Document to the framework.
2642 """
2643 doc = self._docType()
2644 doc.SetFilename(path)
2645 doc.SetData(data)
2646 doc.SetParentDocument(parentDocument)
2647 doc.SetDocumentTemplate(self)
2648 self.GetDocumentManager().AddDocument(doc)
2649 doc.SetCommandProcessor(doc.OnCreateCommandProcessor())
2650 if doc.OnCreate(path, flags):
2651 return doc
2652 else:
2653 if doc in self.GetDocumentManager().GetDocuments():
2654 doc.DeleteAllViews()
2655 return None
2656
2657
2658 class WindowMenuService(DocService):
2659 """
2660 The WindowMenuService is a service that implements a standard Window menu that is used
2661 by the DocSDIFrame. The MDIFrame automatically includes a Window menu and does not use
2662 the WindowMenuService.
2663 """
2664
2665
2666 def __init__(self):
2667 """
2668 Initializes the WindowMenu and its globals.
2669 """
2670 self.ARRANGE_WINDOWS_ID = wx.NewId()
2671 self.SELECT_WINDOW_1_ID = wx.NewId()
2672 self.SELECT_WINDOW_2_ID = wx.NewId()
2673 self.SELECT_WINDOW_3_ID = wx.NewId()
2674 self.SELECT_WINDOW_4_ID = wx.NewId()
2675 self.SELECT_WINDOW_5_ID = wx.NewId()
2676 self.SELECT_WINDOW_6_ID = wx.NewId()
2677 self.SELECT_WINDOW_7_ID = wx.NewId()
2678 self.SELECT_WINDOW_8_ID = wx.NewId()
2679 self.SELECT_WINDOW_9_ID = wx.NewId()
2680 self.SELECT_MORE_WINDOWS_ID = wx.NewId()
2681
2682
2683 def InstallControls(self, frame, menuBar = None, toolBar = None, statusBar = None, document = None):
2684 """
2685 Installs the Window menu.
2686 """
2687
2688 if not self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
2689 return # Only need windows menu for SDI mode, MDI frame automatically creates one
2690
2691 if not _WINDOWS: # Arrange All and window navigation doesn't work on Linux
2692 return
2693
2694 windowMenu = wx.Menu()
2695 item = windowMenu.Append(self.ARRANGE_WINDOWS_ID, _("&Arrange All"), _("Arrange the open windows"))
2696 windowMenu.AppendSeparator()
2697
2698 wx.EVT_MENU(frame, self.ARRANGE_WINDOWS_ID, frame.ProcessEvent)
2699 wx.EVT_UPDATE_UI(frame, self.ARRANGE_WINDOWS_ID, frame.ProcessUpdateUIEvent)
2700 wx.EVT_MENU(frame, self.SELECT_WINDOW_1_ID, frame.ProcessEvent) # wxNewId may have been nonsequential, so can't use EVT_MENU_RANGE
2701 wx.EVT_MENU(frame, self.SELECT_WINDOW_2_ID, frame.ProcessEvent)
2702 wx.EVT_MENU(frame, self.SELECT_WINDOW_3_ID, frame.ProcessEvent)
2703 wx.EVT_MENU(frame, self.SELECT_WINDOW_4_ID, frame.ProcessEvent)
2704 wx.EVT_MENU(frame, self.SELECT_WINDOW_5_ID, frame.ProcessEvent)
2705 wx.EVT_MENU(frame, self.SELECT_WINDOW_6_ID, frame.ProcessEvent)
2706 wx.EVT_MENU(frame, self.SELECT_WINDOW_7_ID, frame.ProcessEvent)
2707 wx.EVT_MENU(frame, self.SELECT_WINDOW_8_ID, frame.ProcessEvent)
2708 wx.EVT_MENU(frame, self.SELECT_WINDOW_9_ID, frame.ProcessEvent)
2709 wx.EVT_MENU(frame, self.SELECT_MORE_WINDOWS_ID, frame.ProcessEvent)
2710
2711 helpMenuIndex = menuBar.FindMenu(_("&Help"))
2712 menuBar.Insert(helpMenuIndex, windowMenu, _("&Window"))
2713
2714 self._lastFrameUpdated = None
2715
2716
2717 def ProcessEvent(self, event):
2718 """
2719 Processes a Window menu event.
2720 """
2721 id = event.GetId()
2722 if id == self.ARRANGE_WINDOWS_ID:
2723 self.OnArrangeWindows(event)
2724 return True
2725 elif id == self.SELECT_MORE_WINDOWS_ID:
2726 self.OnSelectMoreWindows(event)
2727 return True
2728 elif id == self.SELECT_WINDOW_1_ID or id == self.SELECT_WINDOW_2_ID or id == self.SELECT_WINDOW_3_ID or id == self.SELECT_WINDOW_4_ID or id == self.SELECT_WINDOW_5_ID or id == self.SELECT_WINDOW_6_ID or id == self.SELECT_WINDOW_7_ID or id == self.SELECT_WINDOW_8_ID or id == self.SELECT_WINDOW_9_ID:
2729 self.OnSelectWindowMenu(event)
2730 return True
2731 else:
2732 return False
2733
2734
2735 def ProcessUpdateUIEvent(self, event):
2736 """
2737 Updates the Window menu items.
2738 """
2739 id = event.GetId()
2740 if id == self.ARRANGE_WINDOWS_ID:
2741 frame = event.GetEventObject()
2742 if not self._lastFrameUpdated or self._lastFrameUpdated != frame:
2743 self.BuildWindowMenu(frame) # It's a new frame, so update the windows menu... this is as if the View::OnActivateMethod had been invoked
2744 self._lastFrameUpdated = frame
2745 return True
2746 else:
2747 return False
2748
2749
2750 def BuildWindowMenu(self, currentFrame):
2751 """
2752 Builds the Window menu and adds menu items for all of the open documents in the DocManager.
2753 """
2754 windowMenuIndex = currentFrame.GetMenuBar().FindMenu(_("&Window"))
2755 windowMenu = currentFrame.GetMenuBar().GetMenu(windowMenuIndex)
2756 ids = self._GetWindowMenuIDList()
2757 frames = self._GetWindowMenuFrameList(currentFrame)
2758 max = WINDOW_MENU_NUM_ITEMS
2759 if max > len(frames):
2760 max = len(frames)
2761 i = 0
2762 for i in range(0, max):
2763 frame = frames[i]
2764 item = windowMenu.FindItemById(ids[i])
2765 label = '&' + str(i + 1) + ' ' + frame.GetTitle()
2766 if not item:
2767 item = windowMenu.AppendCheckItem(ids[i], label)
2768 else:
2769 windowMenu.SetLabel(ids[i], label)
2770 windowMenu.Check(ids[i], (frame == currentFrame))
2771 if len(frames) > WINDOW_MENU_NUM_ITEMS: # Add the more items item
2772 if not windowMenu.FindItemById(self.SELECT_MORE_WINDOWS_ID):
2773 windowMenu.Append(self.SELECT_MORE_WINDOWS_ID, _("&More Windows..."))
2774 else: # Remove any extra items
2775 if windowMenu.FindItemById(self.SELECT_MORE_WINDOWS_ID):
2776 windowMenu.Remove(self.SELECT_MORE_WINDOWS_ID)
2777
2778
2779
2780 for j in range(i + 1, WINDOW_MENU_NUM_ITEMS):
2781 if windowMenu.FindItemById(ids[j]):
2782 windowMenu.Remove(ids[j])
2783
2784
2785 def _GetWindowMenuIDList(self):
2786 """
2787 Returns a list of the Window menu item IDs.
2788 """
2789 return [self.SELECT_WINDOW_1_ID, self.SELECT_WINDOW_2_ID, self.SELECT_WINDOW_3_ID, self.SELECT_WINDOW_4_ID, self.SELECT_WINDOW_5_ID, self.SELECT_WINDOW_6_ID, self.SELECT_WINDOW_7_ID, self.SELECT_WINDOW_8_ID, self.SELECT_WINDOW_9_ID]
2790
2791
2792 def _GetWindowMenuFrameList(self, currentFrame = None):
2793 """
2794 Returns the Frame associated with each menu item in the Window menu.
2795 """
2796 frameList = []
2797 # get list of windows for documents
2798 for doc in self._docManager.GetDocuments():
2799 for view in doc.GetViews():
2800 frame = view.GetFrame()
2801 if frame not in frameList:
2802 if frame == currentFrame and len(frameList) >= WINDOW_MENU_NUM_ITEMS:
2803 frameList.insert(WINDOW_MENU_NUM_ITEMS - 1, frame)
2804 else:
2805 frameList.append(frame)
2806 # get list of windows for general services
2807 for service in wx.GetApp().GetServices():
2808 view = service.GetView()
2809 if view:
2810 frame = view.GetFrame()
2811 if frame not in frameList:
2812 if frame == currentFrame and len(frameList) >= WINDOW_MENU_NUM_ITEMS:
2813 frameList.insert(WINDOW_MENU_NUM_ITEMS - 1, frame)
2814 else:
2815 frameList.append(frame)
2816
2817 return frameList
2818
2819
2820 def OnArrangeWindows(self, event):
2821 """
2822 Called by Window/Arrange and tiles the frames on the desktop.
2823 """
2824 currentFrame = event.GetEventObject()
2825
2826 tempFrame = wx.Frame(None, -1, "", pos = wx.DefaultPosition, size = wx.DefaultSize)
2827 sizex = tempFrame.GetSize()[0]
2828 sizey = tempFrame.GetSize()[1]
2829 tempFrame.Destroy()
2830
2831 posx = 0
2832 posy = 0
2833 delta = 0
2834 frames = self._GetWindowMenuFrameList()
2835 frames.remove(currentFrame)
2836 frames.append(currentFrame) # Make the current frame the last frame so that it is the last one to appear
2837 for frame in frames:
2838 if delta == 0:
2839 delta = frame.GetClientAreaOrigin()[1]
2840 frame.SetPosition((posx, posy))
2841 frame.SetSize((sizex, sizey))
2842 # TODO: Need to loop around if posx + delta + size > displaysize
2843 frame.SetFocus()
2844 posx = posx + delta
2845 posy = posy + delta
2846 if posx + sizex > wx.DisplaySize()[0] or posy + sizey > wx.DisplaySize()[1]:
2847 posx = 0
2848 posy = 0
2849 currentFrame.SetFocus()
2850
2851
2852 def OnSelectWindowMenu(self, event):
2853 """
2854 Called when the Window menu item representing a Frame is selected and brings the selected
2855 Frame to the front of the desktop.
2856 """
2857 id = event.GetId()
2858 index = self._GetWindowMenuIDList().index(id)
2859 if index > -1:
2860 currentFrame = event.GetEventObject()
2861 frame = self._GetWindowMenuFrameList(currentFrame)[index]
2862 if frame:
2863 wx.CallAfter(frame.Raise)
2864
2865
2866 def OnSelectMoreWindows(self, event):
2867 """
2868 Called when the "Window/Select More Windows..." menu item is selected and enables user to
2869 select from the Frames that do not in the Window list. Useful when there are more than
2870 10 open frames in the application.
2871 """
2872 frames = self._GetWindowMenuFrameList() # TODO - make the current window the first one
2873 strings = map(lambda frame: frame.GetTitle(), frames)
2874 # Should preselect the current window, but not supported by wx.GetSingleChoice
2875 res = wx.GetSingleChoiceIndex(_("Select a window to show:"),
2876 _("Select Window"),
2877 strings,
2878 self)
2879 if res == -1:
2880 return
2881 frames[res].SetFocus()
2882
2883
2884 #----------------------------------------------------------------------------
2885 # File generated by encode_bitmaps.py
2886 #----------------------------------------------------------------------------
2887 from wx import ImageFromStream, BitmapFromImage
2888 from wx import EmptyIcon
2889 import cStringIO
2890
2891 #----------------------------------------------------------------------
2892 def getNewData():
2893 return \
2894 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2895 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2896 \x00\x00[IDAT8\x8d\xed\x93\xb1\n\x001\x08C\x13{\xff\xff\xc7mn\xb8El\x91\x16\
2897 \x97\x0e\x97M\x90\x97\x88JZCE\x8f/4\xba\xb2fZc\n\x00\x00i\xcd \t\x8d\xae\x08\
2898 \xb1\xad\x9c\x0e\x1eS\x1e\x01\xc8\xcf\xdcC\xa6\x112\xf7\x08:N\xb0\xd2\x0f\
2899 \xb8\x010\xdd\x81\xdf\xf1\x8eX\xfd\xc6\xf2\x08/D\xbd\x19(\xc8\xa5\xd9\xfa\
2900 \x00\x00\x00\x00IEND\xaeB`\x82'
2901
2902 def getNewBitmap():
2903 return BitmapFromImage(getNewImage())
2904
2905 def getNewImage():
2906 stream = cStringIO.StringIO(getNewData())
2907 return ImageFromStream(stream)
2908
2909 #----------------------------------------------------------------------
2910 def getOpenData():
2911 return \
2912 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2913 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2914 \x00\x00\x95IDAT8\x8d\xa5\x92\xc1\x12\x03!\x08C\x13\xec\x87\xfb\xe3B\x0f.]\
2915 \xb0\x8e[m.\xea\x0c/\x06\x06R\n\xfe\xd1\xeb\xd7B\xd5f~\x17)\xdc2Pm\x16!\x7f\
2916 \xab6\xe3i\x0b\x9e\xe8\x93\xc0BD\x86\xdfV0\x00\x90R`\xda\xcc\x0c\x00\x0c\x00\
2917 \xc1\x05>\x9a\x87\x19t\x180\x981\xbd\xfd\xe4\xc4Y\x82\xf7\x14\xca\xe7\xb7\
2918 \xa6\t\xee6\x1c\xba\xe18\xab\xc1 \xc3\xb5N?L\xaa5\xb5\xd0\x8dw`JaJ\xb0\x0b\
2919 \x03!\xc1\t\xdc\xb9k\x0f\x9e\xd1\x0b\x18\xf6\xe0x\x95]\xf2\\\xb2\xd6\x1b}\
2920 \x14BL\xb9{t\xc7\x00\x00\x00\x00IEND\xaeB`\x82'
2921
2922 def getOpenBitmap():
2923 return BitmapFromImage(getOpenImage())
2924
2925 def getOpenImage():
2926 stream = cStringIO.StringIO(getOpenData())
2927 return ImageFromStream(stream)
2928
2929 #----------------------------------------------------------------------
2930 def getCopyData():
2931 return \
2932 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2933 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2934 \x00\x00\x9fIDAT8\x8d\xa5\x93\xdb\x0e\x830\x0cC\xed\x84\xdfF\xeb\xb4\xef\xa6\
2935 \xde\x030z\t\x94\tK\x91z\xcb\x01\xbb*i\x8e\'\x9a\x00@yQ\xb4Is\x8e\x00\xb6\
2936 \x0f$Uu\x05\x0e\x01\x91$\r!\xa49\x94\x17I\x02\xc9_\xe3:Nq\x93}XL|\xeb\xe9\
2937 \x05\xa4p\rH\xa29h^[ Y\xd5\xb9\xb5\x17\x94gu\x19DA\x96\xe0c\xfe^\xcf\xe7Y\
2938 \x95\x05\x00M\xf5\x16Z;\x7f\xfdAd\xcf\xee\x1cj\xc1%|\xdan"LL\x19\xda\xe1}\
2939 \x90:\x00#\x95_l5\x04\xec\x89\x9f\xef?|\x8d\x97o\xe1\x8e\xbeJ\xfc\xb1\xde\
2940 \xea\xf8\xb9\xc4\x00\x00\x00\x00IEND\xaeB`\x82'
2941
2942 def getCopyBitmap():
2943 return BitmapFromImage(getCopyImage())
2944
2945 def getCopyImage():
2946 stream = cStringIO.StringIO(getCopyData())
2947 return ImageFromStream(stream)
2948
2949 #----------------------------------------------------------------------
2950 def getPasteData():
2951 return \
2952 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2953 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2954 \x00\x00\xa1IDAT8\x8d\xa5\x93\xd9\x0e\xc3 \x0c\x04\xc7\xa6\xbf]\xc5U\xbf\xbb\
2955 \xd9>$4\\9\xaa\xacd\t\x0c\x1e/H6\xf3\xc4\x1d=FI\xcd\x1f\x95{\xf3d{\x003O]\
2956 \x01\x80\x94/\x0c\x8a\n\xa0\x01\x8a\x88\xdfaD m\x85y\xdd\xde\xc9\x10/\xc9\
2957 \xf9\xc0S2\xf3%\xf2\xba\x04\x94\xea\xfe`\xf4\x9c#U\x80\xbd.\x97\x015\xec&\
2958 \x00@\x9a\xba\x9c\xd9\x0b\x08\xe0\r4\x9fxU\xd2\x84\xe6\xa7N\x1dl\x1dkGe\xee\
2959 \x14\xd0>\xa3\x85\xfc\xe5`\x08]\x87I}\x84\x8e\x04!\xf3\xb48\x18\r\x8bf4\xea\
2960 \xde;\xbc9\xce_!\\\\T\xf75'\xd6\x00\x00\x00\x00IEND\xaeB`\x82"
2961
2962 def getPasteBitmap():
2963 return BitmapFromImage(getPasteImage())
2964
2965 def getPasteImage():
2966 stream = cStringIO.StringIO(getPasteData())
2967 return ImageFromStream(stream)
2968
2969 #----------------------------------------------------------------------
2970 def getSaveData():
2971 return \
2972 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2973 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2974 \x00\x00lIDAT8\x8d\xc5\x93\xe1\n\xc0 \x08\x84=\xed\xc1}\xf1\xcd\xfd\x18B\x98\
2975 mX\x83\x1d\x04\x11\xfayV\x02,\xb4#\xde\xca&\xa2\xe6\x1b;\x0f\xab$\x82\x05\
2976 \x83\x03U\xbdaf\xe9\xea\x13]\xe5\x16\xa2\xd32\xc0].\x03\xa2Z<PU\x02\x90\xc5\
2977 \x0e\xd5S\xc0,p\xa6\xef[xs\xb0t\x89`A|\xff\x12\xe0\x11\xde\x0fS\xe5;\xbb#\
2978 \xfc>\x8d\x17\x18\xfd(\xb72\xc2\x06\x00\x00\x00\x00\x00IEND\xaeB`\x82'
2979
2980 def getSaveBitmap():
2981 return BitmapFromImage(getSaveImage())
2982
2983 def getSaveImage():
2984 stream = cStringIO.StringIO(getSaveData())
2985 return ImageFromStream(stream)
2986
2987 #----------------------------------------------------------------------
2988 def getSaveAllData():
2989 return \
2990 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2991 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2992 \x00\x01\tIDAT8\x8d\xa5\x93\xe1m\x830\x10\x85\xdfA\xd7H\x827\xf0\x02\xado\
2993 \x04\x8f`Fh\xfb\xb7\xad\xcd&$Y\x80\x11\xcc\x06\x8c\xe0E\xd2\xeb\x8f\x16\x04!\
2994 8R\xf3\xa4\x93Nw\xd2\xf3\xa7g\x9b\xa8(\xf1\x88\x9er\xcb\xc3~\')%x\xef\xa7Y\
2995 \x8c\x11J)\x00\xc0\xf1t&PQn\x163\x0b\x00\x99\xcb{/\x00\xc49\'T\x94(\xfe\x83\
2996 \x1dB\x98\xfa\x95\xc1a\xbf\x13\xf9\xbe\xc8\xd7\xe7\x87\x18c\xe0\xbd\x073\xa3\
2997 \xaek\x10\x11\xfa\xbe\xcfgPU\x15RJ\x8bSB\x08h\x9af1\xdb$\xc8aw]\x87\xae\xeb\
2998 \xd6\x04\xd7i\x1bc\xc0\xccPJ\xa1m[03\x98\x19Z\xeb\x951QQ\xc2\xbc<K\x8c\x11"\
2999 \x92\xc5N)M\xbd\xd6\x1a\xafo\xef\x94}\x07#6\x00Xk\x7f\xef\xfdO\xc7\xd3\x19\
3000 \xc0,\x83\x10\x02\x88h\xaa1m\xad\xf5M\xf4E\x06s\x93-\xcd\xf1\xef\x1a\x8c\'^c\
3001 \xdf5\x18\x95C\xbei`\xad\xc50\x0cp\xce-\x96[\xd8s\xd1\xa3\xdf\xf9\x075\xf1v>\
3002 \x92\xcb\xbc\xdd\x00\x00\x00\x00IEND\xaeB`\x82'
3003
3004 def getSaveAllBitmap():
3005 return BitmapFromImage(getSaveAllImage())
3006
3007 def getSaveAllImage():
3008 stream = cStringIO.StringIO(getSaveAllData())
3009 return ImageFromStream(stream)
3010
3011 #----------------------------------------------------------------------
3012 def getPrintData():
3013 return \
3014 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3015 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3016 \x00\x00\xa1IDAT8\x8d\xa5S[\x0e\x02!\x0c\xec\xd0\xbd\xb6\x1a\xf5\xda\x96\xd9\
3017 \x0f\xa1V\x96\x00\xbaMHI\xd3y\xf0(\x90T\xce\xc4\xd6+2\x1bg@$E\x97\x80\xd9H\
3018 \x8e\xf1\x00\xc6\x0e\xda&''\x05\x80\xab\x1f\x08\xa2\xfa\xcc\xc5\xd0\xc1H\xbd\
3019 \n\x89\xbc\xef\xc1\tV\xd5\x91\x14\xcc\xc6\x9a\xa5<#WV\xed\x8d\x18\x94\xc2\
3020 \xd1s'\xa2\xb2\xe7\xc2\xf4STAf\xe3\x16\x0bm\xdc\xae\x17'\xbf?\x9e\x0e\x8an\
3021 \x86G\xc8\xf6\xf9\x91I\xf5\x8b\xa0\n\xff}\x04w\x80\xa4ng\x06l/QD\x04u\x1aW\
3022 \x06(:\xf0\xfd\x99q\xce\xf6\xe2\x0e\xa5\xa2~.\x00=\xb5t\x00\x00\x00\x00IEND\
3023 \xaeB`\x82"
3024
3025 def getPrintBitmap():
3026 return BitmapFromImage(getPrintImage())
3027
3028 def getPrintImage():
3029 stream = cStringIO.StringIO(getPrintData())
3030 return ImageFromStream(stream)
3031
3032 #----------------------------------------------------------------------
3033 def getPrintPreviewData():
3034 return \
3035 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3036 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3037 \x00\x00\xa8IDAT8\x8d\x9d\x93K\x0e\xc30\x08Dg \xd7n\xcd\xc1\x9b\xd2E\x83E\\\
3038 \xffT$/\x82\xc5\x83\x19\x13\x02p,\x82\xa2\x1c\xde\x01p\xf71\x83\xe4\x14"\xab\
3039 \xeeQ\xec\xef\xb3\xdbe{\x82\x0c\xcb\xdf\xc7\xaa{\x86\xb7\xb0-@\xaf(\xc7\xd4\
3040 \x03\x9203P\x94\x14\xa5\x99\xa1\xf5b\x08\x88b+\x05~\xbejQ\x0f\xe2\xbd\x00\
3041 \xe0\x14\x05\xdc\x9d\xa2\xa0(\xcc\xec\x9b\xbb\xee(\xba~F\xea15a\n(\xcfG\x1d5\
3042 d\xe4\xdcTB\xc8\x88\xb1CB\x9b\x9b\x02\x02\x92O@\xaa\x0fXl\xe2\xcd\x0f\xf2g\
3043 \xad\x89\x8d\xbf\xf1\x06\xb9V9 \x0c\x1d\xff\xc6\x07\x8aF\x9e\x04\x12\xb5\xf9\
3044 O\x00\x00\x00\x00IEND\xaeB`\x82'
3045
3046 def getPrintPreviewBitmap():
3047 return BitmapFromImage(getPrintPreviewImage())
3048
3049 def getPrintPreviewImage():
3050 stream = cStringIO.StringIO(getPrintPreviewData())
3051 return ImageFromStream(stream)
3052
3053 #----------------------------------------------------------------------
3054 def getCutData():
3055 return \
3056 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3057 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3058 \x00\x00rIDAT8\x8d\xad\x93\xc1\x0e\xc0 \x08CW\xdco{\xf2\xbb';\xb18\x07\x9d\
3059 \x0b\xe3\xa2\x98\xe6\xb5$\x02H\xd92%\xde\xa3\xf6CY\xff\nH'\xf8\x05`\xb1Y\xfc\
3060 \x10\x00)`\xfdR\x82\x15w\n0W\xe6N\x01\xda\xab\x8e\xe7g\xc0\xe8\xae\xbdj\x04\
3061 \xda#\xe7;\xa8] \xbb\xbb\tL0\x8bX\xa5?\xd2c\x84\xb9 \r6\x96\x97\x0c\xf362\
3062 \xb1k\x90]\xe7\x13\x85\xca7&\xcf\xda\xcdU\x00\x00\x00\x00IEND\xaeB`\x82"
3063
3064 def getCutBitmap():
3065 return BitmapFromImage(getCutImage())
3066
3067 def getCutImage():
3068 stream = cStringIO.StringIO(getCutData())
3069 return ImageFromStream(stream)
3070
3071 #----------------------------------------------------------------------
3072 def getUndoData():
3073 return \
3074 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3075 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3076 \x00\x00lIDAT8\x8d\xed\x92Q\x0b\x800\x08\x84\xd5\xf5\xb7\x07W\xfdo\xed!\xaca\
3077 \xb2\x11{\xe9!a\xa0\xc7\xeec\x1ec\x96B3%S\xeeO\x00\x96\xd1\x05\xd3j\xed\x0c\
3078 \x10\xad\xdb\xce\x97\xc0R\xe8\x0c\x12\xe6\xbd\xcfQs\x1d\xb8\xf5\xd4\x90\x19#\
3079 \xc4\xfbG\x06\xa6\xd5X\x9a'\x0e*\r1\xee\xfd\x1a\xd0\x83\x98V\x03\x1a\xa1\xb7\
3080 k<@\x12\xec\xff\x95\xe7\x01\x07L\x0e(\xe5\xa4\xff\x1c\x88\x00\x00\x00\x00IEN\
3081 D\xaeB`\x82"
3082
3083 def getUndoBitmap():
3084 return BitmapFromImage(getUndoImage())
3085
3086 def getUndoImage():
3087 stream = cStringIO.StringIO(getUndoData())
3088 return ImageFromStream(stream)
3089
3090 #----------------------------------------------------------------------
3091 def getRedoData():
3092 return \
3093 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3094 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3095 \x00\x00jIDAT8\x8d\xed\x92\xcd\n\xc0 \x0c\x83\x9bv\xaf\xed\x16\xf0\xbd\xd7]&\
3096 \xf8\x8f\xe0e\x87\t9$\xb6\x1f\xb5\x08\xa8\xc9\xce\xd1\xad\xeeO\x00\x8e\xdc\\\
3097 gp\xb2,\x80FL\tP\x13\xa8\tI\x17\xa1'\x9f$\xd2\xe6\xb9\xef\x86=\xa5\xfb\x1a\
3098 \xb8\xbc\x03h\x84\xdf\xc1\xeb|\x19\xd0k.\x00\xe4\xb8h\x94\xbf\xa3\x95\xef$\
3099 \xe7\xbbh\xf4\x7f\xe5}\xc0\x03&\x1b&\xe5\xc2\x03!\xa6\x00\x00\x00\x00IEND\
3100 \xaeB`\x82"
3101
3102 def getRedoBitmap():
3103 return BitmapFromImage(getRedoImage())
3104
3105 def getRedoImage():
3106 stream = cStringIO.StringIO(getRedoData())
3107 return ImageFromStream(stream)
3108
3109 #----------------------------------------------------------------------------
3110
3111 def getBlankData():
3112 return \
3113 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
3114 \x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00\
3115 \x85IDATX\x85\xed\x97\xc9\n\xc0 \x0cD3\xda\xff\xffcMo\x96Z\xc4\xa5\x91\x14:9\
3116 \x8a\xe8\xcb\xd3\xb8\x00!\x8ag\x04\xd7\xd9E\xe4\xa8\x1b4'}3 B\xc4L\x7fs\x03\
3117 \xb3\t<\x0c\x94\x81tN\x04p%\xae9\xe9\xa8\x89m{`\xd4\x84\xfd\x12\xa8\x16{#\
3118 \x10\xdb\xab\xa0\x07a\x0e\x00\xe0\xb6\x1fz\x10\xdf;\x07V\xa3U5\xb5\x8d:\xdc\
3119 \r\x10\x80\x00\x04 \x00\x01\x08@\x80\xe6{\xa0w\x8f[\x85\xbb\x01\xfc\xfeoH\
3120 \x80\x13>\xf9(3zH\x1e\xfb\x00\x00\x00\x00IEND\xaeB`\x82"
3121
3122
3123 def getBlankBitmap():
3124 return BitmapFromImage(getBlankImage())
3125
3126 def getBlankImage():
3127 stream = cStringIO.StringIO(getBlankData())
3128 return ImageFromStream(stream)
3129
3130 def getBlankIcon():
3131 icon = EmptyIcon()
3132 icon.CopyFromBitmap(getBlankBitmap())
3133 return icon
3134
3135