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, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <math/util.h> // for KiROUND
23#include <tools/pcb_actions.h>
25#include <pcb_edit_frame.h>
29#include <trigo.h>
30
31// initialise statics
33
34
37 m_toolMgr( aParent->GetToolManager() ),
38 m_xOffset( aParent, m_xLabel, m_xEntry, m_xUnit ),
39 m_yOffset( aParent, m_yLabel, m_yEntry, m_yUnit ),
40 m_stateX( 0.0 ),
41 m_stateY( 0.0 ),
42 m_stateRadius( 0.0 )
43{
44 // We can't set the tab order through wxWidgets due to shortcomings in their mnemonics
45 // implementation on MSW
46 m_tabOrder = {
51 };
52
53 // Configure display origin transforms
56
58
60
62}
63
64
66{
67 updateDialogControls( m_polarCoords->IsChecked() );
68 return DIALOG_POSITION_RELATIVE_BASE::TransferDataToWindow();
69}
70
71
72void DIALOG_POSITION_RELATIVE::ToPolarDeg( double x, double y, double& r, EDA_ANGLE& q )
73{
74 // convert to polar coordinates
75 r = hypot( x, y );
76
77 q = ( r != 0) ? EDA_ANGLE( VECTOR2D( x, y ) ) : ANGLE_0;
78}
79
80
82{
83 if( polar )
84 {
85 const double r = m_xOffset.GetDoubleValue();
86 const EDA_ANGLE q = m_yOffset.GetAngleValue();
87
88 val.x = KiROUND( r * q.Cos() );
89 val.y = KiROUND( r * q.Sin() );
90 }
91 else
92 {
93 // direct read
94 val.x = KiROUND( m_xOffset.GetDoubleValue() );
95 val.y = KiROUND( m_yOffset.GetDoubleValue() );
96 }
97
98 // no validation to do here, but in future, you could return false here
99 return true;
100}
101
102
103void DIALOG_POSITION_RELATIVE::OnPolarChanged( wxCommandEvent& event )
104{
105 bool newPolar = m_polarCoords->IsChecked();
106 double xOffset = m_xOffset.GetDoubleValue();
107 double yOffset = m_yOffset.GetDoubleValue();
108 updateDialogControls( newPolar );
109
110 if( newPolar )
111 {
112 if( xOffset != m_stateX || yOffset != m_stateY )
113 {
114 m_stateX = xOffset;
115 m_stateY = yOffset;
117
118 m_xOffset.SetDoubleValue( m_stateRadius );
119 m_stateRadius = m_xOffset.GetDoubleValue();
120 m_yOffset.SetAngleValue( m_stateTheta );
121 m_stateTheta = m_yOffset.GetAngleValue();
122 }
123 else
124 {
125 m_xOffset.SetDoubleValue( m_stateRadius );
126 m_yOffset.SetAngleValue( m_stateTheta );
127 }
128 }
129 else
130 {
131 if( xOffset != m_stateRadius || yOffset != m_stateTheta.AsDegrees() )
132 {
133 m_stateRadius = xOffset;
134 m_stateTheta = EDA_ANGLE( yOffset, DEGREES_T );
137
138 m_xOffset.SetDoubleValue( m_stateX );
139 m_stateX = m_xOffset.GetDoubleValue();
140 m_yOffset.SetDoubleValue( m_stateY );
141 m_stateY = m_yOffset.GetDoubleValue();
142 }
143 else
144 {
145 m_xOffset.SetDoubleValue( m_stateX );
146 m_yOffset.SetDoubleValue( m_stateY );
147 }
148 }
149}
150
151
153{
154 if( aPolar )
155 {
156 m_xOffset.SetLabel( _( "Distance:" ) ); // Polar radius
157 m_yOffset.SetLabel( _( "Angle:" ) ); // Polar theta or angle
158 m_yOffset.SetUnits( EDA_UNITS::DEGREES );
159 m_clearX->SetToolTip( _( "Reset to the current distance from the reference position." ) );
160 m_clearY->SetToolTip( _( "Reset to the current angle from the reference position." ) );
161 }
162 else
163 {
164 m_xOffset.SetLabel( _( "Offset X:" ) );
165 m_yOffset.SetLabel( _( "Offset Y:" ) );
166 m_yOffset.SetUnits( GetUserUnits() );
167 m_clearX->SetToolTip( _( "Reset to the current X offset from the reference position." ) );
168 m_clearY->SetToolTip( _( "Reset to the current Y offset from the reference position." ) );
169 }
170}
171
172
173void DIALOG_POSITION_RELATIVE::OnClear( wxCommandEvent& event )
174{
175 wxObject* obj = event.GetEventObject();
177 wxASSERT( posrelTool );
178
179 VECTOR2I offset = posrelTool->GetSelectionAnchorPosition() - getAnchorPos();
180 double r;
181 EDA_ANGLE q;
182 ToPolarDeg( offset.x, offset.y, r, q );
183
184 if( obj == m_clearX )
185 {
186 m_stateX = offset.x;
187 m_xOffset.SetDoubleValue( r );
188 m_stateRadius = m_xOffset.GetDoubleValue();
189
190 if( m_polarCoords->IsChecked() )
191 m_xOffset.SetDoubleValue( m_stateRadius );
192 else
193 m_xOffset.SetValue( m_stateX );
194 }
195 else if( obj == m_clearY )
196 {
197 m_stateY = offset.y;
198 m_yOffset.SetAngleValue( q );
199 m_stateTheta = m_yOffset.GetAngleValue();
200
201 if( m_polarCoords->IsChecked() )
202 m_yOffset.SetAngleValue( m_stateTheta );
203 else
204 m_yOffset.SetValue( m_stateY );
205 }
206}
207
208
210{
211 event.Skip();
212
213 PCB_PICKER_TOOL* pickerTool = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
214 wxCHECK( pickerTool, /* void */ );
215
216 Hide();
217
219 PCB_PICKER_TOOL::INTERACTIVE_PARAMS{ this, _( "Select reference item..." ) } );
220}
221
222
224{
225 event.Skip();
226
227 PCB_PICKER_TOOL* pickerTool = m_toolMgr->GetTool<PCB_PICKER_TOOL>();
228 wxCHECK( pickerTool, /* void */ );
229
230 // Hide, but do not close, the dialog
231 Hide();
232
234 PCB_PICKER_TOOL::INTERACTIVE_PARAMS { this, _( "Select reference point..." ) } );
235}
236
237
239{
240 switch( s_anchorType )
241 {
243 m_referenceInfo->SetLabel( _( "Reference location: grid origin" ) );
244 break;
245
247 m_referenceInfo->SetLabel( _( "Reference location: local coordinates origin" ) );
248 break;
249
250 case ANCHOR_ITEM:
251 {
252 UNITS_PROVIDER unitsProvider( pcbIUScale, GetUserUnits() );
253 wxString msg = _( "<none selected>" );
254
255 if( aItem )
256 msg = aItem->GetItemDescription( &unitsProvider, true );
257
258 m_referenceInfo->SetLabel( wxString::Format( _( "Reference item: %s" ), msg ) );
259 break;
260 }
261
262 case ANCHOR_POINT:
263 m_referenceInfo->SetLabel( wxString::Format( _( "Reference location: selected point (%s, %s)" ),
264 m_parentFrame->MessageTextFromValue( m_anchorItemPosition.x ),
265 m_parentFrame->MessageTextFromValue( m_anchorItemPosition.y ) ) );
266 break;
267 }
268}
269
270
272{
273 switch( s_anchorType )
274 {
276 return static_cast<BOARD*>( m_toolMgr->GetModel() )->GetDesignSettings().GetGridOrigin();
277
279 return static_cast<PCB_BASE_FRAME*>( m_toolMgr->GetToolHolder() )->GetScreen()->m_LocalOrigin;
280
281 case ANCHOR_ITEM:
282 case ANCHOR_POINT:
284 }
285
286 // Needed by some compilers to avoid a fatal compil error (no return value).
288}
289
290
292{
294 updateAnchorInfo( nullptr );
295}
296
297
299{
301 updateAnchorInfo( nullptr );
302}
303
304
306{
307 const BOARD_ITEM* item = nullptr;
308
309 if( aItem && aItem->IsBOARD_ITEM() )
310 item = static_cast<const BOARD_ITEM*>( aItem );
311
313 updateAnchorInfo( item );
314
315 if( item )
317
318 Show( true );
319 Raise();
320 SetFocus();
321}
322
323
324void DIALOG_POSITION_RELATIVE::UpdatePickedPoint( const std::optional<VECTOR2I>& aPoint )
325{
327
328 if( aPoint )
329 m_anchorItemPosition = *aPoint;
330
331 updateAnchorInfo( nullptr );
332
333 Show( true );
334 Raise();
335 SetFocus();
336}
337
338
339void DIALOG_POSITION_RELATIVE::OnOkClick( wxCommandEvent& event )
340{
341 // for the output, we only deliver a Cartesian vector
342 VECTOR2I translation;
343
344 if( getTranslationInIU( translation, m_polarCoords->IsChecked() ) )
345 {
347
348 posrelTool->RelativeItemSelectionMove( getAnchorPos(), translation );
349
350 event.Skip();
351 }
352}
353
354
356{
357 wxTextCtrl* obj = static_cast<wxTextCtrl*>( event.GetEventObject() );
358
359 if( obj->GetValue().IsEmpty() )
360 obj->SetValue( "0" );
361
362 event.Skip();
363}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
VECTOR2D m_LocalOrigin
Relative Screen cursor coordinate (on grid) in user units.
Definition base_screen.h:86
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:81
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1149
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:79
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:96
virtual VECTOR2I GetPosition() const
Definition eda_item.h:282
virtual wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const
Return a user-visible description string of this item.
Definition eda_item.cpp:169
bool IsBOARD_ITEM() const
Definition view_item.h:98
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:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682