]> git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/pydocview.py
wxCheckListBox doesn't require wxUSE_OWNER_DRAWN when using WXUNIVERSAL
[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(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(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 document.GetFirstView().OnClose(deleteWindow = False):
1999 if document.GetFirstView().GetFrame():
2000 document.GetFirstView().GetFrame().Close() # wxBug: Need to do this for some random reason
2001 else:
2002 return False
2003 return True
2004
2005
2006 def IsMDI(self):
2007 """
2008 Returns True if the application is in MDI mode.
2009 """
2010 return self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_MDI
2011
2012
2013 def IsSDI(self):
2014 """
2015 Returns True if the application is in SDI mode.
2016 """
2017 return self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI
2018
2019
2020 def ShowSplash(self, image):
2021 """
2022 Shows a splash window with the given image. Input parameter 'image' can either be a wx.Bitmap or a filename.
2023 """
2024 if isinstance(image, wx.Bitmap):
2025 splash_bmp = image
2026 else:
2027 splash_bmp = wx.Image(image).ConvertToBitmap()
2028 self._splash = wx.SplashScreen(splash_bmp,wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_NO_TIMEOUT,0, None, -1)
2029 self._splash.Show()
2030
2031
2032 def CloseSplash(self):
2033 """
2034 Closes the splash window.
2035 """
2036 if self._splash:
2037 self._splash.Close(True)
2038
2039
2040 class _DocFrameFileDropTarget(wx.FileDropTarget):
2041 """
2042 Class used to handle drops into the document frame.
2043 """
2044
2045 def __init__(self, docManager, docFrame):
2046 """
2047 Initializes the FileDropTarget class with the active docManager and the docFrame.
2048 """
2049 wx.FileDropTarget.__init__(self)
2050 self._docManager = docManager
2051 self._docFrame = docFrame
2052
2053
2054 def OnDropFiles(self, x, y, filenames):
2055 """
2056 Called when files are dropped in the drop target and tells the docManager to open
2057 the files.
2058 """
2059 try:
2060 for file in filenames:
2061 self._docManager.CreateDocument(file, wx.lib.docview.DOC_SILENT)
2062 except:
2063 msgTitle = wx.GetApp().GetAppName()
2064 if not msgTitle:
2065 msgTitle = _("File Error")
2066 wx.MessageBox("Could not open '%s'. '%s'" % (docview.FileNameFromPath(file), sys.exc_value),
2067 msgTitle,
2068 wx.OK | wx.ICON_EXCLAMATION,
2069 self._docManager.FindSuitableParent())
2070
2071
2072 class DocMDIParentFrame(wx.lib.docview.DocMDIParentFrame, DocFrameMixIn, DocMDIParentFrameMixIn):
2073 """
2074 The DocMDIParentFrame is the primary frame which the DocApp uses to host MDI child windows. It offers
2075 features such as a default menubar, toolbar, and status bar, and a mechanism to manage embedded windows
2076 on the edges of the DocMDIParentFrame.
2077 """
2078
2079
2080 def __init__(self, docManager, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="DocMDIFrame", embeddedWindows=0):
2081 """
2082 Initializes the DocMDIParentFrame with the default menubar, toolbar, and status bar. Use the
2083 optional embeddedWindows parameter with the embedded window constants to create embedded
2084 windows around the edges of the DocMDIParentFrame.
2085 """
2086 pos, size = self._GetPosSizeFromConfig(pos, size)
2087 wx.lib.docview.DocMDIParentFrame.__init__(self, docManager, parent, id, title, pos, size, style, name)
2088 self._InitFrame(embeddedWindows)
2089
2090
2091 def _LayoutFrame(self):
2092 """
2093 Lays out the frame.
2094 """
2095 wx.LayoutAlgorithm().LayoutMDIFrame(self)
2096 self.GetClientWindow().Refresh()
2097
2098
2099 def ProcessEvent(self, event):
2100 """
2101 Processes an event, searching event tables and calling zero or more
2102 suitable event handler function(s). Note that the ProcessEvent
2103 method is called from the wxPython docview framework directly since
2104 wxPython does not have a virtual ProcessEvent function.
2105 """
2106 if wx.GetApp().ProcessEventBeforeWindows(event):
2107 return True
2108 if wx.lib.docview.DocMDIParentFrame.ProcessEvent(self, event):
2109 return True
2110 return DocMDIParentFrameMixIn.ProcessEvent(self, event)
2111
2112
2113 def ProcessUpdateUIEvent(self, event):
2114 """
2115 Processes a UI event, searching event tables and calling zero or more
2116 suitable event handler function(s). Note that the ProcessEvent
2117 method is called from the wxPython docview framework directly since
2118 wxPython does not have a virtual ProcessEvent function.
2119 """
2120 if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
2121 return True
2122 if wx.lib.docview.DocMDIParentFrame.ProcessUpdateUIEvent(self, event): # Let the views handle the event before the services
2123 return True
2124 if event.GetId() == wx.ID_ABOUT: # Using ID_ABOUT to update the window menu, the window menu items are not triggering
2125 self.UpdateWindowMenu()
2126 return True
2127 return DocMDIParentFrameMixIn.ProcessUpdateUIEvent(self, event)
2128
2129
2130 def UpdateWindowMenu(self):
2131 """
2132 Updates the WindowMenu on Windows platforms.
2133 """
2134 if wx.Platform == '__WXMSW__':
2135 children = filter(lambda child: isinstance(child, wx.MDIChildFrame), self.GetChildren())
2136 windowCount = len(children)
2137 hasWindow = windowCount >= 1
2138 has2OrMoreWindows = windowCount >= 2
2139
2140 windowMenu = self.GetWindowMenu()
2141 if windowMenu:
2142 windowMenu.Enable(wx.IDM_WINDOWTILE, hasWindow)
2143 windowMenu.Enable(wx.IDM_WINDOWTILEHOR, hasWindow)
2144 windowMenu.Enable(wx.IDM_WINDOWCASCADE, hasWindow)
2145 windowMenu.Enable(wx.IDM_WINDOWICONS, hasWindow)
2146 windowMenu.Enable(wx.IDM_WINDOWTILEVERT, hasWindow)
2147 wx.IDM_WINDOWPREV = 4006 # wxBug: Not defined for some reason
2148 windowMenu.Enable(wx.IDM_WINDOWPREV, has2OrMoreWindows)
2149 windowMenu.Enable(wx.IDM_WINDOWNEXT, has2OrMoreWindows)
2150
2151
2152
2153 def OnSize(self, event):
2154 """
2155 Called when the DocMDIParentFrame is resized and lays out the MDI client window.
2156 """
2157 # Needed in case there are splitpanels around the mdi frame
2158 self._LayoutFrame()
2159
2160
2161 def OnCloseWindow(self, event):
2162 """
2163 Called when the DocMDIParentFrame is closed. Remembers the frame size.
2164 """
2165 self.SaveEmbeddedWindowSizes()
2166
2167 # save and close services last.
2168 for service in wx.GetApp().GetServices():
2169 if not service.OnCloseFrame(event):
2170 return
2171
2172 # save and close documents
2173 # documents with a common view, e.g. project view, should save the document, but not close the window
2174 # and let the service close the window.
2175 wx.lib.docview.DocMDIParentFrame.OnCloseWindow(self, event)
2176
2177
2178 class DocSDIFrame(wx.lib.docview.DocChildFrame, DocFrameMixIn):
2179 """
2180 The DocSDIFrame host DocManager Document windows. It offers features such as a default menubar,
2181 toolbar, and status bar.
2182 """
2183
2184
2185 def __init__(self, doc, view, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="DocSDIFrame"):
2186 """
2187 Initializes the DocSDIFrame with the default menubar, toolbar, and status bar.
2188 """
2189 wx.lib.docview.DocChildFrame.__init__(self, doc, view, parent, id, title, pos, size, style, name)
2190 self._fileMenu = None
2191 if doc:
2192 self._docManager = doc.GetDocumentManager()
2193 else:
2194 self._docManager = None
2195 self.SetDropTarget(_DocFrameFileDropTarget(self._docManager, self))
2196
2197 wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
2198 wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
2199 wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
2200
2201 self.InitializePrintData()
2202
2203 menuBar = self.CreateDefaultMenuBar(sdi=True)
2204 toolBar = self.CreateDefaultToolBar()
2205 self.SetToolBar(toolBar)
2206 statusBar = self.CreateDefaultStatusBar()
2207
2208 for service in wx.GetApp().GetServices():
2209 service.InstallControls(self, menuBar = menuBar, toolBar = toolBar, statusBar = statusBar, document = doc)
2210
2211 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
2212
2213
2214 def _LayoutFrame(self):
2215 """
2216 Lays out the Frame.
2217 """
2218 self.Layout()
2219
2220
2221 def OnExit(self, event):
2222 """
2223 Called when the application is exitting.
2224 """
2225 if self._childView.GetDocumentManager().Clear(force = False):
2226 self.Destroy()
2227 else:
2228 event.Veto()
2229
2230
2231 def OnMRUFile(self, event):
2232 """
2233 Opens the appropriate file when it is selected from the file history
2234 menu.
2235 """
2236 n = event.GetId() - wx.ID_FILE1
2237 filename = self._docManager.GetHistoryFile(n)
2238 if filename:
2239 self._docManager.CreateDocument(filename, wx.lib.docview.DOC_SILENT)
2240 else:
2241 self._docManager.RemoveFileFromHistory(n)
2242 msgTitle = wx.GetApp().GetAppName()
2243 if not msgTitle:
2244 msgTitle = _("File Error")
2245 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),
2246 msgTitle,
2247 wx.OK | wx.ICON_EXCLAMATION,
2248 self)
2249
2250
2251 def ProcessEvent(self, event):
2252 """
2253 Processes an event, searching event tables and calling zero or more
2254 suitable event handler function(s). Note that the ProcessEvent
2255 method is called from the wxPython docview framework directly since
2256 wxPython does not have a virtual ProcessEvent function.
2257 """
2258 if wx.GetApp().ProcessEventBeforeWindows(event):
2259 return True
2260 if self._childView:
2261 self._childView.Activate(True)
2262
2263 id = event.GetId()
2264 if id == SAVEALL_ID:
2265 self.OnFileSaveAll(event)
2266 return True
2267
2268 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
2269 return True
2270 else:
2271 return wx.GetApp().ProcessEvent(event)
2272
2273
2274 def ProcessUpdateUIEvent(self, event):
2275 """
2276 Processes a UI event, searching event tables and calling zero or more
2277 suitable event handler function(s). Note that the ProcessEvent
2278 method is called from the wxPython docview framework directly since
2279 wxPython does not have a virtual ProcessEvent function.
2280 """
2281 if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
2282 return True
2283 if self._childView:
2284 if hasattr(self._childView, "GetDocumentManager"):
2285 docMgr = self._childView.GetDocumentManager()
2286 if docMgr:
2287 if docMgr.GetCurrentDocument() != self._childView.GetDocument():
2288 return False
2289 if docMgr.ProcessUpdateUIEvent(event): # Let the views handle the event before the services
2290 return True
2291 id = event.GetId()
2292 if id == wx.ID_CUT:
2293 event.Enable(False)
2294 return True
2295 elif id == wx.ID_COPY:
2296 event.Enable(False)
2297 return True
2298 elif id == wx.ID_PASTE:
2299 event.Enable(False)
2300 return True
2301 elif id == wx.ID_CLEAR:
2302 event.Enable(False)
2303 return True
2304 elif id == wx.ID_SELECTALL:
2305 event.Enable(False)
2306 return True
2307 elif id == SAVEALL_ID:
2308 filesModified = False
2309 docs = wx.GetApp().GetDocumentManager().GetDocuments()
2310 for doc in docs:
2311 if doc.IsModified():
2312 filesModified = True
2313 break
2314
2315 event.Enable(filesModified)
2316 return True
2317 else:
2318 return wx.GetApp().ProcessUpdateUIEvent(event)
2319
2320
2321 def OnCloseWindow(self, event):
2322 """
2323 Called when the window is saved. Enables services to help close the frame.
2324 """
2325 for service in wx.GetApp().GetServices():
2326 service.OnCloseFrame(event)
2327 wx.lib.docview.DocChildFrame.OnCloseWindow(self, event)
2328 if self._fileMenu and self._docManager:
2329 self._docManager.FileHistoryRemoveMenu(self._fileMenu)
2330
2331
2332 class AboutService(DocService):
2333 """
2334 About Dialog Service that installs under the Help menu to show the properties of the current application.
2335 """
2336
2337 def __init__(self, aboutDialog=None, image=None):
2338 """
2339 Initializes the AboutService.
2340 """
2341 if aboutDialog:
2342 self._dlg = aboutDialog
2343 self._image = None
2344 else:
2345 self._dlg = AboutDialog # use default AboutDialog
2346 self._image = image
2347
2348
2349 def ShowAbout(self):
2350 """
2351 Show the AboutDialog
2352 """
2353 if self._image:
2354 dlg = self._dlg(wx.GetApp().GetTopWindow(), self._image)
2355 else:
2356 dlg = self._dlg(wx.GetApp().GetTopWindow())
2357 dlg.CenterOnScreen()
2358 dlg.ShowModal()
2359 dlg.Destroy()
2360
2361
2362 def SetAboutDialog(self, dlg):
2363 """
2364 Customize the AboutDialog
2365 """
2366 self._dlg = dlg
2367
2368
2369 class AboutDialog(wx.Dialog):
2370 """
2371 Opens an AboutDialog. Shared by DocMDIParentFrame and DocSDIFrame.
2372 """
2373
2374 def __init__(self, parent, image=None):
2375 """
2376 Initializes the about dialog.
2377 """
2378 wx.Dialog.__init__(self, parent, -1, _("About ") + wx.GetApp().GetAppName(), style = wx.DEFAULT_DIALOG_STYLE)
2379
2380 sizer = wx.BoxSizer(wx.VERTICAL)
2381 if image:
2382 imageItem = wx.StaticBitmap(self, -1, image.ConvertToBitmap(), (0,0), (image.GetWidth(), image.GetHeight()))
2383 sizer.Add(imageItem, 0, wx.ALIGN_CENTER|wx.ALL, 0)
2384 sizer.Add(wx.StaticText(self, -1, wx.GetApp().GetAppName()), 0, wx.ALIGN_CENTRE|wx.ALL, 5)
2385
2386 btn = wx.Button(self, wx.ID_OK)
2387 sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
2388
2389 self.SetSizer(sizer)
2390 self.SetAutoLayout(True)
2391 sizer.Fit(self)
2392
2393
2394
2395 class FilePropertiesService(DocService):
2396 """
2397 Service that installs under the File menu to show the properties of the file associated
2398 with the current document.
2399 """
2400
2401 PROPERTIES_ID = wx.NewId()
2402
2403
2404 def __init__(self):
2405 """
2406 Initializes the PropertyService.
2407 """
2408 self._customEventHandlers = []
2409
2410
2411 def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
2412 """
2413 Installs a File/Properties menu item.
2414 """
2415 fileMenu = menuBar.GetMenu(menuBar.FindMenu(_("&File")))
2416 exitMenuItemPos = self.GetMenuItemPos(fileMenu, wx.ID_EXIT)
2417 fileMenu.InsertSeparator(exitMenuItemPos)
2418 fileMenu.Insert(exitMenuItemPos, FilePropertiesService.PROPERTIES_ID, _("&Properties"), _("Show file properties"))
2419 wx.EVT_MENU(frame, FilePropertiesService.PROPERTIES_ID, self.ProcessEvent)
2420 wx.EVT_UPDATE_UI(frame, FilePropertiesService.PROPERTIES_ID, self.ProcessUpdateUIEvent)
2421
2422
2423 def ProcessEvent(self, event):
2424 """
2425 Detects when the File/Properties menu item is selected.
2426 """
2427 id = event.GetId()
2428 if id == FilePropertiesService.PROPERTIES_ID:
2429 for eventHandler in self._customEventHandlers:
2430 if eventHandler.ProcessEvent(event):
2431 return True
2432
2433 self.ShowPropertiesDialog()
2434 return True
2435 else:
2436 return False
2437
2438
2439 def ProcessUpdateUIEvent(self, event):
2440 """
2441 Updates the File/Properties menu item.
2442 """
2443 id = event.GetId()
2444 if id == FilePropertiesService.PROPERTIES_ID:
2445 for eventHandler in self._customEventHandlers:
2446 if eventHandler.ProcessUpdateUIEvent(event):
2447 return True
2448
2449 event.Enable(wx.GetApp().GetDocumentManager().GetCurrentDocument() != None)
2450 return True
2451 else:
2452 return False
2453
2454
2455 def ShowPropertiesDialog(self, filename=None):
2456 """
2457 Shows the PropertiesDialog for the specified file.
2458 """
2459 if not filename:
2460 filename = wx.GetApp().GetDocumentManager().GetCurrentDocument().GetFilename()
2461
2462 filePropertiesDialog = FilePropertiesDialog(wx.GetApp().GetTopWindow(), filename)
2463 if filePropertiesDialog.ShowModal() == wx.ID_OK:
2464 pass # Handle OK
2465 filePropertiesDialog.Destroy()
2466
2467
2468 def GetCustomEventHandlers(self):
2469 """
2470 Returns the custom event handlers for the PropertyService.
2471 """
2472 return self._customEventHandlers
2473
2474
2475 def AddCustomEventHandler(self, handler):
2476 """
2477 Adds a custom event handlers for the PropertyService. A custom event handler enables
2478 a different dialog to be provided for a particular file.
2479 """
2480 self._customEventHandlers.append(handler)
2481
2482
2483 def RemoveCustomEventHandler(self, handler):
2484 """
2485 Removes a custom event handler from the PropertyService.
2486 """
2487 self._customEventHandlers.remove(handler)
2488
2489
2490 def chopPath(self, text, length=36):
2491 """
2492 Simple version of textwrap. textwrap.fill() unfortunately chops lines at spaces
2493 and creates odd word boundaries. Instead, we will chop the path without regard to
2494 spaces, but pay attention to path delimiters.
2495 """
2496 chopped = ""
2497 textLen = len(text)
2498 start = 0
2499
2500 while start < textLen:
2501 end = start + length
2502 if end > textLen:
2503 end = textLen
2504
2505 # see if we can find a delimiter to chop the path
2506 if end < textLen:
2507 lastSep = text.rfind(os.sep, start, end + 1)
2508 if lastSep != -1 and lastSep != start:
2509 end = lastSep
2510
2511 if len(chopped):
2512 chopped = chopped + '\n' + text[start:end]
2513 else:
2514 chopped = text[start:end]
2515
2516 start = end
2517
2518 return chopped
2519
2520
2521 class FilePropertiesDialog(wx.Dialog):
2522 """
2523 Dialog that shows the properties of a file. Invoked by the PropertiesService.
2524 """
2525
2526
2527 def __init__(self, parent, filename):
2528 """
2529 Initializes the properties dialog.
2530 """
2531 wx.Dialog.__init__(self, parent, -1, _("File Properties"), size=(310, 330))
2532
2533 HALF_SPACE = 5
2534 SPACE = 10
2535
2536 filePropertiesService = wx.GetApp().GetService(FilePropertiesService)
2537
2538 fileExists = os.path.exists(filename)
2539
2540 notebook = wx.Notebook(self, -1)
2541 tab = wx.Panel(notebook, -1)
2542
2543 gridSizer = RowColSizer()
2544
2545 gridSizer.Add(wx.StaticText(tab, -1, _("Filename:")), flag=wx.RIGHT, border=HALF_SPACE, row=0, col=0)
2546 gridSizer.Add(wx.StaticText(tab, -1, os.path.basename(filename)), row=0, col=1)
2547
2548 gridSizer.Add(wx.StaticText(tab, -1, _("Location:")), flag=wx.RIGHT, border=HALF_SPACE, row=1, col=0)
2549 gridSizer.Add(wx.StaticText(tab, -1, filePropertiesService.chopPath(os.path.dirname(filename))), flag=wx.BOTTOM, border=SPACE, row=1, col=1)
2550
2551 gridSizer.Add(wx.StaticText(tab, -1, _("Size:")), flag=wx.RIGHT, border=HALF_SPACE, row=2, col=0)
2552 if fileExists:
2553 gridSizer.Add(wx.StaticText(tab, -1, str(os.path.getsize(filename)) + ' ' + _("bytes")), row=2, col=1)
2554
2555 lineSizer = wx.BoxSizer(wx.VERTICAL) # let the line expand horizontally without vertical expansion
2556 lineSizer.Add(wx.StaticLine(tab, -1, size = (10,-1)), 0, wx.EXPAND)
2557 gridSizer.Add(lineSizer, flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.TOP, border=HALF_SPACE, row=3, col=0, colspan=2)
2558
2559 gridSizer.Add(wx.StaticText(tab, -1, _("Created:")), flag=wx.RIGHT, border=HALF_SPACE, row=4, col=0)
2560 if fileExists:
2561 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getctime(filename))), row=4, col=1)
2562
2563 gridSizer.Add(wx.StaticText(tab, -1, _("Modified:")), flag=wx.RIGHT, border=HALF_SPACE, row=5, col=0)
2564 if fileExists:
2565 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getmtime(filename))), row=5, col=1)
2566
2567 gridSizer.Add(wx.StaticText(tab, -1, _("Accessed:")), flag=wx.RIGHT, border=HALF_SPACE, row=6, col=0)
2568 if fileExists:
2569 gridSizer.Add(wx.StaticText(tab, -1, time.ctime(os.path.getatime(filename))), row=6, col=1)
2570
2571 # add a border around the inside of the tab
2572 spacerGrid = wx.BoxSizer(wx.VERTICAL)
2573 spacerGrid.Add(gridSizer, 0, wx.ALL, SPACE);
2574 tab.SetSizer(spacerGrid)
2575 notebook.AddPage(tab, _("General"))
2576
2577 sizer = wx.BoxSizer(wx.VERTICAL)
2578 sizer.Add(notebook, 0, wx.ALL | wx.EXPAND, SPACE)
2579 sizer.Add(self.CreateButtonSizer(wx.OK), 0, wx.ALIGN_RIGHT | wx.RIGHT | wx.BOTTOM, HALF_SPACE)
2580
2581 sizer.Fit(self)
2582 self.SetDimensions(-1, -1, 310, -1, wx.SIZE_USE_EXISTING)
2583 self.SetSizer(sizer)
2584 self.Layout()
2585
2586
2587 class ChildDocument(wx.lib.docview.Document):
2588 """
2589 A ChildDocument is a document that represents a portion of a Document. The child
2590 document is managed by the parent document, so it will be prompted to close if its
2591 parent is closed, etc. Child Documents are useful when there are complicated
2592 Views of a Document and users will need to tunnel into the View.
2593 """
2594
2595
2596 def GetData(self):
2597 """
2598 Returns the data that the ChildDocument contains.
2599 """
2600 return self._data
2601
2602
2603 def SetData(self, data):
2604 """
2605 Sets the data that the ChildDocument contains.
2606 """
2607 self._data = data
2608
2609
2610 def GetParentDocument(self):
2611 """
2612 Returns the parent Document of the ChildDocument.
2613 """
2614 return self._parentDocument
2615
2616
2617 def SetParentDocument(self, parentDocument):
2618 """
2619 Sets the parent Document of the ChildDocument.
2620 """
2621 self._parentDocument = parentDocument
2622
2623
2624 def OnSaveDocument(self, filename):
2625 """
2626 Called when the ChildDocument is saved and does the minimum such that the
2627 ChildDocument looks like a real Document to the framework.
2628 """
2629 self.SetFilename(filename, True)
2630 self.Modify(False)
2631 self.SetDocumentSaved(True)
2632 return True
2633
2634
2635 def OnOpenDocument(self, filename):
2636 """
2637 Called when the ChildDocument is opened and does the minimum such that the
2638 ChildDocument looks like a real Document to the framework.
2639 """
2640 self.SetFilename(filename, True)
2641 self.Modify(False)
2642 self.SetDocumentSaved(True)
2643 self.UpdateAllViews()
2644 return True
2645
2646
2647 def Save(self):
2648 """
2649 Called when the ChildDocument is saved and does the minimum such that the
2650 ChildDocument looks like a real Document to the framework.
2651 """
2652 return self.OnSaveDocument(self._documentFile)
2653
2654
2655 def SaveAs(self):
2656 """
2657 Called when the ChildDocument is saved and does the minimum such that the
2658 ChildDocument looks like a real Document to the framework.
2659 """
2660 return self.OnSaveDocument(self._documentFile)
2661
2662
2663 class ChildDocTemplate(wx.lib.docview.DocTemplate):
2664 """
2665 A ChildDocTemplate is a DocTemplate subclass that enables the creation of ChildDocuments
2666 that represents a portion of a Document. The child document is managed by the parent document,
2667 so it will be prompted to close if its parent is closed, etc. Child Documents are useful
2668 when there are complicated Views of a Document and users will need to tunnel into the View.
2669 """
2670
2671
2672 def __init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags=wx.lib.docview.TEMPLATE_INVISIBLE, icon=None):
2673 """
2674 Initializes the ChildDocTemplate.
2675 """
2676 wx.lib.docview.DocTemplate.__init__(self, manager, description, filter, dir, ext, docTypeName, viewTypeName, docType, viewType, flags=flags, icon=icon)
2677
2678
2679 def CreateDocument(self, path, flags, data=None, parentDocument=None):
2680 """
2681 Called when a ChildDocument is to be created and does the minimum such that the
2682 ChildDocument looks like a real Document to the framework.
2683 """
2684 doc = self._docType()
2685 doc.SetFilename(path)
2686 doc.SetData(data)
2687 doc.SetParentDocument(parentDocument)
2688 doc.SetDocumentTemplate(self)
2689 self.GetDocumentManager().AddDocument(doc)
2690 doc.SetCommandProcessor(doc.OnCreateCommandProcessor())
2691 if doc.OnCreate(path, flags):
2692 return doc
2693 else:
2694 if doc in self.GetDocumentManager().GetDocuments():
2695 doc.DeleteAllViews()
2696 return None
2697
2698
2699 class WindowMenuService(DocService):
2700 """
2701 The WindowMenuService is a service that implements a standard Window menu that is used
2702 by the DocSDIFrame. The MDIFrame automatically includes a Window menu and does not use
2703 the WindowMenuService.
2704 """
2705
2706
2707 def __init__(self):
2708 """
2709 Initializes the WindowMenu and its globals.
2710 """
2711 self.ARRANGE_WINDOWS_ID = wx.NewId()
2712 self.SELECT_WINDOW_1_ID = wx.NewId()
2713 self.SELECT_WINDOW_2_ID = wx.NewId()
2714 self.SELECT_WINDOW_3_ID = wx.NewId()
2715 self.SELECT_WINDOW_4_ID = wx.NewId()
2716 self.SELECT_WINDOW_5_ID = wx.NewId()
2717 self.SELECT_WINDOW_6_ID = wx.NewId()
2718 self.SELECT_WINDOW_7_ID = wx.NewId()
2719 self.SELECT_WINDOW_8_ID = wx.NewId()
2720 self.SELECT_WINDOW_9_ID = wx.NewId()
2721 self.SELECT_MORE_WINDOWS_ID = wx.NewId()
2722
2723
2724 def InstallControls(self, frame, menuBar=None, toolBar=None, statusBar=None, document=None):
2725 """
2726 Installs the Window menu.
2727 """
2728
2729 if not self.GetDocumentManager().GetFlags() & wx.lib.docview.DOC_SDI:
2730 return # Only need windows menu for SDI mode, MDI frame automatically creates one
2731
2732 if not _WINDOWS: # Arrange All and window navigation doesn't work on Linux
2733 return
2734
2735 windowMenu = wx.Menu()
2736 item = windowMenu.Append(self.ARRANGE_WINDOWS_ID, _("&Arrange All"), _("Arrange the open windows"))
2737 windowMenu.AppendSeparator()
2738
2739 wx.EVT_MENU(frame, self.ARRANGE_WINDOWS_ID, frame.ProcessEvent)
2740 wx.EVT_UPDATE_UI(frame, self.ARRANGE_WINDOWS_ID, frame.ProcessUpdateUIEvent)
2741 wx.EVT_MENU(frame, self.SELECT_WINDOW_1_ID, frame.ProcessEvent) # wxNewId may have been nonsequential, so can't use EVT_MENU_RANGE
2742 wx.EVT_MENU(frame, self.SELECT_WINDOW_2_ID, frame.ProcessEvent)
2743 wx.EVT_MENU(frame, self.SELECT_WINDOW_3_ID, frame.ProcessEvent)
2744 wx.EVT_MENU(frame, self.SELECT_WINDOW_4_ID, frame.ProcessEvent)
2745 wx.EVT_MENU(frame, self.SELECT_WINDOW_5_ID, frame.ProcessEvent)
2746 wx.EVT_MENU(frame, self.SELECT_WINDOW_6_ID, frame.ProcessEvent)
2747 wx.EVT_MENU(frame, self.SELECT_WINDOW_7_ID, frame.ProcessEvent)
2748 wx.EVT_MENU(frame, self.SELECT_WINDOW_8_ID, frame.ProcessEvent)
2749 wx.EVT_MENU(frame, self.SELECT_WINDOW_9_ID, frame.ProcessEvent)
2750 wx.EVT_MENU(frame, self.SELECT_MORE_WINDOWS_ID, frame.ProcessEvent)
2751
2752 helpMenuIndex = menuBar.FindMenu(_("&Help"))
2753 menuBar.Insert(helpMenuIndex, windowMenu, _("&Window"))
2754
2755 self._lastFrameUpdated = None
2756
2757
2758 def ProcessEvent(self, event):
2759 """
2760 Processes a Window menu event.
2761 """
2762 id = event.GetId()
2763 if id == self.ARRANGE_WINDOWS_ID:
2764 self.OnArrangeWindows(event)
2765 return True
2766 elif id == self.SELECT_MORE_WINDOWS_ID:
2767 self.OnSelectMoreWindows(event)
2768 return True
2769 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:
2770 self.OnSelectWindowMenu(event)
2771 return True
2772 else:
2773 return False
2774
2775
2776 def ProcessUpdateUIEvent(self, event):
2777 """
2778 Updates the Window menu items.
2779 """
2780 id = event.GetId()
2781 if id == self.ARRANGE_WINDOWS_ID:
2782 frame = event.GetEventObject()
2783 if not self._lastFrameUpdated or self._lastFrameUpdated != frame:
2784 self.BuildWindowMenu(frame) # It's a new frame, so update the windows menu... this is as if the View::OnActivateMethod had been invoked
2785 self._lastFrameUpdated = frame
2786 return True
2787 else:
2788 return False
2789
2790
2791 def BuildWindowMenu(self, currentFrame):
2792 """
2793 Builds the Window menu and adds menu items for all of the open documents in the DocManager.
2794 """
2795 windowMenuIndex = currentFrame.GetMenuBar().FindMenu(_("&Window"))
2796 windowMenu = currentFrame.GetMenuBar().GetMenu(windowMenuIndex)
2797 ids = self._GetWindowMenuIDList()
2798 frames = self._GetWindowMenuFrameList(currentFrame)
2799 max = WINDOW_MENU_NUM_ITEMS
2800 if max > len(frames):
2801 max = len(frames)
2802 i = 0
2803 for i in range(0, max):
2804 frame = frames[i]
2805 item = windowMenu.FindItemById(ids[i])
2806 label = '&' + str(i + 1) + ' ' + frame.GetTitle()
2807 if not item:
2808 item = windowMenu.AppendCheckItem(ids[i], label)
2809 else:
2810 windowMenu.SetLabel(ids[i], label)
2811 windowMenu.Check(ids[i], (frame == currentFrame))
2812 if len(frames) > WINDOW_MENU_NUM_ITEMS: # Add the more items item
2813 if not windowMenu.FindItemById(self.SELECT_MORE_WINDOWS_ID):
2814 windowMenu.Append(self.SELECT_MORE_WINDOWS_ID, _("&More Windows..."))
2815 else: # Remove any extra items
2816 if windowMenu.FindItemById(self.SELECT_MORE_WINDOWS_ID):
2817 windowMenu.Remove(self.SELECT_MORE_WINDOWS_ID)
2818
2819
2820
2821 for j in range(i + 1, WINDOW_MENU_NUM_ITEMS):
2822 if windowMenu.FindItemById(ids[j]):
2823 windowMenu.Remove(ids[j])
2824
2825
2826 def _GetWindowMenuIDList(self):
2827 """
2828 Returns a list of the Window menu item IDs.
2829 """
2830 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]
2831
2832
2833 def _GetWindowMenuFrameList(self, currentFrame=None):
2834 """
2835 Returns the Frame associated with each menu item in the Window menu.
2836 """
2837 frameList = []
2838 # get list of windows for documents
2839 for doc in self._docManager.GetDocuments():
2840 for view in doc.GetViews():
2841 frame = view.GetFrame()
2842 if frame not in frameList:
2843 if frame == currentFrame and len(frameList) >= WINDOW_MENU_NUM_ITEMS:
2844 frameList.insert(WINDOW_MENU_NUM_ITEMS - 1, frame)
2845 else:
2846 frameList.append(frame)
2847 # get list of windows for general services
2848 for service in wx.GetApp().GetServices():
2849 view = service.GetView()
2850 if view:
2851 frame = view.GetFrame()
2852 if frame not in frameList:
2853 if frame == currentFrame and len(frameList) >= WINDOW_MENU_NUM_ITEMS:
2854 frameList.insert(WINDOW_MENU_NUM_ITEMS - 1, frame)
2855 else:
2856 frameList.append(frame)
2857
2858 return frameList
2859
2860
2861 def OnArrangeWindows(self, event):
2862 """
2863 Called by Window/Arrange and tiles the frames on the desktop.
2864 """
2865 currentFrame = event.GetEventObject()
2866
2867 tempFrame = wx.Frame(None, -1, "", pos = wx.DefaultPosition, size = wx.DefaultSize)
2868 sizex = tempFrame.GetSize()[0]
2869 sizey = tempFrame.GetSize()[1]
2870 tempFrame.Destroy()
2871
2872 posx = 0
2873 posy = 0
2874 delta = 0
2875 frames = self._GetWindowMenuFrameList()
2876 frames.remove(currentFrame)
2877 frames.append(currentFrame) # Make the current frame the last frame so that it is the last one to appear
2878 for frame in frames:
2879 if delta == 0:
2880 delta = frame.GetClientAreaOrigin()[1]
2881 frame.SetPosition((posx, posy))
2882 frame.SetSize((sizex, sizey))
2883 # TODO: Need to loop around if posx + delta + size > displaysize
2884 frame.SetFocus()
2885 posx = posx + delta
2886 posy = posy + delta
2887 if posx + sizex > wx.DisplaySize()[0] or posy + sizey > wx.DisplaySize()[1]:
2888 posx = 0
2889 posy = 0
2890 currentFrame.SetFocus()
2891
2892
2893 def OnSelectWindowMenu(self, event):
2894 """
2895 Called when the Window menu item representing a Frame is selected and brings the selected
2896 Frame to the front of the desktop.
2897 """
2898 id = event.GetId()
2899 index = self._GetWindowMenuIDList().index(id)
2900 if index > -1:
2901 currentFrame = event.GetEventObject()
2902 frame = self._GetWindowMenuFrameList(currentFrame)[index]
2903 if frame:
2904 wx.CallAfter(frame.Raise)
2905
2906
2907 def OnSelectMoreWindows(self, event):
2908 """
2909 Called when the "Window/Select More Windows..." menu item is selected and enables user to
2910 select from the Frames that do not in the Window list. Useful when there are more than
2911 10 open frames in the application.
2912 """
2913 frames = self._GetWindowMenuFrameList() # TODO - make the current window the first one
2914 strings = map(lambda frame: frame.GetTitle(), frames)
2915 # Should preselect the current window, but not supported by wx.GetSingleChoice
2916 res = wx.GetSingleChoiceIndex(_("Select a window to show:"),
2917 _("Select Window"),
2918 strings,
2919 self)
2920 if res == -1:
2921 return
2922 frames[res].SetFocus()
2923
2924
2925 #----------------------------------------------------------------------------
2926 # File generated by encode_bitmaps.py
2927 #----------------------------------------------------------------------------
2928 from wx import ImageFromStream, BitmapFromImage
2929 import cStringIO
2930
2931 #----------------------------------------------------------------------
2932 def getNewData():
2933 return \
2934 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2935 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2936 \x00\x00[IDAT8\x8d\xed\x93\xb1\n\x001\x08C\x13{\xff\xff\xc7mn\xb8El\x91\x16\
2937 \x97\x0e\x97M\x90\x97\x88JZCE\x8f/4\xba\xb2fZc\n\x00\x00i\xcd \t\x8d\xae\x08\
2938 \xb1\xad\x9c\x0e\x1eS\x1e\x01\xc8\xcf\xdcC\xa6\x112\xf7\x08:N\xb0\xd2\x0f\
2939 \xb8\x010\xdd\x81\xdf\xf1\x8eX\xfd\xc6\xf2\x08/D\xbd\x19(\xc8\xa5\xd9\xfa\
2940 \x00\x00\x00\x00IEND\xaeB`\x82'
2941
2942 def getNewBitmap():
2943 return BitmapFromImage(getNewImage())
2944
2945 def getNewImage():
2946 stream = cStringIO.StringIO(getNewData())
2947 return ImageFromStream(stream)
2948
2949 #----------------------------------------------------------------------
2950 def getOpenData():
2951 return \
2952 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2953 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2954 \x00\x00\x95IDAT8\x8d\xa5\x92\xc1\x12\x03!\x08C\x13\xec\x87\xfb\xe3B\x0f.]\
2955 \xb0\x8e[m.\xea\x0c/\x06\x06R\n\xfe\xd1\xeb\xd7B\xd5f~\x17)\xdc2Pm\x16!\x7f\
2956 \xab6\xe3i\x0b\x9e\xe8\x93\xc0BD\x86\xdfV0\x00\x90R`\xda\xcc\x0c\x00\x0c\x00\
2957 \xc1\x05>\x9a\x87\x19t\x180\x981\xbd\xfd\xe4\xc4Y\x82\xf7\x14\xca\xe7\xb7\
2958 \xa6\t\xee6\x1c\xba\xe18\xab\xc1 \xc3\xb5N?L\xaa5\xb5\xd0\x8dw`JaJ\xb0\x0b\
2959 \x03!\xc1\t\xdc\xb9k\x0f\x9e\xd1\x0b\x18\xf6\xe0x\x95]\xf2\\\xb2\xd6\x1b}\
2960 \x14BL\xb9{t\xc7\x00\x00\x00\x00IEND\xaeB`\x82'
2961
2962 def getOpenBitmap():
2963 return BitmapFromImage(getOpenImage())
2964
2965 def getOpenImage():
2966 stream = cStringIO.StringIO(getOpenData())
2967 return ImageFromStream(stream)
2968
2969 #----------------------------------------------------------------------
2970 def getCopyData():
2971 return \
2972 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2973 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2974 \x00\x00\x9fIDAT8\x8d\xa5\x93\xdb\x0e\x830\x0cC\xed\x84\xdfF\xeb\xb4\xef\xa6\
2975 \xde\x030z\t\x94\tK\x91z\xcb\x01\xbb*i\x8e\'\x9a\x00@yQ\xb4Is\x8e\x00\xb6\
2976 \x0f$Uu\x05\x0e\x01\x91$\r!\xa49\x94\x17I\x02\xc9_\xe3:Nq\x93}XL|\xeb\xe9\
2977 \x05\xa4p\rH\xa29h^[ Y\xd5\xb9\xb5\x17\x94gu\x19DA\x96\xe0c\xfe^\xcf\xe7Y\
2978 \x95\x05\x00M\xf5\x16Z;\x7f\xfdAd\xcf\xee\x1cj\xc1%|\xdan"LL\x19\xda\xe1}\
2979 \x90:\x00#\x95_l5\x04\xec\x89\x9f\xef?|\x8d\x97o\xe1\x8e\xbeJ\xfc\xb1\xde\
2980 \xea\xf8\xb9\xc4\x00\x00\x00\x00IEND\xaeB`\x82'
2981
2982 def getCopyBitmap():
2983 return BitmapFromImage(getCopyImage())
2984
2985 def getCopyImage():
2986 stream = cStringIO.StringIO(getCopyData())
2987 return ImageFromStream(stream)
2988
2989 #----------------------------------------------------------------------
2990 def getPasteData():
2991 return \
2992 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
2993 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
2994 \x00\x00\xa1IDAT8\x8d\xa5\x93\xd9\x0e\xc3 \x0c\x04\xc7\xa6\xbf]\xc5U\xbf\xbb\
2995 \xd9>$4\\9\xaa\xacd\t\x0c\x1e/H6\xf3\xc4\x1d=FI\xcd\x1f\x95{\xf3d{\x003O]\
2996 \x01\x80\x94/\x0c\x8a\n\xa0\x01\x8a\x88\xdfaD m\x85y\xdd\xde\xc9\x10/\xc9\
2997 \xf9\xc0S2\xf3%\xf2\xba\x04\x94\xea\xfe`\xf4\x9c#U\x80\xbd.\x97\x015\xec&\
2998 \x00@\x9a\xba\x9c\xd9\x0b\x08\xe0\r4\x9fxU\xd2\x84\xe6\xa7N\x1dl\x1dkGe\xee\
2999 \x14\xd0>\xa3\x85\xfc\xe5`\x08]\x87I}\x84\x8e\x04!\xf3\xb48\x18\r\x8bf4\xea\
3000 \xde;\xbc9\xce_!\\\\T\xf75'\xd6\x00\x00\x00\x00IEND\xaeB`\x82"
3001
3002 def getPasteBitmap():
3003 return BitmapFromImage(getPasteImage())
3004
3005 def getPasteImage():
3006 stream = cStringIO.StringIO(getPasteData())
3007 return ImageFromStream(stream)
3008
3009 #----------------------------------------------------------------------
3010 def getSaveData():
3011 return \
3012 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3013 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3014 \x00\x00lIDAT8\x8d\xc5\x93\xe1\n\xc0 \x08\x84=\xed\xc1}\xf1\xcd\xfd\x18B\x98\
3015 mX\x83\x1d\x04\x11\xfayV\x02,\xb4#\xde\xca&\xa2\xe6\x1b;\x0f\xab$\x82\x05\
3016 \x83\x03U\xbdaf\xe9\xea\x13]\xe5\x16\xa2\xd32\xc0].\x03\xa2Z<PU\x02\x90\xc5\
3017 \x0e\xd5S\xc0,p\xa6\xef[xs\xb0t\x89`A|\xff\x12\xe0\x11\xde\x0fS\xe5;\xbb#\
3018 \xfc>\x8d\x17\x18\xfd(\xb72\xc2\x06\x00\x00\x00\x00\x00IEND\xaeB`\x82'
3019
3020 def getSaveBitmap():
3021 return BitmapFromImage(getSaveImage())
3022
3023 def getSaveImage():
3024 stream = cStringIO.StringIO(getSaveData())
3025 return ImageFromStream(stream)
3026
3027 #----------------------------------------------------------------------
3028 def getSaveAllData():
3029 return \
3030 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3031 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3032 \x00\x01\tIDAT8\x8d\xa5\x93\xe1m\x830\x10\x85\xdfA\xd7H\x827\xf0\x02\xado\
3033 \x04\x8f`Fh\xfb\xb7\xad\xcd&$Y\x80\x11\xcc\x06\x8c\xe0E\xd2\xeb\x8f\x16\x04!\
3034 8R\xf3\xa4\x93Nw\xd2\xf3\xa7g\x9b\xa8(\xf1\x88\x9er\xcb\xc3~\')%x\xef\xa7Y\
3035 \x8c\x11J)\x00\xc0\xf1t&PQn\x163\x0b\x00\x99\xcb{/\x00\xc49\'T\x94(\xfe\x83\
3036 \x1dB\x98\xfa\x95\xc1a\xbf\x13\xf9\xbe\xc8\xd7\xe7\x87\x18c\xe0\xbd\x073\xa3\
3037 \xaek\x10\x11\xfa\xbe\xcfgPU\x15RJ\x8bSB\x08h\x9af1\xdb$\xc8aw]\x87\xae\xeb\
3038 \xd6\x04\xd7i\x1bc\xc0\xccPJ\xa1m[03\x98\x19Z\xeb\x951QQ\xc2\xbc<K\x8c\x11"\
3039 \x92\xc5N)M\xbd\xd6\x1a\xafo\xef\x94}\x07#6\x00Xk\x7f\xef\xfdO\xc7\xd3\x19\
3040 \xc0,\x83\x10\x02\x88h\xaa1m\xad\xf5M\xf4E\x06s\x93-\xcd\xf1\xef\x1a\x8c\'^c\
3041 \xdf5\x18\x95C\xbei`\xad\xc50\x0cp\xce-\x96[\xd8s\xd1\xa3\xdf\xf9\x075\xf1v>\
3042 \x92\xcb\xbc\xdd\x00\x00\x00\x00IEND\xaeB`\x82'
3043
3044 def getSaveAllBitmap():
3045 return BitmapFromImage(getSaveAllImage())
3046
3047 def getSaveAllImage():
3048 stream = cStringIO.StringIO(getSaveAllData())
3049 return ImageFromStream(stream)
3050
3051 #----------------------------------------------------------------------
3052 def getPrintData():
3053 return \
3054 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3055 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3056 \x00\x00\xa1IDAT8\x8d\xa5S[\x0e\x02!\x0c\xec\xd0\xbd\xb6\x1a\xf5\xda\x96\xd9\
3057 \x0f\xa1V\x96\x00\xbaMHI\xd3y\xf0(\x90T\xce\xc4\xd6+2\x1bg@$E\x97\x80\xd9H\
3058 \x8e\xf1\x00\xc6\x0e\xda&''\x05\x80\xab\x1f\x08\xa2\xfa\xcc\xc5\xd0\xc1H\xbd\
3059 \n\x89\xbc\xef\xc1\tV\xd5\x91\x14\xcc\xc6\x9a\xa5<#WV\xed\x8d\x18\x94\xc2\
3060 \xd1s'\xa2\xb2\xe7\xc2\xf4STAf\xe3\x16\x0bm\xdc\xae\x17'\xbf?\x9e\x0e\x8an\
3061 \x86G\xc8\xf6\xf9\x91I\xf5\x8b\xa0\n\xff}\x04w\x80\xa4ng\x06l/QD\x04u\x1aW\
3062 \x06(:\xf0\xfd\x99q\xce\xf6\xe2\x0e\xa5\xa2~.\x00=\xb5t\x00\x00\x00\x00IEND\
3063 \xaeB`\x82"
3064
3065 def getPrintBitmap():
3066 return BitmapFromImage(getPrintImage())
3067
3068 def getPrintImage():
3069 stream = cStringIO.StringIO(getPrintData())
3070 return ImageFromStream(stream)
3071
3072 #----------------------------------------------------------------------
3073 def getPrintPreviewData():
3074 return \
3075 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3076 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3077 \x00\x00\xa8IDAT8\x8d\x9d\x93K\x0e\xc30\x08Dg \xd7n\xcd\xc1\x9b\xd2E\x83E\\\
3078 \xffT$/\x82\xc5\x83\x19\x13\x02p,\x82\xa2\x1c\xde\x01p\xf71\x83\xe4\x14"\xab\
3079 \xeeQ\xec\xef\xb3\xdbe{\x82\x0c\xcb\xdf\xc7\xaa{\x86\xb7\xb0-@\xaf(\xc7\xd4\
3080 \x03\x9203P\x94\x14\xa5\x99\xa1\xf5b\x08\x88b+\x05~\xbejQ\x0f\xe2\xbd\x00\
3081 \xe0\x14\x05\xdc\x9d\xa2\xa0(\xcc\xec\x9b\xbb\xee(\xba~F\xea15a\n(\xcfG\x1d5\
3082 d\xe4\xdcTB\xc8\x88\xb1CB\x9b\x9b\x02\x02\x92O@\xaa\x0fXl\xe2\xcd\x0f\xf2g\
3083 \xad\x89\x8d\xbf\xf1\x06\xb9V9 \x0c\x1d\xff\xc6\x07\x8aF\x9e\x04\x12\xb5\xf9\
3084 O\x00\x00\x00\x00IEND\xaeB`\x82'
3085
3086 def getPrintPreviewBitmap():
3087 return BitmapFromImage(getPrintPreviewImage())
3088
3089 def getPrintPreviewImage():
3090 stream = cStringIO.StringIO(getPrintPreviewData())
3091 return ImageFromStream(stream)
3092
3093 #----------------------------------------------------------------------
3094 def getCutData():
3095 return \
3096 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3097 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3098 \x00\x00rIDAT8\x8d\xad\x93\xc1\x0e\xc0 \x08CW\xdco{\xf2\xbb';\xb18\x07\x9d\
3099 \x0b\xe3\xa2\x98\xe6\xb5$\x02H\xd92%\xde\xa3\xf6CY\xff\nH'\xf8\x05`\xb1Y\xfc\
3100 \x10\x00)`\xfdR\x82\x15w\n0W\xe6N\x01\xda\xab\x8e\xe7g\xc0\xe8\xae\xbdj\x04\
3101 \xda#\xe7;\xa8] \xbb\xbb\tL0\x8bX\xa5?\xd2c\x84\xb9 \r6\x96\x97\x0c\xf362\
3102 \xb1k\x90]\xe7\x13\x85\xca7&\xcf\xda\xcdU\x00\x00\x00\x00IEND\xaeB`\x82"
3103
3104 def getCutBitmap():
3105 return BitmapFromImage(getCutImage())
3106
3107 def getCutImage():
3108 stream = cStringIO.StringIO(getCutData())
3109 return ImageFromStream(stream)
3110
3111 #----------------------------------------------------------------------
3112 def getUndoData():
3113 return \
3114 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3115 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3116 \x00\x00lIDAT8\x8d\xed\x92Q\x0b\x800\x08\x84\xd5\xf5\xb7\x07W\xfdo\xed!\xaca\
3117 \xb2\x11{\xe9!a\xa0\xc7\xeec\x1ec\x96B3%S\xeeO\x00\x96\xd1\x05\xd3j\xed\x0c\
3118 \x10\xad\xdb\xce\x97\xc0R\xe8\x0c\x12\xe6\xbd\xcfQs\x1d\xb8\xf5\xd4\x90\x19#\
3119 \xc4\xfbG\x06\xa6\xd5X\x9a'\x0e*\r1\xee\xfd\x1a\xd0\x83\x98V\x03\x1a\xa1\xb7\
3120 k<@\x12\xec\xff\x95\xe7\x01\x07L\x0e(\xe5\xa4\xff\x1c\x88\x00\x00\x00\x00IEN\
3121 D\xaeB`\x82"
3122
3123 def getUndoBitmap():
3124 return BitmapFromImage(getUndoImage())
3125
3126 def getUndoImage():
3127 stream = cStringIO.StringIO(getUndoData())
3128 return ImageFromStream(stream)
3129
3130 #----------------------------------------------------------------------
3131 def getRedoData():
3132 return \
3133 "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3134 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3135 \x00\x00jIDAT8\x8d\xed\x92\xcd\n\xc0 \x0c\x83\x9bv\xaf\xed\x16\xf0\xbd\xd7]&\
3136 \xf8\x8f\xe0e\x87\t9$\xb6\x1f\xb5\x08\xa8\xc9\xce\xd1\xad\xeeO\x00\x8e\xdc\\\
3137 gp\xb2,\x80FL\tP\x13\xa8\tI\x17\xa1'\x9f$\xd2\xe6\xb9\xef\x86=\xa5\xfb\x1a\
3138 \xb8\xbc\x03h\x84\xdf\xc1\xeb|\x19\xd0k.\x00\xe4\xb8h\x94\xbf\xa3\x95\xef$\
3139 \xe7\xbbh\xf4\x7f\xe5}\xc0\x03&\x1b&\xe5\xc2\x03!\xa6\x00\x00\x00\x00IEND\
3140 \xaeB`\x82"
3141
3142 def getRedoBitmap():
3143 return BitmapFromImage(getRedoImage())
3144
3145 def getRedoImage():
3146 stream = cStringIO.StringIO(getRedoData())
3147 return ImageFromStream(stream)
3148
3149 #----------------------------------------------------------------------------
3150
3151 def getBlankData():
3152 return \
3153 '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\x00\x00\x00\x10\x08\x06\
3154 \x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\
3155 \x00\x00]IDAT8\x8d\xed\x931\x0e\xc00\x08\x03m\x92\xff\xff8q\x87\xb6C\x11\x89\
3156 \xa8X:\xd4\x13\x03:\x1b\x01\xa45T\xd4\xefBsh\xd7Hk\xdc\x02\x00@\x8a\x19$\xa1\
3157 9\x14A,\x95\xf3\x82G)\xd3\x00\xf24\xf7\x90\x1ev\x07\xee\x1e\xf4:\xc1J?\xe0\
3158 \x0b\x80\xc7\x1d\xf8\x1dg\xc4\xea7\x96G8\x00\xa8\x91\x19(\x85#P\x7f\x00\x00\
3159 \x00\x00IEND\xaeB`\x82'
3160
3161
3162 def getBlankBitmap():
3163 return BitmapFromImage(getBlankImage())
3164
3165 def getBlankImage():
3166 stream = cStringIO.StringIO(getBlankData())
3167 return ImageFromStream(stream)
3168
3169 def getBlankIcon():
3170 return wx.IconFromBitmap(getBlankBitmap())
3171
3172