The procedure for creating a new graphic
object class comprises stages for defining methods to deal with
geometric properties and drawing and stages for making the object
persistent.
The stages are as follows:
This example creates the class
ShadowEllipse
. The complete source code of the
ShadowEllipse
example is available at <installdir> /jviews-framework810/codefragments/shadow-ellipse/src/ShadowEllipse.java.
Stage 1 - Creating the class
To create the class:
-
Create a file named
ShadowEllipse.java
that defines the new class and the necessary overloaded methods. Not every method needs to be overloaded. -
Add the following statements at the beginning of your file:
import ilog.views.*; import ilog.views.io.*; import ilog.views.graphic.*; import java.awt.*; import java.io.*;
These statements allow you to use the basic, the input/output, and the graphic packages of the Rogue Wave JViews library. -
Define a class that inherits from the IlvGraphic class.This class has two colors: one for the ellipse and one for the shadow. It also defines the thickness of the shadow.
-
Define the bounding rectangle of the object.For this, you add a member variable named
drawrect
of typeIlvRect
.import ilog.views.*; import ilog.views.io.*; import ilog.views.graphic.*; import java.awt.*; import java.io.*; /** * 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. */ 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;
Stage 2 - Defining the Constructors
-
Define a constructor to create a new shadow ellipse. These constructors simply set the value of the definition rectangle or create a new
ShadowEllipse
from an existingShadowEllipse
instance:/** * 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) { // First call the superclass constructor // that will copy the information of the superclass. 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()); }
Stage 3 - Overriding the draw Method
-
Draw the object by calling some of the primitive methods contained in the AWT
Graphics
class./** * Draws the object. * Override 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. */ public void draw(Graphics dst, IlvTransformer t) { // First copy the rectangle that defines the bounding // rectangle of the object so that it is not modified. IlvRect r = new IlvRect(drawrect); // To compute the bounding rectangle of the object in // the view coordinate system, apply the transformer ’t’ // to the definition rectangle. // The transformer may define a zoom, a translation or a rotation. // applyFlooris used so the resulting rectangle // is correctly projected for drawing in the view. // The object’s coordinate system is defined by ’float’ values // Need ’int’ values to be able to draw. applyFloor will // apply the transformation to ’r’ and then call Math.floor to // translate ’float’ 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 ready to // draw in this rectangle. In this rectangle, two ellipses // are drawn: first 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 the size of the ellipses should // be (r.width-thickness, r.height-thickness), need to // 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. // Copy the variable ’r’, needed 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); }
The method
draw
fills the two ellipses. The bounding rectangle,
drawrect
, actually covers both ellipses.
Note
The AWT methods, such as
fillArc
, require all coordinates to be integers. In Rogue Wave JViews,
however, the bounding box of a graphic object is defined by
float
values. To convert coordinates from
float
to
int
, use the
applyFloor
and
floor
methods of the
IlvTransformer
class. You must use the same technique to ensure that the other
objects comply with the library.
Stage 4 - Overriding the boundingBox method
-
Define the method
boundingBox
to transform the bounding box. It creates a copy of the rectangledrawrect
even if the transformer isnull
. This is so the returned rectangle can be modified by Rogue Wave JViews./** * Computes the bounding rectangle of the graphic * object when drawn with the specified transformer. */ public IlvRect boundingBox(IlvTransformer t) { // First copy the definition rectangle // so that it is not modified. 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; }
Stage 5 - Overriding the applyTransform method
-
Override the
applyTransform
method to apply a transformation to the shape of the ShadowEllipse rectangle.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. // Simply need to apply the transformer to // the definition rectangle of the object. t.apply(drawrect); }
Stage 6 - Overriding the copy method
-
Override the copy method to call the
ShadowEllipse
copy constructor to make a new instance./** * Copies the object. */ public IlvGraphic copy() { // Simply call the copy constructor that is defined above. return new ShadowEllipse(this); }
Stage 7 - Defining accessors
-
Add public accessors to the graphic object. These accessors deal with thickness and color. They appear in bold type in the following code example.
/** * 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; }