tool_manager.h 12.2 KB
Newer Older
1 2 3 4 5
/*
 * 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>
6
 * @author Maciej Suminski <maciej.suminski@cern.ch>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 *
 * 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>
30 31
#include <typeinfo>
#include <boost/unordered_map.hpp>
32 33 34 35 36 37

#include <math/vector2d.h>

#include <tool/tool_base.h>

class TOOL_BASE;
38
class ACTION_MANAGER;
39 40 41 42 43 44 45 46 47 48 49 50
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
{
Maciej Suminski's avatar
Maciej Suminski committed
51
public:
52
    TOOL_MANAGER();
53

Maciej Suminski's avatar
Maciej Suminski committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
    ~TOOL_MANAGER();

    /**
     * Generates an 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()
71
     * Calls a tool by sending a tool activation event to tool of given ID.
Maciej Suminski's avatar
Maciej Suminski committed
72
     *
73
     * @param aToolId is the ID number of the requested tool.
Maciej Suminski's avatar
Maciej Suminski committed
74
     * @return True if the requested tool was invoked successfully.
Maciej Suminski's avatar
Maciej Suminski committed
75
     */
76
    bool InvokeTool( TOOL_ID aToolId );
Maciej Suminski's avatar
Maciej Suminski committed
77

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
    /**
     * 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.
     */
94
    void RegisterAction( TOOL_ACTION* aAction );
95 96 97 98 99 100 101

    /**
     * Function UnregisterAction()
     * Unregisters an action, so it is no longer active.
     *
     * @param aAction is the action to be unregistered.
     */
102
    void UnregisterAction( TOOL_ACTION* aAction );
Maciej Suminski's avatar
Maciej Suminski committed
103

104 105
    /**
     * Function RunAction()
106
     * Runs the specified action. The common format for action names is "application.ToolName.Action".
107 108 109 110 111 112
     *
     * @param aActionName is the name of action to be invoked.
     * @return True if the action finished successfully, false otherwise.
     */
    bool RunAction( const std::string& aActionName );

113 114 115 116 117 118 119 120
    /**
     * Function RunAction()
     * Runs the specified action.
     *
     * @param aAction is the action to be invoked.
     */
    void RunAction( const TOOL_ACTION& aAction );

Maciej Suminski's avatar
Maciej Suminski committed
121 122
    /**
     * Function FindTool()
123
     * Searches for a tool with given ID.
Maciej Suminski's avatar
Maciej Suminski committed
124
     *
125 126
     * @param aId is the ID number of the requested tool.
     * @return Pointer to the requested tool or NULL in case of failure.
Maciej Suminski's avatar
Maciej Suminski committed
127
     */
Maciej Suminski's avatar
Maciej Suminski committed
128
    TOOL_BASE* FindTool( int aId ) const;
129 130 131 132 133 134 135 136

    /**
     * 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.
     */
Maciej Suminski's avatar
Maciej Suminski committed
137
    TOOL_BASE* FindTool( const std::string& aName ) const;
Maciej Suminski's avatar
Maciej Suminski committed
138

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
    /*
     * Function GetTool()
     * Returns the tool of given type or NULL if there is no such tool registered.
     */
    template<typename T>
    T* GetTool()
    {
        boost::unordered_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;
    }

Maciej Suminski's avatar
Maciej Suminski committed
154
    /**
155 156
     * Function ResetTools()
     * Resets all tools (i.e. calls their Reset() method).
Maciej Suminski's avatar
Maciej Suminski committed
157
     */
158
    void ResetTools( TOOL_BASE::RESET_REASON aReason );
Maciej Suminski's avatar
Maciej Suminski committed
159 160 161 162 163 164 165 166 167 168

    /**
     * Takes an event from the TOOL_DISPATCHER and propagates it to
     * tools that requested events of matching type(s)
     */
    bool ProcessEvent( TOOL_EVENT& 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)
Maciej Suminski's avatar
Maciej Suminski committed
169
     * when the board is set up.
Maciej Suminski's avatar
Maciej Suminski committed
170
     */
171 172
    void SetEnvironment( EDA_ITEM* aModel, KIGFX::VIEW* aView,
            KIGFX::VIEW_CONTROLS* aViewControls, wxWindow* aFrame );
Maciej Suminski's avatar
Maciej Suminski committed
173 174

    /* Accessors for the environment objects (view, model, etc.) */
175
    KIGFX::VIEW* GetView() const
Maciej Suminski's avatar
Maciej Suminski committed
176 177 178 179
    {
        return m_view;
    }

180
    KIGFX::VIEW_CONTROLS* GetViewControls() const
Maciej Suminski's avatar
Maciej Suminski committed
181 182 183 184
    {
        return m_viewControls;
    }

185
    EDA_ITEM* GetModel() const
Maciej Suminski's avatar
Maciej Suminski committed
186 187 188 189
    {
        return m_model;
    }

190
    wxWindow* GetEditFrame() const
Maciej Suminski's avatar
Maciej Suminski committed
191 192 193 194
    {
        return m_editFrame;
    }

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
    /**
     * 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.
     */
    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.
     */
    TOOL_BASE* GetCurrentTool() const
    {
        return FindTool( GetCurrentToolId() );
    }

215 216 217 218 219 220 221 222 223 224
    /**
     * 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;

Maciej Suminski's avatar
Maciej Suminski committed
225 226 227 228 229
    /**
     * 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,
230
            const TOOL_EVENT_LIST& aConditions );
Maciej Suminski's avatar
Maciej Suminski committed
231 232 233 234 235 236 237

    /**
     * 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,
238
            const TOOL_EVENT_LIST& aConditions );
Maciej Suminski's avatar
Maciej Suminski committed
239 240 241 242 243 244 245 246 247 248 249

    /**
     * Sets behaviour of the tool's context popup menu.
     * @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,
250
            CONTEXT_MENU_TRIGGER aTrigger );
Maciej Suminski's avatar
Maciej Suminski committed
251

252
    /**
Maciej Suminski's avatar
Maciej Suminski committed
253
     * Allows a tool to pass the already handled event to the next tool on the stack.
254 255 256 257 258
     */
    void PassEvent()
    {
        m_passEvent = true;
    }
Maciej Suminski's avatar
Maciej Suminski committed
259

260 261 262 263 264 265 266 267 268
    /**
     * Returns list of TOOL_ACTIONs. TOOL_ACTIONs add themselves to the list upon their
     * creation.
     * @return List of TOOL_ACTIONs.
     */
    static std::list<TOOL_ACTION*>& GetActionList()
    {
        // TODO I am afraid this approach won't work when we reach multitab version of kicad.
        static std::list<TOOL_ACTION*> actionList;
269

270 271 272 273
        return actionList;
    }

private:
274 275
    struct TOOL_STATE;
    typedef std::pair<TOOL_EVENT_LIST, TOOL_STATE_FUNC> TRANSITION;
Maciej Suminski's avatar
Maciej Suminski committed
276

277
    void dispatchInternal( TOOL_EVENT& aEvent );
278

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

287 288 289 290 291 292 293 294 295 296
    /**
     * 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( TOOL_EVENT& aEvent );

    /**
     * Function invokeTool()
297 298
     * Invokes a tool by sending a proper event (in contrary to runTool, which makes the tool run
     * for real).
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
     * @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 aToolId 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 aToolId is the tool to be run.
     */
    bool runTool( TOOL_BASE* aTool );

    template <class Parameters>
331
    void invokeTool( const std::string& aName, const Parameters& aToolParams );
332 333 334 335 336 337 338

    /**
     * Function finishTool()
     * Deactivates a tool and does the necessary clean up.
     *
     * @param aState is the state variable of the tool to be stopped.
     */
339
    void finishTool( TOOL_STATE* aState );
340

341 342 343 344 345 346 347 348 349
    /**
     * 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
    {
350
        return m_toolState.count( aTool ) > 0;
351 352 353 354 355 356 357 358 359 360 361 362
    }

    /**
     * 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.
363
    boost::unordered_map<TOOL_BASE*, TOOL_STATE*> m_toolState;
364 365

    /// Index of the registered tools current states, associated by tools' names.
366 367 368 369
    boost::unordered_map<std::string, TOOL_STATE*> m_toolNameIndex;

    /// Index of the registered tools to easily lookup by their type.
    boost::unordered_map<const char*, TOOL_BASE*> m_toolTypes;
370 371

    /// Index of the registered tools current states, associated by tools' ID numbers.
372
    boost::unordered_map<TOOL_ID, TOOL_STATE*> m_toolIdIndex;
373 374

    /// Stack of the active tools
375
    std::deque<TOOL_ID> m_activeTools;
Maciej Suminski's avatar
Maciej Suminski committed
376

377 378 379
    /// Instance of ACTION_MANAGER that handles TOOL_ACTIONs
    ACTION_MANAGER* m_actionMgr;

Maciej Suminski's avatar
Maciej Suminski committed
380
    EDA_ITEM* m_model;
381 382
    KIGFX::VIEW* m_view;
    KIGFX::VIEW_CONTROLS* m_viewControls;
Maciej Suminski's avatar
Maciej Suminski committed
383
    wxWindow* m_editFrame;
384 385

    /// Flag saying if the currently processed event should be passed to other tools.
386
    bool m_passEvent;
Maciej Suminski's avatar
Maciej Suminski committed
387

388
    /// Pointer to the tool on the top of the active tools stack.
389
    TOOL_STATE* m_currentTool;
390 391
};

Maciej Suminski's avatar
Maciej Suminski committed
392
#endif