Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Unified Diff: Source/core/rendering/RenderListBox.cpp

Issue 189543012: Update <select> when any of its <option> children has "display: none" (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« Source/core/html/HTMLOptionElement.cpp ('K') | « Source/core/rendering/RenderListBox.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698