don't discard iframe children.
[kdelibs.git] / khtml / svg / SVGElement.cpp
blob5cdd18bd0a6e4d91cbd7bca40745fa69a4d0bda8
1 /*
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.
23 #include "config.h"
24 #include "wtf/Platform.h"
26 #if ENABLE(SVG)
27 #include "SVGElement.h"
29 /*#include "DOMImplementation.h"*/
30 #include "Document.h"
31 /*#include "Event.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"*/
40 #include "SVGNames.h"
41 #include "SVGSVGElement.h"
42 /*#include "SVGURIReference.h"
43 #include "SVGUseElement.h"
44 #include "XMLNames.h"
45 #include "RegisteredEventListener.h"*/
47 namespace WebCore {
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))
66 return true;
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);
87 ASSERT(false);
88 return "";
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();
99 while (n) {
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();
106 return 0;
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();
114 while (n) {
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();
121 return 0;
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)
133 // standard events
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);
154 else*/
155 if (attr->id() == ATTR_ID) {
156 setHasID();
157 document()->incDOMTreeVersion();
158 } else
159 StyledElement::parseAttribute(attr);
162 bool SVGElement::haveLoadedRequiredResources()
164 Node* child = firstChild();
165 while (child) {
166 if (child->isSVGElement() && !static_cast<SVGElement*>(child)->haveLoadedRequiredResources())
167 return false;
168 child = child->nextSibling();
170 return true;
173 static bool hasLoadListener(SVGElement* node)
175 Node* currentNode = node;
176 while (currentNode && currentNode->isElementNode()) {
177 QList<RegisteredEventListener> *list = static_cast<Element*>(currentNode)->localEventListeners();
178 if (list) {
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*/)
182 return true;
183 /*if ((*it)->eventType() == loadEvent &&
184 (*it)->useCapture() == true || currentNode == node)
185 return true;*/
187 currentNode = currentNode->parentNode();
190 return false;
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()) {
199 RefPtr<Node> parent;
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();
225 return false;
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())
237 return;
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();*/
256 return 0;
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
269 if (useNode) {
270 ASSERT(useNode->hasTagName(SVGNames::useTag));
271 SVGUseElement* use = static_cast<SVGUseElement*>(useNode);
273 SVGElementInstance* instance = use->instanceForShadowTreeElement(this);
275 if (instance)
276 target = instance;
279 e->setTarget(target);
281 RefPtr<FrameView> view = document()->view();
282 return EventTargetNode::dispatchGenericEvent(this, e, ec, tempEvent);*/
283 ASSERT(false);
284 return false;
287 void SVGElement::attributeChanged(Attribute* attr, bool preserveDecls)
289 ASSERT(attr);
290 if (!attr)
291 return;
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);
304 setChanged();
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);
313 setChanged();
319 #endif // ENABLE(SVG)