1/*
2 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
3 *
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.
8 *
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.
13 *
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.
18 */
19
20#ifndef SVGAnimatedProperty_h
21#define SVGAnimatedProperty_h
22
23#if ENABLE(SVG)
24#include "QualifiedName.h"
25#include "SVGAnimatedPropertyDescription.h"
26#include "SVGElement.h"
27#include <wtf/RefCounted.h>
28
29namespace WebCore {
30
31class SVGElement;
32class SVGProperty;
33
34class SVGAnimatedProperty : public RefCounted<SVGAnimatedProperty> {
35public:
36    SVGElement* contextElement() const { return m_contextElement.get(); }
37    const QualifiedName& attributeName() const { return m_attributeName; }
38
39    void commitChange()
40    {
41        ASSERT(m_contextElement);
42        m_contextElement->invalidateSVGAttributes();
43        m_contextElement->svgAttributeChanged(m_attributeName);
44    }
45
46    virtual bool isAnimatedListTearOff() const { return false; }
47
48    // Caching facilities.
49    typedef HashMap<SVGAnimatedPropertyDescription, RefPtr<SVGAnimatedProperty>, SVGAnimatedPropertyDescriptionHash, SVGAnimatedPropertyDescriptionHashTraits> Cache;
50
51    virtual ~SVGAnimatedProperty()
52    {
53        // Remove wrapper from cache.
54        Cache* cache = animatedPropertyCache();
55        const Cache::const_iterator end = cache->end();
56        for (Cache::const_iterator it = cache->begin(); it != end; ++it) {
57            if (it->second == this) {
58                cache->remove(it->first);
59                break;
60            }
61        }
62    }
63
64    template<typename TearOffType, typename PropertyType>
65    static PassRefPtr<TearOffType> lookupOrCreateWrapper(SVGElement* element, const QualifiedName& attributeName, const AtomicString& attributeIdentifier, PropertyType& property)
66    {
67        SVGAnimatedPropertyDescription key(element, attributeIdentifier);
68        RefPtr<SVGAnimatedProperty> wrapper = animatedPropertyCache()->get(key);
69        if (!wrapper) {
70            wrapper = TearOffType::create(element, attributeName, property);
71            animatedPropertyCache()->set(key, wrapper);
72        }
73
74        return static_pointer_cast<TearOffType>(wrapper).release();
75    }
76
77    template<typename TearOffType>
78    static TearOffType* lookupWrapper(SVGElement* element, const AtomicString& attributeIdentifier)
79    {
80        SVGAnimatedPropertyDescription key(element, attributeIdentifier);
81        return static_pointer_cast<TearOffType>(animatedPropertyCache()->get(key)).get();
82    }
83
84protected:
85    SVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName)
86        : m_contextElement(contextElement)
87        , m_attributeName(attributeName)
88    {
89    }
90
91private:
92    static Cache* animatedPropertyCache()
93    {
94        static Cache* s_cache = new Cache;
95        return s_cache;
96    }
97
98    RefPtr<SVGElement> m_contextElement;
99    const QualifiedName& m_attributeName;
100};
101
102}
103
104#endif // ENABLE(SVG)
105#endif // SVGAnimatedProperty_h
106