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.

558 lines
14 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. // Tool activation event.
  82. TA_ACTIVATE = 0x40000,
  83. TA_ANY = 0xffffffff
  84. };
  85. enum TOOL_MOUSE_BUTTONS
  86. {
  87. BUT_NONE = 0x0,
  88. BUT_LEFT = 0x1,
  89. BUT_RIGHT = 0x2,
  90. BUT_MIDDLE = 0x4,
  91. BUT_BUTTON_MASK = BUT_LEFT | BUT_RIGHT | BUT_MIDDLE,
  92. BUT_ANY = 0xffffffff
  93. };
  94. enum TOOL_MODIFIERS
  95. {
  96. MD_SHIFT = 0x1000,
  97. MD_CTRL = 0x2000,
  98. MD_ALT = 0x4000,
  99. MD_MODIFIER_MASK = MD_SHIFT | MD_CTRL | MD_ALT,
  100. };
  101. /// Scope of tool actions
  102. enum TOOL_ACTION_SCOPE
  103. {
  104. AS_CONTEXT = 1, ///> Action belongs to a particular tool (i.e. a part of a pop-up menu)
  105. AS_ACTIVE, ///> All active tools
  106. AS_GLOBAL ///> Global action (toolbar/main menu event, global shortcut)
  107. };
  108. /// Flags for tool actions
  109. enum TOOL_ACTION_FLAGS
  110. {
  111. AF_NONE = 0,
  112. AF_ACTIVATE = 1, ///> Action activates a tool
  113. AF_NOTIFY = 2 ///> Action is a notification (it is by default passed to all tools)
  114. };
  115. /// Defines when a context menu is opened.
  116. enum CONTEXT_MENU_TRIGGER
  117. {
  118. CMENU_BUTTON = 0, // On the right button
  119. CMENU_NOW, // Right now (after TOOL_INTERACTIVE::SetContextMenu)
  120. CMENU_OFF // Never
  121. };
  122. /**
  123. * Class TOOL_EVENT
  124. *
  125. * Generic, UI-independent tool event.
  126. */
  127. class TOOL_EVENT
  128. {
  129. public:
  130. /**
  131. * Function Format()
  132. * Returns information about event in form of a human-readable string.
  133. *
  134. * @return Event information.
  135. */
  136. const std::string Format() const;
  137. TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory = TC_NONE, TOOL_ACTIONS aAction = TA_NONE,
  138. TOOL_ACTION_SCOPE aScope = AS_GLOBAL ) :
  139. m_category( aCategory ),
  140. m_actions( aAction ),
  141. m_scope( aScope ),
  142. m_mouseButtons( 0 ),
  143. m_keyCode( 0 ),
  144. m_modifiers( 0 ),
  145. m_param( NULL ) {}
  146. TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory, TOOL_ACTIONS aAction, int aExtraParam,
  147. TOOL_ACTION_SCOPE aScope = AS_GLOBAL ) :
  148. m_category( aCategory ),
  149. m_actions( aAction ),
  150. m_scope( aScope ),
  151. m_mouseButtons( 0 ),
  152. m_keyCode( 0 ),
  153. m_modifiers( 0 ),
  154. m_param( NULL )
  155. {
  156. if( aCategory == TC_MOUSE )
  157. {
  158. m_mouseButtons = aExtraParam & BUT_BUTTON_MASK;
  159. }
  160. else if( aCategory == TC_KEYBOARD )
  161. {
  162. m_keyCode = aExtraParam & ~MD_MODIFIER_MASK; // Filter out modifiers
  163. }
  164. else if( aCategory == TC_COMMAND )
  165. {
  166. m_commandId = aExtraParam;
  167. }
  168. if( aCategory & ( TC_MOUSE | TC_KEYBOARD ) )
  169. {
  170. m_modifiers = aExtraParam & MD_MODIFIER_MASK;
  171. }
  172. }
  173. TOOL_EVENT( TOOL_EVENT_CATEGORY aCategory, TOOL_ACTIONS aAction,
  174. const std::string& aExtraParam, TOOL_ACTION_SCOPE aScope = AS_GLOBAL ) :
  175. m_category( aCategory ),
  176. m_actions( aAction ),
  177. m_scope( aScope ),
  178. m_mouseButtons( 0 ),
  179. m_keyCode( 0 ),
  180. m_modifiers( 0 ),
  181. m_param( NULL )
  182. {
  183. if( aCategory == TC_COMMAND || aCategory == TC_MESSAGE )
  184. m_commandStr = aExtraParam;
  185. }
  186. ///> Returns the category (eg. mouse/keyboard/action) of an event..
  187. TOOL_EVENT_CATEGORY Category() const
  188. {
  189. return m_category;
  190. }
  191. ///> Returns more specific information about the type of an event.
  192. TOOL_ACTIONS Action() const
  193. {
  194. return m_actions;
  195. }
  196. ///> Returns information about difference between current mouse cursor position and the place
  197. ///> where dragging has started.
  198. const VECTOR2D& Delta() const
  199. {
  200. assert( m_category == TC_MOUSE ); // this should be used only with mouse events
  201. return m_mouseDelta;
  202. }
  203. ///> Returns mouse cursor position in world coordinates.
  204. const VECTOR2D& Position() const
  205. {
  206. assert( m_category == TC_MOUSE ); // this should be used only with mouse events
  207. return m_mousePos;
  208. }
  209. ///> Returns the point where dragging has started.
  210. const VECTOR2D& DragOrigin() const
  211. {
  212. assert( m_category == TC_MOUSE ); // this should be used only with mouse events
  213. return m_mouseDragOrigin;
  214. }
  215. ///> Returns information about mouse buttons state.
  216. int Buttons() const
  217. {
  218. assert( m_category == TC_MOUSE ); // this should be used only with mouse events
  219. return m_mouseButtons;
  220. }
  221. bool IsClick( int aButtonMask = BUT_ANY ) const
  222. {
  223. return ( m_actions == TA_MOUSE_CLICK )
  224. && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
  225. }
  226. bool IsDblClick( int aButtonMask = BUT_ANY ) const
  227. {
  228. return ( m_actions == TA_MOUSE_DBLCLICK )
  229. && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
  230. }
  231. bool IsDrag( int aButtonMask = BUT_ANY ) const
  232. {
  233. return ( m_actions == TA_MOUSE_DRAG ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
  234. }
  235. bool IsMouseUp( int aButtonMask = BUT_ANY ) const
  236. {
  237. return ( m_actions == TA_MOUSE_UP ) && ( ( m_mouseButtons & aButtonMask ) == aButtonMask );
  238. }
  239. bool IsMotion() const
  240. {
  241. return m_actions == TA_MOUSE_MOTION;
  242. }
  243. bool IsCancel() const
  244. {
  245. return m_actions == TA_CANCEL_TOOL;
  246. }
  247. bool IsActivate() const
  248. {
  249. return m_actions == TA_ACTIVATE;
  250. }
  251. ///> Returns information about key modifiers state (Ctrl, Alt, etc.)
  252. int Modifier( int aMask = MD_MODIFIER_MASK ) const
  253. {
  254. return m_modifiers & aMask;
  255. }
  256. int KeyCode() const
  257. {
  258. return m_keyCode;
  259. }
  260. bool IsKeyPressed() const
  261. {
  262. return m_actions == TA_KEY_PRESSED;
  263. }
  264. void SetMouseDragOrigin( const VECTOR2D& aP )
  265. {
  266. m_mouseDragOrigin = aP;
  267. }
  268. void SetMousePosition( const VECTOR2D& aP )
  269. {
  270. m_mousePos = aP;
  271. }
  272. void SetMouseDelta( const VECTOR2D& aP )
  273. {
  274. m_mouseDelta = aP;
  275. }
  276. /**
  277. * Function Matches()
  278. * Tests whether two events match in terms of category & action or command.
  279. *
  280. * @param aEvent is the event to test against.
  281. * @return True if two events match, false otherwise.
  282. */
  283. bool Matches( const TOOL_EVENT& aEvent ) const
  284. {
  285. if( !( m_category & aEvent.m_category ) )
  286. return false;
  287. if( !( m_actions & aEvent.m_actions ) )
  288. return false;
  289. if( m_category == TC_COMMAND || m_category == TC_MESSAGE )
  290. {
  291. if( (bool) m_commandStr && (bool) aEvent.m_commandStr )
  292. return *m_commandStr == *aEvent.m_commandStr;
  293. if( (bool) m_commandId && (bool) aEvent.m_commandId )
  294. return *m_commandId == *aEvent.m_commandId;
  295. }
  296. return true;
  297. }
  298. /**
  299. * Function IsAction()
  300. * Tests if the event contains an action issued upon activation of the given TOOL_ACTION.
  301. * @param aAction is the TOOL_ACTION to be checked against.
  302. * @return True if it matches the given TOOL_ACTION.
  303. */
  304. bool IsAction( const TOOL_ACTION* aAction ) const;
  305. /**
  306. * Function Parameter()
  307. * Returns a non-standard parameter assigned to the event. Its meaning depends on the
  308. * target tool.
  309. */
  310. void* Parameter() const
  311. {
  312. return m_param;
  313. }
  314. /**
  315. * Function SetParameter()
  316. * Sets a non-standard parameter assigned to the event. Its meaning depends on the
  317. * target tool.
  318. * @param aParam is the new parameter.
  319. */
  320. void SetParameter(void* aParam)
  321. {
  322. m_param = aParam;
  323. }
  324. boost::optional<int> GetCommandId() const
  325. {
  326. return m_commandId;
  327. }
  328. boost::optional<std::string> GetCommandStr() const
  329. {
  330. return m_commandStr;
  331. }
  332. private:
  333. friend class TOOL_MANAGER;
  334. TOOL_EVENT_CATEGORY m_category;
  335. TOOL_ACTIONS m_actions;
  336. TOOL_ACTION_SCOPE m_scope;
  337. ///> Difference between mouse cursor position and
  338. ///> the point where dragging event has started
  339. VECTOR2D m_mouseDelta;
  340. ///> Current mouse cursor position
  341. VECTOR2D m_mousePos;
  342. ///> Point where dragging has started
  343. VECTOR2D m_mouseDragOrigin;
  344. ///> State of mouse buttons
  345. int m_mouseButtons;
  346. ///> Stores code of pressed/released key
  347. int m_keyCode;
  348. ///> State of key modifierts (Ctrl/Alt/etc.)
  349. int m_modifiers;
  350. ///> Generic parameter used for passing non-standard data.
  351. void* m_param;
  352. boost::optional<int> m_commandId;
  353. boost::optional<std::string> m_commandStr;
  354. };
  355. typedef boost::optional<TOOL_EVENT> OPT_TOOL_EVENT;
  356. /**
  357. * Class TOOL_EVENT_LIST
  358. *
  359. * A list of TOOL_EVENTs, with overloaded || operators allowing for
  360. * concatenating TOOL_EVENTs with little code.
  361. */
  362. class TOOL_EVENT_LIST
  363. {
  364. public:
  365. typedef TOOL_EVENT value_type;
  366. typedef std::deque<TOOL_EVENT>::iterator iterator;
  367. typedef std::deque<TOOL_EVENT>::const_iterator const_iterator;
  368. ///> Default constructor. Creates an empty list.
  369. TOOL_EVENT_LIST()
  370. {}
  371. ///> Constructor for a list containing only one TOOL_EVENT.
  372. TOOL_EVENT_LIST( const TOOL_EVENT& aSingleEvent )
  373. {
  374. m_events.push_back( aSingleEvent );
  375. }
  376. /**
  377. * Function Format()
  378. * Returns information about event in form of a human-readable string.
  379. *
  380. * @return Event information.
  381. */
  382. const std::string Format() const;
  383. boost::optional<const TOOL_EVENT&> Matches( const TOOL_EVENT& aEvent ) const
  384. {
  385. for( const_iterator i = m_events.begin(); i != m_events.end(); ++i )
  386. if( i->Matches( aEvent ) )
  387. return *i;
  388. return boost::optional<const TOOL_EVENT&>();
  389. }
  390. /**
  391. * Function Add()
  392. * Adds a tool event to the list.
  393. * @param aEvent is the tool event to be addded.
  394. */
  395. void Add( const TOOL_EVENT& aEvent )
  396. {
  397. m_events.push_back( aEvent );
  398. }
  399. iterator begin()
  400. {
  401. return m_events.begin();
  402. }
  403. iterator end()
  404. {
  405. return m_events.end();
  406. }
  407. const_iterator cbegin() const
  408. {
  409. return m_events.begin();
  410. }
  411. const_iterator cend() const
  412. {
  413. return m_events.end();
  414. }
  415. int size() const
  416. {
  417. return m_events.size();
  418. }
  419. void clear()
  420. {
  421. m_events.clear();
  422. }
  423. TOOL_EVENT_LIST& operator=( const TOOL_EVENT_LIST& aEventList )
  424. {
  425. m_events.clear();
  426. for( std::deque<TOOL_EVENT>::const_iterator i = aEventList.m_events.begin();
  427. i != aEventList.m_events.end(); ++i )
  428. {
  429. m_events.push_back( *i );
  430. }
  431. return *this;
  432. }
  433. TOOL_EVENT_LIST& operator=( const TOOL_EVENT& aEvent )
  434. {
  435. m_events.clear();
  436. m_events.push_back( aEvent );
  437. return *this;
  438. }
  439. TOOL_EVENT_LIST& operator||( const TOOL_EVENT& aEvent )
  440. {
  441. Add( aEvent );
  442. return *this;
  443. }
  444. TOOL_EVENT_LIST& operator||( const TOOL_EVENT_LIST& aEvent )
  445. {
  446. return *this;
  447. }
  448. private:
  449. std::deque<TOOL_EVENT> m_events;
  450. };
  451. inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& aEventA, const TOOL_EVENT& aEventB )
  452. {
  453. TOOL_EVENT_LIST l;
  454. l.Add( aEventA );
  455. l.Add( aEventB );
  456. return l;
  457. }
  458. inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& aEvent,
  459. const TOOL_EVENT_LIST& aEventList )
  460. {
  461. TOOL_EVENT_LIST l( aEventList );
  462. l.Add( aEvent );
  463. return l;
  464. }
  465. #endif