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 The 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
37using namespace EDA_UNIT_UTILS::UI;
38
39
40wxDEFINE_EVENT( DELAY_FOCUS, wxCommandEvent );
41
42
43UNIT_BINDER::UNIT_BINDER( EDA_DRAW_FRAME* aParent, wxStaticText* aLabel, wxWindow* aValueCtrl,
44 wxStaticText* aUnitLabel, bool allowEval, bool aBindFrameEvents ) :
45 UNIT_BINDER( aParent, aParent, aLabel, aValueCtrl, aUnitLabel, allowEval, aBindFrameEvents )
46{
47}
48
49UNIT_BINDER::UNIT_BINDER( UNITS_PROVIDER* aUnitsProvider, wxWindow* aEventSource,
50 wxStaticText* aLabel, wxWindow* aValueCtrl, wxStaticText* aUnitLabel,
51 bool aAllowEval, bool aBindFocusEvent ) :
52 m_bindFocusEvent( aBindFocusEvent ),
53 m_label( aLabel ),
54 m_valueCtrl( aValueCtrl ),
55 m_eventSource( aEventSource ),
56 m_unitLabel( aUnitLabel ),
57 m_iuScale( &aUnitsProvider->GetIuScale() ),
58 m_negativeZero( false ),
59 m_dataType( EDA_DATA_TYPE::DISTANCE ),
60 m_precision( 0 ),
61 m_eval( aUnitsProvider->GetUserUnits() ),
62 m_unitsInValue( false ),
63 m_originTransforms( aUnitsProvider->GetOriginTransforms() ),
64 m_coordType( ORIGIN_TRANSFORMS::NOT_A_COORD )
65{
66 init( aUnitsProvider );
67 m_allowEval = aAllowEval && ( !m_valueCtrl || dynamic_cast<wxTextEntry*>( m_valueCtrl ) );
68 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
69
70 if( textEntry )
71 {
72 wxClientDC dc( m_valueCtrl );
73
74 // Gives enough room to display a value in inches in textEntry
75 // 3 digits + '.' + 10 digits
76 wxSize minSize = m_valueCtrl->GetMinSize();
77 int minWidth = dc.GetTextExtent( wxT( "XXX.XXXXXXXXXX" ) ).GetWidth();
78
79 if( minSize.GetWidth() < minWidth )
80 m_valueCtrl->SetMinSize( wxSize( minWidth, minSize.GetHeight() ) );
81
82 // Use ChangeValue() instead of SetValue() so we don't generate events.
83 if( m_negativeZero )
84 textEntry->ChangeValue( wxT( "-0" ) );
85 else
86 textEntry->ChangeValue( wxT( "0" ) );
87 }
88
89 if( m_unitLabel )
91
92 if( m_valueCtrl )
93 {
94 m_valueCtrl->Connect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), nullptr, this );
95 m_valueCtrl->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), nullptr, this );
96 m_valueCtrl->Connect( wxEVT_LEFT_UP, wxMouseEventHandler( UNIT_BINDER::onClick ), nullptr, this );
97 m_valueCtrl->Connect( wxEVT_COMBOBOX, wxCommandEventHandler( UNIT_BINDER::onComboBox ), nullptr, this );
98 }
99
100 if( m_bindFocusEvent )
101 Connect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), nullptr, this );
102
103 if( m_eventSource )
104 {
105 m_eventSource->Connect( EDA_EVT_UNITS_CHANGED, wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ),
106 nullptr, this );
107 }
108}
109
110
112{
113 if( m_valueCtrl )
114 {
115 m_valueCtrl->Disconnect( wxEVT_SET_FOCUS, wxFocusEventHandler( UNIT_BINDER::onSetFocus ), nullptr, this );
116 m_valueCtrl->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( UNIT_BINDER::onKillFocus ), nullptr, this );
117 m_valueCtrl->Disconnect( wxEVT_LEFT_UP, wxMouseEventHandler( UNIT_BINDER::onClick ), nullptr, this );
118 m_valueCtrl->Disconnect( wxEVT_COMBOBOX, wxCommandEventHandler( UNIT_BINDER::onComboBox ), nullptr, this );
119 }
120
121 if( m_bindFocusEvent )
122 Disconnect( DELAY_FOCUS, wxCommandEventHandler( UNIT_BINDER::delayedFocusHandler ), nullptr, this );
123
124 if( m_eventSource )
125 {
126 m_eventSource->Disconnect( EDA_EVT_UNITS_CHANGED, wxCommandEventHandler( UNIT_BINDER::onUnitsChanged ),
127 nullptr, this );
128 }
129}
130
131
133{
134 m_units = aProvider->GetUserUnits();
135 m_needsEval = false;
136 m_selStart = 0;
137 m_selEnd = 0;
138}
139
140
142{
143 m_units = aUnits;
144
146 m_eval.LocaleChanged(); // In case locale changed since last run
147
148 if( m_unitLabel )
150}
151
152
153void UNIT_BINDER::SetPrecision( int aLength )
154{
155 m_precision = std::min( aLength, 6 );
156}
157
158
160{
161 m_dataType = aDataType;
162
163 if( m_unitLabel )
165}
166
167
168void UNIT_BINDER::onUnitsChanged( wxCommandEvent& aEvent )
169{
170 EDA_BASE_FRAME* provider = static_cast<EDA_BASE_FRAME*>( aEvent.GetClientData() );
171
172 if( m_units != EDA_UNITS::UNSCALED
173 && m_units != EDA_UNITS::DEGREES
174 && m_units != EDA_UNITS::PERCENT )
175 {
176 int temp = GetIntValue();
177
178 wxComboBox* const combo = dynamic_cast<wxComboBox*>( m_valueCtrl );
179 std::vector<long long int> comboValues;
180
181 // Read out the current values
182 if( combo )
183 {
184 for( unsigned int i = 0; i < combo->GetCount(); i++ )
185 {
186 const wxString value = combo->GetString( i );
187 long long int conv = ValueFromString( *m_iuScale, m_units, value, m_dataType );
188 comboValues.push_back( conv );
189 }
190 }
191
192 SetUnits( provider->GetUserUnits() );
193 m_iuScale = &provider->GetIuScale();
194
195 // Re-populate the combo box with updated values
196 if( combo )
197 {
198 SetOptionsList( comboValues );
199 }
200
201 if( !IsIndeterminate() )
202 SetValue( temp );
203 }
204
205 aEvent.Skip();
206}
207
208
209void UNIT_BINDER::onClick( wxMouseEvent& aEvent )
210{
211 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
212
213 if( textEntry && ( textEntry->GetValue() == INDETERMINATE_ACTION
214 || textEntry->GetValue() == INDETERMINATE_STATE ) )
215 {
216 // These are tokens, not strings, so do a select all
217 textEntry->SelectAll();
218 }
219
220 // Needed at least on Windows to avoid hanging
221 aEvent.Skip();
222}
223
224
225void UNIT_BINDER::onComboBox( wxCommandEvent& aEvent )
226{
227 wxComboBox* combo = dynamic_cast<wxComboBox*>( m_valueCtrl );
228 wxCHECK( combo, /*void*/ );
229
230 const wxString value = combo->GetStringSelection();
231 const long long int conv = ValueFromString( *m_iuScale, m_units, value, m_dataType );
232
233 SetValue( conv );
234
235 aEvent.Skip();
236}
237
238
239void UNIT_BINDER::onSetFocus( wxFocusEvent& aEvent )
240{
241 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
242
243 if( textEntry )
244 {
245 if( m_allowEval )
246 {
247 wxString oldStr = m_eval.OriginalText();
248
249 if( oldStr.length() && oldStr != textEntry->GetValue() )
250 {
251 textEntry->ChangeValue( oldStr );
252 textEntry->SetSelection( m_selStart, m_selEnd );
253 }
254
255 m_needsEval = true;
256 }
257
258 if( textEntry->GetValue() == INDETERMINATE_ACTION
259 || textEntry->GetValue() == INDETERMINATE_STATE )
260 {
261 // These are tokens, not strings, so do a select all
262 textEntry->SelectAll();
263 }
264 }
265
266 aEvent.Skip();
267}
268
269
270void UNIT_BINDER::onKillFocus( wxFocusEvent& aEvent )
271{
272 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
273
274 if( m_allowEval && textEntry )
275 {
276 wxString value = textEntry->GetValue();
277 bool success = m_eval.Process( value );
278
279 if( success && !value.IsEmpty() )
280 {
281 textEntry->GetSelection( &m_selStart, &m_selEnd );
282
283 value = m_eval.Result();
284
285 if( m_unitsInValue && !value.IsEmpty() )
286 {
287 if( !( m_units == EDA_UNITS::DEGREES || m_units == EDA_UNITS::PERCENT ) )
288 value += wxT( " " );
289
291 }
292
293 textEntry->ChangeValue( value );
294
295#ifdef __WXGTK__
296 // Manually copy the selected text to the primary selection clipboard
297 if( wxTheClipboard->Open() )
298 {
299 wxString sel = textEntry->GetStringSelection();
300 bool clipTarget = wxTheClipboard->IsUsingPrimarySelection();
301 wxTheClipboard->UsePrimarySelection( true );
302 wxTheClipboard->SetData( new wxTextDataObject( sel ) );
303 wxTheClipboard->UsePrimarySelection( clipTarget );
304 wxTheClipboard->Close();
305 }
306#endif
307 }
308
309 m_needsEval = false;
310 }
311
312 aEvent.Skip();
313}
314
315
316wxString valueDescriptionFromLabel( wxStaticText* aLabel )
317{
318 wxString desc = aLabel->GetLabel();
319
320 desc.EndsWith( wxT( ":" ), &desc );
321 return desc;
322}
323
324
325void UNIT_BINDER::delayedFocusHandler( wxCommandEvent& )
326{
327 if( !m_errorMessage.IsEmpty() )
329
330 m_errorMessage = wxEmptyString;
331 m_valueCtrl->SetFocus();
332}
333
334
335bool UNIT_BINDER::Validate( double aMin, double aMax, EDA_UNITS aUnits )
336{
337 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
338
339 if( !textEntry
340 || textEntry->GetValue() == INDETERMINATE_ACTION
341 || textEntry->GetValue() == INDETERMINATE_STATE )
342 {
343 return true;
344 }
345
346 // TODO: Validate() does not currently support m_dataType being anything other than DISTANCE
347 // Note: aMin and aMax are not always given in internal units
348 if( GetValue() < FromUserUnit( *m_iuScale, aUnits, aMin ) )
349 {
350 double val_min_iu = FromUserUnit( *m_iuScale, aUnits, aMin );
351 m_errorMessage = wxString::Format( _( "%s must be at least %s." ),
353 StringFromValue( *m_iuScale, m_units, val_min_iu, true ) );
354
355 textEntry->SelectAll();
356
357 // Don't focus directly; we might be inside a KillFocus event handler
358 wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
359
360 return false;
361 }
362
363 if( GetValue() > FromUserUnit( *m_iuScale, aUnits, aMax ) )
364 {
365 double val_max_iu = FromUserUnit( *m_iuScale, aUnits, aMax );
366 m_errorMessage = wxString::Format( _( "%s must be less than %s." ),
368 StringFromValue( *m_iuScale, m_units, val_max_iu, true ) );
369
370 textEntry->SelectAll();
371
372 // Don't focus directly; we might be inside a KillFocus event handler
373 wxPostEvent( this, wxCommandEvent( DELAY_FOCUS ) );
374
375 return false;
376 }
377
378 return true;
379}
380
381
382void UNIT_BINDER::SetValue( long long int aValue )
383{
384 double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
385 wxString textValue = StringFromValue( *m_iuScale, m_units, displayValue, false, m_dataType );
386
387 if( displayValue == 0 && m_negativeZero )
388 SetValue( wxT( "-" ) + textValue );
389 else
390 SetValue( textValue );
391}
392
393
394void UNIT_BINDER::SetDoubleValue( double aValue )
395{
396 double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
397 wxString textValue = StringFromValue( *m_iuScale, m_units, setPrecision( displayValue, false ), false,
398 m_dataType );
399
400 if( displayValue == 0 && !std::signbit( displayValue ) && m_negativeZero )
401 SetValue( wxT( "-" ) + textValue );
402 else
403 SetValue( textValue );
404}
405
406
408{
409 SetDoubleValue( aValue.AsDegrees() );
410}
411
412
413void UNIT_BINDER::SetValue( const wxString& aValue )
414{
415 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
416 wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
417
418 wxString value = aValue;
419
420 if( m_unitsInValue && !value.IsEmpty() )
421 {
422 if( !( m_units == EDA_UNITS::DEGREES || m_units == EDA_UNITS::PERCENT ) )
423 value += wxT( " " );
424
426 }
427
428 if( textEntry )
429 textEntry->SetValue( value );
430 else if( staticText )
431 staticText->SetLabel( value );
432
433 if( m_allowEval )
434 m_eval.Clear();
435
436 if( m_unitLabel )
438
439}
440
441
442wxString UNIT_BINDER::getTextForValue( long long int aValue ) const
443{
444 const double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
445 wxString textValue = StringFromValue( *m_iuScale, m_units, setPrecision( displayValue, false ), false,
446 m_dataType );
447
448 if( displayValue == 0 && m_negativeZero )
449 textValue = wxT( "-" ) + textValue;
450
451 return textValue;
452}
453
454
455wxString UNIT_BINDER::getTextForDoubleValue( double aValue ) const
456{
457 const double displayValue = m_originTransforms.ToDisplay( aValue, m_coordType );
458 wxString textValue = StringFromValue( *m_iuScale, m_units, setPrecision( displayValue, false ), false,
459 m_dataType );
460
461 if( displayValue == 0 && !std::signbit( displayValue ) && m_negativeZero )
462 textValue = wxT( "-" ) + textValue;
463
464 return textValue;
465}
466
467
468void UNIT_BINDER::ChangeValue( int aValue )
469{
470 ChangeValue( getTextForValue( aValue ) );
471}
472
473
475{
477}
478
479
481{
482 ChangeDoubleValue( aValue.AsDegrees() );
483}
484
485
486void UNIT_BINDER::ChangeValue( const wxString& aValue )
487{
488 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
489 wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
490
491 wxString value = aValue;
492
493 if( m_unitsInValue && !value.IsEmpty() )
494 {
495 if( !( m_units == EDA_UNITS::DEGREES || m_units == EDA_UNITS::PERCENT ) )
496 value += wxT( " " );
497
499 }
500
501 if( textEntry )
502 textEntry->ChangeValue( value );
503 else if( staticText )
504 staticText->SetLabel( value );
505
506 if( m_allowEval )
507 m_eval.Clear();
508
509 if( m_unitLabel )
511}
512
513
515{
516 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
517 wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
518 wxString value;
519
520 if( textEntry )
521 {
522 value = textEntry->GetValue();
523
524 if( m_needsEval && !value.IsEmpty() && m_eval.Process( value ) )
525 value = m_eval.Result();
526 else
527 value = textEntry->GetValue();
528 }
529 else if( staticText )
530 {
531 value = staticText->GetLabel();
532 }
533 else
534 {
535 return 0;
536 }
537
538 long long int displayValue = ValueFromString( *m_iuScale, m_units, value, m_dataType );
539 return m_originTransforms.FromDisplay( displayValue, m_coordType );
540}
541
542
543double UNIT_BINDER::setPrecision( double aValue, bool aValueUsesUserUnits ) const
544{
545 if( m_precision > 1 )
546 {
547 int scale = pow( 10, m_precision );
548 int64_t tmp = aValue;
549
550 if( !aValueUsesUserUnits )
551 tmp = ToUserUnit( *m_iuScale, m_units, aValue ) * scale;
552
553 aValue = static_cast<double>( tmp ) / scale;
554
555 if( !aValueUsesUserUnits )
556 aValue = FromUserUnit( *m_iuScale, m_units, aValue );
557 }
558
559 return aValue;
560}
561
562
564{
565 wxTextEntry* textEntry = dynamic_cast<wxTextEntry*>( m_valueCtrl );
566 wxStaticText* staticText = dynamic_cast<wxStaticText*>( m_valueCtrl );
567 wxString value;
568
569 if( textEntry )
570 {
571 value = textEntry->GetValue();
572
573 if( m_needsEval && !value.IsEmpty() && m_eval.Process( value ) )
574 value = m_eval.Result();
575 else
576 value = textEntry->GetValue();
577 }
578 else if( staticText )
579 {
580 value = staticText->GetLabel();
581 }
582 else
583 {
584 return 0.0;
585 }
586
587 double displayValue = DoubleValueFromString( *m_iuScale, m_units, value, m_dataType );
588 displayValue = setPrecision( displayValue, false );
589
590 return m_originTransforms.FromDisplay( displayValue, m_coordType );
591}
592
593
595{
597}
598
599
600void UNIT_BINDER::SetOptionsList( std::span<const long long int> aOptions )
601{
602 wxComboBox* cb = dynamic_cast<wxComboBox*>( m_valueCtrl );
603 wxCHECK( cb, /* void */ );
604
605 cb->Clear();
606
607 for( long long int value : aOptions )
608 cb->Append( getTextForValue( value ) );
609}
610
611
612void UNIT_BINDER::SetDoubleOptionsList( std::span<const double> aOptions )
613{
614 wxComboBox* cb = dynamic_cast<wxComboBox*>( m_valueCtrl );
615 wxCHECK( cb, /* void */ );
616
617 cb->Clear();
618
619 for( double value : aOptions )
620 cb->Append( getTextForDoubleValue( value ) );
621}
622
623
625{
626 wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl );
627
628 if( te )
629 return te->GetValue() == INDETERMINATE_STATE || te->GetValue() == INDETERMINATE_ACTION;
630
631 return false;
632}
633
634
636{
637 if( wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl ) )
638 return te->GetValue().IsEmpty();
639
640 return false;
641}
642
643
645{
646 if( wxTextEntry* te = dynamic_cast<wxTextEntry*>( m_valueCtrl ) )
647 return te->SetValue( wxEmptyString );
648}
649
650
651void UNIT_BINDER::SetLabel( const wxString& aLabel )
652{
653 m_label->SetLabel( aLabel );
654}
655
656
657void UNIT_BINDER::Enable( bool aEnable )
658{
659 if( m_label )
660 m_label->Enable( aEnable );
661
662 m_valueCtrl->Enable( aEnable );
663
664 if( m_unitLabel )
665 m_unitLabel->Enable( aEnable );
666}
667
668
669void UNIT_BINDER::Show( bool aShow, bool aResize )
670{
671 m_label->Show( aShow );
672 m_valueCtrl->Show( aShow );
673
674 if( m_unitLabel )
675 m_unitLabel->Show( aShow );
676
677 if( aResize )
678 {
679 if( aShow )
680 {
681 m_label->SetSize( -1, -1 );
682 m_valueCtrl->SetSize( -1, -1 );
683
684 if( m_unitLabel )
685 m_unitLabel->SetSize( -1, -1 );
686 }
687 else
688 {
689 m_label->SetSize( 0, 0 );
690 m_valueCtrl->SetSize( 0, 0 );
691
692 if( m_unitLabel )
693 m_unitLabel->SetSize( 0, 0 );
694 }
695 }
696}
697
698
700 UNIT_BINDER( aParent, nullptr, nullptr, nullptr, true, false )
701{
702 m_unitsInValue = true;
703}
704
705
707{
708}
709
711{
712 m_valueCtrl = aControl;
713
714 if( m_valueCtrl )
715 {
716 m_valueCtrl->Bind( wxEVT_SET_FOCUS, &PROPERTY_EDITOR_UNIT_BINDER::onSetFocus, this );
717 m_valueCtrl->Bind( wxEVT_KILL_FOCUS, &PROPERTY_EDITOR_UNIT_BINDER::onKillFocus, this );
718 m_valueCtrl->Bind( wxEVT_LEFT_UP, &PROPERTY_EDITOR_UNIT_BINDER::onClick, this );
719
720 m_valueCtrl->Bind( wxEVT_SHOW,
721 [&]( wxShowEvent& e )
722 {
723 if( !e.IsShown() )
724 SetControl( nullptr );
725 } );
726 }
727}
double AsDegrees() const
Definition: eda_angle.h:116
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:271
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:259
wxString getTextForDoubleValue(double aValue) const
const EDA_IU_SCALE * m_iuScale
Currently used units.
Definition: unit_binder.h:250
wxString m_errorMessage
Definition: unit_binder.h:256
virtual EDA_ANGLE GetAngleValue()
bool m_negativeZero
Indicates "-0" should be displayed for 0.
Definition: unit_binder.h:252
int m_precision
0 to 6.
Definition: unit_binder.h:254
wxStaticText * m_unitLabel
Can be nullptr.
Definition: unit_binder.h:247
bool m_unitsInValue
Units label should be included in value text.
Definition: unit_binder.h:265
wxWindow * m_valueCtrl
Definition: unit_binder.h:245
wxWindow * m_eventSource
Definition: unit_binder.h:246
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:43
wxStaticText * m_label
The bound widgets.
Definition: unit_binder.h:244
ORIGIN_TRANSFORMS & m_originTransforms
A reference to an ORIGIN_TRANSFORMS object.
Definition: unit_binder.h:268
bool m_bindFocusEvent
Definition: unit_binder.h:241
long m_selStart
Selection start and end of the original text.
Definition: unit_binder.h:262
virtual void SetDoubleOptionsList(std::span< const double > aOptions)
EDA_UNITS m_units
Definition: unit_binder.h:251
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:260
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:253
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.
void SetNull()
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:258
bool IsNull() const
Return true if the control holds no value (ie: empty string, not 0).
void onUnitsChanged(wxCommandEvent &aEvent)
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition: confirm.cpp:194
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:48
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:499
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)
Convert aTextValue in aUnits to internal units used by the application.
Definition: eda_units.cpp:679
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)
Return the string from aValue according to aUnits (inch, mm ...) for display.
Definition: eda_units.cpp:310
KICOMMON_API double DoubleValueFromString(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Convert aTextValue to a double.
Definition: eda_units.cpp:559
KICOMMON_API double ToUserUnit(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnit, double aValue)
Convert aValue in internal units to the appropriate user units defined by aUnit.
Definition: eda_units.cpp:289
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:180
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)