00001 /*************************************************************************** 00002 * (c) Jürgen Riegel (juergen.riegel@web.de) 2002 * 00003 * * 00004 * This file is part of the FreeCAD CAx development system. * 00005 * * 00006 * This program is free software; you can redistribute it and/or modify * 00007 * it under the terms of the GNU Library General Public License (LGPL) * 00008 * as published by the Free Software Foundation; either version 2 of * 00009 * the License, or (at your option) any later version. * 00010 * for detail see the LICENCE text file. * 00011 * * 00012 * FreeCAD is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU Library General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU Library General Public * 00018 * License along with FreeCAD; if not, write to the Free Software * 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * 00020 * USA * 00021 * * 00022 * Juergen Riegel 2002 * 00023 ***************************************************************************/ 00024 00025 00026 #ifndef BASE_OBSERVER_H 00027 #define BASE_OBSERVER_H 00028 00029 // Std. configurations 00030 00031 #include <assert.h> 00032 #include <set> 00033 #include <cstring> 00034 #include <cstdio> 00035 00036 00037 namespace Base 00038 { 00039 00040 template <class MessageType> class Subject; 00041 00042 00050 template <class _MessageType> 00051 class Observer 00052 { 00053 public: 00054 00059 Observer(){}; 00060 00065 virtual ~Observer(){}; 00066 00074 virtual void OnChange(Subject<_MessageType>& rCaller,_MessageType rcReason)=0; 00075 00081 virtual void OnDestroy(Subject<_MessageType> & rCaller){} 00082 00088 virtual const char *Name(void){return 0L;} 00089 }; 00090 00098 template <class _MessageType> 00099 class Subject 00100 { 00101 public: 00102 00103 typedef Observer<_MessageType> ObserverType; 00104 typedef _MessageType MessageType; 00105 typedef Subject<_MessageType> SubjectType; 00106 00111 Subject(){}; 00112 00117 virtual ~Subject() 00118 { 00119 if (_ObserverSet.size() > 0) 00120 { 00121 printf("Not detached all observers yet\n"); 00122 assert(0); 00123 } 00124 } 00125 00132 void Attach(Observer<_MessageType> *ToObserv) 00133 { 00134 #ifdef FC_DEBUG 00135 size_t count = _ObserverSet.size(); 00136 printf("Attach observer %p\n", ToObserv); 00137 _ObserverSet.insert(ToObserv); 00138 if ( _ObserverSet.size() == count ) 00139 printf("Observer %p already attached\n", ToObserv); 00140 #else 00141 _ObserverSet.insert(ToObserv); 00142 #endif 00143 } 00144 00151 void Detach(Observer<_MessageType> *ToObserv) 00152 { 00153 #ifdef FC_DEBUG 00154 size_t count = _ObserverSet.size(); 00155 printf("Detach observer %p\n", ToObserv); 00156 _ObserverSet.erase(ToObserv); 00157 if ( _ObserverSet.size() == count ) 00158 printf("Observer %p already detached\n", ToObserv); 00159 #else 00160 _ObserverSet.erase(ToObserv); 00161 #endif 00162 } 00163 00170 void Notify(_MessageType rcReason) 00171 { 00172 for(typename std::set<Observer<_MessageType> * >::iterator Iter=_ObserverSet.begin();Iter!=_ObserverSet.end();Iter++) 00173 (*Iter)->OnChange(*this,rcReason); // send OnChange-signal 00174 } 00175 00180 Observer<_MessageType> * Get(const char *Name) 00181 { 00182 const char* OName; 00183 for(typename std::set<Observer<_MessageType> * >::iterator Iter=_ObserverSet.begin();Iter!=_ObserverSet.end();Iter++) 00184 { 00185 OName = (*Iter)->Name(); // get the name 00186 if(OName && strcmp(OName,Name) == 0) 00187 return *Iter; 00188 } 00189 00190 return 0L; 00191 } 00192 00196 void ClearObserver() 00197 { 00198 _ObserverSet.clear(); 00199 } 00200 00201 00202 protected: 00204 std::set<Observer <_MessageType> *> _ObserverSet; 00205 }; 00206 00207 00208 } //namespace Base 00209 00210 00211 #endif // BASE_OBSERVER_H