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