You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
7.6 KiB

  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. #ifndef PROPERTY_MGR_H
  22. #define PROPERTY_MGR_H
  23. #include <wx/string.h>
  24. #include <map>
  25. #include <unordered_map>
  26. #include <set>
  27. #include <vector>
  28. #include <memory>
  29. #include <common.h>
  30. class PROPERTY_BASE;
  31. class TYPE_CAST_BASE;
  32. ///> Unique type identifier
  33. using TYPE_ID = size_t;
  34. using PROPERTY_LIST = std::vector<PROPERTY_BASE*>;
  35. using PROPERTY_SET = std::set<std::pair<size_t, wxString>>;
  36. /**
  37. * Provides class metadata. Each class handled by PROPERTY_MANAGER
  38. * needs to be described using AddProperty(), AddTypeCast() and InheritsAfter() methods.
  39. *
  40. * Enum types use a dedicated property type (PROPERTY_ENUM), define its possible values
  41. * with ENUM_MAP class, then describe the type using macros:
  42. * - DECLARE_ENUM_TO_WXANY (in header files)
  43. * - IMPLEMENT_ENUM_TO_WXANY (in source files)
  44. * - ENUM_TO_WXANY (*most often used*; combines DECLARE and IMPLEMENT macros,
  45. * if there is no need to share the description using header files)
  46. *
  47. * Once all classes are described, the property list must be build using
  48. * Rebuild() method.
  49. */
  50. class PROPERTY_MANAGER
  51. {
  52. public:
  53. static PROPERTY_MANAGER& Instance()
  54. {
  55. static PROPERTY_MANAGER pm;
  56. return pm;
  57. }
  58. /**
  59. * Associates a name with a type.
  60. *
  61. * Builds a map to provide faster type look-up.
  62. *
  63. * @param aType is the type identifier (obtained using TYPE_HASH()).
  64. * @param aName is the type name.
  65. */
  66. void RegisterType( TYPE_ID aType, const wxString& aName );
  67. /**
  68. * Returns name of a type.
  69. *
  70. * @param aType is the type identifier (obtained using TYPE_HASH()).
  71. * @return Name of the type or empty string, if not available.
  72. */
  73. const wxString& ResolveType( TYPE_ID aType ) const;
  74. /**
  75. * Returns a property for a specific type.
  76. *
  77. * @param aType is the type identifier (obtained using TYPE_HASH()).
  78. * @param aProperty is the property name used during class registration.
  79. * @return Requested property or null pointer if requested property does not exist.
  80. */
  81. PROPERTY_BASE* GetProperty( TYPE_ID aType, const wxString& aProperty ) const;
  82. /**
  83. * Returns all properties for a specific type.
  84. *
  85. * @param aType is the type identifier (obtained using TYPE_HASH()).
  86. * @return Vector storing all properties of the requested type.
  87. */
  88. const PROPERTY_LIST& GetProperties( TYPE_ID aType ) const;
  89. /**
  90. * Casts a type to another type. Used for correct type-casting of types with
  91. * multi-inheritance. Requires registration of an appropriate converter (AddTypeCast).
  92. *
  93. * @param aSource is a pointer to the casted object.
  94. * @param aBase is aSource type identifier (obtained using TYPE_HASH()).
  95. * @param aTarget is the desired type identifier (obtained using TYPE_HASH()).
  96. * @return Properly casted pointer of aTarget type. *
  97. *
  98. * @see AddTypeCast
  99. */
  100. const void* TypeCast( const void* aSource, TYPE_ID aBase, TYPE_ID aTarget ) const;
  101. void* TypeCast( void* aSource, TYPE_ID aBase, TYPE_ID aTarget ) const
  102. {
  103. return const_cast<void*>( TypeCast( (const void*) aSource, aBase, aTarget ) );
  104. }
  105. /**
  106. * Registers a property.
  107. *
  108. * @param aProperty is the property to register.
  109. */
  110. void AddProperty( PROPERTY_BASE* aProperty );
  111. /**
  112. * Replaces an existing property for a specific type.
  113. *
  114. * It is used to modify a property that has been inherited from a base class.
  115. * This method is used instead of AddProperty().
  116. *
  117. * @param aBase is the base class type the delivers the original property.
  118. * @param aName is the name of the replaced property.
  119. * @param aNew is the property replacing the inherited one.
  120. */
  121. void ReplaceProperty( size_t aBase, const wxString& aName, PROPERTY_BASE* aNew );
  122. /**
  123. * Registers a type converter. Required prior TypeCast() usage.
  124. *
  125. * @param aCast is the type converter to register.
  126. */
  127. void AddTypeCast( TYPE_CAST_BASE* aCast );
  128. /**
  129. * Declares an inheritance relationship between types.
  130. *
  131. * @param aBase is the base type identifier (obtained using TYPE_HASH()).
  132. * @param aDerived is the derived type identifier (obtained using TYPE_HASH()).
  133. */
  134. void InheritsAfter( TYPE_ID aDerived, TYPE_ID aBase );
  135. /**
  136. * Returns true if aDerived is inherited from aBase.
  137. */
  138. bool IsOfType( TYPE_ID aDerived, TYPE_ID aBase ) const;
  139. EDA_UNITS GetUnits() const
  140. {
  141. return m_units;
  142. }
  143. void SetUnits( EDA_UNITS aUnits )
  144. {
  145. m_units = aUnits;
  146. }
  147. /**
  148. * Rebuilds the list of all registered properties. Needs to be called
  149. * once before GetProperty()/GetProperties() are used.
  150. */
  151. void Rebuild();
  152. struct CLASS_INFO
  153. {
  154. wxString name;
  155. TYPE_ID type;
  156. std::vector<PROPERTY_BASE*> properties;
  157. };
  158. typedef std::vector<CLASS_INFO> CLASSES_INFO;
  159. CLASSES_INFO GetAllClasses();
  160. std::vector<TYPE_ID> GetMatchingClasses( PROPERTY_BASE* aProperty );
  161. private:
  162. PROPERTY_MANAGER()
  163. : m_dirty( false ), m_units( EDA_UNITS::MILLIMETRES )
  164. {
  165. }
  166. ///> Structure holding type meta-data
  167. struct CLASS_DESC
  168. {
  169. CLASS_DESC( TYPE_ID aId )
  170. : m_id( aId )
  171. {
  172. }
  173. ///> Unique type identifier (obtained using TYPE_HASH)
  174. const TYPE_ID m_id;
  175. ///> Types after which this type inherits
  176. std::vector<std::reference_wrapper<CLASS_DESC>> m_bases;
  177. ///> Properties unique to this type (i.e. not inherited)
  178. std::map<wxString, std::unique_ptr<PROPERTY_BASE>> m_ownProperties;
  179. ///> Type converters available for this type
  180. std::map<TYPE_ID, std::unique_ptr<TYPE_CAST_BASE>> m_typeCasts;
  181. ///> All properties (both unique to the type and inherited)
  182. std::vector<PROPERTY_BASE*> m_allProperties;
  183. ///> Replaced properties (TYPE_ID / name)
  184. PROPERTY_SET m_replaced;
  185. ///> Recreates the list of properties
  186. void rebuild();
  187. ///> Traverses the class inheritance hierarchy bottom-to-top, gathering
  188. ///> all properties available to a type
  189. void collectPropsRecur( PROPERTY_LIST& aResult, PROPERTY_SET& aReplaced ) const;
  190. };
  191. ///> Returns metadata for a specific type
  192. CLASS_DESC& getClass( TYPE_ID aTypeId );
  193. std::unordered_map<TYPE_ID, wxString> m_classNames;
  194. ///> Map of all available types
  195. std::unordered_map<TYPE_ID, CLASS_DESC> m_classes;
  196. /// Flag indicating that the list of properties needs to be rebuild (RebuildProperties())
  197. bool m_dirty;
  198. EDA_UNITS m_units;
  199. };
  200. ///> Helper macro to map type hashes to names
  201. #define REGISTER_TYPE(x) PROPERTY_MANAGER::Instance().RegisterType(TYPE_HASH(x), TYPE_NAME(x))
  202. #endif /* PROPERTY_MGR_H */