Home | History | Annotate | Download | only in properties
      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 SVGPropertyTearOff_h
     21 #define SVGPropertyTearOff_h
     22 
     23 #if ENABLE(SVG)
     24 #include "SVGAnimatedProperty.h"
     25 #include "SVGElement.h"
     26 #include "SVGProperty.h"
     27 
     28 namespace WebCore {
     29 
     30 template<typename PropertyType>
     31 class SVGPropertyTearOff : public SVGProperty {
     32 public:
     33     typedef SVGPropertyTearOff<PropertyType> Self;
     34 
     35     // Used for child types (baseVal/animVal) of a SVGAnimated* property (for example: SVGAnimatedLength::baseVal()).
     36     // Also used for list tear offs (for example: text.x.baseVal.getItem(0)).
     37     static PassRefPtr<Self> create(SVGAnimatedProperty* animatedProperty, SVGPropertyRole role, PropertyType& value)
     38     {
     39         ASSERT(animatedProperty);
     40         return adoptRef(new Self(animatedProperty, role, value));
     41     }
     42 
     43     // Used for non-animated POD types (for example: SVGSVGElement::createSVGLength()).
     44     static PassRefPtr<Self> create(const PropertyType& initialValue)
     45     {
     46         return adoptRef(new Self(initialValue));
     47     }
     48 
     49     PropertyType& propertyReference() { return *m_value; }
     50     SVGAnimatedProperty* animatedProperty() const { return m_animatedProperty.get(); }
     51 
     52     // Used only by the list tear offs!
     53     void setValue(PropertyType& value)
     54     {
     55         if (m_valueIsCopy)
     56             delete m_value;
     57         m_valueIsCopy = false;
     58         m_value = &value;
     59     }
     60 
     61     void setAnimatedProperty(SVGAnimatedProperty* animatedProperty) { m_animatedProperty = animatedProperty; }
     62 
     63     SVGElement* contextElement() const
     64     {
     65         if (!m_animatedProperty || m_valueIsCopy)
     66             return 0;
     67         return m_animatedProperty->contextElement();
     68     }
     69 
     70     void detachWrapper()
     71     {
     72         if (m_valueIsCopy)
     73             return;
     74 
     75         // Switch from a live value, to a non-live value.
     76         // For example: <text x="50"/>
     77         // var item = text.x.baseVal.getItem(0);
     78         // text.setAttribute("x", "100");
     79         // item.value still has to report '50' and it has to be possible to modify 'item'
     80         // w/o changing the "new item" (with x=100) in the text element.
     81         // Whenever the XML DOM modifies the "x" attribute, all existing wrappers are detached, using this function.
     82         m_value = new PropertyType(*m_value);
     83         m_valueIsCopy = true;
     84         m_animatedProperty = 0;
     85     }
     86 
     87     virtual void commitChange()
     88     {
     89         if (!m_animatedProperty || m_valueIsCopy)
     90             return;
     91         m_animatedProperty->commitChange();
     92     }
     93 
     94     virtual SVGPropertyRole role() const { return m_role; }
     95 
     96 protected:
     97     SVGPropertyTearOff(SVGAnimatedProperty* animatedProperty, SVGPropertyRole role, PropertyType& value)
     98         : m_animatedProperty(animatedProperty)
     99         , m_role(role)
    100         , m_value(&value)
    101         , m_valueIsCopy(false)
    102     {
    103         // Using operator & is completly fine, as SVGAnimatedProperty owns this reference,
    104         // and we're guaranteed to live as long as SVGAnimatedProperty does.
    105     }
    106 
    107     SVGPropertyTearOff(const PropertyType& initialValue)
    108         : m_animatedProperty(0)
    109         , m_role(UndefinedRole)
    110         , m_value(new PropertyType(initialValue))
    111         , m_valueIsCopy(true)
    112     {
    113     }
    114 
    115     virtual ~SVGPropertyTearOff()
    116     {
    117         if (m_valueIsCopy)
    118             delete m_value;
    119     }
    120 
    121     RefPtr<SVGAnimatedProperty> m_animatedProperty;
    122     SVGPropertyRole m_role;
    123     PropertyType* m_value;
    124     bool m_valueIsCopy : 1;
    125 };
    126 
    127 }
    128 
    129 #endif // ENABLE(SVG)
    130 #endif // SVGPropertyTearOff_h
    131