KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_properties_panel.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) 2020 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 3
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 along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
23
24#include <font/fontconfig.h>
25#include <pgm_base.h>
26#include <connection_graph.h>
30#include <sch_commit.h>
31#include <sch_edit_frame.h>
32#include <symbol_edit_frame.h>
33#include <symbol_viewer_frame.h>
34#include <schematic.h>
35#include <sch_symbol.h>
36#include <sch_field.h>
37#include <template_fieldnames.h>
39#include <string_utils.h>
40#include <tool/tool_manager.h>
42#include <set>
43
44static const wxString MISSING_FIELD_SENTINEL = wxS( "\uE000" );
45
47{
48public:
49 SCH_SYMBOL_FIELD_PROPERTY( const wxString& aName ) :
50 PROPERTY_BASE( aName ),
51 m_name( aName )
52 {
53 }
54
55 size_t OwnerHash() const override { return TYPE_HASH( SCH_SYMBOL ); }
56 size_t BaseHash() const override { return TYPE_HASH( SCH_SYMBOL ); }
57 size_t TypeHash() const override { return TYPE_HASH( wxString ); }
58
59 bool Writeable( INSPECTABLE* aObject ) const override
60 {
61 return PROPERTY_BASE::Writeable( aObject );
62 }
63
64 void setter( void* obj, wxAny& v ) override
65 {
66 wxString value;
67
68 if( !v.GetAs( &value ) )
69 return;
70
71 SCH_SYMBOL* symbol = reinterpret_cast<SCH_SYMBOL*>( obj );
72 SCH_FIELD* field = symbol->GetField( m_name );
73
74 if( !field )
75 {
76 SCH_FIELD newField( symbol, FIELD_T::USER, m_name );
77 newField.SetText( value );
78 symbol->AddField( newField );
79 }
80 else
81 {
82 field->SetText( value );
83 }
84 }
85
86 wxAny getter( const void* obj ) const override
87 {
88 const SCH_SYMBOL* symbol = reinterpret_cast<const SCH_SYMBOL*>( obj );
89 const SCH_FIELD* field = symbol->GetField( m_name );
90
91 if( field )
92 return wxAny( field->GetText() );
93 else
94 return wxAny( MISSING_FIELD_SENTINEL );
95 }
96
97private:
98 wxString m_name;
99};
100
102
104 PROPERTIES_PANEL( aParent, aFrame ),
105 m_frame( aFrame ),
106 m_propMgr( PROPERTY_MANAGER::Instance() )
107{
108 m_propMgr.Rebuild();
109 bool found = false;
110
111 wxASSERT( wxPGGlobalVars );
112
113 wxString editorKey = PG_UNIT_EDITOR::BuildEditorName( m_frame );
114
115 auto it = wxPGGlobalVars->m_mapEditorClasses.find( editorKey );
116
117 if( it != wxPGGlobalVars->m_mapEditorClasses.end() )
118 {
119 m_unitEditorInstance = static_cast<PG_UNIT_EDITOR*>( it->second );
120 m_unitEditorInstance->UpdateFrame( m_frame );
121 found = true;
122 }
123
124 if( !found )
125 {
126 PG_UNIT_EDITOR* new_editor = new PG_UNIT_EDITOR( m_frame );
127 m_unitEditorInstance = static_cast<PG_UNIT_EDITOR*>( wxPropertyGrid::RegisterEditorClass( new_editor ) );
128 }
129
130 it = wxPGGlobalVars->m_mapEditorClasses.find( PG_CHECKBOX_EDITOR::EDITOR_NAME );
131
132 if( it == wxPGGlobalVars->m_mapEditorClasses.end() )
133 {
134 PG_CHECKBOX_EDITOR* cbEditor = new PG_CHECKBOX_EDITOR();
135 m_checkboxEditorInstance = static_cast<PG_CHECKBOX_EDITOR*>( wxPropertyGrid::RegisterEditorClass( cbEditor ) );
136 }
137 else
138 {
139 m_checkboxEditorInstance = static_cast<PG_CHECKBOX_EDITOR*>( it->second );
140 }
141
142 it = wxPGGlobalVars->m_mapEditorClasses.find( PG_COLOR_EDITOR::EDITOR_NAME );
143
144 if( it == wxPGGlobalVars->m_mapEditorClasses.end() )
145 {
146 PG_COLOR_EDITOR* colorEditor = new PG_COLOR_EDITOR();
147 m_colorEditorInstance = static_cast<PG_COLOR_EDITOR*>( wxPropertyGrid::RegisterEditorClass( colorEditor ) );
148 }
149 else
150 {
151 m_colorEditorInstance = static_cast<PG_COLOR_EDITOR*>( it->second );
152 }
153
154 it = wxPGGlobalVars->m_mapEditorClasses.find( PG_FPID_EDITOR::BuildEditorName( m_frame ) );
155
156 if( it != wxPGGlobalVars->m_mapEditorClasses.end() )
157 {
158 m_fpEditorInstance = static_cast<PG_FPID_EDITOR*>( it->second );
159 m_fpEditorInstance->UpdateFrame( m_frame );
160 }
161 else
162 {
163 PG_FPID_EDITOR* fpEditor = new PG_FPID_EDITOR( m_frame );
164 m_fpEditorInstance = static_cast<PG_FPID_EDITOR*>( wxPropertyGrid::RegisterEditorClass( fpEditor ) );
165 }
166
167 it = wxPGGlobalVars->m_mapEditorClasses.find( PG_URL_EDITOR::BuildEditorName( m_frame ) );
168
169 if( it != wxPGGlobalVars->m_mapEditorClasses.end() )
170 {
171 m_urlEditorInstance = static_cast<PG_URL_EDITOR*>( it->second );
172 m_urlEditorInstance->UpdateFrame( m_frame );
173 }
174 else
175 {
176 PG_URL_EDITOR* urlEditor = new PG_URL_EDITOR( m_frame );
177 m_urlEditorInstance = static_cast<PG_URL_EDITOR*>( wxPropertyGrid::RegisterEditorClass( urlEditor ) );
178 }
179}
180
181
182
184{
185 m_unitEditorInstance->UpdateFrame( nullptr );
186 m_fpEditorInstance->UpdateFrame( nullptr );
187 m_urlEditorInstance->UpdateFrame( nullptr );
188}
189
190
192{
193 SCH_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
194 const SELECTION& selection = selectionTool->GetSelection();
195
196 // Will actually just be updatePropertyValues() if selection hasn't changed
197 rebuildProperties( selection );
198}
199
200
202{
203 SCH_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
204 const SELECTION& selection = selectionTool->GetSelection();
205
206 rebuildProperties( selection );
207}
208
209
211{
212 m_currentFieldNames.clear();
213
214 for( EDA_ITEM* item : aSelection )
215 {
216 if( item->Type() != SCH_SYMBOL_T )
217 continue;
218
219 SCH_SYMBOL* symbol = static_cast<SCH_SYMBOL*>( item );
220
221 for( const SCH_FIELD& field : symbol->GetFields() )
222 {
223 if( field.IsPrivate() )
224 continue;
225
226 m_currentFieldNames.insert( field.GetCanonicalName() );
227 }
228 }
229
230 const wxString groupFields = _HKI( "Fields" );
231
232 for( const wxString& name : m_currentFieldNames )
233 {
234 if( !m_propMgr.GetProperty( TYPE_HASH( SCH_SYMBOL ), name ) )
235 {
236 m_propMgr.AddProperty( new SCH_SYMBOL_FIELD_PROPERTY( name ), groupFields )
237 .SetAvailableFunc( [name]( INSPECTABLE* )
238 {
240 } );
241 }
242 }
243
245}
246
247
248wxPGProperty* SCH_PROPERTIES_PANEL::createPGProperty( const PROPERTY_BASE* aProperty ) const
249{
250 wxPGProperty* prop = PGPropertyFactory( aProperty, m_frame );
251
252 if( auto colorProp = dynamic_cast<PGPROPERTY_COLOR4D*>( prop ) )
253 {
254 COLOR4D bg = m_frame->GetColorSettings()->GetColor( LAYER_SCHEMATIC_BACKGROUND );
255 colorProp->SetBackgroundColor( bg );
256 }
257
258 if( aProperty->Name() == GetCanonicalFieldName( FIELD_T::FOOTPRINT ) )
259 prop->SetEditor( PG_FPID_EDITOR::BuildEditorName( m_frame ) );
260 else if( aProperty->Name() == GetCanonicalFieldName( FIELD_T::DATASHEET ) )
261 prop->SetEditor( PG_URL_EDITOR::BuildEditorName( m_frame ) );
262
263 return prop;
264}
265
266
267PROPERTY_BASE* SCH_PROPERTIES_PANEL::getPropertyFromEvent( const wxPropertyGridEvent& aEvent ) const
268{
269 SCH_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
270 const SELECTION& selection = selectionTool->GetSelection();
271 SCH_ITEM* firstItem = static_cast<SCH_ITEM*>( selection.Front() );
272
273 wxCHECK_MSG( firstItem, nullptr,
274 wxT( "getPropertyFromEvent for a property with nothing selected!") );
275
276 PROPERTY_BASE* property = m_propMgr.GetProperty( TYPE_HASH( *firstItem ),
277 aEvent.GetPropertyName() );
278 wxCHECK_MSG( property, nullptr,
279 wxT( "getPropertyFromEvent for a property not found on the selected item!" ) );
280
281 return property;
282}
283
284
285void SCH_PROPERTIES_PANEL::valueChanging( wxPropertyGridEvent& aEvent )
286{
288 return;
289
290 SCH_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
291 const SELECTION& selection = selectionTool->GetSelection();
292 EDA_ITEM* frontItem = selection.Front();
293
294 if( !frontItem )
295 return;
296
297 if( PROPERTY_BASE* property = getPropertyFromEvent( aEvent ) )
298 {
299 wxVariant newValue = aEvent.GetPropertyValue();
300
301 if( VALIDATOR_RESULT validationFailure = property->Validate( newValue.GetAny(), frontItem ) )
302 {
303 wxString errorMsg = wxString::Format( wxS( "%s: %s" ), wxGetTranslation( property->Name() ),
304 validationFailure->get()->Format( m_frame ) );
305 m_frame->ShowInfoBarError( errorMsg );
306 aEvent.Veto();
307 return;
308 }
309
310 aEvent.Skip();
311 }
312}
313
314
315void SCH_PROPERTIES_PANEL::valueChanged( wxPropertyGridEvent& aEvent )
316{
318 return;
319
320 SCH_SELECTION_TOOL* selectionTool = m_frame->GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
321 const SELECTION& selection = selectionTool->GetSelection();
322
323 wxCHECK( getPropertyFromEvent( aEvent ), /* void */ );
324
325 wxVariant newValue = aEvent.GetPropertyValue();
326 SCH_COMMIT changes( m_frame );
327 SCH_SCREEN* screen = m_frame->GetScreen();
328
329 PROPERTY_COMMIT_HANDLER handler( &changes );
330
331 for( EDA_ITEM* edaItem : selection )
332 {
333 if( !edaItem->IsSCH_ITEM() )
334 continue;
335
336 SCH_ITEM* item = static_cast<SCH_ITEM*>( edaItem );
337 PROPERTY_BASE* property = m_propMgr.GetProperty( TYPE_HASH( *item ),
338 aEvent.GetPropertyName() );
339 wxCHECK( property, /* void */ );
340
341 if( item->Type() == SCH_TABLECELL_T )
342 changes.Modify( item->GetParent(), screen, RECURSE_MODE::NO_RECURSE );
343 else
344 changes.Modify( item, screen, RECURSE_MODE::NO_RECURSE );
345
346 item->Set( property, newValue );
347
348 if( SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( item ) )
349 symbol->SyncOtherUnits( symbol->Schematic()->CurrentSheet(), changes, property );
350 }
351
352 changes.Push( _( "Edit Properties" ) );
353 m_frame->Refresh();
354
355 // Perform grid updates as necessary based on value change
356 AfterCommit();
357
358 aEvent.Skip();
359}
360
361
362void SCH_PROPERTIES_PANEL::OnLanguageChanged( wxCommandEvent& aEvent )
363{
365
366 aEvent.Skip();
367}
368
369
const char * name
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM * GetParent() const
Definition eda_item.h:112
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:97
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:37
bool Set(PROPERTY_BASE *aProperty, wxAny &aValue, bool aNotify=true)
Definition inspectable.h:43
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:104
static const wxString EDITOR_NAME
Definition pg_editors.h:75
static const wxString EDITOR_NAME
Definition pg_editors.h:91
static wxString BuildEditorName(EDA_DRAW_FRAME *aFrame)
static wxString BuildEditorName(EDA_DRAW_FRAME *aFrame)
static wxString BuildEditorName(EDA_DRAW_FRAME *aFrame)
PROPERTIES_PANEL(wxWindow *aParent, EDA_BASE_FRAME *aFrame)
virtual void OnLanguageChanged(wxCommandEvent &aEvent)
virtual void rebuildProperties(const SELECTION &aSelection)
Generates the property grid for a given selection of items.
PROPERTY_BASE(const wxString &aName, PROPERTY_DISPLAY aDisplay=PT_DEFAULT, ORIGIN_TRANSFORMS::COORD_TYPES_T aCoordType=ORIGIN_TRANSFORMS::NOT_A_COORD)
< Used to generate unique IDs. Must come up front so it's initialized before ctor.
Definition property.h:200
virtual bool Writeable(INSPECTABLE *aObject) const
Definition property.h:279
friend class INSPECTABLE
Definition property.h:456
const wxString & Name() const
Definition property.h:219
Provide class metadata.Helper macro to map type hashes to names.
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
virtual void Push(const wxString &aMessage=wxT("A commit"), int aCommitFlags=0) override
Execute the changes.
void SetText(const wxString &aText) override
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:167
wxPGProperty * createPGProperty(const PROPERTY_BASE *aProperty) const override
PROPERTY_MANAGER & m_propMgr
PG_CHECKBOX_EDITOR * m_checkboxEditorInstance
PG_FPID_EDITOR * m_fpEditorInstance
void valueChanging(wxPropertyGridEvent &aEvent) override
PG_UNIT_EDITOR * m_unitEditorInstance
static std::set< wxString > m_currentFieldNames
void valueChanged(wxPropertyGridEvent &aEvent) override
SCH_PROPERTIES_PANEL(wxWindow *aParent, SCH_BASE_FRAME *aFrame)
PG_COLOR_EDITOR * m_colorEditorInstance
PROPERTY_BASE * getPropertyFromEvent(const wxPropertyGridEvent &aEvent) const
void OnLanguageChanged(wxCommandEvent &aEvent) override
void rebuildProperties(const SELECTION &aSelection) override
Generates the property grid for a given selection of items.
PG_URL_EDITOR * m_urlEditorInstance
SCH_SELECTION & GetSelection()
size_t BaseHash() const override
Return type-id of the Base class.
size_t OwnerHash() const override
Return type-id of the Owner class.
size_t TypeHash() const override
Return type-id of the property type.
wxAny getter(const void *obj) const override
SCH_SYMBOL_FIELD_PROPERTY(const wxString &aName)
bool Writeable(INSPECTABLE *aObject) const override
void setter(void *obj, wxAny &v) override
Schematic symbol object.
Definition sch_symbol.h:75
void GetFields(std::vector< SCH_FIELD * > &aVector, bool aVisibleOnly) const override
Populate a std::vector with SCH_FIELDs, sorted in ordinal order.
SCH_FIELD * AddField(const SCH_FIELD &aField)
Add a field to the symbol.
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this symbol.
#define _(s)
@ NO_RECURSE
Definition eda_item.h:52
@ LAYER_SCHEMATIC_BACKGROUND
Definition layer_ids.h:487
#define _HKI(x)
Definition page_info.cpp:44
wxPGProperty * PGPropertyFactory(const PROPERTY_BASE *aProperty, EDA_DRAW_FRAME *aFrame)
Customized abstract wxPGProperty class to handle coordinate/size units.
see class PGM_BASE
APIIMPORT wxPGGlobalVarsClass * wxPGGlobalVars
#define TYPE_HASH(x)
Definition property.h:73
std::optional< std::unique_ptr< VALIDATION_ERROR > > VALIDATOR_RESULT
Null optional means validation succeeded.
static const wxString MISSING_FIELD_SENTINEL
@ USER
The field ID hasn't been set yet; field is invalid.
@ FOOTPRINT
Field Name Module PCB, i.e. "16DIP300".
@ DATASHEET
name of datasheet
wxString GetCanonicalFieldName(FIELD_T aFieldType)
@ SCH_SYMBOL_T
Definition typeinfo.h:174
@ SCH_TABLECELL_T
Definition typeinfo.h:168