Code:
package com.executecodes.combinatorial;
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Point;
@SuppressWarnings("deprecation")
class ExplainBox extends Canvas
{
private static final long serialVersionUID = 1L;
static final int marginX = 6;
static final int marginY = 3;
String text = "";
public ExplainBox()
{
setFont(new Font("TimesRoman", Font.PLAIN, 12));
}
public void setText(String text)
{
this.text = text;
invalidate();
}
public void validate()
{
FontMetrics metrics = getFontMetrics(getFont());
int baseLine = metrics.getAscent();
int lineHeight = baseLine + metrics.getDescent();
int width = metrics.stringWidth(text);
Point corner = location();
reshape(corner.x, corner.y, width + 2 * marginX, lineHeight + 2
* marginY);
}
public void paint(Graphics g)
{
g.setColor(Color.black);
Dimension size = size();
g.drawRect(0, 0, size.width - 1, size.height - 1);
FontMetrics metrics = getFontMetrics(getFont());
g.drawString(text, marginX, marginY + metrics.getAscent());
}
public boolean mouseExit(Event event, int x, int y)
{
return true;
}
}
@SuppressWarnings("deprecation")
class CodePanel extends Panel
{
private static final long serialVersionUID = 1L;
static final int marginX = 15;
static final int marginY = 20;
static final int offsetX = 1;
static final int offsetY = 1;
static final int none = -1;
String code[]; // Array to hold the source code
String explainations[]; // Array to hold the explaination of source code
Font font = new Font("TimesRoman", Font.PLAIN, 16);
int lineHeight;
int baseLine;
int maxWidth = 0;
int highlightedLine = none;
ExplainBox explaination = new ExplainBox();
Applet applet;
public CodePanel(String code[], String explainations[], Applet applet)
{
this.code = code;
this.explainations = explainations;
this.applet = applet;
setBackground(Color.white); // Set the background of code panel to be
// white
explaination.setBackground(Color.lightGray);
explaination.setForeground(Color.lightGray);
add(explaination);
explaination.hide(); // Hide explaination until the code line is clicked
}
public Dimension preferredSize()
{
return new Dimension(280, 300);
}
public void addNotify()
{
super.addNotify();
setFont(font);
FontMetrics metrics = getFontMetrics(font);
baseLine = metrics.getAscent();
lineHeight = baseLine + metrics.getDescent();
for (int i = 0; i < code.length; i++)
{
maxWidth = Math.max(maxWidth, metrics.stringWidth(code[i]));
}
}
public void paint(Graphics g)
{
int y = marginY + baseLine;
for (int i = 0; i < code.length; i++, y += lineHeight)
{
setBackground(Color.white);
g.drawString(code[i], marginX, y);
}
highlightLine(highlightedLine);
}
public void reset()
{
if (highlightedLine != none)
{
colorLine(highlightedLine, Color.white);
}
highlightedLine = none;
}
public void highlightLine(int line)
{
if (highlightedLine != none)
{
colorLine(highlightedLine, Color.white);
}
highlightedLine = line;
if (highlightedLine != none)
{
colorLine(highlightedLine, Color.pink);
}
}
public void colorLine(int line, Color color)
{
Graphics g = getGraphics();
int y = marginY + line * lineHeight;
g.setColor(color);
g.fillRect(0, y, size().width - 1, lineHeight);
g.setColor(Color.black);
g.drawString(code[line], marginX, y + baseLine);
}
public boolean mouseExit(Event event, int x, int y)
{
explaination.hide();
validate();
return true;
}
public boolean mouseUp(Event event, int x, int y)
{
int line = (y - marginY) / lineHeight;
if ((line <= explainations.length) || (explainations[line].equals("")))
{
explaination.setText(explainations[line]);
explaination.setBackground(Color.lightGray);
explaination.validate();
explaination.show();
}
else
{
explaination.hide();
}
validate();
explaination.move(marginX + offsetX, marginY + offsetY + (line + 1)
* lineHeight);
return true;
}
}
@SuppressWarnings("deprecation")
class Algorithm extends Thread
{
CodePanel codeDisplay; // Code Panel
static int granularity; // Granularity Level
SortingApplet applet; // Bubble Sort Applet
Animation animation; // Animation Canvas
public static int indexi = 0; // Loop Index
public static int indexj = 0; // Loop Index
public static int flag = -1;
public Algorithm(CodePanel codeDisplay, int granularity, SortingApplet applet,
Animation animation)
{
this.codeDisplay = codeDisplay;
this.applet = applet;
Algorithm.granularity = granularity;
this.animation = animation;
}
void setGranularity(int granularity)
{
Algorithm.granularity = granularity;
}
public void run()
{
int line = 0; // Line Number
visualize(line, 2); // Visualize current line
indexi = SortingApplet.SourceData.length - 1; // Set loop index value
Algorithm.flag = 1; // Set execution status
animation.repaint(); // Refresh animation canvas
int forLoopLine1 = line; // Mark the line # of first for loop
while (true)
{
if (!(indexi >= 1))
break;
visualize(++line, 2);
indexj = 0;
animation.repaint();
int forLoopLine2 = line; // Mark the line # of second for loop
while (true)
{
if (!(indexj <= (indexi - 1)))
break;
visualize(++line, 2);
animation.repaint();
if (SortingApplet.SourceData[indexj] > SortingApplet.SourceData[indexj + 1])
{
// switch the two array elements
visualize(++line, 2);
int temp = SortingApplet.SourceData[indexj];
animation.repaint();
visualize(++line, 2);
SortingApplet.SourceData[indexj] = SortingApplet.SourceData[indexj + 1];
animation.repaint();
visualize(++line, 2);
SortingApplet.SourceData[indexj + 1] = temp;
animation.repaint();
}
line = forLoopLine2; // Set line # to be the second for loop
visualize(line, 1);
animation.repaint();
indexj++;
}
line = forLoopLine1; // Set line # to be the first for loop
visualize(line, 1);
indexi--;
animation.repaint();
}
Algorithm.flag = -1; // After execution finished, set flag back to -1
animation.repaint();
try
{
sleep(1000);
}
catch (Exception e)
{
}
applet.sortButton.setLabel(" Sort ");
applet.sortButton.disable();
applet.stopButton.disable();
applet.resetButton.enable();
visualize(0, 0); // After execution finished, highlight the first line
applet.finished();
}
void visualize(int line, int level)
{
codeDisplay.highlightLine(line); // Highlight the current line
codeDisplay.repaint();
if (level > granularity)
{
try
{
sleep(300);
}
catch (Exception e)
{
}
;
}
else
{
suspend();
}
}
}
@SuppressWarnings("deprecation")
class Animation extends Panel
{
private static final long serialVersionUID = 1L;
int dX = 30; // starting position for x coordinate
int dBar = 15; // width of bar
int dUnit = 15; // unit height
int dDis = 20; // distance between bars
Image offImage; // Offscreen Image
Graphics offG; // Offscreen Graphics
Font font = new Font("TimesRoman", Font.PLAIN, 14);
public Animation()
{
repaint();
}
public Dimension preferredSize()
{
return new Dimension(320, 300);
}
public Dimension minimumSize()
{
return preferredSize();
}
public void update(Graphics g)
{
paint(g);
}
public void paint(Graphics g)
{
Dimension d = size();
if (offImage == null)
{
offImage = createImage(d.width, d.height);
offG = offImage.getGraphics();
offG.setFont(font);
}
offG.setColor(Color.yellow); // Set background of Animation Canvas to be
// yellow
offG.fillRect(0, 0, d.width, d.height); // Draw background
offG.setColor(Color.blue); // Set color for bars to be blue
int x = 40; // x coordinate of the bar position
for (int i = 0; i < SortingApplet.SourceData.length; i++, x = x + dDis
+ dBar)
{
if (((i == Algorithm.indexj) || (i == Algorithm.indexj + 1))
&& (Algorithm.flag == 1))
{
offG.setColor(Color.green); // Use green color to indicate the
// bars being compared currently
}
else if (((i > Algorithm.indexi) && (Algorithm.flag == 1))
|| ((Algorithm.indexi == 0) && (Algorithm.indexj == 1) && (Algorithm.flag == -1)))
{
offG.setColor(Color.black); // Use black color to indicate bars
// that are already sorted
}
offG.fillRect(x, 180 - SortingApplet.SourceData[i] * dUnit, dBar,
SortingApplet.SourceData[i] * dUnit); // fill bars
offG.setColor(Color.blue); // Reset color to be blue
offG.drawString("" + i, x + 7, 25); // Draw the current index value
// of i
offG.drawString("" + SortingApplet.SourceData[i], x + 7, 40);
}
offG.drawString("Index:", 5, 25);
offG.drawString("Value:", 5, 40);
offG.drawString("I:", 5, 205);
offG.drawString("J:", 5, 230);
offG.drawString("J+1:", 5, 255);
if (Algorithm.indexi != 0)
offG.drawString("i", 40 + 9 + Algorithm.indexi * (dDis + dBar), 205);
if (Algorithm.indexj < Algorithm.indexi)
{
offG.drawString("j", 40 + 9 + Algorithm.indexj * (dDis + dBar), 230);
offG.drawString("j+1", 40 + 7 + (Algorithm.indexj + 1)
* (dDis + dBar), 255); // Mark the current j+1 position
}
g.drawImage(offImage, 0, 0, this);
}
}
@SuppressWarnings("deprecation")
public class SortingApplet extends Applet
{
private static final long serialVersionUID = 1L;
// Source code for Bubble Sort Algorithm
String code[] = { " for ( int i = n - 1; i >= 1; i-- ) ",
" for ( int j = 0; j <= i - 1; j++ ) ",
" if ( data [j] > data[j+1] ) { ",
" int temp = data [j]; ",
" data [j] = data [j+1]; ",
" data [j+1] = temp; ",
" } " };
// Explaination for each line of code
String pseudoCode[] = {
"go through elements of 'data' from last to 1 index",
"go through elements of 'data' from 0 to i index",
"to compare data [j] and data [j+1]",
"before swap, remember data [j]", "assign data [j] = data [j+1]",
"assign data [j+1] the original value of data [j]",
"end of if statement" };
public static int SourceData[] = { 7, 4, 5, 1, 8, 3, 6, 2 };
public static int normalData[] = { 7, 4, 5, 1, 8, 3, 6, 2 };
public static int bestData[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
public static int worstData[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
Button sortButton = new Button(" Sort "); // sort Button
Button stopButton = new Button(" Stop "); // stop Button
Button resetButton = new Button(" Reset "); // reset Button
int choice = 0; // choice index
Choice dataChoice = new Choice(); // choice of different data sets
String dataLabels[] = { "normal case", "best case", "worst case" };
int granularity = 0; // granularity index
Choice granularityChoice = new Choice(); // choice of different granularity
String granularityLabels[] = { "entire sort", "next swap", "next line" }; // granularity
// labels
private Panel controlPanel = new Panel();
CodePanel codeDisplay = new CodePanel(code, pseudoCode, this);
Algorithm algorithm = null;
Animation animation = new Animation();
public void init()
{
setLayout(new BorderLayout()); // Set the panle to be border layout
add("West", codeDisplay);
add("East", animation);
add("South", controlPanel);
controlPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); // Set
// codepanel
// to be
// flowlayout
controlPanel.add(sortButton); // Add sort button
controlPanel.add(stopButton); // Add stop button
stopButton.disable(); // At the beginning, stop button is disabled
controlPanel.add(resetButton); // Add reset button
resetButton.disable(); // At the beginning, resuet button is disabled
controlPanel.add(dataChoice); // Add data choice menu
for (int i = 0; i < dataLabels.length; i++)
{
dataChoice.addItem(dataLabels[i]); // Set label for each menu items
}
controlPanel.add(granularityChoice); // Add granularity choice menu
for (int i = 0; i < granularityLabels.length; i++)
{
granularityChoice.addItem(granularityLabels[i]); // Set label for
// each menu items
}
}
public void finished()
{
algorithm = null;
}
public boolean action(Event event, Object what)
{
if (event.target == sortButton)
{
if (granularity == 0)
sortButton.disable();
else
sortButton.setLabel("Continue");
resetButton.disable(); // Once sorting begins, reset Button is
// disabled
stopButton.enable(); // stop Button is enabled
if (algorithm == null)
{
algorithm = new Algorithm(codeDisplay, granularity, this,
animation);
algorithm.start(); // Start the Bubble Sort Algorithm
}
else
{
algorithm.resume(); // Continue the Bubble Sort Algorithm
}
}
else if (event.target == stopButton)
{ // stop Button is clicked
algorithm.stop(); // Stop the Bubble Sort Algorithm
sortButton.disable(); // Disable the sort Button
stopButton.disable(); // Disable the stop Button
resetButton.enable(); // Enable the reset Button
finished(); // Applet finished
}
else if (event.target == resetButton)
{ // reset Button is clicked
finished(); // Applet finished
sortButton.setLabel(" Sort "); // Set sort Button label
sortButton.enable();
stopButton.disable();
resetDataArray(); // Recover the data array to its initial value
// based on the dataChoice menu
Algorithm.flag = -1; // Reset flag to initial value
animation.repaint(); // Refresch the animation canvas
}
else if (event.target == dataChoice)
{ // If dataChoice menu is changed
choice = dataChoice.getSelectedIndex();
}
else if (event.target == granularityChoice)
{ // If granularityChoice menu is changed
granularity = granularityChoice.getSelectedIndex();
if (algorithm != null)
{
algorithm.setGranularity(granularity); // Set the granularity to
// be the new value in
// the menu
}
}
else
{
return false;
}
return true;
}
public void resetDataArray()
{
// Reset loop index to its initial value
Algorithm.indexi = 0;
Algorithm.indexj = 0;
if (choice == 0)
{ // "Normal Case" is selected
// Reset the source data to be the normal case
for (int i = 0; i < normalData.length; i++)
{
SourceData[i] = normalData[i];
}
}
else if (choice == 1)
{ // "Best Case" is selected
// Reset the source data to be the best case
for (int i = 0; i < bestData.length; i++)
{
SourceData[i] = bestData[i];
}
}
else if (choice == 2)
{ // "Worst Case" is selected
// Reset the source data to be the worst case
for (int i = 0; i < worstData.length; i++)
{
SourceData[i] = worstData[i];
}
}
}
}
Output:
Run this applet to see the output
More Java Programs: