void RenderMenuList::updateOptionsWidth() { float maxOptionWidth = 0; const Vector<Element*>& listItems = toSelectElement(static_cast<Element*>(node()))->listItems(); int size = listItems.size(); FontCachePurgePreventer fontCachePurgePreventer; for (int i = 0; i < size; ++i) { Element* element = listItems[i]; OptionElement* optionElement = toOptionElement(element); if (!optionElement) continue; String text = optionElement->textIndentedToRespectGroupLabel(); if (theme()->popupOptionSupportsTextIndent()) { // Add in the option's text indent. We can't calculate percentage values for now. float optionWidth = 0; if (RenderStyle* optionStyle = element->renderStyle()) optionWidth += optionStyle->textIndent().calcMinValue(0); if (!text.isEmpty()) optionWidth += style()->font().width(text); maxOptionWidth = max(maxOptionWidth, optionWidth); } else if (!text.isEmpty()) maxOptionWidth = max(maxOptionWidth, style()->font().width(text)); } int width = static_cast<int>(ceilf(maxOptionWidth)); if (m_optionsWidth == width) return; m_optionsWidth = width; if (parent()) setNeedsLayoutAndPrefWidthsRecalc(); }
void SelectElement::typeAheadFind(SelectElementData& data, Element* element, KeyboardEvent* event) { if (event->timeStamp() < data.lastCharTime()) return; DOMTimeStamp delta = event->timeStamp() - data.lastCharTime(); data.setLastCharTime(event->timeStamp()); UChar c = event->charCode(); String prefix; int searchStartOffset = 1; if (delta > typeAheadTimeout) { prefix = String(&c, 1); data.setTypedString(prefix); data.setRepeatingChar(c); } else { data.typedString().append(c); if (c == data.repeatingChar()) // The user is likely trying to cycle through all the items starting with this character, so just search on the character prefix = String(&c, 1); else { data.setRepeatingChar(0); prefix = data.typedString(); searchStartOffset = 0; } } const Vector<Element*>& items = data.listItems(element); int itemCount = items.size(); if (itemCount < 1) return; int selected = selectedIndex(data, element); int index = (optionToListIndex(data, element, selected >= 0 ? selected : 0) + searchStartOffset) % itemCount; ASSERT(index >= 0); for (int i = 0; i < itemCount; ++i, index = (index + 1) % itemCount) { OptionElement* optionElement = toOptionElement(items[index]); if (!optionElement || items[index]->disabled()) continue; String text = optionElement->textIndentedToRespectGroupLabel(); if (stripLeadingWhiteSpace(text).startsWith(prefix, false)) { setSelectedIndex(data, element, listToOptionIndex(data, element, index)); if (!data.usesMenuList()) listBoxOnChange(data, element); element->setNeedsStyleRecalc(); return; } } }
void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, int listIndex) { SelectElement* select = toSelectElement(static_cast<Element*>(node())); const Vector<Element*>& listItems = select->listItems(); Element* element = listItems[listIndex]; OptionElement* optionElement = toOptionElement(element); String itemText; if (optionElement) itemText = optionElement->textIndentedToRespectGroupLabel(); else if (OptionGroupElement* optionGroupElement = toOptionGroupElement(element)) itemText = optionGroupElement->groupLabelText(); // Determine where the item text should be placed IntRect r = itemBoundingBoxRect(tx, ty, listIndex); r.move(optionsSpacingHorizontal, style()->font().ascent()); RenderStyle* itemStyle = element->renderStyle(); if (!itemStyle) itemStyle = style(); Color textColor = element->renderStyle() ? element->renderStyle()->color() : style()->color(); if (optionElement && optionElement->selected()) { if (document()->frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node()) textColor = theme()->activeListBoxSelectionForegroundColor(); // Honor the foreground color for disabled items else if (!element->disabled()) textColor = theme()->inactiveListBoxSelectionForegroundColor(); } ColorSpace colorSpace = itemStyle->colorSpace(); paintInfo.context->setFillColor(textColor, colorSpace); Font itemFont = style()->font(); if (isOptionGroupElement(element)) { FontDescription d = itemFont.fontDescription(); d.setWeight(d.bolderWeight()); itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing()); itemFont.update(document()->styleSelector()->fontSelector()); } unsigned length = itemText.length(); const UChar* string = itemText.characters(); TextRun textRun(string, length, 0, 0, 0, itemStyle->direction() == RTL, itemStyle->unicodeBidi() == Override, false, false); // Draw the item text if (itemStyle->visibility() != HIDDEN) paintInfo.context->drawBidiText(itemFont, textRun, r.location()); }