coriolis/hurricane/doc/hurricane/SlotAdapter.dox

320 lines
13 KiB
C++

// -*- C++ -*-
namespace Hurricane {
/*! \defgroup inspectorManagment Inspector : Live Database Explorator (internal)
*
*
* \section sInspectorIntro Introduction
*
* The Hurricane Database provide a generic mechanism to allow
* the inspection of the whole data structure at run-time.
* The associated window/tool is called "The Inspector".
*
* In this section, we will describe how the inspection
* mechanism to new objects.
*
*
* \subsection ssSlotAdapter The SlotAdapter
*
* First, we introduce the SlotAdapter object. Any inspectable
* object has to be associated (see the next section) with a
* SlotAdapter. It's providing the following methods :
\code
class SlotAdapter {
public:
virtual string _GetTypename () const;
virtual string _GetString () const;
virtual Record* _GetRecord () const;
inline virtual Slot* _GetSlot ( const string& name ) const;
};
\endcode
*
*
* Thoses methods correspond to :
* <ul>
* <li>\b _GetTypeName() : the inspected object's type.
* <li>\b _GetString() : a synthetic string description of the
* object's state.
* <li>\b _GetRecord() : the complete description of all object's
* attributes (a list of Slot).
* <li>\b _GetSlot() : a Slot build from this SlotAdapter. As this
* function is supplied by default with the right implementation
* we will not detail it here.
* </ul>
*
*
* \subsection ssObjectTypology Typology of inspectables objects
*
* We distinguish three kind of objects, corresponding to three
* different ways of association to a SlotAdapter.
* <ul>
* <li><b>User defined, with virtual methods</b> : those objects
* must inherit from the NestedSlotAdapter class.
* <li><b>User defined, without virtual methods</b> : thoses
* objects must provides (as ordinary methods)
* \b _GetTypeName() , \b _GetString() , \b _GetRecord() .
* But \b not \b _GetSlot().
* <li><b>External objects</b> : that is, we cannot modify.
* In this case we have to provide a specialised template
* overload for \b ProxyTypeName<>() , \b ProxyString<>() ,
* and \b ProxyRecord<>() (see \ref ssExternalObjects).
* </ul>
*
*
* \subsection ssUserDefinedVirtual User Defined Object with virtual methods
*
* This approach should be preferrred for complex objects
* that are persistents in memory.
*
* Example of implementation :
\code
namespace MyTool {
class MyClass : public NestedSlotAdapter {
protected:
int _value;
public:
int GetValue () const { return _value; }
virtual string _GetTypeName() const { return "MyClass"; };
virtual string _GetString () const { return "<MyClass"+GetString(_value)+">"; };
virtual Record* _GetRecord () const;
};
Record* MyClass::GetRecord () const {
Record* record = new Record(_GetString());
record->Add ( GetSlot("_value",&_value) );
return record;
}
} // End of MyTool namespace.
SetNestedSlotAdapter(MyTool::MyClass)
\endcode
*
* \e MyClass derives from NestedSlotAdapter. Any derived class of
* \e MyClass will inherit of it, so you do not have to (and musn't)
* repeat the inheritance from NestedSlotAdapter.
*
* \e SetNestedSlotAdapter() must be put outside any namespace.
*
* \e SetNestedSlotAdapter() must never be called on objects that do
* not derives from NestedSlotAdapter. There's builtin safety :
* a \c static_cast into NestedSlotAdapter that will make the
* compiler fail.
*
* \e SetNestedSlotAdapter() may be omitted, at the cost of generating
* a intermediary SlotAdapter (that will cost two pointers). Nevertheless
* it will work.
*
*
* \subsection ssUserDefinedWithoutVirtual User Defined Object without virtual methods
*
* This implementation should be preferred for light objects
* that are instanciated in vast amounts (we gain the \e vtable
* pointer over the previous approach).
*
* Example of implementation :
\code
namespace MyTool {
class MyLightClass {
protected:
int _value;
public:
int GetValue () const { return _value; }
string _GetTypeName() const { return "MyLightClass"; };
string _GetString () const { return "<MyLightClass"+GetString(_value)+">"; };
Record* _GetRecord () const;
};
Record* MyLightClass::GetRecord () const {
Record* record = new Record(_GetString());
record->Add ( GetSlot("_value",&_value) );
return record;
}
} // End of MyTool namespace.
\endcode
*
* The methods \b _GetTypeName() , \b _GetString() and \b GetRecord()
* are now non-virtual and there's no call to \b SetNestedSlotAdapter() .
*
*
* \subsection ssExternalObjects External Objects
*
* This is the implementation to uses for managing objects
* from other libraries that we should want to browse in the
* Inspector. In this case we have to provide three overload
* of template functions, as shown below (for boolean type) :
\code
template<>
inline string ProxyTypeName<bool> ( const bool* object ) { return "<PointerSlotAdapter<bool>>"; }
template<>
inline string ProxyString<bool> ( const bool* object ) { return (*object)?"True":"False" ; }
template<>
inline Record* ProxyRecord<bool> ( const bool* object ) { return NULL; }
\endcode
*
*
* \section sGetStringAndGetSlot GetString() and GetSlot() functions
*
* When a class or type is provided with Inspector support,
* you may uses the two generic functions below :
\code
template<typename T> inline string GetString ( T* t );
template<typename T> inline string GetString ( T t );
template<typename T> inline Hurricane::Slot* GetSlot ( const string& name, T* t );
template<typename T> inline Hurricane::Slot* GetSlot ( const string& name, T t );
\endcode
*
* GetString() may be used to print some debugging informations
* on \stdout.
*
* GetSlot() used to built the various entries in a \b _GetRecord()
* method.
*
* <b>Argument type policy</b>
*
* As you noticed there are two overload for each function,
* one with pointer argument, the other with a value argument.
* This is meaningful :
* <ul>
* <li>Passing by pointer means that the data being inspected
* is persistent, and should not be deleted once the
* inspector is closed. This is the case of all DBo
* objects and, for example, Box objects when they are
* attributes of another object.
* <li>Passing by value, means that the data is volatile and
* should be deleted at the inspector closing. As an
* example, the bounding box of an instance which is
* computed on the fly, we must copy the result into
* the SlotAdapter but no longer need it afterwards.
* An important consequence is that thoses objects
* must have a valid copy constructor.
* </ul>
*
* <b>Default type support</b>
*
* Hurricane provide support for the following types :
* <ul>
* <li><b>const char</b>
* <li><b>const char*</b>
* <li><b>const string*</b>
* <li><b>const bool*</b>
* <li><b>const void*</b>
* <li><b>const int*</b>
* <li><b>const long*</b>
* <li><b>const unsigned int*</b>
* <li><b>const unsigned long*</b>
* <li><b>const unsigned long long*</b>
* <li><b>const unsigned short int*</b>
* <li><b>const float*</b>
* <li><b>const double*</b>
* </ul>
* Note that, as long as the pointer type is supported, the value
* is also (except for the \b char type which has a somewhat more
* complex behavior).
*
* It also provide support for the following \STL containers :
* <ul>
* <li><b>const vector<Element>*</b>
* <li><b>const list<Element>*</b>
* <li><b>const map<Key,Element,Compare>*</b>
* <li><b>const set<Element,Compare>*</b>
* <li><b>const multiset<Element,Compare>*</b>
* </ul>
*
*
* \section sIOStreamSupport Support for iostream
*
* If an object (with inspector support) is often printed into
* a stream, you may define an overload of \b operator<<() with
* either the \b PointerIOStreamSupport() or \b ValueIOStreamSupport()
* macros. The macros must in the top-level namespace.
*
*
* \section sLastNote A note for myself
*
* About the deletion mechanism : there are two level of deletion,
* the SlotAdapter deletion and the object deletion.
*
* Object deletion is managed by the SlotAdapter : if the SlotAdapter
* is nested in the object, do not delete, otherwise delete.
*
* SlotAdapter deletion is managed at Slot level : if the object
* is passed by pointer, do not delete the SlotAdapter. if the object
* is passed by value, delete the SlotAdapter.
*/
//! \addtogroup inspectorManagment
//! \{
/*! \class SlotAdapter
* \brief Root class. Provide support for duplicatable objects (\b internal).
*/
/*! \class NestedSlotAdapter
* \brief Provide Inspector support for non-duplicatable (\b internal).
*/
/*! \class PointerSlotAdapter
* \brief Provide Inspector support for external persistant objects (\b internal).
*/
/*! \class ValueSlotAdapter
* \brief Provide Inspector support for external volatile objects (\b internal).
*/
// \}
/*! \name Accessors
*/
// \{
/*! \function string SlotAdapter::_GetTypeName () const;
* \Return a string representing the object type. May be used by
* SlotAdapter::_GetString().
*
* \note No default implementation is supplied.
*/
/*! \function string SlotAdapter::_GetString () const;
* \Return a string representing the object name and characteristics
* in a synthetic way. Used, among other things, as title
* for the Inspector Record browser.
*
* \note Default implementation is supplied, which returns the
* string \c "SlotAdapter::_GetString()" .
*/
/*! \function Record* SlotAdapter::_GetRecord () const;
* \Return a Record representing the object current state.
*
* \note Default implementation is supplied, which returns \NULL.
*/
/*! \function Slot* SlotAdapter::_GetSlot ( const string& name ) const;
* \param name the name to give to the Slot. Usually the class attribute
* name.
* \return a Slot associated to this object to insert into another Record.
* As SlotAdapter is for user-defined objects without virtual
* method the SlotAdapter is created aside to the inspected
* object and must be removed afterwards, so we uses a ValueSlot.
*/
/*! \function Slot* NestedSlotAdapter::_GetSlot ( const string& name ) const;
* \param name the name to give to the Slot. Usually the class attribute
* name.
* \return a Slot associated to this object to insert into another Record.
* NestedSlotAdapter is for user-defined objects with virtual
* method, it must be a base class of the object, and as such
* the object \e is the SlotAdapter. So the removal of the Slot
* must left the SlotAdapter, for this we uses a PointerSlot.
*/
}