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