/* * File : Gradient.java * Created : 06-mar-2002 15:11 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2005 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 General Public License for more details (see the LICENSE file). */ package edu.xtec.jclic.misc; import edu.xtec.util.Domable; import edu.xtec.util.JDomUtility; import java.awt.*; import java.awt.geom.Rectangle2D; /** * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.08.28 */ public class Gradient extends Object implements Cloneable, Domable{ protected Color c1, c2; protected int angle=0; protected GradientPaint gp=null; protected Rectangle2D lastRect=null; protected boolean transparency=false; protected int cycles=1; /** Creates new Gradient */ public Gradient(Color c1, Color c2, int angle, int cycles) { setColors(c1, c2); setAngle(angle); setCycles(cycles); } public Gradient(){ this(Color.black, Color.white, 0, 1); } @Override public Object clone(){ return new Gradient(c1, c2, angle, cycles); } public boolean hasTransparency(){ return transparency; } public void setCycles(int cycles){ this.cycles=Math.max(1, cycles); clear(); } public int getCycles(){ return cycles; } public void setAngle(int angle){ this.angle=angle % 360; clear(); } public int getAngle(){ return angle; } public Color[] getColors(){ return new Color[] {c1, c2}; } public void setColors(Color c1, Color c2){ this.c1=c1; this.c2=c2; transparency=(c1.getAlpha()!=255 || c2.getAlpha()!=255); clear(); } public void clear(){ gp=null; lastRect=null; } public static final String ELEMENT_NAME="gradient"; public static final String C1="source", C2="dest", ANGLE="angle", CYCLES="cycles"; public org.jdom.Element getJDomElement(){ org.jdom.Element e=new org.jdom.Element(ELEMENT_NAME); e.setAttribute(C1, JDomUtility.colorToString(c1)); e.setAttribute(C2, JDomUtility.colorToString(c2)); e.setAttribute(ANGLE, Integer.toString(angle)); if(cycles>1) e.setAttribute(CYCLES, Integer.toString(cycles)); return e; } public static Gradient getGradient(org.jdom.Element e) throws Exception { Gradient g=new Gradient(); g.setProperties(e, null); return g; } public void setProperties(org.jdom.Element e, Object aux) throws Exception { JDomUtility.checkName(e, ELEMENT_NAME); c1=JDomUtility.getColorAttr(e, C1, c1); c2=JDomUtility.getColorAttr(e, C2, c2); setAngle(JDomUtility.getIntAttr(e, ANGLE, angle)); setCycles(JDomUtility.getIntAttr(e, CYCLES, cycles)); } public void paint(Graphics2D g2, Shape shape){ Paint p=g2.getPaint(); g2.setPaint(getGradient(shape)); g2.fill(shape); g2.setPaint(p); } public GradientPaint getGradient(Shape shape){ Rectangle2D r=shape.getBounds2D(); if(gp==null || lastRect==null || !lastRect.equals(r)){ lastRect=r; double rw=r.getWidth(); double rh=r.getHeight(); double radius=rw/2; // angle in radians double alpha=(Math.PI*angle)/180.0; switch(angle){ case 0: case 180: break; case 90: case 270: radius=rh/2; break; default: // diagonal of r radius=Math.sqrt(rw*rw+rh*rh)/2; // diagonal angle double gamma=toFirstQuadrant(Math.atan2(rh, rw)); // diagonal vs. alpha double beta=Math.abs(toFirstQuadrant(alpha)-gamma); // projected radius radius*=Math.cos(beta); } float cx=(float)(r.getX()+rw/2); float cy=(float)(r.getY()+rh/2); float px=(float)(radius*Math.cos(alpha)); float py=(float)(radius*Math.sin(alpha)); gp=new GradientPaint(cx+px, cy-py, c1, cx+px-2*px/cycles, cy-py+2*py/cycles, c2, cycles>1); } return gp; } protected double toFirstQuadrant(double a){ if(a>Math.PI) a=2*Math.PI-a; if(a>Math.PI / 2) a=Math.PI - a; return a; } @Override public boolean equals(Object obj){ boolean result=false; if(obj!=null && obj instanceof Gradient){ Gradient g=(Gradient)obj; result= c1.equals(g.c1) && c2.equals(g.c2) && cycles==g.cycles && angle==g.angle; } return result; } }