diff options
Diffstat (limited to 'include/tool')
-rw-r--r-- | include/tool/action_manager.h | 138 | ||||
-rw-r--r-- | include/tool/context_menu.h | 230 | ||||
-rw-r--r-- | include/tool/coroutine.h | 268 | ||||
-rw-r--r-- | include/tool/delegate.h | 100 | ||||
-rw-r--r-- | include/tool/examples/Makefile | 9 | ||||
-rw-r--r-- | include/tool/examples/coroutine_example.cpp | 49 | ||||
-rw-r--r-- | include/tool/examples/delegate_example.cpp | 34 | ||||
-rw-r--r-- | include/tool/tool_action.h | 223 | ||||
-rw-r--r-- | include/tool/tool_base.h | 226 | ||||
-rw-r--r-- | include/tool/tool_dispatcher.h | 135 | ||||
-rw-r--r-- | include/tool/tool_event.h | 585 | ||||
-rw-r--r-- | include/tool/tool_interactive.h | 121 | ||||
-rw-r--r-- | include/tool/tool_manager.h | 455 | ||||
-rw-r--r-- | include/tool/tool_settings.h | 80 |
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 |