/******************************************************************************* * Copyright (c) 2008 Innoopract Informationssysteme GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation ******************************************************************************/ package org.eclipse.rwt.internal.theme.css; import java.util.*; import org.eclipse.rwt.internal.theme.*; import org.w3c.css.sac.LexicalUnit; public class PropertyResolver { private static final String BOLD = "bold"; private static final String ITALIC = "italic"; private static final String NORMAL = "normal"; private static final String NONE = "none"; private static final String HIDDEN = "hidden"; private static final String DOTTED = "dotted"; private static final String DASHED = "dashed"; private static final String SOLID = "solid"; private static final String DOUBLE = "double"; private static final String GROOVE = "groove"; private static final String RIDGE = "ridge"; private static final String INSET = "inset"; private static final String OUTSET = "outset"; /** A thin border. */ private static final String THIN = "thin"; /** A medium border. */ private static final String MEDIUM = "medium"; /** A thick border. */ private static final String THICK = "thick"; private static final String TRANSPARENT = "transparent"; private static final Map NAMED_COLORS = new HashMap(); private static final List BORDER_STYLES = new ArrayList(); /** Width value for "thin" identifier. */ public static final int THIN_VALUE = 1; /** Width value for "medium" identifier. */ public static final int MEDIUM_VALUE = 3; /** Width value for "thick" identifier. */ public static final int THICK_VALUE = 5; static { // register 16 standard HTML colors NAMED_COLORS.put( "black", new int[] { 0, 0, 0 } ); NAMED_COLORS.put( "gray", new int[] { 128, 128, 128 } ); NAMED_COLORS.put( "silver", new int[] { 192, 192, 192 } ); NAMED_COLORS.put( "white", new int[] { 255, 255, 255 } ); NAMED_COLORS.put( "maroon", new int[] { 128, 0, 0 } ); NAMED_COLORS.put( "red", new int[] { 255, 0, 0 } ); NAMED_COLORS.put( "purple", new int[] { 128, 0, 128 } ); NAMED_COLORS.put( "fuchsia", new int[] { 255, 0, 255 } ); NAMED_COLORS.put( "green", new int[] { 0, 128, 0 } ); NAMED_COLORS.put( "lime", new int[] { 0, 255, 0 } ); NAMED_COLORS.put( "navy", new int[] { 0, 0, 128 } ); NAMED_COLORS.put( "blue", new int[] { 0, 0, 255 } ); NAMED_COLORS.put( "olive", new int[] { 128, 128, 0 } ); NAMED_COLORS.put( "yellow", new int[] { 255, 255, 0 } ); NAMED_COLORS.put( "teal", new int[] { 0, 128, 128 } ); NAMED_COLORS.put( "aqua", new int[] { 0, 255, 255 } ); // register border styles BORDER_STYLES.add( NONE ); // No border; the computed border width is zero. BORDER_STYLES.add( HIDDEN ); // Same as 'none', except in terms of border conflict resolution for table elements. BORDER_STYLES.add( DOTTED ); // The border is a series of dots. BORDER_STYLES.add( DASHED ); // The border is a series of short line segments. BORDER_STYLES.add( SOLID ); // The border is a single line segment. BORDER_STYLES.add( DOUBLE ); // The border is two solid lines. The sum of the two lines and the space between them equals the value of 'border-width'. BORDER_STYLES.add( GROOVE ); // The border looks as though it were carved into the canvas. BORDER_STYLES.add( RIDGE ); // The opposite of 'groove': the border looks as though it were coming out of the canvas. BORDER_STYLES.add( INSET ); // The border makes the box look as though it were embedded in the canvas. BORDER_STYLES.add( OUTSET ); // The opposite of 'inset': the border makes the box look as though it were coming out of the canvas. } public static QxColor readColor( final LexicalUnit input ) { QxColor result = null; short type = input.getLexicalUnitType(); if( type == LexicalUnit.SAC_RGBCOLOR ) { LexicalUnit redParam = input.getParameters(); LexicalUnit greenParam = redParam.getNextLexicalUnit().getNextLexicalUnit(); LexicalUnit blueParam = greenParam.getNextLexicalUnit().getNextLexicalUnit(); short valueType = redParam.getLexicalUnitType(); if( greenParam.getLexicalUnitType() == valueType || blueParam.getLexicalUnitType() == valueType ) { if( valueType == LexicalUnit.SAC_INTEGER ) { int red = normalizeRGBValue( redParam.getIntegerValue() ); int green = normalizeRGBValue( greenParam.getIntegerValue() ); int blue = normalizeRGBValue( blueParam.getIntegerValue() ); result = QxColor.create( red, green, blue ); } else if( valueType == LexicalUnit.SAC_PERCENTAGE ) { float redPercent = normalizePercentValue( redParam.getFloatValue() ); float greenPercent = normalizePercentValue( greenParam.getFloatValue() ); float bluePercent = normalizePercentValue( blueParam.getFloatValue() ); int red = ( int )( 255 * redPercent / 100 ); int green = ( int )( 255 * greenPercent / 100 ); int blue = ( int )( 255 * bluePercent / 100 ); result = QxColor.create( red, green, blue ); } } } else if( type == LexicalUnit.SAC_IDENT ) { String string = input.getStringValue(); if( TRANSPARENT.equals( string ) ) { result = QxColor.TRANSPARENT; } else if( NAMED_COLORS.containsKey( string.toLowerCase() ) ) { int[] values = ( int[] )NAMED_COLORS.get( string.toLowerCase() ); result = QxColor.create( values[ 0 ], values[ 1 ], values[ 2 ] ); } } return result; } public static QxDimension readDimension( final LexicalUnit unit ) { QxDimension result = null; Integer length = readSingleLengthUnit( unit ); if( length != null ) { result = QxDimension.create( length.intValue() ); } return result; } public static QxBoxDimensions readBoxDimensions( final LexicalUnit unit ) { QxBoxDimensions result = null; Integer value1 = readSingleLengthUnit( unit ); if( value1 != null ) { int top, right, left, bottom; top = right = bottom = left = value1.intValue(); LexicalUnit nextUnit = unit.getNextLexicalUnit(); boolean ok = true; int pos = 1; while( nextUnit != null && ok ) { pos++; Integer nextValue = readSingleLengthUnit( nextUnit ); ok &= nextValue != null && pos <= 4; if( ok ) { if( pos == 2 ) { right = left = nextValue.intValue(); } else if( pos == 3 ) { bottom = nextValue.intValue(); } else if( pos == 4 ) { left = nextValue.intValue(); } } nextUnit = nextUnit.getNextLexicalUnit(); } ok &= nextUnit == null; if( ok ) { result = QxBoxDimensions.create( top, right, bottom, left ); } } return result; } public static String readBorderStyle( final LexicalUnit unit ) { String result = null; short type = unit.getLexicalUnitType(); if( type == LexicalUnit.SAC_IDENT ) { String string = unit.getStringValue(); if( BORDER_STYLES.contains( string ) ) { result = string; } } return result; } public static int readBorderWidth( final LexicalUnit unit ) { int result = -1; short type = unit.getLexicalUnitType(); if( type == LexicalUnit.SAC_IDENT ) { String string = unit.getStringValue(); if( THIN.equals( string ) ) { result = THIN_VALUE; } else if( MEDIUM.equals( string ) ) { result = MEDIUM_VALUE; } else if( THICK.equals( string ) ) { result = THICK_VALUE; } } else if( type == LexicalUnit.SAC_PIXEL ) { float value = unit.getFloatValue(); if( value >= 0f ) { result = Math.round( value ); } } return result; } public static QxBorder readBorder( final LexicalUnit unit ) { QxBorder result = null; QxColor color = null; String style = null; int width = -1; LexicalUnit nextUnit = unit; boolean consumed = false; while( nextUnit != null ) { consumed = false; if( !consumed && width == -1 ) { width = readBorderWidth( nextUnit ); consumed |= width != -1; } if( !consumed && style == null ) { style = readBorderStyle( nextUnit ); consumed |= style != null; } if( !consumed && color == null ) { color = readColor( nextUnit ); consumed |= color != null; } nextUnit = consumed ? nextUnit.getNextLexicalUnit() : null; } if( consumed ) { // TODO [rst] create should take a QxColor result = QxBorder.create( width == -1 ? 0 : width, style, color != null ? color.toDefaultString() : null ); } return result; } public static String readFontStyle( final LexicalUnit unit ) { String result = null; short type = unit.getLexicalUnitType(); if( type == LexicalUnit.SAC_IDENT ) { String value = unit.getStringValue(); if( NORMAL.equals( value ) ) { result = value; } else if( ITALIC.equals( value ) ) { result = value; } } return result; } public static String readFontWeight( final LexicalUnit unit ) { String result = null; short type = unit.getLexicalUnitType(); if( type == LexicalUnit.SAC_IDENT ) { String value = unit.getStringValue(); if( NORMAL.equals( value ) ) { result = value; } else if( BOLD.equals( value ) ) { result = value; } } return result; } public static int readFontSize( final LexicalUnit unit ) { int result = -1; Integer length = readSingleLengthUnit( unit ); if( length != null ) { int value = length.intValue(); if( value >= 0 ) { result = value; } } return result; } public static String[] readFontFamily( final LexicalUnit unit ) { List list = new ArrayList(); LexicalUnit nextUnit = unit; boolean ok = true; String buffer = ""; while( nextUnit != null && ok ) { short type = nextUnit.getLexicalUnitType(); if( type == LexicalUnit.SAC_STRING_VALUE || type == LexicalUnit.SAC_IDENT ) { if( buffer.length() > 0 ) { buffer += " "; } buffer += nextUnit.getStringValue(); } else if( type == LexicalUnit.SAC_OPERATOR_COMMA ) { if( buffer.length() > 0 ) { list.add( buffer ); } else { ok = false; } buffer = ""; } nextUnit = nextUnit.getNextLexicalUnit(); } String[] result = null; if( buffer.length() > 0 ) { list.add( buffer ); result = new String[ list.size() ]; list.toArray( result ); } return result; } // The format of a URI value is 'url(' followed by optional whitespace // followed by an optional single quote (') or double quote (") character // followed by the URI itself, followed by an optional single quote (') or // double quote (") character followed by optional whitespace followed by ')'. // The two quote characters must be the same. public static QxFont readFont( final LexicalUnit unit ) { QxFont result = null; String[] family = null; String style = null; String weight = null; int size = -1; boolean consumed = false; boolean consumedSize = false; boolean consumedFamily = false; LexicalUnit nextUnit = unit; while( nextUnit != null && !consumedFamily ) { consumed = false; if( !consumed && !consumedSize && style == null ) { style = readFontStyle( nextUnit ); consumed |= style != null; } if( !consumed && !consumedSize && weight == null ) { weight = readFontWeight( nextUnit ); consumed |= weight != null; } if( !consumed && !consumedFamily && size == -1 ) { size = readFontSize( nextUnit ); consumedSize = size != -1; consumed |= consumedSize; } if( !consumed && consumedSize && family == null ) { family = readFontFamily( nextUnit ); consumedFamily = family != null; consumed |= consumedFamily; } nextUnit = consumed ? nextUnit.getNextLexicalUnit() : null; } if( consumed && consumedSize && consumedFamily ) { boolean bold = BOLD.equals( weight ); boolean italic = ITALIC.equals( style ); result = QxFont.create( family, size, bold, italic ); } return result; } public static String readUrl( final LexicalUnit unit ) { String result = null; short type = unit.getLexicalUnitType(); if( type == LexicalUnit.SAC_URI ) { result = unit.getStringValue(); } return result; } public static QxImage readBackgroundImage( final LexicalUnit unit, final ResourceLoader loader ) { QxImage result = null; short type = unit.getLexicalUnitType(); if( type == LexicalUnit.SAC_URI ) { String value = unit.getStringValue(); result = QxImage.valueOf( value, loader ); } else if( type == LexicalUnit.SAC_IDENT ) { String value = unit.getStringValue(); if( NONE.equals( value ) ) { result = QxImage.NONE; } } return result; } private static Integer readSingleLengthUnit( final LexicalUnit unit ) { Integer result = null; short type = unit.getLexicalUnitType(); if( type == LexicalUnit.SAC_PIXEL ) { result = new Integer( ( int )unit.getFloatValue() ); } return result; } private static int normalizeRGBValue( final int input ) { int result = input; if( input < 0 ) { result = 0; } else if( input > 255 ) { result = 255; } return result; } private static float normalizePercentValue( final float input ) { float result = input; if( input < 0f ) { result = 0f; } else if( input > 100f ) { result = 100f; } return result; } /* * BEGIN Modification for Theme Editor * Returns an QxType out of a LexicalUnit. */ public static QxType getQxType( final String cssProperty, final LexicalUnit unit ) { QxType result = null; if( unit != null ) { // IPropertyWrapper wrapper = PropertyWrapperFactory.createPropertyWrapper( cssProperty, // unit, // null ); // if ( wrapper != null ) { // result = wrapper.getQxType(); // } } return result; } /* * Returns the color value of a border unit. */ public static QxColor readBorderColor( final LexicalUnit unit ) { QxColor result = null; String style = null; int width = -1; LexicalUnit nextUnit = unit; boolean consumed = false; while( nextUnit != null ) { consumed = false; if( !consumed && width == -1 ) { width = readBorderWidth( nextUnit ); consumed |= width != -1; } if( !consumed && style == null ) { style = readBorderStyle( nextUnit ); consumed |= style != null; } if( !consumed && result == null ) { result = readColor( nextUnit ); consumed |= result != null; } nextUnit = consumed ? nextUnit.getNextLexicalUnit() : null; } return result; } /* * END Modification for Theme Editor */ }