/*
* Licensed Materials - Property of Rogue Wave Software, Inc.
* © Copyright Rogue Wave Software, Inc. 2014, 2017
* © Copyright IBM Corp. 2009, 2014
* © Copyright ILOG 1996, 2009
* All Rights Reserved.
*
* Note to U.S. Government Users Restricted Rights:
* The Software and Documentation were developed at private expense and
* are "Commercial Items" as that term is defined at 48 CFR 2.101,
* consisting of "Commercial Computer Software" and
* "Commercial Computer Software Documentation", as such terms are
* used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
* as applicable.
*/
import java.awt.Color;
import java.awt.Graphics;
import java.io.IOException;
import ilog.views.IlvGraphic;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;
import ilog.views.IlvTransformer;
import ilog.views.graphic.IlvArcUtil;
import ilog.views.io.IlvInputStream;
import ilog.views.io.IlvOutputStream;
import ilog.views.io.IlvReadFileException;
/**
* A shadow ellipse object. A graphic object defined by two
* ellipses: The main ellipse and a second ellipse of the same
* size underneath the first one that represents a shadow.
*
* The purpose of this sample is to illustrate how to implement your own
* graphic objects.
*/
public class ShadowEllipse
extends IlvGraphic
{
/**
* The definition rectangle of the ellipse.
* This rectangle is the bounding rectangle of the
* graphic object.
*/
protected final IlvRect drawrect = new IlvRect();
/**
* The color of the ellipse.
*/
private Color color = Color.blue;
/**
* The color of the shadow.
*/
private Color shadowColor = Color.black;
/**
* The thickness of the shadow.
*/
private int thickness = 5;
/**
* Creates a new shadow ellipse.
* @param rect the bounding rectangle of the shadow ellipse.
*/
public ShadowEllipse(IlvRect rect)
{
super();
// Stores the bounding rectangle of the object.
drawrect.reshape(rect.x, rect.y, rect.width, rect.height);
}
/**
* Creates an ellipse by copying another one.
* @param source the object to copy.
*/
public ShadowEllipse(ShadowEllipse source)
{
// We first call the super class constructor
// that will copy the informations of the super class.
super(source);
// Copies the bounding rectangle.
drawrect.reshape(source.drawrect.x, source.drawrect.y,
source.drawrect.width, source.drawrect.height);
// Copies the color and the color of the shadow.
setColor(source.getColor());
setShadowColor(source.getShadowColor());
// Copies the thickness
setThickness(source.getThickness());
}
/**
* Reads the object from an IlvInputStream
* @param stream the input stream.
* @exception IlvReadFileException an error occurs when reading.
*/
public ShadowEllipse(IlvInputStream stream) throws IlvReadFileException
{
// Calls the super class constructor that reads the
// the informations for the super class in the file.
super(stream);
// Reads the color.
setColor(stream.readColor("color"));
// Reads the shadow color.
setShadowColor(stream.readColor("shadowColor"));
// Reads the thickness
setThickness(stream.readInt("thickness"));
// reads the definition rectangle.
IlvRect rect = stream.readRect("rectangle");
drawrect.reshape(rect.x, rect.y, rect.width, rect.height);
}
/**
* Copies the objects.
*/
Override
public IlvGraphic copy()
{
// We simply call the copy constructor that is defined above.
return new ShadowEllipse(this);
}
/**
* Draws the object.
* We overwrite the draw method to define the way the object will appear.
* @param dst The AWT object that will perform the
* drawing operations.
* @param t This parameter is the transformer used to draw the object.
* This parameter may be a translation, a zoom or a rotation.
* When the graphic object is drawn in a view (IlvManagerView),
* this transformer is the transformer of the view.
*/
Override
public void draw(Graphics dst, IlvTransformer t)
{
// We first copy the rectangle that defines the bounding
// rectangle of the object because we do not want to modify it.
IlvRect r = new IlvRect(drawrect);
// To compute the bounding rectangle of the object in
// the view coordinate system, we apply the transformer 't'
// to the definition rectangle.
// The transformer may define a zoom, a translation or a rotation.
// We are using apllyFloor so the resulting rectangle
// is correctly projected for drawing in the view.
// The object's coordinate system is defined by 'double' values
// and we need 'int' values to be able to draw. applyFloor will
// apply the transformation to 'r' ans then calls Math.floor to
// translate 'double' values to 'int' values.
if (t != null)
t.applyFloor(r);
else
r.floor();
// The variable 'r' now contains the bounding rectangle
// of the object in the view's coordinate system and we will
// draw in this rectangle. In this rectangle, we will draw
// two ellispes. We first draw the shadow ellipse on the
// bottom right corner of the definition rectangle, then the main
// ellipse on the top-left corner. Each ellipse will be of size
// (r.width-thickness, r.height-thickness).
int thick = thickness;
// Computes a correct value for thickness.
// Since we want the size of the ellipses
// to be (r.width-thickness, r.height-thickness), we
// must check that the thickness is not too big.
if ((r.width <= thick) || (r.height <= thick))
thick = (int)Math.min(r.width, r.height);
// Sets the size of the ellipses.
r.width -= thick;
r.height -= thick;
// 'r' now contains the bounding area of the main ellipse.
// Computes a rectangle to draw the shadow.
// We copy the variable 'r', we will need it for the
// second ellipse.
IlvRect shadowRect = new IlvRect(r);
shadowRect.translate(thick, thick);
// Draws the shadow ellipse
dst.setColor(getShadowColor());
dst.fillArc((int)shadowRect.x,
(int)shadowRect.y,
(int)shadowRect.width,
(int)shadowRect.height,
0, 360);
// Draws the main ellipse.
dst.setColor(getColor());
dst.fillArc((int)r.x,
(int)r.y,
(int)r.width,
(int)r.height,
0, 360);
}
/**
* Tests if a point lies within the shape of the object.
* This method will be called when you click on the object.
* @param p The point where you in the object's coordinate system.
* @param tp Same point as 'p' but transformed by transformer 't'
* @param t The transformer used to draw the object.
*/
Override
public boolean contains(IlvPoint p, IlvPoint tp,
IlvTransformer t)
{
// We want to allow the use to click on the main ellipse
// but not on the shadow ellipse.
// This method will return true when the clicked point is
// on the main ellipse.
// We first compute the bounding rectangle of the main
// ellipse in the view coordinate system, just like in the
// method draw.
IlvRect r = new IlvRect(drawrect);
if (t != null)
t.apply(r);
int thick = thickness;
if ((r.width <= thick) || (r.height <= thick))
thick = (int)Math.min(r.width, r.height);
r.width -= thick;
r.height -= thick;
// Then we call PointInFilledArc that will return true
// if the point is in the ellipse. 'r' and 'tp' are both
// in the view coordinate system.
return IlvArcUtil.PointInFilledArc(tp, r, 0, 360);
}
/**
* Computes the bounding rectangle of the graphic
* object when drawn with the specified transformer.
*/
Override
public IlvRect boundingBox(IlvTransformer t)
{
// We first copy the definition rectangle
// because we do not want to modify it.
IlvRect rect = new IlvRect(drawrect);
// Apply the transformer on the rectangle to
// translate to the correct coordinate system.
if (t != null) t.apply(rect);
return rect;
}
/**
* Applies a transformation to the shape of the object.
* @param t The transformer to apply
*/
Override
public void applyTransform(IlvTransformer t)
{
// This method is called by method such as IlvGraphic.move
// IlvGraphic.rotate or IlvGraphic.scale to modify the
// shape of the object. For example, when this method
// is called from IlvGraphic.move, the parameter 't' is the
// corresponding translation.
// We simply need to apply the transformer to
// the definition rectangle of the object.
t.apply(drawrect);
}
/**
* Changes the thickness of the shadow ellipse
* @param thickness the new thickness
*/
public void setThickness(int thickness)
{
this.thickness = thickness;
}
/**
* Returns the thickness of the shadow ellipse
* @return the thickness of the object.
*/
public int getThickness()
{
return thickness;
}
/**
* Changes the color of the ellipse.
* @param color the new color.
*/
public void setColor(Color color)
{
this.color = color;
}
/**
* Returns the color of the shadow ellipse
* @return the color of the object.
*/
public Color getColor()
{
return color;
}
/**
* Changes the color of the shadow
* @param color the new color
*/
public void setShadowColor(Color color)
{
this.shadowColor = color;
}
/**
* Returns the color of the shadow
* @return the color of the shadow
*/
public Color getShadowColor()
{
return shadowColor;
}
/**
* Writes the object to an output stream.
*/
Override
public void write(IlvOutputStream stream)
throws IOException
{
// Calls the super class method that will write
// the fields specific to the super class.
super.write(stream);
// Writes the colors.
stream.write("color", getColor());
stream.write("shadowColor", getShadowColor());
// Writes the thickness.
stream.write("thickness", getThickness());
// Writes the definition rectangle.
stream.write("rectangle", drawrect);
}
}