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.

625 lines
18 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2020 CERN
  5. * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  8. * @author Maciej Suminski <maciej.suminski@cern.ch>
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 3
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License along
  21. * with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. #ifndef PROPERTY_H
  24. #define PROPERTY_H
  25. #include <core/wx_stl_compat.h>
  26. #include <wx/any.h>
  27. #include <wx/string.h>
  28. #include <wx/bitmap.h>
  29. #include <wx/font.h> // required for propgrid
  30. #include <wx/validate.h> // required for propgrid
  31. #include <wx/propgrid/property.h>
  32. #include <functional>
  33. #include <map>
  34. #include <memory>
  35. #include <typeindex>
  36. #include <type_traits>
  37. class wxPGProperty;
  38. class INSPECTABLE;
  39. class PROPERTY_BASE;
  40. template<typename T>
  41. class ENUM_MAP;
  42. ///< Common property types
  43. enum PROPERTY_DISPLAY
  44. {
  45. DEFAULT, ///< Default property for a given type
  46. DISTANCE, ///< Display value expressed in distance units (mm/inch)
  47. DEGREE, ///< Display value expressed in degrees
  48. DECIDEGREE ///< Convert decidegrees to degrees for display
  49. };
  50. ///< Macro to generate unique identifier for a type
  51. #define TYPE_HASH( x ) typeid( x ).hash_code()
  52. #define TYPE_NAME( x ) typeid( x ).name()
  53. //#define TYPE_HASH( x ) typeid( std::decay<x>::type ).hash_code()
  54. template<typename Owner, typename T>
  55. class GETTER_BASE
  56. {
  57. public:
  58. virtual ~GETTER_BASE() {}
  59. virtual T operator()( Owner* aOwner ) const = 0;
  60. };
  61. template<typename Owner, typename T, typename FuncType>
  62. class GETTER : public GETTER_BASE<Owner, T>
  63. {
  64. public:
  65. GETTER( FuncType aFunc )
  66. : m_func( aFunc )
  67. {
  68. }
  69. T operator()( Owner* aOwner ) const override
  70. {
  71. return ( aOwner->*m_func )();
  72. }
  73. private:
  74. FuncType m_func;
  75. };
  76. template<typename Owner, typename T>
  77. class SETTER_BASE
  78. {
  79. public:
  80. virtual ~SETTER_BASE() {}
  81. virtual void operator()( Owner* aOwner, T aValue ) = 0;
  82. };
  83. template<typename Owner, typename T, typename FuncType>
  84. class SETTER : public SETTER_BASE<Owner, T>
  85. {
  86. public:
  87. SETTER( FuncType aFunc )
  88. : m_func( aFunc )
  89. {
  90. }
  91. void operator()( Owner* aOwner, T aValue ) override
  92. {
  93. wxCHECK( m_func, /*void*/ );
  94. ( aOwner->*m_func )( aValue );
  95. }
  96. private:
  97. FuncType m_func;
  98. };
  99. template<typename Owner, typename T, typename Base = Owner>
  100. class METHOD
  101. {
  102. public:
  103. constexpr static GETTER_BASE<Owner, T>* Wrap( T (Base::*aFunc)() )
  104. {
  105. return new GETTER<Owner, T, T (Base::*)()>( aFunc );
  106. }
  107. constexpr static GETTER_BASE<Owner, T>* Wrap( const T (Base::*aFunc)() )
  108. {
  109. return new GETTER<Owner, T, T (Base::*)()>( aFunc );
  110. }
  111. constexpr static GETTER_BASE<Owner, T>* Wrap( const T& (Base::*aFunc)() )
  112. {
  113. return new GETTER<Owner, T, const T& (Base::*)()>( aFunc );
  114. }
  115. constexpr static GETTER_BASE<Owner, T>* Wrap( T (Base::*aFunc)() const )
  116. {
  117. return new GETTER<Owner, T, T (Base::*)() const>( aFunc );
  118. }
  119. constexpr static GETTER_BASE<Owner, T>* Wrap( const T (Base::*aFunc)() const )
  120. {
  121. return new GETTER<Owner, T, const T (Base::*)() const>( aFunc );
  122. }
  123. constexpr static GETTER_BASE<Owner, T>* Wrap( const T& (Base::*aFunc)() const )
  124. {
  125. return new GETTER<Owner, T, const T& (Base::*)() const>( aFunc );
  126. }
  127. constexpr static SETTER_BASE<Owner, T>* Wrap( void (Base::*aFunc)( T ) )
  128. {
  129. return aFunc ? new SETTER<Owner, T, void (Base::*)( T )>( aFunc ) : nullptr;
  130. }
  131. constexpr static SETTER_BASE<Owner, T>* Wrap( void (Base::*aFunc)( T& ) )
  132. {
  133. return aFunc ? new SETTER<Owner, T, void (Base::*)( T& )>( aFunc ) : nullptr;
  134. }
  135. constexpr static SETTER_BASE<Owner, T>* Wrap( void (Base::*aFunc)( const T& ) )
  136. {
  137. return aFunc ? new SETTER<Owner, T, void (Base::*)( const T& )>( aFunc ) : nullptr;
  138. }
  139. METHOD() = delete;
  140. };
  141. class PROPERTY_BASE
  142. {
  143. private:
  144. ///< Used to generate unique IDs. Must come up front so it's initialized before ctor.
  145. public:
  146. PROPERTY_BASE( const wxString& aName, PROPERTY_DISPLAY aDisplay = DEFAULT ) :
  147. m_name( aName ),
  148. m_display( aDisplay ),
  149. m_availFunc( [](INSPECTABLE*)->bool { return true; } )
  150. {
  151. }
  152. virtual ~PROPERTY_BASE()
  153. {
  154. }
  155. const wxString& Name() const
  156. {
  157. return m_name;
  158. }
  159. /**
  160. * Return a limited set of possible values (e.g. enum). Check with HasChoices() if a particular
  161. * PROPERTY provides such set.
  162. */
  163. virtual const wxPGChoices& Choices() const
  164. {
  165. static wxPGChoices empty;
  166. return empty;
  167. }
  168. /**
  169. * Set the possible values for for the property.
  170. */
  171. virtual void SetChoices( const wxPGChoices& aChoices )
  172. {
  173. wxFAIL; // only possible for PROPERTY_ENUM
  174. }
  175. /**
  176. * Return true if this PROPERTY has a limited set of possible values.
  177. * @see PROPERTY_BASE::Choices()
  178. */
  179. virtual bool HasChoices() const
  180. {
  181. return false;
  182. }
  183. /**
  184. * Return true if aObject offers this PROPERTY.
  185. */
  186. bool Available( INSPECTABLE* aObject ) const
  187. {
  188. return m_availFunc( aObject );
  189. }
  190. /**
  191. * Set a callback function to determine whether an object provides this property.
  192. */
  193. void SetAvailableFunc( std::function<bool(INSPECTABLE*)> aFunc )
  194. {
  195. m_availFunc = aFunc;
  196. }
  197. /**
  198. * Return type-id of the Owner class.
  199. */
  200. virtual size_t OwnerHash() const = 0;
  201. /**
  202. * Return type-id of the Base class.
  203. */
  204. virtual size_t BaseHash() const = 0;
  205. /**
  206. * Return type-id of the property type.
  207. */
  208. virtual size_t TypeHash() const = 0;
  209. virtual bool IsReadOnly() const = 0;
  210. PROPERTY_DISPLAY GetDisplay() const
  211. {
  212. return m_display;
  213. }
  214. protected:
  215. template<typename T>
  216. void set( void* aObject, T aValue )
  217. {
  218. wxAny a = aValue;
  219. setter( aObject, a );
  220. }
  221. template<typename T>
  222. T get( void* aObject )
  223. {
  224. wxAny a = getter( aObject );
  225. if ( !( std::is_enum<T>::value && a.CheckType<int>() ) && !a.CheckType<T>() )
  226. throw std::invalid_argument( "Invalid requested type" );
  227. return wxANY_AS(a, T);
  228. }
  229. virtual void setter( void* aObject, wxAny& aValue ) = 0;
  230. virtual wxAny getter( void* aObject ) const = 0;
  231. private:
  232. const wxString m_name;
  233. const PROPERTY_DISPLAY m_display;
  234. std::function<bool(INSPECTABLE*)> m_availFunc; ///< Eval to determine if prop is available
  235. friend class INSPECTABLE;
  236. };
  237. template<typename Owner, typename T, typename Base = Owner>
  238. class PROPERTY : public PROPERTY_BASE
  239. {
  240. public:
  241. typedef typename std::decay<T>::type BASE_TYPE;
  242. typedef void (Base::*SETTER)( T );
  243. template<typename SetType, typename GetType>
  244. PROPERTY( const wxString& aName,
  245. void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )(),
  246. PROPERTY_DISPLAY aDisplay = DEFAULT )
  247. : PROPERTY( aName, METHOD<Owner, T, Base>::Wrap( aSetter ),
  248. METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay )
  249. {
  250. }
  251. template<typename SetType, typename GetType>
  252. PROPERTY( const wxString& aName,
  253. void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )() const,
  254. PROPERTY_DISPLAY aDisplay = DEFAULT )
  255. : PROPERTY( aName, METHOD<Owner, T, Base>::Wrap( aSetter ),
  256. METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay )
  257. {
  258. }
  259. size_t OwnerHash() const override
  260. {
  261. return m_ownerHash;
  262. }
  263. size_t BaseHash() const override
  264. {
  265. return m_baseHash;
  266. }
  267. size_t TypeHash() const override
  268. {
  269. return m_typeHash;
  270. }
  271. bool IsReadOnly() const override
  272. {
  273. return !m_setter;
  274. }
  275. protected:
  276. PROPERTY( const wxString& aName, SETTER_BASE<Owner, T>* s, GETTER_BASE<Owner, T>* g,
  277. PROPERTY_DISPLAY aDisplay )
  278. : PROPERTY_BASE( aName, aDisplay ), m_setter( s ), m_getter( g ),
  279. m_ownerHash( TYPE_HASH( Owner ) ), m_baseHash( TYPE_HASH( Base ) ),
  280. m_typeHash( TYPE_HASH( BASE_TYPE ) )
  281. {
  282. }
  283. virtual ~PROPERTY() {}
  284. virtual void setter( void* obj, wxAny& v ) override
  285. {
  286. wxCHECK( !IsReadOnly(), /*void*/ );
  287. if( !v.CheckType<T>() )
  288. throw std::invalid_argument( "Invalid type requested" );
  289. Owner* o = reinterpret_cast<Owner*>( obj );
  290. BASE_TYPE value = wxANY_AS(v, BASE_TYPE);
  291. (*m_setter)( o, value );
  292. }
  293. virtual wxAny getter( void* obj ) const override
  294. {
  295. Owner* o = reinterpret_cast<Owner*>( obj );
  296. wxAny res = (*m_getter)( o );
  297. return res;
  298. }
  299. ///< Set method
  300. std::unique_ptr<SETTER_BASE<Owner, T>> m_setter;
  301. ///< Get method
  302. std::unique_ptr<GETTER_BASE<Owner, T>> m_getter;
  303. ///< Owner class type-id
  304. const size_t m_ownerHash;
  305. ///< Base class type-id
  306. const size_t m_baseHash;
  307. ///< Property value type-id
  308. const size_t m_typeHash;
  309. };
  310. template<typename Owner, typename T, typename Base = Owner>
  311. class PROPERTY_ENUM : public PROPERTY<Owner, T, Base>
  312. {
  313. public:
  314. template<typename SetType, typename GetType>
  315. PROPERTY_ENUM( const wxString& aName,
  316. void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )(),
  317. PROPERTY_DISPLAY aDisplay = PROPERTY_DISPLAY::DEFAULT )
  318. : PROPERTY<Owner, T, Base>( aName, METHOD<Owner, T, Base>::Wrap( aSetter ),
  319. METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay )
  320. {
  321. if ( std::is_enum<T>::value )
  322. {
  323. m_choices = ENUM_MAP<T>::Instance().Choices();
  324. wxASSERT_MSG( m_choices.GetCount() > 0, "No enum choices defined" );
  325. }
  326. }
  327. template<typename SetType, typename GetType>
  328. PROPERTY_ENUM( const wxString& aName,
  329. void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )() const,
  330. PROPERTY_DISPLAY aDisplay = PROPERTY_DISPLAY::DEFAULT )
  331. : PROPERTY<Owner, T, Base>( aName, METHOD<Owner, T, Base>::Wrap( aSetter ),
  332. METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay )
  333. {
  334. if ( std::is_enum<T>::value )
  335. {
  336. m_choices = ENUM_MAP<T>::Instance().Choices();
  337. wxASSERT_MSG( m_choices.GetCount() > 0, "No enum choices defined" );
  338. }
  339. }
  340. virtual void setter( void* obj, wxAny& v ) override
  341. {
  342. wxCHECK( !( PROPERTY<Owner, T, Base>::IsReadOnly() ), /*void*/ );
  343. Owner* o = reinterpret_cast<Owner*>( obj );
  344. if( v.CheckType<T>() )
  345. {
  346. T value = wxANY_AS(v, T);
  347. (*PROPERTY<Owner, T, Base>::m_setter)( o, value );
  348. }
  349. else if (v.CheckType<int>() )
  350. {
  351. int value = wxANY_AS(v, int);
  352. (*PROPERTY<Owner, T, Base>::m_setter)( o, static_cast<T>( value ) );
  353. }
  354. else
  355. {
  356. throw std::invalid_argument( "Invalid type requested" );
  357. }
  358. }
  359. virtual wxAny getter( void* obj ) const override
  360. {
  361. Owner* o = reinterpret_cast<Owner*>( obj );
  362. wxAny res = static_cast<T>( (*PROPERTY<Owner, T, Base>::m_getter)( o ) );
  363. return res;
  364. }
  365. const wxPGChoices& Choices() const override
  366. {
  367. return m_choices;
  368. }
  369. void SetChoices( const wxPGChoices& aChoices ) override
  370. {
  371. m_choices = aChoices;
  372. }
  373. bool HasChoices() const override
  374. {
  375. return m_choices.GetCount() > 0;
  376. }
  377. protected:
  378. wxPGChoices m_choices;
  379. };
  380. class TYPE_CAST_BASE
  381. {
  382. public:
  383. virtual ~TYPE_CAST_BASE() {}
  384. virtual void* operator()( void* aPointer ) const = 0;
  385. virtual const void* operator()( const void* aPointer ) const = 0;
  386. virtual size_t BaseHash() const = 0;
  387. virtual size_t DerivedHash() const = 0;
  388. };
  389. template<typename Base, typename Derived>
  390. class TYPE_CAST : public TYPE_CAST_BASE
  391. {
  392. public:
  393. TYPE_CAST()
  394. {
  395. }
  396. void* operator()( void* aPointer ) const override
  397. {
  398. Base* base = reinterpret_cast<Base*>( aPointer );
  399. return static_cast<Derived*>( base );
  400. }
  401. const void* operator()( const void* aPointer ) const override
  402. {
  403. const Base* base = reinterpret_cast<const Base*>( aPointer );
  404. return static_cast<const Derived*>( base );
  405. }
  406. size_t BaseHash() const override
  407. {
  408. return TYPE_HASH( Base );
  409. }
  410. size_t DerivedHash() const override
  411. {
  412. return TYPE_HASH( Derived );
  413. }
  414. };
  415. template<typename T>
  416. class ENUM_MAP
  417. {
  418. public:
  419. static ENUM_MAP<T>& Instance()
  420. {
  421. static ENUM_MAP<T> inst;
  422. return inst;
  423. }
  424. ENUM_MAP& Map( T aValue, const wxString& aName )
  425. {
  426. m_choices.Add( aName, static_cast<int>( aValue ) );
  427. m_reverseMap[ aName ] = aValue;
  428. return *this;
  429. }
  430. ENUM_MAP& Undefined( T aValue )
  431. {
  432. m_undefined = aValue;
  433. return *this;
  434. }
  435. const wxString& ToString( T value ) const
  436. {
  437. static const wxString s_undef = "UNDEFINED";
  438. int idx = m_choices.Index( static_cast<int>( value ) );
  439. if( idx >= 0 && idx < (int) m_choices.GetCount() )
  440. return m_choices.GetLabel( static_cast<int>( idx ) );
  441. else
  442. return s_undef;
  443. }
  444. bool IsValueDefined( T value ) const
  445. {
  446. int idx = m_choices.Index( static_cast<int>( value ) );
  447. if( idx >= 0 && idx < (int) m_choices.GetCount() )
  448. return true;
  449. return false;
  450. }
  451. const T ToEnum( const wxString value )
  452. {
  453. if( m_reverseMap.count( value ) )
  454. return m_reverseMap[ value ];
  455. else
  456. return m_undefined;
  457. }
  458. wxPGChoices& Choices()
  459. {
  460. return m_choices;
  461. }
  462. private:
  463. wxPGChoices m_choices;
  464. std::unordered_map<wxString, T> m_reverseMap;
  465. T m_undefined; // Returned if the string is not recognized
  466. ENUM_MAP<T>()
  467. {
  468. }
  469. };
  470. // Helper macros to handle enum types
  471. #define DECLARE_ENUM_TO_WXANY( type ) \
  472. template <> \
  473. class wxAnyValueTypeImpl<type> : public wxAnyValueTypeImplBase<type> \
  474. { \
  475. WX_DECLARE_ANY_VALUE_TYPE( wxAnyValueTypeImpl<type> ) \
  476. public: \
  477. wxAnyValueTypeImpl() : wxAnyValueTypeImplBase<type>() {} \
  478. virtual ~wxAnyValueTypeImpl() {} \
  479. virtual bool ConvertValue( const wxAnyValueBuffer& src, wxAnyValueType* dstType, \
  480. wxAnyValueBuffer& dst ) const override \
  481. { \
  482. type value = GetValue( src ); \
  483. ENUM_MAP<type>& conv = ENUM_MAP<type>::Instance(); \
  484. if( ! conv.IsValueDefined( value ) ) \
  485. { \
  486. return false; \
  487. } \
  488. if( dstType->CheckType<wxString>() ) \
  489. { \
  490. wxAnyValueTypeImpl<wxString>::SetValue( conv.ToString( value ), dst ); \
  491. return true; \
  492. } \
  493. if( dstType->CheckType<int>() ) \
  494. { \
  495. wxAnyValueTypeImpl<int>::SetValue( static_cast<int>( value ), dst ); \
  496. return true; \
  497. } \
  498. else \
  499. { \
  500. return false; \
  501. } \
  502. } \
  503. };
  504. #define IMPLEMENT_ENUM_TO_WXANY( type ) WX_IMPLEMENT_ANY_VALUE_TYPE( wxAnyValueTypeImpl<type> )
  505. #define ENUM_TO_WXANY( type ) \
  506. DECLARE_ENUM_TO_WXANY( type ) \
  507. IMPLEMENT_ENUM_TO_WXANY( type )
  508. ///< Macro to define read-only fields (no setter method available)
  509. #define NO_SETTER( owner, type ) ( ( void ( owner::* )( type ) ) nullptr )
  510. /*
  511. #define DECLARE_PROPERTY(owner,type,name,getter,setter) \
  512. namespace anonymous {\
  513. static PROPERTY<owner,type> prop##_owner##_name_( "##name#", setter, getter );\
  514. };
  515. */
  516. #endif /* PROPERTY_H */