1/*
2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "AccessibilitySpinButton.h"
28
29#include "AXObjectCache.h"
30#include "RenderElement.h"
31
32namespace WebCore {
33
34Ref<AccessibilitySpinButton> AccessibilitySpinButton::create()
35{
36 return adoptRef(*new AccessibilitySpinButton);
37}
38
39AccessibilitySpinButton::AccessibilitySpinButton()
40 : m_spinButtonElement(nullptr)
41{
42}
43
44AccessibilitySpinButton::~AccessibilitySpinButton() = default;
45
46AccessibilityObject* AccessibilitySpinButton::incrementButton()
47{
48 if (!m_haveChildren)
49 addChildren();
50 if (!m_haveChildren)
51 return nullptr;
52
53 ASSERT(m_children.size() == 2);
54
55 return m_children[0].get();
56}
57
58AccessibilityObject* AccessibilitySpinButton::decrementButton()
59{
60 if (!m_haveChildren)
61 addChildren();
62 if (!m_haveChildren)
63 return nullptr;
64
65 ASSERT(m_children.size() == 2);
66
67 return m_children[1].get();
68}
69
70LayoutRect AccessibilitySpinButton::elementRect() const
71{
72 ASSERT(m_spinButtonElement);
73
74 if (!m_spinButtonElement || !m_spinButtonElement->renderer())
75 return LayoutRect();
76
77 Vector<FloatQuad> quads;
78 m_spinButtonElement->renderer()->absoluteFocusRingQuads(quads);
79
80 return boundingBoxForQuads(m_spinButtonElement->renderer(), quads);
81}
82
83void AccessibilitySpinButton::addChildren()
84{
85 AXObjectCache* cache = axObjectCache();
86 if (!cache)
87 return;
88
89 m_haveChildren = true;
90
91 auto& incrementor = downcast<AccessibilitySpinButtonPart>(*cache->getOrCreate(AccessibilityRole::SpinButtonPart));
92 incrementor.setIsIncrementor(true);
93 incrementor.setParent(this);
94 m_children.append(&incrementor);
95
96 auto& decrementor = downcast<AccessibilitySpinButtonPart>(*cache->getOrCreate(AccessibilityRole::SpinButtonPart));
97 decrementor.setIsIncrementor(false);
98 decrementor.setParent(this);
99 m_children.append(&decrementor);
100}
101
102void AccessibilitySpinButton::step(int amount)
103{
104 ASSERT(m_spinButtonElement);
105 if (!m_spinButtonElement)
106 return;
107
108 m_spinButtonElement->step(amount);
109}
110
111// AccessibilitySpinButtonPart
112
113AccessibilitySpinButtonPart::AccessibilitySpinButtonPart()
114 : m_isIncrementor(false)
115{
116}
117
118Ref<AccessibilitySpinButtonPart> AccessibilitySpinButtonPart::create()
119{
120 return adoptRef(*new AccessibilitySpinButtonPart);
121}
122
123LayoutRect AccessibilitySpinButtonPart::elementRect() const
124{
125 // FIXME: This logic should exist in the render tree or elsewhere, but there is no
126 // relationship that exists that can be queried.
127
128 LayoutRect parentRect = parentObject()->elementRect();
129 if (m_isIncrementor)
130 parentRect.setHeight(parentRect.height() / 2);
131 else {
132 parentRect.setY(parentRect.y() + parentRect.height() / 2);
133 parentRect.setHeight(parentRect.height() / 2);
134 }
135
136 return parentRect;
137}
138
139bool AccessibilitySpinButtonPart::press()
140{
141 if (!is<AccessibilitySpinButton>(m_parent))
142 return false;
143
144 auto& spinButton = downcast<AccessibilitySpinButton>(*m_parent);
145 if (m_isIncrementor)
146 spinButton.step(1);
147 else
148 spinButton.step(-1);
149
150 return true;
151}
152
153} // namespace WebCore
154