void RenderTextControlSingleLine::autoscroll(const IntPoint& position)
{
    RenderTextControlInnerBlock* renderer = innerTextElement()->renderer();
    if (!renderer)
        return;
    RenderLayer* layer = renderer->layer();
    if (layer)
        layer->autoscroll(position);
}
bool RenderTextControlSingleLine::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Element** stopElement, RenderBox* startBox, const IntPoint& wheelEventAbsolutePoint)
{
    RenderTextControlInnerBlock* renderer = innerTextElement()->renderer();
    if (!renderer)
        return false;
    RenderLayer* layer = renderer->layer();
    if (layer && layer->scroll(direction, granularity, multiplier))
        return true;
    return RenderBlockFlow::scroll(direction, granularity, multiplier, stopElement, startBox, wheelEventAbsolutePoint);
}
Exemplo n.º 3
0
void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderBlockFlow::styleDidChange(diff, oldStyle);
    TextControlInnerTextElement* innerText = innerTextElement();
    if (!innerText)
        return;
    RenderTextControlInnerBlock* innerTextRenderer = innerText->renderer();
    if (innerTextRenderer) {
        // We may have set the width and the height in the old style in layout().
        // Reset them now to avoid getting a spurious layout hint.
        innerTextRenderer->style().setHeight(Length());
        innerTextRenderer->style().setWidth(Length());
        innerTextRenderer->setStyle(createInnerTextStyle(&style()));
    }
    textFormControlElement().updatePlaceholderVisibility();
}
String HTMLTextFormControlElement::valueWithHardLineBreaks() const
{
    // FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer.
    // While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
    if (!isTextFormControl())
        return value();

    TextControlInnerTextElement* innerText = innerTextElement();
    if (!innerText)
        return value();

    RenderTextControlInnerBlock* renderer = innerText->renderer();
    if (!renderer)
        return value();

    Node* breakNode;
    unsigned breakOffset;
    RootInlineBox* line = renderer->firstRootBox();
    if (!line)
        return value();

    getNextSoftBreak(line, breakNode, breakOffset);

    StringBuilder result;
    for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(*node, innerText)) {
        if (is<HTMLBRElement>(*node))
            result.append(newlineCharacter);
        else if (is<Text>(*node)) {
            String data = downcast<Text>(*node).data();
            unsigned length = data.length();
            unsigned position = 0;
            while (breakNode == node && breakOffset <= length) {
                if (breakOffset > position) {
                    result.append(data, position, breakOffset - position);
                    position = breakOffset;
                    result.append(newlineCharacter);
                }
                getNextSoftBreak(line, breakNode, breakOffset);
            }
            result.append(data, position, length - position);
        }
        while (breakNode == node)
            getNextSoftBreak(line, breakNode, breakOffset);
    }
    stripTrailingNewline(result);
    return result.toString();
}
void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    m_desiredInnerTextLogicalHeight = -1;
    RenderTextControl::styleDidChange(diff, oldStyle);

    // We may have set the width and the height in the old style in layout().
    // Reset them now to avoid getting a spurious layout hint.
    HTMLElement* innerBlock = innerBlockElement();
    if (RenderObject* innerBlockRenderer = innerBlock ? innerBlock->renderer() : 0) {
        innerBlockRenderer->style().setHeight(Length());
        innerBlockRenderer->style().setWidth(Length());
    }
    HTMLElement* container = containerElement();
    if (RenderObject* containerRenderer = container ? container->renderer() : 0) {
        containerRenderer->style().setHeight(Length());
        containerRenderer->style().setWidth(Length());
    }
    RenderTextControlInnerBlock* innerTextRenderer = innerTextElement()->renderer();
    if (innerTextRenderer && diff == StyleDifferenceLayout)
        innerTextRenderer->setNeedsLayout(MarkContainingBlockChain);
    if (HTMLElement* placeholder = inputElement().placeholderElement())
        placeholder->setInlineStyleProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip);
    setHasOverflowClip(false);
}
void RenderTextControlSingleLine::layout()
{
    StackStats::LayoutCheckPoint layoutCheckPoint;

    // FIXME: We should remove the height-related hacks in layout() and
    // styleDidChange(). We need them because
    // - Center the inner elements vertically if the input height is taller than
    //   the intrinsic height of the inner elements.
    // - Shrink the inner elment heights if the input height is samller than the
    //   intrinsic heights of the inner elements.

    // We don't honor paddings and borders for textfields without decorations
    // and type=search if the text height is taller than the contentHeight()
    // because of compability.

    RenderTextControlInnerBlock* innerTextRenderer = innerTextElement()->renderer();
    RenderBox* innerBlockRenderer = innerBlockElement() ? innerBlockElement()->renderBox() : 0;

    // To ensure consistency between layouts, we need to reset any conditionally overriden height.
    if (innerTextRenderer && !innerTextRenderer->style().logicalHeight().isAuto()) {
        innerTextRenderer->style().setLogicalHeight(Length(Auto));
        setNeedsLayoutOnAncestors(innerTextRenderer, this);
    }
    if (innerBlockRenderer && !innerBlockRenderer->style().logicalHeight().isAuto()) {
        innerBlockRenderer->style().setLogicalHeight(Length(Auto));
        setNeedsLayoutOnAncestors(innerBlockRenderer, this);
    }

    RenderBlockFlow::layoutBlock(false);

    HTMLElement* container = containerElement();
    RenderBox* containerRenderer = container ? container->renderBox() : 0;

    // Set the text block height
    LayoutUnit desiredLogicalHeight = textBlockLogicalHeight();
    LayoutUnit logicalHeightLimit = computeLogicalHeightLimit();
    if (innerTextRenderer && innerTextRenderer->logicalHeight() > logicalHeightLimit) {
        if (desiredLogicalHeight != innerTextRenderer->logicalHeight())
            setNeedsLayout(MarkOnlyThis);

        m_desiredInnerTextLogicalHeight = desiredLogicalHeight;

        innerTextRenderer->style().setLogicalHeight(Length(desiredLogicalHeight, Fixed));
        innerTextRenderer->setNeedsLayout(MarkOnlyThis);
        if (innerBlockRenderer) {
            innerBlockRenderer->style().setLogicalHeight(Length(desiredLogicalHeight, Fixed));
            innerBlockRenderer->setNeedsLayout(MarkOnlyThis);
        }
    }
    // The container might be taller because of decoration elements.
    if (containerRenderer) {
        containerRenderer->layoutIfNeeded();
        LayoutUnit containerLogicalHeight = containerRenderer->logicalHeight();
        if (containerLogicalHeight > logicalHeightLimit) {
            containerRenderer->style().setLogicalHeight(Length(logicalHeightLimit, Fixed));
            setNeedsLayout(MarkOnlyThis);
        } else if (containerRenderer->logicalHeight() < contentLogicalHeight()) {
            containerRenderer->style().setLogicalHeight(Length(contentLogicalHeight(), Fixed));
            setNeedsLayout(MarkOnlyThis);
        } else
            containerRenderer->style().setLogicalHeight(Length(containerLogicalHeight, Fixed));
    }

    // If we need another layout pass, we have changed one of children's height so we need to relayout them.
    if (needsLayout())
        RenderBlockFlow::layoutBlock(true);

    // Center the child block in the block progression direction (vertical centering for horizontal text fields).
    if (!container && innerTextRenderer && innerTextRenderer->height() != contentLogicalHeight())
        centerRenderer(*innerTextRenderer);
    else
        centerContainerIfNeeded(containerRenderer);

    // Ignores the paddings for the inner spin button.
    if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) {
        RenderBox* parentBox = innerSpinBox->parentBox();
        if (containerRenderer && !containerRenderer->style().isLeftToRightDirection())
            innerSpinBox->setLogicalLocation(LayoutPoint(-paddingLogicalLeft(), -paddingBefore()));
        else
            innerSpinBox->setLogicalLocation(LayoutPoint(parentBox->logicalWidth() - innerSpinBox->logicalWidth() + paddingLogicalRight(), -paddingBefore()));
        innerSpinBox->setLogicalHeight(logicalHeight() - borderBefore() - borderAfter());
    }

    HTMLElement* placeholderElement = inputElement().placeholderElement();
    if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
        LayoutSize innerTextSize;
        if (innerTextRenderer)
            innerTextSize = innerTextRenderer->size();
        placeholderBox->style().setWidth(Length(innerTextSize.width() - placeholderBox->horizontalBorderAndPaddingExtent(), Fixed));
        placeholderBox->style().setHeight(Length(innerTextSize.height() - placeholderBox->verticalBorderAndPaddingExtent(), Fixed));
        bool neededLayout = placeholderBox->needsLayout();
        bool placeholderBoxHadLayout = placeholderBox->everHadLayout();
        placeholderBox->layoutIfNeeded();
        LayoutPoint textOffset;
        if (innerTextRenderer)
            textOffset = innerTextRenderer->location();
        if (innerBlockElement() && innerBlockElement()->renderBox())
            textOffset += toLayoutSize(innerBlockElement()->renderBox()->location());
        if (containerRenderer)
            textOffset += toLayoutSize(containerRenderer->location());
        placeholderBox->setLocation(textOffset);

        if (!placeholderBoxHadLayout && placeholderBox->checkForRepaintDuringLayout()) {
            // This assumes a shadow tree without floats. If floats are added, the
            // logic should be shared with RenderBlock::layoutBlockChild.
            placeholderBox->repaint();
        }
        // The placeholder gets layout last, after the parent text control and its other children,
        // so in order to get the correct overflow from the placeholder we need to recompute it now.
        if (neededLayout)
            computeOverflow(clientLogicalBottom());
    }

#if PLATFORM(IOS)
    // FIXME: We should not be adjusting styles during layout. <rdar://problem/7675493>
    if (inputElement().isSearchField())
        RenderThemeIOS::adjustRoundBorderRadius(style(), *this);
#endif
}