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/stattext.h>
26 #include <wx/textentry.h>
27 #include <limits>
28 #include <base_units.h>
29 #include <draw_frame.h>
30 #include <confirm.h>
31 
32 #include "widgets/unit_binder.h"
33 
34 wxDEFINE_EVENT( DELAY_FOCUS, wxCommandEvent );
35 
37  wxStaticText* aLabel, wxWindow* aValue, wxStaticText* aUnitLabel,
38  bool aUseMils, bool allowEval ) :
39  m_label( aLabel ),
40  m_value( aValue ),
41  m_unitLabel( aUnitLabel ),
42  m_eval( aParent->GetUserUnits(), aUseMils )
43 {
44  // Fix the units (to the current units) for the life of the binder
45  m_units = aParent->GetUserUnits();
46  m_useMils = aUseMils;
47  m_allowEval = allowEval && dynamic_cast<wxTextEntry*>( m_value );
48  m_needsEval = false;
49 
50  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
51  if( textEntry )
52  {
53  // Use ChangeValue() instead of SetValue() so we don't generate events.
54  textEntry->ChangeValue( wxT( "0" ) );
55  }
56 
58 
59  m_value->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), NULL, this );
60  m_value->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), NULL, this );
61  Connect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), NULL, this );
62 }
63 
64 
65 void UNIT_BINDER::SetUnits( EDA_UNITS_T aUnits, bool aUseMils )
66 {
67  m_units = aUnits;
68  m_useMils = aUseMils;
70 }
71 
72 
73 void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
74 {
75  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
76 
77  if( m_allowEval && textEntry )
78  {
79  wxString oldStr = m_eval.OriginalText();
80 
81  if( oldStr.length() )
82  textEntry->SetValue( oldStr );
83 
84  m_needsEval = true;
85  }
86 
87  aEvent.Skip();
88 }
89 
90 
91 void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
92 {
93  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
94 
95  if( m_allowEval && textEntry )
96  {
97  if( m_eval.Process( textEntry->GetValue() ) )
98  textEntry->ChangeValue( m_eval.Result() );
99 
100  m_needsEval = false;
101  }
102 
103  aEvent.Skip();
104 }
105 
106 
107 wxString valueDescriptionFromLabel( wxStaticText* aLabel )
108 {
109  wxString desc = aLabel->GetLabel();
110 
111  desc.EndsWith( wxT( ":" ), &desc );
112  return desc;
113 }
114 
115 
116 void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& )
117 {
118  if( !m_errorMessage.IsEmpty() )
119  DisplayError( m_value->GetParent(), m_errorMessage );
120 
121  m_errorMessage = wxEmptyString;
122  m_value->SetFocus();
123 }
124 
125 
126 bool UNIT_BINDER::Validate( int aMin, int aMax, bool setFocusOnError )
127 {
128  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
129 
130  if( !textEntry || textEntry->GetValue() == INDETERMINATE )
131  return true;
132 
133  if( GetValue() < aMin )
134  {
135  m_errorMessage = wxString::Format( _( "%s must be at least %s." ),
137  StringFromValue( m_units, aMin, true ) );
138 
139  if( setFocusOnError )
140  {
141  textEntry->SelectAll();
142  // Don't focus directly; we might be inside a KillFocus event handler
143  wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
144  }
145 
146  return false;
147  }
148 
149  if( GetValue() > aMax )
150  {
151  m_errorMessage = wxString::Format( _( "%s must be less than %s." ),
153  StringFromValue( m_units, aMax, true ) );
154 
155  if( setFocusOnError )
156  {
157  textEntry->SelectAll();
158  // Don't focus directly; we might be inside a KillFocus event handler
159  wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
160  }
161 
162  return false;
163  }
164 
165  return true;
166 }
167 
168 
169 void UNIT_BINDER::SetValue( int aValue )
170 {
171  SetValue( StringFromValue( m_units, aValue, false, m_useMils ) );
172 }
173 
174 
175 void UNIT_BINDER::SetValue( wxString aValue )
176 {
177  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
178  auto staticText = dynamic_cast<wxStaticText*>( m_value );
179 
180  if( textEntry )
181  textEntry->SetValue( aValue );
182  else if( staticText )
183  staticText->SetLabel( aValue );
184 
185  if( m_allowEval )
186  m_eval.Clear();
187 
189 }
190 
191 
192 void UNIT_BINDER::ChangeValue( int aValue )
193 {
194  ChangeValue( StringFromValue( m_units, aValue, false, m_useMils ) );
195 }
196 
197 
198 void UNIT_BINDER::ChangeValue( 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->ChangeValue( aValue );
205  else if( staticText )
206  staticText->SetLabel( aValue );
207 
208  if( m_allowEval )
209  m_eval.Clear();
210 
212 }
213 
214 
216 {
217  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
218  auto staticText = dynamic_cast<wxStaticText*>( m_value );
219  wxString value;
220 
221  if( textEntry )
222  {
223  if( m_needsEval && m_eval.Process( textEntry->GetValue() ) )
224  value = m_eval.Result();
225  else
226  value = textEntry->GetValue();
227  }
228  else if( staticText )
229  value = staticText->GetLabel();
230  else
231  return 0;
232 
233  return ValueFromString( m_units, value, m_useMils );
234 }
235 
236 
238 {
239  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
240 
241  if( textEntry )
242  return textEntry->GetValue() == INDETERMINATE;
243 
244  return false;
245 }
246 
247 
248 void UNIT_BINDER::SetLabel( const wxString& aLabel )
249 {
250  m_label->SetLabel( aLabel );
251 }
252 
253 
254 void UNIT_BINDER::Enable( bool aEnable )
255 {
256  m_label->Enable( aEnable );
257  m_value->Enable( aEnable );
258  m_unitLabel->Enable( aEnable );
259 }
260 
261 
262 void UNIT_BINDER::Show( bool aShow, bool aResize )
263 {
264  m_label->Show( aShow );
265  m_value->Show( aShow );
266  m_unitLabel->Show( aShow );
267 
268  if( aResize )
269  {
270  if( aShow )
271  {
272  m_label->SetSize( -1, -1 );
273  m_value->SetSize( -1, -1 );
274  m_unitLabel->SetSize( -1, -1 );
275  }
276  else
277  {
278  m_label->SetSize( 0, 0 );
279  m_value->SetSize( 0, 0 );
280  m_unitLabel->SetSize( 0, 0 );
281  }
282  }
283 }
284 
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
virtual bool Validate(int aMin, int aMax, bool setFocusOnError=true)
Function Validate Validates the control against the given range, informing the user of any errors fou...
virtual void SetUnits(EDA_UNITS_T aUnits, bool aUseMils=false)
Function SetUnits Normally not needed (as the UNIT_BINDER inherits from the parent frame),...
Definition: unit_binder.cpp:65
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)
int ValueFromString(EDA_UNITS_T aUnits, const wxString &aTextValue, bool aUseMils)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application.
Definition: base_units.cpp:409
The base class for create windows for drawing purpose.
Definition: draw_frame.h:82
wxString valueDescriptionFromLabel(wxStaticText *aLabel)
virtual int GetValue()
Function GetValue Returns the current value in Internal Units.
void Show(bool aShow, bool aResize=false)
Function Show Shows/hides the label, widget and units label.
bool Process(const wxString &aString)
#define INDETERMINATE
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:289
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:36
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
bool m_allowEval
Definition: unit_binder.h:144
void onKillFocus(wxFocusEvent &aEvent)
Definition: unit_binder.cpp:91
wxString Result() const
void onSetFocus(wxFocusEvent &aEvent)
Definition: unit_binder.cpp:73
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
virtual void SetValue(int aValue)
Function SetValue Sets new value (in Internal Units) for the text field, taking care of units convers...
EDA_UNITS_T m_units
Currently used units.
Definition: unit_binder.h:136
wxString StringFromValue(EDA_UNITS_T aUnits, int aValue, bool aAddUnitSymbol, bool aUseMils)
Function StringFromValue returns the string from aValue according to units (inch, mm ....
Definition: base_units.cpp:210
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:244
EDA_UNITS_T
Definition: common.h:157
void Enable(bool aEnable)
Function Enable Enables/diasables the label, widget and units label.
wxString GetAbbreviatedUnitsLabel(EDA_UNITS_T aUnit, bool aUseMils)
Get the units string for a given units type.
Definition: base_units.cpp:432
virtual void ChangeValue(int aValue)
Function ChangeValue Changes the value (in Internal Units) for the text field, taking care of units c...