summaryrefslogtreecommitdiff
path: root/include/tool/tool_manager.h
blob: 9b28f2355c1ab6a6d0a7ae19681edb82c42af70e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2013 CERN
 * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
 * @author Maciej Suminski <maciej.suminski@cern.ch>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

#ifndef __TOOL_MANAGER_H
#define __TOOL_MANAGER_H

#include <deque>
#include <typeinfo>
#include <map>

#include <tool/tool_base.h>

class TOOL_BASE;
class ACTION_MANAGER;
class CONTEXT_MENU;
class wxWindow;

/**
 * Class TOOL_MANAGER.
 * Master controller class:
 * - registers editing tools
 * - pumps UI events to tools requesting them
 * - manages tool state machines (transitions and wait requests)
 */
class TOOL_MANAGER
{
public:
    TOOL_MANAGER();

    ~TOOL_MANAGER();

    /**
     * Generates a unique ID from for a tool with given name.
     */
    static TOOL_ID MakeToolId( const std::string& aToolName );

    /**
     * Function RegisterTool()
     * Adds a tool to the manager set and sets it up. Called once for
     * each tool during application initialization.
     * @param aTool: tool to be added. Ownership is transferred.
     */
    void RegisterTool( TOOL_BASE* aTool );

    /**
     * Function InvokeTool()
     * Calls a tool by sending a tool activation event to tool of given ID.
     *
     * @param aToolId is the ID number of the requested tool.
     * @return True if the requested tool was invoked successfully.
     */
    bool InvokeTool( TOOL_ID aToolId );

    /**
     * Function InvokeTool()
     * Calls a tool by sending a tool activation event to tool of given name.
     *
     * @param aToolName is the name of the requested tool.
     * @return True if the requested tool was invoked successfully.
     */
    bool InvokeTool( const std::string& aToolName );

    /**
     * Function RegisterAction()
     * Registers an action that can be used to control tools (eg. invoke, trigger specific
     * behaviours).
     *
     * @param aAction is the action to be registered.
     */
    void RegisterAction( TOOL_ACTION* aAction );

    /**
     * Function UnregisterAction()
     * Unregisters an action, so it is no longer active.
     *
     * @param aAction is the action to be unregistered.
     */
    void UnregisterAction( TOOL_ACTION* aAction );

    /**
     * Function RunAction()
     * Runs the specified action. The common format for action names is "application.ToolName.Action".
     *
     * @param aActionName is the name of action to be invoked.
     * @param aNow decides if the action has to be run immediately or after the current coroutine
     * is preemptied.
     * @param aParam is an optional parameter that might be used by the invoked action. Its meaning
     * depends on the action.
     * @return False if the action was not found.
     */
    template<typename T>
    bool RunAction( const std::string& aActionName, bool aNow = false, T aParam = NULL )
    {
        return RunAction( aActionName, aNow, reinterpret_cast<void*>( aParam ) );
    }

    bool RunAction( const std::string& aActionName, bool aNow, void* aParam );

    bool RunAction( const std::string& aActionName, bool aNow = false )
    {
        return RunAction( aActionName, aNow, (void*) NULL );
    }

    /**
     * Function RunAction()
     * Runs the specified action.
     *
     * @param aAction is the action to be invoked.
     * @param aNow decides if the action has to be run immediately or after the current coroutine
     * is preemptied.
     * @param aParam is an optional parameter that might be used by the invoked action. Its meaning
     * depends on the action.
     */
    template<typename T>
    void RunAction( const TOOL_ACTION& aAction, bool aNow = false, T aParam = NULL )
    {
        RunAction( aAction, aNow, reinterpret_cast<void*>( aParam ) );
    }

    void RunAction( const TOOL_ACTION& aAction, bool aNow, void* aParam );

    void RunAction( const TOOL_ACTION& aAction, bool aNow = false )
    {
        RunAction( aAction, aNow, (void*) NULL );
    }

    ///> @copydoc ACTION_MANAGER::GetHotKey()
    int GetHotKey( const TOOL_ACTION& aAction );

    ///> @copydoc ACTION_MANAGER::UpdateHotKeys()
    void UpdateHotKeys();

    /**
     * Function FindTool()
     * Searches for a tool with given ID.
     *
     * @param aId is the ID number of the requested tool.
     * @return Pointer to the requested tool or NULL in case of failure.
     */
    TOOL_BASE* FindTool( int aId ) const;

    /**
     * Function FindTool()
     * Searches for a tool with given name.
     *
     * @param aName is the name of the requested tool.
     * @return Pointer to the requested tool or NULL in case of failure.
     */
    TOOL_BASE* FindTool( const std::string& aName ) const;

    /*
     * Function GetTool()
     * Returns the tool of given type or NULL if there is no such tool registered.
     */
    template<typename T>
    T* GetTool()
    {
        std::map<const char*, TOOL_BASE*>::iterator tool = m_toolTypes.find( typeid( T ).name() );

        if( tool != m_toolTypes.end() )
            return static_cast<T*>( tool->second );

        return NULL;
    }

    /**
     * Function DeactivateTool()
     * Deactivates the currently active tool.
     */
    void DeactivateTool();

    /**
     * Function ResetTools()
     * Resets all tools (i.e. calls their Reset() method).
     */
    void ResetTools( TOOL_BASE::RESET_REASON aReason );

    /**
     * Propagates an event to tools that requested events of matching type(s).
     * @param aEvent is the event to be processed.
     */
    bool ProcessEvent( const TOOL_EVENT& aEvent );

    /**
     * Puts an event to the event queue to be processed at the end of event processing cycle.
     * @param aEvent is the event to be put into the queue.
     */
    inline void PostEvent( const TOOL_EVENT& aEvent )
    {
        m_eventQueue.push_back( aEvent );
    }

    /**
     * Sets the work environment (model, view, view controls and the parent window).
     * These are made available to the tool. Called by the parent frame (PCB_EDIT_FRAME)
     * when the board is set up.
     */
    void SetEnvironment( EDA_ITEM* aModel, KIGFX::VIEW* aView,
            KIGFX::VIEW_CONTROLS* aViewControls, wxWindow* aFrame );

    /* Accessors for the environment objects (view, model, etc.) */
    KIGFX::VIEW* GetView() const
    {
        return m_view;
    }

    inline KIGFX::VIEW_CONTROLS* GetViewControls() const
    {
        return m_viewControls;
    }

    inline EDA_ITEM* GetModel() const
    {
        return m_model;
    }

    inline wxWindow* GetEditFrame() const
    {
        return m_editFrame;
    }

    /**
     * Returns id of the tool that is on the top of the active tools stack
     * (was invoked the most recently).
     * @return Id of the currently used tool.
     */
    inline int GetCurrentToolId() const
    {
        return m_activeTools.front();
    }

    /**
     * Returns the tool that is on the top of the active tools stack
     * (was invoked the most recently).
     * @return Pointer to the currently used tool.
     */
    inline TOOL_BASE* GetCurrentTool() const
    {
        return FindTool( GetCurrentToolId() );
    }

    /**
     * Returns priority of a given tool. Higher number means that the tool is closer to the
     * beginning of the active tools queue (i.e. receives events earlier, tools with lower
     * priority receive events later).
     * @param aToolId is the id of queried tool.
     * @return The priority of a given tool. If returned number is negative, then it means that
     * the tool id is invalid or the tool is not active.
     */
    int GetPriority( int aToolId ) const;

    /**
     * Defines a state transition - the events that cause a given handler method in the tool
     * to be called. Called by TOOL_INTERACTIVE::Go(). May be called from a coroutine context.
     */
    void ScheduleNextState( TOOL_BASE* aTool, TOOL_STATE_FUNC& aHandler,
            const TOOL_EVENT_LIST& aConditions );

    /**
     * Pauses execution of a given tool until one or more events matching aConditions arrives.
     * The pause/resume operation is done through COROUTINE object.
     * Called only from coroutines.
     */
    boost::optional<TOOL_EVENT> ScheduleWait( TOOL_BASE* aTool,
            const TOOL_EVENT_LIST& aConditions );

    /**
     * Sets behaviour of the tool's context popup menu.
     * @param aTool - the parent tool
     * @param aMenu - the menu structure, defined by the tool
     * @param aTrigger - when the menu is activated:
     *  CMENU_NOW: opens the menu right now
     *  CMENU_BUTTON: opens the menu when RMB is pressed
     *  CMENU_OFF: menu is disabled.
     * May be called from a coroutine context.
     */
    void ScheduleContextMenu( TOOL_BASE* aTool, CONTEXT_MENU* aMenu,
            CONTEXT_MENU_TRIGGER aTrigger );

    /**
     * Allows a tool to pass the already handled event to the next tool on the stack.
     */
    void PassEvent()
    {
        m_passEvent = true;
    }

    /**
     * Stores an information to the system clipboard.
     * @param aText is the information to be stored.
     * @return False if error occured.
     */
    bool SaveClipboard( const std::string& aText );

    /**
     * Returns the information currently stored in the system clipboard. If data stored in the
     * clipboard is in non-text format, empty string is returned.
     */
    std::string GetClipboard() const;

private:
    struct TOOL_STATE;
    typedef std::pair<TOOL_EVENT_LIST, TOOL_STATE_FUNC> TRANSITION;

    /**
     * Function dispatchInternal
     * Passes an event at first to the active tools, then to all others.
     */
    void dispatchInternal( const TOOL_EVENT& aEvent );

    /**
     * Function dispatchStandardEvents()
     * Handles specific events, that are intended for TOOL_MANAGER rather than tools.
     * @param aEvent is the event to be processed.
     * @return False if the event was processed and should not go any further.
     */
    bool dispatchStandardEvents( const TOOL_EVENT& aEvent );

    /**
     * Function dispatchActivation()
     * Checks if it is a valid activation event and invokes a proper tool.
     * @param aEvent is an event to be tested.
     * @return True if a tool was invoked, false otherwise.
     */
    bool dispatchActivation( const TOOL_EVENT& aEvent );

    /**
     * Function dispatchContextMenu()
     * Handles context menu related events.
     */
    void dispatchContextMenu( const TOOL_EVENT& aEvent );

    /**
     * Function invokeTool()
     * Invokes a tool by sending a proper event (in contrary to runTool, which makes the tool run
     * for real).
     * @param aTool is the tool to be invoked.
     */
    bool invokeTool( TOOL_BASE* aTool );

    /**
     * Function runTool()
     * Makes a tool active, so it can receive events and react to them. Activated tool is pushed
     * on the active tools stack, so the last activated tool receives events first.
     *
     * @param aToolId is the ID number of tool to be run.
     */
    bool runTool( TOOL_ID aToolId );

    /**
     * Function runTool()
     * Makes a tool active, so it can receive events and react to them. Activated tool is pushed
     * on the active tools stack, so the last activated tool receives events first.
     *
     * @param aName is the name of tool to be run.
     */
    bool runTool( const std::string& aName );

    /**
     * Function runTool()
     * Makes a tool active, so it can receive events and react to them. Activated tool is pushed
     * on the active tools stack, so the last activated tool receives events first.
     *
     * @param aTool is the tool to be run.
     */
    bool runTool( TOOL_BASE* aTool );

    template <class Parameters>
    void invokeTool( const std::string& aName, const Parameters& aToolParams );

    /**
     * Function finishTool()
     * Deactivates a tool and does the necessary clean up.
     *
     * @param aState is the state variable of the tool to be stopped.
     * @param aDeactivate decides if the tool should be removed from the active tools set.
     * @return True if the tool should be deactivated (note it does not necessarily  mean it has
     * been deactivated, aDeactivate parameter decides).
     */
    bool finishTool( TOOL_STATE* aState, bool aDeactivate = true );

    /**
     * Function isRegistered()
     * Returns information about a tool registration status.
     *
     * @param aTool is the tool to be checked.
     * @return true if the tool is in the registered tools list, false otherwise.
     */
    bool isRegistered( TOOL_BASE* aTool ) const
    {
        return m_toolState.count( aTool ) > 0;
    }

    /**
     * Function isActive()
     * Returns information about a tool activation status.
     *
     * @param aTool is the tool to be checked.
     * @return True if the tool is on the active tools stack, false otherwise.
     */
    bool isActive( TOOL_BASE* aTool );

    /// Index of registered tools current states, associated by tools' objects.
    std::map<TOOL_BASE*, TOOL_STATE*> m_toolState;

    /// Index of the registered tools current states, associated by tools' names.
    std::map<std::string, TOOL_STATE*> m_toolNameIndex;

    /// Index of the registered tools to easily lookup by their type.
    std::map<const char*, TOOL_BASE*> m_toolTypes;

    /// Index of the registered tools current states, associated by tools' ID numbers.
    std::map<TOOL_ID, TOOL_STATE*> m_toolIdIndex;

    /// Stack of the active tools
    std::list<TOOL_ID> m_activeTools;

    /// Instance of ACTION_MANAGER that handles TOOL_ACTIONs
    ACTION_MANAGER* m_actionMgr;

    EDA_ITEM* m_model;
    KIGFX::VIEW* m_view;
    KIGFX::VIEW_CONTROLS* m_viewControls;
    wxWindow* m_editFrame;

    /// Queue that stores events to be processed at the end of the event processing cycle.
    std::list<TOOL_EVENT> m_eventQueue;

    /// Flag saying if the currently processed event should be passed to other tools.
    bool m_passEvent;
};

#endif