MeVisLabToolboxReference
MeVisLab/Standard/Sources/ML/MLBase/mlListContainer.h
Go to the documentation of this file.
00001 // **InsertLicense** code
00002 //----------------------------------------------------------------------------------
00004 
00009 //
00010 // Defines the following classes:
00011 // - ListContainerBase: An abstract ML module class implementing basic functionality 
00012 //     for a list container module.
00013 // - ListContainerTemplate: Class template for container modules for a specific list 
00014 //     class. Can also be used as a base class for viewer or editor modules.
00015 //----------------------------------------------------------------------------------
00016 
00017 
00018 
00019 #ifndef __mlListContainer_H
00020 #define __mlListContainer_H
00021 
00022 
00023 // ML-includes
00024 #ifndef __mlModuleIncludes_H
00025 #include "mlModuleIncludes.h"
00026 #endif
00027 #ifndef __mlBaseInit_H
00028 #include "mlBaseInit.h"
00029 #endif
00030 
00031 
00032 // Local includes
00033 #ifndef __mlListBase_H
00034 #include "mlListBase.h"
00035 #endif
00036 #ifndef __mlRangeCasts_H
00037 #include "mlRangeCasts.h"
00038 #endif
00039 
00040 
00041 ML_START_NAMESPACE
00042 
00043 
00046 typedef bool ListContainerHandleNotificationCB(void *usrData, Field* field);
00047 
00048 // ------------------------------------------------------------------
00050 // ------------------------------------------------------------------
00051 
00076 class MLBASEEXPORT ListContainerBase : public Module
00077 {
00078     
00079 public:
00080     
00082     ListContainerBase():Module(0,0) {};
00083     
00088     ListContainerBase (ListBase *listBasePtr, int inputNum, int outputNum);
00089     
00091 
00092 
00093     virtual void handleNotification (Field *field);
00094     
00096     virtual void activateAttachments ();
00097     
00099     virtual void beginSaveFields ();
00100     
00102     virtual void endSaveFields ();
00103     
00105     
00106     
00108     void setHandleNotificationCB (ListContainerHandleNotificationCB *cb = NULL, 
00109         void *userData = NULL);
00110     
00111     
00120 
00121 
00122     virtual void doDeleteAll ();
00123     
00125     virtual void doDeleteItem (MLssize_t index);
00126     
00130     virtual void doInsertItem (MLssize_t index, bool fromCurrentItem);
00131     
00136     virtual void doModifyItem (MLssize_t index, Field *field, bool fromCurrentItem);
00137 
00139     virtual void doCopyItemToTemplate (MLssize_t index);
00140 
00142     virtual void doClearItem (MLssize_t index);
00143 
00145     virtual void doSelectItem (MLssize_t index);
00146     
00148     virtual void doUpdate ();
00149     
00151     
00153     BaseField* getOutputField() { return _fldOutputList; }
00154 
00155     // Returns the maximum number of items.
00156     MLint maxNumItems() const { return _fldMaxSize->getIntValue(); }
00157 
00159     enum OverflowModes
00160     {
00161         OvwNone = 0,             
00162         OvwRemoveFirst,          
00163         OvwRemoveLast,           
00164         OvwRemoveAll,            
00165         OvwRemoveNew,            
00166         OvwNumModes              
00167     };
00168     
00170     int overflowMode() const { return _fldOverflowMode->getEnumValue(); }
00171 
00172     
00173 protected:
00174     
00178 
00179 
00180     virtual ListBase *getInternalList () = 0;
00181     
00187     virtual bool setActiveList (Base *basePtr) = 0;
00188     
00190     virtual bool ownsList () 
00191     { return !_fldInputList || (_listBasePtr != _fldInputList->getBaseValue()); }
00192     
00194     virtual MLssize_t getId (MLssize_t index) = 0;
00195     
00197     
00198     
00202 
00203 
00204     virtual bool isPropertyField (Field *field);
00205     
00207     virtual void resetPropertyFields ();
00208     
00210     virtual void updatePropertyFields () = 0;
00211     
00213     
00214     
00220 
00221 
00222     virtual void deleteItems (MLssize_t index, MLssize_t num) = 0;
00223     
00227     virtual void insertItem (MLssize_t index, bool fromCurrentItem) = 0;
00228     
00234     virtual bool modifyItem (MLssize_t index, Field *field, bool fromCurrentItem) = 0;
00235 
00237     virtual void copyItemToTemplate (MLssize_t index) = 0;
00238 
00240     virtual void copyTemplateToCurrent () = 0;
00241     
00244     virtual void initItem (MLssize_t index) = 0;
00245 
00247     
00248     
00250 
00251 
00252 
00253     virtual void updateListString (bool forceEnable = false);
00254     
00256     virtual void updateDisplay ();
00257     
00259     virtual void updateActionFields ();
00260     
00268     virtual void touchList (ListBase::ActionClass actionClass, MLssize_t id, MLssize_t index);
00269     
00271     
00272     
00273     
00275 
00276     
00277     BaseField *_fldOutputList;           
00278     BaseField *_fldInputList;            
00279     
00280     StringField *_fldListString;         
00281     IntField *_fldNumItems;              
00282     IntField *_fldIndex;                 
00283     
00284     BoolField *_fldPersistent;           
00285     BoolField *_fldListStringEnable;     
00286     BoolField *_fldOwnsList;             
00287     BoolField *_fldApplySelect;          
00288     
00289     IntField *_fldId;                    
00290     StringField *_fldName;               
00291     StringField *_fldNewName;            
00292     
00293     StringField *_fldActionClass;        
00294     IntField *_fldActionIndex;           
00295     IntField *_fldActionId;              
00296     IntField *_fldCurrentIndex;          
00297     
00298     EnumField *_fldOverflowMode;         
00299     IntField *_fldMaxSize;               
00300     
00301     NotifyField *_fldDelete;             
00302     NotifyField *_fldDeleteAll;          
00303     NotifyField *_fldInsert;             
00304     NotifyField *_fldAdd;                
00305     NotifyField *_fldUpdate;             
00306 
00307     BoolField *_fldUseInsertTemplate;    
00308     NotifyField *_fldCopyItemToTemplate; 
00309     NotifyField *_fldCopyTemplateToItem; 
00310     NotifyField *_fldClearItem;          
00311 
00312     BoolField *_fldUpToDate;             
00313     
00315     
00316     
00317     int _lockNotification;               
00318     
00319     
00320 private:
00321     
00326     ListBase *_listBasePtr;
00327     
00329     std::string _listStringBackup;
00330     
00332     ListContainerHandleNotificationCB *_handleNotificationCB;
00333 
00335     void*                              _handleNotificationUserData;
00336     
00337     ML_ABSTRACT_MODULE_CLASS_HEADER(ListContainerBase)
00338         
00339 };
00340 
00341 
00342 
00343 
00344 
00345 
00346 // ------------------------------------------------------------------
00348 // ------------------------------------------------------------------
00349 
00378   template <class T>
00379       class ListContainerTemplate : public ListContainerBase
00380   {
00381 public:
00382     
00386     ListContainerTemplate (int inputNum, int outputNum);
00387     
00389     virtual ~ListContainerTemplate () {}
00390     
00391     
00396     virtual T *getList () { return _listPtr; }
00397     
00398     
00402     typename T::itemType _currentItem;
00403     
00404     
00405 protected:
00406     
00408 
00409     
00413     virtual bool setActiveList (Base *basePtr);
00414     
00416     virtual ListBase *getInternalList () { return &_list; }
00417     
00419     virtual MLssize_t getId (MLssize_t index);
00420     
00422     
00423     
00425 
00426 
00427     virtual void updatePropertyFields ();
00428     
00430     
00431     
00432     
00434 
00435 
00436     virtual void deleteItems (MLssize_t index, MLssize_t num);
00437     
00440     virtual void insertItem (MLssize_t index, bool fromCurrentItem);
00441     
00446     virtual bool modifyItem (MLssize_t index, Field *field, bool fromCurrentItem);
00447     
00449     virtual void copyItemToTemplate (MLssize_t index);
00450 
00452     virtual void copyTemplateToCurrent ();
00453 
00457     virtual void initItem (MLssize_t index);
00458     
00460     
00461     
00466     T *_listPtr;
00467     
00468 private:
00469     
00470     //------------------------------------------------------------------------------------
00473     //------------------------------------------------------------------------------------
00474     ListContainerTemplate(const ListContainerTemplate &)
00475     {
00476         ML_PRINT_FATAL_ERROR("ListContainerTemplate::ListContainerTemplate(const ListContainerTemplate &)",
00477             ML_PROGRAMMING_ERROR,
00478             "Usage of copy constructor of ListContainerTemplate is not supported.");
00479     }
00480     
00481     //------------------------------------------------------------------------------------
00484     //------------------------------------------------------------------------------------
00485     ListContainerTemplate& operator=(const ListContainerTemplate &)
00486     {
00487         ML_PRINT_FATAL_ERROR("ListContainerTemplate& ListContainerTemplate::operator=(const ListContainerTemplate &)",
00488             ML_PROGRAMMING_ERROR,
00489             "Usage of assignment operator of ListContainerTemplate is not supported.");
00490         return *this;
00491     }
00492     
00493     
00494     
00496     T _list;
00497     
00498 };
00499 
00500 
00502 template <class T>
00503 ListContainerTemplate<T>::ListContainerTemplate (int inputNum, int outputNum)
00504 : ListContainerBase(&_list, inputNum, outputNum), 
00505 _listPtr(&_list)
00506 {
00507 
00508     ML_TRACE_IN("template <class T>ListContainerTemplate<T>::ListContainerTemplate (int inputNum, int outputNum):ListContainerBase(&_list, inputNum, outputNum), _listPtr(&_list)");
00509   
00510     // Suppress handleNotification()
00511     _lockNotification = 1;
00512     
00513     // Get runtime type and name of this class and check for valid registration.
00514     const RuntimeType *rt = T::getClassTypeId();
00515     ML_CHECK_RUNTIME_TYPE(rt);
00516     std::string rtName = rt->getName();
00517     
00518     // Add output list field
00519     
00520     std::string listFieldName = std::string("out")+rtName;
00521     
00522     _fldOutputList = getFieldContainer()->addBase(listFieldName.c_str());
00523     _fldOutputList->setBaseValueAndAddAllowedType(_listPtr);
00524     
00525     // Add input list field
00526     listFieldName = std::string("in")+rtName;
00527     _fldInputList = getFieldContainer()->addBase(listFieldName.c_str());
00528     _fldInputList->setBaseValueAndAddAllowedType<ListBase>(NULL);
00529     
00530     // Allow handleNotification()
00531     _lockNotification = 0;
00532 }
00533 
00534 
00538 template <class T>
00539 bool ListContainerTemplate<T>::setActiveList (Base *basePtr)
00540 {
00541 
00542     ML_TRACE_IN("template <class T> bool ListContainerTemplate<T>::setActiveList (Base *basePtr)");
00543 
00544     bool listValid = false;
00545     
00546     if (basePtr && ML_BASE_IS_A(basePtr, T))
00547     {
00548         _listPtr = static_cast<T*>(basePtr);
00549         listValid = true;
00550     } else {
00551         _listPtr = NULL;
00552     }
00553     
00554     return listValid;
00555 }
00556 
00557 
00559 template <class T>
00560 MLssize_t ListContainerTemplate<T>::getId (MLssize_t index)
00561 {
00562 
00563     ML_TRACE_IN("template <class T> MLssize_t ListContainerTemplate<T>::getId (MLssize_tindex)");
00564 
00565     return (_listPtr && (index >= 0) && (index < static_cast<MLssize_t>(_listPtr->size())) ) 
00566         ? (*_listPtr)[mlrange_cast<size_t>(index)].getId() : -1;
00567 }
00568 
00569 
00571 template <class T>
00572 void ListContainerTemplate<T>::updatePropertyFields ()
00573 {
00574 
00575     ML_TRACE_IN("template <class T> void ListContainerTemplate<T>::updatePropertyFields ()");
00576 
00577     const MLssize_t index = _fldIndex->getIntValue();
00578     
00579     if (_listPtr && (index >= 0) && (index < static_cast<MLssize_t>(_listPtr->size())) )
00580     {
00581         _lockNotification++;
00582         
00583         const BaseItem *item = &(*_listPtr)[mlrange_cast<size_t>(index)];
00584         
00585         _fldId->setIntValue(item->getId());
00586         _fldName->setStringValue(item->name() ? item->name() : "");
00587         
00588         _lockNotification--;
00589     }
00590 }
00591 
00592 
00594 template <class T>
00595 void ListContainerTemplate<T>::deleteItems (MLssize_t index, MLssize_t num)
00596 {
00597 
00598     ML_TRACE_IN("template <class T> void ListContainerTemplate<T>::deleteItems (MLssize_t index, MLssize_t num)");
00599 
00600     ML_TRY{
00601       typename T::iterator it;
00602       const MLssize_t listSize = static_cast<MLssize_t>(_listPtr->size());
00603       if (_listPtr && (index >= 0) && (index < listSize) && (num > 0))
00604       {
00605           if (index+num > listSize){
00606               num = listSize-index;
00607           }
00608           it = _listPtr->begin()+index;
00609           _listPtr->erase(it, it+num);
00610       }
00611     }
00612     ML_CATCH_RETHROW;
00613 }
00614 
00615 
00618 template <class T>
00619 void ListContainerTemplate<T>::insertItem (MLssize_t index, bool fromCurrentItem)
00620 {
00621 
00622     ML_TRACE_IN("template <class T> void ListContainerTemplate<T>::insertItem (MLssize_t index, bool fromCurrentItem)");
00623 
00624     ML_TRY{
00625       if (_listPtr && (index >= 0) && (index <= static_cast<MLssize_t>(_listPtr->size())) )
00626       {
00627           if (fromCurrentItem)
00628           {
00629               // Generate new id and store in _currentItem
00630               _currentItem.setId(_listPtr->newId());
00631               // Insert copy of _currentItem
00632               _listPtr->insert(_listPtr->begin()+index, _currentItem);
00633             
00634           } else {
00635             
00636               typename T::itemType tmpItem;
00637               // Insert new item and initialize
00638               _listPtr->insert(_listPtr->begin()+index, tmpItem);
00639 
00640               // explicitly set the name to an empty string, 
00641               // because the initial name is a NULL pointer using an item's standard constructor
00642               (*_listPtr)[mlrange_cast<size_t>(index)].setName("");
00643 
00644               initItem(index);
00645           }
00646       }
00647     }
00648     ML_CATCH_RETHROW;
00649 }
00650 
00651 
00656 template <class T>
00657 bool ListContainerTemplate<T>::modifyItem (MLssize_t index, Field *field, bool fromCurrentItem)
00658 {
00659 
00660     ML_TRACE_IN("template <class T> bool ListContainerTemplate<T>::modifyItem (MLssize_t index, Field *field, bool fromCurrentItem)");
00661 
00662     ML_TRY{
00663       bool modified = true;
00664     
00665       if (_listPtr && (index >= 0) && (index < static_cast<MLssize_t>(_listPtr->size())) )
00666       {
00667           if (fromCurrentItem){
00668             
00669               // Copy _currentItem to list item
00670               (*_listPtr)[mlrange_cast<size_t>(index)] = _currentItem;
00671           }
00672           else if (field == _fldId)
00673           {
00674               // Reject change to item id
00675               _fldId->setIntValue((*_listPtr)[mlrange_cast<size_t>(index)].getId());
00676               modified = false;
00677           }else if (field == _fldName) {
00678               // Change item name
00679               (*_listPtr)[mlrange_cast<size_t>(index)].setName(_fldName->getStringValue().c_str());
00680           } else {
00681               // Not a property field
00682               modified = false;
00683           }
00684       } else {
00685           // Invalid item or list
00686           modified = false;
00687       }
00688     
00689       return modified;
00690     }
00691     ML_CATCH_RETHROW;
00692 }
00693 
00695 template <class T>
00696 void ListContainerTemplate<T>::copyItemToTemplate(MLssize_t index)
00697 {
00698 
00699   ML_TRACE_IN("template <class T> void ListContainerTemplate<T>::copyItemToTemplate(MLssize_t index)");
00700 
00701   typename T::itemType *item= &(*_listPtr)[mlrange_cast<size_t>(index)];
00702 
00703   _fldNewName->setStringValue( item->name() ? item->name() : "" );
00704 
00705 }
00706 
00708 template <class T>
00709 void ListContainerTemplate<T>::copyTemplateToCurrent()
00710 {
00711 
00712   ML_TRACE_IN("template <class T> void ListContainerTemplate<T>::copyTemplateToCurrent()");
00713 
00714   _currentItem.setName( _fldNewName->getStringValue().c_str() );
00715 
00716 }
00717 
00721 template <class T>
00722 void ListContainerTemplate<T>::initItem (MLssize_t index)
00723 {
00724 
00725     ML_TRACE_IN("template <class T> void ListContainerTemplate<T>::initItem (MLssize_t index)");
00726 
00727     typename T::itemType *item= &(*_listPtr)[mlrange_cast<size_t>(index)];
00728 
00729     if (item->getId() == 0) {
00730       // only assign a new id if the id is 0, 
00731       // because we do not want to assign a new id if the clear-field is triggered
00732       // (0 is the initial id of an item, the first id returned by newId is 1)
00733       item->setId(_listPtr->newId());
00734     }
00735 
00736     item->setName("");
00737 
00738 }
00739 
00740 
00741 ML_END_NAMESPACE
00742 
00743 #endif // __mlListContainer_H
00744