diff options
author | Sebastian Geerken <devnull@localhost> | 2014-08-24 23:10:00 +0200 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2014-08-24 23:10:00 +0200 |
commit | 4f846f817255635642a1a2201abd36a9e493c719 (patch) | |
tree | 5d0768f5ae37484ea7662d43eaa9b79f8ee355c2 /dw | |
parent | e569803c28ed96548720f123a63adb40171c1de9 (diff) |
First (since GROWS) work on absolute positions.
Diffstat (limited to 'dw')
-rw-r--r-- | dw/outofflowmgr.cc | 182 | ||||
-rw-r--r-- | dw/outofflowmgr.hh | 38 | ||||
-rw-r--r-- | dw/textblock.cc | 24 | ||||
-rw-r--r-- | dw/textblock.hh | 5 | ||||
-rw-r--r-- | dw/widget.hh | 4 |
5 files changed, 162 insertions, 91 deletions
diff --git a/dw/outofflowmgr.cc b/dw/outofflowmgr.cc index caa7fee5..b6bd3b07 100644 --- a/dw/outofflowmgr.cc +++ b/dw/outofflowmgr.cc @@ -472,16 +472,6 @@ void OutOfFlowMgr::TBInfo::updateAllocation () DBG_OBJ_LEAVE_O (getWidget ()); } -OutOfFlowMgr::AbsolutelyPositioned::AbsolutelyPositioned (OutOfFlowMgr *oofm, - Widget *widget, - Textblock - *generatingBlock, - int externalIndex) -{ - this->widget = widget; - dirty = true; -} - OutOfFlowMgr::OutOfFlowMgr (Textblock *containingBlock) { DBG_OBJ_CREATE ("dw::OutOfFlowMgr"); @@ -509,7 +499,9 @@ OutOfFlowMgr::OutOfFlowMgr (Textblock *containingBlock) leftFloatsMark = rightFloatsMark = 0; lastLeftTBIndex = lastRightTBIndex = 0; - absolutelyPositioned = new Vector<AbsolutelyPositioned> (1, true); + absolutelyPositioned = new Vector<Widget> (1, false); + + DBG_OBJ_SET_NUM ("absolutelyPositioned.size", absolutelyPositioned->size()); containingBlockWasAllocated = containingBlock->wasAllocated (); containingBlockAllocation = *(containingBlock->getAllocation()); @@ -595,6 +587,8 @@ void OutOfFlowMgr::sizeAllocateEnd (Textblock *caller) sizeAllocateFloats (LEFT, leftFloatsCB->size () - 1); sizeAllocateFloats (RIGHT, rightFloatsCB->size () - 1); + sizeAllocateAbsolutelyPositioned (); + // Check changes of both textblocks and floats allocation. (All // is checked by hasRelationChanged (...).) for (lout::container::typed::Iterator<TypedPointer <Textblock> > it = @@ -661,7 +655,7 @@ void OutOfFlowMgr::containerSizeChangedForChildren () for (int i = 0; i < rightFloatsAll->size (); i++) rightFloatsAll->get(i)->getWidget()->containerSizeChanged (); for (int i = 0; i < absolutelyPositioned->size(); i++) - absolutelyPositioned->get(i)->widget->containerSizeChanged (); + absolutelyPositioned->get(i)->containerSizeChanged (); DBG_OBJ_LEAVE (); } @@ -1260,9 +1254,14 @@ int OutOfFlowMgr::calcFloatX (Float *vloat, Side side, int gbX, int gbWidth, void OutOfFlowMgr::draw (View *view, Rectangle *area) { + DBG_OBJ_ENTER ("draw", 0, "draw", "%d, %d, %d * %d", + area->x, area->y, area->width, area->height); + drawFloats (leftFloatsCB, view, area); drawFloats (rightFloatsCB, view, area); drawAbsolutelyPositioned (view, area); + + DBG_OBJ_LEAVE (); } void OutOfFlowMgr::drawFloats (SortedFloatsVector *list, View *view, @@ -1282,10 +1281,10 @@ void OutOfFlowMgr::drawFloats (SortedFloatsVector *list, View *view, void OutOfFlowMgr::drawAbsolutelyPositioned (View *view, Rectangle *area) { for (int i = 0; i < absolutelyPositioned->size(); i++) { - AbsolutelyPositioned *abspos = absolutelyPositioned->get(i); + Widget *child = absolutelyPositioned->get(i); Rectangle childArea; - if (abspos->widget->intersects (area, &childArea)) - abspos->widget->draw (view, &childArea); + if (child->intersects (area, &childArea)) + child->draw (view, &childArea); } } @@ -1309,8 +1308,7 @@ bool OutOfFlowMgr::isWidgetOutOfFlow (Widget *widget) bool OutOfFlowMgr::isWidgetHandledByOOFM (Widget *widget) { // May be extended for fixed (and relative?) positions. - return isWidgetFloat (widget); - // TODO temporary disabled: || isWidgetAbsolutelyPositioned (widget); + return isWidgetFloat (widget) || isWidgetAbsolutelyPositioned (widget); } void OutOfFlowMgr::addWidgetInFlow (Textblock *textblock, @@ -1416,12 +1414,13 @@ void OutOfFlowMgr::addWidgetOOF (Widget *widget, Textblock *generatingBlock, floatsByWidget->put (new TypedPointer<Widget> (widget), vloat); } else if (isWidgetAbsolutelyPositioned (widget)) { - AbsolutelyPositioned *abspos = - new AbsolutelyPositioned (this, widget, generatingBlock, - externalIndex); - absolutelyPositioned->put (abspos); + absolutelyPositioned->put (widget); widget->parentRef = createRefAbsolutelyPositioned (absolutelyPositioned->size() - 1); + DBG_OBJ_SET_NUM ("absolutelyPositioned.size", + absolutelyPositioned->size()); + DBG_OBJ_ARRSET_NUM ("absolutelyPositioned", + absolutelyPositioned->size() - 1, widget); } else // May be extended. assertNotReached(); @@ -1492,8 +1491,7 @@ void OutOfFlowMgr::markSizeChange (int ref) // differentiates many special cases), but the size is not known yet, vloat->generatingBlock->borderChanged (vloat->yReal, vloat->getWidget ()); } else if (isRefAbsolutelyPositioned (ref)) { - int i = getAbsolutelyPositionedIndexFromRef (ref); - absolutelyPositioned->get(i)->dirty = true; + // Nothing to do. } else assertNotReached(); @@ -1537,10 +1535,9 @@ Widget *OutOfFlowMgr::getAbsolutelyPositionedWidgetAtPoint (int x, int y, int level) { for (int i = 0; i < absolutelyPositioned->size(); i++) { - AbsolutelyPositioned *abspos = absolutelyPositioned->get(i); - if (abspos->widget->wasAllocated ()) { - Widget *childAtPoint = - abspos->widget->getWidgetAtPoint (x, y, level + 1); + Widget *child = absolutelyPositioned->get(i); + if (child->wasAllocated ()) { + Widget *childAtPoint = child->getWidgetAtPoint (x, y, level + 1); if (childAtPoint) return childAtPoint; } @@ -2300,6 +2297,48 @@ void OutOfFlowMgr::ensureFloatSize (Float *vloat) DBG_OBJ_LEAVE (); } +int OutOfFlowMgr::getAvailWidthOfChild (Widget *child, bool forceValue) +{ + DBG_OBJ_ENTER ("resize.oofm", 0, + "OutOfFlowMgr/getAvailWidthOfChild", "%p, %s", + child, forceValue ? "true" : "false"); + + int width; + + if (child->getStyle()->width == style::LENGTH_AUTO && + child->getStyle()->minWidth == style::LENGTH_AUTO && + child->getStyle()->maxWidth == style::LENGTH_AUTO) { + // TODO This should (perhaps?) only used when 'width' is undefined. + // TODO Is "boxDiffWidth()" correct here? + DBG_OBJ_MSG ("resize.oofm", 1, "no specification"); + if (forceValue) { + int availWidth = containingBlock->getAvailWidth (true); + width = max (availWidth - containingBlock->boxDiffWidth () + - getAbsPosLeft (child, availWidth) + - getAbsPosRight (child, availWidth), + 0); + } else + width = -1; + } else + // TODO Percentage widths must refer to padding area. + child->calcFinalWidth (child->getStyle(), -1, containingBlock, 0, + forceValue, &width); + + if (width != -1) + width = max (width, child->getMinWidth (NULL, forceValue)); + + DBG_OBJ_MSGF ("resize.oofm", 1, "=> %d", width); + DBG_OBJ_LEAVE (); + + return width; +} + +int OutOfFlowMgr::getAvailHeightOfChild (Widget *child, bool forceValue) +{ + // TODO + return -1; +} + void OutOfFlowMgr::getAbsolutelyPositionedSize (Requisition *cbReq, int *width, int *height) { @@ -2307,6 +2346,17 @@ void OutOfFlowMgr::getAbsolutelyPositionedSize (Requisition *cbReq, int *width, *width = *height = 0; } +int OutOfFlowMgr::getAbsPosBorder (style::Length cssValue, int refLength) +{ + if (style::isAbsLength (cssValue)) + return style::absLengthVal (cssValue); + else if (style::isPerLength (cssValue)) + return style::multiplyWithPerLength (refLength, cssValue); + else + // standard value for 'left', 'right', 'top', 'bottom': + return 0; +} + void OutOfFlowMgr::getAbsolutelyPositionedExtremes (Extremes *cbExtr, int *minWidth, int *maxWidth) @@ -2315,48 +2365,56 @@ void OutOfFlowMgr::getAbsolutelyPositionedExtremes (Extremes *cbExtr, *minWidth = *maxWidth = 0; } -void OutOfFlowMgr::ensureAbsolutelyPositionedSizeAndPosition - (AbsolutelyPositioned *abspos) -{ - // TODO - assertNotReached (); -} - -int OutOfFlowMgr::calcValueForAbsolutelyPositioned - (AbsolutelyPositioned *abspos, Length styleLen, int refLen) -{ - assert (styleLen != LENGTH_AUTO); - if (isAbsLength (styleLen)) - return absLengthVal (styleLen); - else if (isPerLength (styleLen)) - return multiplyWithPerLength (refLen, styleLen); - else { - assertNotReached (); - return 0; // compiler happiness - } -} - void OutOfFlowMgr::sizeAllocateAbsolutelyPositioned () { + DBG_OBJ_ENTER0 ("resize.oofm", 0, "sizeAllocateAbsolutelyPositioned"); + for (int i = 0; i < absolutelyPositioned->size(); i++) { Allocation *cbAllocation = getAllocation (containingBlock); - AbsolutelyPositioned *abspos = absolutelyPositioned->get (i); - ensureAbsolutelyPositionedSizeAndPosition (abspos); + Widget *child = absolutelyPositioned->get (i); + + Requisition childRequisition; + child->sizeRequest (&childRequisition); Allocation childAllocation; - childAllocation.x = cbAllocation->x + abspos->xCB; - childAllocation.y = cbAllocation->y + abspos->yCB; - childAllocation.width = abspos->width; - childAllocation.ascent = abspos->height; - childAllocation.descent = 0; // TODO - - abspos->widget->sizeAllocate (&childAllocation); - - printf ("[%p] allocating child %p at: (%d, %d), %d x (%d + %d)\n", - containingBlock, abspos->widget, childAllocation.x, - childAllocation.y, childAllocation.width, childAllocation.ascent, - childAllocation.descent); + + childAllocation.x = + cbAllocation->x + getAbsPosLeft (child, cbAllocation->width); + childAllocation.y = + cbAllocation->y + getAbsPosTop (child, cbAllocation->ascent + + cbAllocation->descent); + // TODO (i) Consider {min|max}-{width|heigt}. (ii) Clarify where + // sizes refer to. (iii) Height is always apportioned to descent + // (ascent is preserved), which makes sense when the children + // are textblocks. (iv) Consider minimal length? + + if (style::isAbsLength (child->getStyle()->width)) + childAllocation.width = style::absLengthVal (child->getStyle()->width); + else if (style::isPerLength (child->getStyle()->width)) + childAllocation.width = + style::multiplyWithPerLength (cbAllocation->width, + child->getStyle()->width); + else + childAllocation.width = childRequisition.width; + + childAllocation.ascent = childRequisition.ascent; + childAllocation.descent = childRequisition.descent; + if (style::isAbsLength (child->getStyle()->height)) { + int height = style::absLengthVal (child->getStyle()->height); + splitHeightPreserveAscent (height, &childAllocation.ascent, + &childAllocation.descent); + } else if (style::isPerLength (child->getStyle()->height)) { + int height = style::multiplyWithPerLength (cbAllocation->ascent + + cbAllocation->descent, + child->getStyle()->height); + splitHeightPreserveAscent (height, &childAllocation.ascent, + &childAllocation.descent); + } + + child->sizeAllocate (&childAllocation); } + + DBG_OBJ_LEAVE (); } } // namespace dw diff --git a/dw/outofflowmgr.hh b/dw/outofflowmgr.hh index b7283815..c5579368 100644 --- a/dw/outofflowmgr.hh +++ b/dw/outofflowmgr.hh @@ -214,18 +214,6 @@ private: inline Textblock *getTextblock () { return (Textblock*)getWidget (); } }; - class AbsolutelyPositioned: public lout::object::Object - { - public: - core::Widget *widget; - int xCB, yCB; // relative to the containing block - int width, height; - bool dirty; - - AbsolutelyPositioned (OutOfFlowMgr *oofm, core::Widget *widget, - Textblock *generatingBlock, int externalIndex); - }; - // These two lists store all floats, in the order in which they are // defined. Only used for iterators. lout::container::typed::Vector<Float> *leftFloatsAll, *rightFloatsAll; @@ -245,7 +233,7 @@ private: lout::container::typed::HashTable<lout::object::TypedPointer <Textblock>, TBInfo> *tbInfosByTextblock; - lout::container::typed::Vector<AbsolutelyPositioned> *absolutelyPositioned; + lout::container::typed::Vector<core::Widget> *absolutelyPositioned; int lastLeftTBIndex, lastRightTBIndex, leftFloatsMark, rightFloatsMark; @@ -331,13 +319,19 @@ private: int *height); void getAbsolutelyPositionedExtremes (core::Extremes *cbExtr, int *minWidth, int *maxWidth); - void ensureAbsolutelyPositionedSizeAndPosition (AbsolutelyPositioned - *abspos); - int calcValueForAbsolutelyPositioned (AbsolutelyPositioned *abspos, - core::style::Length styleLen, - int refLen); void sizeAllocateAbsolutelyPositioned (); + inline int getAbsPosLeft (core::Widget *child, int availWidth) + { return getAbsPosBorder (child->getStyle()->left, availWidth); } + inline int getAbsPosRight (core::Widget *child, int availWidth) + { return getAbsPosBorder (child->getStyle()->right, availWidth); } + inline int getAbsPosTop (core::Widget *child, int availHeight) + { return getAbsPosBorder (child->getStyle()->top, availHeight); } + inline int getAbsPosBottom (core::Widget *child, int availHeight) + { return getAbsPosBorder (child->getStyle()->bottom, availHeight); } + + int getAbsPosBorder (core::style::Length cssValue, int refLength); + static inline bool isWidgetFloat (core::Widget *widget) { return widget->getStyle()->vloat != core::style::FLOAT_NONE; } static inline bool isWidgetAbsolutelyPositioned (core::Widget *widget) @@ -438,6 +432,12 @@ public: int getClearPosition (Textblock *tb); + inline bool dealingWithSizeOfChild (core::Widget *child) + { return isWidgetAbsolutelyPositioned (child); } + + int getAvailWidthOfChild (core::Widget *child, bool forceValue); + int getAvailHeightOfChild (core::Widget *child, bool forceValue); + inline static bool isRefOutOfFlow (int ref) { return ref != -1 && (ref & 1) != 0; } inline static int createRefNormalFlow (int lineNo) { return lineNo << 1; } @@ -456,7 +456,7 @@ public: return rightFloatsAll->get(i - leftFloatsAll->size())->getWidget (); else return absolutelyPositioned->get(i - (leftFloatsAll->size() + - rightFloatsAll->size()))->widget; + rightFloatsAll->size())); } inline bool affectsLeftBorder (core::Widget *widget) { diff --git a/dw/textblock.cc b/dw/textblock.cc index d2fb7857..0bf4b08a 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -708,12 +708,16 @@ int Textblock::getAvailWidthOfChild (Widget *child, bool forceValue) int width = Widget::getAvailWidthOfChild (child, forceValue); - if (forceValue && this == child->getContainer () && - !mustBeWidenedToAvailWidth ()) { - core::Extremes extremes; - getExtremes (&extremes); - if (width > extremes.maxWidth) - width = extremes.maxWidth; + if (outOfFlowMgr && outOfFlowMgr->dealingWithSizeOfChild (child)) + width = outOfFlowMgr->getAvailWidthOfChild (child, forceValue); + else { + if (forceValue && this == child->getContainer () && + !mustBeWidenedToAvailWidth ()) { + core::Extremes extremes; + getExtremes (&extremes); + if (width > extremes.maxWidth) + width = extremes.maxWidth; + } } DBG_OBJ_MSGF ("resize", 1, "=> %d", width); @@ -721,7 +725,13 @@ int Textblock::getAvailWidthOfChild (Widget *child, bool forceValue) return width; } - +int Textblock::getAvailHeightOfChild (core::Widget *child, bool forceValue) +{ + if (outOfFlowMgr && outOfFlowMgr->dealingWithSizeOfChild (child)) + return outOfFlowMgr->getAvailHeightOfChild (child, forceValue); + else + return Widget::getAvailHeightOfChild (child, forceValue); +} void Textblock::containerSizeChangedForChildren () { diff --git a/dw/textblock.hh b/dw/textblock.hh index 69fcd3da..5e8986b3 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -749,7 +749,10 @@ protected: void sizeRequestImpl (core::Requisition *requisition); void getExtremesImpl (core::Extremes *extremes); void sizeAllocateImpl (core::Allocation *allocation); - int getAvailWidthOfChild (Widget *child, bool forceValue); + + int getAvailWidthOfChild (core::Widget *child, bool forceValue); + int getAvailHeightOfChild (core::Widget *child, bool forceValue); + void containerSizeChangedForChildren (); bool affectsSizeChangeContainerChild (Widget *child); bool usesAvailWidth (); diff --git a/dw/widget.hh b/dw/widget.hh index 0f3e2d37..a624eeb2 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -292,8 +292,6 @@ protected: */ virtual void markExtremesChange (int ref); - int getMinWidth (Extremes *extremes, bool forceValue); - virtual int getAvailWidthOfChild (Widget *child, bool forceValue); virtual int getAvailHeightOfChild (Widget *child, bool forceValue); virtual void correctRequisitionOfChild (Widget *child, @@ -441,6 +439,8 @@ public: virtual int applyPerWidth (int containerWidth, style::Length perWidth); virtual int applyPerHeight (int containerHeight, style::Length perHeight); + int getMinWidth (Extremes *extremes, bool forceValue); + virtual bool isBlockLevel (); virtual bool isPossibleContainer (); |