diff options
-rw-r--r-- | dw/layout.cc | 2 | ||||
-rw-r--r-- | dw/oofawarewidget.cc | 138 | ||||
-rw-r--r-- | dw/oofawarewidget.hh | 22 | ||||
-rw-r--r-- | dw/ooffloatsmgr.cc | 37 | ||||
-rw-r--r-- | dw/ooffloatsmgr.hh | 9 | ||||
-rw-r--r-- | dw/oofpositionedmgr.cc | 18 | ||||
-rw-r--r-- | dw/oofpositionedmgr.hh | 3 | ||||
-rw-r--r-- | dw/outofflowmgr.hh | 4 | ||||
-rw-r--r-- | dw/stackingcontextmgr.cc | 39 | ||||
-rw-r--r-- | dw/stackingcontextmgr.hh | 12 | ||||
-rw-r--r-- | dw/table.cc | 43 | ||||
-rw-r--r-- | dw/table.hh | 4 | ||||
-rw-r--r-- | dw/textblock.cc | 91 | ||||
-rw-r--r-- | dw/textblock.hh | 9 | ||||
-rw-r--r-- | dw/widget.cc | 65 | ||||
-rw-r--r-- | dw/widget.hh | 17 | ||||
-rw-r--r-- | test/dw_simple_container.cc | 283 | ||||
-rw-r--r-- | test/dw_simple_container.hh | 3 |
18 files changed, 553 insertions, 246 deletions
diff --git a/dw/layout.cc b/dw/layout.cc index 60cea8e0..43c27dd8 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -704,7 +704,7 @@ void Layout::draw (View *view, Rectangle *area) widgetDrawArea.width = intersection.width; widgetDrawArea.height = intersection.height; - topLevel->draw (view, &widgetDrawArea); + topLevel->drawToplevel (view, &widgetDrawArea); view->finishDrawing (&intersection); } diff --git a/dw/oofawarewidget.cc b/dw/oofawarewidget.cc index 3ffdef5d..e3a1f55e 100644 --- a/dw/oofawarewidget.cc +++ b/dw/oofawarewidget.cc @@ -24,12 +24,30 @@ using namespace dw; using namespace dw::core; +using namespace dw::core::style; +using namespace lout::object; +using namespace lout::container::untyped; using namespace lout::misc; namespace dw { namespace oof { +const char *OOFAwareWidget::OOFStackIterator::majorLevelText (int majorLevel) +{ + switch (majorLevel) { + case START: return "START"; + case BACKGROUND: return "BACKGROUND"; + case SC_BOTTOM: return "SC_BOTTOM"; + case IN_FLOW: return "IN_FLOW"; + case OOF_REF: return "OOF_REF"; + case OOF_CONT: return "OOF_CONT"; + case SC_TOP: return "SC_TOP"; + case END: return "END"; + default: return "???"; + } +} + int OOFAwareWidget::CLASS_ID = -1; OOFAwareWidget::OOFAwareWidget () @@ -59,7 +77,7 @@ OOFAwareWidget::~OOFAwareWidget () DBG_OBJ_DELETE (); } -void OOFAwareWidget::notifySetAsTopLevel() +void OOFAwareWidget::notifySetAsTopLevel () { oofContainer[OOFM_FLOATS] = oofContainer[OOFM_ABSOLUTE] = oofContainer[OOFM_FIXED] = this; @@ -90,10 +108,10 @@ bool OOFAwareWidget::isOOFContainer (Widget *widget, int oofmIndex) ((OOFAwareWidget*)widget->getParent()) ->isPossibleContainerParent (OOFM_FLOATS)) || // Inline blocks are containing blocks, too. - widget->getStyle()->display == core::style::DISPLAY_INLINE_BLOCK || + widget->getStyle()->display == DISPLAY_INLINE_BLOCK || // Same for blocks with 'overview' set to another value than // (the default value) 'visible'. - widget->getStyle()->overflow != core::style::OVERFLOW_VISIBLE || + widget->getStyle()->overflow != OVERFLOW_VISIBLE || // Finally, "out of flow" in a narrower sense: floats; // absolutely and fixedly positioned elements; furthermore, // relatively positioned elements must already be @@ -229,7 +247,7 @@ void OOFAwareWidget::correctExtremesByOOF (Extremes *extremes) } } -void OOFAwareWidget::sizeAllocateStart (core::Allocation *allocation) +void OOFAwareWidget::sizeAllocateStart (Allocation *allocation) { for (int i = 0; i < NUM_OOFM; i++) @@ -251,11 +269,101 @@ void OOFAwareWidget::containerSizeChangedForChildrenOOF () outOfFlowMgr[i]->containerSizeChangedForChildren (); } -void OOFAwareWidget::drawOOF (View *view, Rectangle *area) +Widget *OOFAwareWidget::draw (View *view, Rectangle *area, Stack *iterator) { - for (int i = 0; i < NUM_OOFM; i++) - if(outOfFlowMgr[i]) - outOfFlowMgr[i]->draw(view, area); + DBG_OBJ_ENTER ("draw", 0, "draw", "%d, %d, %d * %d", + area->x, area->y, area->width, area->height); + + OOFStackIterator *osi = (OOFStackIterator*)iterator->getTop (); + Widget *retWidget = NULL; + + while (retWidget == NULL && osi->majorLevel < OOFStackIterator::END) { + retWidget = drawLevel (view, area, iterator, osi->majorLevel); + + if (retWidget == NULL) { + osi->majorLevel++; + osi->minorLevel = osi->index = 0; + } + } + + + DBG_OBJ_MSGF ("draw", 1, "=> %p", retWidget); + DBG_OBJ_LEAVE (); + return retWidget; +} + +Widget *OOFAwareWidget::drawLevel (View *view, Rectangle *area, Stack *iterator, + int majorLevel) +{ + DBG_OBJ_ENTER ("draw", 0, "OOFAwareWidget/drawLevel", + "(%d, %d, %d * %d), %s", + area->x, area->y, area->width, area->height, + OOFStackIterator::majorLevelText (majorLevel)); + + Widget *retWidget = NULL; + + switch (majorLevel) { + case OOFStackIterator::START: + break; + + case OOFStackIterator::BACKGROUND: + drawWidgetBox (view, area, false); + break; + + case OOFStackIterator::SC_BOTTOM: + if (stackingContextMgr) { + OOFStackIterator *osi = (OOFStackIterator*)iterator->getTop (); + retWidget = stackingContextMgr->drawBottom (view, area, iterator, + &osi->index); + } + break; + + case OOFStackIterator::IN_FLOW: + // Should be implemented in the sub class. + break; + + case OOFStackIterator::OOF_REF: + // Should be implemented in the sub class (when references are hold). + break; + + case OOFStackIterator::OOF_CONT: + retWidget = drawOOF (view, area, iterator); + break; + + case OOFStackIterator::SC_TOP: + if (stackingContextMgr) { + OOFStackIterator *osi = (OOFStackIterator*)iterator->getTop (); + retWidget = stackingContextMgr->drawTop (view, area, iterator, + &osi->index); + } + break; + + case OOFStackIterator::END: + break; + } + + DBG_OBJ_MSGF ("draw", 1, "=> %p", retWidget); + DBG_OBJ_LEAVE (); + return retWidget; +} + +Widget *OOFAwareWidget::drawOOF (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator) +{ + OOFStackIterator *osi = (OOFStackIterator*)iterator->getTop (); + assert (osi->majorLevel == OOFStackIterator::OOF_CONT); + + Widget *retWidget = NULL; + + for (; retWidget == NULL && osi->minorLevel < NUM_OOFM; osi->minorLevel++) { + if(outOfFlowMgr[osi->minorLevel]) + retWidget = outOfFlowMgr[osi->minorLevel]->draw (view, area, iterator, + &(osi->index)); + if (retWidget == NULL) + osi->index = 0; + } + + return retWidget; } Widget *OOFAwareWidget::getWidgetOOFAtPoint (int x, int y) @@ -302,7 +410,7 @@ void OOFAwareWidget::removeChild (Widget *child) assert (isWidgetOOF (child)); } -core::Widget *OOFAwareWidget::getWidgetAtPoint (int x, int y) +Widget *OOFAwareWidget::getWidgetAtPoint (int x, int y) { if (x >= allocation.x && y >= allocation.y && @@ -321,7 +429,7 @@ core::Widget *OOFAwareWidget::getWidgetAtPoint (int x, int y) return oofWidget; Widget *childAtPoint = NULL; - Iterator *it = + core::Iterator *it = iterator ((Content::Type) (Content::WIDGET_IN_FLOW | Content::WIDGET_OOF_CONT), false); @@ -350,6 +458,16 @@ core::Widget *OOFAwareWidget::getWidgetAtPoint (int x, int y) return NULL; } + +Object *OOFAwareWidget::stackingIterator (bool atEnd) +{ + OOFStackIterator *osi = new OOFStackIterator (); + // TODO Consider atEnd. + osi->majorLevel = OOFStackIterator::BACKGROUND; + osi->minorLevel = osi->index = 0; + return osi; +} + void OOFAwareWidget::borderChanged (int y, Widget *vloat) { assertNotReached (); diff --git a/dw/oofawarewidget.hh b/dw/oofawarewidget.hh index d2d5ef85..5525c301 100644 --- a/dw/oofawarewidget.hh +++ b/dw/oofawarewidget.hh @@ -105,6 +105,16 @@ protected: void print (); }; + class OOFStackIterator: public lout::object::Object + { + public: + enum { START, BACKGROUND, SC_BOTTOM, IN_FLOW, OOF_REF, OOF_CONT, SC_TOP, + END } ; + int majorLevel, minorLevel, index; + + static const char *majorLevelText (int majorLevel4); + }; + inline bool isParentRefOOF (int parentRef) { return parentRef != -1 && (parentRef & PARENT_REF_OOFM_MASK); } @@ -169,8 +179,12 @@ protected: void sizeAllocateStart (core::Allocation *allocation); void sizeAllocateEnd (); void containerSizeChangedForChildrenOOF (); - void drawOOF (core::View *view, core::Rectangle *area); - core::Widget *getWidgetOOFAtPoint (int x, int y); + virtual Widget *drawLevel (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator, + int majorLevel); + Widget *drawOOF (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator); + Widget *getWidgetOOFAtPoint (int x, int y); static bool isOOFContainer (Widget *widget, int oofmIndex); @@ -190,6 +204,10 @@ public: OOFAwareWidget (); ~OOFAwareWidget (); + Widget *draw (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator); + lout::object::Object *stackingIterator (bool atEnd); + virtual void borderChanged (int y, core::Widget *vloat); virtual void clearPositionChanged (); virtual void oofSizeChanged (bool extremesChanged); diff --git a/dw/ooffloatsmgr.cc b/dw/ooffloatsmgr.cc index eeca4681..f6f488f2 100644 --- a/dw/ooffloatsmgr.cc +++ b/dw/ooffloatsmgr.cc @@ -1277,30 +1277,47 @@ int OOFFloatsMgr::calcFloatX (Float *vloat, Side side, int gbX, int gbWidth, return x; } -void OOFFloatsMgr::draw (View *view, Rectangle *area) +Widget *OOFFloatsMgr::draw (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index) { - DBG_OBJ_ENTER ("draw", 0, "draw", "%d, %d, %d * %d", - area->x, area->y, area->width, area->height); + DBG_OBJ_ENTER ("draw", 0, "draw", "(%d, %d, %d * %d), [%d]", + area->x, area->y, area->width, area->height, *index); - drawFloats (leftFloatsCB, view, area); - drawFloats (rightFloatsCB, view, area); + Widget *retWidget = NULL; + if (*index < leftFloatsCB->size ()) + retWidget = drawFloats (leftFloatsCB, view, area, iterator, index, 0); + + if (retWidget == NULL) + retWidget = drawFloats (rightFloatsCB, view, area, iterator, index, + leftFloatsCB->size ()); + + DBG_OBJ_MSGF ("draw", 1, "=> %p", retWidget); DBG_OBJ_LEAVE (); + return retWidget; } -void OOFFloatsMgr::drawFloats (SortedFloatsVector *list, View *view, - Rectangle *area) +Widget *OOFFloatsMgr::drawFloats (SortedFloatsVector *list, View *view, + Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index, int startIndex) { // This could be improved, since the list is sorted: search the // first float fitting into the area, and iterate until one is // found below the area. - for (int i = 0; i < list->size(); i++) { - Widget *childWidget = list->get(i)->getWidget (); + + Widget *retWidget = NULL; + + for (; retWidget == NULL && *index - startIndex < list->size(); (*index)++) { + Widget *childWidget = list->get(*index - startIndex)->getWidget (); Rectangle childArea; if (!StackingContextMgr::handledByStackingContextMgr (childWidget) && childWidget->intersects (area, &childArea)) - childWidget->draw (view, &childArea); + retWidget = childWidget->drawTotal (view, &childArea, iterator); } + + return retWidget; } void OOFFloatsMgr::addWidgetInFlow (OOFAwareWidget *textblock, diff --git a/dw/ooffloatsmgr.hh b/dw/ooffloatsmgr.hh index 274e5d3c..e90a72be 100644 --- a/dw/ooffloatsmgr.hh +++ b/dw/ooffloatsmgr.hh @@ -284,8 +284,10 @@ private: bool doFloatsExceedCB (Side side); bool haveExtremesChanged (Side side); - void drawFloats (SortedFloatsVector *list, core::View *view, - core::Rectangle *area); + core::Widget *drawFloats (SortedFloatsVector *list, core::View *view, + core::Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index, int startIndex); core::Widget *getFloatWidgetAtPoint (SortedFloatsVector *list, int x, int y); bool collidesV (Float *vloat, Float *other, SFVType type, int *yReal); @@ -340,7 +342,8 @@ public: core::Allocation *allocation); void sizeAllocateEnd (OOFAwareWidget *caller); void containerSizeChangedForChildren (); - void draw (core::View *view, core::Rectangle *area); + core::Widget *draw (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator, int *index); void markSizeChange (int ref); void markExtremesChange (int ref); diff --git a/dw/oofpositionedmgr.cc b/dw/oofpositionedmgr.cc index 449ea322..07bc45aa 100644 --- a/dw/oofpositionedmgr.cc +++ b/dw/oofpositionedmgr.cc @@ -168,20 +168,26 @@ bool OOFPositionedMgr::haveExtremesChanged () } -void OOFPositionedMgr::draw (View *view, Rectangle *area) +Widget *OOFPositionedMgr::draw (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index) { - DBG_OBJ_ENTER ("draw", 0, "draw", "%d, %d, %d * %d", - area->x, area->y, area->width, area->height); + DBG_OBJ_ENTER ("draw", 0, "draw", "(%d, %d, %d * %d), [%d]", + area->x, area->y, area->width, area->height, *index); - for (int i = 0; i < children->size(); i++) { - Widget *childWidget = children->get(i)->widget; + Widget *retWidget = NULL; + + for (; retWidget == NULL && *index < children->size(); (*index)++) { + Widget *childWidget = children->get(*index)->widget; Rectangle childArea; if (!StackingContextMgr::handledByStackingContextMgr (childWidget) && childWidget->intersects (area, &childArea)) - childWidget->draw (view, &childArea); + retWidget = childWidget->drawTotal (view, &childArea, iterator); } + DBG_OBJ_MSGF ("draw", 1, "=> %p", retWidget); DBG_OBJ_LEAVE (); + return retWidget; } void OOFPositionedMgr::addWidgetInFlow (OOFAwareWidget *widget, diff --git a/dw/oofpositionedmgr.hh b/dw/oofpositionedmgr.hh index 40f3af43..c7f55262 100644 --- a/dw/oofpositionedmgr.hh +++ b/dw/oofpositionedmgr.hh @@ -64,7 +64,8 @@ public: core::Allocation *allocation); void sizeAllocateEnd (OOFAwareWidget *caller); void containerSizeChangedForChildren (); - void draw (core::View *view, core::Rectangle *area); + core::Widget *draw (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator, int *index); void markSizeChange (int ref); void markExtremesChange (int ref); diff --git a/dw/outofflowmgr.hh b/dw/outofflowmgr.hh index b5f50c56..5b74e513 100644 --- a/dw/outofflowmgr.hh +++ b/dw/outofflowmgr.hh @@ -25,7 +25,9 @@ public: core::Allocation *allocation) = 0; virtual void sizeAllocateEnd (OOFAwareWidget *caller) = 0; virtual void containerSizeChangedForChildren () = 0; - virtual void draw (core::View *view, core::Rectangle *area) = 0; + virtual core::Widget *draw (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index) = 0; virtual void markSizeChange (int ref) = 0; virtual void markExtremesChange (int ref) = 0; diff --git a/dw/stackingcontextmgr.cc b/dw/stackingcontextmgr.cc index 373756e2..c7b5f783 100644 --- a/dw/stackingcontextmgr.cc +++ b/dw/stackingcontextmgr.cc @@ -60,48 +60,67 @@ void StackingContextMgr::addChildSCWidget (Widget *widget) DBG_OBJ_ARRSET_PTR ("childSCWidgets", childSCWidgets->size() - 1, widget); } -void StackingContextMgr::drawBottom (View *view, Rectangle *area) +Widget *StackingContextMgr::drawBottom (View *view, Rectangle *area, + lout::container::untyped::Stack + *iterator, + int *index) { DBG_OBJ_ENTER ("draw", 0, "drawBottom", "%d, %d, %d * %d", area->x, area->y, area->width, area->height); - draw (view, area, INT_MIN, -1); + Widget *retWidget = draw (view, area, iterator, index, INT_MIN, -1); DBG_OBJ_LEAVE (); + return retWidget; } -void StackingContextMgr::drawTop (View *view, Rectangle *area) +Widget *StackingContextMgr::drawTop (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index) { DBG_OBJ_ENTER ("draw", 0, "drawTop", "%d, %d, %d * %d", area->x, area->y, area->width, area->height); - draw (view, area, 0, INT_MAX); + Widget *retWidget = draw (view, area, iterator, index, 0, INT_MAX); DBG_OBJ_LEAVE (); + return retWidget; } -void StackingContextMgr::draw (View *view, Rectangle *area, int startZIndex, - int endZIndex) +Widget *StackingContextMgr::draw (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index, int startZIndex, int endZIndex) { DBG_OBJ_ENTER ("draw", 0, "draw", "[%d, %d, %d * %d], %d, %d", area->x, area->y, area->width, area->height, startZIndex, endZIndex); + DBG_OBJ_MSGF ("draw", 1, "initially: index = %d (of %d)", + *index, childSCWidgets->size ()); + + Widget *retWidget = NULL; for (int zIndex = max (minZIndex, startZIndex); - zIndex <= min (maxZIndex, endZIndex); zIndex++) { + retWidget == NULL && zIndex <= min (maxZIndex, endZIndex); + zIndex++) { DBG_OBJ_MSGF ("draw", 1, "drawing zIndex = %d", zIndex); DBG_OBJ_MSG_START (); - for (int i = 0; i < childSCWidgets->size (); i++) { - Widget *child = childSCWidgets->get (i); + // TODO This is wrong. + for (; retWidget == NULL && *index < childSCWidgets->size (); + (*index)++) { + Widget *child = childSCWidgets->get (*index); DBG_OBJ_MSGF ("draw", 2, "widget %p has zIndex = %d", child, child->getStyle()->zIndex); Rectangle childArea; if (child->getStyle()->zIndex == zIndex && child->intersects (area, &childArea)) - child->draw (view, &childArea); + retWidget = child->drawTotal (view, &childArea, iterator); } DBG_OBJ_MSG_END (); } + DBG_OBJ_MSGF ("draw", 1, "finally: index = %d (of %d)", + *index, childSCWidgets->size ()); + DBG_OBJ_MSGF ("draw", 1, "=> %p", retWidget); DBG_OBJ_LEAVE (); + return retWidget; } Widget *StackingContextMgr::getTopWidgetAtPoint (int x, int y) diff --git a/dw/stackingcontextmgr.hh b/dw/stackingcontextmgr.hh index 5c6a0d2f..e7254d7f 100644 --- a/dw/stackingcontextmgr.hh +++ b/dw/stackingcontextmgr.hh @@ -23,7 +23,9 @@ private: lout::container::typed::Vector<Widget> *childSCWidgets; int minZIndex, maxZIndex; - void draw (View *view, Rectangle *area, int startZIndex, int endZIndex); + Widget *draw (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index, int startZIndex, int endZIndex); Widget *getWidgetAtPoint (int x, int y, int startZIndex, int endZIndex); public: @@ -45,8 +47,12 @@ public: void addChildSCWidget (Widget *widget); - void drawBottom (View *view, Rectangle *area); - void drawTop (View *view, Rectangle *area); + Widget *drawBottom (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index); + Widget *drawTop (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator, + int *index); Widget *getTopWidgetAtPoint (int x, int y); Widget *getBottomWidgetAtPoint (int x, int y); diff --git a/dw/table.cc b/dw/table.cc index 5e4083ff..f9858ddd 100644 --- a/dw/table.cc +++ b/dw/table.cc @@ -356,21 +356,24 @@ bool Table::isBlockLevel () return true; } -void Table::draw (core::View *view, core::Rectangle *area) +core::Widget *Table::drawLevel (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator, + int majorLevel) { - DBG_OBJ_ENTER ("draw", 0, "draw", "%d, %d, %d * %d", - area->x, area->y, area->width, area->height); + DBG_OBJ_ENTER ("draw", 0, "Table/drawLevel", "(%d, %d, %d * %d), %s", + area->x, area->y, area->width, area->height, + OOFStackIterator::majorLevelText (majorLevel)); - // Can be optimized, by iterating on the lines in area. - drawWidgetBox (view, area, false); + Widget *retWidget = NULL; #if 0 + // This old code belongs perhaps to the background. Check when reactivated. int offx = getStyle()->boxOffsetX () + getStyle()->hBorderSpacing; int offy = getStyle()->boxOffsetY () + getStyle()->vBorderSpacing; int width = getContentWidth (); - + // This part seems unnecessary. It also segfaulted sometimes when - // cumHeight size was less than numRows. --jcid + // cumHeight size was less than numRows. --jcid for (int row = 0; row < numRows; row++) { if (rowStyle->get (row)) drawBox (view, rowStyle->get (row), area, @@ -381,19 +384,27 @@ void Table::draw (core::View *view, core::Rectangle *area) } #endif - for (int i = 0; i < children->size (); i++) { - if (childDefined (i)) { - Widget *child = children->get(i)->cell.widget; - core::Rectangle childArea; - if (!core::StackingContextMgr::handledByStackingContextMgr (child) && - child->intersects (area, &childArea)) - child->draw (view, &childArea); + switch (majorLevel) { + case OOFStackIterator::IN_FLOW: + for (int i = 0; retWidget == NULL && i < children->size (); i++) { + if (childDefined (i)) { + Widget *child = children->get(i)->cell.widget; + core::Rectangle childArea; + if (!core::StackingContextMgr::handledByStackingContextMgr (child) + && child->intersects (area, &childArea)) + retWidget = child->drawTotal (view, &childArea, iterator); + } } - } + break; - drawOOF (view, area); + default: + retWidget = OOFAwareWidget::drawLevel (view, area, iterator, majorLevel); + break; + } + DBG_OBJ_MSGF ("draw", 1, "=> %p", retWidget); DBG_OBJ_LEAVE (); + return retWidget; } void Table::removeChild (Widget *child) diff --git a/dw/table.hh b/dw/table.hh index 560a2cb7..502b1332 100644 --- a/dw/table.hh +++ b/dw/table.hh @@ -471,7 +471,9 @@ protected: bool isBlockLevel (); - void draw (core::View *view, core::Rectangle *area); + Widget *drawLevel (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator, + int majorLevel); //bool buttonPressImpl (core::EventButton *event); //bool buttonReleaseImpl (core::EventButton *event); diff --git a/dw/textblock.cc b/dw/textblock.cc index 92d7f662..4b915f2e 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -1447,10 +1447,16 @@ void Textblock::drawSpace(int wordIndex, core::View *view, * - area is used always (ev. set it to event->area) * - event is only used when is_expose */ -void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area) +core::Widget *Textblock::drawLine (Line *line, core::View *view, + core::Rectangle *area, + lout::container::untyped::Stack *iterator) { DBG_OBJ_ENTER ("draw", 0, "drawLine", "..., %d, %d, %d * %d", area->x, area->y, area->width, area->height); + + OOFStackIterator *osi = (OOFStackIterator*)iterator->getTop (); + + Widget *retWidget = NULL; int xWidget = line->textOffset; int yWidgetBase = lineYOffsetWidget (line) + line->borderAscent; @@ -1461,10 +1467,13 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area) DBG_MSG_WORD ("draw", 1, "<i>line starts with: </i>", line->firstWord, ""); DBG_MSG_WORD ("draw", 1, "<i>line ends with: </i>", line->lastWord, ""); - for (int wordIndex = line->firstWord; - wordIndex <= line->lastWord && xWidget < area->x + area->width; - wordIndex++) { - Word *word = words->getRef(wordIndex); + if (osi->index < line->firstWord) + osi->index = line->firstWord; + + for (; retWidget == NULL && osi->index <= line->lastWord + && xWidget < area->x + area->width; + osi->index++) { + Word *word = words->getRef (osi->index); int wordSize = word->size.width; if (xWidget + wordSize + word->hyphenWidth + word->effSpace >= area->x) { @@ -1478,36 +1487,36 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area) if (!core::StackingContextMgr::handledByStackingContextMgr (child) && child->intersects (area, &childArea)) - child->draw (view, &childArea); + retWidget = child->drawTotal (view, &childArea, iterator); } else { - int wordIndex2 = wordIndex; + int wordIndex2 = osi->index; while (wordIndex2 < line->lastWord && (words->getRef(wordIndex2)->flags & Word::DRAW_AS_ONE_TEXT) && word->style == words->getRef(wordIndex2 + 1)->style) wordIndex2++; - drawWord(line, wordIndex, wordIndex2, view, area, + drawWord(line, osi->index, wordIndex2, view, area, xWidget, yWidgetBase); wordSize = 0; - for (int i = wordIndex; i <= wordIndex2; i++) + for (int i = osi->index; i <= wordIndex2; i++) wordSize += words->getRef(i)->size.width; - wordIndex = wordIndex2; - word = words->getRef(wordIndex); + osi->index = wordIndex2; + word = words->getRef (osi->index); } } - if (word->effSpace > 0 && wordIndex < line->lastWord && - words->getRef(wordIndex + 1)->content.type != + if (word->effSpace > 0 && osi->index < line->lastWord && + words->getRef(osi->index + 1)->content.type != core::Content::BREAK) { if (word->spaceStyle->hasBackground ()) drawBox (view, word->spaceStyle, area, xWidget + wordSize, yWidgetBase - line->borderAscent, word->effSpace, line->borderAscent + line->borderDescent, false); - drawSpace(wordIndex, view, area, xWidget + wordSize, - yWidgetBase); + drawSpace (osi->index, view, area, xWidget + wordSize, + yWidgetBase); } } @@ -1515,7 +1524,9 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area) xWidget += wordSize + word->effSpace; } + DBG_OBJ_MSGF ("draw", 1, "=> %p", retWidget); DBG_OBJ_LEAVE (); + return retWidget; } /** @@ -1683,36 +1694,42 @@ Textblock::Word *Textblock::findWord (int x, int y, bool *inSpace) return NULL; } -void Textblock::draw (core::View *view, core::Rectangle *area) +core::Widget *Textblock::drawLevel (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator, + int majorLevel) { - DBG_OBJ_ENTER ("draw", 0, "draw", "%d, %d, %d * %d", - area->x, area->y, area->width, area->height); + DBG_OBJ_ENTER ("draw", 0, "Textblock/drawLevel", "(%d, %d, %d * %d), %s", + area->x, area->y, area->width, area->height, + OOFStackIterator::majorLevelText (majorLevel)); - int lineIndex; - Line *line; + Widget *retWidget = NULL; - drawWidgetBox (view, area, false); - - if (stackingContextMgr) - stackingContextMgr->drawBottom (view, area); - - lineIndex = findLineIndexWhenAllocated (area->y); + switch (majorLevel) { + case OOFStackIterator::IN_FLOW: + // Osi->index (word index) is regarded in drawLine. + for (int lineIndex = findLineIndexWhenAllocated (area->y); + retWidget == NULL && lineIndex < lines->size (); lineIndex++) { + Line *line = lines->getRef (lineIndex); + if (lineYOffsetWidget (line) >= area->y + area->height) + break; + + DBG_OBJ_MSGF ("draw", 0, "line %d (of %d)", lineIndex, lines->size ()); + retWidget = drawLine (line, view, area, iterator); + } + break; - for (; lineIndex < lines->size (); lineIndex++) { - line = lines->getRef (lineIndex); - if (lineYOffsetWidget (line) >= area->y + area->height) - break; + case OOFStackIterator::OOF_REF: + // TODO + break; - DBG_OBJ_MSGF ("draw", 0, "line %d (of %d)", lineIndex, lines->size ()); - drawLine (line, view, area); + default: + retWidget = OOFAwareWidget::drawLevel (view, area, iterator, majorLevel); + break; } - drawOOF (view, area); - - if (stackingContextMgr) - stackingContextMgr->drawTop (view, area); - + DBG_OBJ_MSGF ("draw", 1, "=> %p", retWidget); DBG_OBJ_LEAVE (); + return retWidget; } /** diff --git a/dw/textblock.hh b/dw/textblock.hh index 74ef6525..c9f86fa5 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -642,7 +642,8 @@ protected: core::Rectangle *area, int xWidget, int yWidgetBase); void drawSpace (int wordIndex, core::View *view, core::Rectangle *area, int xWidget, int yWidgetBase); - void drawLine (Line *line, core::View *view, core::Rectangle *area); + Widget *drawLine (Line *line, core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator); int findLineIndex (int y); int findLineIndexWhenNotAllocated (int y); int findLineIndexWhenAllocated (int y); @@ -797,6 +798,10 @@ protected: void alignLine (int lineIndex); void calcTextOffset (int lineIndex, int totalWidth); + Widget *drawLevel (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator, + int majorLevel); + void sizeRequestImpl (core::Requisition *requisition); void getExtremesImpl (core::Extremes *extremes); void sizeAllocateImpl (core::Allocation *allocation); @@ -816,8 +821,6 @@ protected: bool isBlockLevel (); - void draw (core::View *view, core::Rectangle *area); - bool buttonPressImpl (core::EventButton *event); bool buttonReleaseImpl (core::EventButton *event); bool motionNotifyImpl (core::EventMotion *event); diff --git a/dw/widget.cc b/dw/widget.cc index be103756..cf955dec 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -179,6 +179,66 @@ bool Widget::intersects (Rectangle *area, Rectangle *intersection) return r; } +/** Area is given in widget coordinates. */ +void Widget::draw (View *view, Rectangle *area) +{ + DBG_OBJ_MSG ("draw", 0, "<b>Widget::draw not implemented</b>"); + misc::assertNotReached (); +} + +/** Area is given in widget coordinates. */ +Widget *Widget::draw (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator) +{ + // Suitable for widgets without children. + draw (view, area); + return NULL; +} + +Widget *Widget::drawTotal (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator) +{ + DBG_OBJ_ENTER ("draw", 0, "drawTotal", "%d, %d, %d * %d", + area->x, area->y, area->width, area->height); + + Object *si = stackingIterator (false); + if (si) { + iterator->push (si); + DBG_OBJ_MSGF ("draw", 1, "pushing on iterator; now %d element(s)", + iterator->size ()); + } else + DBG_OBJ_MSGF ("draw", 1, "nothing on iterator; %d element(s)", + iterator->size ()); + + + Widget *retWidget = draw (view, area, iterator); + + // A return value other than NULL indicates a widget with a complex + // drawing process, for which stackIterator() must return something + // non-NULL, so that the interrupted drawing process can be + // continued. + + assert (retWidget == NULL || si != NULL); + + if (retWidget == NULL && si != NULL) + iterator->pop (); + + DBG_OBJ_MSGF ("draw", 1, "=> %p", retWidget); + DBG_OBJ_LEAVE (); + return retWidget; +} + +void Widget::drawToplevel (View *view, Rectangle *area) +{ + assert (parent == NULL); + + lout::container::untyped::Stack iterator (true); + Widget *retWidget = drawTotal (view, area, &iterator); + + // Everything should be finished at this point. + assert (retWidget == NULL); +} + void Widget::setParent (Widget *parent) { this->parent = parent; @@ -1835,6 +1895,11 @@ void Widget::leaveNotifyImpl (EventCrossing *) tooltip->onLeave(); } +lout::object::Object *Widget::stackingIterator (bool atEnd) +{ + return NULL; +} + void Widget::removeChild (Widget *child) { // Should be implemented. diff --git a/dw/widget.hh b/dw/widget.hh index 4ad397ee..d44454bc 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -277,6 +277,8 @@ protected: inline void queueResize (int ref, bool extremesChanged) { queueResize (ref, extremesChanged, false); } + virtual void draw (View *view, Rectangle *area); + /** * \brief See \ref dw-widget-sizes. */ @@ -468,8 +470,11 @@ public: bool intersects (Rectangle *area, Rectangle *intersection); - /** Area is given in widget coordinates. */ - virtual void draw (View *view, Rectangle *area) = 0; + virtual Widget *draw (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator); + Widget *drawTotal (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator); + void drawToplevel (View *view, Rectangle *area); bool buttonPress (EventButton *event); bool buttonRelease (EventButton *event); @@ -523,6 +528,14 @@ public: * dw::core::Iterator::prev in this case. */ virtual Iterator *iterator (Content::Type mask, bool atEnd) = 0; + + /** + * \brief ... + * + * May return NULL. + */ + virtual lout::object::Object *stackingIterator (bool atEnd); + virtual void removeChild (Widget *child); }; diff --git a/test/dw_simple_container.cc b/test/dw_simple_container.cc index e19511a6..cdc7df5f 100644 --- a/test/dw_simple_container.cc +++ b/test/dw_simple_container.cc @@ -27,190 +27,195 @@ using namespace lout::misc; namespace dw { -int SimpleContainer::CLASS_ID = -1; + int SimpleContainer::CLASS_ID = -1; -// ---------------------------------------------------------------------- + // ---------------------------------------------------------------------- -SimpleContainer::SimpleContainerIterator::SimpleContainerIterator + SimpleContainer::SimpleContainerIterator::SimpleContainerIterator (SimpleContainer *simpleContainer, Content::Type mask, bool atEnd) : - Iterator (simpleContainer, mask, atEnd) -{ - content.type = atEnd ? Content::END : Content::START; -} + Iterator (simpleContainer, mask, atEnd) + { + content.type = atEnd ? Content::END : Content::START; + } -lout::object::Object *SimpleContainer::SimpleContainerIterator::clone () -{ - SimpleContainerIterator *sci = - new SimpleContainerIterator ((SimpleContainer*)getWidget(), - getMask(), false); - sci->content = content; - return sci; -} + lout::object::Object *SimpleContainer::SimpleContainerIterator::clone () + { + SimpleContainerIterator *sci = + new SimpleContainerIterator ((SimpleContainer*)getWidget(), + getMask(), false); + sci->content = content; + return sci; + } -int SimpleContainer::SimpleContainerIterator::index () -{ - switch (content.type) { - case Content::START: - return 0; - case Content::WIDGET_IN_FLOW: - return 1; - case Content::END: - return 2; - default: - assertNotReached (); - return 0; + int SimpleContainer::SimpleContainerIterator::index () + { + switch (content.type) { + case Content::START: + return 0; + case Content::WIDGET_IN_FLOW: + return 1; + case Content::END: + return 2; + default: + assertNotReached (); + return 0; + } } -} -int SimpleContainer::SimpleContainerIterator::compareTo + int SimpleContainer::SimpleContainerIterator::compareTo (lout::object::Comparable *other) -{ - return index () - ((SimpleContainerIterator*)other)->index (); -} + { + return index () - ((SimpleContainerIterator*)other)->index (); + } -bool SimpleContainer::SimpleContainerIterator::next () -{ - SimpleContainer *simpleContainer = (SimpleContainer*)getWidget(); + bool SimpleContainer::SimpleContainerIterator::next () + { + SimpleContainer *simpleContainer = (SimpleContainer*)getWidget(); - if (content.type == Content::END) - return false; + if (content.type == Content::END) + return false; - // simple containers only contain widgets: - if ((getMask() & Content::WIDGET_IN_FLOW) == 0) { - content.type = Content::END; - return false; - } + // simple containers only contain widgets: + if ((getMask() & Content::WIDGET_IN_FLOW) == 0) { + content.type = Content::END; + return false; + } - if (content.type == Content::START) { - if (simpleContainer->child != NULL) { - content.type = Content::WIDGET_IN_FLOW; - content.widget = simpleContainer->child; - return true; - } else { + if (content.type == Content::START) { + if (simpleContainer->child != NULL) { + content.type = Content::WIDGET_IN_FLOW; + content.widget = simpleContainer->child; + return true; + } else { + content.type = Content::END; + return false; + } + } else /* if (content.type == Content::WIDGET) */ { content.type = Content::END; return false; } - } else /* if (content.type == Content::WIDGET) */ { - content.type = Content::END; - return false; } -} -bool SimpleContainer::SimpleContainerIterator::prev () -{ - SimpleContainer *simpleContainer = (SimpleContainer*)getWidget(); + bool SimpleContainer::SimpleContainerIterator::prev () + { + SimpleContainer *simpleContainer = (SimpleContainer*)getWidget(); - if (content.type == Content::START) - return false; + if (content.type == Content::START) + return false; - // simple containers only contain widgets: - if ((getMask() & Content::WIDGET_IN_FLOW) == 0) { - content.type = Content::START; - return false; - } + // simple containers only contain widgets: + if ((getMask() & Content::WIDGET_IN_FLOW) == 0) { + content.type = Content::START; + return false; + } - if (content.type == Content::END) { - if (simpleContainer->child != NULL) { - content.type = Content::WIDGET_IN_FLOW; - content.widget = simpleContainer->child; - return true; - } else { + if (content.type == Content::END) { + if (simpleContainer->child != NULL) { + content.type = Content::WIDGET_IN_FLOW; + content.widget = simpleContainer->child; + return true; + } else { + content.type = Content::START; + return false; + } + } else /* if (content.type == Content::WIDGET) */ { content.type = Content::START; return false; } - } else /* if (content.type == Content::WIDGET) */ { - content.type = Content::START; - return false; } -} -void SimpleContainer::SimpleContainerIterator::highlight (int start, - int end, - HighlightLayer layer) -{ - /** todo Needs this an implementation? */ -} + void SimpleContainer::SimpleContainerIterator::highlight (int start, + int end, + HighlightLayer layer) + { + /** todo Needs this an implementation? */ + } -void SimpleContainer::SimpleContainerIterator::unhighlight (int direction, - HighlightLayer - layer) -{ - /** todo Needs this an implementation? */ -} + void SimpleContainer::SimpleContainerIterator::unhighlight (int direction, + HighlightLayer + layer) + { + /** todo Needs this an implementation? */ + } -void SimpleContainer::SimpleContainerIterator::getAllocation (int start, - int end, - Allocation - *allocation) -{ - /** \bug Not implemented. */ -} + void SimpleContainer::SimpleContainerIterator::getAllocation (int start, + int end, + Allocation + *allocation) + { + /** \bug Not implemented. */ + } -// ---------------------------------------------------------------------- + // ---------------------------------------------------------------------- -SimpleContainer::SimpleContainer () -{ - registerName ("dw::SimpleContainer", &CLASS_ID); - child = NULL; -} + SimpleContainer::SimpleContainer () + { + registerName ("dw::SimpleContainer", &CLASS_ID); + child = NULL; + } -SimpleContainer::~SimpleContainer () -{ - if (child) - delete child; -} + SimpleContainer::~SimpleContainer () + { + if (child) + delete child; + } -void SimpleContainer::sizeRequestImpl (Requisition *requisition) -{ - Requisition childReq; - if (child) - child->sizeRequest (&childReq); - else - childReq.width = childReq.ascent = childReq.descent = 0; + void SimpleContainer::sizeRequestImpl (Requisition *requisition) + { + Requisition childReq; + if (child) + child->sizeRequest (&childReq); + else + childReq.width = childReq.ascent = childReq.descent = 0; - requisition->width = childReq.width + boxDiffWidth (); - requisition->ascent = childReq.ascent + boxOffsetY (); - requisition->descent = childReq.descent + boxRestHeight (); + requisition->width = childReq.width + boxDiffWidth (); + requisition->ascent = childReq.ascent + boxOffsetY (); + requisition->descent = childReq.descent + boxRestHeight (); - correctRequisition (requisition, splitHeightPreserveAscent); -} + correctRequisition (requisition, splitHeightPreserveAscent); + } -void SimpleContainer::getExtremesImpl (Extremes *extremes) -{ - Extremes childExtr; - if (child) - child->getExtremes (&childExtr); - else - childExtr.minWidth = childExtr.maxWidth = 0; + void SimpleContainer::getExtremesImpl (Extremes *extremes) + { + Extremes childExtr; + if (child) + child->getExtremes (&childExtr); + else + childExtr.minWidth = childExtr.maxWidth = 0; - extremes->minWidth = childExtr.minWidth + boxDiffWidth (); - extremes->maxWidth = childExtr.maxWidth + boxDiffWidth (); + extremes->minWidth = childExtr.minWidth + boxDiffWidth (); + extremes->maxWidth = childExtr.maxWidth + boxDiffWidth (); - correctExtremes (extremes); -} + correctExtremes (extremes); + } -void SimpleContainer::sizeAllocateImpl (Allocation *allocation) -{ - Allocation childAlloc; - - if (child) { - childAlloc.x = allocation->x + boxOffsetX (); - childAlloc.y = allocation->y + boxOffsetY (); - childAlloc.width = allocation->width - boxDiffWidth (); - childAlloc.ascent = allocation->ascent - boxOffsetY (); - childAlloc.descent = allocation->descent - boxRestHeight (); - child->sizeAllocate (&childAlloc); + void SimpleContainer::sizeAllocateImpl (Allocation *allocation) + { + Allocation childAlloc; + + if (child) { + childAlloc.x = allocation->x + boxOffsetX (); + childAlloc.y = allocation->y + boxOffsetY (); + childAlloc.width = allocation->width - boxDiffWidth (); + childAlloc.ascent = allocation->ascent - boxOffsetY (); + childAlloc.descent = allocation->descent - boxRestHeight (); + child->sizeAllocate (&childAlloc); + } } -} -void SimpleContainer::draw (View *view, Rectangle *area) +core::Widget *SimpleContainer::draw (View *view, Rectangle *area, + lout::container::untyped::Stack *iterator) { + Widget *retWidget = NULL; + drawWidgetBox (view, area, false); Rectangle childArea; if (child && child->intersects (area, &childArea)) - child->draw (view, &childArea); + retWidget = child->drawTotal (view, &childArea, iterator); + + return retWidget; } Iterator *SimpleContainer::iterator (Content::Type mask, bool atEnd) diff --git a/test/dw_simple_container.hh b/test/dw_simple_container.hh index bb1a37af..0aa19ad6 100644 --- a/test/dw_simple_container.hh +++ b/test/dw_simple_container.hh @@ -44,7 +44,8 @@ public: SimpleContainer (); ~SimpleContainer (); - void draw (core::View *view, core::Rectangle *area); + Widget *draw (core::View *view, core::Rectangle *area, + lout::container::untyped::Stack *iterator); core::Iterator *iterator (core::Content::Type mask, bool atEnd); void removeChild (Widget *child); |