]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/wx/lib/flatnotebook.py
compilation fix
[wxWidgets.git] / wxPython / wx / lib / flatnotebook.py
index fc3199867c22e5f65d938de0e989ed51d5dcf81f..7b259ad4f7265e2b4932c84f06e483be25e73a11 100644 (file)
@@ -11,7 +11,7 @@
 # Python Code By:
 #
 # Andrea Gavana, @ 02 Oct 2006
-# Latest Revision: 10 Oct 2006, 21.00 GMT
+# Latest Revision: 16 Apr 2007, 11.00 GMT
 #
 #
 # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
@@ -37,7 +37,7 @@ Some features:
   - The scrolling is done for bulks of tabs (so, the scrolling is faster and better)
   - The buttons area is never overdrawn by tabs (unlike many other implementations I saw)
   - It is a generic control
-  - Currently there are 4 differnt styles - VC8, VC 71, Standard and Fancy
+  - Currently there are 5 differnt styles - VC8, VC 71, Standard, Fancy and Firefox 2;
   - Mouse middle click can be used to close tabs
   - A function to add right click menu for tabs (simple as SetRightClickMenu)
   - All styles has bottom style as well (they can be drawn in the bottom of screen)
@@ -58,7 +58,7 @@ License And Version:
 
 FlatNotebook Is Freeware And Distributed Under The wxPython License. 
 
-Latest Revision: Andrea Gavana @ 10 Oct 2006, 21.00 GMT
+Latest Revision: Andrea Gavana @ 16 Apr 2007, 11.00 GMT
 
 Version 2.0.
 
@@ -79,7 +79,7 @@ import random
 import math
 import weakref
 import cPickle
-
+    
 # Check for the new method in 2.7 (not present in 2.6.3.3)
 if wx.VERSION_STRING < "2.7":
     wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point)
@@ -123,6 +123,10 @@ FNB_NODRAG = 128
 FNB_VC8 = 256
 """Use Visual Studio 2005 (VC8) style for tabs"""
 
+# Firefox 2 tabs style
+FNB_FF2 = 131072
+"""Use Firefox 2 style for tabs"""
+
 # Place 'X' on a tab
 FNB_X_ON_TAB = 512
 """Place 'X' close button on the active tab"""
@@ -146,6 +150,9 @@ FNB_DROPDOWN_TABS_LIST = 16384
 FNB_ALLOW_FOREIGN_DND = 32768
 """Allows drag 'n' drop operations between different L{FlatNotebook}s"""
 
+FNB_HIDE_ON_SINGLE_TAB = 65536
+"""Hides the Page Container when there is one or fewer tabs"""
+
 VERTICAL_BORDER_PADDING = 4
 
 # Button size is a 16x16 xpm bitmap
@@ -181,7 +188,7 @@ FNB_DROP_DOWN_ARROW = 6 # On the drop down arrow button
 FNB_NOWHERE = 0         # Anywhere else
 """Indicates mouse coordinates not on any tab of the notebook"""
 
-FNB_DEFAULT_STYLE = FNB_MOUSE_MIDDLE_CLOSES_TABS
+FNB_DEFAULT_STYLE = FNB_MOUSE_MIDDLE_CLOSES_TABS | FNB_HIDE_ON_SINGLE_TAB
 """L{FlatNotebook} default style"""
 
 # FlatNotebook Events:
@@ -195,8 +202,8 @@ FNB_DEFAULT_STYLE = FNB_MOUSE_MIDDLE_CLOSES_TABS
 # wxEVT_FLATNOTEBOOK_PAGE_CLOSED: Event Fired When A Page Is Closed.
 # wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU: Event Fired When A Menu Pops-up In A Tab.
 
-wxEVT_FLATNOTEBOOK_PAGE_CHANGED = wx.NewEventType()
-wxEVT_FLATNOTEBOOK_PAGE_CHANGING = wx.NewEventType()
+wxEVT_FLATNOTEBOOK_PAGE_CHANGED = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
+wxEVT_FLATNOTEBOOK_PAGE_CHANGING = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
 wxEVT_FLATNOTEBOOK_PAGE_CLOSING = wx.NewEventType()
 wxEVT_FLATNOTEBOOK_PAGE_CLOSED = wx.NewEventType()
 wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.NewEventType()
@@ -205,10 +212,10 @@ wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.NewEventType()
 #        FlatNotebookEvent
 #-----------------------------------#
 
-EVT_FLATNOTEBOOK_PAGE_CHANGED = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CHANGED, 1)
+EVT_FLATNOTEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED
 """Notify client objects when the active page in L{FlatNotebook} 
 has changed."""
-EVT_FLATNOTEBOOK_PAGE_CHANGING = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, 1)
+EVT_FLATNOTEBOOK_PAGE_CHANGING = wx.EVT_NOTEBOOK_PAGE_CHANGING
 """Notify client objects when the active page in L{FlatNotebook} 
 is about to change."""
 EVT_FLATNOTEBOOK_PAGE_CLOSING = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, 1)
@@ -714,6 +721,86 @@ def PaintStraightGradientBox(dc, rect, startColor, endColor, vertical=True):
 
 
 
+# -----------------------------------------------------------------------------
+# Util functions
+# -----------------------------------------------------------------------------
+
+def DrawButton(dc, rect, focus, upperTabs):
+
+    # Define the rounded rectangle base on the given rect
+    # we need an array of 9 points for it
+    regPts = [wx.Point() for indx in xrange(9)]
+
+    if focus:
+        if upperTabs:
+            leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*8)
+            rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*8)
+        else:
+            leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*5)
+            rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*5)
+    else:
+        leftPt = wx.Point(rect.x, rect.y + (rect.height / 2))
+        rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 2))
+
+    # Define the top region
+    top = wx.RectPP(rect.GetTopLeft(), rightPt)
+    bottom = wx.RectPP(leftPt, rect.GetBottomRight())
+
+    topStartColor = wx.WHITE
+
+    if not focus:
+        topStartColor = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 50)
+
+    topEndColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+    bottomStartColor = topEndColor
+    bottomEndColor = topEndColor
+
+    # Incase we use bottom tabs, switch the colors
+    if upperTabs:
+        if focus:
+            PaintStraightGradientBox(dc, top, topStartColor, topEndColor)
+            PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor)
+        else:
+            PaintStraightGradientBox(dc, top, topEndColor , topStartColor)
+            PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor)
+
+    else:
+        if focus:
+            PaintStraightGradientBox(dc, bottom, topEndColor, bottomEndColor)
+            PaintStraightGradientBox(dc, top,topStartColor,  topStartColor)
+        else:
+            PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor)
+            PaintStraightGradientBox(dc, top, topEndColor, topStartColor)
+    
+    dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
+
+# ---------------------------------------------------------------------------- #
+# Class FNBDropSource
+# Gives Some Custom UI Feedback during the DnD Operations
+# ---------------------------------------------------------------------------- #
+
+class FNBDropSource(wx.DropSource):
+    """
+    Give some custom UI feedback during the drag and drop operation in this
+    function. It is called on each mouse move, so your implementation must
+    not be too slow.
+    """
+    
+    def __init__(self, win):
+        """ Default class constructor. Used internally. """
+        
+        wx.DropSource.__init__(self, win)
+        self._win = win
+
+
+    def GiveFeedback(self, effect):
+        """ Provides user with a nice feedback when tab is being dragged. """
+
+        self._win.DrawDragHint()
+        return False
+
+
 # ---------------------------------------------------------------------------- #
 # Class FNBDragInfo
 # Stores All The Information To Allow Drag And Drop Between Different
@@ -1120,7 +1207,7 @@ class TabNavigatorWindow(wx.Dialog):
     def OnItemSelected(self, event):
         """Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """
 
-       self.CloseDialog()
+        self.CloseDialog()
 
 
     def CloseDialog(self):
@@ -1129,7 +1216,7 @@ class TabNavigatorWindow(wx.Dialog):
         bk = self.GetParent()
         self._selectedItem = self._listBox.GetSelection()
         iter = self._indexMap[self._selectedItem]
-        bk.SetSelection(iter)
+        bk._pages.FireEvent(iter)
         self.EndModal(wx.ID_OK)
         
 
@@ -1194,6 +1281,7 @@ class FNBRenderer:
         self._xBgBmp = wx.EmptyBitmap(16, 14)
         self._leftBgBmp = wx.EmptyBitmap(16, 14)
         self._rightBgBmp = wx.EmptyBitmap(16, 14)
+        self._tabHeight = None
 
 
     def GetLeftButtonPos(self, pageContainer):
@@ -1452,7 +1540,7 @@ class FNBRenderer:
         return bmp
 
 
-    def DrawTabsLine(self, pageContainer, dc):
+    def DrawTabsLine(self, pageContainer, dc, selTabX1=-1, selTabX2=-1):
         """ Draws a line over the tabs. """
 
         pc = pageContainer
@@ -1460,38 +1548,70 @@ class FNBRenderer:
         clntRect = pc.GetClientRect()
         clientRect3 = wx.Rect(0, 0, clntRect.width, clntRect.height)
 
-        if pc.HasFlag(FNB_BOTTOM):
-        
-            clientRect = wx.Rect(0, 2, clntRect.width, clntRect.height - 2)
-            clientRect2 = wx.Rect(0, 1, clntRect.width, clntRect.height - 1)
-        
-        else:
-        
-            clientRect = wx.Rect(0, 0, clntRect.width, clntRect.height - 2)
-            clientRect2 = wx.Rect(0, 0, clntRect.width, clntRect.height - 1)
-        
-        dc.SetBrush(wx.TRANSPARENT_BRUSH)
-        dc.SetPen(wx.Pen(pc.GetSingleLineBorderColour()))
-        dc.DrawRectangleRect(clientRect2)
-        dc.DrawRectangleRect(clientRect3)
+        if pc.HasFlag(FNB_FF2):
+            if not pc.HasFlag(FNB_BOTTOM):
+                fillColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
+            else:
+                fillColor = wx.WHITE
 
-        dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
-        dc.DrawRectangleRect(clientRect)
+            dc.SetPen(wx.Pen(fillColor))
 
-        if not pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
-        
-            dc.SetPen(wx.Pen((pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc._tabAreaColor])[0]))
-            dc.DrawLine(0, 0, 0, clientRect.height+1)
+            if pc.HasFlag(FNB_BOTTOM):
+
+                dc.DrawLine(1, 0, clntRect.width-1, 0)
+                dc.DrawLine(1, 1, clntRect.width-1, 1)
+
+                dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+                dc.DrawLine(1, 2, clntRect.width-1, 2)
+
+                dc.SetPen(wx.Pen(fillColor))
+                dc.DrawLine(selTabX1 + 2, 2, selTabX2 - 1, 2)
+                
+            else:
+                
+                dc.DrawLine(1, clntRect.height, clntRect.width-1, clntRect.height)
+                dc.DrawLine(1, clntRect.height-1, clntRect.width-1, clntRect.height-1)
+
+                dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+                dc.DrawLine(1, clntRect.height-2, clntRect.width-1, clntRect.height-2)
+
+                dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
+                dc.DrawLine(selTabX1 + 2, clntRect.height-2, selTabX2-1, clntRect.height-2)
+
+        else:
             
             if pc.HasFlag(FNB_BOTTOM):
             
-                dc.DrawLine(0, clientRect.height+1, clientRect.width, clientRect.height+1)
+                clientRect = wx.Rect(0, 2, clntRect.width, clntRect.height - 2)
+                clientRect2 = wx.Rect(0, 1, clntRect.width, clntRect.height - 1)
             
             else:
+            
+                clientRect = wx.Rect(0, 0, clntRect.width, clntRect.height - 2)
+                clientRect2 = wx.Rect(0, 0, clntRect.width, clntRect.height - 1)
+            
+            dc.SetBrush(wx.TRANSPARENT_BRUSH)
+            dc.SetPen(wx.Pen(pc.GetSingleLineBorderColour()))
+            dc.DrawRectangleRect(clientRect2)
+            dc.DrawRectangleRect(clientRect3)
+
+            dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
+            dc.DrawRectangleRect(clientRect)
+
+            if not pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
+            
+                dc.SetPen(wx.Pen((pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc._tabAreaColor])[0]))
+                dc.DrawLine(0, 0, 0, clientRect.height+1)
+                
+                if pc.HasFlag(FNB_BOTTOM):
                 
-                dc.DrawLine(0, 0, clientRect.width, 0)
+                    dc.DrawLine(0, clientRect.height+1, clientRect.width, clientRect.height+1)
                 
-            dc.DrawLine(clientRect.width - 1, 0, clientRect.width - 1, clientRect.height+1)
+                else:
+                    
+                    dc.DrawLine(0, 0, clientRect.width, 0)
+                    
+                dc.DrawLine(clientRect.width - 1, 0, clientRect.width - 1, clientRect.height+1)
 
 
     def CalcTabWidth(self, pageContainer, tabIdx, tabHeight):
@@ -1549,6 +1669,9 @@ class FNBRenderer:
     def CalcTabHeight(self, pageContainer):
         """ Calculates the height of the input tab. """
 
+        if self._tabHeight:
+            return self._tabHeight
+
         pc = pageContainer
         dc = wx.MemoryDC()
         dc.SelectObject(wx.EmptyBitmap(1,1))
@@ -1558,8 +1681,10 @@ class FNBRenderer:
         # on MSW, preforming these steps yields wierd results
         normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
         boldFont = normalFont
-        boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-        dc.SetFont(boldFont)
+
+        if "__WXGTK__" in wx.PlatformInfo:
+            boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+            dc.SetFont(boldFont)
 
         height = dc.GetCharHeight()
         
@@ -1568,11 +1693,8 @@ class FNBRenderer:
             # On GTK the tabs are should be larger
             tabHeight += 6
 
-        if pc.HasFlag(FNB_VC71):
-            tabHeight = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 4] or [tabHeight])[0]
-        elif pc.HasFlag(FNB_FANCY_TABS):
-            tabHeight = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 2] or [tabHeight])[0]
-
+        self._tabHeight = tabHeight
+        
         return tabHeight
 
 
@@ -1619,7 +1741,12 @@ class FNBRenderer:
         else:
             colr = (pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0]
             dc.SetPen(wx.Pen(colr))
-        
+
+        if pc.HasFlag(FNB_FF2):
+            lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
+            PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColor, LightColour(pc._tabAreaColor, lightFactor))
+            dc.SetBrush(wx.TRANSPARENT_BRUSH)
+
         dc.DrawRectangle(0, 0, size.x, size.y)
 
         # Take 3 bitmaps for the background for the buttons
@@ -1652,7 +1779,9 @@ class FNBRenderer:
         # We always draw the bottom/upper line of the tabs
         # regradless the style
         dc.SetPen(borderPen)
-        self.DrawTabsLine(pc, dc)
+
+        if not pc.HasFlag(FNB_FF2):
+            self.DrawTabsLine(pc, dc)
 
         # Restore the pen
         dc.SetPen(borderPen)
@@ -1679,13 +1808,13 @@ class FNBRenderer:
         
         # Draw labels
         normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        boldFont = normalFont
+        boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
         boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
         dc.SetFont(boldFont)
 
         posx = pc._pParent.GetPadding()
 
-        # Update all the tabs from 0 to 'pc.self._nFrom' to be non visible
+        # Update all the tabs from 0 to 'pc._nFrom' to be non visible
         for i in xrange(pc._nFrom):
         
             pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
@@ -1696,10 +1825,13 @@ class FNBRenderer:
         #----------------------------------------------------------
         # Go over and draw the visible tabs
         #----------------------------------------------------------
+        x1 = x2 = -1
         for i in xrange(pc._nFrom, len(pc._pagesInfoVec)):
         
             dc.SetPen(borderPen)
-            dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0])
+
+            if not pc.HasFlag(FNB_FF2):
+                dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0])
 
             # Now set the font to the correct font
             dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0])
@@ -1728,6 +1860,10 @@ class FNBRenderer:
             # Draw the tab (border, text, image & 'x' on tab)
             self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
 
+            if pc.GetSelection() == i:
+                x1 = posx
+                x2 = posx + tabWidth + 2
+
             # Restore the text forground
             dc.SetTextForeground(pc._activeTextColor)
 
@@ -1750,7 +1886,52 @@ class FNBRenderer:
         self.DrawX(pc, dc)
         self.DrawDropDownArrow(pc, dc)
 
+        if pc.HasFlag(FNB_FF2):
+            self.DrawTabsLine(pc, dc, x1, x2)
 
+
+    def DrawDragHint(self, pc, tabIdx):
+        """
+        Draws tab drag hint, the default implementation is to do nothing.
+        You can override this function to provide a nice feedback to user.
+        """
+        
+        pass
+
+
+    def NumberTabsCanFit(self, pageContainer, fr=-1):
+
+        pc = pageContainer
+        
+        rect = pc.GetClientRect()
+        clientWidth = rect.width
+
+        vTabInfo = []
+
+        tabHeight = self.CalcTabHeight(pageContainer)
+
+        # The drawing starts from posx 
+        posx = pc._pParent.GetPadding()
+
+        if fr < 0:
+            fr = pc._nFrom
+
+        for i in xrange(fr, len(pc._pagesInfoVec)):
+
+            tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight) 
+            if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
+                break; 
+
+            # Add a result to the returned vector 
+            tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth , tabHeight)
+            vTabInfo.append(tabRect)
+
+            # Advance posx 
+            posx += tabWidth + FNB_HEIGHT_SPACER
+
+        return vTabInfo
+
+    
 # ---------------------------------------------------------------------------- #
 # Class FNBRendererMgr
 # A manager that handles all the renderers defined below and calls the
@@ -1773,16 +1954,12 @@ class FNBRendererMgr:
         self._renderers.update({FNB_VC71: FNBRendererVC71()})
         self._renderers.update({FNB_FANCY_TABS: FNBRendererFancy()})
         self._renderers.update({FNB_VC8: FNBRendererVC8()})
+        self._renderers.update({FNB_FF2: FNBRendererFirefox2()})
 
 
     def GetRenderer(self, style):
         """ Returns the current renderer based on the style selected. """
 
-        # since we dont have a style for default tabs, we 
-        # test for all others - FIXME: add style for default tabs
-        if not style & FNB_VC71 and not style & FNB_VC8 and not style & FNB_FANCY_TABS:
-            return self._renderers[-1]
-
         if style & FNB_VC71:
             return self._renderers[FNB_VC71]
 
@@ -1792,6 +1969,9 @@ class FNBRendererMgr:
         if style & FNB_VC8:
             return self._renderers[FNB_VC8]
 
+        if style & FNB_FF2:
+            return self._renderers[FNB_FF2]
+
         # the default is to return the default renderer
         return self._renderers[-1]
 
@@ -1919,6 +2099,106 @@ class FNBRendererDefault(FNBRenderer):
             self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)            
         
 
+#------------------------------------------
+# Firefox2 renderer 
+#------------------------------------------
+class FNBRendererFirefox2(FNBRenderer):
+    """
+    This class handles the drawing of tabs using the I{Firefox 2} renderer.
+    """
+    
+    def __init__(self):
+        """ Default class constructor. """
+
+        FNBRenderer.__init__(self)
+
+        
+    def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
+        """ Draws a tab using the I{Firefox 2} style. """
+
+        borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
+        pc = pageContainer
+
+        tabPoints = [wx.Point() for indx in xrange(7)]
+        tabPoints[0].x = posx + 2
+        tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+        tabPoints[1].x = tabPoints[0].x
+        tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+        tabPoints[2].x = tabPoints[1].x+2
+        tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+        tabPoints[3].x = posx + tabWidth - 2
+        tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
+
+        tabPoints[4].x = tabPoints[3].x + 2
+        tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
+
+        tabPoints[5].x = tabPoints[4].x
+        tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
+
+        tabPoints[6].x = tabPoints[0].x
+        tabPoints[6].y = tabPoints[0].y
+
+        #------------------------------------
+        # Paint the tab with gradient
+        #------------------------------------
+        rr = wx.RectPP(tabPoints[2], tabPoints[5])
+        DrawButton(dc, rr, pc.GetSelection() == tabIdx , not pc.HasFlag(FNB_BOTTOM))
+
+        dc.SetBrush(wx.TRANSPARENT_BRUSH)
+        dc.SetPen(borderPen)
+
+        # Draw the tab as rounded rectangle
+        dc.DrawPolygon(tabPoints)
+
+        # -----------------------------------
+        # Text and image drawing
+        # -----------------------------------
+
+        # The width of the images are 16 pixels
+        padding = pc.GetParent().GetPadding()
+        shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
+        hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
+        imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
+
+        if hasImage:
+            textOffset = 2*padding + 16 + shapePoints/2 
+        else:
+            textOffset = padding + shapePoints/2
+            
+        textOffset += 2
+
+        if tabIdx != pc.GetSelection():
+        
+            # Set the text background to be like the vertical lines
+            dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
+
+        if hasImage:
+            imageXOffset = textOffset - 16 - padding
+            pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
+                               posx + imageXOffset, imageYCoord,
+                               wx.IMAGELIST_DRAW_TRANSPARENT, True)
+        
+        dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
+
+        # draw 'x' on tab (if enabled)
+        if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
+        
+            textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
+            tabCloseButtonXCoord = posx + textOffset + textWidth + 1
+
+            # take a bitmap from the position of the 'x' button (the x on tab button)
+            # this bitmap will be used later to delete old buttons
+            tabCloseButtonYCoord = imageYCoord
+            x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
+            self._tabXBgBmp = self._GetBitmap(dc, x_rect, self._tabXBgBmp)
+
+            # Draw the tab
+            self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
+        
+
 #------------------------------------------------------------------
 # Visual studio 7.1 
 #------------------------------------------------------------------
@@ -1947,14 +2227,15 @@ class FNBRendererVC71(FNBRenderer):
         if tabIdx == pc.GetSelection():
         
             posy = (pc.HasFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
-            dc.DrawRectangle(posx, posy, tabWidth, tabHeight - 1)
+            tabH = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 5] or [tabHeight - 3])[0]
+            dc.DrawRectangle(posx, posy, tabWidth, tabH) 
 
             # Draw a black line on the left side of the
             # rectangle
             dc.SetPen(wx.BLACK_PEN)
 
             blackLineY1 = VERTICAL_BORDER_PADDING
-            blackLineY2 = (pc.HasFlag(FNB_BOTTOM) and [pc.GetSize().y - 5] or [pc.GetSize().y - 3])[0]
+            blackLineY2 = tabH
             dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2)
 
             # To give the tab more 3D look we do the following
@@ -1993,7 +2274,7 @@ class FNBRendererVC71(FNBRenderer):
         # The width of the images are 16 pixels
         padding = pc.GetParent().GetPadding()
         hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
-        imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
+        imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [5] or [8])[0]
 
         if hasImage:
             textOffset = 2*pc._pParent._nPadding + 16
@@ -2058,7 +2339,7 @@ class FNBRendererFancy(FNBRenderer):
         if tabIdx == pc.GetSelection():
         
             posy = (pc.HasFlag(FNB_BOTTOM) and [2] or [VERTICAL_BORDER_PADDING])[0]
-            th = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 2] or [tabHeight - 5])[0]
+            th = tabHeight - 5
 
             rect = wx.Rect(posx, posy, tabWidth, th)
 
@@ -2166,7 +2447,7 @@ class FNBRendererVC8(FNBRenderer):
 
         # Set the font for measuring the tab height
         normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        boldFont = normalFont
+        boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
         boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
 
         # Calculate the number of rows required for drawing the tabs
@@ -2467,8 +2748,8 @@ class FNBRendererVC8(FNBRenderer):
             pc._colorTo   = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 0) 
             pc._colorFrom = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 60)
         
-        col2 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourTo()] or [pc._pParent.GetGradientColourFrom()])[0]
-        col1 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourFrom()] or [pc._pParent.GetGradientColourTo()])[0]
+        col2 = pc._pParent.GetGradientColourTo()
+        col1 = pc._pParent.GetGradientColourFrom()
 
         # If colorful tabs style is set, override the tab color
         if pc.HasFlag(FNB_COLORFUL_TABS):
@@ -2752,11 +3033,17 @@ class FlatNotebook(wx.Panel):
 
         # Set default page height
         dc = wx.ClientDC(self)
-        font = self.GetFont()
-        font.SetWeight(wx.FONTWEIGHT_BOLD)
-        dc.SetFont(font)
-        height = dc.GetCharHeight()
         
+        if "__WXGTK__" in wx.PlatformInfo:
+            # For GTK it seems that we must do this steps in order
+            # for the tabs will get the proper height on initialization
+            # on MSW, preforming these steps yields wierd results
+            boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+            boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
+            dc.SetFont(boldFont)
+        
+        height = dc.GetCharHeight()
+
         tabHeight = height + FNB_HEIGHT_SPACER         # We use 8 pixels as padding
         
         if "__WXGTK__" in wx.PlatformInfo:
@@ -2826,7 +3113,7 @@ class FlatNotebook(wx.Panel):
             event.SetOldSelection(oldSelection)
             event.SetEventObject(self)
             
-            if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed():
+            if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
                 bSelected = True            
         
         curSel = self._pages.GetSelection()
@@ -2866,21 +3153,24 @@ class FlatNotebook(wx.Panel):
 
             # Hide the page
             page.Hide()
-        
+
+        self.Thaw()        
         self._mainSizer.Layout()
-        self.Thaw()
         self.Refresh()
 
         return True        
 
 
-    def SetImageList(self, imglist):
-        """
-        Sets the image list for the page control. It does not take ownership
-        of the image list, you must delete it yourself.
-        """
+    def SetImageList(self, imageList):
+        """ Sets the image list for the page control. """
+
+        self._pages.SetImageList(imageList)
+
+
+    def AssignImageList(self, imageList):
+        """ Assigns the image list for the page control. """
 
-        self._pages.SetImageList(imglist)
+        self._pages.AssignImageList(imageList)
 
 
     def GetImageList(self):
@@ -2941,7 +3231,7 @@ class FlatNotebook(wx.Panel):
             event.SetOldSelection(oldSelection)
             event.SetEventObject(self)
             
-            if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed():
+            if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
                 bSelected = True            
         
         self._pages.InsertPage(indx, text, bSelected, imageId)
@@ -2971,9 +3261,9 @@ class FlatNotebook(wx.Panel):
         
             # Hide the page
             page.Hide()
-        
+
         self.Thaw()
-        self._mainSizer.Layout()
+        self._mainSizer.Layout()        
         self.Refresh()
 
         return True
@@ -3124,17 +3414,18 @@ class FlatNotebook(wx.Panel):
         return self._pages.GetSelection()
 
 
-    def AdvanceSelection(self, bForward=True):
+    def AdvanceSelection(self, forward=True):
         """
         Cycles through the tabs.
         The call to this function generates the page changing events.
         """
 
-        self._pages.AdvanceSelection(bForward)
+        self._pages.AdvanceSelection(forward)
 
 
     def GetPageCount(self):
         """ Returns the number of pages in the L{FlatNotebook} control. """
+
         return self._pages.GetPageCount()
 
 
@@ -3142,6 +3433,8 @@ class FlatNotebook(wx.Panel):
         """ Handles the wx.EVT_NAVIGATION_KEY event for L{FlatNotebook}. """
 
         if event.IsWindowChange():
+            if len(self._windows) == 0:
+                return
             # change pages
             if self.HasFlag(FNB_SMART_TABS):
                 if not self._popupWin:
@@ -3238,6 +3531,8 @@ class FlatNotebook(wx.Panel):
         """ Sets the L{FlatNotebook} window style flags. """
             
         wx.Panel.SetWindowStyleFlag(self, style)
+        renderer = self._pages._mgr.GetRenderer(self.GetWindowStyleFlag())
+        renderer._tabHeight = None
 
         if self._pages:
         
@@ -3245,6 +3540,10 @@ class FlatNotebook(wx.Panel):
             # refreshing the tab container is not enough
             self.SetSelection(self._pages._iActivePage)
 
+        if not self._pages.HasFlag(FNB_HIDE_ON_SINGLE_TAB):
+            #For Redrawing the Tabs once you remove the Hide tyle
+            self._pages._ReShow()
+
 
     def RemovePage(self, page):
         """ Deletes the specified page, without deleting the associated window. """
@@ -3287,10 +3586,10 @@ class FlatNotebook(wx.Panel):
         self._pages._pRightClickMenu = menu
 
 
-    def GetPageText(self, page):
+    def GetPageText(self, nPage):
         """ Returns the tab caption. """
 
-        return self._pages.GetPageText(page)
+        return self._pages.GetPageText(nPage)
 
 
     def SetGradientColours(self, fr, to, border):
@@ -3349,22 +3648,22 @@ class FlatNotebook(wx.Panel):
         return self._pages._activeTextColor
 
 
-    def SetPageImage(self, page, imgindex):
+    def SetPageImage(self, page, image):
         """
         Sets the image index for the given page. Image is an index into the
         image list which was set with SetImageList.
         """
 
-        self._pages.SetPageImage(page, imgindex)
+        self._pages.SetPageImage(page, image)
 
 
-    def GetPageImage(self, page):
+    def GetPageImage(self, nPage):
         """
         Returns the image index for the given page. Image is an index into the
         image list which was set with SetImageList.
         """
 
-        return self._pages.GetPageImage(page)
+        return self._pages.GetPageImage(nPage)
 
 
     def GetEnabled(self, page):
@@ -3453,7 +3752,7 @@ class PageContainer(wx.Panel):
         self._colorFrom = wx.WHITE
         self._activeTabColor = wx.WHITE
         self._activeTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT)
-        self._nonActiveTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
+        self._nonActiveTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT)
         self._tabAreaColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
 
         self._nFrom = 0
@@ -3462,10 +3761,11 @@ class PageContainer(wx.Panel):
         # Set default page height, this is done according to the system font
         memDc = wx.MemoryDC()
         memDc.SelectObject(wx.EmptyBitmap(1,1))
-        normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        boldFont = normalFont
-        boldFont.SetWeight(wx.BOLD)
-        memDc.SetFont(boldFont)
+    
+        if "__WXGTK__" in wx.PlatformInfo:
+            boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+            boldFont.SetWeight(wx.BOLD)
+            memDc.SetFont(boldFont)
 
         height = memDc.GetCharHeight()
         tabHeight = height + FNB_HEIGHT_SPACER # We use 10 pixels as padding
@@ -3496,23 +3796,25 @@ class PageContainer(wx.Panel):
         pass
 
     
+    def _ReShow(self):
+        """ Handles the Redraw of the tabs when the FNB_HIDE_ON_SINGLE_TAB has been removed """
+        self.Show()
+        self.GetParent()._mainSizer.Layout()
+        self.Refresh()
+
+
     def OnPaint(self, event):
         """ Handles the wx.EVT_PAINT event for L{PageContainer}."""
 
-        # Currently having problems with buffered DCs because of
-        # recent changes.  Just do the buffering ourselves instead.
-        #dc = wx.BufferedPaintDC(self)
-        size = self.GetSize()
-        bmp = wx.EmptyBitmap(*size)
-        dc = wx.MemoryDC()
-        dc.SelectObject(bmp)
-        
+        dc = wx.BufferedPaintDC(self)
         renderer = self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag())
         renderer.DrawTabs(self, dc)
 
-        pdc = wx.PaintDC(self)
-        pdc.Blit(0,0, size.width, size.height, dc, 0,0)
-        
+        if self.HasFlag(FNB_HIDE_ON_SINGLE_TAB) and len(self._pagesInfoVec) <= 1:
+            self.Hide()
+            self.GetParent()._mainSizer.Layout()
+            self.Refresh()
+
 
     def AddPage(self, caption, selected=True, imgindex=-1):
         """
@@ -3566,6 +3868,21 @@ class PageContainer(wx.Panel):
     def OnSize(self, event):
         """ Handles the wx.EVT_SIZE events for L{PageContainer}. """
 
+        # When resizing the control, try to fit to screen as many tabs as we can 
+        style = self.GetParent().GetWindowStyleFlag() 
+        renderer = self._mgr.GetRenderer(style)
+        
+        fr = 0
+        page = self.GetSelection()
+        
+        for fr in xrange(self._nFrom):
+            vTabInfo = renderer.NumberTabsCanFit(self, fr)
+            if page - fr >= len(vTabInfo):
+                continue
+            break
+
+        self._nFrom = fr
+
         self.Refresh() # Call on paint
         event.Skip()
 
@@ -3589,30 +3906,26 @@ class PageContainer(wx.Panel):
 
     def OnRightDown(self, event):
         """ Handles the wx.EVT_RIGHT_DOWN events for L{PageContainer}. """
-
-        if self._pRightClickMenu:
         
-            where, tabIdx = self.HitTest(event.GetPosition())
+        where, tabIdx = self.HitTest(event.GetPosition())
 
-            if where in [FNB_TAB, FNB_TAB_X]:
+        if where in [FNB_TAB, FNB_TAB_X]:
 
-                if self._pagesInfoVec[tabIdx].GetEnabled():
-                    # Set the current tab to be active
-                    self.SetSelection(tabIdx)
-
-                    # If the owner has defined a context menu for the tabs,
-                    # popup the right click menu
-                    if self._pRightClickMenu:
-                        self.PopupMenu(self._pRightClickMenu)
-                    else:
-                        # send a message to popup a custom menu
-                        event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, self.GetParent().GetId())
-                        event.SetSelection(tabIdx)
-                        event.SetOldSelection(self._iActivePage)
-                        event.SetEventObject(self.GetParent())
-                        self.GetParent().GetEventHandler().ProcessEvent(event)
-                
-            event.Skip()
+            if self._pagesInfoVec[tabIdx].GetEnabled():
+                # Fire events and eventually (if allowed) change selection
+                self.FireEvent(tabIdx)
+
+                # send a message to popup a custom menu
+                event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, self.GetParent().GetId())
+                event.SetSelection(tabIdx)
+                event.SetOldSelection(self._iActivePage)
+                event.SetEventObject(self.GetParent())
+                self.GetParent().GetEventHandler().ProcessEvent(event)
+
+                if self._pRightClickMenu:
+                    self.PopupMenu(self._pRightClickMenu)
+            
+        event.Skip()
 
 
     def OnLeftDown(self, event):
@@ -3646,79 +3959,66 @@ class PageContainer(wx.Panel):
         elif self._nLeftClickZone == FNB_TAB:
             
             if self._iActivePage != tabIdx:
-            
+                
                 # In case the tab is disabled, we dont allow to choose it
                 if self._pagesInfoVec[tabIdx].GetEnabled():
+                    self.FireEvent(tabIdx)
 
-                    oldSelection = self._iActivePage
 
-                    event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
-                    event.SetSelection(tabIdx)
-                    event.SetOldSelection(oldSelection)
-                    event.SetEventObject(self.GetParent())
-                    
-                    if not self.GetParent().GetEventHandler().ProcessEvent(event) or event.IsAllowed():
-                    
-                        self.SetSelection(tabIdx)
+    def RotateLeft(self):
 
-                        # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
-                        event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
-                        event.SetOldSelection(oldSelection)
-                        self.GetParent().GetEventHandler().ProcessEvent(event)        
+        if self._nFrom == 0:
+            return
 
+        # Make sure that the button was pressed before
+        if self._nLeftButtonStatus != FNB_BTN_PRESSED:
+            return
 
-    def OnLeftUp(self, event):
-        """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """
+        self._nLeftButtonStatus = FNB_BTN_HOVER
 
-        # forget the zone that was initially clicked
-        self._nLeftClickZone = FNB_NOWHERE
+        # We scroll left with bulks of 5
+        scrollLeft = self.GetNumTabsCanScrollLeft()
 
-        where, tabIdx = self.HitTest(event.GetPosition())
-        
-        if where == FNB_LEFT_ARROW:
-            
-            if self._nFrom == 0:
-                return
+        self._nFrom -= scrollLeft
+        if self._nFrom < 0:
+            self._nFrom = 0
 
-            # Make sure that the button was pressed before
-            if self._nLeftButtonStatus != FNB_BTN_PRESSED:
-                return
+        self.Refresh()
 
-            self._nLeftButtonStatus = FNB_BTN_HOVER
 
-            # We scroll left with bulks of 5
-            scrollLeft = self.GetNumTabsCanScrollLeft()
+    def RotateRight(self):
 
-            self._nFrom -= scrollLeft
-            if self._nFrom < 0:
-                self._nFrom = 0
+        if self._nFrom >= len(self._pagesInfoVec) - 1:
+            return
 
-            self.Refresh()
-            
-        elif where == FNB_RIGHT_ARROW:
-            
-            if self._nFrom >= len(self._pagesInfoVec) - 1:
-                return
+        # Make sure that the button was pressed before
+        if self._nRightButtonStatus != FNB_BTN_PRESSED:
+            return
 
-            # Make sure that the button was pressed before
-            if self._nRightButtonStatus != FNB_BTN_PRESSED:
-                return
+        self._nRightButtonStatus = FNB_BTN_HOVER
 
-            self._nRightButtonStatus = FNB_BTN_HOVER
+        # Check if the right most tab is visible, if it is
+        # don't rotate right anymore
+        if self._pagesInfoVec[len(self._pagesInfoVec)-1].GetPosition() != wx.Point(-1, -1):
+            return
 
-            # Check if the right most tab is visible, if it is
-            # don't rotate right anymore
-            if self._pagesInfoVec[-1].GetPosition() != wx.Point(-1, -1):
-                return
+        self._nFrom += 1
+        self.Refresh()
 
-            lastVisibleTab = self.GetLastVisibleTab()
-            if lastVisibleTab < 0:
-                # Probably the screen is too small for displaying even a single
-                # tab, in this case we do nothing
-                return
 
-            self._nFrom += self.GetNumOfVisibleTabs()
-            self.Refresh()
+    def OnLeftUp(self, event):
+        """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """
+
+        # forget the zone that was initially clicked
+        self._nLeftClickZone = FNB_NOWHERE
+
+        where, tabIdx = self.HitTest(event.GetPosition())
+        
+        if where == FNB_LEFT_ARROW:
+            self.RotateLeft()
+            
+        elif where == FNB_RIGHT_ARROW:
+            self.RotateRight()
             
         elif where == FNB_X:
             
@@ -3755,6 +4055,8 @@ class PageContainer(wx.Panel):
 
             self.PopupTabsMenu()
 
+        event.Skip()
+        
 
     def HitTest(self, pt):
         """
@@ -3867,22 +4169,18 @@ class PageContainer(wx.Panel):
                 da_page.SetFocus()
         
         if not self.IsTabVisible(page):
-        
-            if page == len(self._pagesInfoVec) - 1:
-                # Incase the added tab is last,
-                # the function IsTabVisible() will always return False
-                # and thus will cause an evil behaviour that the new
-                # tab will hide all other tabs, we need to check if the
-                # new selected tab can fit to the current screen
-                if not self.CanFitToScreen(page):
-                    self._nFrom = page
-                            
-            else:
+            # Try to remove one tab from start and try again
+            
+            if not self.CanFitToScreen(page):
 
-                if not self.CanFitToScreen(page):
-                    # Redraw the tabs starting from page
+                if self._nFrom > page:
                     self._nFrom = page
-                    
+                else:
+                    while self._nFrom < page:
+                        self._nFrom += 1
+                        if self.CanFitToScreen(page):
+                            break
         self.Refresh()
 
 
@@ -4033,14 +4331,14 @@ class PageContainer(wx.Panel):
                     wx.SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY))
                 
                 # Support for drag and drop
-                if event.LeftIsDown() and not (style & FNB_NODRAG):
+                if event.Dragging() and not (style & FNB_NODRAG):
 
                     self._isdragging = True                
                     draginfo = FNBDragInfo(self, tabIdx)
                     drginfo = cPickle.dumps(draginfo)
                     dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook"))
                     dataobject.SetData(drginfo)
-                    dragSource = wx.DropSource(self)
+                    dragSource = FNBDropSource(self)
                     dragSource.SetData(dataobject)
                     dragSource.DoDragDrop(wx.Drag_DefaultMove)
                     
@@ -4082,6 +4380,9 @@ class PageContainer(wx.Panel):
     def GetLastVisibleTab(self):
         """ Returns the last visible tab. """
 
+        if self._nFrom < 0:
+            return -1
+
         ii = 0
         
         for ii in xrange(self._nFrom, len(self._pagesInfoVec)):
@@ -4095,66 +4396,10 @@ class PageContainer(wx.Panel):
     def GetNumTabsCanScrollLeft(self):
         """ Returns the number of tabs than can be scrolled left. """
 
-        # Reserved area for the buttons (<>x)
-        rect = self.GetClientRect()
-        clientWidth = rect.width
-        posx = self._pParent._nPadding
-        numTabs = 0
-        pom = 0
-        
-        # In case we have error prevent crash
-        if self._nFrom < 0:
-            return 0
-
-        dc = wx.ClientDC(self)
-
-        style = self.GetParent().GetWindowStyleFlag()
-        render = self._mgr.GetRenderer(style)
-        
-        for ii in xrange(self._nFrom, -1, -1):
-
-            boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)        
-            boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-            dc.SetFont(boldFont)
+        if self._nFrom - 1 >= 0:
+            return 1
 
-            height = dc.GetCharHeight()
-
-            tabHeight = height + FNB_HEIGHT_SPACER # We use 6 pixels as padding
-            if style & FNB_VC71:
-                tabHeight = (style & FNB_BOTTOM and [tabHeight - 4] or [tabHeight])[0]
-            elif style & FNB_FANCY_TABS:
-                tabHeight = (style & FNB_BOTTOM and [tabHeight - 3] or [tabHeight])[0]
-
-            width, pom = dc.GetTextExtent(self.GetPageText(ii))
-            if style != FNB_VC71:
-                shapePoints = int(tabHeight*math.tan(float(self._pagesInfoVec[ii].GetTabAngle())/180.0*math.pi))
-            else:
-                shapePoints = 0
-
-            tabWidth = 2*self._pParent._nPadding + width
-            
-            if not (style & FNB_VC71):
-                # Default style
-                tabWidth += 2*shapePoints
-
-            hasImage = self._ImageList != None and self._pagesInfoVec[ii].GetImageIndex() != -1
-
-            # For VC71 style, we only add the icon size (16 pixels)
-            if hasImage:
-            
-                if not self.IsDefaultTabs():
-                    tabWidth += 16 + self._pParent._nPadding
-                else:
-                    # Default style
-                    tabWidth += 16 + self._pParent._nPadding + shapePoints/2
-            
-            if posx + tabWidth + render.GetButtonsAreaLength(self) >= clientWidth:
-                break
-
-            numTabs = numTabs + 1
-            posx += tabWidth
-        
-        return numTabs
+        return 0
 
 
     def IsDefaultTabs(self):
@@ -4178,7 +4423,6 @@ class PageContainer(wx.Panel):
 
         nMax = self.GetPageCount() - 1
         
-        oldSelection = self._iActivePage
         if bForward:
             newSelection = (nSel == nMax and [0] or [nSel + 1])[0]
         else:
@@ -4186,20 +4430,8 @@ class PageContainer(wx.Panel):
 
         if not self._pagesInfoVec[newSelection].GetEnabled():
             return
-        
-        event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
-        event.SetSelection(newSelection)
-        event.SetOldSelection(oldSelection)
-        event.SetEventObject(self.GetParent())
-        
-        if not self.GetParent().GetEventHandler().ProcessEvent(event) or event.IsAllowed():
-        
-            self.SetSelection(newSelection)
 
-            # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
-            event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
-            event.SetOldSelection(oldSelection)
-            self.GetParent().GetEventHandler().ProcessEvent(event)       
+        self.FireEvent(newSelection)
 
 
     def OnMouseLeave(self, event):
@@ -4304,10 +4536,10 @@ class PageContainer(wx.Panel):
             
                 if where == FNB_TAB:
                     self.MoveTabPage(nTabPage, nIndex)
-        
+                           
         elif self.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND:
         
-            if wx.Platform in ["__WXMSW__", "__WXGTK__"]:
+            if wx.Platform in ["__WXMSW__", "__WXGTK__", "__WXMAC__"]:
                 if nTabPage >= 0:
                 
                     window = oldNotebook.GetPage(nTabPage)
@@ -4321,7 +4553,7 @@ class PageContainer(wx.Panel):
 
                         if imageindex >= 0:
 
-                            bmp = oldNotebook.GetImageList().GetBitmap(imageindex)
+                            bmp = oldNotebook.GetImageList().GetIcon(imageindex)
                             newImageList = newNotebook.GetImageList()
     
                             if not newImageList:
@@ -4331,7 +4563,7 @@ class PageContainer(wx.Panel):
                             else:
                                 imageindex = newImageList.GetImageCount()
 
-                            newImageList.Add(bmp)
+                            newImageList.AddIcon(bmp)
                             newNotebook.SetImageList(newImageList)
                                 
                         newNotebook.InsertPage(nIndex, window, caption, True, imageindex)
@@ -4401,39 +4633,12 @@ class PageContainer(wx.Panel):
         style = self.GetParent().GetWindowStyleFlag()
         render = self._mgr.GetRenderer(style)
 
-        if not self.HasFlag(FNB_VC8):
-            rect = self.GetClientRect();
-            clientWidth = rect.width;
-            tabHeight = render.CalcTabHeight(self)
-            tabWidth = render.CalcTabWidth(self, page, tabHeight)
-
-            posx = self._pParent._nPadding
-
-            if self._nFrom >= 0:
-
-                for i in xrange(self._nFrom, len(self._pagesInfoVec)):
-
-                    if self._pagesInfoVec[i].GetPosition() == wx.Point(-1, -1):
-                        break
-                    
-                    posx += self._pagesInfoVec[i].GetSize().x
-
-            if posx + tabWidth + render.GetButtonsAreaLength(self) >= clientWidth:
-                return False
-
-            return True
-
-        else:
-
-            # TODO:: this is ugly and should be improved, we should *never* access the
-            # raw pointer directly like we do here (render.Get())
-            vc8_render = render
-            vTabInfo = vc8_render.NumberTabsCanFit(self)
+        vTabInfo = render.NumberTabsCanFit(self)
 
-            if page - self._nFrom >= len(vTabInfo):
-                return False
-            
-            return True
+        if page - self._nFrom >= len(vTabInfo):
+            return False
+        
+        return True
 
 
     def GetNumOfVisibleTabs(self):
@@ -4503,10 +4708,16 @@ class PageContainer(wx.Panel):
     def OnLeftDClick(self, event):
         """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """
 
-        if self.HasFlag(FNB_DCLICK_CLOSES_TABS):
+        where, tabIdx = self.HitTest(event.GetPosition())
+        
+        if where == FNB_RIGHT_ARROW:
+            self.RotateRight()
+
+        elif where == FNB_LEFT_ARROW:
+            self.RotateLeft()
+
+        elif self.HasFlag(FNB_DCLICK_CLOSES_TABS):
         
-            where, tabIdx = self.HitTest(event.GetPosition())
-            
             if where == FNB_TAB:
                 self.DeletePage(tabIdx)
         
@@ -4530,6 +4741,7 @@ class PageContainer(wx.Panel):
             #   item.SetBitmaps( (*m_ImageList)[pi.GetImageIndex()] );
 
             popupMenu.AppendItem(item)
+            item.Enable(pi.GetEnabled())
             
         self.PopupMenu(popupMenu)
 
@@ -4538,8 +4750,36 @@ class PageContainer(wx.Panel):
         """ Handles the wx.EVT_MENU event for L{PageContainer}. """
 
         selection = event.GetId()
-        self._pParent.SetSelection(selection)
+        self.FireEvent(selection)
+
 
+    def FireEvent(self, selection):
+        """
+        Fires the wxEVT_FLATNOTEBOOK_PAGE_CHANGING and wxEVT_FLATNOTEBOOK_PAGE_CHANGED events
+        called from other methods (from menu selection or Smart Tabbing).
+        Utility function.
+        """
+
+        if selection == self._iActivePage:
+            # No events for the same selection
+            return
+        
+        oldSelection = self._iActivePage
+
+        event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
+        event.SetSelection(selection)
+        event.SetOldSelection(oldSelection)
+        event.SetEventObject(self.GetParent())
+        
+        if not self.GetParent().GetEventHandler().ProcessEvent(event) or event.IsAllowed():
+        
+            self.SetSelection(selection)
+
+            # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
+            event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
+            event.SetOldSelection(oldSelection)
+            self.GetParent().GetEventHandler().ProcessEvent(event)
+            
 
     def SetImageList(self, imglist):
         """ Sets the image list for the page control. """
@@ -4547,6 +4787,12 @@ class PageContainer(wx.Panel):
         self._ImageList = imglist
 
 
+    def AssignImageList(self, imglist):
+        """ Assigns the image list for the page control. """
+
+        self._ImageList = imglist
+
+
     def GetImageList(self):
         """ Returns the image list for the page control. """
 
@@ -4578,3 +4824,13 @@ class PageContainer(wx.Panel):
         return True 
 
 
+    def DrawDragHint(self):
+        """ Draws small arrow at the place that the tab will be placed. """
+
+        # get the index of tab that will be replaced with the dragged tab
+        pt = wx.GetMousePosition()
+        client_pt = self.ScreenToClient(pt)
+        where, tabIdx = self.HitTest(client_pt)
+        self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()).DrawDragHint(self, tabIdx)
+
+