int cbAuiNotebook::GetTabPositionFromIndex(int index) { if (GetPageCount() <= 0) return wxNOT_FOUND; UpdateTabControlsArray(); wxAuiTabCtrl* tabCtrl = nullptr; int idx = -1; if (!FindTab(GetPage(index), &tabCtrl, &idx)) return wxNOT_FOUND; if (!tabCtrl || idx < 0) return wxNOT_FOUND; int indexOffset = 0; 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[i]; if (pane.name == wxT("dummy")) continue; if (pane.window == GetTabFrameFromTabCtrl(tabCtrl)) break; for (size_t j = 0; j < m_TabCtrls.GetCount(); ++j) { if (pane.window == GetTabFrameFromTabCtrl(m_TabCtrls[j])) { indexOffset += m_TabCtrls[j]->GetPageCount(); break; } } } return idx + indexOffset; }
void tpanelnotebook::FillWindowLayout(unsigned int mainframeindex) { wxAuiPaneInfoArray &all_panes = m_mgr.GetAllPanes(); size_t pane_count = all_panes.GetCount(); size_t pagecount = GetPageCount(); for (size_t i = 0; i < pagecount; ++i) { tpanelparentwin_nt *tppw = dynamic_cast<tpanelparentwin_nt*>(GetPage(i)); if (!tppw) continue; wxAuiTabCtrl* tc; int tabindex; if (!FindTab(tppw, &tc, &tabindex)) continue; wxWindow *tabframe = GetTabFrameFromTabCtrl(tc); if (!tabframe) continue; unsigned int splitindex = 0; bool found = false; for (size_t j = 0; j < pane_count; ++j) { if (all_panes.Item(j).name == wxT("dummy")) { continue; } if (all_panes.Item(j).window == tabframe) { found = true; break; } else { splitindex++; } } if (!found) continue; ad.twinlayout.emplace_back(); twin_layout_desc &twld = ad.twinlayout.back(); twld.mainframeindex = mainframeindex; twld.splitindex = splitindex; twld.tabindex = tabindex; auto tp = tppw->pimpl()->tp_base; twld.tpautos = tp->tpautos; twld.tpudcautos = tp->tpudcautos; twld.name = tp->name; twld.dispname = tp->dispname; twld.flags = tp->flags; twld.intersect_flags = tppw->pimpl()->intersect_flags; twld.tppw_flags = tppw->pimpl()->tppw_flags & TPPWF::DB_SAVE_MASK; } }
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; }
wxString cbAuiNotebook::SavePerspective(const wxString projectTitle) { // Build list of panes/tabs wxString tabs, tabsTmp; wxArrayString panes; // first get all tab-controls UpdateTabControlsArray(); 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; wxAuiTabCtrl* tabCtrl = nullptr; for (size_t j = 0; j < m_TabCtrls.GetCount(); ++j) { if (pane.window == GetTabFrameFromTabCtrl(m_TabCtrls.Item(j))) { tabCtrl = m_TabCtrls.Item(j); break; } } if (tabCtrl) { tabsTmp.Clear(); // add tab id's size_t page_count = tabCtrl->GetPageCount(); for (size_t p = 0; p < page_count; ++p) { wxAuiNotebookPage& page = tabCtrl->GetPage(p); const size_t page_idx = m_tabs.GetIdxFromWindow(page.window); wxString id = UniqueIdFromTooltip(GetPageToolTip(page_idx)); // file does not belong to any project, so don't save if (id.BeforeLast(':').empty()) continue; // if we save a project (projectTitle non empty), but file does not belong to the project // skip it if (!projectTitle.empty() && id.BeforeLast(':') != projectTitle) continue; if (!tabsTmp.empty()) tabsTmp += wxT(","); #if wxCHECK_VERSION(3, 0, 0) if ((int)page_idx == m_curPage) #else if ((int)page_idx == m_curpage) #endif tabsTmp += wxT("*"); else if ((int)p == tabCtrl->GetActivePage()) tabsTmp += wxT("+"); tabsTmp += wxString::Format(wxT("%lu"), static_cast<unsigned long>(page_idx)); tabsTmp += wxT(";"); tabsTmp += id; } if (!tabsTmp.empty()) { if (!tabs.empty()) tabs += wxT("|"); panes.Add(pane.name); tabs += pane.name; tabs += wxT("="); tabs += tabsTmp; } } } tabs += wxT("@"); tabsTmp = m_mgr.SavePerspective(); wxArrayString arTabsTmp = GetArrayFromString(tabsTmp, wxT("|")); for (size_t i = arTabsTmp.GetCount(); i > 0 ; ) { if (arTabsTmp.Item(--i).StartsWith(wxT("name="))) { wxString strTmp = arTabsTmp.Item(i).AfterFirst('=').BeforeFirst(';'); if (strTmp == wxT("dummy")) continue; if (panes.Index(strTmp) < 0) arTabsTmp.RemoveAt(i); } } tabsTmp = GetStringFromArray(arTabsTmp, wxT("|")); // Add frame perspective tabs += tabsTmp; return tabs; }