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 
25 #include <cstring>
26 #include <string>
27 
28 #include <tool/tool_event.h>
29 #include <tool/tool_action.h>
30 #include <tool/tool_manager.h>
31 #include <tool/actions.h>
32 
33 #ifdef WX_COMPATIBILITY
34 #include <wx/debug.h>
35 #else
36 #include <cassert>
37 #endif
38 
39 struct FlagString
40 {
41     int flag;
42     std::string str;
43 };
44 
45 
flag2string(int aFlag,const FlagString * aExps)46 static const std::string flag2string( int aFlag, const FlagString* aExps )
47 {
48     std::string rv;
49 
50     for( int i = 0; aExps[i].str.length(); i++ )
51     {
52         if( aExps[i].flag & aFlag )
53             rv += aExps[i].str + " ";
54     }
55 
56     return rv;
57 }
58 
59 
init()60 void TOOL_EVENT::init()
61 {
62     // By default only MESSAGEs and Cancels are passed to multiple recipients
63     m_passEvent = m_category == TC_MESSAGE || IsCancelInteractive() || IsActivate();
64 
65     m_hasPosition = ( m_category == TC_MOUSE || m_category == TC_COMMAND );
66 
67     // Cancel tool doesn't contain a position
68     if( IsCancel() )
69         m_hasPosition = false;
70 
71     m_forceImmediate = false;
72     m_reactivate = false;
73 }
74 
75 
returnCheckedPosition(const VECTOR2D & aPos) const76 VECTOR2D TOOL_EVENT::returnCheckedPosition( const VECTOR2D& aPos ) const
77 {
78 #ifdef WX_COMPATIBILITY
79     wxCHECK_MSG( HasPosition(), VECTOR2D(), "Attempted to get position from non-position event" );
80 #else
81     assert( HasPosition() );
82 #endif
83 
84     return aPos;
85 }
86 
87 
IsAction(const TOOL_ACTION * aAction) const88 bool TOOL_EVENT::IsAction( const TOOL_ACTION* aAction ) const
89 {
90     return Matches( aAction->MakeEvent() );
91 }
92 
93 
Format() const94 const std::string TOOL_EVENT::Format() const
95 {
96     std::string ev;
97 
98     const FlagString categories[] =
99     {
100         { TC_MOUSE,    "mouse"    },
101         { TC_KEYBOARD, "keyboard" },
102         { TC_COMMAND,  "command"  },
103         { TC_MESSAGE,  "message"  },
104         { TC_VIEW,     "view"     },
105         { 0,           ""         }
106     };
107 
108     const FlagString actions[] =
109     {
110         { TA_MOUSE_CLICK,        "click"               },
111         { TA_MOUSE_DBLCLICK,     "double click"        },
112         { TA_MOUSE_UP,           "button-up"           },
113         { TA_MOUSE_DOWN,         "button-down"         },
114         { TA_MOUSE_DRAG,         "drag"                },
115         { TA_MOUSE_MOTION,       "motion"              },
116         { TA_MOUSE_WHEEL,        "wheel"               },
117         { TA_KEY_PRESSED,        "key-pressed"         },
118         { TA_VIEW_REFRESH,       "view-refresh"        },
119         { TA_VIEW_ZOOM,          "view-zoom"           },
120         { TA_VIEW_PAN,           "view-pan"            },
121         { TA_VIEW_DIRTY,         "view-dirty"          },
122         { TA_CHANGE_LAYER,       "change-layer"        },
123         { TA_CANCEL_TOOL,        "cancel-tool"         },
124         { TA_CHOICE_MENU_UPDATE, "choice-menu-update"  },
125         { TA_CHOICE_MENU_CHOICE, "choice-menu-choice"  },
126         { TA_UNDO_REDO_PRE,      "undo-redo-pre"       },
127         { TA_UNDO_REDO_POST,     "undo-redo-post"      },
128         { TA_ACTION,             "action"              },
129         { TA_ACTIVATE,           "activate"            },
130         { 0,                     ""                    }
131     };
132 
133     const FlagString buttons[] =
134     {
135         { BUT_NONE,   "none"   },
136         { BUT_LEFT,   "left"   },
137         { BUT_RIGHT,  "right"  },
138         { BUT_MIDDLE, "middle" },
139         { 0,          ""       }
140     };
141 
142     const FlagString modifiers[] =
143     {
144         { MD_SHIFT, "shift" },
145         { MD_CTRL,  "ctrl"  },
146         { MD_ALT,   "alt"   },
147         { 0,        ""      }
148     };
149 
150     ev = "category: ";
151     ev += flag2string( m_category, categories );
152     ev += " action: ";
153     ev += flag2string( m_actions, actions );
154 
155     if( m_actions & TA_MOUSE )
156     {
157         ev += " btns: ";
158         ev += flag2string( m_mouseButtons, buttons );
159     }
160 
161     if( m_actions & TA_KEYBOARD )
162     {
163         char tmp[128];
164         sprintf( tmp, "key: %d", m_keyCode );
165         ev += tmp;
166     }
167 
168     if( m_actions & ( TA_MOUSE | TA_KEYBOARD ) )
169     {
170         ev += " mods: ";
171         ev += flag2string( m_modifiers, modifiers );
172     }
173 
174     if( m_commandId )
175     {
176         char tmp[128];
177         sprintf( tmp, "cmd-id: %d", *m_commandId );
178         ev += tmp;
179     }
180 
181     if( m_commandStr )
182         ev += "cmd-str: " + ( *m_commandStr );
183 
184     return ev;
185 }
186 
187 
Format() const188 const std::string TOOL_EVENT_LIST::Format() const
189 {
190     std::string s;
191 
192     for( const TOOL_EVENT& e : m_events )
193         s += e.Format() + " ";
194 
195     return s;
196 }
197 
198 
IsClick(int aButtonMask) const199 bool TOOL_EVENT::IsClick( int aButtonMask ) const
200 {
201     return ( m_actions & TA_MOUSE_CLICK ) && ( m_mouseButtons & aButtonMask ) == m_mouseButtons;
202 }
203 
204 
IsDblClick(int aButtonMask) const205 bool TOOL_EVENT::IsDblClick( int aButtonMask ) const
206 {
207     return m_actions == TA_MOUSE_DBLCLICK && ( m_mouseButtons & aButtonMask ) == m_mouseButtons;
208 }
209 
210 
IsCancelInteractive() const211 bool TOOL_EVENT::IsCancelInteractive() const
212 {
213     return( ( m_commandStr.is_initialized()
214                 && m_commandStr.get() == ACTIONS::cancelInteractive.GetName() )
215          || ( m_commandId.is_initialized()
216                 && m_commandId.get() == ACTIONS::cancelInteractive.GetId() )
217          || ( m_actions == TA_CANCEL_TOOL ) );
218 }
219 
220 
IsSelectionEvent() const221 bool TOOL_EVENT::IsSelectionEvent() const
222 {
223     return Matches( EVENTS::ClearedEvent )
224         || Matches( EVENTS::UnselectedEvent )
225         || Matches( EVENTS::SelectedEvent );
226 }
227 
228 
IsPointEditor() const229 bool TOOL_EVENT::IsPointEditor() const
230 {
231     return( ( m_commandStr.is_initialized()
232                     && m_commandStr.get().find( "PointEditor" ) != GetCommandStr()->npos )
233          || ( m_commandId.is_initialized()
234                     && m_commandId.get() == ACTIONS::activatePointEditor.GetId() ) );
235 }
236 
237 
IsMoveTool() const238 bool TOOL_EVENT::IsMoveTool() const
239 {
240     return( m_commandStr.is_initialized()
241                 && m_commandStr.get().find( "InteractiveMove" ) != GetCommandStr()->npos );
242 }
243 
244 
IsSimulator() const245 bool TOOL_EVENT::IsSimulator() const
246 {
247     return( m_commandStr.is_initialized()
248                 && m_commandStr.get().find( "Simulation" ) != GetCommandStr()->npos );
249 }
250