📄 rendertextcontrolsingleline.cpp
字号:
} return width;}int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const{ int factor = inputElement()->size(); if (factor <= 0) factor = 20; int result = static_cast<int>(ceilf(charWidth * factor)); if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) result += resultsRenderer->borderLeft() + resultsRenderer->borderRight() + resultsRenderer->paddingLeft() + resultsRenderer->paddingRight(); if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) result += cancelRenderer->borderLeft() + cancelRenderer->borderRight() + cancelRenderer->paddingLeft() + cancelRenderer->paddingRight(); return result;}void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineHeight){ if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) { toRenderBlock(resultsRenderer)->calcHeight(); setHeight(max(height(), resultsRenderer->borderTop() + resultsRenderer->borderBottom() + resultsRenderer->paddingTop() + resultsRenderer->paddingBottom() + resultsRenderer->marginTop() + resultsRenderer->marginBottom())); lineHeight = max(lineHeight, resultsRenderer->height()); } if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) { toRenderBlock(cancelRenderer)->calcHeight(); setHeight(max(height(), cancelRenderer->borderTop() + cancelRenderer->borderBottom() + cancelRenderer->paddingTop() + cancelRenderer->paddingBottom() + cancelRenderer->marginTop() + cancelRenderer->marginBottom())); lineHeight = max(lineHeight, cancelRenderer->height()); } setHeight(height() + lineHeight);}void RenderTextControlSingleLine::createSubtreeIfNeeded(){ if (!inputElement()->isSearchField()) { RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get()); return; } if (!m_innerBlock) { // Create the inner block element m_innerBlock = new TextControlInnerElement(document(), node()); m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena()); } if (!m_resultsButton) { // Create the search results button element m_resultsButton = new SearchFieldResultsButtonElement(document()); m_resultsButton->attachInnerElement(m_innerBlock.get(), createResultsButtonStyle(m_innerBlock->renderer()->style()), renderArena()); } // Create innerText element before adding the cancel button RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get()); if (!m_cancelButton) { // Create the cancel button element m_cancelButton = new SearchFieldCancelButtonElement(document()); m_cancelButton->attachInnerElement(m_innerBlock.get(), createCancelButtonStyle(m_innerBlock->renderer()->style()), renderArena()); }}void RenderTextControlSingleLine::updateFromElement(){ createSubtreeIfNeeded(); RenderTextControl::updateFromElement(); bool placeholderVisibilityShouldChange = m_placeholderVisible != placeholderShouldBeVisible(); m_placeholderVisible = placeholderShouldBeVisible(); if (RenderObject* cancelButtonRenderer = m_cancelButton ? m_cancelButton->renderer() : 0) updateCancelButtonVisibility(cancelButtonRenderer->style()); if (m_placeholderVisible) { ExceptionCode ec = 0; innerTextElement()->setInnerText(inputElement()->placeholderValue(), ec); ASSERT(!ec); } else if (!formControlElement()->valueMatchesRenderer() || placeholderVisibilityShouldChange) setInnerTextValue(inputElement()->value()); if (m_searchPopupIsVisible) m_searchPopup->updateFromElement();}void RenderTextControlSingleLine::cacheSelection(int start, int end){ inputElement()->cacheSelection(start, end);}PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const{ RefPtr<RenderStyle> textBlockStyle; if (placeholderShouldBeVisible()) { RenderStyle* pseudoStyle = getCachedPseudoStyle(INPUT_PLACEHOLDER); textBlockStyle = RenderStyle::clone(pseudoStyle); } else { textBlockStyle = RenderStyle::create(); textBlockStyle->inheritFrom(startStyle); } adjustInnerTextStyle(startStyle, textBlockStyle.get()); textBlockStyle->setWhiteSpace(PRE); textBlockStyle->setWordWrap(NormalWordWrap); textBlockStyle->setOverflowX(OHIDDEN); textBlockStyle->setOverflowY(OHIDDEN); // Do not allow line-height to be smaller than our default. if (textBlockStyle->font().lineSpacing() > lineHeight(true, true)) textBlockStyle->setLineHeight(Length(-100.0f, Percent)); textBlockStyle->setDisplay(m_innerBlock ? INLINE_BLOCK : BLOCK); // We're adding one extra pixel of padding to match WinIE. textBlockStyle->setPaddingLeft(Length(1, Fixed)); textBlockStyle->setPaddingRight(Length(1, Fixed)); // When the placeholder is going to be displayed, temporarily override the text security to be "none". // After this, updateFromElement will immediately update the text displayed. // When the placeholder is no longer visible, updatePlaceholderVisiblity will reset the style, // and the text security mode will be set back to the computed value correctly. if (placeholderShouldBeVisible()) textBlockStyle->setTextSecurity(TSNONE); return textBlockStyle.release();}PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const RenderStyle* startStyle) const{ ASSERT(node()->isHTMLElement()); RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create(); innerBlockStyle->inheritFrom(startStyle); innerBlockStyle->setDisplay(BLOCK); innerBlockStyle->setDirection(LTR); // We don't want the shadow dom to be editable, so we set this block to read-only in case the input itself is editable. innerBlockStyle->setUserModify(READ_ONLY); return innerBlockStyle.release();}PassRefPtr<RenderStyle> RenderTextControlSingleLine::createResultsButtonStyle(const RenderStyle* startStyle) const{ ASSERT(node()->isHTMLElement()); HTMLInputElement* input = static_cast<HTMLInputElement*>(node()); RefPtr<RenderStyle> resultsBlockStyle; if (input->maxResults() < 0) resultsBlockStyle = getCachedPseudoStyle(SEARCH_DECORATION); else if (!input->maxResults()) resultsBlockStyle = getCachedPseudoStyle(SEARCH_RESULTS_DECORATION); else resultsBlockStyle = getCachedPseudoStyle(SEARCH_RESULTS_BUTTON); if (!resultsBlockStyle) resultsBlockStyle = RenderStyle::create(); if (startStyle) resultsBlockStyle->inheritFrom(startStyle); return resultsBlockStyle.release();}PassRefPtr<RenderStyle> RenderTextControlSingleLine::createCancelButtonStyle(const RenderStyle* startStyle) const{ ASSERT(node()->isHTMLElement()); RefPtr<RenderStyle> cancelBlockStyle; if (RefPtr<RenderStyle> pseudoStyle = getCachedPseudoStyle(SEARCH_CANCEL_BUTTON)) // We may be sharing style with another search field, but we must not share the cancel button style. cancelBlockStyle = RenderStyle::clone(pseudoStyle.get()); else cancelBlockStyle = RenderStyle::create(); if (startStyle) cancelBlockStyle->inheritFrom(startStyle); updateCancelButtonVisibility(cancelBlockStyle.get()); return cancelBlockStyle.release();}void RenderTextControlSingleLine::updateCancelButtonVisibility(RenderStyle* style) const{ ASSERT(node()->isHTMLElement()); HTMLInputElement* input = static_cast<HTMLInputElement*>(node()); style->setVisibility(input->value().isEmpty() ? HIDDEN : VISIBLE);}const AtomicString& RenderTextControlSingleLine::autosaveName() const{ return static_cast<Element*>(node())->getAttribute(autosaveAttr);}void RenderTextControlSingleLine::startSearchEventTimer(){ ASSERT(node()->isHTMLElement()); unsigned length = text().length(); // If there's no text, fire the event right away. if (!length) { stopSearchEventTimer(); static_cast<HTMLInputElement*>(node())->onSearch(); return; } // After typing the first key, we wait 0.5 seconds. // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on. m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length));}void RenderTextControlSingleLine::searchEventTimerFired(Timer<RenderTextControlSingleLine>*){ ASSERT(node()->isHTMLElement()); static_cast<HTMLInputElement*>(node())->onSearch();}// PopupMenuClient methodsvoid RenderTextControlSingleLine::valueChanged(unsigned listIndex, bool fireEvents){ ASSERT(node()->isHTMLElement()); ASSERT(static_cast<int>(listIndex) < listSize()); HTMLInputElement* input = static_cast<HTMLInputElement*>(node()); if (static_cast<int>(listIndex) == (listSize() - 1)) { if (fireEvents) { m_recentSearches.clear(); const AtomicString& name = autosaveName(); if (!name.isEmpty()) { if (!m_searchPopup) m_searchPopup = SearchPopupMenu::create(this); m_searchPopup->saveRecentSearches(name, m_recentSearches); } } } else { input->setValue(itemText(listIndex)); if (fireEvents) input->onSearch(); input->select(); }}String RenderTextControlSingleLine::itemText(unsigned listIndex) const{ int size = listSize(); if (size == 1) { ASSERT(!listIndex); return searchMenuNoRecentSearchesText(); } if (!listIndex) return searchMenuRecentSearchesText(); if (itemIsSeparator(listIndex)) return String(); if (static_cast<int>(listIndex) == (size - 1)) return searchMenuClearRecentSearchesText(); return m_recentSearches[listIndex - 1];}bool RenderTextControlSingleLine::itemIsEnabled(unsigned listIndex) const{ if (!listIndex || itemIsSeparator(listIndex)) return false; return true;}PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const{ return menuStyle();}PopupMenuStyle RenderTextControlSingleLine::menuStyle() const{ return PopupMenuStyle(style()->color(), style()->backgroundColor(), style()->font(), style()->visibility() == VISIBLE);}int RenderTextControlSingleLine::clientInsetLeft() const{ // Inset the menu by the radius of the cap on the left so that // it only runs along the straight part of the bezel. return height() / 2;}int RenderTextControlSingleLine::clientInsetRight() const{ // Inset the menu by the radius of the cap on the right so that // it only runs along the straight part of the bezel (unless it needs // to be wider). return height() / 2;}int RenderTextControlSingleLine::clientPaddingLeft() const{ int padding = paddingLeft(); if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) padding += resultsRenderer->width(); return padding;}int RenderTextControlSingleLine::clientPaddingRight() const{ int padding = paddingRight(); if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) padding += cancelRenderer->width(); return padding;}int RenderTextControlSingleLine::listSize() const{ // If there are no recent searches, then our menu will have 1 "No recent searches" item. if (!m_recentSearches.size()) return 1; // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item. return m_recentSearches.size() + 3;}int RenderTextControlSingleLine::selectedIndex() const{ return -1;}bool RenderTextControlSingleLine::itemIsSeparator(unsigned listIndex) const{ // The separator will be the second to last item in our list. return static_cast<int>(listIndex) == (listSize() - 2);}bool RenderTextControlSingleLine::itemIsLabel(unsigned listIndex) const{ return listIndex == 0;}bool RenderTextControlSingleLine::itemIsSelected(unsigned) const{ return false;}void RenderTextControlSingleLine::setTextFromItem(unsigned listIndex){ ASSERT(node()->isHTMLElement()); static_cast<HTMLInputElement*>(node())->setValue(itemText(listIndex));}FontSelector* RenderTextControlSingleLine::fontSelector() const{ return document()->styleSelector()->fontSelector();}HostWindow* RenderTextControlSingleLine::hostWindow() const{ return document()->view()->hostWindow();}PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize){ RefPtr<Scrollbar> widget; bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR); if (hasCustomScrollbarStyle) widget = RenderScrollbar::createCustomScrollbar(client, orientation, this); else widget = Scrollbar::createNativeScrollbar(client, orientation, controlSize); return widget.release();}InputElement* RenderTextControlSingleLine::inputElement() const{ return toInputElement(static_cast<Element*>(node()));}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -