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 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 
39 
41  PCB_TOOL_BASE( "pcbnew.PositionRelative" ),
42  m_dialog( NULL ),
43  m_selectionTool( NULL ),
44  m_anchor_item( NULL )
45 {
46 }
47 
48 
50 {
51  if( aReason != RUN )
52  m_commit = std::make_unique<BOARD_COMMIT>( this );
53 }
54 
55 
57 {
58  // Find the selection tool, so they can cooperate
60 
61  return m_selectionTool != nullptr;
62 }
63 
64 
65 // TODO: Clean up this global once TOOL_EVENT supports std::functions as parameters
67 
68 
70 {
71  PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
72 
74 
76  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
77  {
78  std::set<BOARD_ITEM*> to_add;
79 
80  // Iterate from the back so we don't have to worry about removals.
81  for( int i = aCollector.GetCount() - 1; i >= 0; --i )
82  {
83  BOARD_ITEM* item = aCollector[i];
84 
85  if( item->Type() == PCB_MARKER_T )
86  aCollector.Remove( item );
87 
89  if( !sTool->IsFootprintEditor() && item->Type() == PCB_PAD_T && item->IsLocked()
90  && !item->GetParent()->IsLocked() )
91  {
92  if( !aCollector.HasItem( item->GetParent() ) )
93  to_add.insert( item->GetParent() );
94 
96 
97  aCollector.Remove( item );
98  }
99  }
100 
101  for( BOARD_ITEM* item : to_add )
102  aCollector.Append( item );
103  },
104  !m_isFootprintEditor /* prompt user regarding locked items */ );
105 
106  if( selection.Empty() )
107  return 0;
108 
110 
112  m_selectionAnchor = static_cast<PAD*>( g_PositionRelativePadAnchor )->GetPosition();
113  else
115 
116  // The dialog is not modal and not deleted between calls.
117  // It means some options can have changed since the last call.
118  // Therefore we need to rebuild it in case UI units have changed since the last call.
119  if( m_dialog && m_dialog->GetUserUnits() != editFrame->GetUserUnits() )
120  {
121  m_dialog->Destroy();
122  m_dialog = nullptr;
123  }
124 
125  if( !m_dialog )
127 
128  m_dialog->Show( true );
129 
130  return 0;
131 }
132 
133 
134 int POSITION_RELATIVE_TOOL::RelativeItemSelectionMove( wxPoint aPosAnchor, wxPoint aTranslation )
135 {
136  wxPoint aggregateTranslation = aPosAnchor + aTranslation - GetSelectionAnchorPosition();
137 
138  for( auto item : m_selection )
139  {
140  // Don't move a pad by itself unless editing the footprint
141  if( item->Type() == PCB_PAD_T && frame()->IsType( FRAME_PCB_EDITOR ) )
142  item = item->GetParent();
143 
144  m_commit->Modify( item );
145  static_cast<BOARD_ITEM*>( item )->Move( aggregateTranslation );
146  }
147 
148  m_commit->Push( _( "Position Relative" ) );
149 
150  if( m_selection.IsHover() )
152 
154 
155  canvas()->Refresh();
156  return 0;
157 }
158 
159 
161 {
162  std::string tool = "pcbnew.PositionRelative.selectReferenceItem";
164  STATUS_TEXT_POPUP statusPopup( frame() );
165  bool done = false;
166 
167  Activate();
168 
169  statusPopup.SetText( _( "Click on reference item..." ) );
170 
171  picker->SetClickHandler(
172  [&]( const VECTOR2D& aPoint ) -> bool
173  {
176  []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector,
177  PCB_SELECTION_TOOL* sTool )
178  {
179  } );
180 
181  if( sel.Empty() )
182  return true; // still looking for an item
183 
184  m_anchor_item = sel.Front();
185  statusPopup.Hide();
186 
187  if( m_dialog )
188  m_dialog->UpdateAnchor( sel.Front() );
189 
190  return false; // got our item; don't need any more
191  } );
192 
193  picker->SetMotionHandler(
194  [&] ( const VECTOR2D& aPos )
195  {
196  statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
197  } );
198 
199  picker->SetCancelHandler(
200  [&]()
201  {
202  statusPopup.Hide();
203 
204  if( m_dialog )
206  } );
207 
208  picker->SetFinalizeHandler(
209  [&]( const int& aFinalState )
210  {
211  done = true;
212  } );
213 
214  statusPopup.Move( wxGetMousePosition() + wxPoint( 20, -50 ) );
215  statusPopup.Popup();
216 
217  m_toolMgr->RunAction( ACTIONS::pickerTool, true, &tool );
218 
219  while( !done )
220  {
221  // Pass events unless we receive a null event, then we must shut down
222  if( TOOL_EVENT* evt = Wait() )
223  evt->SetPassEvent();
224  else
225  break;
226  }
227 
228  return 0;
229 }
230 
231 
233 {
237 }
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:63
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:72
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:82
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:80
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:215
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:141
static TOOL_ACTION selectpositionRelativeItem
Selection of anchor item for position relative tool.
Definition: pcb_actions.h:242
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:302
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:115
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:206
static TOOL_ACTION pickerTool
Definition: actions.h:158
void Append(EDA_ITEM *item)
Add an item to the end of the list.
Definition: collector.h:105
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:120
PCB_BASE_EDIT_FRAME * frame() const
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:87
DIALOG_POSITION_RELATIVE * m_dialog
const PCB_SELECTION & selection() const
#define NULL
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:173
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:203
EDA_ITEM * GetTopLeftItem(bool aFootprintsOnly=false) const override
bool m_isFootprintEditor
bool Show(bool show) override
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:122
Generic tool for picking an item.
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:71
int RelativeItemSelectionMove(wxPoint anchor, wxPoint translation)
Position the m_position_relative_selection selection relative to anchor position using the given tran...
virtual bool IsLocked() const
Definition: board_item.h:249
class MARKER_PCB, 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
#define _(s)
Definition: 3d_actions.cpp:33
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:241
BOARD_ITEM * g_PositionRelativePadAnchor
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:239
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
void Activate()
Run the tool.
PCB_DRAW_PANEL_GAL * canvas() const
BOARD_ITEM_CONTAINER * GetParent() const
Definition: board_item.h:168
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:203
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:163