271 lines
8.0 KiB
C++
271 lines
8.0 KiB
C++
#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 (const Object *other) const override;
|
|
void intoStringBuffer(lout::misc::StringBuffer *sb) const override;
|
|
|
|
inline Widget *getWidget () { return widget; }
|
|
inline const Widget *getWidget () const { return widget; }
|
|
inline Content *getContent () { return &content; }
|
|
inline Content::Type getMask () const { 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() const override;
|
|
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 () { }
|
|
|
|
static Widget *getRespectiveParent (Widget *widget, Content::Type mask);
|
|
inline Widget *getRespectiveParent (Widget *widget) {
|
|
return getRespectiveParent (widget, mask);
|
|
}
|
|
|
|
static int getRespectiveLevel (Widget *widget, Content::Type mask);
|
|
inline int getRespectiveLevel (Widget *widget) {
|
|
return getRespectiveLevel (widget, mask);
|
|
}
|
|
|
|
public:
|
|
DeepIterator(Iterator *it);
|
|
~DeepIterator();
|
|
|
|
lout::object::Object *clone () const override;
|
|
|
|
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, bool followReferences);
|
|
~CharIterator ();
|
|
|
|
lout::object::Object *clone() const override;
|
|
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__
|