Rubber-stamped by Brady Eidson.
[webbrowser.git] / WebCore / svg / SVGElementInstance.cpp
blob46e82216df369124f1afa75bebca8d3ff0508765
1 /*
2 Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "config.h"
22 #if ENABLE(SVG)
23 #include "SVGElementInstance.h"
25 #include "ContainerNodeAlgorithms.h"
26 #include "Event.h"
27 #include "EventException.h"
28 #include "EventListener.h"
29 #include "EventNames.h"
30 #include "FrameView.h"
31 #include "SVGElementInstanceList.h"
32 #include "SVGUseElement.h"
34 #include <wtf/RefCountedLeakCounter.h>
36 #if USE(JSC)
37 #include "GCController.h"
38 #endif
40 namespace WebCore {
42 #ifndef NDEBUG
43 static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance");
44 #endif
46 static EventTargetData& dummyEventTargetData()
48 DEFINE_STATIC_LOCAL(EventTargetData, dummyEventTargetData, ());
49 dummyEventTargetData.eventListenerMap.clear();
50 return dummyEventTargetData;
53 SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, PassRefPtr<SVGElement> originalElement)
54 : m_needsUpdate(false)
55 , m_useElement(useElement)
56 , m_element(originalElement)
57 , m_previousSibling(0)
58 , m_nextSibling(0)
59 , m_firstChild(0)
60 , m_lastChild(0)
62 ASSERT(m_useElement);
63 ASSERT(m_element);
65 // Register as instance for passed element.
66 m_element->mapInstanceToElement(this);
68 #ifndef NDEBUG
69 instanceCounter.increment();
70 #endif
73 SVGElementInstance::~SVGElementInstance()
75 #ifndef NDEBUG
76 instanceCounter.decrement();
77 #endif
79 // Deregister as instance for passed element.
80 m_element->removeInstanceMapping(this);
82 removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this);
85 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes()
87 return SVGElementInstanceList::create(this);
90 void SVGElementInstance::setShadowTreeElement(SVGElement* element)
92 ASSERT(element);
93 m_shadowTreeElement = element;
96 void SVGElementInstance::forgetWrapper()
98 #if USE(JSC)
99 // FIXME: This is fragile, as discussed with Sam. Need to find a better solution.
100 // Think about the case where JS explicitely holds "var root = useElement.instanceRoot;".
101 // We still have to recreate this wrapper somehow. The gc collection below, won't catch it.
103 // If the use shadow tree has been rebuilt, just the JSSVGElementInstance objects
104 // are still holding RefPtrs of SVGElementInstance objects, which prevent us to
105 // be deleted (and the shadow tree is not destructed as well). Force JS GC.
106 gcController().garbageCollectNow();
107 #endif
110 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child)
112 appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this);
115 void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element)
117 if (!element)
118 return;
120 HashSet<SVGElementInstance*> set = element->instancesForElement();
121 if (set.isEmpty())
122 return;
124 // Find all use elements referencing the instances - ask them _once_ to rebuild.
125 HashSet<SVGElementInstance*>::const_iterator it = set.begin();
126 const HashSet<SVGElementInstance*>::const_iterator end = set.end();
128 for (; it != end; ++it)
129 (*it)->setNeedsUpdate(true);
132 void SVGElementInstance::setNeedsUpdate(bool value)
134 m_needsUpdate = value;
136 if (m_needsUpdate)
137 correspondingUseElement()->setNeedsStyleRecalc();
140 ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const
142 if (SVGElement* element = correspondingElement())
143 return element->document();
144 return 0;
147 bool SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
149 if (!correspondingElement())
150 return false;
151 return correspondingElement()->addEventListener(eventType, listener, useCapture);
154 bool SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
156 if (!correspondingElement())
157 return false;
158 return correspondingElement()->removeEventListener(eventType, listener, useCapture);
161 void SVGElementInstance::removeAllEventListeners()
163 if (!correspondingElement())
164 return;
165 correspondingElement()->removeAllEventListeners();
168 bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> prpEvent)
170 RefPtr<EventTarget> protect = this;
171 RefPtr<Event> event = prpEvent;
173 event->setTarget(this);
175 SVGElement* element = shadowTreeElement();
176 if (!element)
177 return false;
179 RefPtr<FrameView> view = element->document()->view();
180 return element->dispatchGenericEvent(event.release());
183 EventTargetData* SVGElementInstance::eventTargetData()
185 return correspondingElement() ? correspondingElement()->eventTargetData() : 0;
188 EventTargetData* SVGElementInstance::ensureEventTargetData()
190 return &dummyEventTargetData(); // return something, so we don't crash
193 } // namespace WebCore
195 #endif // ENABLE(SVG)