| /******************************************************************************* |
| * 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 |
| */ |
| } |