KiCad PCB EDA Suite
lib_move_tool.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2019 CERN
5  * Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
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 <tool/tool_manager.h>
27 #include <ee_actions.h>
28 #include <bitmaps.h>
29 #include <eda_item.h>
30 #include "lib_move_tool.h"
31 #include "lib_pin_tool.h"
32 
33 
35  EE_TOOL_BASE( "eeschema.SymbolMoveTool" ),
36  m_moveInProgress( false ),
37  m_moveOffset( 0, 0 )
38 {
39 }
40 
41 
43 {
45 
46  //
47  // Add move actions to the selection tool menu
48  //
50 
52 
53  return true;
54 }
55 
56 
58 {
59  EE_TOOL_BASE::Reset( aReason );
60 
61  if( aReason == MODEL_RELOAD )
62  {
63  m_moveInProgress = false;
64  m_moveOffset = { 0, 0 };
65  }
66 }
67 
68 
69 int LIB_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
70 {
72 
73  m_anchorPos = { 0, 0 };
74 
75  // Be sure that there is at least one item that we can move. If there's no selection try
76  // looking for the stuff under mouse cursor (i.e. Kicad old-style hover selection).
78  bool unselect = selection.IsHover();
79 
81  || selection.Empty() || m_moveInProgress )
82  return 0;
83 
84  std::string tool = aEvent.GetCommandStr().get();
85  m_frame->PushTool( tool );
86  Activate();
87 
88  controls->ShowCursor( true );
89  controls->SetAutoPan( true );
90 
91  bool restore_state = false;
92  bool chain_commands = false;
93  TOOL_EVENT* evt = const_cast<TOOL_EVENT*>( &aEvent );
94  VECTOR2I prevPos;
95 
96  if( !selection.Front()->IsNew() )
98 
99  m_cursor = controls->GetCursorPosition();
100 
101  // Main loop: keep receiving events
102  do
103  {
105 
106  if( evt->IsAction( &EE_ACTIONS::move ) || evt->IsMotion() || evt->IsDrag( BUT_LEFT )
109  {
110  if( !m_moveInProgress ) // Prepare to start moving/dragging
111  {
112  LIB_ITEM* lib_item = (LIB_ITEM*) selection.Front();
113 
114  // Pick up any synchronized pins
115  //
116  // Careful when pasting. The pasted pin will be at the same location as it
117  // was copied from, leading us to believe it's a synchronized pin. It's not.
118  if( selection.GetSize() == 1 && lib_item->Type() == LIB_PIN_T
120  && ( lib_item->GetEditFlags() & IS_PASTED ) == 0 )
121  {
122  LIB_PIN* cur_pin = (LIB_PIN*) lib_item;
123  LIB_PART* part = m_frame->GetCurPart();
124 
125  for( LIB_PIN* pin = part->GetNextPin(); pin; pin = part->GetNextPin( pin ) )
126  {
127  if( pin->GetPosition() == cur_pin->GetPosition()
128  && pin->GetOrientation() == cur_pin->GetOrientation()
129  && pin->GetConvert() == cur_pin->GetConvert() )
130  {
131  m_selectionTool->AddItemToSel( pin, true /*quiet mode*/ );
132  }
133  }
134  }
135 
136  // Apply any initial offset in case we're coming from a previous command.
137  //
138  for( EDA_ITEM* item : selection )
139  moveItem( item, m_moveOffset );
140 
141  // Set up the starting position and move/drag offset
142  //
143  m_cursor = controls->GetCursorPosition();
144 
145  if( lib_item->IsNew() )
146  {
147  m_anchorPos = selection.GetReferencePoint();
148  VECTOR2I delta = m_cursor - mapCoords( m_anchorPos );
149 
150  // Drag items to the current cursor position
151  for( EDA_ITEM* item : selection )
152  {
153  moveItem( item, delta );
154  updateItem( item, false );
155  }
156 
158  }
159  else if( selection.Size() == 1 && m_frame->GetMoveWarpsCursor() )
160  {
161  wxPoint itemPos = lib_item->GetPosition();
162  m_anchorPos = wxPoint( itemPos.x, -itemPos.y );
163 
164  getViewControls()->WarpCursor( m_anchorPos, true, true );
166  }
167  else
168  {
171  }
172 
173  controls->SetCursorPosition( m_cursor, false );
175 
176  prevPos = m_cursor;
177  controls->SetAutoPan( true );
178  m_moveInProgress = true;
179  }
180 
181  //------------------------------------------------------------------------
182  // Follow the mouse
183  //
184  m_cursor = controls->GetCursorPosition();
185  VECTOR2I delta( m_cursor - prevPos );
187 
188  m_moveOffset += delta;
189  prevPos = m_cursor;
190 
191  for( EDA_ITEM* item : selection )
192  {
193  moveItem( item, delta );
194  updateItem( item, false );
195  }
196 
198  }
199  //------------------------------------------------------------------------
200  // Handle cancel
201  //
202  else if( evt->IsCancelInteractive() || evt->IsActivate() )
203  {
204  if( m_moveInProgress )
205  {
206  evt->SetPassEvent( false );
207  restore_state = true;
208  }
209 
210  break;
211  }
212  //------------------------------------------------------------------------
213  // Handle TOOL_ACTION special cases
214  //
215  else if( evt->Action() == TA_UNDO_REDO_PRE )
216  {
217  unselect = true;
218  break;
219  }
220  else if( evt->Category() == TC_COMMAND )
221  {
222  if( evt->IsAction( &ACTIONS::doDelete ) )
223  {
224  // Exit on a remove operation; there is no further processing for removed items.
225  break;
226  }
227  else if( evt->IsAction( &ACTIONS::duplicate ) )
228  {
229  if( selection.Front()->IsNew() )
230  {
231  // This doesn't really make sense; we'll just end up dragging a stack of
232  // objects so Duplicate() is going to ignore this and we'll just carry on.
233  continue;
234  }
235 
236  // Move original back and exit. The duplicate will run in its own loop.
237  restore_state = true;
238  unselect = false;
239  chain_commands = true;
240  break;
241  }
242  else
243  {
244  evt->SetPassEvent();
245  }
246  }
247  //------------------------------------------------------------------------
248  // Handle context menu
249  //
250  else if( evt->IsClick( BUT_RIGHT ) )
251  {
253  }
254  //------------------------------------------------------------------------
255  // Handle drop
256  //
257  else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) )
258  {
259  if( selection.GetSize() == 1 && selection.Front()->Type() == LIB_PIN_T )
260  {
262 
263  if( !pinTool->PlacePin( (LIB_PIN*) selection.Front() ) )
264  restore_state = true;
265  }
266 
267  break; // Finish
268  }
269  else
270  {
271  evt->SetPassEvent();
272  }
273 
274  } while( ( evt = Wait() ) ); // Assignment intentional; not equality test
275 
276  controls->ForceCursorPosition( false );
277  controls->ShowCursor( false );
278  controls->SetAutoPan( false );
279 
280  if( !chain_commands )
281  m_moveOffset = { 0, 0 };
282 
283  m_anchorPos = { 0, 0 };
284 
285  for( auto item : selection )
286  item->ClearEditFlags();
287 
288  if( restore_state )
289  {
291 
292  if( unselect )
294  else
296  }
297  else
298  {
299  if( unselect )
301 
302  m_frame->OnModify();
303  }
304 
305  m_moveInProgress = false;
306  m_frame->PopTool( tool );
307  return 0;
308 }
309 
310 
312 {
313  static_cast<LIB_ITEM*>( aItem )->Offset( mapCoords( aDelta ) );
314  aItem->SetFlags( IS_MOVED );
315 }
316 
317 
319 {
320  Go( &LIB_MOVE_TOOL::Main, EE_ACTIONS::move.MakeEvent() );
322 }
VECTOR2I m_cursor
Last cursor position (needed for getModificationPoint() to avoid changes of edit reference point).
Definition: lib_move_tool.h:69
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag of the current symbol.
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
bool m_moveInProgress
Flag determining if anything is being dragged right now
Definition: lib_move_tool.h:62
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
Definition: ee_tool_base.h:90
static const TOOL_EVENT SelectedEvent
Definition: actions.h:213
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
bool IsHover() const
Definition: selection.h:70
void SetPassEvent(bool aPass=true)
Definition: tool_event.h:256
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
Model changes (required full reload)
Definition: tool_base.h:82
static TOOL_ACTION doDelete
Definition: actions.h:75
int GetOrientation() const
Definition: lib_pin.h:125
TOOL_ACTIONS Action() const
Returns more specific information about the type of an event.
Definition: tool_event.h:250
bool IsClick(int aButtonMask=BUT_ANY) const
Definition: tool_event.cpp:178
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
int Main(const TOOL_EVENT &aEvent)
Function Main()
static TOOL_ACTION symbolMoveActivate
Definition: ee_actions.h:112
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
TOOL_MENU & GetToolMenu()
bool IsMotion() const
Definition: tool_event.h:306
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:141
void setTransitions() override
Sets up handlers for various events.
TOOL_EVENT_CATEGORY Category() const
Returns the category (eg. mouse/keyboard/action) of an event..
Definition: tool_event.h:247
virtual void SetCursorPosition(const VECTOR2D &aPosition, bool aWarpView=true, bool aTriggeredByArrows=false, long aArrowCommand=0)=0
Moves cursor to the requested position expressed in world coordinates.
VECTOR2I m_anchorPos
Definition: lib_move_tool.h:70
virtual wxPoint GetPosition() const
Definition: eda_item.h:325
static bool IdleSelection(const SELECTION &aSelection)
Tests if all selected items are not being edited.
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
void SetCurrentCursor(KICURSOR cursor)
Function SetCurrentCursor Set the current cursor shape for this panel.
static const TOOL_EVENT SelectedItemsModified
Definition: actions.h:218
The base class for drawable items used by schematic library components.
Definition: lib_item.h:62
bool IsAction(const TOOL_ACTION *aAction) const
Function IsAction() Tests if the event contains an action issued upon activation of the given TOOL_AC...
Definition: tool_event.cpp:67
bool IsNew() const
Definition: eda_item.h:187
bool Init() override
Function Init() Init() is called once upon a registration of the tool.
Definition: ee_tool_base.h:69
EE_SELECTION & GetSelection()
Function GetSelection()
EE_SELECTION & RequestSelection(const KICAD_T *aFilterList=EE_COLLECTOR::AllItems)
Function RequestSelection()
virtual void WarpCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
Function WarpCursor() If enabled (.
bool IsDrag(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:296
void SetFlags(STATUS_FLAGS aMask)
Definition: eda_item.h:220
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
void saveCopyInUndoList(EDA_ITEM *aItem, UNDO_REDO aType, bool aAppend=false)
Similar to m_frame->SaveCopyInUndoList(), but handles items that are owned by their parents.
Definition: ee_tool_base.h:138
STATUS_FLAGS GetEditFlags() const
Definition: eda_item.h:225
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
virtual void PopTool(const std::string &actionName)
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
TOOL_EVENT.
Definition: tool_event.h:171
Define a library symbol object.
VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (such a...
EE_SELECTION_TOOL * m_selectionTool
Definition: ee_tool_base.h:181
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
static const TOOL_EVENT SelectedItemsMoved
Definition: actions.h:221
static TOOL_ACTION clearSelection
Clears the current selection.
Definition: ee_actions.h:56
bool IsMouseUp(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:301
static VECTOR2D mapCoords(const wxPoint &aCoord)
#define IS_MOVED
Item being moved.
Definition: eda_item.h:105
int GetConvert() const
Definition: lib_item.h:299
bool IsCancelInteractive()
Function IsCancelInteractive()
Definition: tool_event.cpp:190
LIB_PART * GetCurPart()
Return the current part being edited or NULL if none selected.
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:120
void moveItem(EDA_ITEM *aItem, VECTOR2I aDelta)
void updateItem(EDA_ITEM *aItem, bool aUpdateRTree) const
Similar to getView()->Update(), but handles items that are redrawn by their parents and updating the ...
Definition: ee_tool_base.h:107
wxPoint GetPosition() const override
Definition: lib_pin.h:258
virtual unsigned int GetSize() const override
Function GetSize() Returns the number of stored items.
Definition: selection.h:99
LIB_PIN * GetNextPin(LIB_PIN *aItem=NULL)
Return the next pin object from the draw list.
#define IS_PASTED
Modifier on IS_NEW which indicates it came from clipboard.
Definition: eda_item.h:119
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:463
bool IsActivate() const
Definition: tool_event.h:321
int AddItemToSel(const TOOL_EVENT &aEvent)
bool IsAlias() const
EDA_ITEM is a base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:148
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
bool GetMoveWarpsCursor() const
Indicates that a move operation should warp the mouse pointer to the origin of the move object.
Definition: tools_holder.h:159
void Activate()
Function Activate() Runs the tool.
static TOOL_ACTION move
Definition: ee_actions.h:114
EE_TOOL_BASE.
Definition: ee_tool_base.h:50
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:42
void PostEvent(const TOOL_EVENT &aEvent)
Puts an event to the event queue to be processed at the end of event processing cycle.
Definition: tool_manager.h:274
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Adds a menu entry to run a TOOL_ACTION on selected items.
bool PlacePin(LIB_PIN *aPin)
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
static TOOL_ACTION duplicate
Definition: actions.h:74
static TOOL_ACTION refreshPreview
Definition: actions.h:109
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
EDA_ITEM * Front() const
Definition: selection.h:201
KICAD_T Type() const
Function Type()
Definition: eda_item.h:181
VECTOR2I m_moveOffset
Used for chaining commands
Definition: lib_move_tool.h:65