📄 renderlistbox.cpp
字号:
const UChar* string = itemText.characters(); TextRun textRun(string, length, 0, 0, 0, itemStyle->direction() == RTL, itemStyle->unicodeBidi() == Override, false, false); // Draw the item text if (itemStyle->visibility() != HIDDEN) paintInfo.context->drawBidiText(itemFont, textRun, r.location());}void RenderListBox::paintItemBackground(PaintInfo& paintInfo, int tx, int ty, int listIndex){ HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node()); const Vector<HTMLElement*>& listItems = select->listItems(); HTMLElement* element = listItems[listIndex]; OptionElement* optionElement = toOptionElement(element); Color backColor; if (optionElement && optionElement->selected()) { if (document()->frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node()) backColor = theme()->activeListBoxSelectionBackgroundColor(); else backColor = theme()->inactiveListBoxSelectionBackgroundColor(); } else backColor = element->renderStyle() ? element->renderStyle()->backgroundColor() : style()->backgroundColor(); // Draw the background for this list box item if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDEN) { IntRect itemRect = itemBoundingBoxRect(tx, ty, listIndex); itemRect.intersect(controlClipRect(tx, ty)); paintInfo.context->fillRect(itemRect, backColor); }}bool RenderListBox::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty){ if (!m_vBar) return false; IntRect vertRect(_tx + width() - borderRight() - m_vBar->width(), _ty, m_vBar->width(), height() - borderTop() - borderBottom()); if (vertRect.contains(_x, _y)) { result.setScrollbar(m_vBar.get()); return true; } return false;}int RenderListBox::listIndexAtOffset(int offsetX, int offsetY){ if (!numItems()) return -1; if (offsetY < borderTop() + paddingTop() || offsetY > height() - paddingBottom() - borderBottom()) return -1; int scrollbarWidth = m_vBar ? m_vBar->width() : 0; if (offsetX < borderLeft() + paddingLeft() || offsetX > width() - borderRight() - paddingRight() - scrollbarWidth) return -1; int newOffset = (offsetY - borderTop() - paddingTop()) / itemHeight() + m_indexOffset; return newOffset < numItems() ? newOffset : -1;}void RenderListBox::panScroll(const IntPoint& panStartMousePosition){ const int maxSpeed = 20; const int iconRadius = 7; const int speedReducer = 4; // FIXME: This doesn't work correctly with transforms. FloatPoint absOffset = localToAbsolute(); IntPoint currentMousePosition = document()->frame()->eventHandler()->currentMousePosition(); // We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent static IntPoint previousMousePosition; if (currentMousePosition.y() < 0) currentMousePosition = previousMousePosition; else previousMousePosition = currentMousePosition; int yDelta = currentMousePosition.y() - panStartMousePosition.y(); // If the point is too far from the center we limit the speed yDelta = max(min(yDelta, maxSpeed), -maxSpeed); if(abs(yDelta) < iconRadius) // at the center we let the space for the icon return; if (yDelta > 0) //offsetY = view()->viewHeight(); absOffset.move(0, listHeight()); else if (yDelta < 0) yDelta--; // Let's attenuate the speed yDelta /= speedReducer; IntPoint scrollPoint(0,0); scrollPoint.setY(absOffset.y() + yDelta); int newOffset = scrollToward(scrollPoint); if (newOffset < 0) return; m_inAutoscroll = true; HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node()); select->updateListBoxSelection(!select->multiple()); m_inAutoscroll = false;}int RenderListBox::scrollToward(const IntPoint& destination){ // FIXME: This doesn't work correctly with transforms. FloatPoint absPos = localToAbsolute(); int offsetX = destination.x() - absPos.x(); int offsetY = destination.y() - absPos.y(); int rows = numVisibleItems(); int offset = m_indexOffset; if (offsetY < borderTop() + paddingTop() && scrollToRevealElementAtListIndex(offset - 1)) return offset - 1; if (offsetY > height() - paddingBottom() - borderBottom() && scrollToRevealElementAtListIndex(offset + rows)) return offset + rows - 1; return listIndexAtOffset(offsetX, offsetY);}void RenderListBox::autoscroll(){ IntPoint pos = document()->frame()->view()->windowToContents(document()->frame()->eventHandler()->currentMousePosition()); int endIndex = scrollToward(pos); if (endIndex >= 0) { HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node()); m_inAutoscroll = true; if (!select->multiple()) select->setActiveSelectionAnchorIndex(endIndex); select->setActiveSelectionEndIndex(endIndex); select->updateListBoxSelection(!select->multiple()); m_inAutoscroll = false; }}void RenderListBox::stopAutoscroll(){ static_cast<HTMLSelectElement*>(node())->listBoxOnChange();}bool RenderListBox::scrollToRevealElementAtListIndex(int index){ if (index < 0 || index >= numItems() || listIndexIsVisible(index)) return false; int newOffset; if (index < m_indexOffset) newOffset = index; else newOffset = index - numVisibleItems() + 1; m_indexOffset = newOffset; if (m_vBar) m_vBar->setValue(m_indexOffset); return true;}bool RenderListBox::listIndexIsVisible(int index){ return index >= m_indexOffset && index < m_indexOffset + numVisibleItems();}bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier){ return m_vBar && m_vBar->scroll(direction, granularity, multiplier);}void RenderListBox::valueChanged(unsigned listIndex){ HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node()); select->setSelectedIndex(select->listToOptionIndex(listIndex)); select->onChange();}void RenderListBox::valueChanged(Scrollbar*){ int newOffset = m_vBar->value(); if (newOffset != m_indexOffset) { m_indexOffset = newOffset; repaint(); // Fire the scroll DOM event. node()->dispatchEventForType(eventNames().scrollEvent, false, false); }}int RenderListBox::itemHeight() const{ return style()->font().height() + rowSpacing;}int RenderListBox::verticalScrollbarWidth() const{ return m_vBar ? m_vBar->width() : 0;}// FIXME: We ignore padding in the vertical direction as far as these values are concerned, since that's// how the control currently paints.int RenderListBox::scrollWidth() const{ // There is no horizontal scrolling allowed. return clientWidth();}int RenderListBox::scrollHeight() const{ return max(clientHeight(), listHeight());}int RenderListBox::scrollLeft() const{ return 0;}void RenderListBox::setScrollLeft(int){}int RenderListBox::scrollTop() const{ return m_indexOffset * itemHeight();}void RenderListBox::setScrollTop(int newTop){ // Determine an index and scroll to it. int index = newTop / itemHeight(); if (index < 0 || index >= numItems() || index == m_indexOffset) return; m_indexOffset = index; if (m_vBar) m_vBar->setValue(index);}bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction){ if (!RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction)) return false; const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(node())->listItems(); int size = numItems(); tx += this->x(); ty += this->y(); for (int i = 0; i < size; ++i) { if (itemBoundingBoxRect(tx, ty, i).contains(x, y)) { if (HTMLElement* node = listItems[i]) { result.setInnerNode(node); if (!result.innerNonSharedNode()) result.setInnerNonSharedNode(node); result.setLocalPoint(IntPoint(x - tx, y - ty)); break; } } } return true;}IntRect RenderListBox::controlClipRect(int tx, int ty) const{ IntRect clipRect = contentBoxRect(); clipRect.move(tx, ty); return clipRect;}bool RenderListBox::isActive() const{ Page* page = document()->frame()->page(); return page && page->focusController()->isActive();}void RenderListBox::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect){ IntRect scrollRect = rect; scrollRect.move(width() - borderRight() - scrollbar->width(), borderTop()); repaintRectangle(scrollRect);}PassRefPtr<Scrollbar> RenderListBox::createScrollbar(){ RefPtr<Scrollbar> widget; bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR); if (hasCustomScrollbarStyle) widget = RenderScrollbar::createCustomScrollbar(this, VerticalScrollbar, this); else widget = Scrollbar::createNativeScrollbar(this, VerticalScrollbar, theme()->scrollbarControlSizeForPart(ListboxPart)); document()->view()->addChild(widget.get()); return widget.release();}void RenderListBox::destroyScrollbar(){ if (!m_vBar) return; m_vBar->removeFromParent(); m_vBar->setClient(0); m_vBar = 0;}void RenderListBox::setHasVerticalScrollbar(bool hasScrollbar){ if (hasScrollbar == (m_vBar != 0)) return; if (hasScrollbar) m_vBar = createScrollbar(); else destroyScrollbar(); if (m_vBar) m_vBar->styleChanged();#if ENABLE(DASHBOARD_SUPPORT) // Force an update since we know the scrollbars have changed things. if (document()->hasDashboardRegions()) document()->setDashboardRegionsDirty(true);#endif}} // namespace WebCore
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -