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 )
263 {
264  m_label->Show( aShow );
265  m_value->Show( aShow );
266  m_unitLabel->Show( aShow );
267 }
268 
wxString m_errorMessage
Validation support.
Definition: unit_binder.h:137
wxString Result() const
void delayedFocusHandler(wxCommandEvent &aEvent)
wxWindow * m_value
Definition: unit_binder.h:129
Implementation of conversion functions that require both schematic and board internal units...
This file is part of the common library.
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:142
wxDEFINE_EVENT(DELAY_FOCUS, wxCommandEvent)
wxString OriginalText() const
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:78
wxString valueDescriptionFromLabel(wxStaticText *aLabel)
virtual int GetValue()
Function GetValue Returns the current value in Internal Units.
bool Process(const wxString &aString)
#define INDETERMINATE
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:281
void Show(bool aShow)
Function Show Shows/hides the label, widget and units label.
wxStaticText * m_label
The bound widgets
Definition: unit_binder.h:128
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:130
NUMERIC_EVALUATOR m_eval
Evaluator
Definition: unit_binder.h:140
bool m_useMils
Definition: unit_binder.h:134
bool m_allowEval
Definition: unit_binder.h:141
void onKillFocus(wxFocusEvent &aEvent)
Definition: unit_binder.cpp:91
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:133
bool IsIndeterminate() const
Function IsIndeterminate Returns true if the control holds the indeterminate value (for instance...
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:245
EDA_UNITS_T
Definition: common.h:160
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...