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.
23 #include "SVGElementInstance.h"
25 #include "ContainerNodeAlgorithms.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>
37 #include "GCController.h"
43 static WTF::RefCountedLeakCounter
instanceCounter("WebCoreSVGElementInstance");
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)
65 // Register as instance for passed element.
66 m_element
->mapInstanceToElement(this);
69 instanceCounter
.increment();
73 SVGElementInstance::~SVGElementInstance()
76 instanceCounter
.decrement();
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
)
93 m_shadowTreeElement
= element
;
96 void SVGElementInstance::forgetWrapper()
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();
110 void SVGElementInstance::appendChild(PassRefPtr
<SVGElementInstance
> child
)
112 appendChildToContainer
<SVGElementInstance
, SVGElementInstance
>(child
.get(), this);
115 void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement
* element
)
120 HashSet
<SVGElementInstance
*> set
= element
->instancesForElement();
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
;
137 correspondingUseElement()->setNeedsStyleRecalc();
140 ScriptExecutionContext
* SVGElementInstance::scriptExecutionContext() const
142 if (SVGElement
* element
= correspondingElement())
143 return element
->document();
147 bool SVGElementInstance::addEventListener(const AtomicString
& eventType
, PassRefPtr
<EventListener
> listener
, bool useCapture
)
149 if (!correspondingElement())
151 return correspondingElement()->addEventListener(eventType
, listener
, useCapture
);
154 bool SVGElementInstance::removeEventListener(const AtomicString
& eventType
, EventListener
* listener
, bool useCapture
)
156 if (!correspondingElement())
158 return correspondingElement()->removeEventListener(eventType
, listener
, useCapture
);
161 void SVGElementInstance::removeAllEventListeners()
163 if (!correspondingElement())
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();
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)