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