Code::Blocks  SVN r11506
menuitemsmanager.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: 10322 $
6  * $Id: menuitemsmanager.cpp 10322 2015-06-05 07:57:16Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/menuitemsmanager.cpp $
8  */
9 
10 #ifndef CB_PRECOMP
11  #include <wx/frame.h> // GetMenuBar
12 #endif
13 
14 #include "sdk_precomp.h"
15 #include "manager.h"
16 #include "menuitemsmanager.h"
17 #include <wx/regex.h>
18 
19 namespace
20 {
21  wxRegEx reInsert(_T("([0-9]+):.+"));
22 }
23 
24 MenuItemsManager::MenuItemsManager(bool autoClearOnDestroy)
25  : m_AutoClearOnDestroy(autoClearOnDestroy)
26 {
27  //ctor
28 }
29 
31 {
32  //dtor
34  {
35  Clear();
36  m_MenuItems.Clear();
37  }
38 }
39 
48 wxMenuItem* MenuItemsManager::Add(wxMenu* parent, int id, const wxString& caption, const wxString& helptext)
49 {
50  if (!parent)
51  return nullptr;
52  wxMenuItem* ni = new wxMenuItem(parent, id, caption, helptext);
53  m_MenuItems.Add(ni);
54  parent->Append(ni);
55  return ni;
56 }
57 
67 wxMenuItem* MenuItemsManager::Insert(wxMenu* parent, int index, int id, const wxString& caption, const wxString& helptext)
68 {
69  if (!parent)
70  return nullptr;
71  wxMenuItem* ni = new wxMenuItem(parent, id, caption, helptext);
72  m_MenuItems.Add(ni);
73  parent->Insert(index, ni);
74  return ni;
75 } // end of Insert
76 
80 {
81  for (unsigned int i = 0; i < m_MenuItems.Count(); ++i)
82  {
83  wxMenuItem* ni = m_MenuItems[i];
84  wxMenu* menu = ni->GetMenu();
85  wxMenu* subMenu = ni->GetSubMenu();
86  if (menu)
87  {
88  // only delete if it's not a submenu or, if it is but it's empty
89  if (!subMenu || subMenu->GetMenuItemCount() == 0)
90  menu->Delete(ni);
91  }
92  }
93  m_MenuItems.Clear();
94 } // end of Clear
95 
105 int MenuItemsManager::CreateFromString(const wxString& menuPath, int id)
106 {
107  wxMenuBar* mbar = Manager::Get()->GetAppFrame()->GetMenuBar();
108  wxMenu* menu = nullptr;
109  size_t pos = 0;
110  while (true)
111  {
112  // ignore consecutive slashes
113  while (pos < menuPath.Length() && menuPath.GetChar(pos) == _T('/'))
114  {
115  ++pos;
116  }
117 
118  // find next slash
119  size_t nextPos = pos;
120  while (nextPos < menuPath.Length() && menuPath.GetChar(++nextPos) != _T('/'))
121  ;
122 
123  wxString current = menuPath.Mid(pos, nextPos - pos);
124  if (current.IsEmpty())
125  break;
126  bool isLast = nextPos >= menuPath.Length();
127 
128  bool insert = false;
129  unsigned long insertIndex = 0;
130  if (reInsert.Matches(current))
131  {
132  // insert menu instead append (format "insertIndex:menuName")
133  wxString indexS = reInsert.GetMatch(current, 1);
134  if (indexS.ToULong(&insertIndex, 10))
135  {
136  current.Remove(0, indexS.Length() + 1); // +1 to remove the ":" too
137  insert = true;
138  }
139  }
140 
141  if (!menu)
142  {
143  if (isLast)
144  return 0;
145 
146  // for first entry we must search on the menubar
147  int menuPos = mbar->FindMenu(current);
148  if (menuPos == wxNOT_FOUND)
149  {
150  menu = new wxMenu();
151  mbar->Insert(insert ? insertIndex : mbar->GetMenuCount() - 2, menu, current); // -2 to be inserted before "Settings"
152  }
153  else
154  menu = mbar->GetMenu(menuPos);
155  }
156  else
157  {
158  bool needsSep = current.StartsWith(_T("-"));
159  if (needsSep)
160  current.Remove(0, 1); // remove dash (-)
161 
162  int existingID = menu->FindItem(current);
163  if (existingID != wxNOT_FOUND)
164  {
165  // existing menu
166  // if it is the final item we want to create, display error and stop
167 
168  if (isLast)
169  return existingID;
170 
171  // else just keep the menu pointer updated
172  wxMenuItem *item = menu->FindChildItem(existingID);
173  if (item)
174  {
175  wxMenu* existingMenu = item->GetSubMenu();
176  if (existingMenu)
177  menu = existingMenu;
178  else
179  return 0;
180  }
181  else
182  return 0;
183  }
184  else
185  {
186  if (needsSep)
187  {
188  wxMenuItem* item = new wxMenuItem(menu, wxID_SEPARATOR);
189  menu->Insert(insert ? insertIndex : menu->GetMenuItemCount(), item);
190  }
191 
192  if (current.IsEmpty()) // may be now if it was just a separator (-)
193  break;
194 
195  if (isLast)
196  {
197  Insert(menu, insert ? insertIndex : menu->GetMenuItemCount(), id, current, wxEmptyString);
198  return id;
199  }
200  else
201  {
202  wxMenu* sub = new wxMenu;
203  wxMenuItem* item = new wxMenuItem(menu, -1, current, wxEmptyString, wxITEM_NORMAL, sub);
204  menu->Insert(insert ? insertIndex : menu->GetMenuItemCount(), item);
205  menu = sub;
206  }
207  }
208  }
209 
210  pos = nextPos; // prepare for next loop
211  }
212  return 0;
213 } // end of CreateFromString
virtual bool Insert(size_t pos, wxMenu *menu, const wxString &title)
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
size_t Length() const
wxMenuItem * Append(int id, const wxString &item=wxEmptyString, const wxString &helpString=wxEmptyString, wxItemKind kind=wxITEM_NORMAL)
#define _T(string)
virtual int CreateFromString(const wxString &menuPath, int id)
Create menu path from string.
bool ToULong(unsigned long *val, int base=10) const
wxString & Remove(size_t pos)
#define wxNOT_FOUND
size_t GetMenuItemCount() const
wxFrame * GetAppFrame() const
Definition: manager.cpp:419
bool Delete(int id)
wxMenu * GetMenu() const
virtual void Clear()
Clear all managed menu items.
wxMenu * GetMenu(size_t menuIndex) const
wxString wxEmptyString
int FindMenu(const wxString &title) const
size_t GetMenuCount() const
virtual int FindItem(const wxString &itemString) const
bool IsEmpty() const
virtual ~MenuItemsManager()
wxMenuItem * FindChildItem(int id, size_t *pos=NULL) const
virtual wxMenuItem * Insert(wxMenu *parent, int index, int id, const wxString &caption, const wxString &helptext)
Insert a menu item.
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
wxUniChar GetChar(size_t n) const
wxMenu * GetSubMenu() const
MenuItemsManager(bool autoClearOnDestroy=true)
MenuItemsList m_MenuItems
wxString Mid(size_t first, size_t nCount=wxString::npos) const
wxMenuItem * Insert(size_t pos, wxMenuItem *menuItem)
virtual wxMenuItem * Add(wxMenu *parent, int id, const wxString &caption, const wxString &helptext)
Add a menu item.