Home | History | Annotate | Download | only in svg
      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