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 
27 #include <utility>
28 
33 static bool validateFloatField( const wxString& aStr )
34 {
35  // Skip empty fields
36  if( aStr.size() == 0 )
37  return false;
38 
39  // a single . or , doesn't count as number, although valid in a float
40  if( aStr.size() == 1 )
41  {
42  if( (aStr.compare( "." ) == 0) ||
43  (aStr.compare( "," ) == 0) )
44  return false;
45  }
46 
47  return true;
48 }
49 
50 
52  m_minVal( 0.0 ),
53  m_maxVal( 1.0 ),
54  m_currentValue( 0.0 ),
55  m_precision( 4 )
56 {}
57 
58 
59 void INCREMENTAL_TEXT_CTRL::SetStep( double aMin, double aMax,
60  STEP_FUNCTION aStepFunc )
61 {
62  wxASSERT( aMin <= aMax );
63 
64  m_minVal = std::min( aMin, aMax );
65  m_maxVal = std::max( aMin, aMax );
66  m_stepFunc = std::move( aStepFunc );
67 
68  // finally, clamp the current value and re-display
70 }
71 
72 
74 {
75  if( m_currentValue > m_maxVal )
77 
78  if( m_currentValue < m_minVal )
80 
81  wxString fmt = wxString::Format( "%%.%df", m_precision );
83 }
84 
85 
87 {
88  const wxString txt = getCtrlText();
89  if( !validateFloatField( txt ) )
90  return;
91 
92  txt.ToDouble( &m_currentValue );
93  m_currentValue += aInc;
94 
96 }
97 
98 
100 {
102 }
103 
104 
106 {
107  m_precision = aPrecision;
108 }
109 
110 
111 void INCREMENTAL_TEXT_CTRL::SetValue( double aValue )
112 {
113  m_currentValue = aValue;
114  updateTextValue();
115 }
116 
117 
119 {
120  // sanitise before handing the value - if the user did something
121  // like close a window with outstanding text changes, we need
122  // to clamp the value and re-interpret the text
123  incrementCtrlBy( 0.0 );
124 
125  return m_currentValue;
126 }
127 
128 
130  wxTextCtrl& aTextCtrl ):
131  m_spinBtn( aSpinBtn ),
132  m_textCtrl( aTextCtrl )
133 {
134  (void) m_spinBtn;
135 
136  // set always enabled, otherwise it's very hard to keep in sync
137  aSpinBtn.SetRange( -INT_MAX, INT_MAX );
138 
139  auto spinUpHandler = [this] ( wxSpinEvent& event )
140  {
141  incrementCtrl( true );
142  };
143 
144  // spin up/down if a single step of the field
145  auto spinDownHandler = [this] ( wxSpinEvent& event )
146  {
147  incrementCtrl( false );
148  };
149 
150  auto mouseWheelHandler = [this] ( wxMouseEvent& aEvent )
151  {
152  incrementCtrl( aEvent.GetWheelRotation() >= 0 );
153  };
154 
155  aSpinBtn.Bind( wxEVT_SPIN_UP, spinUpHandler );
156  aSpinBtn.Bind( wxEVT_SPIN_DOWN, spinDownHandler );
157 
158  m_textCtrl.Bind( wxEVT_MOUSEWHEEL, mouseWheelHandler );
159 
160  m_textCtrl.Bind( wxEVT_KILL_FOCUS, &SPIN_INCREMENTAL_TEXT_CTRL::onFocusLoss, this );
161 }
162 
164 {
165  // this must be unbound, as kill focus can arrive after the
166  // text control is gone
167  m_textCtrl.Unbind( wxEVT_KILL_FOCUS, &SPIN_INCREMENTAL_TEXT_CTRL::onFocusLoss, this );
168 }
169 
170 
171 void SPIN_INCREMENTAL_TEXT_CTRL::onFocusLoss( wxFocusEvent& aEvent )
172 {
173  // re-read the input and sanitize any user changes
174  incrementCtrlBy( 0.0 );
175 }
176 
177 
178 void SPIN_INCREMENTAL_TEXT_CTRL::setTextCtrl( const wxString& val )
179 {
180  m_textCtrl.SetValue( val );
181 }
182 
183 
185 {
186  return m_textCtrl.GetValue();
187 }
188 
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