KiCad PCB EDA Suite
unit_binder.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-2015 CERN
5  * Author: Maciej Suminski <maciej.suminski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <wx/clipbrd.h>
26 #include <wx/stattext.h>
27 #include <wx/textentry.h>
28 #include <limits>
29 #include <base_units.h>
30 #include <eda_draw_frame.h>
31 #include <confirm.h>
32 
33 #include "widgets/unit_binder.h"
34 
35 wxDEFINE_EVENT( DELAY_FOCUS, wxCommandEvent );
36 
38  wxStaticText* aLabel, wxWindow* aValue, wxStaticText* aUnitLabel,
39  bool aUseMils, bool allowEval ) :
40  m_label( aLabel ),
41  m_value( aValue ),
42  m_unitLabel( aUnitLabel ),
43  m_eval( aParent->GetUserUnits(), aUseMils )
44 {
45  // Fix the units (to the current units) for the life of the binder
46  m_units = aParent->GetUserUnits();
47  m_useMils = aUseMils;
48  m_allowEval = allowEval && dynamic_cast<wxTextEntry*>( m_value );
49  m_needsEval = false;
50  m_selStart = 0;
51  m_selEnd = 0;
52 
53  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
54  if( textEntry )
55  {
56  // Use ChangeValue() instead of SetValue() so we don't generate events.
57  textEntry->ChangeValue( wxT( "0" ) );
58  }
59 
61 
62  m_value->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), NULL, this );
63  m_value->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), NULL, this );
64  Connect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), NULL, this );
65 }
66 
67 
68 void UNIT_BINDER::SetUnits( EDA_UNITS aUnits, bool aUseMils )
69 {
70  m_units = aUnits;
71  m_useMils = aUseMils;
73 }
74 
75 
76 void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
77 {
78  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
79 
80  if( m_allowEval && textEntry )
81  {
82  wxString oldStr = m_eval.OriginalText();
83 
84  if( oldStr.length() )
85  {
86  textEntry->SetValue( oldStr );
87  textEntry->SetSelection( m_selStart, m_selEnd );
88  }
89 
90  m_needsEval = true;
91  }
92 
93  aEvent.Skip();
94 }
95 
96 
97 void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
98 {
99  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
100 
101  if( m_allowEval && textEntry )
102  {
103  if( m_eval.Process( textEntry->GetValue() ) )
104  {
105  textEntry->GetSelection( &m_selStart, &m_selEnd );
106  wxString sel = textEntry->GetStringSelection();
107 
108  textEntry->ChangeValue( m_eval.Result() );
109 
110 #ifdef __WXGTK__
111  // Manually copy the selected text to the primary selection clipboard
112  if( wxTheClipboard->Open() )
113  {
114  bool clipTarget = wxTheClipboard->IsUsingPrimarySelection();
115  wxTheClipboard->UsePrimarySelection( true );
116  wxTheClipboard->SetData( new wxTextDataObject( sel ) );
117  wxTheClipboard->UsePrimarySelection( clipTarget );
118  wxTheClipboard->Close();
119  }
120 #endif
121  }
122 
123  m_needsEval = false;
124  }
125 
126  aEvent.Skip();
127 }
128 
129 
130 wxString valueDescriptionFromLabel( wxStaticText* aLabel )
131 {
132  wxString desc = aLabel->GetLabel();
133 
134  desc.EndsWith( wxT( ":" ), &desc );
135  return desc;
136 }
137 
138 
139 void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& )
140 {
141  if( !m_errorMessage.IsEmpty() )
142  DisplayError( m_value->GetParent(), m_errorMessage );
143 
144  m_errorMessage = wxEmptyString;
145  m_value->SetFocus();
146 }
147 
148 
149 bool UNIT_BINDER::Validate( long long int aMin, long long int aMax, bool setFocusOnError )
150 {
151  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
152 
153  if( !textEntry || textEntry->GetValue() == INDETERMINATE )
154  return true;
155 
156  if( GetValue() < aMin )
157  {
158  m_errorMessage = wxString::Format( _( "%s must be at least %s." ),
160  StringFromValue( m_units, aMin, true ) );
161 
162  if( setFocusOnError )
163  {
164  textEntry->SelectAll();
165  // Don't focus directly; we might be inside a KillFocus event handler
166  wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
167  }
168 
169  return false;
170  }
171 
172  if( GetValue() > aMax )
173  {
174  m_errorMessage = wxString::Format( _( "%s must be less than %s." ),
176  StringFromValue( m_units, aMax, true ) );
177 
178  if( setFocusOnError )
179  {
180  textEntry->SelectAll();
181  // Don't focus directly; we might be inside a KillFocus event handler
182  wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
183  }
184 
185  return false;
186  }
187 
188  return true;
189 }
190 
191 
192 void UNIT_BINDER::SetValue( int aValue )
193 {
194  SetValue( StringFromValue( m_units, aValue, false, m_useMils ) );
195 }
196 
197 
198 void UNIT_BINDER::SetValue( wxString aValue )
199 {
200  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
201  auto staticText = dynamic_cast<wxStaticText*>( m_value );
202 
203  if( textEntry )
204  textEntry->SetValue( aValue );
205  else if( staticText )
206  staticText->SetLabel( aValue );
207 
208  if( m_allowEval )
209  m_eval.Clear();
210 
212 }
213 
214 
215 void UNIT_BINDER::ChangeValue( int aValue )
216 {
217  ChangeValue( StringFromValue( m_units, aValue, false, m_useMils ) );
218 }
219 
220 
221 void UNIT_BINDER::ChangeValue( wxString aValue )
222 {
223  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
224  auto staticText = dynamic_cast<wxStaticText*>( m_value );
225 
226  if( textEntry )
227  textEntry->ChangeValue( aValue );
228  else if( staticText )
229  staticText->SetLabel( aValue );
230 
231  if( m_allowEval )
232  m_eval.Clear();
233 
235 }
236 
237 
238 long long int UNIT_BINDER::GetValue()
239 {
240  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
241  auto staticText = dynamic_cast<wxStaticText*>( m_value );
242  wxString value;
243 
244  if( textEntry )
245  {
246  if( m_needsEval && m_eval.Process( textEntry->GetValue() ) )
247  value = m_eval.Result();
248  else
249  value = textEntry->GetValue();
250  }
251  else if( staticText )
252  value = staticText->GetLabel();
253  else
254  return 0;
255 
256  return ValueFromString( m_units, value, m_useMils );
257 }
258 
259 
261 {
262  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
263 
264  if( textEntry )
265  return textEntry->GetValue() == INDETERMINATE;
266 
267  return false;
268 }
269 
270 
271 void UNIT_BINDER::SetLabel( const wxString& aLabel )
272 {
273  m_label->SetLabel( aLabel );
274 }
275 
276 
277 void UNIT_BINDER::Enable( bool aEnable )
278 {
279  m_label->Enable( aEnable );
280  m_value->Enable( aEnable );
281  m_unitLabel->Enable( aEnable );
282 }
283 
284 
285 void UNIT_BINDER::Show( bool aShow, bool aResize )
286 {
287  m_label->Show( aShow );
288  m_value->Show( aShow );
289  m_unitLabel->Show( aShow );
290 
291  if( aResize )
292  {
293  if( aShow )
294  {
295  m_label->SetSize( -1, -1 );
296  m_value->SetSize( -1, -1 );
297  m_unitLabel->SetSize( -1, -1 );
298  }
299  else
300  {
301  m_label->SetSize( 0, 0 );
302  m_value->SetSize( 0, 0 );
303  m_unitLabel->SetSize( 0, 0 );
304  }
305  }
306 }
307 
EDA_UNITS
Definition: common.h:72
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:236
wxString m_errorMessage
Validation support.
Definition: unit_binder.h:140
void delayedFocusHandler(wxCommandEvent &aEvent)
int GetUserUnits()
Returns the currently selected user unit value for the interface.
wxWindow * m_value
Definition: unit_binder.h:132
Implementation of conversion functions that require both schematic and board internal units.
This file is part of the common library.
wxString OriginalText() const
wxString StringFromValue(EDA_UNITS aUnits, double aValue, bool aAddUnitSymbol, bool aUseMils)
Function StringFromValue returns the string from aValue according to units (inch, mm ....
Definition: base_units.cpp:219
bool m_needsEval
Definition: unit_binder.h:145
bool IsIndeterminate() const
Function IsIndeterminate Returns true if the control holds the indeterminate value (for instance,...
wxDEFINE_EVENT(DELAY_FOCUS, wxCommandEvent)
The base class for create windows for drawing purpose.
wxString GetAbbreviatedUnitsLabel(EDA_UNITS aUnit, bool aUseMils)
Get the units string for a given units type.
Definition: base_units.cpp:452
wxString valueDescriptionFromLabel(wxStaticText *aLabel)
EDA_UNITS m_units
Currently used units.
Definition: unit_binder.h:136
void Show(bool aShow, bool aResize=false)
Function Show Shows/hides the label, widget and units label.
bool Process(const wxString &aString)
#define NULL
#define INDETERMINATE
wxStaticText * m_label
The bound widgets
Definition: unit_binder.h:131
UNIT_BINDER(EDA_DRAW_FRAME *aParent, wxStaticText *aLabel, wxWindow *aValue, wxStaticText *aUnitLabel, bool aUseMils=false, bool aAllowEval=true)
Constructor.
Definition: unit_binder.cpp:37
wxStaticText * m_unitLabel
Definition: unit_binder.h:133
NUMERIC_EVALUATOR m_eval
Evaluator
Definition: unit_binder.h:143
bool m_useMils
Definition: unit_binder.h:137
virtual bool Validate(long long int aMin, long long int aMax, bool setFocusOnError=true)
Function Validate Validates the control against the given range, informing the user of any errors fou...
bool m_allowEval
Definition: unit_binder.h:144
void onKillFocus(wxFocusEvent &aEvent)
Definition: unit_binder.cpp:97
wxString Result() const
void onSetFocus(wxFocusEvent &aEvent)
Definition: unit_binder.cpp:76
void SetLabel(const wxString &aLabel)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
#define _(s)
Definition: 3d_actions.cpp:31
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
virtual long long int GetValue()
Function GetValue Returns the current value in Internal Units.
long m_selStart
Selection start and end of the original text
Definition: unit_binder.h:148
long long int ValueFromString(EDA_UNITS aUnits, const wxString &aTextValue, bool aUseMils)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application.
Definition: base_units.cpp:429
void Enable(bool aEnable)
Function Enable Enables/diasables the label, widget and units label.
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
virtual void SetUnits(EDA_UNITS aUnits, bool aUseMils=false)
Function SetUnits Normally not needed (as the UNIT_BINDER inherits from the parent frame),...
Definition: unit_binder.cpp:68
virtual void ChangeValue(int aValue)
Function ChangeValue Changes the value (in Internal Units) for the text field, taking care of units c...