| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. |
| 3 * 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | 3 * 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * | 8 * |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 // widget, but I'm not sure this is right for the new control. | 79 // widget, but I'm not sure this is right for the new control. |
| 80 const int baselineAdjustment = 7; | 80 const int baselineAdjustment = 7; |
| 81 | 81 |
| 82 RenderListBox::RenderListBox(Element* element) | 82 RenderListBox::RenderListBox(Element* element) |
| 83 : RenderBlockFlow(element) | 83 : RenderBlockFlow(element) |
| 84 , m_optionsChanged(true) | 84 , m_optionsChanged(true) |
| 85 , m_scrollToRevealSelectionAfterLayout(true) | 85 , m_scrollToRevealSelectionAfterLayout(true) |
| 86 , m_inAutoscroll(false) | 86 , m_inAutoscroll(false) |
| 87 , m_optionsWidth(0) | 87 , m_optionsWidth(0) |
| 88 , m_indexOffset(0) | 88 , m_indexOffset(0) |
| 89 , m_listItemCount(0) |
| 89 { | 90 { |
| 90 ASSERT(element); | 91 ASSERT(element); |
| 91 ASSERT(element->isHTMLElement()); | 92 ASSERT(element->isHTMLElement()); |
| 92 ASSERT(isHTMLSelectElement(element)); | 93 ASSERT(isHTMLSelectElement(element)); |
| 93 | 94 |
| 94 if (FrameView* frameView = frame()->view()) | 95 if (FrameView* frameView = frame()->view()) |
| 95 frameView->addScrollableArea(this); | 96 frameView->addScrollableArea(this); |
| 96 } | 97 } |
| 97 | 98 |
| 98 RenderListBox::~RenderListBox() | 99 RenderListBox::~RenderListBox() |
| (...skipping 12 matching lines...) Expand all Loading... |
| 111 } | 112 } |
| 112 | 113 |
| 113 inline HTMLSelectElement* RenderListBox::selectElement() const | 114 inline HTMLSelectElement* RenderListBox::selectElement() const |
| 114 { | 115 { |
| 115 return toHTMLSelectElement(node()); | 116 return toHTMLSelectElement(node()); |
| 116 } | 117 } |
| 117 | 118 |
| 118 void RenderListBox::updateFromElement() | 119 void RenderListBox::updateFromElement() |
| 119 { | 120 { |
| 120 FontCachePurgePreventer fontCachePurgePreventer; | 121 FontCachePurgePreventer fontCachePurgePreventer; |
| 121 | |
| 122 if (m_optionsChanged) { | 122 if (m_optionsChanged) { |
| 123 const Vector<HTMLElement*>& listItems = selectElement()->listItems(); | 123 const Vector<HTMLElement*>& listItems = selectElement()->listItems(); |
| 124 int size = numItems(); | 124 int size = static_cast<int>(listItems.size()); |
| 125 | 125 |
| 126 float width = 0; | 126 float width = 0; |
| 127 m_listItemCount = 0; |
| 127 for (int i = 0; i < size; ++i) { | 128 for (int i = 0; i < size; ++i) { |
| 128 HTMLElement* element = listItems[i]; | 129 const HTMLElement& element = *listItems[i]; |
| 130 |
| 129 String text; | 131 String text; |
| 130 Font itemFont = style()->font(); | 132 Font itemFont = style()->font(); |
| 131 if (isHTMLOptionElement(*element)) { | 133 if (isHTMLOptionElement(element)) { |
| 132 text = toHTMLOptionElement(*element).textIndentedToRespectGroupL
abel(); | 134 const HTMLOptionElement& optionElement = toHTMLOptionElement(ele
ment); |
| 133 } else if (isHTMLOptGroupElement(*element)) { | 135 if (optionElement.isDisplayNone()) |
| 134 text = toHTMLOptGroupElement(*element).groupLabelText(); | 136 continue; |
| 137 text = optionElement.textIndentedToRespectGroupLabel(); |
| 138 ++m_listItemCount; |
| 139 } else if (isHTMLOptGroupElement(element)) { |
| 140 if (toHTMLOptGroupElement(element).isDisplayNone()) |
| 141 continue; |
| 142 text = toHTMLOptGroupElement(element).groupLabelText(); |
| 135 FontDescription d = itemFont.fontDescription(); | 143 FontDescription d = itemFont.fontDescription(); |
| 136 d.setWeight(d.bolderWeight()); | 144 d.setWeight(d.bolderWeight()); |
| 137 itemFont = Font(d); | 145 itemFont = Font(d); |
| 138 itemFont.update(document().styleEngine()->fontSelector()); | 146 itemFont.update(document().styleEngine()->fontSelector()); |
| 147 ++m_listItemCount; |
| 148 } else if (isHTMLHRElement(element)) { |
| 149 // HTMLSelect adds it to its list, so we will also add it to mat
ch the count. |
| 150 ++m_listItemCount; |
| 151 continue; |
| 139 } | 152 } |
| 140 | 153 |
| 141 if (!text.isEmpty()) { | 154 if (!text.isEmpty()) { |
| 142 applyTextTransform(style(), text, ' '); | 155 applyTextTransform(style(), text, ' '); |
| 143 | 156 |
| 144 bool hasStrongDirectionality; | 157 bool hasStrongDirectionality; |
| 145 TextDirection direction = determineDirectionality(text, hasStron
gDirectionality); | 158 TextDirection direction = determineDirectionality(text, hasStron
gDirectionality); |
| 146 TextRun textRun = constructTextRun(this, itemFont, text, style()
, TextRun::AllowTrailingExpansion); | 159 TextRun textRun = constructTextRun(this, itemFont, text, style()
, TextRun::AllowTrailingExpansion); |
| 147 if (hasStrongDirectionality) | 160 if (hasStrongDirectionality) |
| 148 textRun.setDirection(direction); | 161 textRun.setDirection(direction); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 repaintScrollbarIfNeeded(); | 212 repaintScrollbarIfNeeded(); |
| 200 RenderBox::repaintTreeAfterLayout(); | 213 RenderBox::repaintTreeAfterLayout(); |
| 201 } | 214 } |
| 202 | 215 |
| 203 void RenderListBox::scrollToRevealSelection() | 216 void RenderListBox::scrollToRevealSelection() |
| 204 { | 217 { |
| 205 HTMLSelectElement* select = selectElement(); | 218 HTMLSelectElement* select = selectElement(); |
| 206 | 219 |
| 207 m_scrollToRevealSelectionAfterLayout = false; | 220 m_scrollToRevealSelectionAfterLayout = false; |
| 208 | 221 |
| 209 int firstIndex = select->activeSelectionStartListIndex(); | 222 int firstIndex = listIndexToRenderListBoxIndex(select->activeSelectionStartL
istIndex()); |
| 210 if (firstIndex >= 0 && !listIndexIsVisible(select->activeSelectionEndListInd
ex())) | 223 int lastIndex = listIndexToRenderListBoxIndex(select->activeSelectionEndList
Index()); |
| 211 scrollToRevealElementAtListIndex(firstIndex); | 224 if (firstIndex >= 0 && !listIndexIsVisible(lastIndex)) |
| 225 scrollToRevealElementAtListIndexInternal(firstIndex); |
| 212 } | 226 } |
| 213 | 227 |
| 214 void RenderListBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, L
ayoutUnit& maxLogicalWidth) const | 228 void RenderListBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, L
ayoutUnit& maxLogicalWidth) const |
| 215 { | 229 { |
| 216 maxLogicalWidth = m_optionsWidth + 2 * optionsSpacingHorizontal; | 230 maxLogicalWidth = m_optionsWidth + 2 * optionsSpacingHorizontal; |
| 217 if (m_vBar) | 231 if (m_vBar) |
| 218 maxLogicalWidth += verticalScrollbarWidth(); | 232 maxLogicalWidth += verticalScrollbarWidth(); |
| 219 if (!style()->width().isPercent()) | 233 if (!style()->width().isPercent()) |
| 220 minLogicalWidth = maxLogicalWidth; | 234 minLogicalWidth = maxLogicalWidth; |
| 221 } | 235 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 } | 273 } |
| 260 | 274 |
| 261 int RenderListBox::numVisibleItems() const | 275 int RenderListBox::numVisibleItems() const |
| 262 { | 276 { |
| 263 // Only count fully visible rows. But don't return 0 even if only part of a
row shows. | 277 // Only count fully visible rows. But don't return 0 even if only part of a
row shows. |
| 264 return max<int>(1, (contentHeight() + rowSpacing) / itemHeight()); | 278 return max<int>(1, (contentHeight() + rowSpacing) / itemHeight()); |
| 265 } | 279 } |
| 266 | 280 |
| 267 int RenderListBox::numItems() const | 281 int RenderListBox::numItems() const |
| 268 { | 282 { |
| 269 return selectElement()->listItems().size(); | 283 return m_listItemCount; |
| 270 } | 284 } |
| 271 | 285 |
| 272 LayoutUnit RenderListBox::listHeight() const | 286 LayoutUnit RenderListBox::listHeight() const |
| 273 { | 287 { |
| 274 return itemHeight() * numItems() - rowSpacing; | 288 return itemHeight() * numItems() - rowSpacing; |
| 275 } | 289 } |
| 276 | 290 |
| 277 void RenderListBox::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, Logi
calExtentComputedValues& computedValues) const | 291 void RenderListBox::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, Logi
calExtentComputedValues& computedValues) const |
| 278 { | 292 { |
| 279 LayoutUnit height = itemHeight() * size() - rowSpacing + borderAndPaddingHei
ght(); | 293 LayoutUnit height = itemHeight() * size() - rowSpacing + borderAndPaddingHei
ght(); |
| 280 RenderBox::computeLogicalHeight(height, logicalTop, computedValues); | 294 RenderBox::computeLogicalHeight(height, logicalTop, computedValues); |
| 281 } | 295 } |
| 282 | 296 |
| 283 int RenderListBox::baselinePosition(FontBaseline baselineType, bool firstLine, L
ineDirectionMode lineDirection, LinePositionMode linePositionMode) const | 297 int RenderListBox::baselinePosition(FontBaseline baselineType, bool firstLine, L
ineDirectionMode lineDirection, LinePositionMode linePositionMode) const |
| 284 { | 298 { |
| 285 return RenderBox::baselinePosition(baselineType, firstLine, lineDirection, l
inePositionMode) - baselineAdjustment; | 299 return RenderBox::baselinePosition(baselineType, firstLine, lineDirection, l
inePositionMode) - baselineAdjustment; |
| 286 } | 300 } |
| 287 | 301 |
| 288 LayoutRect RenderListBox::itemBoundingBoxRect(const LayoutPoint& additionalOffse
t, int index) | 302 LayoutRect RenderListBox::itemBoundingBoxRectInternal(const LayoutPoint& additio
nalOffset, int index) const |
| 289 { | 303 { |
| 290 // For RTL, items start after the left-side vertical scrollbar. | 304 // For RTL, items start after the left-side vertical scrollbar. |
| 291 int scrollbarOffset = style()->shouldPlaceBlockDirectionScrollbarOnLogicalLe
ft() ? verticalScrollbarWidth() : 0; | 305 int scrollbarOffset = style()->shouldPlaceBlockDirectionScrollbarOnLogicalLe
ft() ? verticalScrollbarWidth() : 0; |
| 292 return LayoutRect(additionalOffset.x() + borderLeft() + paddingLeft() + scro
llbarOffset, | 306 return LayoutRect(additionalOffset.x() + borderLeft() + paddingLeft() + scro
llbarOffset, |
| 293 additionalOffset.y() + borderTop() + paddingTop() + itemHeight() * (inde
x - m_indexOffset), | 307 additionalOffset.y() + borderTop() + paddingTop() + itemHeight() * (inde
x - m_indexOffset), |
| 294 contentWidth(), itemHeight()); | 308 contentWidth(), itemHeight()); |
| 295 } | 309 } |
| 296 | 310 |
| 297 void RenderListBox::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOf
fset) | 311 void RenderListBox::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOf
fset) |
| 298 { | 312 { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 void RenderListBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&
additionalOffset, const RenderLayerModelObject* paintContainer) | 354 void RenderListBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&
additionalOffset, const RenderLayerModelObject* paintContainer) |
| 341 { | 355 { |
| 342 if (!isSpatialNavigationEnabled(frame())) | 356 if (!isSpatialNavigationEnabled(frame())) |
| 343 return RenderBlockFlow::addFocusRingRects(rects, additionalOffset, paint
Container); | 357 return RenderBlockFlow::addFocusRingRects(rects, additionalOffset, paint
Container); |
| 344 | 358 |
| 345 HTMLSelectElement* select = selectElement(); | 359 HTMLSelectElement* select = selectElement(); |
| 346 | 360 |
| 347 // Focus the last selected item. | 361 // Focus the last selected item. |
| 348 int selectedItem = select->activeSelectionEndListIndex(); | 362 int selectedItem = select->activeSelectionEndListIndex(); |
| 349 if (selectedItem >= 0) { | 363 if (selectedItem >= 0) { |
| 350 rects.append(pixelSnappedIntRect(itemBoundingBoxRect(additionalOffset, s
electedItem))); | 364 rects.append(pixelSnappedIntRect(itemBoundingBoxRectInternal(additionalO
ffset, selectedItem))); |
| 351 return; | 365 return; |
| 352 } | 366 } |
| 353 | 367 |
| 354 // No selected items, find the first non-disabled item. | 368 // No selected items, find the first non-disabled item. |
| 355 int size = numItems(); | 369 int size = numItems(); |
| 356 const Vector<HTMLElement*>& listItems = select->listItems(); | 370 const Vector<HTMLElement*>& listItems = select->listItems(); |
| 357 for (int i = 0; i < size; ++i) { | 371 for (int i = 0; i < size; ++i) { |
| 358 HTMLElement* element = listItems[i]; | 372 HTMLElement* element = listItems[renderListBoxIndexToListIndex(i)]; |
| 359 if (isHTMLOptionElement(*element) && !element->isDisabledFormControl())
{ | 373 if (isHTMLOptionElement(*element) && !element->isDisabledFormControl())
{ |
| 360 rects.append(pixelSnappedIntRect(itemBoundingBoxRect(additionalOffse
t, i))); | 374 rects.append(pixelSnappedIntRect(itemBoundingBoxRectInternal(additio
nalOffset, i))); |
| 361 return; | 375 return; |
| 362 } | 376 } |
| 363 } | 377 } |
| 364 } | 378 } |
| 365 | 379 |
| 366 int RenderListBox::scrollbarLeft() const | 380 int RenderListBox::scrollbarLeft() const |
| 367 { | 381 { |
| 368 int scrollbarLeft = 0; | 382 int scrollbarLeft = 0; |
| 369 if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) | 383 if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) |
| 370 scrollbarLeft = borderLeft(); | 384 scrollbarLeft = borderLeft(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 return offset; | 419 return offset; |
| 406 } | 420 } |
| 407 | 421 |
| 408 void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint&
paintOffset, int listIndex) | 422 void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint&
paintOffset, int listIndex) |
| 409 { | 423 { |
| 410 FontCachePurgePreventer fontCachePurgePreventer; | 424 FontCachePurgePreventer fontCachePurgePreventer; |
| 411 | 425 |
| 412 HTMLSelectElement* select = selectElement(); | 426 HTMLSelectElement* select = selectElement(); |
| 413 | 427 |
| 414 const Vector<HTMLElement*>& listItems = select->listItems(); | 428 const Vector<HTMLElement*>& listItems = select->listItems(); |
| 415 HTMLElement* element = listItems[listIndex]; | 429 HTMLElement* element = listItems[renderListBoxIndexToListIndex(listIndex)]; |
| 416 | 430 |
| 417 RenderStyle* itemStyle = element->renderStyle(); | 431 RenderStyle* itemStyle = element->renderStyle(); |
| 418 if (!itemStyle) | 432 if (!itemStyle) |
| 419 itemStyle = style(); | 433 itemStyle = style(); |
| 420 | 434 |
| 421 if (itemStyle->visibility() == HIDDEN) | 435 if (itemStyle->visibility() == HIDDEN) |
| 422 return; | 436 return; |
| 423 | 437 |
| 424 String itemText; | 438 String itemText; |
| 425 bool isOptionElement = isHTMLOptionElement(*element); | 439 bool isOptionElement = isHTMLOptionElement(*element); |
| 426 if (isOptionElement) | 440 if (isOptionElement) |
| 427 itemText = toHTMLOptionElement(*element).textIndentedToRespectGroupLabel
(); | 441 itemText = toHTMLOptionElement(*element).textIndentedToRespectGroupLabel
(); |
| 428 else if (isHTMLOptGroupElement(*element)) | 442 else if (isHTMLOptGroupElement(*element)) |
| 429 itemText = toHTMLOptGroupElement(*element).groupLabelText(); | 443 itemText = toHTMLOptGroupElement(*element).groupLabelText(); |
| 430 applyTextTransform(style(), itemText, ' '); | 444 applyTextTransform(style(), itemText, ' '); |
| 431 | 445 |
| 432 Color textColor = element->renderStyle() ? resolveColor(element->renderStyle
(), CSSPropertyColor) : resolveColor(CSSPropertyColor); | 446 Color textColor = element->renderStyle() ? resolveColor(element->renderStyle
(), CSSPropertyColor) : resolveColor(CSSPropertyColor); |
| 433 if (isOptionElement && ((toHTMLOptionElement(*element).selected() && select-
>suggestedIndex() < 0) || listIndex == select->suggestedIndex())) { | 447 if (isOptionElement && ((toHTMLOptionElement(*element).selected() && select-
>suggestedIndex() < 0) || listIndex == select->suggestedIndex())) { |
| 434 if (frame()->selection().isFocusedAndActive() && document().focusedEleme
nt() == node()) | 448 if (frame()->selection().isFocusedAndActive() && document().focusedEleme
nt() == node()) |
| 435 textColor = RenderTheme::theme().activeListBoxSelectionForegroundCol
or(); | 449 textColor = RenderTheme::theme().activeListBoxSelectionForegroundCol
or(); |
| 436 // Honor the foreground color for disabled items | 450 // Honor the foreground color for disabled items |
| 437 else if (!element->isDisabledFormControl() && !select->isDisabledFormCon
trol()) | 451 else if (!element->isDisabledFormControl() && !select->isDisabledFormCon
trol()) |
| 438 textColor = RenderTheme::theme().inactiveListBoxSelectionForegroundC
olor(); | 452 textColor = RenderTheme::theme().inactiveListBoxSelectionForegroundC
olor(); |
| 439 } | 453 } |
| 440 | 454 |
| 441 paintInfo.context->setFillColor(textColor); | 455 paintInfo.context->setFillColor(textColor); |
| 442 | 456 |
| 443 TextRun textRun(itemText, 0, 0, TextRun::AllowTrailingExpansion, itemStyle->
direction(), isOverride(itemStyle->unicodeBidi()), true, TextRun::NoRounding); | 457 TextRun textRun(itemText, 0, 0, TextRun::AllowTrailingExpansion, itemStyle->
direction(), isOverride(itemStyle->unicodeBidi()), true, TextRun::NoRounding); |
| 444 Font itemFont = style()->font(); | 458 Font itemFont = style()->font(); |
| 445 LayoutRect r = itemBoundingBoxRect(paintOffset, listIndex); | 459 LayoutRect r = itemBoundingBoxRectInternal(paintOffset, listIndex); |
| 446 r.move(itemOffsetForAlignment(textRun, itemStyle, itemFont, r)); | 460 r.move(itemOffsetForAlignment(textRun, itemStyle, itemFont, r)); |
| 447 | 461 |
| 448 if (isHTMLOptGroupElement(*element)) { | 462 if (isHTMLOptGroupElement(*element)) { |
| 449 FontDescription d = itemFont.fontDescription(); | 463 FontDescription d = itemFont.fontDescription(); |
| 450 d.setWeight(d.bolderWeight()); | 464 d.setWeight(d.bolderWeight()); |
| 451 itemFont = Font(d); | 465 itemFont = Font(d); |
| 452 itemFont.update(document().styleEngine()->fontSelector()); | 466 itemFont.update(document().styleEngine()->fontSelector()); |
| 453 } | 467 } |
| 454 | 468 |
| 455 // Draw the item text | 469 // Draw the item text |
| 456 TextRunPaintInfo textRunPaintInfo(textRun); | 470 TextRunPaintInfo textRunPaintInfo(textRun); |
| 457 textRunPaintInfo.bounds = r; | 471 textRunPaintInfo.bounds = r; |
| 458 paintInfo.context->drawBidiText(itemFont, textRunPaintInfo, roundedIntPoint(
r.location())); | 472 paintInfo.context->drawBidiText(itemFont, textRunPaintInfo, roundedIntPoint(
r.location())); |
| 459 } | 473 } |
| 460 | 474 |
| 461 void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint&
paintOffset, int listIndex) | 475 void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint&
paintOffset, int listIndex) |
| 462 { | 476 { |
| 463 const Vector<HTMLElement*>& listItems = selectElement()->listItems(); | 477 const Vector<HTMLElement*>& listItems = selectElement()->listItems(); |
| 464 HTMLElement* element = listItems[listIndex]; | 478 HTMLElement* element = listItems[renderListBoxIndexToListIndex(listIndex)]; |
| 465 | 479 |
| 466 Color backColor; | 480 Color backColor; |
| 467 if (isHTMLOptionElement(*element) && ((toHTMLOptionElement(*element).selecte
d() && selectElement()->suggestedIndex() < 0) || listIndex == selectElement()->s
uggestedIndex())) { | 481 if (isHTMLOptionElement(*element) && ((toHTMLOptionElement(*element).selecte
d() && selectElement()->suggestedIndex() < 0) || listIndex == selectElement()->s
uggestedIndex())) { |
| 468 if (frame()->selection().isFocusedAndActive() && document().focusedEleme
nt() == node()) | 482 if (frame()->selection().isFocusedAndActive() && document().focusedEleme
nt() == node()) |
| 469 backColor = RenderTheme::theme().activeListBoxSelectionBackgroundCol
or(); | 483 backColor = RenderTheme::theme().activeListBoxSelectionBackgroundCol
or(); |
| 470 else | 484 else |
| 471 backColor = RenderTheme::theme().inactiveListBoxSelectionBackgroundC
olor(); | 485 backColor = RenderTheme::theme().inactiveListBoxSelectionBackgroundC
olor(); |
| 472 } else { | 486 } else { |
| 473 backColor = element->renderStyle() ? resolveColor(element->renderStyle()
, CSSPropertyBackgroundColor) : resolveColor(CSSPropertyBackgroundColor); | 487 backColor = element->renderStyle() ? resolveColor(element->renderStyle()
, CSSPropertyBackgroundColor) : resolveColor(CSSPropertyBackgroundColor); |
| 474 } | 488 } |
| 475 | 489 |
| 476 // Draw the background for this list box item | 490 // Draw the background for this list box item |
| 477 if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDE
N) { | 491 if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDE
N) { |
| 478 LayoutRect itemRect = itemBoundingBoxRect(paintOffset, listIndex); | 492 LayoutRect itemRect = itemBoundingBoxRectInternal(paintOffset, listIndex
); |
| 479 itemRect.intersect(controlClipRect(paintOffset)); | 493 itemRect.intersect(controlClipRect(paintOffset)); |
| 480 paintInfo.context->fillRect(pixelSnappedIntRect(itemRect), backColor); | 494 paintInfo.context->fillRect(pixelSnappedIntRect(itemRect), backColor); |
| 481 } | 495 } |
| 482 } | 496 } |
| 483 | 497 |
| 484 bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const Layout
Point& locationInContainer, const LayoutPoint& accumulatedOffset) | 498 bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const Layout
Point& locationInContainer, const LayoutPoint& accumulatedOffset) |
| 485 { | 499 { |
| 486 if (!m_vBar || !m_vBar->shouldParticipateInHitTesting()) | 500 if (!m_vBar || !m_vBar->shouldParticipateInHitTesting()) |
| 487 return false; | 501 return false; |
| 488 | 502 |
| 489 LayoutRect vertRect(accumulatedOffset.x() + scrollbarLeft(), | 503 LayoutRect vertRect(accumulatedOffset.x() + scrollbarLeft(), |
| 490 accumulatedOffset.y() + borderTop(), | 504 accumulatedOffset.y() + borderTop(), |
| 491 verticalScrollbarWidth(), | 505 verticalScrollbarWidth(), |
| 492 height() - borderTop() - borderBottom()); | 506 height() - borderTop() - borderBottom()); |
| 493 | 507 |
| 494 if (vertRect.contains(locationInContainer)) { | 508 if (vertRect.contains(locationInContainer)) { |
| 495 result.setScrollbar(m_vBar.get()); | 509 result.setScrollbar(m_vBar.get()); |
| 496 return true; | 510 return true; |
| 497 } | 511 } |
| 498 return false; | 512 return false; |
| 499 } | 513 } |
| 500 | 514 |
| 501 int RenderListBox::listIndexAtOffset(const LayoutSize& offset) | 515 int RenderListBox::listIndexAtOffset(const LayoutSize& offset) const |
| 502 { | 516 { |
| 503 if (!numItems()) | 517 if (!numItems()) |
| 504 return -1; | 518 return -1; |
| 505 | 519 |
| 506 if (offset.height() < borderTop() + paddingTop() || offset.height() > height
() - paddingBottom() - borderBottom()) | 520 if (offset.height() < borderTop() + paddingTop() || offset.height() > height
() - paddingBottom() - borderBottom()) |
| 507 return -1; | 521 return -1; |
| 508 | 522 |
| 509 int scrollbarWidth = verticalScrollbarWidth(); | 523 int scrollbarWidth = verticalScrollbarWidth(); |
| 510 int rightScrollbarOffset = style()->shouldPlaceBlockDirectionScrollbarOnLogi
calLeft() ? scrollbarWidth : 0; | 524 int rightScrollbarOffset = style()->shouldPlaceBlockDirectionScrollbarOnLogi
calLeft() ? scrollbarWidth : 0; |
| 511 int leftScrollbarOffset = style()->shouldPlaceBlockDirectionScrollbarOnLogic
alLeft() ? 0 : scrollbarWidth; | 525 int leftScrollbarOffset = style()->shouldPlaceBlockDirectionScrollbarOnLogic
alLeft() ? 0 : scrollbarWidth; |
| 512 if (offset.width() < borderLeft() + paddingLeft() + rightScrollbarOffset | 526 if (offset.width() < borderLeft() + paddingLeft() + rightScrollbarOffset |
| 513 || offset.width() > width() - borderRight() - paddingRight() - leftScrol
lbarOffset) | 527 || offset.width() > width() - borderRight() - paddingRight() - leftScrol
lbarOffset) |
| 514 return -1; | 528 return -1; |
| 515 | 529 |
| 516 int newOffset = (offset.height() - borderTop() - paddingTop()) / itemHeight(
) + m_indexOffset; | 530 int newOffset = (offset.height() - borderTop() - paddingTop()) / itemHeight(
) + m_indexOffset; |
| 517 return newOffset < numItems() ? newOffset : -1; | 531 return newOffset < numItems() ? renderListBoxIndexToListIndex(newOffset) : -
1; |
| 518 } | 532 } |
| 519 | 533 |
| 520 void RenderListBox::panScroll(const IntPoint& panStartMousePosition) | 534 void RenderListBox::panScroll(const IntPoint& panStartMousePosition) |
| 521 { | 535 { |
| 522 const int maxSpeed = 20; | 536 const int maxSpeed = 20; |
| 523 const int iconRadius = 7; | 537 const int iconRadius = 7; |
| 524 const int speedReducer = 4; | 538 const int speedReducer = 4; |
| 525 | 539 |
| 526 // FIXME: This doesn't work correctly with transforms. | 540 // FIXME: This doesn't work correctly with transforms. |
| 527 FloatPoint absOffset = localToAbsolute(); | 541 FloatPoint absOffset = localToAbsolute(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 | 578 |
| 565 int RenderListBox::scrollToward(const IntPoint& destination) | 579 int RenderListBox::scrollToward(const IntPoint& destination) |
| 566 { | 580 { |
| 567 // FIXME: This doesn't work correctly with transforms. | 581 // FIXME: This doesn't work correctly with transforms. |
| 568 FloatPoint absPos = localToAbsolute(); | 582 FloatPoint absPos = localToAbsolute(); |
| 569 IntSize positionOffset = roundedIntSize(destination - absPos); | 583 IntSize positionOffset = roundedIntSize(destination - absPos); |
| 570 | 584 |
| 571 int rows = numVisibleItems(); | 585 int rows = numVisibleItems(); |
| 572 int offset = m_indexOffset; | 586 int offset = m_indexOffset; |
| 573 | 587 |
| 574 if (positionOffset.height() < borderTop() + paddingTop() && scrollToRevealEl
ementAtListIndex(offset - 1)) | 588 if (positionOffset.height() < borderTop() + paddingTop() && scrollToRevealEl
ementAtListIndexInternal(offset - 1)) |
| 575 return offset - 1; | 589 return offset - 1; |
| 576 | 590 |
| 577 if (positionOffset.height() > height() - paddingBottom() - borderBottom() &&
scrollToRevealElementAtListIndex(offset + rows)) | 591 if (positionOffset.height() > height() - paddingBottom() - borderBottom() &&
scrollToRevealElementAtListIndexInternal(offset + rows)) |
| 578 return offset + rows - 1; | 592 return offset + rows - 1; |
| 579 | 593 |
| 580 return listIndexAtOffset(positionOffset); | 594 return listIndexAtOffset(positionOffset); |
| 581 } | 595 } |
| 582 | 596 |
| 583 void RenderListBox::autoscroll(const IntPoint&) | 597 void RenderListBox::autoscroll(const IntPoint&) |
| 584 { | 598 { |
| 585 IntPoint pos = frame()->view()->windowToContents(frame()->eventHandler().las
tKnownMousePosition()); | 599 IntPoint pos = frame()->view()->windowToContents(frame()->eventHandler().las
tKnownMousePosition()); |
| 586 | 600 |
| 587 int endIndex = scrollToward(pos); | 601 int endIndex = scrollToward(pos); |
| 588 if (selectElement()->isDisabledFormControl()) | 602 if (selectElement()->isDisabledFormControl()) |
| 589 return; | 603 return; |
| 590 | 604 |
| 591 if (endIndex >= 0) { | 605 if (endIndex >= 0) { |
| 592 HTMLSelectElement* select = selectElement(); | 606 HTMLSelectElement* select = selectElement(); |
| 593 m_inAutoscroll = true; | 607 m_inAutoscroll = true; |
| 594 | 608 |
| 595 if (!select->multiple()) | 609 if (!select->multiple()) |
| 596 select->setActiveSelectionAnchorIndex(endIndex); | 610 select->setActiveSelectionAnchorIndex(renderListBoxIndexToListIndex(
endIndex)); |
| 597 | 611 |
| 598 select->setActiveSelectionEndIndex(endIndex); | 612 select->setActiveSelectionEndIndex(renderListBoxIndexToListIndex(endInde
x)); |
| 599 select->updateListBoxSelection(!select->multiple()); | 613 select->updateListBoxSelection(!select->multiple()); |
| 600 m_inAutoscroll = false; | 614 m_inAutoscroll = false; |
| 601 } | 615 } |
| 602 } | 616 } |
| 603 | 617 |
| 604 void RenderListBox::stopAutoscroll() | 618 void RenderListBox::stopAutoscroll() |
| 605 { | 619 { |
| 606 if (selectElement()->isDisabledFormControl()) | 620 if (selectElement()->isDisabledFormControl()) |
| 607 return; | 621 return; |
| 608 | 622 |
| 609 selectElement()->listBoxOnChange(); | 623 selectElement()->listBoxOnChange(); |
| 610 } | 624 } |
| 611 | 625 |
| 612 bool RenderListBox::scrollToRevealElementAtListIndex(int index) | 626 bool RenderListBox::scrollToRevealElementAtListIndexInternal(int index) |
| 613 { | 627 { |
| 614 if (index < 0 || index >= numItems() || listIndexIsVisible(index)) | 628 if (index < 0 || index >= numItems() || listIndexIsVisible(index)) |
| 615 return false; | 629 return false; |
| 616 | 630 |
| 617 int newOffset; | 631 int newOffset; |
| 618 if (index < m_indexOffset) | 632 if (index < m_indexOffset) |
| 619 newOffset = index; | 633 newOffset = index; |
| 620 else | 634 else |
| 621 newOffset = index - numVisibleItems() + 1; | 635 newOffset = index - numVisibleItems() + 1; |
| 622 | 636 |
| 623 scrollToOffsetWithoutAnimation(VerticalScrollbar, newOffset); | 637 scrollToOffsetWithoutAnimation(VerticalScrollbar, newOffset); |
| 624 | 638 |
| 625 return true; | 639 return true; |
| 626 } | 640 } |
| 627 | 641 |
| 628 bool RenderListBox::listIndexIsVisible(int index) | 642 bool RenderListBox::listIndexIsVisible(int index) const |
| 629 { | 643 { |
| 630 return index >= m_indexOffset && index < m_indexOffset + numVisibleItems(); | 644 return index >= m_indexOffset && index < m_indexOffset + numVisibleItems(); |
| 631 } | 645 } |
| 632 | 646 |
| 633 bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granular
ity, float multiplier) | 647 bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granular
ity, float multiplier) |
| 634 { | 648 { |
| 635 return ScrollableArea::scroll(direction, granularity, multiplier); | 649 return ScrollableArea::scroll(direction, granularity, multiplier); |
| 636 } | 650 } |
| 637 | 651 |
| 638 int RenderListBox::scrollSize(ScrollbarOrientation orientation) const | 652 int RenderListBox::scrollSize(ScrollbarOrientation orientation) const |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 | 728 |
| 715 bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated
Offset, HitTestAction hitTestAction) | 729 bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
sult, const HitTestLocation& locationInContainer, const LayoutPoint& accumulated
Offset, HitTestAction hitTestAction) |
| 716 { | 730 { |
| 717 if (!RenderBlockFlow::nodeAtPoint(request, result, locationInContainer, accu
mulatedOffset, hitTestAction)) | 731 if (!RenderBlockFlow::nodeAtPoint(request, result, locationInContainer, accu
mulatedOffset, hitTestAction)) |
| 718 return false; | 732 return false; |
| 719 const Vector<HTMLElement*>& listItems = selectElement()->listItems(); | 733 const Vector<HTMLElement*>& listItems = selectElement()->listItems(); |
| 720 int size = numItems(); | 734 int size = numItems(); |
| 721 LayoutPoint adjustedLocation = accumulatedOffset + location(); | 735 LayoutPoint adjustedLocation = accumulatedOffset + location(); |
| 722 | 736 |
| 723 for (int i = 0; i < size; ++i) { | 737 for (int i = 0; i < size; ++i) { |
| 724 if (itemBoundingBoxRect(adjustedLocation, i).contains(locationInContaine
r.point())) { | 738 if (itemBoundingBoxRectInternal(adjustedLocation, i).contains(locationIn
Container.point())) { |
| 725 if (Element* node = listItems[i]) { | 739 if (Element* node = listItems[renderListBoxIndexToListIndex(i)]) { |
| 726 result.setInnerNode(node); | 740 result.setInnerNode(node); |
| 727 if (!result.innerNonSharedNode()) | 741 if (!result.innerNonSharedNode()) |
| 728 result.setInnerNonSharedNode(node); | 742 result.setInnerNonSharedNode(node); |
| 729 result.setLocalPoint(locationInContainer.point() - toLayoutSize(
adjustedLocation)); | 743 result.setLocalPoint(locationInContainer.point() - toLayoutSize(
adjustedLocation)); |
| 730 break; | 744 break; |
| 731 } | 745 } |
| 732 } | 746 } |
| 733 } | 747 } |
| 734 | 748 |
| 735 return true; | 749 return true; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 destroyScrollbar(); | 960 destroyScrollbar(); |
| 947 | 961 |
| 948 if (m_vBar) | 962 if (m_vBar) |
| 949 m_vBar->styleChanged(); | 963 m_vBar->styleChanged(); |
| 950 | 964 |
| 951 // Force an update since we know the scrollbars have changed things. | 965 // Force an update since we know the scrollbars have changed things. |
| 952 if (document().hasAnnotatedRegions()) | 966 if (document().hasAnnotatedRegions()) |
| 953 document().setAnnotatedRegionsDirty(true); | 967 document().setAnnotatedRegionsDirty(true); |
| 954 } | 968 } |
| 955 | 969 |
| 970 int RenderListBox::renderListBoxIndexToListIndex(int index) const |
| 971 { |
| 972 const Vector<HTMLElement*>& listItems = selectElement()->listItems(); |
| 973 const int size = static_cast<int>(listItems.size()); |
| 974 |
| 975 if (size == numItems()) |
| 976 return index; |
| 977 |
| 978 int listBoxIndex = 0; |
| 979 int listIndex = 0; |
| 980 for (; listIndex < size; ++listIndex) { |
| 981 const HTMLElement& element = *listItems[listIndex]; |
| 982 if (isHTMLOptionElement(element) && toHTMLOptionElement(element).isDispl
ayNone()) |
| 983 continue; |
| 984 if (isHTMLOptGroupElement(element) && toHTMLOptGroupElement(element).isD
isplayNone()) |
| 985 continue; |
| 986 if (index == listBoxIndex) |
| 987 break; |
| 988 ++listBoxIndex; |
| 989 } |
| 990 return listIndex; |
| 991 } |
| 992 |
| 993 int RenderListBox::listIndexToRenderListBoxIndex(int index) const |
| 994 { |
| 995 const Vector<HTMLElement*>& listItems = selectElement()->listItems(); |
| 996 const int size = static_cast<int>(listItems.size()); |
| 997 |
| 998 if (size == numItems()) |
| 999 return index; |
| 1000 |
| 1001 int listBoxIndex = 0; |
| 1002 for (int listIndex = 0; listIndex < size; ++listIndex) { |
| 1003 const HTMLElement& element = *listItems[listIndex]; |
| 1004 if (isHTMLOptionElement(element) && toHTMLOptionElement(element).isDispl
ayNone()) |
| 1005 continue; |
| 1006 if (isHTMLOptGroupElement(element) && toHTMLOptGroupElement(element).isD
isplayNone()) |
| 1007 continue; |
| 1008 if (index == listIndex) |
| 1009 break; |
| 1010 ++listBoxIndex; |
| 1011 } |
| 1012 return listBoxIndex; |
| 1013 } |
| 1014 |
| 1015 LayoutRect RenderListBox::itemBoundingBoxRect(const LayoutPoint& point, int inde
x) const |
| 1016 { |
| 1017 return itemBoundingBoxRectInternal(point, listIndexToRenderListBoxIndex(inde
x)); |
| 1018 } |
| 1019 |
| 1020 bool RenderListBox::scrollToRevealElementAtListIndex(int index) |
| 1021 { |
| 1022 return scrollToRevealElementAtListIndexInternal(listIndexToRenderListBoxInde
x(index)); |
| 1023 } |
| 1024 |
| 956 } // namespace WebCore | 1025 } // namespace WebCore |
| OLD | NEW |