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