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.

619 lines
16 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_H
  22. #define PROPERTY_H
  23. #include <wx/any.h>
  24. #include <wx/string.h>
  25. #include <wx/bitmap.h>
  26. #include <wx/propgrid/property.h>
  27. #include <functional>
  28. #include <map>
  29. #include <memory>
  30. #include <typeindex>
  31. #include <type_traits>
  32. class wxPGProperty;
  33. class INSPECTABLE;
  34. class PROPERTY_BASE;
  35. template<typename T>
  36. class ENUM_MAP;
  37. ///> Common property types
  38. enum PROPERTY_DISPLAY
  39. {
  40. DEFAULT, ///< Default property for a given type
  41. DISTANCE, ///< Display value expressed in distance units (mm/inch)
  42. DEGREE, ///< Display value expressed in degrees
  43. DECIDEGREE ///< Convert decidegrees to degrees for display
  44. };
  45. ///> Macro to generate unique identifier for a type
  46. #define TYPE_HASH( x ) typeid( x ).hash_code()
  47. #define TYPE_NAME( x ) typeid( x ).name()
  48. //#define TYPE_HASH( x ) typeid( std::decay<x>::type ).hash_code()
  49. template<typename Owner, typename T>
  50. class GETTER_BASE
  51. {
  52. public:
  53. virtual ~GETTER_BASE() {}
  54. virtual T operator()( Owner* aOwner ) const = 0;
  55. };
  56. template<typename Owner, typename T, typename FuncType>
  57. class GETTER : public GETTER_BASE<Owner, T>
  58. {
  59. public:
  60. GETTER( FuncType aFunc )
  61. : m_func( aFunc )
  62. {
  63. }
  64. T operator()( Owner* aOwner ) const override
  65. {
  66. return ( aOwner->*m_func )();
  67. }
  68. private:
  69. FuncType m_func;
  70. };
  71. template<typename Owner, typename T>
  72. class SETTER_BASE
  73. {
  74. public:
  75. virtual ~SETTER_BASE() {}
  76. virtual void operator()( Owner* aOwner, T aValue ) = 0;
  77. };
  78. template<typename Owner, typename T, typename FuncType>
  79. class SETTER : public SETTER_BASE<Owner, T>
  80. {
  81. public:
  82. SETTER( FuncType aFunc )
  83. : m_func( aFunc )
  84. {
  85. }
  86. void operator()( Owner* aOwner, T aValue ) override
  87. {
  88. wxCHECK( m_func, /*void*/ );
  89. ( aOwner->*m_func )( aValue );
  90. }
  91. private:
  92. FuncType m_func;
  93. };
  94. template<typename Owner, typename T, typename Base = Owner>
  95. class METHOD
  96. {
  97. public:
  98. constexpr static GETTER_BASE<Owner, T>* Wrap( T (Base::*aFunc)() )
  99. {
  100. return new GETTER<Owner, T, T (Base::*)()>( aFunc );
  101. }
  102. constexpr static GETTER_BASE<Owner, T>* Wrap( const T (Base::*aFunc)() )
  103. {
  104. return new GETTER<Owner, T, T (Base::*)()>( aFunc );
  105. }
  106. constexpr static GETTER_BASE<Owner, T>* Wrap( const T& (Base::*aFunc)() )
  107. {
  108. return new GETTER<Owner, T, const T& (Base::*)()>( aFunc );
  109. }
  110. constexpr static GETTER_BASE<Owner, T>* Wrap( T (Base::*aFunc)() const )
  111. {
  112. return new GETTER<Owner, T, T (Base::*)() const>( aFunc );
  113. }
  114. constexpr static GETTER_BASE<Owner, T>* Wrap( const T (Base::*aFunc)() const )
  115. {
  116. return new GETTER<Owner, T, const T (Base::*)() const>( aFunc );
  117. }
  118. constexpr static GETTER_BASE<Owner, T>* Wrap( const T& (Base::*aFunc)() const )
  119. {
  120. return new GETTER<Owner, T, const T& (Base::*)() const>( aFunc );
  121. }
  122. constexpr static SETTER_BASE<Owner, T>* Wrap( void (Base::*aFunc)( T ) )
  123. {
  124. return aFunc ? new SETTER<Owner, T, void (Base::*)( T )>( aFunc ) : nullptr;
  125. }
  126. constexpr static SETTER_BASE<Owner, T>* Wrap( void (Base::*aFunc)( T& ) )
  127. {
  128. return aFunc ? new SETTER<Owner, T, void (Base::*)( T& )>( aFunc ) : nullptr;
  129. }
  130. constexpr static SETTER_BASE<Owner, T>* Wrap( void (Base::*aFunc)( const T& ) )
  131. {
  132. return aFunc ? new SETTER<Owner, T, void (Base::*)( const T& )>( aFunc ) : nullptr;
  133. }
  134. METHOD() = delete;
  135. };
  136. class PROPERTY_BASE
  137. {
  138. private:
  139. ///> Used to generate unique IDs
  140. size_t nextId = 0;
  141. public:
  142. PROPERTY_BASE( const wxString& aName, PROPERTY_DISPLAY aDisplay = DEFAULT ) :
  143. m_id( nextId ),
  144. m_name( aName ),
  145. m_display( aDisplay ),
  146. m_availFunc( [](INSPECTABLE*)->bool { return true; } )
  147. {
  148. ++nextId;
  149. }
  150. virtual ~PROPERTY_BASE()
  151. {
  152. }
  153. const wxString& Name() const
  154. {
  155. return m_name;
  156. }
  157. /**
  158. * Returns a limited set of possible values (e.g. enum). Check with HasChoices() if a particular
  159. * PROPERTY provides such set.
  160. */
  161. virtual const wxPGChoices& Choices() const
  162. {
  163. static wxPGChoices empty;
  164. return empty;
  165. }
  166. /**
  167. * Sets the possible values for for the property.
  168. */
  169. virtual void SetChoices( const wxPGChoices& aChoices )
  170. {
  171. wxFAIL; // only possible for PROPERTY_ENUM
  172. }
  173. /**
  174. * Returns true if this PROPERTY has a limited set of possible values.
  175. * @see PROPERTY_BASE::Choices()
  176. */
  177. virtual bool HasChoices() const
  178. {
  179. return false;
  180. }
  181. /**
  182. * Returns true if aObject offers this PROPERTY.
  183. */
  184. bool Available( INSPECTABLE* aObject ) const
  185. {
  186. return m_availFunc( aObject );
  187. }
  188. /**
  189. * Sets a callback function to determine whether an object provides this property.
  190. */
  191. void SetAvailableFunc( std::function<bool(INSPECTABLE*)> aFunc )
  192. {
  193. m_availFunc = aFunc;
  194. }
  195. /**
  196. * Returns type-id of the Owner class.
  197. */
  198. virtual size_t OwnerHash() const = 0;
  199. /**
  200. * Returns type-id of the Base class.
  201. */
  202. virtual size_t BaseHash() const = 0;
  203. /**
  204. * Returns type-id of the property type.
  205. */
  206. virtual size_t TypeHash() const = 0;
  207. /**
  208. * Returns unique ID of the property.
  209. */
  210. size_t Id() const
  211. {
  212. return m_id;
  213. }
  214. virtual bool IsReadOnly() const = 0;
  215. PROPERTY_DISPLAY GetDisplay() const
  216. {
  217. return m_display;
  218. }
  219. protected:
  220. template<typename T>
  221. void set( void* aObject, T aValue )
  222. {
  223. wxAny a = aValue;
  224. setter( aObject, a );
  225. }
  226. template<typename T>
  227. T get( void* aObject )
  228. {
  229. wxAny a = getter( aObject );
  230. if ( !( std::is_enum<T>::value && a.CheckType<int>() ) && !a.CheckType<T>() )
  231. throw std::invalid_argument("Invalid requested type");
  232. return wxANY_AS(a, T);
  233. }
  234. virtual void setter( void* aObject, wxAny& aValue ) = 0;
  235. virtual wxAny getter( void* aObject ) const = 0;
  236. private:
  237. const size_t m_id;
  238. const wxString m_name;
  239. const PROPERTY_DISPLAY m_display;
  240. ///> Condition that determines whether the property is available
  241. std::function<bool(INSPECTABLE*)> m_availFunc;
  242. friend class INSPECTABLE;
  243. };
  244. template<typename Owner, typename T, typename Base = Owner>
  245. class PROPERTY : public PROPERTY_BASE
  246. {
  247. public:
  248. typedef typename std::decay<T>::type BASE_TYPE;
  249. typedef void (Base::*SETTER)( T );
  250. template<typename SetType, typename GetType>
  251. PROPERTY( const wxString& aName,
  252. void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )(),
  253. PROPERTY_DISPLAY aDisplay = DEFAULT )
  254. : PROPERTY( aName, METHOD<Owner, T, Base>::Wrap( aSetter ),
  255. METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay )
  256. {
  257. }
  258. template<typename SetType, typename GetType>
  259. PROPERTY( const wxString& aName,
  260. void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )() const,
  261. PROPERTY_DISPLAY aDisplay = DEFAULT )
  262. : PROPERTY( aName, METHOD<Owner, T, Base>::Wrap( aSetter ),
  263. METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay )
  264. {
  265. }
  266. size_t OwnerHash() const override
  267. {
  268. return m_ownerHash;
  269. }
  270. size_t BaseHash() const override
  271. {
  272. return m_baseHash;
  273. }
  274. size_t TypeHash() const override
  275. {
  276. return m_typeHash;
  277. }
  278. bool IsReadOnly() const override
  279. {
  280. return !m_setter;
  281. }
  282. protected:
  283. PROPERTY( const wxString& aName, SETTER_BASE<Owner, T>* s, GETTER_BASE<Owner, T>* g,
  284. PROPERTY_DISPLAY aDisplay )
  285. : PROPERTY_BASE( aName, aDisplay ), m_setter( s ), m_getter( g ),
  286. m_ownerHash( TYPE_HASH( Owner ) ), m_baseHash( TYPE_HASH( Base ) ),
  287. m_typeHash( TYPE_HASH( BASE_TYPE ) )
  288. {
  289. }
  290. virtual ~PROPERTY() {}
  291. virtual void setter( void* obj, wxAny& v ) override
  292. {
  293. wxCHECK( !IsReadOnly(), /*void*/ );
  294. if( !v.CheckType<T>() )
  295. throw std::invalid_argument( "Invalid type requested" );
  296. Owner* o = reinterpret_cast<Owner*>( obj );
  297. BASE_TYPE value = wxANY_AS(v, BASE_TYPE);
  298. (*m_setter)( o, value );
  299. }
  300. virtual wxAny getter( void* obj ) const override
  301. {
  302. Owner* o = reinterpret_cast<Owner*>( obj );
  303. wxAny res = (*m_getter)( o );
  304. return res;
  305. }
  306. ///> Set method
  307. std::unique_ptr<SETTER_BASE<Owner, T>> m_setter;
  308. ///> Get method
  309. std::unique_ptr<GETTER_BASE<Owner, T>> m_getter;
  310. ///> Owner class type-id
  311. const size_t m_ownerHash;
  312. ///> Base class type-id
  313. const size_t m_baseHash;
  314. ///> Property value type-id
  315. const size_t m_typeHash;
  316. };
  317. template<typename Owner, typename T, typename Base = Owner>
  318. class PROPERTY_ENUM : public PROPERTY<Owner, T, Base>
  319. {
  320. public:
  321. template<typename SetType, typename GetType>
  322. PROPERTY_ENUM( const wxString& aName,
  323. void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )(),
  324. PROPERTY_DISPLAY aDisplay = PROPERTY_DISPLAY::DEFAULT )
  325. : PROPERTY<Owner, T, Base>( aName, METHOD<Owner, T, Base>::Wrap( aSetter ),
  326. METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay )
  327. {
  328. if ( std::is_enum<T>::value )
  329. {
  330. m_choices = ENUM_MAP<T>::Instance().Choices();
  331. wxASSERT_MSG( m_choices.GetCount() > 0, "No enum choices defined" );
  332. }
  333. }
  334. template<typename SetType, typename GetType>
  335. PROPERTY_ENUM( const wxString& aName,
  336. void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )() const,
  337. PROPERTY_DISPLAY aDisplay = PROPERTY_DISPLAY::DEFAULT )
  338. : PROPERTY<Owner, T, Base>( aName, METHOD<Owner, T, Base>::Wrap( aSetter ),
  339. METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay )
  340. {
  341. if ( std::is_enum<T>::value )
  342. {
  343. m_choices = ENUM_MAP<T>::Instance().Choices();
  344. wxASSERT_MSG( m_choices.GetCount() > 0, "No enum choices defined" );
  345. }
  346. }
  347. virtual void setter( void* obj, wxAny& v ) override
  348. {
  349. wxCHECK( !( PROPERTY<Owner, T, Base>::IsReadOnly() ), /*void*/ );
  350. Owner* o = reinterpret_cast<Owner*>( obj );
  351. if( v.CheckType<T>() )
  352. {
  353. T value = wxANY_AS(v, T);
  354. (*PROPERTY<Owner, T, Base>::m_setter)( o, value );
  355. }
  356. else if (v.CheckType<int>() )
  357. {
  358. int value = wxANY_AS(v, int);
  359. (*PROPERTY<Owner, T, Base>::m_setter)( o, static_cast<T>( value ) );
  360. }
  361. else
  362. {
  363. throw std::invalid_argument( "Invalid type requested" );
  364. }
  365. }
  366. virtual wxAny getter( void* obj ) const override
  367. {
  368. Owner* o = reinterpret_cast<Owner*>( obj );
  369. wxAny res = static_cast<T>( (*PROPERTY<Owner, T, Base>::m_getter)( o ) );
  370. return res;
  371. }
  372. const wxPGChoices& Choices() const override
  373. {
  374. return m_choices;
  375. }
  376. void SetChoices( const wxPGChoices& aChoices ) override
  377. {
  378. m_choices = aChoices;
  379. }
  380. bool HasChoices() const override
  381. {
  382. return m_choices.GetCount() > 0;
  383. }
  384. protected:
  385. wxPGChoices m_choices;
  386. };
  387. class TYPE_CAST_BASE
  388. {
  389. public:
  390. virtual ~TYPE_CAST_BASE() {}
  391. virtual void* operator()( void* aPointer ) const = 0;
  392. virtual const void* operator()( const void* aPointer ) const = 0;
  393. virtual size_t BaseHash() const = 0;
  394. virtual size_t DerivedHash() const = 0;
  395. };
  396. template<typename Base, typename Derived>
  397. class TYPE_CAST : public TYPE_CAST_BASE
  398. {
  399. public:
  400. TYPE_CAST()
  401. {
  402. }
  403. void* operator()( void* aPointer ) const override
  404. {
  405. Base* base = reinterpret_cast<Base*>( aPointer );
  406. return static_cast<Derived*>( base );
  407. }
  408. const void* operator()( const void* aPointer ) const override
  409. {
  410. const Base* base = reinterpret_cast<const Base*>( aPointer );
  411. return static_cast<const Derived*>( base );
  412. }
  413. size_t BaseHash() const override
  414. {
  415. return TYPE_HASH( Base );
  416. }
  417. size_t DerivedHash() const override
  418. {
  419. return TYPE_HASH( Derived );
  420. }
  421. };
  422. template<typename T>
  423. class ENUM_MAP
  424. {
  425. public:
  426. static ENUM_MAP<T>& Instance()
  427. {
  428. static ENUM_MAP<T> inst;
  429. return inst;
  430. }
  431. ENUM_MAP& Map( T aValue, const wxString& aName )
  432. {
  433. m_choices.Add( aName, static_cast<int>( aValue ) );
  434. m_reverseMap[ aName ] = aValue;
  435. return *this;
  436. }
  437. ENUM_MAP& Undefined( T aValue )
  438. {
  439. m_undefined = aValue;
  440. return *this;
  441. }
  442. const wxString& ToString( T value ) const
  443. {
  444. static const wxString s_undef = "UNDEFINED";
  445. int idx = m_choices.Index( static_cast<int>( value ) );
  446. if( idx >= 0 && idx < (int) m_choices.GetCount() )
  447. return m_choices.GetLabel( static_cast<int>( idx ) );
  448. else
  449. return s_undef;
  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,\
  480. wxAnyValueType* dstType, wxAnyValueBuffer& dst ) const override\
  481. {\
  482. type value = GetValue(src);\
  483. ENUM_MAP<type>& conv = ENUM_MAP<type>::Instance();\
  484. if( dstType->CheckType<wxString>() )\
  485. {\
  486. wxAnyValueTypeImpl<wxString>::SetValue( conv.ToString( value ), dst );\
  487. return true;\
  488. }\
  489. if( dstType->CheckType<int>() )\
  490. {\
  491. wxAnyValueTypeImpl<int>::SetValue( static_cast<int>(value), dst );\
  492. return true;\
  493. }\
  494. else\
  495. {\
  496. return false;\
  497. }\
  498. }\
  499. };
  500. #define IMPLEMENT_ENUM_TO_WXANY(type)\
  501. WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl<type>)
  502. #define ENUM_TO_WXANY(type)\
  503. DECLARE_ENUM_TO_WXANY(type)\
  504. IMPLEMENT_ENUM_TO_WXANY(type)
  505. ///> Macro to define read-only fields (no setter method available)
  506. #define NO_SETTER(owner, type) ((void (owner::*)(type))nullptr)
  507. /*
  508. #define DECLARE_PROPERTY(owner,type,name,getter,setter) \
  509. namespace anonymous {\
  510. static PROPERTY<owner,type> prop##_owner##_name_( "##name#", setter, getter );\
  511. };
  512. */
  513. #endif /* PROPERTY_H */