aboutsummaryrefslogtreecommitdiff
path: root/dw
diff options
context:
space:
mode:
Diffstat (limited to 'dw')
-rw-r--r--dw/layout.cc1
-rw-r--r--dw/style.cc12
-rw-r--r--dw/style.hh17
-rw-r--r--dw/textblock.cc371
-rw-r--r--dw/textblock.hh82
-rw-r--r--dw/types.hh3
-rw-r--r--dw/widget.cc21
-rw-r--r--dw/widget.hh3
8 files changed, 486 insertions, 24 deletions
diff --git a/dw/layout.cc b/dw/layout.cc
index 9dfd5e9b..d2610687 100644
--- a/dw/layout.cc
+++ b/dw/layout.cc
@@ -248,6 +248,7 @@ void Layout::addWidget (Widget *widget)
topLevel = widget;
widget->layout = this;
+ widget->notifySetAsTopLevel();
findtextState.setWidget (widget);
diff --git a/dw/style.cc b/dw/style.cc
index b5549d3f..4276862a 100644
--- a/dw/style.cc
+++ b/dw/style.cc
@@ -17,8 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -47,6 +45,8 @@ void StyleAttrs::initValues ()
valign = VALIGN_BASELINE;
backgroundColor = NULL;
width = height = lineHeight = LENGTH_AUTO;
+ vloat = FLOAT_NONE;
+ clear = CLEAR_NONE;
textIndent = 0;
margin.setVal (0);
borderWidth.setVal (0);
@@ -73,6 +73,8 @@ void StyleAttrs::resetValues ()
valign = VALIGN_BASELINE;
textAlignChar = '.';
+ vloat = FLOAT_NONE; /** \todo Correct? Check specification. */
+ clear = CLEAR_NONE; /** \todo Correct? Check specification. */
backgroundColor = NULL;
width = LENGTH_AUTO;
height = LENGTH_AUTO;
@@ -117,6 +119,8 @@ bool StyleAttrs::equals (object::Object *other) {
textAlign == otherAttrs->textAlign &&
valign == otherAttrs->valign &&
textAlignChar == otherAttrs->textAlignChar &&
+ vloat == otherAttrs->vloat &&
+ clear == otherAttrs->clear &&
hBorderSpacing == otherAttrs->hBorderSpacing &&
vBorderSpacing == otherAttrs->vBorderSpacing &&
wordSpacing == otherAttrs->wordSpacing &&
@@ -154,6 +158,8 @@ int StyleAttrs::hashValue () {
textAlign +
valign +
textAlignChar +
+ vloat +
+ clear +
hBorderSpacing +
vBorderSpacing +
wordSpacing +
@@ -244,6 +250,8 @@ void Style::copyAttrs (StyleAttrs *attrs)
textAlign = attrs->textAlign;
valign = attrs->valign;
textAlignChar = attrs->textAlignChar;
+ vloat = attrs->vloat;
+ clear = attrs->clear;
hBorderSpacing = attrs->hBorderSpacing;
vBorderSpacing = attrs->vBorderSpacing;
wordSpacing = attrs->wordSpacing;
diff --git a/dw/style.hh b/dw/style.hh
index 4ebb7bb5..370d8d1b 100644
--- a/dw/style.hh
+++ b/dw/style.hh
@@ -273,7 +273,6 @@ enum ListStylePosition {
LIST_STYLE_POSITION_INSIDE,
LIST_STYLE_POSITION_OUTSIDE
};
-
enum ListStyleType {
LIST_STYLE_TYPE_DISC,
LIST_STYLE_TYPE_CIRCLE,
@@ -325,6 +324,19 @@ enum WhiteSpace {
WHITE_SPACE_PRE_LINE,
};
+enum FloatType {
+ FLOAT_NONE,
+ FLOAT_LEFT,
+ FLOAT_RIGHT
+};
+
+enum ClearType {
+ CLEAR_LEFT,
+ CLEAR_RIGHT,
+ CLEAR_BOTH,
+ CLEAR_NONE
+};
+
/**
* \brief Type for representing all lengths within dw::core::style.
*
@@ -441,6 +453,9 @@ public:
TextAlignType textAlign;
VAlignType valign;
char textAlignChar; /* In future, strings will be supported. */
+
+ FloatType vloat; /* "float" is a keyword. */
+ ClearType clear;
int hBorderSpacing, vBorderSpacing, wordSpacing;
Length width, height, lineHeight, textIndent;
diff --git a/dw/textblock.cc b/dw/textblock.cc
index 23465d23..6ded2413 100644
--- a/dw/textblock.cc
+++ b/dw/textblock.cc
@@ -17,13 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
#include "textblock.hh"
+#include "table.hh" // Yes, this is ugly. -- SG
#include "../lout/msg.h"
#include "../lout/misc.hh"
#include <stdio.h>
+#include <math.h> // remove again
#include <limits.h>
/*
@@ -68,6 +68,7 @@ Textblock::Textblock (bool limitTextWidth)
*/
lines = new misc::SimpleVector <Line> (1);
words = new misc::SimpleVector <Word> (1);
+ leftFloatSide = rightFloatSide = NULL;
anchors = new misc::SimpleVector <Anchor> (1);
//DBG_OBJ_SET_NUM(page, "num_lines", num_lines);
@@ -124,6 +125,11 @@ Textblock::~Textblock ()
delete lines;
delete words;
delete anchors;
+
+ if(leftFloatSide)
+ delete leftFloatSide;
+ if(rightFloatSide)
+ delete rightFloatSide;
/* Make sure we don't own widgets anymore. Necessary before call of
parent class destructor. (???) */
@@ -435,11 +441,16 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation)
xCursor += (word->size.width + word->effSpace);
}
}
-
+
+ if(leftFloatSide)
+ leftFloatSide->sizeAllocate(allocation);
+ if(rightFloatSide)
+ rightFloatSide->sizeAllocate(allocation);
+
for (int i = 0; i < anchors->size(); i++) {
Anchor *anchor = anchors->getRef(i);
int y;
-
+
if (anchor->wordIndex >= words->size()) {
y = allocation->y + allocation->ascent + allocation->descent;
} else {
@@ -479,15 +490,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;
+ }
}
}
@@ -502,7 +563,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;
}
@@ -517,7 +582,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;
}
}
@@ -531,7 +600,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;
}
}
@@ -828,6 +901,8 @@ Textblock::Line *Textblock::addLine (int wordIndex, 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->boxAscent);
@@ -927,6 +1002,19 @@ void Textblock::wordWrap(int 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->boxAscent + line->boxDescent : 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;
@@ -956,7 +1044,7 @@ void Textblock::wordWrap(int wordIndex)
// page->lastLine_width, prevWord->orig_space,
// word->size.width, availWidth);
newLine = lastLineWidth + prevWord->origSpace + word->size.width >
- availWidth;
+ availWidth - (lastLine->boxLeft + lastLine->boxRight);
//DBG_MSGF (page, "wrap", 0, "... %s.",
// newLine ? "No" : "Yes");
}
@@ -1069,7 +1157,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;
case core::style::TEXT_ALIGN_RIGHT:
@@ -1096,9 +1184,15 @@ void Textblock::wordWrap(int wordIndex)
} else {
lastLine->leftOffset = leftOffset;
}
+
+ int y =
+ allocation.y - containingBox->allocation.y +
+ getStyle()->boxOffsetY () + lastLine->top;
+ lastLine->boxLeft = calcLeftFloatBorder(y, this);
+ lastLine->boxRight = calcRightFloatBorder(y, this);
}
mustQueueResize = true;
-
+
//DBG_MSG_END (page);
}
@@ -1219,7 +1313,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);
}
@@ -1562,6 +1658,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);
}
/**
@@ -1702,7 +1803,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);
@@ -1817,8 +1920,8 @@ void Textblock::addParbreak (int space, core::style::Style *style)
if (!isfirst) {
/* The page we searched for has been found. */
Word *word2;
- int lineno = widget->parentRef;
-
+ // ABC
+ int lineno = widget->parentRef >> 3;
if (lineno > 0 &&
(word2 =
textblock2->words->getRef(textblock2->lines
@@ -1826,7 +1929,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;
}
}
@@ -1879,6 +1986,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.
@@ -1949,8 +2072,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;
}
}
@@ -2018,6 +2147,214 @@ 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.width > 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->getStyle()->boxOffsetX();
+}
+
+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->getStyle()->boxOffsetX();
+ 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->getStyle()->boxRestWidth();
+}
+
+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->getStyle()->boxRestWidth();
+ 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):
diff --git a/dw/textblock.hh b/dw/textblock.hh
index 96cb40e5..ea7795b8 100644
--- a/dw/textblock.hh
+++ b/dw/textblock.hh
@@ -10,6 +10,9 @@ namespace dw {
* \brief A Widget for rendering text blocks, i.e. paragraphs or sequences
* of paragraphs.
*
+ * <strong>Important Note:</strong>: This documentation is out of date, since
+ * floats have been implementet. Will be updated and extended soon.
+ *
* <h3>Signals</h3>
*
* dw::Textblock uses the signals defined in
@@ -130,6 +133,66 @@ namespace dw {
*/
class Textblock: public core::Widget
{
+private:
+ Textblock *containingBox;
+
+ class FloatSide
+ {
+ protected:
+ class Float: public lout::object::Object
+ {
+ public:
+ Textblock *floatGenerator;
+ core::Widget *widget;
+ int lineNo, y, width, ascent, descent;
+ };
+
+ Textblock *floatContainer;
+ lout::container::typed::Vector<Float> *floats;
+ lout::container::typed::HashTable<lout::object::TypedPointer<dw::core::Widget>, Float> *floatsByWidget;
+
+ Float *findFloat(int y);
+
+ virtual int calcBorderFromContainer(Float *vloat) = 0;
+ virtual int calcBorderDiff(Textblock *child) = 0;
+
+ public:
+ FloatSide(Textblock *floatContainer);
+ virtual ~FloatSide();
+
+ inline int size() { return floats->size(); }
+ void addFloat(Widget *widget, Textblock *floatGenerator);
+ void handleFloat(Widget *widget, int lineNo, int y, int lineWidth, int lineHeight);
+ int calcBorder(int y, Textblock *viewdFrom);
+ virtual void sizeAllocate(core::Allocation *containingBoxAllocation) = 0;
+ void draw (core::View *view, core::Rectangle *area);
+ void queueResize(int ref);
+ };
+
+ class LeftFloatSide: public FloatSide
+ {
+ protected:
+ int calcBorderFromContainer(Float *vloat);
+ int calcBorderDiff(Textblock *child);
+
+ public:
+ LeftFloatSide(Textblock *floatContainer) : FloatSide(floatContainer) { }
+ void sizeAllocate(core::Allocation *containingBoxAllocation);
+ };
+
+ class RightFloatSide: public FloatSide
+ {
+ protected:
+ int calcBorderFromContainer(Float *vloat);
+ int calcBorderDiff(Textblock *child);
+
+ public:
+ RightFloatSide(Textblock *floatContainer) : FloatSide(floatContainer) { }
+ void sizeAllocate(core::Allocation *containingBoxAllocation);
+ };
+
+ FloatSide *leftFloatSide, *rightFloatSide;
+
protected:
struct Line
{
@@ -140,7 +203,8 @@ protected:
* page->lines[0].top is always 0. */
int top, boxAscent, boxDescent, contentAscent, contentDescent,
breakSpace, leftOffset;
-
+ int boxLeft, boxRight;
+
/* This is similar to descent, but includes the bottom margins of the
* widgets within this line. */
int marginDescent;
@@ -278,7 +342,15 @@ protected:
void calcTextSize (const char *text, size_t len, core::style::Style *style,
core::Requisition *size);
-
+ void addFloatIntoContainer(core::Widget *widget, Textblock *floatGenerator);
+ void handleFloatInContainer(Widget *widget, int lineNo,
+ int y, int lineWidth, int lineHeight);
+
+ inline int calcLeftFloatBorder(int y, Textblock *viewedFrom)
+ { return containingBox->leftFloatSide ? containingBox->leftFloatSide->calcBorder(y, viewedFrom) : 0; }
+ inline int calcRightFloatBorder(int y, Textblock *viewedFrom)
+ { return containingBox->rightFloatSide ? containingBox->rightFloatSide->calcBorder(y, viewedFrom) : 0; }
+
/**
* \brief Returns the x offset (the indentation plus any offset needed for
* centering or right justification) for the line.
@@ -288,7 +360,7 @@ protected:
*/
inline int lineXOffsetContents (Line *line)
{
- return innerPadding + line->leftOffset +
+ return innerPadding + line->leftOffset + line->boxLeft +
(line == lines->getRef (0) ? line1OffsetEff : 0);
}
@@ -351,6 +423,8 @@ protected:
void markSizeChange (int ref);
void markExtremesChange (int ref);
+ void notifySetAsTopLevel();
+ void notifySetParent();
void setWidth (int width);
void setAscent (int ascent);
void setDescent (int descent);
@@ -385,6 +459,8 @@ public:
void addParbreak (int space, core::style::Style *style);
void addLinebreak (core::style::Style *style);
+ void addFloatIntoGenerator (core::Widget *widget, core::style::Style *style);
+
core::Widget *getWidgetAtPoint (int x, int y, int level);
void handOverBreak (core::style::Style *style);
void changeLinkColor (int link, int newColor);
diff --git a/dw/types.hh b/dw/types.hh
index a8c244c7..b5204331 100644
--- a/dw/types.hh
+++ b/dw/types.hh
@@ -190,8 +190,9 @@ struct Content
TEXT = 1 << 2,
WIDGET = 1 << 3,
BREAK = 1 << 4,
+ FLOAT_REF = 1 << 6, /** \todo A bit ugly. */
ALL = 0xff,
- REAL_CONTENT = 0xff ^ (START | END),
+ REAL_CONTENT = 0xff ^ (START | END | FLOAT_REF),
SELECTION_CONTENT = TEXT | WIDGET | BREAK
};
/* Content is embedded in struct Word therefore we
diff --git a/dw/widget.cc b/dw/widget.cc
index 2a6fbfc3..cc73b32b 100644
--- a/dw/widget.cc
+++ b/dw/widget.cc
@@ -108,6 +108,8 @@ void Widget::setParent (Widget *parent)
if (!buttonSensitiveSet)
buttonSensitive = parent->buttonSensitive;
+ notifySetParent();
+
//DBG_OBJ_ASSOC (widget, parent);
}
@@ -566,6 +568,25 @@ void Widget::markExtremesChange (int ref)
{
}
+/**
+ * \brief This method is called after a widget has been set as the top of a
+ * widget tree.
+ *
+ * A widget may override this method when it is necessary to be notified.
+ */
+void Widget::notifySetAsTopLevel()
+{
+}
+
+/**
+ * \brief This method is called after a widget has been added to a parent.
+ *
+ * A widget may override this method when it is necessary to be notified.
+ */
+void Widget::notifySetParent()
+{
+}
+
void Widget::setWidth (int width)
{
}
diff --git a/dw/widget.hh b/dw/widget.hh
index b751a282..e18344c7 100644
--- a/dw/widget.hh
+++ b/dw/widget.hh
@@ -178,6 +178,9 @@ protected:
*/
virtual void markExtremesChange (int ref);
+ virtual void notifySetAsTopLevel();
+ virtual void notifySetParent();
+
virtual bool buttonPressImpl (EventButton *event);
virtual bool buttonReleaseImpl (EventButton *event);
virtual bool motionNotifyImpl (EventMotion *event);