diff options
Diffstat (limited to 'Source/WebCore/svg/SVGTRefElement.cpp')
-rw-r--r-- | Source/WebCore/svg/SVGTRefElement.cpp | 133 |
1 files changed, 74 insertions, 59 deletions
diff --git a/Source/WebCore/svg/SVGTRefElement.cpp b/Source/WebCore/svg/SVGTRefElement.cpp index 836cfbbd4..dc023162e 100644 --- a/Source/WebCore/svg/SVGTRefElement.cpp +++ b/Source/WebCore/svg/SVGTRefElement.cpp @@ -49,13 +49,6 @@ BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGTRefElement) REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTextPositioningElement) END_REGISTER_ANIMATED_PROPERTIES -inline SVGTRefElement::SVGTRefElement(const QualifiedName& tagName, Document* document) - : SVGTextPositioningElement(tagName, document) -{ - ASSERT(hasTagName(SVGNames::trefTag)); - registerAnimatedPropertiesForSVGTRefElement(); -} - PassRefPtr<SVGTRefElement> SVGTRefElement::create(const QualifiedName& tagName, Document* document) { RefPtr<SVGTRefElement> element = adoptRef(new SVGTRefElement(tagName, document)); @@ -63,59 +56,83 @@ PassRefPtr<SVGTRefElement> SVGTRefElement::create(const QualifiedName& tagName, return element.release(); } -class TargetListener : public EventListener { +class SVGTRefTargetEventListener : public EventListener { public: - static PassRefPtr<TargetListener> create(SVGTRefElement* trefElement, String targetId) + static PassRefPtr<SVGTRefTargetEventListener> create(SVGTRefElement* trefElement) { - return adoptRef(new TargetListener(trefElement, targetId)); + return adoptRef(new SVGTRefTargetEventListener(trefElement)); } - static const TargetListener* cast(const EventListener* listener) + static const SVGTRefTargetEventListener* cast(const EventListener* listener) { - return listener->type() == CPPEventListenerType ? static_cast<const TargetListener*>(listener) : 0; + return listener->type() == SVGTRefTargetEventListenerType + ? static_cast<const SVGTRefTargetEventListener*>(listener) : 0; } - virtual bool operator==(const EventListener&); - - void clear() - { - Element* target = m_trefElement->treeScope()->getElementById(m_targetId); - if (target) { - target->removeEventListener(eventNames().DOMSubtreeModifiedEvent, this, false); - target->removeEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, this, false); - } - - m_trefElement = 0; - m_targetId = String(); - } + void attach(Element* target, String& targetId); + void detach(); + bool isAttached() const { return m_attached; } private: - TargetListener(SVGTRefElement* trefElement, String targetId) - : EventListener(CPPEventListenerType) - , m_trefElement(trefElement) - , m_targetId(targetId) - { - } + SVGTRefTargetEventListener(SVGTRefElement* trefElement); - virtual void handleEvent(ScriptExecutionContext*, Event*); + virtual void handleEvent(ScriptExecutionContext*, Event*) OVERRIDE; + virtual bool operator==(const EventListener&) OVERRIDE; SVGTRefElement* m_trefElement; String m_targetId; + bool m_attached; }; -bool TargetListener::operator==(const EventListener& listener) +SVGTRefTargetEventListener::SVGTRefTargetEventListener(SVGTRefElement* trefElement) + : EventListener(SVGTRefTargetEventListenerType) + , m_trefElement(trefElement) + , m_attached(false) { - if (const TargetListener* subtreeModificationEventListener = TargetListener::cast(&listener)) - return m_trefElement == subtreeModificationEventListener->m_trefElement; + ASSERT(m_trefElement); +} + +void SVGTRefTargetEventListener::attach(Element* target, String& targetId) +{ + ASSERT(!isAttached()); + ASSERT(target); + ASSERT(target->inDocument()); + ASSERT(!targetId.isEmpty()); + + target->addEventListener(eventNames().DOMSubtreeModifiedEvent, this, false); + target->addEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, this, false); + m_targetId = targetId; + m_attached = true; +} + +void SVGTRefTargetEventListener::detach() +{ + if (!isAttached()) + return; + + if (Element* target = m_trefElement->treeScope()->getElementById(m_targetId)) { + target->removeEventListener(eventNames().DOMSubtreeModifiedEvent, this, false); + target->removeEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, this, false); + } + + m_targetId = emptyString(); + m_attached = false; +} + +bool SVGTRefTargetEventListener::operator==(const EventListener& listener) +{ + if (const SVGTRefTargetEventListener* targetListener = SVGTRefTargetEventListener::cast(&listener)) + return m_trefElement == targetListener->m_trefElement; return false; } -void TargetListener::handleEvent(ScriptExecutionContext*, Event* event) +void SVGTRefTargetEventListener::handleEvent(ScriptExecutionContext*, Event* event) { - if (m_trefElement && event->type() == eventNames().DOMSubtreeModifiedEvent && m_trefElement != event->target()) - m_trefElement->updateReferencedText(); + ASSERT(isAttached()); - if (m_trefElement && event->type() == eventNames().DOMNodeRemovedFromDocumentEvent) + if (event->type() == eventNames().DOMSubtreeModifiedEvent && m_trefElement != event->target()) + m_trefElement->updateReferencedText(); + else if (event->type() == eventNames().DOMNodeRemovedFromDocumentEvent) m_trefElement->detachTarget(); } @@ -148,9 +165,17 @@ void SVGShadowText::willRecalcTextStyle(StyleChange change) } } +inline SVGTRefElement::SVGTRefElement(const QualifiedName& tagName, Document* document) + : SVGTextPositioningElement(tagName, document) + , m_targetListener(SVGTRefTargetEventListener::create(this)) +{ + ASSERT(hasTagName(SVGNames::trefTag)); + registerAnimatedPropertiesForSVGTRefElement(); +} + SVGTRefElement::~SVGTRefElement() { - clearEventListener(); + m_targetListener->detach(); } void SVGTRefElement::createShadowSubtree() @@ -175,7 +200,7 @@ void SVGTRefElement::updateReferencedText() void SVGTRefElement::detachTarget() { // Remove active listeners and clear the text content. - clearEventListener(); + m_targetListener->detach(); String emptyContent; ExceptionCode ignore = 0; @@ -185,7 +210,8 @@ void SVGTRefElement::detachTarget() if (container) container->setTextContent(emptyContent, ignore); - ASSERT(inDocument()); + if (!inDocument()) + return; // Mark the referenced ID as pending. String id; @@ -263,7 +289,7 @@ bool SVGTRefElement::rendererIsNeeded(const NodeRenderingContext& context) void SVGTRefElement::buildPendingResource() { // Remove any existing event listener. - clearEventListener(); + m_targetListener->detach(); // If we're not yet in a document, this function will be called again from insertedInto(). if (!inDocument()) @@ -280,17 +306,14 @@ void SVGTRefElement::buildPendingResource() return; } - updateReferencedText(); - // Don't set up event listeners if this is a shadow tree node. // SVGUseElement::transferEventListenersToShadowTree() handles this task, and addEventListener() // expects every element instance to have an associated shadow tree element - which is not the // case when we land here from SVGUseElement::buildShadowTree(). - if (!isInShadowTree()) { - m_eventListener = TargetListener::create(this, id); - target->addEventListener(eventNames().DOMSubtreeModifiedEvent, m_eventListener.get(), false); - target->addEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, m_eventListener.get(), false); - } + if (!isInShadowTree()) + m_targetListener->attach(target, id); + + updateReferencedText(); } Node::InsertionNotificationRequest SVGTRefElement::insertedInto(ContainerNode* rootParent) @@ -305,15 +328,7 @@ void SVGTRefElement::removedFrom(ContainerNode* rootParent) { SVGStyledElement::removedFrom(rootParent); if (rootParent->inDocument()) - clearEventListener(); -} - -void SVGTRefElement::clearEventListener() -{ - if (m_eventListener) { - m_eventListener->clear(); - m_eventListener = 0; - } + m_targetListener->detach(); } } |