1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
|
#ifndef __ITERATOR_HH__
#define __ITERATOR_HH__
#ifndef __INCLUDED_FROM_DW_CORE_HH__
# error Do not include this file directly, use "core.hh" instead.
#endif
namespace dw {
namespace core {
/**
* \brief Iterators are used to iterate through the contents of a widget.
*
* When using iterators, you should care about the results of
* dw::core::Widget::hasContents.
*
* \sa dw::core::Widget::iterator
*/
class Iterator: public lout::object::Comparable
{
protected:
Iterator(Widget *widget, Content::Type mask, bool atEnd);
Iterator(Iterator &it);
~Iterator();
Content content;
private:
Widget *widget;
Content::Type mask;
public:
bool equals (Object *other);
inline Widget *getWidget () { return widget; }
inline Content *getContent () { return &content; }
inline Content::Type getMask () { return mask; }
virtual void unref ();
/**
* \brief Move iterator forward and store content it.
*
* Returns true on success.
*/
virtual bool next () = 0;
/**
* \brief Move iterator backward and store content it.
*
* Returns true on success.
*/
virtual bool prev () = 0;
/**
* \brief Extend highlighted region to contain part of the current content.
*
* For text, start and end define the
* characters, otherwise, the shape is defined as [0, 1], i.e. for
* highlighting a whole dw::core::Content, pass 0 and >= 1.
* To unhighlight see also dw::core::Iterator::unhighlight.
*/
virtual void highlight (int start, int end, HighlightLayer layer) = 0;
/**
* \brief Shrink highlighted region to no longer contain the
* current content.
*
* The direction parameter indicates whether the highlighted region should
* be reduced from the start (direction > 0) or from the end
* (direction < 0). If direction is 0 all content is unhighlighted.
*/
virtual void unhighlight (int direction, HighlightLayer layer) = 0;
/**
* \brief Return the shape, which a part of the item, the iterator points
* on, allocates.
*
* The parameters start and end have the same meaning as in
* DwIterator::highlight().
*/
virtual void getAllocation (int start, int end, Allocation *allocation) = 0;
inline Iterator *cloneIterator () { return (Iterator*)clone(); }
static void scrollTo (Iterator *it1, Iterator *it2, int start, int end,
HPosition hpos, VPosition vpos);
};
/**
* \brief This implementation of dw::core::Iterator can be used by widgets
* with no contents.
*/
class EmptyIterator: public Iterator
{
private:
EmptyIterator (EmptyIterator &it);
public:
EmptyIterator (Widget *widget, Content::Type mask, bool atEnd);
lout::object::Object *clone();
int compareTo(lout::object::Comparable *other);
bool next ();
bool prev ();
void highlight (int start, int end, HighlightLayer layer);
void unhighlight (int direction, HighlightLayer layer);
void getAllocation (int start, int end, Allocation *allocation);
};
/**
* \brief This implementation of dw::core::Iterator can be used by widgets
* having one text word as contents
*/
class TextIterator: public Iterator
{
private:
/** May be NULL, in this case, the next is skipped. */
const char *text;
TextIterator (TextIterator &it);
public:
TextIterator (Widget *widget, Content::Type mask, bool atEnd,
const char *text);
int compareTo(lout::object::Comparable *other);
bool next ();
bool prev ();
void getAllocation (int start, int end, Allocation *allocation);
};
/**
* \brief A stack of iterators, to iterate recursively through a widget tree.
*
* This class is similar to dw::core::Iterator, but not
* created by a widget, but explicitly from another iterator. Deep
* iterators do not have the limitation, that iteration is only done within
* a widget, instead, child widgets are iterated through recursively.
*/
class DeepIterator: public lout::object::Comparable
{
private:
class Stack: public lout::container::typed::Vector<Iterator>
{
public:
inline Stack (): lout::container::typed::Vector<Iterator> (4, false) { }
~Stack ();
inline Iterator *getTop () { return get (size () - 1); }
inline void push (Iterator *it) { put(it, -1); }
inline void pop() { getTop()->unref (); remove (size () - 1); }
};
Stack stack;
static Iterator *searchDownward (Iterator *it, Content::Type mask,
bool fromEnd);
static Iterator *searchSideward (Iterator *it, Content::Type mask,
bool fromEnd);
Content::Type mask;
Content content;
bool hasContents;
inline DeepIterator () { }
public:
DeepIterator(Iterator *it);
~DeepIterator();
lout::object::Object *clone ();
DeepIterator *createVariant(Iterator *it);
inline Iterator *getTopIterator () { return stack.getTop(); }
inline Content *getContent () { return &content; }
bool isEmpty ();
bool next ();
bool prev ();
inline DeepIterator *cloneDeepIterator() { return (DeepIterator*)clone(); }
int compareTo(lout::object::Comparable *other);
/**
* \brief Highlight a part of the current content.
*
* Unhighlight the current content by passing -1 as start (see also
* (dw::core::Iterator::unhighlight). For text, start and end define the
* characters, otherwise, the shape is defined as [0, 1], i.e. for
* highlighting a whole dw::core::Content, pass 0 and >= 1.
*/
inline void highlight (int start, int end, HighlightLayer layer)
{ stack.getTop()->highlight (start, end, layer); }
/**
* \brief Return the shape, which a part of the item, the iterator points
* on, allocates.
*
* The parameters start and end have the same meaning as in
* DwIterator::highlight().
*/
inline void getAllocation (int start, int end, Allocation *allocation)
{ stack.getTop()->getAllocation (start, end, allocation); }
inline void unhighlight (int direction, HighlightLayer layer)
{ stack.getTop()->unhighlight (direction, layer); }
inline static void scrollTo (DeepIterator *it1, DeepIterator *it2,
int start, int end,
HPosition hpos, VPosition vpos)
{ Iterator::scrollTo(it1->stack.getTop(), it2->stack.getTop(),
start, end, hpos, vpos); }
};
class CharIterator: public lout::object::Comparable
{
public:
// START and END must not clash with any char value
// neither for signed nor unsigned char.
enum { START = 257, END = 258 };
private:
DeepIterator *it;
int pos, ch;
CharIterator ();
public:
CharIterator (Widget *widget);
~CharIterator ();
lout::object::Object *clone();
int compareTo(lout::object::Comparable *other);
bool next ();
bool prev ();
inline int getChar() { return ch; }
inline CharIterator *cloneCharIterator() { return (CharIterator*)clone(); }
static void highlight (CharIterator *it1, CharIterator *it2,
HighlightLayer layer);
static void unhighlight (CharIterator *it1, CharIterator *it2,
HighlightLayer layer);
inline static void scrollTo (CharIterator *it1, CharIterator *it2,
HPosition hpos, VPosition vpos)
{ DeepIterator::scrollTo(it1->it, it2->it, it1->pos, it2->pos,
hpos, vpos); }
};
} // namespace core
} // namespace dw
#endif // __ITERATOR_HH__
|