1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
5 #include "EditorCommonAPI.h"
7 #include <CryString/CryString.h>
8 #include <CrySandbox/CrySignal.h>
15 //! CAbstractMenu is a simple menu abstraction which is similar to QMenu and provides the following benefits:
16 //! - Priority based ordering
17 //! - Sections instead of manually adding separators
18 //! - Removing of menu items
19 //! An abstract menu is a list of menu items. Each menu item is either an action or another menu.
20 //! Each menu item has a priority and a section. Within a menu, menu items are lexicographically sorted
21 //! by (section, priority, order of insertion).
22 //! Sections are intended to be visually separated.
23 class EDITOR_COMMON_API CAbstractMenu
: public _i_reference_target_t
26 enum EPriorities
: int
28 ePriorities_Append
= INT_MIN
, //! See CAbstractMenu::AddAction.
29 ePriorities_Min
//! Priorities are in the range [PRIORITY_MIN, INT_MAX].
34 eSections_Default
= INT_MIN
, //! See CAbstractMenu::AddAction.
35 eSections_Min
//! Sections are in the range [SECTION_MIN, INT_MAX].
38 //! Creates a menu-like widget (e.g., QMenu, QMenuBar, ...) from an abstract menu.
39 //! \sa CAbstractMenu::Build()
48 //! Adds this action to widget. Does not take ownership of the action.
49 virtual void AddAction(QAction
* pAction
) {}
51 //! Adds a section to the widget.
52 virtual void AddSection(const SSection
& sec
) {}
54 //! Enables or disables the menu
55 virtual void SetEnabled(bool enabled
) {}
57 //! Adds a sub-menu to the widget.
58 //! \return A widget builder for the sub-menu; or a pointer that owns nothing, if no sub-menu should be created.
59 virtual std::unique_ptr
<IWidgetBuilder
> AddMenu(const CAbstractMenu
* pMenu
) { return std::unique_ptr
<IWidgetBuilder
>(); }
72 CAbstractMenu(const CAbstractMenu
&) = delete;
73 CAbstractMenu
& operator=(const CAbstractMenu
&) = delete;
75 int GetNextEmptySection() const;
77 int GetMaxSection() const;
78 int GetMaxPriority(int section
) const;
82 //! Add an action to the menu.
83 //! \param priority If value is EPriorities::ePriorities_Append, the item is assigned the next integer that is
84 //! greater than the maximum priority of all existing items. This effectively appends the item
85 //! to the menu. Otherwise the value is the priority of the menu item.
86 //! \param section If value is ESections::eSections_Default, the item will be added to the default section.
87 //! Otherwise the menu item is added to this section.
89 void AddAction(QAction
* pAction
, int sectionHint
= eSections_Default
, int priorityHint
= ePriorities_Append
);
91 //! Add an action based on editor commands to the menu. The command must be registered and be a UI command.
92 //! \param priority If value is EPriorities::ePriorities_Append, the item is assigned the next integer that is
93 //! greater than the maximum priority of all existing items. This effectively appends the item
94 //! to the menu. Otherwise the value is the priority of the menu item.
95 //! \param section If value is ESections::eSections_Default, the item will be added to the default section.
96 //! Otherwise the menu item is added to this section.
97 //! \sa ICommandManager
98 void AddCommandAction(const char* szCommand
, int sectionHint
= eSections_Default
, int priorityHint
= ePriorities_Append
);
100 //! Creates an action and adds it to the menu.
101 //! \param priority If value is EPriorities::ePriorities_Append, the item is assigned the next integer that is
102 //! greater than the maximum priority of all existing items. This effectively appends the item
103 //! to the menu. Otherwise the value is the priority of the menu item.
104 //! \param section If value is ESections::eSections_Default, the item will be added to the default section.
105 //! Otherwise the menu item is added to this section.
106 QAction
* CreateAction(const QString
& name
, int sectionHint
= eSections_Default
, int priorityHint
= ePriorities_Append
);
108 //! Creates an action and adds it to the menu.
109 //! \param priority If value is EPriorities::ePriorities_Append, the item is assigned the next integer that is
110 //! greater than the maximum priority of all existing items. This effectively appends the item
111 //! to the menu. Otherwise the value is the priority of the menu item.
112 //! \param section If value is ESections::eSections_Default, the item will be added to the default section.
113 //! Otherwise the menu item is added to this section.
114 QAction
* CreateAction(const QIcon
& icon
, const QString
& name
, int sectionHint
= eSections_Default
, int priorityHint
= ePriorities_Append
);
116 //! Creates and adds a new sub-menu.
117 //! \param priority If value is EPriorities::ePriorities_Append, the item is assigned the next integer that is
118 //! greater than the maximum priority of all existing items. This effectively appends the item
119 //! to the menu. Otherwise the value is the priority of the menu item.
120 //! \param section If value is ESections::eSections_Default, the item will be added to the default section.
121 //! Otherwise the menu item is added to this section.
123 CAbstractMenu
* CreateMenu(const char* szName
, int sectionHint
= eSections_Default
, int priorityHint
= ePriorities_Append
);
125 //! Creates and adds a new sub-menu.
126 //! \param priority If value is EPriorities::ePriorities_Append, the item is assigned the next integer that is
127 //! greater than the maximum priority of all existing items. This effectively appends the item
128 //! to the menu. Otherwise the value is the priority of the menu item.
129 //! \param section If value is ESections::eSections_Default, the item will be added to the default section.
130 //! Otherwise the menu item is added to this section.
132 CAbstractMenu
* CreateMenu(const QString
& name
, int sectionHint
= eSections_Default
, int priorityHint
= ePriorities_Append
);
134 void SetSectionName(int section
, const char* szName
);
136 bool IsNamedSection(int section
) const;
137 const char* GetSectionName(int section
) const;
138 // Returns index of the section with the name equal to the szName value or eSections_Default if no such section is found.
139 int FindSectionByName(const char* szName
) const;
140 // Returns index of the section with the name equal to the szName value.
141 // If the section is not found it will be created.
142 int FindOrCreateSectionByName(const char* szName
);
144 CAbstractMenu
* FindMenu(const char* szName
);
145 CAbstractMenu
* FindMenuRecursive(const char* szName
);
147 bool ContainsAction(const QAction
* pAction
) const;
149 //! Will disable all its child actions, leaving them in the menu but greyed out
150 void SetEnabled(bool enabled
) { m_bEnabled
= enabled
; }
151 bool IsEnabled() const { return m_bEnabled
; }
153 const char* GetName() const;
155 void Build(IWidgetBuilder
& widgetBuilder
) const;
157 CCrySignal
<void()> signalActionAdded
;
158 CCrySignal
<void(CAbstractMenu
*)> signalMenuAdded
;
159 CCrySignal
<void(CAbstractMenu
*)> signalAboutToShow
;
162 CAbstractMenu(const char* szName
);
164 int GetSectionFromHint(int sectionHint
) const;
165 int GetPriorityFromHint(int priorityHint
, int section
) const;
166 int GetDefaultSection() const;
168 void InsertItem(SMenuItem
* pItem
);
169 void InsertNamedSection(std::unique_ptr
<SNamedSection
>&& namedSection
);
172 std::vector
<_smart_ptr
<CAbstractMenu
>> m_subMenus
;
173 std::vector
<std::unique_ptr
<QAction
>> m_actions
;
174 std::vector
<std::unique_ptr
<SSubMenuItem
>> m_subMenuItems
;
175 std::vector
<std::unique_ptr
<SActionItem
>> m_actionItems
;
176 std::vector
<SMenuItem
*> m_sortedItems
;
177 std::vector
<std::unique_ptr
<SNamedSection
>> m_sortedNamedSections
;