001 /*--------------------------------------------------------------------------+ 002 $Id: CSSDeclarationBlock.java 26283 2010-02-18 11:18:57Z juergens $ 003 | | 004 | Copyright 2005-2010 Technische Universitaet Muenchen | 005 | | 006 | Licensed under the Apache License, Version 2.0 (the "License"); | 007 | you may not use this file except in compliance with the License. | 008 | You may obtain a copy of the License at | 009 | | 010 | http://www.apache.org/licenses/LICENSE-2.0 | 011 | | 012 | Unless required by applicable law or agreed to in writing, software | 013 | distributed under the License is distributed on an "AS IS" BASIS, | 014 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 015 | See the License for the specific language governing permissions and | 016 | limitations under the License. | 017 +--------------------------------------------------------------------------*/ 018 package edu.tum.cs.commons.html; 019 020 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_BOTTOM_COLOR; 021 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_BOTTOM_STYLE; 022 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_BOTTOM_WIDTH; 023 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_LEFT_COLOR; 024 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_LEFT_STYLE; 025 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_LEFT_WIDTH; 026 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_RIGHT_COLOR; 027 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_RIGHT_STYLE; 028 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_RIGHT_WIDTH; 029 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_TOP_COLOR; 030 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_TOP_STYLE; 031 import static edu.tum.cs.commons.html.ECSSProperty.BORDER_TOP_WIDTH; 032 import static edu.tum.cs.commons.html.ECSSProperty.MARGIN_BOTTOM; 033 import static edu.tum.cs.commons.html.ECSSProperty.MARGIN_LEFT; 034 import static edu.tum.cs.commons.html.ECSSProperty.MARGIN_RIGHT; 035 import static edu.tum.cs.commons.html.ECSSProperty.MARGIN_TOP; 036 import static edu.tum.cs.commons.html.ECSSProperty.PADDING_BOTTOM; 037 import static edu.tum.cs.commons.html.ECSSProperty.PADDING_LEFT; 038 import static edu.tum.cs.commons.html.ECSSProperty.PADDING_RIGHT; 039 import static edu.tum.cs.commons.html.ECSSProperty.PADDING_TOP; 040 041 import java.io.PrintStream; 042 import java.util.ArrayList; 043 import java.util.EnumMap; 044 import java.util.HashMap; 045 import java.util.List; 046 import java.util.Map; 047 048 /** 049 * This class describes a set of CSS declarations (property value pairs). 050 * Additionally it allows for simple multiple inheritance, where the properties 051 * of all inherited blocks are merged (including the block itself). The classes 052 * coming later in the inheritance list and the block itself will overwrite any 053 * properties defined multiple times. 054 * 055 * @author hummelb 056 * @author $Author: juergens $ 057 * @version $Rev: 26283 $ 058 * @levd.rating GREEN Hash: 539B6065D69734F5F5B5E2B3B7D3461A 059 */ 060 public class CSSDeclarationBlock { 061 062 /** The properties and the values */ 063 private final Map<ECSSProperty, String> properties = new EnumMap<ECSSProperty, String>( 064 ECSSProperty.class); 065 066 /** The list of blocks we inherit from. */ 067 private final List<CSSDeclarationBlock> inheritsFrom = new ArrayList<CSSDeclarationBlock>(); 068 069 /** 070 * Create new declaration block. 071 * 072 * @param values 073 * the property value pairs to add (so the number must be even). 074 */ 075 public CSSDeclarationBlock(Object... values) { 076 if (values.length % 2 != 0) { 077 throw new IllegalArgumentException( 078 "Expected even number of arguments"); 079 } 080 for (int i = 0; i < values.length; i += 2) { 081 if (!(values[i] instanceof ECSSProperty)) { 082 throw new IllegalArgumentException( 083 "Expected CSS property as parameter " + i 084 + " instead of " + values[i].getClass()); 085 } 086 if (!(values[i + 1] instanceof String)) { 087 throw new IllegalArgumentException( 088 "Expected property value (String) as parameter " 089 + (i + 1) + " instead of " 090 + values[i + 1].getClass()); 091 } 092 093 setProperty((ECSSProperty) values[i], (String) values[i + 1]); 094 } 095 } 096 097 /** 098 * Create new declaration block. 099 * 100 * @param superBlock 101 * the block to inherit from. 102 * @param values 103 * the property value pairs to add (so the number must be even). 104 */ 105 public CSSDeclarationBlock(CSSDeclarationBlock superBlock, Object... values) { 106 this(values); 107 inheritFrom(superBlock); 108 } 109 110 /** 111 * Adds a property to this block. Is a property with this name exists, it 112 * will be overwritten. 113 * 114 * @return this 115 */ 116 public CSSDeclarationBlock setProperty(ECSSProperty property, String value) { 117 properties.put(property, value); 118 return this; 119 } 120 121 /** 122 * Sets all given properties to the same value. 123 * 124 * @return this 125 */ 126 private CSSDeclarationBlock setProperties(String value, 127 ECSSProperty... properties) { 128 for (ECSSProperty p : properties) { 129 setProperty(p, value); 130 } 131 return this; 132 } 133 134 /** 135 * Sets the margin to the given value. 136 * 137 * @return this 138 */ 139 public CSSDeclarationBlock setMargin(String value) { 140 return setProperties(value, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, 141 MARGIN_TOP); 142 } 143 144 /** 145 * Sets the padding to the given value. 146 * 147 * @return this 148 */ 149 public CSSDeclarationBlock setPadding(String value) { 150 return setProperties(value, PADDING_BOTTOM, PADDING_LEFT, 151 PADDING_RIGHT, PADDING_TOP); 152 } 153 154 /** 155 * Sets the border to the given values. 156 * 157 * @return this 158 */ 159 public CSSDeclarationBlock setBorder(String width, String style, 160 String color) { 161 setBorderWidth(width); 162 setBorderStyle(style); 163 setBorderColor(color); 164 return this; 165 } 166 167 /** 168 * Sets the border width to the given value. 169 * 170 * @return this 171 */ 172 public CSSDeclarationBlock setBorderWidth(String width) { 173 return setProperties(width, BORDER_BOTTOM_WIDTH, BORDER_LEFT_WIDTH, 174 BORDER_RIGHT_WIDTH, BORDER_TOP_WIDTH); 175 } 176 177 /** 178 * Sets the border style to the given value. 179 * 180 * @return this 181 */ 182 public CSSDeclarationBlock setBorderStyle(String style) { 183 return setProperties(style, BORDER_BOTTOM_STYLE, BORDER_LEFT_STYLE, 184 BORDER_RIGHT_STYLE, BORDER_TOP_STYLE); 185 } 186 187 /** 188 * Sets the border color to the given value. 189 * 190 * @return this 191 */ 192 public CSSDeclarationBlock setBorderColor(String color) { 193 return setProperties(color, BORDER_BOTTOM_COLOR, BORDER_LEFT_COLOR, 194 BORDER_RIGHT_COLOR, BORDER_TOP_COLOR); 195 } 196 197 /** 198 * Removes the property from this block (whether it exists or not). 199 * 200 * @return this 201 */ 202 public CSSDeclarationBlock removeProperty(String property) { 203 properties.remove(property); 204 return this; 205 } 206 207 /** 208 * Returns the value of the property (or null if it is not defined for this 209 * block). 210 */ 211 public String getProperty(String property) { 212 return properties.get(property); 213 } 214 215 /** 216 * Adds another block to inherit from. 217 * 218 * @return this 219 */ 220 public CSSDeclarationBlock inheritFrom(CSSDeclarationBlock css) { 221 inheritsFrom.add(css); 222 return this; 223 } 224 225 /** 226 * Adds all properties (including those inherited) to the given map. Calling 227 * this with an empty map will result in a map containing the actual 228 * properties of this block. 229 */ 230 private void fillFullPropertyMap(Map<ECSSProperty, String> map) { 231 for (CSSDeclarationBlock block : inheritsFrom) { 232 block.fillFullPropertyMap(map); 233 } 234 map.putAll(properties); 235 } 236 237 /** 238 * Writes the full (including inherited) properties into the given stream 239 * using the format for CSS files, i.e. one property in each line followed 240 * by a colon, the value, and a semicolon. 241 */ 242 public void writeOut(PrintStream ps, String indent) { 243 Map<ECSSProperty, String> result = new HashMap<ECSSProperty, String>(); 244 fillFullPropertyMap(result); 245 246 for (ECSSProperty property : result.keySet()) { 247 ps.println(indent + property.getName() + ": " 248 + result.get(property) + ";"); 249 } 250 251 } 252 253 /** 254 * Returns the full (including inherited) properties as a single line string 255 * using the format suitable for inline styles as used in HTML. 256 */ 257 public String toInlineStyle() { 258 StringBuilder sb = new StringBuilder(); 259 Map<ECSSProperty, String> result = new HashMap<ECSSProperty, String>(); 260 fillFullPropertyMap(result); 261 262 for (ECSSProperty property : result.keySet()) { 263 sb.append(property.getName() + ": " + result.get(property) + "; "); 264 } 265 return sb.toString(); 266 } 267 }