]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/pydocview.py
Changes to how overridable C++ methods are virtualized for Python.
[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, _("&Delete"), _("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 menuBar.Append(helpMenu, _("&Help"))
148
149 wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
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
198 # save child documents first
199 for doc in docs:
200 if isinstance(doc, wx.lib.pydocview.ChildDocument):
201 doc.Save()
202
203 # save parent and other documents later
204 for doc in docs:
205 if not isinstance(doc, wx.lib.pydocview.ChildDocument):
206 doc.Save()
207
208
209 def OnAbout(self, event):
210 """
211 Invokes the about dialog.
212 """
213 aboutService = wx.GetApp().GetService(AboutService)
214 if aboutService:
215 aboutService.ShowAbout()
216
217
218 def OnViewToolBar(self, event):
219 """
220 Toggles whether the ToolBar is visible.
221 """
222 self._toolBar.Show(not self._toolBar.IsShown())
223 self._LayoutFrame()
224
225
226 def OnUpdateViewToolBar(self, event):
227 """
228 Updates the View ToolBar menu item.
229 """
230 event.Check(self.GetToolBar().IsShown())
231
232
233 def OnViewStatusBar(self, event):
234 """
235 Toggles whether the StatusBar is visible.
236 """
237 self.GetStatusBar().Show(not self.GetStatusBar().IsShown())
238 self._LayoutFrame()
239
240
241 def OnUpdateViewStatusBar(self, event):
242 """
243 Updates the View StatusBar menu item.
244 """
245 event.Check(self.GetStatusBar().IsShown())
246
247
248 def UpdateStatus(self, message = _("Ready")):
249 """
250 Updates the StatusBar.
251 """
252 # wxBug: Menubar and toolbar help strings don't pop the status text back
253 if self.GetStatusBar().GetStatusText() != message:
254 self.GetStatusBar().PushStatusText(message)
255
256
257 class DocMDIParentFrameMixIn:
258 """
259 Class with common code used by DocMDIParentFrame and DocTabbedParentFrame.
260 """
261
262
263 def _GetPosSizeFromConfig(self, pos, size):
264 """
265 Adjusts the position and size of the frame using the saved config position and size.
266 """
267 config = wx.ConfigBase_Get()
268 if pos == wx.DefaultPosition and size == wx.DefaultSize and config.ReadInt("MDIFrameMaximized", False):
269 pos = [0, 0]
270 size = wx.DisplaySize()
271 # 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
272 else:
273 if pos == wx.DefaultPosition:
274 pos = config.ReadInt("MDIFrameXLoc", -1), config.ReadInt("MDIFrameYLoc", -1)
275
276 if wx.Display_GetFromPoint(pos) == -1: # Check if the frame position is offscreen
277 pos = wx.DefaultPosition
278
279 if size == wx.DefaultSize:
280 size = wx.Size(config.ReadInt("MDIFrameXSize", 450), config.ReadInt("MDIFrameYSize", 300))
281 return pos, size
282
283
284 def _InitFrame(self, embeddedWindows):
285 """
286 Initializes the frame and creates the default menubar, toolbar, and status bar.
287 """
288 self._embeddedWindows = []
289 self.SetDropTarget(_DocFrameFileDropTarget(self._docManager, self))
290
291 if wx.GetApp().GetDefaultIcon():
292 self.SetIcon(wx.GetApp().GetDefaultIcon())
293
294 wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
295 wx.EVT_SIZE(self, self.OnSize)
296
297 self.InitializePrintData()
298
299 toolBar = self.CreateDefaultToolBar()
300 self.SetToolBar(toolBar)
301 menuBar = self.CreateDefaultMenuBar()
302 statusBar = self.CreateDefaultStatusBar()
303
304 config = wx.ConfigBase_Get()
305 if config.ReadInt("MDIFrameMaximized", False):
306 # wxBug: On maximize, statusbar leaves a residual that needs to be refereshed, happens even when user does it
307 self.Maximize()
308
309 self.CreateEmbeddedWindows(embeddedWindows)
310 self._LayoutFrame()
311
312 if wx.Platform == '__WXMAC__':
313 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
314
315 wx.GetApp().SetTopWindow(self) # Need to do this here in case the services are looking for wx.GetApp().GetTopWindow()
316 for service in wx.GetApp().GetServices():
317 service.InstallControls(self, menuBar = menuBar, toolBar = toolBar, statusBar = statusBar)
318 if hasattr(service, "ShowWindow"):
319 service.ShowWindow() # instantiate service windows for correct positioning, we'll hide/show them later based on user preference
320
321 if wx.Platform != '__WXMAC__':
322 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
323
324
325 def ProcessEvent(self, event):
326 """
327 Processes an event, searching event tables and calling zero or more
328 suitable event handler function(s). Note that the ProcessEvent
329 method is called from the wxPython docview framework directly since
330 wxPython does not have a virtual ProcessEvent function.
331 """
332 id = event.GetId()
333 if id == SAVEALL_ID:
334 self.OnFileSaveAll(event)
335 return True
336
337 return wx.GetApp().ProcessEvent(event)
338
339
340 def ProcessUpdateUIEvent(self, event):
341 """
342 Processes a UI event, searching event tables and calling zero or more
343 suitable event handler function(s). Note that the ProcessEvent
344 method is called from the wxPython docview framework directly since
345 wxPython does not have a virtual ProcessEvent function.
346 """
347 id = event.GetId()
348 if id == wx.ID_CUT:
349 event.Enable(False)
350 return True
351 elif id == wx.ID_COPY:
352 event.Enable(False)
353 return True
354 elif id == wx.ID_PASTE:
355 event.Enable(False)
356 return True
357 elif id == wx.ID_CLEAR:
358 event.Enable(False)
359 return True
360 elif id == wx.ID_SELECTALL:
361 event.Enable(False)
362 return True
363 elif id == SAVEALL_ID:
364 filesModified = False
365 docs = wx.GetApp().GetDocumentManager().GetDocuments()
366 for doc in docs:
367 if doc.IsModified():
368 filesModified = True
369 break
370
371 event.Enable(filesModified)
372 return True
373 else:
374 return wx.GetApp().ProcessUpdateUIEvent(event)
375
376
377 def CreateEmbeddedWindows(self, windows=0):
378 """
379 Create the specified embedded windows around the edges of the frame.
380 """
381 frameSize = self.GetSize() # TODO: GetClientWindow.GetSize is still returning 0,0 since the frame isn't fully constructed yet, so using full frame size
382 MIN_SIZE = 20
383 defaultHSize = max(MIN_SIZE, int(frameSize[0] / 6))
384 defaultVSize = max(MIN_SIZE, int(frameSize[1] / 7))
385 defaultSubVSize = int(frameSize[1] / 2)
386 config = wx.ConfigBase_Get()
387 if windows & (EMBEDDED_WINDOW_LEFT | EMBEDDED_WINDOW_TOPLEFT | EMBEDDED_WINDOW_BOTTOMLEFT):
388 self._leftEmbWindow = self._CreateEmbeddedWindow(self, (max(MIN_SIZE,config.ReadInt("MDIEmbedLeftSize", defaultHSize)), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_LEFT, visible = config.ReadInt("MDIEmbedLeftVisible", 1), sash = wx.SASH_RIGHT)
389 else:
390 self._leftEmbWindow = None
391 if windows & EMBEDDED_WINDOW_TOPLEFT:
392 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)
393 else:
394 self._topLeftEmbWindow = None
395 if windows & EMBEDDED_WINDOW_BOTTOMLEFT:
396 self._bottomLeftEmbWindow = self._CreateEmbeddedWindow(self._leftEmbWindow, (-1, config.ReadInt("MDIEmbedBottomLeftSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomLeftVisible", 1))
397 else:
398 self._bottomLeftEmbWindow = None
399 if windows & (EMBEDDED_WINDOW_RIGHT | EMBEDDED_WINDOW_TOPRIGHT | EMBEDDED_WINDOW_BOTTOMRIGHT):
400 self._rightEmbWindow = self._CreateEmbeddedWindow(self, (max(MIN_SIZE,config.ReadInt("MDIEmbedRightSize", defaultHSize)), -1), wx.LAYOUT_VERTICAL, wx.LAYOUT_RIGHT, visible = config.ReadInt("MDIEmbedRightVisible", 1), sash = wx.SASH_LEFT)
401 else:
402 self._rightEmbWindow = None
403 if windows & EMBEDDED_WINDOW_TOPRIGHT:
404 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)
405 else:
406 self._topRightEmbWindow = None
407 if windows & EMBEDDED_WINDOW_BOTTOMRIGHT:
408 self._bottomRightEmbWindow = self._CreateEmbeddedWindow(self._rightEmbWindow, (-1, config.ReadInt("MDIEmbedBottomRightSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomRightVisible", 1))
409 else:
410 self._bottomRightEmbWindow = None
411 if windows & EMBEDDED_WINDOW_TOP:
412 self._topEmbWindow = self._CreateEmbeddedWindow(self, (-1, max(MIN_SIZE,config.ReadInt("MDIEmbedTopSize", defaultVSize))), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_TOP, visible = config.ReadInt("MDIEmbedTopVisible", 1), sash = wx.SASH_BOTTOM)
413 else:
414 self._topEmbWindow = None
415 if windows & EMBEDDED_WINDOW_BOTTOM:
416 self._bottomEmbWindow = self._CreateEmbeddedWindow(self, (-1, max(MIN_SIZE,config.ReadInt("MDIEmbedBottomSize", defaultVSize))), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomVisible", 1), sash = wx.SASH_TOP)
417 else:
418 self._bottomEmbWindow = None
419
420
421 def SaveEmbeddedWindowSizes(self):
422 """
423 Saves the sizes of the embedded windows.
424 """
425 config = wx.ConfigBase_Get()
426 if not self.IsMaximized():
427 config.WriteInt("MDIFrameXLoc", self.GetPositionTuple()[0])
428 config.WriteInt("MDIFrameYLoc", self.GetPositionTuple()[1])
429 config.WriteInt("MDIFrameXSize", self.GetSizeTuple()[0])
430 config.WriteInt("MDIFrameYSize", self.GetSizeTuple()[1])
431 config.WriteInt("MDIFrameMaximized", self.IsMaximized())
432 config.WriteInt("ViewToolBar", self._toolBar.IsShown())
433 config.WriteInt("ViewStatusBar", self.GetStatusBar().IsShown())
434
435 if self._leftEmbWindow:
436 config.WriteInt("MDIEmbedLeftSize", self._leftEmbWindow.GetSize()[0])
437 config.WriteInt("MDIEmbedLeftVisible", self._leftEmbWindow.IsShown())
438 if self._topLeftEmbWindow:
439 if self._topLeftEmbWindow._sizeBeforeHidden:
440 size = self._topLeftEmbWindow._sizeBeforeHidden[1]
441 else:
442 size = self._topLeftEmbWindow.GetSize()[1]
443 config.WriteInt("MDIEmbedTopLeftSize", size)
444 config.WriteInt("MDIEmbedTopLeftVisible", self._topLeftEmbWindow.IsShown())
445 if self._bottomLeftEmbWindow:
446 if self._bottomLeftEmbWindow._sizeBeforeHidden:
447 size = self._bottomLeftEmbWindow._sizeBeforeHidden[1]
448 else:
449 size = self._bottomLeftEmbWindow.GetSize()[1]
450 config.WriteInt("MDIEmbedBottomLeftSize", size)
451 config.WriteInt("MDIEmbedBottomLeftVisible", self._bottomLeftEmbWindow.IsShown())
452 if self._rightEmbWindow:
453 config.WriteInt("MDIEmbedRightSize", self._rightEmbWindow.GetSize()[0])
454 config.WriteInt("MDIEmbedRightVisible", self._rightEmbWindow.IsShown())
455 if self._topRightEmbWindow:
456 if self._topRightEmbWindow._sizeBeforeHidden:
457 size = self._topRightEmbWindow._sizeBeforeHidden[1]
458 else:
459 size = self._topRightEmbWindow.GetSize()[1]
460 config.WriteInt("MDIEmbedTopRightSize", size)
461 config.WriteInt("MDIEmbedTopRightVisible", self._topRightEmbWindow.IsShown())
462 if self._bottomRightEmbWindow:
463 if self._bottomRightEmbWindow._sizeBeforeHidden:
464 size = self._bottomRightEmbWindow._sizeBeforeHidden[1]
465 else:
466 size = self._bottomRightEmbWindow.GetSize()[1]
467 config.WriteInt("MDIEmbedBottomRightSize", size)
468 config.WriteInt("MDIEmbedBottomRightVisible", self._bottomRightEmbWindow.IsShown())
469 if self._topEmbWindow:
470 config.WriteInt("MDIEmbedTopSize", self._topEmbWindow.GetSize()[1])
471 config.WriteInt("MDIEmbedTopVisible", self._topEmbWindow.IsShown())
472 if self._bottomEmbWindow:
473 config.WriteInt("MDIEmbedBottomSize", self._bottomEmbWindow.GetSize()[1])
474 config.WriteInt("MDIEmbedBottomVisible", self._bottomEmbWindow.IsShown())
475
476
477 def GetEmbeddedWindow(self, loc):
478 """
479 Returns the instance of the embedded window specified by the embedded window location constant.
480 """
481 if loc == EMBEDDED_WINDOW_TOP:
482 return self._topEmbWindow
483 elif loc == EMBEDDED_WINDOW_BOTTOM:
484 return self._bottomEmbWindow
485 elif loc == EMBEDDED_WINDOW_LEFT:
486 return self._leftEmbWindow
487 elif loc == EMBEDDED_WINDOW_RIGHT:
488 return self._rightEmbWindow
489 elif loc == EMBEDDED_WINDOW_TOPLEFT:
490 return self._topLeftEmbWindow
491 elif loc == EMBEDDED_WINDOW_BOTTOMLEFT:
492 return self._bottomLeftEmbWindow
493 elif loc == EMBEDDED_WINDOW_TOPRIGHT:
494 return self._topRightEmbWindow
495 elif loc == EMBEDDED_WINDOW_BOTTOMRIGHT:
496 return self._bottomRightEmbWindow
497 return None
498
499
500 def _CreateEmbeddedWindow(self, parent, size, orientation, alignment, visible=True, sash=None):
501 """
502 Creates the embedded window with the specified size, orientation, and alignment. If the
503 window is not visible it will retain the size with which it was last viewed.
504 """
505 window = wx.SashLayoutWindow(parent, wx.NewId(), style = wx.NO_BORDER | wx.SW_3D)
506 window.SetDefaultSize(size)
507 window.SetOrientation(orientation)
508 window.SetAlignment(alignment)
509 if sash != None: # wx.SASH_TOP is 0 so check for None instead of just doing "if sash:"
510 window.SetSashVisible(sash, True)
511 ####
512 def OnEmbeddedWindowSashDrag(event):
513 if event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE:
514 return
515 sashWindow = event.GetEventObject()
516 if sashWindow.GetAlignment() == wx.LAYOUT_TOP or sashWindow.GetAlignment() == wx.LAYOUT_BOTTOM:
517 size = wx.Size(-1, event.GetDragRect().height)
518 else:
519 size = wx.Size(event.GetDragRect().width, -1)
520 event.GetEventObject().SetDefaultSize(size)
521 self._LayoutFrame()
522 sashWindow.Refresh()
523 if isinstance(sashWindow.GetParent(), wx.SashLayoutWindow):
524 sashWindow.Show()
525 parentSashWindow = sashWindow.GetParent() # Force a refresh
526 parentSashWindow.Layout()
527 parentSashWindow.Refresh()
528 parentSashWindow.SetSize((parentSashWindow.GetSize().width + 1, parentSashWindow.GetSize().height + 1))
529 ####
530 wx.EVT_SASH_DRAGGED(window, window.GetId(), OnEmbeddedWindowSashDrag)
531 window._sizeBeforeHidden = None
532 if not visible:
533 window.Show(False)
534 if isinstance(parent, wx.SashLayoutWindow): # It's a window embedded in another sash window so remember its actual size to show it again
535 window._sizeBeforeHidden = size
536 return window
537
538
539 def ShowEmbeddedWindow(self, window, show=True):
540 """
541 Shows or hides the embedded window specified by the embedded window location constant.
542 """
543 window.Show(show)
544 if isinstance(window.GetParent(), wx.SashLayoutWindow): # It is a parent sashwindow with multiple embedded sashwindows
545 parentSashWindow = window.GetParent()
546 if show: # Make sure it is visible in case all of the subwindows were hidden
547 parentSashWindow.Show()
548 if show and window._sizeBeforeHidden:
549 if window._sizeBeforeHidden[1] == parentSashWindow.GetClientSize()[1]:
550 if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).IsShown():
551 window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).GetSize()[1]))
552 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).IsShown():
553 window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).GetSize()[1]))
554 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).IsShown():
555 window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).GetSize()[1]))
556 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).IsShown():
557 window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).GetSize()[1]))
558 else:
559 window.SetDefaultSize(window._sizeBeforeHidden)
560 # 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
561 if window._sizeBeforeHidden[1] < parentSashWindow.GetClientSize()[1]:
562 otherWindowSize = (-1, parentSashWindow.GetClientSize()[1] - window._sizeBeforeHidden[1])
563 if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT):
564 self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).SetDefaultSize(otherWindowSize)
565 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT):
566 self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).SetDefaultSize(otherWindowSize)
567 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT):
568 self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).SetDefaultSize(otherWindowSize)
569 elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT):
570 self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).SetDefaultSize(otherWindowSize)
571
572 if not show:
573 if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).IsShown() \
574 or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).IsShown() \
575 or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).IsShown() \
576 or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).IsShown():
577 parentSashWindow.Hide() # Hide the parent sashwindow if all of the children are hidden
578 parentSashWindow.Layout() # Force a refresh
579 parentSashWindow.Refresh()
580 parentSashWindow.SetSize((parentSashWindow.GetSize().width + 1, parentSashWindow.GetSize().height + 1))
581 self._LayoutFrame()
582
583
584 def HideEmbeddedWindow(self, window):
585 """
586 Hides the embedded window specified by the embedded window location constant.
587 """
588 self.ShowEmbeddedWindow(window, show=False)
589
590
591 class DocTabbedChildFrame(wx.Panel):
592 """
593 The wxDocMDIChildFrame class provides a default frame for displaying
594 documents on separate windows. This class can only be used for MDI child
595 frames.
596
597 The class is part of the document/view framework supported by wxWindows,
598 and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
599 classes.
600 """
601
602
603 def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
604 """
605 Constructor. Note that the event table must be rebuilt for the
606 frame since the EvtHandler is not virtual.
607 """
608 wx.Panel.__init__(self, frame.GetNotebook(), id)
609 self._childDocument = doc
610 self._childView = view
611 frame.AddNotebookPage(self, doc.GetPrintableName())
612 if view:
613 view.SetFrame(self)
614
615
616 def GetIcon(self):
617 """
618 Dummy method since the icon of tabbed frames are managed by the notebook.
619 """
620 return None
621
622
623 def SetIcon(self, icon):
624 """
625 Dummy method since the icon of tabbed frames are managed by the notebook.
626 """
627 pass
628
629
630 def Destroy(self):
631 """
632 Removes the current notebook page.
633 """
634 wx.GetApp().GetTopWindow().RemoveNotebookPage(self)
635
636
637 def SetFocus(self):
638 """
639 Activates the current notebook page.
640 """
641 wx.GetApp().GetTopWindow().ActivateNotebookPage(self)
642
643
644 def Activate(self): # Need this in case there are embedded sash windows and such, OnActivate is not getting called
645 """
646 Activates the current view.
647 """
648 # Called by Project Editor
649 if self._childView:
650 self._childView.Activate(True)
651
652
653 def GetTitle(self):
654 """
655 Returns the frame's title.
656 """
657 return wx.GetApp().GetTopWindow().GetNotebookPageTitle(self)
658
659
660 def SetTitle(self, title):
661 """
662 Sets the frame's title.
663 """
664 wx.GetApp().GetTopWindow().SetNotebookPageTitle(self, title)
665
666
667 def ProcessEvent(event):
668 """
669 Processes an event, searching event tables and calling zero or more
670 suitable event handler function(s). Note that the ProcessEvent
671 method is called from the wxPython docview framework directly since
672 wxPython does not have a virtual ProcessEvent function.
673 """
674 if not self._childView or not self._childView.ProcessEvent(event):
675 if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
676 return False
677 else:
678 return True
679 else:
680 return True
681
682
683 def GetDocument(self):
684 """
685 Returns the document associated with this frame.
686 """
687 return self._childDocument
688
689
690 def SetDocument(self, document):
691 """
692 Sets the document for this frame.
693 """
694 self._childDocument = document
695
696
697 def GetView(self):
698 """
699 Returns the view associated with this frame.
700 """
701 return self._childView
702
703
704 def SetView(self, view):
705 """
706 Sets the view for this frame.
707 """
708 self._childView = view
709
710
711 class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
712 """
713 The DocTabbedParentFrame class provides a default top-level frame for
714 applications using the document/view framework. This class can only be
715 used for MDI parent frames that use a tabbed interface.
716
717 It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
718 classes.
719 """
720
721
722 def __init__(self, docManager, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "DocTabbedParentFrame", embeddedWindows = 0):
723 """
724 Constructor. Note that the event table must be rebuilt for the
725 frame since the EvtHandler is not virtual.
726 """
727 pos, size = self._GetPosSizeFromConfig(pos, size)
728 wx.Frame.__init__(self, frame, id, title, pos, size, style, name)
729
730 # From docview.MDIParentFrame
731 self._docManager = docManager
732
733 wx.EVT_CLOSE(self, self.OnCloseWindow)
734
735 wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
736 wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
737
738 wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
739 wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
740 wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
741 wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
742 wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
743 wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
744 wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
745 wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
746 wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
747 wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
748 wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
749 wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
750 wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
751
752 wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
753 wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
754 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
755 wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
756 wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
757 wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
758 wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
759 wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
760 wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
761 wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
762 wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
763 wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
764 # End From docview.MDIParentFrame
765
766 self.CreateNotebook()
767 self._InitFrame(embeddedWindows)
768
769
770 def _LayoutFrame(self):
771 """
772 Lays out the frame.
773 """
774 wx.LayoutAlgorithm().LayoutFrame(self, self._notebook)
775
776
777 def CreateNotebook(self):
778 """
779 Creates the notebook to use for the tabbed document interface.
780 """
781 if wx.Platform != "__WXMAC__":
782 self._notebook = wx.Notebook(self, wx.NewId())
783 else:
784 self._notebook = wx.Listbook(self, wx.NewId(), style=wx.LB_LEFT)
785 # self._notebook.SetSizer(wx.NotebookSizer(self._notebook))
786 if wx.Platform != "__WXMAC__":
787 wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
788 else:
789 wx.EVT_LISTBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
790 wx.EVT_RIGHT_DOWN(self._notebook, self.OnNotebookRightClick)
791 wx.EVT_MIDDLE_DOWN(self._notebook, self.OnNotebookMiddleClick)
792
793 # wxBug: wx.Listbook does not implement HitTest the same way wx.Notebook
794 # does, so for now don't fire MouseOver events.
795 if wx.Platform != "__WXMAC__":
796 wx.EVT_MOTION(self._notebook, self.OnNotebookMouseOver)
797
798 templates = wx.GetApp().GetDocumentManager().GetTemplates()
799 iconList = wx.ImageList(16, 16, initialCount = len(templates))
800 self._iconIndexLookup = []
801 for template in templates:
802 icon = template.GetIcon()
803 if icon:
804 if icon.GetHeight() != 16 or icon.GetWidth() != 16:
805 icon.SetHeight(16)
806 icon.SetWidth(16)
807 if wx.GetApp().GetDebug():
808 print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName
809 iconIndex = iconList.AddIcon(icon)
810 self._iconIndexLookup.append((template, iconIndex))
811
812 icon = getBlankIcon()
813 if icon.GetHeight() != 16 or icon.GetWidth() != 16:
814 icon.SetHeight(16)
815 icon.SetWidth(16)
816 if wx.GetApp().GetDebug():
817 print "Warning: getBlankIcon isn't 16x16, not crossplatform"
818 self._blankIconIndex = iconList.AddIcon(icon)
819 self._notebook.AssignImageList(iconList)
820
821
822 def GetNotebook(self):
823 """
824 Returns the notebook used by the tabbed document interface.
825 """
826 return self._notebook
827
828
829 def GetActiveChild(self):
830 """
831 Returns the active notebook page, which to the framework is treated as
832 a document frame.
833 """
834 index = self._notebook.GetSelection()
835 if index == -1:
836 return None
837 return self._notebook.GetPage(index)
838
839
840 def OnNotebookPageChanged(self, event):
841 """
842 Activates a notebook page's view when it is selected.
843 """
844 index = self._notebook.GetSelection()
845 if index > -1:
846 self._notebook.GetPage(index).GetView().Activate()
847
848
849 def OnNotebookMouseOver(self, event):
850 # wxBug: On Windows XP the tooltips don't automatically disappear when you move the mouse and it is on a notebook tab, has nothing to do with this code!!!
851 index, type = self._notebook.HitTest(event.GetPosition())
852
853 if index > -1:
854 doc = self._notebook.GetPage(index).GetView().GetDocument()
855 self._notebook.SetToolTip(wx.ToolTip(doc.GetFilename()))
856 else:
857 self._notebook.SetToolTip(wx.ToolTip(""))
858 event.Skip()
859
860
861 def OnNotebookMiddleClick(self, event):
862 """
863 Handles middle clicks for the notebook, closing the document whose tab was
864 clicked on.
865 """
866 index, type = self._notebook.HitTest(event.GetPosition())
867 if index > -1:
868 doc = self._notebook.GetPage(index).GetView().GetDocument()
869 if doc:
870 doc.DeleteAllViews()
871
872 def OnNotebookRightClick(self, event):
873 """
874 Handles right clicks for the notebook, enabling users to either close
875 a tab or select from the available documents if the user clicks on the
876 notebook's white space.
877 """
878 index, type = self._notebook.HitTest(event.GetPosition())
879 menu = wx.Menu()
880 x, y = event.GetX(), event.GetY()
881 if index > -1:
882 doc = self._notebook.GetPage(index).GetView().GetDocument()
883 id = wx.NewId()
884 menu.Append(id, _("Close"))
885 def OnRightMenuSelect(event):
886 doc.DeleteAllViews()
887 wx.EVT_MENU(self, id, OnRightMenuSelect)
888 if self._notebook.GetPageCount() > 1:
889 id = wx.NewId()
890 menu.Append(id, _("Close All but \"%s\"" % doc.GetPrintableName()))
891 def OnRightMenuSelect(event):
892 for i in range(self._notebook.GetPageCount()-1, -1, -1): # Go from len-1 to 0
893 if i != index:
894 doc = self._notebook.GetPage(i).GetView().GetDocument()
895 if not self.GetDocumentManager().CloseDocument(doc, False):
896 return
897 wx.EVT_MENU(self, id, OnRightMenuSelect)
898 menu.AppendSeparator()
899 tabsMenu = wx.Menu()
900 menu.AppendMenu(wx.NewId(), _("Select Tab"), tabsMenu)
901 else:
902 y = y - 25 # wxBug: It is offsetting click events in the blank notebook area
903 tabsMenu = menu
904
905 if self._notebook.GetPageCount() > 1:
906 selectIDs = {}
907 for i in range(0, self._notebook.GetPageCount()):
908 id = wx.NewId()
909 selectIDs[id] = i
910 tabsMenu.Append(id, self._notebook.GetPageText(i))
911 def OnRightMenuSelect(event):
912 self._notebook.SetSelection(selectIDs[event.GetId()])
913 wx.EVT_MENU(self, id, OnRightMenuSelect)
914
915 self._notebook.PopupMenu(menu, wx.Point(x, y))
916 menu.Destroy()
917
918
919 def AddNotebookPage(self, panel, title):
920 """
921 Adds a document page to the notebook.
922 """
923 self._notebook.AddPage(panel, title)
924 index = self._notebook.GetPageCount() - 1
925 self._notebook.SetSelection(index)
926
927 found = False # Now set the icon
928 template = panel.GetDocument().GetDocumentTemplate()
929 if template:
930 for t, iconIndex in self._iconIndexLookup:
931 if t is template:
932 self._notebook.SetPageImage(index, iconIndex)
933 found = True
934 break
935 if not found:
936 self._notebook.SetPageImage(index, self._blankIconIndex)
937
938 # wxBug: the wxListbook used on Mac needs its tabs list resized
939 # whenever a new tab is added, but the only way to do this is
940 # to resize the entire control
941 if wx.Platform == "__WXMAC__":
942 content_size = self._notebook.GetSize()
943 self._notebook.SetSize((content_size.x+2, -1))
944 self._notebook.SetSize((content_size.x, -1))
945
946 self._notebook.Layout()
947
948
949
950 def RemoveNotebookPage(self, panel):
951 """
952 Removes a document page from the notebook.
953 """
954 index = self.GetNotebookPageIndex(panel)
955 if index > -1:
956 self._notebook.DeletePage(index)
957
958
959 def ActivateNotebookPage(self, panel):
960 """
961 Sets the notebook to the specified panel.
962 """
963 index = self.GetNotebookPageIndex(panel)
964 if index > -1:
965 self._notebook.SetFocus()
966 self._notebook.SetSelection(index)
967
968
969 def GetNotebookPageTitle(self, panel):
970 return self._notebook.GetPageText(self.GetNotebookPageIndex(panel))
971
972
973 def SetNotebookPageTitle(self, panel, title):
974 self._notebook.SetPageText(self.GetNotebookPageIndex(panel), title)
975
976
977 def GetNotebookPageIndex(self, panel):
978 """
979 Returns the index of particular notebook panel.
980 """
981 index = -1
982 for i in range(self._notebook.GetPageCount()):
983 if self._notebook.GetPage(i) == panel:
984 index = i
985 break
986 return index
987
988
989 def ProcessEvent(self, event):
990 """
991 Processes an event, searching event tables and calling zero or more
992 suitable event handler function(s). Note that the ProcessEvent
993 method is called from the wxPython docview framework directly since
994 wxPython does not have a virtual ProcessEvent function.
995 """
996 if wx.GetApp().ProcessEventBeforeWindows(event):
997 return True
998 if self._docManager and self._docManager.ProcessEvent(event):
999 return True
1000 return DocMDIParentFrameMixIn.ProcessEvent(self, event)
1001
1002
1003 def ProcessUpdateUIEvent(self, event):
1004 """
1005 Processes a UI event, searching event tables and calling zero or more
1006 suitable event handler function(s). Note that the ProcessEvent
1007 method is called from the wxPython docview framework directly since
1008 wxPython does not have a virtual ProcessEvent function.
1009 """
1010 if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
1011 return True
1012 if self._docManager and self._docManager.ProcessUpdateUIEvent(event):
1013 return True
1014 return DocMDIParentFrameMixIn.ProcessUpdateUIEvent(self, event)
1015
1016
1017 def OnExit(self, event):
1018 """
1019 Called when File/Exit is chosen and closes the window.
1020 """
1021 self.Close()
1022
1023
1024 def OnMRUFile(self, event):
1025 """
1026 Opens the appropriate file when it is selected from the file history
1027 menu.
1028 """
1029 n = event.GetId() - wx.ID_FILE1
1030 filename = self._docManager.GetHistoryFile(n)
1031 if filename:
1032 self._docManager.CreateDocument(filename, wx.lib.docview.DOC_SILENT)
1033 else:
1034 self._docManager.RemoveFileFromHistory(n)
1035 msgTitle = wx.GetApp().GetAppName()
1036 if not msgTitle:
1037 msgTitle = _("File Error")
1038 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),
1039 msgTitle,
1040 wx.OK | wx.ICON_EXCLAMATION,
1041 self)
1042
1043
1044 def OnSize(self, event):
1045 """
1046 Called when the frame is resized and lays out the client window.
1047 """
1048 # Needed in case there are splitpanels around the mdi frame
1049 self._LayoutFrame()
1050
1051
1052 def OnCloseWindow(self, event):
1053 """
1054 Called when the frame is closed. Remembers the frame size.
1055 """
1056 self.SaveEmbeddedWindowSizes()
1057
1058 # save and close services last
1059 for service in wx.GetApp().GetServices():
1060 if not service.OnCloseFrame(event):
1061 return
1062
1063 # From docview.MDIParentFrame
1064 if self._docManager.Clear(not event.CanVeto()):
1065 self.Destroy()
1066 else:
1067 event.Veto()
1068
1069
1070 class DocMDIChildFrame(wx.MDIChildFrame):
1071 """
1072 The wxDocMDIChildFrame class provides a default frame for displaying
1073 documents on separate windows. This class can only be used for MDI child
1074 frames.
1075
1076 The class is part of the document/view framework supported by wxWindows,
1077 and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
1078 classes.
1079 """
1080
1081
1082 def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
1083 """
1084 Constructor. Note that the event table must be rebuilt for the
1085 frame since the EvtHandler is not virtual.
1086 """
1087 wx.MDIChildFrame.__init__(self, frame, id, title, pos, size, style, name)
1088 self._childDocument = doc
1089 self._childView = view
1090 if view:
1091 view.SetFrame(self)
1092 # self.Create(doc, view, frame, id, title, pos, size, style, name)
1093 self._activeEvent = None
1094 self._activated = 0
1095 wx.EVT_ACTIVATE(self, self.OnActivate)
1096 wx.EVT_CLOSE(self, self.OnCloseWindow)
1097
1098 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
1099 mdiChildren = filter(lambda x: isinstance(x, wx.MDIChildFrame), frame.GetChildren())
1100 if len(mdiChildren) == 1:
1101 self.Activate()
1102
1103
1104 ## # Couldn't get this to work, but seems to work fine with single stage construction
1105 ## def Create(self, doc, view, frame, id, title, pos, size, style, name):
1106 ## self._childDocument = doc
1107 ## self._childView = view
1108 ## if wx.MDIChildFrame.Create(self, frame, id, title, pos, size, style, name):
1109 ## if view:
1110 ## view.SetFrame(self)
1111 ## return True
1112 ## return False
1113
1114
1115
1116 def Activate(self): # Need this in case there are embedded sash windows and such, OnActivate is not getting called
1117 """
1118 Activates the current view.
1119 """
1120 if self._childView:
1121 self._childView.Activate(True)
1122
1123
1124 def ProcessEvent(event):
1125 """
1126 Processes an event, searching event tables and calling zero or more
1127 suitable event handler function(s). Note that the ProcessEvent
1128 method is called from the wxPython docview framework directly since
1129 wxPython does not have a virtual ProcessEvent function.
1130 """
1131 if self._activeEvent == event:
1132 return False
1133
1134 self._activeEvent = event # Break recursion loops
1135
1136 if self._childView:
1137 self._childView.Activate(True)
1138
1139 if not self._childView or not self._childView.ProcessEvent(event):
1140 if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
1141 ret = False
1142 else:
1143 ret = True
1144 else:
1145 ret = True
1146
1147 self._activeEvent = None
1148 return ret
1149
1150
1151 def OnActivate(self, event):
1152 """
1153 Sets the currently active view to be the frame's view. You may need to
1154 override (but still call) this function in order to set the keyboard
1155 focus for your subwindow.
1156 """
1157 if self._activated != 0:
1158 return True
1159 self._activated += 1
1160 wx.MDIChildFrame.Activate(self)
1161 if event.GetActive() and self._childView:
1162 self._childView.Activate(event.GetActive())
1163 self._activated = 0
1164
1165
1166 def OnCloseWindow(self, event):
1167 """
1168 Closes and deletes the current view and document.
1169 """
1170 if self._childView:
1171 ans = False
1172 if not event.CanVeto():
1173 ans = True
1174 else:
1175 ans = self._childView.Close(deleteWindow = False)
1176
1177 if ans:
1178 self._childView.Activate(False)
1179 self._childView.Destroy()
1180 self._childView = None
1181 if self._childDocument:
1182 self._childDocument.Destroy() # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
1183 self._childDocument = None
1184 self.Destroy()
1185 else:
1186 event.Veto()
1187 else:
1188 event.Veto()
1189
1190
1191 def GetDocument(self):
1192 """
1193 Returns the document associated with this frame.
1194 """
1195 return self._childDocument
1196
1197
1198 def SetDocument(self, document):
1199 """
1200 Sets the document for this frame.
1201 """
1202 self._childDocument = document
1203
1204
1205 def GetView(self):
1206 """
1207 Returns the view associated with this frame.
1208 """
1209 return self._childView
1210
1211
1212 def SetView(self, view):
1213 """
1214 Sets the view for this frame.
1215 """
1216 self._childView = view
1217
1218
1219
1220
1221
1222 class DocService(wx.EvtHandler):
1223 """
1224 An abstract class used to add reusable services to a docview application.
1225 """
1226
1227
1228 def __init__(self):
1229 """Initializes the DocService."""
1230 pass
1231
1232
1233 def GetDocumentManager(self):
1234 """Returns the DocManager for the docview application."""
1235 return self._docManager
1236
1237
1238 def SetDocumentManager(self, docManager):
1239 """Sets the DocManager for the docview application."""
1240 self._docManager = docManager
1241
1242
1243 def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
1244 """Called to install controls into the menubar and toolbar of a SDI or MDI window. Override this method for a particular service."""
1245 pass
1246
1247
1248 def ProcessEventBeforeWindows(self, event):
1249 """
1250 Processes an event before the main window has a chance to process the window.
1251 Override this method for a particular service.
1252 """
1253 return False
1254
1255
1256 def ProcessUpdateUIEventBeforeWindows(self, event):
1257 """
1258 Processes a UI event before the main window has a chance to process the window.
1259 Override this method for a particular service.
1260 """
1261 return False
1262
1263
1264 def ProcessEvent(self, event):
1265 """
1266 Processes an event, searching event tables and calling zero or more
1267 suitable event handler function(s). Note that the ProcessEvent
1268 method is called from the wxPython docview framework directly since
1269 wxPython does not have a virtual ProcessEvent function.
1270 """
1271 return False
1272
1273
1274 def ProcessUpdateUIEvent(self, event):
1275 """
1276 Processes a UI event, searching event tables and calling zero or more
1277 suitable event handler function(s). Note that the ProcessEvent
1278 method is called from the wxPython docview framework directly since
1279 wxPython does not have a virtual ProcessEvent function.
1280 """
1281 return False
1282
1283
1284 def OnCloseFrame(self, event):
1285 """
1286 Called when the a docview frame is being closed. Override this method
1287 so a service can either do cleanup or veto the frame being closed by
1288 returning false.
1289 """
1290 return True
1291
1292
1293 def OnExit(self):
1294 """
1295 Called when the the docview application is being closed. Override this method
1296 so a service can either do cleanup or veto the frame being closed by
1297 returning false.
1298 """
1299 pass
1300
1301
1302 def GetMenuItemPos(self, menu, id):
1303 """
1304 Utility method used to find the position of a menu item so that services can
1305 easily find where to insert a menu item in InstallControls.
1306 """
1307 menuItems = menu.GetMenuItems()
1308 for i, menuItem in enumerate(menuItems):
1309 if menuItem.GetId() == id:
1310 return i
1311 return i
1312
1313
1314 def GetView(self):
1315 """
1316 Called by WindowMenuService to get views for services that don't
1317 have dedicated documents such as the Outline Service.
1318 """
1319 return None
1320
1321
1322 class DocOptionsService(DocService):
1323 """
1324 A service that implements an options menu item and an options dialog with
1325 notebook tabs. New tabs can be added by other services by calling the
1326 "AddOptionsPanel" method.
1327 """
1328
1329
1330 def __init__(self, showGeneralOptions=True, supportedModes=wx.lib.docview.DOC_SDI & wx.lib.docview.DOC_MDI):
1331 """
1332 Initializes the options service with the option of suppressing the default
1333 general options pane that is included with the options service by setting
1334 showGeneralOptions to False. It allowModeChanges is set to False, the
1335 default general options pane will allow users to change the document
1336 interface mode between SDI and MDI modes.
1337 """
1338 DocService.__init__(self)
1339 self.ClearOptionsPanels()
1340 self._supportedModes = supportedModes
1341 self._toolOptionsID = wx.ID_PREFERENCES
1342 if showGeneralOptions:
1343 self.AddOptionsPanel(GeneralOptionsPanel)
1344
1345
1346 def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
1347 """
1348 Installs a "Tools" menu with an "Options" menu item.
1349 """
1350 toolsMenuIndex = menuBar.FindMenu(_("&Tools"))
1351 if toolsMenuIndex > -1:
1352 toolsMenu = menuBar.GetMenu(toolsMenuIndex)
1353 else:
1354 toolsMenu = wx.Menu()
1355 if toolsMenuIndex == -1:
1356 formatMenuIndex = menuBar.FindMenu(_("&Format"))
1357 menuBar.Insert(formatMenuIndex + 1, toolsMenu, _("&Tools"))
1358 if toolsMenu:
1359 if toolsMenu.GetMenuItemCount():
1360 toolsMenu.AppendSeparator()
1361 toolsMenu.Append(self._toolOptionsID, _("&Options..."), _("Sets options"))
1362 wx.EVT_MENU(frame, self._toolOptionsID, frame.ProcessEvent)
1363
1364
1365 def ProcessEvent(self, event):
1366 """
1367 Checks to see if the "Options" menu item has been selected.
1368 """
1369 id = event.GetId()
1370 if id == self._toolOptionsID:
1371 self.OnOptions(event)
1372 return True
1373 else:
1374 return False
1375
1376
1377 def GetSupportedModes(self):
1378 """
1379 Return the modes supported by the application. Use docview.DOC_SDI and
1380 docview.DOC_MDI flags to check if SDI and/or MDI modes are supported.
1381 """
1382 return self._supportedModes
1383
1384
1385 def SetSupportedModes(self, _supportedModessupportedModes):
1386 """
1387 Sets the modes supported by the application. Use docview.DOC_SDI and
1388 docview.DOC_MDI flags to set if SDI and/or MDI modes are supported.
1389 """
1390 self._supportedModes = supportedModes
1391
1392
1393 def ClearOptionsPanels(self):
1394 """
1395 Clears all of the options panels that have been added into the
1396 options dialog.
1397 """
1398 self._optionsPanels = []
1399
1400
1401 def AddOptionsPanel(self, optionsPanel):
1402 """
1403 Adds an options panel to the options dialog.
1404 """
1405 self._optionsPanels.append(optionsPanel)
1406
1407
1408 def OnOptions(self, event):
1409 """
1410 Shows the options dialog, called when the "Options" menu item is selected.
1411 """
1412 if len(self._optionsPanels) == 0:
1413 return
1414 optionsDialog = OptionsDialog(wx.GetApp().GetTopWindow(), self._optionsPanels, self._docManager)
1415 optionsDialog.CenterOnParent()
1416 if optionsDialog.ShowModal() == wx.ID_OK:
1417 optionsDialog.OnOK(optionsDialog) # wxBug: wxDialog should be calling this automatically but doesn't
1418 optionsDialog.Destroy()
1419
1420
1421 class OptionsDialog(wx.Dialog):
1422 """
1423 A default options dialog used by the OptionsService that hosts a notebook
1424 tab of options panels.
1425 """
1426
1427
1428 def __init__(self, parent, optionsPanelClasses, docManager):
1429 """
1430 Initializes the options dialog with a notebook page that contains new
1431 instances of the passed optionsPanelClasses.
1432 """
1433 wx.Dialog.__init__(self, parent, -1, _("Options"))
1434
1435 self._optionsPanels = []
1436 self._docManager = docManager
1437
1438 HALF_SPACE = 5
1439 SPACE = 10
1440
1441 sizer = wx.BoxSizer(wx.VERTICAL)
1442
1443 if wx.Platform == "__WXMAC__":
1444 optionsNotebook = wx.Listbook(self, wx.NewId(), style=wx.LB_DEFAULT)
1445 else:
1446 optionsNotebook = wx.Notebook(self, wx.NewId(), style=wx.NB_MULTILINE) # NB_MULTILINE is windows platform only
1447 sizer.Add(optionsNotebook, 0, wx.ALL | wx.EXPAND, SPACE)
1448
1449 if wx.Platform == "__WXMAC__":
1450 iconList = wx.ImageList(16, 16, initialCount = len(optionsPanelClasses))
1451 self._iconIndexLookup = []
1452
1453 for optionsPanelClass in optionsPanelClasses:
1454 optionsPanel = optionsPanelClass(optionsNotebook, -1)
1455 self._optionsPanels.append(optionsPanel)
1456
1457 # We need to populate the image list before setting notebook images
1458 if hasattr(optionsPanel, "GetIcon"):
1459 icon = optionsPanel.GetIcon()
1460 else:
1461 icon = None
1462 if icon:
1463 if icon.GetHeight() != 16 or icon.GetWidth() != 16:
1464 icon.SetHeight(16)
1465 icon.SetWidth(16)
1466 if wx.GetApp().GetDebug():
1467 print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName
1468 iconIndex = iconList.AddIcon(icon)
1469 self._iconIndexLookup.append((optionsPanel, iconIndex))
1470
1471 else:
1472 # use -1 to represent that this panel has no icon
1473 self._iconIndexLookup.append((optionsPanel, -1))
1474
1475 optionsNotebook.AssignImageList(iconList)
1476
1477 # Add icons to notebook
1478 for index in range(0, len(optionsPanelClasses)-1):
1479 iconIndex = self._iconIndexLookup[index][1]
1480 if iconIndex >= 0:
1481 optionsNotebook.SetPageImage(index, iconIndex)
1482 else:
1483 for optionsPanelClass in optionsPanelClasses:
1484 optionsPanel = optionsPanelClass(optionsNotebook, -1)
1485 self._optionsPanels.append(optionsPanel)
1486
1487 sizer.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
1488 self.SetSizer(sizer)
1489 self.Layout()
1490 self.Fit()
1491 wx.CallAfter(self.DoRefresh)
1492
1493
1494 def DoRefresh(self):
1495 """
1496 wxBug: On Windows XP when using a multiline notebook the default page doesn't get
1497 drawn, but it works when using a single line notebook.
1498 """
1499 self.Refresh()
1500
1501
1502 def GetDocManager(self):
1503 """
1504 Returns the document manager passed to the OptionsDialog constructor.
1505 """
1506 return self._docManager
1507
1508
1509 def OnOK(self, event):
1510 """
1511 Calls the OnOK method of all of the OptionDialog's embedded panels
1512 """
1513 for optionsPanel in self._optionsPanels:
1514 optionsPanel.OnOK(event)
1515
1516
1517 class GeneralOptionsPanel(wx.Panel):
1518 """
1519 A general options panel that is used in the OptionDialog to configure the
1520 generic properties of a pydocview application, such as "show tips at startup"
1521 and whether to use SDI or MDI for the application.
1522 """
1523
1524
1525 def __init__(self, parent, id):
1526 """
1527 Initializes the panel by adding an "Options" folder tab to the parent notebook and
1528 populating the panel with the generic properties of a pydocview application.
1529 """
1530 wx.Panel.__init__(self, parent, id)
1531 SPACE = 10
1532 HALF_SPACE = 5
1533 config = wx.ConfigBase_Get()
1534 self._showTipsCheckBox = wx.CheckBox(self, -1, _("Show tips at start up"))
1535 self._showTipsCheckBox.SetValue(config.ReadInt("ShowTipAtStartup", True))
1536 if self._AllowModeChanges():
1537 supportedModes = wx.GetApp().GetService(DocOptionsService).GetSupportedModes()
1538 choices = []
1539 self._sdiChoice = _("Show each document in its own window")
1540 self._mdiChoice = _("Show all documents in a single window with tabs")
1541 self._winMdiChoice = _("Show all documents in a single window with child windows")
1542 if supportedModes & wx.lib.docview.DOC_SDI:
1543 choices.append(self._sdiChoice)
1544 choices.append(self._mdiChoice)
1545 if wx.Platform == "__WXMSW__":
1546 choices.append(self._winMdiChoice)
1547 self._documentRadioBox = wx.RadioBox(self, -1, _("Document Interface"),
1548 choices = choices,
1549 majorDimension=1,
1550 )
1551 if config.ReadInt("UseWinMDI", False):
1552 self._documentRadioBox.SetStringSelection(self._winMdiChoice)
1553 elif config.ReadInt("UseMDI", True):
1554 self._documentRadioBox.SetStringSelection(self._mdiChoice)
1555 else:
1556 self._documentRadioBox.SetStringSelection(self._sdiChoice)
1557 def OnDocumentInterfaceSelect(event):
1558 if not self._documentInterfaceMessageShown:
1559 msgTitle = wx.GetApp().GetAppName()
1560 if not msgTitle:
1561 msgTitle = _("Document Options")
1562 wx.MessageBox(_("Document interface changes will not appear until the application is restarted."),
1563 msgTitle,
1564 wx.OK | wx.ICON_INFORMATION,
1565 self.GetParent())
1566 self._documentInterfaceMessageShown = True
1567 wx.EVT_RADIOBOX(self, self._documentRadioBox.GetId(), OnDocumentInterfaceSelect)
1568 optionsBorderSizer = wx.BoxSizer(wx.VERTICAL)
1569 optionsSizer = wx.BoxSizer(wx.VERTICAL)
1570 if self._AllowModeChanges():
1571 optionsSizer.Add(self._documentRadioBox, 0, wx.ALL, HALF_SPACE)
1572 optionsSizer.Add(self._showTipsCheckBox, 0, wx.ALL, HALF_SPACE)
1573 optionsBorderSizer.Add(optionsSizer, 0, wx.ALL, SPACE)
1574 self.SetSizer(optionsBorderSizer)
1575 self.Layout()
1576 self._documentInterfaceMessageShown = False
1577 parent.AddPage(self, _("Options"))
1578
1579
1580 def _AllowModeChanges(self):
1581 supportedModes = wx.GetApp().GetService(DocOptionsService).GetSupportedModes()
1582 return supportedModes & wx.lib.docview.DOC_SDI and supportedModes & wx.lib.docview.DOC_MDI or wx.Platform == "__WXMSW__" and supportedModes & wx.lib.docview.DOC_MDI # More than one mode is supported, allow selection
1583
1584
1585 def OnOK(self, optionsDialog):
1586 """
1587 Updates the config based on the selections in the options panel.
1588 """
1589 config = wx.ConfigBase_Get()
1590 config.WriteInt("ShowTipAtStartup", self._showTipsCheckBox.GetValue())
1591 if self._AllowModeChanges():
1592 config.WriteInt("UseMDI", (self._documentRadioBox.GetStringSelection() == self._mdiChoice))
1593 config.WriteInt("UseWinMDI", (self._documentRadioBox.GetStringSelection() == self._winMdiChoice))
1594
1595
1596 def GetIcon(self):
1597 """ Return icon for options panel on the Mac. """
1598 return wx.GetApp().GetDefaultIcon()
1599
1600
1601 class DocApp(wx.PySimpleApp):
1602 """
1603 The DocApp class serves as the base class for pydocview applications and offers
1604 functionality such as services, creation of SDI and MDI frames, show tips,
1605 and a splash screen.
1606 """
1607
1608
1609 def OnInit(self):
1610 """
1611 Initializes the DocApp.
1612 """
1613 self._services = []
1614 self._defaultIcon = None
1615 self._registeredCloseEvent = False
1616 self._useTabbedMDI = True
1617
1618 if not hasattr(self, "_debug"): # only set if not already initialized
1619 self._debug = False
1620 if not hasattr(self, "_singleInstance"): # only set if not already initialized
1621 self._singleInstance = True
1622
1623 # if _singleInstance is TRUE only allow one single instance of app to run.
1624 # When user tries to run a second instance of the app, abort startup,
1625 # But if user also specifies files to open in command line, send message to running app to open those files
1626 if self._singleInstance:
1627 # create shared memory temporary file
1628 if wx.Platform == '__WXMSW__':
1629 tfile = tempfile.TemporaryFile(prefix="ag", suffix="tmp")
1630 fno = tfile.fileno()
1631 self._sharedMemory = mmap.mmap(fno, 1024, "shared_memory")
1632 else:
1633 tfile = file(os.path.join(tempfile.gettempdir(), tempfile.gettempprefix() + self.GetAppName() + '-' + wx.GetUserId() + "AGSharedMemory"), 'w+b')
1634 tfile.write("*")
1635 tfile.seek(1024)
1636 tfile.write(" ")
1637 tfile.flush()
1638 fno = tfile.fileno()
1639 self._sharedMemory = mmap.mmap(fno, 1024)
1640
1641 self._singleInstanceChecker = wx.SingleInstanceChecker(self.GetAppName() + '-' + wx.GetUserId(), tempfile.gettempdir())
1642 if self._singleInstanceChecker.IsAnotherRunning():
1643 # have running single instance open file arguments
1644 data = pickle.dumps(sys.argv[1:])
1645 while 1:
1646 self._sharedMemory.seek(0)
1647 marker = self._sharedMemory.read_byte()
1648 if marker == '\0' or marker == '*': # available buffer
1649 self._sharedMemory.seek(0)
1650 self._sharedMemory.write_byte('-') # set writing marker
1651 self._sharedMemory.write(data) # write files we tried to open to shared memory
1652 self._sharedMemory.seek(0)
1653 self._sharedMemory.write_byte('+') # set finished writing marker
1654 self._sharedMemory.flush()
1655 break
1656 else:
1657 time.sleep(1) # give enough time for buffer to be available
1658
1659 return False
1660 else:
1661 self._timer = wx.PyTimer(self.DoBackgroundListenAndLoad)
1662 self._timer.Start(250)
1663
1664 return True
1665
1666
1667 def OpenMainFrame(self):
1668 docManager = self.GetDocumentManager()
1669 if docManager.GetFlags() & wx.lib.docview.DOC_MDI:
1670 if self.GetUseTabbedMDI():
1671 frame = wx.lib.pydocview.DocTabbedParentFrame(docManager, None, -1, self.GetAppName())
1672 else:
1673 frame = wx.lib.pydocview.DocMDIParentFrame(docManager, None, -1, self.GetAppName())
1674 frame.Show(True)
1675
1676 def MacOpenFile(self, filename):
1677 self.GetDocumentManager().CreateDocument(os.path.normpath(filename), wx.lib.docview.DOC_SILENT)
1678
1679 # force display of running app
1680 topWindow = wx.GetApp().GetTopWindow()
1681 if topWindow.IsIconized():
1682 topWindow.Iconize(False)
1683 else:
1684 topWindow.Raise()
1685
1686 def DoBackgroundListenAndLoad(self):
1687 """
1688 Open any files specified in the given command line argument passed in via shared memory
1689 """
1690 self._timer.Stop()
1691
1692 self._sharedMemory.seek(0)
1693 if self._sharedMemory.read_byte() == '+': # available data
1694 data = self._sharedMemory.read(1024-1)
1695 self._sharedMemory.seek(0)
1696 self._sharedMemory.write_byte("*") # finished reading, set buffer free marker
1697 self._sharedMemory.flush()
1698 args = pickle.loads(data)
1699 for arg in args:
1700 if (wx.Platform != "__WXMSW__" or arg[0] != "/") and arg[0] != '-' and os.path.exists(arg):
1701 self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT)
1702
1703 # force display of running app
1704 topWindow = wx.GetApp().GetTopWindow()
1705 if topWindow.IsIconized():
1706 topWindow.Iconize(False)
1707 else:
1708 topWindow.Raise()
1709
1710
1711 self._timer.Start(1000) # 1 second interval
1712
1713
1714 def OpenCommandLineArgs(self):
1715 """
1716 Called to open files that have been passed to the application from the
1717 command line.
1718 """
1719 args = sys.argv[1:]
1720 for arg in args:
1721 if (wx.Platform != "__WXMSW__" or arg[0] != "/") and arg[0] != '-' and os.path.exists(arg):
1722 self.GetDocumentManager().CreateDocument(os.path.normpath(arg), wx.lib.docview.DOC_SILENT)
1723
1724
1725 def GetDocumentManager(self):
1726 """
1727 Returns the document manager associated to the DocApp.
1728 """
1729 return self._docManager
1730
1731
1732 def SetDocumentManager(self, docManager):
1733 """
1734 Sets the document manager associated with the DocApp and loads the
1735 DocApp's file history into the document manager.
1736 """
1737 self._docManager = docManager
1738 config = wx.ConfigBase_Get()
1739 self.GetDocumentManager().FileHistoryLoad(config)
1740
1741
1742 def ProcessEventBeforeWindows(self, event):
1743 """
1744 Enables services to process an event before the main window has a chance to
1745 process the window.
1746 """
1747 for service in self._services:
1748 if service.ProcessEventBeforeWindows(event):
1749 return True
1750 return False
1751
1752
1753 def ProcessUpdateUIEventBeforeWindows(self, event):
1754 """
1755 Enables services to process a UI event before the main window has a chance
1756 to process the window.
1757 """
1758 for service in self._services:
1759 if service.ProcessUpdateUIEventBeforeWindows(event):
1760 return True
1761 return False
1762
1763
1764 def ProcessEvent(self, event):
1765 """
1766 Processes an event, searching event tables and calling zero or more
1767 suitable event handler function(s). Note that the ProcessEvent
1768 method is called from the wxPython docview framework directly since
1769 wxPython does not have a virtual ProcessEvent function.
1770 """
1771 for service in self._services:
1772 if service.ProcessEvent(event):
1773 return True
1774 return False
1775
1776
1777 def ProcessUpdateUIEvent(self, event):
1778 """
1779 Processes a UI event, searching event tables and calling zero or more
1780 suitable event handler function(s). Note that the ProcessEvent
1781 method is called from the wxPython docview framework directly since
1782 wxPython does not have a virtual ProcessEvent function.
1783 """
1784 for service in self._services:
1785 if service.ProcessUpdateUIEvent(event):
1786 return True
1787 return False
1788
1789
1790 def InstallService(self, service):
1791 """
1792 Installs an instance of a DocService into the DocApp.
1793 """
1794 service.SetDocumentManager(self._docManager)
1795 self._services.append(service)
1796 return service
1797
1798
1799 def GetServices(self):
1800 """
1801 Returns the DocService instances that have been installed into the DocApp.
1802 """
1803 return self._services
1804
1805
1806 def GetService(self, type):
1807 """
1808 Returns the instance of a particular type of service that has been installed
1809 into the DocApp. For example, "wx.GetApp().GetService(pydocview.OptionsService)"
1810 returns the isntance of the OptionsService that is running within the DocApp.
1811 """
1812 for service in self._services:
1813 if isinstance(service, type):
1814 return service
1815 return None
1816
1817
1818 def OnExit(self):
1819 """
1820 Called when the DocApp is exited, enables the installed DocServices to exit
1821 and saves the DocManager's file history.
1822 """
1823 for service in self._services:
1824 service.OnExit()
1825 config = wx.ConfigBase_Get()
1826 self._docManager.FileHistorySave(config)
1827
1828 if hasattr(self, "_singleInstanceChecker"):
1829 del self._singleInstanceChecker
1830
1831
1832 def GetDefaultDocManagerFlags(self):
1833 """
1834 Returns the default flags to use when creating the DocManager.
1835 """
1836 config = wx.ConfigBase_Get()
1837 if config.ReadInt("UseMDI", True) or config.ReadInt("UseWinMDI", False):
1838 flags = wx.lib.docview.DOC_MDI | wx.lib.docview.DOC_OPEN_ONCE
1839 if config.ReadInt("UseWinMDI", False):
1840 self.SetUseTabbedMDI(False)
1841 else:
1842 flags = wx.lib.docview.DOC_SDI | wx.lib.docview.DOC_OPEN_ONCE
1843 return flags
1844
1845
1846 def ShowTip(self, frame, tipProvider):
1847 """
1848 Shows the tip window, generally this is called when an application starts.
1849 A wx.TipProvider must be passed.
1850 """
1851 config = wx.ConfigBase_Get()
1852 showTip = config.ReadInt("ShowTipAtStartup", 1)
1853 if showTip:
1854 index = config.ReadInt("TipIndex", 0)
1855 showTipResult = wx.ShowTip(wx.GetApp().GetTopWindow(), tipProvider, showAtStartup = showTip)
1856 if showTipResult != showTip:
1857 config.WriteInt("ShowTipAtStartup", showTipResult)
1858
1859
1860 def GetEditMenu(self, frame):
1861 """
1862 Utility method that finds the Edit menu within the menubar of a frame.
1863 """
1864 menuBar = frame.GetMenuBar()
1865 if not menuBar:
1866 return None
1867 editMenuIndex = menuBar.FindMenu(_("&Edit"))
1868 if editMenuIndex == -1:
1869 return None
1870 return menuBar.GetMenu(editMenuIndex)
1871
1872
1873 def GetUseTabbedMDI(self):
1874 """
1875 Returns True if Windows MDI should use folder tabs instead of child windows.
1876 """
1877 return self._useTabbedMDI
1878
1879
1880 def SetUseTabbedMDI(self, useTabbedMDI):
1881 """
1882 Set to True if Windows MDI should use folder tabs instead of child windows.
1883 """
1884 self._useTabbedMDI = useTabbedMDI
1885
1886
1887 def CreateDocumentFrame(self, view, doc, flags, id = -1, title = "", pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
1888 """
1889 Called by the DocManager to create and return a new Frame for a Document.
1890 Chooses whether to create an MDIChildFrame or SDI Frame based on the
1891 DocManager's flags.
1892 """
1893 docflags = self.GetDocumentManager().GetFlags()
1894 if docflags & wx.lib.docview.DOC_SDI:
1895 frame = self.CreateSDIDocumentFrame(doc, view, id, title, pos, size, style)
1896 frame.Show()
1897
1898 # wxBug: operating system bug, first window is set to the position of last window closed, ignoring passed in position on frame creation
1899 # also, initial size is incorrect for the same reasons
1900 if frame.GetPosition() != pos:
1901 frame.Move(pos)
1902 if frame.GetSize() != size:
1903 frame.SetSize(size)
1904
1905 if doc and doc.GetCommandProcessor():
1906 doc.GetCommandProcessor().SetEditMenu(self.GetEditMenu(frame))
1907 elif docflags & wx.lib.docview.DOC_MDI:
1908 if self.GetUseTabbedMDI():
1909 frame = self.CreateTabbedDocumentFrame(doc, view, id, title, pos, size, style)
1910 else:
1911 frame = self.CreateMDIDocumentFrame(doc, view, id, title, pos, size, style)
1912 if doc:
1913 if doc.GetDocumentTemplate().GetIcon():
1914 frame.SetIcon(doc.GetDocumentTemplate().GetIcon())
1915 elif wx.GetApp().GetTopWindow().GetIcon():
1916 frame.SetIcon(wx.GetApp().GetTopWindow().GetIcon())
1917 if doc and doc.GetCommandProcessor():
1918 doc.GetCommandProcessor().SetEditMenu(self.GetEditMenu(wx.GetApp().GetTopWindow()))
1919 if not frame.GetIcon() and self._defaultIcon:
1920 frame.SetIcon(self.GetDefaultIcon())
1921 view.SetFrame(frame)
1922 return frame
1923
1924
1925 def CreateSDIDocumentFrame(self, doc, view, id=-1, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
1926 """
1927 Creates and returns an SDI Document Frame.
1928 """
1929 frame = DocSDIFrame(doc, view, None, id, title, pos, size, style)
1930 return frame
1931
1932
1933 def CreateTabbedDocumentFrame(self, doc, view, id=-1, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
1934 """
1935 Creates and returns an MDI Document Frame for a Tabbed MDI view
1936 """
1937 frame = DocTabbedChildFrame(doc, view, wx.GetApp().GetTopWindow(), id, title, pos, size, style)
1938 return frame
1939
1940
1941 def CreateMDIDocumentFrame(self, doc, view, id=-1, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
1942 """
1943 Creates and returns an MDI Document Frame.
1944 """
1945 # if any child windows are maximized, then user must want any new children maximized
1946 # if no children exist, then use the default value from registry
1947 # wxBug: Only current window is maximized, so need to check every child frame
1948 parentFrame = wx.GetApp().GetTopWindow()
1949 childrenMaximized = filter(lambda child: isinstance(child, wx.MDIChildFrame) and child.IsMaximized(), parentFrame.GetChildren())
1950 if childrenMaximized:
1951 maximize = True
1952 else:
1953 children = filter(lambda child: isinstance(child, wx.MDIChildFrame), parentFrame.GetChildren())
1954 if children:
1955 # other windows exist and none are maximized
1956 maximize = False
1957 else:
1958 # get default setting from registry
1959 maximize = wx.ConfigBase_Get().ReadInt("MDIChildFrameMaximized", False)
1960
1961 frame = wx.lib.docview.DocMDIChildFrame(doc, view, wx.GetApp().GetTopWindow(), id, title, pos, size, style)
1962 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
1963 frame.Maximize(True)
1964
1965 ## wx.EVT_MAXIMIZE(frame, self.OnMaximize) # wxBug: This doesn't work, need to save MDIChildFrameMaximized state on close of windows instead
1966 wx.EVT_CLOSE(frame, self.OnCloseChildWindow)
1967 if not self._registeredCloseEvent:
1968 wx.EVT_CLOSE(parentFrame, self.OnCloseMainWindow) # need to check on this, but only once
1969 self._registeredCloseEvent = True
1970
1971 return frame
1972
1973
1974 def SaveMDIDocumentFrameMaximizedState(self, maximized):
1975 """
1976 Remember in the config whether the MDI Frame is maximized so that it can be restored
1977 on open.
1978 """
1979 config = wx.ConfigBase_Get()
1980 maximizeFlag = config.ReadInt("MDIChildFrameMaximized", False)
1981 if maximized != maximizeFlag:
1982 config.WriteInt("MDIChildFrameMaximized", maximized)
1983
1984
1985 def OnCloseChildWindow(self, event):
1986 """
1987 Called when an MDI Child Frame is closed. Calls SaveMDIDocumentFrameMaximizedState to
1988 remember whether the MDI Frame is maximized so that it can be restored on open.
1989 """
1990 self.SaveMDIDocumentFrameMaximizedState(event.GetEventObject().IsMaximized())
1991 event.Skip()
1992
1993
1994 def OnCloseMainWindow(self, event):
1995 """
1996 Called when the MDI Parent Frame is closed. Remembers whether the MDI Parent Frame is
1997 maximized.
1998 """
1999 children = event.GetEventObject().GetChildren()
2000 childrenMaximized = filter(lambda child: isinstance(child, wx.MDIChildFrame)and child.IsMaximized(), children)
2001 if childrenMaximized:
2002 self.SaveMDIDocumentFrameMaximizedState(True)
2003 else:
2004 childrenNotMaximized = filter(lambda child: isinstance(child, wx.MDIChildFrame), children)
2005
2006 if childrenNotMaximized:
2007 # other windows exist and none are maximized
2008 self.SaveMDIDocumentFrameMaximizedState(False)
2009
2010 event.Skip()
2011
2012
2013 def GetDefaultIcon(self):
2014 """
2015 Returns the application's default icon.
2016 """
2017 return self._defaultIcon
2018
2019
2020 def SetDefaultIcon(self, icon):
2021 """
2022 Sets the application's default icon.
2023 """
2024 self._defaultIcon = icon
2025
2026
2027 def GetDebug(self):
2028 """
2029 Returns True if the application is in debug mode.
2030 """
2031 return self._debug
2032
2033
2034 def SetDebug(self, debug):
2035 """
2036 Sets the application's debug mode.
2037 """
2038 self._debug = debug
2039
2040
2041 def GetSingleInstance(self):
2042 """
2043 Returns True if the application is in single instance mode. Used to determine if multiple instances of the application is allowed to launch.
2044 """
2045 return self._singleInstance
2046
2047
2048 def SetSingleInstance(self, singleInstance):
2049 """
2050 Sets application's single instance mode.
2051 """
2052 self._singleInstance = singleInstance
2053
2054
2055
2056 def CreateChildDocument(self, parentDocument, documentType, objectToEdit, path=''):
2057 """
2058 Creates a child window of a document that edits an object. The child window
2059 is managed by the parent document frame, so it will be prompted to close if its
2060 parent is closed, etc. Child Documents are useful when there are complicated
2061 Views of a Document and users will need to tunnel into the View.
2062 """
2063 for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
2064 if isinstance(document, ChildDocument) and document.GetParentDocument() == parentDocument:
2065 if document.GetData() == objectToEdit:
2066 if hasattr(document.GetFirstView().GetFrame(), "SetFocus"):
2067 document.GetFirstView().GetFrame().SetFocus()
2068 return document
2069 for temp in wx.GetApp().GetDocumentManager().GetTemplates():
2070 if temp.GetDocumentType() == documentType:
2071 break
2072 temp = None
2073 newDoc = temp.CreateDocument(path, 0, data = objectToEdit, parentDocument = parentDocument)
2074 newDoc.SetDocumentName(temp.GetDocumentName())
2075 newDoc.SetDocumentTemplate(temp)
2076 if path == '':
2077 newDoc.OnNewDocument()
2078 else:
2079 if not newDoc.OnOpenDocument(path):
2080 newDoc.DeleteAllViews() # Implicitly deleted by DeleteAllViews
2081 return None
2082 return newDoc
2083
2084
2085 def CloseChildDocuments(self, parentDocument):
2086 """
2087 Closes the child windows of a Document.
2088 """
2089 for document in self.GetDocumentManager().GetDocuments()[:]: # Cloning list to make sure we go through all docs even as they are deleted
2090 if isinstance(document, ChildDocument) and document.GetParentDocument() == parentDocument:
2091 if document.GetFirstView().GetFrame():
2092 document.GetFirstView().GetFrame().SetFocus()
2093 if not document.GetFirstView().OnClose():
2094 return False
2095 return True
2096
2097
2098 def IsMDI(self):
2099 """
2100 Returns True if the application is in MDI mode.
2101 """
2102 return self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_MDI
2103
2104
2105 def IsSDI(self):
2106 """
2107 Returns True if the application is in SDI mode.
2108 """
2109 return self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI
2110
2111
2112 def ShowSplash(self, image):
2113 """
2114 Shows a splash window with the given image. Input parameter 'image' can either be a wx.Bitmap or a filename.
2115 """
2116 if isinstance(image, wx.Bitmap):
2117 splash_bmp = image
2118 else:
2119 splash_bmp = wx.Image(image).ConvertToBitmap()
2120 self._splash = wx.SplashScreen(splash_bmp, wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_NO_TIMEOUT, 0, None, -1, style=wx.SIMPLE_BORDER|wx.FRAME_NO_TASKBAR)
2121 self._splash.Show()
2122
2123
2124 def CloseSplash(self):
2125 """
2126 Closes the splash window.
2127 """
2128 if self._splash:
2129 self._splash.Close(True)
2130
2131
2132 class _DocFrameFileDropTarget(wx.FileDropTarget):
2133 """
2134 Class used to handle drops into the document frame.
2135 """
2136
2137 def __init__(self, docManager, docFrame):
2138 """
2139 Initializes the FileDropTarget class with the active docManager and the docFrame.
2140 """
2141 wx.FileDropTarget.__init__(self)
2142 self._docManager = docManager
2143 self._docFrame = docFrame
2144
2145
2146 def OnDropFiles(self, x, y, filenames):
2147 """
2148 Called when files are dropped in the drop target and tells the docManager to open
2149 the files.
2150 """
2151 try:
2152 for file in filenames:
2153 self._docManager.CreateDocument(file, wx.lib.docview.DOC_SILENT)
2154 except:
2155 msgTitle = wx.GetApp().GetAppName()
2156 if not msgTitle:
2157 msgTitle = _("File Error")
2158 wx.MessageBox("Could not open '%s'. '%s'" % (docview.FileNameFromPath(file), sys.exc_value),
2159 msgTitle,
2160 wx.OK | wx.ICON_EXCLAMATION,
2161 self._docManager.FindSuitableParent())
2162
2163
2164 class DocMDIParentFrame(wx.lib.docview.DocMDIParentFrame, DocFrameMixIn, DocMDIParentFrameMixIn):
2165 """
2166 The DocMDIParentFrame is the primary frame which the DocApp uses to host MDI child windows. It offers
2167 features such as a default menubar, toolbar, and status bar, and a mechanism to manage embedded windows
2168 on the edges of the DocMDIParentFrame.
2169 """
2170
2171
2172 def __init__(self, docManager, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="DocMDIFrame", embeddedWindows=0):
2173 """
2174 Initializes the DocMDIParentFrame with the default menubar, toolbar, and status bar. Use the
2175 optional embeddedWindows parameter with the embedded window constants to create embedded
2176 windows around the edges of the DocMDIParentFrame.
2177 """
2178 pos, size = self._GetPosSizeFromConfig(pos, size)
2179 wx.lib.docview.DocMDIParentFrame.__init__(self, docManager, parent, id, title, pos, size, style, name)
2180 self._InitFrame(embeddedWindows)
2181
2182
2183 def _LayoutFrame(self):
2184 """
2185 Lays out the frame.
2186 """
2187 wx.LayoutAlgorithm().LayoutMDIFrame(self)
2188 self.GetClientWindow().Refresh()
2189
2190
2191 def ProcessEvent(self, event):
2192 """
2193 Processes an event, searching event tables and calling zero or more
2194 suitable event handler function(s). Note that the ProcessEvent
2195 method is called from the wxPython docview framework directly since
2196 wxPython does not have a virtual ProcessEvent function.
2197 """
2198 if wx.GetApp().ProcessEventBeforeWindows(event):
2199 return True
2200 if wx.lib.docview.DocMDIParentFrame.ProcessEvent(self, event):
2201 return True
2202 return DocMDIParentFrameMixIn.ProcessEvent(self, event)
2203
2204
2205 def ProcessUpdateUIEvent(self, event):
2206 """
2207 Processes a UI event, searching event tables and calling zero or more
2208 suitable event handler function(s). Note that the ProcessEvent
2209 method is called from the wxPython docview framework directly since
2210 wxPython does not have a virtual ProcessEvent function.
2211 """
2212 if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
2213 return True
2214 if wx.lib.docview.DocMDIParentFrame.ProcessUpdateUIEvent(self, event): # Let the views handle the event before the services
2215 return True
2216 if event.GetId() == wx.ID_ABOUT: # Using ID_ABOUT to update the window menu, the window menu items are not triggering
2217 self.UpdateWindowMenu()
2218 return True
2219 return DocMDIParentFrameMixIn.ProcessUpdateUIEvent(self, event)
2220
2221
2222 def UpdateWindowMenu(self):
2223 """
2224 Updates the WindowMenu on Windows platforms.
2225 """
2226 if wx.Platform == '__WXMSW__':
2227 children = filter(lambda child: isinstance(child, wx.MDIChildFrame), self.GetChildren())
2228 windowCount = len(children)
2229 hasWindow = windowCount >= 1
2230 has2OrMoreWindows = windowCount >= 2
2231
2232 windowMenu = self.GetWindowMenu()
2233 if windowMenu:
2234 windowMenu.Enable(wx.IDM_WINDOWTILE, hasWindow)
2235 windowMenu.Enable(wx.IDM_WINDOWTILEHOR, hasWindow)
2236 windowMenu.Enable(wx.IDM_WINDOWCASCADE, hasWindow)
2237 windowMenu.Enable(wx.IDM_WINDOWICONS, hasWindow)
2238 windowMenu.Enable(wx.IDM_WINDOWTILEVERT, hasWindow)
2239 wx.IDM_WINDOWPREV = 4006 # wxBug: Not defined for some reason
2240 windowMenu.Enable(wx.IDM_WINDOWPREV, has2OrMoreWindows)
2241 windowMenu.Enable(wx.IDM_WINDOWNEXT, has2OrMoreWindows)
2242
2243
2244
2245 def OnSize(self, event):
2246 """
2247 Called when the DocMDIParentFrame is resized and lays out the MDI client window.
2248 """
2249 # Needed in case there are splitpanels around the mdi frame
2250 self._LayoutFrame()
2251
2252
2253 def OnCloseWindow(self, event):
2254 """
2255 Called when the DocMDIParentFrame is closed. Remembers the frame size.
2256 """
2257 self.SaveEmbeddedWindowSizes()
2258
2259 # save and close services last.
2260 for service in wx.GetApp().GetServices():
2261 if not service.OnCloseFrame(event):
2262 return
2263
2264 # save and close documents
2265 # documents with a common view, e.g. project view, should save the document, but not close the window
2266 # and let the service close the window.
2267 wx.lib.docview.DocMDIParentFrame.OnCloseWindow(self, event)
2268
2269
2270 class DocSDIFrame(wx.lib.docview.DocChildFrame, DocFrameMixIn):
2271 """
2272 The DocSDIFrame host DocManager Document windows. It offers features such as a default menubar,
2273 toolbar, and status bar.
2274 """
2275
2276
2277 def __init__(self, doc, view, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="DocSDIFrame"):
2278 """
2279 Initializes the DocSDIFrame with the default menubar, toolbar, and status bar.
2280 """
2281 wx.lib.docview.DocChildFrame.__init__(self, doc, view, parent, id, title, pos, size, style, name)
2282 self._fileMenu = None
2283 if doc:
2284 self._docManager = doc.GetDocumentManager()
2285 else:
2286 self._docManager = None
2287 self.SetDropTarget(_DocFrameFileDropTarget(self._docManager, self))
2288
2289 wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
2290 wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
2291 wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
2292
2293 self.InitializePrintData()
2294
2295 menuBar = self.CreateDefaultMenuBar(sdi=True)
2296 toolBar = self.CreateDefaultToolBar()
2297 self.SetToolBar(toolBar)
2298 statusBar = self.CreateDefaultStatusBar()
2299
2300 for service in wx.GetApp().GetServices():
2301 service.InstallControls(self, menuBar = menuBar, toolBar = toolBar, statusBar = statusBar, document = doc)
2302
2303 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
2304
2305
2306 def _LayoutFrame(self):
2307 """
2308 Lays out the Frame.
2309 """
2310 self.Layout()
2311
2312
2313 def OnExit(self, event):
2314 """
2315 Called when the application is exitting.
2316 """
2317 if self._childView.GetDocumentManager().Clear(force = False):
2318 self.Destroy()
2319 else:
2320 event.Veto()
2321
2322
2323 def OnMRUFile(self, event):
2324 """
2325 Opens the appropriate file when it is selected from the file history
2326 menu.
2327 """
2328 n = event.GetId() - wx.ID_FILE1
2329 filename = self._docManager.GetHistoryFile(n)
2330 if filename:
2331 self._docManager.CreateDocument(filename, wx.lib.docview.DOC_SILENT)
2332 else:
2333 self._docManager.RemoveFileFromHistory(n)
2334 msgTitle = wx.GetApp().GetAppName()
2335 if not msgTitle:
2336 msgTitle = _("File Error")
2337 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),
2338 msgTitle,
2339 wx.OK | wx.ICON_EXCLAMATION,
2340 self)
2341
2342
2343 def ProcessEvent(self, event):
2344 """
2345 Processes an event, searching event tables and calling zero or more
2346 suitable event handler function(s). Note that the ProcessEvent
2347 method is called from the wxPython docview framework directly since
2348 wxPython does not have a virtual ProcessEvent function.
2349 """
2350 if wx.GetApp().ProcessEventBeforeWindows(event):
2351 return True
2352 if self._childView:
2353 self._childView.Activate(True)
2354
2355 id = event.GetId()
2356 if id == SAVEALL_ID:
2357 self.OnFileSaveAll(event)
2358 return True
2359
2360 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
2361 return True
2362 else:
2363 return wx.GetApp().ProcessEvent(event)
2364
2365
2366 def ProcessUpdateUIEvent(self, event):
2367 """
2368 Processes a UI event, searching event tables and calling zero or more
2369 suitable event handler function(s). Note that the ProcessEvent
2370 method is called from the wxPython docview framework directly since
2371 wxPython does not have a virtual ProcessEvent function.
2372 """
2373 if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
2374 return True
2375 if self._childView:
2376 if hasattr(self._childView, "GetDocumentManager"):
2377 docMgr = self._childView.GetDocumentManager()
2378 if docMgr:
2379 if docMgr.GetCurrentDocument() != self._childView.GetDocument():
2380 return False
2381 if docMgr.ProcessUpdateUIEvent(event): # Let the views handle the event before the services
2382 return True
2383 id = event.GetId()
2384 if id == wx.ID_CUT:
2385 event.Enable(False)
2386 return True
2387 elif id == wx.ID_COPY:
2388 event.Enable(False)
2389 return True
2390 elif id == wx.ID_PASTE:
2391 event.Enable(False)
2392 return True
2393 elif id == wx.ID_CLEAR:
2394 event.Enable(False)
2395 return True
2396 elif id == wx.ID_SELECTALL:
2397 event.Enable(False)
2398 return True
2399 elif id == SAVEALL_ID:
2400 filesModified = False
2401 docs = wx.GetApp().GetDocumentManager().GetDocuments()
2402 for doc in docs:
2403 if doc.IsModified():
2404 filesModified = True
2405 break
2406
2407 event.Enable(filesModified)
2408 return True
2409 else:
2410 return wx.GetApp().ProcessUpdateUIEvent(event)
2411
2412
2413 def OnCloseWindow(self, event):
2414 """
2415 Called when the window is saved. Enables services to help close the frame.
2416 """
2417 for service in wx.GetApp().GetServices():
2418 service.OnCloseFrame(event)
2419 wx.lib.docview.DocChildFrame.OnCloseWindow(self, event)
2420 if self._fileMenu and self._docManager:
2421 self._docManager.FileHistoryRemoveMenu(self._fileMenu)
2422
2423
2424 class AboutService(DocService):
2425 """
2426 About Dialog Service that installs under the Help menu to show the properties of the current application.
2427 """
2428
2429 def __init__(self, aboutDialog=None, image=None):
2430 """
2431 Initializes the AboutService.
2432 """
2433 if aboutDialog:
2434 self._dlg = aboutDialog
2435 self._image = None
2436 else:
2437 self._dlg = AboutDialog # use default AboutDialog
2438 self._image = image
2439
2440
2441 def ShowAbout(self):
2442 """
2443 Show the AboutDialog
2444 """
2445 if self._image:
2446 dlg = self._dlg(wx.GetApp().GetTopWindow(), self._image)
2447 else:
2448 dlg = self._dlg(wx.GetApp().GetTopWindow())
2449 dlg.CenterOnParent()
2450 dlg.ShowModal()
2451 dlg.Destroy()
2452
2453
2454 def SetAboutDialog(self, dlg):
2455 """
2456 Customize the AboutDialog
2457 """
2458 self._dlg = dlg
2459
2460
2461 class AboutDialog(wx.Dialog):
2462 """
2463 Opens an AboutDialog. Shared by DocMDIParentFrame and DocSDIFrame.
2464 """
2465
2466 def __init__(self, parent, image=None):
2467 """
2468 Initializes the about dialog.
2469 """
2470 wx.Dialog.__init__(self, parent, -1, _("About ") + wx.GetApp().GetAppName(), style = wx.DEFAULT_DIALOG_STYLE)
2471
2472 sizer = wx.BoxSizer(wx.VERTICAL)
2473 if image:
2474 imageItem = wx.StaticBitmap(self, -1, image.ConvertToBitmap(), (0,0), (image.GetWidth(), image.GetHeight()))
2475 sizer.Add(imageItem, 0, wx.ALIGN_CENTER|wx.ALL, 0)
2476 sizer.Add(wx.StaticText(self, -1, wx.GetApp().GetAppName()), 0, wx.ALIGN_CENTRE|wx.ALL, 5)
2477
2478 btn = wx.Button(self, wx.ID_OK)
2479 sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
2480
2481 self.SetSizer(sizer)
2482 sizer.Fit(self)
2483
2484
2485
2486 class FilePropertiesService(DocService):
2487 """
2488 Service that installs under the File menu to show the properties of the file associated
2489 with the current document.
2490 """
2491
2492 PROPERTIES_ID = wx.NewId()
2493
2494
2495 def __init__(self):
2496 """
2497 Initializes the PropertyService.
2498 """
2499 self._customEventHandlers = []
2500
2501
2502 def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
2503 """
2504 Installs a File/Properties menu item.
2505 """
2506 fileMenu = menuBar.GetMenu(menuBar.FindMenu(_("&File")))
2507 exitMenuItemPos = self.GetMenuItemPos(fileMenu, wx.ID_EXIT)
2508 fileMenu.InsertSeparator(exitMenuItemPos)
2509 fileMenu.Insert(exitMenuItemPos, FilePropertiesService.PROPERTIES_ID, _("&Properties"), _("Show file properties"))
2510 wx.EVT_MENU(frame, FilePropertiesService.PROPERTIES_ID, self.ProcessEvent)
2511 wx.EVT_UPDATE_UI(frame, FilePropertiesService.PROPERTIES_ID, self.ProcessUpdateUIEvent)
2512
2513
2514 def ProcessEvent(self, event):
2515 """
2516 Detects when the File/Properties menu item is selected.
2517 """
2518 id = event.GetId()
2519 if id == FilePropertiesService.PROPERTIES_ID:
2520 for eventHandler in self._customEventHandlers:
2521 if eventHandler.ProcessEvent(event):
2522 return True
2523
2524 self.ShowPropertiesDialog()
2525 return True
2526 else:
2527 return False
2528
2529
2530 def ProcessUpdateUIEvent(self, event):
2531 """
2532 Updates the File/Properties menu item.
2533 """
2534 id = event.GetId()
2535 if id == FilePropertiesService.PROPERTIES_ID:
2536 for eventHandler in self._customEventHandlers:
2537 if eventHandler.ProcessUpdateUIEvent(event):
2538 return True
2539
2540 event.Enable(wx.GetApp().GetDocumentManager().GetCurrentDocument() != None)
2541 return True
2542 else:
2543 return False
2544
2545
2546 def ShowPropertiesDialog(self, filename=None):
2547 """
2548 Shows the PropertiesDialog for the specified file.
2549 """
2550 if not filename:
2551 filename = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
2552
2553 filePropertiesDialog = FilePropertiesDialog(wx.GetApp().GetTopWindow(), filename)
2554 filePropertiesDialog.CenterOnParent()
2555 if filePropertiesDialog.ShowModal() == wx.ID_OK:
2556 pass # Handle OK
2557 filePropertiesDialog.Destroy()
2558
2559
2560 def GetCustomEventHandlers(self):
2561 """
2562 Returns the custom event handlers for the PropertyService.
2563 """
2564 return self._customEventHandlers
2565
2566
2567 def AddCustomEventHandler(self, handler):
2568 """
2569 Adds a custom event handlers for the PropertyService. A custom event handler enables
2570 a different dialog to be provided for a particular file.
2571 """
2572 self._customEventHandlers.append(handler)
2573
2574
2575 def RemoveCustomEventHandler(self, handler):
2576 """
2577 Removes a custom event handler from the PropertyService.
2578 """
2579 self._customEventHandlers.remove(handler)
2580
2581
2582 def chopPath(self, text, length=36):
2583 """
2584 Simple version of textwrap. textwrap.fill() unfortunately chops lines at spaces
2585 and creates odd word boundaries. Instead, we will chop the path without regard to
2586 spaces, but pay attention to path delimiters.
2587 """
2588 chopped = ""
2589 textLen = len(text)
2590 start = 0
2591
2592 while start < textLen:
2593 end = start + length
2594 if end > textLen:
2595 end = textLen
2596
2597 # see if we can find a delimiter to chop the path
2598 if end < textLen:
2599 lastSep = text.rfind(os.sep, start, end + 1)
2600 if lastSep != -1 and lastSep != start:
2601 end = lastSep
2602
2603 if len(chopped):
2604 chopped = chopped + '\n' + text[start:end]
2605 else:
2606 chopped = text[start:end]
2607
2608 start = end
2609
2610 return chopped
2611
2612
2613 class FilePropertiesDialog(wx.Dialog):
2614 """
2615 Dialog that shows the properties of a file. Invoked by the PropertiesService.
2616 """
2617
2618
2619 def __init__(self, parent, filename):
2620 """
2621 Initializes the properties dialog.
2622 """
2623 wx.Dialog.__init__(self, parent, -1, _("File Properties"), size=(310, 330))
2624
2625 HALF_SPACE = 5
2626 SPACE = 10
2627
2628 filePropertiesService = wx.GetApp().GetService(FilePropertiesService)
2629
2630 fileExists = os.path.exists(filename)
2631
2632 notebook = wx.Notebook(self, -1)
2633 tab = wx.Panel(notebook, -1)
2634
2635 gridSizer = RowColSizer()
2636
2637 gridSizer.Add(wx.StaticText(tab, -1, _("Filename:")), flag=wx.RIGHT, border=HALF_SPACE, row=0, col=0)
2638 gridSizer.Add(wx.StaticText(tab, -1, os.path.basename(filename)), row=0, col=1)
2639
2640 gridSizer.Add(wx.StaticText(tab, -1, _("Location:")), flag=wx.RIGHT, border=HALF_SPACE, row=1, col=0)
2641 gridSizer.Add(wx.StaticText(tab, -1, filePropertiesService.chopPath(os.path.dirname(filename))), flag=wx.BOTTOM, border=SPACE, row=1, col=1)
2642
2643 gridSizer.Add(wx.StaticText(tab, -1, _("Size:")), flag=wx.RIGHT, border=HALF_SPACE, row=2, col=0)
2644 if fileExists:
2645 gridSizer.Add(wx.StaticText(tab, -1, str(os.path.getsize(filename)) + ' ' + _("bytes")), row=2, col=1)
2646
2647 lineSizer = wx.BoxSizer(wx.VERTICAL) # let the line expand horizontally without vertical expansion
2648 lineSizer.Add(wx.StaticLine(tab, -1, size = (10,-1)), 0, wx.EXPAND)
2649 gridSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=HALF_SPACE, row=3, col=0, colspan=2)
2650
2651 gridSizer.Add(wx.StaticText(tab, -1, _("Created:")), flag=wx.RIGHT, border=HALF_SPACE, row=4, col=0)
2652 if fileExists:
2653 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getctime(filename))), row=4, col=1)
2654
2655 gridSizer.Add(wx.StaticText(tab, -1, _("Modified:")), flag=wx.RIGHT, border=HALF_SPACE, row=5, col=0)
2656 if fileExists:
2657 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getmtime(filename))), row=5, col=1)
2658
2659 gridSizer.Add(wx.StaticText(tab, -1, _("Accessed:")), flag=wx.RIGHT, border=HALF_SPACE, row=6, col=0)
2660 if fileExists:
2661 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getatime(filename))), row=6, col=1)
2662
2663 # add a border around the inside of the tab
2664 spacerGrid = wx.BoxSizer(wx.VERTICAL)
2665 spacerGrid.Add(gridSizer, 0, wx.ALL, SPACE);
2666 tab.SetSizer(spacerGrid)
2667 notebook.AddPage(tab, _("General"))
2668
2669 sizer = wx.BoxSizer(wx.VERTICAL)
2670 sizer.Add(notebook, 0, wx.ALL | wx.EXPAND, SPACE)
2671 sizer.Add(self.CreateButtonSizer(wx.OK), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
2672
2673 sizer.Fit(self)
2674 self.SetDimensions(-1, -1, 310, -1, wx.SIZE_USE_EXISTING)
2675 self.SetSizer(sizer)
2676 self.Layout()
2677
2678
2679 class ChildDocument(wx.lib.docview.Document):
2680 """
2681 A ChildDocument is a document that represents a portion of a Document. The child
2682 document is managed by the parent document, so it will be prompted to close if its
2683 parent is closed, etc. Child Documents are useful when there are complicated
2684 Views of a Document and users will need to tunnel into the View.
2685 """
2686
2687
2688 def GetData(self):
2689 """
2690 Returns the data that the ChildDocument contains.
2691 """
2692 return self._data
2693
2694
2695 def SetData(self, data):
2696 """
2697 Sets the data that the ChildDocument contains.
2698 """
2699 self._data = data
2700
2701
2702 def GetParentDocument(self):
2703 """
2704 Returns the parent Document of the ChildDocument.
2705 """
2706 return self._parentDocument
2707
2708
2709 def SetParentDocument(self, parentDocument):
2710 """
2711 Sets the parent Document of the ChildDocument.
2712 """
2713 self._parentDocument = parentDocument
2714
2715
2716 def OnSaveDocument(self, filename):
2717 """
2718 Called when the ChildDocument is saved and does the minimum such that the
2719 ChildDocument looks like a real Document to the framework.
2720 """
2721 self.SetFilename(filename, True)
2722 self.Modify(False)
2723 self.SetDocumentSaved(True)
2724 return True
2725
2726
2727 def OnOpenDocument(self, filename):
2728 """
2729 Called when the ChildDocument is opened and does the minimum such that the
2730 ChildDocument looks like a real Document to the framework.
2731 """
2732 self.SetFilename(filename, True)
2733 self.Modify(False)
2734 self.SetDocumentSaved(True)
2735 self.UpdateAllViews()
2736 return True
2737
2738
2739 def Save(self):
2740 """
2741 Called when the ChildDocument is saved and does the minimum such that the
2742 ChildDocument looks like a real Document to the framework.
2743 """
2744 return self.OnSaveDocument(self._documentFile)
2745
2746
2747 def SaveAs(self):
2748 """
2749 Called when the ChildDocument is saved and does the minimum such that the
2750 ChildDocument looks like a real Document to the framework.
2751 """
2752 return self.OnSaveDocument(self._documentFile)
2753
2754
2755 class ChildDocTemplate(wx.lib.docview.DocTemplate):
2756 """
2757 A ChildDocTemplate is a DocTemplate subclass that enables the creation of ChildDocuments
2758 that represents a portion of a Document. The child document is managed by the parent document,
2759 so it will be prompted to close if its parent is closed, etc. Child Documents are useful
2760 when there are complicated Views of a Document and users will need to tunnel into the View.
2761 """
2762
2763
2764 def __init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags=wx.lib.docview.TEMPLATE_INVISIBLE, icon=None):
2765 """
2766 Initializes the ChildDocTemplate.
2767 """
2768 wx.lib.docview.DocTemplate.__init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags=flags, icon=icon)
2769
2770
2771 def CreateDocument(self, path, flags, data=None, parentDocument=None):
2772 """
2773 Called when a ChildDocument is to be created and does the minimum such that the
2774 ChildDocument looks like a real Document to the framework.
2775 """
2776 doc = self._docType()
2777 doc.SetFilename(path)
2778 doc.SetData(data)
2779 doc.SetParentDocument(parentDocument)
2780 doc.SetDocumentTemplate(self)
2781 self.GetDocumentManager().AddDocument(doc)
2782 doc.SetCommandProcessor(doc.OnCreateCommandProcessor())
2783 if doc.OnCreate(path, flags):
2784 return doc
2785 else:
2786 if doc in self.GetDocumentManager().GetDocuments():
2787 doc.DeleteAllViews()
2788 return None
2789
2790
2791 class WindowMenuService(DocService):
2792 """
2793 The WindowMenuService is a service that implements a standard Window menu that is used
2794 by the DocSDIFrame. The MDIFrame automatically includes a Window menu and does not use
2795 the WindowMenuService.
2796 """
2797
2798
2799 def __init__(self):
2800 """
2801 Initializes the WindowMenu and its globals.
2802 """
2803 self.ARRANGE_WINDOWS_ID = wx.NewId()
2804 self.SELECT_WINDOW_1_ID = wx.NewId()
2805 self.SELECT_WINDOW_2_ID = wx.NewId()
2806 self.SELECT_WINDOW_3_ID = wx.NewId()
2807 self.SELECT_WINDOW_4_ID = wx.NewId()
2808 self.SELECT_WINDOW_5_ID = wx.NewId()
2809 self.SELECT_WINDOW_6_ID = wx.NewId()
2810 self.SELECT_WINDOW_7_ID = wx.NewId()
2811 self.SELECT_WINDOW_8_ID = wx.NewId()
2812 self.SELECT_WINDOW_9_ID = wx.NewId()
2813 self.SELECT_MORE_WINDOWS_ID = wx.NewId()
2814
2815
2816 def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
2817 """
2818 Installs the Window menu.
2819 """
2820
2821 if not self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
2822 return # Only need windows menu for SDI mode, MDI frame automatically creates one
2823
2824 if not _WINDOWS: # Arrange All and window navigation doesn't work on Linux
2825 return
2826
2827 windowMenu = wx.Menu()
2828 item = windowMenu.Append(self.ARRANGE_WINDOWS_ID, _("&Arrange All"), _("Arrange the open windows"))
2829 windowMenu.AppendSeparator()
2830
2831 wx.EVT_MENU(frame, self.ARRANGE_WINDOWS_ID, frame.ProcessEvent)
2832 wx.EVT_UPDATE_UI(frame, self.ARRANGE_WINDOWS_ID, frame.ProcessUpdateUIEvent)
2833 wx.EVT_MENU(frame, self.SELECT_WINDOW_1_ID, frame.ProcessEvent) # wxNewId may have been nonsequential, so can't use EVT_MENU_RANGE
2834 wx.EVT_MENU(frame, self.SELECT_WINDOW_2_ID, frame.ProcessEvent)
2835 wx.EVT_MENU(frame, self.SELECT_WINDOW_3_ID, frame.ProcessEvent)
2836 wx.EVT_MENU(frame, self.SELECT_WINDOW_4_ID, frame.ProcessEvent)
2837 wx.EVT_MENU(frame, self.SELECT_WINDOW_5_ID, frame.ProcessEvent)
2838 wx.EVT_MENU(frame, self.SELECT_WINDOW_6_ID, frame.ProcessEvent)
2839 wx.EVT_MENU(frame, self.SELECT_WINDOW_7_ID, frame.ProcessEvent)
2840 wx.EVT_MENU(frame, self.SELECT_WINDOW_8_ID, frame.ProcessEvent)
2841 wx.EVT_MENU(frame, self.SELECT_WINDOW_9_ID, frame.ProcessEvent)
2842 wx.EVT_MENU(frame, self.SELECT_MORE_WINDOWS_ID, frame.ProcessEvent)
2843
2844 helpMenuIndex = menuBar.FindMenu(_("&Help"))
2845 menuBar.Insert(helpMenuIndex, windowMenu, _("&Window"))
2846
2847 self._lastFrameUpdated = None
2848
2849
2850 def ProcessEvent(self, event):
2851 """
2852 Processes a Window menu event.
2853 """
2854 id = event.GetId()
2855 if id == self.ARRANGE_WINDOWS_ID:
2856 self.OnArrangeWindows(event)
2857 return True
2858 elif id == self.SELECT_MORE_WINDOWS_ID:
2859 self.OnSelectMoreWindows(event)
2860 return True
2861 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:
2862 self.OnSelectWindowMenu(event)
2863 return True
2864 else:
2865 return False
2866
2867
2868 def ProcessUpdateUIEvent(self, event):
2869 """
2870 Updates the Window menu items.
2871 """
2872 id = event.GetId()
2873 if id == self.ARRANGE_WINDOWS_ID:
2874 frame = event.GetEventObject()
2875 if not self._lastFrameUpdated or self._lastFrameUpdated != frame:
2876 self.BuildWindowMenu(frame) # It's a new frame, so update the windows menu... this is as if the View::OnActivateMethod had been invoked
2877 self._lastFrameUpdated = frame
2878 return True
2879 else:
2880 return False
2881
2882
2883 def BuildWindowMenu(self, currentFrame):
2884 """
2885 Builds the Window menu and adds menu items for all of the open documents in the DocManager.
2886 """
2887 windowMenuIndex = currentFrame.GetMenuBar().FindMenu(_("&Window"))
2888 windowMenu = currentFrame.GetMenuBar().GetMenu(windowMenuIndex)
2889 ids = self._GetWindowMenuIDList()
2890 frames = self._GetWindowMenuFrameList(currentFrame)
2891 max = WINDOW_MENU_NUM_ITEMS
2892 if max > len(frames):
2893 max = len(frames)
2894 i = 0
2895 for i in range(0, max):
2896 frame = frames[i]
2897 item = windowMenu.FindItemById(ids[i])
2898 label = '&' + str(i + 1) + ' ' + frame.GetTitle()
2899 if not item:
2900 item = windowMenu.AppendCheckItem(ids[i], label)
2901 else:
2902 windowMenu.SetLabel(ids[i], label)
2903 windowMenu.Check(ids[i], (frame == currentFrame))
2904 if len(frames) > WINDOW_MENU_NUM_ITEMS: # Add the more items item
2905 if not windowMenu.FindItemById(self.SELECT_MORE_WINDOWS_ID):
2906 windowMenu.Append(self.SELECT_MORE_WINDOWS_ID, _("&More Windows..."))
2907 else: # Remove any extra items
2908 if windowMenu.FindItemById(self.SELECT_MORE_WINDOWS_ID):
2909 windowMenu.Remove(self.SELECT_MORE_WINDOWS_ID)
2910
2911
2912
2913 for j in range(i + 1, WINDOW_MENU_NUM_ITEMS):
2914 if windowMenu.FindItemById(ids[j]):
2915 windowMenu.Remove(ids[j])
2916
2917
2918 def _GetWindowMenuIDList(self):
2919 """
2920 Returns a list of the Window menu item IDs.
2921 """
2922 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]
2923
2924
2925 def _GetWindowMenuFrameList(self, currentFrame=None):
2926 """
2927 Returns the Frame associated with each menu item in the Window menu.
2928 """
2929 frameList = []
2930 # get list of windows for documents
2931 for doc in self._docManager.GetDocuments():
2932 for view in doc.GetViews():
2933 frame = view.GetFrame()
2934 if frame not in frameList:
2935 if frame == currentFrame and len(frameList) >= WINDOW_MENU_NUM_ITEMS:
2936 frameList.insert(WINDOW_MENU_NUM_ITEMS - 1, frame)
2937 else:
2938 frameList.append(frame)
2939 # get list of windows for general services
2940 for service in wx.GetApp().GetServices():
2941 view = service.GetView()
2942 if view:
2943 frame = view.GetFrame()
2944 if frame not in frameList:
2945 if frame == currentFrame and len(frameList) >= WINDOW_MENU_NUM_ITEMS:
2946 frameList.insert(WINDOW_MENU_NUM_ITEMS - 1, frame)
2947 else:
2948 frameList.append(frame)
2949
2950 return frameList
2951
2952
2953 def OnArrangeWindows(self, event):
2954 """
2955 Called by Window/Arrange and tiles the frames on the desktop.
2956 """
2957 currentFrame = event.GetEventObject()
2958
2959 tempFrame = wx.Frame(None, -1, "", pos = wx.DefaultPosition, size = wx.DefaultSize)
2960 sizex = tempFrame.GetSize()[0]
2961 sizey = tempFrame.GetSize()[1]
2962 tempFrame.Destroy()
2963
2964 posx = 0
2965 posy = 0
2966 delta = 0
2967 frames = self._GetWindowMenuFrameList()
2968 frames.remove(currentFrame)
2969 frames.append(currentFrame) # Make the current frame the last frame so that it is the last one to appear
2970 for frame in frames:
2971 if delta == 0:
2972 delta = frame.GetClientAreaOrigin()[1]
2973 frame.SetPosition((posx, posy))
2974 frame.SetSize((sizex, sizey))
2975 # TODO: Need to loop around if posx + delta + size > displaysize
2976 frame.SetFocus()
2977 posx = posx + delta
2978 posy = posy + delta
2979 if posx + sizex > wx.DisplaySize()[0] or posy + sizey > wx.DisplaySize()[1]:
2980 posx = 0
2981 posy = 0
2982 currentFrame.SetFocus()
2983
2984
2985 def OnSelectWindowMenu(self, event):
2986 """
2987 Called when the Window menu item representing a Frame is selected and brings the selected
2988 Frame to the front of the desktop.
2989 """
2990 id = event.GetId()
2991 index = self._GetWindowMenuIDList().index(id)
2992 if index > -1:
2993 currentFrame = event.GetEventObject()
2994 frame = self._GetWindowMenuFrameList(currentFrame)[index]
2995 if frame:
2996 wx.CallAfter(frame.Raise)
2997
2998
2999 def OnSelectMoreWindows(self, event):
3000 """
3001 Called when the "Window/Select More Windows..." menu item is selected and enables user to
3002 select from the Frames that do not in the Window list. Useful when there are more than
3003 10 open frames in the application.
3004 """
3005 frames = self._GetWindowMenuFrameList() # TODO - make the current window the first one
3006 strings = map(lambda frame: frame.GetTitle(), frames)
3007 # Should preselect the current window, but not supported by wx.GetSingleChoice
3008 res = wx.GetSingleChoiceIndex(_("Select a window to show:"),
3009 _("Select Window"),
3010 strings,
3011 self)
3012 if res == -1:
3013 return
3014 frames[res].SetFocus()
3015
3016
3017 #----------------------------------------------------------------------------
3018 # File generated by encode_bitmaps.py
3019 #----------------------------------------------------------------------------
3020 from wx import ImageFromStream, BitmapFromImage
3021 import cStringIO
3022
3023 #----------------------------------------------------------------------
3024 def getNewData():
3025 return \
3026 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3027 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3028 \x00\x01\x04IDAT8\x8d\xa5\x93\xbdj\x02A\x10\xc7\x7f{gme\xe5c\xe4\t\x82\x85\
3029 \x85\x85oa\xe5+\xd8Z\xd8'e\xfa\x80\xd8\xd8X\x19R\xc4\x07\x90\x04\xd1J\x08\
3030 \x17\x0cr\\V\xe1\xe4\xfc\x80\xb58\xf7\xd8\xbd\x0f\xa280\xec\xec2\xbf\xff\xce\
3031 \xcc\xb2B8.\xf7X\xc9\xdc|L\x97J\xc7\xbe\x0c\x01\xf0\xd6\x01\x00RFtZu\x91Q\
3032 \x10\x8e\x9b\xf8\xe4\xf3[-w*\xf1\xafm\xec\xcf\x83\x89\x1a\xad\x94\xea\xbe\
3033 \x8c\x95\x99/\x1c\x17\xe7\xdaR\xcb%xh\xd4hw_\x95yn\xb5\xe0\xcb\x90\xea%\x0eO\
3034 \xf1\xba\xd9\xc7\xe5\xbf\x0f\xdfX]\xda)\x140A\r\x03<6klO\xf0w\x84~\xef\xc9\
3035 \xca/lA\xc3@\x02\xe7\x99U\x81\xb7\x0e\xa8\xec\xed\x04\x13\xde\x1c\xfe\x11\
3036 \x902\xb2@\xc8\xc2\x8b\xd9\xbcX\xc0\x045\xac\xc1 Jg\xe6\x08\xe8)\xa7o\xd5\
3037 \xb0\xbf\xcb\nd\x86x\x0b\x9c+p\x0b\x0c\xa9\x16~\xbc_\xeb\x9d\xd3\x03\xcb3q\
3038 \xefo\xbc\xfa/\x14\xd9\x19\x1f\xfb\x8aa\x87\xf2\xf7\x16\x00\x00\x00\x00IEND\
3039 \xaeB`\x82"
3040
3041 def getNewBitmap():
3042 return BitmapFromImage(getNewImage())
3043
3044 def getNewImage():
3045 stream = cStringIO.StringIO(getNewData())
3046 return ImageFromStream(stream)
3047
3048 #----------------------------------------------------------------------
3049 def getOpenData():
3050 return \
3051 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3052 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3053 \x00\x01gIDAT8\x8d\xa5\x93=KBQ\x18\xc7\x7fWo)5\x1594DC\x04!\xd1\x0bM-\xd1\
3054 \xd0T\x81\xba\xb7\xf8\x01Z\x9a\xdb\xfa\x08AC\x10\x0e\xb5\x86\xbaDC`CMaN\xd9\
3055 \x0bQF7\xe2z\xc1kz\xcd\xc4\x97\xd3\xa0\xde\xbc\\oE\xfd\xa7s\xce\xf3\xfc\x7f\
3056 \xe7y\xce\x8b$\xb9\xdc\xfcG2@\xf1bC\x00\x18%\xcd\x12\x1c^\xdc\x97~\x04\x18\
3057 \xe7K\xa2of\x05\x80\xfe\x8e@\xc3\xc8\xf2zJ\x13\xac+\xe6\xfax(a\x81\xca\xa2w\
3058 \x8a\x86\x91\x85\xaanE\xf7\x0c\xe0\xf3\xcf\x03P}|3\x97\x93\x11U\xcc\x85\xd3&\
3059 D\xee\xf4\x88\xb2\xfa5)\xab(\x99"\x00\xb9\x87c\x0b;\x19\xf1\x0b\x80\xb9pZ\
3060 \xb2\x00\x00\xd3T\xcb\xa5\x00(\xe4Uf\xd7\xb6m\xbd\xa7\x0e\xd6\x89\xc7\xa2\
3061 \xc2\x04<_\xdf\xe3\x15\x1a\xb5V\xbfc\xab\x9b6S7\xc9FIC\xbf\xcb\xe0\x15\x1a\
3062 \xbe\xe9e|\xad@C\xbfu4\x9d\xecnQ\x99\xdci\x02\x00\xea\x1f\x1a\x15]a\xa8pcK\
3063 \xae\xbf?9\x82\x02\xc1\x90$\x1b\xba\x82<\xe8\xeb\x9a\\\xcb)\xdd|\x14r\x15<\
3064 \xad\xb1\xab\x99\x98bdb\xd4q\xa7\xefd\xbb\x05\xa7\xdd\x8f\x0e/\x9d\x01\x85\
3065 \xbc\nX+8K\\\x99\xe5\x02x\x16\xf6\xba\x02$\xc9\xe56\x1fF[\xda\x8bn\x9er\xa7\
3066 \x02\xc1\x90\xedoH\xed\xdf\x18\x8fE\xc5o\x0c\x8e\x80\xbf\xea\x13\xa8\x18\x89\
3067 5\xe7L\xb3:\x00\x00\x00\x00IEND\xaeB`\x82'
3068
3069 def getOpenBitmap():
3070 return BitmapFromImage(getOpenImage())
3071
3072 def getOpenImage():
3073 stream = cStringIO.StringIO(getOpenData())
3074 return ImageFromStream(stream)
3075
3076 #----------------------------------------------------------------------
3077 def getCopyData():
3078 return \
3079 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3080 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3081 \x00\x01_IDAT8\x8d\x8d\x92\xbfK\x02a\x18\xc7?w\xfa\'\xd8\xd0\xa0\xe4v\xd0$M\
3082 \x8dB\x11\x11\xa5B\x7f@C\xd0RC{k8E\x834\xb45\n\x15\xfd\x80hhh\xd2\xadI\x82\
3083 \xa4!\xb8\x84\xca\xd4;\xa5\xf2R\xe1m\xd0\xfb\xf5^\x1e~\xe1\xe5^\x9e{\xbe\x9f\
3084 \xf7\xfb\xbcwJ\xa9\xa2\x0bFj\x98\xdf\x00\xd4\xea\x06\x00f\xdbbosQ!L\xa5\x8a.\
3085 \xaa_"\xb0\x8e\xce\xcb\xa2\xfc)\xc4N\xfeT(j\x84\xb1\xabT\xd1E,\x19w\x80\x8d\
3086 \x97Ww?A"\xd5n\xf2*\x96\x8c\x13K\xc6\xd1R\x1aZJcai\x1e\x80\xf4j\x9a\xed\xfd\
3087 \xa2\xf0\x01B\xe7\x1b\xa9\xd9\x1d>;\x03X\xd9X\xf7AToC\xb3\xeb\xc6\x96e\xb6-\
3088 \x1en\xef\xb999\x03\xe0\xea\xf2B\x00Dku\x83)\xcd\x85\x8c;}n9\r\x80\xd1\x87b\
3089 \xbe\x00\xb33\xc3\x04f\xdbr\x9a;\x03\xbfI\x86\x1a\xfd\xe0\x01\xaam\xec\x0c\
3090 \x86\r\xf6\x8d{\xcd\xf6;\x00\xb3\'\x01\xde?\x9a>\xba\x9cH6\xb7,x~\xaa:=Q\x9f\
3091 \xb9\xe7\x1fE\xae\xb7\\\xb6\x1f\xe0\x8d\x15H$\x99\x1b?\x12@\xd7\xdf\xd0\x0f\
3092 \nN!\x91\x98\x9e\xd8\x0c\x10\xbd>\xdeU\xeco\np\xf7\xf8\xebK\x14fvF\xc8ds\xce\
3093 \xff\xbd\xb6u(\xbc\x89\xbc\x17\xf6\x9f\x14E\x8d\x04\x8a\xdeDa\xcads\xca\x1f\
3094 \x0cI\xd4\xda\x88E\x9d\xc4\x00\x00\x00\x00IEND\xaeB`\x82'
3095
3096 def getCopyBitmap():
3097 return BitmapFromImage(getCopyImage())
3098
3099 def getCopyImage():
3100 stream = cStringIO.StringIO(getCopyData())
3101 return ImageFromStream(stream)
3102
3103 #----------------------------------------------------------------------
3104 def getPasteData():
3105 return \
3106 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3107 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3108 \x00\x01\x90IDAT8\x8d\x8d\x93?H\x02a\x18\x87\x9fSw\xb1\xa9!q\xc8\xb0?B\xd0\
3109 \x98\x10DS\x10\x98\x82C\xd1\x12\x1a\xcd\rb&\xad\x1a\x144F`[\xd4 hBPKC\x83P\
3110 \x8b4\xe4\xa9tP\x82\x98\x88`$\x82\x8b\xd8p\xddu\xa7\xa5\xfd\x96{\xbf\xef\xfd\
3111 \xbd\xcf\xf7~w\xf7\n\x82\xc1\x08@M\xect\xd1(x\x12ef\xcaN./\x11\\\xdc\xd3\xa6\
3112 pz\x8d\x82\x12\x0b\x82\xc1HM\xect-c\xf7\xaa!\x10\xc9\xe0]rR\xac\xb4\x01\xc8\
3113 \xe5%\xe2\xbbF5_|\x0c\xa9\x10\x03=\nD2\x00$\xef\x9e\xc9\xe5%ryI\xde?\xe8\xe8\
3114 |\xe9\xabT\x17\xc0\xd4\x0b\xd8\nl\xa8q\xfd\xa3%\xb7\xd9x\xe1\xad=\xc2q\xba\
3115 \xc2\x8e\xfbU\xe7\xef\x03\x00\x98m\xd6\xef\xa7\xb23\xc9\xdbm\x06\xfb\x8a\x8f\
3116 \xe0y\x8a\xc0\xc4\x10\x00\xc0\xcdEB\x8d\x97\xd7}j\xbc\xb0\xe6!~\x99d\xd11\
3117 \x04\xa0-R$]'\xa84M4\xca\x05p8\x7f\x07\xd4?Z\x98mr\x07\x95\xa6\x9c\xf6o{\xb0\
3118 \xce\xbb\x00\xb0\x03\xe9\xc3\xd8\xf0+h;x\xf9\xfc\xcb\xd5\x0bh>Pzw1>\x0bg\xa7\
3119 )]\xaaQ.\x00`\xdb\x0c\x0f\x00hN\xf4o{~=\xf9\xa9\x0eY\xb1\x8awI\xf3\x0ej\x05\
3120 \xb0\x98\x1f\x00x-\xd5\xb0\xce\xc3\xd1~LW\x98\x15\xab\xccM\x8f\xfe\xaf\x03\
3121 \x00w0\xccS\xfdgm\xfb\xc3\xd7\xf7++w\xd5\x16\x0f\x92\t\xe4\xe9zN\x86\xbe\xa7\
3122 1\xaa\xfbLY\xb1:\x10 (\xe3\x0c?\x03\xf2_\xb9W=\xc2\x17\x1c\xf8\x87\x9a\x03\
3123 \x12\xd7\xb9\x00\x00\x00\x00IEND\xaeB`\x82"
3124
3125 def getPasteBitmap():
3126 return BitmapFromImage(getPasteImage())
3127
3128 def getPasteImage():
3129 stream = cStringIO.StringIO(getPasteData())
3130 return ImageFromStream(stream)
3131
3132 #----------------------------------------------------------------------
3133 def getSaveData():
3134 return \
3135 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3136 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3137 \x00\x01\x1dIDAT8\x8d\x9d\x93=N\xc3@\x10\x85\xbf\xf5\xa2-\xf1\x11\xa0\x8dC\
3138 \x8f\x82\xa0\xe5\xa7\xa6\xe2\x04\xb4p\x00\x1a\xfb\x02\x11T\xf4\xa4\xa0\xc1\
3139 \xc1\\\x01\x90R"\xc5\xa4\x89RD\x14\x04$\xa2@\x01\xb1\x04C\xe1\xc8\xb1`\x1dC^\
3140 5;?\xef\xcd\x8cv\x94r4\xf1\xc5\xa7P\x82a\xff\xb7o\xfd@+\x94\xa3\xb9o"2\xa8K\
3141 \x18\x86R\x84\xc1\x87\xc8\xdd\xf3X|\xdf\x17\x11\x91\x9bc$\x8a"q\xf2\x8cZk\
3142 \xab\xfa\xd3\x18\x1e\xdf\x12\xba\xef\x06\x80\xdb\x13\x95\xc5\x1ckE\t\xd6\xb6\
3143 \xf7\xec\x04I\x92\x94\xaa\xff\xc4\\\x1d\xf0\xd2\xfd\x1bA\x99:\xc0B\xfe\xb1\
3144 \xbb\xf1@\x10\x043\xc5\x8f6\xaf\x00\xe8u\xc0]\x9e\x10\x0c\xfb@m\x92\xb0\xbf8\
3145 \xcd\x1e\xb5\xacm\xdb;\x18\xb5\xc0]%8}\xcd\x85+\x99\xd5\x8e\xbf2\xfb\xfc\xb0\
3146 g\x1f!U\xac\xe0y^\xe62\xc6p\xd6h\x14\x8e4s\x89\xc6\xa4\xcb[\xa9V\xffG\xa0\
3147 \xb5\xce\x8a\x97j[\xb4\xe3\xb8\x90@)\'\xfd\xbe\xd7\xf5\xe2\x83\xeau\xec~w\'\
3148 \x9a\x12\x00\\6\xc3\xd2\xab,\xec`^|\x03\xb6\xdf|Q.\xa7\x15\x89\x00\x00\x00\
3149 \x00IEND\xaeB`\x82'
3150
3151 def getSaveBitmap():
3152 return BitmapFromImage(getSaveImage())
3153
3154 def getSaveImage():
3155 stream = cStringIO.StringIO(getSaveData())
3156 return ImageFromStream(stream)
3157
3158 #----------------------------------------------------------------------
3159 def getSaveAllData():
3160 return \
3161 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3162 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3163 \x00\x01UIDAT8\x8d\x9d\x93\xbfK\xc3@\x1c\xc5\xdf%\x01g\xeb \x1d\x8a\x8b\x83M\
3164 \x11\xe9\x16\x8a\x8b\xff@\xa0\xdd\x14\'\x17\x17A2\xe9,\x08\xc9\x14\x82n.nn\
3165 \x9a\xde?\xe0R;\xb88\x99v\xe8`\x86\n."\x81\xb6\xb4\xb4~\x1d\xd2\xc4^\x92j\
3166 \xf5\x03\xc7\xfd~\xf7\xeeq\xc7<\x17\x84)\xa3\x1e\x04\x863\xfd\xf10\xac\xb7\
3167 \x8fe&,\xf2\\\x10\xf9\x06q\xce)I\x7fL\xf4\xda\'2M\x93\x88\x88\x1e.@\x9csb\
3168 \x92\x8c\xb8x.\xa8X6\xd0z\xb2c\xd1?9\x89\x1c\xfc\xd7\x89\x82\x04\xeb\x9f:Z\
3169 \xf5l\';9\xe0\xf1\xea\x14\xca\x12\xb0\xe2\xebh8 ))\x00\x00\xc5\xb2\x81\x8e\
3170 \xc4\xb1\xb5GB\xd9< \x14\xf6\t\xf7\xef&*Ga\xf6\x99\x02Y\x0c&\xc0\xc7\x08x\
3171 \xe9\x01A\x10\xa0y\xc9\x16\x17\x98\xdd\x1cQ\xd1\x8d\x9f\x05<\xcf\x136\xcf#\
3172 \x15b\xc4\xc9\xee\x1b,\xcb\x8a\xfbA\x10\xc4\xed\xf3\xc3\x01\x00\xc0o\x03J\
3173 \xa9&\xb3\x86c\xd3r![\xe47\x14 |\x14\xcf\xb7\x13JNZ7\xab\xc2\xe9\xddn7\x9e\
3174 \xbb>\xcb\x01\x98\xc9\xa0T\x93Y\x93\xdbH\xa2\xaa*4MC\xb5Z\xcdt \x84\x98\xfa(\
3175 S\xf2\xf9\xfc\xdc+0&\xc9\xa9\xc1\x86\xf3}\x1d\xbf\r\xacm\x84\xf5\xc2\x02\x00\
3176 Pw\xefR\x99d\xf1\x05z\x94\xd0b\xcb S\xf3\x00\x00\x00\x00IEND\xaeB`\x82'
3177
3178 def getSaveAllBitmap():
3179 return BitmapFromImage(getSaveAllImage())
3180
3181 def getSaveAllImage():
3182 stream = cStringIO.StringIO(getSaveAllData())
3183 return ImageFromStream(stream)
3184
3185 #----------------------------------------------------------------------
3186 def getPrintData():
3187 return \
3188 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3189 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3190 \x00\x01\xa7IDAT8\x8d\xa5S=K\xc3P\x14=\xef\xb5 \x0e\xf6\x17\xb8$X\x10\xa7\
3191 \x82\xb4\n]\x05A\x07\xebd%\xfe\x02\x97\x82\xe0\xa0\x83\xa3\x88\xb5E\xfd\x07j\
3192 \x0bq\xea\x07\x18(8:5\x16\xa2H\xf1\x8bN\x12\tt\xe9\x8b\xddZ\x9eC|i\x93\xd4\
3193 \x0f\xf0\xc0\xe1\xe6\xbe\xdc{\xde\xb9\xc9{\x84\xd0\x10\xfe\x83\xb0x8m\xf6\
3194 \xb8i\xf7=/\xfb\xad\x07O\x9e]\x9f%\x01\x05BC 4\x84\x1d\xbd\xc7\xfdx\xb2\x1d^\
3195 \x99\x9c\x1f\xe6\x8ey\xb5Z\xe5\xa2^\x90\n\xa1\x83\xb91\xb2{;p\xf0\xfc\xe1\
3196 \xc4W\xdb\x89\xe3\xcb\x19\xa8\xaa\x8aJ\xb9\xc4\x87\r\xd0\xe1\xc4o\xf9/\x08\
3197 \x03\xc0\xc5\xf9\x19\x07\x80\xfb\xaf\x9d\xc5\xae-6(4\xed>\x9aoA\x01zq~\xc6\
3198 \x15E\x81\xa2(\xee\xe2\xd4\x84\x13\xe5H\xb0\xc1?\x06\x05\x80b\xb1\xe8\x16\
3199 \xbc\xda\x0e[\xcc\xa1i\xf71\xfcw\xf2\xf9\xbcG\x84\x14\n\x05\x1e\x8b\xc5\xa0\
3200 \xd5\xae\xb1\xbd\x95\x81eY#gm\xb7\xdb\x9e|cs\x1fw7\x97$lZm\xc4\x00,-. \x9b?\
3201 \xc1tT\x1e)\xc0\x18C$\x12\x01c\xce\x87\xe9\xbe\xeb\xa8\x94K\x9cNGeh\xb5k\x00\
3202 \x80\xd1\xa8#\x91H@\x96\xe5\x00%I\xc2\xe3K\x0b\x9a\xa6A\x92$W8\xbc\x92Z%\xeb\
3203 \xe95n4\xea\x01\xab\x9dN\xc7\xe3"9\x1fGr>\xeeYs\x8fr:\x9d\x06c\x0c\x86ax\nL\
3204 \xcb;\xbb\x1f\x84\xd0\x10*\xe5\x12WU\x15\xcd7`f\xf2\xc7z\x00\x80\xae\xeb\xc8\
3205 \xe5rXI\xad\x12"nc\xa5\\\xe2{G*\xba\xef\xfa\xaf\x02\xa2\xd9u \xe0?\xe7\xdfA4\
3206 \x03\xc0\'\xe3\x82\xc9\x18g\x90\x8e]\x00\x00\x00\x00IEND\xaeB`\x82'
3207
3208 def getPrintBitmap():
3209 return BitmapFromImage(getPrintImage())
3210
3211 def getPrintImage():
3212 stream = cStringIO.StringIO(getPrintData())
3213 return ImageFromStream(stream)
3214
3215 #----------------------------------------------------------------------
3216 def getPrintPreviewData():
3217 return \
3218 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3219 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3220 \x00\x01mIDAT8\x8d\x8d\x92\xbdK\x02a\x1c\xc7?w\x1a\x85E\x04588XHa\xd1\x14!AB\
3221 \r.\xbd\x07m-By.M\xfe\x03N\x05\x0e\xed\xf9\x124\x045\x04\x15\xdc\xda&4\xb5DC\
3222 J\x8a\x81E\t.\x82\x918\xd8\xf0pOw\xde\x19}\xe1\xe1w\xf7;>\xdf\xdf\xcbs\xca\
3223 \xddC\xb9C\x97\x1e\x8bU\xf9\x9c\xd8]V\xba\xbf\x9b\xa5\x02\xf8\xa6\xc6-ge=\
3224 \x0c@p)\xcc\xc1\xe1\xa5\xad\x80\xcd\xa0\x97\x86\xfb`5\xba\xf3\xa7\x89\xdb)Y\
3225 \xff\x16\xf1"{%s\xb77\xd7\x9d\xcd\xadm\xdb86\x03\x03\x0eE\xc2\x04\xdbPk\xc1y\
3226 2Edf\xday\x84\xe6\xdb\x93\x84\x8c\xd8h\x8bSk\xf5j\xdcdPj\x8eX`C\x06\x9c?\x8a\
3227 \xe3\xef/\xa3\xeb:\xb1\xfd=\xdb.,#4\xdav\x18-m\x01b\xd0\xc9\xe6N\xe5.Ts\xcbN\
3228 pz\x0e\xa2~\x91\x0bx\x00-m\xe9D-W>%h\xc0\x1f_\xbf\x15\xef\xeb\x90\xaf\xc1\
3229 \xe2\x18x="\x82\xb8\x15\xd9\x81yYf\x18\xe0\xac"\xc0\xc0\x10\x84\xc6D4\xcb\
3230 \xf2#u\xc3\xb2m`t\x00&\x07E4\xcb]x.QH\xa6\xec$\x13\xf83q^\xb44^\x8f\xb8\xa5"\
3231 p\x9c\x88\xa3\x91\xe1\x9d5\x00\x14Eu\xc9y\x9c\xa4\xeb\xba\xe5}\xb6\x9a\x01`\
3232 \xc1\x07\xf39\x97\xa2(\xaa\xab\x17+\xd5]\xe0\xf5dC\x9a\xfc\xcb\xc0\xc9\xd00\
3233 \xf9\x011\xc9\x87\xf3\xb4\xd1t\xaf\x00\x00\x00\x00IEND\xaeB`\x82'
3234
3235 def getPrintPreviewBitmap():
3236 return BitmapFromImage(getPrintPreviewImage())
3237
3238 def getPrintPreviewImage():
3239 stream = cStringIO.StringIO(getPrintPreviewData())
3240 return ImageFromStream(stream)
3241
3242 #----------------------------------------------------------------------
3243 def getCutData():
3244 return \
3245 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3246 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3247 \x00\x01HIDAT8\x8d\x85\x92OK\x02Q\x14\xc5\x7f\xa3\x05}\x1b\xa1\xc0\x9d\xb4\
3248 \xaaf6\x93a\x10\xe3^\x83l\xdf\xc6\xa5\x1bIA\xb4\xa0\x9cM\xe5"\x84\x18\xff\
3249 \x108\xbb\xf0\x93\xb4v\x15h\xa9\xaf\x16\xaf\x85\xbcat^\xd3\x81\xb79\xf7\xdc\
3250 \xf3\xce{\xf7b$\x92\x84O\xa7\xd3\x91\x9b\\\xf8\xd4\xeb\xb5\xb5z\x02\r\x9e\
3251 \x1e\x1f\xa4\x8eo5\x1b\x12`\xd0\xef\x05u\xadA.\x97\xc3u\xef\xd7LZ\xcd\x86\
3252 \xb4\xedlD\xab5\xd0A\x08\xc1l6e>_\xc4\x1b\x88o\x01@\xde\xc9\x07\x91k\xd7Ui\
3253 \x9a\x96\xd6xk\x93(\x14\xce\r@\x1e\x1e\x1cE\xc4\x9e\xe7\x91J\xa58\xce\x9e\
3254 \x18\x7f\x1a\x00,\x17\xab\x98\xb6\x9dE\x08!M\xd3\x8aDW0\x8cDR[P\xb1U\xa3\xef\
3255 \x8f"\xb7C\xcc\'\xee\xbdw\xf1</h\xceL\x86Z\x9d\xf6\to\x17\xbb2m90z\xc6\xf7!3\
3256 \x19\x92\xb6\x1c\xc6\xdd\xab\x886v\x8ci\xcb\t\x9a\x15\xc2K\xa45P\xb7\x17o+\
3257 \x00,\xa6\x9f\x00\x14o+\xec\x9f\x15X\xba\x97\xf1\tTC\x1c\xfe]e\x80v\xa9\xcc\
3258 \xb8\xeb2\xfb\xf8\xe2\xf5\xaeA\xbbT\xd6\xea"c\x1c\xf4{r\xfbe\xf5Y?\xa7\xd5\
3259 \x80W\xd1w\n7k\xa3\xd4\xee\x81\x8a\x18\x16\xea8\x80_\\\xa2\x8b\x88!\xd2S\x08\
3260 \x00\x00\x00\x00IEND\xaeB`\x82'
3261
3262 def getCutBitmap():
3263 return BitmapFromImage(getCutImage())
3264
3265 def getCutImage():
3266 stream = cStringIO.StringIO(getCutData())
3267 return ImageFromStream(stream)
3268
3269 #----------------------------------------------------------------------
3270 def getUndoData():
3271 return \
3272 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3273 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3274 \x00\x01\xa7IDAT8\x8d\xa5\x90\xbfK[Q\x18\x86\x9fs#\x8d\x7fBu\xc8\xd6\xc9\xc1\
3275 \xa1\x83\xd0\x16\xa1C@*\x98\xc4\xa2\x12\xda\x8e5\x9b\x83\x04\x07Aph\x17)\x16\
3276 \xdd\xd4\xc1\xa1Z\x1b\xc5&9\xa6P\xbaw\xa8\x9b\x9b\xa0S\xb0\xe2\x8f\\%1^\x8d\
3277 \xde\xfa9\x84s\xf1\xea\xa5\x06<p\x86\xc3\xf9\x9e\xe7\xbc\xefQ\xca\n\xf1\x90\
3278 \xd5t\xdf@\xba\x10\x95r\xcd\x01`\xee\xf5o\xd5\xb0 ]\x88\n@\xd7\xb3^\x00.\xaf\
3279 \xce\xd8\x9d>\x10\x80\x1fC[\x9eH\x05UH\x17\xa2r\x13\xac\x9d_Pq\x8f\x01(96\
3280 \xdf\x16\xd7X\xff\xb8\xaf\x02\x05\x066\xa0+5\xe6\xb3\x0b\x1c\xeeW\x00x\xd1\
3281 \xf3\x14\x80\xaf\x93\xbf\xd8\xcb\xb8\xeaN\x05\xd3\xd7\xbc\x9a\xd1\xdf\x19\
3282 \x8cL@\xa4~\x9f\x9a\xec\xa3\xb3\xa7\r\x80|.+>\xc1\xfb\xd5\xe72\xf0\xf2-U\xa7\
3283 \xec\x83c\xf1\x84\xd79\x9f\xcbJj\xa9/\xf8\x13\xcb\xe7U.\xaf\xcep\xa5\x06P\
3284 \x8f\x1d\xf1'\x8c\xc5\x13*\x9f\xcb\x8a'\xe8_l\x17\x80\xe57\x1b\xea\xd4\xae\
3285 \xc7w\xfe9\x94\x1c\xdb\x83\x1e\x0f4\t\xc0^\xc6UFb\xee\xacS\xdba\xf8\xd5\x08\
3286 \xdd\xd3O\xc4t7\xab\xb8m\x93Z\xf2w\xbe\xfdgJk-\xb3\xc5\x11\xc6\xde\x8dS\x95\
3287 \x8a\xd7\xbf\xe4\xd8\xec\x9c\xecr\xb2Sfm\xf9\x0f3\xc9\x15\xdf\xcb^\x82X<\xa1\
3288 \x06#\x13\x0c}\x1a\x06 \xdc\xfc\xc87\xf0?\xb8\x1e\xc1\n\xa1\xac\x10Zk\xe9\
3289 \x18k\x95\x9fGS\xf2\xa58*\x9f7S\xd2\x92\x0c\x8b\xd6Z\xccL\xd0\xf6\x1d\xb4\
3290 \xd6\xd2\x92\x0c\xcb\xea\xdf\x0f\r\xc1w\x047%\x8d\xc0\x81\x02#i\x04VV\x88k\
3291 \x82\xbe\xde\xc2\xb0\xb2\xea\xa7\x00\x00\x00\x00IEND\xaeB`\x82"
3292
3293 def getUndoBitmap():
3294 return BitmapFromImage(getUndoImage())
3295
3296 def getUndoImage():
3297 stream = cStringIO.StringIO(getUndoData())
3298 return ImageFromStream(stream)
3299
3300 #----------------------------------------------------------------------
3301 def getRedoData():
3302 return \
3303 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3304 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3305 \x00\x01\x88IDAT8\x8d\xa5\x92\xc1K\x02A\x14\xc6\xbfQ\t\xbc\x14tJ\xfb\x0f2\
3306 \x08\xbaD\xdd:\xe5!\xd2\xad$/\x82FP\x06\x99\x87\x04\xa1\x83D\x10\x0b\x85\xd4\
3307 \xa9\x8c (\x82<\xad\xce\xa9\xff\xc0[\xd2)\xbcu\t\xb2\xd0\xa5\xb5\x94\x14z\
3308 \x1dd\x87]\x1bBh\xe0\xc1\xf0\xde\xfb~3\xef\x9ba\xcc\xe1\xc4\x7f\x96K\x96\xdc\
3309 \xd6\xfcd\xeeO\x94;\xd67\xc0\x14Fg\xd7E\xae~\xa5S\xe3\xd3@!\xfe(\x051s\x84m\
3310 \xcdOV!\x004\xbf\r\x00\x80\xde\xae\xe2B\xbb\x94B\\\x00\x10\xb9\x9a\x12\xe2,W\
3311 Eqc~S\xec\xd7\x94\x18\xaa\xafY*e^l\x10\x87\xf5\xb4,W\xb1<\x98\x16q\x98W\xa1\
3312 \xb7\xab\x00\x80F\xa7\x0e\x00(\x164\xb2\x02\xc0\x1cN(\xb9qRr\xe3\xc49'\xe6p\
3313 \xc2\x1a3\xfb\xa3t\xfb\xbcK\xe7O[\xa4V\xc2\xe4K\x0e\xdb\xfa\\\x00\x10\xf3\
3314 \x1c\x00\x00\x02AEj\x94\xd11P\xffz\x93\x95\xba\x80^\xe1\xf4\xde\x08\x01@)\
3315 \xf3\xc2\xdek-!\xae5u\xe8\xcf-\x00\x80gi\x80l\x1e\xf4\xae\xc4j\x14c\x89!1o\
3316 \xad\xa9\x8b\xda\xc6\xf5\n\x16v&\xbb\x16\xc8~b\xb1\xa0\x91\xfa\x10G4\xb2h;\
3317 \xbd\xd1\xfe\x10=\xfc\xe8\x1eg\x91\xbc\xfc\x06\x81\xa0\xc2\xd2\x13\xa789\xbe\
3318 \x91\xde\xce\x14\x07\x82\nC\xaf\xeb\xd6\xe0\x9c\x93/9Lj%L\xa9\xf2\x1c\xa5\
3319 \xcas\xe4\r\xb9m\xaf\xf0'\xc0\x84xCnR+\xe1_\xe2\xbe\x00V\x88\xec\x9f\xf4\x05\
3320 0!\xb2\xfc\x0f\xe0\xc4\xb6\xad\x97R\xe5z\x00\x00\x00\x00IEND\xaeB`\x82"
3321
3322 def getRedoBitmap():
3323 return BitmapFromImage(getRedoImage())
3324
3325 def getRedoImage():
3326 stream = cStringIO.StringIO(getRedoData())
3327 return ImageFromStream(stream)
3328
3329 #----------------------------------------------------------------------------
3330
3331 def getBlankData():
3332 return \
3333 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3334 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3335 \x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\
3336 \xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\
3337 9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\
3338 \x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\
3339 \x00\x00IEND\xaeB`\x82'
3340
3341
3342 def getBlankBitmap():
3343 return BitmapFromImage(getBlankImage())
3344
3345 def getBlankImage():
3346 stream = cStringIO.StringIO(getBlankData())
3347 return ImageFromStream(stream)
3348
3349 def getBlankIcon():
3350 return wx.IconFromBitmap(getBlankBitmap())
3351
3352