package edu.princeton.cs.algs4.growingtree.framework; /* * @(#)MovingBSTTreeAnimation.java * * Last Modified: 9/15/01 */ import java.util.*; import java.awt.*; /** * * The Animation object that defines the Moving of a MovingBSTTree. Two constructors exist, * one setting the animator and animation color Schemes. This animation is the core of many * other animations that involve moving (Rotation).

* * 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/15/01 */ public class MovingBSTTreeAnimation

extends AbstractAnimation { /** * Private doubles used to hold the current and previous location steps. */ private double currentLocation = 0.0; private double previousLocation = 0.0; /** * Private boolean defining if the node has already been made, just not drawn. */ private boolean animationMade = false; /** * Refers to the linked list which will store the moving nodes used in the animation. */ private LinkedList> movingNodes; /** * Refers to the linked list which will store the nodes that correspond to each moving * node in the previous LinkedList. */ private LinkedList> nodes; /** * Color Scheme used for the animator, using one of the NodeSettings Schemes. */ private NodeSettings nodeAnimationScheme; /** * Color Scheme used for the key of the animator, using one of the KeySettings Schemes. */ private KeySettings keyAnimationScheme; /** * The constructor which initiates the status as Animation.PLAY, default step size, * the default NodeAnimationScheme and KeyAnimationScheme. */ public MovingBSTTreeAnimation() { this(null, null, Animation.PLAY, DEFAULT_STEP); } /** * The constructor which initiates the status as Animation.PLAY, default step size, * the given NodeAnimationScheme and KeyAnimationScheme. * * @param NodeAnimationScheme the NodeSettings which the nodes uses during animation. * @param KeyAnimationScheme the KeySettings which the key in each moving node is drawn. */ public MovingBSTTreeAnimation(NodeSettings NodeAnimationScheme, KeySettings KeyAnimationScheme) { this(NodeAnimationScheme, KeyAnimationScheme, Animation.PLAY, DEFAULT_STEP); } /** * The constructor which initiates the status and prepares the color Schemes. * * @param NodeAnimationScheme the NodeSettings which the nodes uses during animation. * @param KeyAnimationScheme the KeySettings which the key in each moving node is drawn. * @param startingCmd the Animation command that this should start. * @param stepTime the time for each step of the Animation. Sets the initial value. */ public MovingBSTTreeAnimation(NodeSettings NodeAnimationScheme, KeySettings KeyAnimationScheme, String startingCmd, int stepTime) { super(); // Set defaults if no color schemes exist if (NodeAnimationScheme == null) { NodeAnimationScheme = new NodeSettings(); } if (KeyAnimationScheme == null) { KeyAnimationScheme = new KeySettings(); } movingNodes = new LinkedList>(); nodes = new LinkedList>(); setAnimationScheme((NodeSettings)NodeAnimationScheme.clone(), (KeySettings)KeyAnimationScheme.clone()); // Set the starting command. setStartingCommand(startingCmd); // Set Step size setStepTime(stepTime); } /************************/ /* Accessor methods */ /************************/ /** * Gets the moving nodes used in the Animation. The return is the clone * of the LinkedList used within the class. Cloning of a LinkedList is a shallow * copy. * * return LinkedList representing the movingBSTTrees. */ public LinkedList> getMovingNodes() { return (LinkedList>)movingNodes.clone(); } /** * Gets the node Animationg scheme for each moving node. * * @return animation scheme for the moving nodes. */ public NodeSettings getNodeAnimationScheme() { return nodeAnimationScheme; } /** * Gets the BSTTree nodes used in the Animation. The return is the clone * of the LinkedList used within the class. Cloning of a LinkedList is a shallow * copy. * * return LinkedList representing the BSTTrees that the movingBSTTrees imitate. */ public LinkedList> getNodes() { return (LinkedList>)nodes.clone(); } /** * Gets the moving node within the Animation that imitates the passed BSTTree node. * If the BSTTree node does not exist in the Animation, null is returned. * * @param node BSTTree node which the returning MovingBSTTree node imitates. * @return MovingBSTTree which imitates the given node. */ public MovingBSTTree

getMovingNode(GrowingTreeNode

node) { int index = nodes.indexOf(node); if (index == -1) return null; else return (MovingBSTTree

)movingNodes.get(index); } /** * Gets the first moving node in the list. * * @return the first MovingBSTTree in the animation. */ public MovingBSTTree

getFirstMovingNode() { return (MovingBSTTree

)movingNodes.getFirst(); } /** * Returns true if the moving node list is empty. * * @return true if the animation contains no moving nodes. */ public boolean isEmpty() { return (movingNodes.isEmpty()); } /** * Gets the NodeSettings for the animation of the moving node. * * @return NodeSettings for the node animating. */ public NodeSettings getAnimationScheme() { return nodeAnimationScheme; } /** * Gets the KeySettings for the animation key for the moving node. * * @return KeySettings for the key of the node animating. */ public KeySettings getKeyAnimationScheme() { return keyAnimationScheme; } /************************/ /* Mutator methods */ /************************/ /** * Sets the animation scheme for each moving node. * * @param nodeScheme the NodeSettings for the animation of the moving node. * @param keyScheme the KeySettings for the animationg of the key within the moving node. */ public void setAnimationScheme(NodeSettings nodeScheme, KeySettings keyScheme) { setNodeAnimationScheme(nodeScheme); setKeyAnimationScheme(keyScheme); // Sets settings of entire list setListSettings(getAnimationScheme(), getKeyAnimationScheme()); } /** * Adds the movingBSTTree along with the BSTTree node as a pair. The moving Node imitates * the given nod. * * @param movingNode MovingBSTTree that is added to the animation. * @param node BSTTree that is added to the animation. */ public void add(MovingBSTTree

movingNode, GrowingTreeNode

node) { movingNodes.add(movingNode); nodes.add(node); } /** * Sets the NodeSettings for the animation of the moving node. * * @param scheme NodeSettings for the node animating. */ public void setNodeAnimationScheme(NodeSettings scheme) { nodeAnimationScheme = (NodeSettings)scheme.clone(); } /** * Sets the KeySettings for the animation key for the moving node. * * @param scheme KeySettings for the key of the node animating. */ public void setKeyAnimationScheme(KeySettings scheme) { keyAnimationScheme = (KeySettings)scheme.clone(); } /** * 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. * * @param g2 the graphics to which the animation step should be drawn. * @param startingStatus the starting status used if necessary. */ public void drawAnimation(Graphics2D g2, String startingStatus) { // Sets starting command setStartingCommand(startingStatus); // Empty if (isEmpty()) { setStatus(Animation.FINISH); animationAction(); return; } // BEGIN status if (getStatus().equals(Animation.BEGIN)) { currentLocation = 0.0; setStatus(getStartingCommand()); animateList(g2, currentLocation); // Call listeners animationAction(); return; } // Currently on a step and no changes have occured. Return to startingStatus if (getStatus().equals(Animation.STEP)) { setStatus(getStartingCommand()); } // PLAY status if ((getStatus().equals(Animation.PLAY)) && (!animationMade)) { if (getStep()) { currentLocation = 1; } else { currentLocation += getStepSize(); if (currentLocation > 1) currentLocation = 1; } } // REWIND status if ((getStatus().equals(Animation.REWIND)) && (!animationMade)) { if (getStep()) { currentLocation = 0; } else { currentLocation -= getStepSize(); if (currentLocation < 0) { setStatus(Animation.STOP); currentLocation = 0; animationAction(); return; } } } // PAUSE status if (getStatus().equals(Animation.PAUSE)) { } // STOP status if (getStatus().equals(Animation.STOP)) { return; } // FINISH status if (getStatus().equals(Animation.FINISH)) { animationAction(); return; } // Draws entire list animateList(g2, currentLocation); // Call listeners animationAction(); animationMade = false; } /** * Makes the animation of the next step, using the status of the animation (Animation.PLAY, Animation.PAUSE and so forth). * After completing the making, nodeMade is set to true, so when the animation is actually drawn, it will not skip a step. * * @param g2 the graphics to which the animation step should be drawn. * @param startingStatus the starting status used if necessary. */ public void makeAnimation(Graphics2D g2, String startingStatus) { // Sets starting command setStartingCommand(startingStatus); // Empty if (isEmpty()) { setStatus(Animation.FINISH); animationAction(); return; } // BEGIN status if (getStatus().equals(Animation.BEGIN)) { currentLocation = 0.0; setStatus(getStartingCommand()); animateList(g2, currentLocation); // Call listeners animationAction(); return; } // Currently on a step and no changes have occured. Return to startingStatus if (getStatus().equals(Animation.STEP)) { setStatus(getStartingCommand()); } // PLAY status if (getStatus().equals(Animation.PLAY)) { if (getStep()) { currentLocation = 1; } else { currentLocation += getStepSize(); if (currentLocation > 1) currentLocation = 1; } } // REWIND status if (getStatus().equals(Animation.REWIND)) { if (getStep()) { currentLocation = 0; } else { currentLocation -= getStepSize(); if (currentLocation < 0) { setStatus(Animation.STOP); currentLocation = 0; animationAction(); return; } } } // PAUSE status if (getStatus().equals(Animation.PAUSE)) { } // STOP status if (getStatus().equals(Animation.STOP)) { return; } // FINISH status if (getStatus().equals(Animation.FINISH)) { animationAction(); return; } // Draws entire list makeList(g2, currentLocation); animationMade=true; } /** * Animates the entire list of moving Nodes. The animation is drawn to the graphics2D, using * the step. The step must be between 0 and 1, 0 being the beginning of the movement and 1 * being the end. * * @param g2 Graphics2D to which the moving node is drawn. * @param step double between 0 and 1, indicating the progress of the movement. */ private void animateList(Graphics2D g2, double step) { int size = movingNodes.size(); for(int i=0; i < size; i++) { ((MovingBSTTree

)movingNodes.get(i)).drawNodeAndLink(g2, step); } } /** * Makes the entire list of moving Nodes. The animation is made within the graphics2D, using * the step. The step must be between 0 and 1, 0 being the beginning of the movement and 1 * being the end. * * @param g2 Graphics2D to which the moving node is drawn. * @param step double between 0 and 1, indicating the progress of the movement. */ private void makeList(Graphics2D g2, double step) { int size = movingNodes.size(); for(int i=0; i < size; i++) { ((MovingBSTTree

)movingNodes.get(i)).makeNode(g2, step); } } /** * Sets the settings of every moving node in the list. Both the NodeSettings and KeySettings * must be set. * * @param s NodeSettings used to set the node settings of every moving node. * @param k KeySettings used to set the key settings of every moving node. */ private void setListSettings(NodeSettings s, KeySettings k) { int size = movingNodes.size(); for(int i=0; i < size; i++) { ((MovingBSTTree

)movingNodes.get(i)).setNodeSettings(s); ((DrawableKey)((MovingBSTTree

)movingNodes.get(i)).getValue()).setKeySettings(k); } } /** * Calls all of the listeners of the current Animation and passed information regarding the * progress and status of the current Animation. Additionally, the id of the type of animation is * passed. Within, the animationEventPerformed method is called. * * @param cmd String Animation command passed instead of the current Status. * @param description String description for messages. */ protected void animationAction(String cmd, String description) { super.animationAction(AnimationEvent.MOVING_NODES_ANIMATION, cmd, description, currentLocation); } }