⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rendertextcontrolsingleline.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/** * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)  * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "config.h"#include "RenderTextControlSingleLine.h"#include "CSSStyleSelector.h"#include "Event.h"#include "EventNames.h"#include "Frame.h"#include "FrameView.h"#include "HitTestResult.h"#include "HTMLInputElement.h"#include "HTMLNames.h"#include "InputElement.h"#include "LocalizedStrings.h"#include "MouseEvent.h"#include "PlatformKeyboardEvent.h"#include "RenderScrollbar.h"#include "RenderTheme.h"#include "SearchPopupMenu.h"#include "SelectionController.h"#include "Settings.h"#include "TextControlInnerElements.h"using namespace std;namespace WebCore {using namespace HTMLNames;RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node)    : RenderTextControl(node)    , m_placeholderVisible(false)    , m_searchPopupIsVisible(false)    , m_shouldDrawCapsLockIndicator(false)    , m_searchEventTimer(this, &RenderTextControlSingleLine::searchEventTimerFired)    , m_searchPopup(0){}RenderTextControlSingleLine::~RenderTextControlSingleLine(){    if (m_searchPopup) {        m_searchPopup->disconnectClient();        m_searchPopup = 0;    }     if (m_innerBlock)        m_innerBlock->detach();}bool RenderTextControlSingleLine::placeholderShouldBeVisible() const{    return inputElement()->placeholderShouldBeVisible();}void RenderTextControlSingleLine::updatePlaceholderVisibility(){    RenderStyle* parentStyle = m_innerBlock ? m_innerBlock->renderer()->style() : style();    RefPtr<RenderStyle> textBlockStyle = createInnerTextStyle(parentStyle);    HTMLElement* innerText = innerTextElement();    innerText->renderer()->setStyle(textBlockStyle);    for (Node* n = innerText->firstChild(); n; n = n->traverseNextNode(innerText)) {        if (RenderObject* renderer = n->renderer())            renderer->setStyle(textBlockStyle);    }    updateFromElement();}void RenderTextControlSingleLine::addSearchResult(){    ASSERT(node()->isHTMLElement());    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());    if (input->maxResults() <= 0)        return;    String value = input->value();    if (value.isEmpty())        return;    Settings* settings = document()->settings();    if (!settings || settings->privateBrowsingEnabled())        return;    int size = static_cast<int>(m_recentSearches.size());    for (int i = size - 1; i >= 0; --i) {        if (m_recentSearches[i] == value)            m_recentSearches.remove(i);    }    m_recentSearches.insert(0, value);    while (static_cast<int>(m_recentSearches.size()) > input->maxResults())        m_recentSearches.removeLast();    const AtomicString& name = autosaveName();    if (!m_searchPopup)        m_searchPopup = SearchPopupMenu::create(this);    m_searchPopup->saveRecentSearches(name, m_recentSearches);}void RenderTextControlSingleLine::stopSearchEventTimer(){    ASSERT(node()->isHTMLElement());    m_searchEventTimer.stop();}void RenderTextControlSingleLine::showPopup(){    ASSERT(node()->isHTMLElement());    if (m_searchPopupIsVisible)        return;    if (!m_searchPopup)        m_searchPopup = SearchPopupMenu::create(this);    if (!m_searchPopup->enabled())        return;    m_searchPopupIsVisible = true;    const AtomicString& name = autosaveName();    m_searchPopup->loadRecentSearches(name, m_recentSearches);    // Trim the recent searches list if the maximum size has changed since we last saved.    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());    if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) {        do {            m_recentSearches.removeLast();        } while (static_cast<int>(m_recentSearches.size()) > input->maxResults());        m_searchPopup->saveRecentSearches(name, m_recentSearches);    }    m_searchPopup->show(absoluteBoundingBoxRect(true), document()->view(), -1);}void RenderTextControlSingleLine::hidePopup(){    ASSERT(node()->isHTMLElement());    if (m_searchPopup)        m_searchPopup->hide();    m_searchPopupIsVisible = false;}void RenderTextControlSingleLine::subtreeHasChanged(){    bool wasEdited = isEdited();    RenderTextControl::subtreeHasChanged();    InputElement* input = inputElement();    input->setValueFromRenderer(input->constrainValue(text()));    if (RenderObject* cancelButtonRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)        updateCancelButtonVisibility(cancelButtonRenderer->style());    // If the incremental attribute is set, then dispatch the search event    if (input->searchEventsShouldBeDispatched())        startSearchEventTimer();    if (!wasEdited && node()->focused()) {        if (Frame* frame = document()->frame())            frame->textFieldDidBeginEditing(static_cast<Element*>(node()));    }    if (node()->focused()) {        if (Frame* frame = document()->frame())            frame->textDidChangeInTextField(static_cast<Element*>(node()));    }}void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, int tx, int ty){    RenderTextControl::paint(paintInfo, tx, ty);    if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator) {        IntRect contentsRect = contentBoxRect();        // Convert the rect into the coords used for painting the content        contentsRect.move(tx + x(), ty + y());        theme()->paintCapsLockIndicator(this, paintInfo, contentsRect);    }}void RenderTextControlSingleLine::layout(){    int oldHeight = height();    calcHeight();    int oldWidth = width();    calcWidth();    bool relayoutChildren = oldHeight != height() || oldWidth != width();    RenderBox* innerTextRenderer = innerTextElement()->renderBox();    RenderBox* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderBox() : 0;    // Set the text block height    int desiredHeight = textBlockHeight();    int currentHeight = innerTextRenderer->height();    if (m_innerBlock || currentHeight > height()) {        if (desiredHeight != currentHeight)            relayoutChildren = true;        innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));    }    if (m_innerBlock) {        ASSERT(innerBlockRenderer);        if (desiredHeight != innerBlockRenderer->height())            relayoutChildren = true;        innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));    }    // Set the text block width    int desiredWidth = textBlockWidth();    if (desiredWidth != innerTextRenderer->width())        relayoutChildren = true;    innerTextRenderer->style()->setWidth(Length(desiredWidth, Fixed));    if (m_innerBlock) {        int innerBlockWidth = width() - paddingLeft() - paddingRight() - borderLeft() - borderRight();        if (innerBlockWidth != innerBlockRenderer->width())            relayoutChildren = true;        innerBlockRenderer->style()->setWidth(Length(innerBlockWidth, Fixed));    }    RenderBlock::layoutBlock(relayoutChildren);    // For text fields, center the inner text vertically    // Don't do this for search fields, since we don't honor height for them    if (!m_innerBlock) {        currentHeight = innerTextRenderer->height();        if (currentHeight < height())            innerTextRenderer->setLocation(innerTextRenderer->x(), (height() - currentHeight) / 2);    }}bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction hitTestAction){    // If we're within the text control, we want to act as if we've hit the inner text block element, in case the point    // was on the control but not on the inner element (see Radar 4617841).    // In a search field, we want to act as if we've hit the results block if we're to the left of the inner text block,    // and act as if we've hit the close block if we're to the right of the inner text block.    if (!RenderTextControl::nodeAtPoint(request, result, xPos, yPos, tx, ty, hitTestAction))        return false;    if (result.innerNode() != node() && result.innerNode() != innerTextElement())        return false;    hitInnerTextBlock(result, xPos, yPos, tx, ty);    if (!m_innerBlock)        return true;    Node* innerNode = 0;    RenderBox* innerBlockRenderer = m_innerBlock->renderBox();    RenderBox* innerTextRenderer = innerTextElement()->renderBox();    IntPoint localPoint = result.localPoint();    localPoint.move(-innerBlockRenderer->x(), -innerBlockRenderer->y());    int textLeft = tx + x() + innerBlockRenderer->x() + innerTextRenderer->x();    if (m_resultsButton && m_resultsButton->renderer() && xPos < textLeft)        innerNode = m_resultsButton.get();    if (!innerNode) {        int textRight = textLeft + innerTextRenderer->width();        if (m_cancelButton && m_cancelButton->renderer() && xPos > textRight)            innerNode = m_cancelButton.get();    }    if (innerNode) {        result.setInnerNode(innerNode);        localPoint.move(-innerNode->renderBox()->x(), -innerNode->renderBox()->y());    }    result.setLocalPoint(localPoint);    return true;}void RenderTextControlSingleLine::forwardEvent(Event* event){    RenderBox* innerTextRenderer = innerTextElement()->renderBox();    if (event->type() == eventNames().blurEvent) {        if (innerTextRenderer) {            if (RenderLayer* innerLayer = innerTextRenderer->layer())                innerLayer->scrollToOffset(style()->direction() == RTL ? innerLayer->scrollWidth() : 0, 0);        }        capsLockStateMayHaveChanged();    } else if (event->type() == eventNames().focusEvent)        capsLockStateMayHaveChanged();    if (!event->isMouseEvent()) {        RenderTextControl::forwardEvent(event);        return;    }    FloatPoint localPoint = innerTextRenderer->absoluteToLocal(FloatPoint(static_cast<MouseEvent*>(event)->pageX(), static_cast<MouseEvent*>(event)->pageY()), false, true);    if (m_resultsButton && localPoint.x() < innerTextRenderer->borderBoxRect().x())        m_resultsButton->defaultEventHandler(event);    else if (m_cancelButton && localPoint.x() > innerTextRenderer->borderBoxRect().right())        m_cancelButton->defaultEventHandler(event);    else        RenderTextControl::forwardEvent(event);}void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle){    RenderTextControl::styleDidChange(diff, oldStyle);    if (RenderObject* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderer() : 0) {        // 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.        innerBlockRenderer->style()->setHeight(Length());        innerBlockRenderer->style()->setWidth(Length());        innerBlockRenderer->setStyle(createInnerBlockStyle(style()));    }    if (RenderObject* resultsRenderer = m_resultsButton ? m_resultsButton->renderer() : 0)        resultsRenderer->setStyle(createResultsButtonStyle(style()));    if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)        cancelRenderer->setStyle(createCancelButtonStyle(style()));}void RenderTextControlSingleLine::capsLockStateMayHaveChanged(){    if (!node() || !document())        return;    // Only draw the caps lock indicator if these things are true:    // 1) The field is a password field    // 2) The frame is active    // 3) The element is focused    // 4) The caps lock is on    bool shouldDrawCapsLockIndicator = false;    if (Frame* frame = document()->frame())        shouldDrawCapsLockIndicator = inputElement()->isPasswordField()                                      && frame->selection()->isFocusedAndActive()                                      && document()->focusedNode() == node()                                      && PlatformKeyboardEvent::currentCapsLockState();    if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {        m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;        repaint();    }}int RenderTextControlSingleLine::textBlockWidth() const{    int width = RenderTextControl::textBlockWidth();    if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) {        resultsRenderer->calcWidth();        width -= resultsRenderer->width() + resultsRenderer->marginLeft() + resultsRenderer->marginRight();    }    if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) {        cancelRenderer->calcWidth();        width -= cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -