/*
Copyright 2006 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.portrayal.simple;
import sim.portrayal.*;
import java.awt.*;
import sim.display.*;
import java.awt.event.*;
/**
A wrapper for other Portrayal2Ds which also draws a big circle around them -- useful for
distinguishing one object from other similar-looking objects. When you create this
CirclePortrayal2D, you will pass in an underlying Portrayal2D which is supposed to draw
the actual object; CirclePortrayal2D will then add on the circle. If the object
will draw itself (it's its own Portrayal2D), you can signify this by passing in null for the
underlying Portrayal2D.
<p>There are certain guidelines you can specify for when the circle is to be drawn. At construction
time you can state that the circle should <i>only</i> be drawn when the object is selected.
Additionally if you call the setCircleShowing(...) function, you can turn off or on circle
drawing entirely for this CirclePortrayal2D.
<p>You may specify a color or paint for the circle (the default is blue).
<p>The circle is drawn centered at the object's [info.draw.x, info.draw.y]
origin and with the radius:
<pre><tt>
x diameter: (int)(scale * info.draw.width + offset);
y diameter: (int)(scale * info.draw.height + offset);
</tt></pre>
<p>... that is, scale is a value which scales when you zoom in, and offset adds
additional fixed pixels. The default is scale = 2.0, offset = 0. This draws the circle
at twice the expected width and height of the object.
<p><b>Note: </b> One oddity of CircledPortrayal2D is due to the fact that the circle is only
drawn if the object is being drawn. While most FieldPortrayals ask objects just off-screen
to draw themselves just to be careful, if an object is significantly off-screen, it may not
be asked to draw itself, and so the circle will not be drawn -- even though part of the circle
could be on-screen at the time! C'est la vie.
*/
public class CircledPortrayal2D extends OvalPortrayal2D
{
public static final double DEFAULT_SCALE = 2.0;
public static final double DEFAULT_OFFSET = 0.0;
public SimplePortrayal2D child;
/** Overrides all drawing. */
boolean showCircle = true;
boolean onlyCircleWhenSelected;
public void setOnlyCircleWhenSelected(boolean val) { onlyCircleWhenSelected = val; }
public boolean getOnlyCircleWhenSelected() { return onlyCircleWhenSelected; }
public boolean isCircleShowing() { return showCircle; }
public void setCircleShowing(boolean val) { showCircle = val; }
/** If child is null, then the underlying model object
is presumed to be a Portrayal2D and will be used. */
public CircledPortrayal2D(SimplePortrayal2D child, double offset, double scale,
Paint paint, boolean onlyCircleWhenSelected)
{
super(paint, scale, false); // the scale will be twice what the user requests
this.offset = offset;
this.child = child;
this.paint = paint;
this.onlyCircleWhenSelected = onlyCircleWhenSelected;
}
/** Draw a circle of radius scale = 2.0, dr = 0, in blue. Draw the circle regardless of selection.
If child is null, then the underlying model object is presumed to be a Portrayal2D and will be used. */
public CircledPortrayal2D(SimplePortrayal2D child)
{
this(child, Color.blue, false);
}
/** Draw a circle of radius or = 2.0, dr = 0.
If child is null, then the underlying model object is presumed to be a Portrayal2D and will be used. */
public CircledPortrayal2D(SimplePortrayal2D child, Paint paint, boolean onlyCircleWhenSelected)
{
this(child, DEFAULT_OFFSET, DEFAULT_SCALE, paint, onlyCircleWhenSelected);
}
public SimplePortrayal2D getChild(Object object)
{
if (child!=null) return child;
else
{
if (!(object instanceof SimplePortrayal2D))
throw new RuntimeException("Object provided to CircledPortrayal2D is not a SimplePortrayal2D: " + object);
return (SimplePortrayal2D) object;
}
}
public void draw(Object object, Graphics2D graphics, DrawInfo2D info)
{
getChild(object).draw(object,graphics,info);
if (showCircle && (info.selected || !onlyCircleWhenSelected))
super.draw(object, graphics, info);
}
public boolean hitObject(Object object, DrawInfo2D range)
{
return getChild(object).hitObject(object,range);
}
public boolean setSelected(LocationWrapper wrapper, boolean selected)
{
return getChild(wrapper.getObject()).setSelected(wrapper, selected);
}
public Inspector getInspector(LocationWrapper wrapper, GUIState state)
{
return getChild(wrapper.getObject()).getInspector(wrapper,state);
}
public String getName(LocationWrapper wrapper)
{
return getChild(wrapper.getObject()).getName(wrapper);
}
public boolean handleMouseEvent(GUIState guistate, Manipulating2D manipulating, LocationWrapper wrapper,
MouseEvent event, DrawInfo2D fieldPortrayalDrawInfo, int type)
{
return getChild(wrapper.getObject()).handleMouseEvent(guistate, manipulating, wrapper, event, fieldPortrayalDrawInfo, type); // let someone else have it
}
}