Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 | |
| 6 #include "modules/accessibility/AXRadioInput.h" | |
| 7 | |
| 8 #include "core/dom/ElementTraversal.h" | |
| 9 #include "core/html/HTMLInputElement.h" | |
| 10 #include "modules/accessibility/AXObjectCacheImpl.h" | |
| 11 | |
| 12 namespace blink { | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 HTMLElement* nextElement(const HTMLElement& element, HTMLFormElement* stayWithin , bool forward) | |
| 17 { | |
| 18 return forward ? Traversal<HTMLElement>::next(element, (Node* )stayWithin) : Traversal<HTMLElement>::previous(element, (Node* )stayWithin); | |
| 19 } | |
| 20 | |
| 21 } // namespace | |
| 22 | |
| 23 using namespace HTMLNames; | |
| 24 | |
| 25 AXRadioInput::AXRadioInput(LayoutObject* layoutObject, AXObjectCacheImpl& axObje ctCache) | |
| 26 : AXLayoutObject(layoutObject, axObjectCache) | |
| 27 { | |
| 28 // Updates posInSet and setSize for the current object and the next objects. | |
| 29 if (!calculatePosInSet()) | |
| 30 return; | |
| 31 // When a new object is inserted, it needs to update setSize for the previou s objects. | |
| 32 requestUpdateToNextNode(false); | |
| 33 } | |
| 34 | |
| 35 AXRadioInput* AXRadioInput::create(LayoutObject* layoutObject, AXObjectCacheImpl & axObjectCache) | |
| 36 { | |
| 37 return new AXRadioInput(layoutObject, axObjectCache); | |
| 38 } | |
| 39 | |
| 40 void AXRadioInput::updatePosAndSetSize(int position) | |
| 41 { | |
| 42 if (position) | |
| 43 m_posInSet = position; | |
| 44 m_setSize = sizeOfRadioGroup(); | |
| 45 } | |
| 46 | |
| 47 void AXRadioInput::requestUpdateToNextNode(bool forward) | |
| 48 { | |
| 49 HTMLInputElement* nextElement = findNextFocusableRadioButtonInGroup(element( ), forward); | |
| 50 AXObject* nextAXobject = axObjectCache().get(nextElement); | |
| 51 if (!nextAXobject || !nextAXobject->isAXRadioInput()) | |
| 52 return; | |
| 53 int position = 0; | |
| 54 if (forward) | |
| 55 position = posInSet() + 1; | |
| 56 // It moves to backward only when a new node inserted to AX tree which alrea dy exists. | |
| 57 // it just needs update for setSize and its position is not changed. | |
| 58 toAXRadioInput(nextAXobject)->updatePosAndSetSize(position); | |
| 59 axObjectCache().postNotification(nextAXobject, AXObjectCacheImpl::AXAriaAttr ibuteChanged); | |
| 60 toAXRadioInput(nextAXobject)->requestUpdateToNextNode(forward); | |
| 61 } | |
| 62 | |
| 63 HTMLInputElement* AXRadioInput::findFristFocusableRadioButtonInGroup(HTMLInputEl ement* current) const | |
|
keishi
2016/02/29 05:19:19
s/Frist/First/
je_julie(Not used)
2016/02/29 15:11:44
Done.
| |
| 64 { | |
| 65 while (HTMLInputElement* prevElement = findNextFocusableRadioButtonInGroup(c urrent, false)) | |
| 66 current = prevElement; | |
| 67 return current; | |
| 68 } | |
| 69 | |
| 70 int AXRadioInput::posInSet() const | |
| 71 { | |
| 72 if (hasAttribute(aria_posinsetAttr)) | |
| 73 return getAttribute(aria_posinsetAttr).toInt(); | |
| 74 return m_posInSet; | |
| 75 } | |
| 76 | |
| 77 int AXRadioInput::setSize() const | |
| 78 { | |
| 79 if (hasAttribute(aria_setsizeAttr)) | |
| 80 return getAttribute(aria_setsizeAttr).toInt(); | |
| 81 return m_setSize; | |
| 82 } | |
| 83 | |
| 84 bool AXRadioInput::calculatePosInSet() | |
| 85 { | |
| 86 // Calculate 'posInSet' attribute when AXRadioInputs need to be updated | |
| 87 // as a new AXRadioInput Object is added or one of objects from RadioGroup i s removed. | |
| 88 bool needToUpdatePrev = false; | |
| 89 int position = 1; | |
| 90 HTMLInputElement* prevElement = findNextFocusableRadioButtonInGroup(element( ), false); | |
| 91 if (prevElement) { | |
| 92 AXObject* object = axObjectCache().get(prevElement); | |
| 93 // If the previous element doesn't have AXObject yet, caculate position from the first element. | |
| 94 // Otherwise, get position from the previous AXObject. | |
| 95 if (!object || !object->isAXRadioInput()) { | |
| 96 position = countFromFirstElement(); | |
| 97 } else { | |
| 98 position = object->posInSet() + 1; | |
| 99 // It returns true if previous objects need to be updated. | |
| 100 // When AX tree exists already and a new node is inserted, | |
| 101 // as updating is started from the inserted node, | |
| 102 // we need to update setSize for previous nodes. | |
| 103 if (setSize() != object->setSize()) | |
| 104 needToUpdatePrev = true; | |
| 105 } | |
| 106 } | |
| 107 updatePosAndSetSize(position); | |
| 108 | |
| 109 // If it is not the last element, request update to the next node. | |
| 110 if (position != setSize()) | |
| 111 requestUpdateToNextNode(true); | |
| 112 return needToUpdatePrev; | |
| 113 } | |
| 114 | |
| 115 HTMLInputElement* AXRadioInput::findNextFocusableRadioButtonInGroup(HTMLInputEle ment* current, bool forward) const | |
|
keishi
2016/02/29 05:19:19
nit: This function isn't checking focusable.
je_julie(Not used)
2016/02/29 15:11:44
According to spec, there is no mention about focus
dmazzoni
2016/02/29 17:16:18
That's fine, but change the name of the function f
| |
| 116 { | |
| 117 for (HTMLElement* htmlElement = nextElement(*current, current->form(), forwa rd); htmlElement; htmlElement = nextElement(*htmlElement, current->form(), forwa rd)) { | |
| 118 if (!isHTMLInputElement(*htmlElement)) | |
| 119 continue; | |
| 120 HTMLInputElement* inputElement = toHTMLInputElement(htmlElement); | |
| 121 if (current->form() == inputElement->form() && inputElement->isRadioButt on() && inputElement->name() == current->name()) | |
| 122 return inputElement; | |
| 123 } | |
| 124 return nullptr; | |
| 125 } | |
| 126 | |
| 127 int AXRadioInput::countFromFirstElement() const | |
| 128 { | |
| 129 int count = 1; | |
| 130 HTMLInputElement* current = element(); | |
| 131 while (HTMLInputElement* prevElement = findNextFocusableRadioButtonInGroup(c urrent, false)) { | |
| 132 current = prevElement; | |
| 133 count++; | |
| 134 } | |
| 135 return count; | |
| 136 } | |
| 137 | |
| 138 HTMLInputElement* AXRadioInput::element() const | |
| 139 { | |
| 140 return toHTMLInputElement(m_layoutObject->node()); | |
| 141 } | |
| 142 | |
| 143 int AXRadioInput::sizeOfRadioGroup() const | |
| 144 { | |
| 145 int size = element()->sizeOfRadioGroup(); | |
| 146 // If it has no size in Group, it means that there is only itself. | |
| 147 if (!size) | |
| 148 return 1; | |
| 149 return size; | |
| 150 } | |
| 151 | |
| 152 } // namespace blink | |
| OLD | NEW |