Mega Code Archive

 
Categories / Java / Collections Data Structure
 

This program animates a sort algorithm

/*    This program is a part of the companion code for Core Java 8th ed.    (http://horstmann.com/corejava)    This program is free software: you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation, either version 3 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program.  If not, see <http://www.gnu.org/licenses/>. */ import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Rectangle2D; import java.util.Arrays; import java.util.Comparator; import java.util.concurrent.Semaphore; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; /**  * This program animates a sort algorithm.  * @version 1.01 2007-05-18  * @author Cay Horstmann  */ public class AlgorithmAnimation {    public static void main(String[] args)    {       EventQueue.invokeLater(new Runnable()          {             public void run()             {                JFrame frame = new AnimationFrame();                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                frame.setVisible(true);             }          });    } } /**  * This frame shows the array as it is sorted, together with buttons to single-step the animation or  * to run it without interruption.  */ class AnimationFrame extends JFrame {    public AnimationFrame()    {       ArrayComponent comp = new ArrayComponent();       add(comp, BorderLayout.CENTER);       final Sorter sorter = new Sorter(comp);       JButton runButton = new JButton("Run");       runButton.addActionListener(new ActionListener()          {             public void actionPerformed(ActionEvent event)             {                sorter.setRun();             }          });       JButton stepButton = new JButton("Step");       stepButton.addActionListener(new ActionListener()          {             public void actionPerformed(ActionEvent event)             {                sorter.setStep();             }          });       JPanel buttons = new JPanel();       buttons.add(runButton);       buttons.add(stepButton);       add(buttons, BorderLayout.NORTH);       setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);       Thread t = new Thread(sorter);       t.start();    }    private static final int DEFAULT_WIDTH = 300;    private static final int DEFAULT_HEIGHT = 300; } /**  * This runnable executes a sort algorithm. When two elements are compared, the algorithm pauses and  * updates a component.  */ class Sorter implements Runnable {    /**     * Constructs a Sorter.     * @param values the array to be sorted     * @param comp the component on which to display the sorting progress     */    public Sorter(ArrayComponent comp)    {       values = new Double[VALUES_LENGTH];       for (int i = 0; i < values.length; i++)          values[i] = new Double(Math.random());       this.component = comp;       this.gate = new Semaphore(1);       this.run = false;    }    /**     * Sets the sorter to "run" mode. Called on the event dispatch thread.     */    public void setRun()    {       run = true;       gate.release();    }    /**     * Sets the sorter to "step" mode. Called on the event dispatch thread.     */    public void setStep()    {       run = false;       gate.release();    }    public void run()    {       Comparator<Double> comp = new Comparator<Double>()          {             public int compare(Double i1, Double i2)             {                component.setValues(values, i1, i2);                try                {                   if (run) Thread.sleep(DELAY);                   else gate.acquire();                }                catch (InterruptedException exception)                {                   Thread.currentThread().interrupt();                }                return i1.compareTo(i2);             }          };       Arrays.sort(values, comp);       component.setValues(values, null, null);    }    private Double[] values;    private ArrayComponent component;    private Semaphore gate;    private static final int DELAY = 100;    private volatile boolean run;    private static final int VALUES_LENGTH = 30; } /**  * This component draws an array and marks two elements in the array.  */ class ArrayComponent extends JComponent {    /**     * Sets the values to be painted. Called on the sorter thread.     * @param values the array of values to display     * @param marked1 the first marked element     * @param marked2 the second marked element     */    public synchronized void setValues(Double[] values, Double marked1, Double marked2)    {       this.values = values.clone();       this.marked1 = marked1;       this.marked2 = marked2;       repaint();    }    public synchronized void paintComponent(Graphics g) // Called on the event dispatch thread    {       if (values == null) return;       Graphics2D g2 = (Graphics2D) g;       int width = getWidth() / values.length;       for (int i = 0; i < values.length; i++)       {          double height = values[i] * getHeight();          Rectangle2D bar = new Rectangle2D.Double(width * i, 0, width, height);          if (values[i] == marked1 || values[i] == marked2) g2.fill(bar);          else g2.draw(bar);       }    }    private Double marked1;    private Double marked2;    private Double[] values; }