1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013 CERN
5  * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * @author Maciej Suminski <maciej.suminski@cern.ch>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
25  */
26 
27 #ifndef ACTION_MANAGER_H_
28 #define ACTION_MANAGER_H_
29 
30 #include <list>
31 #include <map>
32 #include <string>
33 #include <set>
34 
35 #include <tool/selection_conditions.h>
36 
37 class TOOL_BASE;
38 class TOOL_MANAGER;
39 class TOOL_ACTION;
40 
41 /**
42  * Functors that can be used to figure out how the action controls should be displayed in the UI
43  * and if an action should be enabled given the current selection.
44  *
45  * @note @c checkCondition is also used for determining the state of a toggled toolbar item
46  *       (the item is toggled when the condition is true).
47  */
48 struct ACTION_CONDITIONS
49 {
ACTION_CONDITIONSACTION_CONDITIONS50     ACTION_CONDITIONS()
51     {
52         checkCondition  = SELECTION_CONDITIONS::ShowNever;      // Never check by default
53         enableCondition = SELECTION_CONDITIONS::ShowAlways;     // Always enable by default
54         showCondition   = SELECTION_CONDITIONS::ShowAlways;     // Always show by default
55     }
56 
CheckACTION_CONDITIONS57     ACTION_CONDITIONS& Check( const SELECTION_CONDITION& aCondition )
58     {
59         checkCondition = aCondition;
60         return *this;
61     }
62 
EnableACTION_CONDITIONS63     ACTION_CONDITIONS& Enable( const SELECTION_CONDITION& aCondition )
64     {
65         enableCondition = aCondition;
66         return *this;
67     }
68 
ShowACTION_CONDITIONS69     ACTION_CONDITIONS& Show( const SELECTION_CONDITION& aCondition )
70     {
71         showCondition = aCondition;
72         return *this;
73     }
74 
75     SELECTION_CONDITION checkCondition;     ///< Returns true if the UI control should be checked
76     SELECTION_CONDITION enableCondition;    ///< Returns true if the UI control should be enabled
77     SELECTION_CONDITION showCondition;      ///< Returns true if the UI control should be shown
78 };
79 
80 /**
81  * Manage #TOOL_ACTION objects.
82  *
83  * Registering them and allows one to run them using associated hot keys, names or ids.
84  */
85 class ACTION_MANAGER
86 {
87 public:
88     /**
89      * @param aToolManager is a tool manager instance that is used to pass events to tools.
90      */
91     ACTION_MANAGER( TOOL_MANAGER* aToolManager );
92 
93     /**
94      * Unregister every registered action.
95      */
96     ~ACTION_MANAGER();
97 
98     /**
99      * Add a tool action to the manager and sets it up. After that it is possible to invoke
100      * the action using hotkeys or sending a command event with its name.
101      *
102      * @param aAction: action to be added. Ownership is not transferred.
103      */
104     void RegisterAction( TOOL_ACTION* aAction );
105 
106     /**
107      * Generate an unique ID from for an action with given name.
108      */
109     static int MakeActionId( const std::string& aActionName );
110 
111     /**
112      * Get a list of currently-registered actions mapped by their name.
113      */
114     const std::map<std::string, TOOL_ACTION*>& GetActions() const;
115 
116     /**
117      * Find an action with a given name (if there is one available).
118      *
119      * @param aActionName is the searched action.
120      * @return Pointer to a TOOL_ACTION object or NULL if there is no such action.
121      */
122     TOOL_ACTION* FindAction( const std::string& aActionName ) const;
123 
124     /**
125      * Run an action associated with a hotkey (if there is one available).
126      *
127      * @param aHotKey is the hotkey to be handled.
128      * @return True if there was an action associated with the hotkey, false otherwise.
129      */
130     bool RunHotKey( int aHotKey ) const;
131 
132     /**
133      * Return the hot key associated with a given action or 0 if there is none.
134      *
135      * @param aAction is the queried action.
136      */
137     int GetHotKey( const TOOL_ACTION& aAction ) const;
138 
139     /**
140      * Optionally read the hotkey config files and then rebuilds the internal hotkey maps.
141      */
142     void UpdateHotKeys( bool aFullUpdate );
143 
144     /**
145      * Return list of TOOL_ACTIONs.
146      *
147      * #TOOL_ACTIONs add themselves to the list upon their creation.
148      *
149      * @return List of TOOL_ACTIONs.
150      */
GetActionList()151     static std::list<TOOL_ACTION*>& GetActionList()
152     {
153         static std::list<TOOL_ACTION*> actionList;
154 
155         return actionList;
156     }
157 
158     /**
159      * Set the conditions the UI elements for activating a specific tool action should use
160      * for determining the current UI state (e.g. checked, enabled, shown)
161      *
162      * @param aAction is the tool action using these conditions.
163      * @param aConditions are the conditions to use for the action.
164      */
165     void SetConditions( const TOOL_ACTION& aAction, const ACTION_CONDITIONS& aConditions );
166 
167     /**
168      * Get the conditions to use for a specific tool action.
169      *
170      * @param aAction is the tool action.
171      * @return the action conditions, returns nullptr if no conditions are registered.
172      */
173     const ACTION_CONDITIONS* GetCondition( const TOOL_ACTION& aAction ) const;
174 
175 private:
176     // Resolve a hotkey by applying legacy and current settings over the action's
177     // default hotkey.
178     int processHotKey( TOOL_ACTION* aAction, std::map<std::string, int> aLegacyMap,
179                        std::map<std::string, int> aHotKeyMap );
180 
181     ///< Tool manager needed to run actions
182     TOOL_MANAGER* m_toolMgr;
183 
184     ///< Map for indexing actions by their names
185     std::map<std::string, TOOL_ACTION*> m_actionNameIndex;
186 
187     ///< Map for indexing actions by their hotkeys
188     typedef std::map<int, std::list<TOOL_ACTION*> > HOTKEY_LIST;
189     HOTKEY_LIST m_actionHotKeys;
190 
191     ///< Quick action<->hot key lookup
192     std::map<int, int> m_hotkeys;
193 
194     /// Map the command ID that wx uses for the action to the UI conditions for the
195     /// menu/toolbar items
196     std::map<int, ACTION_CONDITIONS> m_uiConditions;
197 };
198 
199 #endif /* ACTION_MANAGER_H_ */
200