/src/mozilla-central/accessible/html/HTMLImageMapAccessible.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | #include "HTMLImageMapAccessible.h" |
7 | | |
8 | | #include "ARIAMap.h" |
9 | | #include "nsAccUtils.h" |
10 | | #include "DocAccessible-inl.h" |
11 | | #include "Role.h" |
12 | | |
13 | | #include "nsIServiceManager.h" |
14 | | #include "nsIFrame.h" |
15 | | #include "nsImageFrame.h" |
16 | | #include "nsImageMap.h" |
17 | | #include "nsIURI.h" |
18 | | #include "mozilla/dom/HTMLAreaElement.h" |
19 | | |
20 | | using namespace mozilla::a11y; |
21 | | |
22 | | //////////////////////////////////////////////////////////////////////////////// |
23 | | // HTMLImageMapAccessible |
24 | | //////////////////////////////////////////////////////////////////////////////// |
25 | | |
26 | | HTMLImageMapAccessible:: |
27 | | HTMLImageMapAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
28 | | ImageAccessibleWrap(aContent, aDoc) |
29 | 0 | { |
30 | 0 | mType = eImageMapType; |
31 | 0 |
|
32 | 0 | UpdateChildAreas(false); |
33 | 0 | } |
34 | | |
35 | | //////////////////////////////////////////////////////////////////////////////// |
36 | | // HTMLImageMapAccessible: Accessible public |
37 | | |
38 | | role |
39 | | HTMLImageMapAccessible::NativeRole() const |
40 | 0 | { |
41 | 0 | return roles::IMAGE_MAP; |
42 | 0 | } |
43 | | |
44 | | //////////////////////////////////////////////////////////////////////////////// |
45 | | // HTMLImageMapAccessible: HyperLinkAccessible |
46 | | |
47 | | uint32_t |
48 | | HTMLImageMapAccessible::AnchorCount() |
49 | 0 | { |
50 | 0 | return ChildCount(); |
51 | 0 | } |
52 | | |
53 | | Accessible* |
54 | | HTMLImageMapAccessible::AnchorAt(uint32_t aAnchorIndex) |
55 | 0 | { |
56 | 0 | return GetChildAt(aAnchorIndex); |
57 | 0 | } |
58 | | |
59 | | already_AddRefed<nsIURI> |
60 | | HTMLImageMapAccessible::AnchorURIAt(uint32_t aAnchorIndex) const |
61 | 0 | { |
62 | 0 | Accessible* area = GetChildAt(aAnchorIndex); |
63 | 0 | if (!area) |
64 | 0 | return nullptr; |
65 | 0 | |
66 | 0 | nsIContent* linkContent = area->GetContent(); |
67 | 0 | return linkContent ? linkContent->GetHrefURI() : nullptr; |
68 | 0 | } |
69 | | |
70 | | //////////////////////////////////////////////////////////////////////////////// |
71 | | // HTMLImageMapAccessible: public |
72 | | |
73 | | void |
74 | | HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents) |
75 | 0 | { |
76 | 0 | nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame()); |
77 | 0 |
|
78 | 0 | // If image map is not initialized yet then we trigger one time more later. |
79 | 0 | nsImageMap* imageMapObj = imageFrame->GetExistingImageMap(); |
80 | 0 | if (!imageMapObj) |
81 | 0 | return; |
82 | 0 | |
83 | 0 | TreeMutation mt(this, TreeMutation::kNoEvents & !aDoFireEvents); |
84 | 0 |
|
85 | 0 | // Remove areas that are not a valid part of the image map anymore. |
86 | 0 | for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) { |
87 | 0 | Accessible* area = mChildren.ElementAt(childIdx); |
88 | 0 | if (area->GetContent()->GetPrimaryFrame()) |
89 | 0 | continue; |
90 | 0 | |
91 | 0 | mt.BeforeRemoval(area); |
92 | 0 | RemoveChild(area); |
93 | 0 | } |
94 | 0 |
|
95 | 0 | // Insert new areas into the tree. |
96 | 0 | uint32_t areaElmCount = imageMapObj->AreaCount(); |
97 | 0 | for (uint32_t idx = 0; idx < areaElmCount; idx++) { |
98 | 0 | nsIContent* areaContent = imageMapObj->GetAreaAt(idx); |
99 | 0 | Accessible* area = mChildren.SafeElementAt(idx); |
100 | 0 | if (!area || area->GetContent() != areaContent) { |
101 | 0 | RefPtr<Accessible> area = new HTMLAreaAccessible(areaContent, mDoc); |
102 | 0 | mDoc->BindToDocument(area, aria::GetRoleMap(areaContent->AsElement())); |
103 | 0 |
|
104 | 0 | if (!InsertChildAt(idx, area)) { |
105 | 0 | mDoc->UnbindFromDocument(area); |
106 | 0 | break; |
107 | 0 | } |
108 | 0 | |
109 | 0 | mt.AfterInsertion(area); |
110 | 0 | } |
111 | 0 | } |
112 | 0 |
|
113 | 0 | mt.Done(); |
114 | 0 | } |
115 | | |
116 | | Accessible* |
117 | | HTMLImageMapAccessible::GetChildAccessibleFor(const nsINode* aNode) const |
118 | 0 | { |
119 | 0 | uint32_t length = mChildren.Length(); |
120 | 0 | for (uint32_t i = 0; i < length; i++) { |
121 | 0 | Accessible* area = mChildren[i]; |
122 | 0 | if (area->GetContent() == aNode) |
123 | 0 | return area; |
124 | 0 | } |
125 | 0 |
|
126 | 0 | return nullptr; |
127 | 0 | } |
128 | | |
129 | | //////////////////////////////////////////////////////////////////////////////// |
130 | | // HTMLAreaAccessible |
131 | | //////////////////////////////////////////////////////////////////////////////// |
132 | | |
133 | | HTMLAreaAccessible:: |
134 | | HTMLAreaAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
135 | | HTMLLinkAccessible(aContent, aDoc) |
136 | 0 | { |
137 | 0 | // Make HTML area DOM element not accessible. HTML image map accessible |
138 | 0 | // manages its tree itself. |
139 | 0 | mStateFlags |= eNotNodeMapEntry; |
140 | 0 | } |
141 | | |
142 | | //////////////////////////////////////////////////////////////////////////////// |
143 | | // HTMLAreaAccessible: Accessible |
144 | | |
145 | | ENameValueFlag |
146 | | HTMLAreaAccessible::NativeName(nsString& aName) const |
147 | 0 | { |
148 | 0 | ENameValueFlag nameFlag = Accessible::NativeName(aName); |
149 | 0 | if (!aName.IsEmpty()) |
150 | 0 | return nameFlag; |
151 | 0 | |
152 | 0 | if (!mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName)) |
153 | 0 | Value(aName); |
154 | 0 |
|
155 | 0 | return eNameOK; |
156 | 0 | } |
157 | | |
158 | | void |
159 | | HTMLAreaAccessible::Description(nsString& aDescription) |
160 | 0 | { |
161 | 0 | aDescription.Truncate(); |
162 | 0 |
|
163 | 0 | // Still to do - follow IE's standard here |
164 | 0 | RefPtr<dom::HTMLAreaElement> area = |
165 | 0 | dom::HTMLAreaElement::FromNodeOrNull(mContent); |
166 | 0 | if (area) |
167 | 0 | area->GetShape(aDescription); |
168 | 0 | } |
169 | | |
170 | | //////////////////////////////////////////////////////////////////////////////// |
171 | | // HTMLAreaAccessible: Accessible public |
172 | | |
173 | | Accessible* |
174 | | HTMLAreaAccessible::ChildAtPoint(int32_t aX, int32_t aY, |
175 | | EWhichChildAtPoint aWhichChild) |
176 | 0 | { |
177 | 0 | // Don't walk into area accessibles. |
178 | 0 | return this; |
179 | 0 | } |
180 | | |
181 | | //////////////////////////////////////////////////////////////////////////////// |
182 | | // HTMLImageMapAccessible: HyperLinkAccessible |
183 | | |
184 | | uint32_t |
185 | | HTMLAreaAccessible::StartOffset() |
186 | 0 | { |
187 | 0 | // Image map accessible is not hypertext accessible therefore |
188 | 0 | // StartOffset/EndOffset implementations of Accessible doesn't work here. |
189 | 0 | // We return index in parent because image map contains area links only which |
190 | 0 | // are embedded objects. |
191 | 0 | // XXX: image map should be a hypertext accessible. |
192 | 0 | return IndexInParent(); |
193 | 0 | } |
194 | | |
195 | | uint32_t |
196 | | HTMLAreaAccessible::EndOffset() |
197 | 0 | { |
198 | 0 | return IndexInParent() + 1; |
199 | 0 | } |
200 | | |
201 | | nsRect |
202 | | HTMLAreaAccessible::RelativeBounds(nsIFrame** aBoundingFrame) const |
203 | 0 | { |
204 | 0 | nsIFrame* frame = GetFrame(); |
205 | 0 | if (!frame) |
206 | 0 | return nsRect(); |
207 | 0 | |
208 | 0 | nsImageFrame* imageFrame = do_QueryFrame(frame); |
209 | 0 | nsImageMap* map = imageFrame->GetImageMap(); |
210 | 0 |
|
211 | 0 | nsRect bounds; |
212 | 0 | nsresult rv = map->GetBoundsForAreaContent(mContent, bounds); |
213 | 0 | if (NS_FAILED(rv)) |
214 | 0 | return nsRect(); |
215 | 0 | |
216 | 0 | // XXX Areas are screwy; they return their rects as a pair of points, one pair |
217 | 0 | // stored into the width and height. |
218 | 0 | *aBoundingFrame = frame; |
219 | 0 | bounds.SizeTo(bounds.Width() - bounds.X(), bounds.Height() - bounds.Y()); |
220 | 0 | return bounds; |
221 | 0 | } |