aboutsummaryrefslogtreecommitdiff
path: root/dw/iterator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dw/iterator.cc')
-rw-r--r--dw/iterator.cc146
1 files changed, 129 insertions, 17 deletions
diff --git a/dw/iterator.cc b/dw/iterator.cc
index 18d7cd5a..18d62a49 100644
--- a/dw/iterator.cc
+++ b/dw/iterator.cc
@@ -55,6 +55,24 @@ bool Iterator::equals (Object *other)
(getWidget() == otherIt->getWidget() && compareTo(otherIt) == 0);
}
+void Iterator::intoStringBuffer(misc::StringBuffer *sb)
+{
+ sb->append ("{ widget = ");
+ //widget->intoStringBuffer (sb);
+ sb->appendPointer (widget);
+ sb->append (" (");
+ sb->append (widget->getClassName());
+ sb->append (")>");
+
+ sb->append (", mask = ");
+ Content::maskIntoStringBuffer (mask, sb);
+
+ sb->append (", content = ");
+ Content::intoStringBuffer (&content, sb);
+
+ sb->append (" }");
+}
+
/**
* \brief Delete the iterator.
*
@@ -186,6 +204,14 @@ void Iterator::scrollTo (Iterator *it1, Iterator *it2, int start, int end,
}
}
+
+void Iterator::print ()
+{
+ misc::StringBuffer sb;
+ intoStringBuffer (&sb);
+ printf ("%s", sb.getChars ());
+}
+
// -------------------
// EmptyIterator
// -------------------
@@ -343,7 +369,7 @@ Iterator *DeepIterator::searchDownward (Iterator *it, Content::Type mask,
//DEBUG_MSG (1, "%*smoving down (%swards) from %s\n",
// indent, "", from_end ? "back" : "for", a_Dw_iterator_text (it));
- assert (it->getContent()->type == Content::WIDGET);
+ assert (it->getContent()->type & Content::ANY_WIDGET);
it2 = it->getContent()->widget->iterator (mask, fromEnd);
if (it2 == NULL) {
@@ -356,7 +382,7 @@ Iterator *DeepIterator::searchDownward (Iterator *it, Content::Type mask,
//DEBUG_MSG (1, "%*sexamining %s\n",
// indent, "", a_Dw_iterator_text (it2));
- if (it2->getContent()->type == Content::WIDGET) {
+ if (it2->getContent()->type & Content::ANY_WIDGET) {
// Another widget. Search in it downwards.
it3 = searchDownward (it2, mask, fromEnd);
if (it3 != NULL) {
@@ -390,11 +416,11 @@ Iterator *DeepIterator::searchSideward (Iterator *it, Content::Type mask,
//DEBUG_MSG (1, "%*smoving %swards from %s\n",
// indent, "", from_end ? "back" : "for", a_Dw_iterator_text (it));
- assert (it->getContent()->type == Content::WIDGET);
+ assert (it->getContent()->type & Content::ANY_WIDGET);
it2 = it->cloneIterator ();
while (fromEnd ? it2->prev () : it2->next ()) {
- if (it2->getContent()->type == Content::WIDGET) {
+ if (it2->getContent()->type & Content::ANY_WIDGET) {
// Search downwards in this widget.
it3 = searchDownward (it2, mask, fromEnd);
if (it3 != NULL) {
@@ -416,13 +442,14 @@ Iterator *DeepIterator::searchSideward (Iterator *it, Content::Type mask,
/* Nothing found, go upwards in the tree (if possible). */
it2->unref ();
- if (it->getWidget()->getParent ()) {
- it2 = it->getWidget()->getParent()->iterator (mask, false);
+ Widget *respParent = getRespectiveParent (it->getWidget(), it->getMask());
+ if (respParent) {
+ it2 = respParent->iterator (mask, false);
while (true) {
if (!it2->next ())
misc::assertNotReached ();
- if (it2->getContent()->type == Content::WIDGET &&
+ if (it2->getContent()->type & Content::ANY_WIDGET &&
it2->getContent()->widget == it->getWidget ()) {
it3 = searchSideward (it2, mask, fromEnd);
it2->unref ();
@@ -440,6 +467,27 @@ Iterator *DeepIterator::searchSideward (Iterator *it, Content::Type mask,
return NULL;
}
+Widget *DeepIterator::getRespectiveParent (Widget *widget, Content::Type mask)
+{
+ // Return, depending on which is requested indirectly (follow
+ // references or containments) the parent (container) or the
+ // generator. At this point, the type of the parent/generator is
+ // not known (since the parent/generator is not known), so we have
+ // to examine the mask. This is the reason why only one of
+ // WIDGET_OOF_CONT and WIDGET_OOF_REF is allowed.
+
+ return (mask & Content::WIDGET_OOF_REF) ?
+ widget->getGenerator() : widget->getParent();
+}
+
+int DeepIterator::getRespectiveLevel (Widget *widget, Content::Type mask)
+{
+ // Similar to getRespectiveParent.
+
+ return (mask & Content::WIDGET_OOF_REF) ?
+ widget->getGeneratorLevel() : widget->getLevel();
+}
+
/**
* \brief Create a new deep iterator from an existing dw::core::Iterator.
*
@@ -456,6 +504,19 @@ Iterator *DeepIterator::searchSideward (Iterator *it, Content::Type mask,
*/
DeepIterator::DeepIterator (Iterator *it)
{
+ //printf ("Starting creating DeepIterator %p ...\n", this);
+ //printf ("Initial iterator: ");
+ //it->print ();
+ //printf ("\n");
+
+ // Widgets out of flow are either followed widtin containers, or
+ // generators. Both (and also nothing at all) is not allowed. See
+ // also comment in getRespectiveParent.
+ int oofMask =
+ it->getMask() & (Content::WIDGET_OOF_CONT | Content::WIDGET_OOF_REF);
+ assert (oofMask == Content::WIDGET_OOF_CONT ||
+ oofMask == Content::WIDGET_OOF_REF);
+
//DEBUG_MSG (1, "a_Dw_ext_iterator_new: %s\n", a_Dw_iterator_text (it));
// Clone input iterator, so the iterator passed as parameter
@@ -467,7 +528,7 @@ DeepIterator::DeepIterator (Iterator *it)
// If it points to a widget, find a near non-widget content,
// since an DeepIterator should never return widgets.
- if (it->getContent()->type == Content::WIDGET) {
+ if (it->getContent()->type & Content::ANY_WIDGET) {
Iterator *it2;
// The second argument of searchDownward is actually a matter of
@@ -494,31 +555,50 @@ DeepIterator::DeepIterator (Iterator *it)
// \todo There may be a faster way instead of iterating through the
// parent widgets.
+ //printf ("Starting with: ");
+ //it->print ();
+ //printf ("\n");
+
// Construct the iterators.
- int thisLevel = it->getWidget()->getLevel (), level;
+ int thisLevel = getRespectiveLevel (it->getWidget()), level;
Widget *w;
- for (w = it->getWidget (), level = thisLevel; w->getParent() != NULL;
- w = w->getParent (), level--) {
- Iterator *it = w->getParent()->iterator (mask, false);
+ for (w = it->getWidget (), level = thisLevel;
+ getRespectiveParent (w) != NULL;
+ w = getRespectiveParent (w), level--) {
+ Iterator *it = getRespectiveParent(w)->iterator (mask, false);
+
+ //printf (" parent: %s %p\n", w->getClassName (), w);
+
stack.put (it, level - 1);
while (true) {
+ //printf (" ");
+ //it->print ();
+ //printf ("\n");
+
bool hasNext = it->next();
assert (hasNext);
- if (it->getContent()->type == Content::WIDGET &&
+ if (it->getContent()->type & Content::ANY_WIDGET &&
it->getContent()->widget == w)
break;
}
+
+ //printf (" %d: ", level - 1);
+ //it->print ();
+ //printf ("\n");
}
stack.put (it, thisLevel);
content = *(it->getContent());
}
+
+ //printf ("... done creating DeepIterator %p.\n", this);
}
DeepIterator::~DeepIterator ()
{
+ //printf ("Deleting DeepIterator %p ...\n", this);
}
object::Object *DeepIterator::clone ()
@@ -539,9 +619,29 @@ int DeepIterator::compareTo (object::Comparable *other)
{
DeepIterator *otherDeepIterator = (DeepIterator*)other;
+ //printf ("Compare: %s\n", stack.toString ());
+ //printf (" to: %s\n", otherDeepIterator->stack.toString ());
+
// Search the highest level, where the widgets are the same.
int level = 0;
+ // The Comparable interface does not define "uncomparable". Deep
+ // iterators are only comparable if they belong to the same widget
+ // tree, so have the same widget at the bottom at the
+ // stack. If this is not the case, we abort.
+
+ assert (stack.size() > 0);
+ assert (otherDeepIterator->stack.size() > 0);
+
+ //printf ("Equal? The %s %p (of %p) and the %s %p (of %p)?\n",
+ // stack.get(0)->getWidget()->getClassName(),
+ // stack.get(0)->getWidget(), this,
+ // otherDeepIterator->stack.get(0)->getWidget()->getClassName(),
+ // otherDeepIterator->stack.get(0)->getWidget(), otherDeepIterator);
+
+ assert (stack.get(0)->getWidget()
+ == otherDeepIterator->stack.get(level)->getWidget());
+
while (stack.get(level)->getWidget ()
== otherDeepIterator->stack.get(level)->getWidget ()) {
if (level == stack.size() - 1 ||
@@ -550,10 +650,14 @@ int DeepIterator::compareTo (object::Comparable *other)
level++;
}
+ //printf (" => level = %d (temorally)\n", level);
+
while (stack.get(level)->getWidget ()
!= otherDeepIterator->stack.get(level)->getWidget ())
level--;
+ //printf (" => level = %d (finally)\n", level);
+
return stack.get(level)->compareTo (otherDeepIterator->stack.get(level));
}
@@ -577,7 +681,7 @@ bool DeepIterator::next ()
Iterator *it = stack.getTop ();
if (it->next ()) {
- if (it->getContent()->type == Content::WIDGET) {
+ if (it->getContent()->type & Content::ANY_WIDGET) {
// Widget: new iterator on stack, to search in this widget.
stack.push (it->getContent()->widget->iterator (mask, false));
return next ();
@@ -610,7 +714,7 @@ bool DeepIterator::prev ()
Iterator *it = stack.getTop ();
if (it->prev ()) {
- if (it->getContent()->type == Content::WIDGET) {
+ if (it->getContent()->type & Content::ANY_WIDGET) {
// Widget: new iterator on stack, to search in this widget.
stack.push (it->getContent()->widget->iterator (mask, true));
return prev ();
@@ -642,9 +746,17 @@ CharIterator::CharIterator ()
it = NULL;
}
-CharIterator::CharIterator (Widget *widget)
+/**
+ * \brief ...
+ *
+ * If followReferences is true, only the reference are followed, when
+ * the container and generator for a widget is different. If false,
+ * only the container is followed.
+ */
+CharIterator::CharIterator (Widget *widget, bool followReferences)
{
- Iterator *i = widget->iterator (Content::SELECTION_CONTENT, false);
+ Iterator *i =
+ widget->iterator (Content::maskForSelection (followReferences), false);
it = new DeepIterator (i);
i->unref ();
ch = START;