aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/dw-widget-sizes.doc1
-rw-r--r--dw/layout.cc27
-rw-r--r--dw/layout.hh1
-rw-r--r--dw/outofflowmgr.cc94
-rw-r--r--dw/outofflowmgr.hh5
-rw-r--r--dw/table.cc4
-rw-r--r--dw/table.hh2
-rw-r--r--dw/textblock.cc8
-rw-r--r--dw/ui.cc2
-rw-r--r--dw/widget.cc48
-rw-r--r--dw/widget.hh30
11 files changed, 166 insertions, 56 deletions
diff --git a/doc/dw-widget-sizes.doc b/doc/dw-widget-sizes.doc
index a4675c8a..a90749d9 100644
--- a/doc/dw-widget-sizes.doc
+++ b/doc/dw-widget-sizes.doc
@@ -222,6 +222,7 @@ The rules in detail:
limitations. It has to be ensured that no endless recursion is
caused, e. g. by calling dw::core::Widget::queueResize for a
child. (But this is not the only case.) See below for details.
+ (**Update:** I'd rather like to leave this forbidden.)
The facts that dw::core::Widget::queueResize can be called within
other methods, leads to following guidelines:
diff --git a/dw/layout.cc b/dw/layout.cc
index 521f4f76..5285dfea 100644
--- a/dw/layout.cc
+++ b/dw/layout.cc
@@ -186,6 +186,8 @@ Layout::Layout (Platform *platform)
topLevel = NULL;
widgetAtPoint = NULL;
+ queueResizeList = new typed::Vector<Widget> (4, false);
+
DBG_OBJ_CREATE (this, "DwRenderLayout");
bgColor = NULL;
@@ -233,6 +235,7 @@ Layout::~Layout ()
topLevel = NULL;
delete w;
}
+ delete queueResizeList;
delete platform;
delete view;
delete anchorsTable;
@@ -248,6 +251,7 @@ void Layout::addWidget (Widget *widget)
topLevel = widget;
widget->layout = this;
+ queueResizeList->clear ();
widget->notifySetAsTopLevel();
findtextState.setWidget (widget);
@@ -263,6 +267,7 @@ void Layout::removeWidget ()
* \bug Some more attributes must be reset here.
*/
topLevel = NULL;
+ queueResizeList->clear ();
widgetAtPoint = NULL;
canvasWidth = canvasAscent = canvasDescent = 0;
scrollX = scrollY = 0;
@@ -654,10 +659,28 @@ void Layout::setBgColor (style::Color *color)
void Layout::resizeIdle ()
{
//static int calls = 0;
- //MSG(" Layout::resizeIdle calls = %d\n", ++calls);
+ //printf ("Layout::resizeIdle calls = %d\n", ++calls);
assert (resizeIdleId != -1);
+ for (typed::Iterator <Widget> it = queueResizeList->iterator();
+ it.hasNext (); ) {
+ Widget *widget = it.getNext ();
+
+ //printf (" the %stop-level %s %p was queued (extremes changed: %s)\n",
+ // widget->parent ? "non-" : "", widget->getClassName(), widget,
+ // widget->extremesQueued () ? "yes" : "no");
+
+ widget->setFlags (Widget::NEEDS_RESIZE);
+ widget->unsetFlags (Widget::RESIZE_QUEUED);
+
+ if (widget->extremesQueued ()) {
+ widget->setFlags (Widget::EXTREMES_CHANGED);
+ widget->unsetFlags (Widget::EXTREMES_QUEUED);
+ }
+ }
+ queueResizeList->clear ();
+
// Reset already here, since in this function, queueResize() may be
// called again.
resizeIdleId = -1;
@@ -706,6 +729,8 @@ void Layout::resizeIdle ()
}
updateAnchor ();
+
+ //printf ("Layout::resizeIdle end\n");
}
void Layout::setSizeHints ()
diff --git a/dw/layout.hh b/dw/layout.hh
index 51d764a4..46fc9ffe 100644
--- a/dw/layout.hh
+++ b/dw/layout.hh
@@ -132,6 +132,7 @@ private:
Platform *platform;
View *view;
Widget *topLevel, *widgetAtPoint;
+ lout::container::typed::Vector<Widget> *queueResizeList;
/* The state, which must be projected into the view. */
style::Color *bgColor;
diff --git a/dw/outofflowmgr.cc b/dw/outofflowmgr.cc
index c6d87d44..fe1156b8 100644
--- a/dw/outofflowmgr.cc
+++ b/dw/outofflowmgr.cc
@@ -373,8 +373,9 @@ void OutOfFlowMgr::sizeAllocateEnd ()
sizeAllocateFloats (RIGHT);
sizeAllocateAbsolutelyPositioned ();
- // 3. Textblocks have already been allocated, but we store some
- // information for later use. TODO: Update this comment!
+ // 3. Textblocks have already been allocated, but we (i) check
+ // allocation change of textblocks, and (ii) store some information
+ // for later use.
for (lout::container::typed::Iterator<TypedPointer <Textblock> > it =
tbInfosByTextblock->iterator ();
it.hasNext (); ) {
@@ -388,8 +389,10 @@ void OutOfFlowMgr::sizeAllocateEnd ()
int width = tbAllocation->width;
int height = tbAllocation->ascent + tbAllocation->descent;
+ // (i) Check allocation change of textblocks.
if ((!tbInfo->wasAllocated || tbInfo->xCB != xCB || tbInfo->yCB != yCB ||
tbInfo->width != width || tbInfo->height != height)) {
+ // Changed: change borders when covered by floats.
int oldPos, newPos;
Widget *oldFloat, *newFloat;
// To calculate the minimum, both allocations, old and new,
@@ -420,7 +423,8 @@ void OutOfFlowMgr::sizeAllocateEnd ()
}
}
}
-
+
+ // (ii) store some information for later use.
tbInfo->wasAllocated = true;
tbInfo->xCB = xCB;
tbInfo->yCB = yCB;
@@ -474,31 +478,42 @@ bool OutOfFlowMgr::isTextblockCoveredByFloats (SortedFloatsVector *list,
// TODO binary search
Float *v = list->get(i);
- assert (wasAllocated (v->generatingBlock));
-
- if (tb != v->generatingBlock) {
- int flh = v->dirty ? 0 : v->size.ascent + v->size.descent;
- int y1 = getAllocation(v->generatingBlock)->y + v->yReal;
- int y2 = y1 + flh;
-
- // TODO: Also regard horizontal dimension (same for tellPositionOrNot).
- if (y2 > tby && y1 < tby + tbHeight) {
- covered = true;
- if (y1 - tby < *floatPos) {
- *floatPos = y1 - tby;
- *vloat = v->widget;
- }
- }
+ // TODO Clarify the old condition: tb != v->generatingBlock. Neccessary?
+ if (tb != v->generatingBlock &&
+ isTextblockCoveredByFloat (v, tb, tbx, tby, tbWidth, tbHeight,
+ floatPos)) {
+ covered = true;
+ *vloat = v->widget;
}
// All floarts are searched, to find the minimum. TODO: Are
- // floats sorted, so this can be shortene? (The first is the
+ // floats sorted, so this can be shortened? (The first is the
// minimum?)
}
return covered;
}
+bool OutOfFlowMgr::isTextblockCoveredByFloat (Float *vloat, Textblock *tb,
+ int tbx, int tby,
+ int tbWidth, int tbHeight,
+ int *floatPos)
+{
+ assert (wasAllocated (vloat->generatingBlock));
+
+ int flh = vloat->dirty ? 0 : vloat->size.ascent + vloat->size.descent;
+ int y1 = getAllocation(vloat->generatingBlock)->y + vloat->yReal;
+ int y2 = y1 + flh;
+
+ // TODO: Also regard horizontal dimension (same for tellPositionOrNot)?
+ if (y2 > tby && y1 < tby + tbHeight) {
+ if (floatPos != NULL && y1 - tby < *floatPos)
+ *floatPos = y1 - tby;
+ return true;
+ } else
+ return false;
+}
+
void OutOfFlowMgr::moveFromGBToCB (Side side)
{
SortedFloatsVector *dest = side == LEFT ? leftFloatsCB : rightFloatsCB;
@@ -578,8 +593,8 @@ void OutOfFlowMgr::sizeAllocateFloats (Side side)
vloat->widget->sizeAllocate (&childAllocation);
- //printf ("allocate %s #%d -> (%d, %d), %d x (%d + %d)\n",
- // right ? "right" : "left", i, childAllocation.x,
+ //printf (" allocate %s float #%d -> (%d, %d), %d x (%d + %d)\n",
+ // side == LEFT ? "left" : "right", i, childAllocation.x,
// childAllocation.y, childAllocation.width,
// childAllocation.ascent, childAllocation.descent);
}
@@ -790,9 +805,8 @@ void OutOfFlowMgr::markSizeChange (int ref)
}
vloat->dirty = true;
- // TODO May cause problems (endless resizing?) when float has no
- // defined position.
- vloat->generatingBlock->borderChanged (vloat->yReal, vloat->widget);
+
+ // Effects take place in ensureFloatSize.
} else if (isRefAbsolutelyPositioned (ref)) {
int i = getAbsolutelyPositionedIndexFromRef (ref);
absolutelyPositioned->get(i)->dirty = true;
@@ -1358,7 +1372,37 @@ void OutOfFlowMgr::ensureFloatSize (Float *vloat)
// vloat->size.width, vloat->size.ascent, vloat->size.descent);
vloat->cbAvailWidth = containingBlock->getAvailWidth ();
- vloat->dirty = false;
+ vloat->dirty = false;
+
+ // TODO (i) Comment (ii) linear search?
+ if (wasAllocated (vloat->generatingBlock)) {
+ //printf ("=== start checking textblocks ===\n");
+
+ for (lout::container::typed::Iterator<TypedPointer <Textblock> > it =
+ tbInfosByTextblock->iterator ();
+ it.hasNext (); ) {
+ Textblock *tb = it.getNext()->getTypedValue();
+ if (wasAllocated (tb)) {
+ Allocation *tba = getAllocation (tb);
+ int floatPos;
+
+ if (isTextblockCoveredByFloat
+ (vloat, tb, tba->x - containingBlockAllocation.x,
+ tba->y - containingBlockAllocation.y,
+ tba->width, tba->ascent + tba->descent, &floatPos)) {
+ //printf (" ---> yes: %p (parent: %p)\n", tb,
+ // tb->getParent());
+ tb->borderChanged (floatPos, vloat->widget);
+ } //else
+ // printf (" ---> not covered: %p (parent: %p)\n", tb,
+ // tb->getParent());
+ } //else
+ // printf (" ---> not allocated: %p (parent: %p)\n", tb,
+ // tb->getParent());
+ }
+
+ //printf ("=== end checking textblocks ===\n");
+ }
}
}
diff --git a/dw/outofflowmgr.hh b/dw/outofflowmgr.hh
index c373a50c..23b8134c 100644
--- a/dw/outofflowmgr.hh
+++ b/dw/outofflowmgr.hh
@@ -205,7 +205,10 @@ private:
bool isTextblockCoveredByFloats (SortedFloatsVector *list, Textblock *tb,
int tbx, int tby, int tbWidth, int tbHeight,
int *floatPos, core::Widget **vloat);
-
+ bool isTextblockCoveredByFloat (Float *vloat, Textblock *tb,
+ int tbx, int tby, int tbWidth, int tbHeight,
+ int *floatPos);
+
void drawFloats (SortedFloatsVector *list, core::View *view,
core::Rectangle *area);
void drawAbsolutelyPositioned (core::View *view, core::Rectangle *area);
diff --git a/dw/table.cc b/dw/table.cc
index 5587f469..be910a63 100644
--- a/dw/table.cc
+++ b/dw/table.cc
@@ -480,7 +480,7 @@ void Table::reallocChildren (int newNumCols, int newNumRows)
void Table::calcCellSizes ()
{
- if (needsResize ())
+ if (needsResize () || resizeQueued ())
forceCalcCellSizes ();
}
@@ -638,7 +638,7 @@ void Table::apportionRowSpan ()
*/
void Table::calcColumnExtremes ()
{
- if (extremesChanged ())
+ if (extremesChanged () || extremesQueued ())
forceCalcColumnExtremes ();
}
diff --git a/dw/table.hh b/dw/table.hh
index b8feb835..4a14cfb6 100644
--- a/dw/table.hh
+++ b/dw/table.hh
@@ -71,7 +71,7 @@ namespace dw {
* is the case.
*
* [C] Whether this function is called, depends on NEEDS_RESIZE /
- * EXTREMES_CHANGED.
+ * RESIZE_QUEUED / EXTREMES_CHANGED / EXTREMES_QUEUED.
*
*
* <h4>Apportionment</h4>
diff --git a/dw/textblock.cc b/dw/textblock.cc
index 35c9bb07..dc9fc484 100644
--- a/dw/textblock.cc
+++ b/dw/textblock.cc
@@ -2354,10 +2354,12 @@ void Textblock::queueDrawRange (int index1, int index2)
void Textblock::borderChanged (int y, Widget *vloat)
{
- PRINTF ("[%p] Border has changed: %d (float %s %p, with generator %p)\n",
+ PRINTF ("[%p] BORDER_CHANGED: %d (float %s %p, with generator %p)\n",
this, y, vloat->getClassName(), vloat, vloat->getGenerator());
int lineIndex = findLineIndex (y);
+ PRINTF (" Line index: %d (of %d).\n", lineIndex, lines->size ());
+
// Nothing to do at all, when lineIndex >= lines->size (),
// i. e. the change is below the bottom of this widget.
if (lineIndex < lines->size ()) {
@@ -2368,8 +2370,8 @@ void Textblock::borderChanged (int y, Widget *vloat)
else
wrapLineIndex = lineIndex;
- PRINTF ("[%p] Rewrapping from line %d (of %d).\n",
- this, wrapLineIndex, lines->size ());
+ PRINTF (" Rewrapping from line %d (of %d).\n",
+ wrapLineIndex, lines->size ());
if (vloat->getGenerator() == this) {
bool found = false;
diff --git a/dw/ui.cc b/dw/ui.cc
index dd98b2e9..374f360b 100644
--- a/dw/ui.cc
+++ b/dw/ui.cc
@@ -268,7 +268,7 @@ void ComplexButtonResource::LayoutReceiver::canvasSizeChanged (int width,
/**
* \todo Verify that this is correct.
*/
- resource->queueResize (resource->childWidget->extremesChanged ());
+ resource->queueResize (resource->childWidget->extremesQueued ());
}
ComplexButtonResource::ComplexButtonResource ()
diff --git a/dw/widget.cc b/dw/widget.cc
index 12430f01..42566a17 100644
--- a/dw/widget.cc
+++ b/dw/widget.cc
@@ -130,32 +130,50 @@ void Widget::queueResize (int ref, bool extremesChanged)
{
Widget *widget2, *child;
- //printf("The %stop-level %s %p with parentRef = %d has changed its size.\n",
- // parent ? "non-" : "", getClassName(), this, parentRef);
+ //printf("The %stop-level %s %p with parentRef = %d has changed its size. "
+ // "Layout = %p.\n",
+ // parent ? "non-" : "", getClassName(), this, parentRef, layout);
+
+ Flags resizeFlag, extremesFlag;
+
+ if (layout) {
+ // If RESIZE_QUEUED is set, this widget is already in the list.
+ if (!resizeQueued ())
+ layout->queueResizeList->put (this);
+
+ resizeFlag = RESIZE_QUEUED;
+ extremesFlag = EXTREMES_QUEUED;
+ } else {
+ resizeFlag = NEEDS_RESIZE;
+ extremesFlag = EXTREMES_CHANGED;
+ }
- setFlags (NEEDS_RESIZE);
+ setFlags (resizeFlag);
setFlags (NEEDS_ALLOCATE);
markSizeChange (ref);
-
+
if (extremesChanged) {
- setFlags (EXTREMES_CHANGED);
+ setFlags (extremesFlag);
markExtremesChange (ref);
}
-
- for (widget2 = parent, child = this;
- widget2;
- child = widget2, widget2 = widget2->parent) {
- widget2->setFlags (NEEDS_RESIZE);
- widget2->markSizeChange (child->parentRef);
- widget2->setFlags (NEEDS_ALLOCATE);
-
- //printf (" Setting DW_NEEDS_RESIZE and NEEDS_ALLOCATE for the "
+
+ for (widget2 = parent, child = this; widget2;
+ child = widget2, widget2 = widget2->parent) {
+ //printf (" Setting %s and NEEDS_ALLOCATE for the "
// "%stop-level %s %p with parentRef = %d\n",
+ // resizeFlag == RESIZE_QUEUED ? "RESIZE_QUEUED" : "NEEDS_RESIZE",
// widget2->parent ? "non-" : "", widget2->getClassName(), widget2,
// widget2->parentRef);
+ if (layout && !widget2->resizeQueued ())
+ layout->queueResizeList->put (widget2);
+
+ widget2->setFlags (resizeFlag);
+ widget2->markSizeChange (child->parentRef);
+ widget2->setFlags (NEEDS_ALLOCATE);
+
if (extremesChanged) {
- widget2->setFlags (EXTREMES_CHANGED);
+ widget2->setFlags (extremesFlag);
widget2->markExtremesChange (child->parentRef);
}
}
diff --git a/dw/widget.hh b/dw/widget.hh
index 58306c92..a99e12ab 100644
--- a/dw/widget.hh
+++ b/dw/widget.hh
@@ -27,23 +27,37 @@ class Widget: public lout::identity::IdentifiableObject
protected:
enum Flags {
/**
+ * \todo Comment this.
+ */
+ RESIZE_QUEUED = 1 << 0,
+
+ /**
+ * \todo Comment this.
+ */
+ EXTREMES_QUEUED = 1 << 1,
+
+ /**
* \brief Set, when dw::core::Widget::requisition is not up to date
* anymore.
+ *
+ * \todo Update, see RESIZE_QUEUED.
*/
- NEEDS_RESIZE = 1 << 0,
+ NEEDS_RESIZE = 1 << 2,
/**
* \brief Only used internally, set to enforce size allocation.
*
* (I've forgotten the case, for which this is necessary.)
*/
- NEEDS_ALLOCATE = 1 << 1,
+ NEEDS_ALLOCATE = 1 << 3,
/**
* \brief Set, when dw::core::Widget::extremes is not up to date
* anymore.
+ *
+ * \todo Update, see RESIZE_QUEUED.
*/
- EXTREMES_CHANGED = 1 << 2,
+ EXTREMES_CHANGED = 1 << 4,
/**
* \brief Set by the widget itself (in the constructor), when set...
@@ -51,7 +65,7 @@ protected:
*
* Will hopefully be removed, after redesigning the size model.
*/
- USES_HINTS = 1 << 3,
+ USES_HINTS = 1 << 5,
/**
* \brief Set by the widget itself (in the constructor), when it contains
@@ -59,19 +73,19 @@ protected:
*
* Will hopefully be removed, after redesigning the size model.
*/
- HAS_CONTENTS = 1 << 4,
+ HAS_CONTENTS = 1 << 6,
/**
* \brief Set, when a widget was already once allocated,
*
* The dw::Image widget uses this flag, see dw::Image::setBuffer.
*/
- WAS_ALLOCATED = 1 << 5,
+ WAS_ALLOCATED = 1 << 7,
/**
* \brief Set for block-level widgets (as opposed to inline widgets)
*/
- BLOCK_LEVEL = 1 << 6,
+ BLOCK_LEVEL = 1 << 8,
};
private:
@@ -244,6 +258,8 @@ public:
Widget ();
~Widget ();
+ inline bool resizeQueued () { return flags & RESIZE_QUEUED; }
+ inline bool extremesQueued () { return flags & EXTREMES_QUEUED; }
inline bool needsResize () { return flags & NEEDS_RESIZE; }
inline bool needsAllocate () { return flags & NEEDS_ALLOCATE; }
inline bool extremesChanged () { return flags & EXTREMES_CHANGED; }