00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef IDIOSKOPOSINTROSPECTABLE_H
00021 #define IDIOSKOPOSINTROSPECTABLE_H
00022
00023 #include <map>
00024 #include <string>
00025
00026 #include <sigc++/sigc++.h>
00027
00028 #include <idioskopos/pointer.h>
00029 #include <idioskopos/error.h>
00030 #include <idioskopos/object.h>
00031 #include <idioskopos/property.h>
00032 #include <idioskopos/referenceproperty.h>
00033
00034 namespace Idioskopos
00035 {
00036
00037 typedef std::map<Object*, Object::pointer> DynamicPropertyMap;
00038 typedef std::map<Glib::ustring, Object*> PropertyMap;
00039
00044 class Introspectable: public Object
00045 {
00046 public:
00047 typedef IdioskoposPointer<Introspectable> pointer;
00048
00049 IDIOSKOPOS_OBJECT_AND_REGISTRAR(Introspectable);
00050
00051 Introspectable( const Glib::ustring& name,
00052 sigc::slot<void> slot=sigc::slot<void>() );
00053
00054 Introspectable( const Glib::ustring& name,
00055 Introspectable& container,
00056 sigc::slot<void> slot=sigc::slot<void>() );
00057
00058 static pointer create( const Glib::ustring& name,
00059 sigc::slot<void> slot=sigc::slot<void>() );
00060
00061 static pointer create( const Glib::ustring& name,
00062 Introspectable& container,
00063 sigc::slot<void> slot=sigc::slot<void>() );
00064
00065 ~Introspectable();
00066
00067 Object* get_property( const Glib::ustring& name );
00068
00069 bool has_property( const Glib::ustring& name );
00070
00074 bool add_property( Object& property );
00075
00076 bool add_property( Object::pointer property );
00077
00078 void remove_property( const Glib::ustring& name );
00079
00080 sigc::signal<void, Object*> signal_property_value_changed();
00081
00082 sigc::signal<void, Object*, const Glib::ustring&> signal_property_name_changed();
00083
00084 virtual sigc::signal<void, Object*> signal_property_added();
00085
00086 virtual sigc::signal<void, Object*> signal_property_removed();
00087
00088 template <typename T>
00089 PropertyBase<T>& property( const Glib::ustring& name );
00090
00091 template <typename T>
00092 PropertyBase<T>* property_ptr( const Glib::ustring& name );
00093
00094 const std::type_info& type() const
00095 {
00096 return typeid( Introspectable );
00097 }
00098
00104 virtual size_t num_properties() const;
00105
00106 virtual Glib::ustring xml(int indent=-1);
00107
00108 virtual void set_xml(const Glib::ustring& s, bool change_names=false, bool create_missing=true);
00109
00110 virtual void set_xml(const xmlpp::Node* n, bool change_names=false, bool create_missing=true);
00111
00112 virtual iterator properties_begin();
00113 virtual iterator properties_end();
00114
00115 virtual Object& operator[] ( const Glib::ustring& name ) throw ( error::bad_property_name );
00116
00117 protected:
00118 std::set<Object*> m_properties;
00119 PropertyMap m_property_name_map;
00120 DynamicPropertyMap m_dynamic_property_map;
00121
00122 Glib::ustring m_separator;
00123
00124 sigc::signal<void, Object*> m_signal_property_value_changed;
00125 std::map<Object*, sigc::connection> m_property_value_changed_connection;
00126 void on_property_value_changed( Object* );
00127
00128 sigc::signal<void, Object*, const Glib::ustring&> m_signal_property_name_changed;
00129 std::map<Object*, sigc::connection> m_property_name_changed_connection;
00130 void on_property_name_changed( const Glib::ustring&, Object* );
00131
00132
00133 sigc::signal<void, Object*> m_signal_property_added;
00134
00135 sigc::signal<void, Object*> m_signal_property_removed;
00136
00137 virtual iterator next_property(std::set<Object*>::iterator i);
00138
00139 virtual iterator previous_property(std::set<Object*>::iterator i);
00140 };
00141
00142 template <typename T>
00143 inline
00144 PropertyBase<T>& Introspectable::property( const Glib::ustring& name )
00145 {
00146 Object * pb = get_property( name );
00147 if ( pb == NULL )
00148 throw error::bad_property_name();
00149 try {
00150 PropertyBase<T>& prop = dynamic_cast<PropertyBase<T>&>( *pb );
00151 return prop;
00152 } catch ( ... ) {
00153 throw error::cast::wrong_property_type();
00154 }
00155 }
00156
00157 template <typename T>
00158 inline
00159 PropertyBase<T>* Introspectable::property_ptr( const Glib::ustring& name )
00160 {
00161 PropertyBase<T>* prop;
00162 Object* pb = get_property( name );
00163 if ( pb == NULL )
00164 return NULL;
00165 try {
00166 prop = dynamic_cast<PropertyBase<T>*>( pb );
00167 return prop;
00168 } catch ( ... ) {
00169 return NULL;
00170 }
00171 }
00172
00173 }
00174
00175 #endif