summaryrefslogtreecommitdiff
path: root/include/tool
diff options
context:
space:
mode:
Diffstat (limited to 'include/tool')
-rw-r--r--include/tool/action_manager.h138
-rw-r--r--include/tool/context_menu.h230
-rw-r--r--include/tool/coroutine.h268
-rw-r--r--include/tool/delegate.h100
-rw-r--r--include/tool/examples/Makefile9
-rw-r--r--include/tool/examples/coroutine_example.cpp49
-rw-r--r--include/tool/examples/delegate_example.cpp34
-rw-r--r--include/tool/tool_action.h223
-rw-r--r--include/tool/tool_base.h226
-rw-r--r--include/tool/tool_dispatcher.h135
-rw-r--r--include/tool/tool_event.h585
-rw-r--r--include/tool/tool_interactive.h121
-rw-r--r--include/tool/tool_manager.h455
-rw-r--r--include/tool/tool_settings.h80
14 files changed, 2653 insertions, 0 deletions
diff --git a/include/tool/action_manager.h b/include/tool/action_manager.h
new file mode 100644
index 0000000..34809e0
--- /dev/null
+++ b/include/tool/action_manager.h
@@ -0,0 +1,138 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013 CERN
+ * @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 ACTION_MANAGER_H_
+#define ACTION_MANAGER_H_
+
+#include <list>
+#include <map>
+#include <string>
+
+class TOOL_BASE;
+class TOOL_MANAGER;
+class TOOL_ACTION;
+
+/**
+ * Class ACTION_MANAGER
+ *
+ * Takes care of TOOL_ACTION objects. Registers them and allows to run them using associated
+ * hot keys, names or ids.
+ */
+class ACTION_MANAGER
+{
+public:
+ /**
+ * Constructor.
+ * @param aToolManager is a tool manager instance that is used to pass events to tools.
+ */
+ ACTION_MANAGER( TOOL_MANAGER* aToolManager );
+
+ /**
+ * Destructor.
+ * Unregisters every registered action.
+ */
+ ~ACTION_MANAGER();
+
+ /**
+ * Function RegisterAction()
+ * Adds a tool action to the manager and sets it up. After that is is possible to invoke
+ * the action using hotkeys or sending a command event with its name.
+ * @param aAction: action to be added. Ownership is not transferred.
+ */
+ void RegisterAction( TOOL_ACTION* aAction );
+
+ /**
+ * Function UnregisterAction()
+ * Removes a tool action from the manager and makes it unavailable for further usage.
+ * @param aAction: action to be removed.
+ */
+ void UnregisterAction( TOOL_ACTION* aAction );
+
+ /**
+ * Generates an unique ID from for an action with given name.
+ */
+ static int MakeActionId( const std::string& aActionName );
+
+ /**
+ * Function FindAction()
+ * Finds an action with a given name (if there is one available).
+ * @param aActionName is the searched action.
+ * @return Pointer to a TOOL_ACTION object or NULL if there is no such action.
+ */
+ TOOL_ACTION* FindAction( const std::string& aActionName ) const;
+
+ /**
+ * Function RunHotKey()
+ * Runs an action associated with a hotkey (if there is one available).
+ * @param aHotKey is the hotkey to be handled.
+ * @return True if there was an action associated with the hotkey, false otherwise.
+ */
+ bool RunHotKey( int aHotKey ) const;
+
+ /**
+ * Function GetHotKey()
+ * Returns the hot key associated with a given action or 0 if there is none.
+ * @param aAction is the queried action.
+ */
+ int GetHotKey( const TOOL_ACTION& aAction ) const;
+
+ /**
+ * Function UpdateHotKeys()
+ * Updates TOOL_ACTIONs hot key assignment according to the current frame's Hot Key Editor settings.
+ */
+ void UpdateHotKeys();
+
+ /**
+ * Function GetActionList()
+ * 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()
+ {
+ static std::list<TOOL_ACTION*> actionList;
+
+ return actionList;
+ }
+
+private:
+ ///> Resolves a reference to legacy hot key settings to a particular hot key.
+ ///> @param aAction is the action to be resolved.
+ int processHotKey( TOOL_ACTION* aAction );
+
+ ///> Tool manager needed to run actions
+ TOOL_MANAGER* m_toolMgr;
+
+ ///> Map for indexing actions by their names
+ std::map<std::string, TOOL_ACTION*> m_actionNameIndex;
+
+ ///> Map for indexing actions by their hotkeys
+ typedef std::map<int, std::list<TOOL_ACTION*> > HOTKEY_LIST;
+ HOTKEY_LIST m_actionHotKeys;
+
+ ///> Quick action<->hot key lookup
+ std::map<int, int> m_hotkeys;
+};
+
+#endif /* ACTION_MANAGER_H_ */
diff --git a/include/tool/context_menu.h b/include/tool/context_menu.h
new file mode 100644
index 0000000..819cb5e
--- /dev/null
+++ b/include/tool/context_menu.h
@@ -0,0 +1,230 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013-2015 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 __CONTEXT_MENU_H
+#define __CONTEXT_MENU_H
+
+#include <map>
+#include <list>
+#include <boost/function.hpp>
+
+#include <wx/menu.h>
+#include <tool/tool_action.h>
+
+class TOOL_INTERACTIVE;
+
+/**
+ * Class CONTEXT_MENU
+ *
+ * Defines the structure of a context (usually right-click) popup menu
+ * for a given tool.
+ */
+class CONTEXT_MENU : public wxMenu
+{
+public:
+ ///> Default constructor
+ CONTEXT_MENU();
+
+ ///> Copy constructor
+ CONTEXT_MENU( const CONTEXT_MENU& aMenu );
+
+ virtual ~CONTEXT_MENU();
+
+ CONTEXT_MENU& operator=( const CONTEXT_MENU& aMenu );
+
+ /**
+ * Function SetTitle()
+ * Sets title for the context menu. The title is shown as a text label shown on the top of
+ * the menu.
+ * @param aTitle is the new title.
+ */
+ void SetTitle( const wxString& aTitle );
+
+ /**
+ * Function SetIcon()
+ * Assigns an icon for the entry.
+ * @param aIcon is the icon to be assigned. NULL is used to remove icon.
+ */
+ inline void SetIcon( const BITMAP_OPAQUE* aIcon )
+ {
+ m_icon = aIcon;
+ }
+
+ /**
+ * Function Add()
+ * Adds an entry to the menu. After highlighting/selecting the entry, a TOOL_EVENT command is
+ * sent that contains ID of the entry.
+ * @param aLabel is the text label show in the menu.
+ * @param aId is the ID that is sent in the TOOL_EVENT. It should be unique for every entry.
+ * @param aIcon is an optional icon.
+ */
+ wxMenuItem* Add( const wxString& aLabel, int aId, const BITMAP_OPAQUE* aIcon = NULL );
+
+ /**
+ * Function Add()
+ * Adds an entry to the menu, basing on the TOOL_ACTION object. After selecting the entry,
+ * a TOOL_EVENT command containing name of the action is sent.
+ * @param aAction is the action to be added to menu entry.
+ */
+ wxMenuItem* Add( const TOOL_ACTION& aAction );
+
+ /**
+ * Function Add()
+ * Adds a context menu as a submenu. The difference between this function and wxMenu::AppendSubMenu()
+ * is the capability to handle icons.
+ * @param aMenu is the submenu to be added.
+ * @param aLabel is the caption displayed for the menu entry.
+ * @param aExpand allows to add all entries from the menu as individual entries rather than
+ * add everything as a submenu.
+ */
+ std::list<wxMenuItem*> Add( CONTEXT_MENU* aMenu, const wxString& aLabel, bool aExpand = false );
+
+ /**
+ * Function Clear()
+ * Removes all the entries from the menu (as well as its title). It leaves the menu in the
+ * initial state.
+ */
+ void Clear();
+
+ /**
+ * Function GetSelected()
+ * Returns the position of selected item. If the returned value is negative, that means that
+ * menu was dismissed.
+ * @return The position of selected item in the context menu.
+ */
+ inline int GetSelected() const
+ {
+ return m_selected;
+ }
+
+ /**
+ * Function UpdateAll()
+ * Runs update handlers for the menu and its submenus.
+ */
+ void UpdateAll();
+
+ // Helper typedefs
+ typedef boost::function<OPT_TOOL_EVENT(const wxMenuEvent&)> MENU_HANDLER;
+ typedef boost::function<void()> UPDATE_HANDLER;
+
+ /**
+ * Function SetMenuHandler()
+ * Sets the menu event handler to another function.
+ */
+ inline void SetMenuHandler( MENU_HANDLER aMenuHandler )
+ {
+ m_menu_handler = aMenuHandler;
+ }
+
+ /**
+ * Function SetUpdateHandler()
+ * Sets the update handler to a different function.
+ */
+ inline void SetUpdateHandler( UPDATE_HANDLER aUpdateHandler )
+ {
+ m_update_handler = aUpdateHandler;
+ }
+
+ /**
+ * Function SetTool()
+ * Sets a tool that is the creator of the menu.
+ * @param aTool is the tool that created the menu.
+ */
+ void SetTool( TOOL_INTERACTIVE* aTool );
+
+protected:
+ ///> Returns an instance of TOOL_MANAGER class.
+ TOOL_MANAGER* getToolManager();
+
+ ///> Returns the corresponding wxMenuItem identifier for a TOOL_ACTION object.
+ static inline int getMenuId( const TOOL_ACTION& aAction )
+ {
+ return aAction.GetId() + ACTION_ID;
+ }
+
+private:
+ // Empty stubs used by the default constructor
+ static OPT_TOOL_EVENT menuHandlerStub(const wxMenuEvent& );
+ static void updateHandlerStub();
+
+ /**
+ * Function appendCopy
+ * Appends a copy of wxMenuItem.
+ */
+ wxMenuItem* appendCopy( const wxMenuItem* aSource );
+
+ ///> Common part of copy constructor and assignment operator.
+ void copyFrom( const CONTEXT_MENU& aMenu );
+
+ ///> Initializes handlers for events.
+ void setupEvents();
+
+ ///> The default menu event handler.
+ void onMenuEvent( wxMenuEvent& aEvent );
+
+ ///> Updates hot key settings for TOOL_ACTIONs in this menu.
+ void updateHotKeys();
+
+ ///> Traverses the submenus tree looking for a submenu capable of handling a particular menu
+ ///> event. In case it is handled, it is returned the aToolEvent parameter.
+ void runEventHandlers( const wxMenuEvent& aMenuEvent, OPT_TOOL_EVENT& aToolEvent );
+
+ ///> Runs a function on the menu and all its submenus.
+ void runOnSubmenus( boost::function<void(CONTEXT_MENU*)> aFunction );
+
+ ///> Flag indicating that the menu title was set up.
+ bool m_titleSet;
+
+ ///> Stores the id number of selected item.
+ int m_selected;
+
+ ///> Creator of the menu
+ TOOL_INTERACTIVE* m_tool;
+
+ ///> Menu items with ID higher than that are considered TOOL_ACTIONs
+ static const int ACTION_ID = 30000;
+
+ ///> Associates tool actions with menu item IDs. Non-owning.
+ std::map<int, const TOOL_ACTION*> m_toolActions;
+
+ ///> List of submenus.
+ std::list<CONTEXT_MENU*> m_submenus;
+
+ ///> Parent CONTEXT_MENU.
+ CONTEXT_MENU* m_parent;
+
+ ///> Optional icon
+ const BITMAP_OPAQUE* m_icon;
+
+ ///> Optional callback to translate wxMenuEvents to TOOL_EVENTs.
+ MENU_HANDLER m_menu_handler;
+
+ ///> Optional callback to update the menu state before it is displayed.
+ UPDATE_HANDLER m_update_handler;
+
+ friend class TOOL_INTERACTIVE;
+};
+
+#endif
diff --git a/include/tool/coroutine.h b/include/tool/coroutine.h
new file mode 100644
index 0000000..c7eaf5f
--- /dev/null
+++ b/include/tool/coroutine.h
@@ -0,0 +1,268 @@
+/*
+ * 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>
+ *
+ * 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 __COROUTINE_H
+#define __COROUTINE_H
+
+#include <cstdlib>
+
+#include <boost/context/fcontext.hpp>
+#include <boost/version.hpp>
+
+#include "delegate.h"
+
+/**
+ * Class COROUNTINE.
+ * Implements a coroutine. Wikipedia has a good explanation:
+ *
+ * "Coroutines are computer program components that generalize subroutines to
+ * allow multiple entry points for suspending and resuming execution at certain locations.
+ * Coroutines are well-suited for implementing more familiar program components such as cooperative
+ * tasks, exceptions, event loop, iterators, infinite lists and pipes."
+ *
+ * In other words, a coroutine can be considered a lightweight thread - which can be
+ * preempted only when it deliberately yields the control to the caller. This way,
+ * we avoid concurrency problems such as locking / race conditions.
+ *
+ * Uses boost::context library to do the actual context switching.
+ *
+ * This particular version takes a DELEGATE as an entry point, so it can invoke
+ * methods within a given object as separate coroutines.
+ *
+ * See coroutine_example.cpp for sample code.
+ */
+
+template <class ReturnType, class ArgType>
+class COROUTINE
+{
+public:
+ COROUTINE() :
+ m_saved( NULL ), m_self( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize ),
+ m_running( false )
+ {
+ }
+
+ /**
+ * Constructor
+ * Creates a coroutine from a member method of an object
+ */
+ template <class T>
+ COROUTINE( T* object, ReturnType(T::* ptr)( ArgType ) ) :
+ m_func( object, ptr ), m_self( NULL ), m_saved( NULL ), m_stack( NULL ),
+ m_stackSize( c_defaultStackSize ), m_running( false )
+ {
+ }
+
+ /**
+ * Constructor
+ * Creates a coroutine from a delegate object
+ */
+ COROUTINE( DELEGATE<ReturnType, ArgType> aEntry ) :
+ m_func( aEntry ), m_saved( NULL ), m_self( NULL ), m_stack( NULL ),
+ m_stackSize( c_defaultStackSize ), m_running( false )
+ {
+ // Avoid not initialized members, and make static analysers quiet
+ m_args = 0;
+ m_retVal = 0;
+ }
+
+ ~COROUTINE()
+ {
+ if( m_saved )
+ delete m_saved;
+
+#if BOOST_VERSION >= 105600
+ if( m_self )
+ delete m_self;
+#endif
+
+ if( m_stack )
+ free( m_stack );
+ }
+
+ /**
+ * Function Yield()
+ *
+ * Stops execution of the coroutine and returns control to the caller.
+ * After a yield, Call() or Resume() methods invoked by the caller will
+ * immediately return true, indicating that we are not done yet, just asleep.
+ */
+ void Yield()
+ {
+ jump( m_self, m_saved, 0 );
+ }
+
+ /**
+ * Function Yield()
+ *
+ * Yield with a value - passes a value of given type to the caller.
+ * Useful for implementing generator objects.
+ */
+ void Yield( ReturnType& aRetVal )
+ {
+ m_retVal = aRetVal;
+ jump( m_self, m_saved, 0 );
+ }
+
+ /**
+ * Function SetEntry()
+ *
+ * Defines the entry point for the coroutine, if not set in the constructor.
+ */
+ void SetEntry( DELEGATE<ReturnType, ArgType> aEntry )
+ {
+ m_func = aEntry;
+ }
+
+ /* Function Call()
+ *
+ * Starts execution of a coroutine, passing args as its arguments.
+ * @return true, if the coroutine has yielded and false if it has finished its
+ * execution (returned).
+ */
+ bool Call( ArgType aArgs )
+ {
+ // fixme: Clean up stack stuff. Add a guard
+ m_stack = malloc( c_defaultStackSize );
+
+ // align to 16 bytes
+ void* sp = (void*) ( ( ( (ptrdiff_t) m_stack ) + m_stackSize - 0xf ) & ( ~0x0f ) );
+
+ // correct the stack size
+ m_stackSize -= ( (size_t) m_stack + m_stackSize - (size_t) sp );
+
+ assert( m_self == NULL );
+ assert( m_saved == NULL );
+
+ m_args = &aArgs;
+#if BOOST_VERSION >= 105600
+ m_self = new boost::context::fcontext_t();
+ *m_self = boost::context::make_fcontext( sp, m_stackSize, callerStub );
+#else
+ m_self = boost::context::make_fcontext( sp, m_stackSize, callerStub );
+#endif
+ m_saved = new boost::context::fcontext_t();
+
+ m_running = true;
+ // off we go!
+ jump( m_saved, m_self, reinterpret_cast<intptr_t>( this ) );
+ return m_running;
+ }
+
+ /**
+ * Function Resume()
+ *
+ * Resumes execution of a previously yielded coroutine.
+ * @return true, if the coroutine has yielded again and false if it has finished its
+ * execution (returned).
+ */
+ bool Resume()
+ {
+ jump( m_saved, m_self, 0 );
+
+ return m_running;
+ }
+
+ /**
+ * Function ReturnValue()
+ *
+ * Returns the yielded value (the argument Yield() was called with)
+ */
+ const ReturnType& ReturnValue() const
+ {
+ return m_retVal;
+ }
+
+ /**
+ * Function Running()
+ *
+ * @return true, if the coroutine is active
+ */
+ bool Running() const
+ {
+ return m_running;
+ }
+
+private:
+ static const int c_defaultStackSize = 2000000; // fixme: make configurable
+
+ /* real entry point of the coroutine */
+ static void callerStub( intptr_t aData )
+ {
+ // get pointer to self
+ COROUTINE<ReturnType, ArgType>* cor = reinterpret_cast<COROUTINE<ReturnType, ArgType>*>( aData );
+
+ // call the coroutine method
+ cor->m_retVal = cor->m_func( *cor->m_args );
+ cor->m_running = false;
+
+ // go back to wherever we came from.
+ jump( cor->m_self, cor->m_saved, 0 ); // reinterpret_cast<intptr_t>( this ));
+ }
+
+ ///> Wrapper for jump_fcontext to assure compatibility between different boost versions
+ static inline intptr_t jump(boost::context::fcontext_t* aOld, boost::context::fcontext_t* aNew,
+ intptr_t aP, bool aPreserveFPU = true )
+ {
+#if BOOST_VERSION >= 105600
+ return boost::context::jump_fcontext( aOld, *aNew, aP, aPreserveFPU );
+#else
+ return boost::context::jump_fcontext( aOld, aNew, aP, aPreserveFPU );
+#endif
+ }
+
+ template <typename T>
+ struct strip_ref
+ {
+ typedef T result;
+ };
+
+ template <typename T>
+ struct strip_ref<T&>
+ {
+ typedef T result;
+ };
+
+ DELEGATE<ReturnType, ArgType> m_func;
+
+ ///< pointer to coroutine entry arguments. Stripped of references
+ ///< to avoid compiler errors.
+ typename strip_ref<ArgType>::result* m_args;
+ ReturnType m_retVal;
+
+ ///< saved caller context
+ boost::context::fcontext_t* m_saved;
+
+ ///< saved coroutine context
+ boost::context::fcontext_t* m_self;
+
+ ///< coroutine stack
+ void* m_stack;
+
+ size_t m_stackSize;
+
+ bool m_running;
+};
+
+#endif
diff --git a/include/tool/delegate.h b/include/tool/delegate.h
new file mode 100644
index 0000000..a350dec
--- /dev/null
+++ b/include/tool/delegate.h
@@ -0,0 +1,100 @@
+/*
+ * 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>
+ *
+ * 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 __DELEGATE_H
+#define __DELEGATE_H
+
+
+/**
+ * class DELEGATE
+ * A trivial delegate (pointer to member method of an object) pattern implementation.
+ * Check delegate_example.cpp for a coding sample.
+ */
+
+template <class ReturnType, class Arg>
+class DELEGATE
+{
+public:
+ typedef ReturnType (DELEGATE<ReturnType, Arg>::* MemberPointer)( Arg );
+ typedef ReturnType _ReturnType;
+ typedef Arg _ArgType;
+
+ DELEGATE()
+ {
+ }
+
+ template <class T>
+ DELEGATE( T* aObject, ReturnType(T::* aPtr)( Arg ) )
+ {
+ m_ptr = reinterpret_cast<MemberPointer>( aPtr );
+ m_object = reinterpret_cast<void*>( aObject );
+ };
+
+
+ ReturnType operator()( Arg aA ) const
+ {
+ DELEGATE<ReturnType, Arg>* casted = reinterpret_cast<DELEGATE<ReturnType, Arg>*>( m_object );
+ return (casted->*m_ptr)( aA );
+ }
+
+private:
+ MemberPointer m_ptr;
+ void* m_object;
+};
+
+/**
+ * Class DELEGATE0
+ * Same as DELEGATE, but with no arguments.
+ */
+template <class ReturnType>
+class DELEGATE0
+{
+public:
+ typedef ReturnType ( DELEGATE0<ReturnType>::* MemberPointer )();
+ typedef ReturnType _ReturnType;
+
+ DELEGATE0()
+ {
+ }
+
+ template <class T>
+ DELEGATE0( T* aObject, ReturnType(T::* aPtr)() )
+ {
+ m_ptr = reinterpret_cast<MemberPointer>( aPtr );
+ m_object = reinterpret_cast<void*>( aObject );
+ };
+
+
+ ReturnType operator()() const
+ {
+ DELEGATE0<ReturnType>* casted = reinterpret_cast<DELEGATE0<ReturnType>*>( m_object );
+ return ( casted->*m_ptr )();
+ }
+
+private:
+ MemberPointer m_ptr;
+ void* m_object;
+};
+
+#endif
diff --git a/include/tool/examples/Makefile b/include/tool/examples/Makefile
new file mode 100644
index 0000000..a605263
--- /dev/null
+++ b/include/tool/examples/Makefile
@@ -0,0 +1,9 @@
+CXXFLAGS = -I../.. -I../../boost
+
+all: delegate_example coroutine_example
+
+delegate_example: delegate_example.cpp
+ g++ -o $@ $^ $(CXXFLAGS)
+
+coroutine_example: coroutine_example.cpp
+ g++ -o $@ $^ $(CXXFLAGS) -lboost_context \ No newline at end of file
diff --git a/include/tool/examples/coroutine_example.cpp b/include/tool/examples/coroutine_example.cpp
new file mode 100644
index 0000000..c36de8b
--- /dev/null
+++ b/include/tool/examples/coroutine_example.cpp
@@ -0,0 +1,49 @@
+#include <cstdio>
+#include <string>
+
+#include <tool/coroutine.h>
+
+typedef COROUTINE<int, int> MyCoroutine;
+
+class MyClass
+{
+public:
+ int CountTo( int n )
+ {
+ printf( "%s: Coroutine says hi. I will count from 1 to %d and yield each value.\n",
+ __FUNCTION__,
+ n );
+
+ for( int i = 1; i <= n; i++ )
+ {
+ printf( "%s: Yielding %d\n", __FUNCTION__, i );
+ cofunc.Yield( i );
+ }
+ }
+
+ void Run()
+ {
+ cofunc = MyCoroutine( this, &MyClass::CountTo );
+ printf( "%s: Calling coroutine that will count from 1 to 5.\n", __FUNCTION__ );
+ cofunc.Call( 5 );
+
+ while( cofunc.Running() )
+ {
+ printf( "%s: Got value: %d\n", __FUNCTION__, cofunc.ReturnValue() );
+ cofunc.Resume();
+ }
+
+ printf( "%s: Done!\n", __FUNCTION__ );
+ }
+
+ MyCoroutine cofunc;
+};
+
+
+main() {
+ MyClass obj;
+
+ obj.Run();
+
+ return 0;
+}
diff --git a/include/tool/examples/delegate_example.cpp b/include/tool/examples/delegate_example.cpp
new file mode 100644
index 0000000..3d3c782
--- /dev/null
+++ b/include/tool/examples/delegate_example.cpp
@@ -0,0 +1,34 @@
+#include <cstdio>
+#include <string>
+
+#include <tool/delegate.h>
+
+class MyClass
+{
+public:
+ int MyMethod( const string& arg )
+ {
+ printf( "MyClass(this = %p)::MyMethod() called with string '%s', length %d\n", this,
+ arg.c_str(), arg.length() );
+ return arg.length();
+ }
+};
+
+typedef DELEGATE<int, const string&> MyDelegate;
+
+main()
+{
+ MyClass t1;
+ MyClass t2;
+
+ MyDelegate ptr1( &t1, &MyClass::MyMethod );
+ MyDelegate ptr2( &t2, &MyClass::MyMethod );
+
+ int retval1, retval2;
+
+ retval1 = ptr1( "apples" );
+ retval2 = ptr2( "cherries" );
+
+ printf( "Object 1 returned %d, object 2 returned %d\n", retval1, retval2 );
+ return 0;
+}
diff --git a/include/tool/tool_action.h b/include/tool/tool_action.h
new file mode 100644
index 0000000..727397a
--- /dev/null
+++ b/include/tool/tool_action.h
@@ -0,0 +1,223 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013-2015 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_ACTION_H
+#define __TOOL_ACTION_H
+
+#include <string>
+#include <cassert>
+
+#include <tool/tool_event.h>
+
+struct BITMAP_OPAQUE;
+
+/**
+ * Class TOOL_ACTION
+ *
+ * Represents a single user action. For instance:
+ * - changing layer to top by pressing PgUp
+ * - running the DRC from the menu
+ * and so on, and so forth....
+ * Action class groups all necessary properties of an action, including explanation,
+ * icons, hotkeys, menu items, etc.
+ */
+class TOOL_ACTION
+{
+public:
+ TOOL_ACTION( const std::string& aName, TOOL_ACTION_SCOPE aScope = AS_CONTEXT,
+ int aDefaultHotKey = 0, const wxString aMenuItem = wxEmptyString,
+ const wxString& aMenuDesc = wxEmptyString, const BITMAP_OPAQUE* aIcon = NULL,
+ TOOL_ACTION_FLAGS aFlags = AF_NONE, void* aParam = NULL );
+
+ ~TOOL_ACTION();
+
+ bool operator==( const TOOL_ACTION& aRhs ) const
+ {
+ return m_id == aRhs.m_id;
+ }
+
+ bool operator!=( const TOOL_ACTION& aRhs ) const
+ {
+ return m_id != aRhs.m_id;
+ }
+
+ /**
+ * Function GetName()
+ * Returns name of the action. It is the same one that is contained in TOOL_EVENT that is
+ * sent by activating the TOOL_ACTION.
+ *
+ * @return Name of the action.
+ */
+ const std::string& GetName() const
+ {
+ return m_name;
+ }
+
+ /**
+ * Function GetId()
+ * Returns the unique id of the TOOL_ACTION object. It is valid only after registering the
+ * TOOL_ACTION by ACTION_MANAGER.
+ *
+ * @return The unique identification number. If the number is negative, then it is not valid.
+ */
+ int GetId() const
+ {
+ return m_id;
+ }
+
+ /**
+ * Function HasHotKey()
+ * Checks if the action has a hot key assigned.
+ *
+ * @return True if there is a hot key assigned, false otherwise.
+ */
+
+ /**
+ * Function MakeEvent()
+ * Returns the event associated with the action (i.e. the event that will be sent after
+ * activating the action).
+ *
+ * @return The event associated with the action.
+ */
+ TOOL_EVENT MakeEvent() const
+ {
+ if( IsActivation() )
+ return TOOL_EVENT( TC_COMMAND, TA_ACTIVATE, m_name, m_scope, m_param );
+ else if( IsNotification() )
+ return TOOL_EVENT( TC_MESSAGE, TA_NONE, m_name, m_scope, m_param );
+ else
+ return TOOL_EVENT( TC_COMMAND, TA_ACTION, m_name, m_scope, m_param );
+ }
+
+ const wxString& GetMenuItem() const
+ {
+ return m_menuItem;
+ }
+
+ void SetMenuItem( const wxString& aItem )
+ {
+ m_menuItem = aItem;
+ }
+
+ const wxString& GetDescription() const
+ {
+ return m_menuDescription;
+ }
+
+ void SetDescription( const wxString& aDescription )
+ {
+ m_menuDescription = aDescription;
+ }
+
+ TOOL_ACTION_SCOPE GetScope() const
+ {
+ return m_scope;
+ }
+
+ /**
+ * Returns name of the tool associated with the action. It is basically the action name
+ * stripped of the last part (e.g. for "pcbnew.InteractiveDrawing.drawCircle" it is
+ * "pcbnew.InteractiveDrawing").
+ */
+ std::string GetToolName() const;
+
+ /**
+ * Returns true if the action is intended to activate a tool.
+ */
+ bool IsActivation() const
+ {
+ return m_flags & AF_ACTIVATE;
+ }
+
+ /**
+ * Returns true if the action is a notification.
+ */
+ bool IsNotification() const
+ {
+ return m_flags & AF_NOTIFY;
+ }
+
+ /**
+ * Returns an icon associated with the action. It is used in context menu.
+ */
+ const BITMAP_OPAQUE* GetIcon() const
+ {
+ return m_icon;
+ }
+
+ /**
+ * Creates a hot key code that refers to a legacy hot key setting, instead of a particular key.
+ * @param aHotKey is an ID of hot key to be referred (see @hotkeys.h).
+ */
+ inline static int LegacyHotKey( int aHotKey )
+ {
+ assert( ( aHotKey & LEGACY_HK ) == 0 );
+
+ return aHotKey | LEGACY_HK;
+ }
+
+private:
+ friend class ACTION_MANAGER;
+
+ /// Returns the hot key assigned in the object definition. It may refer to a legacy hot key setting
+ /// (if LEGACY_HK flag is set).
+ int getDefaultHotKey()
+ {
+ return m_defaultHotKey;
+ }
+
+ /// Name of the action (convention is: app.[tool.]action.name)
+ std::string m_name;
+
+ /// Scope of the action
+ TOOL_ACTION_SCOPE m_scope;
+
+ /// Default hot key that activates the action.
+ const int m_defaultHotKey;
+
+ /// Menu entry text
+ wxString m_menuItem;
+
+ /// Pop-up help
+ wxString m_menuDescription;
+
+ // Icon for menu entry
+ const BITMAP_OPAQUE* m_icon;
+
+ /// Unique ID for fast matching. Assigned by ACTION_MANAGER.
+ int m_id;
+
+ /// Action flags
+ TOOL_ACTION_FLAGS m_flags;
+
+ /// Generic parameter
+ void* m_param;
+
+ /// Flag to determine the hot key settings is not a particular key, but a reference to legacy
+ /// hot key setting.
+ static const int LEGACY_HK = 0x800000;
+};
+
+#endif
diff --git a/include/tool/tool_base.h b/include/tool/tool_base.h
new file mode 100644
index 0000000..584a979
--- /dev/null
+++ b/include/tool/tool_base.h
@@ -0,0 +1,226 @@
+/*
+ * 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>
+ *
+ * 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_BASE_H
+#define __TOOL_BASE_H
+
+#include <cassert>
+#include <base_struct.h> // for KICAD_T
+
+#include <tool/tool_event.h>
+#include <tool/tool_settings.h>
+
+#include <tool/delegate.h>
+
+class EDA_ITEM;
+class TOOL_MANAGER;
+
+namespace KIGFX
+{
+class VIEW;
+class VIEW_CONTROLS;
+};
+
+enum TOOL_TYPE
+{
+ ///> Tool that interacts with the user
+ INTERACTIVE = 0x01,
+
+ ///> Tool that runs in the background without any user intervention
+ BATCH = 0x02
+};
+
+/// Unique identifier for tools
+typedef int TOOL_ID;
+typedef DELEGATE<int, const TOOL_EVENT&> TOOL_STATE_FUNC;
+
+/**
+ * Class TOOL_BASE
+ *
+ * Base abstract interface for all kinds of tools.
+ */
+
+class TOOL_BASE
+{
+public:
+ TOOL_BASE( TOOL_TYPE aType, TOOL_ID aId, const std::string& aName = std::string( "" ) ) :
+ m_type( aType ),
+ m_toolId( aId ),
+ m_toolName( aName ),
+ m_toolMgr( NULL ) {};
+
+ virtual ~TOOL_BASE() {};
+
+ ///> Determines the reason of reset for a tool
+ enum RESET_REASON
+ {
+ RUN, ///< Tool is invoked after being inactive
+ MODEL_RELOAD, ///< Model changes
+ GAL_SWITCH ///< Rendering engine changes
+ };
+
+ /**
+ * Function Init()
+ * Init() is called once upon a registration of the tool.
+ *
+ * @return True if the initialization went fine, false - otherwise.
+ */
+ virtual bool Init()
+ {
+ return true;
+ }
+
+ /**
+ * Function Reset()
+ * Brings the tool to a known, initial state. If the tool claimed anything from
+ * the model or the view, it must release it when its reset.
+ * @param aReason contains information about the reason of tool reset.
+ */
+ virtual void Reset( RESET_REASON aReason ) = 0;
+
+ /**
+ * Function GetType()
+ * Returns the type of the tool.
+ * @return The type of the tool.
+ */
+ TOOL_TYPE GetType() const
+ {
+ return m_type;
+ }
+
+ /**
+ * Function GetId()
+ * Returns the unique identifier of the tool. The identifier is set by an instance of
+ * TOOL_MANAGER.
+ * @return Identifier of the tool.
+ */
+ TOOL_ID GetId() const
+ {
+ return m_toolId;
+ }
+
+ /**
+ * Function GetName()
+ * Returns the name of the tool. Tool names are expected to obey the format:
+ * application.ToolName (eg. pcbnew.InteractiveSelection).
+ * @return The name of the tool.
+ */
+ const std::string& GetName() const
+ {
+ return m_toolName;
+ }
+
+ /**
+ * Function GetManager()
+ * Returns the instance of TOOL_MANAGER that takes care of the tool.
+ * @return Instance of the TOOL_MANAGER. If there is no TOOL_MANAGER associated, it returns
+ * NULL.
+ */
+ TOOL_MANAGER* GetManager() const
+ {
+ return m_toolMgr;
+ }
+
+ /**
+ * Function SetTransitions()
+ * This method is meant to be overridden in order to specify handlers for events. It is called
+ * every time tool is reset or finished.
+ */
+ virtual void SetTransitions() {};
+
+ TOOL_SETTINGS& GetSettings();
+
+protected:
+ friend class TOOL_MANAGER;
+ friend class TOOL_SETTINGS;
+
+ /**
+ * Function attachManager()
+ *
+ * Sets the TOOL_MANAGER the tool will belong to.
+ * Called by TOOL_MANAGER::RegisterTool()
+ */
+ void attachManager( TOOL_MANAGER* aManager );
+
+ /**
+ * Function getView()
+ *
+ * Returns the instance of VIEW object used in the application. It allows tools to draw.
+ * @return The instance of VIEW.
+ */
+ KIGFX::VIEW* getView() const;
+
+ /**
+ * Function getViewControls()
+ *
+ * Returns the instance of VIEW_CONTROLS object used in the application. It allows tools to
+ * read & modify user input and its settings (eg. show cursor, enable snapping to grid, etc.)
+ * @return The instance of VIEW_CONTROLS.
+ */
+ KIGFX::VIEW_CONTROLS* getViewControls() const;
+
+ /**
+ * Function getEditFrame()
+ *
+ * Returns the application window object, casted to requested user type.
+ */
+ template <typename T>
+ T* getEditFrame() const
+ {
+ return static_cast<T*>( getEditFrameInt() );
+ }
+
+ /**
+ * Function getModel()
+ *
+ * Returns the model object if it matches the requested type.
+ */
+ template <typename T>
+ T* getModel() const
+ {
+ EDA_ITEM* m = getModelInt();
+
+ return static_cast<T*>( m );
+ }
+
+ ///> Stores the type of the tool.
+ TOOL_TYPE m_type;
+
+ ///> Unique identifier for the tool, assigned by a TOOL_MANAGER instance.
+ TOOL_ID m_toolId;
+
+ ///> Name of the tool. Names are expected to obey the format application.ToolName
+ ///> (eg. pcbnew.InteractiveSelection).
+ std::string m_toolName;
+ TOOL_MANAGER* m_toolMgr;
+ TOOL_SETTINGS m_toolSettings;
+
+private:
+ // hide the implementation to avoid spreading half of
+ // kicad and wxWidgets headers to the tools that may not need them at all!
+ EDA_ITEM* getModelInt() const;
+ wxWindow* getEditFrameInt() const;
+};
+
+#endif
diff --git a/include/tool/tool_dispatcher.h b/include/tool/tool_dispatcher.h
new file mode 100644
index 0000000..cf6e852
--- /dev/null
+++ b/include/tool/tool_dispatcher.h
@@ -0,0 +1,135 @@
+/*
+ * 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>
+ *
+ * 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_DISPATCHER_H
+#define __TOOL_DISPATCHER_H
+
+#include <vector>
+#include <wx/event.h>
+#include <tool/tool_event.h>
+
+class TOOL_MANAGER;
+class PCB_BASE_FRAME;
+
+namespace KIGFX
+{
+class VIEW;
+};
+
+/**
+ * Class TOOL_DISPATCHER
+ *
+ * - takes wx events,
+ * - fixes all wx quirks (mouse warping, panning, ordering problems, etc)
+ * - translates coordinates to world space
+ * - low-level input conditioning (drag/click threshold), updating mouse position during view auto-scroll/pan.
+ * - issues TOOL_EVENTS to the tool manager
+ */
+
+class TOOL_DISPATCHER : public wxEvtHandler
+{
+public:
+ /**
+ * Constructor
+ *
+ * @param aToolMgr: tool manager instance the events will be sent to
+ */
+ TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr );
+
+ virtual ~TOOL_DISPATCHER();
+
+ /**
+ * Function ResetState()
+ * Brings the dispatcher to its initial state.
+ */
+ virtual void ResetState();
+
+ /**
+ * Function DispatchWxEvent()
+ * Processes wxEvents (mostly UI events), translates them to TOOL_EVENTs, and makes tools
+ * handle those.
+ * @param aEvent is the wxWidgets event to be processed.
+ */
+ virtual void DispatchWxEvent( wxEvent& aEvent );
+
+ /**
+ * Function DispatchWxCommand()
+ * Processes wxCommands (mostly menu related events) and runs appropriate actions (eg. run the
+ * specified tool).
+ * @param aEvent is the wxCommandEvent to be processed.
+ */
+ virtual void DispatchWxCommand( wxCommandEvent& aEvent );
+
+private:
+ ///> Number of mouse buttons that is handled in events.
+ static const int MouseButtonCount = 3;
+
+ ///> The time threshold for a mouse button press that distinguishes between a single mouse
+ ///> click and a beginning of drag event (expressed in milliseconds).
+ static const int DragTimeThreshold = 300;
+
+ ///> The distance threshold for mouse cursor that disinguishes between a single mouse click
+ ///> and a beginning of drag event (expressed in screen pixels).
+ static const int DragDistanceThreshold = 8;
+
+ ///> Handles mouse related events (click, motion, dragging).
+ bool handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion );
+
+ ///> Saves the state of key modifiers (Alt, Ctrl and so on).
+ static int decodeModifiers( const wxKeyboardState* aState )
+ {
+ int mods = 0;
+
+ if( aState->ControlDown() )
+ mods |= MD_CTRL;
+
+ if( aState->AltDown() )
+ mods |= MD_ALT;
+
+ if( aState->ShiftDown() )
+ mods |= MD_SHIFT;
+
+ return mods;
+ }
+
+ ///> Redraws the status bar and message panel.
+ void updateUI();
+
+ ///> Stores all the informations regarding a mouse button state.
+ struct BUTTON_STATE;
+
+ ///> The last mouse cursor position (in world coordinates).
+ VECTOR2D m_lastMousePos;
+
+ ///> State of mouse buttons.
+ std::vector<BUTTON_STATE*> m_buttons;
+
+ ///> Returns the instance of VIEW, used by the application.
+ KIGFX::VIEW* getView();
+
+ ///> Instance of tool manager that cooperates with the dispatcher.
+ TOOL_MANAGER* m_toolMgr;
+};
+
+#endif
diff --git a/include/tool/tool_event.h b/include/tool/tool_event.h
new file mode 100644
index 0000000..4def191
--- /dev/null
+++ b/include/tool/tool_event.h
@@ -0,0 +1,585 @@
+/*
+ * 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>
+ *
+ * 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_EVENT_H
+#define __TOOL_EVENT_H
+
+#include <cstdio>
+#include <deque>
+
+#include <math/vector2d.h>
+#include <cassert>
+
+#include <boost/optional.hpp>
+
+class TOOL_ACTION;
+class TOOL_MANAGER;
+
+/**
+ * Internal (GUI-independent) event definitions.
+ * Enums are mostly self-explanatory.
+ */
+enum TOOL_EVENT_CATEGORY
+{
+ TC_NONE = 0x00,
+ TC_MOUSE = 0x01,
+ TC_KEYBOARD = 0x02,
+ TC_COMMAND = 0x04,
+ TC_MESSAGE = 0x08,
+ TC_VIEW = 0x10,
+ TC_ANY = 0xffffffff
+};
+
+enum TOOL_ACTIONS
+{
+ // UI input events
+ TA_NONE = 0x0000,
+ TA_MOUSE_CLICK = 0x0001,
+ TA_MOUSE_DBLCLICK = 0x0002,
+ TA_MOUSE_UP = 0x0004,
+ TA_MOUSE_DOWN = 0x0008,
+ TA_MOUSE_DRAG = 0x0010,
+ TA_MOUSE_MOTION = 0x0020,
+ TA_MOUSE_WHEEL = 0x0040,
+ TA_MOUSE = 0x007f,
+
+ TA_KEY_PRESSED = 0x0080,
+ TA_KEYBOARD = TA_KEY_PRESSED,
+
+ // View related events
+ TA_VIEW_REFRESH = 0x0100,
+ TA_VIEW_ZOOM = 0x0200,
+ TA_VIEW_PAN = 0x0400,
+ TA_VIEW_DIRTY = 0x0800,
+ TA_VIEW = 0x0f00,
+
+ TA_CHANGE_LAYER = 0x1000,
+
+ // Tool cancel event. Issued automagically when the user hits escape or selects End Tool from
+ // the context menu.
+ TA_CANCEL_TOOL = 0x2000,
+
+ // Context menu update. Issued whenever context menu is open and the user hovers the mouse
+ // over one of choices. Used in dynamic highligting in disambiguation menu
+ TA_CONTEXT_MENU_UPDATE = 0x4000,
+
+ // Context menu choice. Sent if the user picked something from the context menu or
+ // closed it without selecting anything.
+ TA_CONTEXT_MENU_CHOICE = 0x8000,
+
+ // Context menu is closed, no matter whether anything has been chosen or not.
+ TA_CONTEXT_MENU_CLOSED = 0x10000,
+
+ TA_CONTEXT_MENU = TA_CONTEXT_MENU_UPDATE | TA_CONTEXT_MENU_CHOICE | TA_CONTEXT_MENU_CLOSED,
+
+ // This event is sent *before* undo/redo command is performed.
+ TA_UNDO_REDO = 0x20000,
+
+ // Tool action (allows to control tools).
+ TA_ACTION = 0x40000,
+
+ // Tool activation event.
+ TA_ACTIVATE = 0x80000,
+
+ TA_ANY = 0xffffffff
+};
+
+enum TOOL_MOUSE_BUTTONS
+{
+ BUT_NONE = 0x0,
+ BUT_LEFT = 0x1,
+ BUT_RIGHT = 0x2,
+ BUT_MIDDLE = 0x4,
+ BUT_BUTTON_MASK = BUT_LEFT | BUT_RIGHT | BUT_MIDDLE,
+ BUT_ANY = 0xffffffff
+};
+
+enum TOOL_MODIFIERS
+{
+ MD_SHIFT = 0x1000,
+ MD_CTRL = 0x2000,
+ MD_ALT = 0x4000,
+ MD_MODIFIER_MASK = MD_SHIFT | MD_CTRL | MD_ALT,
+};
+
+/// Scope of tool actions
+enum TOOL_ACTION_SCOPE
+{
+ AS_CONTEXT = 1, ///> Action belongs to a particular tool (i.e. a part of a pop-up menu)
+ AS_ACTIVE, ///> All active tools
+ AS_GLOBAL ///> Global action (toolbar/main menu event, global shortcut)
+};
+
+/// Flags for tool actions
+enum TOOL_ACTION_FLAGS
+{
+ AF_NONE = 0,
+ AF_ACTIVATE = 1, ///> Action activates a tool
+ AF_NOTIFY = 2 ///> Action is a notification (it is by default passed to all tools)
+};
+
+/// Defines when a context menu is opened.
+enum CONTEXT_MENU_TRIGGER
+{
+ CMENU_BUTTON = 0, // On the right button
+ CMENU_NOW, // Right now (after TOOL_INTERACTIVE::SetContextMenu)
+ CMENU_OFF // Never
+};
+
+/**
+ * Class TOOL_EVENT
+ *
+ * Generic, UI-independent tool event.
+ */
+class TOOL_EVENT
+{
+public:
+ /**
+ * Function Format()
+ * Returns information about event in form of a human-readable string.
+ *
+ * @return Event information.
+ */
+ const std::string Format() const;
+
+ TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory = TC_NONE, TOOL_ACTIONS aAction = TA_NONE,
+ TOOL_ACTION_SCOPE aScope = AS_GLOBAL, void* aParameter = NULL ) :
+ m_category( aCategory ),
+ m_actions( aAction ),
+ m_scope( aScope ),
+ m_mouseButtons( 0 ),
+ m_keyCode( 0 ),
+ m_modifiers( 0 ),
+ m_param( aParameter ) {}
+
+ TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory, TOOL_ACTIONS aAction, int aExtraParam,
+ TOOL_ACTION_SCOPE aScope = AS_GLOBAL, void* aParameter = NULL ) :
+ m_category( aCategory ),
+ m_actions( aAction ),
+ m_scope( aScope ),
+ m_mouseButtons( 0 ),
+ m_keyCode( 0 ),
+ m_modifiers( 0 ),
+ m_param( aParameter )
+ {
+ if( aCategory == TC_MOUSE )
+ {
+ setMouseButtons( aExtraParam & BUT_BUTTON_MASK );
+ }
+ else if( aCategory == TC_KEYBOARD )
+ {
+ m_keyCode = aExtraParam & ~MD_MODIFIER_MASK; // Filter out modifiers
+ }
+ else if( aCategory == TC_COMMAND )
+ {
+ m_commandId = aExtraParam;
+ }
+
+ if( aCategory & ( TC_MOUSE | TC_KEYBOARD ) )
+ {
+ m_modifiers = aExtraParam & MD_MODIFIER_MASK;
+ }
+ }
+
+ TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory, TOOL_ACTIONS aAction,
+ const std::string& aExtraParam, TOOL_ACTION_SCOPE aScope = AS_GLOBAL,
+ void* aParameter = NULL ) :
+ m_category( aCategory ),
+ m_actions( aAction ),
+ m_scope( aScope ),
+ m_mouseButtons( 0 ),
+ m_keyCode( 0 ),
+ m_modifiers( 0 ),
+ m_param( aParameter )
+ {
+ if( aCategory == TC_COMMAND || aCategory == TC_MESSAGE )
+ m_commandStr = aExtraParam;
+ }
+
+ ///> Returns the category (eg. mouse/keyboard/action) of an event..
+ TOOL_EVENT_CATEGORY Category() const
+ {
+ return m_category;
+ }
+
+ ///> Returns more specific information about the type of an event.
+ TOOL_ACTIONS Action() const
+ {
+ return m_actions;
+ }
+
+ ///> Returns information about difference between current mouse cursor position and the place
+ ///> where dragging has started.
+ const VECTOR2D& Delta() const
+ {
+ assert( m_category == TC_MOUSE ); // this should be used only with mouse events
+ return m_mouseDelta;
+ }
+
+ ///> Returns mouse cursor position in world coordinates.
+ const VECTOR2D& Position() const
+ {
+ assert( m_category == TC_MOUSE ); // this should be used only with mouse events
+ return m_mousePos;
+ }
+
+ ///> Returns the point where dragging has started.
+ const VECTOR2D& DragOrigin() const
+ {
+ assert( m_category == TC_MOUSE ); // this should be used only with mouse events
+ return m_mouseDragOrigin;
+ }
+
+ ///> Returns information about mouse buttons state.
+ int Buttons() const
+ {
+ assert( m_category == TC_MOUSE ); // this should be used only with mouse events
+ return m_mouseButtons;
+ }
+
+ bool IsClick( int aButtonMask = BUT_ANY ) const
+ {
+ return ( m_actions == TA_MOUSE_CLICK )
+ && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
+ }
+
+ bool IsDblClick( int aButtonMask = BUT_ANY ) const
+ {
+ return ( m_actions == TA_MOUSE_DBLCLICK )
+ && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
+ }
+
+ bool IsDrag( int aButtonMask = BUT_ANY ) const
+ {
+ return ( m_actions == TA_MOUSE_DRAG ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
+ }
+
+ bool IsMouseUp( int aButtonMask = BUT_ANY ) const
+ {
+ return ( m_actions == TA_MOUSE_UP ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
+ }
+
+ bool IsMotion() const
+ {
+ return m_actions == TA_MOUSE_MOTION;
+ }
+
+ bool IsCancel() const
+ {
+ return m_actions == TA_CANCEL_TOOL;
+ }
+
+ bool IsActivate() const
+ {
+ return m_actions == TA_ACTIVATE;
+ }
+
+ ///> Returns information about key modifiers state (Ctrl, Alt, etc.)
+ int Modifier( int aMask = MD_MODIFIER_MASK ) const
+ {
+ return m_modifiers & aMask;
+ }
+
+ int KeyCode() const
+ {
+ return m_keyCode;
+ }
+
+ bool IsKeyPressed() const
+ {
+ return m_actions == TA_KEY_PRESSED;
+ }
+
+ /**
+ * Function Matches()
+ * Tests whether two events match in terms of category & action or command.
+ *
+ * @param aEvent is the event to test against.
+ * @return True if two events match, false otherwise.
+ */
+ bool Matches( const TOOL_EVENT& aEvent ) const
+ {
+ if( !( m_category & aEvent.m_category ) )
+ return false;
+
+ if( m_category == TC_COMMAND || m_category == TC_MESSAGE )
+ {
+ if( (bool) m_commandStr && (bool) aEvent.m_commandStr )
+ return *m_commandStr == *aEvent.m_commandStr;
+
+ if( (bool) m_commandId && (bool) aEvent.m_commandId )
+ return *m_commandId == *aEvent.m_commandId;
+ }
+
+ // BUGFIX: TA_ANY should match EVERYTHING, even TA_NONE (for TC_MESSAGE)
+ if( m_actions == TA_ANY && aEvent.m_actions == TA_NONE && aEvent.m_category == TC_MESSAGE )
+ return true;
+
+ // BUGFIX: This check must happen after the TC_COMMAND check because otherwise events of
+ // the form { TC_COMMAND, TA_NONE } will be incorrectly skipped
+ if( !( m_actions & aEvent.m_actions ) )
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Function IsAction()
+ * Tests if the event contains an action issued upon activation of the given TOOL_ACTION.
+ * @param aAction is the TOOL_ACTION to be checked against.
+ * @return True if it matches the given TOOL_ACTION.
+ */
+ bool IsAction( const TOOL_ACTION* aAction ) const;
+
+ /**
+ * Function Parameter()
+ * Returns a non-standard parameter assigned to the event. Its meaning depends on the
+ * target tool.
+ */
+ template<typename T>
+ inline T Parameter() const
+ {
+ return reinterpret_cast<T>( m_param );
+ }
+
+ /**
+ * Function SetParameter()
+ * Sets a non-standard parameter assigned to the event. Its meaning depends on the
+ * target tool.
+ * @param aParam is the new parameter.
+ */
+ template<typename T>
+ void SetParameter(T aParam)
+ {
+ m_param = (void*) aParam;
+ }
+
+ boost::optional<int> GetCommandId() const
+ {
+ return m_commandId;
+ }
+
+ boost::optional<std::string> GetCommandStr() const
+ {
+ return m_commandStr;
+ }
+
+ void SetMousePosition( const VECTOR2D& aP )
+ {
+ m_mousePos = aP;
+ }
+
+private:
+ friend class TOOL_DISPATCHER;
+
+ void setMouseDragOrigin( const VECTOR2D& aP )
+ {
+ m_mouseDragOrigin = aP;
+ }
+
+ void setMouseDelta( const VECTOR2D& aP )
+ {
+ m_mouseDelta = aP;
+ }
+
+ void setMouseButtons( int aButtons )
+ {
+ assert( ( aButtons & ~BUT_BUTTON_MASK ) == 0 );
+ m_mouseButtons = aButtons;
+ }
+
+ void setModifiers( int aMods )
+ {
+ assert( ( aMods & ~MD_MODIFIER_MASK ) == 0 );
+ m_modifiers = aMods;
+ }
+
+ TOOL_EVENT_CATEGORY m_category;
+ TOOL_ACTIONS m_actions;
+ TOOL_ACTION_SCOPE m_scope;
+
+ ///> Difference between mouse cursor position and
+ ///> the point where dragging event has started
+ VECTOR2D m_mouseDelta;
+
+ ///> Current mouse cursor position
+ VECTOR2D m_mousePos;
+
+ ///> Point where dragging has started
+ VECTOR2D m_mouseDragOrigin;
+
+ ///> State of mouse buttons
+ int m_mouseButtons;
+
+ ///> Stores code of pressed/released key
+ int m_keyCode;
+
+ ///> State of key modifierts (Ctrl/Alt/etc.)
+ int m_modifiers;
+
+ ///> Generic parameter used for passing non-standard data.
+ void* m_param;
+
+ boost::optional<int> m_commandId;
+ boost::optional<std::string> m_commandStr;
+};
+
+typedef boost::optional<TOOL_EVENT> OPT_TOOL_EVENT;
+
+/**
+ * Class TOOL_EVENT_LIST
+ *
+ * A list of TOOL_EVENTs, with overloaded || operators allowing for
+ * concatenating TOOL_EVENTs with little code.
+ */
+class TOOL_EVENT_LIST
+{
+public:
+ typedef TOOL_EVENT value_type;
+ typedef std::deque<TOOL_EVENT>::iterator iterator;
+ typedef std::deque<TOOL_EVENT>::const_iterator const_iterator;
+
+ ///> Default constructor. Creates an empty list.
+ TOOL_EVENT_LIST()
+ {}
+
+ ///> Constructor for a list containing only one TOOL_EVENT.
+ TOOL_EVENT_LIST( const TOOL_EVENT& aSingleEvent )
+ {
+ m_events.push_back( aSingleEvent );
+ }
+
+ /**
+ * Function Format()
+ * Returns information about event in form of a human-readable string.
+ *
+ * @return Event information.
+ */
+ const std::string Format() const;
+
+ boost::optional<const TOOL_EVENT&> Matches( const TOOL_EVENT& aEvent ) const
+ {
+ for( const_iterator i = m_events.begin(); i != m_events.end(); ++i )
+ if( i->Matches( aEvent ) )
+ return *i;
+
+ return boost::optional<const TOOL_EVENT&>();
+ }
+
+ /**
+ * Function Add()
+ * Adds a tool event to the list.
+ * @param aEvent is the tool event to be addded.
+ */
+ void Add( const TOOL_EVENT& aEvent )
+ {
+ m_events.push_back( aEvent );
+ }
+
+ iterator begin()
+ {
+ return m_events.begin();
+ }
+
+ iterator end()
+ {
+ return m_events.end();
+ }
+
+ const_iterator cbegin() const
+ {
+ return m_events.begin();
+ }
+
+ const_iterator cend() const
+ {
+ return m_events.end();
+ }
+
+ int size() const
+ {
+ return m_events.size();
+ }
+
+ void clear()
+ {
+ m_events.clear();
+ }
+
+ TOOL_EVENT_LIST& operator=( const TOOL_EVENT_LIST& aEventList )
+ {
+ m_events.clear();
+
+ for( std::deque<TOOL_EVENT>::const_iterator i = aEventList.m_events.begin();
+ i != aEventList.m_events.end(); ++i )
+ {
+ m_events.push_back( *i );
+ }
+
+ return *this;
+ }
+
+ TOOL_EVENT_LIST& operator=( const TOOL_EVENT& aEvent )
+ {
+ m_events.clear();
+ m_events.push_back( aEvent );
+ return *this;
+ }
+
+ TOOL_EVENT_LIST& operator||( const TOOL_EVENT& aEvent )
+ {
+ Add( aEvent );
+ return *this;
+ }
+
+ TOOL_EVENT_LIST& operator||( const TOOL_EVENT_LIST& aEvent )
+ {
+ std::copy( aEvent.m_events.begin(), aEvent.m_events.end(), std::back_inserter( m_events ) );
+ return *this;
+ }
+
+private:
+ std::deque<TOOL_EVENT> m_events;
+};
+
+inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& aEventA, const TOOL_EVENT& aEventB )
+{
+ TOOL_EVENT_LIST l;
+
+ l.Add( aEventA );
+ l.Add( aEventB );
+
+ return l;
+}
+
+inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& aEvent,
+ const TOOL_EVENT_LIST& aEventList )
+{
+ TOOL_EVENT_LIST l( aEventList );
+
+ l.Add( aEvent );
+ return l;
+}
+
+#endif
diff --git a/include/tool/tool_interactive.h b/include/tool/tool_interactive.h
new file mode 100644
index 0000000..17d2de7
--- /dev/null
+++ b/include/tool/tool_interactive.h
@@ -0,0 +1,121 @@
+/*
+ * 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>
+ *
+ * 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_INTERACTIVE_H
+#define __TOOL_INTERACTIVE_H
+
+#include <string>
+
+#include <tool/tool_event.h>
+#include <tool/tool_base.h>
+
+class CONTEXT_MENU;
+
+class TOOL_INTERACTIVE : public TOOL_BASE
+{
+public:
+ /**
+ * Constructor
+ *
+ * Creates a tool with given id & name. The name must be unique. */
+ TOOL_INTERACTIVE( TOOL_ID aId, const std::string& aName );
+
+ /**
+ * Constructor
+ *
+ * Creates a tool with given name. The name must be unique. */
+ TOOL_INTERACTIVE( const std::string& aName );
+ virtual ~TOOL_INTERACTIVE();
+
+ /**
+ * Function Activate()
+ * Runs the tool. After activation, the tool starts receiving events until it is finished.
+ */
+ void Activate();
+
+ /**
+ * Function SetContextMenu()
+ *
+ * Assigns a context menu and tells when it should be activated.
+ * @param aMenu is the menu to be assigned.
+ * @param aTrigger determines conditions upon which the context menu is activated.
+ */
+ void SetContextMenu( CONTEXT_MENU* aMenu, CONTEXT_MENU_TRIGGER aTrigger = CMENU_BUTTON );
+
+ /**
+ * Function Go()
+ *
+ * Defines which state (aStateFunc) to go when a certain event arrives (aConditions).
+ * No conditions means any event.
+ */
+ template <class T>
+ void Go( int (T::* aStateFunc)( const TOOL_EVENT& ),
+ const TOOL_EVENT_LIST& aConditions = TOOL_EVENT( TC_ANY, TA_ANY ) );
+
+ /**
+ * Function Wait()
+ *
+ * Suspends execution of the tool until an event specified in aEventList arrives.
+ * No parameters means waiting for any event.
+ */
+ OPT_TOOL_EVENT Wait( const TOOL_EVENT_LIST& aEventList = TOOL_EVENT( TC_ANY, TA_ANY ) );
+
+ /** functions below are not yet implemented - their interface may change */
+ /*template <class Parameters, class ReturnValue>
+ bool InvokeTool( const std::string& aToolName, const Parameters& parameters,
+ ReturnValue& returnValue );
+
+ template <class Parameters, class ReturnValue>
+ bool InvokeWindow( const std::string& aWindowName, const Parameters& parameters,
+ ReturnValue& returnValue );
+
+ template <class T>
+ void Yield( const T& returnValue );*/
+
+protected:
+ /* helper functions for constructing events for Wait() and Go() with less typing */
+ const TOOL_EVENT evActivate( std::string aToolName = "" );
+ const TOOL_EVENT evCommand( int aCommandId = -1 );
+ const TOOL_EVENT evCommand( std::string aCommandStr = "" );
+ const TOOL_EVENT evMotion();
+ const TOOL_EVENT evClick( int aButton = BUT_ANY );
+ const TOOL_EVENT evDrag( int aButton = BUT_ANY );
+ const TOOL_EVENT evButtonUp( int aButton = BUT_ANY );
+ const TOOL_EVENT evButtonDown(int aButton = BUT_ANY );
+
+private:
+ void goInternal( TOOL_STATE_FUNC& aState, const TOOL_EVENT_LIST& aConditions );
+};
+
+// hide TOOL_MANAGER implementation
+template <class T>
+void TOOL_INTERACTIVE::Go( int (T::* aStateFunc)( const TOOL_EVENT& ),
+ const TOOL_EVENT_LIST& aConditions )
+{
+ TOOL_STATE_FUNC sptr( static_cast<T*>( this ), aStateFunc );
+
+ goInternal( sptr, aConditions );
+}
+
+#endif
diff --git a/include/tool/tool_manager.h b/include/tool/tool_manager.h
new file mode 100644
index 0000000..9b28f23
--- /dev/null
+++ b/include/tool/tool_manager.h
@@ -0,0 +1,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
diff --git a/include/tool/tool_settings.h b/include/tool/tool_settings.h
new file mode 100644
index 0000000..64d2612
--- /dev/null
+++ b/include/tool/tool_settings.h
@@ -0,0 +1,80 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 CERN
+ * @author Tomasz Wlostowski <tomasz.wlostowski@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_SETTINGS_H
+#define __TOOL_SETTINGS_H
+
+#include <wx/confbase.h>
+
+/**
+ * Class TOOL_SETTINGS
+ *
+ * Manages persistent settings for a tool (just a simple wrapper to wxConfigBase)
+ */
+class TOOL_BASE;
+
+class TOOL_SETTINGS
+{
+ public:
+ TOOL_SETTINGS( TOOL_BASE* aTool = NULL );
+ ~TOOL_SETTINGS();
+
+ template<class T>
+ T Get( const wxString& aName, T aDefaultValue ) const
+ {
+ wxConfigBase* config = getConfigBase();
+
+ if( !config )
+ return aDefaultValue;
+
+ T tmp = aDefaultValue;
+
+ config->Read( getKeyName( aName ), &tmp );
+ return tmp;
+ }
+
+ template<class T>
+ void Set( const wxString& aName, const T &aValue )
+ {
+ wxConfigBase* config = getConfigBase();
+
+ if( !config )
+ return;
+
+ config->Write( getKeyName( aName ), aValue );
+ }
+
+ private:
+ wxString getKeyName( const wxString& aEntryName ) const;
+
+ ///> Returns pointer to currently used wxConfigBase. It might be NULL, if there is no
+ ///> TOOL_BASE assigned.
+ wxConfigBase* getConfigBase() const;
+
+ TOOL_BASE* m_tool;
+
+};
+
+#endif