KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2022 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>
26using namespace std::placeholders;
27
28#include <kiplatform/ui.h>
30#include <tools/pcb_actions.h>
34#include <status_popup.h>
35#include <board_commit.h>
36#include <confirm.h>
37#include <collectors.h>
38#include <pad.h>
39#include <footprint.h>
40#include <pcb_group.h>
41
42
44 PCB_TOOL_BASE( "pcbnew.PositionRelative" ),
45 m_dialog( nullptr ),
46 m_selectionTool( nullptr ),
47 m_anchor_item( nullptr )
48{
49}
50
51
53{
54 if( aReason != RUN )
55 m_commit = std::make_unique<BOARD_COMMIT>( this );
56}
57
58
60{
61 // Find the selection tool, so they can cooperate
63
64 return m_selectionTool != nullptr;
65}
66
67
69{
70 PCB_BASE_FRAME* editFrame = getEditFrame<PCB_BASE_FRAME>();
71
73 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
74 {
75 sTool->FilterCollectorForHierarchy( aCollector, true );
76 sTool->FilterCollectorForMarkers( aCollector );
77 },
78 !m_isFootprintEditor /* prompt user regarding locked items */ );
79
80 if( selection.Empty() )
81 return 0;
82
84
85 // We prefer footprints, then pads, then anything else here.
86 EDA_ITEM* preferredItem = m_selection.GetTopLeftItem( true );
87
88 if( !preferredItem && m_selection.HasType( PCB_PAD_T ) )
89 {
90 PCB_SELECTION padsOnly = m_selection;
91 std::deque<EDA_ITEM*>& items = padsOnly.Items();
92 items.erase( std::remove_if( items.begin(), items.end(),
93 []( const EDA_ITEM* aItem )
94 {
95 return aItem->Type() != PCB_PAD_T;
96 } ), items.end() );
97
98 preferredItem = padsOnly.GetTopLeftItem();
99 }
100
101 if( preferredItem )
102 m_selectionAnchor = preferredItem->GetPosition();
103 else
105
106 // The dialog is not modal and not deleted between calls.
107 // It means some options can have changed since the last call.
108 // Therefore we need to rebuild it in case UI units have changed since the last call.
109 if( m_dialog && m_dialog->GetUserUnits() != editFrame->GetUserUnits() )
110 {
111 m_dialog->Destroy();
112 m_dialog = nullptr;
113 }
114
115 if( !m_dialog )
116 m_dialog = new DIALOG_POSITION_RELATIVE( editFrame );
117
118 m_dialog->Show( true );
119
120 return 0;
121}
122
123
125 const VECTOR2I& aTranslation )
126{
127 VECTOR2I aggregateTranslation = aPosAnchor + aTranslation - GetSelectionAnchorPosition();
128
129 for( EDA_ITEM* item : m_selection )
130 {
131 if( BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item ) )
132 {
133 // Don't move a pad by itself unless editing the footprint
134 if( boardItem->Type() == PCB_PAD_T
135 && !frame()->GetPcbNewSettings()->m_AllowFreePads
136 && frame()->IsType( FRAME_PCB_EDITOR ) )
137 {
138 boardItem = boardItem->GetParent();
139 }
140
141 m_commit->Modify( boardItem );
142 boardItem->Move( aggregateTranslation );
143 }
144 }
145
146 m_commit->Push( _( "Position Relative" ) );
147
148 if( m_selection.IsHover() )
150
152
153 canvas()->Refresh();
154 return 0;
155}
156
157
159{
161 STATUS_TEXT_POPUP statusPopup( frame() );
162 bool done = false;
163
164 Activate();
165
166 statusPopup.SetText( _( "Click on reference item..." ) );
167
168 picker->SetClickHandler(
169 [&]( const VECTOR2D& aPoint ) -> bool
170 {
173 []( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector,
174 PCB_SELECTION_TOOL* sTool )
175 {
176 } );
177
178 if( sel.Empty() )
179 return true; // still looking for an item
180
181 m_anchor_item = sel.Front();
182 statusPopup.Hide();
183
184 if( m_dialog )
185 m_dialog->UpdateAnchor( sel.Front() );
186
187 return false; // got our item; don't need any more
188 } );
189
190 picker->SetMotionHandler(
191 [&] ( const VECTOR2D& aPos )
192 {
193 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) );
194 } );
195
196 picker->SetCancelHandler(
197 [&]()
198 {
199 statusPopup.Hide();
200
201 if( m_dialog )
203 } );
204
205 picker->SetFinalizeHandler(
206 [&]( const int& aFinalState )
207 {
208 done = true;
209 } );
210
211 statusPopup.Move( KIPLATFORM::UI::GetMousePosition() + wxPoint( 20, -50 ) );
212 statusPopup.Popup();
213 canvas()->SetStatusPopup( statusPopup.GetPanel() );
214
216
217 while( !done )
218 {
219 // Pass events unless we receive a null event, then we must shut down
220 if( TOOL_EVENT* evt = Wait() )
221 evt->SetPassEvent();
222 else
223 break;
224 }
225
226 canvas()->SetStatusPopup( nullptr );
227
228 return 0;
229}
230
231
233{
237}
static TOOL_ACTION pickerTool
Definition: actions.h:189
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
bool Show(bool show) override
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:122
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
void SetStatusPopup(wxWindow *aPopup)
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:239
static const TOOL_EVENT SelectedItemsModified
Selected items were moved, this can be very high frequency on the canvas, use with care.
Definition: actions.h:264
Used when the right click button is pressed, or when the select tool is in effect.
Definition: collectors.h:206
static TOOL_ACTION selectionClear
Clear the current selection.
Definition: pcb_actions.h:68
static TOOL_ACTION positionRelative
Activation of the position relative tool.
Definition: pcb_actions.h:314
static TOOL_ACTION selectpositionRelativeItem
Selection of anchor item for position relative tool.
Definition: pcb_actions.h:317
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
Generic tool for picking an item.
The selection tool: currently supports:
void FilterCollectorForMarkers(GENERAL_COLLECTOR &aCollector) const
Drop any PCB_MARKERs from the collector.
PCB_SELECTION & RequestSelection(CLIENT_SELECTION_FILTER aClientFilter, bool aConfirmLockedItems=false)
Return the current selection, filtered according to aClientFilter.
void FilterCollectorForHierarchy(GENERAL_COLLECTOR &aCollector, bool aMultiselect) const
In general we don't want to select both a parent and any of it's children.
EDA_ITEM * GetTopLeftItem(bool aFootprintsOnly=false) const override
PCB_BASE_EDIT_FRAME * frame() const
PCB_DRAW_PANEL_GAL * canvas() const
bool m_isFootprintEditor
const PCB_SELECTION & selection() const
void SetMotionHandler(MOTION_HANDLER aHandler)
Set a handler for mouse motion.
Definition: picker_tool.h:83
void SetClickHandler(CLICK_HANDLER aHandler)
Set a handler for mouse click event.
Definition: picker_tool.h:72
void SetCancelHandler(CANCEL_HANDLER aHandler)
Set a handler for cancel events (ESC or context-menu Cancel).
Definition: picker_tool.h:92
void SetFinalizeHandler(FINALIZE_HANDLER aHandler)
Set a handler for the finalize event.
Definition: picker_tool.h:103
int RelativeItemSelectionMove(const VECTOR2I &anchor, const VECTOR2I &translation)
Position the m_position_relative_selection selection relative to anchor position using the given tran...
int PositionRelative(const TOOL_EVENT &aEvent)
Invoke a dialog box to allow positioning of the item relative to another by an exact amount.
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
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 Init() override
Init() is called once upon a registration of the tool.
DIALOG_POSITION_RELATIVE * m_dialog
std::unique_ptr< BOARD_COMMIT > m_commit
VECTOR2I GetSelectionAnchorPosition() const
Return the position of the selected item(s)
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
PCB_SELECTION_TOOL * m_selectionTool
bool IsHover() const
Definition: selection.h:83
EDA_ITEM * Front() const
Definition: selection.h:208
bool HasType(KICAD_T aType) const
Checks if there is at least one item of requested kind.
Definition: selection.cpp:144
std::deque< EDA_ITEM * > & Items()
Definition: selection.h:213
bool Empty() const
Checks if there is anything selected.
Definition: selection.h:109
Extension of STATUS_POPUP for displaying a single line text.
Definition: status_popup.h:84
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:216
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
@ RUN
Tool is invoked after being inactive.
Definition: tool_base.h:79
Generic, UI-independent tool event.
Definition: tool_event.h:167
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).
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.
void Activate()
Run the tool.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagate an event to tools that requested events of matching type(s).
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:145
EDA_UNITS GetUserUnits() const
This file is part of the common library.
#define _(s)
@ FRAME_PCB_EDITOR
Definition: frame_type.h:42
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition: gtk/ui.cpp:601
Class to handle a set of BOARD_ITEMs.
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87