bool cbAuiNotebook::LoadPerspective(const wxString& layout, bool mergeLayouts) { if (layout.IsEmpty()) return false; wxString tabs = layout.BeforeFirst (wxT ('@') ); // 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) { // only remove tabs that are in the layout-string, do not touch others, // so the layout of an already loaded workspace or project will not get destroyed, if the // current layout did not know the tab. The layout file which is loaded last takes precedence, // if there are two or more layout strings containing the actual tab. if ( tabs.Find( UniqueIdFromTooltip(GetPageToolTip(i)) ) < 0 ) continue; 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(); wxString currentLayout; if (mergeLayouts) { currentLayout = m_mgr.SavePerspective(); wxString tempLayout; while (!currentLayout.empty()) { if ( currentLayout.BeforeFirst('|').StartsWith(_("layout2")) || currentLayout.BeforeFirst('|').StartsWith(_("name=dummy")) ) { currentLayout = currentLayout.AfterFirst(('|')); currentLayout.Trim(); currentLayout.Trim(true); } else { wxString pane_part = currentLayout.BeforeFirst('|'); pane_part.Trim(); pane_part.Trim(true); if (!pane_part.empty()) tempLayout += pane_part + wxT("|"); currentLayout = currentLayout.AfterFirst('|'); currentLayout.Trim(); currentLayout.Trim(true); } } currentLayout = tempLayout; if (currentLayout.empty()) mergeLayouts = false; } size_t sel_page = 0; int active_tab = 0; bool found = false; wxString frames = layout.AfterFirst (wxT ('@') ); // if we load an additional project to an exiting layout, the first new tab always goes into a new frame bool firstTabInCtrl =! currentLayout.empty(); // This creates a new tabframe if none exists; a workaround, because we can not directly access // the needed wxTabFrame class, because it is not exported. // This also takes care of all needed pane-info wxAuiTabCtrl* dest_tabs = GetActiveTabCtrl(); 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 wxString pane_name = tab_part.BeforeFirst(wxT('=')); // create a new tab frame #if wxCHECK_VERSION(3, 0, 0) m_curPage = -1; #else m_curpage = -1; #endif // 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(',')); wxString name = tab.AfterFirst(wxT(';')); tab = tab.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); // Move tab to pane const int index_in_m_tabs = GetTabIndexFromTooltip(name); if (index_in_m_tabs < 0) continue; wxAuiNotebookPage& page = m_tabs.GetPage(index_in_m_tabs); // save the actual active tab, because it will be set to 0 after a Split() active_tab = dest_tabs->GetActivePage(); 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 = index_in_m_tabs; // If we should be the first tab in a tab-ctrl we switch to the next existing tab, // or create a new one by calling Split() and update the dest_tabs accordingly. if (firstTabInCtrl) { int nextIndex = m_TabCtrls.Index(dest_tabs) + 1; if (nextIndex == 0 || nextIndex >= static_cast<int>(m_TabCtrls.GetCount())) { Split(index_in_m_tabs, wxRIGHT); // reset the active tab, because a Split() set it to zero dest_tabs->SetActivePage(active_tab); dest_tabs = GetActiveTabCtrl(); } else dest_tabs = m_TabCtrls.Item(nextIndex); } // Change the pane name to the one we have stored in the layout-string. wxAuiPaneInfo& pane = m_mgr.GetPane( GetTabFrameFromTabCtrl(dest_tabs) ); if (pane.name != pane_name) { tab.Replace(pane_name, pane.name); frames.Replace(pane_name, pane.name); pane_name = pane.name; } firstTabInCtrl = false; found = true; } // We come here after at least one tabctrl is filled, so the next tab should go in a new one firstTabInCtrl = true; tabs = tabs.AfterFirst(wxT('|')); } // Check for windows not readded to the notebook and add the at the end. for (size_t i = 0; i < tab_count; ++i) { wxAuiNotebookPage& page = m_tabs.GetPage(i); // find out which onscreen tab ctrl owns this tab // if none then add it to the last used tabctrl wxAuiTabCtrl* ctrl; int ctrl_idx; if ( !FindTab(page.window, &ctrl, &ctrl_idx) ) { const size_t newpage_idx = dest_tabs->GetPageCount(); dest_tabs->InsertPage (page.window, page, newpage_idx); } } if (mergeLayouts) { wxRegEx reDockSize(_T("(dock_size[()0-9,]+=)[0-9]+")); const wxString replacement(wxT("\\1-1")); // Make a centered frame left docked frames.Replace(wxString::Format(wxT("dock_size(%d"), wxAUI_DOCK_CENTER), wxString::Format(wxT("dock_size(%d"), wxAUI_DOCK_LEFT)); frames.Replace(wxString::Format(wxT("dir=%d"), wxAUI_DOCK_CENTER), wxString::Format(wxT("dir=%d"), wxAUI_DOCK_LEFT)); if (reDockSize.Matches(frames)) reDockSize.ReplaceAll(&frames,replacement); if (reDockSize.Matches(currentLayout)) reDockSize.ReplaceAll(¤tLayout,replacement); while (!currentLayout.empty()) { wxString pane_part = currentLayout.BeforeFirst('|'); pane_part.Trim(); pane_part.Trim(true); if (!pane_part.empty()) frames += pane_part + wxT("|"); currentLayout = currentLayout.AfterFirst('|'); currentLayout.Trim(); currentLayout.Trim(true); } } if (found) m_mgr.LoadPerspective(frames); RemoveEmptyTabFrames(); // Force refresh of selection #if wxCHECK_VERSION(3, 0, 0) m_curPage = -1; #else m_curpage = -1; #endif SetSelection(sel_page); UpdateTabControlsArray(); return true; }
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; }