00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #pragma once
00018
00019 #include "maxheap.h"
00020 #include "ref.h"
00021
00022 class RefTarget: public MaxHeapOperators
00023 {
00024 protected:
00025 RefTargetHandle mRef;
00026 Interval mValid;
00027 bool mHeld;
00028
00029 public:
00030 RefTarget() : mRef(NULL), mHeld(false) { }
00031 RefTarget(RefTargetHandle ref, const Interval& valid = NEVER) : mRef(ref), mHeld(false) { mValid = valid; }
00032 RefTarget(const RefTarget& refTarget) : mRef(refTarget.mRef), mHeld(false) { mValid = refTarget.mValid; }
00033 virtual ~RefTarget() {;}
00034 virtual RefTarget& operator=(const RefTarget& refTarget) { mRef = refTarget.mRef; mValid = refTarget.mValid; return *this; }
00035
00036 RefTargetHandle GetRefTargetHandle() const { return mRef; }
00037 void SetRefTargetHandle(RefTargetHandle ref) { mRef = ref; }
00038 const Interval& GetValidity() const { return mValid; }
00039 void SetValidity(const Interval& valid) { mValid = valid; }
00040 bool IsHeld() const { return mHeld; }
00041 void SetHeld(bool held) { mHeld = held; }
00042 };
00043
00044
00045 template <class T> class RefMgr;
00046
00047
00048
00049
00050
00051
00052 template <class T> class RefMgrAddDeleteRestore : public RestoreObj, public ReferenceMaker
00053 {
00054 RefMgr<T>* mMgr;
00055 T* mRefTarg;
00056
00057 RefTargetHandle mRef;
00058 BOOL undone;
00059
00060 public:
00061 RefMgrAddDeleteRestore(RefMgr<T>* mgr, int which, RefTargetHandle ref)
00062 : mMgr(NULL), mRefTarg(which < 0 ? NULL : mgr->GetRefTarget(which)), mRef(ref), undone(FALSE)
00063 {
00064 ReplaceReference(0, mgr);
00065 if (mRefTarg != NULL)
00066 mRefTarg->SetHeld(true);
00067 }
00068
00069 ~RefMgrAddDeleteRestore()
00070 {
00071 if (mRefTarg != NULL) {
00072 if (mMgr != NULL)
00073 mMgr->RemoveRef(mRefTarg);
00074 delete mRefTarg;
00075 }
00076 DeleteAllRefs();
00077 }
00078
00079 virtual Class_ID ClassID() { return Class_ID(0x102f266c, 0x23492667); }
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 void Restore(int isUndo)
00091 {
00092 int isUndo2;
00093 BOOL isInRestore = theHold.Restoring(isUndo2);
00094 if (isInRestore)
00095 {
00096 if (undone) return;
00097 undone = TRUE;
00098 }
00099 else
00100 {
00101 if (!undone) return;
00102 undone = FALSE;
00103 }
00104 if (mMgr != NULL) {
00105 if (mRefTarg == NULL) {
00106 int i = mMgr->FindRefTargetHandleIndex(mRef);
00107 if (i >= 0) {
00108 mRefTarg = mMgr->mRefTargetPtrs[i];
00109 mRefTarg->SetHeld(true);
00110 mMgr->mRefTargetPtrs.Delete(i, 1);
00111 }
00112 } else {
00113 mMgr->RemoveRef(mRefTarg);
00114 mRefTarg->SetRefTargetHandle(mRef);
00115 mMgr->mRefTargetPtrs.Append(1, &mRefTarg, 3);
00116 mRefTarg->SetHeld(false);
00117 mRefTarg = NULL;
00118 }
00119 }
00120 }
00121
00122 void Redo() { Restore(false); }
00123
00124 MSTR Description() { return _M("RefMgrAddDeleteRestore"); }
00125
00126 virtual RefResult NotifyRefChanged(
00127 Interval changeInt,
00128 RefTargetHandle hTarget,
00129 PartID& partID,
00130 RefMessage message
00131 )
00132 {
00133 switch (message) {
00134 case REFMSG_TARGET_DELETED:
00135 mMgr = NULL;
00136 break;
00137 }
00138
00139 return REF_SUCCEED;
00140 }
00141 virtual int NumRefs() { return 1; }
00142 virtual RefTargetHandle GetReference(int i) { return i == 0 ? mMgr : NULL; }
00143 protected:
00144 virtual void SetReference(int i, RefTargetHandle rtarg)
00145 {
00146 if (i == 0)
00147 mMgr = static_cast<RefMgr<T>*>(rtarg);
00148 }
00149 public:
00150 virtual BOOL CanTransferReference(int i) { return FALSE; }
00151 };
00152
00153
00154
00155 template <class T> class RefMgr : public ReferenceTarget
00156 {
00157 friend class RefMgrAddDeleteRestore<T>;
00158
00159 protected:
00160 typedef RefResult (* TNotifyCB)(void *cbParam, Interval changeInt, T* pRefTarget, RefTargetHandle hTarger, PartID& partID, RefMessage message);
00161
00162 Tab<T*> mRefTargetPtrs;
00163 TNotifyCB mNotifyCB;
00164 void *mNotifyCBParam;
00165
00166 public:
00167 RefMgr() : mNotifyCB(NULL), mNotifyCBParam(NULL) { }
00168
00169 virtual ~RefMgr() { DeleteAllRefs(); }
00170
00171 virtual Class_ID ClassID() { return Class_ID(0x7eff2f08, 0x25707aa2); }
00172
00173 virtual void DeleteThis()
00174 {
00175 delete this;
00176 }
00177
00178 virtual void Init(TNotifyCB notifyCB=NULL, void *notifyCBParam=NULL)
00179 {
00180 mRefTargetPtrs.ZeroCount();
00181 mNotifyCB = notifyCB;
00182 mNotifyCBParam = notifyCBParam;
00183 }
00184
00185 virtual int Count() { return mRefTargetPtrs.Count(); }
00186
00187 virtual int FindRefTargetHandleIndex(RefTargetHandle rtarg)
00188 {
00189 int n = mRefTargetPtrs.Count();
00190 for (int i=0; i<n; i++)
00191 {
00192 if (mRefTargetPtrs[i]->GetRefTargetHandle() == rtarg)
00193 return i;
00194 }
00195 return -1;
00196 }
00197
00198 virtual int FindRefTargetIndex(T *pRefTarget)
00199 {
00200 int n = mRefTargetPtrs.Count();
00201 for (int i=0; i<n; i++)
00202 {
00203 if (mRefTargetPtrs[i]->GetRefTargetHandle() == pRefTarget->GetRefTargetHandle())
00204 return i;
00205 }
00206 return -1;
00207 }
00208
00209 virtual T* FindRefTarget(RefTargetHandle rtarg)
00210 {
00211 int index = FindRefTargetHandleIndex(rtarg);
00212 return (index == -1) ? NULL : mRefTargetPtrs[index];
00213 }
00214
00215 virtual T* GetRefTarget(int i)
00216 {
00217 if ( i < mRefTargetPtrs.Count() )
00218 return mRefTargetPtrs[i];
00219 else
00220 return NULL;
00221 }
00222
00223 virtual bool AddUndo(int which, RefTargetHandle ref)
00224 {
00225 bool undo = false;
00226 if (!theHold.RestoreOrRedoing()) {
00227 int resumeCount = 0;
00228
00229 while (theHold.IsSuspended()) {
00230 theHold.Resume();
00231 ++resumeCount;
00232 }
00233
00234 undo = theHold.Holding() != 0;
00235 if (undo)
00236 theHold.Put(new RefMgrAddDeleteRestore<T>(this, which, ref));
00237
00238 while (--resumeCount >= 0)
00239 theHold.Suspend();
00240 }
00241 return undo;
00242 }
00243
00244 virtual bool AddRef(T* pRefTarget)
00245 {
00246
00247 RefTargetHandle pRefTargHandle = pRefTarget->GetRefTargetHandle();
00248 if ( (pRefTargHandle != NULL) && (FindRefTargetIndex(pRefTarget) == -1) )
00249 {
00250 pRefTarget->SetRefTargetHandle(NULL);
00251 mRefTargetPtrs.Append(1, &pRefTarget);
00252 HoldSuspend hs;
00253 if ( ReplaceReference (mRefTargetPtrs.Count()-1, pRefTargHandle) != REF_SUCCEED )
00254 {
00255 pRefTarget->SetRefTargetHandle(pRefTargHandle);
00256 mRefTargetPtrs.Delete(mRefTargetPtrs.Count()-1, 1);
00257 return false;
00258 }
00259 hs.Resume();
00260 NotifyDependents(FOREVER, 0, REFMSG_SUBANIM_STRUCTURE_CHANGED);
00261
00262
00263 AddUndo(-1, pRefTarget->GetRefTargetHandle());
00264 return true;
00265 }
00266 else
00267 return false;
00268 }
00269
00270
00271 virtual bool RemoveRef(RefTargetHandle rtarg)
00272 {
00273 return RemoveRef( FindRefTargetHandleIndex(rtarg) );
00274 }
00275
00276 virtual bool RemoveRef(T* pRefTarget)
00277 {
00278 return RemoveRef( FindRefTargetIndex(pRefTarget) );
00279 }
00280
00281 virtual bool RemoveRef(int index)
00282 {
00283 if ( (index >= 0) && ( index < Count() ) )
00284 {
00285 DeleteReference(index);
00286 T* targ = mRefTargetPtrs[index];
00287 if (targ != NULL && !targ->IsHeld())
00288 {
00289 delete targ;
00290 }
00291 mRefTargetPtrs.Delete(index, 1);
00292 NotifyDependents(FOREVER, 0, REFMSG_SUBANIM_STRUCTURE_CHANGED);
00293 return true;
00294 }
00295 return false;
00296 }
00297
00298
00299 virtual void Clear()
00300 {
00301 DeleteAllRefsFromMe();
00302 for ( int i = mRefTargetPtrs.Count(); --i >= 0; ) {
00303 T* targ = mRefTargetPtrs[i];
00304 if (targ != NULL && !targ->IsHeld())
00305 {
00306 delete targ;
00307 }
00308 }
00309 mRefTargetPtrs.ZeroCount();
00310 NotifyDependents(FOREVER, 0, REFMSG_SUBANIM_STRUCTURE_CHANGED);
00311 }
00312
00313
00314
00315 virtual int NumRefs() { return Count(); }
00316
00317
00318
00319 virtual RefResult DeleteReference(int which) {
00320 RefTargetHandle ref = GetReference(which);
00321 RefResult ret = ReferenceTarget::DeleteReference(which);
00322 if (ret == REF_SUCCEED) {
00323 AddUndo(which, ref);
00324 }
00325 return ret;
00326 }
00327
00328 virtual ReferenceTarget* GetReference(int i)
00329 {
00330 if ( i < mRefTargetPtrs.Count() )
00331 return mRefTargetPtrs[i]->GetRefTargetHandle();
00332 else
00333 return NULL;
00334 }
00335
00336 protected:
00337 virtual void SetReference(int i, RefTargetHandle rtarg)
00338 {
00339
00340
00341 if (!theHold.RestoreOrRedoing()) {
00342 int count = mRefTargetPtrs.Count();
00343 assert(i < count || rtarg == NULL);
00344 if ( i < count )
00345 mRefTargetPtrs[i]->SetRefTargetHandle(rtarg);
00346 }
00347 }
00348 public:
00349 virtual RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
00350 {
00351 RefResult refResult(REF_SUCCEED);
00352 if (mNotifyCB)
00353 {
00354 T* pRefTarget = FindRefTarget(hTarget);
00355 refResult = mNotifyCB(mNotifyCBParam, changeInt, pRefTarget, hTarget, partID, message);
00356 }
00357
00358 switch (message)
00359 {
00360 case REFMSG_TARGET_DELETED:
00361 {
00362
00363 int i = FindRefTargetHandleIndex(hTarget);
00364 assert(i >= 0);
00365 if (i >= 0)
00366 {
00367
00368 if (!AddUndo(i, hTarget))
00369 {
00370 delete mRefTargetPtrs[i];
00371 }
00372 mRefTargetPtrs.Delete(i, 1);
00373 }
00374
00375 break;
00376 }
00377 }
00378 return refResult;
00379 }
00380 };
00381