KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pg_editors.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <eda_draw_frame.h>
27#include <widgets/unit_binder.h>
28#include <bitmaps.h>
29#include <frame_type.h>
30#include <kiway_player.h>
31#include <kiway.h>
32#include <wx/filedlg.h>
33#include <wx/intl.h>
34#include <eda_doc.h>
35#include <kiplatform/ui.h>
36#include <kiway_mail.h>
37
38#include <wx/button.h>
39#include <wx/bmpbuttn.h>
40
41#include <wx/log.h>
42
43const wxString PG_UNIT_EDITOR::EDITOR_NAME = wxS( "KiCadUnitEditor" );
44const wxString PG_CHECKBOX_EDITOR::EDITOR_NAME = wxS( "KiCadCheckboxEditor" );
45const wxString PG_COLOR_EDITOR::EDITOR_NAME = wxS( "KiCadColorEditor" );
46const wxString PG_RATIO_EDITOR::EDITOR_NAME = wxS( "KiCadRatioEditor" );
47const wxString PG_FPID_EDITOR::EDITOR_NAME = wxS( "KiCadFpidEditor" );
48const wxString PG_URL_EDITOR::EDITOR_NAME = wxS( "KiCadUrlEditor" );
49
50
52 wxPGTextCtrlEditor(),
53 m_frame( aFrame )
54{
55 m_unitBinder = std::make_unique<PROPERTY_EDITOR_UNIT_BINDER>( m_frame );
56 m_unitBinder->SetUnits( m_frame->GetUserUnits() );
57
59}
60
61
65
66
68{
69 if( !aFrame )
70 return EDITOR_NAME + "NoFrame";
71
72 return EDITOR_NAME + aFrame->GetName();
73}
74
75
77{
78 m_frame = aFrame;
79
80 if( aFrame )
81 {
82 m_unitBinder = std::make_unique<PROPERTY_EDITOR_UNIT_BINDER>( m_frame );
83 m_unitBinder->SetUnits( m_frame->GetUserUnits() );
84 }
85 else
86 {
87 m_unitBinder = nullptr;
88 }
89}
90
91
92wxPGWindowList PG_UNIT_EDITOR::CreateControls( wxPropertyGrid* aPropGrid, wxPGProperty* aProperty,
93 const wxPoint& aPos, const wxSize& aSize ) const
94{
95 wxASSERT( m_unitBinder );
96
97#if wxCHECK_VERSION( 3, 3, 0 )
98 wxString text = aProperty->GetValueAsString( wxPGPropValFormatFlags::EditableValue );
99#else
100 wxString text = aProperty->GetValueAsString( wxPG_EDITABLE_VALUE );
101#endif
102 wxWindow* win = aPropGrid->GenerateEditorTextCtrl( aPos, aSize, text, nullptr, 0,
103 aProperty->GetMaxLength() );
104 wxPGWindowList ret( win, nullptr );
105
106 m_unitBinder->SetControl( win );
107 m_unitBinder->RequireEval();
108 m_unitBinder->SetUnits( m_frame->GetUserUnits() );
109
110 if( PGPROPERTY_DISTANCE* prop = dynamic_cast<PGPROPERTY_DISTANCE*>( aProperty ) )
111 {
112 m_unitBinder->SetCoordType( prop->CoordType() );
113 }
114 else if( dynamic_cast<PGPROPERTY_AREA*>( aProperty) != nullptr )
115 {
116 m_unitBinder->SetDataType( EDA_DATA_TYPE::AREA );
117 }
118 else if( dynamic_cast<PGPROPERTY_ANGLE*>( aProperty ) != nullptr )
119 {
121 m_unitBinder->SetUnits( EDA_UNITS::DEGREES );
122 }
123 else if( dynamic_cast<PGPROPERTY_TIME*>( aProperty ) != nullptr )
124 {
125 m_unitBinder->SetUnits( EDA_UNITS::PS );
126 }
127
128 UpdateControl( aProperty, win );
129
130 return ret;
131}
132
133
134void PG_UNIT_EDITOR::UpdateControl( wxPGProperty* aProperty, wxWindow* aCtrl ) const
135{
136 wxVariant var = aProperty->GetValue();
137
138 if( PGPROPERTY_ANGLE* angleProp = dynamic_cast<PGPROPERTY_ANGLE*>( aProperty ) )
139 {
140 if( var.GetType() == wxT( "EDA_ANGLE" ) )
141 {
142 EDA_ANGLE_VARIANT_DATA* angleData =
143 static_cast<EDA_ANGLE_VARIANT_DATA*>( var.GetData() );
144 m_unitBinder->ChangeAngleValue( angleData->Angle() );
145 }
146 else if( !aProperty->IsValueUnspecified() )
147 {
148 double scale = angleProp->GetScale();
149 m_unitBinder->ChangeDoubleValue( var.GetDouble() / scale );
150 }
151 }
152 else if( var.GetType() == wxT( "std::optional<int>" ) )
153 {
154 auto* variantData = static_cast<STD_OPTIONAL_INT_VARIANT_DATA*>( var.GetData() );
155
156 if( variantData->Value().has_value() )
157 m_unitBinder->ChangeValue( variantData->Value().value() );
158 else
159 m_unitBinder->ChangeValue( wxEmptyString );
160 }
161 else if( var.GetType() == wxPG_VARIANT_TYPE_LONG )
162 {
163 m_unitBinder->ChangeValue( var.GetLong() );
164 }
165 else if( var.GetType() == wxPG_VARIANT_TYPE_LONGLONG )
166 {
167 m_unitBinder->ChangeDoubleValue( var.GetLongLong().ToDouble() );
168 }
169 else if( var.GetType() == wxPG_VARIANT_TYPE_DOUBLE )
170 {
171 m_unitBinder->ChangeValue( var.GetDouble() );
172 }
173 else if( var.GetType() == wxT( "EDA_ANGLE" ) )
174 {
175 EDA_ANGLE_VARIANT_DATA* angleData = static_cast<EDA_ANGLE_VARIANT_DATA*>( var.GetData() );
176 m_unitBinder->ChangeAngleValue( angleData->Angle() );
177 }
178 else if( !aProperty->IsValueUnspecified() )
179 {
180 wxFAIL_MSG( wxT( "PG_UNIT_EDITOR should only be used with numeric properties!" ) );
181 }
182}
183
184
185bool PG_UNIT_EDITOR::OnEvent( wxPropertyGrid* aPropGrid, wxPGProperty* aProperty,
186 wxWindow* aCtrl, wxEvent& aEvent ) const
187{
188 if( aEvent.GetEventType() == wxEVT_LEFT_UP )
189 {
190 if( wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( aCtrl ) )
191 {
192 if( !textCtrl->HasFocus() )
193 {
194 textCtrl->SelectAll();
195 return false;
196 }
197 }
198 }
199
200 return wxPGTextCtrlEditor::OnEvent( aPropGrid, aProperty, aCtrl, aEvent );
201}
202
203
204bool PG_UNIT_EDITOR::GetValueFromControl( wxVariant& aVariant, wxPGProperty* aProperty,
205 wxWindow* aCtrl ) const
206{
207 if( !m_unitBinder )
208 return false;
209
210 wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( aCtrl );
211 wxCHECK_MSG( textCtrl, false, "PG_UNIT_EDITOR requires a text control!" );
212 wxString textVal = textCtrl->GetValue();
213
214 if( textVal == wxT( "<...>" ) )
215 {
216 aVariant.MakeNull();
217 return true;
218 }
219
220 bool changed;
221
222 if( dynamic_cast<PGPROPERTY_ANGLE*>( aProperty ) != nullptr )
223 {
224 EDA_ANGLE angle = m_unitBinder->GetAngleValue();
225
226 if( aVariant.GetType() == wxT( "EDA_ANGLE" ) )
227 {
228 EDA_ANGLE_VARIANT_DATA* ad = static_cast<EDA_ANGLE_VARIANT_DATA*>( aVariant.GetData() );
229 changed = ( aVariant.IsNull() || angle != ad->Angle() );
230
231 if( changed )
232 {
233 ad->SetAngle( angle );
234 m_unitBinder->SetAngleValue( angle );
235 }
236 }
237 else
238 {
239 PGPROPERTY_ANGLE* angleProp = static_cast<PGPROPERTY_ANGLE*>( aProperty );
240 double scaledValue = angle.AsDegrees() * angleProp->GetScale();
241
242 changed = ( aVariant.IsNull() || scaledValue != aVariant.GetDouble() );
243
244 if( changed )
245 {
246 aVariant = scaledValue;
247 m_unitBinder->SetDoubleValue( angle.AsDegrees() );
248 }
249 }
250 }
251 else if( dynamic_cast<PGPROPERTY_AREA*>( aProperty ) != nullptr )
252 {
253 wxLongLongNative result = m_unitBinder->GetValue();
254 changed = ( aVariant.IsNull() || result != aVariant.GetLongLong() );
255
256 if( changed )
257 {
258 aVariant = result;
259 m_unitBinder->SetDoubleValue( result.ToDouble() );
260 }
261 }
262 else if( aVariant.GetType() == wxT( "std::optional<int>" ) )
263 {
264 auto* variantData = static_cast<STD_OPTIONAL_INT_VARIANT_DATA*>( aVariant.GetData() );
265 std::optional<int> result;
266
267 if( m_unitBinder->IsNull() )
268 {
269 changed = ( aVariant.IsNull() || variantData->Value().has_value() );
270
271 if( changed )
272 {
273 aVariant = wxVariant( std::optional<int>() );
274 m_unitBinder->SetValue( wxEmptyString );
275 }
276 }
277 else
278 {
279 result = std::optional<int>( m_unitBinder->GetIntValue() );
280 changed = ( aVariant.IsNull() || result != variantData->Value() );
281
282 if( changed )
283 {
284 aVariant = wxVariant( result );
285 m_unitBinder->SetValue( result.value() );
286 }
287 }
288 }
289 else
290 {
291 long result = m_unitBinder->GetValue();
292 changed = ( aVariant.IsNull() || result != aVariant.GetLong() );
293
294 if( changed )
295 {
296 aVariant = result;
297 m_unitBinder->SetValue( result );
298 }
299 }
300
301 // Changing unspecified always causes event (returning true here should be enough to trigger it).
302 if( !changed && aVariant.IsNull() )
303 changed = true;
304
305 return changed;
306}
307
308
310 wxPGCheckBoxEditor()
311{
312}
313
314
315wxPGWindowList PG_CHECKBOX_EDITOR::CreateControls( wxPropertyGrid* aGrid, wxPGProperty* aProperty,
316 const wxPoint& aPos, const wxSize& aSize ) const
317{
318 // Override wx behavior and toggle unspecified checkboxes to "true"
319 // CreateControls for a checkbox editor is only triggered when the user activates the checkbox
320 // Set the value to false here; the base class will then trigger an event setting it true.
321 if( aProperty->IsValueUnspecified() )
322 aProperty->SetValueFromInt( 0 );
323
324 return wxPGCheckBoxEditor::CreateControls( aGrid, aProperty, aPos, aSize );
325}
326
327
328bool PG_COLOR_EDITOR::OnEvent( wxPropertyGrid* aGrid, wxPGProperty* aProperty, wxWindow* aWindow,
329 wxEvent& aEvent ) const
330{
331 return false;
332}
333
334
335wxPGWindowList PG_COLOR_EDITOR::CreateControls( wxPropertyGrid* aGrid, wxPGProperty* aProperty,
336 const wxPoint& aPos, const wxSize& aSize ) const
337{
338 auto colorProp = dynamic_cast<PGPROPERTY_COLOR4D*>( aProperty );
339
340 if( !colorProp )
341 return nullptr;
342
343 KIGFX::COLOR4D color = colorFromProperty( aProperty );
344 KIGFX::COLOR4D defColor = colorFromVariant( colorProp->GetDefaultValue() );
345
346 COLOR_SWATCH* editor = new COLOR_SWATCH( aGrid->GetPanel(), color, wxID_ANY,
347 colorProp->GetBackgroundColor(), defColor,
348 SWATCH_LARGE, true );
349 editor->SetPosition( aPos );
350 editor->SetSize( aSize );
351
352 // Capture property name instead of pointer to avoid dangling pointer if grid is rebuilt
353 wxString propName = colorProp->GetName();
354
355 editor->Bind( COLOR_SWATCH_CHANGED,
356 [=]( wxCommandEvent& aEvt )
357 {
358 wxPGProperty* prop = aGrid->GetPropertyByName( propName );
359
360 if( prop )
361 {
362 wxVariant val;
363 auto data = new COLOR4D_VARIANT_DATA( editor->GetSwatchColor() );
364 val.SetData( data );
365 aGrid->ChangePropertyValue( prop, val );
366 }
367 } );
368
369#if wxCHECK_VERSION( 3, 3, 0 )
370 if( aGrid->GetInternalFlags() & wxPropertyGrid::wxPG_FL_ACTIVATION_BY_CLICK )
371#else
372 if( aGrid->GetInternalFlags() & wxPG_FL_ACTIVATION_BY_CLICK )
373#endif
374 {
375 aGrid->CallAfter(
376 [=]()
377 {
378 editor->GetNewSwatchColor();
379
380 wxPGProperty* prop = aGrid->GetPropertyByName( propName );
381
382 if( prop )
383 aGrid->DrawItem( prop );
384 } );
385 }
386
387 return editor;
388}
389
390
391void PG_COLOR_EDITOR::UpdateControl( wxPGProperty* aProperty, wxWindow* aCtrl ) const
392{
393 if( auto swatch = dynamic_cast<COLOR_SWATCH*>( aCtrl ) )
394 swatch->SetSwatchColor( colorFromProperty( aProperty ), false );
395}
396
397
398KIGFX::COLOR4D PG_COLOR_EDITOR::colorFromVariant( const wxVariant& aVariant ) const
399{
401 COLOR4D_VARIANT_DATA* data = nullptr;
402
403 if( aVariant.IsType( wxS( "COLOR4D" ) ) )
404 {
405 data = static_cast<COLOR4D_VARIANT_DATA*>( aVariant.GetData() );
406 color = data->Color();
407 }
408
409 return color;
410}
411
412
414{
415 return colorFromVariant( aProperty->GetValue() );
416}
417
418
419bool PG_RATIO_EDITOR::GetValueFromControl( wxVariant& aVariant, wxPGProperty* aProperty,
420 wxWindow* aCtrl ) const
421{
422 wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( aCtrl );
423 wxCHECK_MSG( textCtrl, false, "PG_RATIO_EDITOR requires a text control!" );
424 wxString textVal = textCtrl->GetValue();
425
426 if( textVal == wxT( "<...>" ) )
427 {
428 aVariant.MakeNull();
429 return true;
430 }
431
432 bool changed;
433
434 if( aVariant.GetType() == wxT( "std::optional<double>" ) )
435 {
436 auto* variantData = static_cast<STD_OPTIONAL_DOUBLE_VARIANT_DATA*>( aVariant.GetData() );
437
438 if( textVal.empty() )
439 {
440 changed = ( aVariant.IsNull() || variantData->Value().has_value() );
441
442 if( changed )
443 aVariant = wxVariant( std::optional<double>() );
444 }
445 else
446 {
447 // One could argue that 1.0 would be a better default for a ratio, but we currently
448 // only use this for solder paste margins, where 0.0 makes more sense.
449 double dblValue = 0.0;
450 textVal.ToDouble( &dblValue );
451 std::optional<double> result( dblValue );
452 changed = ( aVariant.IsNull() || result != variantData->Value() );
453
454 if( changed )
455 {
456 aVariant = wxVariant( result );
457 textCtrl->SetValue( wxString::Format( wxS( "%g" ), dblValue ) );
458 }
459 }
460 }
461 else
462 {
463 // One could argue that 1.0 would be a better default for a ratio, but we currently
464 // only use this for solder paste margins, where 0.0 makes more sense.
465 double result = 0.0;
466 textVal.ToDouble( &result );
467 changed = ( aVariant.IsNull() || result != aVariant.GetDouble() );
468
469 if( changed )
470 {
471 aVariant = result;
472 textCtrl->SetValue( wxString::Format( wxS( "%g" ), result ) );
473 }
474 }
475
476 // Changing unspecified always causes event (returning true here should be enough to trigger it).
477 if( !changed && aVariant.IsNull() )
478 changed = true;
479
480 return changed;
481}
482
483
484void PG_RATIO_EDITOR::UpdateControl( wxPGProperty* aProperty, wxWindow* aCtrl ) const
485{
486 wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>( aCtrl );
487 wxVariant var = aProperty->GetValue();
488
489 wxCHECK_MSG( textCtrl, /*void*/, wxT( "PG_RATIO_EDITOR must be used with a textCtrl!" ) );
490
491 if( var.GetType() == wxT( "std::optional<double>" ) )
492 {
493 auto* variantData = static_cast<STD_OPTIONAL_DOUBLE_VARIANT_DATA*>( var.GetData() );
494 wxString strValue;
495
496 if( variantData->Value().has_value() )
497 strValue = wxString::Format( wxS( "%g" ), variantData->Value().value() );
498
499 textCtrl->ChangeValue( strValue );
500 }
501 else if( var.GetType() == wxPG_VARIANT_TYPE_DOUBLE )
502 {
503 textCtrl->ChangeValue( wxString::Format( wxS( "%g" ), var.GetDouble() ) );
504 }
505 else if( !aProperty->IsValueUnspecified() )
506 {
507 wxFAIL_MSG( wxT( "PG_RATIO_EDITOR should only be used with scale-free numeric properties!" ) );
508 }
509}
510
511
512PG_FPID_EDITOR::PG_FPID_EDITOR( EDA_DRAW_FRAME* aFrame, const std::function<std::string()>& aNetlistCallback ) :
513 m_frame( aFrame ),
514 m_netlistCallback( aNetlistCallback )
515{
516 m_editorName = BuildEditorName( aFrame );
517}
518
519
521{
522 m_frame = aFrame;
523 m_editorName = BuildEditorName( aFrame );
524}
525
526
527void PG_FPID_EDITOR::UpdateCallback( const std::function<std::string()>& aNetlistCallback )
528{
529 m_netlistCallback = aNetlistCallback;
530}
531
532
534{
535 if( !aFrame )
536 return EDITOR_NAME + "NoFrame";
537
538 return EDITOR_NAME + aFrame->GetName();
539}
540
541
542wxPGWindowList PG_FPID_EDITOR::CreateControls( wxPropertyGrid* aGrid, wxPGProperty* aProperty,
543 const wxPoint& aPos, const wxSize& aSize ) const
544{
545 wxPGMultiButton* buttons = new wxPGMultiButton( aGrid, aSize );
546 buttons->Add( KiBitmap( BITMAPS::small_library ) );
547 buttons->Finalize( aGrid, aPos );
548 wxSize textSize = buttons->GetPrimarySize();
549 wxWindow* textCtrl = aGrid->GenerateEditorTextCtrl( aPos, textSize, aProperty->GetValueAsString(),
550 nullptr, 0, aProperty->GetMaxLength() );
551 wxPGWindowList ret( textCtrl, buttons );
552 return ret;
553}
554
555
556bool PG_FPID_EDITOR::OnEvent( wxPropertyGrid* aGrid, wxPGProperty* aProperty, wxWindow* aCtrl,
557 wxEvent& aEvent ) const
558{
559 if( aEvent.GetEventType() == wxEVT_BUTTON )
560 {
561 if( !m_frame )
562 return true;
563
564 wxString fpid = aProperty->GetValue().GetString();
565
566 if( KIWAY_PLAYER* frame = m_frame->Kiway().Player( FRAME_FOOTPRINT_CHOOSER, true, m_frame ) )
567 {
568 // Create symbol netlist for footprint picker
569 std::string symbolNetlist = m_netlistCallback();
570
571 if( !symbolNetlist.empty() )
572 {
574 frame->KiwayMailIn( event );
575 }
576
577 if( frame->ShowModal( &fpid, m_frame ) )
578 aGrid->ChangePropertyValue( aProperty, fpid );
579
580 frame->Destroy();
581 }
582
583 return true;
584 }
585
586 return wxPGTextCtrlEditor::OnEvent( aGrid, aProperty, aCtrl, aEvent );
587}
588
589
591{
592 m_editorName = BuildEditorName( aFrame );
593}
594
595
597{
598 m_frame = aFrame;
599 m_editorName = BuildEditorName( aFrame );
600}
601
602
604{
605 if( !aFrame )
606 return EDITOR_NAME + "NoFrame";
607
608 return EDITOR_NAME + aFrame->GetName();
609}
610
611
612wxPGWindowList PG_URL_EDITOR::CreateControls( wxPropertyGrid* aGrid, wxPGProperty* aProperty,
613 const wxPoint& aPos, const wxSize& aSize ) const
614{
615 wxPGMultiButton* buttons = new wxPGMultiButton( aGrid, aSize );
616 // Use a folder icon when no datasheet is set; otherwise use a globe icon.
617 wxString urlValue = aProperty->GetValueAsString();
618 bool hasUrl = !( urlValue.IsEmpty() || urlValue == wxS( "~" ) );
619 buttons->Add( KiBitmap( hasUrl ? BITMAPS::www : BITMAPS::small_folder ) );
620 buttons->Finalize( aGrid, aPos );
621 wxSize textSize = buttons->GetPrimarySize();
622 wxWindow* textCtrl = aGrid->GenerateEditorTextCtrl( aPos, textSize,
623 aProperty->GetValueAsString(), nullptr, 0,
624 aProperty->GetMaxLength() );
625 wxPGWindowList ret( textCtrl, buttons );
626 return ret;
627}
628
629
630bool PG_URL_EDITOR::OnEvent( wxPropertyGrid* aGrid, wxPGProperty* aProperty, wxWindow* aCtrl,
631 wxEvent& aEvent ) const
632{
633 if( aEvent.GetEventType() == wxEVT_BUTTON )
634 {
635 if( !m_frame )
636 return true;
637
638 wxString filename = aProperty->GetValue().GetString();
639
640 if( filename.IsEmpty() || filename == wxS( "~" ) )
641 {
642 wxFileDialog openFileDialog( m_frame, _( "Open file" ), wxS( "" ), wxS( "" ),
643 _( "All Files" ) + wxS( " (*.*)|*.*" ),
644 wxFD_OPEN | wxFD_FILE_MUST_EXIST );
645
647
648 if( openFileDialog.ShowModal() == wxID_OK )
649 {
650 filename = openFileDialog.GetPath();
651 aGrid->ChangePropertyValue( aProperty, wxString::Format( wxS( "file://%s" ),
652 filename ) );
653 }
654 }
655 else
656 {
657 GetAssociatedDocument( m_frame, filename, &m_frame->Prj() );
658 }
659
660 // Update the button icon to reflect presence/absence of URL
661 if( wxObject* src = aEvent.GetEventObject() )
662 {
663 wxString newUrl = aProperty->GetValueAsString();
664 bool hasUrl = !( newUrl.IsEmpty() || newUrl == wxS( "~" ) );
665 auto bmp = KiBitmap( hasUrl ? BITMAPS::www : BITMAPS::small_folder );
666
667 if( wxWindow* win = wxDynamicCast( src, wxWindow ) )
668 {
669 if( wxBitmapButton* bb = wxDynamicCast( win, wxBitmapButton ) )
670 {
671 bb->SetBitmap( bmp );
672 }
673 else if( wxButton* b = wxDynamicCast( win, wxButton ) )
674 {
675 b->SetBitmap( bmp );
676 }
677 else if( wxWindow* parent = win->GetParent() )
678 {
679 if( wxPGMultiButton* buttons = wxDynamicCast( parent, wxPGMultiButton ) )
680 {
681 wxWindow* btn0 = buttons->GetButton( 0 );
682 if( wxBitmapButton* bb0 = wxDynamicCast( btn0, wxBitmapButton ) )
683 bb0->SetBitmap( bmp );
684 else if( wxButton* b0 = wxDynamicCast( btn0, wxButton ) )
685 b0->SetBitmap( bmp );
686 }
687 }
688 }
689 }
690 return true;
691 }
692
693 return wxPGTextCtrlEditor::OnEvent( aGrid, aProperty, aCtrl, aEvent );
694}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:100
const KIGFX::COLOR4D & Color()
A simple color swatch of the kind used to set layer colors.
const EDA_ANGLE & Angle()
void SetAngle(const EDA_ANGLE &aAngle)
double AsDegrees() const
Definition eda_angle.h:115
The base class for create windows for drawing purpose.
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
Carry a payload from one KIWAY_PLAYER to another within a PROJECT.
Definition kiway_mail.h:34
A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of a KiCad project.
Customized wxPGProperty class to handle angles.
double GetScale() const
Customized abstract wxPGProperty class to handle coordinate/size units.
wxPGWindowList CreateControls(wxPropertyGrid *aGrid, wxPGProperty *aProperty, const wxPoint &aPos, const wxSize &aSize) const override
static const wxString EDITOR_NAME
Definition pg_editors.h:75
static const wxString EDITOR_NAME
Definition pg_editors.h:91
wxPGWindowList CreateControls(wxPropertyGrid *aGrid, wxPGProperty *aProperty, const wxPoint &aPos, const wxSize &aSize) const override
bool OnEvent(wxPropertyGrid *aGrid, wxPGProperty *aProperty, wxWindow *aWindow, wxEvent &aEvent) const override
KIGFX::COLOR4D colorFromVariant(const wxVariant &aVariant) const
void UpdateControl(wxPGProperty *aProperty, wxWindow *aCtrl) const override
KIGFX::COLOR4D colorFromProperty(wxPGProperty *aProperty) const
wxString m_editorName
Definition pg_editors.h:153
void UpdateFrame(EDA_DRAW_FRAME *aFrame)
std::function< std::string()> m_netlistCallback
Definition pg_editors.h:154
PG_FPID_EDITOR(EDA_DRAW_FRAME *aFrame, const std::function< std::string()> &aNetlistCallback)
void UpdateCallback(const std::function< std::string()> &aNetlistCallback)
wxPGWindowList CreateControls(wxPropertyGrid *aGrid, wxPGProperty *aProperty, const wxPoint &aPos, const wxSize &aSize) const override
static const wxString EDITOR_NAME
Definition pg_editors.h:131
EDA_DRAW_FRAME * m_frame
Definition pg_editors.h:152
static wxString BuildEditorName(EDA_DRAW_FRAME *aFrame)
bool OnEvent(wxPropertyGrid *aGrid, wxPGProperty *aProperty, wxWindow *aCtrl, wxEvent &aEvent) const override
bool GetValueFromControl(wxVariant &aVariant, wxPGProperty *aProperty, wxWindow *aCtrl) const override
static const wxString EDITOR_NAME
Definition pg_editors.h:117
void UpdateControl(wxPGProperty *aProperty, wxWindow *aCtrl) const override
std::unique_ptr< PROPERTY_EDITOR_UNIT_BINDER > m_unitBinder
Definition pg_editors.h:66
wxPGWindowList CreateControls(wxPropertyGrid *aPropGrid, wxPGProperty *aProperty, const wxPoint &aPos, const wxSize &aSize) const override
static const wxString EDITOR_NAME
Definition pg_editors.h:34
void UpdateControl(wxPGProperty *aProperty, wxWindow *aCtrl) const override
void UpdateFrame(EDA_DRAW_FRAME *aFrame)
When restarting an editor, the instance of PG_UNIT_EDITOR may be the same but the referenced frame is...
EDA_DRAW_FRAME * m_frame
Definition pg_editors.h:64
PG_UNIT_EDITOR(EDA_DRAW_FRAME *aFrame)
bool GetValueFromControl(wxVariant &aVariant, wxPGProperty *aProperty, wxWindow *aCtrl) const override
wxString m_editorName
Definition pg_editors.h:68
bool OnEvent(wxPropertyGrid *aPropGrid, wxPGProperty *aProperty, wxWindow *aCtrl, wxEvent &aEvent) const override
static wxString BuildEditorName(EDA_DRAW_FRAME *aFrame)
virtual ~PG_UNIT_EDITOR()
static const wxString EDITOR_NAME
Definition pg_editors.h:161
PG_URL_EDITOR(EDA_DRAW_FRAME *aFrame)
wxString m_editorName
Definition pg_editors.h:181
static wxString BuildEditorName(EDA_DRAW_FRAME *aFrame)
void UpdateFrame(EDA_DRAW_FRAME *aFrame)
EDA_DRAW_FRAME * m_frame
Definition pg_editors.h:180
wxPGWindowList CreateControls(wxPropertyGrid *aGrid, wxPGProperty *aProperty, const wxPoint &aPos, const wxSize &aSize) const override
bool OnEvent(wxPropertyGrid *aGrid, wxPGProperty *aProperty, wxWindow *aCtrl, wxEvent &aEvent) const override
@ SWATCH_LARGE
#define _(s)
bool GetAssociatedDocument(wxWindow *aParent, const wxString &aDocName, PROJECT *aProject, SEARCH_STACK *aPaths, std::vector< EMBEDDED_FILES * > aFilesStack)
Open a document (file) with the suitable browser.
Definition eda_doc.cpp:59
This file is part of the common library.
@ FRAME_FOOTPRINT_CHOOSER
Definition frame_type.h:40
@ MAIL_SYMBOL_NETLIST
Definition mail_type.h:41
void AllowNetworkFileSystems(wxDialog *aDialog)
Configure a file dialog to show network and virtual file systems.
Definition wxgtk/ui.cpp:533
static std::string strValue(double aValue)
const int scale
wxString result
Test unit parsing edge cases and error handling.