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 24 #ifndef PROPERTY_H 25 #define PROPERTY_H 26 27 #include <core/wx_stl_compat.h> 28 29 #include <wx/any.h> 30 #include <wx/string.h> 31 #include <wx/bitmap.h> 32 #include <wx/font.h> // required for propgrid 33 #include <wx/validate.h> // required for propgrid 34 #include <wx/propgrid/property.h> 35 36 #include <functional> 37 #include <map> 38 #include <memory> 39 #include <typeindex> 40 #include <type_traits> 41 42 class wxPGProperty; 43 class INSPECTABLE; 44 class PROPERTY_BASE; 45 46 template<typename T> 47 class ENUM_MAP; 48 49 ///< Common property types 50 enum PROPERTY_DISPLAY 51 { 52 DEFAULT, ///< Default property for a given type 53 DISTANCE, ///< Display value expressed in distance units (mm/inch) 54 DEGREE, ///< Display value expressed in degrees 55 DECIDEGREE ///< Convert decidegrees to degrees for display 56 }; 57 58 ///< Macro to generate unique identifier for a type 59 #define TYPE_HASH( x ) typeid( x ).hash_code() 60 #define TYPE_NAME( x ) typeid( x ).name() 61 //#define TYPE_HASH( x ) typeid( std::decay<x>::type ).hash_code() 62 63 template<typename Owner, typename T> 64 class GETTER_BASE 65 { 66 public: ~GETTER_BASE()67 virtual ~GETTER_BASE() {} 68 69 virtual T operator()( Owner* aOwner ) const = 0; 70 }; 71 72 template<typename Owner, typename T, typename FuncType> 73 class GETTER : public GETTER_BASE<Owner, T> 74 { 75 public: GETTER(FuncType aFunc)76 GETTER( FuncType aFunc ) 77 : m_func( aFunc ) 78 { 79 } 80 operator()81 T operator()( Owner* aOwner ) const override 82 { 83 return ( aOwner->*m_func )(); 84 } 85 86 private: 87 FuncType m_func; 88 }; 89 90 template<typename Owner, typename T> 91 class SETTER_BASE 92 { 93 public: ~SETTER_BASE()94 virtual ~SETTER_BASE() {} 95 96 virtual void operator()( Owner* aOwner, T aValue ) = 0; 97 }; 98 99 template<typename Owner, typename T, typename FuncType> 100 class SETTER : public SETTER_BASE<Owner, T> 101 { 102 public: SETTER(FuncType aFunc)103 SETTER( FuncType aFunc ) 104 : m_func( aFunc ) 105 { 106 } 107 operator()108 void operator()( Owner* aOwner, T aValue ) override 109 { 110 wxCHECK( m_func, /*void*/ ); 111 ( aOwner->*m_func )( aValue ); 112 } 113 114 private: 115 FuncType m_func; 116 }; 117 118 119 template<typename Owner, typename T, typename Base = Owner> 120 class METHOD 121 { 122 public: Wrap(T (Base::* aFunc)())123 constexpr static GETTER_BASE<Owner, T>* Wrap( T (Base::*aFunc)() ) 124 { 125 return new GETTER<Owner, T, T (Base::*)()>( aFunc ); 126 } 127 Wrap(const T (Base::* aFunc)())128 constexpr static GETTER_BASE<Owner, T>* Wrap( const T (Base::*aFunc)() ) 129 { 130 return new GETTER<Owner, T, T (Base::*)()>( aFunc ); 131 } 132 Wrap(const T & (Base::* aFunc)())133 constexpr static GETTER_BASE<Owner, T>* Wrap( const T& (Base::*aFunc)() ) 134 { 135 return new GETTER<Owner, T, const T& (Base::*)()>( aFunc ); 136 } 137 Wrap(T (Base::* aFunc)()const)138 constexpr static GETTER_BASE<Owner, T>* Wrap( T (Base::*aFunc)() const ) 139 { 140 return new GETTER<Owner, T, T (Base::*)() const>( aFunc ); 141 } 142 Wrap(const T (Base::* aFunc)()const)143 constexpr static GETTER_BASE<Owner, T>* Wrap( const T (Base::*aFunc)() const ) 144 { 145 return new GETTER<Owner, T, const T (Base::*)() const>( aFunc ); 146 } 147 Wrap(const T & (Base::* aFunc)()const)148 constexpr static GETTER_BASE<Owner, T>* Wrap( const T& (Base::*aFunc)() const ) 149 { 150 return new GETTER<Owner, T, const T& (Base::*)() const>( aFunc ); 151 } 152 Wrap(void (Base::* aFunc)(T))153 constexpr static SETTER_BASE<Owner, T>* Wrap( void (Base::*aFunc)( T ) ) 154 { 155 return aFunc ? new SETTER<Owner, T, void (Base::*)( T )>( aFunc ) : nullptr; 156 } 157 Wrap(void (Base::* aFunc)(T &))158 constexpr static SETTER_BASE<Owner, T>* Wrap( void (Base::*aFunc)( T& ) ) 159 { 160 return aFunc ? new SETTER<Owner, T, void (Base::*)( T& )>( aFunc ) : nullptr; 161 } 162 Wrap(void (Base::* aFunc)(const T &))163 constexpr static SETTER_BASE<Owner, T>* Wrap( void (Base::*aFunc)( const T& ) ) 164 { 165 return aFunc ? new SETTER<Owner, T, void (Base::*)( const T& )>( aFunc ) : nullptr; 166 } 167 168 METHOD() = delete; 169 }; 170 171 172 class PROPERTY_BASE 173 { 174 private: 175 ///< Used to generate unique IDs. Must come up front so it's initialized before ctor. 176 177 public: 178 PROPERTY_BASE( const wxString& aName, PROPERTY_DISPLAY aDisplay = DEFAULT ) : m_name(aName)179 m_name( aName ), 180 m_display( aDisplay ), 181 m_availFunc( [](INSPECTABLE*)->bool { return true; } ) 182 { 183 } 184 ~PROPERTY_BASE()185 virtual ~PROPERTY_BASE() 186 { 187 } 188 Name()189 const wxString& Name() const 190 { 191 return m_name; 192 } 193 194 /** 195 * Return a limited set of possible values (e.g. enum). Check with HasChoices() if a particular 196 * PROPERTY provides such set. 197 */ Choices()198 virtual const wxPGChoices& Choices() const 199 { 200 static wxPGChoices empty; 201 return empty; 202 } 203 204 /** 205 * Set the possible values for for the property. 206 */ SetChoices(const wxPGChoices & aChoices)207 virtual void SetChoices( const wxPGChoices& aChoices ) 208 { 209 wxFAIL; // only possible for PROPERTY_ENUM 210 } 211 212 /** 213 * Return true if this PROPERTY has a limited set of possible values. 214 * @see PROPERTY_BASE::Choices() 215 */ HasChoices()216 virtual bool HasChoices() const 217 { 218 return false; 219 } 220 221 /** 222 * Return true if aObject offers this PROPERTY. 223 */ Available(INSPECTABLE * aObject)224 bool Available( INSPECTABLE* aObject ) const 225 { 226 return m_availFunc( aObject ); 227 } 228 229 /** 230 * Set a callback function to determine whether an object provides this property. 231 */ SetAvailableFunc(std::function<bool (INSPECTABLE *)> aFunc)232 void SetAvailableFunc( std::function<bool(INSPECTABLE*)> aFunc ) 233 { 234 m_availFunc = aFunc; 235 } 236 237 /** 238 * Return type-id of the Owner class. 239 */ 240 virtual size_t OwnerHash() const = 0; 241 242 /** 243 * Return type-id of the Base class. 244 */ 245 virtual size_t BaseHash() const = 0; 246 247 /** 248 * Return type-id of the property type. 249 */ 250 virtual size_t TypeHash() const = 0; 251 252 virtual bool IsReadOnly() const = 0; 253 GetDisplay()254 PROPERTY_DISPLAY GetDisplay() const 255 { 256 return m_display; 257 } 258 259 protected: 260 template<typename T> set(void * aObject,T aValue)261 void set( void* aObject, T aValue ) 262 { 263 wxAny a = aValue; 264 setter( aObject, a ); 265 } 266 267 template<typename T> get(void * aObject)268 T get( void* aObject ) 269 { 270 wxAny a = getter( aObject ); 271 272 if ( !( std::is_enum<T>::value && a.CheckType<int>() ) && !a.CheckType<T>() ) 273 throw std::invalid_argument( "Invalid requested type" ); 274 275 return wxANY_AS(a, T); 276 } 277 278 virtual void setter( void* aObject, wxAny& aValue ) = 0; 279 virtual wxAny getter( void* aObject ) const = 0; 280 281 private: 282 const wxString m_name; 283 const PROPERTY_DISPLAY m_display; 284 285 std::function<bool(INSPECTABLE*)> m_availFunc; ///< Eval to determine if prop is available 286 287 friend class INSPECTABLE; 288 }; 289 290 291 template<typename Owner, typename T, typename Base = Owner> 292 class PROPERTY : public PROPERTY_BASE 293 { 294 public: 295 typedef typename std::decay<T>::type BASE_TYPE; 296 typedef void (Base::*SETTER)( T ); 297 298 template<typename SetType, typename GetType> 299 PROPERTY( const wxString& aName, 300 void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )(), 301 PROPERTY_DISPLAY aDisplay = DEFAULT ) PROPERTY(aName,METHOD<Owner,T,Base>::Wrap (aSetter),METHOD<Owner,T,Base>::Wrap (aGetter),aDisplay)302 : PROPERTY( aName, METHOD<Owner, T, Base>::Wrap( aSetter ), 303 METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay ) 304 { 305 } 306 307 template<typename SetType, typename GetType> 308 PROPERTY( const wxString& aName, 309 void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )() const, 310 PROPERTY_DISPLAY aDisplay = DEFAULT ) PROPERTY(aName,METHOD<Owner,T,Base>::Wrap (aSetter),METHOD<Owner,T,Base>::Wrap (aGetter),aDisplay)311 : PROPERTY( aName, METHOD<Owner, T, Base>::Wrap( aSetter ), 312 METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay ) 313 { 314 } 315 OwnerHash()316 size_t OwnerHash() const override 317 { 318 return m_ownerHash; 319 } 320 BaseHash()321 size_t BaseHash() const override 322 { 323 return m_baseHash; 324 } 325 TypeHash()326 size_t TypeHash() const override 327 { 328 return m_typeHash; 329 } 330 IsReadOnly()331 bool IsReadOnly() const override 332 { 333 return !m_setter; 334 } 335 336 protected: PROPERTY(const wxString & aName,SETTER_BASE<Owner,T> * s,GETTER_BASE<Owner,T> * g,PROPERTY_DISPLAY aDisplay)337 PROPERTY( const wxString& aName, SETTER_BASE<Owner, T>* s, GETTER_BASE<Owner, T>* g, 338 PROPERTY_DISPLAY aDisplay ) 339 : PROPERTY_BASE( aName, aDisplay ), m_setter( s ), m_getter( g ), 340 m_ownerHash( TYPE_HASH( Owner ) ), m_baseHash( TYPE_HASH( Base ) ), 341 m_typeHash( TYPE_HASH( BASE_TYPE ) ) 342 { 343 } 344 ~PROPERTY()345 virtual ~PROPERTY() {} 346 setter(void * obj,wxAny & v)347 virtual void setter( void* obj, wxAny& v ) override 348 { 349 wxCHECK( !IsReadOnly(), /*void*/ ); 350 351 if( !v.CheckType<T>() ) 352 throw std::invalid_argument( "Invalid type requested" ); 353 354 Owner* o = reinterpret_cast<Owner*>( obj ); 355 BASE_TYPE value = wxANY_AS(v, BASE_TYPE); 356 (*m_setter)( o, value ); 357 } 358 getter(void * obj)359 virtual wxAny getter( void* obj ) const override 360 { 361 Owner* o = reinterpret_cast<Owner*>( obj ); 362 wxAny res = (*m_getter)( o ); 363 return res; 364 } 365 366 ///< Set method 367 std::unique_ptr<SETTER_BASE<Owner, T>> m_setter; 368 369 ///< Get method 370 std::unique_ptr<GETTER_BASE<Owner, T>> m_getter; 371 372 ///< Owner class type-id 373 const size_t m_ownerHash; 374 375 ///< Base class type-id 376 const size_t m_baseHash; 377 378 ///< Property value type-id 379 const size_t m_typeHash; 380 }; 381 382 383 template<typename Owner, typename T, typename Base = Owner> 384 class PROPERTY_ENUM : public PROPERTY<Owner, T, Base> 385 { 386 public: 387 template<typename SetType, typename GetType> 388 PROPERTY_ENUM( const wxString& aName, 389 void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )(), 390 PROPERTY_DISPLAY aDisplay = PROPERTY_DISPLAY::DEFAULT ) 391 : PROPERTY<Owner, T, Base>( aName, METHOD<Owner, T, Base>::Wrap( aSetter ), 392 METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay ) 393 { 394 if ( std::is_enum<T>::value ) 395 { 396 m_choices = ENUM_MAP<T>::Instance().Choices(); 397 wxASSERT_MSG( m_choices.GetCount() > 0, "No enum choices defined" ); 398 } 399 } 400 401 template<typename SetType, typename GetType> 402 PROPERTY_ENUM( const wxString& aName, 403 void ( Base::*aSetter )( SetType ), GetType( Base::*aGetter )() const, 404 PROPERTY_DISPLAY aDisplay = PROPERTY_DISPLAY::DEFAULT ) 405 : PROPERTY<Owner, T, Base>( aName, METHOD<Owner, T, Base>::Wrap( aSetter ), 406 METHOD<Owner, T, Base>::Wrap( aGetter ), aDisplay ) 407 { 408 if ( std::is_enum<T>::value ) 409 { 410 m_choices = ENUM_MAP<T>::Instance().Choices(); 411 wxASSERT_MSG( m_choices.GetCount() > 0, "No enum choices defined" ); 412 } 413 } 414 setter(void * obj,wxAny & v)415 virtual void setter( void* obj, wxAny& v ) override 416 { 417 wxCHECK( !( PROPERTY<Owner, T, Base>::IsReadOnly() ), /*void*/ ); 418 Owner* o = reinterpret_cast<Owner*>( obj ); 419 420 if( v.CheckType<T>() ) 421 { 422 T value = wxANY_AS(v, T); 423 (*PROPERTY<Owner, T, Base>::m_setter)( o, value ); 424 } 425 else if (v.CheckType<int>() ) 426 { 427 int value = wxANY_AS(v, int); 428 (*PROPERTY<Owner, T, Base>::m_setter)( o, static_cast<T>( value ) ); 429 } 430 else 431 { 432 throw std::invalid_argument( "Invalid type requested" ); 433 } 434 } 435 getter(void * obj)436 virtual wxAny getter( void* obj ) const override 437 { 438 Owner* o = reinterpret_cast<Owner*>( obj ); 439 wxAny res = static_cast<T>( (*PROPERTY<Owner, T, Base>::m_getter)( o ) ); 440 return res; 441 } 442 Choices()443 const wxPGChoices& Choices() const override 444 { 445 return m_choices; 446 } 447 SetChoices(const wxPGChoices & aChoices)448 void SetChoices( const wxPGChoices& aChoices ) override 449 { 450 m_choices = aChoices; 451 } 452 HasChoices()453 bool HasChoices() const override 454 { 455 return m_choices.GetCount() > 0; 456 } 457 458 protected: 459 wxPGChoices m_choices; 460 }; 461 462 463 class TYPE_CAST_BASE 464 { 465 public: ~TYPE_CAST_BASE()466 virtual ~TYPE_CAST_BASE() {} 467 virtual void* operator()( void* aPointer ) const = 0; 468 virtual const void* operator()( const void* aPointer ) const = 0; 469 virtual size_t BaseHash() const = 0; 470 virtual size_t DerivedHash() const = 0; 471 }; 472 473 474 template<typename Base, typename Derived> 475 class TYPE_CAST : public TYPE_CAST_BASE 476 { 477 public: TYPE_CAST()478 TYPE_CAST() 479 { 480 } 481 operator()482 void* operator()( void* aPointer ) const override 483 { 484 Base* base = reinterpret_cast<Base*>( aPointer ); 485 return static_cast<Derived*>( base ); 486 } 487 operator()488 const void* operator()( const void* aPointer ) const override 489 { 490 const Base* base = reinterpret_cast<const Base*>( aPointer ); 491 return static_cast<const Derived*>( base ); 492 } 493 BaseHash()494 size_t BaseHash() const override 495 { 496 return TYPE_HASH( Base ); 497 } 498 DerivedHash()499 size_t DerivedHash() const override 500 { 501 return TYPE_HASH( Derived ); 502 } 503 }; 504 505 506 template<typename T> 507 class ENUM_MAP 508 { 509 public: Instance()510 static ENUM_MAP<T>& Instance() 511 { 512 static ENUM_MAP<T> inst; 513 return inst; 514 } 515 Map(T aValue,const wxString & aName)516 ENUM_MAP& Map( T aValue, const wxString& aName ) 517 { 518 m_choices.Add( aName, static_cast<int>( aValue ) ); 519 m_reverseMap[ aName ] = aValue; 520 return *this; 521 } 522 Undefined(T aValue)523 ENUM_MAP& Undefined( T aValue ) 524 { 525 m_undefined = aValue; 526 return *this; 527 } 528 ToString(T value)529 const wxString& ToString( T value ) const 530 { 531 static const wxString s_undef = "UNDEFINED"; 532 533 int idx = m_choices.Index( static_cast<int>( value ) ); 534 535 if( idx >= 0 && idx < (int) m_choices.GetCount() ) 536 return m_choices.GetLabel( static_cast<int>( idx ) ); 537 else 538 return s_undef; 539 } 540 IsValueDefined(T value)541 bool IsValueDefined( T value ) const 542 { 543 int idx = m_choices.Index( static_cast<int>( value ) ); 544 545 if( idx >= 0 && idx < (int) m_choices.GetCount() ) 546 return true; 547 548 return false; 549 } 550 ToEnum(const wxString value)551 const T ToEnum( const wxString value ) 552 { 553 if( m_reverseMap.count( value ) ) 554 return m_reverseMap[ value ]; 555 else 556 return m_undefined; 557 } 558 Choices()559 wxPGChoices& Choices() 560 { 561 return m_choices; 562 } 563 564 private: 565 wxPGChoices m_choices; 566 std::unordered_map<wxString, T> m_reverseMap; 567 T m_undefined; // Returned if the string is not recognized 568 569 ENUM_MAP<T>() 570 { 571 } 572 }; 573 574 575 // Helper macros to handle enum types 576 #define DECLARE_ENUM_TO_WXANY( type ) \ 577 template <> \ 578 class wxAnyValueTypeImpl<type> : public wxAnyValueTypeImplBase<type> \ 579 { \ 580 WX_DECLARE_ANY_VALUE_TYPE( wxAnyValueTypeImpl<type> ) \ 581 public: \ 582 wxAnyValueTypeImpl() : wxAnyValueTypeImplBase<type>() {} \ 583 virtual ~wxAnyValueTypeImpl() {} \ 584 virtual bool ConvertValue( const wxAnyValueBuffer& src, wxAnyValueType* dstType, \ 585 wxAnyValueBuffer& dst ) const override \ 586 { \ 587 type value = GetValue( src ); \ 588 ENUM_MAP<type>& conv = ENUM_MAP<type>::Instance(); \ 589 if( ! conv.IsValueDefined( value ) ) \ 590 { \ 591 return false; \ 592 } \ 593 if( dstType->CheckType<wxString>() ) \ 594 { \ 595 wxAnyValueTypeImpl<wxString>::SetValue( conv.ToString( value ), dst ); \ 596 return true; \ 597 } \ 598 if( dstType->CheckType<int>() ) \ 599 { \ 600 wxAnyValueTypeImpl<int>::SetValue( static_cast<int>( value ), dst ); \ 601 return true; \ 602 } \ 603 else \ 604 { \ 605 return false; \ 606 } \ 607 } \ 608 }; 609 610 #define IMPLEMENT_ENUM_TO_WXANY( type ) WX_IMPLEMENT_ANY_VALUE_TYPE( wxAnyValueTypeImpl<type> ) 611 612 #define ENUM_TO_WXANY( type ) \ 613 DECLARE_ENUM_TO_WXANY( type ) \ 614 IMPLEMENT_ENUM_TO_WXANY( type ) 615 616 ///< Macro to define read-only fields (no setter method available) 617 #define NO_SETTER( owner, type ) ( ( void ( owner::* )( type ) ) nullptr ) 618 619 /* 620 #define DECLARE_PROPERTY(owner,type,name,getter,setter) \ 621 namespace anonymous {\ 622 static PROPERTY<owner,type> prop##_owner##_name_( "##name#", setter, getter );\ 623 }; 624 */ 625 #endif /* PROPERTY_H */ 626