00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __UT_Iterator__
00020 #define __UT_Iterator__
00021
00022 #include "UT_Notifier.h"
00023
00024 class UT_API UT_IteratorEvent
00025 {
00026 public:
00027 enum TYPE {
00028 ADD,
00029 REMOVE,
00030 INVALID,
00031 };
00032 TYPE type;
00033
00034
00035 int lo, hi;
00036
00037 UT_IteratorEvent(TYPE type_, int lo_, int hi_) :
00038 type(type_), lo(lo_), hi(hi_) { }
00039 };
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 template <typename ELEMENT, typename CONTAINER>
00055 class UT_Iterator
00056 {
00057 public:
00058
00059
00060
00061 UT_Iterator(const CONTAINER &container,
00062 UT_NotifierImpl<UT_IteratorEvent &> *notifier,
00063 int idx = 0, bool reverse = false)
00064 : myContainer(container),
00065 myIndex((!reverse) ? idx : myContainer.entries() - idx - 1),
00066 myDirection((!reverse) ? 1 : -1),
00067 myIsInvalid(false),
00068 myIsAlreadyAtNext(false),
00069 myIsFirstTime(true)
00070 {
00071 if(notifier)
00072 {
00073
00074 UT_Functor1<void, UT_IteratorEvent &>
00075 functor(this, &UT_Iterator::onEvent);
00076 notifier->addObserver(myNotifierList, functor);
00077 }
00078 }
00079
00080
00081 bool isValid()
00082 {
00083 return !myIsInvalid && myIndex >= 0 && myIndex < myContainer.entries();
00084 }
00085
00086
00087
00088 ELEMENT current()
00089 {
00090 UT_ASSERT(isValid());
00091 return myContainer(myIndex);
00092 }
00093
00094
00095
00096
00097
00098 bool next()
00099 {
00100 if(myIsAlreadyAtNext)
00101 {
00102 myIsAlreadyAtNext = false;
00103 return isValid();
00104 }
00105 if(!isValid())
00106 {
00107 return false;
00108 }
00109 myIndex += myDirection;
00110 return true;
00111 }
00112
00113
00114
00115 int index()
00116 {
00117 UT_ASSERT(isValid());
00118 return myIndex;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 template <typename ELEMENT_OUT>
00134 bool get(ELEMENT_OUT &e)
00135 {
00136 if(!myIsFirstTime)
00137 {
00138 if(!next())
00139 {
00140 e = (ELEMENT_OUT) myContainer.null();
00141 return false;
00142 }
00143 }
00144 myIsFirstTime = false;
00145 if(!isValid())
00146 {
00147 e = (ELEMENT_OUT) myContainer.null();
00148 return false;
00149 }
00150 e = (ELEMENT_OUT)current();
00151 return true;
00152 }
00153
00154
00155 private:
00156 const CONTAINER &myContainer;
00157 UT_NotifierList myNotifierList;
00158
00159 int myIndex;
00160 int myDirection;
00161
00162
00163 bool myIsInvalid;
00164
00165
00166
00167 bool myIsAlreadyAtNext;
00168
00169
00170 bool myIsFirstTime;
00171
00172 void onEvent(UT_IteratorEvent &event)
00173 {
00174 switch(event.type)
00175 {
00176
00177 case UT_IteratorEvent::ADD:
00178 if( myIndex >= event.lo )
00179 {
00180 myIndex += (event.hi - event.lo + 1);
00181 }
00182 break;
00183
00184
00185 case UT_IteratorEvent::REMOVE:
00186 if( myIndex > event.hi )
00187 {
00188 myIndex -= (event.hi - event.lo + 1);
00189 }
00190 else if( myIndex >= event.lo )
00191 {
00192
00193 myIndex = event.lo;
00194 if( myDirection == -1 )
00195 myIndex--;
00196 myIsAlreadyAtNext = true;
00197 }
00198 break;
00199
00200
00201
00202 case UT_IteratorEvent::INVALID:
00203 myIsInvalid = true;
00204 break;
00205
00206 default:
00207 UT_ASSERT(!"Unknown enumeration value!");
00208 break;
00209 }
00210 }
00211 };
00212
00213 #endif