X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4f450f41a2c02db9c35e3e566b381c85b5714de8..64f8f94ca0797f2d4a0c7daf34500ccc23c7d83e:/src/aui/auibook.cpp diff --git a/src/aui/auibook.cpp b/src/aui/auibook.cpp index a634917abd..5d7b97897f 100644 --- a/src/aui/auibook.cpp +++ b/src/aui/auibook.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: src/aui/notebook.cpp +// Name: src/aui/auibook.cpp // Purpose: wxaui: wx advanced user interface - notebook // Author: Benjamin I. Williams // Modified by: @@ -20,14 +20,16 @@ #if wxUSE_AUI -#include "wx/settings.h" #include "wx/aui/auibook.h" -#include "wx/aui/tabmdi.h" -#include "wx/dcbuffer.h" #ifndef WX_PRECOMP + #include "wx/settings.h" + #include "wx/image.h" #endif +#include "wx/aui/tabmdi.h" +#include "wx/dcbuffer.h" + #include "wx/arrimpl.cpp" WX_DEFINE_OBJARRAY(wxAuiNotebookPageArray) WX_DEFINE_OBJARRAY(wxAuiTabContainerButtonArray) @@ -43,17 +45,8 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION) IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent) -// -- 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. // This functions are here for this proof of concept @@ -72,8 +65,8 @@ static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h, const wxColour& color) { wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage(); - img.Replace(255,255,255,123,123,123); - img.Replace(0,0,0,color.Red(),color.Green(),color.Blue()); + img.Replace(0,0,0,123,123,123); + img.Replace(255,255,255,color.Red(),color.Green(),color.Blue()); img.SetMaskColour(123,123,123); return wxBitmap(img); } @@ -109,19 +102,22 @@ static void DrawButton(wxDC& dc, -wxAuiTabContainer::wxAuiTabContainer() + +// -- wxDefaultTabArt class implementation -- + +wxDefaultTabArt::wxDefaultTabArt() { m_normal_font = *wxNORMAL_FONT; m_selected_font = *wxNORMAL_FONT; m_selected_font.SetWeight(wxBOLD); m_measuring_font = m_selected_font; - + wxColour base_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); - + wxColour background_colour = StepColour(base_colour, 95); wxColour normaltab_colour = base_colour; wxColour selectedtab_colour = *wxWHITE; - + m_bkbrush = wxBrush(background_colour); m_normal_bkbrush = wxBrush(normaltab_colour); m_normal_bkpen = wxPen(normaltab_colour); @@ -129,23 +125,192 @@ wxAuiTabContainer::wxAuiTabContainer() m_selected_bkpen = wxPen(selectedtab_colour); } +wxDefaultTabArt::~wxDefaultTabArt() +{ +} + +void wxDefaultTabArt::DrawBackground( + wxDC* dc, + 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 wxDefaultTabArt::DrawTab(wxDC* dc, + const wxRect& in_rect, + const wxString& caption_text, + bool active, + wxRect* out_rect, + int* x_extent) +{ + wxCoord normal_textx, normal_texty; + wxCoord selected_textx, selected_texty; + wxCoord measured_textx, measured_texty; + wxCoord textx, texty; + + + // if the caption is empty, measure some temporary text + wxString caption = caption_text; + if (caption_text.empty()) + caption = wxT("Xj"); + + // measure text + dc->SetFont(m_measuring_font); + dc->GetTextExtent(caption, &measured_textx, &measured_texty); + + dc->SetFont(m_selected_font); + dc->GetTextExtent(caption, &selected_textx, &selected_texty); + + dc->SetFont(m_normal_font); + dc->GetTextExtent(caption, &normal_textx, &normal_texty); + + caption = caption_text; + + wxCoord tab_height = measured_texty + 4; + wxCoord tab_width = measured_textx + tab_height + 5; + wxCoord tab_x = in_rect.x; + wxCoord tab_y = in_rect.y + in_rect.height - tab_height; + + + // select pen, brush and font for the tab to be drawn + + if (active) + { + dc->SetPen(m_selected_bkpen); + dc->SetBrush(m_selected_bkbrush); + dc->SetFont(m_selected_font); + textx = selected_textx; + texty = selected_texty; + } + else + { + dc->SetPen(m_normal_bkpen); + dc->SetBrush(m_normal_bkbrush); + dc->SetFont(m_normal_font); + 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->DrawPolygon(6, points); + + dc->SetPen(*wxGREY_PEN); + + //dc->DrawLines(active ? 6 : 7, points); + dc->DrawLines(7, points); + + // -- draw text -- + + dc->DrawText(caption, + tab_x + (tab_height/3) + (tab_width/2) - (textx/2), + tab_y + tab_height - texty - 2); + + *out_rect = wxRect(tab_x, tab_y, tab_width, tab_height); + *x_extent = tab_width - (tab_height/2) - 1; +} + + +void wxDefaultTabArt::SetNormalFont(const wxFont& font) +{ + m_normal_font = font; +} + +void wxDefaultTabArt::SetSelectedFont(const wxFont& font) +{ + m_selected_font = font; +} + +void wxDefaultTabArt::SetMeasuringFont(const wxFont& font) +{ + m_measuring_font = 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_art = new wxDefaultTabArt; +} + wxAuiTabContainer::~wxAuiTabContainer() { + delete m_art; +} + +void wxAuiTabContainer::SetArtProvider(wxTabArt* art) +{ + delete m_art; + m_art = art; +} + +wxTabArt* wxAuiTabContainer::GetArtProvider() +{ + return m_art; } void wxAuiTabContainer::SetNormalFont(const wxFont& font) { - m_normal_font = font; + m_art->SetNormalFont(font); } void wxAuiTabContainer::SetSelectedFont(const wxFont& font) { - m_selected_font = font; + m_art->SetSelectedFont(font); } void wxAuiTabContainer::SetMeasuringFont(const wxFont& font) { - m_measuring_font = font; + m_art->SetMeasuringFont(font); } void wxAuiTabContainer::SetRect(const wxRect& rect) @@ -159,7 +324,7 @@ bool wxAuiTabContainer::AddPage(wxWindow* page, wxAuiNotebookPage page_info; page_info = info; page_info.window = page; - + m_pages.Add(page_info); return true; @@ -172,7 +337,7 @@ bool wxAuiTabContainer::InsertPage(wxWindow* page, wxAuiNotebookPage page_info; page_info = info; page_info.window = page; - + if (idx >= m_pages.GetCount()) m_pages.Add(page_info); else @@ -193,14 +358,14 @@ bool wxAuiTabContainer::RemovePage(wxWindow* wnd) 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) { @@ -215,7 +380,7 @@ bool wxAuiTabContainer::SetActivePage(wxWindow* wnd) page.active = false; } } - + return found; } @@ -233,10 +398,10 @@ 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(); @@ -246,7 +411,7 @@ int wxAuiTabContainer::GetActivePage() const if (page.active) return i; } - + return -1; } @@ -254,7 +419,7 @@ wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const { if (idx >= m_pages.GetCount()) return NULL; - + return m_pages[idx].window; } @@ -287,202 +452,134 @@ size_t wxAuiTabContainer::GetPageCount() const return m_pages.GetCount(); } -void wxAuiTabContainer::AddButton(int id, const wxBitmap& bmp) +void wxAuiTabContainer::AddButton(int id, int location, const wxBitmap& bmp) { wxAuiTabContainerButton button; button.id = id; button.bitmap = bmp; + button.location = location; button.cur_state = wxAUI_BUTTON_STATE_NORMAL; - + m_buttons.Add(button); } -// DrawTab() draws an individual tab. -// As it is virtual it may be overridden. -// -// 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 wxAuiTabContainer::DrawTab(wxDC* dc, - const wxRect& in_rect, - const wxString& caption, - bool active, - wxRect* out_rect, - int* x_extent) -{ - wxCoord normal_textx, normal_texty; - wxCoord selected_textx, selected_texty; - wxCoord measured_textx, measured_texty; - wxCoord textx, texty; - - - // measure text - dc->SetFont(m_measuring_font); - dc->GetTextExtent(caption, &measured_textx, &measured_texty); - - dc->SetFont(m_selected_font); - dc->GetTextExtent(caption, &selected_textx, &selected_texty); - - dc->SetFont(m_normal_font); - dc->GetTextExtent(caption, &normal_textx, &normal_texty); - - - wxCoord tab_height = measured_texty + 4; - wxCoord tab_width = measured_textx + tab_height + 5; - wxCoord tab_x = in_rect.x; - wxCoord tab_y = in_rect.y + in_rect.height - tab_height; - - - // select pen, brush and font for the tab to be drawn - - if (active) - { - dc->SetPen(m_selected_bkpen); - dc->SetBrush(m_selected_bkbrush); - dc->SetFont(m_selected_font); - textx = selected_textx; - texty = selected_texty; - } - else - { - dc->SetPen(m_normal_bkpen); - dc->SetBrush(m_normal_bkbrush); - dc->SetFont(m_normal_font); - 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->DrawPolygon(6, points); - - dc->SetPen(*wxGREY_PEN); - - //dc->DrawLines(active ? 6 : 7, points); - dc->DrawLines(7, points); - - // -- draw text -- - - dc->DrawText(caption, - tab_x + (tab_height/3) + (tab_width/2) - (textx/2), - tab_y + tab_height - texty - 2); - - *out_rect = wxRect(tab_x, tab_y, tab_width, tab_height); - *x_extent = tab_width - (tab_height/2) - 1; -} - - // 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) -{ +{ wxMemoryDC dc; wxBitmap bmp; bmp.Create(m_rect.GetWidth(), m_rect.GetHeight()); dc.SelectObject(bmp); - - // draw background - dc.SetBrush(m_bkbrush); - dc.SetPen(*wxTRANSPARENT_PEN); - dc.DrawRectangle(-1, -1, m_rect.GetWidth()+2, m_rect.GetHeight()+2); - - // draw base line - dc.SetPen(*wxGREY_PEN); - dc.DrawLine(0, m_rect.GetHeight()-1, m_rect.GetWidth(), m_rect.GetHeight()-1); - - - size_t i, page_count = m_pages.GetCount(); + + m_art->DrawBackground(&dc, m_rect); + int offset = 0; + size_t i; + + // draw the buttons on the right side + offset = m_rect.x + m_rect.width; + size_t button_count = m_buttons.GetCount(); + for (i = 0; i < button_count; ++i) + { + wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1); + + if (button.location != wxRIGHT) + continue; + + wxRect button_rect(offset - button.bitmap.GetWidth(), 1, + button.bitmap.GetWidth(), button.bitmap.GetHeight()); + + button.rect = button_rect; + + DrawButton(dc, button.rect, button.bitmap, + //m_bkbrush.GetColour(), + *wxWHITE, + button.cur_state); + + offset -= button.bitmap.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; + + wxRect button_rect(offset, 1, + button.bitmap.GetWidth(), + button.bitmap.GetHeight()); + + button.rect = button_rect; + + DrawButton(dc, button.rect, button.bitmap, + //m_bkbrush.GetColour(), + *wxWHITE, + button.cur_state); + + offset += button.bitmap.GetWidth(); + } + + + // draw the tabs + size_t page_count = m_pages.GetCount(); size_t active = 999; int active_offset = 0; - + int x_extent = 0; wxRect rect = m_rect; rect.y = 0; rect.width = 1000; rect.height = m_rect.height; - + for (i = 0; i < page_count; ++i) { wxAuiNotebookPage& page = m_pages.Item(i); - + rect.x = offset; - - DrawTab(&dc, + + m_art->DrawTab(&dc, rect, page.caption, page.active, &page.rect, &x_extent); - + if (page.active) { active = i; active_offset = offset; } - + offset += x_extent; } - + // draw the active tab again so it stands in the foreground if (active < m_pages.GetCount()) { wxAuiNotebookPage& page = m_pages.Item(active); rect.x = active_offset; - DrawTab(&dc, + m_art->DrawTab(&dc, rect, page.caption, page.active, &page.rect, &x_extent); } - - // draw the buttons - offset = m_rect.x + m_rect.width; - size_t button_count = m_buttons.GetCount(); - for (i = 0; i < button_count; ++i) - { - wxAuiTabContainerButton& button = m_buttons.Item(button_count - i - 1); - - wxRect button_rect(offset - button.bitmap.GetWidth(), 1, - button.bitmap.GetWidth(), button.bitmap.GetHeight()); - - button.rect = button_rect; - - DrawButton(dc, button.rect, button.bitmap, - m_bkbrush.GetColour(), - button.cur_state); - - offset -= button.bitmap.GetWidth(); - } - - + + raw_dc->Blit(m_rect.x, m_rect.y, m_rect.GetWidth(), m_rect.GetHeight(), &dc, 0, 0); } @@ -492,21 +589,21 @@ void wxAuiTabContainer::Render(wxDC* raw_dc) // true if a tab was hit, otherwise false bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const { - if (!m_rect.Inside(x,y)) + if (!m_rect.Contains(x,y)) return false; - + size_t i, page_count = m_pages.GetCount(); - + for (i = 0; i < page_count; ++i) { wxAuiNotebookPage& page = m_pages.Item(i); - if (page.rect.Inside(x,y)) + if (page.rect.Contains(x,y)) { *hit = page.window; return true; } } - + return false; } @@ -515,21 +612,21 @@ bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const bool wxAuiTabContainer::ButtonHitTest(int x, int y, wxAuiTabContainerButton** hit) const { - if (!m_rect.Inside(x,y)) + if (!m_rect.Contains(x,y)) return false; - + size_t i, button_count = m_buttons.GetCount(); - + for (i = 0; i < button_count; ++i) { wxAuiTabContainerButton& button = m_buttons.Item(i); - if (button.rect.Inside(x,y)) + if (button.rect.Contains(x,y)) { *hit = &button; return true; } } - + return false; } @@ -603,28 +700,40 @@ wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, - long style) : wxControl(parent, id, pos, size, style) + long style) : wxControl(parent, id, pos, size, style) { m_click_pt = wxDefaultPosition; m_is_dragging = false; m_hover_button = NULL; - - // copied from dockart-- needs to put in a common place + + // FIXME: copied from dockart-- needs to put in a common place +#if defined( __WXMAC__ ) + static unsigned char close_bits[]={ + 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3, + 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3, + 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF }; +#elif defined( __WXGTK__) + static unsigned char close_bits[]={ + 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8, + 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef, + 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#else static unsigned char close_bits[]={ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9, 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; - - AddButton(101, BitmapFromBits(close_bits, 16, 16, *wxBLACK)); +#endif + + AddButton(101, wxRIGHT, BitmapFromBits(close_bits, 16, 16, *wxBLACK)); } void wxAuiTabCtrl::OnPaint(wxPaintEvent&) { wxPaintDC dc(this); - + dc.SetFont(GetFont()); - + if (GetPageCount() > 0) Render(&dc); } @@ -646,7 +755,7 @@ void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt) m_click_pt = wxDefaultPosition; m_is_dragging = false; m_click_tab = -1; - + wxWindow* wnd; if (TabHitTest(evt.m_x, evt.m_y, &wnd)) { @@ -655,12 +764,12 @@ void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt) e.SetOldSelection(GetActivePage()); e.SetEventObject(this); GetEventHandler()->ProcessEvent(e); - + m_click_pt.x = evt.m_x; m_click_pt.y = evt.m_y; m_click_tab = e.GetSelection(); } - + if (m_hover_button) { m_hover_button->cur_state = wxAUI_BUTTON_STATE_PRESSED; @@ -673,7 +782,7 @@ void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&) { if (GetCapture() == this) ReleaseMouse(); - + if (m_is_dragging) { wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId); @@ -683,19 +792,19 @@ void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&) GetEventHandler()->ProcessEvent(evt); return; } - + if (m_hover_button) { m_hover_button->cur_state = wxAUI_BUTTON_STATE_HOVER; Refresh(); Update(); - + wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId); evt.SetInt(m_hover_button->id); evt.SetEventObject(this); GetEventHandler()->ProcessEvent(evt); } - + m_click_pt = wxDefaultPosition; m_is_dragging = false; m_click_tab = -1; @@ -709,6 +818,14 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt) wxAuiTabContainerButton* button; if (ButtonHitTest(pos.x, pos.y, &button)) { + if (m_hover_button && button != m_hover_button) + { + m_hover_button->cur_state = wxAUI_BUTTON_STATE_NORMAL; + m_hover_button = NULL; + Refresh(); + Update(); + } + if (button->cur_state != wxAUI_BUTTON_STATE_HOVER) { button->cur_state = wxAUI_BUTTON_STATE_HOVER; @@ -728,11 +845,11 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt) Update(); } } - - + + if (!evt.LeftIsDown() || m_click_pt == wxDefaultPosition) return; - + if (m_is_dragging) { wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId); @@ -741,9 +858,9 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt) evt.SetEventObject(this); GetEventHandler()->ProcessEvent(evt); return; - } - - + } + + int drag_x_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_X); int drag_y_threshold = wxSystemSettings::GetMetric(wxSYS_DRAG_Y); @@ -755,7 +872,7 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt) evt.SetOldSelection(m_click_tab); evt.SetEventObject(this); GetEventHandler()->ProcessEvent(evt); - + m_is_dragging = true; } } @@ -790,12 +907,12 @@ public: m_rect = wxRect(0,0,200,200); m_tab_ctrl_height = 20; } - + void SetTabCtrlHeight(int h) { m_tab_ctrl_height = h; } - + void DoSetSize(int x, int y, int width, int height, int WXUNUSED(sizeFlags = wxSIZE_AUTO)) @@ -803,7 +920,7 @@ public: m_rect = wxRect(x, y, width, height); DoSizing(); } - + void DoGetClientSize(int* x, int* y) const { *x = m_rect.width; @@ -811,26 +928,27 @@ public: } bool Show( bool WXUNUSED(show = true) ) { return false; } - + void DoSizing() { if (!m_tabs) return; - + int tab_height = wxMin(m_rect.height, m_tab_ctrl_height); m_tab_rect = wxRect(m_rect.x, m_rect.y, m_rect.width, tab_height); m_tabs->SetSize(m_rect.x, m_rect.y, m_rect.width, tab_height); m_tabs->SetRect(wxRect(0, 0, m_rect.width, tab_height)); m_tabs->Refresh(); - + m_tabs->Update(); + wxAuiNotebookPageArray& pages = m_tabs->GetPages(); size_t i, page_count = pages.GetCount(); - + for (i = 0; i < page_count; ++i) { wxAuiNotebookPage& page = pages.Item(i); page.window->SetSize(m_rect.x, m_rect.y+tab_height, m_rect.width, m_rect.height-tab_height); - + if (page.window->IsKindOf(CLASSINFO(wxTabMDIChildFrame))) { wxTabMDIChildFrame* wnd = (wxTabMDIChildFrame*)page.window; @@ -846,12 +964,12 @@ public: if (y) *y = m_rect.GetHeight(); } - + void Update() { // does nothing } - + public: wxRect m_rect; @@ -876,10 +994,10 @@ BEGIN_EVENT_TABLE(wxAuiMultiNotebook, wxControl) wxAuiMultiNotebook::OnTabClicked) EVT_COMMAND_RANGE(10000, 10100, wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, - wxAuiMultiNotebook::OnTabBeginDrag) + wxAuiMultiNotebook::OnTabBeginDrag) EVT_COMMAND_RANGE(10000, 10100, wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, - wxAuiMultiNotebook::OnTabEndDrag) + wxAuiMultiNotebook::OnTabEndDrag) EVT_COMMAND_RANGE(10000, 10100, wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, wxAuiMultiNotebook::OnTabDragMotion) @@ -913,9 +1031,9 @@ bool wxAuiMultiNotebook::Create(wxWindow* parent, { if (!wxControl::Create(parent, id, pos, size, style)) return false; - + InitNotebook(); - + return true; } @@ -927,27 +1045,27 @@ void wxAuiMultiNotebook::InitNotebook() m_tab_id_counter = 10000; m_dummy_wnd = NULL; m_tab_ctrl_height = 20; - + m_normal_font = *wxNORMAL_FONT; m_selected_font = *wxNORMAL_FONT; m_selected_font.SetWeight(wxBOLD); - + // choose a default for the tab height wxClientDC dc(this); int tx, ty; dc.SetFont(m_selected_font); dc.GetTextExtent(wxT("ABCDEFGHhijklm"), &tx, &ty); m_tab_ctrl_height = (ty*150)/100; - - m_dummy_wnd = new wxWindow(this, -1, wxPoint(0,0), wxSize(0,0)); + + m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0)); m_dummy_wnd->SetSize(200, 200); m_dummy_wnd->Show(false); - + m_mgr.SetManagedWindow(this); - + m_mgr.AddPane(m_dummy_wnd, wxPaneInfo().Name(wxT("dummy")).Bottom().Show(false)); - + m_mgr.Update(); } @@ -956,6 +1074,16 @@ wxAuiMultiNotebook::~wxAuiMultiNotebook() m_mgr.UnInit(); } +void wxAuiMultiNotebook::SetArtProvider(wxTabArt* art) +{ + m_tabs.SetArtProvider(art); +} + +wxTabArt* wxAuiMultiNotebook::GetArtProvider() +{ + return m_tabs.GetArtProvider(); +} + bool wxAuiMultiNotebook::AddPage(wxWindow* page, const wxString& caption, bool select, @@ -963,7 +1091,7 @@ bool wxAuiMultiNotebook::AddPage(wxWindow* page, { return InsertPage(GetPageCount(), page, caption, select, bitmap); } - + bool wxAuiMultiNotebook::InsertPage(size_t page_idx, wxWindow* page, const wxString& caption, @@ -988,18 +1116,18 @@ bool wxAuiMultiNotebook::InsertPage(size_t page_idx, active_tabctrl->AddPage(page, info); else active_tabctrl->InsertPage(page, info, page_idx); - + DoSizing(); active_tabctrl->DoShowHide(); - + if (select) { int idx = m_tabs.GetIdxFromWindow(page); wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiMultiNotebook::InsertPage()")); - + SetSelection(idx); } - + return true; } @@ -1007,57 +1135,48 @@ bool wxAuiMultiNotebook::InsertPage(size_t page_idx, // DeletePage() removes a tab from the multi-notebook, // and destroys the window as well bool wxAuiMultiNotebook::DeletePage(size_t page_idx) -{ - wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx); - - +{ + wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx); + wxWindow* new_active = NULL; + // find out which onscreen tab ctrl owns this tab wxAuiTabCtrl* ctrl; int ctrl_idx; if (!FindTab(wnd, &ctrl, &ctrl_idx)) return false; - + // find a new page and set it as active int new_idx = ctrl_idx+1; if (new_idx >= (int)ctrl->GetPageCount()) new_idx = ctrl_idx-1; - + if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount()) { - wxWindow* new_wnd = ctrl->GetWindowFromIdx(new_idx); - int main_idx = m_tabs.GetIdxFromWindow(new_wnd); - wxASSERT(main_idx != -1); - SetSelection(main_idx); + new_active = ctrl->GetWindowFromIdx(new_idx); } else { // set the active page to the first page that // isn't the one being deleted - bool found = false; size_t i, page_count = m_tabs.GetPageCount(); for (i = 0; i < page_count; ++i) { wxWindow* w = m_tabs.GetWindowFromIdx(i); if (wnd != w) { - found = true; - SetSelection(i); + new_active = m_tabs.GetWindowFromIdx(i); break; } } - - if (!found) - m_curpage = -1; } - - + // remove the tab from main catalog if (!m_tabs.RemovePage(wnd)) return false; - + // remove the tab from the onscreen tab ctrl ctrl->RemovePage(wnd); - + // actually destroy the window now if (wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame))) { @@ -1070,9 +1189,16 @@ bool wxAuiMultiNotebook::DeletePage(size_t page_idx) { wnd->Destroy(); } - + RemoveEmptyTabFrames(); - + + // set new active pane + if (new_active) + { + m_curpage = -1; + SetSelection(m_tabs.GetIdxFromWindow(new_active)); + } + return true; } @@ -1086,7 +1212,7 @@ bool wxAuiMultiNotebook::RemovePage(size_t page_idx) wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx); if (!m_tabs.RemovePage(wnd)) return false; - + // remove the tab from the onscreen tab ctrl wxAuiTabCtrl* ctrl; int ctrl_idx; @@ -1095,20 +1221,20 @@ bool wxAuiMultiNotebook::RemovePage(size_t page_idx) ctrl->RemovePage(wnd); return true; } - + return false; } // SetPageText() changes the tab caption of the specified page bool wxAuiMultiNotebook::SetPageText(size_t page_idx, const wxString& text) -{ +{ if (page_idx >= m_tabs.GetPageCount()) return false; - + // update our own tab catalog wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx); page_info.caption = text; - + // update what's on screen wxAuiTabCtrl* ctrl; int ctrl_idx; @@ -1117,9 +1243,9 @@ bool wxAuiMultiNotebook::SetPageText(size_t page_idx, const wxString& text) wxAuiNotebookPage& info = ctrl->GetPage(ctrl_idx); info.caption = text; ctrl->Refresh(); + ctrl->Update(); } - - + return true; } @@ -1135,7 +1261,7 @@ size_t wxAuiMultiNotebook::SetSelection(size_t new_page) wxWindow* wnd = m_tabs.GetWindowFromIdx(new_page); if (!wnd) return m_curpage; - + wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, m_windowId); evt.SetSelection(new_page); evt.SetOldSelection(m_curpage); @@ -1151,13 +1277,13 @@ size_t wxAuiMultiNotebook::SetSelection(size_t new_page) wxAuiTabCtrl* ctrl; int ctrl_idx; if (FindTab(wnd, &ctrl, &ctrl_idx)) - { + { m_tabs.SetActivePage(wnd); - + ctrl->SetActivePage(ctrl_idx); DoSizing(); ctrl->DoShowHide(); - + int old_curpage = m_curpage; m_curpage = new_page; @@ -1179,7 +1305,7 @@ size_t wxAuiMultiNotebook::SetSelection(size_t new_page) } wnd->SetFocus(); - + return old_curpage; } } @@ -1199,7 +1325,7 @@ size_t wxAuiMultiNotebook::GetPageCount() const wxWindow* wxAuiMultiNotebook::GetPage(size_t page_idx) const { wxASSERT(page_idx < m_tabs.GetPageCount()); - + return m_tabs.GetWindowFromIdx(page_idx); } @@ -1226,15 +1352,15 @@ wxAuiTabCtrl* wxAuiMultiNotebook::GetActiveTabCtrl() { wxAuiTabCtrl* ctrl; int idx; - + // find the tab ctrl with the current page if (FindTab(m_tabs.GetPage(m_curpage).window, &ctrl, &idx)) - { + { return ctrl; } } - + // no current page, just find the first tab ctrl wxPaneInfoArray& all_panes = m_mgr.GetAllPanes(); size_t i, pane_count = all_panes.GetCount(); @@ -1242,11 +1368,11 @@ wxAuiTabCtrl* wxAuiMultiNotebook::GetActiveTabCtrl() { if (all_panes.Item(i).name == wxT("dummy")) continue; - + wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window; return tabframe->m_tabs; } - + // If there is no tabframe at all, create one wxTabFrame* tabframe = new wxTabFrame; tabframe->SetTabCtrlHeight(m_tab_ctrl_height); @@ -1256,10 +1382,10 @@ wxAuiTabCtrl* wxAuiMultiNotebook::GetActiveTabCtrl() wxDefaultSize, wxNO_BORDER); m_mgr.AddPane(tabframe, - wxPaneInfo().Center().CaptionVisible(false)); - + wxPaneInfo().Center().CaptionVisible(false)); + m_mgr.Update(); - + return tabframe->m_tabs; } @@ -1274,9 +1400,9 @@ bool wxAuiMultiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx) { if (all_panes.Item(i).name == wxT("dummy")) continue; - + wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window; - + int page_idx = tabframe->m_tabs->GetIdxFromWindow(page); if (page_idx != -1) { @@ -1285,7 +1411,7 @@ bool wxAuiMultiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx) return true; } } - + return false; } @@ -1301,16 +1427,16 @@ void wxAuiMultiNotebook::OnSize(wxSizeEvent&) void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent& command_evt) { wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt; - + wxAuiTabCtrl* ctrl = (wxAuiTabCtrl*)evt.GetEventObject(); wxASSERT(ctrl != NULL); - + wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection()); wxASSERT(wnd != NULL); - + int idx = m_tabs.GetIdxFromWindow(wnd); wxASSERT(idx != -1); - + SetSelection(idx); } @@ -1323,9 +1449,9 @@ void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt) wxPoint screen_pt = ::wxGetMousePosition(); wxPoint client_pt = ScreenToClient(screen_pt); wxPoint zero(0,0); - + wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - + wxAuiTabCtrl* tab_ctrl = GetTabCtrlFromPoint(client_pt); if (tab_ctrl == src_tabs) { @@ -1333,7 +1459,7 @@ void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt) m_mgr.HideHint(); return; } - + if (tab_ctrl) { wxRect hint_rect = tab_ctrl->GetRect(); @@ -1353,7 +1479,7 @@ void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt) wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt; m_mgr.HideHint(); - + // get the mouse position, which will be used to determine the drop point wxPoint mouse_screen_pt = ::wxGetMousePosition(); @@ -1363,7 +1489,7 @@ void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt) // the src tab control is the control that fired this event wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject(); wxAuiTabCtrl* dest_tabs = NULL; - + // If the pointer is in an existing tab frame, do a tab insert wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt); @@ -1371,7 +1497,7 @@ void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt) if (tab_frame) { dest_tabs = tab_frame->m_tabs; - + if (dest_tabs == src_tabs) return; } @@ -1391,9 +1517,9 @@ void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt) m_mgr.Update(); dest_tabs = new_tabs->m_tabs; } - - - + + + // remove the page from the source tabs wxAuiNotebookPage page_info = src_tabs->GetPage(evt.GetSelection()); page_info.active = false; @@ -1405,16 +1531,16 @@ void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt) src_tabs->Refresh(); } - - + + // add the page to the destination tabs dest_tabs->AddPage(page_info.window, page_info); - + if (src_tabs->GetPageCount() == 0) - { + { RemoveEmptyTabFrames(); } - + DoSizing(); dest_tabs->DoShowHide(); dest_tabs->Refresh(); @@ -1432,12 +1558,12 @@ wxAuiTabCtrl* wxAuiMultiNotebook::GetTabCtrlFromPoint(const wxPoint& pt) { if (all_panes.Item(i).name == wxT("dummy")) continue; - + wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window; - if (tabframe->m_tab_rect.Inside(pt)) + if (tabframe->m_tab_rect.Contains(pt)) return tabframe->m_tabs; } - + return NULL; } @@ -1451,21 +1577,21 @@ wxWindow* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl) { if (all_panes.Item(i).name == wxT("dummy")) continue; - + wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window; if (tabframe->m_tabs == tab_ctrl) { return tabframe; } } - + return NULL; } void wxAuiMultiNotebook::RemoveEmptyTabFrames() { bool must_update = false; - + // if we've just removed the last tab from the source // tab set, the remove the tab control completely wxPaneInfoArray all_panes = m_mgr.GetAllPanes(); @@ -1479,19 +1605,19 @@ void wxAuiMultiNotebook::RemoveEmptyTabFrames() if (tab_frame->m_tabs->GetPageCount() == 0) { m_mgr.DetachPane(tab_frame); - + // use pending delete because sometimes during // window closing, refreshs are pending if (!wxPendingDelete.Member(tab_frame->m_tabs)) - wxPendingDelete.Append(tab_frame->m_tabs); + wxPendingDelete.Append(tab_frame->m_tabs); //tab_frame->m_tabs->Destroy(); - + delete tab_frame; must_update = true; } } - - + + // check to see if there is still a center pane; // if there isn't, make a frame the center pane wxPaneInfoArray panes = m_mgr.GetAllPanes(); @@ -1514,7 +1640,7 @@ void wxAuiMultiNotebook::RemoveEmptyTabFrames() must_update = true; } - m_mgr.Update(); + m_mgr.Update(); } void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent& evt) @@ -1522,7 +1648,7 @@ void wxAuiMultiNotebook::OnChildFocus(wxChildFocusEvent& evt) int idx = m_tabs.GetIdxFromWindow(evt.GetWindow()); if (idx != -1 && idx != m_curpage) { - SetSelection(idx); + SetSelection(idx); } } @@ -1531,17 +1657,17 @@ void wxAuiMultiNotebook::OnTabButton(wxCommandEvent& command_evt) { wxAuiNotebookEvent& evt = (wxAuiNotebookEvent&)command_evt; wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - + int button_id = evt.GetInt(); - + if (button_id == wxAuiButtonClose) { int selection = tabs->GetActivePage(); - + if (selection != -1) { wxWindow* close_wnd = tabs->GetWindowFromIdx(selection); - + if (close_wnd->IsKindOf(CLASSINFO(wxTabMDIChildFrame))) { close_wnd->Close();