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 }