diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 799f736c5449..f3e1a8e7ffde 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -410,7 +410,7 @@ nsListControlFrame::Reflow(nsPresContext* aPresContext, (NS_SUBTREE_DIRTY(this) || aReflowState.ShouldReflowAllKids()); nsHTMLReflowState state(aReflowState); - int32_t length = GetNumberOfOptions(); + int32_t length = GetNumberOfRows(); nscoord oldHeightOfARow = HeightOfARow(); @@ -572,7 +572,7 @@ nsListControlFrame::ReflowAsDropdown(nsPresContext* aPresContext, if (above <= 0 && below <= 0) { state.SetComputedHeight(heightOfARow); mNumDisplayRows = 1; - mDropdownCanGrow = GetNumberOfOptions() > 1; + mDropdownCanGrow = GetNumberOfRows() > 1; } else { nscoord bp = aReflowState.mComputedBorderPadding.TopBottom(); nscoord availableHeight = NS_MAX(above, below) - bp; @@ -580,7 +580,7 @@ nsListControlFrame::ReflowAsDropdown(nsPresContext* aPresContext, int32_t rows; if (visibleHeight <= availableHeight) { // The dropdown fits in the available height. - rows = GetNumberOfOptions(); + rows = GetNumberOfRows(); mNumDisplayRows = clamped(rows, 1, kMaxDropDownRows); if (mNumDisplayRows == rows) { newHeight = visibleHeight; // use the exact height @@ -756,6 +756,39 @@ nsListControlFrame::InitSelectionRange(int32_t aClickedIndex) } } +static uint32_t +CountOptionsAndOptgroups(nsIFrame* aFrame) +{ + uint32_t count = 0; + nsFrameList::Enumerator e(aFrame->PrincipalChildList()); + for (; !e.AtEnd(); e.Next()) { + nsIFrame* child = e.get(); + nsIContent* content = child->GetContent(); + if (content) { + if (content->IsHTML(nsGkAtoms::option)) { + ++count; + } else { + nsCOMPtr optgroup = do_QueryInterface(content); + if (optgroup) { + nsAutoString label; + optgroup->GetLabel(label); + if (label.Length() > 0) { + ++count; + } + count += CountOptionsAndOptgroups(child); + } + } + } + } + return count; +} + +uint32_t +nsListControlFrame::GetNumberOfRows() +{ + return ::CountOptionsAndOptgroups(GetContentInsertionFrame()); +} + //--------------------------------------------------------- bool nsListControlFrame::PerformSelection(int32_t aClickedIndex, diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index 9f17ec950950..66195037e59d 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -389,6 +389,11 @@ protected: nscoord HeightOfARow() { return GetOptionsContainer()->HeightOfARow(); } + + /** + * @return how many displayable options/optgroups this frame has. + */ + uint32_t GetNumberOfRows(); // Data Members int32_t mStartSelectionIndex;