be9bdfd3f848 — Sebastian Geerken 8 years ago
Fix update problem related to CSS 'clear'.
3 files changed, 57 insertions(+), 13 deletions(-)

M dw/ooffloatsmgr.cc
M dw/ooffloatsmgr.hh
M dw/textblock.cc
M dw/ooffloatsmgr.cc +46 -12
@@ 652,18 652,8 @@ void OOFFloatsMgr::markSizeChange (int r
       vloat->dirty = true;  
       DBG_OBJ_SET_BOOL_O (vloat->getWidget (), "<Float>.dirty", vloat->dirty);
 
-      assert (vloat->getWidget()->getWidgetReference() != NULL);
-     
-      int first = getOOFAwareWidget(vloat->generator)->index;
-      DBG_OBJ_MSGF ("resize.oofm", 1, "updating from %d", first);
-      
-      tbInfos->get(first)->getOOFAwareWidget()
-         ->updateReference (vloat->getWidget()->getWidgetReference()
-                            ->parentRef);
-      
-      for (int i = first + 1; i < tbInfos->size(); i++)
-         tbInfos->get(i)->getOOFAwareWidget()->updateReference(0);
-
+      updateGenerators (vloat);
+   
       floatRef = ref;
       DBG_OBJ_SET_NUM ("floatRef", floatRef);
    }

          
@@ 672,6 662,29 @@ void OOFFloatsMgr::markSizeChange (int r
 }
 
 /**
+ * \brief Update all generators which are affected by a given float.
+ */
+void OOFFloatsMgr::updateGenerators (Float *vloat)
+{
+   DBG_OBJ_ENTER ("resize.oofm", 0, "updateGenerators", "#%d [%p]",
+                  vloat->index, vloat->getWidget ());
+                  
+   assert (vloat->getWidget()->getWidgetReference() != NULL);
+   
+   int first = getOOFAwareWidget(vloat->generator)->index;
+   DBG_OBJ_MSGF ("resize.oofm", 1, "updating from %d", first);
+   
+   tbInfos->get(first)->getOOFAwareWidget()
+      ->updateReference (vloat->getWidget()->getWidgetReference()
+                         ->parentRef);
+   
+   for (int i = first + 1; i < tbInfos->size(); i++)
+      tbInfos->get(i)->getOOFAwareWidget()->updateReference(0);
+
+   DBG_OBJ_LEAVE ();
+}
+   
+/**
  * `y` is given relative to the container.
  */
 int OOFFloatsMgr::findTBInfo (int y)

          
@@ 741,6 754,8 @@ void OOFFloatsMgr::tellPosition1 (Widget
    getFloatsListsAndSide (vloat, &listSame, &listOpp, &side);
    ensureFloatSize (vloat);
 
+   int oldYReal = vloat->yReal;
+   
    // "yReal" may change due to collisions (see below).
    vloat->yReq = vloat->yReal = y;
 

          
@@ 805,6 820,25 @@ void OOFFloatsMgr::tellPosition1 (Widget
    DBG_OBJ_MSGF ("resize.oofm", 1, "vloat->yReq = %d, vloat->yReal = %d",
                  vloat->yReq, vloat->yReal);
 
+   // In some cases, an explicit update is neccessary, as in this example:
+   //
+   // <body>
+   //     <div id="a">
+   //         <div id="b" style="float:left">main</div>
+   //     </div>
+   //     <div id="c" style="clear:both">x</div>
+   //     <div id="d">footer</div>
+   // </body>
+   //
+   // Without an explicit update, #c would keep an old value for extraSpace.top,
+   // based on the old value of vloat->yReal.
+   //
+   // Notice that #c would be updated otherwise, if it had at least one word
+   // content.
+
+   if (vloat->yReal != oldYReal)
+      updateGenerators (vloat);
+
    DBG_OBJ_LEAVE ();
 }
 

          
M dw/ooffloatsmgr.hh +1 -0
@@ 170,6 170,7 @@ private:
    void moveExternalIndices (lout::container::typed::Vector<Float> *list,
                              int oldStartIndex, int diff);
    Float *findFloatByWidget (core::Widget *widget);
+   void updateGenerators (Float *vloat);
    int findTBInfo (int y);
 
    void sizeAllocateFloats (Side side);

          
M dw/textblock.cc +10 -1
@@ 3044,8 3044,17 @@ void Textblock::queueDrawRange (int inde
 
 void Textblock::updateReference (int ref)
 {
-   if (words->size () > 0)
+   DBG_OBJ_ENTER ("resize", 0, "updateReference", "%d", ref);
+
+   // This method can be optimized: nothing must be done when (i) there are no
+   // words, *and* (ii) there is no float clearance. If the second is not the
+   // case, `queueResize` must still be called, since `extraSpace.top` may be
+   // changed.
+
+   if (!(words->size () == 0 && getStyle()->clear == core::style::CLEAR_NONE))
       queueResize (ref, false);
+
+   DBG_OBJ_LEAVE ();
 }
 
 void Textblock::widgetRefSizeChanged (int externalIndex)