Find file
Fetching contributors…
Cannot retrieve contributors at this time
278 lines (220 sloc) 7.48 KB
#include "eauibook.h"
#include <wx/log.h>
BEGIN_EVENT_TABLE(eAuiNotebook, wxAuiNotebook)
EVT_MOUSEWHEEL(eAuiNotebook::OnMouseWheel)
END_EVENT_TABLE()
// This class redefined here as a workaround for not having
// access to the original wxTabFrame definition in auibook.cpp
// Doing it like this is a fragile hack, but it lets us
// avoid patching wxWidgets.
class wxTabFrame : public wxWindow
{
public:
wxTabFrame();
~wxTabFrame();
void SetTabCtrlHeight(int h)
{
m_tab_ctrl_height = h;
}
void DoSetSize(int x, int y,
int width, int height,
int WXUNUSED(sizeFlags = wxSIZE_AUTO));
void DoGetClientSize(int* x, int* y) const;
bool Show( bool WXUNUSED(show = true) );
void DoSizing();
void DoGetSize(int* x, int* y) const;
void Update();
public:
wxRect m_rect;
wxRect m_tab_rect;
wxAuiTabCtrl* m_tabs;
int m_tab_ctrl_height;
};
// Constructor
eAuiNotebook::eAuiNotebook(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style):
wxAuiNotebook(parent, id, pos, size, style) {}
// Convert page index to tab position
int eAuiNotebook::PageToTab(size_t page_idx) {
wxWindow* page = m_tabs.GetWindowFromIdx(page_idx);
wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
const size_t pane_count = all_panes.GetCount();
size_t offset = 0;
for (size_t i = 0; i < pane_count; ++i)
{
if (all_panes.Item(i).name == wxT("dummy"))
continue;
wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
const int page_idx = tabframe->m_tabs->GetIdxFromWindow(page);
if (page_idx != -1)
return offset + page_idx;
offset += tabframe->m_tabs->GetPageCount();
}
wxASSERT(false); // invalid page_idx
return -1;
}
// Convert tab position to page index
int eAuiNotebook::TabToPage(size_t tab_idx) {
wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
const size_t pane_count = all_panes.GetCount();
size_t offset = 0;
for (size_t i = 0; i < pane_count; ++i)
{
if (all_panes.Item(i).name == wxT("dummy"))
continue;
wxTabFrame* tabframe = (wxTabFrame*)all_panes.Item(i).window;
const size_t tab_count = tabframe->m_tabs->GetPageCount();
if (offset + tab_count <= tab_idx) offset += tab_count;
else {
wxWindow* page = tabframe->m_tabs->GetWindowFromIdx(tab_idx-offset);
return m_tabs.GetIdxFromWindow(page);
}
}
wxASSERT(false); // we should never reach here
return -1;
}
wxString eAuiNotebook::SavePerspective() {
// Build list of panes/tabs
wxString tabs;
wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
const size_t pane_count = all_panes.GetCount();
for (size_t i = 0; i < pane_count; ++i)
{
wxAuiPaneInfo& pane = all_panes.Item(i);
if (pane.name == wxT("dummy"))
continue;
wxTabFrame* tabframe = (wxTabFrame*)pane.window;
if (!tabs.empty()) tabs += wxT("|");
tabs += pane.name;
tabs += wxT("=");
// add tab id's
size_t page_count = tabframe->m_tabs->GetPageCount();
for (size_t p = 0; p < page_count; ++p)
{
wxAuiNotebookPage& page = tabframe->m_tabs->GetPage(p);
const size_t page_idx = m_tabs.GetIdxFromWindow(page.window);
if (p) tabs += wxT(",");
if ((int)page_idx == m_curpage) tabs += wxT("*");
else if ((int)p == tabframe->m_tabs->GetActivePage()) tabs += wxT("+");
tabs += wxString::Format(wxT("%u"), page_idx);
}
}
tabs += wxT("@");
// Add frame perspective
tabs += m_mgr.SavePerspective();
return tabs;
}
bool eAuiNotebook::LoadPerspective(const wxString& layout) {
// Remove all tab ctrls (but still keep them in main index)
const size_t tab_count = m_tabs.GetPageCount();
for (size_t i = 0; i < tab_count; ++i) {
wxWindow* wnd = m_tabs.GetWindowFromIdx(i);
// find out which onscreen tab ctrl owns this tab
wxAuiTabCtrl* ctrl;
int ctrl_idx;
if (!FindTab(wnd, &ctrl, &ctrl_idx))
return false;
// remove the tab from ctrl
if (!ctrl->RemovePage(wnd))
return false;
}
RemoveEmptyTabFrames();
size_t sel_page = 0;
wxString tabs = layout.BeforeFirst(wxT('@'));
while (1)
{
const wxString tab_part = tabs.BeforeFirst(wxT('|'));
// if the string is empty, we're done parsing
if (tab_part.empty())
break;
// Get pane name
const wxString pane_name = tab_part.BeforeFirst(wxT('='));
// create a new tab frame
wxTabFrame* new_tabs = new wxTabFrame;
new_tabs->m_tabs = new wxAuiTabCtrl(this,
m_tab_id_counter++,
wxDefaultPosition,
wxDefaultSize,
wxNO_BORDER|wxWANTS_CHARS);
new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
new_tabs->m_tabs->SetFlags(m_flags);
wxAuiTabCtrl *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().Name(pane_name).Bottom().CaptionVisible(false);
m_mgr.AddPane(new_tabs, pane_info);
// Get list of tab id's and move them to pane
wxString tab_list = tab_part.AfterFirst(wxT('='));
while(1) {
wxString tab = tab_list.BeforeFirst(wxT(','));
if (tab.empty()) break;
tab_list = tab_list.AfterFirst(wxT(','));
// Check if this page has an 'active' marker
const wxChar c = tab[0];
if (c == wxT('+') || c == wxT('*')) {
tab = tab.Mid(1);
}
const size_t tab_idx = wxAtoi(tab.c_str());
if (tab_idx >= GetPageCount()) continue;
// Move tab to pane
wxAuiNotebookPage& page = m_tabs.GetPage(tab_idx);
const size_t newpage_idx = dest_tabs->GetPageCount();
dest_tabs->InsertPage(page.window, page, newpage_idx);
if (c == wxT('+')) dest_tabs->SetActivePage(newpage_idx);
else if ( c == wxT('*')) sel_page = tab_idx;
}
dest_tabs->DoShowHide();
tabs = tabs.AfterFirst(wxT('|'));
}
// Load the frame perspective
const wxString frames = layout.AfterFirst(wxT('@'));
m_mgr.LoadPerspective(frames);
// Force refresh of selection
m_curpage = -1;
SetSelection(sel_page);
return true;
}
// This code is based largely on the following patch, but modified to work with the wrap_around parameter
// http://trac.wxwidgets.org/attachment/ticket/10848/wxAuiNotebook.patch
void eAuiNotebook::ChangeTab(bool forward, bool wrap_around) {
if (GetPageCount() <= 1) return;
int currentSelection = this->GetSelection();
wxAuiTabCtrl* tabCtrl = 0;
int idx = -1;
if(!FindTab(GetPage(currentSelection), &tabCtrl, &idx)) return;
if(!tabCtrl || idx < 0) return;
wxWindow* page = 0;
int pageCount = tabCtrl->GetPageCount();
forward ? idx++ : idx--;
if(idx < 0) {
idx = wrap_around ? pageCount - 1 : 0;
} else if(idx >= pageCount) {
idx = wrap_around ? 0 : pageCount-1;
}
page = tabCtrl->GetPage(idx).window;
if(page) {
currentSelection = GetPageIndex(page);
SetSelection(currentSelection);
}
}
void eAuiNotebook::SelectNextTab(bool wrap_around) {
ChangeTab(true, wrap_around);
}
void eAuiNotebook::SelectPrevTab(bool wrap_around) {
ChangeTab(false, wrap_around);
}
void eAuiNotebook::OnMouseWheel(wxMouseEvent& event) {
const wxCoord x = event.GetX();
const wxCoord y = event.GetY();
bool hit = ((0 <= y) && (y < this->m_tab_ctrl_height) &&
(0 <= x) && (x < this->GetSize().GetWidth()));
if (!hit) {
event.Skip(true);
return;
}
const int rotation = event.GetWheelRotation();
wxLogDebug(_("Rotation: %d"), rotation);
// Don't use wrap-around tab selection when mouse-wheeling
if (rotation < 0) SelectNextTab(false);
else if (rotation > 0) SelectPrevTab(false);
}