KiCad PCB EDA Suite
position_relative_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) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <functional>
25 #include <memory>
26 using namespace std::placeholders;
27 
28 #include "position_relative_tool.h"
29 #include "pcb_actions.h"
30 #include "pcb_selection_tool.h"
31 #include "edit_tool.h"
32 #include "pcb_picker_tool.h"
34 #include <status_popup.h>
35 #include <board_commit.h>
36 #include <bitmaps.h>
37 #include <confirm.h>
38 #include <collectors.h>
39 #include <pad.h>
40 
41 
43  PCB_TOOL_BASE( "pcbnew.PositionRelative" ),
44  m_dialog( nullptr ),
45  m_selectionTool( nullptr ),
46  m_anchor_item( nullptr )
47 {
48 }
49 
50 
52 {
53  if( aReason != RUN )
54  m_commit = std::make_unique<BOARD_COMMIT>( this );
55 }
56 
57 
59 {
60  // Find the selection tool, so they can cooperate
62 
63  return m_selectionTool != nullptr;
64 }
65 
66 
67 // TODO: Clean up this global once TOOL_EVENT supports std::functions as parameters
69 
70 
72 {
73  PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
74 
76 
78  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
79  {
80  std::set<BOARD_ITEM*> to_add;
81 
82  // Iterate from the back so we don't have to worry about removals.
83  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
84  {
85  BOARD_ITEM* item = aCollector[i];
86 
87  if( item->Type() == PCB_MARKER_T )
88  aCollector.Remove( item );
89 
91  if( !sTool->IsFootprintEditor() && item->Type() == PCB_PAD_T && item->IsLocked()
92  && !item->GetParent()->IsLocked() )
93  {
94  if( !aCollector.HasItem( item->GetParent() ) )
95  to_add.insert( item->GetParent() );
96 
98 
99  aCollector.Remove( item );
100  }
101  }
102 
103  for( BOARD_ITEM* item : to_add )
104  aCollector.Append( item );
105  },
106  !m_isFootprintEditor /* prompt user regarding locked items */ );
107 
108  if( selection.Empty() )
109  return 0;
110 
112 
114  m_selectionAnchor = static_cast<PAD*>( g_PositionRelativePadAnchor )->GetPosition();
115  else
117 
118  // The dialog is not modal and not deleted between calls.
119  // It means some options can have changed since the last call.
120  // Therefore we need to rebuild it in case UI units have changed since the last call.
121  if( m_dialog && m_dialog->GetUserUnits() != editFrame->GetUserUnits() )
122  {
123  m_dialog->Destroy();
124  m_dialog = nullptr;
125  }
126 
127  if( !m_dialog )
129 
130  m_dialog->Show( true );
131 
132  return 0;
133 }
134 
135 
137  const wxPoint& aTranslation )
138 {
139  wxPoint aggregateTranslation = aPosAnchor + aTranslation - GetSelectionAnchorPosition();
140 
141  for( auto item : m_selection )
142  {
143  // Don't move a pad by itself unless editing the footprint
144  if( item->Type() == PCB_PAD_T && frame()->IsType( FRAME_PCB_EDITOR ) )
145  item = item->GetParent();
146 
147  m_commit->Modify( item );
148  static_cast<BOARD_ITEM*>( item )->Move( aggregateTranslation );
149  }
150 
151  m_commit->Push( _( "Position Relative" ) );
152 
153  if( m_selection.IsHover() )
155 
157 
158  canvas()->Refresh();
159  return 0;
160 }
161 
162 
164 {
165  std::string tool = "pcbnew.PositionRelative.selectReferenceItem";
167  STATUS_TEXT_POPUP statusPopup( frame() );
168  bool done = false;
169 
170  Activate();
171 
172  statusPopup.SetText( _( "Click on reference item..." ) );
173 
174  picker->SetClickHandler(
175  [&]( const VECTOR2D& aPoint ) -> bool
176  {
179  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector,
180  PCB_SELECTION_TOOL* sTool )
181  {
182  } );
183 
184  if( sel.Empty() )
185  return true; // still looking for an item
186 
187  m_anchor_item = sel.Front();
188  statusPopup.Hide();
189 
190  if( m_dialog )
191  m_dialog->UpdateAnchor( sel.Front() );
192 
193  return false; // got our item; don't need any more
194  } );
195 
196  picker->SetMotionHandler(
197  [&] ( const VECTOR2D& aPos )
198  {
199  statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
200  } );
201 
202  picker->SetCancelHandler(
203  [&]()
204  {
205  statusPopup.Hide();
206 
207  if( m_dialog )
209  } );
210 
211  picker->SetFinalizeHandler(
212  [&]( const int& aFinalState )
213  {
214  done = true;
215  } );
216 
217  statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
218  statusPopup.Popup();
219 
220  m_toolMgr->RunAction( ACTIONS::pickerTool, true, &tool );
221 
222  while( !done )
223  {
224  // Pass events unless we receive a null event, then we must shut down
225  if( TOOL_EVENT* evt = Wait() )
226  evt->SetPassEvent();
227  else
228  break;
229  }
230 
231  return 0;
232 }
233 
234 
236 {
240 }
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:59
bool Init() override
Init() is called once upon a registration of the tool.
std::unique_ptr< BOARD_COMMIT > m_commit
bool IsHover() const
Definition: selection.h:74
wxPoint GetSelectionAnchorPosition() const
Return the position of the selected item(s)
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
int PositionRelative(const TOOL_EVENT &aEvent)
Invoke a dialog box to allow positioning of the item relative to another by an exact amount.
This file is part of the common library.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
Extension of STATUS_POPUP for displaying a single line text.
Definition: status_popup.h:79
Tool is invoked after being inactive.
Definition: tool_base.h:79
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:143
static TOOL_ACTION selectpositionRelativeItem
Selection of anchor item for position relative tool.
Definition: pcb_actions.h:235
class PAD, a pad in a footprint
Definition: typeinfo.h:89
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:102
virtual wxPoint GetPosition() const
Definition: eda_item.h:252
virtual bool IsLocked() const
Definition: board_item.cpp:64
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
void Remove(int aIndex)
Remove the item at aIndex (first position is 0).
Definition: collector.h:110
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:204
static TOOL_ACTION pickerTool
Definition: actions.h:155
void Append(EDA_ITEM *item)
Add an item to the end of the list.
Definition: collector.h:100
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:119
PCB_BASE_EDIT_FRAME * frame() const
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:82
DIALOG_POSITION_RELATIVE * m_dialog
const PCB_SELECTION & selection() const
int SelectPositionRelativeItem(const TOOL_EVENT &aEvent)
Invoke the picker tool to select the item to which the previous selection will be placed relative to.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
Generic, UI-independent tool event.
Definition: tool_event.h:152
void SetMotionHandler(MOTION_HANDLER aHandler)
Set a handler for mouse motion.
Definition: picker_tool.h:82
bool HasItem(const EDA_ITEM *aItem) const
Tests if aItem has already been collected.
Definition: collector.h:196
#define _(s)
EDA_ITEM * GetTopLeftItem(bool aFootprintsOnly=false) const override
bool m_isFootprintEditor
int RelativeItemSelectionMove(const wxPoint &anchor, const wxPoint &translation)
Position the m_position_relative_selection selection relative to anchor position using the given tran...
bool Show(bool show) override
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:98
Generic tool for picking an item.
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:71
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:98
PCB_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, bool aConfirmLockedItems=false)
Return the current selection set, filtered according to aFlags and aClientFilter.
bool IsType(FRAME_T aType) const
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:240
BOARD_ITEM * g_PositionRelativePadAnchor
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
The selection tool: currently supports:
bool IsFootprintEditor() const
static TOOL_ACTION positionRelative
Activation of the position relative tool.
Definition: pcb_actions.h:232
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
void Activate()
Run the tool.
PCB_DRAW_PANEL_GAL * canvas() const
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:135
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCB_SELECTION_TOOL * m_selectionTool
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
void SetCancelHandler(CANCEL_HANDLER aHandler)
Set a handler for cancel events (ESC or context-menu Cancel).
Definition: picker_tool.h:91
EDA_ITEM * Front() const
Definition: selection.h:145
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113