]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wx/lib/flatnotebook.py
Prevent seg fault for older GTK+
[wxWidgets.git] / wxPython / wx / lib / flatnotebook.py
index 7b259ad4f7265e2b4932c84f06e483be25e73a11..214f6821c387a58af0f49dd9297917b1c7dc096b 100644 (file)
@@ -11,7 +11,7 @@
 # Python Code By:
 #
 # Andrea Gavana, @ 02 Oct 2006
 # Python Code By:
 #
 # Andrea Gavana, @ 02 Oct 2006
-# Latest Revision: 16 Apr 2007, 11.00 GMT
+# Latest Revision: 28 Jun 2007, 21.00 GMT
 #
 #
 # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
 #
 #
 # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
@@ -58,9 +58,9 @@ License And Version:
 
 FlatNotebook Is Freeware And Distributed Under The wxPython License. 
 
 
 FlatNotebook Is Freeware And Distributed Under The wxPython License. 
 
-Latest Revision: Andrea Gavana @ 16 Apr 2007, 11.00 GMT
+Latest Revision: Andrea Gavana @ 28 Jun 2007, 21.00 GMT
 
 
-Version 2.0.
+Version 2.2.
 
 @undocumented: FNB_HEIGHT_SPACER, VERTICAL_BORDER_PADDING, VC8_SHAPE_LEN,
     wxEVT*, left_arrow_*, right_arrow*, x_button*, down_arrow*,
 
 @undocumented: FNB_HEIGHT_SPACER, VERTICAL_BORDER_PADDING, VC8_SHAPE_LEN,
     wxEVT*, left_arrow_*, right_arrow*, x_button*, down_arrow*,
@@ -892,6 +892,7 @@ class PageInfo:
         self._region = wx.Region()
         self._xRect = wx.Rect()
         self._color = None
         self._region = wx.Region()
         self._xRect = wx.Rect()
         self._color = None
+        self._hasFocus = False
 
 
     def SetCaption(self, value):
 
 
     def SetCaption(self, value):
@@ -960,7 +961,7 @@ class PageInfo:
         return self._bEnabled 
 
 
         return self._bEnabled 
 
 
-    def Enable(self, enabled):
+    def EnableTab(self, enabled):
         """ Sets the tab enabled or disabled. """
 
         self._bEnabled = enabled 
         """ Sets the tab enabled or disabled. """
 
         self._bEnabled = enabled 
@@ -1283,6 +1284,13 @@ class FNBRenderer:
         self._rightBgBmp = wx.EmptyBitmap(16, 14)
         self._tabHeight = None
 
         self._rightBgBmp = wx.EmptyBitmap(16, 14)
         self._tabHeight = None
 
+        if wx.Platform == "__WXMAC__":
+            self._focusPen = wx.Pen(wx.BLACK, 1, wx.SOLID)
+        else:
+            self._focusPen = wx.Pen(wx.BLACK, 1, wx.USER_DASH)
+            self._focusPen.SetDashes([1, 1])
+            self._focusPen.SetCap(wx.CAP_BUTT)
+
 
     def GetLeftButtonPos(self, pageContainer):
         """ Returns the left button position in the navigation area. """
 
     def GetLeftButtonPos(self, pageContainer):
         """ Returns the left button position in the navigation area. """
@@ -1459,7 +1467,7 @@ class FNBRenderer:
 
         # erase old bitmap
         posx = self.GetDropArrowButtonPos(pc)
 
         # erase old bitmap
         posx = self.GetDropArrowButtonPos(pc)
-        dc.DrawBitmap(self._xBgBmp, posx, 6)
+        dc.DrawBitmap(self._rightBgBmp, posx, 6)
 
         # Draw the new bitmap
         dc.DrawBitmap(downBmp, posx, 6, True)
 
         # Draw the new bitmap
         dc.DrawBitmap(downBmp, posx, 6, True)
@@ -1872,6 +1880,8 @@ class FNBRenderer:
 
             pc._pagesInfoVec[i].SetPosition(wx.Point(posx, posy))
             pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
 
             pc._pagesInfoVec[i].SetPosition(wx.Point(posx, posy))
             pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
+            self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[i])
+
             posx += tabWidth
         
         # Update all tabs that can not fit into the screen as non-visible
             posx += tabWidth
         
         # Update all tabs that can not fit into the screen as non-visible
@@ -1890,6 +1900,25 @@ class FNBRenderer:
             self.DrawTabsLine(pc, dc, x1, x2)
 
 
             self.DrawTabsLine(pc, dc, x1, x2)
 
 
+    def DrawFocusRectangle(self, dc, pageContainer, page):
+        """ Draws a focus rectangle like the native Notebooks. """
+        
+        if not page._hasFocus:
+            return
+
+        tabPos = page.GetPosition()
+        if pageContainer.GetParent().GetWindowStyleFlag() & FNB_VC8:
+            vc8ShapeLen = self.CalcTabHeight(pageContainer) - VERTICAL_BORDER_PADDING - 2
+            tabPos.x += vc8ShapeLen
+            
+        rect = wx.RectPS(tabPos, page.GetSize())
+        rect = wx.Rect(rect.x+2, rect.y+2, rect.width-4, rect.height-8)
+        
+        dc.SetBrush(wx.TRANSPARENT_BRUSH)
+        dc.SetPen(self._focusPen)
+        dc.DrawRoundedRectangleRect(rect, 2)
+        
+
     def DrawDragHint(self, pc, tabIdx):
         """
         Draws tab drag hint, the default implementation is to do nothing.
     def DrawDragHint(self, pc, tabIdx):
         """
         Draws tab drag hint, the default implementation is to do nothing.
@@ -2736,6 +2765,8 @@ class FNBRendererVC8(FNBRenderer):
             # Draw the tab
             self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
 
             # Draw the tab
             self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
 
+        self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[tabIdx])
+
 
     def FillVC8GradientColour(self, pageContainer, dc, tabPoints, bSelectedTab, tabIdx):
         """ Fills a tab with a gradient shading. """
 
     def FillVC8GradientColour(self, pageContainer, dc, tabPoints, bSelectedTab, tabIdx):
         """ Fills a tab with a gradient shading. """
@@ -2975,7 +3006,7 @@ class FNBRendererVC8(FNBRenderer):
 # Class FlatNotebook
 # ---------------------------------------------------------------------------- #
 
 # Class FlatNotebook
 # ---------------------------------------------------------------------------- #
 
-class FlatNotebook(wx.Panel):
+class FlatNotebook(wx.PyPanel):
     """
     Display one or more windows in a notebook.
     
     """
     Display one or more windows in a notebook.
     
@@ -3011,7 +3042,7 @@ class FlatNotebook(wx.Panel):
         self._windows = []
         self._popupWin = None
 
         self._windows = []
         self._popupWin = None
 
-        wx.Panel.__init__(self, parent, id, pos, size, style)
+        wx.PyPanel.__init__(self, parent, id, pos, size, style)
         
         self._pages = PageContainer(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style)
 
         
         self._pages = PageContainer(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style)
 
@@ -3059,6 +3090,24 @@ class FlatNotebook(wx.Panel):
         self.SetDropTarget(self._pDropTarget)
 
 
         self.SetDropTarget(self._pDropTarget)
 
 
+    def DoGetBestSize(self):
+        """ Overrides DoGetBestSize to handle sizers nicely. """
+
+        if not self._windows:
+            # Something is better than nothing... no pages!
+            return wx.Size(20, 20)
+
+        maxWidth = maxHeight = 0
+        tabHeight = self.GetPageBestSize().height
+
+        for win in self._windows:
+            # Loop over all the windows to get their best size
+            width, height = win.GetBestSize()
+            maxWidth, maxHeight = max(maxWidth, width), max(maxHeight, height)
+
+        return wx.Size(maxWidth, maxHeight+tabHeight)
+    
+
     def SetActiveTabTextColour(self, textColour):
         """ Sets the text colour for the active tab. """
 
     def SetActiveTabTextColour(self, textColour):
         """ Sets the text colour for the active tab. """
 
@@ -3353,6 +3402,7 @@ class FlatNotebook(wx.Panel):
 
         self._pages.DoDeletePage(page)
         self.Refresh()
 
         self._pages.DoDeletePage(page)
         self.Refresh()
+        self.Update()  
 
         # Fire a closed event
         closedEvent = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, self.GetId())
 
         # Fire a closed event
         closedEvent = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, self.GetId())
@@ -3450,11 +3500,9 @@ class FlatNotebook(wx.Panel):
             else:
                 # change pages
                 self.AdvanceSelection(event.GetDirection())
             else:
                 # change pages
                 self.AdvanceSelection(event.GetDirection())
+
         else:
         else:
-            # pass to the parent
-            if self.GetParent():
-                event.SetCurrentFocus(self)
-                self.GetParent().ProcessEvent(event)
+            event.Skip()
             
 
     def GetPageShapeAngle(self, page_index):
             
 
     def GetPageShapeAngle(self, page_index):
@@ -3530,7 +3578,7 @@ class FlatNotebook(wx.Panel):
     def SetWindowStyleFlag(self, style):
         """ Sets the L{FlatNotebook} window style flags. """
             
     def SetWindowStyleFlag(self, style):
         """ Sets the L{FlatNotebook} window style flags. """
             
-        wx.Panel.SetWindowStyleFlag(self, style)
+        wx.PyPanel.SetWindowStyleFlag(self, style)
         renderer = self._pages._mgr.GetRenderer(self.GetWindowStyleFlag())
         renderer._tabHeight = None
 
         renderer = self._pages._mgr.GetRenderer(self.GetWindowStyleFlag())
         renderer._tabHeight = None
 
@@ -3672,14 +3720,14 @@ class FlatNotebook(wx.Panel):
         return self._pages.GetEnabled(page)
 
 
         return self._pages.GetEnabled(page)
 
 
-    def Enable(self, page, enabled=True):
+    def EnableTab(self, page, enabled=True):
         """ Enables or disables a tab. """
 
         if page >= len(self._windows):
             return
 
         self._windows[page].Enable(enabled)
         """ Enables or disables a tab. """
 
         if page >= len(self._windows):
             return
 
         self._windows[page].Enable(enabled)
-        self._pages.Enable(page, enabled)
+        self._pages.EnableTab(page, enabled)
 
 
     def GetNonActiveTabTextColour(self):
 
 
     def GetNonActiveTabTextColour(self):
@@ -3771,7 +3819,7 @@ class PageContainer(wx.Panel):
         tabHeight = height + FNB_HEIGHT_SPACER # We use 10 pixels as padding
 
         wx.Panel.__init__(self, parent, id, pos, wx.Size(size.x, tabHeight),
         tabHeight = height + FNB_HEIGHT_SPACER # We use 10 pixels as padding
 
         wx.Panel.__init__(self, parent, id, pos, wx.Size(size.x, tabHeight),
-                          style|wx.NO_BORDER|wx.NO_FULL_REPAINT_ON_RESIZE)
+                          style|wx.NO_BORDER|wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS)
 
         self._pDropTarget = FNBDropTarget(self)
         self.SetDropTarget(self._pDropTarget)
 
         self._pDropTarget = FNBDropTarget(self)
         self.SetDropTarget(self._pDropTarget)
@@ -3788,7 +3836,10 @@ class PageContainer(wx.Panel):
         self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
         self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow)
         self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
         self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
         self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow)
         self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
-
+        self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
+        self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+        
 
     def OnEraseBackground(self, event):
         """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing)."""
 
     def OnEraseBackground(self, event):
         """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing)."""
@@ -4355,7 +4406,7 @@ class PageContainer(wx.Panel):
                 dc = wx.ClientDC(self)
                 
                 if bRedrawX:
                 dc = wx.ClientDC(self)
                 
                 if bRedrawX:
-                
+                                
                     render.DrawX(self, dc)
                 
                 if bRedrawLeft:
                     render.DrawX(self, dc)
                 
                 if bRedrawLeft:
@@ -4368,7 +4419,7 @@ class PageContainer(wx.Panel):
                 
                 if bRedrawTabX:
                 
                 
                 if bRedrawTabX:
                 
-                    render.DrawTabX(self, dc, self._pagesInfoVec[tabIdx].GetXRect(), tabIdx, self._nTabXButtonStatus)
+                    self.Refresh()
 
                 if bRedrawDropArrow:
 
 
                 if bRedrawDropArrow:
 
@@ -4662,13 +4713,13 @@ class PageContainer(wx.Panel):
         return self._pagesInfoVec[page].GetEnabled()
 
 
         return self._pagesInfoVec[page].GetEnabled()
 
 
-    def Enable(self, page, enabled=True):
+    def EnableTab(self, page, enabled=True):
         """ Enables or disables a tab. """
 
         if page >= len(self._pagesInfoVec):
             return
         
         """ Enables or disables a tab. """
 
         if page >= len(self._pagesInfoVec):
             return
         
-        self._pagesInfoVec[page].Enable(enabled)
+        self._pagesInfoVec[page].EnableTab(enabled)
         
 
     def GetSingleLineBorderColour(self):
         
 
     def GetSingleLineBorderColour(self):
@@ -4726,6 +4777,57 @@ class PageContainer(wx.Panel):
             event.Skip()
         
 
             event.Skip()
         
 
+    def OnSetFocus(self, event):
+        """ Handles the wx.EVT_SET_FOCUS event for L{PageContainer}. """
+
+        if self._iActivePage < 0:
+            event.Skip()
+            return
+
+        self.SetFocusedPage(self._iActivePage)
+
+
+    def OnKillFocus(self, event):
+        """ Handles the wx.EVT_KILL_FOCUS event for L{PageContainer}. """
+
+        self.SetFocusedPage()
+
+
+    def OnKeyDown(self, event):
+        """
+        When the PageContainer has the focus tabs can be changed with
+        the left/right arrow keys.
+        """
+        key = event.GetKeyCode()
+        print key
+        if key == wx.WXK_LEFT:
+            self.GetParent().AdvanceSelection(False)
+        elif key == wx.WXK_RIGHT:
+            self.GetParent().AdvanceSelection(True)
+        elif key == wx.WXK_TAB:
+            flags = 0
+            if not event.ShiftDown(): flags |= wx.NavigationKeyEvent.IsForward
+            if event.CmdDown():       flags |= wx.NavigationKeyEvent.WinChange
+            self.Navigate(flags)
+        else:
+            event.Skip()
+
+            
+    def SetFocusedPage(self, pageIndex=-1):
+        """
+        Sets/Unsets the focus on the appropriate page.
+        If pageIndex is defaulted, we have lost focus and no focus indicator is drawn.
+        """
+
+        for indx, page in enumerate(self._pagesInfoVec):
+            if indx == pageIndex:
+                page._hasFocus = True
+            else:
+                page._hasFocus = False
+            
+        self.Refresh()
+                
+
     def PopupTabsMenu(self):
         """ Pops up the menu activated with the drop down arrow in the navigation area. """
 
     def PopupTabsMenu(self):
         """ Pops up the menu activated with the drop down arrow in the navigation area. """
 
@@ -4733,15 +4835,16 @@ class PageContainer(wx.Panel):
 
         for i in xrange(len(self._pagesInfoVec)):
             pi = self._pagesInfoVec[i]
 
         for i in xrange(len(self._pagesInfoVec)):
             pi = self._pagesInfoVec[i]
-            item = wx.MenuItem(popupMenu, i, pi.GetCaption(), pi.GetCaption(), wx.ITEM_NORMAL)
+            item = wx.MenuItem(popupMenu, i+1, pi.GetCaption(), pi.GetCaption(), wx.ITEM_NORMAL)
             self.Bind(wx.EVT_MENU, self.OnTabMenuSelection, item)
 
             self.Bind(wx.EVT_MENU, self.OnTabMenuSelection, item)
 
-            # This code is commented, since there is an alignment problem with wx2.6.3 & Menus
-            # if self.TabHasImage(ii):
-            #   item.SetBitmaps( (*m_ImageList)[pi.GetImageIndex()] );
+            # There is an alignment problem with wx2.6.3 & Menus so only use
+            # images for versions above 2.6.3
+            if wx.VERSION > (2, 6, 3, 0) and self.TabHasImage(i):
+                item.SetBitmap(self.GetImageList().GetBitmap(pi.GetImageIndex()))
 
             popupMenu.AppendItem(item)
 
             popupMenu.AppendItem(item)
-            item.Enable(pi.GetEnabled())
+            item.EnableTab(pi.GetEnabled())
             
         self.PopupMenu(popupMenu)
 
             
         self.PopupMenu(popupMenu)
 
@@ -4749,7 +4852,7 @@ class PageContainer(wx.Panel):
     def OnTabMenuSelection(self, event):
         """ Handles the wx.EVT_MENU event for L{PageContainer}. """
 
     def OnTabMenuSelection(self, event):
         """ Handles the wx.EVT_MENU event for L{PageContainer}. """
 
-        selection = event.GetId()
+        selection = event.GetId() - 1
         self.FireEvent(selection)
 
 
         self.FireEvent(selection)
 
 
@@ -4779,6 +4882,7 @@ class PageContainer(wx.Panel):
             event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
             event.SetOldSelection(oldSelection)
             self.GetParent().GetEventHandler().ProcessEvent(event)
             event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
             event.SetOldSelection(oldSelection)
             self.GetParent().GetEventHandler().ProcessEvent(event)
+            self.SetFocus()
             
 
     def SetImageList(self, imglist):
             
 
     def SetImageList(self, imglist):