summaryrefslogtreecommitdiff
path: root/dw/oofpositionedmgr.cc
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2014-09-01 00:30:01 +0200
committerSebastian Geerken <devnull@localhost>2014-09-01 00:30:01 +0200
commita2cf34555c64fa87bd146071cf46bd381c695761 (patch)
treea49d40dd73dd486d0f0111e28dd7a7189ed60970 /dw/oofpositionedmgr.cc
parent9430132423d99689de9c02db79df60fd1b4a5703 (diff)
Many changes: split up OutOfFlowMgr for floats, and absolutely and fixedly positioned elements; also with different containing blocks.
Diffstat (limited to 'dw/oofpositionedmgr.cc')
-rw-r--r--dw/oofpositionedmgr.cc428
1 files changed, 428 insertions, 0 deletions
diff --git a/dw/oofpositionedmgr.cc b/dw/oofpositionedmgr.cc
new file mode 100644
index 00000000..590b8545
--- /dev/null
+++ b/dw/oofpositionedmgr.cc
@@ -0,0 +1,428 @@
+/*
+ * Dillo Widget
+ *
+ * Copyright 2013-2014 Sebastian Geerken <sgeerken@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "oofpositionedmgr.hh"
+#include "textblock.hh"
+#include "../lout/debug.hh"
+
+using namespace lout::object;
+using namespace lout::container::typed;
+using namespace lout::misc;
+using namespace dw::core;
+using namespace dw::core::style;
+
+namespace dw {
+
+OOFPositionedMgr::OOFPositionedMgr (Textblock *containingBlock)
+{
+ DBG_OBJ_CREATE ("dw::OOFPositionedMgr");
+
+ this->containingBlock = (Textblock*)containingBlock;
+ children = new Vector<Widget> (1, false);
+ DBG_OBJ_SET_NUM ("children.size", children->size());
+}
+
+OOFPositionedMgr::~OOFPositionedMgr ()
+{
+ delete children;
+
+ DBG_OBJ_DELETE ();
+}
+
+void OOFPositionedMgr::sizeAllocateStart (Textblock *caller,
+ Allocation *allocation)
+{
+ containingBlockAllocation = *allocation;
+}
+
+void OOFPositionedMgr::sizeAllocateEnd (Textblock *caller)
+{
+ DBG_OBJ_ENTER ("resize.oofm", 0, "sizeAllocateEnd", "%p", caller);
+
+ if (caller == containingBlock) {
+ sizeAllocateChildren ();
+
+ bool sizeChanged = doChildrenExceedCB ();
+ bool extremesChanged = haveExtremesChanged ();
+ if (sizeChanged || extremesChanged)
+ containingBlock->oofSizeChanged (extremesChanged);
+ }
+
+ DBG_OBJ_LEAVE ();
+}
+
+
+void OOFPositionedMgr::sizeAllocateChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize.oofm", 0, "sizeAllocateAbsolutelyPositioned");
+
+ //int refWidth = containingBlock->getAvailWidth (true);
+ //int refHeight = containingBlock->getAvailHeight (true);
+ int refWidth = containingBlockAllocation.width;
+ int refHeight =
+ containingBlockAllocation.ascent + containingBlockAllocation.descent;
+
+ for (int i = 0; i < children->size(); i++) {
+ Widget *child = children->get (i);
+
+ Requisition childRequisition;
+ child->sizeRequest (&childRequisition);
+
+ Allocation childAllocation;
+
+ childAllocation.x =
+ containingBlockAllocation.x + getAbsPosLeft (child, refWidth);
+ childAllocation.y =
+ containingBlockAllocation.y + getAbsPosTop (child, refHeight);
+ // 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 (refWidth, 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 (refHeight,
+ child->getStyle()->height);
+ splitHeightPreserveAscent (height, &childAllocation.ascent,
+ &childAllocation.descent);
+ }
+
+ child->sizeAllocate (&childAllocation);
+ }
+
+ DBG_OBJ_LEAVE ();
+}
+
+void OOFPositionedMgr::containerSizeChangedForChildren ()
+{
+ DBG_OBJ_ENTER0 ("resize", 0, "containerSizeChangedForChildren");
+
+ for (int i = 0; i < children->size(); i++)
+ children->get(i)->containerSizeChanged ();
+
+ DBG_OBJ_LEAVE ();
+}
+
+bool OOFPositionedMgr::doChildrenExceedCB ()
+{
+#if 0
+ DBG_OBJ_ENTER ("resize.oofm", 0, "doFloatsExceedCB", "%s",
+ side == LEFT ? "LEFT" : "RIGHT");
+
+ // This method is called to determine whether the *requisition* of
+ // the CB must be recalculated. So, we check the float allocations
+ // against the *requisition* of the CB, which may (e. g. within
+ // tables) differ from the new allocation. (Generally, a widget may
+ // allocated at a different size.)
+ Requisition cbReq;
+ containingBlock->sizeRequest (&cbReq);
+
+ for (int i = 0; i < children->size () && !exceeds; i++) {
+ Widget *child = children->get (i);
+ Allocation *childAlloc = child->getAllocation ();
+ DBG_OBJ_MSGF ("resize.oofm", 2,
+ "Does childAlloc = (%d, %d, %d * %d) exceed CBA = "
+ "(%d, %d, %d * %d)?",
+ childAlloc->x, childAlloc->y, childAlloc->width,
+ childAlloc->ascent + childAlloc->descent,
+ containingBlockAllocation.x, containingBlockAllocation.y,
+ cbReq.width, cbReq.ascent + cbReq.descent);
+ if (childAlloc->x + childAlloc->width
+ > containingBlockAllocation.x + cbReq.width ||
+ childAlloc->y + childAlloc->ascent + childAlloc->descent
+ > containingBlockAllocation.y + cbReq.ascent + cbReq.descent) {
+ exceeds = true;
+ DBG_OBJ_MSG ("resize.oofm", 2, "Yes.");
+ } else
+ DBG_OBJ_MSG ("resize.oofm", 2, "No.");
+ }
+
+ DBG_OBJ_MSGF ("resize.oofm", 1, "=> %s", exceeds ? "true" : "false");
+ DBG_OBJ_LEAVE ();
+
+ return exceeds;
+#endif
+
+ return false;
+}
+
+bool OOFPositionedMgr::haveExtremesChanged ()
+{
+ // TODO Something to do?
+ return false;
+}
+
+
+void OOFPositionedMgr::draw (View *view, Rectangle *area)
+{
+ DBG_OBJ_ENTER ("draw", 0, "draw", "%d, %d, %d * %d",
+ area->x, area->y, area->width, area->height);
+
+ for (int i = 0; i < children->size(); i++) {
+ Widget *child = children->get(i);
+ Rectangle childArea;
+ if (child->intersects (area, &childArea))
+ child->draw (view, &childArea);
+ }
+
+ DBG_OBJ_LEAVE ();
+}
+
+
+void OOFPositionedMgr::addWidgetInFlow (Textblock *textblock,
+ Textblock *parentBlock, int externalIndex)
+{
+}
+
+int OOFPositionedMgr::addWidgetOOF (Widget *widget, Textblock *generatingBlock,
+ int externalIndex)
+{
+ DBG_OBJ_ENTER ("construct.oofm", 0, "addWidgetOOF", "%p, %p, %d",
+ widget, generatingBlock, externalIndex);
+
+ children->put (widget);
+ int subRef = children->size() - 1;
+ DBG_OBJ_SET_NUM ("children.size", children->size());
+ DBG_OBJ_ARRSET_PTR ("children", children->size() - 1, widget);
+
+ DBG_OBJ_MSGF ("construct.oofm", 1, "=> %d", subRef);
+ DBG_OBJ_LEAVE ();
+ return subRef;
+}
+
+void OOFPositionedMgr::moveExternalIndices (Textblock *generatingBlock,
+ int oldStartIndex, int diff)
+{
+}
+
+void OOFPositionedMgr::markSizeChange (int ref)
+{
+}
+
+
+void OOFPositionedMgr::markExtremesChange (int ref)
+{
+}
+
+Widget *OOFPositionedMgr::getWidgetAtPoint (int x, int y, int level)
+{
+ for (int i = 0; i < children->size(); i++) {
+ Widget *child = children->get(i);
+ if (child->wasAllocated ()) {
+ Widget *childAtPoint = child->getWidgetAtPoint (x, y, level + 1);
+ if (childAtPoint)
+ return childAtPoint;
+ }
+ }
+
+ return NULL;
+}
+
+void OOFPositionedMgr::tellPosition (Widget *widget, int yReq)
+{
+}
+
+void OOFPositionedMgr::getSize (Requisition *cbReq, int *oofWidth,
+ int *oofHeight)
+{
+ DBG_OBJ_ENTER0 ("resize.oofm", 0, "getSize");
+
+ // TODO
+ *oofWidth = *oofHeight = 0;
+
+ DBG_OBJ_LEAVE ();
+}
+
+void OOFPositionedMgr::getExtremes (Extremes *cbExtr, int *oofMinWidth,
+ int *oofMaxWidth)
+{
+ DBG_OBJ_ENTER ("resize.oofm", 0, "getExtremes", "(%d / %d), ...",
+ cbExtr->minWidth, cbExtr->maxWidth);
+
+ // TODO Something to do?
+ *oofMinWidth = *oofMaxWidth = 0;
+
+ DBG_OBJ_LEAVE ();
+}
+
+
+int OOFPositionedMgr::getLeftBorder (Textblock *textblock, int y, int h,
+ Textblock *lastGB, int lastExtIndex)
+{
+ return 0;
+}
+
+int OOFPositionedMgr::getRightBorder (Textblock *textblock, int y, int h,
+ Textblock *lastGB, int lastExtIndex)
+{
+ return 0;
+}
+
+bool OOFPositionedMgr::hasFloatLeft (Textblock *textblock, int y, int h,
+ Textblock *lastGB, int lastExtIndex)
+{
+ return false;
+}
+
+bool OOFPositionedMgr::hasFloatRight (Textblock *textblock, int y, int h,
+ Textblock *lastGB, int lastExtIndex)
+{
+ return false;
+}
+
+
+int OOFPositionedMgr::getLeftFloatHeight (Textblock *textblock, int y, int h,
+ Textblock *lastGB, int lastExtIndex)
+{
+ return 0;
+}
+
+int OOFPositionedMgr::getRightFloatHeight (Textblock *textblock, int y, int h,
+ Textblock *lastGB, int lastExtIndex)
+{
+ return 0;
+}
+
+int OOFPositionedMgr::getClearPosition (Textblock *textblock)
+{
+ return 0;
+}
+
+bool OOFPositionedMgr::affectsLeftBorder (Widget *widget)
+{
+ return false;
+}
+
+bool OOFPositionedMgr::affectsRightBorder (Widget *widget)
+{
+ return false;
+}
+
+bool OOFPositionedMgr::dealingWithSizeOfChild (Widget *child)
+{
+ return true;
+}
+
+int OOFPositionedMgr::getAvailWidthOfChild (Widget *child, bool forceValue)
+{
+ DBG_OBJ_ENTER ("resize.oofm", 0,
+ "OOFPositionedMgr/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 OOFPositionedMgr::getAvailHeightOfChild (Widget *child, bool forceValue)
+{
+ // TODO FF shows a bit different priority for heights than for
+ // widths, in case of over-determined values.
+
+ DBG_OBJ_ENTER ("resize.oofm", 0,
+ "OOFPositionedMgr/getAvailHeightOfChild", "%p, %s",
+ child, forceValue ? "true" : "false");
+
+ int height;
+
+ if (child->getStyle()->height == style::LENGTH_AUTO &&
+ child->getStyle()->minHeight == style::LENGTH_AUTO &&
+ child->getStyle()->maxHeight == style::LENGTH_AUTO) {
+ // TODO This should (perhaps?) only used when 'height' is undefined.
+ // TODO Is "boxDiffHeight()" correct here?
+ DBG_OBJ_MSG ("resize.oofm", 1, "no specification");
+ if (forceValue) {
+ int availHeight = containingBlock->getAvailHeight (true);
+ height = max (availHeight - containingBlock->boxDiffHeight ()
+ - getAbsPosTop (child, availHeight)
+ - getAbsPosBottom (child, availHeight),
+ 0);
+ } else
+ height = -1;
+ } else
+ // TODO Percentage heights must refer to padding area.
+ height = child->calcHeight (child->getStyle()->height, true, -1,
+ containingBlock, forceValue);
+
+ DBG_OBJ_MSGF ("resize.oofm", 1, "=> %d", height);
+ DBG_OBJ_LEAVE ();
+
+ return height;
+}
+
+int OOFPositionedMgr::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;
+}
+
+int OOFPositionedMgr::getNumWidgets ()
+{
+ return children->size();
+}
+
+Widget *OOFPositionedMgr::getWidget (int i)
+{
+ return children->get (i);
+}
+
+} // namespace dw