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
63 updateDialogControls( m_polarCoords->IsChecked() );
64
66
68}
69
70
71void DIALOG_POSITION_RELATIVE::ToPolarDeg( double x, double y, double& r, EDA_ANGLE& q )
72{
73 // convert to polar coordinates
74 r = hypot( x, y );
75
76 q = ( r != 0) ? EDA_ANGLE( VECTOR2D( x, y ) ) : ANGLE_0;
77}
78
79
81{
82 if( polar )
83 {
84 const double r = m_xOffset.GetDoubleValue();
85 const EDA_ANGLE q = m_yOffset.GetAngleValue();
86
87 val.x = KiROUND( r * q.Cos() );
88 val.y = KiROUND( r * q.Sin() );
89 }
90 else
91 {
92 // direct read
93 val.x = KiROUND( m_xOffset.GetDoubleValue() );
94 val.y = KiROUND( m_yOffset.GetDoubleValue() );
95 }
96
97 // no validation to do here, but in future, you could return false here
98 return true;
99}
100
101
102void DIALOG_POSITION_RELATIVE::OnPolarChanged( wxCommandEvent& event )
103{
104 bool newPolar = m_polarCoords->IsChecked();
105 double xOffset = m_xOffset.GetDoubleValue();
106 double yOffset = m_yOffset.GetDoubleValue();
107 updateDialogControls( newPolar );
108
109 if( newPolar )
110 {
111 if( xOffset != m_stateX || yOffset != m_stateY )
112 {
113 m_stateX = xOffset;
114 m_stateY = yOffset;
116
117 m_xOffset.SetDoubleValue( m_stateRadius );
118 m_stateRadius = m_xOffset.GetDoubleValue();
119 m_yOffset.SetAngleValue( m_stateTheta );
120 m_stateTheta = m_yOffset.GetAngleValue();
121 }
122 else
123 {
124 m_xOffset.SetDoubleValue( m_stateRadius );
125 m_yOffset.SetAngleValue( m_stateTheta );
126 }
127 }
128 else
129 {
130 if( xOffset != m_stateRadius || yOffset != m_stateTheta.AsDegrees() )
131 {
132 m_stateRadius = xOffset;
133 m_stateTheta = EDA_ANGLE( yOffset, DEGREES_T );
136
137 m_xOffset.SetDoubleValue( m_stateX );
138 m_stateX = m_xOffset.GetDoubleValue();
139 m_yOffset.SetDoubleValue( m_stateY );
140 m_stateY = m_yOffset.GetDoubleValue();
141 }
142 else
143 {
144 m_xOffset.SetDoubleValue( m_stateX );
145 m_yOffset.SetDoubleValue( m_stateY );
146 }
147 }
148}
149
150
152{
153 if( aPolar )
154 {
155 m_xOffset.SetLabel( _( "Distance:" ) ); // Polar radius
156 m_yOffset.SetLabel( _( "Angle:" ) ); // Polar theta or angle
157 m_yOffset.SetUnits( EDA_UNITS::DEGREES );
158 m_clearX->SetToolTip( _( "Reset to the current distance from the reference position." ) );
159 m_clearY->SetToolTip( _( "Reset to the current angle from the reference position." ) );
160 }
161 else
162 {
163 m_xOffset.SetLabel( _( "Offset X:" ) );
164 m_yOffset.SetLabel( _( "Offset Y:" ) );
165 m_yOffset.SetUnits( GetUserUnits() );
166 m_clearX->SetToolTip( _( "Reset to the current X offset from the reference position." ) );
167 m_clearY->SetToolTip( _( "Reset to the current Y offset from the reference position." ) );
168 }
169}
170
171
172void DIALOG_POSITION_RELATIVE::OnClear( wxCommandEvent& event )
173{
174 wxObject* obj = event.GetEventObject();
176 wxASSERT( posrelTool );
177
178 VECTOR2I offset = posrelTool->GetSelectionAnchorPosition() - getAnchorPos();
179 double r;
180 EDA_ANGLE q;
181 ToPolarDeg( offset.x, offset.y, r, q );
182
183 if( obj == m_clearX )
184 {
185 m_stateX = offset.x;
186 m_xOffset.SetDoubleValue( r );
187 m_stateRadius = m_xOffset.GetDoubleValue();
188
189 if( m_polarCoords->IsChecked() )
190 m_xOffset.SetDoubleValue( m_stateRadius );
191 else
192 m_xOffset.SetValue( m_stateX );
193 }
194 else if( obj == m_clearY )
195 {
196 m_stateY = offset.y;
197 m_yOffset.SetAngleValue( q );
198 m_stateTheta = m_yOffset.GetAngleValue();
199
200 if( m_polarCoords->IsChecked() )
201 m_yOffset.SetAngleValue( m_stateTheta );
202 else
203 m_yOffset.SetValue( m_stateY );
204 }
205}
206
207
209{
210 event.Skip();
211
212 PCB_PICKER_TOOL* pickerTool = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
213 wxCHECK( pickerTool, /* void */ );
214
216 PCB_PICKER_TOOL::INTERACTIVE_PARAMS{ this, _( "Select reference item..." ) } );
217
218 Hide();
219}
220
221
223{
224 event.Skip();
225
226 PCB_PICKER_TOOL* pickerTool = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
227 wxCHECK( pickerTool, /* void */ );
228
229 // Hide, but do not close, the dialog
230 Hide();
231
233 PCB_PICKER_TOOL::INTERACTIVE_PARAMS { this, _( "Select reference point..." ) } );
234}
235
236
238{
239 switch( s_anchorType )
240 {
242 m_referenceInfo->SetLabel( _( "Reference location: grid origin" ) );
243 break;
244
246 m_referenceInfo->SetLabel( _( "Reference location: local coordinates origin" ) );
247 break;
248
249 case ANCHOR_ITEM:
250 {
251 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUserUnits() );
252 wxString msg = _( "<none selected>" );
253
254 if( aItem )
255 msg = aItem->GetItemDescription( &unitsProvider, true );
256
257 m_referenceInfo->SetLabel( wxString::Format( _( "Reference item: %s" ), msg ) );
258 break;
259 }
260
261 case ANCHOR_POINT:
262 m_referenceInfo->SetLabel( wxString::Format( _( "Reference location: selected point (%s, %s)" ),
263 m_parentFrame->MessageTextFromValue( m_anchorItemPosition.x ),
264 m_parentFrame->MessageTextFromValue( m_anchorItemPosition.y ) ) );
265 break;
266 }
267}
268
269
271{
272 switch( s_anchorType )
273 {
275 return static_cast<BOARD*>( m_toolMgr->GetModel() )->GetDesignSettings().GetGridOrigin();
276
278 return static_cast<PCB_BASE_FRAME*>( m_toolMgr->GetToolHolder() )->GetScreen()->m_LocalOrigin;
279
280 case ANCHOR_ITEM:
281 case ANCHOR_POINT:
283 }
284
285 // Needed by some compilers to avoid a fatal compil error (no return value).
287}
288
289
291{
293 updateAnchorInfo( nullptr );
294}
295
296
298{
300 updateAnchorInfo( nullptr );
301}
302
303
305{
306 const BOARD_ITEM* item = nullptr;
307
308 if( aItem && aItem->IsBOARD_ITEM() )
309 item = static_cast<const BOARD_ITEM*>( aItem );
310
312 updateAnchorInfo( item );
313
314 if( item )
316
317 Show( true );
318}
319
320
321void DIALOG_POSITION_RELATIVE::UpdatePickedPoint( const std::optional<VECTOR2I>& aPoint )
322{
324
325 if( aPoint )
326 m_anchorItemPosition = *aPoint;
327
328 updateAnchorInfo( nullptr );
329
330 Show( true );
331}
332
333
334void DIALOG_POSITION_RELATIVE::OnOkClick( wxCommandEvent& event )
335{
336 // for the output, we only deliver a Cartesian vector
337 VECTOR2I translation;
338
339 if( getTranslationInIU( translation, m_polarCoords->IsChecked() ) )
340 {
342
343 posrelTool->RelativeItemSelectionMove( getAnchorPos(), translation );
344
345 event.Skip();
346 }
347}
348
349
351{
352 wxTextCtrl* obj = static_cast<wxTextCtrl*>( event.GetEventObject() );
353
354 if( obj->GetValue().IsEmpty() )
355 obj->SetValue( "0" );
356
357 event.Skip();
358}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
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:79
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:317
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1040
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:98
virtual VECTOR2I GetPosition() const
Definition eda_item.h:272
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition eda_item.cpp:144
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:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694