X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ae4558e051de18f4a66af89be36d88411645c0a9..7bb82a7415a0fae8b691611665593e8550a7bcf7:/src/aui/auibook.cpp?ds=sidebyside diff --git a/src/aui/auibook.cpp b/src/aui/auibook.cpp index 12511fae34..6de8fcede5 100644 --- a/src/aui/auibook.cpp +++ b/src/aui/auibook.cpp @@ -45,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 @@ -80,7 +71,7 @@ static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h, return wxBitmap(img); } -static void DrawButton(wxDC& dc, +static void DrawButtonS(wxDC& dc, const wxRect& _rect, const wxBitmap& bmp, const wxColour& bkcolour, @@ -111,7 +102,10 @@ static void DrawButton(wxDC& dc, -wxAuiTabContainer::wxAuiTabContainer() + +// -- wxDefaultTabArt class implementation -- + +wxDefaultTabArt::wxDefaultTabArt() { m_normal_font = *wxNORMAL_FONT; m_selected_font = *wxNORMAL_FONT; @@ -129,25 +123,325 @@ wxAuiTabContainer::wxAuiTabContainer() m_normal_bkpen = wxPen(normaltab_colour); m_selected_bkbrush = wxBrush(selectedtab_colour); m_selected_bkpen = wxPen(selectedtab_colour); + + +#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}; +#endif + + static unsigned char left_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0xfe, + 0x1f, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x3f, 0xfe, 0x7f, 0xfe, 0xff, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + static unsigned char right_bits[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x9f, 0xff, 0x1f, 0xff, + 0x1f, 0xfe, 0x1f, 0xfc, 0x1f, 0xfe, 0x1f, 0xff, 0x9f, 0xff, 0xdf, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + m_active_close_bmp = BitmapFromBits(close_bits, 16, 16, *wxBLACK); + m_disabled_close_bmp = BitmapFromBits(close_bits, 16, 16, wxColour(128,128,128)); + + m_active_left_bmp = BitmapFromBits(left_bits, 16, 16, *wxBLACK); + m_disabled_left_bmp = BitmapFromBits(left_bits, 16, 16, wxColour(128,128,128)); + + m_active_right_bmp = BitmapFromBits(right_bits, 16, 16, *wxBLACK); + m_disabled_right_bmp = BitmapFromBits(right_bits, 16, 16, wxColour(128,128,128)); +} + +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 textx, texty; + + // if the caption is empty, measure some temporary text + wxString caption = caption_text; + if (caption_text.empty()) + caption = wxT("Xj"); + + dc->SetFont(m_selected_font); + dc->GetTextExtent(caption, &selected_textx, &selected_texty); + + dc->SetFont(m_normal_font); + dc->GetTextExtent(caption, &normal_textx, &normal_texty); + + // figure out the size of the tab + wxSize tab_size = GetTabSize(dc, caption, active, 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; + + // 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)/2 - (texty/2) + 1); + + *out_rect = wxRect(tab_x, tab_y, tab_width, tab_height); +} + + +wxSize wxDefaultTabArt::GetTabSize(wxDC* dc, + const wxString& caption, + bool WXUNUSED(active), + int* x_extent) +{ + wxCoord measured_textx, measured_texty; + + dc->SetFont(m_measuring_font); + dc->GetTextExtent(caption, &measured_textx, &measured_texty); + + wxCoord tab_height = measured_texty + 4; + wxCoord tab_width = measured_textx + tab_height + 5; + + *x_extent = tab_width - (tab_height/2) - 1; + + return wxSize(tab_width, tab_height); +} + + +void wxDefaultTabArt::DrawButton( + wxDC* dc, + const wxRect& in_rect, + int bitmap_id, + int button_state, + int orientation, + const wxBitmap& bitmap_override, + wxRect* out_rect) +{ + wxBitmap bmp; + wxRect rect; + + if (bitmap_override.IsOk()) + { + bmp = bitmap_override; + } + else + { + switch (bitmap_id) + { + case wxAUI_BUTTON_CLOSE: + if (button_state & wxAUI_BUTTON_STATE_DISABLED) + bmp = m_disabled_close_bmp; + else + bmp = m_active_close_bmp; + break; + case wxAUI_BUTTON_LEFT: + if (button_state & wxAUI_BUTTON_STATE_DISABLED) + bmp = m_disabled_left_bmp; + else + bmp = m_active_left_bmp; + break; + case wxAUI_BUTTON_RIGHT: + if (button_state & wxAUI_BUTTON_STATE_DISABLED) + bmp = m_disabled_right_bmp; + else + bmp = m_active_right_bmp; + 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 wxDefaultTabArt::GetBestTabCtrlSize(wxWindow* wnd) +{ + wxClientDC dc(wnd); + dc.SetFont(m_measuring_font); + int x_ext = 0; + wxSize s = GetTabSize(&dc, wxT("ABCDEFGHIj"), true, &x_ext); + return s.y+3; +} + +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_tab_offset = 0; + m_art = new wxDefaultTabArt; + + AddButton(wxAUI_BUTTON_LEFT, wxLEFT); + AddButton(wxAUI_BUTTON_RIGHT, wxRIGHT); + AddButton(wxAUI_BUTTON_CLOSE, wxRIGHT); } 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) @@ -183,6 +477,25 @@ bool wxAuiTabContainer::InsertPage(wxWindow* page, 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(); @@ -289,142 +602,193 @@ 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& normal_bitmap, + const wxBitmap& disabled_bitmap) { wxAuiTabContainerButton button; button.id = id; - button.bitmap = bmp; + button.bitmap = normal_bitmap; + button.dis_bitmap = disabled_bitmap; + 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_text, - bool active, - wxRect* out_rect, - int* x_extent) +size_t wxAuiTabContainer::GetTabOffset() const { - 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); + return m_tab_offset; +} - caption = caption_text; +void wxAuiTabContainer::SetTabOffset(size_t offset) +{ + m_tab_offset = offset; +} - 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; +// 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; + 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); - // select pen, brush and font for the tab to be drawn - if (active) + // 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) { - dc->SetPen(m_selected_bkpen); - dc->SetBrush(m_selected_bkbrush); - dc->SetFont(m_selected_font); - textx = selected_textx; - texty = selected_texty; + wxAuiNotebookPage& page = m_pages.Item(i); + int x_extent = 0; + wxSize size = m_art->GetTabSize(&dc, page.caption, page.active, &x_extent); + + if (i+1 < page_count) + total_width += x_extent; + else + total_width += size.x; + + if (i >= m_tab_offset) + { + if (i+1 < page_count) + visible_width += x_extent; + else + visible_width += size.x; + } + } + + if (total_width > m_rect.GetWidth() - 20 || m_tab_offset != 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.cur_state &= ~wxAUI_BUTTON_STATE_HIDDEN; + } + } } else { - dc->SetPen(m_normal_bkpen); - dc->SetBrush(m_normal_bkbrush); - dc->SetFont(m_normal_font); - textx = normal_textx; - texty = normal_texty; + // 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.cur_state |= 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_tab_offset == 0) + button.cur_state |= wxAUI_BUTTON_STATE_DISABLED; + else + button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED; + } + if (button.id == wxAUI_BUTTON_RIGHT) + { + if (visible_width < m_rect.GetWidth() - ((int)button_count*16)) + button.cur_state |= wxAUI_BUTTON_STATE_DISABLED; + else + button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED; + } + } - // -- 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); + // draw background + m_art->DrawBackground(&dc, m_rect); - *out_rect = wxRect(tab_x, tab_y, tab_width, tab_height); - *x_extent = tab_width - (tab_height/2) - 1; -} + // 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.cur_state & wxAUI_BUTTON_STATE_HIDDEN) + continue; + + wxRect button_rect = m_rect; + button_rect.SetY(1); + button_rect.SetWidth(offset); + + m_art->DrawButton(&dc, + button_rect, + button.id, + button.cur_state, + wxRIGHT, + wxNullBitmap, + &button.rect); + + offset -= button.rect.GetWidth(); + right_buttons_width += button.rect.GetWidth(); + } -// 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); + 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.cur_state & wxAUI_BUTTON_STATE_HIDDEN) + continue; + + wxRect button_rect(offset, 1, 1000, m_rect.height); + + m_art->DrawButton(&dc, + button_rect, + button.id, + button.cur_state, + wxLEFT, + wxNullBitmap, + &button.rect); + + offset += button.rect.GetWidth(); + left_buttons_width += button.rect.GetWidth(); + } - size_t i, page_count = m_pages.GetCount(); - int offset = 0; + offset = left_buttons_width; + + + dc.SetClippingRegion(left_buttons_width, 0, + m_rect.GetWidth() - right_buttons_width - left_buttons_width - 2, + m_rect.GetHeight()); + + // draw the tabs size_t active = 999; int active_offset = 0; @@ -435,13 +799,13 @@ void wxAuiTabContainer::Render(wxDC* raw_dc) rect.width = 1000; rect.height = m_rect.height; - for (i = 0; i < page_count; ++i) + for (i = m_tab_offset; i < page_count; ++i) { wxAuiNotebookPage& page = m_pages.Item(i); rect.x = offset; - DrawTab(&dc, + m_art->DrawTab(&dc, rect, page.caption, page.active, @@ -458,12 +822,12 @@ void wxAuiTabContainer::Render(wxDC* raw_dc) } // draw the active tab again so it stands in the foreground - if (active < m_pages.GetCount()) + if (active >= m_tab_offset && 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, @@ -471,27 +835,11 @@ void wxAuiTabContainer::Render(wxDC* raw_dc) &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); + dc.DestroyClippingRegion(); + + raw_dc->Blit(m_rect.x, m_rect.y, + m_rect.GetWidth(), m_rect.GetHeight(), + &dc, 0, 0); } @@ -502,15 +850,19 @@ bool wxAuiTabContainer::TabHitTest(int x, int y, wxWindow** hit) const { if (!m_rect.Contains(x,y)) return false; + + if (ButtonHitTest(x, y, NULL)) + return false; size_t i, page_count = m_pages.GetCount(); - for (i = 0; i < page_count; ++i) + for (i = m_tab_offset; i < page_count; ++i) { wxAuiNotebookPage& page = m_pages.Item(i); if (page.rect.Contains(x,y)) { - *hit = page.window; + if (hit) + *hit = page.window; return true; } } @@ -533,7 +885,8 @@ bool wxAuiTabContainer::ButtonHitTest(int x, int y, wxAuiTabContainerButton& button = m_buttons.Item(i); if (button.rect.Contains(x,y)) { - *hit = &button; + if (hit) + *hit = &button; return true; } } @@ -594,7 +947,6 @@ void wxAuiTabContainer::DoShowHide() // -- wxAuiTabCtrl class implementation -- -const int wxAuiButtonClose = 101; BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl) EVT_PAINT(wxAuiTabCtrl::OnPaint) @@ -604,6 +956,7 @@ BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl) EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp) EVT_MOTION(wxAuiTabCtrl::OnMotion) EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow) + EVT_AUINOTEBOOK_BUTTON(-1, wxAuiTabCtrl::OnButton) END_EVENT_TABLE() @@ -616,28 +969,11 @@ wxAuiTabCtrl::wxAuiTabCtrl(wxWindow* parent, m_click_pt = wxDefaultPosition; m_is_dragging = false; m_hover_button = NULL; - - // 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}; -#endif - - AddButton(101, BitmapFromBits(close_bits, 16, 16, *wxBLACK)); } +wxAuiTabCtrl::~wxAuiTabCtrl() +{ +} void wxAuiTabCtrl::OnPaint(wxPaintEvent&) { @@ -665,7 +1001,7 @@ void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt) CaptureMouse(); m_click_pt = wxDefaultPosition; m_is_dragging = false; - m_click_tab = -1; + m_click_tab = NULL; wxWindow* wnd; if (TabHitTest(evt.m_x, evt.m_y, &wnd)) @@ -678,7 +1014,7 @@ void wxAuiTabCtrl::OnLeftDown(wxMouseEvent& evt) m_click_pt.x = evt.m_x; m_click_pt.y = evt.m_y; - m_click_tab = e.GetSelection(); + m_click_tab = wnd; } if (m_hover_button) @@ -697,8 +1033,8 @@ void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&) if (m_is_dragging) { wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId); - evt.SetSelection(m_click_tab); - evt.SetOldSelection(m_click_tab); + evt.SetSelection(GetIdxFromWindow(m_click_tab)); + evt.SetOldSelection(evt.GetSelection()); evt.SetEventObject(this); GetEventHandler()->ProcessEvent(evt); return; @@ -710,15 +1046,18 @@ void wxAuiTabCtrl::OnLeftUp(wxMouseEvent&) Refresh(); Update(); - wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId); - evt.SetInt(m_hover_button->id); - evt.SetEventObject(this); - GetEventHandler()->ProcessEvent(evt); + if (!(m_hover_button->cur_state & wxAUI_BUTTON_STATE_DISABLED)) + { + 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; + m_click_tab = NULL; } void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt) @@ -729,6 +1068,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; @@ -756,8 +1103,8 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt) if (m_is_dragging) { wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, m_windowId); - evt.SetSelection(m_click_tab); - evt.SetOldSelection(m_click_tab); + evt.SetSelection(GetIdxFromWindow(m_click_tab)); + evt.SetOldSelection(evt.GetSelection()); evt.SetEventObject(this); GetEventHandler()->ProcessEvent(evt); return; @@ -771,8 +1118,8 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt) abs(pos.y - m_click_pt.y) > drag_y_threshold) { wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, m_windowId); - evt.SetSelection(m_click_tab); - evt.SetOldSelection(m_click_tab); + evt.SetSelection(GetIdxFromWindow(m_click_tab)); + evt.SetOldSelection(evt.GetSelection()); evt.SetEventObject(this); GetEventHandler()->ProcessEvent(evt); @@ -791,6 +1138,33 @@ void wxAuiTabCtrl::OnLeaveWindow(wxMouseEvent& WXUNUSED(event)) } } +void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event) +{ + int button = event.GetInt(); + + if (button == wxAUI_BUTTON_LEFT || button == wxAUI_BUTTON_RIGHT) + { + if (button == wxAUI_BUTTON_LEFT) + { + if (GetTabOffset() > 0) + { + SetTabOffset(GetTabOffset()-1); + Refresh(); + Update(); + } + } + else + { + SetTabOffset(GetTabOffset()+1); + Refresh(); + Update(); + } + } + else + { + event.Skip(); + } +} // wxTabFrame is an interesting case. It's important that all child pages // of the multi-notebook control are all actually children of that control @@ -954,11 +1328,7 @@ void wxAuiMultiNotebook::InitNotebook() 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_tab_ctrl_height = m_tabs.GetArtProvider()->GetBestTabCtrlSize(this); m_dummy_wnd = new wxWindow(this, wxID_ANY, wxPoint(0,0), wxSize(0,0)); m_dummy_wnd->SetSize(200, 200); @@ -977,6 +1347,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, @@ -1335,6 +1715,7 @@ void wxAuiMultiNotebook::OnTabClicked(wxCommandEvent& command_evt) void wxAuiMultiNotebook::OnTabBeginDrag(wxCommandEvent&) { + m_last_drag_x = 0; } void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt) @@ -1345,17 +1726,46 @@ void wxAuiMultiNotebook::OnTabDragMotion(wxCommandEvent& evt) wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject(); - wxAuiTabCtrl* tab_ctrl = GetTabCtrlFromPoint(client_pt); - if (tab_ctrl == src_tabs) + wxAuiTabCtrl* dest_tabs = GetTabCtrlFromPoint(client_pt); + if (dest_tabs == src_tabs) { - // inner-tabctrl dragging is not yet implemented + // always hide the hint for inner-tabctrl drag m_mgr.HideHint(); + + wxPoint pt = dest_tabs->ScreenToClient(screen_pt); + wxWindow* dest_location_tab; + + // this is an inner-tab drag/reposition + if (dest_tabs->TabHitTest(pt.x, pt.y, &dest_location_tab)) + { + int src_idx = evt.GetSelection(); + int dest_idx = dest_tabs->GetIdxFromWindow(dest_location_tab); + + // prevent jumpy drag + if ((src_idx == dest_idx) || dest_idx == -1 || + (src_idx > dest_idx && m_last_drag_x <= pt.x) || + (src_idx < dest_idx && m_last_drag_x >= pt.x)) + { + m_last_drag_x = pt.x; + return; + } + + + wxWindow* src_tab = dest_tabs->GetWindowFromIdx(src_idx); + dest_tabs->MovePage(src_tab, dest_idx); + dest_tabs->SetActivePage((size_t)dest_idx); + dest_tabs->DoShowHide(); + dest_tabs->Refresh(); + m_last_drag_x = pt.x; + + } + return; } - if (tab_ctrl) + if (dest_tabs) { - wxRect hint_rect = tab_ctrl->GetRect(); + wxRect hint_rect = dest_tabs->GetRect(); ClientToScreen(&hint_rect.x, &hint_rect.y); m_mgr.ShowHint(hint_rect); } @@ -1387,12 +1797,22 @@ void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt) // If the pointer is in an existing tab frame, do a tab insert wxWindow* hit_wnd = ::wxFindWindowAtPoint(mouse_screen_pt); wxTabFrame* tab_frame = (wxTabFrame*)GetTabFrameFromTabCtrl(hit_wnd); + int insert_idx = -1; if (tab_frame) { dest_tabs = tab_frame->m_tabs; if (dest_tabs == src_tabs) return; + + + wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt); + wxWindow* target = NULL; + dest_tabs->TabHitTest(pt.x, pt.y, &target); + if (target) + { + insert_idx = dest_tabs->GetIdxFromWindow(target); + } } else { @@ -1427,7 +1847,9 @@ void wxAuiMultiNotebook::OnTabEndDrag(wxCommandEvent& command_evt) // add the page to the destination tabs - dest_tabs->AddPage(page_info.window, page_info); + if (insert_idx == -1) + insert_idx = dest_tabs->GetPageCount(); + dest_tabs->InsertPage(page_info.window, page_info, insert_idx); if (src_tabs->GetPageCount() == 0) { @@ -1483,8 +1905,6 @@ wxWindow* wxAuiMultiNotebook::GetTabFrameFromTabCtrl(wxWindow* tab_ctrl) 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(); @@ -1506,7 +1926,6 @@ void wxAuiMultiNotebook::RemoveEmptyTabFrames() //tab_frame->m_tabs->Destroy(); delete tab_frame; - must_update = true; } } @@ -1530,7 +1949,6 @@ void wxAuiMultiNotebook::RemoveEmptyTabFrames() if (!center_found && first_good) { m_mgr.GetPane(first_good).Centre(); - must_update = true; } m_mgr.Update(); @@ -1553,7 +1971,7 @@ void wxAuiMultiNotebook::OnTabButton(wxCommandEvent& command_evt) int button_id = evt.GetInt(); - if (button_id == wxAuiButtonClose) + if (button_id == wxAUI_BUTTON_CLOSE) { int selection = tabs->GetActivePage();