diff options
Diffstat (limited to 'dw/textblock.cc')
-rw-r--r-- | dw/textblock.cc | 110 |
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); } } |