diff options
author | Sebastian Geerken <devnull@localhost> | 2015-06-08 22:18:41 +0200 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2015-06-08 22:18:41 +0200 |
commit | 7c8f69de8bc95c6078ee5fc0b63d263a80f31b44 (patch) | |
tree | b495c1320496cd5ff67c56b6a07d5a79c218455b | |
parent | 826577556fa8b8eedcf1620b4104115d83dbce0b (diff) |
SRDOP: Positions relative to multiple references; design now considers handling conflicts.
-rw-r--r-- | devdoc/dw-size-request-pos.doc | 85 | ||||
-rw-r--r-- | dw/bullet.cc | 6 | ||||
-rw-r--r-- | dw/bullet.hh | 6 | ||||
-rw-r--r-- | dw/image.cc | 6 | ||||
-rw-r--r-- | dw/image.hh | 6 | ||||
-rw-r--r-- | dw/ooffloatsmgr.cc | 13 | ||||
-rw-r--r-- | dw/ooffloatsmgr.hh | 4 | ||||
-rw-r--r-- | dw/oofpositionedmgr.cc | 12 | ||||
-rw-r--r-- | dw/oofpositionedmgr.hh | 5 | ||||
-rw-r--r-- | dw/outofflowmgr.hh | 9 | ||||
-rw-r--r-- | dw/ruler.cc | 6 | ||||
-rw-r--r-- | dw/ruler.hh | 6 | ||||
-rw-r--r-- | dw/table.cc | 6 | ||||
-rw-r--r-- | dw/table.hh | 6 | ||||
-rw-r--r-- | dw/textblock.cc | 170 | ||||
-rw-r--r-- | dw/textblock.hh | 23 | ||||
-rw-r--r-- | dw/textblock_linebreaking.cc | 51 | ||||
-rw-r--r-- | dw/ui.cc | 5 | ||||
-rw-r--r-- | dw/ui.hh | 6 | ||||
-rw-r--r-- | dw/widget.cc | 53 | ||||
-rw-r--r-- | dw/widget.hh | 44 | ||||
-rw-r--r-- | test/dw_simple_container.cc | 6 | ||||
-rw-r--r-- | test/dw_simple_container.hh | 6 |
23 files changed, 363 insertions, 177 deletions
diff --git a/devdoc/dw-size-request-pos.doc b/devdoc/dw-size-request-pos.doc index dc497d00..32cc3089 100644 --- a/devdoc/dw-size-request-pos.doc +++ b/devdoc/dw-size-request-pos.doc @@ -6,6 +6,10 @@ dw-widget-sizes, \ref dw-grows, and **Size requisitions depending on positions** (this document). </div> +<div style="border: 2px solid #ff4040; margin: 1em 0; + padding: 0.5em 1em; background-color: #fff0f0"><b>Info:</b> + May not be up to date, needs a review.</div> + Motivation ========== @@ -23,32 +27,57 @@ General Idea A widget size may depend on the position relative to an anchestor widget. If a widget wants to get the size of a child widget, it should -1. call the new method dw::core::Widget::sizeRequestReference, - which returns NULL, when the child's size does not depend on the - position, or a widget relative to which the child's position must - be calculated; -2. call dw::core::Widget::sizeRequest with the position relative to - this widget. +1. call the new methods dw::core::Widget::numSizeRequestReferences and + dw::core::Widget::sizeRequestReference, which return all widgets + relative to which the child's position must be calculated; +2. call dw::core::Widget::sizeRequest with the positions relative to + these widgets. -The position passed to dw::core::Widget::sizeRequest must be the -position at which this child will be allocated. +All positions passed to dw::core::Widget::sizeRequest must costitute +the position at which this child will be allocated. There are situations where the parent widget is unable to determine -this position before the size is known. An example: a textblock widget -cannot determine the position of an inline widget (like an image, or -an inline block) before the line is finished; on the other hand, -finishing the line depends on knowing the sizes of the inline widgets. - -This may result in a conflict, when the size of an inline widgets -depends on the position. Fortunately, this is not the case in dillo: -the only widget whose size depends on the position is dw::Textblock -(the size will depend on the position within its floats container); but -an inline blocks constitute its own floats container, so that there is -no dependance on a position within another widget. - -Generally, this case should be handled by providing a fallback -strategy. (TODO: How does this look like? The widget is forced to -calculate its size independant of the position?) +these positions before the size is known. An example: a textblock +widget cannot determine the positions of an inline widget (like an +image, or an inline block) before the line is finished; on the other +hand, finishing the line depends on knowing the sizes of the inline +widgets. + +This may result in a conflict, when the size of an inline widget +depends on positions. Generally, the only widget whose size depends on +positions is dw::Textblock (the size will depend on the positions +within its oof container, see \ref dw-out-of-flow), so this conflict +occurs with inline blocks. + +This conflict is handled in different ways: + +1. Fortunately, this case is irrelevat for floats: an inline blocks + constitute its own floats container, so that there is no dependance + on a position within another widget. + +2. For positioned elements, this case is relevant, since an inline + block is in most cases not a container for positioned element. In + this case, a generator will call the methods + dw::oof::OutOfFlowMgr::tellIncompletePosition1 and + dw::oof::OutOfFlowMgr::tellIncompletePosition2, instead of + dw::oof::OutOfFlowMgr::tellPosition and + dw::oof::OutOfFlowMgr::tellPosition2, respectively. (Since this + case is irrelevant for floats, + dw::oof::OOFFloatsMgr::tellIncompletePosition1 and + dw::oof::OOFFloatsMgr::tellIncompletePosition2 are not implemented but + simply abort.) + +(This is not (yet) considered for borders: borders are only relevant +for floats, but conflicts do not occur for floats.) + + +Extremes +-------- +Extremes may depend on the position in an analogue way, see: + +- dw::core::Widget::numGetExtremesReferences, +- dw::core::Widget::getExtremesReference, and +- dw::core::Widget::getExtremes. Resizing -------- @@ -102,4 +131,14 @@ Plan 6. Implement step 3 for positioned elements (affects only dw::oof:OOFPositionedMgr). *INCOMPLETE.* + +Issues +====== + +- Since the signature of dw::core::Widget::sizeRequestImpl changes + quite often during the development of *size requisitions depending + on positions*, a simpler option dw::core::Widget::sizeRequestSimpl + has been added. May be removed again, after the design is stable. + + */ diff --git a/dw/bullet.cc b/dw/bullet.cc index f3ce7a3b..98feb556 100644 --- a/dw/bullet.cc +++ b/dw/bullet.cc @@ -35,16 +35,14 @@ Bullet::~Bullet () DBG_OBJ_DELETE (); } -void Bullet::sizeRequestImpl (core::Requisition *requisition, bool posDefined, - int x, int y) +void Bullet::sizeRequestSimpl (core::Requisition *requisition) { requisition->width = lout::misc::max (getStyle()->font->xHeight * 4 / 5, 1); requisition->ascent = lout::misc::max (getStyle()->font->xHeight, 1); requisition->descent = 0; } -void Bullet::getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y) +void Bullet::getExtremesSimpl (core::Extremes *extremes) { extremes->minWidth = extremes->maxWidth = extremes->adjustmentWidth = extremes->minWidthIntrinsic = extremes->maxWidthIntrinsic = diff --git a/dw/bullet.hh b/dw/bullet.hh index 76ea2553..ac94738e 100644 --- a/dw/bullet.hh +++ b/dw/bullet.hh @@ -14,10 +14,8 @@ namespace dw { class Bullet: public core::Widget { protected: - void sizeRequestImpl (core::Requisition *requisition, bool posDefined, int x, - int y); - void getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y); + void sizeRequestSimpl (core::Requisition *requisition); + void getExtremesSimpl (core::Extremes *extremes); void containerSizeChangedForChildren (); void draw (core::View *view, core::Rectangle *area, core::DrawingContext *context); diff --git a/dw/image.cc b/dw/image.cc index 77d87a61..519b82bb 100644 --- a/dw/image.cc +++ b/dw/image.cc @@ -172,8 +172,7 @@ Image::~Image() DBG_OBJ_DELETE (); } -void Image::sizeRequestImpl (core::Requisition *requisition, bool posDefined, - int x, int y) +void Image::sizeRequestSimpl (core::Requisition *requisition) { DBG_OBJ_ENTER0 ("resize", 0, "sizeRequestImpl"); @@ -238,8 +237,7 @@ void Image::sizeRequestImpl (core::Requisition *requisition, bool posDefined, DBG_OBJ_LEAVE (); } -void Image::getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y) +void Image::getExtremesSimpl (core::Extremes *extremes) { int contentWidth; if (buffer) diff --git a/dw/image.hh b/dw/image.hh index 1de315bd..ae47f307 100644 --- a/dw/image.hh +++ b/dw/image.hh @@ -130,10 +130,8 @@ private: bool isMap; protected: - void sizeRequestImpl (core::Requisition *requisition, bool posDefined, int x, - int y); - void getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y); + void sizeRequestSimpl (core::Requisition *requisition); + void getExtremesSimpl (core::Extremes *extremes); void sizeAllocateImpl (core::Allocation *allocation); void containerSizeChangedForChildren (); diff --git a/dw/ooffloatsmgr.cc b/dw/ooffloatsmgr.cc index 10e72bae..e804138c 100644 --- a/dw/ooffloatsmgr.cc +++ b/dw/ooffloatsmgr.cc @@ -1608,6 +1608,19 @@ void OOFFloatsMgr::tellPosition1 (Widget *widget, int x, int y) void OOFFloatsMgr::tellPosition2 (Widget *widget, int x, int y) { + // Nothing to do. +} + +void OOFFloatsMgr::tellIncompletePosition1 (Widget *generator, Widget *widget, + int x, int y) +{ + assertNotReached (); +} + +void OOFFloatsMgr::tellIncompletePosition2 (Widget *generator, Widget *widget, + int x, int y) +{ + assertNotReached (); } bool OOFFloatsMgr::collidesV (Float *vloat, Float *other, SFVType type, diff --git a/dw/ooffloatsmgr.hh b/dw/ooffloatsmgr.hh index 1a66e2ff..c30ac172 100644 --- a/dw/ooffloatsmgr.hh +++ b/dw/ooffloatsmgr.hh @@ -360,6 +360,10 @@ public: void tellPosition1 (core::Widget *widget, int x, int y); void tellPosition2 (core::Widget *widget, int x, int y); + void tellIncompletePosition1 (core::Widget *generator, core::Widget *widget, + int x, int y); + void tellIncompletePosition2 (core::Widget *generator, core::Widget *widget, + int x, int y); void getSize (core::Requisition *cbReq, int *oofWidth, int *oofHeight); bool containerMustAdjustExtraSpace (); diff --git a/dw/oofpositionedmgr.cc b/dw/oofpositionedmgr.cc index 28852258..1ab7e06e 100644 --- a/dw/oofpositionedmgr.cc +++ b/dw/oofpositionedmgr.cc @@ -270,6 +270,18 @@ void OOFPositionedMgr::tellPosition2 (Widget *widget, int x, int y) DBG_OBJ_LEAVE (); } +void OOFPositionedMgr::tellIncompletePosition1 (Widget *generator, + Widget *widget, int x, int y) +{ + // Nothing to do. +} + +void OOFPositionedMgr::tellIncompletePosition2 (Widget *generator, + Widget *widget, int x, int y) +{ + // TODO +} + bool OOFPositionedMgr::containerMustAdjustExtraSpace () { return true; diff --git a/dw/oofpositionedmgr.hh b/dw/oofpositionedmgr.hh index 4edf11e8..09706235 100644 --- a/dw/oofpositionedmgr.hh +++ b/dw/oofpositionedmgr.hh @@ -101,6 +101,11 @@ public: void tellPosition1 (core::Widget *widget, int x, int y); void tellPosition2 (core::Widget *widget, int x, int y); + void tellIncompletePosition1 (core::Widget *generator, core::Widget *widget, + int x, int y); + void tellIncompletePosition2 (core::Widget *generator, core::Widget *widget, + int x, int y); + bool containerMustAdjustExtraSpace (); diff --git a/dw/outofflowmgr.hh b/dw/outofflowmgr.hh index 6dff2055..88ec349d 100644 --- a/dw/outofflowmgr.hh +++ b/dw/outofflowmgr.hh @@ -55,7 +55,14 @@ public: * tellPosition2. Coordinates are relative to the *container*. */ virtual void tellPosition2 (core::Widget *widget, int x, int y) = 0; - + + virtual void tellIncompletePosition1 (core::Widget *generator, + core::Widget *widget, int x, int y) + = 0; + virtual void tellIncompletePosition2 (core::Widget *generator, + core::Widget *widget, int x, int y) + = 0; + virtual void getSize (core::Requisition *containerReq, int *oofWidth, int *oofHeight) = 0; virtual bool containerMustAdjustExtraSpace ()= 0; diff --git a/dw/ruler.cc b/dw/ruler.cc index 6b3d9bd1..bff43479 100644 --- a/dw/ruler.cc +++ b/dw/ruler.cc @@ -39,16 +39,14 @@ Ruler::~Ruler () DBG_OBJ_DELETE (); } -void Ruler::sizeRequestImpl (core::Requisition *requisition, bool posDefined, - int x, int y) +void Ruler::sizeRequestSimpl (core::Requisition *requisition) { requisition->width = lout::misc::max (getAvailWidth (true), boxDiffWidth ()); requisition->ascent = boxOffsetY (); requisition->descent = boxRestHeight (); } -void Ruler::getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y) +void Ruler::getExtremesSimpl (core::Extremes *extremes) { extremes->minWidth = extremes->maxWidth = boxDiffWidth (); extremes->minWidthIntrinsic = extremes->minWidth; diff --git a/dw/ruler.hh b/dw/ruler.hh index abbabe4c..74323d95 100644 --- a/dw/ruler.hh +++ b/dw/ruler.hh @@ -20,10 +20,8 @@ namespace dw { class Ruler: public RegardingBorder { protected: - void sizeRequestImpl (core::Requisition *requisition, bool posDefined, int x, - int y); - void getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y); + void sizeRequestSimpl (core::Requisition *requisition); + void getExtremesSimpl (core::Extremes *extremes); void containerSizeChangedForChildren (); bool usesAvailWidth (); void draw (core::View *view, core::Rectangle *area, diff --git a/dw/table.cc b/dw/table.cc index e8c8f2d1..4c953e62 100644 --- a/dw/table.cc +++ b/dw/table.cc @@ -103,8 +103,7 @@ Table::~Table() DBG_OBJ_DELETE (); } -void Table::sizeRequestImpl (core::Requisition *requisition, bool posDefined, - int x, int y) +void Table::sizeRequestSimpl (core::Requisition *requisition) { DBG_OBJ_ENTER0 ("resize", 0, "sizeRequestImpl"); @@ -130,8 +129,7 @@ void Table::sizeRequestImpl (core::Requisition *requisition, bool posDefined, DBG_OBJ_LEAVE (); } -void Table::getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y) +void Table::getExtremesSimpl (core::Extremes *extremes) { DBG_OBJ_ENTER0 ("resize", 0, "getExtremesImpl"); diff --git a/dw/table.hh b/dw/table.hh index 0f164c90..3729da71 100644 --- a/dw/table.hh +++ b/dw/table.hh @@ -461,10 +461,8 @@ private: } protected: - void sizeRequestImpl (core::Requisition *requisition, bool posDefined, int x, - int y); - void getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y); + void sizeRequestSimpl (core::Requisition *requisition); + void getExtremesSimpl (core::Extremes *extremes); void sizeAllocateImpl (core::Allocation *allocation); void resizeDrawImpl (); diff --git a/dw/textblock.cc b/dw/textblock.cc index 6102f21e..262554c6 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -217,8 +217,11 @@ Textblock::Textblock (bool limitTextWidth) DBG_OBJ_SET_NUM ("redrawY", redrawY); lastWordDrawn = -1; DBG_OBJ_SET_NUM ("lastWordDrawn", lastWordDrawn); - sizeRequestPosDefined = false; - DBG_OBJ_SET_BOOL ("sizeRequestPosDefined", sizeRequestPosDefined); + + sizeRequestNumPos = 0; + sizeRequestReferences = NULL; + sizeRequestX = sizeRequestY = NULL; + DBG_OBJ_SET_BOOL ("sizeRequestNumPos", sizeRequestNumPos); /* * The initial sizes of lines and words should not be @@ -285,6 +288,13 @@ Textblock::~Textblock () delete words; delete anchors; + if (sizeRequestReferences) + delete[] sizeRequestReferences; + if (sizeRequestX) + delete[] sizeRequestX; + if (sizeRequestY) + delete[] sizeRequestY; + /* Make sure we don't own widgets anymore. Necessary before call of parent class destructor. (???) */ words = NULL; @@ -297,24 +307,32 @@ Textblock::~Textblock () * padding/border/margin. This can be used to align the first lines * of several textblocks in a horizontal line. */ -void Textblock::sizeRequestImpl (core::Requisition *requisition, - bool posDefined, int x, int y) +void Textblock::sizeRequestImpl (core::Requisition *requisition, int numPos, + Widget **references, int *x, int *y) { DBG_OBJ_ENTER0 ("resize", 0, "sizeRequestImpl"); - assert (posDefined || !needsPositionForSize ()); - - sizeRequestPosDefined = true; - if (posDefined) { - sizeRequestX = x; - sizeRequestY = y; - } else { - sizeRequestX = 0; - sizeRequestY = 0; + if (sizeRequestReferences) + delete[] sizeRequestReferences; + if (sizeRequestX) + delete[] sizeRequestX; + if (sizeRequestY) + delete[] sizeRequestY; + + sizeRequestNumPos = numPos; + DBG_OBJ_SET_BOOL ("sizeRequestNumPos", sizeRequestNumPos); + + sizeRequestReferences = new Widget*[numPos]; + sizeRequestX = new int[numPos]; + sizeRequestY = new int[numPos]; + for (int i = 0; i < numPos; i++) { + sizeRequestReferences[i] = references[i]; + sizeRequestX[i] = x[i]; + sizeRequestY[i] = y[i]; + DBG_OBJ_ARRSET_PTR ("sizeRequestReferences", i, sizeRequestReferences[i]); + DBG_OBJ_ARRSET_NUM ("sizeRequestX", i, sizeRequestX[i]); + DBG_OBJ_ARRSET_NUM ("sizeRequestY", i, sizeRequestY[i]); } - DBG_OBJ_SET_BOOL ("sizeRequestPosDefined", sizeRequestPosDefined); - DBG_OBJ_SET_NUM ("sizeRequestX", sizeRequestX); - DBG_OBJ_SET_NUM ("sizeRequestY", sizeRequestY); int newLineBreakWidth = getAvailWidth (true); if (newLineBreakWidth != lineBreakWidth) { @@ -399,14 +417,14 @@ void Textblock::sizeRequestImpl (core::Requisition *requisition, DBG_OBJ_LEAVE (); } -core::Widget *Textblock::sizeRequestReference () +int Textblock::numSizeRequestReferences () { - return needsPositionForSize() ? oofContainer[OOFM_FLOATS] : NULL; + return 0; } -bool Textblock::needsPositionForSize () +core::Widget *Textblock::sizeRequestReference (int index) { - return oofContainer[OOFM_FLOATS] != this; + return NULL; } int Textblock::calcVerticalBorder (int widgetPadding, int widgetBorder, @@ -446,8 +464,7 @@ void Textblock::getWordExtremes (Word *word, core::Extremes *extremes) word->size.width; } -void Textblock::getExtremesImpl (core::Extremes *extremes, bool posDefined, - int x, int y) +void Textblock::getExtremesSimpl (core::Extremes *extremes) { DBG_OBJ_ENTER0 ("resize", 0, "getExtremesImpl"); @@ -1160,9 +1177,9 @@ core::Iterator *Textblock::iterator (core::Content::Type mask, bool atEnd) /* * Draw the decorations on a word. */ -void Textblock::decorateText(core::View *view, core::style::Style *style, - core::style::Color::Shading shading, - int x, int yBase, int width) +void Textblock::decorateText (core::View *view, core::style::Style *style, + core::style::Color::Shading shading, + int x, int yBase, int width) { int y, height; @@ -2256,52 +2273,89 @@ bool Textblock::calcSizeOfWidgetInFlow (int wordIndex, Widget *widget, DBG_OBJ_ENTER ("resize", 0, "calcSizeOfWidgetInFlow", "%d, %p, ...", wordIndex, widget); - int lastWord = lines->empty () ? -1 : lines->getLastRef()->lastWord; - assert (wordIndex > lastWord); bool result; - Widget *reference = widget->sizeRequestReference (); - - if (reference == NULL) { - widget->sizeRequest (size); - result = false; - } else { - assert (getParent () == NULL || sizeRequestPosDefined); - assert - (wordIndex == 0 || - words->getRef(wordIndex - 1)->content.type == core::Content::BREAK); - assert (reference == oofContainer[OOFM_FLOATS]); - - // The following assertion is always the case in dillo, and - // plausible (since floats are the reason why the size depends - // on the position); and it simplifies the calculation of x - // below. - assert (widget->instanceOf (RegardingBorder::CLASS_ID) && - !isOOFContainer (widget, OOFM_FLOATS)); - - int xRef, yRef; - if (getParent () == NULL) - xRef = yRef = 0; - else { - xRef = sizeRequestX; - yRef = sizeRequestY; - } - - int x = xRef + boxOffsetX () + leftInnerPadding + if ((wordIndex == 0 || + words->getRef(wordIndex - 1)->content.type == core::Content::BREAK) && + (widget->getStyle()->display == core::style::DISPLAY_BLOCK || + widget->getStyle()->display == core::style::DISPLAY_LIST_ITEM || + widget->getStyle()->display == core::style::DISPLAY_TABLE)) { + // pass positions + int lastWord = lines->empty () ? -1 : lines->getLastRef()->lastWord; + assert (wordIndex > lastWord); + + int xRel = boxOffsetX () + leftInnerPadding + (lines->size () == 0 ? line1OffsetEff : 0); int lastMargin, yLine = yOffsetOfLineToBeCreated (&lastMargin); - int y = yRef + yLine - lastMargin + int yRel = yLine - lastMargin + max (lastMargin, widget->getStyle()->margin.top); - - widget->sizeRequest (size, true, x, y); + int numPos = 0; + int numChildReferences = widget->numSizeRequestReferences (); + Widget **references = new Widget*[numChildReferences]; + int *x = new int[numChildReferences]; + int *y = new int[numChildReferences]; + + for (int i = 0; i < numChildReferences; i++) { + Widget *childReference = widget->sizeRequestReference (i); + if (childReference == this) { + references[numPos] = childReference; + x[numPos] = xRel; + y[numPos] = yRel; + numPos++; + } else { + for (int j = 0; j < sizeRequestNumPos; j++) { + if (childReference == sizeRequestReferences[j]) { + references[numPos] = childReference; + x[numPos] = sizeRequestX[j] + xRel; + y[numPos] = sizeRequestY[j] + yRel; + numPos++; + } + } + } + } + + widget->sizeRequest (size, numPos, references, x, y); + + delete references; + delete x; + delete y; + result = true; + } else { + // do not pass positions (inline elements etc) + widget->sizeRequest (size); + result = false; } DBG_OBJ_LEAVE_VAL ("%s", boolToStr (result)); return result; } +bool Textblock::findSizeRequestReference (Widget *reference, int *xRef, + int *yRef) +{ + if (reference == this) { + if (xRef) + *xRef = 0; + if (yRef) + *yRef = 0; + return true; + } else { + for (int i = 0; i < sizeRequestNumPos; i++) { + if (reference == sizeRequestReferences[i]) { + if (xRef) + *xRef = sizeRequestX[i]; + if (yRef) + *yRef = sizeRequestY[i]; + return true; + } + } + + return false; + } +} + /** * Add a word (without hyphens) to the page structure. */ diff --git a/dw/textblock.hh b/dw/textblock.hh index 907ab4b4..3decda6d 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -576,10 +576,11 @@ protected: int redrawY; int lastWordDrawn; - bool sizeRequestPosDefined; - int sizeRequestX, sizeRequestY; + int sizeRequestNumPos; + Widget **sizeRequestReferences; + int *sizeRequestX, *sizeRequestY; - /* This value is (currently) set by setAscent(). */ + /* This value is currently) set by setAscent(). */ int lineBreakWidth; int wrapRefLines, wrapRefParagraphs; /* 0-based. Important: Both @@ -618,7 +619,6 @@ protected: int hoverLink; /* The link under the mouse pointer */ void queueDrawRange (int index1, int index2); - bool needsPositionForSize (); int calcVerticalBorder (int widgetPadding, int widgetBorder, int widgetMargin, int lineBorderTotal, int lineMarginTotal); @@ -682,6 +682,11 @@ protected: core::Requisition *size, bool isStart, bool isEnd); bool calcSizeOfWidgetInFlow (int wordIndex, Widget *widget, core::Requisition *size); + bool findSizeRequestReference (Widget *reference, int *xRef = NULL, + int *yRef = NULL); + bool findSizeRequestReference (int oofmIndex, int *xRef = NULL, + int *yRef = NULL) + { return findSizeRequestReference (oofContainer[oofmIndex], xRef, yRef); } /** * Of nested text blocks, only the most inner one must regard the @@ -815,11 +820,11 @@ protected: Widget *getWidgetAtPointLevel (int x, int y, int level, core::GettingWidgetAtPointContext *context); - void sizeRequestImpl (core::Requisition *requisition, bool posDefined, int x, - int y); - Widget *sizeRequestReference (); - void getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y); + void sizeRequestImpl (core::Requisition *requisition, int numPos, + Widget **references, int *x, int *y); + int numSizeRequestReferences (); + Widget *sizeRequestReference (int index); + void getExtremesSimpl (core::Extremes *extremes); void sizeAllocateImpl (core::Allocation *allocation); void calcExtraSpaceImpl (); diff --git a/dw/textblock_linebreaking.cc b/dw/textblock_linebreaking.cc index 31fcb833..03933830 100644 --- a/dw/textblock_linebreaking.cc +++ b/dw/textblock_linebreaking.cc @@ -463,16 +463,19 @@ Textblock::Line *Textblock::addLine (int firstWord, int lastWord, if (word->content.type == core::Content::WIDGET_OOF_REF) { Widget *widget = word->content.widget; - oof::OutOfFlowMgr *oofm = - searchOutOfFlowMgr (getWidgetOOFIndex (widget)); + int oofmIndex = getWidgetOOFIndex (widget); + oof::OutOfFlowMgr *oofm = searchOutOfFlowMgr (oofmIndex); // See also Textblock::sizeAllocate, and notes there about // vertical alignment. Calculating the vertical position // should probably be centralized. if (oofm) { - assert (sizeRequestPosDefined); - oofm->tellPosition2 (widget, sizeRequestX + xWidget, - sizeRequestY + yLine + (line->borderAscent - - word->size.ascent)); + int xRel = xWidget; + int yRel = yLine + (line->borderAscent - word->size.ascent); + int xRef, yRef; + if (findSizeRequestReference (oofmIndex, &xRef, &yRef)) + oofm->tellPosition2 (widget, xRef + xRel, yRef + yRel); + else + oofm->tellIncompletePosition2 (widget, this, xRel, yRel); } } @@ -757,12 +760,14 @@ int Textblock::wrapWordInFlow (int wordIndex, bool wrapAll) lastFloatPos = newFloatPos; Widget *widget = words->getRef(lastFloatPos)->content.widget; - oof::OutOfFlowMgr *oofm = - searchOutOfFlowMgr (getWidgetOOFIndex (widget)); + int oofmIndex = getWidgetOOFIndex (widget); + oof::OutOfFlowMgr *oofm = searchOutOfFlowMgr (oofmIndex); if (oofm && oofm->mayAffectBordersAtAll ()) { - assert (sizeRequestPosDefined); - oofm->tellPosition1 (widget, sizeRequestX + boxOffsetX (), - sizeRequestY + yNewLine); + int xRel = boxOffsetX (), yRel = yNewLine, xRef, yRef; + if (findSizeRequestReference (oofmIndex, &xRef, &yRef)) + oofm->tellPosition1 (widget, xRef + xRel, yRef + yRel); + else + oofm->tellIncompletePosition1 (widget, this, xRel, yRel); } balanceBreakPosAndHeight (wordIndex, firstIndex, &searchUntil, @@ -852,16 +857,19 @@ int Textblock::wrapWordOofRef (int wordIndex, bool wrapAll) // Floats, which affect either border, are handled in wrapWordInFlow; this // is rather for positioned elements (but only for completeness: // tellPosition1 is not implemented for positioned elements). - oof::OutOfFlowMgr *oofm = searchOutOfFlowMgr (getWidgetOOFIndex (widget)); + int oofmIndex = getWidgetOOFIndex (widget); + oof::OutOfFlowMgr *oofm = searchOutOfFlowMgr (oofmIndex); DBG_OBJ_MSGF ("construct.word", 1, "parentRef = %d, oofm = %p", widget->parentRef, oofm); if (oofm && !oofm->mayAffectBordersAtAll ()) { // TODO Again, "x" is not correct (see above). - assert (sizeRequestPosDefined); - oofm->tellPosition1 (widget, sizeRequestX + boxOffsetX (), - sizeRequestY + yNewLine); + int xRel = boxOffsetX (), yRel = yNewLine, xRef, yRef; + if (findSizeRequestReference (oofmIndex, &xRef, &yRef)) + oofm->tellPosition1 (widget, xRef + xRel, yRef + yRel); + else + oofm->tellIncompletePosition1 (widget, this, xRel, yRel); } - + DBG_OBJ_LEAVE (); return 0; // Words list not changed. @@ -2014,19 +2022,19 @@ void Textblock::calcBorders (int lastOofRef, int height) bool oofmDefined = false; for (int i = 0; i < NUM_OOFM && !oofmDefined; i++) - if (searchOutOfFlowMgr(i)) + if (findSizeRequestReference (i)) oofmDefined = true; if (oofmDefined) { int firstWordOfLine = lines->size() > 0 ? lines->getLastRef()->lastWord + 1 : 0; int effOofRef = misc::max (lastOofRef, firstWordOfLine - 1); - assert (sizeRequestPosDefined); - int y = sizeRequestY + yOffsetOfLineToBeCreated (); + int yRel = yOffsetOfLineToBeCreated (), yRef; for (int i = 0; i < NUM_OOFM; i++) { - oof::OutOfFlowMgr *oofm = searchOutOfFlowMgr(i); - if (oofm) { + oof::OutOfFlowMgr *oofm; + if ((oofm = searchOutOfFlowMgr (i)) && + findSizeRequestReference (i, NULL, &yRef)) { // Consider the example: // // <div> @@ -2059,6 +2067,7 @@ void Textblock::calcBorders (int lastOofRef, int height) // than the first word of the new line, so a solution is to use // the maximum of both. + int y = yRef + yRel; bool thisHasLeft, thisHasRight; thisHasLeft = oofm->hasFloatLeft (this, y, height, this, effOofRef); @@ -48,13 +48,12 @@ Embed::~Embed() DBG_OBJ_DELETE (); } -void Embed::sizeRequestImpl (Requisition *requisition, bool posDefined, int x, - int y) +void Embed::sizeRequestSimpl (Requisition *requisition) { resource->sizeRequest (requisition); } -void Embed::getExtremesImpl (Extremes *extremes, bool posDefined, int x, int y) +void Embed::getExtremesSimpl (Extremes *extremes) { resource->getExtremes (extremes); correctExtremes (extremes, false); @@ -228,10 +228,8 @@ private: Resource *resource; protected: - void sizeRequestImpl (Requisition *requisition, bool posDefined, int x, - int y); - void getExtremesImpl (Extremes *extremes, bool posDefined, int x, - int y); + void sizeRequestSimpl (Requisition *requisition); + void getExtremesSimpl (Extremes *extremes); void sizeAllocateImpl (Allocation *allocation); int getAvailWidthOfChild (Widget *child, bool forceValue); diff --git a/dw/widget.cc b/dw/widget.cc index 18555fa4..b3d47efb 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -567,8 +567,8 @@ bool Widget::usesAvailHeight () * \brief This method is a wrapper for Widget::sizeRequestImpl(); it calls * the latter only when needed. */ -void Widget::sizeRequest (Requisition *requisition, bool posDefined, int x, - int y) +void Widget::sizeRequest (Requisition *requisition, int numPos, + Widget **references, int *x, int *y) { assert (!queueResizeEntered ()); @@ -588,7 +588,7 @@ void Widget::sizeRequest (Requisition *requisition, bool posDefined, int x, if (needsResize ()) { calcExtraSpace (); /** \todo Check requisition == &(this->requisition) and do what? */ - sizeRequestImpl (requisition, posDefined, x, y); + sizeRequestImpl (requisition, numPos, references, x, y); this->requisition = *requisition; unsetFlags (NEEDS_RESIZE); @@ -988,7 +988,8 @@ int Widget::calcHeight (style::Length cssValue, bool usePercentage, /** * \brief Wrapper for Widget::getExtremesImpl(). */ -void Widget::getExtremes (Extremes *extremes, bool posDefined, int x, int y) +void Widget::getExtremes (Extremes *extremes, int numPos, Widget **references, + int *x, int *y) { assert (!queueResizeEntered ()); @@ -1011,7 +1012,7 @@ void Widget::getExtremes (Extremes *extremes, bool posDefined, int x, int y) // For backward compatibility (part 1/2): extremes->minWidthIntrinsic = extremes->maxWidthIntrinsic = -1; - getExtremesImpl (extremes, posDefined, x, y); + getExtremesImpl (extremes, numPos, references, x, y); // For backward compatibility (part 2/2): if (extremes->minWidthIntrinsic == -1) @@ -1054,13 +1055,25 @@ void Widget::calcExtraSpace () DBG_OBJ_SET_NUM ("extraSpace.right", extraSpace.right); } -Widget *Widget::sizeRequestReference () +int Widget::numSizeRequestReferences () { + return 0; +} + +Widget *Widget::sizeRequestReference (int index) +{ + misc::assertNotReached (); return NULL; } -Widget *Widget::getExtremesReference () +int Widget::numGetExtremesReferences () { + return 0; +} + +Widget *Widget::getExtremesReference (int index) +{ + misc::assertNotReached (); return NULL; } @@ -1543,6 +1556,32 @@ void Widget::getPaddingArea (int *xPad, int *yPad, int *widthPad, *heightPad -= style->borderWidth.top + style->borderWidth.bottom; } +void Widget::sizeRequestImpl (Requisition *requisition, int numPos, + Widget **references, int *x, int *y) +{ + // Use the simple variant. + sizeRequestSimpl (requisition); +} + +void Widget::sizeRequestSimpl (Requisition *requisition) +{ + // Either variant should be implemented. + misc::assertNotReached (); +} + +void Widget::getExtremesImpl (Extremes *extremes, int numPos, + Widget **references, int *x, int *y) +{ + // Use the simple variant. + getExtremesSimpl (extremes); +} + +void Widget::getExtremesSimpl (Extremes *extremes) +{ + // Either variant should be implemented. + misc::assertNotReached (); +} + void Widget::sizeAllocateImpl (Allocation *allocation) { } diff --git a/dw/widget.hh b/dw/widget.hh index ed7eae2b..5db9aa33 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -280,14 +280,26 @@ protected: /** * \brief See \ref dw-widget-sizes. */ - virtual void sizeRequestImpl (Requisition *requisition, bool posDefined, - int x, int y) = 0; - + virtual void sizeRequestImpl (Requisition *requisition, int numPos, + Widget **references, int *x, int *y); + + /** + * \brief Simple variant, to be implemented by widgets with sizes + * not depending on positions. + */ + virtual void sizeRequestSimpl (Requisition *requisition); + /** * \brief See \ref dw-widget-sizes. */ - virtual void getExtremesImpl (Extremes *extremes, bool posDefined, int x, - int y) = 0; + virtual void getExtremesImpl (Extremes *extremes, int numPos, + Widget **references, int *x, int *y); + + /** + * \brief Simple variant, to be implemented by widgets with + * extremes not depending on positions. + */ + virtual void getExtremesSimpl (Extremes *extremes); virtual void calcExtraSpaceImpl (); @@ -444,21 +456,31 @@ public: inline int boxRestHeight () { return extraSpace.bottom + getStyle()->boxRestHeight (); } inline int boxDiffHeight () { return boxOffsetY () + boxRestHeight (); } + + /** + * \brief See \ref dw-widget-sizes (or \ref dw-size-request-pos). + */ + virtual int numSizeRequestReferences (); + + /** + * \brief See \ref dw-widget-sizes (or \ref dw-size-request-pos). + */ + virtual Widget *sizeRequestReference (int index); /** * \brief See \ref dw-widget-sizes (or \ref dw-size-request-pos). */ - virtual Widget *sizeRequestReference (); + virtual int numGetExtremesReferences (); /** * \brief See \ref dw-widget-sizes (or \ref dw-size-request-pos). */ - virtual Widget *getExtremesReference (); + virtual Widget *getExtremesReference (int index); - void sizeRequest (Requisition *requisition, bool posDefined = false, - int x = 0, int y = 0); - void getExtremes (Extremes *extremes, bool posDefined = false, int x = 0, - int y = 0); + void sizeRequest (Requisition *requisition, int numPos = 0, + Widget **references = NULL, int *x = NULL, int *y = NULL); + void getExtremes (Extremes *extremes, int numPos = 0, + Widget **references = NULL, int *x = NULL, int *y = NULL); void sizeAllocate (Allocation *allocation); void calcExtraSpace (); diff --git a/test/dw_simple_container.cc b/test/dw_simple_container.cc index 26d030a3..923642b1 100644 --- a/test/dw_simple_container.cc +++ b/test/dw_simple_container.cc @@ -160,8 +160,7 @@ SimpleContainer::~SimpleContainer () delete child; } -void SimpleContainer::sizeRequestImpl (Requisition *requisition, - bool posDefined, int x, int y) +void SimpleContainer::sizeRequestSimpl (Requisition *requisition) { Requisition childReq; if (child) @@ -177,8 +176,7 @@ void SimpleContainer::sizeRequestImpl (Requisition *requisition, } -void SimpleContainer::getExtremesImpl (Extremes *extremes, bool posDefined, - int x, int y) +void SimpleContainer::getExtremesSimpl (Extremes *extremes) { Extremes childExtr; if (child) diff --git a/test/dw_simple_container.hh b/test/dw_simple_container.hh index 10c4b712..bd40b41e 100644 --- a/test/dw_simple_container.hh +++ b/test/dw_simple_container.hh @@ -34,10 +34,8 @@ private: Widget *child; protected: - void sizeRequestImpl (core::Requisition *requisition, bool posDefined, int x, - int y); - void getExtremesImpl (core::Extremes *extremes, bool posDefined, int x, - int y); + void sizeRequestSimpl (core::Requisition *requisition); + void getExtremesSimpl (core::Extremes *extremes); void sizeAllocateImpl (core::Allocation *allocation); public: |