package edu.princeton.cs.algs4.growingtree.framework; /* * @(#)DisplayChangeAnimation.java * * Last Modified: 9/01/02 */ import java.util.*; import java.awt.*; import java.awt.geom.*; /** * * The Animation object that defines the Rotation of a BSTTree. Two constructors exist, * one setting the animator and animation color Schemes, one setting those to defaults.
* * The object restores all values changed in the given nodes, however, if the object * is never allowed to finish, the restoring of values becomes impossible. On any exception occuring * elsewhere, the object may not restore the conditions correctly. * * @author Corey Sanders * @version 1.4 9/01/02 */ public class DisplayChangeAnimation
extends AbstractAnimation { /** * The Default step size used in the animation (16). */ public final static int DEFAULT_STEP = 16; /** * Constant that defines the starting location. */ private final int START = 0; /** * Constant the defines the final moving location. */ private final int MOVE = 1; /** * Private doubles used to hold the current and previous location steps. */ private double currentLocation = 0.0; /** * The previous location of the animation. */ private double previousLocation; /** * The moving nodes for the display change. */ private MovingBSTTreeAnimation
movingTreeNodes;
/**
* The int defining the change in display.
*/
private int displayChange;
/**
* The linked list containing all of the right null links nodes
*/
private LinkedList head;
/**
* The constructor which initiates the status and sets the color Schemes to default. Also sets
* starting command to Animation.PLAY, and sets the step time to the default.
*
* @param head the BSTTreeHead head of the tree whose display is changing.
* @param displayChange the new kind of display, according to BSTTreeHead.SECT_DISPLAY or BSTTreeHead.BINARY_DISPLAY
*/
public DisplayChangeAnimation(GrowingTreeHead head, int displayChange) {
this(head, displayChange, null, null, Animation.PLAY, DEFAULT_STEP);
}
/**
* The constructor which initiates the status and prepares the color schemes.
*
* @param head the BSTTreeHead head of the tree whose display is changing.
* @param displayChange the new kind of display, according to BSTTreeHead.SECT_DISPLAY or BSTTreeHead.BINARY_DISPLAY
* @param NodeOriginalAnimationScheme original scheme for the root.
* @param KeyOriginalScheme original scheme for the key.
* @param startingCmd the Animation command that should start.
* @param stepTime the time for each step of the Animation. Sets the initial value.
*/
public DisplayChangeAnimation(GrowingTreeHead head, int displayChange, NodeSettings NodeOriginalScheme, KeySettings KeyOriginalScheme, String startingCmd, int stepTime) {
super();
// Set defaults if no color schemes exist
if (NodeOriginalScheme == null) {
NodeOriginalScheme = new NodeSettings();
}
if (KeyOriginalScheme == null) {
KeyOriginalScheme = new KeySettings();
}
setNodeOriginalScheme((NodeSettings)NodeOriginalScheme.clone());
setKeyOriginalScheme((KeySettings)KeyOriginalScheme.clone());
setLeftNullNodes(new LinkedList (getNodeOriginalScheme(), getKeyOriginalScheme()));
setStartingCommand(startingCmd);
setStepTime(stepTime);
}
/************************/
/* Accessor methods */
/************************/
/**
* Gets the displayChange for the display change animation.
*
* @return displayChange integer defined in BSTTreeHead.
*/
public int getDisplayChange() {
return displayChange;
}
/**
* Gets the right null link nodes.
*
* @return LinkedList for the right null link nodes.
*/
private LinkedList getHead() {
return head;
}
/**
* Gets the MovingBSTTreeAnimation for the tree whose display is changing.
*
* @return MovingBSTTreeAnimation for the entire tree display change.
*/
public MovingBSTTreeAnimation getMovingTreeNodes() {
return movingTreeNodes;
}
/**
* Gets the NodeSettings for the original node scheme for the rotation.
*
* @return NodeSettings for the original node scheme.
*/
public NodeSettings getNodeOriginalScheme() {
return nodeOriginalScheme;
}
/**
* Gets the KeySettings for the original scheme of the key.
*
* @return KeySettings for the original key scheme.
*/
public KeySettings getKeyOriginalScheme() {
return keyOriginalScheme;
}
/************************/
/* Mutator methods */
/************************/
/**
* Sets the displayChange for the animation.
*
* @param displayChange the int defined within BSTTreeHead (SECT_DISPLAY or BINARY_DISPLAY).
*/
public void setDisplayChange(int displayChange) {
this.displayChange = displayChange;
}
/**
* Sets the right null link nodes.
*
* @param LinkedList for the right null link nodes.
*/
private void setRightNullNodes(LinkedList head) {
this.head = head;
}
/**
* Sets the MovingBSTTreeAnimation for the tree whose display is changing.
*
* @param movingTreeNodes MovingBSTTreeAnimation for the entire tree display change.
*/
public void setMovingTreeNodes(MovingBSTTreeAnimation movingTreeNodes) {
this.movingTreeNodes = movingTreeNodes;
}
/**
* Sets the NodeSettings for the original scheme for the rotation.
*
* @param scheme NodeSettings for the original scheme.
*/
public void setNodeOriginalScheme(NodeSettings scheme) {
nodeOriginalScheme = scheme;
}
/**
* Sets the KeySettings for the original scheme of the key during rotation.
*
* @param scheme KeySettings for the original of the key.
*/
public void setKeyOriginalScheme(KeySettings scheme) {
keyOriginalScheme = scheme;
}
/*****************************/
/* Entire Animators Mutators */
/*****************************/
/**
* Creates the moving nodes corresponding to the entire tree.
*/
private void createFinalTreeMovingNodes() {
// Intialize
//finalTreeMovingNodes = new MovingBSTTreeAnimation();
// Top node
GrowingTreeNode topNode = (GrowingTreeNode )getHead().getChild();
if (topNode == null)
return;
MovingBSTTree topMovingNode = new MovingBSTTree (topNode);
if (topNode.isAnimateDrawing()) {
// Add grandchild to descendant animation
getMovingTreeNodes().add(topMovingNode, topNode);
topMovingNode.setMovePosition(MovingBSTTree.FOLLOW_NODE);
// Set listeners
getMovingTreeNodes().addAnimationListener(topNode);
(topNode).addAnimator(getMovingTreeNodes());
}
// Add all children
MovingBSTTree left = addTreeNode((GrowingTreeNode )topNode.getLeftNodeInternal(), getMovingTreeNodes(), MovingBSTTree.FOLLOW_NODE, topMovingNode);
MovingBSTTree right = addTreeNode((GrowingTreeNode )topNode.getRightNodeInternal(), getMovingTreeNodes(), MovingBSTTree.FOLLOW_NODE, topMovingNode);
if (left != null) {
topMovingNode.setLeftTree(left);
}
else {
getLeftNullNodes().add(topMovingNode);
}
if (right != null) {
topMovingNode.setRightTree(right);
}
else {
getRightNullNodes().add(topMovingNode);
}
}
/**
* Adds all children nodes to the animator list, setting the Moving node as its parent. The move position
* defines the moving of the new node.
*
* @param node the node which the MovingBSTTree made imitates.
* @param animator the MovingBSTTreeAnimation to which the new MovingBSTTree node is added.
* @param movePostion the moving position of the new MovingBSTTree.
* @return MovingBSTTree the new tree moving node.
*/
private MovingBSTTree addTreeNode(GrowingTreeNode node, MovingBSTTreeAnimation animator, int movePosition, MovingBSTTree parent) {
if (node.isEmpty())
return null;
// Create new MovingBSTTree
MovingBSTTree movingNode = new MovingBSTTree (node, parent);
if (node.isAnimateDrawing()) {
// Sets the move position
movingNode.setMovePosition(movePosition);
// Adds the animator to the MovingBSTTreeAnimation
animator.add(movingNode, node);
// Adds the listener to the animation and the animation to the node.
animator.addAnimationListener(node);
node.addAnimator(animator);
MovingBSTTree left = addTreeNode((GrowingTreeNode )node.getLeftNodeInternal(), animator, MovingBSTTree.FOLLOW_NODE, movingNode);
MovingBSTTree right = addTreeNode((GrowingTreeNode )node.getRightNodeInternal(), animator, MovingBSTTree.FOLLOW_NODE, movingNode);
// Recursively goes through children
if (left != null) {
movingNode.setLeftTree(left);
}
else {
getLeftNullNodes().add(movingNode);
}
if (right != null) {
movingNode.setRightTree(right);
}
else {
getRightNullNodes().add(movingNode);
}
}
movingNode.setCurrentTransform(movingNode.getStartTransform());
return movingNode;
}
/**
* Draws the animation of the next step, using the status of the animation (Animation.PLAY, Animation.PAUSE and so forth).
* After completing the drawing, the Animation sends an
* The starting status used for the animation is the one previously defined.
*
* @param g2 Graphics2D to which the graphics are drawn.
*/
public void drawAnimation(Graphics2D g2) {
drawAnimation(g2, getStartingCommand());
}
/**
* Draws the animation of the next step, using the status of the animation (Animation.PLAY, Animation.PAUSE and so forth).
* After completing the drawing, the Animation sends an AnimationEvent to all its listeners, indicating
* any information that the listerners may wish to use.
*
* BSTTreeHead calls:
* )getLeftNullNodes().get(i)).drawFollowNode(g2, currentLocation, true);
}
for(int i=0; i )getRightNullNodes().get(i)).drawFollowNode(g2, currentLocation, true);
}
}
getMovingTreeNodes().drawAnimation(g2, action);
}
// Animation is completed
if (currentLocation >= MOVE) {
// Set step, to finish the animation
getMovingTreeNodes().setStep(true);
// Draw
getMovingTreeNodes().makeAnimation(g2, Animation.PLAY);
getMovingTreeNodes().drawAnimation(g2, Animation.PLAY);
// Set own status to FINISH
setStatus(Animation.FINISH);
}
// FINISH status
if (getStatus().equals(Animation.FINISH)) {
// Completion messages
messageAction(Animation.FINISH);
// Set all status to FINISH
getMovingTreeNodes().setStatus(Animation.FINISH);
getMovingTreeNodes().makeAnimation(g2, startingStatus);
// Draw
getMovingTreeNodes().drawAnimation(g2, startingStatus);
}
// Call listeners
animationAction();
}
}
AnimationEvent
to all its listeners, indicating
* any information that the listerners may wish to use.
*
* Other Animation Objects used:
* rotateUpTreeType
- called when animation does completes
*
*
* @param g2 the graphics to which the animation step should be drawn.
* @param startingStatus sent to the animators
*/
public void drawAnimation(Graphics2D g2, String startingStatus) {
setStartingCommand(startingStatus);
// Sets the animation step size.
getMovingTreeNodes().setStepSize(getStepSize());
// Sets the animation step size.
//getMovingTreeNodes().setStep(getStep());
getMovingTreeNodes().setStep(false);
// FINISH status (set from outside)
if (getStatus().equals(Animation.FINISH)) {
// Actual rotation
getHead().setDisplay(getDisplayChange());
}
// BEGIN status
if (getStatus().equals(Animation.BEGIN)) {
currentLocation = 0.0;
previousLocation = 0.0;
// Create the final moving nodes
createFinalTreeMovingNodes();
//getMovingTreeNodes().drawAnimation(g2, startingStatus);
//getMovingTreeNodes().setAnimationScheme(getNodeOriginalScheme(), getKeyOriginalScheme());
// Actual display change
getHead().setDisplay(getDisplayChange());
// REDRAW message
messageAction(Animation.REDRAW);
if (displayChange == GrowingTreeHead.BINARY_DISPLAY) {
for(int i=0; i