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