Modified: trunk/Source/WebCore/html/HTMLSelectElement.cpp (97122 => 97123)
--- trunk/Source/WebCore/html/HTMLSelectElement.cpp 2011-10-11 04:55:43 UTC (rev 97122)
+++ trunk/Source/WebCore/html/HTMLSelectElement.cpp 2011-10-11 04:57:27 UTC (rev 97123)
@@ -76,7 +76,6 @@
HTMLSelectElement::HTMLSelectElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
: HTMLFormControlElementWithState(tagName, document, form)
- , m_recalcListItems(false)
{
ASSERT(hasTagName(selectTag));
}
@@ -315,12 +314,12 @@
void HTMLSelectElement::recalcListItems(bool updateSelectedStates) const
{
- const_cast<HTMLSelectElement*>(this)->recalcListItemsInternal(updateSelectedStates);
+ recalcListItems(const_cast<SelectElementData&>(m_data), this, updateSelectedStates);
}
void HTMLSelectElement::recalcListItemsIfNeeded()
{
- if (m_recalcListItems)
+ if (m_data.shouldRecalcListItems())
recalcListItems();
}
@@ -457,19 +456,19 @@
int HTMLSelectElement::nextSelectableListIndex(int startIndex) const
{
- return nextValidIndex(listItems(), startIndex, SkipForwards, 1);
+ return nextValidIndex(m_data.listItems(this), startIndex, SkipForwards, 1);
}
int HTMLSelectElement::previousSelectableListIndex(int startIndex) const
{
if (startIndex == -1)
- startIndex = listItems().size();
- return nextValidIndex(listItems(), startIndex, SkipBackwards, 1);
+ startIndex = m_data.listItems(this).size();
+ return nextValidIndex(m_data.listItems(this), startIndex, SkipBackwards, 1);
}
int HTMLSelectElement::firstSelectableListIndex() const
{
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
int index = nextValidIndex(items, items.size(), SkipBackwards, INT_MAX);
if (static_cast<unsigned>(index) == items.size())
return -1;
@@ -478,13 +477,13 @@
int HTMLSelectElement::lastSelectableListIndex() const
{
- return nextValidIndex(listItems(), -1, SkipForwards, INT_MAX);
+ return nextValidIndex(m_data.listItems(this), -1, SkipForwards, INT_MAX);
}
// Returns the index of the next valid item one page away from |startIndex| in direction |direction|.
int HTMLSelectElement::nextSelectableListIndexPageAway(int startIndex, SkipDirection direction) const
{
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
// Can't use data->size() because renderer forces a minimum size.
int pageSize = 0;
if (renderer()->isListBox())
@@ -527,7 +526,7 @@
Vector<bool>& lastOnChangeSelection = m_data.lastOnChangeSelection();
lastOnChangeSelection.clear();
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
for (unsigned i = 0; i < items.size(); ++i) {
OptionElement* optionElement = toOptionElement(items[i]);
lastOnChangeSelection.append(optionElement && optionElement->selected());
@@ -543,7 +542,7 @@
Vector<bool>& cachedStateForActiveSelection = m_data.cachedStateForActiveSelection();
cachedStateForActiveSelection.clear();
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
for (unsigned i = 0; i < items.size(); ++i) {
OptionElement* optionElement = toOptionElement(items[i]);
cachedStateForActiveSelection.append(optionElement && optionElement->selected());
@@ -558,13 +557,13 @@
void HTMLSelectElement::updateListBoxSelection(bool deselectOtherOptions)
{
ASSERT(renderer() && (renderer()->isListBox() || m_data.multiple()));
- ASSERT(!listItems().size() || m_data.activeSelectionAnchorIndex() >= 0);
+ ASSERT(!m_data.listItems(this).size() || m_data.activeSelectionAnchorIndex() >= 0);
unsigned start = min(m_data.activeSelectionAnchorIndex(), m_data.activeSelectionEndIndex());
unsigned end = max(m_data.activeSelectionAnchorIndex(), m_data.activeSelectionEndIndex());
Vector<bool>& cachedStateForActiveSelection = m_data.cachedStateForActiveSelection();
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
for (unsigned i = 0; i < items.size(); ++i) {
OptionElement* optionElement = toOptionElement(items[i]);
if (!optionElement || items[i]->disabled())
@@ -587,7 +586,7 @@
ASSERT(!m_data.usesMenuList() || m_data.multiple());
Vector<bool>& lastOnChangeSelection = m_data.lastOnChangeSelection();
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
// If the cached selection list is empty, or the size has changed, then fire
// dispatchFormControlChangeEvent, and return early.
@@ -641,28 +640,9 @@
}
}
-void HTMLSelectElement::checkListItems() const
-{
-#if !ASSERT_DISABLED
- Vector<Element*> items = m_listItems;
- const_cast<HTMLSelectElement*>(this)->recalcListItemsInternal(false);
- ASSERT(items == m_listItems);
-#endif
-}
-
-const Vector<Element*>& HTMLSelectElement::listItems() const
-{
- if (m_recalcListItems)
- const_cast<HTMLSelectElement*>(this)->recalcListItemsInternal(false);
- else
- checkListItems();
-
- return m_listItems;
-}
-
void HTMLSelectElement::setRecalcListItems()
{
- m_recalcListItems = true;
+ m_data.setShouldRecalcListItems(true);
// Manual selection anchor is reset when manipulating the select programmatically.
m_data.setActiveSelectionAnchorIndex(-1);
setOptionsChangedOnRenderer();
@@ -671,16 +651,17 @@
m_collectionInfo.reset();
}
-void HTMLSelectElement::recalcListItemsInternal(bool updateSelectedStates)
+void HTMLSelectElement::recalcListItems(SelectElementData& data, const Element* element, bool updateSelectedStates)
{
- m_listItems.clear();
+ Vector<Element*>& listItems = data.rawListItems();
+ listItems.clear();
- m_recalcListItems = false;
+ data.setShouldRecalcListItems(false);
OptionElement* foundSelected = 0;
- for (Node* currentNode = this->firstChild(); currentNode;) {
+ for (Node* currentNode = element->firstChild(); currentNode;) {
if (!currentNode->isElementNode()) {
- currentNode = currentNode->traverseNextSibling(this);
+ currentNode = currentNode->traverseNextSibling(element);
continue;
}
@@ -690,7 +671,7 @@
// flatten the tree automatically, so we follow suit.
// (http://www.w3.org/TR/html401/interact/forms.html#h-17.6)
if (isOptionGroupElement(current)) {
- m_listItems.append(current);
+ listItems.append(current);
if (current->firstChild()) {
currentNode = current->firstChild();
continue;
@@ -698,10 +679,10 @@
}
if (OptionElement* optionElement = toOptionElement(current)) {
- m_listItems.append(current);
+ listItems.append(current);
- if (updateSelectedStates && !m_data.multiple()) {
- if (!foundSelected && (m_data.size() <= 1 || optionElement->selected())) {
+ if (updateSelectedStates && !data.multiple()) {
+ if (!foundSelected && (data.size() <= 1 || optionElement->selected())) {
foundSelected = optionElement;
foundSelected->setSelectedState(true);
} else if (foundSelected && optionElement->selected()) {
@@ -712,7 +693,7 @@
}
if (current->hasTagName(HTMLNames::hrTag))
- m_listItems.append(current);
+ listItems.append(current);
// In conforming HTML code, only <optgroup> and <option> will be found
// within a <select>. We call traverseNextSibling so that we only step
@@ -720,7 +701,7 @@
// with the case where odd tags like a <div> have been added but we
// handle this because such tags have already been removed from the
// <select>'s subtree at this point.
- currentNode = currentNode->traverseNextSibling(this);
+ currentNode = currentNode->traverseNextSibling(element);
}
}
@@ -729,7 +710,7 @@
unsigned index = 0;
// return the number of the first option selected
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
for (size_t i = 0; i < items.size(); ++i) {
if (OptionElement* optionElement = toOptionElement(items[i])) {
if (optionElement->selected())
@@ -748,7 +729,7 @@
if (!m_data.multiple())
deselect = true;
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
int listIndex = optionToListIndex(optionIndex);
Element* excludeElement = 0;
@@ -791,7 +772,7 @@
int HTMLSelectElement::optionToListIndex(int optionIndex) const
{
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
int listSize = static_cast<int>(items.size());
if (optionIndex < 0 || optionIndex >= listSize)
return -1;
@@ -810,7 +791,7 @@
int HTMLSelectElement::listToOptionIndex(int listIndex) const
{
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isOptionElement(items[listIndex]))
return -1;
@@ -845,7 +826,7 @@
void HTMLSelectElement::deselectItemsWithoutValidation(Element* excludeElement)
{
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
for (unsigned i = 0; i < items.size(); ++i) {
if (items[i] == excludeElement)
continue;
@@ -857,7 +838,7 @@
bool HTMLSelectElement::saveFormControlState(String& value) const
{
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
int length = items.size();
// FIXME: Change this code to use the new StringImpl::createUninitialized code path.
@@ -874,9 +855,9 @@
void HTMLSelectElement::restoreFormControlState(const String& state)
{
- recalcListItems();
+ recalcListItems(m_data, this);
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
int length = items.size();
for (int i = 0; i < length; ++i) {
@@ -904,7 +885,7 @@
return false;
bool successful = false;
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
for (unsigned i = 0; i < items.size(); ++i) {
OptionElement* optionElement = toOptionElement(items[i]);
@@ -925,7 +906,7 @@
OptionElement* firstOption = 0;
OptionElement* selectedOption = 0;
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
for (unsigned i = 0; i < items.size(); ++i) {
OptionElement* optionElement = toOptionElement(items[i]);
if (!optionElement)
@@ -999,7 +980,7 @@
const String& keyIdentifier = static_cast<KeyboardEvent*>(event)->keyIdentifier();
bool handled = true;
- const Vector<Element*>& listItems = this->listItems();
+ const Vector<Element*>& listItems = m_data.listItems(this);
int listIndex = optionToListIndex(selectedIndex());
if (keyIdentifier == "Down" || keyIdentifier == "Right")
@@ -1127,7 +1108,7 @@
bool shiftSelect = m_data.multiple() && shift;
bool multiSelect = m_data.multiple() && multi && !shift;
- Element* clickedElement = listItems()[listIndex];
+ Element* clickedElement = m_data.listItems(this)[listIndex];
OptionElement* option = toOptionElement(clickedElement);
if (option) {
// Keep track of whether an active selection (like during drag
@@ -1167,7 +1148,7 @@
void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
{
- const Vector<Element*>& listItems = this->listItems();
+ const Vector<Element*>& listItems = m_data.listItems(this);
if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
focus();
@@ -1325,7 +1306,7 @@
// FIXME: We should iterate the listItems in the reverse order.
unsigned index = 0;
bool found = false;
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
for (size_t i = 0; i < items.size(); ++i) {
if (OptionElement* optionElement = toOptionElement(items[i])) {
if (optionElement->selected()) {
@@ -1381,7 +1362,7 @@
}
}
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
int itemCount = items.size();
if (itemCount < 1)
return;
@@ -1419,7 +1400,7 @@
// When the element is created during document parsing, it won't have any
// items yet - but for innerHTML and related methods, this method is called
// after the whole subtree is constructed.
- recalcListItems(true);
+ recalcListItems(m_data, this, true);
HTMLFormControlElementWithState::insertedIntoTree(deep);
}
@@ -1430,7 +1411,7 @@
accessKeyAction(false);
// if this index is already selected, unselect. otherwise update the selected index
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
int listIndex = optionToListIndex(index);
if (OptionElement* optionElement = (listIndex >= 0 ? toOptionElement(items[listIndex]) : 0)) {
if (optionElement->selected())
@@ -1451,7 +1432,7 @@
{
unsigned options = 0;
- const Vector<Element*>& items = listItems();
+ const Vector<Element*>& items = m_data.listItems(this);
for (unsigned i = 0; i < items.size(); ++i) {
if (isOptionElement(items[i]))
++options;
Modified: trunk/Source/WebCore/html/HTMLSelectElement.h (97122 => 97123)
--- trunk/Source/WebCore/html/HTMLSelectElement.h 2011-10-11 04:55:43 UTC (rev 97122)
+++ trunk/Source/WebCore/html/HTMLSelectElement.h 2011-10-11 04:57:27 UTC (rev 97123)
@@ -30,7 +30,6 @@
#include "Event.h"
#include "HTMLFormControlElement.h"
#include "SelectElement.h"
-#include <wtf/Vector.h>
namespace WebCore {
@@ -67,7 +66,7 @@
void setRecalcListItems();
void recalcListItemsIfNeeded();
- const Vector<Element*>& listItems() const;
+ const Vector<Element*>& listItems() const { return m_data.listItems(this); }
virtual void accessKeyAction(bool sendToAnyElement);
void accessKeySetSelectedIndex(int);
@@ -144,8 +143,7 @@
bool hasPlaceholderLabelOption() const;
- void checkListItems() const;
- void recalcListItemsInternal(bool updateSelectedStates = true);
+ static void recalcListItems(SelectElementData&, const Element*, bool updateSelectedStates = true);
void setSelectedIndexInternal(int optionIndex, bool deselect = true, bool fireOnChangeNow = false, bool userDrivenChange = true);
void deselectItemsWithoutValidation(Element* excludeElement = 0);
void parseMultipleAttribute(const Attribute*);
@@ -155,6 +153,7 @@
bool platformHandleKeydownEvent(KeyboardEvent*);
void listBoxDefaultEventHandler(Event*);
void setOptionsChangedOnRenderer();
+ friend class SelectElementData;
enum SkipDirection {
SkipBackwards = -1,
@@ -169,8 +168,6 @@
SelectElementData m_data;
CollectionCache m_collectionInfo;
- Vector<Element*> m_listItems;
- bool m_recalcListItems;
};
HTMLSelectElement* toSelectElement(Element*);