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