1 /* 2 Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 Copyright (C) Research In Motion Limited 2010. All rights reserved. 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Library General Public 7 License as published by the Free Software Foundation; either 8 version 2 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public License 16 along with this library; see the file COPYING.LIB. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 21 #include "config.h" 22 23 #if ENABLE(SVG) 24 #include "SVGElementInstance.h" 25 26 #include "ContainerNodeAlgorithms.h" 27 #include "Event.h" 28 #include "EventException.h" 29 #include "EventListener.h" 30 #include "EventNames.h" 31 #include "FrameView.h" 32 #include "SVGElementInstanceList.h" 33 #include "SVGUseElement.h" 34 35 #include <wtf/RefCountedLeakCounter.h> 36 37 namespace WebCore { 38 39 #ifndef NDEBUG 40 static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance"); 41 #endif 42 43 SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, PassRefPtr<SVGElement> originalElement) 44 : m_useElement(useElement) 45 , m_element(originalElement) 46 , m_previousSibling(0) 47 , m_nextSibling(0) 48 , m_firstChild(0) 49 , m_lastChild(0) 50 { 51 ASSERT(m_useElement); 52 ASSERT(m_element); 53 54 // Register as instance for passed element. 55 m_element->mapInstanceToElement(this); 56 57 #ifndef NDEBUG 58 instanceCounter.increment(); 59 #endif 60 } 61 62 SVGElementInstance::~SVGElementInstance() 63 { 64 #ifndef NDEBUG 65 instanceCounter.decrement(); 66 #endif 67 68 // Deregister as instance for passed element. 69 m_element->removeInstanceMapping(this); 70 71 removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this); 72 } 73 74 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes() 75 { 76 return SVGElementInstanceList::create(this); 77 } 78 79 void SVGElementInstance::setShadowTreeElement(SVGElement* element) 80 { 81 ASSERT(element); 82 m_shadowTreeElement = element; 83 } 84 85 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child) 86 { 87 appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this); 88 } 89 90 void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element) 91 { 92 if (!element) 93 return; 94 95 if (element->isStyled() && static_cast<SVGStyledElement*>(element)->instanceUpdatesBlocked()) 96 return; 97 98 const HashSet<SVGElementInstance*>& set = element->instancesForElement(); 99 if (set.isEmpty()) 100 return; 101 102 // Mark all use elements referencing 'element' for rebuilding 103 const HashSet<SVGElementInstance*>::const_iterator end = set.end(); 104 for (HashSet<SVGElementInstance*>::const_iterator it = set.begin(); it != end; ++it) { 105 ASSERT((*it)->correspondingElement() == element); 106 (*it)->correspondingUseElement()->invalidateShadowTree(); 107 } 108 } 109 110 ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const 111 { 112 return m_element->document(); 113 } 114 115 bool SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 116 { 117 return m_element->addEventListener(eventType, listener, useCapture); 118 } 119 120 bool SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) 121 { 122 return m_element->removeEventListener(eventType, listener, useCapture); 123 } 124 125 void SVGElementInstance::removeAllEventListeners() 126 { 127 m_element->removeAllEventListeners(); 128 } 129 130 bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> prpEvent) 131 { 132 RefPtr<EventTarget> protect = this; 133 RefPtr<Event> event = prpEvent; 134 135 event->setTarget(this); 136 137 SVGElement* element = shadowTreeElement(); 138 if (!element) 139 return false; 140 141 RefPtr<FrameView> view = element->document()->view(); 142 return element->dispatchGenericEvent(event.release()); 143 } 144 145 EventTargetData* SVGElementInstance::eventTargetData() 146 { 147 return m_element->eventTargetData(); 148 } 149 150 EventTargetData* SVGElementInstance::ensureEventTargetData() 151 { 152 // Avoid crashing - return a default dummy value 153 DEFINE_STATIC_LOCAL(EventTargetData, dummyEventTargetData, ()); 154 dummyEventTargetData.eventListenerMap.clear(); 155 return &dummyEventTargetData; 156 } 157 158 } 159 160 #endif 161