KHTML
SVGElement.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 00003 2004, 2005, 2006, 2008 Rob Buis <buis@kde.org> 00004 00005 This file is part of the KDE project 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #include "config.h" 00024 #include "wtf/Platform.h" 00025 00026 #if ENABLE(SVG) 00027 #include "SVGElement.h" 00028 00029 /*#include "DOMImplementation.h"*/ 00030 #include "Document.h" 00031 /*#include "Event.h" 00032 #include "EventListener.h" 00033 #include "EventNames.h" 00034 #include "FrameView.h" 00035 #include "HTMLNames.h" 00036 #include "PlatformString.h" 00037 #include "RenderObject.h" 00038 #include "SVGDocumentExtensions.h" 00039 #include "SVGElementInstance.h"*/ 00040 #include "SVGNames.h" 00041 #include "SVGSVGElement.h" 00042 /*#include "SVGURIReference.h" 00043 #include "SVGUseElement.h" 00044 #include "RegisteredEventListener.h"*/ 00045 00046 namespace WebCore { 00047 00048 using namespace DOM; 00049 00050 //using namespace HTMLNames; 00051 //using namespace EventNames; 00052 00053 SVGElement::SVGElement(const QualifiedName& tagName, Document* doc) 00054 : StyledElement(doc) // it's wrong, remove it!!! FIXME: vtokarev 00055 // : StyledElement(tagName, doc) 00056 // , m_shadowParent(0) 00057 { 00058 m_prefix = tagName.prefixId(); 00059 } 00060 00061 SVGElement::~SVGElement() 00062 { 00063 } 00064 00065 bool SVGElement::isSupported(StringImpl* feature, StringImpl* version) const 00066 { 00067 return DOMImplementation::hasFeature(feature, version); 00068 } 00069 00070 00071 String SVGElement::attrid() const 00072 { 00073 return getAttribute(idAttr); 00074 } 00075 00076 00077 void SVGElement::setId(const String& value, ExceptionCode&) 00078 { 00079 setAttribute(idAttr, value); 00080 } 00081 00082 00083 String SVGElement::xmlbase() const 00084 { 00085 return getAttribute(ATTR_XML_BASE); 00086 } 00087 00088 void SVGElement::setXmlbase(const String& value, ExceptionCode&) 00089 { 00090 setAttribute(ATTR_XML_BASE, value); 00091 } 00092 00093 SVGSVGElement* SVGElement::ownerSVGElement() const 00094 { 00095 Node* n = isShadowNode() ? const_cast<SVGElement*>(this)->shadowParentNode() : parentNode(); 00096 while (n) { 00097 if (/*n->hasTagName(SVGNames::svgTag)*/n->id() == SVGNames::svgTag.id()) 00098 return static_cast<SVGSVGElement*>(n); 00099 00100 n = n->isShadowNode() ? n->shadowParentNode() : n->parentNode(); 00101 } 00102 00103 return 0; 00104 } 00105 00106 SVGElement* SVGElement::viewportElement() const 00107 { 00108 // This function needs shadow tree support - as RenderSVGContainer uses this function 00109 // to determine the "overflow" property. <use> on <symbol> wouldn't work otherwhise. 00110 /*Node* n = isShadowNode() ? const_cast<SVGElement*>(this)->shadowParentNode() : parentNode(); 00111 while (n) { 00112 if (n->hasTagName(SVGNames::svgTag) || n->hasTagName(SVGNames::imageTag) || n->hasTagName(SVGNames::symbolTag)) 00113 return static_cast<SVGElement*>(n); 00114 00115 n = n->isShadowNode() ? n->shadowParentNode() : n->parentNode(); 00116 }*/ 00117 00118 return 0; 00119 } 00120 00121 void SVGElement::addSVGEventListener(/*const AtomicString& eventType*/const EventImpl::EventId& eventType, const Attribute* attr) 00122 { 00123 kDebug() << "add listener for: " << EventName::fromId(eventType).toString() << endl; 00124 Element::setHTMLEventListener(EventName::fromId(eventType), document()->accessSVGExtensions()-> 00125 createSVGEventListener(attr->localName().string(), attr->value(), this)); 00126 } 00127 00128 void SVGElement::parseMappedAttribute(MappedAttribute* attr) 00129 { 00130 // standard events 00131 if (/*attr->name() == onloadAttr*/attr->id() == ATTR_ONLOAD) 00132 addSVGEventListener(/*loadEvent*/EventImpl::LOAD_EVENT, attr); 00133 else if (/*attr->name() == onclickAttr*/attr->id() == ATTR_ONCLICK) 00134 addSVGEventListener(/*clickEvent*/EventImpl::CLICK_EVENT, attr); 00135 else /*if (attr->name() == onmousedownAttr) 00136 addSVGEventListener(mousedownEvent, attr); 00137 else if (attr->name() == onmousemoveAttr) 00138 addSVGEventListener(mousemoveEvent, attr); 00139 else if (attr->name() == onmouseoutAttr) 00140 addSVGEventListener(mouseoutEvent, attr); 00141 else if (attr->name() == onmouseoverAttr) 00142 addSVGEventListener(mouseoverEvent, attr); 00143 else if (attr->name() == onmouseupAttr) 00144 addSVGEventListener(mouseupEvent, attr); 00145 else if (attr->name() == SVGNames::onfocusinAttr) 00146 addSVGEventListener(DOMFocusInEvent, attr); 00147 else if (attr->name() == SVGNames::onfocusoutAttr) 00148 addSVGEventListener(DOMFocusOutEvent, attr); 00149 else if (attr->name() == SVGNames::onactivateAttr) 00150 addSVGEventListener(DOMActivateEvent, attr); 00151 else*/ 00152 if (attr->id() == ATTR_ID) { 00153 setHasID(); 00154 document()->incDOMTreeVersion(DocumentImpl::TV_IDNameHref); 00155 } else 00156 StyledElement::parseAttribute(attr); 00157 } 00158 00159 bool SVGElement::haveLoadedRequiredResources() 00160 { 00161 Node* child = firstChild(); 00162 while (child) { 00163 if (child->isSVGElement() && !static_cast<SVGElement*>(child)->haveLoadedRequiredResources()) 00164 return false; 00165 child = child->nextSibling(); 00166 } 00167 return true; 00168 } 00169 00170 static bool hasLoadListener(SVGElement* node) 00171 { 00172 Node* currentNode = node; 00173 while (currentNode && currentNode->isElementNode()) { 00174 QList<RegisteredEventListener> *list = static_cast<Element*>(currentNode)->localEventListeners(); 00175 if (list) { 00176 QList<RegisteredEventListener>::Iterator end = list->end(); 00177 for (QList<RegisteredEventListener>::Iterator it = list->begin(); it != end; ++it) 00178 if ((*it).useCapture || (*it).eventName.id() == EventImpl::LOAD_EVENT/* || currentNode == node*/) 00179 return true; 00180 /*if ((*it)->eventType() == loadEvent && 00181 (*it)->useCapture() == true || currentNode == node) 00182 return true;*/ 00183 } 00184 currentNode = currentNode->parentNode(); 00185 } 00186 00187 return false; 00188 } 00189 00190 void SVGElement::sendSVGLoadEventIfPossible(bool sendParentLoadEvents) 00191 { 00192 kDebug() << "send svg load event" << endl; 00193 RefPtr<SVGElement> currentTarget = this; 00194 kDebug() << currentTarget << currentTarget->haveLoadedRequiredResources() << endl; 00195 while (currentTarget && currentTarget->haveLoadedRequiredResources()) { 00196 RefPtr<Node> parent; 00197 if (sendParentLoadEvents) 00198 parent = currentTarget->parentNode(); // save the next parent to dispatch too incase dispatching the event changes the tree 00199 kDebug() << hasLoadListener(currentTarget.get()) << endl; 00200 if (hasLoadListener(currentTarget.get())) { 00201 //Event* event = new Event(EventImpl::LOAD_EVENT, true/*false*/, false); 00202 //event->setTarget(currentTarget.get()); 00203 //ExceptionCode ignored = 0; 00204 //dispatchGenericEvent(/*currentTarget.get(), */event, ignored/*, false*/); 00205 dispatchHTMLEvent(EventImpl::LOAD_EVENT, false, false); 00206 } 00207 currentTarget = (parent && parent->isSVGElement()) ? static_pointer_cast<SVGElement>(parent) : RefPtr<SVGElement>(); 00208 } 00209 } 00210 00211 void SVGElement::finishParsingChildren() 00212 { 00213 // finishParsingChildren() is called when the close tag is reached for an element (e.g. </svg>) 00214 // we send SVGLoad events here if we can, otherwise they'll be sent when any required loads finish 00215 sendSVGLoadEventIfPossible(); 00216 } 00217 00218 bool SVGElement::childShouldCreateRenderer(Node* child) const 00219 { 00220 if (child->isSVGElement()) 00221 return static_cast<SVGElement*>(child)->isValid(); 00222 return false; 00223 } 00224 00225 void SVGElement::insertedIntoDocument() 00226 { 00227 StyledElement::insertedIntoDocument(); 00228 /*SVGDocumentExtensions* extensions = document()->accessSVGExtensions(); 00229 00230 String resourceId = SVGURIReference::getTarget(id()); 00231 if (extensions->isPendingResource(resourceId)) { 00232 std::auto_ptr<HashSet<SVGStyledElement*> > clients(extensions->removePendingResource(resourceId)); 00233 if (clients->isEmpty()) 00234 return; 00235 00236 HashSet<SVGStyledElement*>::const_iterator it = clients->begin(); 00237 const HashSet<SVGStyledElement*>::const_iterator end = clients->end(); 00238 00239 for (; it != end; ++it) 00240 (*it)->buildPendingResource(); 00241 00242 SVGResource::invalidateClients(*clients); 00243 }*/ 00244 } 00245 00246 static Node* shadowTreeParentElementForShadowTreeElement(Node* node) 00247 { 00248 for (Node* n = node; n; n = n->parentNode()) { 00249 /*if (n->isShadowNode()) 00250 return n->shadowParentNode();*/ 00251 } 00252 00253 return 0; 00254 } 00255 00256 bool SVGElement::dispatchEvent(Event* e, ExceptionCode& ec, bool tempEvent) 00257 { 00258 Q_UNUSED(e); 00259 Q_UNUSED(ec); 00260 Q_UNUSED(tempEvent); 00261 kDebug() << "dispatch event" << endl; 00262 // TODO: This function will be removed in a follow-up patch! 00263 00264 /*EventTarget* target = this; 00265 Node* useNode = shadowTreeParentElementForShadowTreeElement(this); 00266 00267 // If we are a hidden shadow tree element, the target must 00268 // point to our corresponding SVGElementInstance object 00269 if (useNode) { 00270 ASSERT(useNode->hasTagName(SVGNames::useTag)); 00271 SVGUseElement* use = static_cast<SVGUseElement*>(useNode); 00272 00273 SVGElementInstance* instance = use->instanceForShadowTreeElement(this); 00274 00275 if (instance) 00276 target = instance; 00277 } 00278 00279 e->setTarget(target); 00280 00281 RefPtr<FrameView> view = document()->view(); 00282 return EventTargetNode::dispatchGenericEvent(this, e, ec, tempEvent);*/ 00283 ASSERT(false); 00284 return false; 00285 } 00286 00287 void SVGElement::attributeChanged(Attribute* attr, bool preserveDecls) 00288 { 00289 ASSERT(attr); 00290 if (!attr) 00291 return; 00292 00293 StyledElement::attributeChanged(attr, preserveDecls); 00294 svgAttributeChanged(attr->name()); 00295 } 00296 00297 // for KHTML compatibility 00298 void SVGElement::addCSSProperty(Attribute* attr, int id, const String& value) 00299 { 00300 Q_UNUSED(attr); 00301 kDebug() << "called with: " << id << " " << value << endl; 00302 /* WARNING: copy&past'ed from HTMLElementImpl class */ 00303 if (!m_hasCombinedStyle) createNonCSSDecl(); 00304 nonCSSStyleDecls()->setProperty(id, value, false); 00305 setChanged(); 00306 } 00307 00308 void SVGElement::addCSSProperty(Attribute* attr, int id, int value) 00309 { 00310 Q_UNUSED(attr); 00311 kDebug() << "called with: " << id << " " << value << endl; 00312 /* WARNING: copy&past'ed from HTMLElementImpl class */ 00313 if (!m_hasCombinedStyle) createNonCSSDecl(); 00314 nonCSSStyleDecls()->setProperty(id, value, false); 00315 setChanged(); 00316 } 00317 00318 00319 } 00320 00321 #endif // ENABLE(SVG)
KDE 4.6 API Reference