Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "CSSVariablesDeclaration.h"
     28 
     29 #include "CSSParser.h"
     30 #include "CSSRule.h"
     31 #include "CSSValueList.h"
     32 #include "Document.h"
     33 #include "ExceptionCode.h"
     34 
     35 namespace WebCore {
     36 
     37 CSSVariablesDeclaration::CSSVariablesDeclaration(StyleBase* parent, const Vector<String>& names, const Vector<RefPtr<CSSValue> >& values)
     38     : StyleBase(parent)
     39 {
     40     m_variableNames = names;
     41     ASSERT(names.size() == values.size());
     42     unsigned s = names.size();
     43     for (unsigned i = 0; i < s; ++i)
     44         addParsedVariable(names[i], values[i], false);
     45 }
     46 
     47 CSSVariablesDeclaration::~CSSVariablesDeclaration()
     48 {
     49 }
     50 
     51 String CSSVariablesDeclaration::getVariableValue(const String& variableName)
     52 {
     53     CSSValue* val = m_variablesMap.get(variableName).get();
     54     if (val)
     55         return val->cssText();
     56     return "";
     57 }
     58 
     59 String CSSVariablesDeclaration::removeVariable(const String& variableName, ExceptionCode&)
     60 {
     61     // FIXME: The spec has this method taking an exception code but no exceptions are
     62     // specified as being thrown.
     63     RefPtr<CSSValue> val = m_variablesMap.take(variableName);
     64     String result = val ? val->cssText() : "";
     65     if (val) {
     66         int s = m_variableNames.size();
     67         for (int i = 0; i < s; ++i) {
     68             if (m_variableNames[i] == variableName) {
     69                 m_variableNames.remove(i);
     70                 i--;
     71                 s--;
     72             }
     73         }
     74 
     75         setNeedsStyleRecalc();
     76     }
     77 
     78     // FIXME: Communicate this change so that the document will update.
     79     return result;
     80 }
     81 
     82 void CSSVariablesDeclaration::setVariable(const String& variableName, const String& variableValue, ExceptionCode& excCode)
     83 {
     84     // Try to parse the variable value into a Value*.  If it fails we throw an exception.
     85     CSSParser parser(useStrictParsing());
     86     if (!parser.parseVariable(this, variableName, variableValue)) // If the parse succeeds, it will call addParsedVariable (our internal method for doing the add) with the parsed Value*.
     87         excCode = SYNTAX_ERR;
     88     else
     89         setNeedsStyleRecalc();
     90 }
     91 
     92 void CSSVariablesDeclaration::addParsedVariable(const String& variableName, PassRefPtr<CSSValue> variableValue, bool updateNamesList)
     93 {
     94 // FIXME: Disabling declarations as variable values for now since they no longer have a common base class with CSSValues.
     95 #if 0
     96     variableValue->setParent(this); // Needed to connect variables that are CSSMutableStyleDeclarations, since the parent couldn't be set until now.
     97 #endif
     98 
     99     // Don't leak duplicates.  For multiple variables with the same name, the last one
    100     // declared will win.
    101     CSSValue* current = m_variablesMap.take(variableName).get();
    102     if (!current && updateNamesList)
    103         m_variableNames.append(variableName);
    104     m_variablesMap.set(variableName, variableValue);
    105 
    106     // FIXME: Communicate this change so the document will update.
    107 }
    108 
    109 CSSValueList* CSSVariablesDeclaration::getParsedVariable(const String& variableName)
    110 {
    111     CSSValue* result = m_variablesMap.get(variableName).get();
    112     if (result->isValueList())
    113         return static_cast<CSSValueList*>(result);
    114     return 0;
    115 }
    116 
    117 CSSMutableStyleDeclaration* CSSVariablesDeclaration::getParsedVariableDeclarationBlock(const String&)
    118 {
    119 // FIXME: Disabling declarations as variable values for now since they no longer have a common base class with CSSValues.
    120 #if 0
    121     StyleBase* result = m_variablesMap.get(variableName).get();
    122 
    123     if (result->isMutableStyleDeclaration())
    124         return static_cast<CSSMutableStyleDeclaration*>(result);
    125 #endif
    126     return 0;
    127 }
    128 
    129 unsigned CSSVariablesDeclaration::length() const
    130 {
    131     return m_variableNames.size();
    132 }
    133 
    134 String CSSVariablesDeclaration::item(unsigned index)
    135 {
    136     if (index >= m_variableNames.size())
    137         return "";
    138     return m_variableNames[index];
    139 }
    140 
    141 CSSRule* CSSVariablesDeclaration::parentRule()
    142 {
    143     return (parent() && parent()->isRule()) ? static_cast<CSSRule*>(parent()) : 0;
    144 }
    145 
    146 String CSSVariablesDeclaration::cssText() const
    147 {
    148     String result = "{ ";
    149     unsigned s = m_variableNames.size();
    150     for (unsigned i = 0; i < s; ++i) {
    151         result += m_variableNames[i] + ": ";
    152         result += m_variablesMap.get(m_variableNames[i])->cssText();
    153         if (i < s - 1)
    154             result += "; ";
    155     }
    156     result += " }";
    157     return result;
    158 }
    159 
    160 void CSSVariablesDeclaration::setCssText(const String&)
    161 {
    162     // FIXME: It's not clear if this is actually settable.
    163 }
    164 
    165 void CSSVariablesDeclaration::setNeedsStyleRecalc()
    166 {
    167     // FIXME: Make this much better (it has the same problem CSSMutableStyleDeclaration does).
    168     StyleBase* root = this;
    169     while (StyleBase* parent = root->parent())
    170         root = parent;
    171     if (root->isCSSStyleSheet())
    172         static_cast<CSSStyleSheet*>(root)->doc()->updateStyleSelector();
    173 }
    174 
    175 }
    176