KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 * Copyright (C) 2020-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Maciej Suminski <[email protected]>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <wx/clipbrd.h>
27#include <wx/combobox.h>
28#include <wx/stattext.h>
29#include <wx/textentry.h>
30#include <eda_units.h>
31#include <eda_draw_frame.h>
32#include <confirm.h>
33
34#include "widgets/unit_binder.h"
35#include "wx/dcclient.h"
36
37
38wxDEFINE_EVENT( DELAY_FOCUS, wxCommandEvent );
39
40
41UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent, wxStaticText* aLabel, wxWindow* aValueCtrl,
42 wxStaticText* aUnitLabel, bool allowEval, bool aBindFrameEvents ) :
43 UNIT_BINDER( aParent, aParent, aLabel, aValueCtrl, aUnitLabel, allowEval, aBindFrameEvents )
44{
45}
46
47UNIT_BINDER::UNIT_BINDER( UNITS_PROVIDER* aUnitsProvider, wxWindow* aEventSource,
48 wxStaticText* aLabel, wxWindow* aValueCtrl, wxStaticText* aUnitLabel,
49 bool aAllowEval, bool aBindFocusEvent ) :
50 m_bindFocusEvent( aBindFocusEvent ),
51 m_label( aLabel ),
52 m_valueCtrl( aValueCtrl ),
53 m_unitLabel( aUnitLabel ),
54 m_iuScale( &aUnitsProvider->GetIuScale() ),
55 m_negativeZero( false ),
56 m_dataType( EDA_DATA_TYPE::DISTANCE ),
57 m_precision( 0 ),
58 m_eval( aUnitsProvider->GetUserUnits() ),
59 m_unitsInValue( false ),
60 m_originTransforms( aUnitsProvider->GetOriginTransforms() ),
61 m_coordType( ORIGIN_TRANSFORMS::NOT_A_COORD )
62{
63 init( aUnitsProvider );
64 m_allowEval = aAllowEval && ( !m_valueCtrl || dynamic_cast<wxTextEntry*>( m_valueCtrl ) );
65 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
66
67 if( textEntry )
68 {
69 wxClientDC dc( m_valueCtrl );
70
71 // Gives enough room to display a value in inches in textEntry
72 // 3 digits + '.' + 10 digits
73 wxSize minSize = m_valueCtrl->GetMinSize();
74 int minWidth = dc.GetTextExtent( wxT( "XXX.XXXXXXXXXX" ) ).GetWidth();
75
76 if( minSize.GetWidth() < minWidth )
77 m_valueCtrl->SetMinSize( wxSize( minWidth, minSize.GetHeight() ) );
78
79 // Use ChangeValue() instead of SetValue() so we don't generate events.
80 if( m_negativeZero )
81 textEntry->ChangeValue( wxT( "-0" ) );
82 else
83 textEntry->ChangeValue( wxT( "0" ) );
84 }
85
86 if( m_unitLabel )
88
89 if( m_valueCtrl )
90 {
91 m_valueCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ),
92 nullptr, this );
93 m_valueCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ),
94 nullptr, this );
95 m_valueCtrl->Connect( wxEVT_LEFT_UP, wxMouseEventHandler( UNIT_BINDER::onClick ),
96 nullptr, this );
97 m_valueCtrl->Connect( wxEVT_COMBOBOX, wxCommandEventHandler( UNIT_BINDER::onComboBox ),
98 nullptr, this );
99 }
100
101 if( m_bindFocusEvent )
102 {
103 Connect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), nullptr,
104 this );
105 }
106
107 if( aEventSource )
108 {
109 aEventSource->Connect( EDA_EVT_UNITS_CHANGED,
110 wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ),
111 nullptr, this );
112 }
113}
114
115
117{
118 if( m_bindFocusEvent )
119 {
120 Disconnect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), nullptr,
121 this );
122 }
123
124 if( m_valueCtrl )
125 {
126 m_valueCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ),
127 nullptr, this );
128 m_valueCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ),
129 nullptr, this );
130 m_valueCtrl->Disconnect( wxEVT_LEFT_UP, wxMouseEventHandler( UNIT_BINDER::onClick ),
131 nullptr, this );
132 m_valueCtrl->Disconnect( wxEVT_COMBOBOX, wxCommandEventHandler( UNIT_BINDER::onComboBox ),
133 nullptr, this );
134 }
135}
136
137
139{
140 m_units = aProvider->GetUserUnits();
141 m_needsEval = false;
142 m_selStart = 0;
143 m_selEnd = 0;
144}
145
146
148{
149 m_units = aUnits;
150
152 m_eval.LocaleChanged(); // In case locale changed since last run
153
154 if( m_unitLabel )
156}
157
158
159void UNIT_BINDER::SetPrecision( int aLength )
160{
161 m_precision = std::min( aLength, 6 );
162}
163
164
166{
167 m_dataType = aDataType;
168
169 if( m_unitLabel )
171}
172
173
174void UNIT_BINDER::onUnitsChanged( wxCommandEvent& aEvent )
175{
176 EDA_BASE_FRAME* provider = static_cast<EDA_BASE_FRAME*>( aEvent.GetClientData() );
177
178 if( m_units != EDA_UNITS::UNSCALED
179 && m_units != EDA_UNITS::DEGREES
180 && m_units != EDA_UNITS::PERCENT )
181 {
182 int temp = GetIntValue();
183
184 wxComboBox* const combo = dynamic_cast<wxComboBox*>( m_valueCtrl );
185 std::vector<long long int> comboValues;
186
187 // Read out the current values
188 if( combo )
189 {
190 for( unsigned int i = 0; i < combo->GetCount(); i++ )
191 {
192 const wxString value = combo->GetString( i );
194 value, m_dataType );
195 comboValues.push_back( conv );
196 }
197 }
198
199 SetUnits( provider->GetUserUnits() );
200 m_iuScale = &provider->GetIuScale();
201
202 // Re-populate the combo box with updated values
203 if( combo )
204 {
205 SetOptionsList( comboValues );
206 }
207
208 if( !IsIndeterminate() )
209 SetValue( temp );
210 }
211
212 aEvent.Skip();
213}
214
215
216void UNIT_BINDER::onClick( wxMouseEvent& aEvent )
217{
218 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
219
220 if( textEntry && ( textEntry->GetValue() == INDETERMINATE_ACTION
221 || textEntry->GetValue() == INDETERMINATE_STATE ) )
222 {
223 // These are tokens, not strings, so do a select all
224 textEntry->SelectAll();
225 }
226
227 // Needed at least on Windows to avoid hanging
228 aEvent.Skip();
229}
230
231
232void UNIT_BINDER::onComboBox( wxCommandEvent& aEvent )
233{
234 wxComboBox* combo = dynamic_cast<wxComboBox*>( m_valueCtrl );
235 wxCHECK( combo, /*void*/ );
236
237 const wxString value = combo->GetStringSelection();
238 const long long int conv =
240
241 SetValue( conv );
242
243 aEvent.Skip();
244}
245
246
247void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
248{
249 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
250
251 if( textEntry )
252 {
253 if( m_allowEval )
254 {
255 wxString oldStr = m_eval.OriginalText();
256
257 if( oldStr.length() && oldStr != textEntry->GetValue() )
258 {
259 textEntry->ChangeValue( oldStr );
260 textEntry->SetSelection( m_selStart, m_selEnd );
261 }
262
263 m_needsEval = true;
264 }
265
266 if( textEntry->GetValue() == INDETERMINATE_ACTION
267 || textEntry->GetValue() == INDETERMINATE_STATE )
268 {
269 // These are tokens, not strings, so do a select all
270 textEntry->SelectAll();
271 }
272 }
273
274 aEvent.Skip();
275}
276
277
278void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
279{
280 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
281
282 if( m_allowEval && textEntry )
283 {
284 wxString value = textEntry->GetValue();
285 bool success = m_eval.Process( value );
286
287 if( success && !value.IsEmpty() )
288 {
289 textEntry->GetSelection( &m_selStart, &m_selEnd );
290
291 value = m_eval.Result();
292
293 if( m_unitsInValue && !value.IsEmpty() )
294 {
295 if( !( m_units == EDA_UNITS::DEGREES || m_units == EDA_UNITS::PERCENT ) )
296 value += wxT( " " );
297
299 }
300
301 textEntry->ChangeValue( value );
302
303#ifdef __WXGTK__
304 // Manually copy the selected text to the primary selection clipboard
305 if( wxTheClipboard->Open() )
306 {
307 wxString sel = textEntry->GetStringSelection();
308 bool clipTarget = wxTheClipboard->IsUsingPrimarySelection();
309 wxTheClipboard->UsePrimarySelection( true );
310 wxTheClipboard->SetData( new wxTextDataObject( sel ) );
311 wxTheClipboard->UsePrimarySelection( clipTarget );
312 wxTheClipboard->Close();
313 }
314#endif
315 }
316
317 m_needsEval = false;
318 }
319
320 aEvent.Skip();
321}
322
323
324wxString valueDescriptionFromLabel( wxStaticText* aLabel )
325{
326 wxString desc = aLabel->GetLabel();
327
328 desc.EndsWith( wxT( ":" ), &desc );
329 return desc;
330}
331
332
333void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& )
334{
335 if( !m_errorMessage.IsEmpty() )
336 DisplayError( m_valueCtrl->GetParent(), m_errorMessage );
337
338 m_errorMessage = wxEmptyString;
339 m_valueCtrl->SetFocus();
340}
341
342
343bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits )
344{
345 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
346
347 if( !textEntry
348 || textEntry->GetValue() == INDETERMINATE_ACTION
349 || textEntry->GetValue() == INDETERMINATE_STATE )
350 {
351 return true;
352 }
353
354 // TODO: Validate() does not currently support m_dataType being anything other than DISTANCE
355 // Note: aMin and aMax are not always given in internal units
356 if( GetValue() < EDA_UNIT_UTILS::UI::FromUserUnit( *m_iuScale, aUnits, aMin ) )
357 {
358 double val_min_iu = EDA_UNIT_UTILS::UI::FromUserUnit( *m_iuScale, aUnits, aMin );
359 m_errorMessage = wxString::Format( _( "%s must be at least %s." ),
362 val_min_iu,
363 true ) );
364
365 textEntry->SelectAll();
366
367 // Don't focus directly; we might be inside a KillFocus event handler
368 wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
369
370 return false;
371 }
372
373 if( GetValue() > EDA_UNIT_UTILS::UI::FromUserUnit( *m_iuScale, aUnits, aMax ) )
374 {
375 double val_max_iu = EDA_UNIT_UTILS::UI::FromUserUnit( *m_iuScale, aUnits, aMax );
376 m_errorMessage = wxString::Format( _( "%s must be less than %s." ),
379 val_max_iu,
380 true ) );
381
382 textEntry->SelectAll();
383
384 // Don't focus directly; we might be inside a KillFocus event handler
385 wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
386
387 return false;
388 }
389
390 return true;
391}
392
393
394void UNIT_BINDER::SetValue( long long int aValue )
395{
396 double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
397 wxString textValue = EDA_UNIT_UTILS::UI::StringFromValue( *m_iuScale, m_units, displayValue,
398 false, m_dataType );
399
400 if( displayValue == 0 && m_negativeZero )
401 SetValue( wxT( "-" ) + textValue );
402 else
403 SetValue( textValue );
404}
405
406
407void UNIT_BINDER::SetDoubleValue( double aValue )
408{
409 double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
411 setPrecision( displayValue, false ),
412 false, m_dataType );
413
414 if( displayValue == 0 && !std::signbit( displayValue ) && m_negativeZero )
415 SetValue( wxT( "-" ) + textValue );
416 else
417 SetValue( textValue );
418}
419
420
422{
423 SetDoubleValue( aValue.AsDegrees() );
424}
425
426
427void UNIT_BINDER::SetValue( const wxString& aValue )
428{
429 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
430 wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
431
432 wxString value = aValue;
433
434 if( m_unitsInValue && !value.IsEmpty() )
435 {
436 if( !( m_units == EDA_UNITS::DEGREES || m_units == EDA_UNITS::PERCENT ) )
437 value += wxT( " " );
438
440 }
441
442 if( textEntry )
443 textEntry->SetValue( value );
444 else if( staticText )
445 staticText->SetLabel( value );
446
447 if( m_allowEval )
448 m_eval.Clear();
449
450 if( m_unitLabel )
452
453}
454
455
456wxString UNIT_BINDER::getTextForValue( long long int aValue ) const
457{
458 const double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
459 wxString textValue = EDA_UNIT_UTILS::UI::StringFromValue(
460 *m_iuScale, m_units, setPrecision( displayValue, false ), false, m_dataType );
461
462 if( displayValue == 0 && m_negativeZero )
463 textValue = wxT( "-" ) + textValue;
464
465 return textValue;
466}
467
468
469wxString UNIT_BINDER::getTextForDoubleValue( double aValue ) const
470{
471 const double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
472 wxString textValue = EDA_UNIT_UTILS::UI::StringFromValue(
473 *m_iuScale, m_units, setPrecision( displayValue, false ), false, m_dataType );
474
475 if( displayValue == 0 && !std::signbit( displayValue ) && m_negativeZero )
476 textValue = wxT( "-" ) + textValue;
477
478 return textValue;
479}
480
481
482void UNIT_BINDER::ChangeValue( int aValue )
483{
484 ChangeValue( getTextForValue( aValue ) );
485}
486
487
489{
491}
492
493
495{
496 ChangeDoubleValue( aValue.AsDegrees() );
497}
498
499
500void UNIT_BINDER::ChangeValue( const wxString& aValue )
501{
502 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
503 wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
504
505 wxString value = aValue;
506
507 if( m_unitsInValue && !value.IsEmpty() )
508 {
509 if( !( m_units == EDA_UNITS::DEGREES || m_units == EDA_UNITS::PERCENT ) )
510 value += wxT( " " );
511
513 }
514
515 if( textEntry )
516 textEntry->ChangeValue( value );
517 else if( staticText )
518 staticText->SetLabel( value );
519
520 if( m_allowEval )
521 m_eval.Clear();
522
523 if( m_unitLabel )
525}
526
527
529{
530 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
531 wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
532 wxString value;
533
534 if( textEntry )
535 {
536 value = textEntry->GetValue();
537
538 if( m_needsEval && !value.IsEmpty() && m_eval.Process( value ) )
539 value = m_eval.Result();
540 else
541 value = textEntry->GetValue();
542 }
543 else if( staticText )
544 {
545 value = staticText->GetLabel();
546 }
547 else
548 {
549 return 0;
550 }
551
552 long long int displayValue = EDA_UNIT_UTILS::UI::ValueFromString( *m_iuScale, m_units, value,
553 m_dataType );
554 return m_originTransforms.FromDisplay( displayValue, m_coordType );
555}
556
557
558double UNIT_BINDER::setPrecision( double aValue, bool aValueUsesUserUnits ) const
559{
560 if( m_precision > 1 )
561 {
562 int scale = pow( 10, m_precision );
563 int64_t tmp = aValue;
564 if( !aValueUsesUserUnits )
565 {
567 }
568
569 aValue = static_cast<double>( tmp ) / scale;
570
571 if( !aValueUsesUserUnits )
573 }
574
575 return aValue;
576}
577
578
580{
581 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
582 wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
583 wxString value;
584
585 if( textEntry )
586 {
587 value = textEntry->GetValue();
588
589 if( m_needsEval && !value.IsEmpty() && m_eval.Process( value ) )
590 value = m_eval.Result();
591 else
592 value = textEntry->GetValue();
593 }
594 else if( staticText )
595 {
596 value = staticText->GetLabel();
597 }
598 else
599 {
600 return 0.0;
601 }
602
604 value, m_dataType );
605 displayValue = setPrecision( displayValue, false );
606
607 return m_originTransforms.FromDisplay( displayValue, m_coordType );
608}
609
610
612{
614}
615
616
617void UNIT_BINDER::SetOptionsList( std::span<const long long int> aOptions )
618{
619 wxComboBox* cb = dynamic_cast<wxComboBox*>( m_valueCtrl );
620 wxCHECK( cb, /* void */ );
621
622 cb->Clear();
623
624 for( long long int value : aOptions )
625 {
626 cb->Append( getTextForValue( value ) );
627 }
628}
629
630
631void UNIT_BINDER::SetDoubleOptionsList( std::span<const double> aOptions )
632{
633 wxComboBox* cb = dynamic_cast<wxComboBox*>( m_valueCtrl );
634 wxCHECK( cb, /* void */ );
635
636 cb->Clear();
637
638 for( double value : aOptions )
639 {
640 cb->Append( getTextForDoubleValue( value ) );
641 }
642}
643
644
646{
647 wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl );
648
649 if( te )
650 return te->GetValue() == INDETERMINATE_STATE || te->GetValue() == INDETERMINATE_ACTION;
651
652 return false;
653}
654
655
657{
658 wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl );
659
660 if( te )
661 return te->GetValue().IsEmpty();
662
663 return false;
664}
665
666
667void UNIT_BINDER::SetLabel( const wxString& aLabel )
668{
669 m_label->SetLabel( aLabel );
670}
671
672
673void UNIT_BINDER::Enable( bool aEnable )
674{
675 if( m_label )
676 m_label->Enable( aEnable );
677
678 m_valueCtrl->Enable( aEnable );
679
680 if( m_unitLabel )
681 m_unitLabel->Enable( aEnable );
682}
683
684
685void UNIT_BINDER::Show( bool aShow, bool aResize )
686{
687 m_label->Show( aShow );
688 m_valueCtrl->Show( aShow );
689
690 if( m_unitLabel )
691 m_unitLabel->Show( aShow );
692
693 if( aResize )
694 {
695 if( aShow )
696 {
697 m_label->SetSize( -1, -1 );
698 m_valueCtrl->SetSize( -1, -1 );
699
700 if( m_unitLabel )
701 m_unitLabel->SetSize( -1, -1 );
702 }
703 else
704 {
705 m_label->SetSize( 0, 0 );
706 m_valueCtrl->SetSize( 0, 0 );
707
708 if( m_unitLabel )
709 m_unitLabel->SetSize( 0, 0 );
710 }
711 }
712}
713
714
716 UNIT_BINDER( aParent, nullptr, nullptr, nullptr, true, false )
717{
718 m_unitsInValue = true;
719}
720
721
723{
724}
725
727{
728 m_valueCtrl = aControl;
729
730 if( m_valueCtrl )
731 {
732 m_valueCtrl->Bind( wxEVT_SET_FOCUS, &PROPERTY_EDITOR_UNIT_BINDER::onSetFocus, this );
733 m_valueCtrl->Bind( wxEVT_KILL_FOCUS, &PROPERTY_EDITOR_UNIT_BINDER::onKillFocus, this );
734 m_valueCtrl->Bind( wxEVT_LEFT_UP, &PROPERTY_EDITOR_UNIT_BINDER::onClick, this );
735
736 m_valueCtrl->Bind( wxEVT_SHOW,
737 [&]( wxShowEvent& e )
738 {
739 if( !e.IsShown() )
740 SetControl( nullptr );
741 } );
742 }
743}
double AsDegrees() const
Definition: eda_angle.h:113
The base frame for deriving all KiCad main window classes.
The base class for create windows for drawing purpose.
wxString OriginalText() const
wxString Result() const
void SetDefaultUnits(EDA_UNITS aUnits)
bool Process(const wxString &aString)
A class to perform either relative or absolute display origin transforms for a single axis of a point...
virtual int FromDisplay(int aValue, COORD_TYPES_T aCoordType) const
virtual int ToDisplay(int aValue, COORD_TYPES_T aCoordType) const
void SetControl(wxWindow *aControl)
PROPERTY_EDITOR_UNIT_BINDER(EDA_DRAW_FRAME *aParent)
const EDA_IU_SCALE & GetIuScale() const
EDA_UNITS GetUserUnits() const
double setPrecision(double aValue, bool aValueUsesUserUnits) const
When m_precision > 0 truncate the value aValue to show only m_precision digits in mantissa.
ORIGIN_TRANSFORMS::COORD_TYPES_T m_coordType
Type of coordinate for display origin transforms.
Definition: unit_binder.h:269
wxString getTextForValue(long long int aValue) const
int GetIntValue()
Definition: unit_binder.h:129
virtual void ChangeDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
void onKillFocus(wxFocusEvent &aEvent)
virtual long long int GetValue()
Return the current value in Internal Units.
void Enable(bool aEnable)
Enable/disable the label, widget and units label.
void onClick(wxMouseEvent &aEvent)
virtual void SetPrecision(int aLength)
Normally not needed, but can be used to set the precision when using internal units that are floats (...
virtual void SetUnits(EDA_UNITS aUnits)
Normally not needed (as the UNIT_BINDER inherits from the parent frame), but can be used to set to DE...
bool m_allowEval
Definition: unit_binder.h:257
wxString getTextForDoubleValue(double aValue) const
const EDA_IU_SCALE * m_iuScale
Definition: unit_binder.h:248
wxString m_errorMessage
Definition: unit_binder.h:254
virtual EDA_ANGLE GetAngleValue()
bool m_negativeZero
Indicates "-0" should be displayed for 0.
Definition: unit_binder.h:250
int m_precision
0 to 6
Definition: unit_binder.h:252
wxStaticText * m_unitLabel
Can be nullptr.
Definition: unit_binder.h:245
bool m_unitsInValue
Units label should be included in value text.
Definition: unit_binder.h:263
wxWindow * m_valueCtrl
Definition: unit_binder.h:244
void onSetFocus(wxFocusEvent &aEvent)
void onComboBox(wxCommandEvent &aEvent)
UNIT_BINDER(EDA_DRAW_FRAME *aParent, wxStaticText *aLabel, wxWindow *aValueCtrl, wxStaticText *aUnitLabel, bool aAllowEval=true, bool aBindFocusEvent=true)
Definition: unit_binder.cpp:41
wxStaticText * m_label
Definition: unit_binder.h:243
ORIGIN_TRANSFORMS & m_originTransforms
A reference to an ORIGIN_TRANSFORMS object.
Definition: unit_binder.h:266
bool m_bindFocusEvent
The bound widgets.
Definition: unit_binder.h:240
long m_selStart
Selection start and end of the original text.
Definition: unit_binder.h:260
virtual void SetDoubleOptionsList(std::span< const double > aOptions)
EDA_UNITS m_units
Definition: unit_binder.h:249
virtual double GetDoubleValue()
Return the current value in Internal Units.
virtual void SetOptionsList(std::span< const long long int > aOptions)
Set the list of options for a combobox control.
bool IsIndeterminate() const
Return true if the control holds the indeterminate value (for instance, if it represents a multiple s...
bool m_needsEval
Definition: unit_binder.h:258
void SetDataType(EDA_DATA_TYPE aDataType)
Used to override the datatype of the displayed property (default is DISTANCE)
void delayedFocusHandler(wxCommandEvent &aEvent)
EDA_DATA_TYPE m_dataType
Definition: unit_binder.h:251
virtual void SetAngleValue(const EDA_ANGLE &aValue)
void SetLabel(const wxString &aLabel)
void init(UNITS_PROVIDER *aProvider)
virtual void ChangeAngleValue(const EDA_ANGLE &aValue)
virtual void SetDoubleValue(double aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
virtual ~UNIT_BINDER() override
virtual bool Validate(double aMin, double aMax, EDA_UNITS aUnits=EDA_UNITS::UNSCALED)
Validate the control against the given range, informing the user of any errors found.
virtual void ChangeValue(int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion WITHOUT trigger...
virtual void SetValue(long long int aValue)
Set new value (in Internal Units) for the text field, taking care of units conversion.
void Show(bool aShow, bool aResize=false)
Show/hide the label, widget and units label.
NUMERIC_EVALUATOR m_eval
Definition: unit_binder.h:256
bool IsNull() const
Return true if the control holds no value (ie: empty string, not 0).
void onUnitsChanged(wxCommandEvent &aEvent)
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
This file is part of the common library.
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
@ DEGREES_T
Definition: eda_angle.h:31
EDA_DATA_TYPE
The type of unit.
Definition: eda_units.h:38
EDA_UNITS
Definition: eda_units.h:46
KICOMMON_API double FromUserUnit(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnit, double aValue)
Return in internal units the value aValue given in a real unit such as "in", "mm",...
Definition: eda_units.cpp:510
KICOMMON_API long long int ValueFromString(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Function ValueFromString converts aTextValue in aUnits to internal units used by the application.
Definition: eda_units.cpp:671
KICOMMON_API wxString StringFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Returns the string from aValue according to aUnits (inch, mm ...) for display.
Definition: eda_units.cpp:300
KICOMMON_API double DoubleValueFromString(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Function DoubleValueFromString converts aTextValue to a double.
Definition: eda_units.cpp:576
KICOMMON_API double ToUserUnit(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnit, double aValue)
Function To_User_Unit convert aValue in internal units to the appropriate user units defined by aUnit...
Definition: eda_units.cpp:259
KICOMMON_API wxString GetLabel(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:155
int GetUserUnits()
Return the currently selected user unit value for the interface.
const int scale
#define INDETERMINATE_ACTION
Definition: ui_common.h:47
#define INDETERMINATE_STATE
Used for holding indeterminate values, such as with multiple selections holding different values or c...
Definition: ui_common.h:46
wxDEFINE_EVENT(DELAY_FOCUS, wxCommandEvent)
wxString valueDescriptionFromLabel(wxStaticText *aLabel)