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