+        frameSize = self.GetSize()   # TODO: GetClientWindow.GetSize is still returning 0,0 since the frame isn't fully constructed yet, so using full frame size
+        defaultHSize = int(frameSize[0] / 6)
+        defaultVSize = int(frameSize[1] / 7)
+        defaultSubVSize = int(frameSize[1] / 2)
+        config = wx.ConfigBase_Get()
+        if windows & (EMBEDDED_WINDOW_LEFT | EMBEDDED_WINDOW_TOPLEFT | EMBEDDED_WINDOW_BOTTOMLEFT):
+            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)
+        else:
+            self._leftEmbWindow = None
+        if windows & EMBEDDED_WINDOW_TOPLEFT:
+            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)
+        else:
+            self._topLeftEmbWindow = None
+        if windows & EMBEDDED_WINDOW_BOTTOMLEFT:
+            self._bottomLeftEmbWindow = self._CreateEmbeddedWindow(self._leftEmbWindow, (-1, config.ReadInt("MDIEmbedBottomLeftSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomLeftVisible", 1))
+        else:
+            self._bottomLeftEmbWindow = None
+        if windows & (EMBEDDED_WINDOW_RIGHT | EMBEDDED_WINDOW_TOPRIGHT | EMBEDDED_WINDOW_BOTTOMRIGHT):
+            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)
+        else:
+            self._rightEmbWindow = None
+        if windows & EMBEDDED_WINDOW_TOPRIGHT:
+            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)
+        else:
+            self._topRightEmbWindow = None
+        if windows & EMBEDDED_WINDOW_BOTTOMRIGHT:
+            self._bottomRightEmbWindow = self._CreateEmbeddedWindow(self._rightEmbWindow, (-1, config.ReadInt("MDIEmbedBottomRightSize", defaultSubVSize)), wx.LAYOUT_HORIZONTAL, wx.LAYOUT_BOTTOM, visible = config.ReadInt("MDIEmbedBottomRightVisible", 1))
+        else:
+            self._bottomRightEmbWindow = None
+        if windows & EMBEDDED_WINDOW_TOP:
+            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)
+        else:
+            self._topEmbWindow = None
+        if windows & EMBEDDED_WINDOW_BOTTOM:
+            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)
+        else:
+            self._bottomEmbWindow = None
+
+
+    def SaveEmbeddedWindowSizes(self):
+        """
+        Saves the sizes of the embedded windows.
+        """
+        config = wx.ConfigBase_Get()
+        if not self.IsMaximized():
+            config.WriteInt("MDIFrameXLoc", self.GetPositionTuple()[0])
+            config.WriteInt("MDIFrameYLoc", self.GetPositionTuple()[1])
+            config.WriteInt("MDIFrameXSize", self.GetSizeTuple()[0])
+            config.WriteInt("MDIFrameYSize", self.GetSizeTuple()[1])
+        config.WriteInt("MDIFrameMaximized", self.IsMaximized())
+        config.WriteInt("ViewToolBar", self._toolBar.IsShown())
+        config.WriteInt("ViewStatusBar", self.GetStatusBar().IsShown())
+
+        if self._leftEmbWindow:
+            config.WriteInt("MDIEmbedLeftSize", self._leftEmbWindow.GetSize()[0])
+            config.WriteInt("MDIEmbedLeftVisible", self._leftEmbWindow.IsShown())
+        if self._topLeftEmbWindow:
+            if self._topLeftEmbWindow._sizeBeforeHidden:
+                size = self._topLeftEmbWindow._sizeBeforeHidden[1]
+            else:
+                size = self._topLeftEmbWindow.GetSize()[1]
+            config.WriteInt("MDIEmbedTopLeftSize", size)
+            config.WriteInt("MDIEmbedTopLeftVisible", self._topLeftEmbWindow.IsShown())
+        if self._bottomLeftEmbWindow:
+            if self._bottomLeftEmbWindow._sizeBeforeHidden:
+                size = self._bottomLeftEmbWindow._sizeBeforeHidden[1]
+            else:
+                size = self._bottomLeftEmbWindow.GetSize()[1]
+            config.WriteInt("MDIEmbedBottomLeftSize", size)
+            config.WriteInt("MDIEmbedBottomLeftVisible", self._bottomLeftEmbWindow.IsShown())
+        if self._rightEmbWindow:
+            config.WriteInt("MDIEmbedRightSize", self._rightEmbWindow.GetSize()[0])
+            config.WriteInt("MDIEmbedRightVisible", self._rightEmbWindow.IsShown())
+        if self._topRightEmbWindow:
+            if self._topRightEmbWindow._sizeBeforeHidden:
+                size = self._topRightEmbWindow._sizeBeforeHidden[1]
+            else:
+                size = self._topRightEmbWindow.GetSize()[1]
+            config.WriteInt("MDIEmbedTopRightSize", size)
+            config.WriteInt("MDIEmbedTopRightVisible", self._topRightEmbWindow.IsShown())
+        if self._bottomRightEmbWindow:
+            if self._bottomRightEmbWindow._sizeBeforeHidden:
+                size = self._bottomRightEmbWindow._sizeBeforeHidden[1]
+            else:
+                size = self._bottomRightEmbWindow.GetSize()[1]
+            config.WriteInt("MDIEmbedBottomRightSize", size)
+            config.WriteInt("MDIEmbedBottomRightVisible", self._bottomRightEmbWindow.IsShown())
+        if self._topEmbWindow:
+            config.WriteInt("MDIEmbedTopSize", self._topEmbWindow.GetSize()[1])
+            config.WriteInt("MDIEmbedTopVisible", self._topEmbWindow.IsShown())
+        if self._bottomEmbWindow:
+            config.WriteInt("MDIEmbedBottomSize", self._bottomEmbWindow.GetSize()[1])
+            config.WriteInt("MDIEmbedBottomVisible", self._bottomEmbWindow.IsShown())
+
+
+    def GetEmbeddedWindow(self, loc):
+        """
+        Returns the instance of the embedded window specified by the embedded window location constant.
+        """
+        if loc == EMBEDDED_WINDOW_TOP:
+            return self._topEmbWindow
+        elif loc == EMBEDDED_WINDOW_BOTTOM:
+            return self._bottomEmbWindow
+        elif loc == EMBEDDED_WINDOW_LEFT:
+            return self._leftEmbWindow
+        elif loc == EMBEDDED_WINDOW_RIGHT:
+            return self._rightEmbWindow
+        elif loc == EMBEDDED_WINDOW_TOPLEFT:
+            return self._topLeftEmbWindow
+        elif loc == EMBEDDED_WINDOW_BOTTOMLEFT:
+            return self._bottomLeftEmbWindow
+        elif loc == EMBEDDED_WINDOW_TOPRIGHT:
+            return self._topRightEmbWindow
+        elif loc == EMBEDDED_WINDOW_BOTTOMRIGHT:
+            return self._bottomRightEmbWindow
+        return None
+
+
+    def _CreateEmbeddedWindow(self, parent, size, orientation, alignment, visible=True, sash=None):
+        """
+        Creates the embedded window with the specified size, orientation, and alignment.  If the 
+        window is not visible it will retain the size with which it was last viewed.
+        """
+        window = wx.SashLayoutWindow(parent, wx.NewId(), style = wx.NO_BORDER | wx.SW_3D)
+        window.SetDefaultSize(size)
+        window.SetOrientation(orientation)
+        window.SetAlignment(alignment)
+        if sash != None:  # wx.SASH_TOP is 0 so check for None instead of just doing "if sash:"
+            window.SetSashVisible(sash, True)
+        ####
+        def OnEmbeddedWindowSashDrag(event):
+            if event.GetDragStatus() == wx.SASH_STATUS_OUT_OF_RANGE:
+                return
+            sashWindow = event.GetEventObject()
+            if sashWindow.GetAlignment() == wx.LAYOUT_TOP or sashWindow.GetAlignment() == wx.LAYOUT_BOTTOM:
+                size = wx.Size(-1, event.GetDragRect().height)
+            else:
+                size = wx.Size(event.GetDragRect().width, -1)
+            event.GetEventObject().SetDefaultSize(size)
+            self._LayoutFrame()
+            sashWindow.Refresh()
+            if isinstance(sashWindow.GetParent(), wx.SashLayoutWindow):
+                sashWindow.Show()
+                parentSashWindow = sashWindow.GetParent()  # Force a refresh
+                parentSashWindow.Layout()
+                parentSashWindow.Refresh()
+                parentSashWindow.SetSize((parentSashWindow.GetSize().width + 1, parentSashWindow.GetSize().height + 1))
+        ####
+        wx.EVT_SASH_DRAGGED(window, window.GetId(), OnEmbeddedWindowSashDrag)
+        window._sizeBeforeHidden = None
+        if not visible:
+            window.Show(False)
+            if isinstance(parent, wx.SashLayoutWindow): # It's a window embedded in another sash window so remember its actual size to show it again
+                window._sizeBeforeHidden = size
+        return window
+
+
+    def ShowEmbeddedWindow(self, window, show=True):
+        """
+        Shows or hides the embedded window specified by the embedded window location constant.
+        """
+        window.Show(show)
+        if isinstance(window.GetParent(), wx.SashLayoutWindow):  # It is a parent sashwindow with multiple embedded sashwindows
+            parentSashWindow = window.GetParent()
+            if show:  # Make sure it is visible in case all of the subwindows were hidden
+                parentSashWindow.Show()                
+            if show and window._sizeBeforeHidden:
+                if window._sizeBeforeHidden[1] == parentSashWindow.GetClientSize()[1]:
+                    if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).IsShown():
+                        window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).GetSize()[1]))
+                    elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).IsShown():
+                        window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).GetSize()[1]))
+                    elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).IsShown():
+                        window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).GetSize()[1]))
+                    elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT) and self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).IsShown():
+                        window.SetDefaultSize((window._sizeBeforeHidden[0], window._sizeBeforeHidden[0] - self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).GetSize()[1]))
+                else:
+                    window.SetDefaultSize(window._sizeBeforeHidden)
+                    # 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
+                    if window._sizeBeforeHidden[1] < parentSashWindow.GetClientSize()[1]:
+                        otherWindowSize = (-1, parentSashWindow.GetClientSize()[1] - window._sizeBeforeHidden[1])
+                        if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT):
+                            self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).SetDefaultSize(otherWindowSize)
+                        elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT):
+                            self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).SetDefaultSize(otherWindowSize)
+                        elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT):
+                            self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).SetDefaultSize(otherWindowSize)
+                        elif window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT):
+                            self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).SetDefaultSize(otherWindowSize)
+                    
+            if not show:
+                if window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT).IsShown() \
+                    or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPRIGHT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMRIGHT).IsShown() \
+                    or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT).IsShown() \
+                    or window == self.GetEmbeddedWindow(EMBEDDED_WINDOW_TOPLEFT) and not self.GetEmbeddedWindow(EMBEDDED_WINDOW_BOTTOMLEFT).IsShown():
+                    parentSashWindow.Hide()  # Hide the parent sashwindow if all of the children are hidden
+            parentSashWindow.Layout()   # Force a refresh
+            parentSashWindow.Refresh()
+            parentSashWindow.SetSize((parentSashWindow.GetSize().width + 1, parentSashWindow.GetSize().height + 1))
+        self._LayoutFrame()
+
+
+    def HideEmbeddedWindow(self):
+        """
+        Hides the embedded window specified by the embedded window location constant.
+        """
+        self.ShowEmbeddedWindow(show = False)
+
+
+class DocTabbedChildFrame(wx.Panel):
+    """
+    The wxDocMDIChildFrame class provides a default frame for displaying
+    documents on separate windows. This class can only be used for MDI child
+    frames.
+
+    The class is part of the document/view framework supported by wxWindows,
+    and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
+    classes.
+    """
+
+
+    def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
+        """
+        Constructor.  Note that the event table must be rebuilt for the
+        frame since the EvtHandler is not virtual.
+        """
+        wx.Panel.__init__(self, frame.GetNotebook(), id)
+        self._childDocument = doc
+        self._childView = view
+        frame.AddNotebookPage(self, doc.GetPrintableName())
+        if view:
+            view.SetFrame(self)
+
+
+    def GetIcon(self):
+        """
+        Dummy method since the icon of tabbed frames are managed by the notebook.
+        """
+        return None
+        
+
+    def SetIcon(self, icon):
+        """
+        Dummy method since the icon of tabbed frames are managed by the notebook.
+        """
+        pass
+
+
+    def Destroy(self):
+        """
+        Removes the current notebook page.
+        """
+        wx.GetApp().GetTopWindow().RemoveNotebookPage(self)
+
+
+    def SetFocus(self):
+        """
+        Activates the current notebook page.
+        """
+        wx.GetApp().GetTopWindow().ActivateNotebookPage(self)
+
+
+    def Activate(self):  # Need this in case there are embedded sash windows and such, OnActivate is not getting called
+        """
+        Activates the current view.
+        """
+        # Called by Project Editor
+        if self._childView:
+            self._childView.Activate(True)
+
+
+    def GetTitle(self):
+        """
+        Returns the frame's title.
+        """
+        wx.GetApp().GetTopWindow().GetNotebookPageTitle(self)
+
+
+    def SetTitle(self, title):
+        """
+        Sets the frame's title.
+        """
+        wx.GetApp().GetTopWindow().SetNotebookPageTitle(self, title)
+
+
+    def ProcessEvent(event):
+        """
+        Processes an event, searching event tables and calling zero or more
+        suitable event handler function(s).  Note that the ProcessEvent
+        method is called from the wxPython docview framework directly since
+        wxPython does not have a virtual ProcessEvent function.
+        """
+        if not self._childView or not self._childView.ProcessEvent(event):
+            if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
+                return False
+            else:
+                return True
+        else:
+            return True
+
+
+    def GetDocument(self):
+        """
+        Returns the document associated with this frame.
+        """
+        return self._childDocument
+
+
+    def SetDocument(self, document):
+        """
+        Sets the document for this frame.
+        """
+        self._childDocument = document
+
+
+    def GetView(self):
+        """
+        Returns the view associated with this frame.
+        """
+        return self._childView
+
+
+    def SetView(self, view):
+        """
+        Sets the view for this frame.
+        """
+        self._childView = view
+
+
+class DocTabbedParentFrame(wx.Frame, DocFrameMixIn, DocMDIParentFrameMixIn):
+    """
+    The DocTabbedParentFrame class provides a default top-level frame for
+    applications using the document/view framework. This class can only be
+    used for MDI parent frames that use a tabbed interface.
+
+    It cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
+    classes.
+    """
+
+
+    def __init__(self, docManager, frame, id, title, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, name = "DocTabbedParentFrame", embeddedWindows = 0):
+        """
+        Constructor.  Note that the event table must be rebuilt for the
+        frame since the EvtHandler is not virtual.
+        """
+        pos, size = self._GetPosSizeFromConfig(pos, size)
+        wx.Frame.__init__(self, frame, id, title, pos, size, style, name)
+
+        # From docview.MDIParentFrame
+        self._docManager = docManager
+
+        wx.EVT_CLOSE(self, self.OnCloseWindow)
+
+        wx.EVT_MENU(self, wx.ID_EXIT, self.OnExit)
+        wx.EVT_MENU_RANGE(self, wx.ID_FILE1, wx.ID_FILE9, self.OnMRUFile)
+
+        wx.EVT_MENU(self, wx.ID_NEW, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_OPEN, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_CLOSE_ALL, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_CLOSE, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_REVERT, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_SAVE, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_SAVEAS, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_UNDO, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_REDO, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_PRINT, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_PRINT_SETUP, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_PREVIEW, self.ProcessEvent)
+        wx.EVT_MENU(self, wx.ID_ABOUT, self.OnAbout)
+
+        wx.EVT_UPDATE_UI(self, wx.ID_NEW, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_OPEN, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_CLOSE_ALL, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_CLOSE, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_REVERT, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_SAVE, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_SAVEAS, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_UNDO, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_REDO, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_PRINT, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_PRINT_SETUP, self.ProcessUpdateUIEvent)
+        wx.EVT_UPDATE_UI(self, wx.ID_PREVIEW, self.ProcessUpdateUIEvent)
+        # End From docview.MDIParentFrame
+
+        self.CreateNotebook()
+        self._InitFrame(embeddedWindows)
+        
+
+    def _LayoutFrame(self):
+        """
+        Lays out the frame.
+        """
+        wx.LayoutAlgorithm().LayoutFrame(self, self._notebook)
+        
+
+    def CreateNotebook(self):
+        """
+        Creates the notebook to use for the tabbed document interface.
+        """     
+        self._notebook = wx.Notebook(self, wx.NewId())
+        # self._notebook.SetSizer(wx.NotebookSizer(self._notebook))
+        wx.EVT_NOTEBOOK_PAGE_CHANGED(self, self._notebook.GetId(), self.OnNotebookPageChanged)
+        wx.EVT_RIGHT_DOWN(self._notebook, self.OnNotebookRightClick)
+        wx.EVT_MOTION(self._notebook, self.OnNotebookMouseOver)
+
+        templates = wx.GetApp().GetDocumentManager().GetTemplates()
+        iconList = wx.ImageList(16, 16, initialCount = len(templates))
+        self._iconIndexLookup = []
+        for template in templates:
+            icon = template.GetIcon()
+            if icon:
+                if icon.GetHeight() != 16 or icon.GetWidth() != 16:
+                    icon.SetHeight(16)
+                    icon.SetWidth(16)
+                    if wx.GetApp().GetDebug():
+                        print "Warning: icon for '%s' isn't 16x16, not crossplatform" % template._docTypeName
+                iconIndex = iconList.AddIcon(icon)
+                self._iconIndexLookup.append((template, iconIndex))
+                
+        icon = getBlankIcon()
+        if icon.GetHeight() != 16 or icon.GetWidth() != 16:
+            icon.SetHeight(16)
+            icon.SetWidth(16)
+            if wx.GetApp().GetDebug():
+                print "Warning: getBlankIcon isn't 16x16, not crossplatform"
+        self._blankIconIndex = iconList.AddIcon(icon)
+        self._notebook.AssignImageList(iconList)
+
+
+    def GetNotebook(self):
+        """
+        Returns the notebook used by the tabbed document interface.
+        """
+        return self._notebook
+        
+
+    def GetActiveChild(self):
+        """
+        Returns the active notebook page, which to the framework is treated as
+        a document frame.
+        """
+        index = self._notebook.GetSelection()
+        if index == -1:
+            return None
+        return self._notebook.GetPage(index)
+
+
+    def OnNotebookPageChanged(self, event):
+        """
+        Activates a notebook page's view when it is selected.
+        """
+        index = self._notebook.GetSelection()
+        if index > -1:
+            self._notebook.GetPage(index).GetView().Activate()
+
+
+    def OnNotebookMouseOver(self, event):
+        # wxBug: On Windows XP the tooltips don't automatically disappear when you move the mouse and it is on a notebook tab, has nothing to do with this code!!!
+        index, type = self._notebook.HitTest(event.GetPosition())
+        if index > -1:
+            doc = self._notebook.GetPage(index).GetView().GetDocument()
+            self._notebook.SetToolTip(wx.ToolTip(doc.GetFilename()))
+        else:
+            self._notebook.SetToolTip(wx.ToolTip(""))
+        event.Skip()
+            
+
+    def OnNotebookRightClick(self, event):
+        """
+        Handles right clicks for the notebook, enabling users to either close
+        a tab or select from the available documents if the user clicks on the
+        notebook's white space.
+        """
+        index, type = self._notebook.HitTest(event.GetPosition())
+        menu = wx.Menu()
+        x, y = event.GetX(), event.GetY()
+        if index > -1:
+            doc = self._notebook.GetPage(index).GetView().GetDocument()
+            id = wx.NewId()
+            menu.Append(id, _("Close"))
+            def OnRightMenuSelect(event):
+                doc.DeleteAllViews()
+            wx.EVT_MENU(self, id, OnRightMenuSelect)
+            if self._notebook.GetPageCount() > 1:
+                id = wx.NewId()
+                menu.Append(id, _("Close All but \"%s\"" % doc.GetPrintableName()))
+                def OnRightMenuSelect(event):
+                    for i in range(self._notebook.GetPageCount()-1, -1, -1): # Go from len-1 to 0
+                        if i != index:
+                            doc = self._notebook.GetPage(i).GetView().GetDocument()
+                            if not self.GetDocumentManager().CloseDocument(doc, False):
+                                return
+                wx.EVT_MENU(self, id, OnRightMenuSelect)
+                menu.AppendSeparator()
+                tabsMenu = wx.Menu()
+                menu.AppendMenu(wx.NewId(), _("Select Tab"), tabsMenu)
+        else:
+            y = y - 25  # wxBug: It is offsetting click events in the blank notebook area
+            tabsMenu = menu
+
+        if self._notebook.GetPageCount() > 1:
+            selectIDs = {}
+            for i in range(0, self._notebook.GetPageCount()):
+                id = wx.NewId()
+                selectIDs[id] = i
+                tabsMenu.Append(id, self._notebook.GetPageText(i))
+                def OnRightMenuSelect(event):
+                    self._notebook.SetSelection(selectIDs[event.GetId()])
+                wx.EVT_MENU(self, id, OnRightMenuSelect)
+        
+        self._notebook.PopupMenu(menu, wx.Point(x, y))
+        menu.Destroy()
+            
+            
+    def AddNotebookPage(self, panel, title):
+        """
+        Adds a document page to the notebook.
+        """
+        self._notebook.AddPage(panel, title)
+        index = self._notebook.GetPageCount() - 1
+        self._notebook.SetSelection(index)
+
+        found = False  # Now set the icon
+        template = panel.GetDocument().GetDocumentTemplate()
+        if template:
+            for t, iconIndex in self._iconIndexLookup:
+                if t is template:
+                    self._notebook.SetPageImage(index, iconIndex)
+                    found = True
+                    break
+        if not found:
+            self._notebook.SetPageImage(index, self._blankIconIndex)
+        self._notebook.Layout()
+
+
+    def RemoveNotebookPage(self, panel):
+        """
+        Removes a document page from the notebook.
+        """
+        index = self.GetNotebookPageIndex(panel)
+        if index > -1:
+            self._notebook.DeletePage(index)
+
+
+    def ActivateNotebookPage(self, panel):
+        """
+        Sets the notebook to the specified panel.
+        """
+        index = self.GetNotebookPageIndex(panel)
+        if index > -1:
+            self._notebook.SetFocus()
+            self._notebook.SetSelection(index)
+        
+
+    def GetNotebookPageTitle(self, panel):
+        self._notebook.GetPageText(self.GetNotebookPageIndex(panel))
+        
+
+    def SetNotebookPageTitle(self, panel, title):
+        self._notebook.SetPageText(self.GetNotebookPageIndex(panel), title)
+        
+
+    def GetNotebookPageIndex(self, panel):
+        """
+        Returns the index of particular notebook panel.
+        """
+        index = -1
+        for i in range(self._notebook.GetPageCount()):
+            if self._notebook.GetPage(i) == panel:
+                index = i
+                break
+        return index
+        
+
+    def ProcessEvent(self, event):
+        """
+        Processes an event, searching event tables and calling zero or more
+        suitable event handler function(s).  Note that the ProcessEvent
+        method is called from the wxPython docview framework directly since
+        wxPython does not have a virtual ProcessEvent function.
+        """
+        if wx.GetApp().ProcessEventBeforeWindows(event):
+            return True
+        if self._docManager and self._docManager.ProcessEvent(event):
+            return True
+        return DocMDIParentFrameMixIn.ProcessEvent(self, event)
+
+
+    def ProcessUpdateUIEvent(self, event):
+        """
+        Processes a UI event, searching event tables and calling zero or more
+        suitable event handler function(s).  Note that the ProcessEvent
+        method is called from the wxPython docview framework directly since
+        wxPython does not have a virtual ProcessEvent function.
+        """
+        if wx.GetApp().ProcessUpdateUIEventBeforeWindows(event):
+            return True
+        if self._docManager and self._docManager.ProcessUpdateUIEvent(event):
+            return True
+        return DocMDIParentFrameMixIn.ProcessUpdateUIEvent(self, event)
+
+
+    def OnExit(self, event):
+        """
+        Called when File/Exit is chosen and closes the window.
+        """
+        self.Close()
+
+
+    def OnMRUFile(self, event):
+        """
+        Opens the appropriate file when it is selected from the file history
+        menu.
+        """
+        n = event.GetId() - wx.ID_FILE1
+        filename = self._docManager.GetHistoryFile(n)
+        if filename:
+            self._docManager.CreateDocument(filename, wx.lib.docview.DOC_SILENT)
+        else:
+            self._docManager.RemoveFileFromHistory(n)
+            msgTitle = wx.GetApp().GetAppName()
+            if not msgTitle:
+                msgTitle = _("File Error")
+            wx.MessageBox("The file '%s' doesn't exist and couldn't be opened.\nIt has been removed from the most recently used files list" % FileNameFromPath(file),
+                          msgTitle,
+                          wx.OK | wx.ICON_EXCLAMATION,
+                          self)
+
+
+    def OnSize(self, event):
+        """
+        Called when the frame is resized and lays out the client window.
+        """
+        # Needed in case there are splitpanels around the mdi frame
+        self._LayoutFrame()
+
+
+    def OnCloseWindow(self, event):
+        """
+        Called when the frame is closed.  Remembers the frame size.
+        """
+        self.SaveEmbeddedWindowSizes()
+
+        # save and close services last
+        for service in wx.GetApp().GetServices():
+            if not service.OnCloseFrame(event):
+                return
+
+        # From docview.MDIParentFrame
+        if self._docManager.Clear(not event.CanVeto()):
+            self.Destroy()
+        else:
+            event.Veto()
+            
+
+class DocMDIChildFrame(wx.MDIChildFrame):
+    """
+    The wxDocMDIChildFrame class provides a default frame for displaying
+    documents on separate windows. This class can only be used for MDI child
+    frames.
+
+    The class is part of the document/view framework supported by wxWindows,
+    and cooperates with the wxView, wxDocument, wxDocManager and wxDocTemplate
+    classes.
+    """
+
+
+    def __init__(self, doc, view, frame, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE, name="frame"):
+        """
+        Constructor.  Note that the event table must be rebuilt for the
+        frame since the EvtHandler is not virtual.
+        """
+        wx.MDIChildFrame.__init__(self, frame, id, title, pos, size, style, name)
+        self._childDocument = doc
+        self._childView = view
+        if view:
+            view.SetFrame(self)
+        # self.Create(doc, view, frame, id, title, pos, size, style, name)
+        self._activeEvent = None
+        self._activated = 0
+        wx.EVT_ACTIVATE(self, self.OnActivate)
+        wx.EVT_CLOSE(self, self.OnCloseWindow)
+
+        if frame:  # wxBug: For some reason the EVT_ACTIVATE event is not getting triggered for the first mdi client window that is opened so we have to do it manually
+            mdiChildren = filter(lambda x: isinstance(x, wx.MDIChildFrame), frame.GetChildren())
+            if len(mdiChildren) == 1:
+                self.Activate()
+
+
+##    # Couldn't get this to work, but seems to work fine with single stage construction
+##    def Create(self, doc, view, frame, id, title, pos, size, style, name):
+##        self._childDocument = doc
+##        self._childView = view
+##        if wx.MDIChildFrame.Create(self, frame, id, title, pos, size, style, name):
+##            if view:
+##                view.SetFrame(self)
+##                return True
+##        return False
+
+
+
+    def Activate(self):  # Need this in case there are embedded sash windows and such, OnActivate is not getting called
+        """
+        Activates the current view.
+        """
+        if self._childView:
+            self._childView.Activate(True)
+
+
+    def ProcessEvent(event):
+        """
+        Processes an event, searching event tables and calling zero or more
+        suitable event handler function(s).  Note that the ProcessEvent
+        method is called from the wxPython docview framework directly since
+        wxPython does not have a virtual ProcessEvent function.
+        """
+        if self._activeEvent == event:
+            return False
+
+        self._activeEvent = event  # Break recursion loops
+
+        if self._childView:
+            self._childView.Activate(True)
+
+        if not self._childView or not self._childView.ProcessEvent(event):
+            if not isinstance(event, wx.CommandEvent) or not self.GetParent() or not self.GetParent().ProcessEvent(event):
+                ret = False
+            else:
+                ret = True
+        else:
+            ret = True
+
+        self._activeEvent = None
+        return ret
+
+
+    def OnActivate(self, event):
+        """
+        Sets the currently active view to be the frame's view. You may need to
+        override (but still call) this function in order to set the keyboard
+        focus for your subwindow.
+        """
+        if self._activated != 0:
+            return True
+        self._activated += 1
+        wx.MDIChildFrame.Activate(self)
+        if event.GetActive() and self._childView:
+            self._childView.Activate(event.GetActive())
+        self._activated = 0
+
+
+    def OnCloseWindow(self, event):
+        """
+        Closes and deletes the current view and document.
+        """
+        if self._childView:
+            ans = False
+            if not event.CanVeto():
+                ans = True
+            else:
+                ans = self._childView.Close(deleteWindow = False)
+
+            if ans:
+                self._childView.Activate(False)
+                self._childView.Destroy()
+                self._childView = None
+                if self._childDocument:
+                    self._childDocument.Destroy()  # This isn't in the wxWindows codebase but the document needs to be disposed of somehow
+                self._childDocument = None
+                self.Destroy()
+            else:
+                event.Veto()
+        else:
+            event.Veto()