214 lines
6.5 KiB
C++
214 lines
6.5 KiB
C++
/***************************************************************************
|
|
* (c) Jürgen Riegel (juergen.riegel@web.de) 2002 *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Library General Public License (LGPL) *
|
|
* as published by the Free Software Foundation; either version 2 of *
|
|
* the License, or (at your option) any later version. *
|
|
* for detail see the LICENCE text file. *
|
|
* *
|
|
* FreeCAD is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with FreeCAD; if not, write to the Free Software *
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
* USA *
|
|
* *
|
|
* Juergen Riegel 2002 *
|
|
***************************************************************************/
|
|
|
|
|
|
#ifndef BASE_OBSERVER_H
|
|
#define BASE_OBSERVER_H
|
|
|
|
// Std. configurations
|
|
|
|
#include <assert.h>
|
|
#include <set>
|
|
#include <cstring>
|
|
#include <cstdio>
|
|
|
|
|
|
namespace Base
|
|
{
|
|
|
|
template <class MessageType> class Subject;
|
|
|
|
|
|
/** Observer class
|
|
* Implementation of the well known Observer Design Pattern.
|
|
* The observed object, which inherit FCSubject, will call all
|
|
* its observers in case of changes. A observer class has to
|
|
* Attach itself to the observed object.
|
|
* @see FCSubject
|
|
*/
|
|
template <class _MessageType>
|
|
class Observer
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* A constructor.
|
|
* No special function so far.
|
|
*/
|
|
Observer(){}
|
|
|
|
/**
|
|
* A destructor.
|
|
* No special function so far.
|
|
*/
|
|
virtual ~Observer(){}
|
|
|
|
/**
|
|
* This method need to be reimplemented from the concrete Observer
|
|
* and get called by the observed class
|
|
* @param rCaller a reference to the calling object
|
|
* @param rcReason
|
|
* \todo undocumented parameter 2
|
|
*/
|
|
virtual void OnChange(Subject<_MessageType>& rCaller,_MessageType rcReason)=0;
|
|
|
|
/**
|
|
* This method need to be reimplemented from the concrete Observer
|
|
* and get called by the observed class
|
|
* @param rCaller a reference to the calling object
|
|
*/
|
|
virtual void OnDestroy(Subject<_MessageType> & rCaller) {
|
|
(void)rCaller;
|
|
}
|
|
|
|
/**
|
|
* This method can be reimplemented from the concrete Observer
|
|
* and returns the name of the observer. Needed to use the Get
|
|
* Method of the Subject.
|
|
*/
|
|
virtual const char *Name(void){return 0L;}
|
|
};
|
|
|
|
/** Subject class
|
|
* Implementation of the well known Observer Design Pattern.
|
|
* The observed object, which inherit FCSubject, will call all
|
|
* its observers in case of changes. A observer class has to
|
|
* Attach itself to the observed object.
|
|
* @see FCObserver
|
|
*/
|
|
template <class _MessageType>
|
|
class Subject
|
|
{
|
|
public:
|
|
|
|
typedef Observer<_MessageType> ObserverType;
|
|
typedef _MessageType MessageType;
|
|
typedef Subject<_MessageType> SubjectType;
|
|
|
|
/**
|
|
* A constructor.
|
|
* No special function so far.
|
|
*/
|
|
Subject(){}
|
|
|
|
/**
|
|
* A destructor.
|
|
* No special function so far.
|
|
*/
|
|
virtual ~Subject()
|
|
{
|
|
if (_ObserverSet.size() > 0)
|
|
{
|
|
printf("Not detached all observers yet\n");
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
/** Attach an Observer
|
|
* Attach an Observer to the list of Observers which get
|
|
* called when Notify is called.
|
|
* @param ToObserv A pointer to a concrete Observer
|
|
* @see Notify
|
|
*/
|
|
void Attach(Observer<_MessageType> *ToObserv)
|
|
{
|
|
#ifdef FC_DEBUG
|
|
size_t count = _ObserverSet.size();
|
|
//printf("Attach observer %p\n", ToObserv);
|
|
_ObserverSet.insert(ToObserv);
|
|
if ( _ObserverSet.size() == count )
|
|
printf("Observer %p already attached\n", ToObserv);
|
|
#else
|
|
_ObserverSet.insert(ToObserv);
|
|
#endif
|
|
}
|
|
|
|
/** Detach an Observer
|
|
* Detach an Observer from the list of Observers which get
|
|
* called when Notify is called.
|
|
* @param ToObserv A pointer to a concrete Observer
|
|
* @see Notify
|
|
*/
|
|
void Detach(Observer<_MessageType> *ToObserv)
|
|
{
|
|
#ifdef FC_DEBUG
|
|
size_t count = _ObserverSet.size();
|
|
//printf("Detach observer %p\n", ToObserv);
|
|
_ObserverSet.erase(ToObserv);
|
|
if ( _ObserverSet.size() == count )
|
|
printf("Observer %p already detached\n", ToObserv);
|
|
#else
|
|
_ObserverSet.erase(ToObserv);
|
|
#endif
|
|
}
|
|
|
|
/** Notify all Observers
|
|
* Send a message to all Observers attached to this subject.
|
|
* The Message depends on the implementation of a concrete
|
|
* Oberserver and Subject.
|
|
* @see Notify
|
|
*/
|
|
void Notify(_MessageType rcReason)
|
|
{
|
|
for(typename std::set<Observer<_MessageType> * >::iterator Iter=_ObserverSet.begin();Iter!=_ObserverSet.end();++Iter)
|
|
(*Iter)->OnChange(*this,rcReason); // send OnChange-signal
|
|
}
|
|
|
|
/** Get an Observer by name
|
|
* Get a observer by name if the observer reimplements the Name() mthode.
|
|
* @see Observer
|
|
*/
|
|
Observer<_MessageType> * Get(const char *Name)
|
|
{
|
|
const char* OName;
|
|
for(typename std::set<Observer<_MessageType> * >::iterator Iter=_ObserverSet.begin();Iter!=_ObserverSet.end();++Iter)
|
|
{
|
|
OName = (*Iter)->Name(); // get the name
|
|
if(OName && strcmp(OName,Name) == 0)
|
|
return *Iter;
|
|
}
|
|
|
|
return 0L;
|
|
}
|
|
|
|
/** Clears the list of all registered observers.
|
|
* @note Using this function in your code may be an indication of design problems.
|
|
*/
|
|
void ClearObserver()
|
|
{
|
|
_ObserverSet.clear();
|
|
}
|
|
|
|
|
|
protected:
|
|
/// Vector of attached observers
|
|
std::set<Observer <_MessageType> *> _ObserverSet;
|
|
};
|
|
|
|
|
|
} //namespace Base
|
|
|
|
|
|
#endif // BASE_OBSERVER_H
|