]> git.saurik.com Git - wxWidgets.git/blobdiff - src/aui/auibook.cpp
Getting closer to working tree/list wxDataViewCtrl.
[wxWidgets.git] / src / aui / auibook.cpp
index e6baedb46d8084c229c6f12521f96f4b2e7037f1..00d1d073ff278e77f3983e434abe4224c69004c7 100644 (file)
@@ -47,6 +47,10 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN)
 
 
 IMPLEMENT_CLASS(wxAuiNotebook, wxControl)
@@ -230,7 +234,12 @@ wxAuiDefaultTabArt::~wxAuiDefaultTabArt()
 
 wxAuiTabArt* wxAuiDefaultTabArt::Clone()
 {
-    return static_cast<wxAuiTabArt*>(new wxAuiDefaultTabArt);
+    wxAuiDefaultTabArt* art = new wxAuiDefaultTabArt;
+    art->SetNormalFont(m_normal_font);
+    art->SetSelectedFont(m_selected_font);
+    art->SetMeasuringFont(m_measuring_font);
+
+    return art;
 }
 
 void wxAuiDefaultTabArt::SetFlags(unsigned int flags)
@@ -308,7 +317,7 @@ void wxAuiDefaultTabArt::DrawTab(wxDC& dc,
 {
     wxCoord normal_textx, normal_texty;
     wxCoord selected_textx, selected_texty;
-    wxCoord textx, texty;
+    wxCoord texty;
 
     // if the caption is empty, measure some temporary text
     wxString caption = page.caption;
@@ -344,13 +353,11 @@ void wxAuiDefaultTabArt::DrawTab(wxDC& dc,
     if (page.active)
     {
         dc.SetFont(m_selected_font);
-        textx = selected_textx;
         texty = selected_texty;
     }
-     else
+    else
     {
         dc.SetFont(m_normal_font);
-        textx = normal_textx;
         texty = normal_texty;
     }
 
@@ -427,7 +434,7 @@ void wxAuiDefaultTabArt::DrawTab(wxDC& dc,
         wxColor bottom_color = m_base_colour;
         dc.GradientFillLinear(r, bottom_color, top_color, wxNORTH);
     }
-     else
+    else
     {
         // draw inactive tab
 
@@ -465,7 +472,6 @@ void wxAuiDefaultTabArt::DrawTab(wxDC& dc,
     // this gets rid of the top one of those lines in the tab control
     if (page.active)
     {
-        wxColor start_color = m_base_colour;
         dc.SetPen(m_base_colour_pen);
         dc.DrawLine(border_points[0].x+1,
                     border_points[0].y,
@@ -495,7 +501,7 @@ void wxAuiDefaultTabArt::DrawTab(wxDC& dc,
         text_offset = bitmap_offset + page.bitmap.GetWidth();
         text_offset += 3; // bitmap padding
     }
-     else
+    else
     {
         text_offset = tab_x + 8;
     }
@@ -606,25 +612,25 @@ void wxAuiDefaultTabArt::DrawButton(wxDC& dc,
         case wxAUI_BUTTON_CLOSE:
             if (button_state & wxAUI_BUTTON_STATE_DISABLED)
                 bmp = m_disabled_close_bmp;
-                 else
+            else
                 bmp = m_active_close_bmp;
             break;
         case wxAUI_BUTTON_LEFT:
             if (button_state & wxAUI_BUTTON_STATE_DISABLED)
                 bmp = m_disabled_left_bmp;
-                 else
+            else
                 bmp = m_active_left_bmp;
             break;
         case wxAUI_BUTTON_RIGHT:
             if (button_state & wxAUI_BUTTON_STATE_DISABLED)
                 bmp = m_disabled_right_bmp;
-                 else
+            else
                 bmp = m_active_right_bmp;
             break;
         case wxAUI_BUTTON_WINDOWLIST:
             if (button_state & wxAUI_BUTTON_STATE_DISABLED)
                 bmp = m_disabled_windowlist_bmp;
-                 else
+            else
                 bmp = m_active_windowlist_bmp;
             break;
     }
@@ -642,7 +648,7 @@ void wxAuiDefaultTabArt::DrawButton(wxDC& dc,
         rect.SetWidth(bmp.GetWidth());
         rect.SetHeight(bmp.GetHeight());
     }
-     else
+    else
     {
         rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
                       ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
@@ -666,7 +672,14 @@ int wxAuiDefaultTabArt::ShowDropDown(wxWindow* wnd,
     for (i = 0; i < count; ++i)
     {
         const wxAuiNotebookPage& page = pages.Item(i);
-        menuPopup.AppendCheckItem(1000+i, page.caption);
+        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(" ");
+
+        menuPopup.AppendCheckItem(1000+i, caption);
     }
 
     if (active_idx != -1)
@@ -721,7 +734,7 @@ int wxAuiDefaultTabArt::GetBestTabCtrlSize(wxWindow* wnd,
         wxBitmap bmp;
         if (measure_bmp.IsOk())
             bmp = measure_bmp;
-             else
+        else
             bmp = page.bitmap;
 
         // we don't use the caption text because we don't
@@ -914,7 +927,7 @@ void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
         textx = selected_textx;
         texty = selected_texty;
     }
-     else
+    else
     {
         dc.SetPen(m_normal_bkpen);
         dc.SetBrush(m_normal_bkbrush);
@@ -959,7 +972,7 @@ void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
         close_button_width = m_active_close_bmp.GetWidth();
         text_offset = tab_x + (tab_height/2) + ((tab_width-close_button_width)/2) - (textx/2);
     }
-     else
+    else
     {
         text_offset = tab_x + (tab_height/3) + (tab_width/2) - (textx/2);
     }
@@ -985,7 +998,7 @@ void wxAuiSimpleTabArt::DrawTab(wxDC& dc,
         wxBitmap bmp;
         if (page.active)
             bmp = m_active_close_bmp;
-             else
+        else
             bmp = m_disabled_close_bmp;
 
         wxRect rect(tab_x + tab_width - close_button_width - 1,
@@ -1054,25 +1067,25 @@ void wxAuiSimpleTabArt::DrawButton(wxDC& dc,
         case wxAUI_BUTTON_CLOSE:
             if (button_state & wxAUI_BUTTON_STATE_DISABLED)
                 bmp = m_disabled_close_bmp;
-                 else
+            else
                 bmp = m_active_close_bmp;
             break;
         case wxAUI_BUTTON_LEFT:
             if (button_state & wxAUI_BUTTON_STATE_DISABLED)
                 bmp = m_disabled_left_bmp;
-                 else
+            else
                 bmp = m_active_left_bmp;
             break;
         case wxAUI_BUTTON_RIGHT:
             if (button_state & wxAUI_BUTTON_STATE_DISABLED)
                 bmp = m_disabled_right_bmp;
-                 else
+            else
                 bmp = m_active_right_bmp;
             break;
         case wxAUI_BUTTON_WINDOWLIST:
             if (button_state & wxAUI_BUTTON_STATE_DISABLED)
                 bmp = m_disabled_windowlist_bmp;
-                 else
+            else
                 bmp = m_active_windowlist_bmp;
             break;
     }
@@ -1089,7 +1102,7 @@ void wxAuiSimpleTabArt::DrawButton(wxDC& dc,
         rect.SetWidth(bmp.GetWidth());
         rect.SetHeight(bmp.GetHeight());
     }
-     else
+    else
     {
         rect = wxRect(in_rect.x + in_rect.width - bmp.GetWidth(),
                       ((in_rect.y + in_rect.height)/2) - (bmp.GetHeight()/2),
@@ -1128,7 +1141,7 @@ int wxAuiSimpleTabArt::ShowDropDown(wxWindow* wnd,
     pt = wnd->ScreenToClient(pt);
     if (pt.x < 100)
         pt.x = 0;
-         else
+    else
         pt.x -= 100;
 
     // find out the screen coordinate at the bottom of the tab ctrl
@@ -1320,7 +1333,7 @@ bool wxAuiTabContainer::InsertPage(wxWindow* page,
 
     if (idx >= m_pages.GetCount())
         m_pages.Add(page_info);
-         else
+    else
         m_pages.Insert(page_info, idx);
 
     // let the art provider know how many pages we have
@@ -1387,7 +1400,7 @@ bool wxAuiTabContainer::SetActivePage(wxWindow* wnd)
             page.active = true;
             found = true;
         }
-         else
+        else
         {
             page.active = false;
         }
@@ -1437,14 +1450,14 @@ wxWindow* wxAuiTabContainer::GetWindowFromIdx(size_t idx) const
 
 int wxAuiTabContainer::GetIdxFromWindow(wxWindow* wnd) const
 {
-    size_t i, page_count = m_pages.GetCount();
-    for (i = 0; i < page_count; ++i)
+    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 -1;
+    return wxNOT_FOUND;
 }
 
 wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
@@ -1454,6 +1467,13 @@ wxAuiNotebookPage& wxAuiTabContainer::GetPage(size_t idx)
     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;
@@ -1559,14 +1579,14 @@ void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
 
         if (i+1 < page_count)
             total_width += x_extent;
-             else
+        else
             total_width += size.x;
 
         if (i >= m_tab_offset)
         {
             if (i+1 < page_count)
                 visible_width += x_extent;
-                 else
+            else
                 visible_width += size.x;
         }
     }
@@ -1584,7 +1604,7 @@ void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
             }
         }
     }
-     else
+    else
     {
         // hide left/right buttons
         for (i = 0; i < button_count; ++i)
@@ -1606,14 +1626,14 @@ void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
         {
             if (m_tab_offset == 0)
                 button.cur_state |= wxAUI_BUTTON_STATE_DISABLED;
-                 else
+            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
+            else
                 button.cur_state &= ~wxAUI_BUTTON_STATE_DISABLED;
         }
     }
@@ -1731,11 +1751,9 @@ void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
         wxAuiTabContainerButton& tab_button = m_tab_close_buttons.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;
             if (tab_button.cur_state == wxAUI_BUTTON_STATE_HIDDEN)
             {
                 tab_button.id = wxAUI_BUTTON_CLOSE;
@@ -1743,7 +1761,7 @@ void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
                 tab_button.location = wxCENTER;
             }
         }
-         else
+        else
         {
             tab_button.cur_state = wxAUI_BUTTON_STATE_HIDDEN;
         }
@@ -1788,14 +1806,6 @@ void wxAuiTabContainer::Render(wxDC* raw_dc, wxWindow* wnd)
 
         wxAuiTabContainerButton& tab_button = m_tab_close_buttons.Item(active);
 
-        // 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;
-        }
-
         rect.x = active_offset;
         m_art->DrawTab(dc,
                        wnd,
@@ -1899,7 +1909,7 @@ static void ShowWnd(wxWindow* wnd, bool show)
         wxAuiMDIChildFrame* cf = (wxAuiMDIChildFrame*)wnd;
         cf->DoShow(show);
     }
-     else
+    else
     {
         wnd->Show(show);
     }
@@ -1928,7 +1938,8 @@ void wxAuiTabContainer::DoShowHide()
     for (i = 0; i < page_count; ++i)
     {
         wxAuiNotebookPage& page = pages.Item(i);
-        ShowWnd(page.window, page.active);
+        if (!page.active)
+            ShowWnd(page.window, false);
     }
 }
 
@@ -1948,6 +1959,10 @@ BEGIN_EVENT_TABLE(wxAuiTabCtrl, wxControl)
     EVT_LEFT_DOWN(wxAuiTabCtrl::OnLeftDown)
     EVT_LEFT_DCLICK(wxAuiTabCtrl::OnLeftDown)
     EVT_LEFT_UP(wxAuiTabCtrl::OnLeftUp)
+    EVT_MIDDLE_DOWN(wxAuiTabCtrl::OnMiddleDown)
+    EVT_MIDDLE_UP(wxAuiTabCtrl::OnMiddleUp)
+    EVT_RIGHT_DOWN(wxAuiTabCtrl::OnRightDown)
+    EVT_RIGHT_UP(wxAuiTabCtrl::OnRightUp)
     EVT_MOTION(wxAuiTabCtrl::OnMotion)
     EVT_LEAVE_WINDOW(wxAuiTabCtrl::OnLeaveWindow)
     EVT_AUINOTEBOOK_BUTTON(wxID_ANY, wxAuiTabCtrl::OnButton)
@@ -2039,11 +2054,14 @@ void wxAuiTabCtrl::OnLeftUp(wxMouseEvent& evt)
 
     if (m_is_dragging)
     {
+        m_is_dragging = false;
+
         wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, m_windowId);
         evt.SetSelection(GetIdxFromWindow(m_click_tab));
         evt.SetOldSelection(evt.GetSelection());
         evt.SetEventObject(this);
         GetEventHandler()->ProcessEvent(evt);
+
         return;
     }
 
@@ -2066,6 +2084,7 @@ void wxAuiTabCtrl::OnLeftUp(wxMouseEvent& evt)
         if (!(m_pressed_button->cur_state & wxAUI_BUTTON_STATE_DISABLED))
         {
             wxAuiNotebookEvent evt(wxEVT_COMMAND_AUINOTEBOOK_BUTTON, m_windowId);
+            evt.SetSelection(GetIdxFromWindow(m_click_tab));
             evt.SetInt(m_pressed_button->id);
             evt.SetEventObject(this);
             GetEventHandler()->ProcessEvent(evt);
@@ -2079,6 +2098,54 @@ void wxAuiTabCtrl::OnLeftUp(wxMouseEvent& evt)
     m_click_tab = NULL;
 }
 
+void wxAuiTabCtrl::OnMiddleUp(wxMouseEvent& evt)
+{
+    wxWindow* wnd = NULL;
+    if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
+        return;
+
+    wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId);
+    e.SetEventObject(this);
+    e.SetSelection(GetIdxFromWindow(wnd));
+    GetEventHandler()->ProcessEvent(e);
+}
+
+void wxAuiTabCtrl::OnMiddleDown(wxMouseEvent& evt)
+{
+    wxWindow* wnd = NULL;
+    if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
+        return;
+
+    wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId);
+    e.SetEventObject(this);
+    e.SetSelection(GetIdxFromWindow(wnd));
+    GetEventHandler()->ProcessEvent(e);
+}
+
+void wxAuiTabCtrl::OnRightUp(wxMouseEvent& evt)
+{
+    wxWindow* wnd = NULL;
+    if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
+        return;
+
+    wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId);
+    e.SetEventObject(this);
+    e.SetSelection(GetIdxFromWindow(wnd));
+    GetEventHandler()->ProcessEvent(e);
+}
+
+void wxAuiTabCtrl::OnRightDown(wxMouseEvent& evt)
+{
+    wxWindow* wnd = NULL;
+    if (!TabHitTest(evt.m_x, evt.m_y, &wnd))
+        return;
+
+    wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId);
+    e.SetEventObject(this);
+    e.SetSelection(GetIdxFromWindow(wnd));
+    GetEventHandler()->ProcessEvent(e);
+}
+
 void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
 {
     wxPoint pos = evt.GetPosition();
@@ -2104,7 +2171,7 @@ void wxAuiTabCtrl::OnMotion(wxMouseEvent& evt)
             return;
         }
     }
-     else
+    else
     {
         if (m_hover_button)
         {
@@ -2172,14 +2239,14 @@ void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event)
                 Update();
             }
         }
-         else
+        else
         {
             SetTabOffset(GetTabOffset()+1);
             Refresh();
             Update();
         }
     }
-     else if (button == wxAUI_BUTTON_WINDOWLIST)
+    else if (button == wxAUI_BUTTON_WINDOWLIST)
     {
         int idx = GetArtProvider()->ShowDropDown(this, m_pages, GetActivePage());
 
@@ -2192,7 +2259,7 @@ void wxAuiTabCtrl::OnButton(wxAuiNotebookEvent& event)
             GetEventHandler()->ProcessEvent(e);
         }
     }
-     else
+    else
     {
         event.Skip();
     }
@@ -2217,11 +2284,17 @@ public:
         m_tab_ctrl_height = 20;
     }
 
+    ~wxTabFrame()
+    {
+        wxDELETE(m_tabs);
+    }
+
     void SetTabCtrlHeight(int h)
     {
         m_tab_ctrl_height = h;
     }
 
+protected:
     void DoSetSize(int x, int y,
                    int width, int height,
                    int WXUNUSED(sizeFlags = wxSIZE_AUTO))
@@ -2236,6 +2309,7 @@ public:
         *y = m_rect.height;
     }
 
+public:
     bool Show( bool WXUNUSED(show = true) ) { return false; }
 
     void DoSizing()
@@ -2266,6 +2340,7 @@ public:
         }
     }
 
+protected:
     void DoGetSize(int* x, int* y) const
     {
         if (x)
@@ -2274,13 +2349,12 @@ public:
             *y = m_rect.GetHeight();
     }
 
+public:
     void Update()
     {
         // does nothing
     }
 
-public:
-
     wxRect m_rect;
     wxRect m_tab_rect;
     wxAuiTabCtrl* m_tabs;
@@ -2311,6 +2385,18 @@ BEGIN_EVENT_TABLE(wxAuiNotebook, wxControl)
     EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
                       wxEVT_COMMAND_AUINOTEBOOK_BUTTON,
                       wxAuiNotebook::OnTabButton)
+    EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
+                      wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN,
+                      wxAuiNotebook::OnTabMiddleDown)
+    EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
+                      wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP,
+                      wxAuiNotebook::OnTabMiddleUp)
+    EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
+                      wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN,
+                      wxAuiNotebook::OnTabRightDown)
+    EVT_COMMAND_RANGE(wxAuiBaseTabCtrlId, wxAuiBaseTabCtrlId+500,
+                      wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP,
+                      wxAuiNotebook::OnTabRightUp)
 END_EVENT_TABLE()
 
 wxAuiNotebook::wxAuiNotebook()
@@ -2499,7 +2585,7 @@ wxSize wxAuiNotebook::CalculateNewSplitSize()
         new_split_size.x /= 2;
         new_split_size.y /= 2;
     }
-     else
+    else
     {
         // this is in place of a more complicated calculation
         // that needs to be implemented
@@ -2591,12 +2677,13 @@ bool wxAuiNotebook::InsertPage(size_t page_idx,
     // select is false, it must become the "current page"
     // (though no select events will be fired)
     if (!select && m_tabs.GetPageCount() == 1)
-        m_curpage = GetPageIndex(page);
+        select = true;
+        //m_curpage = GetPageIndex(page);
 
     wxAuiTabCtrl* active_tabctrl = GetActiveTabCtrl();
     if (page_idx >= active_tabctrl->GetPageCount())
         active_tabctrl->AddPage(page, info);
-         else
+    else
         active_tabctrl->InsertPage(page, info, page_idx);
 
     UpdateTabCtrlHeight();
@@ -2605,10 +2692,7 @@ bool wxAuiNotebook::InsertPage(size_t page_idx,
 
     if (select)
     {
-        int idx = m_tabs.GetIdxFromWindow(page);
-        wxASSERT_MSG(idx != -1, wxT("Invalid Page index returned on wxAuiNotebook::InsertPage()"));
-
-        SetSelection(idx);
+        SetSelectionToWindow(page);
     }
 
     return true;
@@ -2619,8 +2703,15 @@ bool wxAuiNotebook::InsertPage(size_t page_idx,
 // and destroys the window as well
 bool wxAuiNotebook::DeletePage(size_t page_idx)
 {
+    if (page_idx >= m_tabs.GetPageCount())
+        return false;
+
     wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
 
+    // hide the window in advance, as this will
+    // prevent flicker
+    ShowWnd(wnd, false);
+
     if (!RemovePage(page_idx))
         return false;
 
@@ -2632,7 +2723,7 @@ bool wxAuiNotebook::DeletePage(size_t page_idx)
         if (!wxPendingDelete.Member(wnd))
             wxPendingDelete.Append(wnd);
     }
-     else
+    else
     {
         wnd->Destroy();
     }
@@ -2646,46 +2737,80 @@ bool wxAuiNotebook::DeletePage(size_t page_idx)
 // but does not destroy the window
 bool wxAuiNotebook::RemovePage(size_t page_idx)
 {
+    // save active window pointer
+    wxWindow* active_wnd = NULL;
+    if (m_curpage >= 0)
+        active_wnd = m_tabs.GetWindowFromIdx(m_curpage);
+
+    // save pointer of window being deleted
     wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
     wxWindow* new_active = NULL;
 
+    // make sure we found the page
+    if (!wnd)
+        return false;
+
     // 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;
+    bool is_curpage = (m_curpage == (int)page_idx);
+    bool is_active_in_split = ctrl->GetPage(ctrl_idx).active;
 
-    if (new_idx >= 0 && new_idx < (int)ctrl->GetPageCount())
-    {
-        new_active = ctrl->GetWindowFromIdx(new_idx);
-    }
-     else
+
+    // remove the tab from main catalog
+    if (!m_tabs.RemovePage(wnd))
+        return false;
+
+    // remove the tab from the onscreen tab ctrl
+    ctrl->RemovePage(wnd);
+
+    if (is_active_in_split)
     {
-        // set the active page to the first page that
-        // isn't the one being deleted
-        size_t i, page_count = m_tabs.GetPageCount();
-        for (i = 0; i < page_count; ++i)
+        int ctrl_new_page_count = (int)ctrl->GetPageCount();
+
+        if (ctrl_idx >= ctrl_new_page_count)
+            ctrl_idx = ctrl_new_page_count-1;
+
+        if (ctrl_idx >= 0 && ctrl_idx < (int)ctrl->GetPageCount())
         {
-            wxWindow* w = m_tabs.GetWindowFromIdx(i);
-            if (wnd != w)
+            // set new page as active in the tab split
+            ctrl->SetActivePage(ctrl_idx);
+
+            // if the page deleted was the current page for the
+            // entire tab control, then record the window
+            // pointer of the new active page for activation
+            if (is_curpage)
             {
-                new_active = m_tabs.GetWindowFromIdx(i);
-                break;
+                new_active = ctrl->GetWindowFromIdx(ctrl_idx);
             }
         }
     }
+    else
+    {
+        // we are not deleting the active page, so keep it the same
+        new_active = active_wnd;
+    }
 
-    // remove the tab from main catalog
-    if (!m_tabs.RemovePage(wnd))
-        return false;
 
-    // remove the tab from the onscreen tab ctrl
-    ctrl->RemovePage(wnd);
+    if (!new_active)
+    {
+        // we haven't yet found a new page to active,
+        // so select the next page from the main tab
+        // catalogue
+
+        if (page_idx < m_tabs.GetPageCount())
+        {
+            new_active = m_tabs.GetPage(page_idx).window;
+        }
+
+        if (!new_active && m_tabs.GetPageCount() > 0)
+        {
+            new_active = m_tabs.GetPage(0).window;
+        }
+    }
 
 
     RemoveEmptyTabFrames();
@@ -2694,7 +2819,7 @@ bool wxAuiNotebook::RemovePage(size_t page_idx)
     if (new_active)
     {
         m_curpage = -1;
-        SetSelection(m_tabs.GetIdxFromWindow(new_active));
+        SetSelectionToWindow(new_active);
     }
 
     return true;
@@ -2733,6 +2858,16 @@ bool wxAuiNotebook::SetPageText(size_t page_idx, const wxString& text)
     return true;
 }
 
+// returns the page caption
+wxString wxAuiNotebook::GetPageText(size_t page_idx) const
+{
+    if (page_idx >= m_tabs.GetPageCount())
+        return wxEmptyString;
+
+    // update our own tab catalog
+    const wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
+    return page_info.caption;
+}
 
 bool wxAuiNotebook::SetPageBitmap(size_t page_idx, const wxBitmap& bitmap)
 {
@@ -2760,6 +2895,16 @@ bool wxAuiNotebook::SetPageBitmap(size_t page_idx, const wxBitmap& bitmap)
     return true;
 }
 
+// returns the page bitmap
+wxBitmap wxAuiNotebook::GetPageBitmap(size_t page_idx) const
+{
+    if (page_idx >= m_tabs.GetPageCount())
+        return wxBitmap();
+
+    // update our own tab catalog
+    const wxAuiNotebookPage& page_info = m_tabs.GetPage(page_idx);
+    return page_info.bitmap;
+}
 
 // GetSelection() returns the index of the currently active page
 int wxAuiNotebook::GetSelection() const
@@ -2815,7 +2960,7 @@ size_t wxAuiNotebook::SetSelection(size_t new_page)
                 wxAuiTabCtrl* tabctrl = ((wxTabFrame*)pane.window)->m_tabs;
                 if (tabctrl != ctrl)
                     tabctrl->SetSelectedFont(m_normal_font);
-                     else
+                else
                     tabctrl->SetSelectedFont(m_selected_font);
                 tabctrl->Refresh();
             }
@@ -2829,6 +2974,14 @@ size_t wxAuiNotebook::SetSelection(size_t new_page)
     return m_curpage;
 }
 
+void wxAuiNotebook::SetSelectionToWindow(wxWindow *win)
+{
+    const int idx = m_tabs.GetIdxFromWindow(win);
+    wxCHECK_RET( idx != wxNOT_FOUND, _T("invalid notebook page") );
+
+    SetSelection(idx);
+}
+
 // GetPageCount() returns the total number of
 // pages managed by the multi-notebook
 size_t wxAuiNotebook::GetPageCount() const
@@ -2933,6 +3086,120 @@ bool wxAuiNotebook::FindTab(wxWindow* page, wxAuiTabCtrl** ctrl, int* idx)
     return false;
 }
 
+void wxAuiNotebook::Split(size_t page, int direction)
+{
+    wxSize cli_size = GetClientSize();
+
+    // get the page's window pointer
+    wxWindow* wnd = GetPage(page);
+    if (!wnd)
+        return;
+
+    // notebooks with 1 or less pages can't be split
+    if (GetPageCount() < 2)
+        return;
+
+    // find out which tab control the page currently belongs to
+    wxAuiTabCtrl *src_tabs, *dest_tabs;
+    int src_idx = -1;
+    src_tabs = NULL;
+    if (!FindTab(wnd, &src_tabs, &src_idx))
+        return;
+    if (!src_tabs || src_idx == -1)
+        return;
+
+    // choose a split size
+    wxSize split_size;
+    if (GetPageCount() > 2)
+    {
+        split_size = CalculateNewSplitSize();
+    }
+    else
+    {
+        // because there are two panes, always split them
+        // equally
+        split_size = GetClientSize();
+        split_size.x /= 2;
+        split_size.y /= 2;
+    }
+
+
+    // create a new tab frame
+    wxTabFrame* new_tabs = new wxTabFrame;
+    new_tabs->m_rect = wxRect(wxPoint(0,0), split_size);
+    new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
+    new_tabs->m_tabs = new wxAuiTabCtrl(this,
+                                        m_tab_id_counter++,
+                                        wxDefaultPosition,
+                                        wxDefaultSize,
+                                        wxNO_BORDER);
+    new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
+    new_tabs->m_tabs->SetFlags(m_flags);
+    dest_tabs = new_tabs->m_tabs;
+
+    // create a pane info structure with the information
+    // about where the pane should be added
+    wxAuiPaneInfo pane_info = wxAuiPaneInfo().Bottom().CaptionVisible(false);
+    wxPoint mouse_pt;
+
+    if (direction == wxLEFT)
+    {
+        pane_info.Left();
+        mouse_pt = wxPoint(0, cli_size.y/2);
+    }
+    else if (direction == wxRIGHT)
+    {
+        pane_info.Right();
+        mouse_pt = wxPoint(cli_size.x, cli_size.y/2);
+    }
+    else if (direction == wxTOP)
+    {
+        pane_info.Top();
+        mouse_pt = wxPoint(cli_size.x/2, 0);
+    }
+    else if (direction == wxBOTTOM)
+    {
+        pane_info.Bottom();
+        mouse_pt = wxPoint(cli_size.x/2, cli_size.y);
+    }
+
+    m_mgr.AddPane(new_tabs, pane_info, mouse_pt);
+    m_mgr.Update();
+
+    // remove the page from the source tabs
+    wxAuiNotebookPage page_info = src_tabs->GetPage(src_idx);
+    page_info.active = false;
+    src_tabs->RemovePage(page_info.window);
+    if (src_tabs->GetPageCount() > 0)
+    {
+        src_tabs->SetActivePage((size_t)0);
+        src_tabs->DoShowHide();
+        src_tabs->Refresh();
+    }
+
+
+    // add the page to the destination tabs
+    dest_tabs->InsertPage(page_info.window, page_info, 0);
+
+    if (src_tabs->GetPageCount() == 0)
+    {
+        RemoveEmptyTabFrames();
+    }
+
+    DoSizing();
+    dest_tabs->DoShowHide();
+    dest_tabs->Refresh();
+
+    // force the set selection function reset the selection
+    m_curpage = -1;
+
+    // set the active page to the one we just split off
+    SetSelectionToPage(page_info);
+
+    UpdateHintWindowSize();
+}
+
+
 void wxAuiNotebook::OnSize(wxSizeEvent& evt)
 {
     UpdateHintWindowSize();
@@ -2950,10 +3217,7 @@ void wxAuiNotebook::OnTabClicked(wxCommandEvent& command_evt)
     wxWindow* wnd = ctrl->GetWindowFromIdx(evt.GetSelection());
     wxASSERT(wnd != NULL);
 
-    int idx = m_tabs.GetIdxFromWindow(wnd);
-    wxASSERT(idx != -1);
-
-    SetSelection(idx);
+    SetSelectionToWindow(wnd);
 }
 
 void wxAuiNotebook::OnTabBeginDrag(wxCommandEvent&)
@@ -3051,7 +3315,7 @@ void wxAuiNotebook::OnTabDragMotion(wxCommandEvent& evt)
                 }
             }
         }
-         else
+        else
         {
             if (!dest_tabs)
             {
@@ -3084,7 +3348,7 @@ void wxAuiNotebook::OnTabDragMotion(wxCommandEvent& evt)
         ClientToScreen(&hint_rect.x, &hint_rect.y);
         m_mgr.ShowHint(hint_rect);
     }
-     else
+    else
     {
         m_mgr.DrawHintRect(m_dummy_wnd, client_pt, zero);
     }
@@ -3100,12 +3364,9 @@ void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
 
 
     wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
-    wxAuiTabCtrl* dest_tabs = NULL;
-    if (src_tabs)
-    {
-        // set cursor back to an arrow
-        src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
-    }
+    wxCHECK_RET( src_tabs, _T("no source object?") );
+
+    src_tabs->SetCursor(wxCursor(wxCURSOR_ARROW));
 
     // get the mouse position, which will be used to determine the drop point
     wxPoint mouse_screen_pt = ::wxGetMousePosition();
@@ -3155,9 +3416,11 @@ void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
 
                 // get main index of the page
                 int main_idx = m_tabs.GetIdxFromWindow(src_page);
+                wxCHECK_RET( main_idx != wxNOT_FOUND, _T("no source page?") );
+
 
                 // make a copy of the page info
-                wxAuiNotebookPage page_info = m_tabs.GetPage((size_t)main_idx);
+                wxAuiNotebookPage page_info = m_tabs.GetPage(main_idx);
 
                 // remove the page from the source notebook
                 RemovePage(main_idx);
@@ -3190,7 +3453,7 @@ void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
                 dest_tabs->Refresh();
 
                 // set the selection in the destination tab control
-                nb->SetSelection(nb->m_tabs.GetIdxFromWindow(page_info.window));
+                nb->SetSelectionToPage(page_info);
 
                 return;
             }
@@ -3201,6 +3464,8 @@ void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
 
 
     // only perform a tab split if it's allowed
+    wxAuiTabCtrl* dest_tabs = NULL;
+
     if ((m_flags & wxAUI_NB_TAB_SPLIT) && m_tabs.GetPageCount() >= 2)
     {
         // If the pointer is in an existing tab frame, do a tab insert
@@ -3223,7 +3488,7 @@ void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
                 insert_idx = dest_tabs->GetIdxFromWindow(target);
             }
         }
-         else
+        else
         {
             wxPoint zero(0,0);
             wxRect rect = m_mgr.CalculateHintRect(m_dummy_wnd,
@@ -3287,7 +3552,7 @@ void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
         m_curpage = -1;
 
         // set the active page to the one we just split off
-        SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
+        SetSelectionToPage(page_info);
 
         UpdateHintWindowSize();
     }
@@ -3355,7 +3620,8 @@ void wxAuiNotebook::RemoveEmptyTabFrames()
             // window closing, refreshs are pending
             if (!wxPendingDelete.Member(tab_frame->m_tabs))
                 wxPendingDelete.Append(tab_frame->m_tabs);
-            //tab_frame->m_tabs->Destroy();
+
+            tab_frame->m_tabs = NULL;
 
             delete tab_frame;
         }
@@ -3388,6 +3654,27 @@ void wxAuiNotebook::RemoveEmptyTabFrames()
 
 void wxAuiNotebook::OnChildFocus(wxChildFocusEvent& evt)
 {
+    // if we're dragging a tab, don't change the current selection.
+    // This code prevents a bug that used to happen when the hint window
+    // was hidden.  In the bug, the focus would return to the notebook
+    // child, which would then enter this handler and call
+    // SetSelection, which is not desired turn tab dragging.
+
+    wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
+    size_t i, pane_count = all_panes.GetCount();
+    for (i = 0; i < pane_count; ++i)
+    {
+        wxAuiPaneInfo& pane = all_panes.Item(i);
+        if (pane.name == wxT("dummy"))
+            continue;
+        wxTabFrame* tabframe = (wxTabFrame*)pane.window;
+        if (tabframe->m_tabs->IsDragging())
+            return;
+    }
+
+
+    // change the tab selection to the child
+    // which was focused
     int idx = m_tabs.GetIdxFromWindow(evt.GetWindow());
     if (idx != -1 && idx != m_curpage)
     {
@@ -3405,13 +3692,12 @@ void wxAuiNotebook::OnTabButton(wxCommandEvent& command_evt)
 
     if (button_id == wxAUI_BUTTON_CLOSE)
     {
-        int selection = tabs->GetActivePage();
+        int selection = evt.GetSelection();
 
         if (selection != -1)
         {
             wxWindow* close_wnd = tabs->GetWindowFromIdx(selection);
 
-
             // ask owner if it's ok to close the tab
             wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, m_windowId);
             e.SetSelection(m_tabs.GetIdxFromWindow(close_wnd));
@@ -3426,9 +3712,11 @@ void wxAuiNotebook::OnTabButton(wxCommandEvent& command_evt)
             {
                 close_wnd->Close();
             }
-             else
+            else
             {
                 int main_idx = m_tabs.GetIdxFromWindow(close_wnd);
+                wxCHECK_RET( main_idx != wxNOT_FOUND, _T("no page to delete?") );
+
                 DeletePage(main_idx);
             }
         }
@@ -3436,6 +3724,120 @@ void wxAuiNotebook::OnTabButton(wxCommandEvent& command_evt)
 }
 
 
+void wxAuiNotebook::OnTabMiddleDown(wxCommandEvent& evt)
+{
+    // patch event through to owner
+    wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
+    wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
+
+    wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, m_windowId);
+    e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
+    e.SetEventObject(this);
+    GetEventHandler()->ProcessEvent(e);
+}
+
+void wxAuiNotebook::OnTabMiddleUp(wxCommandEvent& evt)
+{
+    // if the wxAUI_NB_MIDDLE_CLICK_CLOSE is specified, middle
+    // click should act like a tab close action.  However, first
+    // give the owner an opportunity to handle the middle up event
+    // for custom action
+
+    wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
+    wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
+
+    wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, m_windowId);
+    e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
+    e.SetEventObject(this);
+    if (GetEventHandler()->ProcessEvent(e))
+        return;
+    if (!e.IsAllowed())
+        return;
+
+    // check if we are supposed to close on middle-up
+    if ((m_flags & wxAUI_NB_MIDDLE_CLICK_CLOSE) == 0)
+        return;
+
+    // simulate the user pressing the close button on the tab
+    evt.SetInt(wxAUI_BUTTON_CLOSE);
+    OnTabButton(evt);
+}
+
+void wxAuiNotebook::OnTabRightDown(wxCommandEvent& evt)
+{
+    // patch event through to owner
+    wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
+    wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
+
+    wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, m_windowId);
+    e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
+    e.SetEventObject(this);
+    GetEventHandler()->ProcessEvent(e);
+}
+
+void wxAuiNotebook::OnTabRightUp(wxCommandEvent& evt)
+{
+    // patch event through to owner
+    wxAuiTabCtrl* tabs = (wxAuiTabCtrl*)evt.GetEventObject();
+    wxWindow* wnd = tabs->GetWindowFromIdx(evt.GetSelection());
+
+    wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, m_windowId);
+    e.SetSelection(m_tabs.GetIdxFromWindow(wnd));
+    e.SetEventObject(this);
+    GetEventHandler()->ProcessEvent(e);
+}
+
+// Sets the normal font
+void wxAuiNotebook::SetNormalFont(const wxFont& font)
+{
+    m_normal_font = font;
+    GetArtProvider()->SetNormalFont(font);
+}
+
+// Sets the selected tab font
+void wxAuiNotebook::SetSelectedFont(const wxFont& font)
+{
+    m_selected_font = font;
+    GetArtProvider()->SetSelectedFont(font);
+}
+
+// Sets the measuring font
+void wxAuiNotebook::SetMeasuringFont(const wxFont& font)
+{
+    GetArtProvider()->SetMeasuringFont(font);
+}
+
+// Sets the tab font
+bool wxAuiNotebook::SetFont(const wxFont& font)
+{
+    wxControl::SetFont(font);
+
+    wxFont normalFont(font);
+    wxFont selectedFont(normalFont);
+    selectedFont.SetWeight(wxBOLD);
+
+    SetNormalFont(normalFont);
+    SetSelectedFont(selectedFont);
+    SetMeasuringFont(selectedFont);
+
+    return true;
+}
+
+// Gets the tab control height
+int wxAuiNotebook::GetTabCtrlHeight() const
+{
+    return m_tab_ctrl_height;
+}
+
+// Gets the height of the notebook for a given page height
+int wxAuiNotebook::GetHeightForPageHeight(int pageHeight)
+{
+    UpdateTabCtrlHeight();
+
+    int tabCtrlHeight = GetTabCtrlHeight();
+    int decorHeight = 2;
+    return tabCtrlHeight + pageHeight + decorHeight;
+}
 
 
 #endif // wxUSE_AUI