Logo Search packages:      
Sourcecode: codeblocks version File versions  Download package

renderer.cpp

///////////////////////////////////////////////////////////////////////////////
// Name:          renderer.cpp 
// Purpose:     implementation of the different renderers used by wxFlatNotebook
// Author:      Eran Ifrah <eranif@bezeqint.net>
// Created:     30/12/2005
// Modified:    01/01/2006
// Copyright:   Eran Ifrah (c)
// Licence:     wxWindows license <http://www.wxwidgets.org/licence3.txt>
///////////////////////////////////////////////////////////////////////////////
#include <wx/wxFlatNotebook/renderer.h>
#include <wx/wxFlatNotebook/wxFlatNotebook.h> // for the styles
#include <wx/wxFlatNotebook/fnb_resources.h>
#include <wx/image.h>

#ifdef DEVELOPMENT
# define FNB_LOG_MSG( msg ) { wxString logmsg; logmsg << msg; wxLogMessage( logmsg ); }
#else
# define FNB_LOG_MSG( msg ) { wxString logmsg; logmsg << msg; }
#endif

//-----------------------------------------------------------------------------
// Util functions
//-----------------------------------------------------------------------------

static void DrawButton(wxDC& dc, 
                  const wxRect& rect, 
                  const bool &focus, 
                  const bool &upperTabs)
{
      // Define the middle points
      wxPoint leftPt, rightPt;
      if( focus ){
            if( upperTabs ){
                  leftPt = wxPoint(rect.x, rect.y + (rect.height / 10)*8 );
                  rightPt = wxPoint(rect.x + rect.width - 2, rect.y + (rect.height / 10)*8);
            } else {
                  leftPt = wxPoint(rect.x, rect.y + (rect.height / 10)*5 );
                  rightPt = wxPoint(rect.x + rect.width - 2, rect.y + (rect.height / 10)*5);
            }
      } else {
            leftPt = wxPoint(rect.x, rect.y + (rect.height / 2) );
            rightPt = wxPoint(rect.x + rect.width - 2, rect.y + (rect.height / 2));
      }

      // Define the top region
      wxRect top(rect.GetLeftTop(), rightPt);
      wxRect bottom(leftPt, rect.GetBottomRight());

      wxColour topStartColor(wxT("WHITE"));

      if( !focus ){
            topStartColor = wxFNBRenderer::LightColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE), 50);
      }

      wxColour topEndColor( wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
      wxColour bottomStartColor(topEndColor);
      wxColour bottomEndColor(topEndColor);

      // Incase we use bottom tabs, switch the colors
      if( upperTabs ){
            if( focus ){
                  wxFNBRenderer::PaintStraightGradientBox(dc, top, topStartColor, topEndColor);
                  wxFNBRenderer::PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor);
            } else {
                  wxFNBRenderer::PaintStraightGradientBox(dc, top, topEndColor , topStartColor);
                  wxFNBRenderer::PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor);
            }
      } else {
            if( focus ){
                  wxFNBRenderer::PaintStraightGradientBox(dc, bottom, topEndColor, bottomEndColor);
                  wxFNBRenderer::PaintStraightGradientBox(dc, top,topStartColor,  topStartColor);
            } else {
                  wxFNBRenderer::PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor);
                  wxFNBRenderer::PaintStraightGradientBox(dc, top, topEndColor, topStartColor);
            }
      }
      
      dc.SetBrush( *wxTRANSPARENT_BRUSH );
}

wxFNBRenderer::wxFNBRenderer()
: m_tabXBgBmp(16, 16)
, m_xBgBmp(16, 14)
, m_leftBgBmp(16, 14)
, m_rightBgBmp(16, 14)
{
}

wxFNBRenderer::~wxFNBRenderer()
{
}

int wxFNBRenderer::GetLeftButtonPos(wxWindow* pageContainer)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      long style = pc->GetParent()->GetWindowStyleFlag();
      wxRect rect = pc->GetClientRect();
      int clientWidth = rect.width;
      if(style & wxFNB_NO_X_BUTTON)
            return clientWidth - 38;
      else
            return clientWidth - 54;
}

int wxFNBRenderer::GetRightButtonPos(wxWindow* pageContainer)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      long style = pc->GetParent()->GetWindowStyleFlag();
      wxRect rect = pc->GetClientRect();
      int clientWidth = rect.width;
      if(style & wxFNB_NO_X_BUTTON)
            return clientWidth - 22;
      else
            return clientWidth - 38;
}

int wxFNBRenderer::GetDropArrowButtonPos(wxWindow *pageContainer)
{
      return GetRightButtonPos(pageContainer);
}

int wxFNBRenderer::GetXPos(wxWindow* pageContainer)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      long style = pc->GetParent()->GetWindowStyleFlag();
      wxRect rect = pc->GetClientRect();
      int clientWidth = rect.width;
      if(style & wxFNB_NO_X_BUTTON)
            return clientWidth;
      else
            return clientWidth - 22;
}

int wxFNBRenderer::GetButtonsAreaLength(wxWindow* pageContainer)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      long style = pc->GetParent()->GetWindowStyleFlag();

      // ''
      if(style & wxFNB_NO_NAV_BUTTONS && style & wxFNB_NO_X_BUTTON && !(style & wxFNB_DROPDOWN_TABS_LIST))
            return 0;
      
      // 'x'
      if((style & wxFNB_NO_NAV_BUTTONS) && !(style & wxFNB_NO_X_BUTTON) && !(style & wxFNB_DROPDOWN_TABS_LIST))
            return 22;
      
      // '<>'
      if(!(style & wxFNB_NO_NAV_BUTTONS) && (style & wxFNB_NO_X_BUTTON) && !(style & wxFNB_DROPDOWN_TABS_LIST))
            return 53 - 16;
      
      // 'vx'
      if((style & wxFNB_DROPDOWN_TABS_LIST) && !(style & wxFNB_NO_X_BUTTON))
            return 22 + 16;

      // 'v'
      if((style & wxFNB_DROPDOWN_TABS_LIST) && (style & wxFNB_NO_X_BUTTON))
            return 22;

      // '<>x'
      return 53;
}

00163 void wxFNBRenderer::DrawLeftArrow(wxWindow* pageContainer, wxDC& dc)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      long style = pc->GetParent()->GetWindowStyleFlag();
      if(style & wxFNB_NO_NAV_BUTTONS)
            return;

      // Make sure that there are pages in the container
      if(pc->GetPageInfoVector().empty())
            return;

      // Set the bitmap according to the button status
      wxBitmap arrowBmp;
      switch(pc->m_nLeftButtonStatus)
      {
      case wxFNB_BTN_HOVER:
            arrowBmp = wxBitmap(left_arrow_hilite_xpm);
            break;
      case wxFNB_BTN_PRESSED:
            arrowBmp = wxBitmap(left_arrow_pressed_xpm);
            break;
      case wxFNB_BTN_NONE:
      default:
            arrowBmp = wxBitmap(left_arrow_xpm);
            break;
      }

      if(pc->m_nFrom == 0)
      {
            // Handle disabled arrow
            arrowBmp = wxBitmap(left_arrow_disabled_xpm);
      }

      arrowBmp.SetMask(new wxMask(arrowBmp, MASK_COLOR));

      // Erase old bitmap
      int posx = GetLeftButtonPos( pc );
      dc.DrawBitmap(m_leftBgBmp, posx, 6);

      // Draw the new bitmap
      dc.DrawBitmap(arrowBmp, posx, 6, true);
}

00206 void wxFNBRenderer::DrawRightArrow(wxWindow* pageContainer, wxDC& dc)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      long style = pc->GetParent()->GetWindowStyleFlag();
      if(style & wxFNB_NO_NAV_BUTTONS)
            return;

      // Make sure that there are pages in the container
      if(pc->GetPageInfoVector().empty())
            return;

      // Set the bitmap according to the button status
      wxBitmap arrowBmp;
      switch(pc->m_nRightButtonStatus)
      {
      case wxFNB_BTN_HOVER:
            arrowBmp = wxBitmap(right_arrow_hilite_xpm);
            break;
      case wxFNB_BTN_PRESSED:
            arrowBmp = wxBitmap(right_arrow_pressed_xpm);
            break;
      case wxFNB_BTN_NONE:
      default:
            arrowBmp = wxBitmap(right_arrow_xpm);
            break;
      }


      // Check if the right most tab is visible, if it is
      // don't rotate right anymore
      if(pc->GetPageInfoVector()[pc->GetPageInfoVector().GetCount()-1].GetPosition() != wxPoint(-1, -1))
      {
            arrowBmp = wxBitmap(right_arrow_disabled_xpm);
      }

      arrowBmp.SetMask(new wxMask(arrowBmp, MASK_COLOR));

      // erase old bitmap
      int posx = GetRightButtonPos( pc ) ;
      dc.DrawBitmap(m_rightBgBmp, posx, 6);

      // Draw the new bitmap
      dc.DrawBitmap(arrowBmp, posx, 6, true);
}

00251 void wxFNBRenderer::DrawDropDownArrow(wxWindow* pageContainer, wxDC& dc)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      // Check if this style is enabled
      long style = pc->GetParent()->GetWindowStyleFlag();
      if(! (style & wxFNB_DROPDOWN_TABS_LIST) )
            return;

      // Make sure that there are pages in the container
      if(pc->GetPageInfoVector().empty())
            return;

      // Set the bitmap according to the button status
      wxBitmap xbmp;
      
      switch(pc->m_nArrowDownButtonStatus)
      {
      case wxFNB_BTN_HOVER:
            xbmp = wxBitmap(down_arrow_hilite_xpm);
            break;
      case wxFNB_BTN_PRESSED:
            xbmp = wxBitmap(down_arrow_pressed_xpm);
            break;
      case wxFNB_BTN_NONE:
      default:
            xbmp = wxBitmap(down_arrow_xpm);
            break;
      }

      xbmp.SetMask(new wxMask(xbmp, MASK_COLOR));
      // erase old bitmap
      int posx = GetDropArrowButtonPos( pc );
      dc.DrawBitmap(m_rightBgBmp, posx, 6);

      // Draw the new bitmap
      dc.DrawBitmap(xbmp, posx, 6, true);
}

00289 void wxFNBRenderer::DrawX(wxWindow* pageContainer, wxDC& dc)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      // Check if this style is enabled
      long style = pc->GetParent()->GetWindowStyleFlag();
      if(style & wxFNB_NO_X_BUTTON)
            return;

      // Make sure that there are pages in the container
      if(pc->GetPageInfoVector().empty())
            return;

      // Set the bitmap according to the button status
      wxBitmap xbmp;
      switch(pc->m_nXButtonStatus)
      {
      case wxFNB_BTN_HOVER:
            xbmp = wxBitmap(x_button_hilite_xpm);
            break;
      case wxFNB_BTN_PRESSED:
            xbmp = wxBitmap(x_button_pressed_xpm);
            break;
      case wxFNB_BTN_NONE:
      default:
            xbmp = wxBitmap(x_button_xpm);
            break;
      }

      xbmp.SetMask(new wxMask(xbmp, MASK_COLOR));
      // erase old bitmap
      int posx = GetXPos( pc );
      dc.DrawBitmap(m_xBgBmp, posx, 6);

      // Draw the new bitmap
      dc.DrawBitmap(xbmp, posx, 6, true);
}

00326 void wxFNBRenderer::PaintStraightGradientBox(wxDC& dc, const wxRect& rect, const wxColour& startColor, const wxColour& endColor, bool  vertical)
{
      int rd, gd, bd, high = 0;
      rd = endColor.Red() - startColor.Red();
      gd = endColor.Green() - startColor.Green();
      bd = endColor.Blue() - startColor.Blue();

      /// Save the current pen and brush
      wxPen savedPen = dc.GetPen();
      wxBrush savedBrush = dc.GetBrush();

      if ( vertical )
            high = rect.GetHeight()-1;
      else
            high = rect.GetWidth()-1;

      if( high < 1 )
            return;

      for (int i = 0; i <= high; ++i)
      {
            int r = startColor.Red() +  ((i*rd*100)/high)/100;
            int g = startColor.Green() + ((i*gd*100)/high)/100;
            int b = startColor.Blue() + ((i*bd*100)/high)/100;

            wxPen p(wxColor(r, g, b));
            dc.SetPen(p);

            if ( vertical )
                  dc.DrawLine(rect.x, rect.y+i, rect.x+rect.width, rect.y+i);
            else
                  dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height);
      }

      /// Restore the pen and brush
      dc.SetPen( savedPen );
      dc.SetBrush( savedBrush );
}

00365 void wxFNBRenderer::DrawTabX(wxWindow* pageContainer, wxDC& dc, const wxRect& rect, const int& tabIdx, const int btnStatus)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      if(!pc->HasFlag(wxFNB_X_ON_TAB))
            return;

      /// We draw the 'x' on the active tab only
      if(tabIdx != pc->GetSelection() || tabIdx < 0)
            return;

      // Set the bitmap according to the button status
      wxBitmap xBmp;
      switch(btnStatus)
      {
      case wxFNB_BTN_HOVER:
            xBmp = wxBitmap(x_button_xpm);
            break;
      case wxFNB_BTN_PRESSED:
            xBmp = wxBitmap(tab_x_button_pressed_xpm);
            break;
      case wxFNB_BTN_NONE:
      default:
            xBmp = wxBitmap(x_button_xpm);
            break;
      }

      /// Set the masking
      xBmp.SetMask(new wxMask(xBmp, MASK_COLOR));

      // erase old button
      dc.DrawBitmap(m_tabXBgBmp, rect.x, rect.y);

      // Draw the new bitmap
      dc.DrawBitmap(xBmp, rect.x, rect.y, true);

      // Update the vectpr
      wxRect rr(rect.x, rect.y, 14, 13);
      pc->GetPageInfoVector()[tabIdx].SetXRect( rr );
}

00405 void wxFNBRenderer::GetBitmap(wxDC &dc, const wxRect &rect, wxBitmap &bmp)
{
      wxMemoryDC mem_dc;
      mem_dc.SelectObject(bmp);
      mem_dc.Blit(0, 0, rect.width, rect.height, &dc, rect.x, rect.y);
      mem_dc.SelectObject(wxNullBitmap);
}

00413 wxColor wxFNBRenderer::RandomColor()
{
      int r, g, b;
      r = rand() % 256; // Random value betweem 0-255
      g = rand() % 256; // Random value betweem 0-255
      b = rand() % 256; // Random value betweem 0-255
      return wxColor(r, g, b);
}

00422 wxColor wxFNBRenderer::LightColour(const wxColour& color, int percent)
{
      int rd, gd, bd, high = 0;
      wxColor end_color = wxT("WHITE");
      rd = end_color.Red() - color.Red();
      gd = end_color.Green() - color.Green();
      bd = end_color.Blue() - color.Blue();
      high = 100;

      // We take the percent way of the color from color --> white
      int i = percent;
      int r = color.Red() +  ((i*rd*100)/high)/100;
      int g = color.Green() + ((i*gd*100)/high)/100;
      int b = color.Blue() + ((i*bd*100)/high)/100;
      return wxColor(r, g, b);
}

00439 void wxFNBRenderer::DrawTabsLine(wxWindow* pageContainer, wxDC& dc, wxCoord selTabX1, wxCoord selTabX2)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      wxRect clntRect = pc->GetClientRect();
      wxRect clientRect, clientRect2, clientRect3;
      clientRect3 = wxRect(0, 0, clntRect.width, clntRect.height);

      if( pc->HasFlag(wxFNB_FF2) ){
            wxColour fillColor;
            if( !pc->HasFlag(wxFNB_BOTTOM) ){
                  fillColor = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
            } else {
                  fillColor = wxColor(wxT("WHITE"));
            }

            dc.SetPen( wxPen(fillColor) );
            if(pc->HasFlag(wxFNB_BOTTOM)){

                  dc.DrawLine(1, 0, clntRect.width-1, 0);
                  dc.DrawLine(1, 1, clntRect.width-1, 1);

                  dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)));
                  dc.DrawLine(1, 2, clntRect.width-1, 2);

                  dc.SetPen(wxPen(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(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)));
                  dc.DrawLine(1, clntRect.height-2, clntRect.width-1, clntRect.height-2);

                  dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)));
                  dc.DrawLine(selTabX1 + 2, clntRect.height-2, selTabX2-1, clntRect.height-2);
            }
      } else {


            if(pc->HasFlag(wxFNB_BOTTOM))
            {
                  clientRect = wxRect(0, 2, clntRect.width, clntRect.height - 2);
                  clientRect2 = wxRect(0, 1, clntRect.width, clntRect.height - 1);
            }
            else
            {
                  clientRect = wxRect(0, 0, clntRect.width, clntRect.height - 2);
                  clientRect2 = wxRect(0, 0, clntRect.width, clntRect.height - 1);
            }

            dc.SetBrush(*wxTRANSPARENT_BRUSH);
            dc.SetPen( wxPen(pc->GetSingleLineBorderColor()) );
            dc.DrawRectangle(clientRect2);
            dc.DrawRectangle(clientRect3);

      /// Patch ---- Ti-R ---- Enable to have the same color border has the selected tab
            if(pc->HasFlag(wxFNB_INVERSE_COLOR_LINE_VC8))
                  dc.SetPen(wxPen(pc->m_colorBorder));
            else
                  dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)));

            dc.DrawRectangle(clientRect);

            if( !pc->HasFlag(wxFNB_TABS_BORDER_SIMPLE) )
            {
                  dc.SetPen(wxPen( pc->HasFlag( wxFNB_VC71) ? wxColour(247, 243, 233) : pc->m_tabAreaColor));
                  dc.DrawLine(0, 0, 0, clientRect.height+1);
                  if(pc->HasFlag(wxFNB_BOTTOM))
                  {
                        dc.DrawLine(0, clientRect.height+1, clientRect.width, clientRect.height+1);
                  }
                  else
                        dc.DrawLine(0, 0, clientRect.width, 0);
                  dc.DrawLine(clientRect.width - 1, 0, clientRect.width - 1, clientRect.height+1);
            }

      /// Patch ---- Ti-R ---- Enable to have the same color border has the selected tab
            if(pc->HasFlag(wxFNB_BOTTOM_LINE_COLOR_CHANGE))
            {
                  dc.SetPen(wxPen(pc->m_colorBorder));

                  clientRect3 = wxRect(0, clntRect.height-2, 1, 2);
                  dc.DrawRectangle(clientRect3);

                  clientRect3 = wxRect(clntRect.width-1, clntRect.height-2, 1, 2);
                  dc.DrawRectangle(clientRect3);
            }
      }
}

00531 int wxFNBRenderer::CalcTabWidth(wxWindow *pageContainer, int tabIdx, int tabHeight)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      int tabWidth, shapePoints(0), width, pom;
      wxMemoryDC dc;

      // bitmap must be set before it can be used for anything
      wxBitmap bmp(10, 10);
      dc.SelectObject(bmp);
      
      /// Patch (SetTextForeground) ---- Ti-R ---- Good Text Colour
            /// -- old code ---
//    wxFont normalFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
      wxFont normalFont = pc->m_font;
      wxFont boldFont(normalFont);
      boldFont.SetWeight(wxFONTWEIGHT_BOLD);

      if( pc->IsDefaultTabs() )
            shapePoints = (int)(tabHeight*tan((double)pc->GetPageInfoVector()[tabIdx].GetTabAngle()/180.0*M_PI));

      if(pc->GetSelection() == tabIdx)
            dc.SetFont(boldFont);
      else
            dc.SetFont(normalFont);
      dc.GetTextExtent(pc->GetPageText(tabIdx), &width, &pom);

      // Set a minimum size to a tab
      if(width < 20)
            width = 20;

      tabWidth = ((wxFlatNotebook *)pc->m_pParent)->GetPadding() * 2 + width;
      
      /// Style to add a small 'x' button on the top right
      /// of the tab
      if(pc->HasFlag(wxFNB_X_ON_TAB) && tabIdx == pc->GetSelection())
      {
            int spacer = 9;
            if( pc->HasFlag(wxFNB_VC8) )
                  spacer = 4;

            tabWidth += ((wxFlatNotebook *)pc->m_pParent)->GetPadding() + spacer;
      }

      if( pc->IsDefaultTabs() )
            // Default style
            tabWidth += 2 * shapePoints;

      bool hasImage = (pc->m_ImageList != NULL && pc->GetPageInfoVector()[tabIdx].GetImageIndex() != -1);

      // For VC71 style, we only add the icon size (16 pixels)
      if(hasImage)
      {
            if( ! pc->IsDefaultTabs() )
                  tabWidth += (16 + ((wxFlatNotebook*)pc->m_pParent)->GetPadding());
            else
                  // Default style
                  tabWidth += (16 + ((wxFlatNotebook*)pc->m_pParent)->GetPadding()) + shapePoints / 2;
      }
      return tabWidth;
}

00592 void wxFNBRenderer::NumberTabsCanFit(wxWindow *pageContainer, std::vector<wxRect> &vTabInfo, int from)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      int tabHeight, clientWidth;
      
      wxRect rect = pc->GetClientRect();
      clientWidth = rect.width;

      /// Empty results
      vTabInfo.clear();

      tabHeight = CalcTabHeight( pageContainer );

      // The drawing starts from posx
      int posx = ((wxFlatNotebook *)pc->m_pParent)->GetPadding();
      
      if( from < 0 )
            from = pc->m_nFrom;

      for(int i = from; i<(int)pc->GetPageInfoVector().GetCount(); i++)
      {
            int tabWidth = CalcTabWidth( pageContainer, i, tabHeight );
            if(posx + tabWidth + GetButtonsAreaLength( pc ) >= clientWidth)
                  break;

            /// Add a result to the returned vector
            wxRect tabRect(posx, VERTICAL_BORDER_PADDING, tabWidth , tabHeight);
            vTabInfo.push_back(tabRect);

            /// Advance posx
            posx += tabWidth;
      }
}

00626 void wxFNBRenderer::DrawDragHint(wxWindow *pageContainer, int tabIdx)
{
      wxUnusedVar( pageContainer );
      wxUnusedVar( tabIdx );
}

00632 int wxFNBRenderer::CalcTabHeight(wxWindow *pageContainer)
{
      int tabHeight;
      wxMemoryDC dc;
      wxUnusedVar( pageContainer );

      wxBitmap bmp(10, 10);
      dc.SelectObject(bmp);

      // 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
      wxFont normalFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
      wxFont boldFont = normalFont;
      boldFont.SetWeight(wxFONTWEIGHT_BOLD);
#ifdef __WXGTK__
      dc.SetFont( boldFont );
#endif

      static int height(-1);
      static int width(-1);

      if( height == -1 && width == -1 )
      {
            wxString stam = wxT("Tp");    // Temp data to get the text height;
            dc.GetTextExtent(stam, &width, &height);
      }

      tabHeight = height + wxFNB_HEIGHT_SPACER; // We use 8 pixels as padding
#ifdef __WXGTK__
      // On GTK the tabs are should be larger
      tabHeight += 6;
#endif
      return tabHeight;
}

00668 void wxFNBRenderer::DrawTabs(wxWindow *pageContainer, wxDC &dc, wxEvent &event)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
#ifndef __WXMAC__
      // Works well on MSW & GTK, however this lines should be skipped on MAC
      if(pc->GetPageInfoVector().empty() || pc->m_nFrom >= (int)pc->GetPageInfoVector().GetCount())
      {
            pc->Hide();
            event.Skip();
            return;
      }
#endif

      // Get the text hight
      int tabHeight = CalcTabHeight(pageContainer);
      long style = pc->GetParent()->GetWindowStyleFlag();
      
      // Calculate the number of rows required for drawing the tabs
      wxRect rect = pc->GetClientRect();
//    int clientWidth = rect.width;

      // Set the maximum client size
#ifdef __WXMAC__
      pc->SetSizeHints(wxSize(GetButtonsAreaLength( pc ), tabHeight));
#endif
      wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));

      wxBrush backBrush;
      if(style & wxFNB_VC71)
            backBrush = wxBrush(wxColour(247, 243, 233));
      else
            backBrush = wxBrush(pc->m_tabAreaColor);

      wxBrush noselBrush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
      wxBrush selBrush = wxBrush(pc->m_activeTabColor);

      wxSize size = pc->GetSize();

      // Background
    dc.SetTextBackground((style & wxFNB_VC71 ? wxColour(247, 243, 233) : pc->GetBackgroundColour()));
      dc.SetTextForeground(pc->m_activeTextColor);
      dc.SetBrush(backBrush);

      // If border style is set, set the pen to be border pen
      if(pc->HasFlag(wxFNB_TABS_BORDER_SIMPLE))
            dc.SetPen(borderPen);
      else
      {
            wxColor colr = pc->HasFlag( wxFNB_VC71 ) ? wxColour(247, 243, 233) : pc->GetBackgroundColour();
            dc.SetPen( wxPen(colr) );
      }

      if( pc->HasFlag(wxFNB_FF2) ){
            int lightFactor = pc->HasFlag(wxFNB_BACKGROUND_GRADIENT) ? 70 : 0;
            PaintStraightGradientBox(dc, pc->GetClientRect(), pc->m_tabAreaColor, LightColour(pc->m_tabAreaColor, lightFactor));
            dc.SetBrush( *wxTRANSPARENT_BRUSH );
            dc.DrawRectangle(0, 0, size.x, size.y);
      } else {
            dc.DrawRectangle(0, 0, size.x, size.y);
      }

      // Take 3 bitmaps for the background for the buttons
      {
            wxMemoryDC mem_dc;
            wxRect rect;

            //---------------------------------------
            // X button
            //---------------------------------------
            rect = wxRect(GetXPos( pc ), 6, 16, 14);
            mem_dc.SelectObject(m_xBgBmp);
            mem_dc.Blit(0, 0, rect.width, rect.height, &dc, rect.x, rect.y);
            mem_dc.SelectObject(wxNullBitmap);

            //---------------------------------------
            // Right button
            //---------------------------------------
            rect = wxRect(GetRightButtonPos( pc ), 6, 16, 14);
            mem_dc.SelectObject(m_rightBgBmp);
            mem_dc.Blit(0, 0, rect.width, rect.height, &dc, rect.x, rect.y);
            mem_dc.SelectObject(wxNullBitmap);

            //---------------------------------------
            // Left button
            //---------------------------------------
            rect = wxRect(GetLeftButtonPos( pc ), 6, 16, 14);
            mem_dc.SelectObject(m_leftBgBmp);
            mem_dc.Blit(0, 0, rect.width, rect.height, &dc, rect.x, rect.y);
            mem_dc.SelectObject(wxNullBitmap);
      }

      // We always draw the bottom/upper line of the tabs
      // regradless the style
      dc.SetPen(borderPen);

      if( pc->HasFlag(wxFNB_FF2) == false ){
            DrawTabsLine(pc, dc);
      }

      // Restore the pen
      dc.SetPen(borderPen);

      if(pc->HasFlag( wxFNB_VC71 ))
      {
            int greyLineYVal  = pc->HasFlag( wxFNB_BOTTOM ) ? 0 : size.y - 2;
            int whiteLineYVal = pc->HasFlag( wxFNB_BOTTOM ) ? 3 : size.y - 3;

            wxPen pen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
            dc.SetPen(pen);

            // Draw thik grey line between the windows area and
            // the tab area
            int num = 0;
            for(; num<3; num++)
                  dc.DrawLine(0, greyLineYVal + num, size.x, greyLineYVal + num);

            wxPen wbPen = pc->HasFlag(wxFNB_BOTTOM) ? *wxBLACK_PEN : *wxWHITE_PEN;
            dc.SetPen( wbPen );
            dc.DrawLine(1, whiteLineYVal, size.x - 1, whiteLineYVal);

            // Restore the pen
            dc.SetPen(borderPen);
      }

#ifdef __WXMAC__
      // On MAC, Add these lines so the tab background gets painted
      if(pc->GetPageInfoVector().empty() || pc->m_nFrom >= (int)pc->GetPageInfoVector().GetCount())
      {
            pc->Hide();
            return;
      }
#endif

      // Draw labels
      /// Patch (SetTextForeground) ---- Ti-R ---- Good Text Colour
            /// -- old code ---
            //wxFont normalFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
      wxFont normalFont = pc->m_font;
      wxFont boldFont = normalFont;
      boldFont.SetWeight(wxFONTWEIGHT_BOLD);
      dc.SetFont(boldFont);

      int posx = ((wxFlatNotebook *)pc->m_pParent)->GetPadding();
      int i = 0;

      // Update all the tabs from 0 to 'pc->m_nFrom' to be non visible
      for(i=0; i<pc->m_nFrom; i++)
      {
            pc->GetPageInfoVector()[i].SetPosition(wxPoint(-1, -1));
            pc->GetPageInfoVector()[i].GetRegion().Clear();
      }

      //----------------------------------------------------------
      // Go over and draw the visible tabs
      //----------------------------------------------------------
      wxCoord x1(-1), x2(-1);
      std::vector<wxRect> vTabsInfo;
      NumberTabsCanFit(pc, vTabsInfo);

      for(i=pc->m_nFrom; i<pc->m_nFrom+(int)vTabsInfo.size(); i++)
      {
            dc.SetPen(borderPen);
            if( !pc->HasFlag(wxFNB_FF2) ){
                  dc.SetBrush((i==pc->GetSelection()) ? selBrush : noselBrush);
            }

            // Now set the font to the correct font
            dc.SetFont((i==pc->GetSelection()) ? boldFont : normalFont);

            // Add the padding to the tab width
            // Tab width:
            // +-----------------------------------------------------------+
            // | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
            // +-----------------------------------------------------------+
            int tabWidth = CalcTabWidth(pageContainer, i, tabHeight);

            // By default we clean the tab region
            pc->GetPageInfoVector()[i].GetRegion().Clear();

            // Clean the 'x' buttn on the tab.
            // A 'Clean' rectanlge, is a rectangle with width or height
            // with values lower than or equal to 0
            pc->GetPageInfoVector()[i].GetXRect().SetSize(wxSize(-1, -1));

            // Draw the tab (border, text, image & 'x' on tab)
            DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc->m_nTabXButtonStatus);
            
            if(pc->GetSelection() == i){
                  x1 = posx;
                  x2 = posx + tabWidth + 2;
            }

            // Restore the text forground
            dc.SetTextForeground(pc->m_activeTextColor);

            // Update the tab position & size
            int posy = pc->HasFlag(wxFNB_BOTTOM) ? 0 : VERTICAL_BORDER_PADDING;

            pc->GetPageInfoVector()[i].SetPosition(wxPoint(posx, posy));
            pc->GetPageInfoVector()[i].SetSize(wxSize(tabWidth, tabHeight));
            posx += tabWidth;
      }

      // Update all tabs that can not fit into the screen as non-visible
      for(; i<(int)pc->GetPageInfoVector().GetCount(); i++)
      {
            pc->GetPageInfoVector()[i].SetPosition(wxPoint(-1, -1));
            pc->GetPageInfoVector()[i].GetRegion().Clear();
      }

      // Draw the left/right/close buttons
      // Left arrow
      DrawLeftArrow(pc, dc);
      DrawRightArrow(pc, dc);
      DrawX(pc, dc);
      DrawDropDownArrow(pc, dc);

      if( pc->HasFlag(wxFNB_FF2) ){
            DrawTabsLine(pc, dc, x1, x2);
      }
}

//------------------------------------------
// Renderer manager
//------------------------------------------
wxFNBRendererMgr::wxFNBRendererMgr()
{
      // register renderers
      m_renderers[-1] = wxFNBRendererPtr(new wxFNBRendererDefault());
      m_renderers[wxFNB_VC71] = wxFNBRendererPtr(new wxFNBRendererVC71());
      m_renderers[wxFNB_FANCY_TABS] = wxFNBRendererPtr(new wxFNBRendererFancy());
      m_renderers[wxFNB_VC8] = wxFNBRendererPtr(new wxFNBRendererVC8());
      m_renderers[wxFNB_FF2] = wxFNBRendererPtr(new wxFNBRendererFirefox2());
}

wxFNBRendererMgr::~wxFNBRendererMgr()
{
}

00907 wxFNBRendererPtr wxFNBRendererMgr::GetRenderer(long style)
{
      // Do the ugly switch/case
      if( style & wxFNB_VC71 )
            return m_renderers[wxFNB_VC71];

      if( style & wxFNB_FANCY_TABS )
            return m_renderers[wxFNB_FANCY_TABS];

      if( style & wxFNB_VC8 )
            return m_renderers[wxFNB_VC8];

      if( style & wxFNB_FF2 )
            return m_renderers[wxFNB_FF2];

      // the default is to return the default renderer
      return m_renderers[-1];
}

//------------------------------------------
// Default renderer 
//------------------------------------------

00930 void wxFNBRendererDefault::DrawTab(wxWindow* pageContainer, wxDC &dc, const int &posx, const int &tabIdx, const int &tabWidth, const int &tabHeight, const int btnStatus)
{
            // Default style
      wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );

      wxPoint tabPoints[7];
      tabPoints[0].x = posx;
      tabPoints[0].y = pc->HasFlag(wxFNB_BOTTOM) ? 2 : tabHeight - 2;

      tabPoints[1].x = (int)(posx+(tabHeight-2)*tan((double)(pc->GetPageInfoVector())[tabIdx].GetTabAngle()/180.0*M_PI));
      tabPoints[1].y = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - (VERTICAL_BORDER_PADDING+2) : (VERTICAL_BORDER_PADDING+2);

      tabPoints[2].x = tabPoints[1].x+2;
      tabPoints[2].y = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - VERTICAL_BORDER_PADDING : VERTICAL_BORDER_PADDING;

      tabPoints[3].x = (int)(posx+tabWidth-(tabHeight-2)*tan((double)(pc->GetPageInfoVector())[tabIdx].GetTabAngle()/180.0*M_PI))-2;
      tabPoints[3].y = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - VERTICAL_BORDER_PADDING : VERTICAL_BORDER_PADDING;

      tabPoints[4].x = tabPoints[3].x+2;
      tabPoints[4].y = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - (VERTICAL_BORDER_PADDING+2) : (VERTICAL_BORDER_PADDING+2);

      tabPoints[5].x = (int)(tabPoints[4].x+(tabHeight-2)*tan((double)(pc->GetPageInfoVector())[tabIdx].GetTabAngle()/180.0*M_PI));
      tabPoints[5].y = pc->HasFlag(wxFNB_BOTTOM) ? 2 : tabHeight - 2;

      tabPoints[6].x = tabPoints[0].x;
      tabPoints[6].y = tabPoints[0].y;

      if(tabIdx == pc->GetSelection())
      {
            // Draw the tab as rounded rectangle
            dc.DrawPolygon(7, tabPoints);
      }
      else
      {
            if(tabIdx != pc->GetSelection() - 1)
            {
                  // Draw a vertical line to the right of the text
                  int pt1x, pt1y, pt2x, pt2y;
                  pt1x = tabPoints[5].x;
                  pt1y = pc->HasFlag(wxFNB_BOTTOM) ? 4 : tabHeight - 6;
                  pt2x = tabPoints[5].x;
                  pt2y = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - 4 : 4 ;
                  dc.DrawLine(pt1x, pt1y, pt2x, pt2y);
            }
      }

      if(tabIdx == pc->GetSelection())
      {
            wxPen savePen = dc.GetPen();
            wxPen whitePen = wxPen(*wxWHITE);
            whitePen.SetWidth(1);
            dc.SetPen(whitePen);

            wxPoint secPt = wxPoint(tabPoints[5].x + 1, tabPoints[5].y);
            dc.DrawLine(tabPoints[0], secPt);

            // Restore the pen
            dc.SetPen(savePen);
      }

      // -----------------------------------
      // Text and image drawing
      // -----------------------------------

      // Text drawing offset from the left border of the
      // rectangle
      int textOffset;

      // The width of the images are 16 pixels
      int padding = static_cast<wxFlatNotebook*>( pc->GetParent() )->GetPadding();
      int shapePoints = (int)(tabHeight * tan((double)pc->GetPageInfoVector()[tabIdx].GetTabAngle()/180.0*M_PI));
      bool hasImage = pc->GetPageInfoVector()[tabIdx].GetImageIndex() != -1;

#ifdef __WXMSW__
      int imageYCoord = pc->HasFlag(wxFNB_BOTTOM) ? 6 : 8;
#else 
      int imageYCoord = pc->HasFlag(wxFNB_BOTTOM) ? 6 : 10;
#endif

      hasImage ? textOffset = padding * 2 + 16 + shapePoints / 2 : textOffset = padding + shapePoints / 2 ;
      textOffset += 2;

      if(tabIdx != pc->GetSelection())
      {
            // Set the text background to be like the vertical lines
            dc.SetTextForeground( pc->GetNonoActiveTextColor() );
      }

      if(hasImage)
      {
            int imageXOffset = textOffset - 16 - padding;
            dc.DrawBitmap((*pc->GetImageList())[pc->GetPageInfoVector()[tabIdx].GetImageIndex()],
                  posx + imageXOffset, imageYCoord, true);
      }

      dc.DrawText(pc->GetPageText(tabIdx), posx + textOffset, imageYCoord);

      // draw 'x' on tab (if enabled)
      if(pc->HasFlag(wxFNB_X_ON_TAB) && tabIdx == pc->GetSelection())
      {
            int textWidth, textHeight;
            dc.GetTextExtent(pc->GetPageText(tabIdx), &textWidth, &textHeight);
            int 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
            int tabCloseButtonYCoord = imageYCoord;
            wxRect x_rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16);
            GetBitmap(dc, x_rect, m_tabXBgBmp);

            // Draw the tab
            DrawTabX(pc, dc, x_rect, tabIdx, btnStatus);                
      }
}

//------------------------------------------
// Firefox2 renderer 
//------------------------------------------
01049 void wxFNBRendererFirefox2::DrawTab(wxWindow* pageContainer, wxDC &dc, const int &posx, const int &tabIdx, const int &tabWidth, const int &tabHeight, const int btnStatus)
{
            // Default style
      wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );

      wxPoint tabPoints[7];
      tabPoints[0].x = posx + 2;
      tabPoints[0].y = pc->HasFlag(wxFNB_BOTTOM) ? 2 : tabHeight - 2;

      tabPoints[1].x = tabPoints[0].x;
      tabPoints[1].y = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - (VERTICAL_BORDER_PADDING+2) : (VERTICAL_BORDER_PADDING+2);

      tabPoints[2].x = tabPoints[1].x+2;
      tabPoints[2].y = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - VERTICAL_BORDER_PADDING : VERTICAL_BORDER_PADDING;

      tabPoints[3].x = posx +tabWidth - 2;
      tabPoints[3].y = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - VERTICAL_BORDER_PADDING : VERTICAL_BORDER_PADDING;

      tabPoints[4].x = tabPoints[3].x+2;
      tabPoints[4].y = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - (VERTICAL_BORDER_PADDING+2) : (VERTICAL_BORDER_PADDING+2);

      tabPoints[5].x = tabPoints[4].x;
      tabPoints[5].y = pc->HasFlag(wxFNB_BOTTOM) ? 2 : tabHeight - 2;

      tabPoints[6].x = tabPoints[0].x;
      tabPoints[6].y = tabPoints[0].y;

      //------------------------------------
      // Paint the tab with gradient
      //------------------------------------
      wxRect rr(tabPoints[2], tabPoints[5]);

      DrawButton( dc, 
                        rr, 
                        (pc->GetSelection() == tabIdx) || (pc->HasFlag( wxFNB_PREVIEW_SELECT_TAB ) && pc->GetEnabled(tabIdx) && pc->m_nTabStatus == wxFNB_BTN_HOVER && pc->m_nTabPreviewId == tabIdx) , 
                        !pc->HasFlag(wxFNB_BOTTOM));

      dc.SetBrush( *wxTRANSPARENT_BRUSH );
      dc.SetPen( borderPen );

      // Draw the tab as rounded rectangle
      dc.DrawPolygon(7, tabPoints);

      // -----------------------------------
      // Text and image drawing
      // -----------------------------------

      // Text drawing offset from the left border of the
      // rectangle
      int textOffset;

      // The width of the images are 16 pixels
      int padding = static_cast<wxFlatNotebook*>( pc->GetParent() )->GetPadding();
      int shapePoints = (int)(tabHeight * tan((double)pc->GetPageInfoVector()[tabIdx].GetTabAngle()/180.0*M_PI));
      bool hasImage = pc->GetPageInfoVector()[tabIdx].GetImageIndex() != -1;

#ifdef __WXMSW__
      int imageYCoord = pc->HasFlag(wxFNB_BOTTOM) ? 6 : 8;
#else 
      int imageYCoord = pc->HasFlag(wxFNB_BOTTOM) ? 6 : 10;
#endif

      hasImage ? textOffset = padding * 2 + 16 + shapePoints / 2 : textOffset = padding + shapePoints / 2 ;
      textOffset += 2;

      if(tabIdx != pc->GetSelection())
      {
            // Set the text background to be like the vertical lines
            dc.SetTextForeground( pc->GetNonoActiveTextColor() );
      }

      if(hasImage)
      {
            int imageXOffset = textOffset - 16 - padding;
            dc.DrawBitmap((*pc->GetImageList())[pc->GetPageInfoVector()[tabIdx].GetImageIndex()],
                  posx + imageXOffset, imageYCoord, true);
      }

      dc.DrawText(pc->GetPageText(tabIdx), posx + textOffset, imageYCoord);

      // draw 'x' on tab (if enabled)
      if(pc->HasFlag(wxFNB_X_ON_TAB) && tabIdx == pc->GetSelection())
      {
            int textWidth, textHeight;
            dc.GetTextExtent(pc->GetPageText(tabIdx), &textWidth, &textHeight);
            int 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
            int tabCloseButtonYCoord = imageYCoord;
            wxRect x_rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16);
            GetBitmap(dc, x_rect, m_tabXBgBmp);

            // Draw the tab
            DrawTabX(pc, dc, x_rect, tabIdx, btnStatus);                
      }
}
//------------------------------------------------------------------
// Visual studio 7.1 
//------------------------------------------------------------------

01151 void wxFNBRendererVC71::DrawTab(wxWindow* pageContainer, wxDC &dc, const int &posx, const int &tabIdx, const int &tabWidth, const int &tabHeight, const int btnStatus)
{
            // Visual studio 7.1 style
      wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );

      dc.SetPen((tabIdx == pc->GetSelection()) ? wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)) : borderPen);
    dc.SetBrush(((tabIdx == pc->GetSelection()) ? wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)) : wxBrush(wxColour(247, 243, 233))));

      if(tabIdx == pc->GetSelection())
      {
            int posy = pc->HasFlag(wxFNB_BOTTOM) ? 0 : VERTICAL_BORDER_PADDING;
            int tabH = pc->HasFlag(wxFNB_BOTTOM) ? tabHeight - 5 : tabHeight - 3;

            dc.DrawRectangle(posx, posy, tabWidth, tabH);

            // Draw a black line on the left side of the
            // rectangle
            wxPen pen = wxPen(*wxBLACK);
            dc.SetPen(pen);

            int blackLineY1 = VERTICAL_BORDER_PADDING;
            int blackLineY2 = tabH;
            dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2);

            // To give the tab more 3D look we do the following
            // Incase the tab is on top,
            // Draw a thik white line on topof the rectangle
            // Otherwise, draw a thin (1 pixel) black line at the bottom

            pen = wxPen(pc->HasFlag(wxFNB_BOTTOM) ? *wxBLACK : *wxWHITE);
            dc.SetPen(pen);
            int whiteLinePosY = pc->HasFlag(wxFNB_BOTTOM) ? blackLineY2 : VERTICAL_BORDER_PADDING ;
            dc.DrawLine(posx , whiteLinePosY, posx + tabWidth + 1, whiteLinePosY);

            // Draw a white vertical line to the left of the tab
            dc.SetPen( *wxWHITE_PEN );
            if( !pc->HasFlag(wxFNB_BOTTOM) ) blackLineY2 += 1;
            dc.DrawLine(posx, blackLineY1, posx, blackLineY2);
      }
      else
      {
            // We dont draw a rectangle for non selected tabs, but only
            // vertical line on the left

            int blackLineY1 = pc->HasFlag(wxFNB_BOTTOM) ? VERTICAL_BORDER_PADDING + 2 : VERTICAL_BORDER_PADDING + 1;
            int blackLineY2 = pc->GetSize().y - 5 ;
            dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2);
      }

      // -----------------------------------
      // Text and image drawing
      // -----------------------------------

      // Text drawing offset from the left border of the
      // rectangle
      int textOffset;

      // The width of the images are 16 pixels
      int padding = static_cast<wxFlatNotebook*>( pc->GetParent() )->GetPadding();
      bool hasImage = pc->GetPageInfoVector()[tabIdx].GetImageIndex() != -1;
      int imageYCoord = pc->HasFlag(wxFNB_BOTTOM) ? 5 : 8;
      
      hasImage ? textOffset = padding * 2 + 16 : textOffset = padding;

      if(tabIdx != pc->GetSelection())
      {
            // Set the text background to be like the vertical lines
            dc.SetTextForeground(pc->GetNonoActiveTextColor());
      }

      if(hasImage)
      {
            int imageXOffset = textOffset - 16 - padding;
            dc.DrawBitmap((*pc->GetImageList())[pc->GetPageInfoVector()[tabIdx].GetImageIndex()],
                  posx + imageXOffset, imageYCoord, true);
      }

      dc.DrawText(pc->GetPageText(tabIdx), posx + textOffset, imageYCoord);
      
      // draw 'x' on tab (if enabled)
      if(pc->HasFlag(wxFNB_X_ON_TAB) && tabIdx == pc->GetSelection())
      {
            int textWidth, textHeight;
            dc.GetTextExtent(pc->GetPageText(tabIdx), &textWidth, &textHeight);
            int 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
            int tabCloseButtonYCoord = imageYCoord;
            wxRect x_rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16);
            GetBitmap(dc, x_rect, m_tabXBgBmp);

            // Draw the tab
            DrawTabX(pc, dc, x_rect, tabIdx, btnStatus);                
      }
}

//------------------------------------------------------------------
// Fancy style
//------------------------------------------------------------------

01253 void wxFNBRendererFancy::DrawTab(wxWindow* pageContainer, wxDC &dc, const int &posx, const int &tabIdx, const int &tabWidth, const int &tabHeight, const int btnStatus)
{
            // Fancy tabs - like with VC71 but with the following differences:
      // - The Selected tab is colored with gradient color
      wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );

      wxPen pen = (tabIdx == pc->GetSelection()) ? wxPen( pc->GetBorderColour() ) : wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));

      if(tabIdx == pc->GetSelection())
      {
            int posy = pc->HasFlag(wxFNB_BOTTOM) ? 2 : VERTICAL_BORDER_PADDING;
            int th = tabHeight - 5;

            wxRect rect(posx, posy, tabWidth, th);

            wxColour col2 = (pc->HasFlag( wxFNB_BOTTOM ) ) ? pc->GetGradientColourTo() : pc->GetGradientColourFrom();
            wxColour col1 = (pc->HasFlag( wxFNB_BOTTOM ) ) ? pc->GetGradientColourFrom() : pc->GetGradientColourTo();

            PaintStraightGradientBox(dc, rect, col1, col2);
            dc.SetBrush(*wxTRANSPARENT_BRUSH);
            dc.SetPen(pen);
            dc.DrawRectangle(rect);

            // erase the bottom/top line of the rectangle
            dc.SetPen( wxPen( pc->GetGradientColourFrom() ) );
            if(pc->HasFlag(wxFNB_BOTTOM))
            dc.DrawLine(rect.x, 2, rect.x + rect.width, 2);
            else
                  dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1);
      }
      else
      {
            // We dont draw a rectangle for non selected tabs, but only
            // vertical line on the left
            dc.SetPen(borderPen);
            dc.DrawLine(posx + tabWidth, VERTICAL_BORDER_PADDING + 3, posx + tabWidth, tabHeight - 4);
      }

      // -----------------------------------
      // Text and image drawing
      // -----------------------------------

      // Text drawing offset from the left border of the
      // rectangle
      int textOffset;

      // The width of the images are 16 pixels
      int padding = static_cast<wxFlatNotebook*>( pc->GetParent() )->GetPadding();
      bool hasImage = pc->GetPageInfoVector()[tabIdx].GetImageIndex() != -1;
#ifdef __WXMSW__
      int imageYCoord = pc->HasFlag(wxFNB_BOTTOM) ? 6 : 8;
#else 
      int imageYCoord = pc->HasFlag(wxFNB_BOTTOM) ? 6 : 10;
#endif

      hasImage ? textOffset = padding * 2 + 16 : textOffset = padding ;

      if(tabIdx != pc->GetSelection())
      {
            // Set the text background to be like the vertical lines
            dc.SetTextForeground(pc->GetNonoActiveTextColor());
      }

      if(hasImage)
      {
            int imageXOffset = textOffset - 16 - padding;
            dc.DrawBitmap((*pc->GetImageList())[pc->GetPageInfoVector()[tabIdx].GetImageIndex()],
                  posx + imageXOffset, imageYCoord, true);
      }

      dc.DrawText(pc->GetPageText(tabIdx), posx + textOffset, imageYCoord);
      
      // draw 'x' on tab (if enabled)
      if(pc->HasFlag(wxFNB_X_ON_TAB) && tabIdx == pc->GetSelection())
      {
            int textWidth, textHeight;
            dc.GetTextExtent(pc->GetPageText(tabIdx), &textWidth, &textHeight);
            int 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
            int tabCloseButtonYCoord = imageYCoord;
            wxRect x_rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16);
            GetBitmap(dc, x_rect, m_tabXBgBmp);

            // Draw the tab
            DrawTabX(pc, dc, x_rect, tabIdx, btnStatus);                
      }
}

//------------------------------------------------------------------
// Visual studio 2005 (VS8)
//------------------------------------------------------------------
01347 void wxFNBRendererVC8::DrawTabs(wxWindow *pageContainer, wxDC &dc, wxEvent &event)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );

#ifndef __WXMAC__ 
      // Works well on MSW & GTK, however this lines should be skipped on MAC
      if(pc->GetPageInfoVector().empty() || pc->m_nFrom >= (int)pc->GetPageInfoVector().GetCount())
      {
            pc->Hide();
            event.Skip();
            return;
      }
#endif

      // Get the text hight
      int tabHeight = CalcTabHeight( pageContainer );

      // Set the font for measuring the tab height
      /// Patch (SetTextForeground) ---- Ti-R ---- Good Text Colour
            /// -- old code ---
            //wxFont normalFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
      wxFont normalFont = pc->m_font;
      wxFont boldFont = normalFont;
      boldFont.SetWeight(wxFONTWEIGHT_BOLD);

      // Calculate the number of rows required for drawing the tabs
      wxRect rect = pc->GetClientRect();

      // Set the maximum client size
#ifdef __WXMAC__
      pc->SetSizeHints(wxSize(GetButtonsAreaLength( pc ), tabHeight));
#endif 
      wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));

      /// Create brushes
      wxBrush backBrush;
      backBrush = wxBrush(pc->m_tabAreaColor);
      wxBrush noselBrush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
      wxBrush selBrush = wxBrush(pc->m_activeTabColor);
      wxSize size = pc->GetSize();

      // Background
      dc.SetTextBackground(pc->GetBackgroundColour());
      dc.SetTextForeground(pc->m_activeTextColor);
      
      // If border style is set, set the pen to be border pen
      if( pc->HasFlag(wxFNB_TABS_BORDER_SIMPLE) )
            dc.SetPen(borderPen);
      else
            dc.SetPen(*wxTRANSPARENT_PEN);

      int lightFactor = pc->HasFlag(wxFNB_BACKGROUND_GRADIENT) ? 70 : 0;
      /// For VC8 style, we color the tab area in gradient coloring
      PaintStraightGradientBox(dc, pc->GetClientRect(), pc->m_tabAreaColor, LightColour(pc->m_tabAreaColor, lightFactor));

      dc.SetBrush(*wxTRANSPARENT_BRUSH);
      dc.DrawRectangle(0, 0, size.x, size.y);

      // Take 3 bitmaps for the background for the buttons
      {
            wxMemoryDC mem_dc;
            wxRect rect;
            
            //---------------------------------------
            // X button
            //---------------------------------------
            rect = wxRect(GetXPos( pc ), 6, 16, 14);
            mem_dc.SelectObject(m_xBgBmp);
            mem_dc.Blit(0, 0, rect.width, rect.height, &dc, rect.x, rect.y);
            mem_dc.SelectObject(wxNullBitmap);

            //---------------------------------------
            // Right button
            //---------------------------------------
            rect = wxRect(GetRightButtonPos( pc ), 6, 16, 14);
            mem_dc.SelectObject(m_rightBgBmp);
            mem_dc.Blit(0, 0, rect.width, rect.height, &dc, rect.x, rect.y);
            mem_dc.SelectObject(wxNullBitmap);

            //---------------------------------------
            // Left button
            //---------------------------------------
            rect = wxRect(GetLeftButtonPos( pc ), 6, 16, 14);
            mem_dc.SelectObject(m_leftBgBmp);
            mem_dc.Blit(0, 0, rect.width, rect.height, &dc, rect.x, rect.y);
            mem_dc.SelectObject(wxNullBitmap);
      }

      // We always draw the bottom/upper line of the tabs
      // regradless the style
      dc.SetPen(borderPen);
      DrawTabsLine(pc, dc);

      // Restore the pen
      dc.SetPen(borderPen);

      // Draw labels
      dc.SetFont(boldFont);
      int posx;
      int i = 0, cur = 0;

      // Update all the tabs from 0 to 'pc->m_nFrom' to be non visible
      for(i=0; i<pc->m_nFrom; i++)
      {
            pc->GetPageInfoVector()[i].SetPosition(wxPoint(-1, -1));
            pc->GetPageInfoVector()[i].GetRegion().Clear();
      }

      // Draw the visible tabs, in VC8 style, we draw them from right to left
      std::vector<wxRect> vTabsInfo;
      NumberTabsCanFit(pc, vTabsInfo);
      int activeTabPosx(0);
      int activeTabWidth(0);
      int   activeTabHeight(0);

      for(cur=(int)vTabsInfo.size() - 1; cur>=0; cur--) 
      {
            /// 'i' points to the index of the currently drawn tab
            /// in pc->GetPageInfoVector() vector
            i = pc->m_nFrom + cur;
            dc.SetPen(borderPen);
            dc.SetBrush((i==pc->GetSelection()) ? selBrush : noselBrush);

            // Now set the font to the correct font
            dc.SetFont((i==pc->GetSelection()) ? boldFont : normalFont);

            // Add the padding to the tab width
            // Tab width:
            // +-----------------------------------------------------------+
            // | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
            // +-----------------------------------------------------------+

            int tabWidth = CalcTabWidth( pageContainer, i, tabHeight );
            posx = vTabsInfo[cur].x;

            // By default we clean the tab region
            // incase we use the VC8 style which requires
            // the region, it will be filled by the function
            // drawVc8Tab
            pc->GetPageInfoVector()[i].GetRegion().Clear();
            
            // Clean the 'x' buttn on the tab 
            // 'Clean' rectanlge is a rectangle with width or height
            // with values lower than or equal to 0
            pc->GetPageInfoVector()[i].GetXRect().SetSize(wxSize(-1, -1));

            // Draw the tab
            // Incase we are drawing the active tab
            // we need to redraw so it will appear on top
            // of all other tabs

            // when using the vc8 style, we keep the position of the active tab so we will draw it again later
            if( i == pc->GetSelection() && pc->HasFlag( wxFNB_VC8 ) )
            {
                  activeTabPosx = posx;
                  activeTabWidth = tabWidth;
                  activeTabHeight = tabHeight;
            }
            else
            {
                  DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc->m_nTabXButtonStatus);
            }

            // Restore the text forground
            dc.SetTextForeground(pc->m_activeTextColor);

            // Update the tab position & size
            pc->GetPageInfoVector()[i].SetPosition(wxPoint(posx, VERTICAL_BORDER_PADDING));
            pc->GetPageInfoVector()[i].SetSize(wxSize(tabWidth, tabHeight));
      }

      // Incase we are in VC8 style, redraw the active tab (incase it is visible)
      if(pc->GetSelection() >= pc->m_nFrom && pc->GetSelection()< pc->m_nFrom + (int)vTabsInfo.size() )
      {
            DrawTab(pc, dc, activeTabPosx, pc->GetSelection(), activeTabWidth, activeTabHeight, pc->m_nTabXButtonStatus);
      }

      // Update all tabs that can not fit into the screen as non-visible
      int xx;
      for(xx = pc->m_nFrom + (int)vTabsInfo.size(); xx<(int)pc->GetPageInfoVector().size(); xx++)
      {
            pc->GetPageInfoVector()[xx].SetPosition(wxPoint(-1, -1));
            pc->GetPageInfoVector()[xx].GetRegion().Clear();
      }

      // Draw the left/right/close buttons 
      // Left arrow
      DrawLeftArrow(pc, dc);
      DrawRightArrow(pc, dc);
      DrawX(pc, dc);
      DrawDropDownArrow(pc, dc);
}

01540 void wxFNBRendererVC8::DrawTab(wxWindow* pageContainer, wxDC &dc, const int &posx, const int &tabIdx, const int &tabWidth, const int &tabHeight, const int btnStatus)
{
      // Fancy tabs - like with VC71 but with the following differences:
      // - The Selected tab is colored with gradient color
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      wxPen borderPen = wxPen( pc->GetBorderColour() );
      wxPoint tabPoints[8];

      // If we draw the first tab or the active tab, 
      // we draw a full tab, else we draw a truncated tab
      //
      //             X(2)                  X(3)
      //        X(1)                            X(4)
      //                                          
      //                                           X(5)
      //                                           
      // X(0),(7)                                  X(6)
      //
      //

      tabPoints[0].x = pc->HasFlag( wxFNB_BOTTOM ) ? posx : posx + m_factor;
      tabPoints[0].y = pc->HasFlag( wxFNB_BOTTOM ) ? 2 : tabHeight - 3;

      tabPoints[1].x = tabPoints[0].x + tabHeight - VERTICAL_BORDER_PADDING - 3 - m_factor;
      tabPoints[1].y = pc->HasFlag( wxFNB_BOTTOM ) ? tabHeight  - (VERTICAL_BORDER_PADDING+2) : (VERTICAL_BORDER_PADDING+2);

      tabPoints[2].x = tabPoints[1].x + 4;
      tabPoints[2].y = pc->HasFlag( wxFNB_BOTTOM ) ? tabHeight  - VERTICAL_BORDER_PADDING : VERTICAL_BORDER_PADDING;

      tabPoints[3].x = tabPoints[2].x + tabWidth - 2;
      tabPoints[3].y = pc->HasFlag( wxFNB_BOTTOM ) ? tabHeight  - VERTICAL_BORDER_PADDING : VERTICAL_BORDER_PADDING;

      tabPoints[4].x = tabPoints[3].x + 1;
      tabPoints[4].y = pc->HasFlag( wxFNB_BOTTOM ) ? tabPoints[3].y - 1 : tabPoints[3].y + 1;

      tabPoints[5].x = tabPoints[4].x + 1;
      tabPoints[5].y = pc->HasFlag( wxFNB_BOTTOM ) ? (tabPoints[4].y - 1 ): tabPoints[4].y + 1;

      tabPoints[6].x = tabPoints[2].x + tabWidth;
      tabPoints[6].y = tabPoints[0].y;

      tabPoints[7].x = tabPoints[0].x;
      tabPoints[7].y = tabPoints[0].y;

      pc->GetPageInfoVector()[tabIdx].SetRegion(8, tabPoints);

      // Draw the polygon
      wxBrush br = dc.GetBrush();
      dc.SetBrush(wxBrush(tabIdx == pc->GetSelection() ? pc->GetActiveTabColour() : pc->GetGradientColourTo() ));
      
/// Patch ---- Ti-R ---- Enable to have the same line color as the selected tab
      if(pc->HasFlag( wxFNB_INVERSE_COLOR_LINE_VC8 ))
            dc.SetPen(wxPen(tabIdx == pc->GetSelection() ? pc->GetBorderColour() : wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)));
      else
            dc.SetPen(wxPen(tabIdx == pc->GetSelection() ? wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW) : pc->GetBorderColour()));
      dc.DrawPolygon(8, tabPoints);

      // Restore the brush
      dc.SetBrush(br);

      wxRect rect = pc->GetClientRect();

      if(tabIdx != pc->GetSelection() && !pc->HasFlag( wxFNB_BOTTOM ))
      {

      /// Patch ---- Ti-R ---- Enable to have the same line color as the selected tab
            if(pc->HasFlag( wxFNB_INVERSE_COLOR_LINE_VC8 ))
            {
                  // Top default tabs
                  dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)));
            }
            else
            {
                  // Top default tabs
                  dc.SetPen(wxPen( pc->GetBorderColour() ));
            }

            int lineY = rect.height;
            wxPen curPen = dc.GetPen();
            curPen.SetWidth(1);
            dc.SetPen(curPen);
            dc.DrawLine(posx, lineY, posx+rect.width, lineY);
      }

      // Incase we are drawing the selected tab, we draw the border of it as well
      // but without the bottom (upper line incase of wxBOTTOM)
      if(tabIdx == pc->GetSelection())
      {
            wxPen borderPen ;

      /// Patch ---- Ti-R ---- Enable to have the same line color as the selected tab
            if(pc->HasFlag( wxFNB_INVERSE_COLOR_LINE_VC8 ))
                  borderPen = pc->GetBorderColour();
            else
                  borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));

            wxBrush brush(*wxTRANSPARENT_BRUSH);
            dc.SetPen(borderPen);
            dc.SetBrush(brush);
            dc.DrawPolygon(8, tabPoints);

            // Delete the bottom line (or the upper one, incase we use wxBOTTOM) 
            dc.SetPen(wxPen(wxT("WHITE")));
            dc.DrawLine(tabPoints[0], tabPoints[6]);
      }


      FillVC8GradientColor(pc, dc, tabPoints, tabIdx == pc->GetSelection(), tabIdx);

      // Draw a thin line to the right of the non-selected tab
      if(tabIdx != pc->GetSelection())
      {
            dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)));
            dc.DrawLine(tabPoints[4].x-1, tabPoints[4].y, tabPoints[5].x-1, tabPoints[5].y);
            dc.DrawLine(tabPoints[5].x-1, tabPoints[5].y, tabPoints[6].x-1, tabPoints[6].y);
      }

      // Text drawing offset from the left border of the 
      // rectangle
      int textOffset;

      // The width of the images are 16 pixels
      int vc8ShapeLen = tabHeight - VERTICAL_BORDER_PADDING - 2;
      if( pc->TabHasImage( tabIdx ) )
            textOffset = ((wxFlatNotebook *)pc->m_pParent)->GetPadding() * 2 + 16 + vc8ShapeLen; 
      else
            textOffset = ((wxFlatNotebook *)pc->m_pParent)->GetPadding() + vc8ShapeLen;

      // Draw the image for the tab if any
#ifdef __WXMSW__
      int imageYCoord = pc->HasFlag(wxFNB_BOTTOM) ? 6 : 8;
#else 
      int imageYCoord = pc->HasFlag(wxFNB_BOTTOM) ? 6 : 10;
#endif

      if( pc->TabHasImage( tabIdx ) )
      {
            int imageXOffset = textOffset - 16 - ((wxFlatNotebook *)pc->m_pParent)->GetPadding();
            dc.DrawBitmap((*pc->GetImageList())[pc->GetPageInfoVector()[tabIdx].GetImageIndex()], 
                  posx + imageXOffset, imageYCoord, true);
      }

      /// Patch (SetTextForeground) ---- Ti-R ---- Good Text Colour
            /// -- old code ---
            //wxFont boldFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
      wxFont boldFont = pc->m_font;

      /// Patch (Test GetEnabled) ---- Ti-R ---- change color is disable
      if(!pc->GetEnabled(tabIdx))
      {
            dc.SetTextForeground(pc->m_disableTextColor);
      }
      else
      {
            // if selected tab, draw text in bold
            if( tabIdx == pc->GetSelection() )
            {
            /// Patch (SetTextForeground) ---- Ti-R ---- Good Text Colour
                  dc.SetTextForeground(pc->m_activeTextColor);
                  boldFont.SetWeight(wxFONTWEIGHT_BOLD);
            }
            else
            {
            /// Patch (SetTextForeground) ---- Ti-R ---- Good Text Colour
                  dc.SetTextForeground(pc->m_nonActiveTextColor);
            }
      }

      dc.SetFont( boldFont );
      dc.DrawText(pc->GetPageText(tabIdx), posx + textOffset, imageYCoord);
      
      // draw 'x' on tab (if enabled)
      if(pc->HasFlag(wxFNB_X_ON_TAB) && tabIdx == pc->GetSelection())
      {
            int textWidth, textHeight;
            dc.GetTextExtent(pc->GetPageText(tabIdx), &textWidth, &textHeight);
            int 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
            int tabCloseButtonYCoord = imageYCoord;
            wxRect x_rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16);
            GetBitmap(dc, x_rect, m_tabXBgBmp);
            wxBitmap bmp( 16, 16 );

            // Draw the tab
            DrawTabX(pc, dc, x_rect, tabIdx, btnStatus);                
      }
}

01730 void wxFNBRendererVC8::FillVC8GradientColor(wxWindow* pageContainer, wxDC &dc, const wxPoint tabPoints[], const bool bSelectedTab, const int tabIdx)
{
wxColour p_colorFrom;
wxColour p_colorTo;

      // calculate gradient coefficients
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );

      /// Patch (comment) ---- Ti-R ---- No need anymore, see below
/*    if( m_first )
      {
            m_first = false;
            pc->m_colorTo   = LightColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE), 0); 
            pc->m_colorFrom = LightColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE), 60);
      }*/

      /// (BEGIN) Patch (m_nTabStatus) ---- Ti-R ---- Set the preview color
      if( pc->HasFlag( wxFNB_PREVIEW_SELECT_TAB ) && pc->GetEnabled(tabIdx) && pc->m_nTabStatus == wxFNB_BTN_HOVER && pc->m_nTabPreviewId == tabIdx)
      {
            p_colorTo   = pc->m_colorPreview; 
            p_colorFrom = pc->m_colorPreview;
      }
      else
      {
            p_colorTo   = pc->GetGradientColourTo(); //LightColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE), 0); 
            p_colorFrom = pc->GetGradientColourFrom(); //LightColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE), 60);
      }
      /// (END) Patch (m_nTabStatus) ---- Ti-R ---- 

      wxColour col2 = pc->HasFlag( wxFNB_BOTTOM ) ? p_colorTo : p_colorFrom;
      wxColour col1 = pc->HasFlag( wxFNB_BOTTOM ) ? p_colorFrom : p_colorTo;

      // If colorful tabs style is set, override the tab color
      if(pc->HasFlag(wxFNB_COLORFUL_TABS))
      {
            if( !pc->GetPageInfoVector()[tabIdx].GetColor().Ok() )
            {
                  // First time, generate color, and keep it in the vector
                  wxColor tabColor(RandomColor());
                  pc->GetPageInfoVector()[tabIdx].SetColor(tabColor);
            }

            if( pc->HasFlag(wxFNB_BOTTOM) )
            {
                  col2 = LightColour( pc->GetPageInfoVector()[tabIdx].GetColor() , 50 );
                  col1 = LightColour( pc->GetPageInfoVector()[tabIdx].GetColor() , 80 );
            }
            else
            {
                  col1 = LightColour( pc->GetPageInfoVector()[tabIdx].GetColor() , 50 );
                  col2 = LightColour( pc->GetPageInfoVector()[tabIdx].GetColor() , 80 );
            }
      }

      int size = abs(tabPoints[2].y - tabPoints[0].y) - 1;

      double rstep = double((col2.Red() -   col1.Red())) / double(size), rf = 0,
            gstep = double((col2.Green() - col1.Green())) / double(size), gf = 0,
            bstep = double((col2.Blue() -  col1.Blue())) / double(size), bf = 0;

      wxColour currCol;
      int y = tabPoints[0].y; 

      // If we are drawing the selected tab, we need also to draw a line 
      // from 0->tabPoints[0].x and tabPoints[6].x -> end, we achieve this
      // by drawing the rectangle with transparent brush
      // the line under the selected tab will be deleted by the drwaing loop
      if( bSelectedTab )
            DrawTabsLine(pc, dc);

      while( true )
      {
            if(pc->HasFlag( wxFNB_BOTTOM ))
            {
                  if(y > tabPoints[0].y + size)
                        break;
            }
            else
            {
                  if(y < tabPoints[0].y - size)
                        break;
            }

            currCol.Set(
                  (unsigned char)(col1.Red() + rf),
                  (unsigned char)(col1.Green() + gf),
                  (unsigned char)(col1.Blue() + bf)
                  );

            dc.SetPen(bSelectedTab ? wxPen(pc->m_activeTabColor) : wxPen(currCol));
            int startX = GetStartX(tabPoints, y, pc->GetParent()->GetWindowStyleFlag()) ;
            int endX   = GetEndX(tabPoints, y, pc->GetParent()->GetWindowStyleFlag());
            dc.DrawLine(startX, y, endX, y);

            // Draw the border using the 'edge' point
            /// Patch ---- Ti-R ---- Enable to have the same line color as the selected tab
            if(pc->HasFlag( wxFNB_INVERSE_COLOR_LINE_VC8 ))
                  dc.SetPen(wxPen(bSelectedTab ? pc->m_colorBorder : wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)));
            else
                  dc.SetPen(wxPen(bSelectedTab ? wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW) : pc->m_colorBorder));
            
            dc.DrawPoint(startX, y);
            dc.DrawPoint(endX, y);
            
            // Progress the color 
            rf += rstep; gf += gstep; bf += bstep;

            pc->HasFlag( wxFNB_BOTTOM ) ? y++ : y--;
      }
}

int wxFNBRendererVC8::GetStartX(const wxPoint tabPoints[], const int &y, long style)
{
      double x1 = 0, x2 = 0, y1 = 0, y2 = 0;

      // We check the 3 points to the left
      bool bBottomStyle = style & wxFNB_BOTTOM ? true : false;
      bool match = false;

      if(bBottomStyle)
      {
            for(int i=0; i<3; i++)
            {     
                  if(y >= tabPoints[i].y && y < tabPoints[i+1].y)
                  {
                        x1 = tabPoints[i].x;
                        x2 = tabPoints[i+1].x;
                        y1 = tabPoints[i].y;
                        y2 = tabPoints[i+1].y;
                        match = true;
                        break;
                  }
            }
      }
      else
      {
            for(int i=0; i<3; i++)
            {     
                  if(y <= tabPoints[i].y && y > tabPoints[i+1].y)
                  {
                        x1 = tabPoints[i].x;
                        x2 = tabPoints[i+1].x;
                        y1 = tabPoints[i].y;
                        y2 = tabPoints[i+1].y;
                        match = true;
                        break;
                  }
            }
      }

      if(!match)
            return tabPoints[2].x;

      // According to the equation y = ax + b => x = (y-b)/a
      // We know the first 2 points

      double a;
      if(x2 == x1) 
            return static_cast<int>( x2 );
      else
            a = (y2 - y1) / (x2 - x1);

      double b = y1 - ((y2 - y1) / (x2 - x1)) * x1;

      if(a == 0) 
            return static_cast<int>( x1 );

      double x = (y - b) / a;
      return static_cast<int>( x );
}

int wxFNBRendererVC8::GetEndX(const wxPoint tabPoints[], const int &y, long style)
{
      double x1 = 0, x2 = 0, y1 = 0, y2 = 0;

      // We check the 3 points to the left
      bool bBottomStyle = style & wxFNB_BOTTOM ? true : false;
      bool match = false;

      if(bBottomStyle)
      {
            for(int i=7; i>3; i--)
            {     
                  if(y >= tabPoints[i].y && y < tabPoints[i-1].y)
                  {
                        x1 = tabPoints[i].x;
                        x2 = tabPoints[i-1].x;
                        y1 = tabPoints[i].y;
                        y2 = tabPoints[i-1].y;
                        match = true;
                        break;
                  }
            }
      }
      else
      {
            for(int i=7; i>3; i--)
            {     
                  if(y <= tabPoints[i].y && y > tabPoints[i-1].y)
                  {
                        x1 = tabPoints[i].x;
                        x2 = tabPoints[i-1].x;
                        y1 = tabPoints[i].y;
                        y2 = tabPoints[i-1].y;
                        match = true;
                        break;
                  }
            }
      }

      if(!match)
            return tabPoints[3].x;

      // According to the equation y = ax + b => x = (y-b)/a
      // We know the first 2 points
      double a = (y2 - y1) / (x2 - x1);

      // Vertical line
      if(x1 == x2)
            return (int)x1;

      double b = y1 - ((y2 - y1) / (x2 - x1)) * x1;

      if(a == 0) 
            return (int)x1;

      double x = (y - b) / a;
      return (int)x;
}

01960 void wxFNBRendererVC8::NumberTabsCanFit(wxWindow *pageContainer, std::vector<wxRect> &vTabInfo, int from)
{
      wxPageContainer *pc = static_cast<wxPageContainer*>( pageContainer );
      int tabHeight, clientWidth;
      
      wxRect rect = pc->GetClientRect();
      clientWidth = rect.width;

      /// Empty results
      vTabInfo.clear();

      tabHeight = CalcTabHeight( pageContainer );

      // The drawing starts from posx
      int posx = ((wxFlatNotebook *)pc->m_pParent)->GetPadding();
      
      if( from < 0 )
            from = pc->m_nFrom;

      for(int i = from; i<(int)pc->GetPageInfoVector().GetCount(); i++)
      {
            int vc8glitch = tabHeight + wxFNB_HEIGHT_SPACER;
            int tabWidth = CalcTabWidth( pageContainer, i, tabHeight );
            if(posx + tabWidth + vc8glitch + GetButtonsAreaLength( pc ) >= clientWidth)
                  break;

            /// Add a result to the returned vector
            wxRect tabRect(posx, VERTICAL_BORDER_PADDING, tabWidth , tabHeight);
            vTabInfo.push_back(tabRect);

            /// Advance posx
            posx += tabWidth + wxFNB_HEIGHT_SPACER;
      }
}

Generated by  Doxygen 1.6.0   Back to index