/*
* @(#)DrawingKey.java
*
* Last Modified: 9/15/01
*/
import java.util.*;
import java.lang.*;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
/**
* DrawingKey
implements DrawableKey
for it is a specific type that
* draws Object keys. Its constructor needs the Object key it will draw.
*
* @see DrawableKey
*
* @author Corey Sanders
* @version 2.1 9/15/01
*/
public class DrawingKey extends Object implements DrawableKey {
/**
* Previous Drawn Shape
*/
private Shape currentShape = null;
/**
* Previous Drawn Shape
*/
private Shape originalShape = null;
/**
* Current Transform
*/
private AffineTransform currentTransform = null;
/**
* The current drawing settings of the node.
*/
private KeySettings currentSettings = null;
/**
* The previous drawing settings of the node.
*/
private KeySettings previousSettings = null;
/**
* The count for how many total saves the current Node has been called
* (to save the NodeSettings).
*/
private int countSaves = 0;
/**
* The Object key used to draw this key, using the method toString
.
*/
private Object key;
/**
* Constructor that instantiates the DrawingIntegerKey
using the given Object k.
* @param k the Object
drawn to the screen.
*/
public DrawingKey(Object k) {
setKey(k);
}
/**
* Returns a copy of this AffineTransform
object.
* @return an Object
that is a copy of this
* AffineTransform
object.
*/
public Object clone() {
try {
return super.clone();
}
catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
/**
* Sets the Object
key of the DrawableKey
.
*
* @param k Object
key for use in drawing the key.
*/
public void setKey(Object k) {
key = k;
}
/**
* Gets the Object
key of the DrawableKey
.
*
* @return Object
key used for drawing the key.
*/
public Object getKey() {
return key;
}
/**
* Sets the KeySettings
of the DrawableKey
.
* These settings are used for drawing the key in a given Graphics2D.
*
* @param s KeySettings
for use in drawing the key.
*/
public void setSettings(KeySettings s) {
KeySettings newSettings = (KeySettings)s.clone();
// No previous saved settings
if (!isSettingsSaved()) {
// null previous settings
previousSettings = null;
currentSettings = newSettings;
// Reset saves
countSaves = 0;
}
else {
// Set previous settings as s, because currently the settings are saved.
previousSettings = newSettings;
}
}
/**
* Sets the KeySettings
of the DrawableKey
.
* These settings are used for drawing the key in a given Graphics2D.
*
* @param s KeySettings
for use in drawing the key.
*/
public void setKeySettings(KeySettings s) {
currentSettings = (KeySettings)s.clone();
}
/**
* Gets the KeySettings
of the key.
*
* @return KeySettings
for use in drawing the key.
*/
public KeySettings getSettings() {
return currentSettings;
}
/**
* Returns true if the KeySettings are currently saved for the DrawingTree.
*
* @return true if the settings are saved.
*/
public boolean isSettingsSaved() {
// Saved if previousSettings is not null.
return (previousSettings != null);
}
/**
* Saves the settings for the tree, incrementing the count of saves by one and setting the
* previous settings accordingly.
*/
public void saveSettings() {
countSaves++;
if (previousSettings == null) {
previousSettings = (KeySettings)currentSettings.clone();
}
}
/**
* Restores the settings for the tree, decrementing the count of saves by one.
* If the settings have been restored completely, than the KeySettings for the tree
* are set accordingly.
*/
public void restoreSettings() {
countSaves--;
if (countSaves <= 0) { // Completely Restored
currentSettings = previousSettings;
previousSettings = null;
countSaves = 0;
}
}
/**
* Draws the key filling the given Graphics2D. The method completely fills the Graphics2D passed
* to it, using no AffineTransforms.
*
* @param g2 Graphics2D that fills with the key.
*/
public void fillKey(Graphics2D g2) {
// Get bounds of the Graphics2D
Rectangle bounds = g2.getClipBounds();
// Find the drawingX, Y, Width, and Height, to fill the entire Graphics.
double drawingX = Math.ceil(bounds.getX() + getSettings().getKeyOutlineStrokeWidth());
double drawingY = Math.ceil(bounds.getY() + getSettings().getKeyOutlineStrokeWidth());
double drawingWidth = Math.floor(bounds.getWidth() - drawingX - getSettings().getKeyOutlineStrokeWidth());
double drawingHeight = Math.floor(bounds.getHeight() - drawingY - getSettings().getKeyOutlineStrokeWidth());
AffineTransform scaleTransform = AffineTransform.getScaleInstance(drawingWidth, drawingHeight);
AffineTransform translateTransform = AffineTransform.getTranslateInstance(drawingX, drawingY);
translateTransform.concatenate(scaleTransform);
drawKey(g2, translateTransform);
}
/**
* Draws the key in the given Graphics2D, using the AffineTransform passed to it.
* The method uses the AffineTransform using no previous transforms.
*
* @param g2 Graphics2D that this fills with the key.
* @param a AffineTransform
that transforms the key, assuming no previous transforms occur.
*/
public void drawKey(Graphics2D g2, AffineTransform a) {
if (originalShape == null)
setOriginalShape(g2);
if (getKey() instanceof Character) {
if ( (((Character)getKey()).charValue() == 'i') || (((Character)getKey()).charValue() == 'I') ) {
double oldScale = a.getScaleX();
// Find the drawingX, Y, Width, and Height, to fill the entire Graphics.
a.scale(1.0/5.0, 1);
a.translate(( (2*oldScale)/5.0) / a.getScaleX(), 0);
}
}
currentShape = a.createTransformedShape(originalShape);
drawKey(g2);
}
/**
* Draws the key, first setting all values for the Graphics2D g2.
* The drawing is done using the current Shape, defined generally in drawKey
or
* fillKey
.
*
* @param g2 Graphics2D that the key is painted to.
*/
public void drawKey(Graphics2D g2) {
// Set graphics information
g2.setComposite(getSettings().getKeyComposite());
g2.setPaint(getSettings().getKeyFillPaint());
g2.fill(currentShape);
g2.setStroke(getSettings().getKeyOutlineStroke());
g2.setPaint(getSettings().getKeyOutlinePaint());
g2.draw(currentShape);
}
/**
* sets the Original Shape using the g2 simply for the FontRenderContext
.
* @param g2 Graphics2D that FontRenderContext is aquired from.
*/
private void setOriginalShape(Graphics2D g2) {
String key = getKey().toString();
// Makes a textLayout using the key.
TextLayout text = new TextLayout(key, getSettings().getFont(), g2.getFontRenderContext());
// Makes a Shape
Shape keyShape = text.getOutline(null);
// Get Bounds of the Shape
Rectangle2D keyShapeBounds = keyShape.getBounds2D();
// Scales to size of 1 and transforms to (0,0)
AffineTransform scaleTransform = AffineTransform.getScaleInstance(1 / keyShapeBounds.getWidth() , 1 / keyShapeBounds.getHeight());
AffineTransform translateTransform = AffineTransform.getTranslateInstance((-keyShapeBounds.getX()), (-keyShapeBounds.getY()));
scaleTransform.concatenate(translateTransform);
originalShape = scaleTransform.createTransformedShape(keyShape);
}
}