diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
commit | 8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch) | |
tree | 11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebCore/svg/SVGElementInstance.cpp | |
parent | 648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff) | |
download | external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.zip external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.gz external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'WebCore/svg/SVGElementInstance.cpp')
-rw-r--r-- | WebCore/svg/SVGElementInstance.cpp | 572 |
1 files changed, 572 insertions, 0 deletions
diff --git a/WebCore/svg/SVGElementInstance.cpp b/WebCore/svg/SVGElementInstance.cpp new file mode 100644 index 0000000..e548900 --- /dev/null +++ b/WebCore/svg/SVGElementInstance.cpp @@ -0,0 +1,572 @@ +/* + Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> + + This file is part of the KDE project + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#if ENABLE(SVG) +#include "SVGElementInstance.h" + +#include "ContainerNodeAlgorithms.h" +#include "Document.h" +#include "Event.h" +#include "EventException.h" +#include "EventListener.h" +#include "EventNames.h" +#include "FrameView.h" +#include "GCController.h" +#include "SVGElementInstanceList.h" +#include "SVGUseElement.h" + +#include <wtf/RefCountedLeakCounter.h> + +namespace WebCore { + +#ifndef NDEBUG +static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance"); +#endif + +SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, SVGElement* originalElement) + : m_needsUpdate(false) + , m_useElement(useElement) + , m_element(originalElement) + , m_previousSibling(0) + , m_nextSibling(0) + , m_firstChild(0) + , m_lastChild(0) +{ + ASSERT(m_useElement); + ASSERT(m_element); + + // Register as instance for passed element. + m_element->mapInstanceToElement(this); + +#ifndef NDEBUG + instanceCounter.increment(); +#endif +} + +SVGElementInstance::~SVGElementInstance() +{ +#ifndef NDEBUG + instanceCounter.decrement(); +#endif + + // Deregister as instance for passed element. + m_element->removeInstanceMapping(this); + + removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this); +} + +PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes() +{ + return SVGElementInstanceList::create(this); +} + +void SVGElementInstance::setShadowTreeElement(SVGElement* element) +{ + ASSERT(element); + m_shadowTreeElement = element; +} + +void SVGElementInstance::forgetWrapper() +{ + // FIXME: This is fragile, as discussed with Sam. Need to find a better solution. + // Think about the case where JS explicitely holds "var root = useElement.instanceRoot;". + // We still have to recreate this wrapper somehow. The gc collection below, won't catch it. + + // If the use shadow tree has been rebuilt, just the JSSVGElementInstance objects + // are still holding RefPtrs of SVGElementInstance objects, which prevent us to + // be deleted (and the shadow tree is not destructed as well). Force JS GC. + gcController().garbageCollectNow(); +} + +void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child) +{ + appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this); +} + +void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element) +{ + if (!element) + return; + + HashSet<SVGElementInstance*> set = element->instancesForElement(); + if (set.isEmpty()) + return; + + // Find all use elements referencing the instances - ask them _once_ to rebuild. + HashSet<SVGElementInstance*>::const_iterator it = set.begin(); + const HashSet<SVGElementInstance*>::const_iterator end = set.end(); + + for (; it != end; ++it) + (*it)->setNeedsUpdate(true); +} + +void SVGElementInstance::setNeedsUpdate(bool value) +{ + m_needsUpdate = value; + + if (m_needsUpdate) + correspondingUseElement()->setChanged(); +} + +ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const +{ + if (SVGElement* element = correspondingElement()) + return element->scriptExecutionContext(); + return 0; +} + +void SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) +{ + if (SVGElement* element = correspondingElement()) + element->addEventListener(eventType, listener, useCapture); +} + +void SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) +{ + if (SVGElement* element = correspondingElement()) + element->removeEventListener(eventType, listener, useCapture); +} + +bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec) +{ + RefPtr<Event> evt(e); + ASSERT(!eventDispatchForbidden()); + if (!evt || evt->type().isEmpty()) { + ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; + return false; + } + + // The event has to be dispatched to the shadowTreeElement(), not the correspondingElement()! + SVGElement* element = shadowTreeElement(); + if (!element) + return false; + + evt->setTarget(this); + + RefPtr<FrameView> view = element->document()->view(); + return element->dispatchGenericEvent(evt.release(), ec); +} + +EventListener* SVGElementInstance::onabort() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().abortEvent); +} + +void SVGElementInstance::setOnabort(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().abortEvent, eventListener); +} + +EventListener* SVGElementInstance::onblur() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().blurEvent); +} + +void SVGElementInstance::setOnblur(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().blurEvent, eventListener); +} + +EventListener* SVGElementInstance::onchange() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().changeEvent); +} + +void SVGElementInstance::setOnchange(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().changeEvent, eventListener); +} + +EventListener* SVGElementInstance::onclick() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().clickEvent); +} + +void SVGElementInstance::setOnclick(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().clickEvent, eventListener); +} + +EventListener* SVGElementInstance::oncontextmenu() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().contextmenuEvent); +} + +void SVGElementInstance::setOncontextmenu(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().contextmenuEvent, eventListener); +} + +EventListener* SVGElementInstance::ondblclick() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dblclickEvent); +} + +void SVGElementInstance::setOndblclick(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dblclickEvent, eventListener); +} + +EventListener* SVGElementInstance::onerror() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().errorEvent); +} + +void SVGElementInstance::setOnerror(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().errorEvent, eventListener); +} + +EventListener* SVGElementInstance::onfocus() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().focusEvent); +} + +void SVGElementInstance::setOnfocus(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().focusEvent, eventListener); +} + +EventListener* SVGElementInstance::oninput() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().inputEvent); +} + +void SVGElementInstance::setOninput(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().inputEvent, eventListener); +} + +EventListener* SVGElementInstance::onkeydown() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().keydownEvent); +} + +void SVGElementInstance::setOnkeydown(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().keydownEvent, eventListener); +} + +EventListener* SVGElementInstance::onkeypress() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().keypressEvent); +} + +void SVGElementInstance::setOnkeypress(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().keypressEvent, eventListener); +} + +EventListener* SVGElementInstance::onkeyup() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().keyupEvent); +} + +void SVGElementInstance::setOnkeyup(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().keyupEvent, eventListener); +} + +EventListener* SVGElementInstance::onload() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().loadEvent); +} + +void SVGElementInstance::setOnload(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().loadEvent, eventListener); +} + +EventListener* SVGElementInstance::onmousedown() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mousedownEvent); +} + +void SVGElementInstance::setOnmousedown(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mousedownEvent, eventListener); +} + +EventListener* SVGElementInstance::onmousemove() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mousemoveEvent); +} + +void SVGElementInstance::setOnmousemove(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mousemoveEvent, eventListener); +} + +EventListener* SVGElementInstance::onmouseout() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mouseoutEvent); +} + +void SVGElementInstance::setOnmouseout(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mouseoutEvent, eventListener); +} + +EventListener* SVGElementInstance::onmouseover() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mouseoverEvent); +} + +void SVGElementInstance::setOnmouseover(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mouseoverEvent, eventListener); +} + +EventListener* SVGElementInstance::onmouseup() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mouseupEvent); +} + +void SVGElementInstance::setOnmouseup(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mouseupEvent, eventListener); +} + +EventListener* SVGElementInstance::onmousewheel() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().mousewheelEvent); +} + +void SVGElementInstance::setOnmousewheel(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().mousewheelEvent, eventListener); +} + +EventListener* SVGElementInstance::onbeforecut() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().beforecutEvent); +} + +void SVGElementInstance::setOnbeforecut(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().beforecutEvent, eventListener); +} + +EventListener* SVGElementInstance::oncut() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().cutEvent); +} + +void SVGElementInstance::setOncut(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().cutEvent, eventListener); +} + +EventListener* SVGElementInstance::onbeforecopy() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().beforecopyEvent); +} + +void SVGElementInstance::setOnbeforecopy(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().beforecopyEvent, eventListener); +} + +EventListener* SVGElementInstance::oncopy() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().copyEvent); +} + +void SVGElementInstance::setOncopy(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().copyEvent, eventListener); +} + +EventListener* SVGElementInstance::onbeforepaste() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().beforepasteEvent); +} + +void SVGElementInstance::setOnbeforepaste(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().beforepasteEvent, eventListener); +} + +EventListener* SVGElementInstance::onpaste() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().pasteEvent); +} + +void SVGElementInstance::setOnpaste(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().pasteEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragenter() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragenterEvent); +} + +void SVGElementInstance::setOndragenter(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragenterEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragover() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragoverEvent); +} + +void SVGElementInstance::setOndragover(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragoverEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragleave() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragleaveEvent); +} + +void SVGElementInstance::setOndragleave(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragleaveEvent, eventListener); +} + +EventListener* SVGElementInstance::ondrop() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dropEvent); +} + +void SVGElementInstance::setOndrop(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dropEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragstart() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragstartEvent); +} + +void SVGElementInstance::setOndragstart(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragstartEvent, eventListener); +} + +EventListener* SVGElementInstance::ondrag() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragEvent); +} + +void SVGElementInstance::setOndrag(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragEvent, eventListener); +} + +EventListener* SVGElementInstance::ondragend() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().dragendEvent); +} + +void SVGElementInstance::setOndragend(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().dragendEvent, eventListener); +} + +EventListener* SVGElementInstance::onreset() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().resetEvent); +} + +void SVGElementInstance::setOnreset(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().resetEvent, eventListener); +} + +EventListener* SVGElementInstance::onresize() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().resizeEvent); +} + +void SVGElementInstance::setOnresize(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().resizeEvent, eventListener); +} + +EventListener* SVGElementInstance::onscroll() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().scrollEvent); +} + +void SVGElementInstance::setOnscroll(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().scrollEvent, eventListener); +} + +EventListener* SVGElementInstance::onsearch() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().searchEvent); +} + +void SVGElementInstance::setOnsearch(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().searchEvent, eventListener); +} + +EventListener* SVGElementInstance::onselect() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().selectEvent); +} + +void SVGElementInstance::setOnselect(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().selectEvent, eventListener); +} + +EventListener* SVGElementInstance::onselectstart() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().selectstartEvent); +} + +void SVGElementInstance::setOnselectstart(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().selectstartEvent, eventListener); +} + +EventListener* SVGElementInstance::onsubmit() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().submitEvent); +} + +void SVGElementInstance::setOnsubmit(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().submitEvent, eventListener); +} + +EventListener* SVGElementInstance::onunload() const +{ + return correspondingElement()->inlineEventListenerForType(eventNames().unloadEvent); +} + +void SVGElementInstance::setOnunload(PassRefPtr<EventListener> eventListener) +{ + correspondingElement()->setInlineEventListenerForType(eventNames().unloadEvent, eventListener); +} + +} + +#endif // ENABLE(SVG) |