001: /*
002: ItsNat Java Web Application Framework
003: Copyright (C) 2007 Innowhere Software Services S.L., Spanish Company
004: Author: Jose Maria Arranz Santamaria
005:
006: This program is free software: you can redistribute it and/or modify
007: it under the terms of the GNU Affero General Public License as published by
008: the Free Software Foundation, either version 3 of the License, or
009: (at your option) any later version. See the GNU Affero General Public
010: License for more details. See the copy of the GNU Affero General Public License
011: included in this program. If not, see <http://www.gnu.org/licenses/>.
012: */
013:
014: package org.itsnat.impl.core.css;
015:
016: import java.util.ArrayList;
017: import java.util.HashMap;
018: import java.util.List;
019: import java.util.Map;
020: import org.w3c.dom.DOMException;
021: import org.w3c.dom.css.CSSRule;
022: import org.w3c.dom.css.CSSStyleDeclaration;
023: import org.w3c.dom.css.CSSValue;
024: import org.itsnat.impl.core.css.lex.SemiColon;
025: import org.itsnat.impl.core.css.lex.SourceCode;
026: import org.itsnat.impl.core.dom.ItsNatElementImpl;
027: import org.itsnat.impl.core.domutil.ItsNatDOMUtilInternal;
028:
029: /**
030: *
031: * @author jmarranz
032: */
033: public class CSSStyleDeclarationImpl implements CSSStyleDeclaration {
034: protected String cssText = ""; // Caché
035: protected ItsNatElementImpl parent;
036: protected Map propertyMap = new HashMap();
037: protected List propertyList = new ArrayList();
038:
039: /** Creates a new instance of CSSStyleDeclarationImpl */
040: public CSSStyleDeclarationImpl(ItsNatElementImpl parent) {
041: this .parent = parent;
042: }
043:
044: public String getCssText() {
045: rebuild();
046:
047: return this .cssText;
048: }
049:
050: public void setCssText(String cssText) throws DOMException {
051: ItsNatDOMUtilInternal.setAttribute(parent, "style", cssText); // Actualizamos por sistema pues puede haber cambiado el atributo aunque no sea por aquí
052: rebuild(cssText);
053: }
054:
055: public CSSPropertyImpl getPropertyObject(String propertyName) {
056: getCssText(); // Actualiza si es necesario
057: propertyName = propertyName.toLowerCase();
058: return (CSSPropertyImpl) propertyMap.get(propertyName);
059: }
060:
061: public String getPropertyValue(String propertyName) {
062: CSSPropertyImpl property = getPropertyObject(propertyName);
063: return property.getCssTextSourceCode(false).toString();
064: }
065:
066: public CSSValue getPropertyCSSValue(String propertyName) {
067: // Deberíamos devolver null si es una propiedad "shorthand" pero
068: // nos interesa manipular las propiedades via CSSValue
069: CSSPropertyImpl property = getPropertyObject(propertyName);
070: if (property == null)
071: return null;
072: return property.getCSSValue();
073: }
074:
075: public String removeProperty(String propertyName)
076: throws DOMException {
077: propertyName = propertyName.toLowerCase();
078:
079: CSSPropertyImpl property = getPropertyObject(propertyName);
080: if (property == null)
081: return "";
082: String res = property.getCssTextSourceCode(false).toString();
083:
084: propertyList.remove(property);
085: propertyMap.remove(propertyName);
086:
087: // Renderizamos de nuevo ahora sin la propiedad quitada
088: updateCssTextFromPropertyList();
089:
090: return res;
091: }
092:
093: public void updateCssTextFromPropertyList() {
094: StringBuffer cssText = new StringBuffer();
095: for (int i = 0; i < propertyList.size(); i++) {
096: if (i != 0)
097: cssText.append(';');
098: CSSPropertyImpl currProperty = (CSSPropertyImpl) propertyList
099: .get(i);
100: cssText.append(currProperty.getPropertyName() + ":"
101: + currProperty.getCssTextSourceCode(false));
102: }
103:
104: this .cssText = cssText.toString(); // Evitamos así la reconstrucción de las listas al llamar a setCssTextSourceCode
105: setCssText(this .cssText);
106: }
107:
108: public String getPropertyPriority(String propertyName) {
109: return ""; // NO soportamos !important
110: }
111:
112: public void notifyToElementChangedProperty(
113: CSSPropertyImpl property, SourceCode value) {
114: CSSPropertyImpl propertyElem = getPropertyObject(property
115: .getPropertyName()); // El mero hecho de hacer esta llamada reconstruye la lista si hubiera cambiado el Element por otra vía
116: if (propertyElem != null) {
117: if (propertyElem != property) {
118: // Substituimos con la nueva y reconstruimos
119: addCSSProperty(property, true);
120: } else {
121: // Aun así ha cambiado el valor, hay que notificar al Element
122: updateCssTextFromPropertyList();
123: }
124: } else // No está, fue eliminada del Element indirectamente, la añadimos de nuevo
125: {
126: addCSSProperty(property, true);
127: }
128: }
129:
130: public void setProperty(String propertyName, String value,
131: String priority) throws DOMException {
132: // Ignoramos la prioridad (!important) no la soportamos
133: CSSPropertyImpl property = getPropertyObject(propertyName); // El mero hecho de hacer esta llamada reconstruye la lista si hubiera cambiado el Element por otra vía
134: if (property != null) {
135: String currentValue = property.getCssText(false);
136: if (!currentValue.equals(value)) {
137: property.setCssText(value, false);
138: // Actualizamos el cssText y el Element
139: updateCssTextFromPropertyList();
140: }
141: } else // No está, es una nueva propiedad
142: {
143: addCSSProperty(propertyName, value, true);
144: }
145: }
146:
147: public int getLength() {
148: return propertyList.size();
149: }
150:
151: public String item(int index) {
152: CSSPropertyImpl currProperty = (CSSPropertyImpl) propertyList
153: .get(index);
154: return currProperty.getCssTextSourceCode().toString();
155: }
156:
157: public CSSRule getParentRule() {
158: // Sólo soportamos propiedades CSS declaradas en atributos style de elementos
159: // por ahora
160: return null;
161: }
162:
163: private void rebuild() {
164: // El atributo puede ser cambiado en cualquier momento
165: // por eso obtenemos siempre el valor desde la fuente original
166:
167: String cssText = parent.getAttribute("style"); // Nunca es nula (cadena vacía si acaso)
168: rebuild(cssText);
169: }
170:
171: private void addCSSProperty(String propertyName, String value,
172: boolean updateCssText) {
173: CSSPropertyImpl property = new CSSPropertyImpl(propertyName,
174: value, this );
175: addCSSProperty(property, updateCssText);
176: }
177:
178: private void addCSSProperty(CSSPropertyImpl property,
179: boolean updateCssText) {
180: propertyList.add(property);
181: propertyMap.put(property.getPropertyName(), property);
182:
183: // Actualizamos el cssText y el Element
184: if (updateCssText)
185: updateCssTextFromPropertyList();
186: }
187:
188: private void rebuild(String cssText) {
189: if (this .cssText.equals(cssText))
190: return; // No es necesario reconstruir las listas
191:
192: this .cssText = cssText;
193:
194: propertyList.clear();
195: propertyMap.clear();
196:
197: SourceCode cssTextSource = SourceCode.newSourceCode(cssText);
198: SourceCode[] cssTextSourceProps = cssTextSource.split(SemiColon
199: .getSingleton());
200:
201: for (int i = 0; i < cssTextSourceProps.length; i++) {
202: SourceCode cssTextSourceProp = cssTextSourceProps[i];
203: addCSSProperty(
204: new CSSPropertyImpl(cssTextSourceProp, this ), false);
205: }
206: }
207: }
|