KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dialog_position_relative.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 The 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
25
26#include <math/util.h> // for KiROUND
27#include <tools/pcb_actions.h>
29#include <pcb_edit_frame.h>
33#include <trigo.h>
34
35// initialise statics
37
38
41 m_toolMgr( aParent->GetToolManager() ),
42 m_xOffset( aParent, m_xLabel, m_xEntry, m_xUnit ),
43 m_yOffset( aParent, m_yLabel, m_yEntry, m_yUnit ),
44 m_stateX( 0.0 ),
45 m_stateY( 0.0 ),
46 m_stateRadius( 0.0 )
47{
48 // We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
49 // implementation on MSW
50 m_tabOrder = {
55 };
56
57 // Configure display origin transforms
60
62
64
66}
67
68
70{
71 updateDialogControls( m_polarCoords->IsChecked() );
72 return DIALOG_POSITION_RELATIVE_BASE::TransferDataToWindow();
73}
74
75
76void DIALOG_POSITION_RELATIVE::ToPolarDeg( double x, double y, double& r, EDA_ANGLE& q )
77{
78 // convert to polar coordinates
79 r = hypot( x, y );
80
81 q = ( r != 0) ? EDA_ANGLE( VECTOR2D( x, y ) ) : ANGLE_0;
82}
83
84
86{
87 if( polar )
88 {
89 const double r = m_xOffset.GetDoubleValue();
90 const EDA_ANGLE q = m_yOffset.GetAngleValue();
91
92 val.x = KiROUND( r * q.Cos() );
93 val.y = KiROUND( r * q.Sin() );
94 }
95 else
96 {
97 // direct read
98 val.x = KiROUND( m_xOffset.GetDoubleValue() );
99 val.y = KiROUND( m_yOffset.GetDoubleValue() );
100 }
101
102 // no validation to do here, but in future, you could return false here
103 return true;
104}
105
106
107void DIALOG_POSITION_RELATIVE::OnPolarChanged( wxCommandEvent& event )
108{
109 bool newPolar = m_polarCoords->IsChecked();
110 double xOffset = m_xOffset.GetDoubleValue();
111 double yOffset = m_yOffset.GetDoubleValue();
112 updateDialogControls( newPolar );
113
114 if( newPolar )
115 {
116 if( xOffset != m_stateX || yOffset != m_stateY )
117 {
118 m_stateX = xOffset;
119 m_stateY = yOffset;
121
122 m_xOffset.SetDoubleValue( m_stateRadius );
123 m_stateRadius = m_xOffset.GetDoubleValue();
124 m_yOffset.SetAngleValue( m_stateTheta );
125 m_stateTheta = m_yOffset.GetAngleValue();
126 }
127 else
128 {
129 m_xOffset.SetDoubleValue( m_stateRadius );
130 m_yOffset.SetAngleValue( m_stateTheta );
131 }
132 }
133 else
134 {
135 if( xOffset != m_stateRadius || yOffset != m_stateTheta.AsDegrees() )
136 {
137 m_stateRadius = xOffset;
138 m_stateTheta = EDA_ANGLE( yOffset, DEGREES_T );
141
142 m_xOffset.SetDoubleValue( m_stateX );
143 m_stateX = m_xOffset.GetDoubleValue();
144 m_yOffset.SetDoubleValue( m_stateY );
145 m_stateY = m_yOffset.GetDoubleValue();
146 }
147 else
148 {
149 m_xOffset.SetDoubleValue( m_stateX );
150 m_yOffset.SetDoubleValue( m_stateY );
151 }
152 }
153}
154
155
157{
158 if( aPolar )
159 {
160 m_xOffset.SetLabel( _( "Distance:" ) ); // Polar radius
161 m_yOffset.SetLabel( _( "Angle:" ) ); // Polar theta or angle
162 m_yOffset.SetUnits( EDA_UNITS::DEGREES );
163 m_clearX->SetToolTip( _( "Reset to the current distance from the reference position." ) );
164 m_clearY->SetToolTip( _( "Reset to the current angle from the reference position." ) );
165 }
166 else
167 {
168 m_xOffset.SetLabel( _( "Offset X:" ) );
169 m_yOffset.SetLabel( _( "Offset Y:" ) );
170 m_yOffset.SetUnits( GetUserUnits() );
171 m_clearX->SetToolTip( _( "Reset to the current X offset from the reference position." ) );
172 m_clearY->SetToolTip( _( "Reset to the current Y offset from the reference position." ) );
173 }
174}
175
176
177void DIALOG_POSITION_RELATIVE::OnClear( wxCommandEvent& event )
178{
179 wxObject* obj = event.GetEventObject();
181 wxASSERT( posrelTool );
182
183 VECTOR2I offset = posrelTool->GetSelectionAnchorPosition() - getAnchorPos();
184 double r;
185 EDA_ANGLE q;
186 ToPolarDeg( offset.x, offset.y, r, q );
187
188 if( obj == m_clearX )
189 {
190 m_stateX = offset.x;
191 m_xOffset.SetDoubleValue( r );
192 m_stateRadius = m_xOffset.GetDoubleValue();
193
194 if( m_polarCoords->IsChecked() )
195 m_xOffset.SetDoubleValue( m_stateRadius );
196 else
197 m_xOffset.SetValue( m_stateX );
198 }
199 else if( obj == m_clearY )
200 {
201 m_stateY = offset.y;
202 m_yOffset.SetAngleValue( q );
203 m_stateTheta = m_yOffset.GetAngleValue();
204
205 if( m_polarCoords->IsChecked() )
206 m_yOffset.SetAngleValue( m_stateTheta );
207 else
208 m_yOffset.SetValue( m_stateY );
209 }
210}
211
212
214{
215 event.Skip();
216
217 PCB_PICKER_TOOL* pickerTool = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
218 wxCHECK( pickerTool, /* void */ );
219
220 Hide();
221
223 PCB_PICKER_TOOL::INTERACTIVE_PARAMS{ this, _( "Select reference item..." ) } );
224}
225
226
228{
229 event.Skip();
230
231 PCB_PICKER_TOOL* pickerTool = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
232 wxCHECK( pickerTool, /* void */ );
233
234 // Hide, but do not close, the dialog
235 Hide();
236
238 PCB_PICKER_TOOL::INTERACTIVE_PARAMS { this, _( "Select reference point..." ) } );
239}
240
241
243{
244 switch( s_anchorType )
245 {
247 m_referenceInfo->SetLabel( _( "Reference location: grid origin" ) );
248 break;
249
251 m_referenceInfo->SetLabel( _( "Reference location: local coordinates origin" ) );
252 break;
253
254 case ANCHOR_ITEM:
255 {
256 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUserUnits() );
257 wxString msg = _( "<none selected>" );
258
259 if( aItem )
260 msg = aItem->GetItemDescription( &unitsProvider, true );
261
262 m_referenceInfo->SetLabel( wxString::Format( _( "Reference item: %s" ), msg ) );
263 break;
264 }
265
266 case ANCHOR_POINT:
267 m_referenceInfo->SetLabel( wxString::Format( _( "Reference location: selected point (%s, %s)" ),
268 m_parentFrame->MessageTextFromValue( m_anchorItemPosition.x ),
269 m_parentFrame->MessageTextFromValue( m_anchorItemPosition.y ) ) );
270 break;
271 }
272}
273
274
276{
277 switch( s_anchorType )
278 {
280 return static_cast<BOARD*>( m_toolMgr->GetModel() )->GetDesignSettings().GetGridOrigin();
281
283 return static_cast<PCB_BASE_FRAME*>( m_toolMgr->GetToolHolder() )->GetScreen()->m_LocalOrigin;
284
285 case ANCHOR_ITEM:
286 case ANCHOR_POINT:
288 }
289
290 // Needed by some compilers to avoid a fatal compil error (no return value).
292}
293
294
296{
298 updateAnchorInfo( nullptr );
299}
300
301
303{
305 updateAnchorInfo( nullptr );
306}
307
308
310{
311 const BOARD_ITEM* item = nullptr;
312
313 if( aItem && aItem->IsBOARD_ITEM() )
314 item = static_cast<const BOARD_ITEM*>( aItem );
315
317 updateAnchorInfo( item );
318
319 if( item )
321
322 Show( true );
323 Raise();
324 SetFocus();
325}
326
327
328void DIALOG_POSITION_RELATIVE::UpdatePickedPoint( const std::optional<VECTOR2I>& aPoint )
329{
331
332 if( aPoint )
333 m_anchorItemPosition = *aPoint;
334
335 updateAnchorInfo( nullptr );
336
337 Show( true );
338 Raise();
339 SetFocus();
340}
341
342
343void DIALOG_POSITION_RELATIVE::OnOkClick( wxCommandEvent& event )
344{
345 // for the output, we only deliver a Cartesian vector
346 VECTOR2I translation;
347
348 if( getTranslationInIU( translation, m_polarCoords->IsChecked() ) )
349 {
351
352 posrelTool->RelativeItemSelectionMove( getAnchorPos(), translation );
353
354 event.Skip();
355 }
356}
357
358
360{
361 wxTextCtrl* obj = static_cast<wxTextCtrl*>( event.GetEventObject() );
362
363 if( obj->GetValue().IsEmpty() )
364 obj->SetValue( "0" );
365
366 event.Skip();
367}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:125
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
VECTOR2D m_LocalOrigin
Relative Screen cursor coordinate (on grid) in user units.
Definition base_screen.h:90
const VECTOR2I & GetGridOrigin() const
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1101
DIALOG_POSITION_RELATIVE_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &title=_("Position Relative To Reference Item"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
bool getTranslationInIU(VECTOR2I &val, bool polar)
Get the (Cartesian) translation described by the text entries.
void OnUseGridOriginClick(wxCommandEvent &event) override
void OnPolarChanged(wxCommandEvent &event) override
void OnOkClick(wxCommandEvent &event) override
void OnClear(wxCommandEvent &event) override
void OnSelectItemClick(wxCommandEvent &event) override
void UpdatePickedPoint(const std::optional< VECTOR2I > &aPoint) override
void OnSelectPointClick(wxCommandEvent &event) override
void UpdatePickedItem(const EDA_ITEM *aItem) override
void OnTextFocusLost(wxFocusEvent &event) override
Reset a text field to be 0 if it was exited while blank.
void OnUseUserOriginClick(wxCommandEvent &event) override
ANCHOR_TYPE
Persistent dialog options.
void ToPolarDeg(double x, double y, double &r, EDA_ANGLE &q)
Convert a given Cartesian point into a polar representation.
void updateAnchorInfo(const BOARD_ITEM *aItem)
DIALOG_POSITION_RELATIVE(PCB_BASE_FRAME *aParent)
std::vector< wxWindow * > m_tabOrder
bool Show(bool show) override
void SetInitialFocus(wxWindow *aWindow)
Sets the window (usually a wxTextCtrl) that should be focused when the dialog is shown.
Definition dialog_shim.h:82
void SetupStandardButtons(std::map< int, wxString > aLabels={})
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
EDA_BASE_FRAME * m_parentFrame
EDA_UNITS GetUserUnits() const
double Sin() const
Definition eda_angle.h:178
double Cos() const
Definition eda_angle.h:197
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:100
virtual VECTOR2I GetPosition() const
Definition eda_item.h:279
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition eda_item.cpp:154
bool IsBOARD_ITEM() const
Definition view_item.h:102
static TOOL_ACTION selectPointInteractively
static TOOL_ACTION selectItemInteractively
Selection of reference points/items.
Base PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
Generic tool for picking an item.
The interactive edit tool.
int RelativeItemSelectionMove(const VECTOR2I &anchor, const VECTOR2I &translation)
Position the m_position_relative_selection selection relative to anchor position using the given tran...
VECTOR2I GetSelectionAnchorPosition() const
Return the position of the selected item(s)
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
@ DEGREES_T
Definition eda_angle.h:31
Functions for manipulating tab traversal in forms and dialogs.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
VECTOR2< double > VECTOR2D
Definition vector2d.h:686