00001 /*! \file 00002 \author victorien ferry & www.m4nkind.com 00003 \brief This file applies the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1 , read file COPYING. 00004 */ 00005 #ifndef COM_M4NKIND_BaseContext_H 00006 #define COM_M4NKIND_BaseContext_H 00007 00008 #include "BaseObject.h" 00009 #include "ClassNode.h" 00010 #include "PackList.h" 00011 00012 class PackObjectReference; 00013 class PackResource; 00014 class VirtualMachine; 00015 /*! 00016 \class BaseContextTool 00017 \brief base model for extending more Tool Methods to BaseContext. 00018 */ 00019 class BaseContextTool {}; 00020 00021 /*! 00022 \class BaseContext 00023 \ingroup BaseContextDocGroup 00024 \brief \ref BaseContextDocGroup "You may also browse the BaseContext Related Documentations page sorted by theme."\n 00025 Class that manages a whole database as a set of Objects inheriting class BaseObject.\n 00026 BaseContext::Serialize_Out() and BaseContext::Serialize_In() will provide a quick and full 00027 persistent serialization of all features of a whole azurveda Context. When reading the context, 00028 the objects references will be resolved. 00029 In editable compilation mode you can use: 00030 - Hook notifications for all events, useful for Graphical Interfaces: see AddGUIUpdateFunction() 00031 - Merge serialization: simply melt as many context objects you want with MergeSerialize_In() 00032 - Hability to destroy all objects that are useless to a given object with DestroyAllIndependantObjects(). 00033 Together with the merge method, it gives a complete control for large and complex contexts. 00034 - automatic Undo/Redo stack functionnalities with Undo(), Redo(), SetMaximumNumberOfUndoableEvents(). 00035 This undoes affect the modification of any editable object members in the context. 00036 (BETA: currently,undo stack is flushed when an element is destroyed in a list.) 00037 - Thread management withAddOneLockForThreadUse(),RemoveOneLockForThreadUse().\n 00038 \n 00039 To use a context object, you first init a context by registering possible extended classes 00040 or packages, derived from BaseObject, with RegisterClassList(). 00041 In editable mode, you can create new BaseObjects using the BaseContext::NewObject(), and destroy them with 00042 BaseContext::DestroyObject(). Then you can initialize each objects using BaseObject::Create(), and close 00043 them with BaseObject::Close(). See BaseObject for more informations on Object Creation.\n 00044 After the context is created, you can provide a VirtualMachine with SetMachine(), 00045 it stands for the hardware-abstracted machine its objects will use.\n 00046 00047 Low Level internal notes: 00048 - Internally, and transparently for the user, BaseContext manage a tree of the known classes with ClassNode. 00049 - BaseContext is derived from ClassNode, it Manages the virtual 'BaseObject', as a ClassNode. 00050 - It is possible to get the serialized size of the whole context at any moment with GetSerializedSize() 00051 */ 00052 class BaseContext : public ClassNode 00053 { 00054 /*================================================================== 00055 PUBLIC 00056 ==================================================================*/ 00057 public: 00058 friend class BaseObject; 00059 friend class BaseContextTool; 00060 friend class PackResource; 00061 friend class PackObjectReference; 00062 /*! 00063 \ingroup BaseContextDocGroup_InitMethods 00064 \brief Constructor. 00065 */ 00066 BaseContext(void); 00067 #ifdef _ENGINE_EDITABLE_ 00068 /*! 00069 \ingroup BaseContextDocGroup_InitMethods 00070 \brief Destructor. 00071 */ 00072 virtual ~BaseContext(void); 00073 #endif 00074 #ifdef _ENGINE_EDITABLE_ 00075 /*! 00076 \ingroup BaseContextDocGroup_ObjectEditionMethods 00077 \brief Faktory Method to create a new Object in the context. All object members 00078 should be inited to default, then use BaseObject's Set methods in editable mode to modify them. 00079 You must pass a valid Class descriptor and an _ObjectName, or nothing, in which case 00080 a name will be computed according to the class. If an object with the same name 00081 exists, then a new name is computed. get the final name with BaseObject::GetName(); 00082 This method is only compiled in editable mode, in non-editable, Serialize_In() should construct everything. 00083 \param _classDescription the description struct of a class, like BaseObject::m_Description 00084 \param _ObjectName. the objectName then used to reference it can be NULL, then a new name is computed. 00085 \return The Object Created. 0L if class unknown or anywhat. 00086 */ 00087 BaseObject *NewObject( const BaseObject::ClassDescription & _classDescription ,char * _ObjectName=0L ); 00088 #endif 00089 #ifdef _ENGINE_EDITABLE_ 00090 /*! 00091 \ingroup BaseContextDocGroup_ObjectEditionMethods 00092 \brief In editable mode, it is possible to destroy an object from the context base: 00093 You got to use this method, not "delete". 00094 \param _objectToDelete The object to delete. 00095 */ 00096 void DestroyObject( BaseObject * _objectToDelete ); 00097 #endif 00098 #ifdef _ENGINE_EDITABLE_ 00099 /*! 00100 \ingroup BaseContextDocGroup_ObjectEditionMethods 00101 \brief Really destroy all object from the context. It should result a clean 00102 context like it it was just constructed empty. 00103 */ 00104 void DestroyAllObjects( ); 00105 #endif 00106 #ifdef _ENGINE_EDITABLE_ 00107 /*! 00108 \ingroup BaseContextDocGroup_ObjectEditionMethods 00109 \brief All File Resources used by objects in the context will be set 00110 as binaries Linked within the context, or not according to parameter. 00111 \param _isLink true: is linked, false, is in file. 00112 */ 00113 void Resources_SetLinkModeToAll(bool _isLink ); 00114 #endif 00115 /*! 00116 \ingroup BaseContextDocGroup_InputOutputMethods 00117 \brief Read the object description from a byte chunk. Could crash if chunk not valid. 00118 It serializes first the class name, the number of object instancied, then 00119 the number of sub-classnodes instancied, then all object instancied, then 00120 all subclasses recursively. 00121 */ 00122 virtual const unsigned char * Serialize_In( const unsigned char * _pDescriptionChunk); 00123 #ifdef _ENGINE_EDITABLE_ 00124 /*! 00125 \ingroup BaseContextDocGroup_InputOutputMethods 00126 \brief get the size of the whole byte chunk that will be written by Serialize_Out(). 00127 \return byte size of the serialisation to do. 00128 */ 00129 virtual unsigned int GetSerializedDescriptionSize(void); 00130 #endif 00131 #ifdef _ENGINE_EDITABLE_ 00132 /*! 00133 \ingroup BaseContextDocGroup_InputOutputMethods 00134 \brief write the Current object definition to a Chunk using private packed types, recursively. 00135 \param _pDescriptionChunkToFill the chunk where to write the objet description chunk. 00136 \return the end of the chunk written, possibly unlocated. Don't use this if you don't need it. 00137 */ 00138 virtual unsigned char * Serialize_Out(unsigned char * _pDescriptionChunkToFill); 00139 #endif 00140 /*! 00141 \ingroup BaseContextDocGroup_InitMethods 00142 \brief Link a VirtualMachine object to the Context, to provide 00143 a hardware/API abstraction that objects will use. 00144 You must use this after the constructor and before serialization 00145 or any edition. the context DOES NOT manage machine object destruction. 00146 so don't destroy it 'till context is destroyed. 00147 \param _pMachine the machine then used by the context 00148 */ 00149 virtual void SetMachine( VirtualMachine *_pMachine ){ m_pMachine =_pMachine; }; 00150 /*! 00151 \ingroup BaseContextDocGroup_InitMethods 00152 \brief return the machine currently linked to the context. 00153 \param _pMachine the machine then used by the context 00154 */ 00155 inline VirtualMachine *GetMachine(){ return m_pMachine; }; 00156 00157 #ifdef _ENGINE_EDITABLE_ 00158 /*! 00159 \brief Each BaseType's inherited classes must explicit an ID for their 00160 class, or let use one of the super class at least through this virtual method. 00161 This is needed by GUIs to detect the types of each sub-members, and shape 00162 an interface for each Object according to their member list. 00163 \return a const character string, that must be unique and unchanged for all serializable base type. 00164 */ 00165 virtual const char *GetClassID() const { return "BaseContext"; }; 00166 #endif 00167 #ifdef _ENGINE_EDITABLE_ 00168 00169 /*! 00170 \ingroup BaseContextDocGroup_EventManagement 00171 \brief Used by BaseObjects "%Set()" member methods to notify what happened when one of 00172 the member was edited, to change its value. It is used to manage the Undo/Redo capability. 00173 You should not use this method unless you create a PackSerializable base type and code it's Set() accessor. 00174 \param _UpDateType eVedaUpdate enum that identify the update info type. 00175 \param _pObjectEdited BaseObject if _UpDateType is about an object or member. 00176 \param _ObjectMember BaseType if _UpDateType is about a member. 00177 \param _PreviousShapeChunk optionnal serialization of the previous state or 0L. 00178 \param _PreviousShapeChunkLength optionnal serialization of the previous state or 0L. 00179 \param _NewShapeChunk optionnal serialization of the new state or 0L. 00180 \param _NewShapeChunkLength optionnal serialization of the new state or 0L. 00181 */ 00182 void NotifyObjectChange( eVedaUpdate _UpDateType, BaseObject *_pObjectEdited, BaseType *_ObjectMember, 00183 const unsigned char *_PreviousShapeChunk=0L, 00184 unsigned int _PreviousShapeChunkLength=0L, 00185 const unsigned char *_NewShapeChunk=0L, 00186 unsigned int _NewShapeChunkLength=0L 00187 ); 00188 #endif 00189 /*! 00190 \brief used to scan the list of all object-to-object reference in this context. 00191 you can scan the list by then using PackObjectReference::GetPointerOnNextObjectReferenceInContextList() 00192 \return the first PackObjectReference. 00193 */ 00194 inline PackObjectReference *GetFirstObjectReferenceInContextList(){ return m_pFirstObjectReferenceInContextList; }; 00195 00196 #ifdef _ENGINE_EDITABLE_ 00197 /*! 00198 \ingroup BaseContextDocGroup_Undoing 00199 \brief test if an Undo() is currently possible. Useful to enable or disable an 00200 Undo Function in an interface. 00201 \return true if it is. 00202 */ 00203 virtual bool CanUndo(); 00204 #endif 00205 #ifdef _ENGINE_EDITABLE_ 00206 /*! 00207 \ingroup BaseContextDocGroup_Undoing 00208 \brief Undo the last modification done on any object of the base, using a private "action history stack". 00209 \return true if the undo was "undone", false if no more undo available. 00210 */ 00211 virtual bool Undo(); 00212 #endif 00213 #ifdef _ENGINE_EDITABLE_ 00214 /*! 00215 \ingroup BaseContextDocGroup_Undoing 00216 \brief test if an Redo() is currently possible. Useful to enable or disable a 00217 Redo Function in an interface. 00218 \return true if it is. 00219 */ 00220 virtual bool CanRedo(); 00221 #endif 00222 #ifdef _ENGINE_EDITABLE_ 00223 /*! 00224 \ingroup BaseContextDocGroup_Undoing 00225 \brief Redo the last undo on any object of the base, using a private "action history stack". 00226 \return true if the last undo was "redone", false if no more redo available. 00227 */ 00228 virtual bool Redo(); 00229 #endif 00230 #ifdef _ENGINE_EDITABLE_ 00231 /*! 00232 \ingroup BaseContextDocGroup_Undoing 00233 \brief Flush the Undo Stack: no undo or redo possible until next modification. 00234 Some edition events (object destruction) on the context need to completely 00235 erase the Undo stack, because the event stack coherence is broken. 00236 */ 00237 void FlushUndoStack(); 00238 #endif 00239 #ifdef _ENGINE_EDITABLE_ 00240 /*! 00241 \ingroup BaseContextDocGroup_Undoing 00242 \brief The undo stack history can be less or more large. Default max is 0: no undo management. 00243 \param _maxnumber maximum number of undoable event. 00244 */ 00245 void SetMaximumNumberOfUndoableEvents( unsigned int _maxNumber ); 00246 #endif 00247 #ifdef _ENGINE_EDITABLE_ 00248 /*! 00249 \ingroup BaseContextDocGroup_EventManagement 00250 \brief You can specify one or more abstract GUI Views to update, by 00251 registering a function or a static method, that will be executed 00252 after each set() done on a member of a managed object, when editing, 00253 and even for a undo/redoes. This function will receive a const description of what 00254 was changed: the context concerned, the object concerned, and the object member concerned. 00255 \param _func You must pass a function pointer on a static method pointer. 00256 \param _GUIObjectToUpdate a user object of your choice that will be returned for this function, or NULL. 00257 */ 00258 void AddGUIUpdateFunction( void (*_func)(void *_GUIObjectToUpdateReturned,eVedaUpdate _updateType,BaseContext *_ContextUpdated,BaseObject *_ObjectUpdated,BaseType *_MemberUpdated) , 00259 void *_GUIObjectToUpdate 00260 ); 00261 #endif 00262 #ifdef _ENGINE_EDITABLE_ 00263 /*! 00264 \ingroup BaseContextDocGroup_EventManagement 00265 \brief Remove an update function set by AddGUIUpdateFunction() 00266 \param _func the func pointer to remove. 00267 \return true if removed, false if unknown. 00268 */ 00269 bool RemoveGUIUpdateFunction( void (*_func)(void *_GUIObjectToUpdateReturned,eVedaUpdate _updateType,BaseContext *_ContextUpdated,BaseObject *_ObjectUpdated,BaseType *_MemberUpdated)) ; 00270 #endif 00271 #ifdef _ENGINE_EDITABLE_ 00272 /*! 00273 \ingroup BaseContextDocGroup_EventManagement 00274 \brief send an update function to all registered GUIs. 00275 \param the update case. 00276 \param _ObjectUpdated the object updated in this context. 00277 \param _MemberUpdated the member of the object updated. 00278 */ 00279 void UpdateAllGUI( eVedaUpdate _updateType,BaseObject *_ObjectUpdated,BaseType *_MemberUpdated); 00280 #endif 00281 00282 #ifdef _ENGINE_EDITABLE_ 00283 /*! 00284 \ingroup BaseContextDocGroup_ObjectEditionMethods 00285 \brief Remove all objects that are not refered directly or indirectly by the object passed. 00286 \param _pObjectWhichAllOtherShouldDependOn Object Which All Other Should Depend On. 00287 */ 00288 void DestroyAllIndependantObjects( BaseObject *_pObjectWhichAllOtherShouldDependOn ); 00289 #endif 00290 #ifdef _ENGINE_EDITABLE_ 00291 /*! 00292 \ingroup BaseContextDocGroup_InputOutputMethods 00293 \brief Acts like Serialize_In() but keep all previous objects. 00294 So you can load and mix 2 or more context this way. 00295 \param _pDescriptionChunk the binary image of a context. 00296 \param _pendName specify a name to add at the end of each new object. 00297 */ 00298 virtual const unsigned char * MergeSerialize_In( const unsigned char * _pDescriptionChunk,const char *_pendName=0L); 00299 #endif 00300 #ifdef _ENGINE_EDITABLE_ 00301 /*! 00302 \ingroup BaseContextDocGroup_EventManagement 00303 \brief Even in editable mode, only one thread owns a context and can 00304 edit, modify, use and destroy it. Other threads can just use 00305 its objects and methods through a AddOneLockForThreadUse() 00306 RemoveOneLockForThreadUse() pair. If false is returned, 00307 it means the lock can't be done, and you should wait a bit and retry. 00308 This way, it avoids cases where an object is modified by the owner thread 00309 and used by another.(For Example, the sound management thread of the Machines use it.) 00310 Add/RemoveOneLockForThreadUse() must only be used by other threads. 00311 Don't use RemoveOneLockForThreadUse() if false is returned. 00312 00313 Note: you can't use BaseObject::Create() on an object from another thread. 00314 But you have to test isCreated() before using object's method, like in the main thread: 00315 isCreated() ensures the object is coherently inited. 00316 */ 00317 virtual bool AddOneLockForThreadUse(); 00318 #endif 00319 #ifdef _ENGINE_EDITABLE_ 00320 /*! 00321 \ingroup BaseContextDocGroup_EventManagement 00322 \brief Even in editable mode, only one thread owns a context and can 00323 edit, modify, use and destroy it. Other threads can just use 00324 its objects and methods through a AddOneLockForThreadUse() 00325 RemoveOneLockForThreadUse() pair. This is to avoid using an object 00326 which could be modified or destroyed by the owner thread. 00327 (it was made for sound management.) 00328 */ 00329 virtual void RemoveOneLockForThreadUse(); 00330 #endif 00331 00332 #ifdef _ENGINE_EDITABLE_ 00333 /*! 00334 \ingroup BaseContextDocGroup_ObjectEditionMethods 00335 \brief give to _ContextToModify the same shape as this. 00336 It means, the same classes are first registered to it, and then 00337 the same objects are cloned into it. 00338 \param _pContextToModify to object modified to shape this. 00339 */ 00340 void CloneClassesAndObjects(BaseContext *_pContextToModify); 00341 #endif 00342 00343 #ifdef _ENGINE_EDITABLE_ 00344 /*! 00345 \ingroup BaseContextDocGroup_InputOutputMethods 00346 \brief Export a .cpp file with 2 tables: 00347 - First, a table of all the class descriptors used by the context, and 00348 that can be used with RegisterClassList(). 00349 - Then, the context serialization binary, standing as a unsigned char table. 00350 - This can be used for automatic executable generation by some implementations. 00351 \param _filePath the path of the file to write. '.c' is added. 00352 \param _pGobalTableName the name of the global variable in the .c file 00353 \param _optimize if true, names are flushed and preferences destroyed, in a clone. 00354 */ 00355 void ExportAsCPPTableFile(const char *_pfileToExport,const char *_pGobalTableName,bool _optimize=true); 00356 #endif 00357 #ifdef _ENGINE_EDITABLE_ 00358 /*! 00359 \brief Get first element of the resource list. It lists all 00360 Resources used as members in the objects. get the next with 00361 GetPointerOnNextResourceInContextList() 00362 \return the first resource 00363 */ 00364 inline PackResource *GetFirstResourceInContextList() { return m_pFirstResourceInContextList; }; 00365 #endif 00366 /*================================================================== 00367 PROTECTED 00368 ==================================================================*/ 00369 protected: 00370 //! The context knows a list of all object-to-object references. This list is updated when the context is edited, and is used for reference resolution at input serialization. 00371 PackObjectReference *m_pFirstObjectReferenceInContextList; 00372 //! The context knows or not a machine to use for hardware/API abstraction. This is not created or destroyed by the context. 00373 VirtualMachine *m_pMachine; 00374 #ifdef _ENGINE_EDITABLE_ 00375 //! The context knows a list of managed resource members. 00376 PackResource *m_pFirstResourceInContextList; 00377 #endif 00378 /*! 00379 \brief link a new PackObjectReference to the context list. Done at object member inition. 00380 \param _pObjectReferenceToLink the new reference to link. 00381 */ 00382 void LinkObjectReference( PackObjectReference *_pObjectReferenceToLink ); 00383 #ifdef _ENGINE_EDITABLE_ 00384 /*! 00385 \brief remove a PackObjectReference from the context list, at its deletion. 00386 \param _pReferenceToUnlink ... 00387 */ 00388 void UnLinkObjectReference( PackObjectReference *_pReferenceToUnlink ); 00389 #endif 00390 #ifdef _ENGINE_EDITABLE_ 00391 /*! 00392 \brief link a new PackResource to the context list. Done at object member inition. 00393 It makes possible to keep an exact list of all managed resources. 00394 \param _pResourceToLink the new reference to link. 00395 */ 00396 void LinkResource( PackResource *_pResourceToLink ); 00397 #endif 00398 #ifdef _ENGINE_EDITABLE_ 00399 /*! 00400 \brief remove a PackResource from the context list, at its deletion. 00401 \param _pResourceToUnlink ... 00402 */ 00403 void UnLinkResource( PackResource *_pResourceToUnlink ); 00404 #endif 00405 #ifdef _ENGINE_EDITABLE_ 00406 //! the nested class used by BaseContext::m_GUIUpdateFunctionList to manage a list of functions to send updates when the context is edited. 00407 class UpdateFunctionListCell : public PackStruct 00408 { public: 00409 void (*m_func)(void *_GUIObjectToUpdateReturned,eVedaUpdate _updateType,BaseContext *_ContextUpdated,BaseObject *_ObjectUpdated,BaseType *_MemberUpdated); 00410 void *m_UserObject; 00411 static BaseType *NewCell(){ return new UpdateFunctionListCell(); }; 00412 }; 00413 //! The list of GUI functions to update when editing this context: 00414 PackList m_GUIUpdateFunctionList; 00415 #endif 00416 00417 #ifdef _ENGINE_EDITABLE_ 00418 //! the nested class used as cells of the undo stack: 00419 class UndoCell : public PackStruct 00420 { 00421 public: 00422 UndoCell(); 00423 void Init(unsigned int _editionType,BaseType *_pObjectMemberEdited,const unsigned char *_PreviousValueChunk,unsigned int _PreviousValueChunkLength,const unsigned char *_AfterValueChunk,unsigned int _AfterValueChunkLength); 00424 virtual ~UndoCell(void); 00425 inline BaseType *GetMemberToChange(){ return m_pObjectMemberEdited;}; 00426 inline unsigned char *GetPreviousValueChunk(){ return m_pPreviousValueChunk;}; 00427 inline unsigned char *GetAfterValueChunk(){ return m_pAfterValueChunk;}; 00428 static BaseType *NewCell(){ return new UndoCell(); }; 00429 protected: 00430 unsigned int m_EditionType; // only 0 managed for the moment: member change. 00431 BaseType *m_pObjectMemberEdited; 00432 unsigned char *m_pPreviousValueChunk; 00433 unsigned char *m_pAfterValueChunk; 00434 }; 00435 //! The stack of undoable/redoable events: 00436 PackList m_UndoStack; 00437 //! the cell of m_UndoStack currently focused by m_UndoStack; 00438 PackStruct::Cell *m_pCurrentUndoCell; 00439 //! The current number of undo-able events: 00440 unsigned int m_CurrentNumberOfUndoableEvents; 00441 //! The maximum number of undo-able events: 00442 unsigned int m_MaximumNumberOfUndoableEvents; 00443 #endif 00444 #ifdef _ENGINE_EDITABLE_ 00445 /*! 00446 \brief Updates all reference members of the context so that the refered 00447 object 's serialization ID is took as serialized value. 00448 */ 00449 void UpdateAllReferencesSerializationID(); 00450 #endif 00451 }; 00452 00453 #endif
/\/\ 4 N k ! N D _______ _ __ ___ _____ ___ _ _ ____ ___________ __//___ /________ |/ / ___________\_______/ \ / _ _ \/ _ / _ / _/_/____/ _ __ / / / / / / / \ \/ / / \ \ / \\___/___/___/ ¯ _____/_____/ ______\___/_____/\________\\ \________/_ ___ __ l____\ /elD! http://www.m4nkind.com \____/