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