Chromium Code Reviews| Index: third_party/WebKit/Source/core/html/forms/RadioButtonGroupScope.cpp |
| diff --git a/third_party/WebKit/Source/core/html/forms/RadioButtonGroupScope.cpp b/third_party/WebKit/Source/core/html/forms/RadioButtonGroupScope.cpp |
| index a09c6707046e34edadc476c3c5790a4a56f06f03..a6a21ddf3b3f52b859a072ad5150c595ae5e716b 100644 |
| --- a/third_party/WebKit/Source/core/html/forms/RadioButtonGroupScope.cpp |
| +++ b/third_party/WebKit/Source/core/html/forms/RadioButtonGroupScope.cpp |
| @@ -22,6 +22,7 @@ |
| #include "core/InputTypeNames.h" |
| #include "core/html/HTMLInputElement.h" |
| +#include "core/layout/LayoutObject.h" |
| #include "wtf/HashMap.h" |
| namespace blink { |
| @@ -38,6 +39,8 @@ public: |
| void requiredAttributeChanged(HTMLInputElement*); |
| void remove(HTMLInputElement*); |
| bool contains(HTMLInputElement*) const; |
| + unsigned sizeOfMembers() const; |
| + void updatePosition() const; |
| DECLARE_TRACE(); |
| @@ -46,6 +49,7 @@ private: |
| void setNeedsValidityCheckForAllButtons(); |
| bool isValid() const; |
| void setCheckedButton(HTMLInputElement*); |
| + bool isNext(HTMLInputElement* list, HTMLInputElement* current) const; |
|
keishi
2016/02/05 03:05:26
nit: Could you make the method name more specific
je_julie(Not used)
2016/02/13 03:19:00
I updated it with isNextPosition().
|
| // The map records the 'required' state of each (button) element. |
| using Members = WillBeHeapHashMap<RawPtrWillBeMember<HTMLInputElement>, bool>; |
| @@ -61,11 +65,13 @@ private: |
| Members m_members; |
| RawPtrWillBeMember<HTMLInputElement> m_checkedButton; |
| size_t m_requiredCount; |
| + bool m_needToUpdateIndex; |
| }; |
| RadioButtonGroup::RadioButtonGroup() |
| : m_checkedButton(nullptr) |
| , m_requiredCount(0) |
| + , m_needToUpdateIndex(false) |
| { |
| } |
| @@ -109,6 +115,8 @@ void RadioButtonGroup::add(HTMLInputElement* button) |
| auto addResult = m_members.add(button, false); |
| if (!addResult.isNewEntry) |
| return; |
| + |
| + m_needToUpdateIndex = true; |
| bool groupWasValid = isValid(); |
| updateRequiredButton(*addResult.storedValue, button->isRequired()); |
| if (button->checked()) |
| @@ -162,6 +170,8 @@ void RadioButtonGroup::remove(HTMLInputElement* button) |
| auto it = m_members.find(button); |
| if (it == m_members.end()) |
| return; |
| + |
| + m_needToUpdateIndex = true; |
| bool wasValid = isValid(); |
| ASSERT(it->value == button->isRequired()); |
| updateRequiredButton(*it, false); |
| @@ -196,6 +206,54 @@ bool RadioButtonGroup::contains(HTMLInputElement* button) const |
| return m_members.contains(button); |
| } |
| +void RadioButtonGroup::updatePosition() const |
| +{ |
| + if (!m_needToUpdateIndex) |
|
keishi
2016/02/05 03:05:26
List order seems to rely on layout.
Does m_needToU
je_julie(Not used)
2016/02/13 03:19:00
I also set this flag in LayoutBlockFlow::layoutBlo
|
| + return; |
| + |
| + WillBeHeapVector<RawPtrWillBeMember<HTMLInputElement>> orderd; |
| + for (auto& element : m_members) { |
| + HTMLInputElement* const current = element.key; |
| + ASSERT(current->type() == InputTypeNames::radio); |
| + if (orderd.isEmpty()) { |
| + orderd.append(current); |
| + } else { |
| + unsigned position = 0; |
| + for (auto& orderedList : orderd) { |
| + if (!isNext(orderedList, current)) |
| + break; |
| + position++; |
| + } |
| + orderd.insert(position, current); |
| + } |
| + } |
| + |
| + unsigned index = 0; |
| + for (auto& orderedList : orderd) { |
| + index++; |
| + orderedList->setPositionInRadioGroup(index); |
| + } |
| +} |
| + |
| +bool RadioButtonGroup::isNext(HTMLInputElement* list, HTMLInputElement* current) const |
| +{ |
| + if (!current->layoutObject() || !list->layoutObject()) |
| + return true; |
| + |
| + IntRect listRect = list->layoutObject()->absoluteBoundingBoxRect(); |
| + IntRect currentRect = current->layoutObject()->absoluteBoundingBoxRect(); |
| + if (listRect.y() < currentRect.y()) |
| + return true; |
| + if (listRect.y() == currentRect.y() && listRect.x() <= currentRect.x()) |
|
keishi
2016/02/05 03:05:26
Just curious. Is this ok for rtl?
je_julie(Not used)
2016/02/13 03:19:00
Right. We have to consider RTL case as well. I upd
|
| + return true; |
| + return false; |
| +} |
| + |
| +unsigned RadioButtonGroup::sizeOfMembers() const |
| +{ |
| + return m_members.size(); |
| +} |
| + |
| DEFINE_TRACE(RadioButtonGroup) |
| { |
| #if ENABLE(OILPAN) |
| @@ -277,6 +335,28 @@ bool RadioButtonGroupScope::isInRequiredGroup(HTMLInputElement* element) const |
| return group && group->isRequired() && group->contains(element); |
| } |
| +unsigned RadioButtonGroupScope::sizeOfGroup(HTMLInputElement* element) const |
| +{ |
| + if (!m_nameToGroupMap) |
| + return 0; |
| + |
| + RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
| + if (!group) |
| + return 0; |
| + return group->sizeOfMembers(); |
| +} |
| + |
| +void RadioButtonGroupScope::updateGroupPosition(HTMLInputElement* element) const |
| +{ |
| + if (!m_nameToGroupMap) |
| + return; |
| + |
| + RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
| + if (!group) |
| + return; |
| + group->updatePosition(); |
| +} |
| + |
| void RadioButtonGroupScope::removeButton(HTMLInputElement* element) |
| { |
| ASSERT(element->type() == InputTypeNames::radio); |