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 SVGAnimatedListPropertyTearOff_h
21#define SVGAnimatedListPropertyTearOff_h
22
23#if ENABLE(SVG)
24#include "SVGAnimatedProperty.h"
25#include "SVGListPropertyTearOff.h"
26#include "SVGStaticListPropertyTearOff.h"
27
28namespace WebCore {
29
30template<typename PropertyType>
31class SVGPropertyTearOff;
32
33template<typename PropertyType>
34class SVGAnimatedListPropertyTearOff : public SVGAnimatedProperty {
35public:
36    typedef typename SVGPropertyTraits<PropertyType>::ListItemType ListItemType;
37    typedef SVGPropertyTearOff<ListItemType> ListItemTearOff;
38    typedef Vector<RefPtr<ListItemTearOff> > ListWrapperCache;
39
40    SVGProperty* baseVal()
41    {
42        if (!m_baseVal)
43            m_baseVal = SVGListPropertyTearOff<PropertyType>::create(this, BaseValRole);
44        return m_baseVal.get();
45    }
46
47    SVGProperty* animVal()
48    {
49        if (!m_animVal)
50            m_animVal = SVGListPropertyTearOff<PropertyType>::create(this, AnimValRole);
51        return m_animVal.get();
52    }
53
54    virtual bool isAnimatedListTearOff() const { return true; }
55
56    int removeItemFromList(SVGProperty* property, bool shouldSynchronizeWrappers)
57    {
58        // This should ever be called for our baseVal, as animVal can't modify the list.
59        typedef SVGPropertyTearOff<typename SVGPropertyTraits<PropertyType>::ListItemType> ListItemTearOff;
60        return static_pointer_cast<SVGListPropertyTearOff<PropertyType> >(m_baseVal)->removeItemFromList(static_cast<ListItemTearOff*>(property), shouldSynchronizeWrappers);
61    }
62
63    void detachListWrappers(unsigned newListSize)
64    {
65        // See SVGPropertyTearOff::detachWrapper() for an explaination what's happening here.
66        unsigned size = m_wrappers.size();
67        ASSERT(size == m_values.size());
68        for (unsigned i = 0; i < size; ++i) {
69            RefPtr<ListItemTearOff>& item = m_wrappers.at(i);
70            if (!item)
71                continue;
72            item->detachWrapper();
73        }
74
75        // Reinitialize the wrapper cache to be equal to the new values size, after the XML DOM changed the list.
76        if (newListSize)
77            m_wrappers.fill(0, newListSize);
78        else
79            m_wrappers.clear();
80    }
81
82    PropertyType& values() { return m_values; }
83    ListWrapperCache& wrappers() { return m_wrappers; }
84
85private:
86    friend class SVGAnimatedProperty;
87
88    static PassRefPtr<SVGAnimatedListPropertyTearOff<PropertyType> > create(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& values)
89    {
90        ASSERT(contextElement);
91        return adoptRef(new SVGAnimatedListPropertyTearOff<PropertyType>(contextElement, attributeName, values));
92    }
93
94protected:
95    SVGAnimatedListPropertyTearOff(SVGElement* contextElement, const QualifiedName& attributeName, PropertyType& values)
96        : SVGAnimatedProperty(contextElement, attributeName)
97        , m_values(values)
98    {
99        if (!values.isEmpty())
100            m_wrappers.fill(0, values.size());
101    }
102
103    PropertyType& m_values;
104
105    // FIXME: The list wrapper cache is shared between baseVal/animVal. If we implement animVal,
106    // we need two seperated wrapper caches if the attribute gets animated.
107    ListWrapperCache m_wrappers;
108
109    RefPtr<SVGProperty> m_baseVal;
110    RefPtr<SVGProperty> m_animVal;
111};
112
113}
114
115#endif // ENABLE(SVG)
116#endif // SVGAnimatedListPropertyTearOff_h
117