/* * {{{ header & license * Copyright (c) 2007 Wisconsin Court System * * This program 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 2.1 * of the License, or (at your option) any later version. * * This program 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * }}} */ package org.xhtmlrenderer.css.parser.property; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.w3c.dom.css.CSSPrimitiveValue; import org.xhtmlrenderer.css.constants.CSSName; import org.xhtmlrenderer.css.constants.IdentValue; import org.xhtmlrenderer.css.parser.CSSParseException; import org.xhtmlrenderer.css.parser.FSRGBColor; import org.xhtmlrenderer.css.parser.PropertyValue; import org.xhtmlrenderer.css.sheet.PropertyDeclaration; public class BorderPropertyBuilders { private static abstract class BorderSidePropertyBuilder extends AbstractPropertyBuilder { protected abstract CSSName[][] getProperties(); private void addAll(List result, CSSName[] properties, CSSPrimitiveValue value, int origin, boolean important) { for (int i = 0; i < properties.length; i++) { result.add(new PropertyDeclaration( properties[i], value, important, origin)); } } public List buildDeclarations( CSSName cssName, List values, int origin, boolean important, boolean inheritAllowed) { CSSName[][] props = getProperties(); List result = new ArrayList(3); if (values.size() == 1 && ((CSSPrimitiveValue)values.get(0)).getCssValueType() == CSSPrimitiveValue.CSS_INHERIT) { CSSPrimitiveValue value = (CSSPrimitiveValue)values.get(0); addAll(result, props[0], value, origin, important); addAll(result, props[1], value, origin, important); addAll(result, props[2], value, origin, important); return result; } else { checkValueCount(cssName, 1, 3, values.size()); boolean haveBorderStyle = false; boolean haveBorderColor = false; boolean haveBorderWidth = false; for (Iterator i = values.iterator(); i.hasNext(); ) { CSSPrimitiveValue value = (CSSPrimitiveValue)i.next(); checkInheritAllowed(value, false); boolean matched = false; CSSPrimitiveValue borderWidth = convertToBorderWidth(value); if (borderWidth != null) { if (haveBorderWidth) { throw new CSSParseException("A border width cannot be set twice", -1); } haveBorderWidth = true; matched = true; addAll(result, props[0], borderWidth, origin, important); } if (isBorderStyle(value)) { if (haveBorderStyle) { throw new CSSParseException("A border style cannot be set twice", -1); } haveBorderStyle = true; matched = true; addAll(result, props[1], value, origin, important); } CSSPrimitiveValue borderColor = convertToBorderColor(value); if (borderColor != null) { if (haveBorderColor) { throw new CSSParseException("A border color cannot be set twice", -1); } haveBorderColor = true; matched = true; addAll(result, props[2], borderColor, origin, important); } if (! matched) { throw new CSSParseException(value.getCssText() + " is not a border width, style, or color", -1); } } if (! haveBorderWidth) { addAll(result, props[0], new PropertyValue(IdentValue.FS_INITIAL_VALUE), origin, important); } if (! haveBorderStyle) { addAll(result, props[1], new PropertyValue(IdentValue.FS_INITIAL_VALUE), origin, important); } if (! haveBorderColor) { addAll(result, props[2], new PropertyValue(IdentValue.FS_INITIAL_VALUE), origin, important); } return result; } } private boolean isBorderStyle(CSSPrimitiveValue value) { if (value.getPrimitiveType() != CSSPrimitiveValue.CSS_IDENT) { return false; } IdentValue ident = IdentValue.valueOf(value.getCssText()); if (ident == null) { return false; } return PrimitivePropertyBuilders.BORDER_STYLES.get(ident.FS_ID); } private CSSPrimitiveValue convertToBorderWidth(CSSPrimitiveValue value) { int type = value.getPrimitiveType(); if (type != CSSPrimitiveValue.CSS_IDENT && ! isLength(value)) { return null; } if (isLength(value)) { return value; } else { IdentValue ident = IdentValue.valueOf(value.getStringValue()); if (ident == null) { return null; } if (PrimitivePropertyBuilders.BORDER_WIDTHS.get(ident.FS_ID)) { return Conversions.getBorderWidth(ident.toString()); } else { return null; } } } private CSSPrimitiveValue convertToBorderColor(CSSPrimitiveValue value) { int type = value.getPrimitiveType(); if (type != CSSPrimitiveValue.CSS_IDENT && type != CSSPrimitiveValue.CSS_RGBCOLOR) { return null; } if (type == CSSPrimitiveValue.CSS_RGBCOLOR) { return value; } else { FSRGBColor color = Conversions.getColor(value.getStringValue()); if (color != null) { return new PropertyValue(color); } IdentValue ident = IdentValue.valueOf(value.getCssText()); if (ident == null || ident != IdentValue.TRANSPARENT) { return null; } return value; } } } public static class BorderTop extends BorderSidePropertyBuilder { protected CSSName[][] getProperties() { return new CSSName[][] { new CSSName[] { CSSName.BORDER_TOP_WIDTH }, new CSSName[] { CSSName.BORDER_TOP_STYLE }, new CSSName[] { CSSName.BORDER_TOP_COLOR } }; } } public static class BorderRight extends BorderSidePropertyBuilder { protected CSSName[][] getProperties() { return new CSSName[][] { new CSSName[] { CSSName.BORDER_RIGHT_WIDTH }, new CSSName[] { CSSName.BORDER_RIGHT_STYLE }, new CSSName[] { CSSName.BORDER_RIGHT_COLOR } }; } } public static class BorderBottom extends BorderSidePropertyBuilder { protected CSSName[][] getProperties() { return new CSSName[][] { new CSSName[] { CSSName.BORDER_BOTTOM_WIDTH }, new CSSName[] { CSSName.BORDER_BOTTOM_STYLE }, new CSSName[] { CSSName.BORDER_BOTTOM_COLOR } }; } } public static class BorderLeft extends BorderSidePropertyBuilder { protected CSSName[][] getProperties() { return new CSSName[][] { new CSSName[] { CSSName.BORDER_LEFT_WIDTH }, new CSSName[] { CSSName.BORDER_LEFT_STYLE }, new CSSName[] { CSSName.BORDER_LEFT_COLOR } }; } } public static class Border extends BorderSidePropertyBuilder { protected CSSName[][] getProperties() { return new CSSName[][] { new CSSName[] { CSSName.BORDER_TOP_WIDTH, CSSName.BORDER_RIGHT_WIDTH, CSSName.BORDER_BOTTOM_WIDTH, CSSName.BORDER_LEFT_WIDTH }, new CSSName[] { CSSName.BORDER_TOP_STYLE, CSSName.BORDER_RIGHT_STYLE, CSSName.BORDER_BOTTOM_STYLE, CSSName.BORDER_LEFT_STYLE }, new CSSName[] { CSSName.BORDER_TOP_COLOR, CSSName.BORDER_RIGHT_COLOR, CSSName.BORDER_BOTTOM_COLOR, CSSName.BORDER_LEFT_COLOR } }; } } }