InformationFrame.java

package edu.hawaii.ics.yucheng;

import java.awt.Dimension;
import java.awt.Toolkit;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * A dialog frame that shows information about a graph and its solution.
 */
@SuppressWarnings("serial")
class InformationFrame extends JFrame {

    /** The battery level. */
    private int                 myBattery;

    /** The string builder. */
    private StringBuilder       myBuilder;

    /** The graph. */
    private final Graph         myGraph;

    /** The vertex index. */
    private int                 myIndex;

    /** A flag indicating if the solver was canceled. */
    private final boolean       myIsCanceled;

    /** A flag indicating if the solver is working. */
    private final boolean       myIsWorking;

    /** The priority sum. */
    private int                 myPriority;

    /** The solution. */
    private final GraphSolution mySolution;

    /** The current vertex visited. */
    private Vertex              myVertex;

    /** The flag indicating if the device was on at the current vertex. */
    private boolean             myWorking;


    /**
     * Initializes a new instance of the class.
     * 
     * @param graph The graph.
     * 
     * @param solution The solution.
     * 
     * @param isWorking A flag indicating if the solver is working.
     * 
     * @param isCanceled A flag indicating if the solver was canceled.
     */
    public InformationFrame(final Graph graph, final GraphSolution solution,
        final boolean isWorking, final boolean isCanceled) {

        myGraph = graph;
        mySolution = solution;
        myIsWorking = isWorking;
        myIsCanceled = isCanceled;

        setTitle("Graph Details");
        setSize(640, 480);

        // Center the popup window in the screen.
        final Toolkit toolkit = Toolkit.getDefaultToolkit();
        final Dimension size = toolkit.getScreenSize();
        final int x = (size.width - 640) / 2;
        final int y = (size.height - 480) / 2;
        setLocation(x, y);

        // Create a text area for the graph details.
        final JTextArea area = new JTextArea();
        area.setTabSize(6);
        area.setLineWrap(true);
        area.setWrapStyleWord(true);
        area.setCaretPosition(0);
        add(new JScrollPane(area));

        // Add the graph detail.
        myBuilder = new StringBuilder();
        buildIntroduction();
        buildObstacles();
        buildPriorities();
        buildConsumptions();

        if (mySolution == null)
            myBuilder.append("\nThis graph has not yet been solved.");
        else
            buildSolution();

        area.setText(myBuilder.toString());
        area.setCaretPosition(0);
        myBuilder = null;
    }


    /**
     * Builds the battery consumption table.
     */
    private void buildConsumptions() {
        myBuilder.append("\nThe graph contains the following energy "
            + "consumption values:\n\n");

        buildDivider();

        for (int j = 0; j < myGraph.height; j++) {
            for (int i = 0; i < myGraph.width - 1; i++)
                myBuilder.append(myGraph.consumption(i, j) + "\t");
            myBuilder.append(myGraph.consumption(myGraph.width - 1, j) + "\n");
        }

        buildDivider();
    }


    /**
     * Builds a divider.
     */
    private void buildDivider() {
        for (int i = 0; i < myGraph.width * 6 - 5; i++)
            myBuilder.append("-");
        myBuilder.append("\n");
    }


    /**
     * Builds the introduction section.
     */
    private void buildIntroduction() {
        if (myGraph.url == null)
            myBuilder.append("This graph was generated randomly.  ");
        else
            myBuilder.append("This graph was downloaded from:\n\n" + myGraph.url
                + "\n\n");

        myBuilder.append("This graph is a " + myGraph.height + "x" + myGraph.width
            + " mesh.  The base is at (" + myGraph.base
            + "), and the initial battery capacity is " + myGraph.capacity + ".");
    }


    /**
     * Builds the obstacles table.
     */
    private void buildObstacles() {
        myBuilder.append("  The graph contains the following obstacles:\n\n");

        buildDivider();

        for (int j = 0; j < myGraph.height; j++) {
            for (int i = 0; i < myGraph.width - 1; i++)
                myBuilder.append(myGraph.isObstacle(i, j) ? "X\t" : ".\t");

            final boolean isObstacle = myGraph.isObstacle(myGraph.width - 1, j);
            myBuilder.append(isObstacle ? "X\n" : ".\n");
        }

        buildDivider();
    }


    /**
     * Builds the priorities table.
     */
    private void buildPriorities() {
        myBuilder.append("\nThe graph contains the following priorities:\n\n");

        buildDivider();

        for (int j = 0; j < myGraph.height; j++) {
            for (int i = 0; i < myGraph.width - 1; i++)
                myBuilder.append(myGraph.priority(i, j) + "\t");

            myBuilder.append(myGraph.priority(myGraph.width - 1, j) + "\n");
        }

        buildDivider();
    }


    /**
     * Builds the solution section.
     */
    private void buildSolution() {
        if (myIsWorking)
            myBuilder.append("\nThis graph is in the process of being solved, and "
                + "the best solution has not yet been found with certainty.  The "
                + "best solution found so far follows.");

        else if (myIsCanceled)
            myBuilder.append("\nThe attempt to solve this graph was canceled "
                + "before it was able to complete.  The best solution found "
                + "prior to this point follows.");

        else
            myBuilder.append("\nThis graph has been solved.");

        myBuilder.append("  The sum of the priorities of the visited vertices "
            + "is " + mySolution.goodness + ".");

        if (mySolution.sequenceLength() == 0) {
            myBuilder.append("  No vertices are visited in this solution.");
            return;
        }

        buildSolutionTableHeader();
        buildSolutionTable();
    }


    /**
     * Builds the solution table.
     */
    private void buildSolutionTable() {
        myIndex = 0;
        myPriority = 0;
        myBattery = myGraph.capacity;

        myWorking = false;
        for (int j = 0; j < mySolution.departureLength() - 1; j++) {
            myIndex++;
            myVertex = mySolution.departureAt(j);
            myBattery--;
            buildSolutionTableRow(false);
        }

        myWorking = true;
        for (int j = 0; j < mySolution.sequenceLength(); j++) {
            myIndex++;
            myVertex = mySolution.sequenceAt(j);
            myBattery -= 1 + myGraph.consumption(myVertex.x, myVertex.y);
            myPriority += myGraph.priority(myVertex.x, myVertex.y);
            buildSolutionTableRow(false);
        }

        myWorking = false;
        for (int j = 1; j < mySolution.arrivalLength(); j++) {
            myIndex++;
            myVertex = mySolution.arrivalAt(j);
            myBattery--;
            buildSolutionTableRow(j + 1 == mySolution.arrivalLength());
        }

        myIndex = 0;
        myPriority = 0;
        myBattery = 0;
        myVertex = null;
    }


    /**
     * Builds the solution table header.
     */
    private void buildSolutionTableHeader() {
        myBuilder.append("  The following table lists each vertex visited along "
            + "with the condition of the device at that vertex.  The "
            + "columns of the table are as follows:\n"
            + "\n  i    vertex number in path"
            + "\n  Wi   device working flag (on or off)"
            + "\n  Vi   vertex location in the graph"
            + "\n  Pi   priority of this vertex"
            + "\n  Bi   battery consumption of this vertex"
            + "\n  P    sum of priorities after visiting this vertex"
            + "\n  B    battery remaining after visiting this vertex"
            + "\n  %    battery percentage after visiting this vertex"
            + "\n\ni\tWi\tVi\tPi\tBi\tP\tB\t%\n"
            + "-----\t-----\t-----\t-----\t-----\t-----\t-----\t-----\n");
    }


    /**
     * Builds a row in the solution table.
     * 
     * @param lastRow True indicates this is the last row.
     */
    private void buildSolutionTableRow(final boolean lastRow) {

        myBuilder.append(myIndex + "\t" + (myWorking ? "on" : "off") + "\t"
            + myVertex);

        if (!lastRow) {
            myBuilder.append("\t");

            if (!myWorking)
                myBuilder.append("(0)\t(1)\t");

            else {
                final int priority = myGraph.priority(myVertex.x, myVertex.y);
                final int consumption = myGraph.consumption(myVertex.x, myVertex.y);
                myBuilder.append(priority + "\t" + consumption + "\t");
            }

            final int percent = myBattery * 100 / myGraph.capacity;
            myBuilder.append(myPriority + "\t" + myBattery + "\t" + percent);
        }

        myBuilder.append("\n");
    }
}
Valid HTML 4.01 Valid CSS