/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.metamodel.data; import java.util.Map; import java.util.WeakHashMap; import org.apache.metamodel.data.Style.Color; import org.apache.metamodel.data.Style.SizeUnit; import org.apache.metamodel.data.Style.TextAlignment; import org.apache.metamodel.util.EqualsBuilder; /** * Builder class for {@link Style} and related objects, like {@link Color}. */ public final class StyleBuilder { private static final Map<String, Color> _colorCache = new WeakHashMap<String, Color>(); private boolean _bold; private boolean _italic; private boolean _underline; private Integer _fontSize; private TextAlignment _alignment; private Color _backgroundColor; private Color _foregroundColor; private SizeUnit _fontSizeUnit; private final Color _defaultForegroundColor; private final Color _defaultBackgroundColor; /** * Constructs a new {@link StyleBuilder} with the default foreground and * background colors. */ public StyleBuilder() { this(createColor((short) 0, (short) 0, (short) 0), createColor( (short) 255, (short) 255, (short) 255)); } /** * Constructs a new {@link StyleBuilder} with a specified default foreground * and background colors. These colors will be disregarded, if posted to the * foreground and background methods. * * @param defaultForegroundColor * @param defaultBackgroundColor */ public StyleBuilder(Color defaultForegroundColor, Color defaultBackgroundColor) { _defaultForegroundColor = defaultForegroundColor; _defaultBackgroundColor = defaultBackgroundColor; } /** * Resets the state of the built style, which will conceptually match it * with {@link Style#NO_STYLE}. */ public void reset() { _bold = false; _italic = false; _underline = false; _fontSize = null; _alignment = null; _backgroundColor = null; _foregroundColor = null; _fontSizeUnit = null; } /** * Creates a {@link Style} object based on the build characteristics. * * @return a {@link Style} object based on the build characteristics. */ public Style create() { StyleImpl style = new StyleImpl(_bold, _italic, _underline, _fontSize, _fontSizeUnit, _alignment, _backgroundColor, _foregroundColor); if (Style.NO_STYLE.equals(style)) { return Style.NO_STYLE; } return style; } /** * Sets the font weight to bold * * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder bold() { _bold = true; return this; } /** * Sets the font style to italic * * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder italic() { _italic = true; return this; } /** * Sets the text decoration to underlined * * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder underline() { _underline = true; return this; } /** * Creates a Color based on a 6-letter RGB hex color code string, eg. * "000000" for black and "FFFFFF" for white. * * @param rgbColorCode * a 6-letter RGB hex color code string * @return a color representing this color code */ public static Color createColor(String rgbColorCode) { assert rgbColorCode.length() == 6; String redParth = rgbColorCode.substring(0, 2); String greenParth = rgbColorCode.substring(2, 4); String blueParth = rgbColorCode.substring(4, 6); return createColor(Integer.parseInt(redParth, 16), Integer.parseInt(greenParth, 16), Integer.parseInt(blueParth, 16)); } /** * Creates a color based on 3 RGB components, represented as ints * * @param r * @param g * @param b * @return a color representing the RGB code */ public static Color createColor(int r, int g, int b) { return createColor(toRgbComponent(r), toRgbComponent(g), toRgbComponent(b)); } /** * Creates a color based on 3 RGB components, represented as shorts * * @param r * @param g * @param b * @return a color representing the RGB code */ public static Color createColor(short r, short g, short b) { String cacheId = r + "," + g + "," + b; Color color = _colorCache.get(cacheId); if (color == null) { color = new ColorImpl(r, g, b); _colorCache.put(cacheId, color); } return color; } private static short toRgbComponent(int r) { if (r < 0) { // if eg. a byte was passed as a RGB component r = (256 + r); } if (r > 255) { throw new IllegalArgumentException( "RGB component cannot be higher than 255"); } return (short) r; } /** * Sets the foreground (text) color of the style * * @param rgbColorCode * a 6-letter hex RGB color code, such as FF0000 (red). * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder foreground(String rgbColorCode) { return foreground(createColor(rgbColorCode)); } /** * Sets the foreground (text) color of the style * * @param rgb * a triplet array of shorts * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder foreground(short[] rgb) { assert rgb.length == 3; return foreground(createColor(rgb[0], rgb[1], rgb[2])); } /** * Sets the foreground (text) color of the style * * @param r * red amount (0-255) * @param g * green amount (0-255) * @param b * blue amount (0-255) * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder foreground(int r, int g, int b) { return foreground(createColor(r, g, b)); } /** * Sets the foreground (text) color of the style * * @param color * the color to use * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder foreground(Color color) { if (EqualsBuilder.equals(_defaultForegroundColor, color)) { _foregroundColor = null; } else { _foregroundColor = color; } return this; } /** * Sets the background (fill) color of the style * * @param rgbColorCode * a 6-letter hex RGB color code, such as FF0000 (red). * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder background(String rgbColorCode) { return background(createColor(rgbColorCode)); } /** * Sets the background (fill) color of the style * * @param rgb * a triplet array of shorts * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder background(short[] rgb) { assert rgb.length == 3; return background(createColor(rgb[0], rgb[1], rgb[2])); } /** * Sets the background (fill) color of the style * * @param r * red amount (0-255) * @param g * green amount (0-255) * @param b * blue amount (0-255) * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder background(int r, int g, int b) { return background(createColor(r, g, b)); } /** * Sets the background (fill) color of the style * * @param color * the color to use * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder background(Color color) { if (EqualsBuilder.equals(_defaultBackgroundColor, color)) { _backgroundColor = null; } else { _backgroundColor = color; } return this; } /** * Sets the font size of the style * * @param fontSize * the font size * @param sizeUnit * the font size unit * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder fontSize(int fontSize, SizeUnit sizeUnit) { _fontSize = fontSize; _fontSizeUnit = sizeUnit; return this; } /** * Sets the text alignment to center * * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder centerAligned() { _alignment = TextAlignment.CENTER; return this; } /** * Sets the text alignment to left * * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder leftAligned() { _alignment = TextAlignment.LEFT; return this; } /** * Sets the text alignment to right * * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder rightAligned() { _alignment = TextAlignment.RIGHT; return this; } /** * Sets the text alignment to justify * * @return the {@link StyleBuilder} self (for cascading method calls) */ public StyleBuilder justifyAligned() { _alignment = TextAlignment.JUSTIFY; return this; } }