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

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: Update Test Expectations 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
« no previous file with comments | « Source/core/rendering/RenderListBox.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/rendering/RenderListBox.cpp
diff --git a/Source/core/rendering/RenderListBox.cpp b/Source/core/rendering/RenderListBox.cpp
index bdeaa58697891a4f86199f8e8b4f0ef9ea4fb248..4a5fa8f77e09ac0b0f303ce00a2278bf701b3de2 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,24 +119,36 @@ 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];
+ const HTMLElement& element = *listItems[i];
+
String text;
Font itemFont = style()->font();
- if (isHTMLOptionElement(*element)) {
- text = toHTMLOptionElement(*element).textIndentedToRespectGroupLabel();
- } else if (isHTMLOptGroupElement(*element)) {
- text = toHTMLOptGroupElement(*element).groupLabelText();
+ if (isHTMLOptionElement(element)) {
+ const HTMLOptionElement& optionElement = toHTMLOptionElement(element);
+ if (optionElement.isDisplayNone())
+ continue;
+ text = optionElement.textIndentedToRespectGroupLabel();
+ ++m_listItemCount;
+ } else if (isHTMLOptGroupElement(element)) {
+ if (toHTMLOptGroupElement(element).isDisplayNone())
+ continue;
+ text = toHTMLOptGroupElement(element).groupLabelText();
FontDescription d = itemFont.fontDescription();
d.setWeight(d.bolderWeight());
itemFont = Font(d);
itemFont.update(document().styleEngine()->fontSelector());
+ ++m_listItemCount;
+ } else if (isHTMLHRElement(element)) {
+ // HTMLSelect adds it to its list, so we will also add it to match the count.
+ ++m_listItemCount;
+ continue;
}
if (!text.isEmpty()) {
@@ -206,9 +219,10 @@ void RenderListBox::scrollToRevealSelection()
m_scrollToRevealSelectionAfterLayout = false;
- int firstIndex = select->activeSelectionStartListIndex();
- if (firstIndex >= 0 && !listIndexIsVisible(select->activeSelectionEndListIndex()))
- scrollToRevealElementAtListIndex(firstIndex);
+ int firstIndex = listIndexToRenderListBoxIndex(select->activeSelectionStartListIndex());
+ int lastIndex = listIndexToRenderListBoxIndex(select->activeSelectionEndListIndex());
+ if (firstIndex >= 0 && !listIndexIsVisible(lastIndex))
+ scrollToRevealElementAtListIndexInternal(firstIndex);
}
void RenderListBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
@@ -266,7 +280,7 @@ int RenderListBox::numVisibleItems() const
int RenderListBox::numItems() const
{
- return selectElement()->listItems().size();
+ return m_listItemCount;
}
LayoutUnit RenderListBox::listHeight() const
@@ -285,7 +299,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 +361,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 +369,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[renderListBoxIndexToListIndex(i)];
if (isHTMLOptionElement(*element) && !element->isDisabledFormControl()) {
- rects.append(pixelSnappedIntRect(itemBoundingBoxRect(additionalOffset, i)));
+ rects.append(pixelSnappedIntRect(itemBoundingBoxRectInternal(additionalOffset, i)));
return;
}
}
@@ -412,7 +426,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint&
HTMLSelectElement* select = selectElement();
const Vector<HTMLElement*>& listItems = select->listItems();
- HTMLElement* element = listItems[listIndex];
+ HTMLElement* element = listItems[renderListBoxIndexToListIndex(listIndex)];
RenderStyle* itemStyle = element->renderStyle();
if (!itemStyle)
@@ -442,7 +456,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 +475,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[renderListBoxIndexToListIndex(listIndex)];
Color backColor;
if (isHTMLOptionElement(*element) && ((toHTMLOptionElement(*element).selected() && selectElement()->suggestedIndex() < 0) || listIndex == selectElement()->suggestedIndex())) {
@@ -475,7 +489,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 +512,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 +528,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() ? renderListBoxIndexToListIndex(newOffset) : -1;
}
void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
@@ -571,10 +585,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 +607,9 @@ void RenderListBox::autoscroll(const IntPoint&)
m_inAutoscroll = true;
if (!select->multiple())
- select->setActiveSelectionAnchorIndex(endIndex);
+ select->setActiveSelectionAnchorIndex(renderListBoxIndexToListIndex(endIndex));
- select->setActiveSelectionEndIndex(endIndex);
+ select->setActiveSelectionEndIndex(renderListBoxIndexToListIndex(endIndex));
select->updateListBoxSelection(!select->multiple());
m_inAutoscroll = false;
}
@@ -609,7 +623,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 +639,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 +735,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[renderListBoxIndexToListIndex(i)]) {
result.setInnerNode(node);
if (!result.innerNonSharedNode())
result.setInnerNonSharedNode(node);
@@ -953,4 +967,59 @@ void RenderListBox::setHasVerticalScrollbar(bool hasScrollbar)
document().setAnnotatedRegionsDirty(true);
}
+int RenderListBox::renderListBoxIndexToListIndex(int index) const
+{
+ const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const int size = static_cast<int>(listItems.size());
+
+ if (size == numItems())
+ return index;
+
+ int listBoxIndex = 0;
+ int listIndex = 0;
+ for (; listIndex < size; ++listIndex) {
+ const HTMLElement& element = *listItems[listIndex];
+ if (isHTMLOptionElement(element) && toHTMLOptionElement(element).isDisplayNone())
+ continue;
+ if (isHTMLOptGroupElement(element) && toHTMLOptGroupElement(element).isDisplayNone())
+ continue;
+ if (index == listBoxIndex)
+ break;
+ ++listBoxIndex;
+ }
+ return listIndex;
+}
+
+int RenderListBox::listIndexToRenderListBoxIndex(int index) const
+{
+ const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+ const int size = static_cast<int>(listItems.size());
+
+ if (size == numItems())
+ return index;
+
+ int listBoxIndex = 0;
+ for (int listIndex = 0; listIndex < size; ++listIndex) {
+ const HTMLElement& element = *listItems[listIndex];
+ if (isHTMLOptionElement(element) && toHTMLOptionElement(element).isDisplayNone())
+ continue;
+ if (isHTMLOptGroupElement(element) && toHTMLOptGroupElement(element).isDisplayNone())
+ continue;
+ if (index == listIndex)
+ break;
+ ++listBoxIndex;
+ }
+ return listBoxIndex;
+}
+
+LayoutRect RenderListBox::itemBoundingBoxRect(const LayoutPoint& point, int index) const
+{
+ return itemBoundingBoxRectInternal(point, listIndexToRenderListBoxIndex(index));
+}
+
+bool RenderListBox::scrollToRevealElementAtListIndex(int index)
+{
+ return scrollToRevealElementAtListIndexInternal(listIndexToRenderListBoxIndex(index));
+}
+
} // namespace WebCore
« no previous file with comments | « Source/core/rendering/RenderListBox.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698