/* * @(#)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); } }