+ return 5;
+}
+
+wxSize wxAuiDefaultTabArt::GetTabSize(wxDC& dc,
+ wxWindow* WXUNUSED(wnd),
+ const wxString& caption,
+ const wxBitmap& bitmap,
+ bool WXUNUSED(active),
+ int close_button_state,
+ int* x_extent)
+{
+ wxCoord measured_textx, measured_texty, tmp;
+
+ dc.SetFont(m_measuringFont);
+ dc.GetTextExtent(caption, &measured_textx, &measured_texty);
+
+ dc.GetTextExtent(wxT("ABCDEFXj"), &tmp, &measured_texty);
+
+ // add padding around the text
+ wxCoord tab_width = measured_textx;
+ wxCoord tab_height = measured_texty;
+
+ // if the close button is showing, add space for it
+ if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
+ tab_width += m_activeCloseBmp.GetWidth() + 3;
+
+ // if there's a bitmap, add space for it
+ if (bitmap.IsOk())
+ {
+ tab_width += bitmap.GetWidth();
+ tab_width += 3; // right side bitmap padding
+ tab_height = wxMax(tab_height, bitmap.GetHeight());
+ }
+
+ // add padding
+ tab_width += 16;
+ tab_height += 10;
+
+ if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
+ {
+ tab_width = m_fixedTabWidth;
+ }
+
+ *x_extent = tab_width;
+
+ return wxSize(tab_width, tab_height);
+}
+
+
+void wxAuiDefaultTabArt::DrawButton(wxDC& dc,
+ wxWindow* WXUNUSED(wnd),
+ const wxRect& in_rect,
+ int bitmap_id,
+ int button_state,
+ int orientation,
+ wxRect* out_rect)
+{
+ wxBitmap bmp;
+ wxRect rect;
+
+ switch (bitmap_id)
+ {
+ case wxAUI_BUTTON_CLOSE:
+ if (button_state & wxAUI_BUTTON_STATE_DISABLED)
+ bmp = m_disabledCloseBmp;
+ else
+ bmp = m_activeCloseBmp;
+ break;
+ case wxAUI_BUTTON_LEFT:
+ if (button_state & wxAUI_BUTTON_STATE_DISABLED)
+ bmp = m_disabledLeftBmp;
+ else
+ bmp = m_activeLeftBmp;
+ break;
+ case wxAUI_BUTTON_RIGHT:
+ if (button_state & wxAUI_BUTTON_STATE_DISABLED)
+ bmp = m_disabledRightBmp;
+ else
+ bmp = m_activeRightBmp;
+ break;
+ case wxAUI_BUTTON_WINDOWLIST:
+ if (button_state & wxAUI_BUTTON_STATE_DISABLED)
+ bmp = m_disabledWindowListBmp;
+ else
+ bmp = m_activeWindowListBmp;
+ break;
+ }
+
+
+ if (!bmp.IsOk())
+ return;
+
+ rect = in_rect;
+
+ if (orientation == wxLEFT)
+ {
+ rect.SetX(in_rect.x);
+ rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
+ rect.SetWidth(bmp.GetWidth());
+ rect.SetHeight(bmp.GetHeight());
+ }
+ else
+ {
+ rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
+ ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
+ bmp.GetWidth(), bmp.GetHeight());
+ }
+
+ IndentPressedBitmap(&rect, button_state);
+ dc.DrawBitmap(bmp, rect.x, rect.y, true);
+
+ *out_rect = rect;
+}
+
+int wxAuiDefaultTabArt::ShowDropDown(wxWindow* wnd,
+ const wxAuiNotebookPageArray& pages,
+ int /*active_idx*/)
+{
+ wxMenu menuPopup;
+
+ size_t i, count = pages.GetCount();
+ for (i = 0; i < count; ++i)
+ {
+ const wxAuiNotebookPage& page = pages.Item(i);
+ wxString caption = page.caption;
+
+ // if there is no caption, make it a space. This will prevent
+ // an assert in the menu code.
+ if (caption.IsEmpty())
+ caption = wxT(" ");
+
+ wxMenuItem* item = new wxMenuItem(NULL, 1000+i, caption);
+ if (page.bitmap.IsOk())
+ item->SetBitmap(page.bitmap);
+ menuPopup.Append(item);
+ }
+
+ // find out where to put the popup menu of window items
+ wxPoint pt = ::wxGetMousePosition();
+ pt = wnd->ScreenToClient(pt);
+
+ // find out the screen coordinate at the bottom of the tab ctrl
+ wxRect cli_rect = wnd->GetClientRect();
+ pt.y = cli_rect.y + cli_rect.height;
+
+ wxAuiCommandCapture* cc = new wxAuiCommandCapture;
+ wnd->PushEventHandler(cc);
+ wnd->PopupMenu(&menuPopup, pt);
+ int command = cc->GetCommandId();
+ wnd->PopEventHandler(true);
+
+ if (command >= 1000)
+ return command-1000;
+
+ return -1;
+}
+
+int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow* wnd,
+ const wxAuiNotebookPageArray& pages,
+ const wxSize& requiredBmp_size)
+{
+ wxClientDC dc(wnd);
+ dc.SetFont(m_measuringFont);
+
+ // sometimes a standard bitmap size needs to be enforced, especially
+ // if some tabs have bitmaps and others don't. This is important because
+ // it prevents the tab control from resizing when tabs are added.
+ wxBitmap measureBmp;
+ if (requiredBmp_size.IsFullySpecified())
+ {
+ measureBmp.Create(requiredBmp_size.x,
+ requiredBmp_size.y);
+ }
+
+
+ int max_y = 0;
+ size_t i, page_count = pages.GetCount();
+ for (i = 0; i < page_count; ++i)
+ {
+ wxAuiNotebookPage& page = pages.Item(i);
+
+ wxBitmap bmp;
+ if (measureBmp.IsOk())
+ bmp = measureBmp;
+ else
+ bmp = page.bitmap;
+
+ // we don't use the caption text because we don't
+ // want tab heights to be different in the case
+ // of a very short piece of text on one tab and a very
+ // tall piece of text on another tab
+ int x_ext = 0;
+ wxSize s = GetTabSize(dc,
+ wnd,
+ wxT("ABCDEFGHIj"),
+ bmp,
+ true,
+ wxAUI_BUTTON_STATE_HIDDEN,
+ &x_ext);
+
+ max_y = wxMax(max_y, s.y);
+ }
+
+ return max_y+2;
+}
+
+void wxAuiDefaultTabArt::SetNormalFont(const wxFont& font)
+{
+ m_normalFont = font;
+}
+
+void wxAuiDefaultTabArt::SetSelectedFont(const wxFont& font)
+{
+ m_selectedFont = font;
+}
+
+void wxAuiDefaultTabArt::SetMeasuringFont(const wxFont& font)
+{
+ m_measuringFont = font;
+}
+
+void wxAuiDefaultTabArt::SetColour(const wxColour& colour)
+{
+ m_baseColour = colour;
+ m_borderPen = wxPen(m_baseColour.ChangeLightness(75));
+ m_baseColourPen = wxPen(m_baseColour);
+ m_baseColourBrush = wxBrush(m_baseColour);
+}
+
+void wxAuiDefaultTabArt::SetActiveColour(const wxColour& colour)
+{
+ m_activeColour = colour;
+}
+
+// -- wxAuiSimpleTabArt class implementation --
+
+wxAuiSimpleTabArt::wxAuiSimpleTabArt()
+{
+ m_normalFont = *wxNORMAL_FONT;
+ m_selectedFont = *wxNORMAL_FONT;
+ m_selectedFont.SetWeight(wxBOLD);
+ m_measuringFont = m_selectedFont;
+
+ m_flags = 0;
+ m_fixedTabWidth = 100;
+
+ wxColour baseColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
+
+ wxColour backgroundColour = baseColour;
+ wxColour normaltabColour = baseColour;
+ wxColour selectedtabColour = *wxWHITE;
+
+ m_bkBrush = wxBrush(backgroundColour);
+ m_normalBkBrush = wxBrush(normaltabColour);
+ m_normalBkPen = wxPen(normaltabColour);
+ m_selectedBkBrush = wxBrush(selectedtabColour);
+ m_selectedBkPen = wxPen(selectedtabColour);
+
+ m_activeCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, *wxBLACK);
+ m_disabledCloseBmp = wxAuiBitmapFromBits(close_bits, 16, 16, wxColour(128,128,128));
+
+ m_activeLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, *wxBLACK);
+ m_disabledLeftBmp = wxAuiBitmapFromBits(left_bits, 16, 16, wxColour(128,128,128));
+
+ m_activeRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, *wxBLACK);
+ m_disabledRightBmp = wxAuiBitmapFromBits(right_bits, 16, 16, wxColour(128,128,128));
+
+ m_activeWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, *wxBLACK);
+ m_disabledWindowListBmp = wxAuiBitmapFromBits(list_bits, 16, 16, wxColour(128,128,128));
+
+}
+
+wxAuiSimpleTabArt::~wxAuiSimpleTabArt()
+{
+}
+
+wxAuiTabArt* wxAuiSimpleTabArt::Clone()
+{
+ return new wxAuiSimpleTabArt(*this);
+}
+
+void wxAuiSimpleTabArt::SetFlags(unsigned int flags)
+{
+ m_flags = flags;
+}
+
+void wxAuiSimpleTabArt::SetSizingInfo(const wxSize& tab_ctrl_size,
+ size_t tab_count)
+{
+ m_fixedTabWidth = 100;
+
+ int tot_width = (int)tab_ctrl_size.x - GetIndentSize() - 4;
+
+ if (m_flags & wxAUI_NB_CLOSE_BUTTON)
+ tot_width -= m_activeCloseBmp.GetWidth();
+ if (m_flags & wxAUI_NB_WINDOWLIST_BUTTON)
+ tot_width -= m_activeWindowListBmp.GetWidth();
+
+ if (tab_count > 0)
+ {
+ m_fixedTabWidth = tot_width/(int)tab_count;
+ }
+
+
+ if (m_fixedTabWidth < 100)
+ m_fixedTabWidth = 100;
+
+ if (m_fixedTabWidth > tot_width/2)
+ m_fixedTabWidth = tot_width/2;
+
+ if (m_fixedTabWidth > 220)
+ m_fixedTabWidth = 220;
+}
+
+void wxAuiSimpleTabArt::SetColour(const wxColour& colour)
+{
+ m_bkBrush = wxBrush(colour);
+ m_normalBkBrush = wxBrush(colour);
+ m_normalBkPen = wxPen(colour);
+}
+
+void wxAuiSimpleTabArt::SetActiveColour(const wxColour& colour)
+{
+ m_selectedBkBrush = wxBrush(colour);
+ m_selectedBkPen = wxPen(colour);
+}
+
+void wxAuiSimpleTabArt::DrawBackground(wxDC& dc,
+ wxWindow* WXUNUSED(wnd),
+ const wxRect& rect)
+{
+ // draw background
+ dc.SetBrush(m_bkBrush);
+ dc.SetPen(*wxTRANSPARENT_PEN);
+ dc.DrawRectangle(-1, -1, rect.GetWidth()+2, rect.GetHeight()+2);
+
+ // draw base line
+ dc.SetPen(*wxGREY_PEN);
+ dc.DrawLine(0, rect.GetHeight()-1, rect.GetWidth(), rect.GetHeight()-1);
+}
+
+
+// DrawTab() draws an individual tab.
+//
+// dc - output dc
+// in_rect - rectangle the tab should be confined to
+// caption - tab's caption
+// active - whether or not the tab is active
+// out_rect - actual output rectangle
+// x_extent - the advance x; where the next tab should start
+
+void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
+ wxWindow* wnd,
+ const wxAuiNotebookPage& page,
+ const wxRect& in_rect,
+ int close_button_state,
+ wxRect* out_tab_rect,
+ wxRect* out_button_rect,
+ int* x_extent)
+{
+ wxCoord normal_textx, normal_texty;
+ wxCoord selected_textx, selected_texty;
+ wxCoord textx, texty;
+
+ // if the caption is empty, measure some temporary text
+ wxString caption = page.caption;
+ if (caption.empty())
+ caption = wxT("Xj");
+
+ dc.SetFont(m_selectedFont);
+ dc.GetTextExtent(caption, &selected_textx, &selected_texty);
+
+ dc.SetFont(m_normalFont);
+ dc.GetTextExtent(caption, &normal_textx, &normal_texty);
+
+ // figure out the size of the tab
+ wxSize tab_size = GetTabSize(dc,
+ wnd,
+ page.caption,
+ page.bitmap,
+ page.active,
+ close_button_state,
+ x_extent);
+
+ wxCoord tab_height = tab_size.y;
+ wxCoord tab_width = tab_size.x;
+ wxCoord tab_x = in_rect.x;
+ wxCoord tab_y = in_rect.y + in_rect.height - tab_height;
+
+ caption = page.caption;
+
+ // select pen, brush and font for the tab to be drawn
+
+ if (page.active)
+ {
+ dc.SetPen(m_selectedBkPen);
+ dc.SetBrush(m_selectedBkBrush);
+ dc.SetFont(m_selectedFont);
+ textx = selected_textx;
+ texty = selected_texty;
+ }
+ else
+ {
+ dc.SetPen(m_normalBkPen);
+ dc.SetBrush(m_normalBkBrush);
+ dc.SetFont(m_normalFont);
+ textx = normal_textx;
+ texty = normal_texty;
+ }
+
+
+ // -- draw line --
+
+ wxPoint points[7];
+ points[0].x = tab_x;
+ points[0].y = tab_y + tab_height - 1;
+ points[1].x = tab_x + tab_height - 3;
+ points[1].y = tab_y + 2;
+ points[2].x = tab_x + tab_height + 3;
+ points[2].y = tab_y;
+ points[3].x = tab_x + tab_width - 2;
+ points[3].y = tab_y;
+ points[4].x = tab_x + tab_width;
+ points[4].y = tab_y + 2;
+ points[5].x = tab_x + tab_width;
+ points[5].y = tab_y + tab_height - 1;
+ points[6] = points[0];
+
+ dc.SetClippingRegion(in_rect);
+
+ dc.DrawPolygon(WXSIZEOF(points) - 1, points);
+
+ dc.SetPen(*wxGREY_PEN);
+
+ //dc.DrawLines(active ? WXSIZEOF(points) - 1 : WXSIZEOF(points), points);
+ dc.DrawLines(WXSIZEOF(points), points);
+
+
+ int text_offset;
+
+ int close_button_width = 0;
+ if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
+ {
+ close_button_width = m_activeCloseBmp.GetWidth();
+ text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
+ }
+ else
+ {
+ text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2);
+ }
+
+ // set minimum text offset
+ if (text_offset < tab_x + tab_height)
+ text_offset = tab_x + tab_height;
+
+ // chop text if necessary
+ wxString draw_text = wxAuiChopText(dc,
+ caption,
+ tab_width - (text_offset-tab_x) - close_button_width);
+
+ // draw tab text
+ dc.DrawText(draw_text,
+ text_offset,
+ (tab_y + tab_height)/2 - (texty/2) + 1);
+
+
+ // draw focus rectangle
+ if (page.active && (wnd->FindFocus() == wnd))
+ {
+ wxRect focusRect(text_offset, ((tab_y + tab_height)/2 - (texty/2) + 1),
+ selected_textx, selected_texty);
+
+ focusRect.Inflate(2, 2);
+
+ wxRendererNative::Get().DrawFocusRect(wnd, dc, focusRect, 0);
+ }
+
+ // draw close button if necessary
+ if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
+ {
+ wxBitmap bmp;
+ if (page.active)
+ bmp = m_activeCloseBmp;
+ else
+ bmp = m_disabledCloseBmp;
+
+ wxRect rect(tab_x + tab_width - close_button_width - 1,
+ tab_y + (tab_height/2) - (bmp.GetHeight()/2) + 1,
+ close_button_width,
+ tab_height - 1);
+ DrawButtons(dc, rect, bmp, *wxWHITE, close_button_state);
+
+ *out_button_rect = rect;
+ }
+
+
+ *out_tab_rect = wxRect(tab_x, tab_y, tab_width, tab_height);
+
+ dc.DestroyClippingRegion();
+}
+
+int wxAuiSimpleTabArt::GetIndentSize()
+{
+ return 0;
+}
+
+wxSize wxAuiSimpleTabArt::GetTabSize(wxDC& dc,
+ wxWindow* WXUNUSED(wnd),
+ const wxString& caption,
+ const wxBitmap& WXUNUSED(bitmap),
+ bool WXUNUSED(active),
+ int close_button_state,
+ int* x_extent)
+{
+ wxCoord measured_textx, measured_texty;
+
+ dc.SetFont(m_measuringFont);
+ dc.GetTextExtent(caption, &measured_textx, &measured_texty);
+
+ wxCoord tab_height = measured_texty + 4;
+ wxCoord tab_width = measured_textx + tab_height + 5;
+
+ if (close_button_state != wxAUI_BUTTON_STATE_HIDDEN)
+ tab_width += m_activeCloseBmp.GetWidth();
+
+ if (m_flags & wxAUI_NB_TAB_FIXED_WIDTH)
+ {
+ tab_width = m_fixedTabWidth;
+ }
+
+ *x_extent = tab_width - (tab_height/2) - 1;
+
+ return wxSize(tab_width, tab_height);
+}
+
+
+void wxAuiSimpleTabArt::DrawButton(wxDC& dc,
+ wxWindow* WXUNUSED(wnd),
+ const wxRect& in_rect,
+ int bitmap_id,
+ int button_state,
+ int orientation,
+ wxRect* out_rect)
+{
+ wxBitmap bmp;
+ wxRect rect;
+
+ switch (bitmap_id)
+ {
+ case wxAUI_BUTTON_CLOSE:
+ if (button_state & wxAUI_BUTTON_STATE_DISABLED)
+ bmp = m_disabledCloseBmp;
+ else
+ bmp = m_activeCloseBmp;
+ break;
+ case wxAUI_BUTTON_LEFT:
+ if (button_state & wxAUI_BUTTON_STATE_DISABLED)
+ bmp = m_disabledLeftBmp;
+ else
+ bmp = m_activeLeftBmp;
+ break;
+ case wxAUI_BUTTON_RIGHT:
+ if (button_state & wxAUI_BUTTON_STATE_DISABLED)
+ bmp = m_disabledRightBmp;
+ else
+ bmp = m_activeRightBmp;
+ break;
+ case wxAUI_BUTTON_WINDOWLIST:
+ if (button_state & wxAUI_BUTTON_STATE_DISABLED)
+ bmp = m_disabledWindowListBmp;
+ else
+ bmp = m_activeWindowListBmp;
+ break;
+ }
+
+ if (!bmp.IsOk())
+ return;
+
+ rect = in_rect;
+
+ if (orientation == wxLEFT)
+ {
+ rect.SetX(in_rect.x);
+ rect.SetY(((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2));
+ rect.SetWidth(bmp.GetWidth());
+ rect.SetHeight(bmp.GetHeight());
+ }
+ else
+ {
+ rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
+ ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
+ bmp.GetWidth(), bmp.GetHeight());
+ }
+
+
+ DrawButtons(dc, rect, bmp, *wxWHITE, button_state);
+
+ *out_rect = rect;
+}
+
+int wxAuiSimpleTabArt::ShowDropDown(wxWindow* wnd,
+ const wxAuiNotebookPageArray& pages,
+ int active_idx)
+{
+ wxMenu menuPopup;
+
+ size_t i, count = pages.GetCount();
+ for (i = 0; i < count; ++i)
+ {
+ const wxAuiNotebookPage& page = pages.Item(i);
+ menuPopup.AppendCheckItem(1000+i, page.caption);
+ }
+
+ if (active_idx != -1)
+ {
+ menuPopup.Check(1000+active_idx, true);
+ }
+
+ // find out where to put the popup menu of window
+ // items. Subtract 100 for now to center the menu
+ // a bit, until a better mechanism can be implemented
+ wxPoint pt = ::wxGetMousePosition();
+ pt = wnd->ScreenToClient(pt);
+ if (pt.x < 100)
+ pt.x = 0;
+ else
+ pt.x -= 100;
+
+ // find out the screen coordinate at the bottom of the tab ctrl
+ wxRect cli_rect = wnd->GetClientRect();
+ pt.y = cli_rect.y + cli_rect.height;
+
+ wxAuiCommandCapture* cc = new wxAuiCommandCapture;
+ wnd->PushEventHandler(cc);
+ wnd->PopupMenu(&menuPopup, pt);
+ int command = cc->GetCommandId();
+ wnd->PopEventHandler(true);
+
+ if (command >= 1000)
+ return command-1000;
+
+ return -1;
+}
+
+int wxAuiSimpleTabArt::GetBestTabCtrlSize(wxWindow* wnd,
+ const wxAuiNotebookPageArray& WXUNUSED(pages),
+ const wxSize& WXUNUSED(requiredBmp_size))
+{
+ wxClientDC dc(wnd);
+ dc.SetFont(m_measuringFont);
+ int x_ext = 0;
+ wxSize s = GetTabSize(dc,
+ wnd,
+ wxT("ABCDEFGHIj"),
+ wxNullBitmap,
+ true,
+ wxAUI_BUTTON_STATE_HIDDEN,
+ &x_ext);
+ return s.y+3;
+}
+
+void wxAuiSimpleTabArt::SetNormalFont(const wxFont& font)
+{
+ m_normalFont = font;
+}
+
+void wxAuiSimpleTabArt::SetSelectedFont(const wxFont& font)
+{
+ m_selectedFont = font;
+}
+
+void wxAuiSimpleTabArt::SetMeasuringFont(const wxFont& font)
+{
+ m_measuringFont = font;
+}
+
+
+
+
+// -- wxAuiTabContainer class implementation --
+
+
+// wxAuiTabContainer is a class which contains information about each
+// tab. It also can render an entire tab control to a specified DC.
+// It's not a window class itself, because this code will be used by
+// the wxFrameMananger, where it is disadvantageous to have separate
+// windows for each tab control in the case of "docked tabs"
+
+// A derived class, wxAuiTabCtrl, is an actual wxWindow-derived window
+// which can be used as a tab control in the normal sense.
+
+
+wxAuiTabContainer::wxAuiTabContainer()
+{
+ m_tabOffset = 0;
+ m_flags = 0;
+ m_art = new wxAuiDefaultTabArt;
+
+ AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
+ AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
+ AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
+ AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
+}
+
+wxAuiTabContainer::~wxAuiTabContainer()
+{
+ delete m_art;
+}
+
+void wxAuiTabContainer::SetArtProvider(wxAuiTabArt* art)
+{
+ delete m_art;
+ m_art = art;
+
+ if (m_art)
+ {
+ m_art->SetFlags(m_flags);
+ }
+}
+
+wxAuiTabArt* wxAuiTabContainer::GetArtProvider() const
+{
+ return m_art;
+}
+
+void wxAuiTabContainer::SetFlags(unsigned int flags)
+{
+ m_flags = flags;
+
+ // check for new close button settings
+ RemoveButton(wxAUI_BUTTON_LEFT);
+ RemoveButton(wxAUI_BUTTON_RIGHT);
+ RemoveButton(wxAUI_BUTTON_WINDOWLIST);
+ RemoveButton(wxAUI_BUTTON_CLOSE);
+
+
+ if (flags & wxAUI_NB_SCROLL_BUTTONS)
+ {
+ AddButton(wxAUI_BUTTON_LEFT, wxLEFT);
+ AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT);
+ }
+
+ if (flags & wxAUI_NB_WINDOWLIST_BUTTON)
+ {
+ AddButton(wxAUI_BUTTON_WINDOWLIST, wxRIGHT);
+ }
+
+ if (flags & wxAUI_NB_CLOSE_BUTTON)
+ {
+ AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT);
+ }
+
+ if (m_art)
+ {
+ m_art->SetFlags(m_flags);
+ }
+}
+
+unsigned int wxAuiTabContainer::GetFlags() const
+{
+ return m_flags;
+}
+
+
+void wxAuiTabContainer::SetNormalFont(const wxFont& font)
+{
+ m_art->SetNormalFont(font);
+}
+
+void wxAuiTabContainer::SetSelectedFont(const wxFont& font)
+{
+ m_art->SetSelectedFont(font);
+}
+
+void wxAuiTabContainer::SetMeasuringFont(const wxFont& font)
+{
+ m_art->SetMeasuringFont(font);
+}
+
+void wxAuiTabContainer::SetColour(const wxColour& colour)
+{
+ m_art->SetColour(colour);
+}
+
+void wxAuiTabContainer::SetActiveColour(const wxColour& colour)
+{
+ m_art->SetActiveColour(colour);
+}
+
+void wxAuiTabContainer::SetRect(const wxRect& rect)
+{
+ m_rect = rect;
+
+ if (m_art)
+ {
+ m_art->SetSizingInfo(rect.GetSize(), m_pages.GetCount());
+ }
+}
+
+bool wxAuiTabContainer::AddPage(wxWindow* page,
+ const wxAuiNotebookPage& info)
+{
+ wxAuiNotebookPage page_info;
+ page_info = info;
+ page_info.window = page;
+
+ m_pages.Add(page_info);
+
+ // let the art provider know how many pages we have
+ if (m_art)
+ {
+ m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
+ }
+
+ return true;
+}
+
+bool wxAuiTabContainer::InsertPage(wxWindow* page,
+ const wxAuiNotebookPage& info,
+ size_t idx)
+{
+ wxAuiNotebookPage page_info;
+ page_info = info;
+ page_info.window = page;
+
+ if (idx >= m_pages.GetCount())
+ m_pages.Add(page_info);
+ else
+ m_pages.Insert(page_info, idx);
+
+ // let the art provider know how many pages we have
+ if (m_art)
+ {
+ m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
+ }
+
+ return true;
+}
+
+bool wxAuiTabContainer::MovePage(wxWindow* page,
+ size_t new_idx)
+{
+ int idx = GetIdxFromWindow(page);
+ if (idx == -1)
+ return false;
+
+ // get page entry, make a copy of it
+ wxAuiNotebookPage p = GetPage(idx);
+
+ // remove old page entry
+ RemovePage(page);
+
+ // insert page where it should be
+ InsertPage(page, p, new_idx);
+
+ return true;
+}
+
+bool wxAuiTabContainer::RemovePage(wxWindow* wnd)
+{
+ size_t i, page_count = m_pages.GetCount();
+ for (i = 0; i < page_count; ++i)
+ {
+ wxAuiNotebookPage& page = m_pages.Item(i);
+ if (page.window == wnd)
+ {
+ m_pages.RemoveAt(i);
+
+ // let the art provider know how many pages we have
+ if (m_art)
+ {
+ m_art->SetSizingInfo(m_rect.GetSize(), m_pages.GetCount());
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
+{
+ bool found = false;
+
+ size_t i, page_count = m_pages.GetCount();
+ for (i = 0; i < page_count; ++i)
+ {
+ wxAuiNotebookPage& page = m_pages.Item(i);
+ if (page.window == wnd)
+ {
+ page.active = true;
+ found = true;
+ }
+ else
+ {
+ page.active = false;
+ }
+ }
+
+ return found;
+}
+
+void wxAuiTabContainer::SetNoneActive()
+{
+ size_t i, page_count = m_pages.GetCount();
+ for (i = 0; i < page_count; ++i)
+ {
+ wxAuiNotebookPage& page = m_pages.Item(i);
+ page.active = false;
+ }
+}
+
+bool wxAuiTabContainer::SetActivePage(size_t page)
+{
+ if (page >= m_pages.GetCount())
+ return false;
+
+ return SetActivePage(m_pages.Item(page).window);
+}
+
+int wxAuiTabContainer::GetActivePage() const
+{
+ size_t i, page_count = m_pages.GetCount();
+ for (i = 0; i < page_count; ++i)
+ {
+ wxAuiNotebookPage& page = m_pages.Item(i);
+ if (page.active)
+ return i;
+ }
+
+ return -1;
+}
+
+wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
+{
+ if (idx >= m_pages.GetCount())
+ return NULL;
+
+ return m_pages[idx].window;
+}
+
+int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
+{
+ const size_t page_count = m_pages.GetCount();
+ for ( size_t i = 0; i < page_count; ++i )
+ {
+ wxAuiNotebookPage& page = m_pages.Item(i);
+ if (page.window == wnd)
+ return i;
+ }
+ return wxNOT_FOUND;
+}
+
+wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
+{
+ wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
+
+ return m_pages[idx];
+}
+
+const wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx) const
+{
+ wxASSERT_MSG(idx < m_pages.GetCount(), wxT("Invalid Page index"));
+
+ return m_pages[idx];
+}
+
+wxAuiNotebookPageArray& wxAuiTabContainer::GetPages()
+{
+ return m_pages;
+}
+
+size_t wxAuiTabContainer::GetPageCount() const
+{
+ return m_pages.GetCount();
+}
+
+void wxAuiTabContainer::AddButton(int id,
+ int location,
+ const wxBitmap& normalBitmap,
+ const wxBitmap& disabledBitmap)
+{
+ wxAuiTabContainerButton button;
+ button.id = id;
+ button.bitmap = normalBitmap;
+ button.disBitmap = disabledBitmap;
+ button.location = location;
+ button.curState = wxAUI_BUTTON_STATE_NORMAL;
+
+ m_buttons.Add(button);
+}
+
+void wxAuiTabContainer::RemoveButton(int id)
+{
+ size_t i, button_count = m_buttons.GetCount();
+
+ for (i = 0; i < button_count; ++i)
+ {
+ if (m_buttons.Item(i).id == id)
+ {
+ m_buttons.RemoveAt(i);
+ return;
+ }
+ }
+}
+
+
+
+size_t wxAuiTabContainer::GetTabOffset() const
+{
+ return m_tabOffset;
+}
+
+void wxAuiTabContainer::SetTabOffset(size_t offset)
+{
+ m_tabOffset = offset;
+}
+
+
+
+
+// Render() renders the tab catalog to the specified DC
+// It is a virtual function and can be overridden to
+// provide custom drawing capabilities
+void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
+{
+ if (!raw_dc || !raw_dc->IsOk())
+ return;
+
+ wxMemoryDC dc;
+
+ // use the same layout direction as the window DC uses to ensure that the
+ // text is rendered correctly
+ dc.SetLayoutDirection(raw_dc->GetLayoutDirection());
+
+ wxBitmap bmp;
+ size_t i;
+ size_t page_count = m_pages.GetCount();
+ size_t button_count = m_buttons.GetCount();
+
+ // create off-screen bitmap
+ bmp.Create(m_rect.GetWidth(), m_rect.GetHeight());
+ dc.SelectObject(bmp);
+
+ if (!dc.IsOk())
+ return;
+
+ // find out if size of tabs is larger than can be
+ // afforded on screen
+ int total_width = 0;
+ int visible_width = 0;
+ for (i = 0; i < page_count; ++i)
+ {
+ wxAuiNotebookPage& page = m_pages.Item(i);
+
+ // determine if a close button is on this tab
+ bool close_button = false;
+ if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
+ ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
+ {
+ close_button = true;
+ }
+
+
+ int x_extent = 0;
+ wxSize size = m_art->GetTabSize(dc,
+ wnd,
+ page.caption,
+ page.bitmap,
+ page.active,
+ close_button ?
+ wxAUI_BUTTON_STATE_NORMAL :
+ wxAUI_BUTTON_STATE_HIDDEN,
+ &x_extent);
+
+ if (i+1 < page_count)
+ total_width += x_extent;
+ else
+ total_width += size.x;
+
+ if (i >= m_tabOffset)
+ {
+ if (i+1 < page_count)
+ visible_width += x_extent;
+ else
+ visible_width += size.x;
+ }
+ }
+
+ if (total_width > m_rect.GetWidth() || m_tabOffset != 0)
+ {
+ // show left/right buttons
+ for (i = 0; i < button_count; ++i)
+ {
+ wxAuiTabContainerButton& button = m_buttons.Item(i);
+ if (button.id == wxAUI_BUTTON_LEFT ||
+ button.id == wxAUI_BUTTON_RIGHT)
+ {
+ button.curState &= ~wxAUI_BUTTON_STATE_HIDDEN;
+ }
+ }
+ }
+ else
+ {
+ // hide left/right buttons
+ for (i = 0; i < button_count; ++i)
+ {
+ wxAuiTabContainerButton& button = m_buttons.Item(i);
+ if (button.id == wxAUI_BUTTON_LEFT ||
+ button.id == wxAUI_BUTTON_RIGHT)
+ {
+ button.curState |= wxAUI_BUTTON_STATE_HIDDEN;
+ }
+ }
+ }
+
+ // determine whether left button should be enabled
+ for (i = 0; i < button_count; ++i)
+ {
+ wxAuiTabContainerButton& button = m_buttons.Item(i);
+ if (button.id == wxAUI_BUTTON_LEFT)
+ {
+ if (m_tabOffset == 0)
+ button.curState |= wxAUI_BUTTON_STATE_DISABLED;
+ else
+ button.curState &= ~wxAUI_BUTTON_STATE_DISABLED;
+ }
+ if (button.id == wxAUI_BUTTON_RIGHT)
+ {
+ if (visible_width < m_rect.GetWidth() - ((int)button_count*16))
+ button.curState |= wxAUI_BUTTON_STATE_DISABLED;
+ else
+ button.curState &= ~wxAUI_BUTTON_STATE_DISABLED;
+ }
+ }
+
+
+
+ // draw background
+ m_art->DrawBackground(dc, wnd, m_rect);
+
+ // draw buttons
+ int left_buttons_width = 0;
+ int right_buttons_width = 0;
+
+ int offset = 0;
+
+ // draw the buttons on the right side
+ offset = m_rect.x + m_rect.width;
+ for (i = 0; i < button_count; ++i)
+ {
+ wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
+
+ if (button.location != wxRIGHT)
+ continue;
+ if (button.curState & wxAUI_BUTTON_STATE_HIDDEN)
+ continue;
+
+ wxRect button_rect = m_rect;
+ button_rect.SetY(1);
+ button_rect.SetWidth(offset);
+
+ m_art->DrawButton(dc,
+ wnd,
+ button_rect,
+ button.id,
+ button.curState,
+ wxRIGHT,
+ &button.rect);
+
+ offset -= button.rect.GetWidth();
+ right_buttons_width += button.rect.GetWidth();
+ }
+
+
+
+ offset = 0;
+
+ // draw the buttons on the left side
+
+ for (i = 0; i < button_count; ++i)
+ {
+ wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
+
+ if (button.location != wxLEFT)
+ continue;
+ if (button.curState & wxAUI_BUTTON_STATE_HIDDEN)
+ continue;
+
+ wxRect button_rect(offset, 1, 1000, m_rect.height);
+
+ m_art->DrawButton(dc,
+ wnd,
+ button_rect,
+ button.id,
+ button.curState,
+ wxLEFT,
+ &button.rect);
+
+ offset += button.rect.GetWidth();
+ left_buttons_width += button.rect.GetWidth();
+ }
+
+ offset = left_buttons_width;
+
+ if (offset == 0)
+ offset += m_art->GetIndentSize();
+
+
+ // prepare the tab-close-button array
+ // make sure tab button entries which aren't used are marked as hidden
+ for (i = page_count; i < m_tabCloseButtons.GetCount(); ++i)
+ m_tabCloseButtons.Item(i).curState = wxAUI_BUTTON_STATE_HIDDEN;
+
+ // make sure there are enough tab button entries to accommodate all tabs
+ while (m_tabCloseButtons.GetCount() < page_count)
+ {
+ wxAuiTabContainerButton tempbtn;
+ tempbtn.id = wxAUI_BUTTON_CLOSE;
+ tempbtn.location = wxCENTER;
+ tempbtn.curState = wxAUI_BUTTON_STATE_HIDDEN;
+ m_tabCloseButtons.Add(tempbtn);
+ }
+
+
+ // buttons before the tab offset must be set to hidden
+ for (i = 0; i < m_tabOffset; ++i)
+ {
+ m_tabCloseButtons.Item(i).curState = wxAUI_BUTTON_STATE_HIDDEN;
+ }
+
+
+ // draw the tabs
+
+ size_t active = 999;
+ int active_offset = 0;
+ wxRect active_rect;
+
+ int x_extent = 0;
+ wxRect rect = m_rect;
+ rect.y = 0;
+ rect.height = m_rect.height;
+
+ for (i = m_tabOffset; i < page_count; ++i)
+ {
+ wxAuiNotebookPage& page = m_pages.Item(i);
+ wxAuiTabContainerButton& tab_button = m_tabCloseButtons.Item(i);
+
+ // determine if a close button is on this tab
+ if ((m_flags & wxAUI_NB_CLOSE_ON_ALL_TABS) != 0 ||
+ ((m_flags & wxAUI_NB_CLOSE_ON_ACTIVE_TAB) != 0 && page.active))
+ {
+ if (tab_button.curState == wxAUI_BUTTON_STATE_HIDDEN)
+ {
+ tab_button.id = wxAUI_BUTTON_CLOSE;
+ tab_button.curState = wxAUI_BUTTON_STATE_NORMAL;
+ tab_button.location = wxCENTER;
+ }
+ }
+ else
+ {
+ tab_button.curState = wxAUI_BUTTON_STATE_HIDDEN;
+ }
+
+ rect.x = offset;
+ rect.width = m_rect.width - right_buttons_width - offset - 2;
+
+ if (rect.width <= 0)
+ break;
+
+ m_art->DrawTab(dc,
+ wnd,
+ page,
+ rect,
+ tab_button.curState,
+ &page.rect,
+ &tab_button.rect,
+ &x_extent);
+
+ if (page.active)
+ {
+ active = i;
+ active_offset = offset;
+ active_rect = rect;
+ }
+
+ offset += x_extent;
+ }
+
+
+ // make sure to deactivate buttons which are off the screen to the right
+ for (++i; i < m_tabCloseButtons.GetCount(); ++i)
+ {
+ m_tabCloseButtons.Item(i).curState = wxAUI_BUTTON_STATE_HIDDEN;
+ }
+
+
+ // draw the active tab again so it stands in the foreground
+ if (active >= m_tabOffset && active < m_pages.GetCount())
+ {
+ wxAuiNotebookPage& page = m_pages.Item(active);
+
+ wxAuiTabContainerButton& tab_button = m_tabCloseButtons.Item(active);
+
+ rect.x = active_offset;
+ m_art->DrawTab(dc,
+ wnd,
+ page,
+ active_rect,
+ tab_button.curState,
+ &page.rect,
+ &tab_button.rect,
+ &x_extent);
+ }
+
+
+ raw_dc->Blit(m_rect.x, m_rect.y,
+ m_rect.GetWidth(), m_rect.GetHeight(),
+ &dc, 0, 0);
+}
+
+// Is the tab visible?
+bool wxAuiTabContainer::IsTabVisible(int tabPage, int tabOffset, wxDC* dc, wxWindow* wnd)
+{
+ if (!dc || !dc->IsOk())
+ return false;
+
+ size_t i;
+ size_t page_count = m_pages.GetCount();
+ size_t button_count = m_buttons.GetCount();
+
+ // Hasn't been rendered yet; assume it's visible
+ if (m_tabCloseButtons.GetCount() < page_count)
+ return true;
+
+ // First check if both buttons are disabled - if so, there's no need to
+ // check further for visibility.
+ int arrowButtonVisibleCount = 0;
+ for (i = 0; i < button_count; ++i)
+ {
+ wxAuiTabContainerButton& button = m_buttons.Item(i);
+ if (button.id == wxAUI_BUTTON_LEFT ||
+ button.id == wxAUI_BUTTON_RIGHT)
+ {
+ if ((button.curState & wxAUI_BUTTON_STATE_HIDDEN) == 0)
+ arrowButtonVisibleCount ++;
+ }
+ }
+
+ // Tab must be visible
+ if (arrowButtonVisibleCount == 0)
+ return true;
+
+ // If tab is less than the given offset, it must be invisible by definition
+ if (tabPage < tabOffset)
+ return false;
+
+ // draw buttons
+ int left_buttons_width = 0;
+ int right_buttons_width = 0;
+
+ int offset = 0;
+
+ // calculate size of the buttons on the right side
+ offset = m_rect.x + m_rect.width;
+ for (i = 0; i < button_count; ++i)
+ {
+ wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
+
+ if (button.location != wxRIGHT)
+ continue;
+ if (button.curState & wxAUI_BUTTON_STATE_HIDDEN)
+ continue;
+
+ offset -= button.rect.GetWidth();
+ right_buttons_width += button.rect.GetWidth();
+ }
+
+ offset = 0;
+
+ // calculate size of the buttons on the left side
+ for (i = 0; i < button_count; ++i)
+ {
+ wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1);
+
+ if (button.location != wxLEFT)
+ continue;
+ if (button.curState & wxAUI_BUTTON_STATE_HIDDEN)
+ continue;
+
+ offset += button.rect.GetWidth();
+ left_buttons_width += button.rect.GetWidth();
+ }
+
+ offset = left_buttons_width;
+
+ if (offset == 0)
+ offset += m_art->GetIndentSize();
+
+ wxRect active_rect;
+
+ wxRect rect = m_rect;
+ rect.y = 0;
+ rect.height = m_rect.height;
+
+ // See if the given page is visible at the given tab offset (effectively scroll position)
+ for (i = tabOffset; i < page_count; ++i)
+ {
+ wxAuiNotebookPage& page = m_pages.Item(i);
+ wxAuiTabContainerButton& tab_button = m_tabCloseButtons.Item(i);
+
+ rect.x = offset;
+ rect.width = m_rect.width - right_buttons_width - offset - 2;
+
+ if (rect.width <= 0)
+ return false; // haven't found the tab, and we've run out of space, so return false
+
+ int x_extent = 0;
+ m_art->GetTabSize(*dc,
+ wnd,
+ page.caption,
+ page.bitmap,
+ page.active,
+ tab_button.curState,
+ &x_extent);
+
+ offset += x_extent;
+
+ if (i == (size_t) tabPage)
+ {
+ // If not all of the tab is visible, and supposing there's space to display it all,
+ // we could do better so we return false.
+ if (((m_rect.width - right_buttons_width - offset - 2) <= 0) && ((m_rect.width - right_buttons_width - left_buttons_width) > x_extent))
+ return false;
+ else
+ return true;
+ }
+ }
+
+ // Shouldn't really get here, but if it does, assume the tab is visible to prevent
+ // further looping in calling code.
+ return true;
+}
+
+// Make the tab visible if it wasn't already
+void wxAuiTabContainer::MakeTabVisible(int tabPage, wxWindow* win)
+{
+ wxClientDC dc(win);
+ if (!IsTabVisible(tabPage, GetTabOffset(), & dc, win))
+ {
+ int i;
+ for (i = 0; i < (int) m_pages.GetCount(); i++)
+ {
+ if (IsTabVisible(tabPage, i, & dc, win))
+ {
+ SetTabOffset(i);
+ win->Refresh();
+ return;
+ }
+ }
+ }
+}
+
+// TabHitTest() tests if a tab was hit, passing the window pointer
+// back if that condition was fulfilled. The function returns
+// true if a tab was hit, otherwise false
+bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const
+{
+ if (!m_rect.Contains(x,y))