Chromium Code Reviews| Index: Source/core/rendering/RenderListBox.cpp |
| diff --git a/Source/core/rendering/RenderListBox.cpp b/Source/core/rendering/RenderListBox.cpp |
| index bdeaa58697891a4f86199f8e8b4f0ef9ea4fb248..d2ab6530d4d6bf7b5ce1b6ee9109eca51ae5e3ef 100644 |
| --- a/Source/core/rendering/RenderListBox.cpp |
| +++ b/Source/core/rendering/RenderListBox.cpp |
| @@ -86,6 +86,7 @@ RenderListBox::RenderListBox(Element* element) |
| , m_inAutoscroll(false) |
| , m_optionsWidth(0) |
| , m_indexOffset(0) |
| + , m_listItemCount(0) |
| { |
| ASSERT(element); |
| ASSERT(element->isHTMLElement()); |
| @@ -118,14 +119,19 @@ inline HTMLSelectElement* RenderListBox::selectElement() const |
| void RenderListBox::updateFromElement() |
| { |
| FontCachePurgePreventer fontCachePurgePreventer; |
| - |
| if (m_optionsChanged) { |
| const Vector<HTMLElement*>& listItems = selectElement()->listItems(); |
| - int size = numItems(); |
| + int size = static_cast<int>(listItems.size()); |
| float width = 0; |
| + m_listItemCount = 0; |
| for (int i = 0; i < size; ++i) { |
| HTMLElement* element = listItems[i]; |
| + RenderStyle* listItemStyle = element->renderStyle(); |
| + if (listItemStyle && listItemStyle->display() == NONE) |
| + continue; |
| + |
| + ++m_listItemCount; |
| String text; |
| Font itemFont = style()->font(); |
| if (isHTMLOptionElement(*element)) { |
| @@ -206,9 +212,10 @@ void RenderListBox::scrollToRevealSelection() |
| m_scrollToRevealSelectionAfterLayout = false; |
| - int firstIndex = select->activeSelectionStartListIndex(); |
| - if (firstIndex >= 0 && !listIndexIsVisible(select->activeSelectionEndListIndex())) |
| - scrollToRevealElementAtListIndex(firstIndex); |
| + int firstIndex = optionIndexToRenderListBoxIndex(select->activeSelectionStartListIndex()); |
| + int lastIndex = optionIndexToRenderListBoxIndex(select->activeSelectionEndListIndex()); |
| + if (firstIndex >= 0 && !listIndexIsVisible(lastIndex)) |
| + scrollToRevealElementAtListIndexInternal(firstIndex); |
| } |
| void RenderListBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const |
| @@ -266,7 +273,7 @@ int RenderListBox::numVisibleItems() const |
| int RenderListBox::numItems() const |
| { |
| - return selectElement()->listItems().size(); |
| + return m_listItemCount; |
| } |
| LayoutUnit RenderListBox::listHeight() const |
| @@ -285,7 +292,7 @@ int RenderListBox::baselinePosition(FontBaseline baselineType, bool firstLine, L |
| return RenderBox::baselinePosition(baselineType, firstLine, lineDirection, linePositionMode) - baselineAdjustment; |
| } |
| -LayoutRect RenderListBox::itemBoundingBoxRect(const LayoutPoint& additionalOffset, int index) |
| +LayoutRect RenderListBox::itemBoundingBoxRectInternal(const LayoutPoint& additionalOffset, int index) const |
| { |
| // For RTL, items start after the left-side vertical scrollbar. |
| int scrollbarOffset = style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft() ? verticalScrollbarWidth() : 0; |
| @@ -347,7 +354,7 @@ void RenderListBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& |
| // Focus the last selected item. |
| int selectedItem = select->activeSelectionEndListIndex(); |
| if (selectedItem >= 0) { |
| - rects.append(pixelSnappedIntRect(itemBoundingBoxRect(additionalOffset, selectedItem))); |
| + rects.append(pixelSnappedIntRect(itemBoundingBoxRectInternal(additionalOffset, selectedItem))); |
| return; |
| } |
| @@ -355,9 +362,9 @@ void RenderListBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& |
| int size = numItems(); |
| const Vector<HTMLElement*>& listItems = select->listItems(); |
| for (int i = 0; i < size; ++i) { |
| - HTMLElement* element = listItems[i]; |
| + HTMLElement* element = listItems[renderListBoxIndexToOptionIndex(i)]; |
| if (isHTMLOptionElement(*element) && !element->isDisabledFormControl()) { |
| - rects.append(pixelSnappedIntRect(itemBoundingBoxRect(additionalOffset, i))); |
| + rects.append(pixelSnappedIntRect(itemBoundingBoxRectInternal(additionalOffset, i))); |
| return; |
| } |
| } |
| @@ -412,7 +419,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint& |
| HTMLSelectElement* select = selectElement(); |
| const Vector<HTMLElement*>& listItems = select->listItems(); |
| - HTMLElement* element = listItems[listIndex]; |
| + HTMLElement* element = listItems[renderListBoxIndexToOptionIndex(listIndex)]; |
| RenderStyle* itemStyle = element->renderStyle(); |
| if (!itemStyle) |
| @@ -442,7 +449,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint& |
| TextRun textRun(itemText, 0, 0, TextRun::AllowTrailingExpansion, itemStyle->direction(), isOverride(itemStyle->unicodeBidi()), true, TextRun::NoRounding); |
| Font itemFont = style()->font(); |
| - LayoutRect r = itemBoundingBoxRect(paintOffset, listIndex); |
| + LayoutRect r = itemBoundingBoxRectInternal(paintOffset, listIndex); |
| r.move(itemOffsetForAlignment(textRun, itemStyle, itemFont, r)); |
| if (isHTMLOptGroupElement(*element)) { |
| @@ -461,7 +468,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint& |
| void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset, int listIndex) |
| { |
| const Vector<HTMLElement*>& listItems = selectElement()->listItems(); |
| - HTMLElement* element = listItems[listIndex]; |
| + HTMLElement* element = listItems[renderListBoxIndexToOptionIndex(listIndex)]; |
| Color backColor; |
| if (isHTMLOptionElement(*element) && ((toHTMLOptionElement(*element).selected() && selectElement()->suggestedIndex() < 0) || listIndex == selectElement()->suggestedIndex())) { |
| @@ -475,7 +482,7 @@ void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint& |
| // Draw the background for this list box item |
| if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDEN) { |
| - LayoutRect itemRect = itemBoundingBoxRect(paintOffset, listIndex); |
| + LayoutRect itemRect = itemBoundingBoxRectInternal(paintOffset, listIndex); |
| itemRect.intersect(controlClipRect(paintOffset)); |
| paintInfo.context->fillRect(pixelSnappedIntRect(itemRect), backColor); |
| } |
| @@ -498,7 +505,7 @@ bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const Layout |
| return false; |
| } |
| -int RenderListBox::listIndexAtOffset(const LayoutSize& offset) |
| +int RenderListBox::listIndexAtOffset(const LayoutSize& offset) const |
| { |
| if (!numItems()) |
| return -1; |
| @@ -514,7 +521,7 @@ int RenderListBox::listIndexAtOffset(const LayoutSize& offset) |
| return -1; |
| int newOffset = (offset.height() - borderTop() - paddingTop()) / itemHeight() + m_indexOffset; |
| - return newOffset < numItems() ? newOffset : -1; |
| + return newOffset < numItems() ? renderListBoxIndexToOptionIndex(newOffset) : -1; |
| } |
| void RenderListBox::panScroll(const IntPoint& panStartMousePosition) |
| @@ -571,10 +578,10 @@ int RenderListBox::scrollToward(const IntPoint& destination) |
| int rows = numVisibleItems(); |
| int offset = m_indexOffset; |
| - if (positionOffset.height() < borderTop() + paddingTop() && scrollToRevealElementAtListIndex(offset - 1)) |
| + if (positionOffset.height() < borderTop() + paddingTop() && scrollToRevealElementAtListIndexInternal(offset - 1)) |
| return offset - 1; |
| - if (positionOffset.height() > height() - paddingBottom() - borderBottom() && scrollToRevealElementAtListIndex(offset + rows)) |
| + if (positionOffset.height() > height() - paddingBottom() - borderBottom() && scrollToRevealElementAtListIndexInternal(offset + rows)) |
| return offset + rows - 1; |
| return listIndexAtOffset(positionOffset); |
| @@ -593,9 +600,9 @@ void RenderListBox::autoscroll(const IntPoint&) |
| m_inAutoscroll = true; |
| if (!select->multiple()) |
| - select->setActiveSelectionAnchorIndex(endIndex); |
| + select->setActiveSelectionAnchorIndex(renderListBoxIndexToOptionIndex(endIndex)); |
| - select->setActiveSelectionEndIndex(endIndex); |
| + select->setActiveSelectionEndIndex(renderListBoxIndexToOptionIndex(endIndex)); |
| select->updateListBoxSelection(!select->multiple()); |
| m_inAutoscroll = false; |
| } |
| @@ -609,7 +616,7 @@ void RenderListBox::stopAutoscroll() |
| selectElement()->listBoxOnChange(); |
| } |
| -bool RenderListBox::scrollToRevealElementAtListIndex(int index) |
| +bool RenderListBox::scrollToRevealElementAtListIndexInternal(int index) |
| { |
| if (index < 0 || index >= numItems() || listIndexIsVisible(index)) |
| return false; |
| @@ -625,7 +632,7 @@ bool RenderListBox::scrollToRevealElementAtListIndex(int index) |
| return true; |
| } |
| -bool RenderListBox::listIndexIsVisible(int index) |
| +bool RenderListBox::listIndexIsVisible(int index) const |
| { |
| return index >= m_indexOffset && index < m_indexOffset + numVisibleItems(); |
| } |
| @@ -721,8 +728,8 @@ bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re |
| LayoutPoint adjustedLocation = accumulatedOffset + location(); |
| for (int i = 0; i < size; ++i) { |
| - if (itemBoundingBoxRect(adjustedLocation, i).contains(locationInContainer.point())) { |
| - if (Element* node = listItems[i]) { |
| + if (itemBoundingBoxRectInternal(adjustedLocation, i).contains(locationInContainer.point())) { |
| + if (Element* node = listItems[renderListBoxIndexToOptionIndex(i)]) { |
| result.setInnerNode(node); |
| if (!result.innerNonSharedNode()) |
| result.setInnerNonSharedNode(node); |
| @@ -953,4 +960,57 @@ void RenderListBox::setHasVerticalScrollbar(bool hasScrollbar) |
| document().setAnnotatedRegionsDirty(true); |
| } |
| +int RenderListBox::renderListBoxIndexToOptionIndex(int index) const |
|
keishi
2014/04/11 15:07:09
I'm sorry this should have been renderListBoxIndex
spartha
2014/04/12 18:53:22
Done.
|
| +{ |
| + const Vector<HTMLElement*>& listItems = selectElement()->listItems(); |
| + const int size = static_cast<int>(listItems.size()); |
| + |
| + if (size == numItems()) |
| + return index; |
| + |
| + int rendererIndex = 0; |
| + int i = 0; |
| + for (; i < size; ++i) { |
| + HTMLElement* element = listItems[i]; |
| + RenderStyle* listItemStyle = element->renderStyle(); |
| + if (listItemStyle && listItemStyle->display() == NONE) |
| + continue; |
| + if (index == rendererIndex) |
| + break; |
| + ++rendererIndex; |
| + } |
| + return i; |
| +} |
| + |
| +int RenderListBox::optionIndexToRenderListBoxIndex(int index) const |
|
keishi
2014/04/11 15:07:09
Ditto.
spartha
2014/04/12 18:53:22
Done.
|
| +{ |
| + const Vector<HTMLElement*>& listItems = selectElement()->listItems(); |
| + const int size = static_cast<int>(listItems.size()); |
| + |
| + if (size == numItems()) |
| + return index; |
| + |
| + int realIndex = 0; |
| + for (int i = 0; i < size; ++i) { |
| + HTMLElement* element = listItems[i]; |
| + RenderStyle* listItemStyle = element->renderStyle(); |
| + if (listItemStyle && listItemStyle->display() == NONE) |
| + continue; |
| + if (index == i) |
| + break; |
| + ++realIndex; |
| + } |
| + return realIndex; |
| +} |
| + |
| +LayoutRect RenderListBox::itemBoundingBoxRect(const LayoutPoint& point, int index) const |
| +{ |
| + return itemBoundingBoxRectInternal(point, optionIndexToRenderListBoxIndex(index)); |
| +} |
| + |
| +bool RenderListBox::scrollToRevealElementAtListIndex(int index) |
| +{ |
| + return scrollToRevealElementAtListIndexInternal(optionIndexToRenderListBoxIndex(index)); |
| +} |
| + |
| } // namespace WebCore |