KiCad PCB EDA Suite
incremental_text_ctrl.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) 2015 Jean-Pierre Charras, jean-pierre.charras at wanadoo.fr
5  * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
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 <incremental_text_ctrl.h>
26 
31 static bool validateFloatField( const wxString& aStr )
32 {
33  // Skip empty fields
34  if( aStr.size() == 0 )
35  return false;
36 
37  // a single . or , doesn't count as number, although valid in a float
38  if( aStr.size() == 1 )
39  {
40  if( (aStr.compare( "." ) == 0) ||
41  (aStr.compare( "," ) == 0) )
42  return false;
43  }
44 
45  return true;
46 }
47 
48 
50  m_minVal( 0.0 ),
51  m_maxVal( 1.0 ),
52  m_currentValue( 0.0 ),
53  m_precision( 4 )
54 {}
55 
56 
57 void INCREMENTAL_TEXT_CTRL::SetStep( double aMin, double aMax,
58  STEP_FUNCTION aStepFunc )
59 {
60  wxASSERT( aMin <= aMax );
61 
62  m_minVal = std::min( aMin, aMax );
63  m_maxVal = std::max( aMin, aMax );
64  m_stepFunc = aStepFunc;
65 
66  // finally, clamp the current value and re-display
68 }
69 
70 
72 {
73  if( m_currentValue > m_maxVal )
75 
76  if( m_currentValue < m_minVal )
78 
79  wxString fmt = wxString::Format( "%%.%df", m_precision );
81 }
82 
83 
85 {
86  const wxString txt = getCtrlText();
87  if( !validateFloatField( txt ) )
88  return;
89 
90  txt.ToDouble( &m_currentValue );
91  m_currentValue += aInc;
92 
94 }
95 
96 
98 {
100 }
101 
102 
104 {
105  m_precision = aPrecision;
106 }
107 
108 
109 void INCREMENTAL_TEXT_CTRL::SetValue( double aValue )
110 {
111  m_currentValue = aValue;
112  updateTextValue();
113 }
114 
115 
117 {
118  // sanitise before handing the value - if the user did something
119  // like close a window with outstanding text changes, we need
120  // to clamp the value and re-interpret the text
121  incrementCtrlBy( 0.0 );
122 
123  return m_currentValue;
124 }
125 
126 
128  wxTextCtrl& aTextCtrl ):
129  m_spinBtn( aSpinBtn ),
130  m_textCtrl( aTextCtrl )
131 {
132  (void) m_spinBtn;
133 
134  // set always enabled, otherwise it's very hard to keep in sync
135  aSpinBtn.SetRange( -INT_MAX, INT_MAX );
136 
137  auto spinUpHandler = [this] ( wxSpinEvent& event )
138  {
139  incrementCtrl( true );
140  };
141 
142  // spin up/down if a single step of the field
143  auto spinDownHandler = [this] ( wxSpinEvent& event )
144  {
145  incrementCtrl( false );
146  };
147 
148  auto mouseWheelHandler = [this] ( wxMouseEvent& aEvent )
149  {
150  incrementCtrl( aEvent.GetWheelRotation() >= 0 );
151  };
152 
153  aSpinBtn.Bind( wxEVT_SPIN_UP, spinUpHandler );
154  aSpinBtn.Bind( wxEVT_SPIN_DOWN, spinDownHandler );
155 
156  m_textCtrl.Bind( wxEVT_MOUSEWHEEL, mouseWheelHandler );
157 
158  m_textCtrl.Bind( wxEVT_KILL_FOCUS, &SPIN_INCREMENTAL_TEXT_CTRL::onFocusLoss, this );
159 }
160 
162 {
163  // this must be unbound, as kill focus can arrive after the
164  // text control is gone
165  m_textCtrl.Unbind( wxEVT_KILL_FOCUS, &SPIN_INCREMENTAL_TEXT_CTRL::onFocusLoss, this );
166 }
167 
168 
169 void SPIN_INCREMENTAL_TEXT_CTRL::onFocusLoss( wxFocusEvent& aEvent )
170 {
171  // re-read the input and sanitize any user changes
172  incrementCtrlBy( 0.0 );
173 }
174 
175 
176 void SPIN_INCREMENTAL_TEXT_CTRL::setTextCtrl( const wxString& val )
177 {
178  m_textCtrl.SetValue( val );
179 }
180 
181 
183 {
184  return m_textCtrl.GetValue();
185 }
186 
std::function< double(bool aUp, double aCurrVal)> STEP_FUNCTION
A callable object type that can be used to provide a step value.
double m_maxVal
Current value of the control.
void setTextCtrl(const wxString &val) override
>
void SetValue(double aValue)
Set the value of the text control, but obey the limits currently set.
double m_currentValue
Precision to display.
virtual void setTextCtrl(const wxString &aVal)=0
Set the text control string value after an increment.
void SetPrecision(int aPrecision)
Set the number of decimal places to display.
void SetStep(double aMin, double aMax, STEP_FUNCTION aNewFunc)
Function SetStep()
static bool validateFloatField(const wxString &aStr)
Check that a string looks like a floating point number that can be dealt with.
wxString getCtrlText() const override
>
SPIN_INCREMENTAL_TEXT_CTRL(wxSpinButton &aSpinBtn, wxTextCtrl &aTextCtrl)
Constructor.
void onFocusLoss(wxFocusEvent &aEvent)
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 max(a, b)
Definition: auxiliary.h:86
void updateTextValue()
Update the text control value with the current value, clamping to limits as needed.
void incrementCtrl(bool aUp)
Single increment up or down by one step.
int m_precision
The function used to determine the step.
double GetValue()
Get the current value of the control.
virtual wxString getCtrlText() const =0
void incrementCtrlBy(double aInc)
Increment the control by the given amount.
#define min(a, b)
Definition: auxiliary.h:85