00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #ifndef INC_MI32_OBSERVER_H
00081 #define INC_MI32_OBSERVER_H
00082
00083 #ifndef INC_MI32_MILIST_H
00084 #include <mi32/milist.h>
00085 #endif
00086
00087 #ifndef GENERATING_DOXYGEN_OUTPUT
00088 class OBSERVER_BASE;
00089
00092 class SUBJECTBASE {
00093 public:
00094
00095 SUBJECTBASE (
00096 ) {
00097 }
00098
00099 virtual ~SUBJECTBASE (
00100 ) {
00101 }
00102
00103 private:
00106 virtual void AddObserver (
00107 OBSERVER_BASE* observer
00108 ) = 0;
00109
00110 virtual void RemoveObserver (
00111 OBSERVER_BASE* observer
00112 ) = 0;
00113
00114 friend class OBSERVER_BASE;
00115 };
00116 #endif
00117
00118
00121 template <class _CT = class OBSERVER_BASE> class SUBJECT : public SUBJECTBASE {
00122 public:
00123
00124 typedef MILIST<_CT*> OBSERVERLIST;
00125 typedef typename OBSERVERLIST::ITERATOR OBSERVERLIST_ITERATOR;
00126
00127 class ITERATOR {
00128 public:
00130 ITERATOR (
00131 ) {}
00132
00133
00134
00135
00137 _CT*& operator* (
00138 ) const {
00139 return (*m_it);
00140 }
00141
00143 _CT* operator-> (
00144 ) {
00145 return (*m_it);
00146 }
00147
00149 ITERATOR& operator++ (
00150 ) {
00151 m_it = m_next;
00152 ++m_next;
00153 return (*this);
00154 }
00155
00156 bool operator== (
00157 const ITERATOR& rhs
00158 ) const {
00159 return (m_it == rhs.m_it);
00160 }
00161
00162 bool operator!= (
00163 const ITERATOR& rhs
00164 ) const {
00165 return (m_it != rhs.m_it);
00166 }
00167
00168 private:
00169 #ifndef GENERATING_DOXYGEN_OUTPUT
00170 friend class SUBJECT<_CT>;
00171 OBSERVERLIST_ITERATOR m_it;
00172 OBSERVERLIST_ITERATOR m_next;
00173
00175 ITERATOR (
00176 const OBSERVERLIST_ITERATOR& it
00177 ) {
00178 m_it = it;
00179 m_next = it;
00180 ++m_next;
00181 }
00182
00184 OBSERVERLIST_ITERATOR& GetIterator (
00185 ) {
00186 return (m_it);
00187 }
00188 #endif
00189
00190 };
00191
00193 SUBJECT (
00194 ) {
00195 }
00196
00199 virtual ~SUBJECT (
00200 ) {
00201 for (ITERATOR it = ObserverBegin() ; it != ObserverEnd() ; ++it) {
00202
00203 (*it)->OnSubjectDestroy();
00204 }
00205 }
00206
00211 void NotifyObservers (
00212 ) {
00213 for (ITERATOR it = ObserverBegin() ; it != ObserverEnd() ; ++it) {
00214
00215 (*it)->OnNotify();
00216 }
00217 return;
00218 }
00219
00220 protected:
00221
00225 ITERATOR ObserverBegin (
00226 ) {
00227 return (ITERATOR(m_Observers.Begin()));
00228 }
00229
00233 ITERATOR ObserverEnd (
00234 ) {
00235 return (ITERATOR(m_Observers.End()));
00236 }
00237
00238 private:
00239 #ifndef GENERATING_DOXYGEN_OUTPUT
00240 MILIST<_CT*> m_Observers;
00241
00243 void AddObserver (
00244 OBSERVER_BASE* observer
00245 ) {
00246 m_Observers.PushFront(static_cast<_CT*>(observer));
00247 }
00248
00252 void RemoveObserver (
00253 OBSERVER_BASE* observer
00254 ) {
00255 for (ITERATOR it = ObserverBegin() ; it != ObserverEnd() ; ++it) {
00256 if ((*it) == static_cast<_CT*>(observer)) {
00257 m_Observers.Remove(it.GetIterator());
00258 break;
00259 }
00260 }
00261 return;
00262 }
00263 #endif
00264
00265 };
00266
00267
00274 class OBSERVER_BASE {
00275 public:
00276
00280 OBSERVER_BASE (
00281 SUBJECTBASE& subject
00282 ) :
00283 m_subject(&subject),
00284 m_bAttached(false)
00285 {
00286 Attach();
00287 }
00288
00290 OBSERVER_BASE (
00291 const OBSERVER_BASE& rhs
00292 ) :
00293 m_subject(rhs.m_subject),
00294 m_bAttached(false)
00295 {
00296 Attach();
00297 }
00298
00300 virtual ~OBSERVER_BASE (
00301 ) {
00306 Detach();
00307 }
00308
00310 OBSERVER_BASE& operator= (
00311 const OBSERVER_BASE& rhs
00312 ) {
00314 if (&rhs != this && rhs.m_subject != m_subject) {
00315 if (m_subject != 0) m_subject->RemoveObserver(this);
00316 m_subject = rhs.m_subject;
00317 if (m_subject != 0) m_subject->AddObserver(this);
00318 }
00319 return (*this);
00320 }
00321
00322
00323 void Attach (
00324 ) {
00325 if (m_subject == 0 || m_bAttached) return;
00326 m_subject->AddObserver(this);
00327 m_bAttached = true;
00328 return;
00329 }
00330
00331 void Detach (
00332 ) {
00333 if (m_subject == 0 || !m_bAttached) return;
00334 m_subject->RemoveObserver(this);
00335 m_bAttached = false;
00336 return;
00337 }
00338
00339 bool IsAttached (
00340 ) const {
00341 return (m_bAttached);
00342 }
00343
00346 void OnSubjectDestroy (
00347 ) {
00348 m_subject = 0;
00349 }
00350
00356 virtual void OnNotify (
00357 ) {
00358 }
00359
00360 private:
00361 #ifndef GENERATING_DOXYGEN_OUTPUT
00362 SUBJECTBASE* m_subject;
00363 bool m_bAttached;
00364 #endif
00365
00366 };
00367
00368
00369
00370 #ifndef GENERATING_DOXYGEN_OUTPUT
00371 #if 0
00373
00374 #ifndef INC_MI32_RECT_H
00375 #include <mi32/rect.h>
00376 #endif
00377
00378 class THINGY;
00379
00384 class EVENTPUMP : public SUBJECT<THINGY> {
00385 public:
00386
00392 void CallOnRedraw (
00393 const DRECT2D& rect
00394 );
00395 };
00396
00399 class THINGY : public OBSERVER_BASE {
00400 public:
00401 THINGY (
00402 EVENTPUMP& pump
00403 ) :
00404 OBSERVER_BASE(pump)
00405 {
00406 }
00407
00408 virtual ~THINGY (
00409 ) {
00410 }
00411
00415 virtual void OnRedraw (
00416 const DRECT2D& rect
00417 );
00418 };
00419
00420
00421 void EVENTPUMP::CallOnRedraw (
00422 const DRECT2D& rect
00423 ) {
00424 for (ITERATOR it = ObserverBegin() ; it != ObserverEnd() ; ++it) {
00425
00426 (*it)->OnRedraw(rect);
00427 }
00428 return;
00429 }
00430
00431 #endif
00432 #endif
00433
00434 #endif
00435