Code::Blocks  SVN r11506
cbauibook.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 11431 $
6  * $Id: cbauibook.cpp 11431 2018-08-04 05:40:37Z ollydbg $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/cbauibook.cpp $
8  */
9 
10 
11 #include "sdk_precomp.h"
12 
13 #ifndef CB_PRECOMP
14  #include "cbauibook.h"
15  #include "cbeditor.h"
16  #include "cbproject.h"
17  #include "configmanager.h"
18  #include "editormanager.h"
19  #include "manager.h"
20  #include "projectmanager.h"
21 
22  #include <wx/app.h>
23  #include <wx/dcclient.h>
24  #include <wx/regex.h>
25 #endif
26 
27 #include <wx/tooltip.h>
28 #include <wx/wupdlock.h>
29 
30 // static
32 cbAuiNotebookArray cbAuiNotebook::s_cbAuiNotebookArray;
33 wxString cbAuiNotebook::s_modKeys = _T("Ctrl");
37 
38 
39 BEGIN_EVENT_TABLE(cbAuiNotebook, wxAuiNotebook)
40 #if wxCHECK_VERSION(3, 0, 0)
41  EVT_NAVIGATION_KEY(cbAuiNotebook::OnNavigationKeyNotebook)
42 #else
43  EVT_NAVIGATION_KEY(cbAuiNotebook::OnNavigationKey)
44 #endif
45  EVT_IDLE(cbAuiNotebook::OnIdle)
46  EVT_AUINOTEBOOK_DRAG_DONE(wxID_ANY, cbAuiNotebook::OnDragDone)
47 END_EVENT_TABLE()
48 
49 cbAuiNotebook::cbAuiNotebook(wxWindow* pParent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
50  : wxAuiNotebook(pParent, id, pos, size, style),
51 #ifdef __WXMSW__
52  m_LastSelected(wxNOT_FOUND),
53  m_LastId(0),
54 #endif
55 #if !wxCHECK_VERSION(3, 0, 0)
56  m_HasToolTip(false),
57 #endif
58  m_SetZoomOnIdle(false),
59  m_MinimizeFreeSpaceOnIdle(false),
60  m_TabCtrlSize(wxDefaultSize)
61 {
62  //ctor
63 #ifdef __WXGTK__
64  m_mgr.SetFlags((m_mgr.GetFlags() | wxAUI_MGR_VENETIAN_BLINDS_HINT) & ~wxAUI_MGR_TRANSPARENT_HINT);
65 #endif // #ifdef __WXGTK__
67 #if defined __WXMSW__ && wxCHECK_VERSION(3, 0, 0)
69 #endif
70  s_AllowMousewheel = cfg->ReadBool(_T("/environment/tabs_use_mousewheel"),true);
71  s_modKeys = cfg->Read(_T("/environment/tabs_mousewheel_modifier"),_T("Ctrl"));
72  s_modToAdvance = cfg->ReadBool(_T("/environment/tabs_mousewheel_advance"),false);
73  cbAuiNotebook::InvertAdvanceDirection(cfg->ReadBool(_T("/environment/tabs_invert_advance"),false));
74  cbAuiNotebook::InvertMoveDirection(cfg->ReadBool(_T("/environment/tabs_invert_move"),false));
75 
76  if (s_cbAuiNotebookArray.Index(this) == wxNOT_FOUND)
77  s_cbAuiNotebookArray.Add(this);
78 }
79 
81 {
82  s_cbAuiNotebookArray.Remove(this);
83 }
84 
86 {
87  bool result = true;
88  // this search must be case-insensitive
89  wxString str = s_modKeys;
90  str.MakeUpper();
91 
92  if (result && str.Contains(wxT("ALT")))
93  result = wxGetKeyState(WXK_ALT);
94  if (result && str.Contains(wxT("CTRL")))
95  result = wxGetKeyState(WXK_CONTROL);
96 #if defined(__WXMAC__) || defined(__WXCOCOA__)
97  if (result && str.Contains(wxT("XCTRL")))
98  result = wxGetKeyState(WXK_COMMAND);
99 #endif
100  if (result && str.Contains(wxT("SHIFT")))
101  result = wxGetKeyState(WXK_SHIFT);
102  return result;
103 }
104 
106 {
107  cbAuiTabCtrlArray saveTabCtrls = m_TabCtrls;
108  m_TabCtrls.Clear();
109  // first get all tab-controls
110  const size_t tab_Count = GetPageCount();
111  for (size_t i = 0; i < tab_Count; ++i)
112  {
113  wxAuiTabCtrl* tabCtrl = nullptr;
114  int idx = -1;
115  if (FindTab(GetPage(i), &tabCtrl, &idx))
116  {
117  if (tabCtrl && m_TabCtrls.Index(tabCtrl) == wxNOT_FOUND)
118  m_TabCtrls.Add(tabCtrl);
119  }
120  else
121  continue;
122  }
123  bool needEventRebind = m_TabCtrls.GetCount() != saveTabCtrls.GetCount();
124  if (!needEventRebind)
125  {
126  for (size_t i = 0; i < m_TabCtrls.GetCount(); ++i)
127  {
128  if (saveTabCtrls.Index(m_TabCtrls[i]) == wxNOT_FOUND)
129  {
130  needEventRebind = true;
131  break;
132  }
133  }
134  }
135  if (needEventRebind)
136  {
138  }
139  // make sure the active page is valid and shown
140  for (size_t i = 0; i < m_TabCtrls.GetCount(); ++i)
141  {
142  int pageCount = m_TabCtrls[i]->GetPageCount();
143  if (m_TabCtrls[i]->GetActivePage() < 0 && pageCount > 0)
144  m_TabCtrls[i]->SetActivePage((size_t)0);
145  if (m_TabCtrls[i]->GetActivePage() >= pageCount && pageCount > 0)
146  m_TabCtrls[i]->SetActivePage(pageCount - 1);
147  m_TabCtrls[i]->DoShowHide();
148  }
149 }
150 
152 {
153  for (size_t i = 0; i < m_TabCtrls.GetCount(); ++i)
154  {
155 #if !wxCHECK_VERSION(3, 0, 0)
156  m_TabCtrls[i]->Disconnect(wxEVT_MOTION, wxMouseEventHandler(cbAuiNotebook::OnMotion));
157  m_TabCtrls[i]->Connect(wxEVT_MOTION , wxMouseEventHandler(cbAuiNotebook::OnMotion));
158 #endif
159  m_TabCtrls[i]->Disconnect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(cbAuiNotebook::OnTabCtrlDblClick));
160  m_TabCtrls[i]->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(cbAuiNotebook::OnTabCtrlDblClick));
161  m_TabCtrls[i]->Disconnect(wxEVT_SIZE, wxSizeEventHandler(cbAuiNotebook::OnResize));
162  m_TabCtrls[i]->Connect(wxEVT_SIZE, wxSizeEventHandler(cbAuiNotebook::OnResize));
163  m_TabCtrls[i]->Disconnect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(cbAuiNotebook::OnTabCtrlMouseWheel));
164 #ifdef __WXMSW__
165  m_TabCtrls[i]->Disconnect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(cbAuiNotebook::OnEnterTabCtrl));
166  m_TabCtrls[i]->Disconnect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(cbAuiNotebook::OnLeaveTabCtrl));
167 #endif
168  if (GetPageCount() > 1)
169  {
170  if (s_AllowMousewheel)
171  m_TabCtrls[i]->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(cbAuiNotebook::OnTabCtrlMouseWheel));
172 #ifdef __WXMSW__
173  m_TabCtrls[i]->Connect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(cbAuiNotebook::OnEnterTabCtrl));
174  m_TabCtrls[i]->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(cbAuiNotebook::OnLeaveTabCtrl));
175 #endif
176  }
177  }
178 }
179 
181 {
183  int sel = GetSelection();
184  if (sel < 0)
185  return;
186 
187  wxWindow* wnd = GetPage(static_cast<size_t>(sel));
188  if (!wnd)
189  return;
190 
191  for (size_t i = 0; i < m_TabCtrls.GetCount(); ++i)
192  {
193  wxWindow* win = m_TabCtrls[i]->GetWindowFromIdx(m_TabCtrls[i]->GetActivePage());
194  if (win && (win == wnd))
195  {
196  m_TabCtrls[i]->SetFocus();
197  break;
198  }
199  }
200 }
201 
203 {
204  if (page)
205  {
206  wxAuiTabCtrl *tabCtrl = nullptr;
207  int idx;
208  if (!FindTab(page, &tabCtrl, &idx))
209  return nullptr;
210  return tabCtrl;
211  }
212  else
213  return GetActiveTabCtrl();
214 }
215 
216 void cbAuiNotebook::GetPagesInTabCtrl(std::vector<wxWindow*> &result, wxWindow *page)
217 {
218  result.clear();
219  wxAuiTabCtrl* tabCtrl = GetTabCtrl(page);
220  if (tabCtrl)
221  {
222  int count = tabCtrl->GetPageCount();
223  for (int ii = 0; ii < count; ++ii)
224  result.push_back(tabCtrl->GetPage(ii).window);
225  }
226 }
227 
229 {
230  // we only set zoom-factor for active (visible) tabs,
231  // all others are set if system is idle
233  for (size_t i = 0; i < m_TabCtrls.GetCount(); ++i)
234  {
235  wxWindow* win = m_TabCtrls[i]->GetWindowFromIdx(m_TabCtrls[i]->GetActivePage());
236  if (win && static_cast<EditorBase*>(win)->IsBuiltinEditor())
237  static_cast<cbEditor*>(win)->SetZoom(zoom);
238  }
239  m_SetZoomOnIdle = true;
240 }
241 
242 void cbAuiNotebook::OnIdle(cb_unused wxIdleEvent& event)
243 {
244  if (m_SetZoomOnIdle)
245  {
246  m_SetZoomOnIdle = false;
247  int zoom = Manager::Get()->GetEditorManager()->GetZoom();
248  for (size_t i = 0; i < GetPageCount(); ++i)
249  {
250  wxWindow* win = GetPage(i);
251  if (win && static_cast<EditorBase*>(win)->IsBuiltinEditor())
252  static_cast<cbEditor*>(win)->SetZoom(zoom);
253  }
254  }
255 
257  {
260  for (size_t i = 0; i < m_TabCtrls.GetCount(); ++i)
262  }
263 
264 }
265 
267 {
269 }
270 
271 #ifdef __WXMSW__
273 {
274  if (!wxTheApp->IsActive())
275  return;
276 
277  wxAuiTabCtrl* tabCtrl = (wxAuiTabCtrl*)event.GetEventObject();
278  if (tabCtrl)
279  {
280  cbAuiNotebook* nb = (cbAuiNotebook*)tabCtrl->GetParent();
281  if (nb)
282  {
283  if ( s_AllowMousewheel
284  && (nb->m_LastSelected == wxNOT_FOUND)
285  && (nb->m_LastId == 0) )
286  {
287  nb->StoreFocus();
288  tabCtrl->SetFocus();
289  }
290  }
291  }
292 }
293 
295 {
296  if (!wxTheApp->IsActive())
297  return;
298 
299  wxAuiTabCtrl* tabCtrl = (wxAuiTabCtrl*)event.GetEventObject();
300  if (tabCtrl)
301  {
302  cbAuiNotebook* nb = (cbAuiNotebook*)tabCtrl->GetParent();
303  if (nb)
304  nb->RestoreFocus();
305  }
306 
307 }
308 
310 {
311  wxWindow* win = FindWindowById(m_LastId);
312  while (win)
313  {
314  if (win == page)
315  return true;
316  win = win->GetParent();
317  }
318  return false;
319 }
320 
322 {
323  // save Id of last focused window and last selected tab
324  wxWindow* win = wxWindow::FindFocus();
325  if (win)
326  m_LastId = win->GetId();
327  else
328  m_LastId = 0;
330 }
331 
333 {
334  // if selected tab has changed, we set the focus on the window it belongs too
336  {
337  wxWindow* win = GetPage(GetSelection());
338  if (win)
339  win->SetFocus();
340  }
341  // otherwise, we restore the former focus, if the window
342  // with the saved Id still exists
343  else if (m_LastId != 0)
344  {
345  wxWindow* win = FindWindowById(m_LastId);
346  if (win)
347  win->SetFocus();
348  }
350  m_LastId = 0;
351 }
352 #endif // #ifdef __WXMSW__
353 
355 {
356  wxWindow* win = nullptr;
357  wxAuiTabCtrl* tabCtrl = (wxAuiTabCtrl*)event.GetEventObject();
358  if (tabCtrl && tabCtrl->TabHitTest(event.GetX(), event.GetY(), &win))
359  {
360  if (win != nullptr)
361  {
362  // send double-click-event
363  CodeBlocksEvent theEvent(cbEVT_CBAUIBOOK_LEFT_DCLICK, GetParent()->GetId());
364  theEvent.SetEventObject(win);
365  GetParent()->GetEventHandler()->ProcessEvent(theEvent);
366  }
367  }
368 }
369 
371 {
372  wxAuiTabCtrl* tabCtrl = (wxAuiTabCtrl*)event.GetEventObject();
373  if (!tabCtrl)
374  return;
375  cbAuiNotebook* nb = (cbAuiNotebook*)tabCtrl->GetParent();
376  if (!nb)
377  return;
378 
379  nb->SetSelection(nb->GetPageIndex(tabCtrl->GetWindowFromIdx(tabCtrl->GetActivePage())));
380 
381  bool modkeys = CheckKeyModifier();
382 
383  bool advance = (!s_modToAdvance && !modkeys) || (s_modToAdvance && modkeys);
384 
385  if (advance)
387  else
388  {
389  size_t tabOffset = tabCtrl->GetTabOffset();
390  size_t lastTabIdx = tabCtrl->GetPageCount()-1;
391  wxWindow* win = nb->GetPage(nb->GetSelection());
392  if (win)
393  {
394  wxClientDC dc(win);
395  if ((event.GetWheelRotation() * s_moveDirection) > 0)
396  {
397  if (!tabCtrl->IsTabVisible(lastTabIdx,tabOffset,&dc,win))
398  tabOffset++;
399  }
400  else
401  {
402  if (tabOffset > 0)
403  tabOffset--;
404  }
405  tabCtrl->SetTabOffset(tabOffset);
406  nb->Refresh();
407  }
408  }
409 }
410 
412 {
413  wxAuiTabCtrl* tabCtrl = (wxAuiTabCtrl*)event.GetEventObject();
414  if (tabCtrl)
415  {
416  cbAuiNotebook* nb = (cbAuiNotebook*)tabCtrl->GetParent();
417  if (nb)
418  {
419  if (nb->m_TabCtrlSize != event.GetSize())
420  {
421  nb->m_TabCtrlSize = event.GetSize();
422  nb->MinimizeFreeSpace();
423  }
424  }
425  }
426  event.Skip();
427 }
428 
429 #if !wxCHECK_VERSION(3, 0, 0)
430 void cbAuiNotebook::OnMotion(wxMouseEvent& event)
431 {
432  event.Skip();
433  wxAuiTabCtrl* tabCtrl = (wxAuiTabCtrl*)event.GetEventObject();
434  if (!tabCtrl)
435  return;
436  cbAuiNotebook* nb = (cbAuiNotebook*)tabCtrl->GetParent();
437  if (!nb || !nb->m_HasToolTip)
438  return;
439 
440  wxWindow* win = nullptr;
441  if (event.Moving() && tabCtrl->TabHitTest(event.m_x, event.m_y, &win))
442  {
443  if (!win)
444  {
445  tabCtrl->UnsetToolTip();
446  return;
447  }
448  wxString text(win->GetName());
449  // If the text changes, set it else, keep old, to avoid
450  // 'moving tooltip' effect
451  wxToolTip* tooltip = tabCtrl->GetToolTip();
452  if (!tooltip || tooltip->GetTip() != text)
453  tabCtrl->SetToolTip(text);
454  }
455  else
456  tabCtrl->UnsetToolTip();
457 }
458 
459 bool cbAuiNotebook::SetPageToolTip(size_t idx, const wxString & text)
460 {
461  if (!m_HasToolTip)
463 
464  m_HasToolTip = true;
465  wxWindow* win = GetPage(idx);
466  if (win && win->GetName() != text)
467  win->SetName(text);
468  else
469  return false;
470  return true;
471 }
473 {
474  wxWindow* win = GetPage(idx);
475  if (win)
476  return win->GetName();
477  return wxEmptyString;
478 }
479 #endif
481 {
482  if (GetPageCount() < 2)
483  return;
485 }
486 
487 void cbAuiNotebook::MinimizeFreeSpace(wxAuiTabCtrl* tabCtrl)
488 {
489  if (!tabCtrl || tabCtrl->GetPageCount() < 2 || !IsWindowReallyShown(this))
490  return;
491 
492  int ctrl_idx = tabCtrl->GetActivePage();
493  wxWindow* win = GetPage(ctrl_idx);
494  if (win)
495  {
496  int tabOffset = tabCtrl->GetTabOffset();
497 
498  wxClientDC dc(win);
499  size_t lastTabIdx = tabCtrl->GetPageCount() - 1;
500 
501  if (!tabCtrl->IsTabVisible(ctrl_idx, tabOffset, & dc, win))
502  {
503  for (int i = lastTabIdx ; i >= 0; --i)
504  {
505  if (tabCtrl->IsTabVisible(ctrl_idx, i, & dc, win))
506  {
507  tabOffset = i;
508  break;
509  }
510  }
511  }
512  while (tabOffset > 0 && tabCtrl->IsTabVisible(lastTabIdx, tabOffset-1, & dc, win))
513  --tabOffset;
514 
515  tabCtrl->SetTabOffset(tabOffset);
516  }
517  tabCtrl->Refresh();
518 }
519 
520 bool cbAuiNotebook::DeletePage(size_t page)
521 {
522 #ifdef __WXMSW__
523  if (IsFocusStored(GetPage(page)))
524  {
526  m_LastId = 0;
527  }
528 #endif // #ifdef __WXMSW__
529  bool result = wxAuiNotebook::DeletePage(page);
531  return result;
532 }
533 
534 bool cbAuiNotebook::RemovePage(size_t page)
535 {
536 #ifdef __WXMSW__
537  if (IsFocusStored(GetPage(page)))
538  {
540  m_LastId = 0;
541  }
542 #endif // #ifdef __WXMSW__
543  bool result = wxAuiNotebook::RemovePage(page);
545  return result;
546 }
547 
548 bool cbAuiNotebook::MovePage(wxWindow* page, size_t new_idx)
549 {
551  bool result = false;
552  if (m_TabCtrls.GetCount() > 0)
553  {
554  result = m_TabCtrls[0]->MovePage(page, new_idx);
555  Refresh();
557  }
558  return result;
559 }
560 
562  const wxString& caption,
563  bool select,
564  const wxBitmap& bitmap)
565 {
566  bool result = wxAuiNotebook::AddPage(page, caption, select, bitmap);
568  return result;
569 }
570 
571 bool cbAuiNotebook::InsertPage(size_t page_idx,
572  wxWindow* page,
573  const wxString& caption,
574  bool select,
575  const wxBitmap& bitmap)
576 {
577  bool result = wxAuiNotebook::InsertPage(page_idx, page, caption, select, bitmap);
579  return result;
580 }
581 
583 {
584  if (GetPageCount() <= 0)
585  return wxNOT_FOUND;
586 
588 
589  wxAuiTabCtrl* tabCtrl = nullptr;
590  int idx = -1;
591 
592  if (!FindTab(GetPage(index), &tabCtrl, &idx))
593  return wxNOT_FOUND;
594 
595  if (!tabCtrl || idx < 0)
596  return wxNOT_FOUND;
597 
598  int indexOffset = 0;
599  wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
600  const size_t pane_count = all_panes.GetCount();
601  for (size_t i = 0; i < pane_count; ++i)
602  {
603  wxAuiPaneInfo& pane = all_panes[i];
604  if (pane.name == wxT("dummy"))
605  continue;
606 
607  if (pane.window == GetTabFrameFromTabCtrl(tabCtrl))
608  break;
609 
610  for (size_t j = 0; j < m_TabCtrls.GetCount(); ++j)
611  {
612  if (pane.window == GetTabFrameFromTabCtrl(m_TabCtrls[j]))
613  {
614  indexOffset += m_TabCtrls[j]->GetPageCount();
615  break;
616  }
617  }
618  }
619  return idx + indexOffset;
620 }
621 
623 {
624  if (GetPageCount() <= 1)
625  return;
626 
627  int currentSelection = GetSelection();
628 
629  wxAuiTabCtrl* tabCtrl = nullptr;
630  int idx = -1;
631 
632  if (!FindTab(GetPage(currentSelection), &tabCtrl, &idx))
633  return;
634 
635  if (!tabCtrl || idx < 0)
636  return;
637 
638  wxWindow* page = nullptr;
639  size_t maxPages = tabCtrl->GetPageCount();
640 
641  forward?idx++:idx--;
642 
643  if (idx < 0)
644  idx = maxPages - 1;
645 
646  if ((size_t)idx < maxPages)
647  page = tabCtrl->GetPage(idx).window;
648 
649  if (!page && maxPages > 0)
650  page = tabCtrl->GetPage(0).window;
651 
652  if (page)
653  {
654  currentSelection = GetPageIndex(page);
655  SetSelection(currentSelection);
656  }
657 }
658 
659 #if wxCHECK_VERSION(3, 0, 0)
661 #else
662 void cbAuiNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
663 #endif
664 {
665  // if we change window, we call our own AdvanceSelection
666  if ( event.IsWindowChange() )
668  else // otherwise we call the event-handler from the parent-class
669  {
670 #if wxCHECK_VERSION(3, 0, 0)
671  wxAuiNotebook::OnNavigationKeyNotebook(event);
672 #else
673  wxAuiNotebook::OnNavigationKey(event);
674 #endif
675  }
676 }
677 
679 {
680  // Build list of panes/tabs
681  wxString tabs, tabsTmp;
682  wxArrayString panes;
683 
684  // first get all tab-controls
686 
687  wxAuiPaneInfoArray& all_panes = m_mgr.GetAllPanes();
688  const size_t pane_count = all_panes.GetCount();
689  for (size_t i = 0; i < pane_count; ++i)
690  {
691  wxAuiPaneInfo& pane = all_panes.Item(i);
692  if (pane.name == wxT("dummy"))
693  continue;
694 
695  wxAuiTabCtrl* tabCtrl = nullptr;
696  for (size_t j = 0; j < m_TabCtrls.GetCount(); ++j)
697  {
698  if (pane.window == GetTabFrameFromTabCtrl(m_TabCtrls.Item(j)))
699  {
700  tabCtrl = m_TabCtrls.Item(j);
701  break;
702  }
703  }
704  if (tabCtrl)
705  {
706  tabsTmp.Clear();
707  // add tab id's
708  size_t page_count = tabCtrl->GetPageCount();
709  for (size_t p = 0; p < page_count; ++p)
710  {
711  wxAuiNotebookPage& page = tabCtrl->GetPage(p);
712  const size_t page_idx = m_tabs.GetIdxFromWindow(page.window);
713 
715 
716  // file does not belong to any project, so don't save
717  if (id.BeforeLast(':').empty())
718  continue;
719 
720  // if we save a project (projectTitle non empty), but file does not belong to the project
721  // skip it
722  if (!projectTitle.empty() && id.BeforeLast(':') != projectTitle)
723  continue;
724 
725  if (!tabsTmp.empty())
726  tabsTmp += wxT(",");
727 
728 #if wxCHECK_VERSION(3, 0, 0)
729  if ((int)page_idx == m_curPage)
730 #else
731  if ((int)page_idx == m_curpage)
732 #endif
733  tabsTmp += wxT("*");
734  else if ((int)p == tabCtrl->GetActivePage())
735  tabsTmp += wxT("+");
736 
737  tabsTmp += wxString::Format(wxT("%lu"), static_cast<unsigned long>(page_idx));
738  tabsTmp += wxT(";");
739  tabsTmp += id;
740  }
741  if (!tabsTmp.empty())
742  {
743  if (!tabs.empty())
744  tabs += wxT("|");
745 
746  panes.Add(pane.name);
747  tabs += pane.name;
748  tabs += wxT("=");
749  tabs += tabsTmp;
750  }
751  }
752  }
753  tabs += wxT("@");
754 
755  tabsTmp = m_mgr.SavePerspective();
756 
757  wxArrayString arTabsTmp = GetArrayFromString(tabsTmp, wxT("|"));
758 
759  for (size_t i = arTabsTmp.GetCount(); i > 0 ; )
760  {
761  if (arTabsTmp.Item(--i).StartsWith(wxT("name=")))
762  {
763  wxString strTmp = arTabsTmp.Item(i).AfterFirst('=').BeforeFirst(';');
764  if (strTmp == wxT("dummy"))
765  continue;
766  if (panes.Index(strTmp) < 0)
767  arTabsTmp.RemoveAt(i);
768  }
769  }
770 
771  tabsTmp = GetStringFromArray(arTabsTmp, wxT("|"));
772 
773  // Add frame perspective
774  tabs += tabsTmp;
775 
776  return tabs;
777 }
778 
780 {
781  ProjectFile* pf = nullptr;
782  cbProject* prj = nullptr;
783  wxString id = wxT("");
784  wxString fn = text.BeforeFirst(wxT('\n'));
785  prj = Manager::Get()->GetProjectManager()->FindProjectForFile(fn, &pf, false, true);
786  if (prj && pf)
787  id = prj->GetTitle() + wxT(':') + pf->relativeFilename;
788  return id;
789 }
790 
792 {
793  if (text == wxT(""))
794  return -1;
795  for (size_t i = 0; i < m_tabs.GetPageCount(); ++i)
796  {
797  if (UniqueIdFromTooltip(GetPageToolTip(i)) == text)
798  return i;
799  }
800  return -1;
801 }
802 
803 bool cbAuiNotebook::LoadPerspective(const wxString& layout, bool mergeLayouts)
804 {
805  if (layout.IsEmpty())
806  return false;
807 
808  wxString tabs = layout.BeforeFirst (wxT ('@') );
809  // Remove all tab ctrls (but still keep them in main index)
810  const size_t tab_count = m_tabs.GetPageCount();
811  for (size_t i = 0; i < tab_count; ++i)
812  {
813  // only remove tabs that are in the layout-string, do not touch others,
814  // so the layout of an already loaded workspace or project will not get destroyed, if the
815  // current layout did not know the tab. The layout file which is loaded last takes precedence,
816  // if there are two or more layout strings containing the actual tab.
817  if ( tabs.Find( UniqueIdFromTooltip(GetPageToolTip(i)) ) < 0 )
818  continue;
819 
820  wxWindow* wnd = m_tabs.GetWindowFromIdx (i);
821 
822  // find out which onscreen tab ctrl owns this tab
823  wxAuiTabCtrl* ctrl;
824  int ctrl_idx;
825  if ( !FindTab(wnd, &ctrl, &ctrl_idx) )
826  return false;
827 
828  // remove the tab from ctrl
829  if ( !ctrl->RemovePage(wnd) )
830  return false;
831  }
832  RemoveEmptyTabFrames();
833  wxString currentLayout;
834  if (mergeLayouts)
835  {
836  currentLayout = m_mgr.SavePerspective();
837  wxString tempLayout;
838  while (!currentLayout.empty())
839  {
840  if ( currentLayout.BeforeFirst('|').StartsWith(_("layout2")) ||
841  currentLayout.BeforeFirst('|').StartsWith(_("name=dummy")) )
842  {
843  currentLayout = currentLayout.AfterFirst(('|'));
844  currentLayout.Trim();
845  currentLayout.Trim(true);
846  }
847  else
848  {
849  wxString pane_part = currentLayout.BeforeFirst('|');
850  pane_part.Trim();
851  pane_part.Trim(true);
852  if (!pane_part.empty())
853  tempLayout += pane_part + wxT("|");
854 
855  currentLayout = currentLayout.AfterFirst('|');
856  currentLayout.Trim();
857  currentLayout.Trim(true);
858  }
859  }
860  currentLayout = tempLayout;
861  if (currentLayout.empty())
862  mergeLayouts = false;
863  }
864 
865  size_t sel_page = 0;
866  int active_tab = 0;
867  bool found = false;
868 
869  wxString frames = layout.AfterFirst (wxT ('@') );
870  // if we load an additional project to an exiting layout, the first new tab always goes into a new frame
871  bool firstTabInCtrl =! currentLayout.empty();
872  // This creates a new tabframe if none exists; a workaround, because we can not directly access
873  // the needed wxTabFrame class, because it is not exported.
874  // This also takes care of all needed pane-info
875  wxAuiTabCtrl* dest_tabs = GetActiveTabCtrl();
876  while (1)
877  {
878  const wxString tab_part = tabs.BeforeFirst(wxT('|'));
879 
880  // if the string is empty, we're done parsing
881  if (tab_part.empty())
882  break;
883 
884  // Get pane name
885  wxString pane_name = tab_part.BeforeFirst(wxT('='));
886 
887  // create a new tab frame
888 #if wxCHECK_VERSION(3, 0, 0)
889  m_curPage = -1;
890 #else
891  m_curpage = -1;
892 #endif
893 
894  // Get list of tab id's and move them to pane
895  wxString tab_list = tab_part.AfterFirst(wxT('='));
896  while (1)
897  {
898  wxString tab = tab_list.BeforeFirst(wxT(','));
899  wxString name = tab.AfterFirst(wxT(';'));
900  tab = tab.BeforeFirst(wxT(';'));
901 
902  if (tab.empty())
903  break;
904  tab_list = tab_list.AfterFirst(wxT(','));
905 
906  // Check if this page has an 'active' marker
907  const wxChar c = tab[0];
908  if (c == wxT('+') || c == wxT('*'))
909  tab = tab.Mid(1);
910 
911  // Move tab to pane
912  const int index_in_m_tabs = GetTabIndexFromTooltip(name);
913  if (index_in_m_tabs < 0)
914  continue;
915 
916  wxAuiNotebookPage& page = m_tabs.GetPage(index_in_m_tabs);
917 
918  // save the actual active tab, because it will be set to 0 after a Split()
919  active_tab = dest_tabs->GetActivePage();
920  const size_t newpage_idx = dest_tabs->GetPageCount();
921  dest_tabs->InsertPage(page.window, page, newpage_idx);
922 
923  if (c == wxT('+'))
924  dest_tabs->SetActivePage(newpage_idx);
925  else if (c == wxT('*'))
926  sel_page = index_in_m_tabs;
927 
928  // If we should be the first tab in a tab-ctrl we switch to the next existing tab,
929  // or create a new one by calling Split() and update the dest_tabs accordingly.
930  if (firstTabInCtrl)
931  {
932  int nextIndex = m_TabCtrls.Index(dest_tabs) + 1;
933  if (nextIndex == 0 || nextIndex >= static_cast<int>(m_TabCtrls.GetCount()))
934  {
935  Split(index_in_m_tabs, wxRIGHT);
936  // reset the active tab, because a Split() set it to zero
937  dest_tabs->SetActivePage(active_tab);
938  dest_tabs = GetActiveTabCtrl();
939  }
940  else
941  dest_tabs = m_TabCtrls.Item(nextIndex);
942  }
943  // Change the pane name to the one we have stored in the layout-string.
944  wxAuiPaneInfo& pane = m_mgr.GetPane( GetTabFrameFromTabCtrl(dest_tabs) );
945  if (pane.name != pane_name)
946  {
947  tab.Replace(pane_name, pane.name);
948  frames.Replace(pane_name, pane.name);
949  pane_name = pane.name;
950  }
951  firstTabInCtrl = false;
952  found = true;
953  }
954  // We come here after at least one tabctrl is filled, so the next tab should go in a new one
955  firstTabInCtrl = true;
956 
957  tabs = tabs.AfterFirst(wxT('|'));
958  }
959 
960  // Check for windows not readded to the notebook and add the at the end.
961  for (size_t i = 0; i < tab_count; ++i)
962  {
963  wxAuiNotebookPage& page = m_tabs.GetPage(i);
964 
965  // find out which onscreen tab ctrl owns this tab
966  // if none then add it to the last used tabctrl
967  wxAuiTabCtrl* ctrl;
968  int ctrl_idx;
969  if ( !FindTab(page.window, &ctrl, &ctrl_idx) )
970  {
971  const size_t newpage_idx = dest_tabs->GetPageCount();
972  dest_tabs->InsertPage (page.window, page, newpage_idx);
973  }
974 
975  }
976 
977  if (mergeLayouts)
978  {
979  wxRegEx reDockSize(_T("(dock_size[()0-9,]+=)[0-9]+"));
980  const wxString replacement(wxT("\\1-1"));
981  // Make a centered frame left docked
982  frames.Replace(wxString::Format(wxT("dock_size(%d"), wxAUI_DOCK_CENTER), wxString::Format(wxT("dock_size(%d"), wxAUI_DOCK_LEFT));
984  if (reDockSize.Matches(frames))
985  reDockSize.ReplaceAll(&frames,replacement);
986  if (reDockSize.Matches(currentLayout))
987  reDockSize.ReplaceAll(&currentLayout,replacement);
988  while (!currentLayout.empty())
989  {
990  wxString pane_part = currentLayout.BeforeFirst('|');
991  pane_part.Trim();
992  pane_part.Trim(true);
993  if (!pane_part.empty())
994  frames += pane_part + wxT("|");
995  currentLayout = currentLayout.AfterFirst('|');
996  currentLayout.Trim();
997  currentLayout.Trim(true);
998  }
999  }
1000 
1001  if (found)
1002  m_mgr.LoadPerspective(frames);
1003  RemoveEmptyTabFrames();
1004 
1005  // Force refresh of selection
1006 #if wxCHECK_VERSION(3, 0, 0)
1007  m_curPage = -1;
1008 #else
1009  m_curpage = -1;
1010 #endif
1011  SetSelection(sel_page);
1012 
1014  return true;
1015 }
1016 
1017 
1018 //bool cbAuiNotebook::LoadPerspective(const wxString& layout) {
1019 // // Remove all tab ctrls (but still keep them in main index)
1020 // const size_t tab_count = m_tabs.GetPageCount();
1021 // for (size_t i = 0; i < tab_count; ++i) {
1022 // wxWindow* wnd = m_tabs.GetWindowFromIdx(i);
1023 //
1024 // // find out which onscreen tab ctrl owns this tab
1025 // wxAuiTabCtrl* ctrl;
1026 // int ctrl_idx;
1027 // if (!FindTab(wnd, &ctrl, &ctrl_idx))
1028 // return false;
1029 //
1030 // // remove the tab from ctrl
1031 // if (!ctrl->RemovePage(wnd))
1032 // return false;
1033 // }
1034 // RemoveEmptyTabFrames();
1035 //
1036 // size_t sel_page = 0;
1037 //
1038 // wxString tabs = layout.BeforeFirst(wxT('@'));
1039 // while (1)
1040 // {
1041 // const wxString tab_part = tabs.BeforeFirst(wxT('|'));
1042 //
1043 // // if the string is empty, we're done parsing
1044 // if (tab_part.empty())
1045 // break;
1046 //
1047 // // Get pane name
1048 // const wxString pane_name = tab_part.BeforeFirst(wxT('='));
1049 //
1050 // // create a new tab frame
1051 // wxTabFrame* new_tabs = new wxTabFrame;
1052 // new_tabs->m_tabs = new wxAuiTabCtrl(this,
1053 // m_tab_id_counter++);
1057 // new_tabs->m_tabs->SetArtProvider(m_tabs.GetArtProvider()->Clone());
1058 // new_tabs->SetTabCtrlHeight(m_tab_ctrl_height);
1059 // new_tabs->m_tabs->SetFlags(m_flags);
1060 // wxAuiTabCtrl *dest_tabs = new_tabs->m_tabs;
1061 //
1062 // // create a pane info structure with the information
1063 // // about where the pane should be added
1064 // wxAuiPaneInfo pane_info = wxAuiPaneInfo().Name(pane_name).Bottom().CaptionVisible(false);
1065 // m_mgr.AddPane(new_tabs, pane_info);
1066 //
1067 // // Get list of tab id's and move them to pane
1068 // wxString tab_list = tab_part.AfterFirst(wxT('='));
1069 // while (1)
1070 // {
1071 // wxString tab = tab_list.BeforeFirst(wxT(','));
1072 // if (tab.empty()) break;
1073 // tab_list = tab_list.AfterFirst(wxT(','));
1074 //
1075 // // Check if this page has an 'active' marker
1076 // const wxChar c = tab[0];
1077 // if (c == wxT('+') || c == wxT('*'))
1078 // tab = tab.Mid(1);
1079 //
1080 // const size_t tab_idx = wxAtoi(tab.c_str());
1081 // if (tab_idx >= GetPageCount()) continue;
1082 //
1083 // // Move tab to pane
1084 // wxAuiNotebookPage& page = m_tabs.GetPage(tab_idx);
1085 // const size_t newpage_idx = dest_tabs->GetPageCount();
1086 // dest_tabs->InsertPage(page.window, page, newpage_idx);
1087 //
1088 // if ( c == wxT('+')) dest_tabs->SetActivePage(newpage_idx);
1089 // else if ( c == wxT('*')) sel_page = tab_idx;
1090 // }
1091 // dest_tabs->DoShowHide();
1092 //
1093 // tabs = tabs.AfterFirst(wxT('|'));
1094 // }
1095 //
1096 // // Load the frame perspective
1097 // const wxString frames = layout.AfterFirst(wxT('@'));
1098 // m_mgr.LoadPerspective(frames);
1099 //
1100 // // Force refresh of selection
1101 // m_curpage = -1;
1102 // SetSelection(sel_page);
1103 //
1104 // return true;
1105 //}
1106 
1107 // static functions(common to all cbAuiNotebooks)
1108 
1110 {
1111  s_AllowMousewheel = allow;
1112  for (size_t i = 0; i < s_cbAuiNotebookArray.GetCount(); ++i)
1113  {
1114  s_cbAuiNotebookArray[i]->UpdateTabControlsArray();
1115  s_cbAuiNotebookArray[i]->ResetTabCtrlEvents();
1116  }
1117 }
1118 
1120 {
1121  s_modKeys = keys;
1122 }
1123 
1125 {
1126  s_modToAdvance = use;
1127 }
1128 
1130 {
1131  s_advanceDirection=invert ? -1 : 1;
1132 }
1133 
1135 {
1136  s_moveDirection=invert ? -1 : 1;
1137 }
DLLIMPORT wxArrayString GetArrayFromString(const wxString &text, const wxString &separator=DEFAULT_ARRAY_SEP, bool trimSpaces=true)
Definition: globals.cpp:134
wxApp * wxTheApp
bool LoadPerspective(const wxString &layout, bool mergeLayouts=false)
Loads serialized notebook layout.
Definition: cbauibook.cpp:803
bool AddPage(wxWindow *page, const wxString &caption, bool select=false, const wxBitmap &bitmap=wxNullBitmap)
Add Page.
Definition: cbauibook.cpp:561
wxCoord GetX() const
const wxString empty(_T(""))
wxString relativeFilename
The relative (to the project) filename of this file.
Definition: projectfile.h:131
static bool s_modToAdvance
Use modkey to advance through tabs with mousewheel.
Definition: cbauibook.h:388
ConfigManager * GetConfigManager(const wxString &name_space) const
Definition: manager.cpp:474
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
bool RemovePage(size_t page)
Remove Page.
Definition: cbauibook.cpp:534
bool DeletePage(size_t page)
Delete Page.
Definition: cbauibook.cpp:520
void OnTabCtrlDblClick(wxMouseEvent &event)
Catch doubleclick-events from wxTabCtrl.
Definition: cbauibook.cpp:354
wxString SavePerspective(const wxString projectTitle=wxEmptyString)
Save layout of the notebook.
Definition: cbauibook.cpp:678
void ResetTabCtrlEvents()
Reset tabctrl events.
Definition: cbauibook.cpp:151
wxSize m_TabCtrlSize
Holds the size of a tabCtrl after a resize event.
Definition: cbauibook.h:343
bool ReadBool(const wxString &name, bool defaultVal=false)
int Index(const wxString &sz, bool bCase=true, bool bFromEnd=false) const
size_t GetPageCount() const
int GetZoom() const
bool Matches(const wxString &text, int flags=0) const
~cbAuiNotebook() override
cbAuiNotebook destructor
Definition: cbauibook.cpp:80
#define _T(string)
DLLIMPORT wxString GetStringFromArray(const wxArrayString &array, const wxString &separator=DEFAULT_ARRAY_SEP, bool SeparatorAtEnd=true)
Definition: globals.cpp:122
wxSize GetSize() const
bool GetDirection() const
wxString AfterFirst(wxUniChar ch) const
wxEventType wxEVT_MOUSEWHEEL
#define wxT(string)
void GetPagesInTabCtrl(std::vector< wxWindow *> &result, wxWindow *page)
Return a vector containing all pages that are in the same tab control as the page passed as parameter...
Definition: cbauibook.cpp:216
#define wxNOT_FOUND
void StoreFocus()
Save old focus.
Definition: cbauibook.cpp:321
Represents a file in a Code::Blocks project.
Definition: projectfile.h:39
int GetWheelRotation() const
bool empty() const
A generic Code::Blocks event.
Definition: sdk_events.h:20
static int s_advanceDirection
Mouseweheel advance direction: negative => invert.
Definition: cbauibook.h:394
static cbAuiNotebookArray s_cbAuiNotebookArray
Holds an array of all existing cbAuiNotebooks.
Definition: cbauibook.h:382
static bool s_AllowMousewheel
Enable or disable scrolling tabs with mousewheel.
Definition: cbauibook.h:379
wxEventType wxEVT_LEAVE_WINDOW
void SetZoom(int zoom)
Set zoomfactor for builtin editors.
Definition: cbauibook.cpp:228
void OnDragDone(wxAuiNotebookEvent &event)
Catch dragdone-events from wxTabCtrl.
Definition: cbauibook.cpp:266
EditorManager * GetEditorManager() const
Definition: manager.cpp:434
wxEventType wxEVT_LEFT_DCLICK
static int s_moveDirection
Mousewheel move direction: negative => invert.
Definition: cbauibook.h:391
void OnLeaveTabCtrl(wxMouseEvent &event)
Catch mouseleave-events from wxTabCtrl.
Definition: cbauibook.cpp:294
wxUSE_UNICODE_dependent wxChar
wxString BeforeFirst(wxUniChar ch, wxString *rest=NULL) const
wxEventType wxEVT_SIZE
virtual void Split(size_t page, int direction)
ProjectManager * GetProjectManager() const
Functions returning pointers to the respective sub-manager instances.
Definition: manager.cpp:429
void FocusActiveTabCtrl()
Set Focus on the tabCtrl belonging to the active tab.
Definition: cbauibook.cpp:180
bool InsertPage(size_t page_idx, wxWindow *page, const wxString &caption, bool select=false, const wxBitmap &bitmap=wxNullBitmap)
Insert Page.
Definition: cbauibook.cpp:571
bool Contains(const wxString &str) const
bool InsertPage(size_t page_idx, wxWindow *page, const wxString &caption, bool select=false, const wxBitmap &bitmap=wxNullBitmap)
Represents a Code::Blocks project.
Definition: cbproject.h:96
void UpdateTabControlsArray()
Updates the array, that holds the wxTabCtrls.
Definition: cbauibook.cpp:105
wxString UniqueIdFromTooltip(const wxString &text)
Create a unique id from the tooltip-text.
Definition: cbauibook.cpp:779
bool DeletePage(size_t page)
size_t SetSelection(size_t new_page)
virtual const wxString & GetTitle() const
Read the target&#39;s title.
int ReplaceAll(wxString *text, const wxString &replacement) const
size_t Replace(const wxString &strOld, const wxString &strNew, bool replaceAll=true)
void OnIdle(cb_unused wxIdleEvent &event)
OnIdle.
Definition: cbauibook.cpp:242
static void InvertMoveDirection(bool invert=false)
Change direction of tab-moving with mousewheel.
Definition: cbauibook.cpp:1134
wxString GetPageToolTip(size_t pageIdx) const
DLLIMPORT bool IsWindowReallyShown(wxWindow *win)
Finds out if a window is really shown.
Definition: globals.cpp:931
wxEventType wxEVT_ENTER_WINDOW
wxString & Item(size_t nIndex)
wxString Read(const wxString &key, const wxString &defaultVal=wxEmptyString)
bool AddPage(wxWindow *page, const wxString &caption, bool select=false, const wxBitmap &bitmap=wxNullBitmap)
int GetTabIndexFromTooltip(const wxString &text)
Get the tab index from tooltiptext.
Definition: cbauibook.cpp:791
static void UseModToAdvance(bool use=false)
Use modkey to advance through tabs with mousewheel.
Definition: cbauibook.cpp:1124
wxString wxEmptyString
EVTIMPORT const wxEventType cbEVT_CBAUIBOOK_LEFT_DCLICK
Definition: sdk_events.cpp:173
void OnNavigationKeyNotebook(wxNavigationKeyEvent &event)
Handle the navigation key event.
Definition: cbauibook.cpp:660
const wxString & _(const wxString &string)
wxString & Trim(bool fromRight=true)
wxAuiTabCtrl * GetTabCtrl(wxWindow *page)
Returns a pointer to the page&#39;s tab control or nullptr.
Definition: cbauibook.cpp:202
wxWindow * GetPage(size_t page_idx) const
bool RemovePage(size_t page)
void OnEnterTabCtrl(wxMouseEvent &event)
Catch mouseenter-events from wxTabCtrl.
Definition: cbauibook.cpp:272
void AdvanceSelection(bool forward=true)
Advances the selection.
Definition: cbauibook.cpp:622
static void AllowScrolling(bool allow=true)
Enable or disable tab-scrolling with mousewheel.
Definition: cbauibook.cpp:1109
static void SetMaxWidth(int width)
bool SetPageToolTip(size_t page, const wxString &text)
int GetTabPositionFromIndex(int index)
Get the tab position.
Definition: cbauibook.cpp:582
static void SetModKeys(wxString keys=_T("Strg"))
Sets the modifier keys for scrolling.
Definition: cbauibook.cpp:1119
int GetPageIndex(wxWindow *page_wnd) const
static const wxString tab
bool IsFocusStored(wxWindow *page)
Checks the old focus.
Definition: cbauibook.cpp:309
A file editor.
Definition: cbeditor.h:43
void RestoreFocus()
Restore old focus.
Definition: cbauibook.cpp:332
bool IsEmpty() const
void Clear()
wxEventType wxEVT_MOTION
void OnResize(wxSizeEvent &event)
Catch resize-events and call MinimizeFreeSpace()
Definition: cbauibook.cpp:411
bool Moving() const
A notebook class This class is derived from wxAuiNotebook, to enhance its abilities.
Definition: cbauibook.h:30
bool IsWindowChange() const
bool CheckKeyModifier()
Check for pressed modifier-keys.
Definition: cbauibook.cpp:85
long m_LastId
Id of last focused window.
Definition: cbauibook.h:319
cbAuiTabCtrlArray m_TabCtrls
Holds the wxTabCtrls used by the notebook.
Definition: cbauibook.h:306
size_t Add(const wxString &str, size_t copies=1)
bool m_SetZoomOnIdle
If true, zoom for all editors is set in next OnIdle-call.
Definition: cbauibook.h:333
cbProject * FindProjectForFile(const wxString &file, ProjectFile **resultFile, bool isRelative, bool isUnixFilename)
Return the project which has the file in it, also return the pointer to the ProjectFile object...
void OnTabCtrlMouseWheel(wxMouseEvent &event)
Catch mousewheel-events from wxTabCtrl.
Definition: cbauibook.cpp:370
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
size_t GetCount() const
int Find(wxUniChar ch, bool fromEnd=false) const
void RemoveAt(size_t nIndex, size_t count=1)
int m_LastSelected
Last selected tab.
Definition: cbauibook.h:314
bool MovePage(wxWindow *page, size_t new_idx)
Move page.
Definition: cbauibook.cpp:548
void MinimizeFreeSpace()
Minmize free horizontal page.
Definition: cbauibook.cpp:480
virtual bool IsActive() const
int GetSelection() const
bool m_MinimizeFreeSpaceOnIdle
If true, MinimizeFreeSpace is called in next OnIdle-call.
Definition: cbauibook.h:337
int wxWindowID
bool wxGetKeyState(wxKeyCode key)
static wxString s_modKeys
Holds the modifier keys for scrolling.
Definition: cbauibook.h:385
static wxString Format(const wxString &format,...)
wxString & MakeUpper()
wxString Mid(size_t first, size_t nCount=wxString::npos) const
static void InvertAdvanceDirection(bool invert=false)
Change direction of tab-advancing with mousewheel.
Definition: cbauibook.cpp:1129