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 
35  wxStaticText* aLabel, wxWindow* aValue, wxStaticText* aUnitLabel,
36  bool aUseMils, int aMin, int aMax, bool allowEval ) :
37  m_label( aLabel ),
38  m_value( aValue ),
39  m_unitLabel( aUnitLabel ),
40  m_eval( aParent->GetUserUnits(), aUseMils )
41 {
42  // Fix the units (to the current units) for the life of the binder
43  m_units = aParent->GetUserUnits();
44  m_useMils = aUseMils;
45  m_min = aMin;
46  m_max = aMax;
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 }
62 
63 
64 void UNIT_BINDER::SetUnits( EDA_UNITS_T aUnits, bool aUseMils )
65 {
66  m_units = aUnits;
67  m_useMils = aUseMils;
69 }
70 
71 
72 void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
73 {
74  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
75 
76  if( m_allowEval && textEntry )
77  {
78  wxString oldStr = m_eval.OriginalText();
79 
80  if( oldStr.length() )
81  textEntry->SetValue( oldStr );
82 
83  m_needsEval = true;
84  }
85 
86  aEvent.Skip();
87 }
88 
89 
90 void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
91 {
92  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
93 
94  if( m_allowEval && textEntry )
95  {
96  if( m_eval.Process( textEntry->GetValue() ) )
97  textEntry->ChangeValue( m_eval.Result() );
98 
99  m_needsEval = false;
100  }
101 
102  Validate( true );
103 
104  aEvent.Skip();
105 }
106 
107 
108 wxString valueDescriptionFromLabel( wxStaticText* aLabel )
109 {
110  wxString desc = aLabel->GetLabel();
111 
112  desc.EndsWith( wxT( ":" ), &desc );
113  return desc;
114 }
115 
116 
118 {
119  if( !m_errorMessage.IsEmpty() )
120  DisplayError( m_value->GetParent(), m_errorMessage );
121 
122  m_errorMessage = wxEmptyString;
123 
124  m_value->SetFocus();
125 
126  m_value->Unbind( wxEVT_IDLE, &UNIT_BINDER::delayedFocusHandler, this );
127 }
128 
129 
130 bool UNIT_BINDER::Validate( bool setFocusOnError )
131 {
132  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
133 
134  if( !textEntry || textEntry->GetValue() == INDETERMINATE )
135  return true;
136 
137  if( m_min > INT_MIN && GetValue() < m_min )
138  {
139  m_errorMessage = wxString::Format( _( "%s must be larger than %s or equal." ),
141  StringFromValue( m_units, m_min, true ) );
142 
143  if( setFocusOnError )
144  {
145  textEntry->SelectAll();
146  // Don't focus directly; we might be inside a KillFocus event handler
147  m_value->Bind( wxEVT_IDLE, &UNIT_BINDER::delayedFocusHandler, this );
148  }
149 
150  return false;
151  }
152 
153  if( m_max < INT_MAX && GetValue() > m_max )
154  {
155  m_errorMessage = wxString::Format( _( "%s must be smaller than %s." ),
157  StringFromValue( m_units, m_max, true ) );
158 
159  if( setFocusOnError )
160  {
161  textEntry->SelectAll();
162  // Don't focus directly; we might be inside a KillFocus event handler
163  m_value->Bind( wxEVT_IDLE, &UNIT_BINDER::delayedFocusHandler, this );
164  }
165 
166  return false;
167  }
168 
169  return true;
170 }
171 
172 
173 void UNIT_BINDER::SetValue( int aValue )
174 {
175  SetValue( StringFromValue( m_units, aValue, false, m_useMils ) );
176 }
177 
178 
179 void UNIT_BINDER::SetValue( wxString aValue )
180 {
181  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
182  auto staticText = dynamic_cast<wxStaticText*>( m_value );
183 
184  if( textEntry )
185  textEntry->SetValue( aValue );
186  else if( staticText )
187  staticText->SetLabel( aValue );
188 
189  if( m_allowEval )
190  m_eval.Clear();
191 
193 }
194 
195 
196 void UNIT_BINDER::ChangeValue( int aValue )
197 {
198  ChangeValue( StringFromValue( m_units, aValue, false, m_useMils ) );
199 }
200 
201 
202 void UNIT_BINDER::ChangeValue( wxString aValue )
203 {
204  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
205  auto staticText = dynamic_cast<wxStaticText*>( m_value );
206 
207  if( textEntry )
208  textEntry->ChangeValue( aValue );
209  else if( staticText )
210  staticText->SetLabel( aValue );
211 
212  if( m_allowEval )
213  m_eval.Clear();
214 
216 }
217 
218 
220 {
221  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
222  auto staticText = dynamic_cast<wxStaticText*>( m_value );
223  wxString value;
224 
225  if( textEntry )
226  {
227  if( m_needsEval && m_eval.Process( textEntry->GetValue() ) )
228  value = m_eval.Result();
229  else
230  value = textEntry->GetValue();
231  }
232  else if( staticText )
233  value = staticText->GetLabel();
234  else
235  return 0;
236 
237  return ValueFromString( m_units, value, m_useMils );
238 }
239 
240 
242 {
243  auto textEntry = dynamic_cast<wxTextEntry*>( m_value );
244 
245  if( textEntry )
246  return textEntry->GetValue() == INDETERMINATE;
247 
248  return false;
249 }
250 
251 
252 void UNIT_BINDER::SetLabel( const wxString& aLabel )
253 {
254  m_label->SetLabel( aLabel );
255 }
256 
257 
258 void UNIT_BINDER::Enable( bool aEnable )
259 {
260  m_label->Enable( aEnable );
261  m_value->Enable( aEnable );
262  m_unitLabel->Enable( aEnable );
263 }
264 
265 
266 void UNIT_BINDER::Show( bool aShow )
267 {
268  m_label->Show( aShow );
269  m_value->Show( aShow );
270  m_unitLabel->Show( aShow );
271 }
272 
virtual bool Validate(bool setFocusOnError=false)
Function Validate Validates the control, informing the user of any errors found.
int m_min
Validation support.
Definition: unit_binder.h:158
wxString m_errorMessage
Definition: unit_binder.h:160
wxString Result() const
wxWindow * m_value
Definition: unit_binder.h:150
Implementation of conversion functions that require both schematic and board internal units...
This file is part of the common library.
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:64
bool m_needsEval
Definition: unit_binder.h:165
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:284
void Show(bool aShow)
Function Show Shows/hides the label, widget and units label.
wxStaticText * m_label
The bound widgets
Definition: unit_binder.h:149
wxStaticText * m_unitLabel
Definition: unit_binder.h:151
NUMERIC_EVALUATOR m_eval
Evaluator
Definition: unit_binder.h:163
bool m_useMils
Definition: unit_binder.h:155
bool m_allowEval
Definition: unit_binder.h:164
void onKillFocus(wxFocusEvent &aEvent)
Definition: unit_binder.cpp:90
void onSetFocus(wxFocusEvent &aEvent)
Definition: unit_binder.cpp:72
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...
void delayedFocusHandler(wxIdleEvent &aEvent)
EDA_UNITS_T m_units
Currently used units.
Definition: unit_binder.h:154
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
UNIT_BINDER(EDA_DRAW_FRAME *aParent, wxStaticText *aLabel, wxWindow *aValue, wxStaticText *aUnitLabel, bool aUseMils=false, int aMin=INT_MIN, int aMax=INT_MAX, bool aAllowEval=true)
Constructor.
Definition: unit_binder.cpp:34
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:159
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...