/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © 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); } }