Code::Blocks  SVN r11506
infopane.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 11476 $
6  * $Id: infopane.cpp 11476 2018-09-29 07:42:00Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/src/infopane.cpp $
8  */
9 
10 #include <sdk.h>
11 
12 #ifndef CB_PRECOMP
13  #include <wx/event.h>
14  #include <wx/menu.h>
15  #include "cbexception.h"
16  #include "globals.h"
17  #include "configmanager.h"
18 #endif
19 
20 #include <wx/wupdlock.h>
21 #include <wx/tokenzr.h>
22 #include "infopane.h"
23 #include "loggers.h"
24 
25 namespace
26 {
27  long idNB_TabTop = wxNewId();
28  long idNB_TabBottom = wxNewId();
29 
30  long idCopyAllToClipboard = wxNewId();
31  long idCopySelectedToClipboard = wxNewId();
32 
33  long idWrapMode = wxNewId();
34  long idClear = wxNewId();
35 
36  long idNB = wxNewId();
37 }
38 
39 BEGIN_EVENT_TABLE(InfoPane, cbAuiNotebook)
40  EVT_MENU(idNB_TabTop, InfoPane::OnTabPosition)
41  EVT_MENU(idNB_TabBottom, InfoPane::OnTabPosition)
42 
43  EVT_MENU_RANGE(idCopyAllToClipboard, idCopySelectedToClipboard, InfoPane::OnCopy)
44 
45  EVT_MENU(idWrapMode, InfoPane::OnWrapMode)
46  EVT_MENU(idClear, InfoPane::OnClear)
47  EVT_MENU(wxID_ANY, InfoPane::OnMenu)
48 
49  EVT_CONTEXT_MENU(InfoPane::ContextMenu)
50 
51  EVT_AUINOTEBOOK_TAB_RIGHT_UP(idNB, InfoPane::OnTabContextMenu)
52  EVT_AUINOTEBOOK_PAGE_CLOSE(idNB, InfoPane::OnCloseClicked)
53 END_EVENT_TABLE()
54 
55 
56 InfoPane::InfoPane(wxWindow* parent) : cbAuiNotebook(parent, idNB, wxDefaultPosition, wxDefaultSize, infopane_flags)
57 {
58  m_DefaultBitmap = cbLoadBitmap(ConfigManager::GetDataFolder() + _T("/images/edit_16x16.png"), wxBITMAP_TYPE_PNG);
59 }
60 
62 {
63  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
64  {
65  Page *page = m_Pages[i];
66  delete page;
67  }
68 }
69 
71 {
73  m_Pages.Sort(&CompareIndexes);
74  wxString layout;
75  for (size_t i = 0 ; i < m_Pages.GetCount(); ++i)
76  {
77  layout << m_Pages.Item(i)->title;
78  layout << _T("=");
79  layout << m_Pages.Item(i)->indexInNB;
80  layout << _T(";");
81  }
82  layout << _T("|selection=");
83  layout << GetSelection();
84  layout << _T(";");
85  return layout;
86 }
87 
89 {
90  wxString theLayout(layout);
91 
92  long selectedTab;
93  theLayout.AfterLast('=').ToLong(&selectedTab);
94  theLayout.Remove(theLayout.Find('|',true));
95  wxStringTokenizer strTok(theLayout, _T(";"));
96  wxString title;
97  while (strTok.HasMoreTokens())
98  {
99  wxString theToken = strTok.GetNextToken();
100  title = theToken.BeforeFirst('=');
101  for (size_t j = 0; j < m_Pages.GetCount();++j)
102  {
103  if (m_Pages.Item(j)->title == title)
104  {
105  long theIndex;
106  if (theToken.AfterFirst('=').ToLong(&theIndex))
107  m_Pages.Item(j)->indexInNB = theIndex;
108  break;
109  }
110  }
111  }
113  SetSelection(selectedTab);
114 }
115 
117 {
118  int index1 = ((*p1)->indexInNB >= 0?(*p1)->indexInNB:~(*p1)->indexInNB);
119  int index2 = ((*p2)->indexInNB >= 0?(*p2)->indexInNB:~(*p2)->indexInNB);
120  return index1 - index2;
121 }
122 
124 {
125  if (m_Pages.GetCount() == 0)
126  return;
127  m_Pages.Sort(cmp_f);
128 
129  cbAuiNotebook::Hide();
130  int index = 0;
131  for (size_t i = 0 ; i < m_Pages.GetCount(); ++i)
132  {
133  int pageIndex = GetPageIndex(m_Pages.Item(i)->window);
134  if (m_Pages.Item(i)->indexInNB < 0)
135  {
136  if (pageIndex >= 0)
137  RemovePage(pageIndex);
138  if (m_Pages.Item(i)->window)
139  m_Pages.Item(i)->window->Hide();
140  }
141  else
142  {
143  if (pageIndex < 0)
144  AddPagePrivate(m_Pages.Item(i)->window, m_Pages.Item(i)->title, m_Pages.Item(i)->icon);
145  if (index++ != pageIndex)
146  MovePage(m_Pages.Item(i)->window, index );
147  }
148  }
149  cbAuiNotebook::Show();
150 }
151 
153 {
154  const wxBitmap& bmp = icon ? *icon : m_DefaultBitmap;
155 
156  AddPage(p, title, false, bmp);
157  return GetPageCount() - 1;
158 }
159 
160 bool InfoPane::InsertPagePrivate(wxWindow* p, const wxString& title, wxBitmap* icon, int index)
161 {
162  const wxBitmap& bmp = icon ? *icon : m_DefaultBitmap;
163 
164  return InsertPage(index, p, title, false, bmp);
165 }
166 
168 {
169  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
170  {
171  // only update for visible tabs
172  if (m_Pages.Item(i)->indexInNB >= 0)
173  m_Pages.Item(i)->indexInNB = GetTabPositionFromIndex(GetPageIndex(m_Pages.Item(i)->window));
174 
175  }
176 }
177 
178 void InfoPane::Toggle(size_t i)
179 {
181  if (m_Pages.Item(i)->indexInNB < 0)
182  {
183  if (InsertPagePrivate(m_Pages.Item(i)->window, m_Pages.Item(i)->title, m_Pages.Item(i)->icon, ~m_Pages.Item(i)->indexInNB))
184  m_Pages.Item(i)->indexInNB = ~m_Pages.Item(i)->indexInNB ;
185  else
186  m_Pages.Item(i)->indexInNB = AddPagePrivate(m_Pages.Item(i)->window, m_Pages.Item(i)->title, m_Pages.Item(i)->icon);
187  }
188  else
189  {
190  // Hide the window, otherwise the controls remain partly visible on some windows-versions
191  // if we toggle the active logger
192  if (m_Pages.Item(i)->window)
193  m_Pages.Item(i)->window->Hide();
194  RemovePage(GetPageIndex(m_Pages.Item(i)->window));
195  m_Pages.Item(i)->indexInNB = ~m_Pages.Item(i)->indexInNB;
196  }
197 }
198 
200 {
201  for (size_t i=0; i < m_Pages.GetCount(); i++)
202  {
203  if (m_Pages.Item(i)->window == win)
204  return i;
205  }
206  return -1;
207 }
208 
209 int InfoPane::GetCurrentPage(bool &is_logger)
210 {
212  is_logger = m_Pages.Item(i)->islogger;
213  return (is_logger ? i : -1);
214 }
215 
217 {
218  if (index < 0 || (size_t)index > m_Pages.GetCount())
219  return NULL;
220  return m_Pages.Item(index)->islogger ? m_Pages.Item(index)->logger : NULL;
221 }
222 
224 {
225  if (index < 0 || (size_t)index > m_Pages.GetCount())
226  return NULL;
227  return !m_Pages.Item(index)->islogger ? m_Pages.Item(index)->window : NULL;
228 }
229 
230 void InfoPane::Show(size_t i)
231 {
232  if (m_Pages.Item(i)->window == nullptr)
233  return;
234 
235  if (m_Pages.Item(i)->indexInNB < 0)
236  Toggle(i);
237  else
238  SetSelection(GetPageIndex(m_Pages.Item(i)->window));
239 }
240 
241 void InfoPane::Hide(Logger* logger)
242 {
243  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
244  {
245  if (m_Pages.Item(i)->logger == logger)
246  {
247  if (m_Pages.Item(i)->indexInNB >= 0)
248  Toggle(i);
249  return;
250  }
251  }
252 }
253 
254 void InfoPane::Show(Logger* logger)
255 {
256  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
257  {
258  if (m_Pages.Item(i)->logger == logger)
259  {
260  if (m_Pages.Item(i)->indexInNB < 0)
261  Toggle(i);
262  else
263  SetSelection(GetPageIndex(m_Pages.Item(i)->window));
264  return;
265  }
266  }
267 }
268 
270 {
271  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
272  {
273  if (m_Pages.Item(i)->window == p)
274  {
275  if (m_Pages.Item(i)->indexInNB >= 0)
276  Toggle(i);
277  return;
278  }
279  }
280 }
281 
283 {
284  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
285  {
286  if (m_Pages.Item(i)->window == p)
287  {
288  if (m_Pages.Item(i)->indexInNB < 0)
289  Toggle(i);
290  else
292  return;
293  }
294  }
295 }
296 
297 
299 {
301  if (m_Pages.Item(i)->islogger)
302  {
303  if (event.GetId() == idCopyAllToClipboard)
304  m_Pages.Item(i)->logger->CopyContentsToClipboard(false);
305  else if (event.GetId() == idCopySelectedToClipboard)
306  m_Pages.Item(i)->logger->CopyContentsToClipboard(true);
307  }
308 }
309 
310 void InfoPane::OnWrapMode(cb_unused wxCommandEvent& event)
311 {
313  if (m_Pages.Item(i)->islogger && m_Pages.Item(i)->logger->HasFeature(Logger::Feature::IsWrappable))
314  {
315  TextCtrlLogger* tcl = static_cast<TextCtrlLogger*>(m_Pages.Item(i)->logger);
316  if (tcl) tcl->ToggleWrapMode();
317  }
318 }
319 
320 void InfoPane::OnClear(cb_unused wxCommandEvent& event)
321 {
323  if (m_Pages.Item(i)->islogger)
324  m_Pages.Item(i)->logger->Clear();
325 }
326 
328 {
329  int eventID = event.GetId();
330  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
331  {
332  if (eventID == m_Pages.Item(i)->eventID)
333  {
334  Toggle(i);
335  return;
336  }
337  }
338 
339  event.Skip();
340  return;
341 }
342 
344 {
346 }
347 
349 {
350  if (event.GetSelection() == -1)
351  return;
352  // select the notebook that sends the event, because the context menu-entries act on the actual selected tab
353  SetSelection(event.GetSelection());
355 }
356 
358 {
359  if (event.GetSelection() == -1)
360  return;
361  // veto the close-event, because we don't want to remove the page (just toggle it)
362  // this avoids an assert-message in debug-build (and wx2.9)
363  event.Veto();
364  // toggle the notebook, that sends the event
366 }
367 
369 {
371  m_Pages.Sort(&CompareIndexes);
372 
373  wxMenu menu;
374 
375  int selection = GetSelection();
376  if ( (selection >= 0)
377  && (selection < static_cast<int>(GetPageCount()))
378  && (m_Pages.Item(GetPageIndexByWindow( GetPage(GetSelection()) ))->islogger) )
379  {
380  Logger* l = m_Pages.Item(GetPageIndexByWindow( GetPage(GetSelection()) ))->logger;
381 
383  {
384  menu.Append(idCopyAllToClipboard, _("Copy contents to clipboard"));
385  menu.Append(idCopySelectedToClipboard, _("Copy selection to clipboard"));
386  }
387  bool needSeparator = true;
389  {
390  if (menu.GetMenuItemCount() > 0)
391  {
392  needSeparator = false;
393  menu.AppendSeparator();
394  }
395  menu.AppendCheckItem(idWrapMode, _("Toggle wrap mode"));
396  menu.Check(idWrapMode, l->GetWrapMode());
397  }
399  {
400  if (needSeparator && menu.GetMenuItemCount() > 0)
401  menu.AppendSeparator();
402  menu.Append(idClear, _("Clear contents"));
403  }
405  l->AppendAdditionalMenuItems(menu);
406  }
407 
408  if (menu.GetMenuItemCount() > 0)
409  menu.AppendSeparator();
410 
411  if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/infopane_tabs_bottom"), false))
412  menu.Append(idNB_TabTop, _("Tabs at top"));
413  else
414  menu.Append(idNB_TabBottom, _("Tabs at bottom"));
415 
416  // add toggle sub-menu
417  wxMenu* view = new wxMenu;
418  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
419  {
420  if (m_Pages.Item(i)->window)
421  {
422  view->Append(m_Pages.Item(i)->eventID, m_Pages.Item(i)->title, wxEmptyString, wxITEM_CHECK);
423  view->Check(m_Pages.Item(i)->eventID, m_Pages.Item(i)->indexInNB >= 0);
424  }
425  }
426 
427  if (view->GetMenuItemCount() > 0)
428  menu.AppendSubMenu(view, _("Toggle..."));
429  else
430  delete view;
431 
432  PopupMenu(&menu);
433 }
434 
436 {
437  long style = GetWindowStyleFlag();
438  style &= ~wxAUI_NB_BOTTOM;
439 
440  if (event.GetId() == idNB_TabBottom)
441  style |= wxAUI_NB_BOTTOM;
442  SetWindowStyleFlag(style);
443  Refresh();
444  // (style & wxAUI_NB_BOTTOM) saves info only about the the tabs position
445  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/environment/infopane_tabs_bottom"), (bool)(style & wxAUI_NB_BOTTOM));
446 }
447 
448 bool InfoPane::AddLogger(Logger* logger, wxWindow* p, const wxString& title, wxBitmap* icon)
449 {
450  if (p)
451  {
452  Page* pg = new Page();
453  pg->indexInNB = AddPagePrivate(p, title, icon);
454  pg->window = p;
455  pg->logger = logger;
456  pg->icon = icon;
457  pg->title = title;
458  pg->eventID = wxNewId();
459  pg->islogger = true;
460 
461  m_Pages.Add(pg);
462 
463  return true;
464  }
465  return false;
466 }
467 
468 bool InfoPane::AddNonLogger(wxWindow* p, const wxString& title, wxBitmap* icon)
469 {
470  if (p)
471  {
472  p->Reparent(this);
473 
474  Page* pg = new Page();
475  pg->indexInNB = AddPagePrivate(p, title, icon);
476  pg->window = p;
477  pg->icon = icon;
478  pg->title = title;
479  pg->eventID = wxNewId();
480  pg->islogger = false;
481 
482  m_Pages.Add(pg);
483 
484  return true;
485  }
486  return false;
487 }
488 
489 
491 {
492  if (!l)
493  return false;
494 
495  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
496  {
497  if (m_Pages.Item(i)->logger == l)
498  {
499  int index = Manager::Get()->GetLogManager()->FindIndex(l);
500  if (index >= 0)
501  Manager::Get()->GetLogManager()->DeleteLog(index);
502 
503  if (m_Pages.Item(i)->indexInNB >= 0)
504  DeletePage(GetPageIndex(m_Pages.Item(i)->window));
505 
506  delete(m_Pages.Item(i));
507  m_Pages.RemoveAt(i);
508  return true;
509  }
510  }
511 
512  return false;
513 }
514 
516 {
517  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
518  {
519  if (m_Pages.Item(i)->window == p)
520  {
521  if (m_Pages.Item(i)->islogger)
522  cbThrow(_T("Bad API usage. Shame on you."));
523 
524  RemovePage(GetPageIndex(m_Pages.Item(i)->window));
525  m_Pages.RemoveAt(i);
526  return true;
527  }
528  }
529 
530  return false;
531 }
532 
534 {
535  for (size_t i = 0; i < m_Pages.GetCount(); ++i)
536  {
537  if (m_Pages.Item(i)->window == p)
538  {
539  if (m_Pages.Item(i)->islogger)
540  cbThrow(_T("Bad API usage. Shame on you."));
541 
542  if (m_Pages.Item(i)->indexInNB >= 0)
543  DeletePage(GetPageIndex(m_Pages.Item(i)->window));
544 
545  delete(m_Pages.Item(i));
546  m_Pages.RemoveAt(i);
547  return true;
548  }
549  }
550 
551  return false;
552 }
553 
wxString AfterLast(wxUniChar ch) const
static const int infopane_flags
Definition: infopane.h:15
virtual ~InfoPane()
Definition: infopane.cpp:61
int GetSelection() const
bool AddPage(wxWindow *page, const wxString &caption, bool select=false, const wxBitmap &bitmap=wxNullBitmap)
Add Page.
Definition: cbauibook.cpp:561
static int CompareIndexes(Page **p1, Page **p2)
Definition: infopane.cpp:116
int wxNewId()
virtual bool HasFeature(cb_optional Feature::Enum feature) const
Definition: logger.h:70
void DoShowContextMenu()
Definition: infopane.cpp:368
void HideNonLogger(wxWindow *p)
Definition: infopane.cpp:269
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
void OnTabPosition(wxCommandEvent &event)
Definition: infopane.cpp:435
bool RemovePage(size_t page)
Remove Page.
Definition: cbauibook.cpp:534
bool DeletePage(size_t page)
Delete Page.
Definition: cbauibook.cpp:520
void ShowNonLogger(wxWindow *p)
Definition: infopane.cpp:282
wxString title
Definition: infopane.h:31
DLLIMPORT wxBitmap cbLoadBitmap(const wxString &filename, wxBitmapType bitmapType=wxBITMAP_TYPE_PNG)
This function loads a bitmap from disk.
Definition: globals.cpp:1102
bool RemoveNonLogger(wxWindow *p)
Definition: infopane.cpp:515
size_t GetPageCount() const
wxBitmap * icon
Definition: infopane.h:33
size_t FindIndex(Logger *l)
Definition: logmanager.cpp:152
virtual void ToggleWrapMode()
Definition: loggers.cpp:199
wxWindow * GetWindow(int index)
Definition: infopane.cpp:223
void OnClear(wxCommandEvent &event)
Definition: infopane.cpp:320
wxMenuItem * Append(int id, const wxString &item=wxEmptyString, const wxString &helpString=wxEmptyString, wxItemKind kind=wxITEM_NORMAL)
#define _T(string)
wxString SaveTabOrder()
Definition: infopane.cpp:70
wxString GetNextToken()
The base class for all kinds of loggers, see loggers.h for its derived classes.
Definition: logger.h:23
wxWindow * GetCurrentPage() const
wxString & Remove(size_t pos)
int GetPageIndexByWindow(wxWindow *win)
Definition: infopane.cpp:199
wxString AfterFirst(wxUniChar ch) const
size_t GetMenuItemCount() const
bool AddLogger(Logger *logger, wxWindow *p, const wxString &title, wxBitmap *icon=nullptr)
Definition: infopane.cpp:448
void OnMenu(wxCommandEvent &event)
Definition: infopane.cpp:327
int AddPagePrivate(wxWindow *p, const wxString &title, wxBitmap *icon=nullptr)
Definition: infopane.cpp:152
void OnCloseClicked(wxAuiNotebookEvent &event)
Definition: infopane.cpp:357
wxString BeforeFirst(wxUniChar ch, wxString *rest=NULL) const
bool InsertPage(size_t page_idx, wxWindow *page, const wxString &caption, bool select=false, const wxBitmap &bitmap=wxNullBitmap)
Insert Page.
Definition: cbauibook.cpp:571
void LoadTabOrder(wxString layout)
Definition: infopane.cpp:88
void Write(const wxString &name, const wxString &value, bool ignoreEmpty=false)
void Check(int id, bool check)
void DeleteLog(int i)
Definition: logmanager.cpp:142
wxMenuItem * AppendSubMenu(wxMenu *submenu, const wxString &text, const wxString &help=wxEmptyString)
size_t SetSelection(size_t new_page)
void OnWrapMode(wxCommandEvent &event)
Definition: infopane.cpp:310
int(* CompareFunction)(Page **, Page **)
Definition: infopane.h:41
bool DeleteLogger(Logger *l)
Definition: infopane.cpp:490
a logger which prints messages to a wxTextCtrl
Definition: loggers.h:90
wxMenuItem * AppendSeparator()
LogManager * GetLogManager() const
Definition: manager.cpp:439
void OnCopy(wxCommandEvent &event)
Definition: infopane.cpp:298
wxString wxEmptyString
Logger * GetLogger(int index)
Definition: infopane.cpp:216
void UpdateEffectiveTabOrder()
Definition: infopane.cpp:167
const wxString & _(const wxString &string)
wxWindow * GetPage(size_t page_idx) const
wxArrayOfPage m_Pages
Definition: infopane.h:48
#define cbThrow(message)
Definition: cbexception.h:42
static wxString GetDataFolder(bool global=true)
bool ToLong(long *val, int base=10) const
bool HasMoreTokens() const
int GetTabPositionFromIndex(int index)
Get the tab position.
Definition: cbauibook.cpp:582
int GetPageIndex(wxWindow *page_wnd) const
wxWindow * window
Definition: infopane.h:34
bool AddNonLogger(wxWindow *p, const wxString &title, wxBitmap *icon=nullptr)
Definition: infopane.cpp:468
A notebook class This class is derived from wxAuiNotebook, to enhance its abilities.
Definition: cbauibook.h:30
virtual bool GetWrapMode() const
Definition: logger.h:69
void Toggle(size_t index)
Definition: infopane.cpp:178
void Hide(size_t i)
void ReorderTabs(CompareFunction cmp_f)
Definition: infopane.cpp:123
bool islogger
Definition: infopane.h:38
int Find(wxUniChar ch, bool fromEnd=false) const
wxBitmap m_DefaultBitmap
Definition: infopane.h:45
void ContextMenu(wxContextMenuEvent &event)
Definition: infopane.cpp:343
void Show(size_t index)
Definition: infopane.cpp:230
bool MovePage(wxWindow *page, size_t new_idx)
Move page.
Definition: cbauibook.cpp:548
bool InsertPagePrivate(wxWindow *p, const wxString &title, wxBitmap *icon=nullptr, int index=-1)
Definition: infopane.cpp:160
Logger * logger
Definition: infopane.h:35
int GetSelection() const
virtual void AppendAdditionalMenuItems(cb_optional wxMenu &menu)
Definition: logger.h:71
#define NULL
Definition: prefix.cpp:59
void OnTabContextMenu(wxAuiNotebookEvent &event)
Definition: infopane.cpp:348
bool DeleteNonLogger(wxWindow *p)
Definition: infopane.cpp:533
wxMenuItem * AppendCheckItem(int id, const wxString &item, const wxString &help=wxEmptyString)