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 "SVGAnimatedPropertyDescription.h"
25#include "SVGElement.h"
26#include "SVGPropertyInfo.h"
27#include <wtf/RefCounted.h>
28
29namespace WebCore {
30
31class SVGElement;
32
33class SVGAnimatedProperty : public RefCounted<SVGAnimatedProperty> {
34public:
35    SVGElement* contextElement() const { return m_contextElement.get(); }
36    const QualifiedName& attributeName() const { return m_attributeName; }
37    AnimatedPropertyType animatedPropertyType() const { return m_animatedPropertyType; }
38    bool isAnimating() const { return m_isAnimating; }
39    bool isReadOnly() const { return m_isReadOnly; }
40    void setIsReadOnly() { m_isReadOnly = true; }
41
42    void commitChange()
43    {
44        ASSERT(m_contextElement);
45        ASSERT(!m_contextElement->m_deletionHasBegun);
46        m_contextElement->invalidateSVGAttributes();
47        m_contextElement->svgAttributeChanged(m_attributeName);
48    }
49
50    virtual bool isAnimatedListTearOff() const { return false; }
51
52    // Caching facilities.
53    typedef HashMap<SVGAnimatedPropertyDescription, SVGAnimatedProperty*, SVGAnimatedPropertyDescriptionHash, SVGAnimatedPropertyDescriptionHashTraits> Cache;
54
55    virtual ~SVGAnimatedProperty()
56    {
57        // Remove wrapper from cache.
58        Cache* cache = animatedPropertyCache();
59        const Cache::const_iterator end = cache->end();
60        for (Cache::const_iterator it = cache->begin(); it != end; ++it) {
61            if (it->value == this) {
62                cache->remove(it->key);
63                break;
64            }
65        }
66
67        // Assure that animationEnded() was called, if animationStarted() was called before.
68        ASSERT(!m_isAnimating);
69    }
70
71    template<typename OwnerType, typename TearOffType, typename PropertyType>
72    static PassRefPtr<TearOffType> lookupOrCreateWrapper(OwnerType* element, const SVGPropertyInfo* info, PropertyType& property)
73    {
74        ASSERT(info);
75        SVGAnimatedPropertyDescription key(element, info->propertyIdentifier);
76        RefPtr<SVGAnimatedProperty> wrapper = animatedPropertyCache()->get(key);
77        if (!wrapper) {
78            wrapper = TearOffType::create(element, info->attributeName, info->animatedPropertyType, property);
79            if (info->animatedPropertyState == PropertyIsReadOnly)
80                wrapper->setIsReadOnly();
81            animatedPropertyCache()->set(key, wrapper.get());
82        }
83        return static_pointer_cast<TearOffType>(wrapper);
84    }
85
86    template<typename OwnerType, typename TearOffType>
87    static TearOffType* lookupWrapper(OwnerType* element, const SVGPropertyInfo* info)
88    {
89        ASSERT(info);
90        SVGAnimatedPropertyDescription key(element, info->propertyIdentifier);
91        return static_cast<TearOffType*>(animatedPropertyCache()->get(key));
92    }
93
94    template<typename OwnerType, typename TearOffType>
95    static TearOffType* lookupWrapper(const OwnerType* element, const SVGPropertyInfo* info)
96    {
97        return lookupWrapper<OwnerType, TearOffType>(const_cast<OwnerType*>(element), info);
98    }
99
100protected:
101    SVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, AnimatedPropertyType animatedPropertyType)
102        : m_contextElement(contextElement)
103        , m_attributeName(attributeName)
104        , m_animatedPropertyType(animatedPropertyType)
105        , m_isAnimating(false)
106        , m_isReadOnly(false)
107    {
108    }
109
110private:
111    static Cache* animatedPropertyCache()
112    {
113        static Cache* s_cache = new Cache;
114        return s_cache;
115    }
116
117    RefPtr<SVGElement> m_contextElement;
118    const QualifiedName& m_attributeName;
119    AnimatedPropertyType m_animatedPropertyType;
120
121protected:
122    bool m_isAnimating;
123    bool m_isReadOnly;
124};
125
126}
127
128#endif // ENABLE(SVG)
129#endif // SVGAnimatedProperty_h
130