2 Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org>
5 This file is part of the KDE project
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
24 #include "wtf/Platform.h"
27 #include "SVGElement.h"
29 /*#include "DOMImplementation.h"*/
32 #include "EventListener.h"
33 #include "EventNames.h"
34 #include "FrameView.h"
35 #include "HTMLNames.h"
36 #include "PlatformString.h"
37 #include "RenderObject.h"
38 #include "SVGDocumentExtensions.h"
39 #include "SVGElementInstance.h"*/
41 #include "SVGSVGElement.h"
42 /*#include "SVGURIReference.h"
43 #include "SVGUseElement.h"
45 #include "RegisteredEventListener.h"*/
49 //using namespace HTMLNames;
50 //using namespace EventNames;
52 SVGElement::SVGElement(const QualifiedName
& tagName
, Document
* doc
)
53 : StyledElement(doc
) // it's wrong, remove it!!! FIXME: vtokarev
54 // : StyledElement(tagName, doc)
55 // , m_shadowParent(0)
59 SVGElement::~SVGElement()
63 bool SVGElement::isSupported(StringImpl
* feature
, StringImpl
* version
) const
65 if (DOMImplementation::instance()->hasFeature(feature
, version
))
68 return DOMImplementation::instance()->hasFeature(feature
, version
);
72 String
SVGElement::attrid() const
74 return getAttribute(idAttr
);
78 void SVGElement::setId(const String
& value
, ExceptionCode
&)
80 setAttribute(idAttr
, value
);
84 String
SVGElement::xmlbase() const
86 //return getAttribute(XMLNames::baseAttr);
91 void SVGElement::setXmlbase(const String
& value
, ExceptionCode
&)
93 //setAttribute(XMLNames::baseAttr, value);
96 SVGSVGElement
* SVGElement::ownerSVGElement() const
98 Node
* n
= isShadowNode() ? const_cast<SVGElement
*>(this)->shadowParentNode() : parentNode();
100 if (/*n->hasTagName(SVGNames::svgTag)*/n
->id() == SVGNames::svgTag
.id())
101 return static_cast<SVGSVGElement
*>(n
);
103 n
= n
->isShadowNode() ? n
->shadowParentNode() : n
->parentNode();
109 SVGElement
* SVGElement::viewportElement() const
111 // This function needs shadow tree support - as RenderSVGContainer uses this function
112 // to determine the "overflow" property. <use> on <symbol> wouldn't work otherwhise.
113 /*Node* n = isShadowNode() ? const_cast<SVGElement*>(this)->shadowParentNode() : parentNode();
115 if (n->hasTagName(SVGNames::svgTag) || n->hasTagName(SVGNames::imageTag) || n->hasTagName(SVGNames::symbolTag))
116 return static_cast<SVGElement*>(n);
118 n = n->isShadowNode() ? n->shadowParentNode() : n->parentNode();
124 void SVGElement::addSVGEventListener(/*const AtomicString& eventType*/const EventImpl::EventId
& eventType
, const Attribute
* attr
)
126 kDebug() << "add listener for: " << EventName::fromId(eventType
).toString() << endl
;
127 Element::setHTMLEventListener(EventName::fromId(eventType
), document()->accessSVGExtensions()->
128 createSVGEventListener(attr
->localName().string(), attr
->value(), this));
131 void SVGElement::parseMappedAttribute(MappedAttribute
* attr
)
134 if (/*attr->name() == onloadAttr*/attr
->id() == ATTR_ONLOAD
)
135 addSVGEventListener(/*loadEvent*/EventImpl::LOAD_EVENT
, attr
);
136 else if (/*attr->name() == onclickAttr*/attr
->id() == ATTR_ONCLICK
)
137 addSVGEventListener(/*clickEvent*/EventImpl::CLICK_EVENT
, attr
);
138 else /*if (attr->name() == onmousedownAttr)
139 addSVGEventListener(mousedownEvent, attr);
140 else if (attr->name() == onmousemoveAttr)
141 addSVGEventListener(mousemoveEvent, attr);
142 else if (attr->name() == onmouseoutAttr)
143 addSVGEventListener(mouseoutEvent, attr);
144 else if (attr->name() == onmouseoverAttr)
145 addSVGEventListener(mouseoverEvent, attr);
146 else if (attr->name() == onmouseupAttr)
147 addSVGEventListener(mouseupEvent, attr);
148 else if (attr->name() == SVGNames::onfocusinAttr)
149 addSVGEventListener(DOMFocusInEvent, attr);
150 else if (attr->name() == SVGNames::onfocusoutAttr)
151 addSVGEventListener(DOMFocusOutEvent, attr);
152 else if (attr->name() == SVGNames::onactivateAttr)
153 addSVGEventListener(DOMActivateEvent, attr);
155 if (attr
->id() == ATTR_ID
) {
157 document()->incDOMTreeVersion();
159 StyledElement::parseAttribute(attr
);
162 bool SVGElement::haveLoadedRequiredResources()
164 Node
* child
= firstChild();
166 if (child
->isSVGElement() && !static_cast<SVGElement
*>(child
)->haveLoadedRequiredResources())
168 child
= child
->nextSibling();
173 static bool hasLoadListener(SVGElement
* node
)
175 Node
* currentNode
= node
;
176 while (currentNode
&& currentNode
->isElementNode()) {
177 QList
<RegisteredEventListener
> *list
= static_cast<Element
*>(currentNode
)->localEventListeners();
179 QList
<RegisteredEventListener
>::Iterator end
= list
->end();
180 for (QList
<RegisteredEventListener
>::Iterator it
= list
->begin(); it
!= end
; ++it
)
181 if ((*it
).useCapture
|| (*it
).eventName
.id() == EventImpl::LOAD_EVENT
/* || currentNode == node*/)
183 /*if ((*it)->eventType() == loadEvent &&
184 (*it)->useCapture() == true || currentNode == node)
187 currentNode
= currentNode
->parentNode();
193 void SVGElement::sendSVGLoadEventIfPossible(bool sendParentLoadEvents
)
195 kDebug() << "send svg load event" << endl
;
196 RefPtr
<SVGElement
> currentTarget
= this;
197 kDebug() << currentTarget
<< currentTarget
->haveLoadedRequiredResources() << endl
;
198 while (currentTarget
&& currentTarget
->haveLoadedRequiredResources()) {
200 if (sendParentLoadEvents
)
201 parent
= currentTarget
->parentNode(); // save the next parent to dispatch too incase dispatching the event changes the tree
202 kDebug() << hasLoadListener(currentTarget
.get()) << endl
;
203 if (hasLoadListener(currentTarget
.get())) {
204 //Event* event = new Event(EventImpl::LOAD_EVENT, true/*false*/, false);
205 //event->setTarget(currentTarget.get());
206 //ExceptionCode ignored = 0;
207 //dispatchGenericEvent(/*currentTarget.get(), */event, ignored/*, false*/);
208 dispatchHTMLEvent(EventImpl::LOAD_EVENT
, false, false);
210 currentTarget
= (parent
&& parent
->isSVGElement()) ? static_pointer_cast
<SVGElement
>(parent
) : RefPtr
<SVGElement
>();
214 void SVGElement::finishParsingChildren()
216 // finishParsingChildren() is called when the close tag is reached for an element (e.g. </svg>)
217 // we send SVGLoad events here if we can, otherwise they'll be sent when any required loads finish
218 sendSVGLoadEventIfPossible();
221 bool SVGElement::childShouldCreateRenderer(Node
* child
) const
223 if (child
->isSVGElement())
224 return static_cast<SVGElement
*>(child
)->isValid();
228 void SVGElement::insertedIntoDocument()
230 StyledElement::insertedIntoDocument();
231 /*SVGDocumentExtensions* extensions = document()->accessSVGExtensions();
233 String resourceId = SVGURIReference::getTarget(id());
234 if (extensions->isPendingResource(resourceId)) {
235 std::auto_ptr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(resourceId));
236 if (clients->isEmpty())
239 HashSet<SVGStyledElement*>::const_iterator it = clients->begin();
240 const HashSet<SVGStyledElement*>::const_iterator end = clients->end();
242 for (; it != end; ++it)
243 (*it)->buildPendingResource();
245 SVGResource::invalidateClients(*clients);
249 static Node
* shadowTreeParentElementForShadowTreeElement(Node
* node
)
251 for (Node
* n
= node
; n
; n
= n
->parentNode()) {
252 /*if (n->isShadowNode())
253 return n->shadowParentNode();*/
259 bool SVGElement::dispatchEvent(Event
* e
, ExceptionCode
& ec
, bool tempEvent
)
261 kDebug() << "dispatch event" << endl
;
262 // TODO: This function will be removed in a follow-up patch!
264 /*EventTarget* target = this;
265 Node* useNode = shadowTreeParentElementForShadowTreeElement(this);
267 // If we are a hidden shadow tree element, the target must
268 // point to our corresponding SVGElementInstance object
270 ASSERT(useNode->hasTagName(SVGNames::useTag));
271 SVGUseElement* use = static_cast<SVGUseElement*>(useNode);
273 SVGElementInstance* instance = use->instanceForShadowTreeElement(this);
279 e->setTarget(target);
281 RefPtr<FrameView> view = document()->view();
282 return EventTargetNode::dispatchGenericEvent(this, e, ec, tempEvent);*/
287 void SVGElement::attributeChanged(Attribute
* attr
, bool preserveDecls
)
293 StyledElement::attributeChanged(attr
, preserveDecls
);
294 svgAttributeChanged(attr
->name());
297 // for KHTML compatibility
298 void SVGElement::addCSSProperty(Attribute
* attr
, int id
, const String
& value
)
300 kDebug() << "called with: " << id
<< " " << value
<< endl
;
301 /* WARNING: copy&past'ed from HTMLElementImpl class */
302 if (!m_hasCombinedStyle
) createNonCSSDecl();
303 nonCSSStyleDecls()->setProperty(id
, value
, false);
307 void SVGElement::addCSSProperty(Attribute
* attr
, int id
, int value
)
309 kDebug() << "called with: " << id
<< " " << value
<< endl
;
310 /* WARNING: copy&past'ed from HTMLElementImpl class */
311 if (!m_hasCombinedStyle
) createNonCSSDecl();
312 nonCSSStyleDecls()->setProperty(id
, value
, false);
319 #endif // ENABLE(SVG)