KiCad PCB EDA Suite
property_mgr.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  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
6  * @author Maciej Suminski <maciej.suminski@cern.ch>
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 
22 #include "property_mgr.h"
23 #include "property.h"
24 
25 #include <algorithm>
26 #include <utility>
27 
28 static wxString EMPTY_STRING( wxEmptyString );
29 
30 
31 void PROPERTY_MANAGER::RegisterType( TYPE_ID aType, const wxString& aName )
32 {
33  wxASSERT( m_classNames.count( aType ) == 0 );
34  m_classNames.emplace( aType, aName );
35 }
36 
37 
38 const wxString& PROPERTY_MANAGER::ResolveType( TYPE_ID aType ) const
39 {
40  auto it = m_classNames.find( aType );
41  return it != m_classNames.end() ? it->second : EMPTY_STRING;
42 }
43 
44 
45 PROPERTY_BASE* PROPERTY_MANAGER::GetProperty( TYPE_ID aType, const wxString& aProperty ) const
46 {
47  if( m_dirty )
48  const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
49 
50  auto it = m_classes.find( aType );
51 
52  if( it == m_classes.end() )
53  return nullptr;
54 
55  const CLASS_DESC& classDesc = it->second;
56 
57  for( PROPERTY_BASE* property : classDesc.m_allProperties )
58  {
59  if( !aProperty.CmpNoCase( property->Name() ) )
60  return property;
61  }
62 
63  return nullptr;
64 }
65 
66 
68 {
69  if( m_dirty )
70  const_cast<PROPERTY_MANAGER*>( this )->Rebuild();
71 
72  static const PROPERTY_LIST empty;
73  auto it = m_classes.find( aType );
74 
75  if( it == m_classes.end() )
76  return empty;
77 
78  return it->second.m_allProperties;
79 }
80 
81 
82 const void* PROPERTY_MANAGER::TypeCast( const void* aSource, TYPE_ID aBase, TYPE_ID aTarget ) const
83 {
84  if( aBase == aTarget )
85  return aSource;
86 
87  auto classDesc = m_classes.find( aBase );
88 
89  if( classDesc == m_classes.end() )
90  return aSource;
91 
92  auto& converters = classDesc->second.m_typeCasts;
93  auto converter = converters.find( aTarget );
94 
95  if( converter == converters.end() ) // explicit type cast not found
96  return IsOfType( aBase, aTarget ) ? aSource : nullptr;
97 
98  return (*converter->second)( aSource );
99 }
100 
101 
103 {
104  const wxString& name = aProperty->Name();
105  TYPE_ID hash = aProperty->OwnerHash();
106  CLASS_DESC& classDesc = getClass( hash );
107  classDesc.m_ownProperties.emplace( name, aProperty );
108  m_dirty = true;
109 }
110 
111 
112 void PROPERTY_MANAGER::ReplaceProperty( size_t aBase, const wxString& aName, PROPERTY_BASE* aNew )
113 {
114  wxASSERT( aBase == aNew->BaseHash() );
115  CLASS_DESC& classDesc = getClass( aNew->OwnerHash() );
116  classDesc.m_replaced.insert( std::make_pair( aBase, aName ) );
117  AddProperty( aNew );
118 }
119 
120 
122 {
123  TYPE_ID derivedHash = aCast->DerivedHash();
124  CLASS_DESC& classDesc = getClass( aCast->BaseHash() );
125  auto& typeCasts = classDesc.m_typeCasts;
126  wxASSERT_MSG( typeCasts.count( derivedHash ) == 0, "Such converter already exists" );
127  typeCasts.emplace( derivedHash, aCast );
128 }
129 
130 
132 {
133  wxASSERT_MSG( aDerived != aBase, "Class cannot inherit from itself" );
134 
135  CLASS_DESC& derived = getClass( aDerived );
136  CLASS_DESC& base = getClass( aBase );
137  derived.m_bases.push_back( base );
138  m_dirty = true;
139 
140  wxASSERT_MSG( derived.m_bases.size() == 1 || derived.m_typeCasts.count( aBase ) == 1,
141  "You need to add a TYPE_CAST for classes inheriting from multiple bases" );
142 }
143 
144 
145 bool PROPERTY_MANAGER::IsOfType( TYPE_ID aDerived, TYPE_ID aBase ) const
146 {
147  if( aDerived == aBase )
148  return true;
149 
150  auto derived = m_classes.find( aDerived );
151  wxCHECK( derived != m_classes.end(), false ); // missing class description
152 
153  // traverse the hierarchy seeking for the base class
154  for( auto& base : derived->second.m_bases )
155  {
156  if( IsOfType( base.get().m_id, aBase ) )
157  return true;
158  }
159 
160  return false;
161 }
162 
163 
165 {
166  for( std::pair<const TYPE_ID, CLASS_DESC>& classEntry : m_classes )
167  classEntry.second.rebuild();
168 
169  m_dirty = false;
170 }
171 
172 
174 {
175  auto it = m_classes.find( aTypeId );
176 
177  if( it == m_classes.end() )
178  tie( it, std::ignore ) = m_classes.emplace( aTypeId, CLASS_DESC( aTypeId ) );
179 
180  return it->second;
181 }
182 
183 
185 {
186  PROPERTY_SET replaced( m_replaced );
187  m_allProperties.clear();
188  collectPropsRecur( m_allProperties, replaced );
189  // We need to keep properties sorted to be able to use std::set_* functions
190  sort( m_allProperties.begin(), m_allProperties.end() );
191 }
192 
193 
195  PROPERTY_SET& aReplaced ) const
196 {
197  for( const std::pair<size_t, wxString>& replacedEntry : m_replaced )
198  aReplaced.emplace( replacedEntry );
199 
200  for( const std::pair<const wxString, std::unique_ptr<PROPERTY_BASE>>& prop : m_ownProperties )
201  {
202  PROPERTY_BASE* property = prop.second.get();
203 
204  // Do not store replaced properties
205  if( aReplaced.count( std::make_pair( property->OwnerHash(), property->Name() ) ) == 0 )
206  aResult.push_back( property );
207  }
208 
209  for( const std::reference_wrapper<CLASS_DESC>& base : m_bases )
210  base.get().collectPropsRecur( aResult, aReplaced );
211 }
212 
213 
214 std::vector<TYPE_ID> PROPERTY_MANAGER::GetMatchingClasses( PROPERTY_BASE* aProperty )
215 {
216  std::vector<TYPE_ID> ids;
217 
218 /*
219  for( auto& cls : m_classes )
220  {
221  CLASS_INFO info;
222 
223  for( auto prop : cls.second.m_allProperties )
224  info.properties.push_back(prop);
225 
226 
227  }
228  */
229 
230  return ids;
231 }
232 
233 
235 {
236  CLASSES_INFO rv;
237 
238  for( std::pair<const TYPE_ID, CLASS_DESC>& classEntry : m_classes )
239  {
240  CLASS_INFO info;
241 
242  info.type = classEntry.first;
243  info.name = m_classNames[classEntry.first];
244 
245  for( PROPERTY_BASE* prop : classEntry.second.m_allProperties )
246  info.properties.push_back( prop );
247 
248  rv.push_back( info );
249  }
250 
251  return rv;
252 }
void Rebuild()
Rebuilds the list of all registered properties.
const PROPERTY_LIST & GetProperties(TYPE_ID aType) const
Returns all properties for a specific type.
std::vector< TYPE_ID > GetMatchingClasses(PROPERTY_BASE *aProperty)
PROPERTY_SET m_replaced
Replaced properties (TYPE_ID / name)
Definition: property_mgr.h:221
virtual size_t BaseHash() const =0
std::vector< PROPERTY_BASE * > properties
Definition: property_mgr.h:182
size_t TYPE_ID
Unique type identifier
Definition: property_mgr.h:41
const void * TypeCast(const void *aSource, TYPE_ID aBase, TYPE_ID aTarget) const
Casts a type to another type.
virtual size_t DerivedHash() const =0
bool m_dirty
Flag indicating that the list of properties needs to be rebuild (RebuildProperties())
Definition: property_mgr.h:240
std::map< TYPE_ID, std::unique_ptr< TYPE_CAST_BASE > > m_typeCasts
Type converters available for this type
Definition: property_mgr.h:215
PROPERTY_BASE * GetProperty(TYPE_ID aType, const wxString &aProperty) const
Returns a property for a specific type.
std::unordered_map< TYPE_ID, CLASS_DESC > m_classes
Map of all available types
Definition: property_mgr.h:237
void collectPropsRecur(PROPERTY_LIST &aResult, PROPERTY_SET &aReplaced) const
Traverses the class inheritance hierarchy bottom-to-top, gathering all properties available to a type
void rebuild()
Recreates the list of properties
Structure holding type meta-data
Definition: property_mgr.h:198
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declares an inheritance relationship between types.
const wxString & Name() const
Definition: property.h:188
const wxString & ResolveType(TYPE_ID aType) const
Returns name of a type.
static wxString EMPTY_STRING(wxEmptyString)
CLASS_DESC & getClass(TYPE_ID aTypeId)
Returns metadata for a specific type
void RegisterType(TYPE_ID aType, const wxString &aName)
Associates a name with a type.
std::unordered_map< TYPE_ID, wxString > m_classNames
Definition: property_mgr.h:234
bool IsOfType(TYPE_ID aDerived, TYPE_ID aBase) const
Returns true if aDerived is inherited from aBase.
std::vector< CLASS_INFO > CLASSES_INFO
Definition: property_mgr.h:185
std::vector< std::reference_wrapper< CLASS_DESC > > m_bases
Types after which this type inherits
Definition: property_mgr.h:209
const char * name
Definition: DXF_plotter.cpp:59
std::vector< PROPERTY_BASE * > PROPERTY_LIST
Definition: property_mgr.h:43
void AddTypeCast(TYPE_CAST_BASE *aCast)
Registers a type converter.
void AddProperty(PROPERTY_BASE *aProperty)
Registers a property.
static bool empty(const wxTextEntryBase *aCtrl)
virtual size_t BaseHash() const =0
Returns type-id of the Base class.
void ReplaceProperty(size_t aBase, const wxString &aName, PROPERTY_BASE *aNew)
Replaces an existing property for a specific type.
CLASSES_INFO GetAllClasses()
T get(void *aObject)
Definition: property.h:275
std::set< std::pair< size_t, wxString > > PROPERTY_SET
Definition: property_mgr.h:45
virtual size_t OwnerHash() const =0
Returns type-id of the Owner class.
std::map< wxString, std::unique_ptr< PROPERTY_BASE > > m_ownProperties
Properties unique to this type (i.e. not inherited)
Definition: property_mgr.h:212
std::vector< PROPERTY_BASE * > m_allProperties
All properties (both unique to the type and inherited)
Definition: property_mgr.h:218