wxAuiNotebook has external tab dragging now

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@43121 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Benjamin Williams
2006-11-06 13:44:26 +00:00
parent 56c6aab7e6
commit 5d3aeb0f57
3 changed files with 308 additions and 90 deletions

View File

@@ -27,6 +27,8 @@
#include "wx/control.h"
class wxAuiNotebook;
enum wxAuiNotebookOption
{
@@ -36,11 +38,13 @@ enum wxAuiNotebookOption
wxAUI_NB_BOTTOM = 1 << 3, // not implemented yet
wxAUI_NB_TAB_SPLIT = 1 << 4,
wxAUI_NB_TAB_MOVE = 1 << 5,
wxAUI_NB_SCROLL_BUTTONS = 1 << 6,
wxAUI_NB_WINDOWLIST_BUTTON = 1 << 7,
wxAUI_NB_CLOSE_BUTTON = 1 << 8,
wxAUI_NB_CLOSE_ON_ACTIVE_TAB = 1 << 9,
wxAUI_NB_CLOSE_ON_ALL_TABS = 1 << 10,
wxAUI_NB_TAB_EXTERNAL_MOVE = 1 << 6,
wxAUI_NB_SCROLL_BUTTONS = 1 << 7,
wxAUI_NB_WINDOWLIST_BUTTON = 1 << 8,
wxAUI_NB_CLOSE_BUTTON = 1 << 9,
wxAUI_NB_CLOSE_ON_ACTIVE_TAB = 1 << 10,
wxAUI_NB_CLOSE_ON_ALL_TABS = 1 << 11,
wxAUI_NB_DEFAULT_STYLE = wxAUI_NB_TOP |
wxAUI_NB_TAB_SPLIT |
@@ -192,24 +196,33 @@ public:
int win_id = 0)
: wxNotifyEvent(command_type, win_id)
{
old_selection = -1;
selection = -1;
drag_source = NULL;
}
#ifndef SWIG
wxAuiNotebookEvent(const wxAuiNotebookEvent& c) : wxNotifyEvent(c)
{
old_selection = c.old_selection;
selection = c.selection;
drag_source = c.drag_source;
}
#endif
wxEvent *Clone() const { return new wxAuiNotebookEvent(*this); }
void SetSelection(int s) { selection = s; m_commandInt = s; }
void SetOldSelection(int s) { old_selection = s; }
int GetSelection() const { return selection; }
void SetOldSelection(int s) { old_selection = s; }
int GetOldSelection() const { return old_selection; }
void SetDragSource(wxAuiNotebook* s) { drag_source = s; }
wxAuiNotebook* GetDragSource() const { return drag_source; }
public:
int old_selection;
int selection;
wxAuiNotebook* drag_source;
#ifndef SWIG
private:
@@ -343,6 +356,7 @@ protected:
wxAuiTabContainerButton* m_hover_button;
#ifndef SWIG
DECLARE_CLASS(wxAuiTabCtrl)
DECLARE_EVENT_TABLE()
#endif
};
@@ -455,6 +469,7 @@ BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_AUI, wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 0)
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_AUI, wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 0)
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_AUI, wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 0)
DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_AUI, wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 0)
END_DECLARE_EVENT_TYPES()
typedef void (wxEvtHandler::*wxAuiNotebookEventFunction)(wxAuiNotebookEvent&);
@@ -474,6 +489,8 @@ typedef void (wxEvtHandler::*wxAuiNotebookEventFunction)(wxAuiNotebookEvent&);
wx__DECLARE_EVT1(wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, winid, wxAuiNotebookEventHandler(fn))
#define EVT_AUINOTEBOOK_DRAG_MOTION(winid, fn) \
wx__DECLARE_EVT1(wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, winid, wxAuiNotebookEventHandler(fn))
#define EVT_AUINOTEBOOK_ALLOW_DND(winid, fn) \
wx__DECLARE_EVT1(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, winid, wxAuiNotebookEventHandler(fn))
#else
@@ -484,6 +501,7 @@ typedef void (wxEvtHandler::*wxAuiNotebookEventFunction)(wxAuiNotebookEvent&);
%constant wxEventType wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG;
%constant wxEventType wxEVT_COMMAND_AUINOTEBOOK_END_DRAG;
%constant wxEventType wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION;
%constant wxEventType wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND;
%pythoncode {
EVT_AUINOTEBOOK_PAGE_CHANGED = wx.PyEventBinder( wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, 1 )
@@ -492,6 +510,7 @@ typedef void (wxEvtHandler::*wxAuiNotebookEventFunction)(wxAuiNotebookEvent&);
EVT_AUINOTEBOOK_BEGIN_DRAG = wx.PyEventBinder( wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, 1 )
EVT_AUINOTEBOOK_END_DRAG = wx.PyEventBinder( wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, 1 )
EVT_AUINOTEBOOK_DRAG_MOTION = wx.PyEventBinder( wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, 1 )
EVT_AUINOTEBOOK_ALLOW_DND = wx.PyEventBinder( wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, 1 )
}
#endif

View File

@@ -90,6 +90,7 @@ class MyFrame : public wxFrame
ID_NotebookCloseButtonAll,
ID_NotebookCloseButtonActive,
ID_NotebookAllowTabMove,
ID_NotebookAllowTabExternalMove,
ID_NotebookAllowTabSplit,
ID_NotebookWindowList,
ID_NotebookScrollButtons,
@@ -136,6 +137,7 @@ private:
void OnCopyPerspectiveCode(wxCommandEvent& evt);
void OnRestorePerspective(wxCommandEvent& evt);
void OnSettings(wxCommandEvent& evt);
void OnAllowNotebookDnD(wxAuiNotebookEvent& evt);
void OnExit(wxCommandEvent& evt);
void OnAbout(wxCommandEvent& evt);
@@ -577,6 +579,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_NotebookCloseButtonAll, MyFrame::OnNotebookFlag)
EVT_MENU(ID_NotebookCloseButtonActive, MyFrame::OnNotebookFlag)
EVT_MENU(ID_NotebookAllowTabMove, MyFrame::OnNotebookFlag)
EVT_MENU(ID_NotebookAllowTabExternalMove, MyFrame::OnNotebookFlag)
EVT_MENU(ID_NotebookAllowTabSplit, MyFrame::OnNotebookFlag)
EVT_MENU(ID_NotebookScrollButtons, MyFrame::OnNotebookFlag)
EVT_MENU(ID_NotebookWindowList, MyFrame::OnNotebookFlag)
@@ -597,6 +600,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_UPDATE_UI(ID_NotebookCloseButtonAll, MyFrame::OnUpdateUI)
EVT_UPDATE_UI(ID_NotebookCloseButtonActive, MyFrame::OnUpdateUI)
EVT_UPDATE_UI(ID_NotebookAllowTabMove, MyFrame::OnUpdateUI)
EVT_UPDATE_UI(ID_NotebookAllowTabExternalMove, MyFrame::OnUpdateUI)
EVT_UPDATE_UI(ID_NotebookAllowTabSplit, MyFrame::OnUpdateUI)
EVT_UPDATE_UI(ID_NotebookScrollButtons, MyFrame::OnUpdateUI)
EVT_UPDATE_UI(ID_NotebookWindowList, MyFrame::OnUpdateUI)
@@ -614,6 +618,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU_RANGE(MyFrame::ID_FirstPerspective, MyFrame::ID_FirstPerspective+1000,
MyFrame::OnRestorePerspective)
EVT_AUI_PANECLOSE(MyFrame::OnPaneClose)
EVT_AUINOTEBOOK_ALLOW_DND(wxID_ANY, MyFrame::OnAllowNotebookDnD)
END_EVENT_TABLE()
@@ -632,7 +637,7 @@ MyFrame::MyFrame(wxWindow* parent,
SetIcon(wxIcon(sample_xpm));
// set up default notebook style
m_notebook_style = wxAUI_NB_DEFAULT_STYLE | wxNO_BORDER;
m_notebook_style = wxAUI_NB_DEFAULT_STYLE | wxAUI_NB_TAB_EXTERNAL_MOVE | wxNO_BORDER;
// create menu
wxMenuBar* mb = new wxMenuBar;
@@ -680,6 +685,7 @@ MyFrame::MyFrame(wxWindow* parent,
notebook_menu->AppendRadioItem(ID_NotebookCloseButtonActive, _("Close Button on Active Tab"));
notebook_menu->AppendSeparator();
notebook_menu->AppendCheckItem(ID_NotebookAllowTabMove, _("Allow Tab Move"));
notebook_menu->AppendCheckItem(ID_NotebookAllowTabExternalMove, _("Allow External Tab Move"));
notebook_menu->AppendCheckItem(ID_NotebookAllowTabSplit, _("Allow Notebook Split"));
notebook_menu->AppendCheckItem(ID_NotebookScrollButtons, _("Scroll Buttons Visible"));
notebook_menu->AppendCheckItem(ID_NotebookWindowList, _("Window List Button Visible"));
@@ -1044,6 +1050,10 @@ void MyFrame::OnNotebookFlag(wxCommandEvent& event)
if (id == ID_NotebookAllowTabMove)
{
m_notebook_style ^= wxAUI_NB_TAB_MOVE;
}
if (id == ID_NotebookAllowTabExternalMove)
{
m_notebook_style ^= wxAUI_NB_TAB_EXTERNAL_MOVE;
}
else if (id == ID_NotebookAllowTabSplit)
{
@@ -1137,6 +1147,9 @@ void MyFrame::OnUpdateUI(wxUpdateUIEvent& event)
case ID_NotebookAllowTabMove:
event.Check((m_notebook_style & wxAUI_NB_TAB_MOVE) != 0);
break;
case ID_NotebookAllowTabExternalMove:
event.Check((m_notebook_style & wxAUI_NB_TAB_EXTERNAL_MOVE) != 0);
break;
case ID_NotebookScrollButtons:
event.Check((m_notebook_style & wxAUI_NB_SCROLL_BUTTONS) != 0);
break;
@@ -1177,7 +1190,7 @@ void MyFrame::OnCreatePerspective(wxCommandEvent& WXUNUSED(event))
m_perspectives.Add(m_mgr.SavePerspective());
}
void MyFrame::OnCopyPerspectiveCode(wxCommandEvent& WXUNUSED(event))
void MyFrame::OnCopyPerspectiveCode(wxCommandEvent& WXUNUSED(evt))
{
wxString s = m_mgr.SavePerspective();
@@ -1190,11 +1203,17 @@ void MyFrame::OnCopyPerspectiveCode(wxCommandEvent& WXUNUSED(event))
#endif
}
void MyFrame::OnRestorePerspective(wxCommandEvent& event)
void MyFrame::OnRestorePerspective(wxCommandEvent& evt)
{
m_mgr.LoadPerspective(m_perspectives.Item(event.GetId() - ID_FirstPerspective));
m_mgr.LoadPerspective(m_perspectives.Item(evt.GetId() - ID_FirstPerspective));
}
void MyFrame::OnAllowNotebookDnD(wxAuiNotebookEvent& evt)
{
// for the purpose of this test application, explicitly
// allow all noteboko drag and drop events
evt.Allow();
}
wxPoint MyFrame::GetStartPosition()
{

View File

@@ -41,9 +41,11 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUINOTEBOOK_BUTTON)
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)
IMPLEMENT_CLASS(wxAuiNotebook, wxControl)
IMPLEMENT_CLASS(wxAuiTabCtrl, wxControl)
IMPLEMENT_DYNAMIC_CLASS(wxAuiNotebookEvent, wxEvent)
@@ -1743,6 +1745,29 @@ bool wxAuiNotebook::InsertPage(size_t page_idx,
bool wxAuiNotebook::DeletePage(size_t page_idx)
{
wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
if (!RemovePage(page_idx))
return false;
// actually destroy the window now
if (wnd->IsKindOf(CLASSINFO(wxAuiMDIChildFrame)))
{
// delete the child frame with pending delete, as is
// customary with frame windows
if (!wxPendingDelete.Member(wnd))
wxPendingDelete.Append(wnd);
}
else
{
wnd->Destroy();
}
return true;
/*
wxWindow* wnd = m_tabs.GetWindowFromIdx(page_idx);
wxWindow* new_active = NULL;
// find out which onscreen tab ctrl owns this tab
@@ -1806,6 +1831,7 @@ bool wxAuiNotebook::DeletePage(size_t page_idx)
}
return true;
*/
}
@@ -1814,21 +1840,58 @@ bool wxAuiNotebook::DeletePage(size_t page_idx)
// but does not destroy the window
bool wxAuiNotebook::RemovePage(size_t page_idx)
{
// remove the tab from our own catalog
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())
{
new_active = ctrl->GetWindowFromIdx(new_idx);
}
else
{
// 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)
{
wxWindow* w = m_tabs.GetWindowFromIdx(i);
if (wnd != w)
{
new_active = m_tabs.GetWindowFromIdx(i);
break;
}
}
}
// remove the tab from main catalog
if (!m_tabs.RemovePage(wnd))
return false;
// remove the tab from the onscreen tab ctrl
wxAuiTabCtrl* ctrl;
int ctrl_idx;
if (FindTab(wnd, &ctrl, &ctrl_idx))
{
ctrl->RemovePage(wnd);
return true;
RemoveEmptyTabFrames();
// set new active pane
if (new_active)
{
m_curpage = -1;
SetSelection(m_tabs.GetIdxFromWindow(new_active));
}
return false;
return true;
}
// SetPageText() changes the tab caption of the specified page
@@ -2059,8 +2122,8 @@ void wxAuiNotebook::OnTabDragMotion(wxCommandEvent& evt)
wxPoint zero(0,0);
wxAuiTabCtrl* src_tabs = (wxAuiTabCtrl*)evt.GetEventObject();
wxAuiTabCtrl* dest_tabs = GetTabCtrlFromPoint(client_pt);
if (dest_tabs == src_tabs)
{
if (src_tabs)
@@ -2109,6 +2172,39 @@ void wxAuiNotebook::OnTabDragMotion(wxCommandEvent& evt)
}
// if external drag is allowed, check if the tab is being dragged
// over a different wxAuiNotebook control
if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
{
wxWindow* tab_ctrl = ::wxFindWindowAtPoint(screen_pt);
// if we are over a hint window, leave
if (tab_ctrl->IsKindOf(CLASSINFO(wxFrame)))
return;
while (tab_ctrl)
{
if (tab_ctrl->IsKindOf(CLASSINFO(wxAuiTabCtrl)))
break;
tab_ctrl = tab_ctrl->GetParent();
}
if (tab_ctrl)
{
wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
if (nb != this)
{
wxRect hint_rect = tab_ctrl->GetRect();
tab_ctrl->ClientToScreen(&hint_rect.x, &hint_rect.y);
m_mgr.ShowHint(hint_rect);
return;
}
}
}
// if tab moving is not allowed, leave
if (!(m_flags & wxAUI_NB_TAB_SPLIT))
{
@@ -2142,16 +2238,12 @@ void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
m_mgr.HideHint();
// if tab moving is not allowed, leave
if (!(m_flags & wxAUI_NB_TAB_SPLIT))
{
return;
}
// set cursor back to an arrow
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));
}
@@ -2160,10 +2252,97 @@ void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
wxPoint mouse_client_pt = ScreenToClient(mouse_screen_pt);
// the src tab control is the control that fired this event
wxAuiTabCtrl* dest_tabs = NULL;
// check for an external move
if (m_flags & wxAUI_NB_TAB_EXTERNAL_MOVE)
{
wxWindow* tab_ctrl = ::wxFindWindowAtPoint(mouse_screen_pt);
while (tab_ctrl)
{
if (tab_ctrl->IsKindOf(CLASSINFO(wxAuiTabCtrl)))
break;
tab_ctrl = tab_ctrl->GetParent();
}
if (tab_ctrl)
{
wxAuiNotebook* nb = (wxAuiNotebook*)tab_ctrl->GetParent();
if (nb != this)
{
// find out from the destination control
// if it's ok to drop this tab here
wxAuiNotebookEvent e(wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, m_windowId);
e.SetSelection(evt.GetSelection());
e.SetOldSelection(evt.GetSelection());
e.SetEventObject(this);
e.SetDragSource(this);
e.Veto(); // dropping must be explicitly approved by control owner
nb->GetEventHandler()->ProcessEvent(e);
if (!e.IsAllowed())
{
// no answer or negative answer
m_mgr.HideHint();
return;
}
// drop was allowed
int src_idx = evt.GetSelection();
wxWindow* src_page = src_tabs->GetWindowFromIdx(src_idx);
// get main index of the page
int main_idx = m_tabs.GetIdxFromWindow(src_page);
// make a copy of the page info
wxAuiNotebookPage page_info = m_tabs.GetPage((size_t)main_idx);
// remove the page from the source notebook
RemovePage(main_idx);
// reparent the page
src_page->Reparent(nb);
// found out the insert idx
wxAuiTabCtrl* dest_tabs = (wxAuiTabCtrl*)tab_ctrl;
wxPoint pt = dest_tabs->ScreenToClient(mouse_screen_pt);
wxWindow* target = NULL;
int insert_idx = -1;
dest_tabs->TabHitTest(pt.x, pt.y, &target);
if (target)
{
insert_idx = dest_tabs->GetIdxFromWindow(target);
}
// add the page to the new notebook
if (insert_idx == -1)
insert_idx = dest_tabs->GetPageCount();
dest_tabs->InsertPage(page_info.window, page_info, insert_idx);
nb->m_tabs.AddPage(page_info.window, page_info);
nb->DoSizing();
dest_tabs->DoShowHide();
dest_tabs->Refresh();
// set the selection in the destination tab control
nb->SetSelection(nb->m_tabs.GetIdxFromWindow(page_info.window));
return;
}
}
}
// only perform a tab split if it's allowed
if (m_flags & wxAUI_NB_TAB_SPLIT)
{
// 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);
@@ -2233,6 +2412,7 @@ void wxAuiNotebook::OnTabEndDrag(wxCommandEvent& command_evt)
dest_tabs->Refresh();
SetSelection(m_tabs.GetIdxFromWindow(page_info.window));
}
}