KiCad PCB EDA Suite
dialog_move_exact.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) 2014 John Beard, john.j.beard@gmail.com
5  * Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors.
6  * Copyright (C) 2017 KiCad Developers, see CHANGELOG.TXT for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <wxPcbStruct.h>
27 #include <base_units.h>
28 #include <macros.h>
29 
30 #include <module_editor_frame.h>
31 #include <widgets/text_ctrl_eval.h>
32 
33 #include "dialog_move_exact.h"
34 
35 // initialise statics
37 
38 
40  DIALOG_MOVE_EXACT_BASE( aParent ),
41  m_parent( aParent ),
42  m_translation( aParams.translation ),
43  m_rotation( aParams.rotation ),
44  m_origin( aParams.origin ),
45  m_anchor( aParams.anchor ),
46  m_allowOverride( aParams.allowOverride ),
47  m_editingFootprint( aParams.editingFootprint )
48 {
49  // set the unit labels
50  m_xUnit->SetLabelText( GetAbbreviatedUnitsLabel( g_UserUnit ) );
51  m_yUnit->SetLabelText( GetAbbreviatedUnitsLabel( g_UserUnit ) );
52 
53  // tabbing goes through the entries in sequence
54  m_yEntry->MoveAfterInTabOrder( m_xEntry );
55  m_rotEntry->MoveAfterInTabOrder( m_yEntry );
56 
57  // and set up the entries according to the saved options
58  m_polarCoords->SetValue( m_options.polarCoords );
59  m_xEntry->SetValue( wxString::FromDouble( m_options.entry1 ) );
60  m_yEntry->SetValue( wxString::FromDouble( m_options.entry2 ) );
61  m_rotEntry->SetValue( wxString::FromDouble( m_options.entryRotation ) );
62  m_originChooser->SetSelection( m_options.origin );
63 
64  if( m_allowOverride )
65  {
68 
69  // ME_ANCHOR_FROM_LIBRARY is not in the wxChoice options so show the first choice instead
71  {
72  m_anchorChoice->SetSelection( ANCHOR_TOP_LEFT_PAD );
73  }
74  else
75  {
76  m_anchorChoice->SetSelection( m_options.anchor );
77  }
78 
80  {
81  // no footprint override necessary in this mode
82  m_cbOverride->Disable();
83  m_anchorChoice->Disable();
84  }
85 
86  if( m_editingFootprint )
87  {
88  // there is no point in showing the center footprint option when editing footprints
90  }
91  }
92  else
93  {
94  // hide the checkbox and choice control if overides are not allowed
95  bMainSizer->Hide( bAnchorSizer, true );
96  }
97 
98  if( wxPoint( 0, 0 ) == aParent->GetScreen()->m_O_Curseur )
99  {
100  // disble the user origin option when the user oigin is not set
101  m_originChooser->Enable( RELATIVE_TO_USER_ORIGIN, false );
102  m_originChooser->SetItemToolTip( RELATIVE_TO_USER_ORIGIN,
103  wxString( "The user origin is currently not set\n"
104  "Set it by using the <space> hotkey" ) );
105  }
106 
107  if( wxPoint( 0, 0 ) == aParent->GetGridOrigin() )
108  {
109  // disble the grid origin option when the user oigin is not set
110  m_originChooser->Enable( RELATIVE_TO_GRID_ORIGIN, false );
111  m_originChooser->SetItemToolTip( RELATIVE_TO_GRID_ORIGIN,
112  wxString( "The grid origin is currently not set\n"
113  "Set it by using the tool in the <place> menu" ) );
114  }
115 
116  if( wxPoint( 0, 0 ) == aParent->GetAuxOrigin() )
117  {
118  // disble the grid origin option when the drill/place oigin is not set
121  wxString( "The drill/place origin is currently not set\n"
122  "Set it by using the tool in the <place> menu" ) );
123  }
124 
125  updateDlgTexts( m_polarCoords->IsChecked() );
126 
127  m_stdButtonsOK->SetDefault();
128 
129  GetSizer()->SetSizeHints( this );
130  Layout();
131 }
132 
133 
135 {
136 }
137 
138 
139 void DIALOG_MOVE_EXACT::ToPolarDeg( double x, double y, double& r, double& q )
140 {
141  // convert to polar coordinates
142  r = hypot ( x, y );
143 
144  q = ( r != 0) ? RAD2DEG( atan2( y, x ) ) : 0;
145 }
146 
147 
149 {
150  if( polar )
151  {
152  const int r = ValueFromTextCtrl( *m_xEntry );
153  const double q = DoubleValueFromString( DEGREES, m_yEntry->GetValue() );
154 
155  val.x = r * cos( DEG2RAD( q / 10.0 ) );
156  val.y = r * sin( DEG2RAD( q / 10.0 ) );
157  }
158  else
159  {
160  // direct read
161  val.x = ValueFromTextCtrl( *m_xEntry );
162  val.y = ValueFromTextCtrl( *m_yEntry );
163  }
164 
165  // no validation to do here, but in future, you could return false here
166  return true;
167 }
168 
169 
170 void DIALOG_MOVE_EXACT::OnPolarChanged( wxCommandEvent& event )
171 {
172  bool newPolar = m_polarCoords->IsChecked();
173  updateDlgTexts( newPolar );
174  wxPoint val;
175 
176  // get the value as previously stored
177  GetTranslationInIU( val, !newPolar );
178 
179  if( newPolar )
180  {
181  // convert to polar coordinates
182  double r, q;
183  ToPolarDeg( val.x, val.y, r, q );
184 
185  PutValueInLocalUnits( *m_xEntry, KiROUND( r / 10.0) * 10 );
186  m_yEntry->SetValue( wxString::FromDouble( q ) );
187  }
188  else
189  {
190  // vector is already in Cartesian, so just render out
191  // note - round off the last decimal place (10nm) to prevent
192  // (some) rounding causing errors when round-tripping
193  // you can never eliminate entirely, however
194  PutValueInLocalUnits( *m_xEntry, KiROUND( val.x / 10.0 ) * 10 );
195  PutValueInLocalUnits( *m_yEntry, KiROUND( val.y / 10.0 ) * 10 );
196  }
197  Layout();
198 }
199 
200 
201 void DIALOG_MOVE_EXACT::OnOriginChanged( wxCommandEvent& event )
202 {
203  if( m_originChooser->GetSelection() == RELATIVE_TO_CURRENT_POSITION )
204  {
205  //no need to override the achor in this mode since the reference in the current position
206  m_cbOverride->Disable();
207  m_anchorChoice->Disable();
208  }
209  else if( m_allowOverride )
210  {
211  m_cbOverride->Enable();
212 
213  if( m_cbOverride->IsChecked() )
214  m_anchorChoice->Enable();
215  }
216 }
217 
218 
219 void DIALOG_MOVE_EXACT::OnOverrideChanged( wxCommandEvent& event )
220 {
221  if( m_cbOverride->IsChecked() )
222  {
223  m_anchorChoice->Enable();
224  }
225  else
226  {
227  m_anchorChoice->Disable();
228  }
229 }
230 
231 
233 {
234  if( aPolar )
235  {
236  m_xLabel->SetLabelText( _( "Distance:" ) ); // Polar radius
237  m_yLabel->SetLabelText( _( "Angle:" ) ); // Polar theta or angle
238 
239  m_yUnit->SetLabelText( GetAbbreviatedUnitsLabel( DEGREES ) );
240  }
241  else
242  {
243  m_xLabel->SetLabelText( _( "Move vector X:" ) );
244  m_yLabel->SetLabelText( _( "Move vector Y:" ) );
245 
246  m_yUnit->SetLabelText( GetAbbreviatedUnitsLabel( g_UserUnit ) );
247  }
248 }
249 
250 
251 void DIALOG_MOVE_EXACT::OnClear( wxCommandEvent& event )
252 {
253  wxObject* obj = event.GetEventObject();
254  wxTextCtrl* entry = NULL;
255 
256  if( obj == m_clearX )
257  {
258  entry = m_xEntry;
259  }
260  else if( obj == m_clearY )
261  {
262  entry = m_yEntry;
263  }
264  else if( obj == m_clearRot )
265  {
266  entry = m_rotEntry;
267  }
268 
269  if( entry )
270  entry->SetValue( "0" );
271 }
272 
273 
274 void DIALOG_MOVE_EXACT::OnOkClick( wxCommandEvent& event )
275 {
277  m_origin = static_cast<MOVE_EXACT_ORIGIN>( m_originChooser->GetSelection() );
278 
279  if( m_cbOverride->IsChecked() && m_allowOverride )
280  {
281  m_anchor = static_cast<MOVE_EXACT_ANCHOR>( m_anchorChoice->GetSelection() );
282  }
283  else
284  {
286  }
287 
288  wxPoint move_vector, origin;
289  // for the output, we only deliver a Cartesian vector
290  bool ok = GetTranslationInIU( move_vector, m_polarCoords->IsChecked() );
291 
292  switch( m_origin )
293  {
295  origin = m_parent->GetScreen()->m_O_Curseur;
296  break;
297 
299  origin = m_parent->GetGridOrigin();
300  break;
301 
303  origin = m_parent->GetAuxOrigin();
304  break;
305 
307  origin = wxPoint( 0, 0 );
308  break;
309 
311  // relative movement means that only the translation values should be used:
312  // -> set origin and anchor to zero
313  origin = wxPoint( 0, 0 );
314  break;
315  }
316 
317  m_translation = move_vector + origin;
318 
319  if( ok )
320  {
321  // save the settings
322  m_options.polarCoords = m_polarCoords->GetValue();
327  m_options.anchor = static_cast<MOVE_EXACT_ANCHOR>( m_anchorChoice->GetSelection() );
328  m_options.overrideAnchor = m_cbOverride->IsChecked();
329  event.Skip();
330  }
331 }
332 
333 
334 void DIALOG_MOVE_EXACT::OnTextFocusLost( wxFocusEvent& event )
335 {
336  wxTextCtrl* obj = static_cast<wxTextCtrl*>( event.GetEventObject() );
337 
338  if( obj->GetValue().IsEmpty() )
339  obj->SetValue( "0" );
340 
341  event.Skip();
342 }
Definition of class FOOTPRINT_EDIT_FRAME.
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
MOVE_EXACT_ORIGIN
Implementation of conversion functions that require both schematic and board internal units...
Class DIALOG_MOVE_EXACT_BASE.
double RAD2DEG(double rad)
Definition: trigo.h:200
const wxPoint & GetGridOrigin() const override
Function GetGridOrigin returns the absolute coordinates of the origin of the snap grid...
MOVE_EXACT_ORIGIN & m_origin
wxPoint m_O_Curseur
Relative Screen cursor coordinate (on grid) in user units.
const wxPoint & GetAuxOrigin() const override
Function GetAuxOrigin returns the origin of the axis used for plotting and various exports...
MOVE_EXACT_ANCHOR
This file contains miscellaneous commonly used macros and functions.
void OnOkClick(wxCommandEvent &event) override
void OnPolarChanged(wxCommandEvent &event) override
DIALOG_MOVE_EXACT(PCB_BASE_FRAME *aParent, MOVE_PARAMETERS &aParams)
void updateDlgTexts(bool aPolar)
bool GetTranslationInIU(wxPoint &val, bool polar)
Get the (Cartesian) translation described by the text entries.
wxString GetAbbreviatedUnitsLabel(EDA_UNITS_T aUnit)
Definition: base_units.cpp:484
int ValueFromTextCtrl(const wxTextCtrl &aTextCtr)
Convert the number Value in a string according to the internal units and the selected unit (g_UserUni...
Definition: base_units.cpp:385
EDA_UNITS_T g_UserUnit
Global variables definitions.
Definition: common.cpp:56
void OnTextFocusLost(wxFocusEvent &event) override
void OnClear(wxCommandEvent &event) override
void PutValueInLocalUnits(wxTextCtrl &aTextCtr, int aValue)
Function PutValueInLocalUnits converts aValue from internal units to user units and append the units ...
Definition: base_units.cpp:266
double DEG2RAD(double deg)
Definition: trigo.h:199
void ToPolarDeg(double x, double y, double &r, double &q)
Convert a given Cartesian point into a polar representation.
PCB_SCREEN * GetScreen() const override
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
MOVE_EXACT_ANCHOR & m_anchor
static MOVE_EXACT_OPTIONS m_options
void OnOriginChanged(wxCommandEvent &event) override
double DoubleValueFromString(EDA_UNITS_T aUnits, const wxString &aTextValue)
Function DoubleValueFromString converts aTextValue to a double.
Definition: base_units.cpp:302
PCB_BASE_FRAME * m_parent
class PCB_BASE_FRAME basic PCB main window class for Pcbnew, Gerbview, and CvPcb footprint viewer...
void OnOverrideChanged(wxCommandEvent &event) override