OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> | 2 * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> |
3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org> |
4 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | 4 * Copyright (C) Research In Motion Limited 2011. All rights reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
10 * | 10 * |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 return adoptRef(new SubtreeModificationEventListener(trefElement, target
Id)); | 68 return adoptRef(new SubtreeModificationEventListener(trefElement, target
Id)); |
69 } | 69 } |
70 | 70 |
71 static const SubtreeModificationEventListener* cast(const EventListener* lis
tener) | 71 static const SubtreeModificationEventListener* cast(const EventListener* lis
tener) |
72 { | 72 { |
73 return listener->type() == CPPEventListenerType ? static_cast<const Subt
reeModificationEventListener*>(listener) : 0; | 73 return listener->type() == CPPEventListenerType ? static_cast<const Subt
reeModificationEventListener*>(listener) : 0; |
74 } | 74 } |
75 | 75 |
76 virtual bool operator==(const EventListener&); | 76 virtual bool operator==(const EventListener&); |
77 | 77 |
78 void removeFromTarget() | 78 void clear() |
79 { | 79 { |
80 Element* target = m_trefElement->treeScope()->getElementById(m_targetId)
; | 80 Element* target = m_trefElement->treeScope()->getElementById(m_targetId)
; |
81 if (target && target->parentNode()) | 81 if (target && target->parentNode()) |
82 target->parentNode()->removeEventListener(eventNames().DOMSubtreeMod
ifiedEvent, this, false); | 82 target->parentNode()->removeEventListener(eventNames().DOMSubtreeMod
ifiedEvent, this, false); |
| 83 |
| 84 m_trefElement = 0; |
| 85 m_targetId = String(); |
83 } | 86 } |
84 | 87 |
85 private: | 88 private: |
86 SubtreeModificationEventListener(SVGTRefElement* trefElement, String targetI
d) | 89 SubtreeModificationEventListener(SVGTRefElement* trefElement, String targetI
d) |
87 : EventListener(CPPEventListenerType) | 90 : EventListener(CPPEventListenerType) |
88 , m_trefElement(trefElement) | 91 , m_trefElement(trefElement) |
89 , m_targetId(targetId) | 92 , m_targetId(targetId) |
90 { | 93 { |
91 } | 94 } |
92 | 95 |
93 virtual void handleEvent(ScriptExecutionContext*, Event*); | 96 virtual void handleEvent(ScriptExecutionContext*, Event*); |
94 | 97 |
95 SVGTRefElement* m_trefElement; | 98 SVGTRefElement* m_trefElement; |
96 String m_targetId; | 99 String m_targetId; |
97 }; | 100 }; |
98 | 101 |
99 bool SubtreeModificationEventListener::operator==(const EventListener& listener) | 102 bool SubtreeModificationEventListener::operator==(const EventListener& listener) |
100 { | 103 { |
101 if (const SubtreeModificationEventListener* subtreeModificationEventListener
= SubtreeModificationEventListener::cast(&listener)) | 104 if (const SubtreeModificationEventListener* subtreeModificationEventListener
= SubtreeModificationEventListener::cast(&listener)) |
102 return m_trefElement == subtreeModificationEventListener->m_trefElement; | 105 return m_trefElement == subtreeModificationEventListener->m_trefElement; |
103 return false; | 106 return false; |
104 } | 107 } |
105 | 108 |
106 void SubtreeModificationEventListener::handleEvent(ScriptExecutionContext*, Even
t* event) | 109 void SubtreeModificationEventListener::handleEvent(ScriptExecutionContext*, Even
t* event) |
107 { | 110 { |
108 if (event->type() == eventNames().DOMSubtreeModifiedEvent && m_trefElement !
= event->target()) | 111 if (m_trefElement && event->type() == eventNames().DOMSubtreeModifiedEvent &
& m_trefElement != event->target()) |
109 m_trefElement->updateReferencedText(); | 112 m_trefElement->updateReferencedText(); |
110 } | 113 } |
111 | 114 |
112 class SVGShadowText : public Text { | 115 class SVGShadowText : public Text { |
113 public: | 116 public: |
114 static PassRefPtr<SVGShadowText> create(Document* document, const String& da
ta) | 117 static PassRefPtr<SVGShadowText> create(Document* document, const String& da
ta) |
115 { | 118 { |
116 return adoptRef(new SVGShadowText(document, data)); | 119 return adoptRef(new SVGShadowText(document, data)); |
117 } | 120 } |
118 private: | 121 private: |
(...skipping 12 matching lines...) Expand all Loading... |
131 | 134 |
132 bool SVGShadowText::willRecalcStyle(StyleChange change) | 135 bool SVGShadowText::willRecalcStyle(StyleChange change) |
133 { | 136 { |
134 if (change != NoChange && parentNode()->shadowHost()) { | 137 if (change != NoChange && parentNode()->shadowHost()) { |
135 if (renderer()) | 138 if (renderer()) |
136 renderer()->setStyle(parentNode()->shadowHost()->renderer()->style()
); | 139 renderer()->setStyle(parentNode()->shadowHost()->renderer()->style()
); |
137 } | 140 } |
138 return true; | 141 return true; |
139 } | 142 } |
140 | 143 |
| 144 SVGTRefElement::~SVGTRefElement() |
| 145 { |
| 146 clearEventListener(); |
| 147 } |
| 148 |
141 void SVGTRefElement::updateReferencedText() | 149 void SVGTRefElement::updateReferencedText() |
142 { | 150 { |
143 Element* target = SVGURIReference::targetElementFromIRIString(href(), docume
nt()); | 151 Element* target = SVGURIReference::targetElementFromIRIString(href(), docume
nt()); |
144 ASSERT(target); | 152 ASSERT(target); |
145 String textContent; | 153 String textContent; |
146 if (target->parentNode()) | 154 if (target->parentNode()) |
147 textContent = target->textContent(); | 155 textContent = target->textContent(); |
148 ExceptionCode ignore = 0; | 156 ExceptionCode ignore = 0; |
149 if (!ensureShadowRoot()->firstChild()) | 157 if (!ensureShadowRoot()->firstChild()) |
150 shadowRoot()->appendChild(SVGShadowText::create(document(), textContent)
, ignore); | 158 shadowRoot()->appendChild(SVGShadowText::create(document(), textContent)
, ignore); |
(...skipping 26 matching lines...) Expand all Loading... |
177 void SVGTRefElement::svgAttributeChanged(const QualifiedName& attrName) | 185 void SVGTRefElement::svgAttributeChanged(const QualifiedName& attrName) |
178 { | 186 { |
179 if (!isSupportedAttribute(attrName)) { | 187 if (!isSupportedAttribute(attrName)) { |
180 SVGTextPositioningElement::svgAttributeChanged(attrName); | 188 SVGTextPositioningElement::svgAttributeChanged(attrName); |
181 return; | 189 return; |
182 } | 190 } |
183 | 191 |
184 SVGElementInstance::InvalidationGuard invalidationGuard(this); | 192 SVGElementInstance::InvalidationGuard invalidationGuard(this); |
185 | 193 |
186 if (SVGURIReference::isKnownAttribute(attrName)) { | 194 if (SVGURIReference::isKnownAttribute(attrName)) { |
187 if (m_eventListener) { | 195 buildPendingResource(); |
188 m_eventListener->removeFromTarget(); | |
189 m_eventListener = 0; | |
190 } | |
191 String id; | |
192 Element* target = SVGURIReference::targetElementFromIRIString(href(), do
cument(), &id); | |
193 if (!target) { | |
194 document()->accessSVGExtensions()->addPendingResource(id, this); | |
195 return; | |
196 } | |
197 updateReferencedText(); | |
198 if (inDocument()) { | |
199 m_eventListener = SubtreeModificationEventListener::create(this, id)
; | |
200 ASSERT(target->parentNode()); | |
201 target->parentNode()->addEventListener(eventNames().DOMSubtreeModifi
edEvent, m_eventListener.get(), false); | |
202 } | |
203 if (RenderObject* renderer = this->renderer()) | 196 if (RenderObject* renderer = this->renderer()) |
204 RenderSVGResource::markForLayoutAndParentResourceInvalidation(render
er); | 197 RenderSVGResource::markForLayoutAndParentResourceInvalidation(render
er); |
205 return; | 198 return; |
206 } | 199 } |
207 | 200 |
208 ASSERT_NOT_REACHED(); | 201 ASSERT_NOT_REACHED(); |
209 } | 202 } |
210 | 203 |
211 RenderObject* SVGTRefElement::createRenderer(RenderArena* arena, RenderStyle*) | 204 RenderObject* SVGTRefElement::createRenderer(RenderArena* arena, RenderStyle*) |
212 { | 205 { |
(...skipping 15 matching lines...) Expand all Loading... |
228 || parentNode()->hasTagName(SVGNames::textTag) | 221 || parentNode()->hasTagName(SVGNames::textTag) |
229 || parentNode()->hasTagName(SVGNames::textPathTag) | 222 || parentNode()->hasTagName(SVGNames::textPathTag) |
230 || parentNode()->hasTagName(SVGNames::tspanTag))) | 223 || parentNode()->hasTagName(SVGNames::tspanTag))) |
231 return StyledElement::rendererIsNeeded(context); | 224 return StyledElement::rendererIsNeeded(context); |
232 | 225 |
233 return false; | 226 return false; |
234 } | 227 } |
235 | 228 |
236 void SVGTRefElement::buildPendingResource() | 229 void SVGTRefElement::buildPendingResource() |
237 { | 230 { |
| 231 // Remove any existing event listener. |
| 232 clearEventListener(); |
| 233 |
| 234 String id; |
| 235 Element* target = SVGURIReference::targetElementFromIRIString(href(), docume
nt(), &id); |
| 236 if (!target) { |
| 237 if (hasPendingResources() || id.isEmpty()) |
| 238 return; |
| 239 |
| 240 ASSERT(!hasPendingResources()); |
| 241 document()->accessSVGExtensions()->addPendingResource(id, this); |
| 242 ASSERT(hasPendingResources()); |
| 243 return; |
| 244 } |
| 245 |
238 updateReferencedText(); | 246 updateReferencedText(); |
239 if (Element* target = SVGURIReference::targetElementFromIRIString(href(), do
cument())) { | 247 |
240 ASSERT(!m_eventListener); | 248 // We should not add the event listener if we are not in document yet. |
241 m_eventListener = SubtreeModificationEventListener::create(this, target-
>getIdAttribute()); | 249 if (!inDocument()) |
242 ASSERT(target->parentNode()); | 250 return; |
243 target->parentNode()->addEventListener(eventNames().DOMSubtreeModifiedEv
ent, m_eventListener.get(), false); | 251 |
244 } | 252 m_eventListener = SubtreeModificationEventListener::create(this, id); |
| 253 ASSERT(target->parentNode()); |
| 254 target->parentNode()->addEventListener(eventNames().DOMSubtreeModifiedEvent,
m_eventListener.get(), false); |
245 } | 255 } |
246 | 256 |
247 void SVGTRefElement::insertedIntoDocument() | 257 void SVGTRefElement::insertedIntoDocument() |
248 { | 258 { |
249 SVGStyledElement::insertedIntoDocument(); | 259 SVGStyledElement::insertedIntoDocument(); |
250 String id; | 260 buildPendingResource(); |
251 Element* target = SVGURIReference::targetElementFromIRIString(href(), docume
nt(), &id); | |
252 if (!target) { | |
253 document()->accessSVGExtensions()->addPendingResource(id, this); | |
254 return; | |
255 } | |
256 updateReferencedText(); | |
257 m_eventListener = SubtreeModificationEventListener::create(this, id); | |
258 ASSERT(target->parentNode()); | |
259 target->parentNode()->addEventListener(eventNames().DOMSubtreeModifiedEvent,
m_eventListener.get(), false); | |
260 } | 261 } |
261 | 262 |
262 void SVGTRefElement::removedFromDocument() | 263 void SVGTRefElement::removedFromDocument() |
263 { | 264 { |
264 SVGStyledElement::removedFromDocument(); | 265 SVGStyledElement::removedFromDocument(); |
| 266 clearEventListener(); |
| 267 } |
265 | 268 |
266 if (!m_eventListener) | 269 void SVGTRefElement::clearEventListener() |
267 return; | 270 { |
268 | 271 if (m_eventListener) { |
269 m_eventListener->removeFromTarget(); | 272 m_eventListener->clear(); |
270 m_eventListener = 0; | 273 m_eventListener = 0; |
| 274 } |
271 } | 275 } |
272 | 276 |
273 } | 277 } |
274 | 278 |
275 #endif // ENABLE(SVG) | 279 #endif // ENABLE(SVG) |
OLD | NEW |