package edu.princeton.cs.algs4.growingtree.framework; /* * @(#)BalanceBSTAnimation.java * * Last Modified: 9/15/01 */ import java.util.*; import java.awt.*; /** * * The Animation object that defines the Balancing of a node in a BSTTree. Two constructors exist, * one setting the starting string command and step time (preferred use). The other uses defaults. * The animation builds PartitionBSTAnimations from the head node as it goes, keeping * only one currently animating and allowing rewinding only to the previous * rotation. The color schemes are set by the head call. The call is * makePartitionAnimation.

* * @author Corey Sanders * @version 1.4 9/15/01 */ public class BalanceBSTAnimation

extends AbstractAnimation implements AnimationListener { /** * Refers to the current PartitionBSTAnimation being drawn. */ PartitionBSTAnimation

currentPartition; /** * Holds the node that is replacing. */ private GrowingTreeNode

node; /** * Holds the node that is replacing. */ private GrowingTreeNode

replacingNode; /** * Private doubles used to hold the current location steps. */ private double currentLocation = 0.0; /** * The constructor which initiates the status. The node * which is being balanced must be passed. * * @param node the BSTTree from which the balancing takes place. * @param startingCmd the Animation command that this should start. * @param stepTime the time for each step of the Animation. Sets the initial value. */ public BalanceBSTAnimation(GrowingTreeNode

node, String startingCmd, int stepTime) { super(); setNode(node); setStartingCommand(startingCmd); setStepTime(stepTime); } /** * The constructor which initiates the status and sets the starting command and step time * * @param node the BSTTree which is balanced. */ public BalanceBSTAnimation(GrowingTreeNode

node) { this(node, Animation.PLAY, DEFAULT_STEP); } /************************/ /* Accessor methods */ /************************/ /** * Gets the node from which the balancing takes place. * * @return BSTTree of the node currently being balanced. */ public GrowingTreeNode

getNode() { return node; } /** * Gets the node currently being replaced by the node being balanced (not set until after partition occurs). * * @return BSTTree of the node currently being replaced and animated. */ public GrowingTreeNode

getReplacingNode() { return replacingNode; } /************************/ /* Mutator methods */ /************************/ /** * Sets the node from which the balancing takes place. * * @param node BSTTree of the node currently being balanced. */ public void setNode(GrowingTreeNode

node) { this.node = node; } /** * Sets the node that will replace the balanced node. * * @param GrowingTreeNode of the node replacing the balancing node. */ public void setReplacingNode(GrowingTreeNode

node) { replacingNode = node; } /*********************/ /* Animation methods */ /*********************/ /** * 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: *

* Other Animation Objects used: * * * @param g2 the graphics to which the animation step should be drawn. * @param startingStatus the status used as the starting command of animation, if needed. */ public void drawAnimation(Graphics2D g2, String startingStatus) { setStartingCommand(startingStatus); // Starting Finish status (set prior to call) if (getStatus().equals(Animation.FINISH)) { if (currentPartition != null) { currentPartition.setStatus(Animation.FINISH); currentPartition.drawAnimation(g2, Animation.FINISH); } else { // Set replacing node (Using selectTree) setReplacingNode((GrowingTreeNode

)((GrowingTreeHead

)getNode().getHead()).selectTreeType(getNode(), getNode().size() / 2)); } if (getReplacingNode() == null) { return; } // Do actual balancing in tree (Setting the correct final location). getNode().getHead().balanceTreeType(getReplacingNode()); } // BEGIN status if (getStatus().equals(Animation.BEGIN)) { animationAction(); // Beginning message messageAction(Animation.BEGIN + " Balance of "+getNode().getKey().toString()); // set starting status setStatus(getStartingCommand()); // Set partition currentPartition =(PartitionBSTAnimation

)((GrowingTreeHead

)getNode().getHead()).makePartitionAnimation(getNode(), getNode().size() / 2); // Set replacing node (Using selectTree) setReplacingNode((GrowingTreeNode

)((GrowingTreeHead

)getNode().getHead()).selectTreeType(getNode(), getNode().size() / 2)); currentPartition.addAnimationListener(this); currentPartition.drawAnimation(g2, getStatus()); 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)) { // Set values for animation currentPartition.setStepTime(getStepTime()); currentPartition.setStep(getStep()); // Set play status currentPartition.setStatus(Animation.PLAY); // Draw rotation animation currentPartition.drawAnimation(g2, Animation.PLAY); messageAction(Animation.PLAY); // Finished with current partition if (currentPartition.getStatus().equals(Animation.FINISH)) { setStatus(Animation.FINISH); } } // REWIND status if (getStatus().equals(Animation.REWIND)) { // Set values for animation currentPartition.setStepTime(getStepTime()); currentPartition.setStep(getStep()); // Set play status currentPartition.setStatus(Animation.REWIND); // Draw rotation animation currentPartition.drawAnimation(g2, Animation.REWIND); messageAction(Animation.REWIND); } // PAUSE status if (getStatus().equals(Animation.PAUSE)) { // Set play status currentPartition.setStatus(Animation.PAUSE); // Draw rotation animation currentPartition.drawAnimation(g2, Animation.PAUSE); messageAction(Animation.PAUSE); } // STOP status if (getStatus().equals(Animation.STOP)) { messageAction(Animation.STOP); return; } // FINISH status if (getStatus().equals(Animation.FINISH)) { messageAction(Animation.FINISH); messageAction("*--------Balance of "+getNode().getKey().toString()+"--------*\nReplaced by "+getReplacingNode().getKey().toString()); animationAction(); messageAction(Animation.REDRAW); return; } // Call listeners animationAction(); } /** * 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.BALANCE_BST_ANIMATION, cmd, description, currentLocation); } /** * Implements AnimationListener which requires the following method. * The only status of animation it listens for is Animation.ANIMATION_MESSAGE, to pass * the message on. * * @param e AnimationEvent that represents the information of the Animation. */ public void animationEventPerformed(AnimationEvent e) { // set location each progress call. currentLocation = e.getProgress(); if (e.getStatus().equals(Animation.ANIMATION_MESSAGE)) { messageAction(e.getAnimationDescription()); } if (e.getStatus().equals(Animation.STEP)) { animationAction(Animation.STEP, null); } } }