Package org.itsnat.impl.core.css

Source Code of org.itsnat.impl.core.css.CSSPrimitiveValueImpl

/*
  ItsNat Java Web Application Framework
  Copyright (C) 2007-2011 Jose Maria Arranz Santamaria, Spanish citizen

  This software is free software; you can redistribute it and/or modify it
  under the terms of the GNU Lesser General Public License as
  published by the Free Software Foundation; either version 3 of
  the License, or (at your option) any later version.
  This software is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details. You should have received
  a copy of the GNU Lesser General Public License along with this program.
  If not, see <http://www.gnu.org/licenses/>.
*/

package org.itsnat.impl.core.css;

import org.w3c.dom.DOMException;
import org.w3c.dom.css.CSSPrimitiveValue;
import org.w3c.dom.css.Counter;
import org.w3c.dom.css.RGBColor;
import org.w3c.dom.css.Rect;
import org.itsnat.impl.core.css.lex.FloatNumber;
import org.itsnat.impl.core.css.lex.HexNumber;
import org.itsnat.impl.core.css.lex.Identifier;
import org.itsnat.impl.core.css.lex.ParenthesisBlock;
import org.itsnat.impl.core.css.lex.Percent;
import org.itsnat.impl.core.css.lex.SourceCode;
import org.itsnat.impl.core.css.lex.StringDoubleQuote;
import org.itsnat.impl.core.css.lex.StringSimpleQuote;
import org.itsnat.impl.core.css.lex.Token;

/**
* http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue
* http://www.w3.org/TR/REC-CSS2/grammar.html
* http://www.w3.org/TR/REC-CSS2/syndata.html
* http://www.princexml.com/doc/properties/
*
* @author jmarranz
*/
public class CSSPrimitiveValueImpl extends CSSValueImpl implements CSSPrimitiveValue
{
    protected short primitiveType = -1;
    protected float floatValue;
    protected Counter counterValue;
    protected Rect rectValue;
    protected RGBColor rgbValue;

    /** Creates a new instance of CSSPrimitiveValueImpl */
    public CSSPrimitiveValueImpl(SourceCode cssTextCode,int code,ObjectValueParent parent)
    {
        super(cssTextCode,code,parent);
        rebuild(cssTextCode);
    }

    public static String floatUnitToString(short unitType)
    {
        switch(unitType)
        {
            case CSS_PERCENTAGE:
                return "%";
            case CSS_S:
                return "s";
            case CSS_EMS:
                return "em";
            case CSS_EXS:
                return "ex";
            case CSS_PX:
                return "px";
            case CSS_CM:
                return "cm";
            case CSS_MM:
                return "mm";
            case CSS_IN:
                return "in";
            case CSS_PT:
                return "pt";
            case CSS_PC:
                return "pc";
            case CSS_MS:
                return "ms";
            case CSS_HZ:
                return "hz";
            case CSS_DEG:
                return "deg";
            case CSS_RAD:
                return "rad";
            case CSS_KHZ:
                return "khz";
            case CSS_GRAD:
                return "grad";
            case CSS_NUMBER:
                return "";
            case CSS_DIMENSION:
                return ""// Precisamente por ser desconocida no podemos saber su nombre
        }

        throw new DOMException(DOMException.INVALID_ACCESS_ERR,"Invalid unit type: " + unitType);
    }

    public boolean setFloatValueInternal(SourceCode cssTextCode)
    {
        // Se supone que hay almenos un token
        Token token0 = cssTextCode.getToken(0);
        if (!(token0 instanceof FloatNumber))
            return false;

        FloatNumber tokenNumber = (FloatNumber)token0;
        float floatValue = tokenNumber.getFloat();
        short unitType = -1;

        if (cssTextCode.tokenCount() > 2)
            throw new DOMException(DOMException.INVALID_ACCESS_ERR,"CSS: number format error: " + cssTextCode.toString());

        if (cssTextCode.tokenCount() == 1)
        {
            // No tiene sufijo
            unitType = CSS_NUMBER;
        }
        else
        {
            // Tiene sufijo
            Token token1 = cssTextCode.getToken(1);
            if (!(token1 instanceof Identifier) &&  !(token1 instanceof Percent))
                throw new DOMException(DOMException.INVALID_ACCESS_ERR,"CSS: expected a unit identifier: " + cssTextCode.toString());

            String suffix = token1.toString();
            suffix = suffix.toLowerCase();

            if ("%".equals(suffix))
            {
                unitType = CSS_PERCENTAGE;
            }
            else
            {

                if ("s".equals(suffix))
                {
                    unitType = CSS_PERCENTAGE;
                }
                else if ("em".equals(suffix))
                {
                    unitType = CSS_EMS;
                }
                else if ("ex".equals(suffix))
                {
                    unitType = CSS_EXS;
                }
                else if ("px".equals(suffix))
                {
                    unitType = CSS_PX;
                }
                else if ("cm".equals(suffix))
                {
                    unitType = CSS_CM;
                }
                else if ("mm".equals(suffix))
                {
                    unitType = CSS_MM;
                }
                else if ("in".equals(suffix))
                {
                    unitType = CSS_IN;
                }
                else if ("pt".equals(suffix))
                {
                    unitType = CSS_PT;
                }
                else if ("pc".equals(suffix))
                {
                    unitType = CSS_PC;
                }
                else if ("ms".equals(suffix))
                {
                    unitType = CSS_MS;
                }
                else if ("hz".equals(suffix))
                {
                    unitType = CSS_HZ;
                }
                else if ("deg".equals(suffix))
                {
                    unitType = CSS_DEG;
                }
                else if ("rad".equals(suffix))
                {
                    unitType = CSS_RAD;
                }
                else if ("khz".equals(suffix))
                {
                    unitType = CSS_KHZ;
                }
                else if ("grad".equals(suffix))
                {
                    unitType = CSS_GRAD;
                }
                else // Unidad desconocida, es el caso CSS_DIMENSION
                {
                    unitType = CSS_DIMENSION;
                }
            }
        }

        this.primitiveType = unitType;
        this.floatValue = floatValue;

        return true;
    }

    public boolean setFunctionBasedValueInternal(SourceCode cssTextCode)
    {
        if (cssTextCode.tokenCount() != 2)
            return false;

        Token token0 = cssTextCode.getToken(0);
        if (!(token0 instanceof Identifier))
            return false;
        Identifier tokIdent = (Identifier)token0;

        Token token1 = cssTextCode.getToken(1);
        if (!(token1 instanceof ParenthesisBlock))
            return false;
        ParenthesisBlock tokBlock = (ParenthesisBlock)token1;

        String identif = tokIdent.toString();
        identif = identif.toLowerCase();

        if (identif.equals("url"))
        {
            this.primitiveType = CSS_URI;
            // No hay ning�n objeto especial, el url queda almacenado en this.cssTextCode
            return true;
        }
        else if (identif.equals("rect"))
        {
            this.primitiveType = CSS_RECT;
            this.rectValue = new RectImpl(tokBlock.getContent(),this);
            return true;
        }
        else if (identif.equals("rgb"))
        {
            // FALTA procesar los valores #rgb y #rrggbb
            this.primitiveType = CSS_RGBCOLOR;
            this.rgbValue = new RGBColorImpl(tokBlock.getContent(),this);
            return true;
        }
        else if (identif.equals("attr"))
        {
            this.primitiveType = CSS_ATTR;
            // No hay ning�n objeto especial, el attr queda almacenado en this.cssTextCode
            return true;
        }
        else if (identif.equals("counter"))
        {
            // Es un CSS_COUNTER pero no lo soportamos
            this.primitiveType = CSS_UNKNOWN;
            // el valor queda almacenado en this.cssTextCode
            return true;
        }
        else if (identif.equals("counters"))
        {
            // Es un CSS_COUNTER pero no lo soportamos
            this.primitiveType = CSS_UNKNOWN;
            // el valor queda almacenado en this.cssTextCode
            return true;
        }

        return false;
    }

    public void rebuild(SourceCode cssTextCode)
    {
        cssTextCode = cssTextCode.trim();

        if (cssTextCode.tokenCount() == 0)
            throw new DOMException(DOMException.INVALID_ACCESS_ERR,"CSS value is not specified, property: " + parent.getPropertyName() + " value: " + this.cssTextCode.toString());

        if (setFloatValueInternal(cssTextCode))
            return;

        // No es un n�mero ni un n�mero + sufijo
        if (setFunctionBasedValueInternal(cssTextCode))
            return;

        if (cssTextCode.tokenCount() == 1)
        {
            Token token = cssTextCode.getToken(0);
            if ((token instanceof StringDoubleQuote) ||
                (token instanceof StringSimpleQuote))
            {
                this.primitiveType = CSS_STRING;
                return;
            }
            else if (token instanceof Identifier)
            {
                this.primitiveType = CSS_IDENT;
                return;
            }
            else if (token instanceof HexNumber)
            {
                // Casos #rgb y #rrggbb
                this.primitiveType = CSS_RGBCOLOR;
                this.rgbValue = new RGBColorImpl((HexNumber)token,this);
                return;
            }
            else
            {
                this.primitiveType = CSS_UNKNOWN;
                return;
            }
        }
        else
        {
            this.primitiveType = CSS_UNKNOWN;
            return;
        }
    }

    public short getCssValueType()
    {
        return CSS_PRIMITIVE_VALUE;
    }

    public short getPrimitiveType()
    {
        return primitiveType;
    }

    public float getFloatValue(short unitType) throws DOMException
    {
        if (this.primitiveType != unitType)
            throw new DOMException(DOMException.INVALID_ACCESS_ERR,"Unit conversions is not supported");

        getCssText(); // Verifica que no ha cambiado indirectamente

        return floatValue;
    }

    public void setFloatValue(short unitType, float floatValue) throws DOMException
    {
        String suffix = floatUnitToString(unitType);
        String cssText = Float.toString(floatValue) + suffix;
        setCssTextSourceCode(new SourceCode(cssText),false);

        this.primitiveType = unitType;
        this.floatValue = floatValue;
    }

    public static boolean isStringBasedType(short primitiveType)
    {
        return ((primitiveType == CSS_STRING) ||
                (primitiveType == CSS_URI) ||
                (primitiveType == CSS_IDENT) ||
                (primitiveType == CSS_ATTR));
    }

    public String getStringValue() throws DOMException
    {
        if (!isStringBasedType(this.primitiveType))
            throw new DOMException(DOMException.INVALID_ACCESS_ERR,"CSS value doesn't contain a string");

        String str = getCssText();
        // Por si la cadena ha sido definida via setCssTextSourceCode
        str = str.trim();
        if (primitiveType == CSS_STRING)
        {
            // Quitamos las comillas " o ' (es obligatorio que est�n)
            str = str.substring(1,str.length() - 1);
        }

        return str;
    }

    public void setStringValue(short stringType, String stringValue) throws DOMException
    {
        if (!isStringBasedType(this.primitiveType))
            throw new DOMException(DOMException.INVALID_ACCESS_ERR,"CSS value doesn't contain a string");
        if (!isStringBasedType(stringType))
            throw new DOMException(DOMException.INVALID_ACCESS_ERR,"New CSS value doesn't contain a string, invalid string type");

        stringValue = stringValue.trim();
        if (primitiveType == CSS_STRING)
        {
            // A�adimos los literales (es obligatorio que est�n)
            stringValue = '"' + stringValue + '"';
        }

        setCssTextSourceCode(new SourceCode(stringValue),false);
        this.primitiveType = stringType;
    }

    public Counter getCounterValue() throws DOMException
    {
        if (primitiveType != CSS_COUNTER)
            throw new DOMException(DOMException.INVALID_ACCESS_ERR,"CSS value doesn't contain a Counter value");

        return this.counterValue; // Por ahora devuelve null, no soportamos counters
    }

    public Rect getRectValue() throws DOMException
    {
        if (primitiveType != CSS_RECT)
            throw new DOMException(DOMException.INVALID_ACCESS_ERR,"CSS value doesn't contain a Rect value");

        return rectValue;
    }

    public RGBColor getRGBColorValue() throws DOMException
    {
        if (primitiveType != CSS_RGBCOLOR)
            throw new DOMException(DOMException.INVALID_ACCESS_ERR,"CSS value doesn't contain a RGBColor value");

        return this.rgbValue;
    }

    public Object getUpdatedChildObjectValueFromElement(Object requester,int requesterCode)
    {
        CSSPrimitiveValueImpl current = (CSSPrimitiveValueImpl)parent.getUpdatedChildObjectValueFromElement(this,getCode());
        if (current != this// Ha cambiado en el elemento (si adem�s hubiera cambiado el tipo de objeto dar�a error antes)
        {
           if (requesterCode == CSSPrimitiveValueLiteralImpl.COUNTER)
               return current.getCounterValue();
           else if (requesterCode == CSSPrimitiveValueLiteralImpl.RECT)
               return current.getRectValue();
           else if (requesterCode == CSSPrimitiveValueLiteralImpl.RGB)
               return current.getRGBColorValue();

           throw new DOMException(DOMException.INVALID_ACCESS_ERR,"INTERNAL ERROR");
        }
        else
            return requester;
    }

    public void notifyToElementChangedCSSText(SourceCode cssText, Object requester)
    {
        setCssTextSourceCode(cssText,false);
    }
}
TOP

Related Classes of org.itsnat.impl.core.css.CSSPrimitiveValueImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.