/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2013 CERN * @author Tomasz Wlostowski * * 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 #include #include #include class TOOL_MANAGER; /** * Internal (GUI-independent) event definitions. * Enums are mostly self-explanatory. */ enum TOOL_EventCategory { TC_None = 0x0, TC_Mouse = 0x1, TC_Command = 0x2, TC_Message = 0x4, TC_View = 0x8, TC_Any = 0xffffffff }; enum TOOL_Actions { TA_None = 0x0, TA_MouseClick = 0x1, TA_MouseUp = 0x2, TA_MouseDown = 0x4, TA_MouseDrag = 0x8, TA_MouseMotion = 0x10, TA_MouseWheel = 0x20, TA_Mouse = 0x3f, TA_ViewRefresh = 0x40, TA_ViewZoom = 0x80, TA_ViewPan = 0x100, TA_ViewDirty = 0x200, TA_ChangeLayer = 0x1000, // Tool cancel event. Issued automagically when the user hits escape or selects End Tool from the context menu. TA_CancelTool = 0x2000, // Tool activation event. Issued by the GUI upon pressing a button/menu selection. TA_ActivateTool = 0x4000, // 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_ContextMenuUpdate = 0x8000, // Context menu choice. Sent if the user picked something from the context menu or closed it without selecting anything. TA_ContextMenuChoice = 0x10000, TA_Any = 0xffffffff }; enum TOOL_MouseButtons { MB_None = 0x0, MB_Left = 0x1, MB_Right = 0x2, MB_Middle = 0x4, MB_ButtonMask = MB_Left | MB_Right | MB_Middle, MB_ModShift = 0x8, MB_ModCtrl = 0x10, MB_ModAlt = 0x20, MB_ModifierMask = MB_ModShift | MB_ModCtrl | MB_ModAlt, MB_Any = 0xffffffff }; // Defines when a context menu is opened. enum TOOL_ContextMenuTrigger { CMENU_BUTTON = 0, // On the right button CMENU_NOW, // Right now (after TOOL_INTERACTIVE::SetContxtMenu) CMENU_OFF // Never }; /** * Class TOOL_EVENT * * Generic, UI-independent tool event. */ class TOOL_EVENT { public: const std::string Format() const; TOOL_EVENT( TOOL_EventCategory aCategory = TC_None, TOOL_Actions aAction = TA_None ): m_category( aCategory ), m_actions( aAction ), m_mouseButtons( 0 ) {} TOOL_EVENT( TOOL_EventCategory aCategory, TOOL_Actions aAction, int aExtraParam ): m_category( aCategory ), m_actions( aAction ) { if( aCategory == TC_Mouse ) m_mouseButtons = aExtraParam; else if ( aCategory == TC_Command ) m_commandId = aExtraParam; } TOOL_EVENT( TOOL_EventCategory aCategory, TOOL_Actions aAction, const std::string& aExtraParam ): m_category( aCategory ), m_actions( aAction ), m_mouseButtons( 0 ) { if( aCategory == TC_Command ) m_commandStr = aExtraParam; } TOOL_EventCategory Category() const { return m_category; } TOOL_Actions Action() const { return m_actions; } const VECTOR2D Delta() const { return m_mouseDelta; } const VECTOR2D& Position() const { return m_mousePos; } const VECTOR2D& DragOrigin() const { return m_mouseDragOrigin; } int Buttons() const { return m_mouseButtons; } bool IsClick( int aButtonMask = MB_Any ) const { return ( m_actions == TA_MouseClick ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask ); } bool IsDrag( int aButtonMask = MB_Any ) const { return ( m_actions == TA_MouseDrag ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask ); } bool IsMouseUp( int aButtonMask = MB_Any ) const { return ( m_actions == TA_MouseUp ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask ); } bool IsMotion() const { return ( m_actions == TA_MouseMotion ); } bool IsCancel() const { return m_actions == TA_CancelTool; } bool Modifier( int aMask = MB_ModifierMask ) const { return ( m_mouseButtons & aMask ); } void Ignore(); void SetMouseDragOrigin( const VECTOR2D &aP ) { m_mouseDragOrigin = aP; } void SetMousePosition( const VECTOR2D& aP ) { m_mousePos = aP; } void SetMouseDelta( const VECTOR2D& aP ) { m_mouseDelta = aP; } bool Matches( const TOOL_EVENT& aEvent ) const { if( ! ( m_category & aEvent.m_category ) ) return false; if( ! ( m_actions & aEvent.m_actions ) ) return false; if( m_category == TC_Command ) { if( m_commandStr && aEvent.m_commandStr ) return ( *m_commandStr == *aEvent.m_commandStr ); if( m_commandId && aEvent.m_commandId ) return ( *m_commandId == *aEvent.m_commandId ); } return true; } boost::optional GetCommandId() { return m_commandId; } private: friend class TOOL_MANAGER; TOOL_EventCategory m_category; TOOL_Actions m_actions; VECTOR2D m_mouseDelta; VECTOR2D m_mousePos; VECTOR2D m_mouseDragOrigin; int m_mouseButtons; boost::optional m_commandId; boost::optional m_commandStr; }; typedef boost::optional 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::iterator iterator; typedef std::deque::const_iterator const_iterator; TOOL_EVENT_LIST() {}; TOOL_EVENT_LIST( const TOOL_EVENT& aSingleEvent ) { m_events.push_back(aSingleEvent); } const std::string Format() const; boost::optional Matches( const TOOL_EVENT &b ) const { for( const_iterator i = m_events.begin(); i != m_events.end(); ++i ) if ( i->Matches( b ) ) return *i; return boost::optional(); } 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& b ) { m_events.clear(); for( std::deque::const_iterator i = b.m_events.begin(); i != b.m_events.end(); ++i ) { m_events.push_back(*i); } return *this; } TOOL_EVENT_LIST& operator=( const TOOL_EVENT& b ) { m_events.clear(); m_events.push_back( b ); return *this; } TOOL_EVENT_LIST& operator||( const TOOL_EVENT& b ) { Add( b ); return *this; } TOOL_EVENT_LIST& operator||( const TOOL_EVENT_LIST& b ) { return *this; } private: std::deque m_events; }; inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& a, const TOOL_EVENT &b ) { TOOL_EVENT_LIST l; l.Add( a ); l.Add( b ); return l; } inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT & a, const TOOL_EVENT_LIST &b ) { TOOL_EVENT_LIST l( b ); l.Add( a ); return l; } #endif