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