diff options
author | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2010-08-20 20:27:07 +0200 |
---|---|---|
committer | Johannes Hofmann <Johannes.Hofmann@gmx.de> | 2010-08-20 20:27:07 +0200 |
commit | e98d02a01ffeb18ede86af025e51ae1ec011c75a (patch) | |
tree | f8b2efbec989335bf2a56b73fcf485f4cd1a01c6 /dw/textblock.cc | |
parent | ce8e972a10c9340312f21511de053242dad3f5db (diff) |
import float prototype and test program by Sebastian Geerken
Diffstat (limited to 'dw/textblock.cc')
-rw-r--r-- | dw/textblock.cc | 370 |
1 files changed, 355 insertions, 15 deletions
diff --git a/dw/textblock.cc b/dw/textblock.cc index d80a7ad4..6bfd4d90 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -18,12 +18,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - - #include "textblock.hh" +#include "table.hh" // Yes, this is ugly. -- SG #include "../lout/misc.hh" #include <stdio.h> +#include <math.h> // remove again #include <limits.h> namespace dw { @@ -55,6 +55,7 @@ Textblock::Textblock (bool limitTextWidth) */ lines = new misc::SimpleVector <Line> (1); words = new misc::SimpleVector <Word> (1); + leftFloatSide = rightFloatSide = NULL; //DBG_OBJ_SET_NUM(page, "num_lines", num_lines); @@ -107,6 +108,11 @@ Textblock::~Textblock () delete lines; delete words; + if(leftFloatSide) + delete leftFloatSide; + if(rightFloatSide) + delete rightFloatSide; + /* Make sure we don't own widgets anymore. Necessary before call of parent class destructor. (???) */ words = NULL; @@ -418,6 +424,11 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation) xCursor += (word->size.width + word->effSpace); } } + + if(leftFloatSide) + leftFloatSide->sizeAllocate(allocation); + if(rightFloatSide) + rightFloatSide->sizeAllocate(allocation); } void Textblock::resizeDrawImpl () @@ -449,15 +460,65 @@ void Textblock::markExtremesChange (int ref) */ void Textblock::markChange (int ref) { - if (ref != -1) { + printf("markChange(%d)\n", ref); + + int refEquiv = (ref == 0) ? 1 | (dw::core::style::FLOAT_NONE << 1) : ref; + + if (refEquiv != -1 && (refEquiv & 1)) { //DBG_MSGF (page, "wrap", 0, "Dw_page_mark_size_change (ref = %d)", ref); - if (wrapRef == -1) - wrapRef = ref; - else - wrapRef = misc::min (wrapRef, ref); + // ABC + switch((refEquiv >> 1) & 3) + { + case dw::core::style::FLOAT_NONE: + if (wrapRef == -1) + wrapRef = refEquiv >> 3; + else + wrapRef = misc::min (wrapRef, refEquiv >> 3); + //DBG_OBJ_SET_NUM (page, "wrap_ref", page->wrap_ref); + printf("wrapRef = %d\n", wrapRef); + break; + + case dw::core::style::FLOAT_LEFT: + leftFloatSide->queueResize(refEquiv); + break; + + case dw::core::style::FLOAT_RIGHT: + rightFloatSide->queueResize(refEquiv); + break; + } + } +} - //DBG_OBJ_SET_NUM (page, "wrap_ref", page->wrap_ref); +void Textblock::notifySetAsTopLevel() +{ + containingBox = this; +} + +void Textblock::notifySetParent() +{ + // Search for containing Box. It can be assumed that this widget has a + // parent, otherwise, notifySetAsToplevel would have been called. + containingBox = NULL; + Textblock *topmostTextblock = this; + + for(Widget *widget = getParent(); widget != NULL; widget = widget->getParent()) + { + if(widget->instanceOf(Textblock::CLASS_ID)) + topmostTextblock = (Textblock*)widget; + } + + for(Widget *widget = getParent(); containingBox == NULL; widget = widget->getParent()) + { + if(widget->getParent() == NULL) + // No other widget left. + containingBox = topmostTextblock; + else if(widget->instanceOf(Textblock::CLASS_ID)) + { + if(widget->getParent()->instanceOf(Table::CLASS_ID) /* this widget is a table cell */ || + widget->getStyle()->vloat != dw::core::style::FLOAT_NONE /* this widget is a float */) + containingBox = (Textblock*)widget; + } } } @@ -472,7 +533,11 @@ void Textblock::setWidth (int width) // page->num_words); availWidth = width; +//<<<<<<< textblock.cc +// queueResize (false, dw::core::style::FLOAT_NONE, false); +//======= queueResize (0, false); +//>>>>>>> 1.24 mustQueueResize = false; redrawY = 0; } @@ -487,7 +552,11 @@ void Textblock::setAscent (int ascent) // page->num_words); availAscent = ascent; +//<<<<<<< textblock.cc +// queueResize (false, dw::core::style::FLOAT_NONE, false); +//======= queueResize (0, false); +//>>>>>>> 1.24 mustQueueResize = false; } } @@ -501,7 +570,11 @@ void Textblock::setDescent (int descent) // page->num_words); availDescent = descent; +//<<<<<<< textblock.cc +// queueResize (false, dw::core::style::FLOAT_NONE, false); +//======= queueResize (0, false); +//>>>>>>> 1.24 mustQueueResize = false; } } @@ -804,6 +877,8 @@ void Textblock::addLine (int wordInd, bool newPar) lastLine->marginDescent = 0; lastLine->breakSpace = 0; lastLine->leftOffset = 0; + lastLine->boxLeft = 0; + lastLine->boxRight = 0; //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1, // lastLine->ascent); @@ -874,6 +949,17 @@ void Textblock::wordWrap(int wordIndex) word = words->getRef (wordIndex); + if(word->content.type == dw::core::Content::FLOAT_REF) + { + Line *line = lines->size() > 0 ? lines->getRef(lines->size() - 1) : NULL; + int y = + allocation.y - containingBox->allocation.y + getStyle()->boxOffsetY() + + (line ? line->top : 0); + int lineHeight = line ? line->ascent + line->descent : 0; + + containingBox->handleFloatInContainer(word->content.widget, misc::max(lines->size() - 1, 0), y, lastLineWidth, lineHeight); + } + if (lines->size () == 0) { //DBG_MSG (page, "wrap", 0, "first line"); newLine = true; @@ -903,8 +989,10 @@ void Textblock::wordWrap(int wordIndex) // word_ind, a_Dw_content_html (&word->content), // page->lastLine_width, prevWord->orig_space, // word->size.width, availWidth); - newLine = (lastLineWidth + prevWord->origSpace - + word->size.width > availWidth); + newLine = (lastLineWidth + prevWord->origSpace + + word->size.width + > availWidth - + (lastLine->boxLeft + lastLine->boxRight)); //DBG_MSGF (page, "wrap", 0, "... %s.", // newLine ? "No" : "Yes"); } @@ -1021,7 +1109,7 @@ void Textblock::wordWrap(int wordIndex) case core::style::TEXT_ALIGN_LEFT: case core::style::TEXT_ALIGN_JUSTIFY: /* see some lines above */ case core::style::TEXT_ALIGN_STRING: /* handled elsewhere (in the - * future) */ + * future) */ leftOffset = 0; break; @@ -1050,10 +1138,16 @@ void Textblock::wordWrap(int wordIndex) // page->words[0].eff_space); } else lastLine->leftOffset = leftOffset; + + int y = + allocation.y - containingBox->allocation.y + + getStyle()->boxOffsetX () + lastLine->top; + lastLine->boxLeft = calcLeftFloatBorder(y, this); + lastLine->boxRight = calcRightFloatBorder(y, this); } mustQueueResize = true; - + //DBG_MSG_END (page); } @@ -1176,7 +1270,9 @@ void Textblock::rewrap () wordWrap (wordIndex); if (word->content.type == core::Content::WIDGET) { - word->content.widget->parentRef = lines->size () - 1; + // ABC + word->content.widget->parentRef = 1 | (dw::core::style::FLOAT_NONE << 1) | ((lines->size () - 1) << 3); + printf("parentRef = %d\n", word->content.widget->parentRef); //DBG_OBJ_SET_NUM (word->content.widget, "parent_ref", // word->content.widget->parent_ref); } @@ -1525,6 +1621,11 @@ void Textblock::draw (core::View *view, core::Rectangle *area) drawLine (line, view, area); } + + if(leftFloatSide) + leftFloatSide->draw(view, area); + if(rightFloatSide) + rightFloatSide->draw(view, area); } /** @@ -1634,7 +1735,9 @@ void Textblock::addWidget (core::Widget *widget, core::style::Style *style) // word->content.widget); wordWrap (words->size () - 1); - word->content.widget->parentRef = lines->size () - 1; + // ABC + word->content.widget->parentRef = 1 | (dw::core::style::FLOAT_NONE << 1) | ((lines->size () - 1) << 3); + printf("parentRef = %d\n", word->content.widget->parentRef); //DBG_OBJ_SET_NUM (word->content.widget, "parent_ref", // word->content.widget->parent_ref); @@ -1760,7 +1863,8 @@ void Textblock::addParbreak (int space, core::style::Style *style) && textblock2->words->get(0).content.widget == widget); if (!isfirst) { /* The page we searched for has been found. */ - lineno = widget->parentRef; + // ABC + lineno = widget->parentRef >> 3; if (lineno > 0 && (word2 = textblock2->words->getRef(textblock2->lines @@ -1768,7 +1872,11 @@ void Textblock::addParbreak (int space, core::style::Style *style) word2->content.type == core::Content::BREAK) { if (word2->content.breakSpace < space) { word2->content.breakSpace = space; +//<<<<<<< textblock.cc +// textblock2->queueResize (false, 1 | (dw::core::style::FLOAT_NONE << 1) | (lineno << 3), false); +//======= textblock2->queueResize (lineno, false); +//>>>>>>> 1.24 textblock2->mustQueueResize = false; } } @@ -1822,6 +1930,22 @@ void Textblock::addLinebreak (core::style::Style *style) wordWrap (words->size () - 1); } +/** \todo This MUST be commented! */ +void Textblock::addFloatIntoGenerator (core::Widget *widget, core::style::Style *style) +{ + Word *word; + + widget->setStyle (style); + containingBox->addFloatIntoContainer(widget, this); + + word = addWord (0, 0, 0, style); + word->content.type = core::Content::FLOAT_REF; + word->content.breakSpace = 0; + word->content.widget = widget; + word->style = style; + wordWrap (words->size () - 1); +} + /** * \brief Search recursively through widget. @@ -1895,8 +2019,14 @@ void Textblock::handOverBreak (core::style::Style *style) */ void Textblock::flush () { +//<<<<<<< textblock.cc +// if (asap || mustQueueResize) { +// printf("queueResize(%s, -1, true)\n", asap ? "true" : "false"); +// queueResize (asap, -1, true); +//======= if (mustQueueResize) { queueResize (-1, true); +//>>>>>>> 1.24 mustQueueResize = false; } } @@ -1964,6 +2094,216 @@ void Textblock::changeWordStyle (int from, int to, core::style::Style *style, // ---------------------------------------------------------------------- +/** \todo This MUST be commented! */ +void Textblock::addFloatIntoContainer(Widget *widget, + Textblock *floatGenerator) +{ + FloatSide *floatSide = NULL; + + switch(widget->getStyle()->vloat) + { + case dw::core::style::FLOAT_LEFT: + if(leftFloatSide == NULL) + leftFloatSide = new LeftFloatSide(this); + floatSide = leftFloatSide; + break; + + case dw::core::style::FLOAT_RIGHT: + if(rightFloatSide == NULL) + rightFloatSide = new RightFloatSide(this); + floatSide = rightFloatSide; + break; + + default: + //TODO lout::misc::fail("invalid value %d for float to be added", widget->getStyle()->vloat); + break; + } + + // ABC + widget->parentRef = 1 | (widget->getStyle()->vloat << 1) | (floatSide->size() << 3); + widget->parentRef = 0; + printf("parentRef = %d\n", widget->parentRef); + widget->setParent(this); + + floatSide->addFloat(widget, floatGenerator); +} + +void Textblock::handleFloatInContainer(Widget *widget, int lineNo, + int y, int lineWidth, int lineHeight) +{ + FloatSide *floatSide = NULL; + + switch(widget->getStyle()->vloat) + { + case dw::core::style::FLOAT_LEFT: + floatSide = leftFloatSide; + break; + + case dw::core::style::FLOAT_RIGHT: + floatSide = rightFloatSide; + break; + + default: + //TODO lout::misc::fail("invalid value %d for float to be handled", widget->getStyle()->vloat); + break; + } + + floatSide->handleFloat(widget, lineNo, y, lineWidth, lineHeight); +} + +Textblock::FloatSide::FloatSide(Textblock *floatContainer) +{ + this->floatContainer = floatContainer; + floats = new container::typed::Vector<Float>(1, false); + floatsByWidget = + new container::typed::HashTable<object::TypedPointer<dw::core::Widget>, Float>(true, true); +} + +Textblock::FloatSide::~FloatSide() +{ + delete floats; + delete floatsByWidget; +} + +void Textblock::FloatSide::addFloat(Widget *widget, Textblock *floatGenerator) +{ + Float *vloat = new Float(); + vloat->floatGenerator = floatGenerator; + vloat->widget = widget; + floats->put(vloat); + object::TypedPointer<Widget> *pointer = new object::TypedPointer<Widget>(widget); + floatsByWidget->put(pointer, vloat); +} + +void Textblock::FloatSide::handleFloat(Widget *widget, int lineNo, + int y, int lineWidth, int lineHeight) +{ + /** \todo lineHeight may change afterwards */ + object::TypedPointer<Widget> pointer(widget); + Float *vloat = floatsByWidget->get(&pointer); + + printf("searching %s in %s\n", pointer.toString(), floatsByWidget->toString()); + + dw::core::Requisition requisition; + widget->sizeRequest(&requisition); + + int effY; + /** \todo Check for another float. Futhermore: what, if the float does not fit + * into a line at all? */ + if(requisition.ascent + requisition.descent > vloat->floatGenerator->availWidth - lineWidth) + effY = y + lineHeight; + else + effY = y; + + vloat->lineNo = lineNo; + vloat->y = effY; + vloat->width = requisition.width; + vloat->ascent = requisition.ascent; + vloat->descent = requisition.descent; +} + +int Textblock::FloatSide::calcBorder(int y, Textblock *viewdFrom) +{ + Float *vloat = findFloat(y); + if(vloat) { + int fromContainer = calcBorderFromContainer(vloat); + int fromThisViewedFrom = fromContainer - calcBorderDiff(viewdFrom); + //printf("fromThisViewedFrom = %d\n", fromThisViewedFrom); + return misc::max(fromThisViewedFrom, 0); + } else + return 0; +} + +Textblock::FloatSide::Float *Textblock::FloatSide::findFloat(int y) +{ + for(int i = 0; i < floats->size(); i++) + { + Float *vloat = floats->get(i); + if(y >= vloat->y && y < vloat->y + vloat->ascent + vloat->descent) + return vloat; + } + + return NULL; +} + +void Textblock::FloatSide::draw (core::View *view, core::Rectangle *area) +{ + for(int i = 0; i < floats->size(); i++) + { + Float *vloat = floats->get(i); + core::Rectangle childArea; + if (vloat->widget->intersects (area, &childArea)) + vloat->widget->draw (view, &childArea); + } +} + +void Textblock::FloatSide::queueResize(int ref) +{ + // TODO Float *vloat = floats->get(ref >> 3); + // TODO vloat->floatGenerator->queueResize(false, 1 | (dw::core::style::FLOAT_NONE << 1) | (vloat->lineNo << 3), true); +} + +int Textblock::LeftFloatSide::calcBorderFromContainer(Textblock::FloatSide::Float *vloat) +{ + return vloat->width + floatContainer->getStyle()->boxOffsetX() + + (vloat->floatGenerator->allocation.x - floatContainer->allocation.x); +} + +int Textblock::LeftFloatSide::calcBorderDiff(Textblock *child) +{ + return child->getStyle()->boxOffsetX(); +} + +void Textblock::LeftFloatSide::sizeAllocate(core::Allocation *containingBoxAllocation) +{ + for(int i = 0; i < floats->size(); i++) + { + Float *vloat = floats->get(i); + core::Allocation childAllocation; + childAllocation.x = + containingBoxAllocation->x + floatContainer->getStyle()->boxOffsetX() + + (vloat->floatGenerator->allocation.x - floatContainer->allocation.x); + childAllocation.y = containingBoxAllocation->y + vloat->y; + childAllocation.width = vloat->width; + childAllocation.ascent = vloat->ascent; + childAllocation.descent = vloat->descent; + vloat->widget->sizeAllocate(&childAllocation); + } +} + +int Textblock::RightFloatSide::calcBorderFromContainer(Textblock::FloatSide::Float *vloat) +{ + return vloat->width + floatContainer->getStyle()->boxRestWidth() + + (vloat->floatGenerator->allocation.x + vloat->floatGenerator->allocation.width - + (floatContainer->allocation.x + floatContainer->allocation.width)); +} + +int Textblock::RightFloatSide::calcBorderDiff(Textblock *child) +{ + return child->getStyle()->boxRestWidth(); +} + +void Textblock::RightFloatSide::sizeAllocate(core::Allocation *containingBoxAllocation) +{ + for(int i = 0; i < floats->size(); i++) + { + Float *vloat = floats->get(i); + core::Allocation childAllocation; + childAllocation.x = + containingBoxAllocation->x + containingBoxAllocation->width - + floatContainer->getStyle()->boxRestWidth() - vloat->width + + (vloat->floatGenerator->allocation.x + vloat->floatGenerator->allocation.width - + (floatContainer->allocation.x + floatContainer->allocation.width)); + childAllocation.y = containingBoxAllocation->y + vloat->y; + childAllocation.width = vloat->width; + childAllocation.ascent = vloat->ascent; + childAllocation.descent = vloat->descent; + vloat->widget->sizeAllocate(&childAllocation); + } +} + +// ---------------------------------------------------------------------- + Textblock::TextblockIterator::TextblockIterator (Textblock *textblock, core::Content::Type mask, bool atEnd): |