aboutsummaryrefslogtreecommitdiff
path: root/dw/textblock.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dw/textblock.cc')
-rw-r--r--dw/textblock.cc110
1 files changed, 65 insertions, 45 deletions
diff --git a/dw/textblock.cc b/dw/textblock.cc
index fffbac2f..6ded2413 100644
--- a/dw/textblock.cc
+++ b/dw/textblock.cc
@@ -26,6 +26,15 @@
#include <math.h> // remove again
#include <limits.h>
+/*
+ * Local variables
+ */
+ /* The tooltip under mouse pointer in current textblock. No ref. hold.
+ * (having one per view looks not worth the extra clutter). */
+static dw::core::style::Tooltip *hoverTooltip = NULL;
+
+
+
using namespace lout;
namespace dw {
@@ -81,8 +90,6 @@ Textblock::Textblock (bool limitTextWidth)
availAscent = 100;
availDescent = 0;
- hoverTooltip = NULL;
-
this->limitTextWidth = limitTextWidth;
for (int layer = 0; layer < core::HIGHLIGHT_NUM_LAYERS; layer++) {
@@ -96,7 +103,10 @@ Textblock::Textblock (bool limitTextWidth)
Textblock::~Textblock ()
{
- //_MSG ("Textblock::~Textblock\n");
+ _MSG("Textblock::~Textblock\n");
+
+ /* make sure not to call a free'd tooltip (very fast overkill) */
+ hoverTooltip = NULL;
for (int i = 0; i < words->size(); i++) {
Word *word = words->getRef (i);
@@ -372,13 +382,13 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation)
* http://www.dillo.org/test/img/ */
childAllocation.y =
lineYOffsetCanvasAllocation (line, allocation)
- + (line->boxAscent - word->size.ascent);
- // - word->content.widget->getStyle()->margin.top;
+ + (line->boxAscent - word->size.ascent)
+ - word->content.widget->getStyle()->margin.top;
childAllocation.width = word->size.width;
- childAllocation.ascent = word->size.ascent;
- // + word->content.widget->getStyle()->margin.top;
- childAllocation.descent = word->size.descent;
- // + word->content.widget->getStyle()->margin.bottom;
+ childAllocation.ascent = word->size.ascent
+ + word->content.widget->getStyle()->margin.top;
+ childAllocation.descent = word->size.descent
+ + word->content.widget->getStyle()->margin.bottom;
oldChildAllocation = word->content.widget->getAllocation();
@@ -609,6 +619,11 @@ bool Textblock::buttonReleaseImpl (core::EventButton *event)
return sendSelectionEvent (core::SelectionState::BUTTON_RELEASE, event);
}
+/*
+ * Handle motion inside the widget
+ * (special care is necessary when switching from another widget,
+ * because hoverLink and hoverTooltip are meaningless then).
+ */
bool Textblock::motionNotifyImpl (core::EventMotion *event)
{
if (event->state & core::BUTTON1_MASK)
@@ -630,6 +645,7 @@ bool Textblock::motionNotifyImpl (core::EventMotion *event)
hoverLink = style->x_link;
hoverTooltip = style->x_tooltip;
}
+
// Show/hide tooltip
if (tooltipOld != hoverTooltip) {
if (tooltipOld)
@@ -639,21 +655,32 @@ bool Textblock::motionNotifyImpl (core::EventMotion *event)
} else if (hoverTooltip)
hoverTooltip->onMotion ();
- if (hoverLink != linkOld)
+ _MSG("MN tb=%p tooltipOld=%p hoverTooltip=%p\n",
+ this, tooltipOld, hoverTooltip);
+ if (hoverLink != linkOld) {
+ /* LinkEnter with hoverLink == -1 is the same as LinkLeave */
return layout->emitLinkEnter (this, hoverLink, -1, -1, -1);
- else
+ } else {
return hoverLink != -1;
+ }
}
}
void Textblock::enterNotifyImpl (core::EventCrossing *event)
{
+ _MSG(" tb=%p, ENTER NotifyImpl hoverTooltip=%p\n", this, hoverTooltip);
+ /* reset hoverLink so linkEnter is detected */
+ hoverLink = -2;
}
void Textblock::leaveNotifyImpl (core::EventCrossing *event)
{
- hoverLink = -1;
- (void) layout->emitLinkEnter (this, hoverLink, -1, -1, -1);
+ _MSG(" tb=%p, LEAVE NotifyImpl: hoverTooltip=%p\n", this, hoverTooltip);
+
+ /* leaving the viewport can't be handled by motionNotifyImpl() */
+ if (hoverLink >= 0)
+ layout->emitLinkEnter (this, -1, -1, -1, -1);
+
if (hoverTooltip) {
hoverTooltip->onLeave();
hoverTooltip = NULL;
@@ -671,10 +698,9 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
int nextWordStartX, wordStartX, wordX, nextWordX, yFirst, yLast;
int charPos = 0, link = -1, prevPos, wordIndex, lineIndex;
Word *word;
- bool found, r, withinContent = true;
+ bool found, r;
if (words->size () == 0) {
- withinContent = false;
wordIndex = -1;
} else {
lastLine = lines->getRef (lines->size () - 1);
@@ -683,12 +709,10 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
lastLine->boxDescent;
if (event->yCanvas < yFirst) {
// Above the first line: take the first word.
- withinContent = false;
wordIndex = 0;
charPos = 0;
} else if (event->yCanvas >= yLast) {
// Below the last line: take the last word.
- withinContent = false;
wordIndex = words->size () - 1;
word = words->getRef (wordIndex);
charPos = word->content.type == core::Content::TEXT ?
@@ -701,13 +725,11 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
if (event->yWidget >
(lineYOffsetWidget (line) + line->boxAscent + line->boxDescent)) {
// Choose this break.
- withinContent = false;
wordIndex = line->lastWord;
charPos = 0;
} else if (event->xWidget < lineXOffsetWidget (line)) {
// Left of the first word in the line.
wordIndex = line->firstWord;
- withinContent = false;
charPos = 0;
} else {
nextWordStartX = lineXOffsetWidget (line);
@@ -761,7 +783,6 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
if (!found) {
// No word found in this line (i.e. we are on the right side),
// take the last of this line.
- withinContent = false;
wordIndex = line->lastWord;
if (wordIndex >= words->size ())
wordIndex--;
@@ -775,8 +796,7 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType,
}
it = new TextblockIterator (this, core::Content::SELECTION_CONTENT,
wordIndex);
- r = selectionHandleEvent (eventType, it, charPos, link, event,
- withinContent);
+ r = selectionHandleEvent (eventType, it, charPos, link, event);
it->unref ();
return r;
}
@@ -1058,29 +1078,29 @@ void Textblock::wordWrap(int wordIndex)
// lastLine->boxDescent);
if (word->content.type == core::Content::WIDGET) {
+ int collapseMarginTop = 0;
+
lastLine->marginDescent =
misc::max (lastLine->marginDescent,
word->size.descent +
word->content.widget->getStyle()->margin.bottom);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1,
- // lastLine->descent);
+ if (lines->size () == 1 &&
+ word->content.widget->blockLevel () &&
+ getStyle ()->borderWidth.top == 0 &&
+ getStyle ()->padding.top == 0) {
+ // collapse top margin of parent element with top margin of first child
+ // see: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
+ collapseMarginTop = getStyle ()->margin.top;
+ }
- /* If the widget is not in the first line of the paragraph, its top
- * margin may make the line higher.
- */
- if (lines->size () > 1) {
- /* Here, we know already what the break and the bottom margin
- * contributed to the space before this line.
- */
- lastLine->boxAscent =
+ lastLine->boxAscent =
misc::max (lastLine->boxAscent,
+ word->size.ascent,
word->size.ascent
- + word->content.widget->getStyle()->margin.top);
+ + word->content.widget->getStyle()->margin.top
+ - collapseMarginTop);
- //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1,
- // lastLine->boxAscent);
- }
} else {
lastLine->marginDescent =
misc::max (lastLine->marginDescent, lastLine->boxDescent);
@@ -1197,11 +1217,7 @@ void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size)
widget->setAscent (availAscent);
widget->setDescent (availDescent);
widget->sizeRequest (size);
-// size->ascent -= wstyle->margin.top;
-// size->descent -= wstyle->margin.bottom;
} else {
- /* TODO: Use margin.{top|bottom} here, like above.
- * (No harm for the next future.) */
if (wstyle->width == core::style::LENGTH_AUTO ||
wstyle->height == core::style::LENGTH_AUTO)
widget->sizeRequest (&requisition);
@@ -1232,6 +1248,10 @@ void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size)
size->descent = (int) (len * availDescent);
}
}
+
+ /* ascent and descent in words do not contain margins. */
+ size->ascent -= wstyle->margin.top;
+ size->descent -= wstyle->margin.bottom;
}
/**
@@ -1499,11 +1519,6 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area)
word->content.type == core::Content::WIDGET) {
if (word->size.width > 0) {
- if (word->style->hasBackground ()) {
- drawBox (view, word->style, area, xWidget,
- yWidgetBase - line->boxAscent, word->size.width,
- line->boxAscent + line->boxDescent, false);
- }
if (word->content.type == core::Content::WIDGET) {
core::Widget *child = word->content.widget;
core::Rectangle childArea;
@@ -1511,6 +1526,11 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area)
if (child->intersects (area, &childArea))
child->draw (view, &childArea);
} else {
+ if (word->style->hasBackground ()) {
+ drawBox (view, word->style, area, xWidget,
+ yWidgetBase - line->boxAscent, word->size.width,
+ line->boxAscent + line->boxDescent, false);
+ }
drawText(wordIndex, view, area, xWidget, yWidgetBase);
}
}