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