/* * ColorMutable.java of project jchart2d, a mutable color. * Copyright (C) 2002 - 2011, Achim Westermann, created on Jun 10, 2011 * * This library 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 library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * If you modify or optimize the code in a useful way please let me know. * Achim.Westermann@gmx.de * * * File : $Source: /cvsroot/jchart2d/jchart2d/src/info/monitorenter/gui/util/ColorMutable.java,v $ * Date : $Date: 2011/01/14 08:36:11 $ * Version: $Revision: 1.3 $ */ package info.monitorenter.gui.util; import java.awt.Color; import java.awt.Graphics; /** * Mutable <code>{@link Color}</code> implementation. * <p> * * The color is wrapped by the logic to fake mutability. As long as the color is * not set setting of values will not have an effect but only be stored until * color is set and then applied to it. * <p> * * * @author <a href="mailto:Achim.Westermann@gmx.de">Achim Westermann </a> * */ public class ColorMutable { /** Transparency value. */ private int m_alpha = -1; /** Blue value. */ private int m_blue = -1; /** The wrapped color. */ private Color m_color; /** Green value. */ private int m_green = -1; /** Red value. */ private int m_red = -1; /** * Sets the color to the graphics context if it is different and returns the * previous one of the graphics context or null if there was no change. * <p> * * @param g * the graphics context to use. * * @return the previously configured color of the graphics context or null if * nothing was done. */ public synchronized Color applyColorIfChange(final Graphics g) { Color result = null; if (this.m_color != null) { final Color gColor = g.getColor(); if (!gColor.equals(this.m_color)) { result = gColor; g.setColor(this.m_color); } } return result; } /** * Sets the color to the graphics context. * <p> * * @param g * the graphics context to use. * * @return the previously configured color of the graphics context or null if * nothing was done. */ public synchronized Color applyColorUnconditionally(final Graphics g) { Color result = null; if (this.m_color != null) { final Color gColor = g.getColor(); result = gColor; g.setColor(this.m_color); } return result; } /** * Asserts that the given value is between 0 and 255. * <p> * * @param value * the value to check. */ private void assertColorValue(final int value) { if (!((value >= 0) && (value <= 255))) { throw new RuntimeException("Argument has to be between 0 and 255. It is " + value); } } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (this.getClass() != obj.getClass()) { return false; } final ColorMutable other = (ColorMutable) obj; if (this.m_alpha != other.m_alpha) { return false; } if (this.m_blue != other.m_blue) { return false; } if (this.m_color == null) { if (other.m_color != null) { return false; } } else if (!this.m_color.equals(other.m_color)) { return false; } if (this.m_green != other.m_green) { return false; } if (this.m_red != other.m_red) { return false; } return true; } /** * Returns the alpha value of the wrapped color. * <p> * * @return the alpha value of the wrapped color. */ public int getAlpha() { return this.m_alpha; } /** * Returns the blue value of the wrapped color. * <p> * * @return the blue value of the wrapped color. */ public int getBlue() { return this.m_blue; } /** * Returns the wrapped color. * <p> * * This will be <code>null</code> if no color has been set before even if * other values have been set before. * <p> * * @return the wrapped color. */ public Color getColor() { return this.m_color; } /** * Returns the green value of the wrapped color. * <p> * * @return the green value of the wrapped color. */ public int getGreen() { return this.m_green; } /** * Returns the red value of the wrapped color. * <p> * * @return the red value of the wrapped color. */ public int getRed() { return this.m_red; } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + this.m_alpha; result = prime * result + this.m_blue; result = prime * result + ((this.m_color == null) ? 0 : this.m_color.hashCode()); result = prime * result + this.m_green; result = prime * result + this.m_red; return result; } /** * Sets the transparency to use for painting. * <p> * This value will be fold into color. If color has not been configured before * it will not have any effect (until a color is set). * <p> * Caution: using a value greater 0 may cost a multiple cpu load! * <p> * * @param alpha * a transparency value between 0 and 255. * * @return the previous transparency used. */ public synchronized int setAlpha(final int alpha) { final int result = this.m_alpha; this.assertColorValue(alpha); this.m_alpha = alpha; if (this.m_color == null) { // nop, the value is cached for the first time use when a color is set. } else { // also directly implant the transparency value to the color. final int orgTransparencyInt = this.m_color.getAlpha(); if (alpha != orgTransparencyInt) { final Color transparentColor = new Color(this.m_color.getRed(), this.m_color.getGreen(), this.m_color.getBlue(), alpha); this.setColor(transparentColor); } } return result; } /** * Sets the blue to use for painting. * <p> * This value will be fold into color. If color has not been configured before * it will not have any effect (until a color is set). * <p> * * @param blue * a blue value between 0 and 255. * * @return the previous blue used. */ public synchronized int setBlue(final int blue) { final int result = this.m_blue; this.assertColorValue(blue); this.m_blue = blue; if (this.m_color == null) { // nop, the value is cached for the first time use when a color is set. } else { // also directly implant the transparency value to the colour. final int orgvalue = this.m_color.getBlue(); if (blue != orgvalue) { final Color newColor = new Color(this.m_color.getRed(), this.m_color.getGreen(), blue, this.m_color.getAlpha()); this.setColor(newColor); } } return result; } /** * Sets the color to use. * <p> * If any other setters have been invoked before (e.g. * <code>{@link #setAlpha(int)}</code>) and the internal color was null those * values will be implanted to the new color before overtaking it. * <p> * * @param color * the new color to use as base for modifications. * * @return the previous color or null if none was set. */ public synchronized Color setColor(final Color color) { final Color result = this.m_color; Color use = color; if (this.m_color == null) { int red = color.getRed(); int green = color.getGreen(); int blue = color.getBlue(); int alpha = color.getAlpha(); boolean change = false; if (this.m_red != -1) { red = this.m_red; change = true; } if (this.m_green != -1) { green = this.m_green; change = true; } if (this.m_blue != -1) { blue = this.m_blue; change = true; } if (this.m_alpha != -1) { alpha = this.m_alpha; change = true; } if (change) { use = new Color(red, green, blue, alpha); } } this.m_color = use; return result; } /** * Sets the green to use for painting. * <p> * This value will be fold into color. If color has not been configured before * it will not have any effect (until a color is set). * <p> * * @param green * a green value between 0 and 255. * * @return the previous green used. */ public synchronized int setGreen(final int green) { final int result = this.m_green; this.assertColorValue(green); this.m_green = green; if (this.m_color == null) { // nop, the value is cached for the first time use when a color is set. } else { // also directly implant the transparency value to the colour. final int orgvalue = this.m_color.getGreen(); if (green != orgvalue) { final Color newColor = new Color(this.m_color.getRed(), green, this.m_color.getBlue(), this.m_color.getAlpha()); this.setColor(newColor); } } return result; } /** * Sets the red to use for painting. * <p> * This value will be fold into color. If color has not been configured before * it will not have any effect (until a color is set). * <p> * * @param red * a red value between 0 and 255. * * @return the previous red used. */ public synchronized int setRed(final int red) { final int result = this.m_red; this.assertColorValue(red); this.m_red = red; if (this.m_color == null) { // nop, the value is cached for the first time use when a color is set. } else { // also directly implant the new value to the color. final int orgvalue = this.m_color.getRed(); if (red != orgvalue) { final Color newColor = new Color(this.m_red, this.m_color.getGreen(), this.m_color .getBlue(), this.m_color.getAlpha()); this.setColor(newColor); } } return result; } }