1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef TrenchBroom_Menu
21 #define TrenchBroom_Menu
22 
23 #include "Preference.h"
24 #include "SharedPointer.h"
25 #include "StringUtils.h"
26 #include "View/Action.h"
27 #include "View/KeyboardShortcutEntry.h"
28 
29 #include <vector>
30 #include <map>
31 
32 class wxMenu;
33 class wxMenuBar;
34 
35 namespace TrenchBroom {
36     namespace View {
37         class ActionMenuItem;
38         class KeyboardShortcut;
39         class MenuItemParent;
40 
41         class MenuItem {
42         public:
43             typedef enum {
44                 Type_Separator,
45                 Type_Action,
46                 Type_Check,
47                 Type_Menu
48             } Type;
49 
50             typedef std::vector<MenuItem*> List;
51         private:
52             Type m_type;
53             MenuItemParent* m_parent;
54         public:
55             MenuItem(const Type type, MenuItemParent* parent);
56             virtual ~MenuItem();
57 
58             Type type() const;
59             const MenuItemParent* parent() const;
60 
61             void appendToMenu(wxMenu* menu, bool withShortcuts) const;
62             void appendToMenu(wxMenuBar* menu, bool withShortcuts) const;
63             const ActionMenuItem* findActionMenuItem(int id) const;
64             void getShortcutEntries(KeyboardShortcutEntry::List& entries);
65 
66             void resetShortcuts();
67         private:
68             virtual void doAppendToMenu(wxMenu* menu, bool withShortcuts) const = 0;
69             virtual void doAppendToMenu(wxMenuBar* menu, bool withShortcuts) const;
70             virtual const ActionMenuItem* doFindActionMenuItem(int id) const;
71             virtual void doGetShortcutEntries(KeyboardShortcutEntry::List& entries);
72             virtual void doResetShortcuts();
73         };
74 
75         class SeparatorItem : public MenuItem {
76         public:
77             SeparatorItem(MenuItemParent* parent);
78         private:
79             void doAppendToMenu(wxMenu* menu, bool withShortcuts) const;
80         };
81 
82         class LabeledMenuItem : public MenuItem {
83         public:
84             LabeledMenuItem(Type type, MenuItemParent* parent);
85             virtual ~LabeledMenuItem();
86         public:
87             int id() const;
88             const String& label() const;
89         private:
90             virtual int doGetId() const = 0;
91             virtual const String& doGetLabel() const = 0;
92         };
93 
94         class ActionMenuItem : public LabeledMenuItem, public KeyboardShortcutEntry {
95         private:
96             mutable Action m_action;
97             mutable Preference<KeyboardShortcut> m_preference;
98         public:
99             ActionMenuItem(Type type, MenuItemParent* parent, int id, const String& label, const KeyboardShortcut& defaultShortcut, bool modifiable);
100             virtual ~ActionMenuItem();
101 
102             wxString menuString(const wxString& suffix, bool withShortcuts) const;
103         private:
104             IO::Path path(const String& text) const;
105         private: // implement LabeledMenuItem interface
106             void doAppendToMenu(wxMenu* menu, bool withShortcuts) const;
107             const ActionMenuItem* doFindActionMenuItem(int id) const;
108             void doGetShortcutEntries(KeyboardShortcutEntry::List& entries);
109             void doResetShortcuts();
110 
111             int doGetId() const;
112             const String& doGetLabel() const;
113         private: // implement KeyboardShortcutEntry interface
114             int doGetActionContext() const;
115             bool doGetModifiable() const;
116             wxString doGetActionDescription() const;
117             wxString doGetJsonString() const;
118             const Preference<KeyboardShortcut>& doGetPreference() const;
119             const KeyboardShortcut& doGetShortcut() const;
120             void doUpdateShortcut(const KeyboardShortcut& shortcut);
121             wxAcceleratorEntry doGetAcceleratorEntry(ActionView view) const;
122         };
123 
124         class Menu;
125 
126         class MenuItemParent : public LabeledMenuItem {
127         private:
128             int m_id;
129             String m_label;
130             List m_items;
131         protected:
132             MenuItemParent(Type type, MenuItemParent* parent, int id, const String& label);
133         public:
134             virtual ~MenuItemParent();
135 
136             void addItem(MenuItem* item);
137             const List& items() const;
138             List& items();
139         private:
140             void doAppendToMenu(wxMenu* menu, bool withShortcuts) const;
141             void doAppendToMenu(wxMenuBar* menu, bool withShortcuts) const;
142             wxMenu* buildMenu(bool withShortcuts) const;
143 
144             const ActionMenuItem* doFindActionMenuItem(int id) const;
145             void doGetShortcutEntries(KeyboardShortcutEntry::List& entries);
146             void doResetShortcuts();
147 
148             int doGetId() const;
149             const String& doGetLabel() const;
150         };
151 
152         class Menu : public MenuItemParent {
153         public:
154             Menu(MenuItemParent* parent, int id, const String& label);
155             Menu(const String& label);
156             virtual ~Menu();
157 
158             MenuItem* addModifiableActionItem(int id, const String& label, const KeyboardShortcut& defaultShortcut = KeyboardShortcut::Empty);
159             MenuItem* addUnmodifiableActionItem(int id, const String& label, const KeyboardShortcut& defaultShortcut = KeyboardShortcut::Empty);
160 
161             MenuItem* addModifiableCheckItem(int id, const String& label, const KeyboardShortcut& defaultShortcut = KeyboardShortcut::Empty);
162             MenuItem* addUnmodifiableCheckItem(int id, const String& label, const KeyboardShortcut& defaultShortcut = KeyboardShortcut::Empty);
163 
164             void addSeparator();
165             Menu* addMenu(const String& label);
166             Menu* addMenu(int id, const String& label);
167         private:
168             MenuItem* addActionItem(int id, const String& label, const KeyboardShortcut& defaultShortcut, bool modifiable);
169             MenuItem* addCheckItem(int id, const String& label, const KeyboardShortcut& defaultShortcut, bool modifiable);
170         };
171 
172         class MenuBar {
173         private:
174             typedef std::vector<Menu*> MenuList;
175             MenuList m_menus;
176         public:
177             MenuBar();
178             ~MenuBar();
179 
180             const ActionMenuItem* findActionMenuItem(int id) const;
181             void resetShortcuts();
182 
183             Menu* addMenu(const String& label);
184             wxMenuBar* createMenuBar(bool withShortcuts);
185 
186             void getShortcutEntries(KeyboardShortcutEntry::List& entries) const;
187         };
188     }
189 }
190 
191 #endif /* defined(TrenchBroom_Menu) */
192