You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

509 lines
13 KiB

12 years ago
12 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013 CERN
  5. * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #ifndef __TOOL_EVENT_H
  25. #define __TOOL_EVENT_H
  26. #include <cstdio>
  27. #include <deque>
  28. #include <math/vector2d.h>
  29. #include <cassert>
  30. #include <boost/optional.hpp>
  31. class TOOL_ACTION;
  32. class TOOL_MANAGER;
  33. /**
  34. * Internal (GUI-independent) event definitions.
  35. * Enums are mostly self-explanatory.
  36. */
  37. enum TOOL_EVENT_CATEGORY
  38. {
  39. TC_NONE = 0x00,
  40. TC_MOUSE = 0x01,
  41. TC_KEYBOARD = 0x02,
  42. TC_COMMAND = 0x04,
  43. TC_MESSAGE = 0x08,
  44. TC_VIEW = 0x10,
  45. TC_ANY = 0xffffffff
  46. };
  47. enum TOOL_ACTIONS
  48. {
  49. // UI input events
  50. TA_NONE = 0x0000,
  51. TA_MOUSE_CLICK = 0x0001,
  52. TA_MOUSE_DBLCLICK = 0x0002,
  53. TA_MOUSE_UP = 0x0004,
  54. TA_MOUSE_DOWN = 0x0008,
  55. TA_MOUSE_DRAG = 0x0010,
  56. TA_MOUSE_MOTION = 0x0020,
  57. TA_MOUSE_WHEEL = 0x0040,
  58. TA_MOUSE = 0x007f,
  59. TA_KEY_PRESSED = 0x0080,
  60. TA_KEYBOARD = TA_KEY_PRESSED,
  61. // View related events
  62. TA_VIEW_REFRESH = 0x0100,
  63. TA_VIEW_ZOOM = 0x0200,
  64. TA_VIEW_PAN = 0x0400,
  65. TA_VIEW_DIRTY = 0x0800,
  66. TA_VIEW = 0x0f00,
  67. TA_CHANGE_LAYER = 0x1000,
  68. // Tool cancel event. Issued automagically when the user hits escape or selects End Tool from
  69. // the context menu.
  70. TA_CANCEL_TOOL = 0x2000,
  71. // Context menu update. Issued whenever context menu is open and the user hovers the mouse
  72. // over one of choices. Used in dynamic highligting in disambiguation menu
  73. TA_CONTEXT_MENU_UPDATE = 0x4000,
  74. // Context menu choice. Sent if the user picked something from the context menu or
  75. // closed it without selecting anything.
  76. TA_CONTEXT_MENU_CHOICE = 0x8000,
  77. // This event is sent *before* undo/redo command is performed.
  78. TA_UNDO_REDO = 0x10000,
  79. // Tool action (allows to control tools)
  80. TA_ACTION = 0x20000,
  81. TA_ANY = 0xffffffff
  82. };
  83. enum TOOL_MOUSE_BUTTONS
  84. {
  85. BUT_NONE = 0x0,
  86. BUT_LEFT = 0x1,
  87. BUT_RIGHT = 0x2,
  88. BUT_MIDDLE = 0x4,
  89. BUT_BUTTON_MASK = BUT_LEFT | BUT_RIGHT | BUT_MIDDLE,
  90. BUT_ANY = 0xffffffff
  91. };
  92. enum TOOL_MODIFIERS
  93. {
  94. MD_SHIFT = 0x1000,
  95. MD_CTRL = 0x2000,
  96. MD_ALT = 0x4000,
  97. MD_MODIFIER_MASK = MD_SHIFT | MD_CTRL | MD_ALT,
  98. };
  99. /// Scope of tool actions
  100. enum TOOL_ACTION_SCOPE
  101. {
  102. AS_CONTEXT = 1, ///> Action belongs to a particular tool (i.e. a part of a pop-up menu)
  103. AS_ACTIVE, ///> All active tools
  104. AS_GLOBAL ///> Global action (toolbar/main menu event, global shortcut)
  105. };
  106. /// Defines when a context menu is opened.
  107. enum CONTEXT_MENU_TRIGGER
  108. {
  109. CMENU_BUTTON = 0, // On the right button
  110. CMENU_NOW, // Right now (after TOOL_INTERACTIVE::SetContextMenu)
  111. CMENU_OFF // Never
  112. };
  113. /**
  114. * Class TOOL_EVENT
  115. *
  116. * Generic, UI-independent tool event.
  117. */
  118. class TOOL_EVENT
  119. {
  120. public:
  121. /**
  122. * Function Format()
  123. * Returns information about event in form of a human-readable string.
  124. *
  125. * @return Event information.
  126. */
  127. const std::string Format() const;
  128. TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory = TC_NONE, TOOL_ACTIONS aAction = TA_NONE,
  129. TOOL_ACTION_SCOPE aScope = AS_GLOBAL ) :
  130. m_category( aCategory ),
  131. m_actions( aAction ),
  132. m_scope( aScope ),
  133. m_mouseButtons( 0 ),
  134. m_keyCode( 0 ),
  135. m_modifiers( 0 ) {}
  136. TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory, TOOL_ACTIONS aAction, int aExtraParam,
  137. TOOL_ACTION_SCOPE aScope = AS_GLOBAL ) :
  138. m_category( aCategory ),
  139. m_actions( aAction ),
  140. m_scope( aScope )
  141. {
  142. if( aCategory == TC_MOUSE )
  143. {
  144. m_mouseButtons = aExtraParam & BUT_BUTTON_MASK;
  145. }
  146. else if( aCategory == TC_KEYBOARD )
  147. {
  148. m_keyCode = aExtraParam & ~MD_MODIFIER_MASK; // Filter out modifiers
  149. }
  150. else if( aCategory == TC_COMMAND )
  151. {
  152. m_commandId = aExtraParam;
  153. }
  154. if( aCategory & ( TC_MOUSE | TC_KEYBOARD ) )
  155. {
  156. m_modifiers = aExtraParam & MD_MODIFIER_MASK;
  157. }
  158. }
  159. TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory, TOOL_ACTIONS aAction,
  160. const std::string& aExtraParam, TOOL_ACTION_SCOPE aScope = AS_GLOBAL ) :
  161. m_category( aCategory ),
  162. m_actions( aAction ),
  163. m_scope( aScope ),
  164. m_mouseButtons( 0 )
  165. {
  166. if( aCategory == TC_COMMAND || aCategory == TC_MESSAGE )
  167. m_commandStr = aExtraParam;
  168. }
  169. ///> Returns the category (eg. mouse/keyboard/action) of an event..
  170. TOOL_EVENT_CATEGORY Category() const
  171. {
  172. return m_category;
  173. }
  174. ///> Returns more specific information about the type of an event.
  175. TOOL_ACTIONS Action() const
  176. {
  177. return m_actions;
  178. }
  179. ///> Returns information about difference between current mouse cursor position and the place
  180. ///> where dragging has started.
  181. const VECTOR2D& Delta() const
  182. {
  183. assert( m_category == TC_MOUSE ); // this should be used only with mouse events
  184. return m_mouseDelta;
  185. }
  186. ///> Returns mouse cursor position in world coordinates.
  187. const VECTOR2D& Position() const
  188. {
  189. assert( m_category == TC_MOUSE ); // this should be used only with mouse events
  190. return m_mousePos;
  191. }
  192. ///> Returns the point where dragging has started.
  193. const VECTOR2D& DragOrigin() const
  194. {
  195. assert( m_category == TC_MOUSE ); // this should be used only with mouse events
  196. return m_mouseDragOrigin;
  197. }
  198. ///> Returns information about mouse buttons state.
  199. int Buttons() const
  200. {
  201. assert( m_category == TC_MOUSE ); // this should be used only with mouse events
  202. return m_mouseButtons;
  203. }
  204. bool IsClick( int aButtonMask = BUT_ANY ) const
  205. {
  206. return ( m_actions == TA_MOUSE_CLICK )
  207. && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
  208. }
  209. bool IsDblClick( int aButtonMask = BUT_ANY ) const
  210. {
  211. return ( m_actions == TA_MOUSE_DBLCLICK )
  212. && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
  213. }
  214. bool IsDrag( int aButtonMask = BUT_ANY ) const
  215. {
  216. return ( m_actions == TA_MOUSE_DRAG ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
  217. }
  218. bool IsMouseUp( int aButtonMask = BUT_ANY ) const
  219. {
  220. return ( m_actions == TA_MOUSE_UP ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
  221. }
  222. bool IsMotion() const
  223. {
  224. return m_actions == TA_MOUSE_MOTION;
  225. }
  226. bool IsCancel() const
  227. {
  228. return m_actions == TA_CANCEL_TOOL;
  229. }
  230. ///> Returns information about key modifiers state (Ctrl, Alt, etc.)
  231. int Modifier( int aMask = MD_MODIFIER_MASK ) const
  232. {
  233. return m_modifiers & aMask;
  234. }
  235. int KeyCode() const
  236. {
  237. return m_keyCode;
  238. }
  239. bool IsKeyPressed() const
  240. {
  241. return m_actions == TA_KEY_PRESSED;
  242. }
  243. void SetMouseDragOrigin( const VECTOR2D& aP )
  244. {
  245. m_mouseDragOrigin = aP;
  246. }
  247. void SetMousePosition( const VECTOR2D& aP )
  248. {
  249. m_mousePos = aP;
  250. }
  251. void SetMouseDelta( const VECTOR2D& aP )
  252. {
  253. m_mouseDelta = aP;
  254. }
  255. /**
  256. * Function Matches()
  257. * Tests whether two events match in terms of category & action or command.
  258. *
  259. * @param aEvent is the event to test against.
  260. * @return True if two events match, false otherwise.
  261. */
  262. bool Matches( const TOOL_EVENT& aEvent ) const
  263. {
  264. if( !( m_category & aEvent.m_category ) )
  265. return false;
  266. if( !( m_actions & aEvent.m_actions ) )
  267. return false;
  268. if( m_category == TC_COMMAND || m_category == TC_MESSAGE )
  269. {
  270. if( m_commandStr && aEvent.m_commandStr )
  271. return *m_commandStr == *aEvent.m_commandStr;
  272. if( m_commandId && aEvent.m_commandId )
  273. return *m_commandId == *aEvent.m_commandId;
  274. // Command-type event has to contain either id or string
  275. assert( false );
  276. }
  277. return true;
  278. }
  279. /**
  280. * Function IsAction()
  281. * Tests if the event contains an action issued upon activation of the given TOOL_ACTION.
  282. * @param aAction is the TOOL_ACTION to be checked against.
  283. * @return True if it matches the given TOOL_ACTION.
  284. */
  285. bool IsAction( const TOOL_ACTION* aAction ) const;
  286. boost::optional<int> GetCommandId()
  287. {
  288. return m_commandId;
  289. }
  290. private:
  291. friend class TOOL_MANAGER;
  292. TOOL_EVENT_CATEGORY m_category;
  293. TOOL_ACTIONS m_actions;
  294. TOOL_ACTION_SCOPE m_scope;
  295. ///> Difference between mouse cursor position and
  296. ///> the point where dragging event has started
  297. VECTOR2D m_mouseDelta;
  298. ///> Current mouse cursor position
  299. VECTOR2D m_mousePos;
  300. ///> Point where dragging has started
  301. VECTOR2D m_mouseDragOrigin;
  302. ///> State of mouse buttons
  303. int m_mouseButtons;
  304. ///> Stores code of pressed/released key
  305. int m_keyCode;
  306. ///> State of key modifierts (Ctrl/Alt/etc.)
  307. int m_modifiers;
  308. boost::optional<int> m_commandId;
  309. boost::optional<std::string> m_commandStr;
  310. };
  311. typedef boost::optional<TOOL_EVENT> OPT_TOOL_EVENT;
  312. /**
  313. * Class TOOL_EVENT_LIST
  314. *
  315. * A list of TOOL_EVENTs, with overloaded || operators allowing for
  316. * concatenating TOOL_EVENTs with little code.
  317. */
  318. class TOOL_EVENT_LIST
  319. {
  320. public:
  321. typedef TOOL_EVENT value_type;
  322. typedef std::deque<TOOL_EVENT>::iterator iterator;
  323. typedef std::deque<TOOL_EVENT>::const_iterator const_iterator;
  324. ///> Default constructor. Creates an empty list.
  325. TOOL_EVENT_LIST()
  326. {}
  327. ///> Constructor for a list containing only one TOOL_EVENT.
  328. TOOL_EVENT_LIST( const TOOL_EVENT& aSingleEvent )
  329. {
  330. m_events.push_back( aSingleEvent );
  331. }
  332. /**
  333. * Function Format()
  334. * Returns information about event in form of a human-readable string.
  335. *
  336. * @return Event information.
  337. */
  338. const std::string Format() const;
  339. boost::optional<const TOOL_EVENT&> Matches( const TOOL_EVENT& aEvent ) const
  340. {
  341. for( const_iterator i = m_events.begin(); i != m_events.end(); ++i )
  342. if( i->Matches( aEvent ) )
  343. return *i;
  344. return boost::optional<const TOOL_EVENT&>();
  345. }
  346. /**
  347. * Function Add()
  348. * Adds a tool event to the list.
  349. * @param aEvent is the tool event to be addded.
  350. */
  351. void Add( const TOOL_EVENT& aEvent )
  352. {
  353. m_events.push_back( aEvent );
  354. }
  355. iterator begin()
  356. {
  357. return m_events.begin();
  358. }
  359. iterator end()
  360. {
  361. return m_events.end();
  362. }
  363. const_iterator cbegin() const
  364. {
  365. return m_events.begin();
  366. }
  367. const_iterator cend() const
  368. {
  369. return m_events.end();
  370. }
  371. int size() const
  372. {
  373. return m_events.size();
  374. }
  375. void clear()
  376. {
  377. m_events.clear();
  378. }
  379. TOOL_EVENT_LIST& operator=( const TOOL_EVENT_LIST& aEventList )
  380. {
  381. m_events.clear();
  382. for( std::deque<TOOL_EVENT>::const_iterator i = aEventList.m_events.begin();
  383. i != aEventList.m_events.end(); ++i )
  384. {
  385. m_events.push_back( *i );
  386. }
  387. return *this;
  388. }
  389. TOOL_EVENT_LIST& operator=( const TOOL_EVENT& aEvent )
  390. {
  391. m_events.clear();
  392. m_events.push_back( aEvent );
  393. return *this;
  394. }
  395. TOOL_EVENT_LIST& operator||( const TOOL_EVENT& aEvent )
  396. {
  397. Add( aEvent );
  398. return *this;
  399. }
  400. TOOL_EVENT_LIST& operator||( const TOOL_EVENT_LIST& aEvent )
  401. {
  402. return *this;
  403. }
  404. private:
  405. std::deque<TOOL_EVENT> m_events;
  406. };
  407. inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& aEventA, const TOOL_EVENT& aEventB )
  408. {
  409. TOOL_EVENT_LIST l;
  410. l.Add( aEventA );
  411. l.Add( aEventB );
  412. return l;
  413. }
  414. inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& aEvent,
  415. const TOOL_EVENT_LIST& aEventList )
  416. {
  417. TOOL_EVENT_LIST l( aEventList );
  418. l.Add( aEvent );
  419. return l;
  420. }
  421. #endif