//****************************************************************************
// CLASS NAME:	DesignPanel.java
//
// AUTHOR:	Rick Brink
//		rick@mail.csh.rit.edu
//		http://www.csh.rit.edu/~rick
//
// VERSION:	1.0
//
// HISTORY:	4/16/96		Initial Version
//         10/06/96     Modified for support of multi-point arcs
//
// COPYRIGHT INFORMATION:
//
// This program and the Java source is in the public domain.
// Permission to use, copy, modify, and distribute this software
// and its documentation for NON-COMMERCIAL purposes and
// without fee is hereby granted.
//
//    Copyright 1996
//
//    Rick Brink
//    1266 Brighton-Henrietta Townline Rd.
//    Rochester, NY 14623
//
// DISCLAIMER:
//
// The author claims no responsibility for any damage, direct or indirect,
// to any harware or software as a result of using this program.
//****************************************************************************

import java.awt.Panel;
import java.awt.Event;
import java.awt.Dimension;
import java.awt.Scrollbar;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.FontMetrics;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.PrintStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Vector;
import java.util.StringTokenizer;

class DesignPanel extends Panel {
    /** Controls horizontal scrolling of the DesignPanel **/
    private protected Scrollbar horizontalScrollbar_;

    /** Controls vertical scrolling of the DesignPanel **/
    private protected Scrollbar verticalScrollbar_;

    /** Used to write the Petri Net design to a file **/
    private protected FileOutputStream fileOutputStream_;

    /** Used to read a Petri Net design file **/
    private protected FileInputStream fileInputStream_;

    /** Used to format the output file stream **/
    private protected PrintStream printStream_;

    /** Used to format the input file stream **/
    private protected DataInputStream dataInputStream_;

    /**
      * Local handle to the PetriTool object for accessing
      * global design parameters and the StatusPanel for
      * messages to the user
    **/
    private protected PetriTool petriTool_;

    /** Temporary handle to an Arc when Arcs are drawn **/
    private protected Arc newArc_ = null;

    /** Vector of all Places in the design **/
    protected Vector placeVector_;

    /** Vector of all Tokens in the design **/
    protected Vector tokenVector_;

    /** Vector of all Transitions in the design **/
    protected Vector transitionVector_;

    /** Vector of all Arcs in the design **/
    protected Vector arcVector_;

    /** Vector of all Captions in the design **/
    private protected Vector captionVector_;

    /** Clipboard Vector of all Places selected for Cut/Copy/Paste **/
    private protected Vector placeVectorBuf_;

    /** Clipboard Vector of all Tokens selected for Cut/Copy/Paste **/
    private protected Vector tokenVectorBuf_;

    /** Clipboard Vector of all Transitions selected for Cut/Copy/Paste **/
    private protected Vector transitionVectorBuf_;

    /** Clipboard Vector of all Arcs selected for Cut/Copy/Paste **/
    private protected Vector arcVectorBuf_;

    /** Clipboard Vector of all Captions selected for Cut/Copy/Paste **/
    private protected Vector captionVectorBuf_;

    /** Used by horizontal Scrollbar to determine current X position **/
    private protected int gridXOffset_ = 0;

    /** Used by vertical Scrollbar to determine current Y position **/
    private protected int gridYOffset_ = 0;

    /** Used for translating X coordinates for scrollbar **/
    private protected int dx = 0;

    /** Used for translating Y coordinates for scrollbar **/
    private protected int dy = 0;

    /** Currently selected button in the ControlPanel **/
    private protected String selectedButton_;


    /** Slope of the Arc being drawn **/
    private protected double arcSlope_;

    /**
      * Number of pixels to move when a Scrollbar SCROLL_LINE_UP
      * or SCROLL_LINE_DOWN event occurs
    **/
    private protected final int LINE_INCREMENT = 50;

    /**
      * Number of pixels to move when a Scrollbar SCROLL_PAGE_UP
      * or SCROLL_PAGE_DOWN event occurs
    **/
    private protected final int PAGE_INCREMENT = 250;

    /** Vector representing the initial marking of the Petri Net **/
    private protected Vector initialMarkingVector_;

    /** Indicates the x coordinate of the dangling component **/
    private protected int xDangle_;

    /** Indicates the y coordinate of the dangling component **/
    private protected int yDangle_;

    /** Indicates if the current design is valid, i.e. no dangling components **/
    private protected boolean validDesign_ = false;

    /**
      * Construct a new DesignPanel.  This is where the Petri Net
      * design will be drawn by the user.
    **/
    public DesignPanel(PetriTool app) {
        petriTool_ = app;
        setLayout( new BorderLayout());
        super.setLayout( new BorderLayout());

        // Add scrollbars
        verticalScrollbar_ = new Scrollbar(Scrollbar.VERTICAL);

        // Under JDK1.02 on Win95, the set increments do not work
        verticalScrollbar_.setLineIncrement (LINE_INCREMENT);
        verticalScrollbar_.setPageIncrement (PAGE_INCREMENT);
        add( "East", verticalScrollbar_);

        horizontalScrollbar_ = new Scrollbar(Scrollbar.HORIZONTAL);

        // Under JDK1.02 on Win95, the set increments do not work
        horizontalScrollbar_.setLineIncrement (LINE_INCREMENT);
        horizontalScrollbar_.setPageIncrement (PAGE_INCREMENT);
        add( "South", horizontalScrollbar_);
        repaint();

        // Initialize vectors for design
        placeVector_ = new Vector();
        tokenVector_ = new Vector();
        transitionVector_ = new Vector();
        arcVector_ = new Vector();
        captionVector_ = new Vector();

        // Initialize buffer vectors for design cut, copy, paste
        placeVectorBuf_ = new Vector();
        tokenVectorBuf_ = new Vector();
        transitionVectorBuf_ = new Vector();
        arcVectorBuf_ = new Vector();
        captionVectorBuf_ = new Vector();

        // Initialize values for simulation
        initialMarkingVector_ = new Vector();
    }

    /**
      * Save the necessary design information to a file by calling
      * the saveToFile() routines of all the design components.
      * Comments in the design file start with a '#'.
    **/
    public void saveDesign(String filename) {
        StatusMessage("Saving to file " + filename);

        // Create an output steam
        try {
            fileOutputStream_ = new FileOutputStream(filename);
            printStream_ = new PrintStream(fileOutputStream_);

            // Print header and system setup values
            petriTool_.saveToFile(printStream_);

            // Print Places
            printStream_.println("#");
            printStream_.println("# PLACES: x, y, label");
            for (int i__ = 0; i__ < placeVector_.size(); i__++) {
                Place tempPlace__ = (Place) placeVector_.
                                        elementAt(i__);
                tempPlace__.saveToFile(printStream_);
            }

            // Print Transitions
            printStream_.println("#");
            printStream_.println("# TRANSITIONS: x, y, label");
            for (int i__ = 0; i__ < transitionVector_.size(); i__++) {
                Transition tempTransition__ = (Transition) transitionVector_.
                                        elementAt(i__);
                tempTransition__.saveToFile(printStream_);
            }

            // Print Tokens
            printStream_.println("#");
            printStream_.println("# TOKENS: x, y, tokensRepresented");
            for (int i__ = 0; i__ < tokenVector_.size(); i__++) {
                Token tempToken__ = (Token) tokenVector_.
                                        elementAt(i__);
                tempToken__.saveToFile(printStream_);
            }

            // Print Arcs
            printStream_.println("#");
            printStream_.println("# ARCS: number Coordinates, x1, y1, ... xN, yN, " +
                                 "x1Draw, y1Draw, ... xNDraw, yNDraw, " +
                                 "region, tokensToEnable, start Component");
            for (int i__ = 0; i__ < arcVector_.size(); i__++) {
                Arc tempArc__ = (Arc) arcVector_.
                                        elementAt(i__);
                tempArc__.saveToFile(printStream_);
            }

            // Print Captions
            printStream_.println("#");
            printStream_.println("# CAPTIONS: x, y, actualSize, fontName, " +
                                 "fontStyle, fontSize, ~^~captionText");
            for (int i__ = 0; i__ < captionVector_.size(); i__++) {
                Caption tempCaption__ = (Caption) captionVector_.
                                        elementAt(i__);
                tempCaption__.saveToFile(printStream_);
            }
            printStream_.println("# END OF DESIGN FILE");
        }
        catch (IOException e) {
            StatusMessage("Error saving design.");
        }

        try {
            fileOutputStream_.close();
        }
        catch (IOException e) {
            StatusMessage("Error saving design.");
        }

    }

    /**
      * Restore a design from a file.  The variables of a particular
      * component are separated by commas, with each component starting
      * on a new line.  The components are grouped next to like
      * components, with comments separating different types of
      * components.  The design file ends with a string
      * '# END OF DESIGN FILE'
    **/
    public void openDesign(String filename) {
        newDesign();
        StatusMessage("Opening file " + filename);
        // Create an input steam
        try {
            fileInputStream_ = new FileInputStream(filename);
            dataInputStream_ = new DataInputStream(fileInputStream_);

            // Load header and system setup values
            petriTool_.loadFromFile(dataInputStream_);

            // Load Places
            // Elliminate any comments
            String input__ = dataInputStream_.readLine();
            while ((input__.startsWith("#")) &&
                   (!input__.startsWith("# END OF DESIGN FILE"))) {
                input__ = dataInputStream_.readLine();
            }
            StringTokenizer tokenizer__ = new StringTokenizer(input__, ", \t\n\r");

            while (tokenizer__.nextToken().equals("Place:")) {
                Place tempPlace__ = new Place();
                tempPlace__.loadFromFile(tokenizer__);
                placeVector_.addElement(tempPlace__);
                input__ = dataInputStream_.readLine();
                tokenizer__ = new StringTokenizer(input__, ", \t\n\r");
            }

            // Load Transitions
            // Elliminate any comments
            while ((input__.startsWith("#")) &&
                   (!input__.startsWith("# END OF DESIGN FILE"))) {
                input__ = dataInputStream_.readLine();
            }
            tokenizer__ = new StringTokenizer(input__, ", \t\n\r");

            while (tokenizer__.nextToken().equals("Transition:")) {
                Transition tempTransition__ = new Transition();
                tempTransition__.loadFromFile(tokenizer__);
                transitionVector_.addElement(tempTransition__);
                input__ = dataInputStream_.readLine();
                tokenizer__ = new StringTokenizer(input__, ", \t\n\r");
            }

            // Load Tokens
            // Elliminate any comments
            while ((input__.startsWith("#")) &&
                   (!input__.startsWith("# END OF DESIGN FILE"))) {
                input__ = dataInputStream_.readLine();
            }
            tokenizer__ = new StringTokenizer(input__, ", \t\n\r");

            while (tokenizer__.nextToken().equals("Token:")) {
                Token tempToken__ = new Token();
                tempToken__.loadFromFile(tokenizer__);
                tokenVector_.addElement(tempToken__);
                input__ = dataInputStream_.readLine();
                tokenizer__ = new StringTokenizer(input__, ", \t\n\r");
            }

            // Load Arcs
            // Elliminate any comments
            while ((input__.startsWith("#")) &&
                   (!input__.startsWith("# END OF DESIGN FILE"))) {
                input__ = dataInputStream_.readLine();
            }
            tokenizer__ = new StringTokenizer(input__, ", \t\n\r");

            while (tokenizer__.nextToken().equals("Arc:")) {
                Arc tempArc__ = new Arc();
                tempArc__.loadFromFile(tokenizer__);
                arcVector_.addElement(tempArc__);
                input__ = dataInputStream_.readLine();
                tokenizer__ = new StringTokenizer(input__, ", \t\n\r");
            }

            // Load Captions
            // Elliminate any comments
            while ((input__.startsWith("#")) &&
                   (!input__.startsWith("# END OF DESIGN FILE"))) {
                input__ = dataInputStream_.readLine();
            }
            tokenizer__ = new StringTokenizer(input__, ", \t\n\r");

            while (!tokenizer__.nextToken().startsWith("#")) {
                Caption tempCaption__ = new Caption();
                tempCaption__.loadFromFile(tokenizer__, input__);
                captionVector_.addElement(tempCaption__);
                input__ = dataInputStream_.readLine();
                tokenizer__ = new StringTokenizer(input__, ", \t\n\r");
            }
        }
        catch (IOException e) {
            StatusMessage("Error loading design.");
        }

        try {
            fileInputStream_.close();
        }
        catch (IOException e) {
            StatusMessage("Error loading design.");
        }

        // Re-calculate the initial marking
        setInitialMarking();

        // Set Place and Transition labels to
        // maximum current label plus one
        int maxLabel__ = 0;
        for (int i__ = 0; i__ < placeVector_.size(); i__++) {
            Place place__ = (Place) placeVector_.elementAt(i__);
            if (place__.getLabel() > maxLabel__) {
                maxLabel__ = place__.getLabel();
            }
        }
        petriTool_.setPlaceLabel(maxLabel__+1);

        maxLabel__ = 0;
        for (int i__ = 0; i__ < transitionVector_.size(); i__++) {
            Transition transition__ = (Transition) transitionVector_.elementAt(i__);
            if (transition__.getLabel() > maxLabel__) {
                maxLabel__ = transition__.getLabel();
            }
        }
        petriTool_.setTransitionLabel(maxLabel__+1);

        repaint();
    }

    /**
      * Returns the Vector representing the initial marking
    **/
    public Vector getInitialMarking() {
        return ((Vector)initialMarkingVector_.clone());
    }

    /**
      * Search through the Vector of Places and set the
      * initialConditionVector to the initial marking.
    **/
    public void setInitialMarking() {
        initialMarkingVector_ = new Vector();
        int gridStep__ = petriTool_.gridStep_;

        for (int i__ = 0; i__ < placeVector_.size(); i__++) {
            Place tempPlace__ = (Place) placeVector_.elementAt(i__);
            int x__ = tempPlace__.getXCoordinate() * gridStep__;
            int y__ = tempPlace__.getYCoordinate() * gridStep__;
            if (tokenOccupies(x__, y__)) {
                Token token__ = getToken(x__, y__);
                tempPlace__.setToken(token__);
            }
            else {
                tempPlace__.setToken(null);
            }
            if (!tempPlace__.tokenInitialized_) {
                initialMarkingVector_.addElement(new Integer(0));
            }
            else {
                initialMarkingVector_.addElement(new Integer(
                    tempPlace__.token_.getTokensRepresented()));
            }
        }
    }


    /**
      * Returns the dimension of the design panel.
    **/
    public Dimension getDimension() {
        return(size());
    }

    /**
      * Returns the maximum X and Y coordinate of any component
      * currently on the panel.  Note that the two coordinates
      * are not necessarily from the same component.
    **/
    public Dimension getMaxDimension() {
        Dimension maxDim__ = new Dimension(0,0);
        for (int i__ = 0; i__ < placeVector_.size(); i__++) {
            Place tempPlace__ = (Place) placeVector_.
                                        elementAt(i__);
            maxDim__.width = Math.max (maxDim__.width,
                                       tempPlace__.getXCoordinate());
            maxDim__.height = Math.max (maxDim__.height,
                                        tempPlace__.getYCoordinate());

        }
        for (int i__ = 0; i__ < transitionVector_.size(); i__++) {
            Transition tempTransition__ = (Transition) transitionVector_.
                                        elementAt(i__);
            maxDim__.width = Math.max (maxDim__.width,
                                       tempTransition__.getXCoordinate());
            maxDim__.height = Math.max (maxDim__.height,
                                        tempTransition__.getYCoordinate());

        }
        return (maxDim__);
    }

    /**
      * Returns the minimum X and Y coordinate of any component
      * currently on the panel.  Note that the two coordinates
      * are not necessarily from the same component.
    **/
    public Dimension getMinDimension() {
        Dimension minDim__ = new Dimension(size().width, size().height);
        for (int i__ = 0; i__ < placeVector_.size(); i__++) {
            Place tempPlace__ = (Place) placeVector_.
                                        elementAt(i__);
            minDim__.width = Math.min (minDim__.width,
                                       tempPlace__.getXCoordinate());
            minDim__.height = Math.min (minDim__.height,
                                        tempPlace__.getYCoordinate());

        }
        for (int i__ = 0; i__ < transitionVector_.size(); i__++) {
            Transition tempTransition__ = (Transition) transitionVector_.
                                        elementAt(i__);
            minDim__.width = Math.min (minDim__.width,
                                       tempTransition__.getXCoordinate());
            minDim__.height = Math.min (minDim__.height,
                                        tempTransition__.getYCoordinate());

        }
        return (minDim__);
    }

    /**
      * Handle Scrollbar events for this Panel, all other events
      * propagate up with super.handleEvent
    **/
    public boolean handleEvent(Event e) {
        if (e.id == Event.WINDOW_MOVED) {
            Dimension d = size();
            int step__ = petriTool_.gridStep_;
            int width__ = petriTool_.gridWidth_;
            int height__ = petriTool_.gridHeight_;

            horizontalScrollbar_.setValues(horizontalScrollbar_.getValue(), width__, 0,width__);
            verticalScrollbar_.setValues(verticalScrollbar_.getValue(), height__, 0,height__);
        }
        else if (e.id == Event.SCROLL_ABSOLUTE ||
                 e.id == Event.SCROLL_LINE_DOWN ||
                 e.id == Event.SCROLL_LINE_UP ||
                 e.id == Event.SCROLL_PAGE_DOWN ||
                 e.id == Event.SCROLL_PAGE_UP) {
            translate(horizontalScrollbar_.getValue(), verticalScrollbar_.getValue());
            return true;
        }

        return super.handleEvent(e);
   }

    /**
      * Assigns values to the two translation variables dx and dy.
    **/
   public void translate (int x, int y) {
       dx = x;
       dy = y;
       repaint();
   }


    /**
      * Display a status message in the status panel
    **/
    public void StatusMessage(String msg) {
        petriTool_.statusPanel_.StatusMessage(msg);
    }

    /**
      * Set new values of the Scrollbars according to the visible area
    **/
    public void adjustScrollbars() {

        String OSName;
        gridXOffset_ = horizontalScrollbar_.getValue();
        gridYOffset_ = verticalScrollbar_.getValue();
        int gridStep__ = petriTool_.gridStep_;

        int VisibleXGridPoints = (size().width / gridStep__) - 1;
        int VisibleYGridPoints = (size().height / gridStep__) - 1;

        // Determine OS because of scrollbar implementation differences
        // between Win95/NT and other operating systems.
        OSName = System.getProperty("os.name");
        if (OSName.equals ("Windows 95") ||
            OSName.equals ("Windows NT")) {
            verticalScrollbar_.setValues(gridYOffset_, VisibleYGridPoints, 0, petriTool_.maxYPoints_ + 1);
            horizontalScrollbar_.setValues(gridXOffset_, VisibleXGridPoints, 0, petriTool_.maxXPoints_ + 1);
        } else {
            verticalScrollbar_.setValues(gridYOffset_, VisibleYGridPoints, 0, petriTool_.maxYPoints_ + 1 - VisibleYGridPoints);
            horizontalScrollbar_.setValues(gridXOffset_, VisibleXGridPoints, 0, petriTool_.maxXPoints_ + 1 - VisibleXGridPoints);
        }

    }

    /**
      * Set new values of the Scrollbars for the Fit to Window command
    **/
    public void adjustScrollbars(int minX, int minY) {

        String OSName;
        int gridStep__ = petriTool_.gridStep_;

        int VisibleXGridPoints = (size().width / gridStep__) - 1;
        int VisibleYGridPoints = (size().height / gridStep__) - 1;

        // Determine OS because of scrollbar implementation differences
        // between Win95/NT and other operating systems.
        OSName = System.getProperty("os.name");
        if (OSName.equals ("Windows 95") ||
            OSName.equals ("Windows NT")) {
            verticalScrollbar_.setValues(minY, VisibleYGridPoints, 0, petriTool_.maxYPoints_ + 1);
            horizontalScrollbar_.setValues(minX, VisibleXGridPoints, 0, petriTool_.maxXPoints_ + 1);
        } else {
            verticalScrollbar_.setValues(minY, VisibleYGridPoints, 0, petriTool_.maxYPoints_ + 1 - VisibleYGridPoints);
            horizontalScrollbar_.setValues(minX, VisibleXGridPoints, 0, petriTool_.maxXPoints_ + 1 - VisibleXGridPoints);
        }
        translate(horizontalScrollbar_.getValue(), verticalScrollbar_.getValue());

    }

    /**
      * Paint the DesignPanel and all of its components to the screen
    **/
    public void paint(Graphics g) {
        g.translate(-dx, -dy);
        adjustScrollbars();
        int step__ = petriTool_.gridStep_;
        int width__ = petriTool_.gridWidth_;
        int height__ = petriTool_.gridHeight_;
        Color foregroundColor__ = petriTool_.foregroundColor_;
        g.setColor (petriTool_.backgroundColor_);
        g.fillRect (step__ / 2, step__ / 2,
                    width__ * step__, height__ * step__);

        if (petriTool_.showGrid_) {
            g.setColor (petriTool_.gridColor_);

            // Draw the background grid
            for (int x = 1; x <= width__; x++) {
                for (int y = 1; y <= height__; y++) {
                    g.drawLine (x * step__, y * step__,
                                x * step__, y * step__);
                }
            }
        }

        // Draw the border
        g.setColor (petriTool_.borderColor_);
        g.drawRect (step__ / 2, step__ / 2, step__ * width__,
                    step__ * height__);

        // Draw the Places
        for (int i__ = 0; i__ < placeVector_.size(); i__++) {
            Place tempPlace__ = (Place) placeVector_.elementAt(i__);
            tempPlace__.draw(g, step__, foregroundColor__,
                             petriTool_.placeLabels_);
        }

        // Draw the Transitions
        for (int i__ = 0; i__ < transitionVector_.size(); i__++) {
            Transition tempTransition__ = (Transition) transitionVector_.
                                        elementAt(i__);
            tempTransition__.draw(g, step__, foregroundColor__,
                                  petriTool_.transitionLabels_);
        }

        // Draw the Tokens
        for (int i__ = 0; i__ < tokenVector_.size(); i__++) {
            Token tempToken__ = (Token) tokenVector_.elementAt(i__);
            tempToken__.draw(g, step__, foregroundColor__);
        }

        // Draw the Arcs
        for (int i__ = 0; i__ < arcVector_.size(); i__++) {
            Arc tempArc__ = (Arc) arcVector_.elementAt(i__);
            tempArc__.draw(g, step__, foregroundColor__);
        }

        // Draw the Captions
        for (int i__ = 0; i__ < captionVector_.size(); i__++) {
            Caption tempCaption__ = (Caption) captionVector_.elementAt(i__);
            tempCaption__.draw(g, step__, petriTool_.captionColor_);
        }

    }

    /**
      * User selected "New", clear out all design panel elements
    **/
    public void newDesign() {
        placeVector_.removeAllElements();
        tokenVector_.removeAllElements();
        transitionVector_.removeAllElements();
        arcVector_.removeAllElements();
        captionVector_.removeAllElements();
        setInitialMarking();
        adjustScrollbars(0,0);
        StatusMessage("New design initialized.");
        repaint();
    }


    /**
      * Determine if the coordinate (x,y) is within the border.
    **/
    public boolean validDimension (int x, int y) {
        int step__ = petriTool_.gridStep_;
        int width__ = petriTool_.gridWidth_;
        int height__ = petriTool_.gridHeight_;
        if ((x >= step__) && (x <= width__*step__ - step__)) {
            if ((y >= step__) && (y <= height__*step__ - step__)) {
                return (true);
            }
        }
        return (false);
    }

    /**
      * Determine if grid square with upper left corner
      * coordinates (x,y) is already occupied.
    **/
    public boolean gridSpaceOccupied(int x, int y) {
        if (placeOccupies (x, y, false) || transitionOccupies (x, y, false)) {
            return (true);
        }
        else {
            return (false);
        }
    }

    /**
      * Check to see if two sets of coordinates (x1, y1) and
      * (x2, y2) are within one grid square of each other,
      * and return true if they are.  If the boolean argument
      * to this function is true, only check to see if the
      * two sets of coordinates are equal.
    **/
    public boolean checkBorderingGridSquares (int x1, int y1,
                                              int x2, int y2,
                                              boolean exact) {
        int x__ = x1;
        int y__ = y1;
        int x = x2;
        int y = y2;

    	// Check the space that was chosen
        if (x__ == x) {
            if (y__ == y) {
                return (true);
            }
        }
        // If the caller only wanted to check the selected grid space
        if (exact) {
            return (false);
        }
        // Check the space up and to the left
        if (x__ == x - 1) {
            if (y__ == y - 1) {
                return (true);
            }
        }
        // Check the space directly above
        if (x__ == x) {
            if (y__ == y - 1) {
                return (true);
            }
        }
        // Check the space up and to the right
        if (x__ == x + 1) {
            if (y__ == y - 1) {
                return (true);
            }
        }
        // Check the space to the right
        if (x__ == x + 1) {
            if (y__ == y) {
                return (true);
            }
        }
        // Check the space down and to the right
        if (x__ == x + 1) {
            if (y__ == y + 1) {
                return (true);
            }
        }
        // Check the space directly below
        if (x__ == x) {
            if (y__ == y + 1) {
                return (true);
            }
        }
        // Check the space down and to the left
        if (x__ == x - 1) {
            if (y__ == y + 1) {
                return (true);
            }
        }
        // Check the space directly to the left
        if (x__ == x - 1) {
            if (y__ == y) {
                return (true);
            }
        }
        return (false);
    }

    /**
      * Determine if grid square with upper left corner
      * coordinates (x,y) is occupied by a Place
    **/
    public boolean placeOccupies (int x, int y, boolean exact) {
        x = x / petriTool_.gridStep_;
        y = y / petriTool_.gridStep_;
        for (int i__ = 0; i__ < placeVector_.size(); i__++) {
            Place tempPlace__ = (Place)placeVector_.elementAt(i__);
            int x__ = tempPlace__.getXCoordinate();
            int y__ = tempPlace__.getYCoordinate();
            if (checkBorderingGridSquares(x__, y__, x, y, exact)) {
            	return (true);
            }
        }
        return (false);
    }


    /**
      * Checks to see if any Arc starts at (x,y)
    **/
    public boolean arcStartsAt (int x, int y, boolean exact) {
        x = x / petriTool_.gridStep_;
        y = y / petriTool_.gridStep_;
        for (int i__ = 0; i__ < arcVector_.size(); i__++) {
            Arc tempArc__ = (Arc)arcVector_.elementAt(i__);
            int x__ = tempArc__.getFirstXCoordinate();
            int y__ = tempArc__.getFirstYCoordinate();
            if (checkBorderingGridSquares(x__, y__, x, y, exact)) {
            	return (true);
            }
        }
        return (false);
    }

    /**
      * Checks to see if any Arc ends at (x,y)
    **/
    public boolean arcEndsAt (int x, int y, boolean exact) {
        x = x / petriTool_.gridStep_;
        y = y / petriTool_.gridStep_;
        for (int i__ = 0; i__ < arcVector_.size(); i__++) {
            Arc tempArc__ = (Arc)arcVector_.elementAt(i__);
            int x__ = tempArc__.getLastXCoordinate();
            int y__ = tempArc__.getLastYCoordinate();
            if (checkBorderingGridSquares(x__, y__, x, y, exact)) {
            	return (true);
            }

        }
        return (false);
    }


    /**
      * Return the Place occupying grid square with
      * upper left corner coordinates (x,y)
    **/
    public Place getPlace (int x, int y) {
        x = x / petriTool_.gridStep_;
        y = y / petriTool_.gridStep_;
        for (int i__ = 0; i__ < placeVector_.size(); i__++) {
            Place tempPlace__ = (Place)placeVector_.elementAt(i__);
            if ((x == tempPlace__.getXCoordinate()) &&
                (y == tempPlace__.getYCoordinate())) {
                return (tempPlace__);
            }
        }
        return (null);
    }

    /**
      * Return the Transition occupying grid square with
      * upper left corner coordinates (x,y)
    **/
    public Transition getTransition (int x, int y) {
        x = x / petriTool_.gridStep_;
        y = y / petriTool_.gridStep_;
        for (int i__ = 0; i__ < transitionVector_.size(); i__++) {
            Transition tempTransition__ = (Transition)transitionVector_.elementAt(i__);
            if ((x == tempTransition__.getXCoordinate()) &&
                (y == tempTransition__.getYCoordinate())) {
                return (tempTransition__);
            }
        }
        return (null);
    }

    /**
      * Determine if grid square with upper left corner
      * coordinates (x,y) is occupied by a Transition
    **/
    public boolean transitionOccupies (int x, int y, boolean exact) {
        x = x / petriTool_.gridStep_;
        y = y / petriTool_.gridStep_;
        for (int i__ = 0; i__ < transitionVector_.size(); i__++) {
            Transition tempTransition__ = (Transition)transitionVector_.elementAt(i__);
            int x__ = tempTransition__.getXCoordinate();
            int y__ = tempTransition__.getYCoordinate();
            if (checkBorderingGridSquares(x__, y__, x, y, exact)) {
            	return(true);
            }
        }
        return (false);
    }

    /**
      * Determine if grid square with upper left corner
      * coordinates (x,y) is occupied by a Token
    **/
    public boolean tokenOccupies (int x, int y) {
        x = x / petriTool_.gridStep_;
        y = y / petriTool_.gridStep_;
        for (int i__ = 0; i__ < tokenVector_.size(); i__++) {
            Token tempToken__ = (Token)tokenVector_.elementAt(i__);

            if ((x == tempToken__.getXCoordinate()) &&
                (y == tempToken__.getYCoordinate())) {
                    return (true);
            }
        }
        return (false);
    }

    /**
      * Return the Token occupying grid square with
      * upper left corner coordinates (x,y)
    **/
    public Token getToken (int x, int y) {
        x = x / petriTool_.gridStep_;
        y = y / petriTool_.gridStep_;
        for (int i__ = 0; i__ < tokenVector_.size(); i__++) {
            Token tempToken__ = (Token)tokenVector_.elementAt(i__);
            if ((x == tempToken__.getXCoordinate()) &&
                (y == tempToken__.getYCoordinate())) {
                return (tempToken__);
            }
        }
        return (null);
    }

    /**
      * Calls the adjustSize(double) routine of all the Caption
      * components when the size of the grid changes during
      * Zoom In/Out events.
    **/
    public void adjustFonts(double factor) {
        for (int i__ = 0; i__ < captionVector_.size(); i__++) {
            Caption tempCaption__ = (Caption) captionVector_.
                                        elementAt(i__);
            tempCaption__.adjustSize(factor);
        }
    }






    /**
      * This routine is called when the user is performing a
      * select operation in a grid space with both a Place
      * and a Token.  It returns true if the location of
      * the selection is outside the area of the Token.
    **/
    public boolean selectPlaceOverToken (int x, int y) {
        int gridStep__ = petriTool_.gridStep_;
        int xRem__ = x % gridStep__;
        int yRem__ = y % gridStep__;

        int upperLimit__ = gridStep__ / 4;
        int lowerLimit__ = gridStep__ - gridStep__ / 4;

        if ((xRem__ > upperLimit__) && (xRem__ < lowerLimit__)) {
            if ((yRem__ > upperLimit__) && (yRem__ < lowerLimit__)) {
                return (false);
            }
        }
        return (true);

    }

    /**
      * When the user selects delete, all of the items currently
      * selected will be deleted by this routine.
    **/
    public boolean deleteSelected() {
        boolean itemsDeleted__ = false;
        Vector obsoleteXVector__ = new Vector();
        Vector obsoleteYVector__ = new Vector();
        int offset__ = 0;
        int maxRange__ = 0;
        int gridStep__ = petriTool_.gridStep_;

        // Remove all selected places
        maxRange__ = placeVector_.size();
        for (int i__ = 0; i__ < maxRange__ ; i__++) {
            Place tempPlace__ = (Place) placeVector_.elementAt(i__ - offset__);
            if (tempPlace__.isSelected()) {
                obsoleteXVector__.addElement
                    (new Integer(tempPlace__.getXCoordinate()));
                obsoleteYVector__.addElement
                    (new Integer(tempPlace__.getYCoordinate()));
                placeVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsDeleted__ = true;

            }
        }

        // Remove all selected transitions
        offset__ = 0;
        maxRange__ = transitionVector_.size();
        for (int i__ = 0; i__ < maxRange__; i__++) {
            Transition tempTransition__ = (Transition) transitionVector_.elementAt(i__ - offset__);
            if (tempTransition__.isSelected()) {
                obsoleteXVector__.addElement
                    (new Integer (tempTransition__.getXCoordinate()));
                obsoleteYVector__.addElement
                    (new Integer (tempTransition__.getYCoordinate()));
                transitionVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsDeleted__ = true;
            }
        }

        // Auto-select arcs that were connected to deleted places/transitions
        // Also, auto-select tokens contained in deleted places
        for (int j__ = 0; j__ < obsoleteXVector__.size(); j__++) {
            Integer tempX__ = (Integer) obsoleteXVector__.elementAt(j__);
            Integer tempY__ = (Integer) obsoleteYVector__.elementAt(j__);
            for (int i__ = 0; i__ < arcVector_.size(); i__++) {
                Arc tempArc__ = (Arc) arcVector_.elementAt(i__);

                if ((tempArc__.getFirstXCoordinate() == tempX__.intValue()) &&
                    (tempArc__.getFirstYCoordinate() == tempY__.intValue())) {
                            tempArc__.setSelected(true);
                }
                else if ((tempArc__.getLastXCoordinate() == tempX__.intValue()) &&
                        (tempArc__.getLastYCoordinate() == tempY__.intValue())) {
                            tempArc__.setSelected(true);
                }
            }
            for (int k__ = 0; k__ < tokenVector_.size(); k__++) {
                Token tempToken__ = (Token) tokenVector_.elementAt(k__);
                if ((tempToken__.getXCoordinate() == tempX__.intValue()) &&
                    (tempToken__.getYCoordinate() == tempY__.intValue())) {
                            tempToken__.setSelected(true);
                }
            }

        }

        // Remove all selected tokens
        offset__ = 0;
        maxRange__ = tokenVector_.size();
        for (int i__ = 0; i__ < maxRange__; i__++) {
            Token tempToken__ = (Token) tokenVector_.elementAt(i__ - offset__);
            if (tempToken__.isSelected()) {
                tokenVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsDeleted__ = true;
                // Update Places to set tokenInitialized = false
                if (placeOccupies(tempToken__.getXCoordinate() * gridStep__,
                                    tempToken__.getYCoordinate() * gridStep__, true)) {
                    Place tempPlace__ = getPlace(tempToken__.getXCoordinate() * gridStep__,
                                        tempToken__.getYCoordinate() * gridStep__);
                    tempPlace__.tokenInitialized_ = false;
                }
            }
        }

        // Remove all selected arcs
        offset__ = 0;
        maxRange__ = arcVector_.size();
        for (int i__ = 0; i__ < maxRange__; i__++) {
            Arc tempArc__ = (Arc) arcVector_.elementAt(i__ - offset__);
            if (tempArc__.isSelected()) {
                arcVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsDeleted__ = true;
            }
        }

        // Remove all selected captions
        offset__ = 0;
        maxRange__ = captionVector_.size();
        for (int i__ = 0; i__ < maxRange__; i__++) {
            Caption tempCaption__ = (Caption) captionVector_.
                                    elementAt(i__ - offset__);
            if (tempCaption__.isSelected()) {
                captionVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsDeleted__ = true;
            }
        }

        // Re-calculate the initial marking
        setInitialMarking();

        return(itemsDeleted__);
    }

    /**
      * When the user selects cut, all of the currently selected
      * components will be moved from the design Vectors to
      * a second buffer vector, where they may be reused by
      * the Paste command
    **/
    public boolean cutSelected() {
        boolean itemsCut__ = false;
        Vector obsoleteXVector__ = new Vector();
        Vector obsoleteYVector__ = new Vector();
        int offset__ = 0;
        int maxRange__ = 0;
        int gridStep__ = petriTool_.gridStep_;

        // Clear out all the clipboard buffers
        placeVectorBuf_.removeAllElements();
        transitionVectorBuf_.removeAllElements();
        arcVectorBuf_.removeAllElements();
        tokenVectorBuf_.removeAllElements();
        captionVectorBuf_.removeAllElements();

        // Remove all selected places
        maxRange__ = placeVector_.size();
        for (int i__ = 0; i__ < maxRange__ ; i__++) {
            Place tempPlace__ = (Place) placeVector_.elementAt(i__ - offset__);


            if (tempPlace__.isSelected()) {

                obsoleteXVector__.addElement
                    (new Integer(tempPlace__.getXCoordinate()));
                obsoleteYVector__.addElement
                    (new Integer(tempPlace__.getYCoordinate()));
                placeVectorBuf_.addElement(placeVector_.elementAt(i__- offset__));
                placeVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsCut__ = true;

                // Delete link to token if token not selected
                // in order to keep simulation vectors correct
                if (tokenOccupies(tempPlace__.getXCoordinate() * gridStep__,
                              tempPlace__.getYCoordinate() * gridStep__)) {
                    Token tempToken__ = getToken(tempPlace__.getXCoordinate() * gridStep__,
                                             tempPlace__.getYCoordinate()* gridStep__);
                    if (!tempToken__.isSelected()) {
                        tempPlace__.tokenInitialized_ = false;
                        tempPlace__.token_ = null;
                    }
                }
            }
        }

        // Remove all selected transitions
        offset__ = 0;
        maxRange__ = transitionVector_.size();
        for (int i__ = 0; i__ < maxRange__; i__++) {
            Transition tempTransition__ = (Transition) transitionVector_.elementAt(i__ - offset__);
            if (tempTransition__.isSelected()) {
                obsoleteXVector__.addElement
                    (new Integer (tempTransition__.getXCoordinate()));
                obsoleteYVector__.addElement
                    (new Integer (tempTransition__.getYCoordinate()));
                transitionVectorBuf_.addElement(transitionVector_.elementAt(i__- offset__));
                transitionVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsCut__ = true;
            }
        }

        // Remove all selected tokens
        offset__ = 0;
        maxRange__ = tokenVector_.size();
        for (int i__ = 0; i__ < maxRange__; i__++) {
            Token tempToken__ = (Token) tokenVector_.elementAt(i__ - offset__);
            if (tempToken__.isSelected()) {
                tokenVectorBuf_.addElement(tokenVector_.elementAt(i__- offset__));
                tokenVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsCut__ = true;
                // Update Places to set tokenInitialized = false
                if (placeOccupies(tempToken__.getXCoordinate() * gridStep__,
                                    tempToken__.getYCoordinate() * gridStep__, true)) {
                    Place tempPlace__ = getPlace(tempToken__.getXCoordinate() * gridStep__,
                                        tempToken__.getYCoordinate() * gridStep__);
                    tempPlace__.tokenInitialized_ = false;
                }
            }
        }
        // Remove all selected arcs
        offset__ = 0;
        maxRange__ = arcVector_.size();
        for (int i__ = 0; i__ < maxRange__; i__++) {
            Arc tempArc__ = (Arc) arcVector_.elementAt(i__ - offset__);
            if (tempArc__.isSelected()) {
                arcVectorBuf_.addElement(arcVector_.elementAt(i__- offset__));
                arcVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsCut__ = true;
            }
        }
        // Remove all selected captions
        offset__ = 0;
        maxRange__ = captionVector_.size();
        for (int i__ = 0; i__ < maxRange__; i__++) {
            Caption tempCaption__ = (Caption) captionVector_.
                                    elementAt(i__ - offset__);
            if (tempCaption__.isSelected()) {
                captionVectorBuf_.addElement(captionVector_.elementAt(i__- offset__));
                captionVector_.removeElementAt(i__ - offset__);
                offset__++;
                itemsCut__ = true;
            }
        }
        // Re-calculate the initial marking
        setInitialMarking();
        return (itemsCut__);
    }

    /**
      * This routine makes a copy of all selected components in the
      * design Vectors and places them into the buffer Vectors where
      * they may be reused by a Paste command
    **/
    public boolean copySelected() {
        boolean itemsCopied__ = false;
        int gridStep__ = petriTool_.gridStep_;

        // Clear out all of the clipboard buffers
        placeVectorBuf_.removeAllElements();
        transitionVectorBuf_.removeAllElements();
        arcVectorBuf_.removeAllElements();
        tokenVectorBuf_.removeAllElements();
        captionVectorBuf_.removeAllElements();

        // Copy all selected places
        for (int i__ = 0; i__ < placeVector_.size(); i__++) {
            Place tempPlace__ = (Place) placeVector_.elementAt(i__);
            Place copyPlace__ = (Place) tempPlace__.clone();
            if (tempPlace__.isSelected()) {
                placeVectorBuf_.addElement(copyPlace__);
                itemsCopied__ = true;

                // Delete link to token if token not selected
                // in order to keep simulation vectors correct
                if (tokenOccupies(copyPlace__.getXCoordinate() * gridStep__,
                              copyPlace__.getYCoordinate() * gridStep__)) {
                    Token tempToken__ = getToken(copyPlace__.getXCoordinate() * gridStep__,
                                             copyPlace__.getYCoordinate()* gridStep__);
                    if (!tempToken__.isSelected()) {
                        copyPlace__.tokenInitialized_ = false;
                        copyPlace__.token_ = null;
                    }
                }
            }
        }

        // Copy all selected transitions
        for (int i__ = 0; i__ < transitionVector_.size(); i__++) {
            Transition tempTransition__ = (Transition) transitionVector_.elementAt(i__);
            Transition copyTransition__ = (Transition) tempTransition__.clone();
            if (tempTransition__.isSelected()) {
                transitionVectorBuf_.addElement(copyTransition__);
                itemsCopied__ = true;
            }
        }

        // Copy all selected tokens
        for (int i__ = 0; i__ < tokenVector_.size(); i__++) {
            Token tempToken__ = (Token) tokenVector_.elementAt(i__);
            Token copyToken__ = (Token) tempToken__.clone();
            if (tempToken__.isSelected()) {
                tokenVectorBuf_.addElement(copyToken__);
                itemsCopied__ = true;
            }
        }
        // Copy all selected arcs
        for (int i__ = 0; i__ < arcVector_.size(); i__++) {
            Arc tempArc__ = (Arc) arcVector_.elementAt(i__);
            Arc copyArc__ = (Arc) tempArc__.clone();
            if (tempArc__.isSelected()) {
                arcVectorBuf_.addElement(copyArc__);
                itemsCopied__ = true;
            }
        }
        // Copy all selected captions
        for (int i__ = 0; i__ < captionVector_.size(); i__++) {
            Caption tempCaption__ = (Caption) captionVector_.
                                    elementAt(i__);
            Caption copyCaption__ = (Caption) tempCaption__.clone();
            if (tempCaption__.isSelected()) {
                captionVectorBuf_.addElement(copyCaption__);
                itemsCopied__ = true;
            }
        }

        return (itemsCopied__);
    }

    /**
      * Returns true if the Arc passed as a parameter to this routine
      * already exists, based on the starting and ending coordinates
      * of the Arc
    **/
    public boolean duplicateArc(Arc newArc) {
        // Don't check the last Arc, since that is the current one
        for (int i__ = 0; i__ < arcVector_.size()-1; i__++) {
            Arc tempArc__ = (Arc) arcVector_.elementAt(i__);
            if ((tempArc__.getFirstXCoordinate() == newArc.getFirstXCoordinate()) &&
                (tempArc__.getFirstYCoordinate() == newArc.getFirstYCoordinate()) &&
                (tempArc__.getLastXCoordinate() == newArc.getLastXCoordinate()) &&
                (tempArc__.getLastYCoordinate() == newArc.getLastYCoordinate())) {
                    return (true);
            }
        }
        return(false);
    }

    /**
      * Attempts to paste the contents of the paste buffer to
      * the design.  The minimum X and Y coordinates of all the
      * components in the select buffer will be placed where
      * the user clicked the mouse as the destination.  If any of
      * the components will overlap already existing componenents
      * in the design, the paste will not occur and the routine
      * will return false.
    **/
    public boolean pasteDesination (int x, int y) {

        int xMin__ = petriTool_.gridWidth_;
        int yMin__ = petriTool_.gridHeight_;
        int xTranslate__ = 0;
        int yTranslate__ = 0;
        x = x / petriTool_.gridStep_;
        y = y / petriTool_.gridStep_;

        // Find upper left square of virtual box surrounding
        // the selected components
        for (int i__ = 0; i__ < placeVectorBuf_.size(); i__++) {
            Place tempPlace__ = (Place)placeVectorBuf_.elementAt(i__);
            if (tempPlace__.getXCoordinate() < xMin__) {
                xMin__ = tempPlace__.getXCoordinate();
            }
            if (tempPlace__.getYCoordinate() < yMin__) {
                yMin__ = tempPlace__.getYCoordinate();
            }
        }
        for (int i__ = 0; i__ < transitionVectorBuf_.size(); i__++) {
            Transition tempTransition__ =
                (Transition)transitionVectorBuf_.elementAt(i__);
            if (tempTransition__.getXCoordinate() < xMin__) {
                xMin__ = tempTransition__.getXCoordinate();
            }
            if (tempTransition__.getYCoordinate() < yMin__) {
                yMin__ = tempTransition__.getYCoordinate();
            }
        }
        for (int i__ = 0; i__ < tokenVectorBuf_.size(); i__++) {
            Token tempToken__ =
                (Token)tokenVectorBuf_.elementAt(i__);
            if (tempToken__.getXCoordinate() < xMin__) {
                xMin__ = tempToken__.getXCoordinate();
            }
            if (tempToken__.getYCoordinate() < yMin__) {
                yMin__ = tempToken__.getYCoordinate();
            }
        }
        for (int i__ = 0; i__ < arcVectorBuf_.size(); i__++) {
            Arc tempArc__ =
                (Arc)arcVectorBuf_.elementAt(i__);
            if (tempArc__.getMinXCoordinate() < xMin__) {
                xMin__ = tempArc__.getMinXCoordinate();
            }
            if (tempArc__.getMinYCoordinate() < yMin__) {
                yMin__ = tempArc__.getMinYCoordinate();
            }
        }
        for (int i__ = 0; i__ < captionVectorBuf_.size(); i__++) {
            Caption tempCaption__ =
                (Caption)captionVectorBuf_.elementAt(i__);
            if (tempCaption__.getXCoordinate() < xMin__) {
                xMin__ = tempCaption__.getXCoordinate();
            }
            if (tempCaption__.getYCoordinate() < yMin__) {
                yMin__ = tempCaption__.getYCoordinate();
            }
        }

        // Find translation quantity in x and y directions
        xTranslate__ = x - xMin__;
        yTranslate__ = y - yMin__;

        Vector xVector__ = new Vector();
        Vector yVector__ = new Vector();

        // Create matching x,y vectors of translated
        // coordinates of the selected objects
        for (int i__ = 0; i__ < placeVectorBuf_.size(); i__++) {
            Place tempPlace__ = (Place)placeVectorBuf_.elementAt(i__);
            xVector__.addElement(new Integer(tempPlace__.getXCoordinate() +
                                 xTranslate__));
            yVector__.addElement(new Integer(tempPlace__.getYCoordinate() +
                                 yTranslate__));
            tempPlace__.translateCoordinates(xTranslate__,yTranslate__);
        }
        for (int i__ = 0; i__ < transitionVectorBuf_.size(); i__++) {
            Transition tempTransition__ = (Transition)transitionVectorBuf_.elementAt(i__);
            xVector__.addElement(new Integer(tempTransition__.getXCoordinate() +
                                 xTranslate__));
            yVector__.addElement(new Integer(tempTransition__.getYCoordinate() +
                                 yTranslate__));
            tempTransition__.translateCoordinates(xTranslate__,yTranslate__);
        }
        for (int i__ = 0; i__ < tokenVectorBuf_.size(); i__++) {
            Token tempToken__ = (Token)tokenVectorBuf_.elementAt(i__);
            xVector__.addElement(new Integer(tempToken__.getXCoordinate() +
                                 xTranslate__));
            yVector__.addElement(new Integer(tempToken__.getYCoordinate() +
                                 yTranslate__));
            tempToken__.translateCoordinates(xTranslate__,yTranslate__);
        }
        // THIS SHOULD BE DESIGNED TO ADD ALL COORDINATES, WE'LL
        // JUST DO FIRST AND LAST COORDINATES FOR NOW AND ALLOW
        // OTHER ARC POINTS OVERLAP
        for (int i__ = 0; i__ < arcVectorBuf_.size(); i__++) {
            Arc tempArc__ = (Arc)arcVectorBuf_.elementAt(i__);
            xVector__.addElement(new Integer(tempArc__.getFirstXCoordinate() +
                                 xTranslate__));
            yVector__.addElement(new Integer(tempArc__.getFirstYCoordinate() +
                                 yTranslate__));
            xVector__.addElement(new Integer(tempArc__.getLastXCoordinate() +
                                 xTranslate__));
            yVector__.addElement(new Integer(tempArc__.getLastYCoordinate() +
                                 yTranslate__));
            tempArc__.translateCoordinates(xTranslate__,yTranslate__);
        }
        for (int i__ = 0; i__ < captionVectorBuf_.size(); i__++) {
            Caption tempCaption__ = (Caption)captionVectorBuf_.elementAt(i__);
            xVector__.addElement(new Integer(tempCaption__.getXCoordinate() +
                                 xTranslate__));
            yVector__.addElement(new Integer(tempCaption__.getYCoordinate() +
                                 yTranslate__));

            // Make sure fonts do not span beyond border
            FontMetrics fm = getFontMetrics(tempCaption__.getFont());
            int width__ = fm.stringWidth(tempCaption__.getText());
            int height__ = fm.getHeight();
            xVector__.addElement(new Integer(tempCaption__.getXCoordinate() +
                                 xTranslate__ + width__ / petriTool_.gridStep_));
            yVector__.addElement(new Integer(tempCaption__.getYCoordinate() +
                                 yTranslate__ - height__ / petriTool_.gridStep_));

            tempCaption__.translateCoordinates(xTranslate__,yTranslate__);
        }

        // Check each of the translated coordinates to see if there
        // is already a component there
        for (int i__ = 0; i__ < xVector__.size(); i__++) {
            Integer xVal__ = (Integer)xVector__.elementAt(i__);
            Integer yVal__ = (Integer)yVector__.elementAt(i__);
            if (gridSpaceOccupied(xVal__.intValue() * petriTool_.gridStep_,
                                  yVal__.intValue() * petriTool_.gridStep_)) {
                StatusMessage("Components overlap, select another destination.");
                return (false);
            }
            if (!validDimension(xVal__.intValue() * petriTool_.gridStep_,
                                yVal__.intValue() * petriTool_.gridStep_)) {
                StatusMessage("Components span beyond border, select another destination.");
                return (false);
            }
        }



        // If we get here, there was no conflict, so add the
        // the selected components to their respective vectors
        for (int i__ = 0; i__ < placeVectorBuf_.size(); i__++) {
            Place tempPlace__ = (Place)placeVectorBuf_.elementAt(i__);
            Place copyPlace__ = (Place) tempPlace__.clone();
            copyPlace__.setLabel(petriTool_.getPlaceLabel());
            placeVector_.addElement(copyPlace__);
        }
        for (int i__ = 0; i__ < transitionVectorBuf_.size(); i__++) {
            Transition tempTransition__ = (Transition)transitionVectorBuf_.elementAt(i__);
            Transition copyTransition__ = (Transition) tempTransition__.clone();
            copyTransition__.setLabel(petriTool_.getTransitionLabel());
            transitionVector_.addElement(copyTransition__);
        }
        for (int i__ = 0; i__ < tokenVectorBuf_.size(); i__++) {
            Token tempToken__ = (Token)tokenVectorBuf_.elementAt(i__);
            Token copyToken__ = (Token) tempToken__.clone();
            tokenVector_.addElement(copyToken__);
        }
        for (int i__ = 0; i__ < arcVectorBuf_.size(); i__++) {
            Arc tempArc__ = (Arc)arcVectorBuf_.elementAt(i__);
            Arc copyArc__ = (Arc) tempArc__.clone();
            arcVector_.addElement(copyArc__);
        }
        for (int i__ = 0; i__ < captionVectorBuf_.size(); i__++) {
            Caption tempCaption__ = (Caption)captionVectorBuf_.elementAt(i__);
            Caption copyCaption__ = (Caption) tempCaption__.clone();
            captionVector_.addElement(copyCaption__);
        }

        // Re-calculate the initial marking
        setInitialMarking();
        return (true);

    }

    /**
      * Handles mouseDown events within the DesignPanel, which
      * will trigger certain actions depending on the state of
      * the ControlPanel and other previous events.
    **/
    public synchronized boolean mouseDown(Event evt, int x, int y) {
        int gridStep__ = petriTool_.gridStep_;

        // For scrollbar translation
        x += dx;
        y += dy;

        int xOriginal__ = x;
        int yOriginal__ = y;

        // Align coordinates so that component is centered
        // in a grid square
        x = x - (x % gridStep__);
        y = y - (y % gridStep__);

        selectedButton_ = petriTool_.controlPanel_.getCurrentButton();

        if (selectedButton_.equals("Pointer")) {
            if (petriTool_.captionInProgress_) {
                if (validDimension(x, y)) {
                    FontMetrics fm = getFontMetrics(petriTool_.captionFont_);
                    int width__ = fm.stringWidth(petriTool_.captionText_);
                    int height__ = fm.getHeight();
                    if (validDimension(x+width__, y-height__)) {
                        if (!gridSpaceOccupied(x, y)) {
                            Caption caption__ = new Caption
                                (x / gridStep__, y / gridStep__ +1,
                                petriTool_.captionText_,
                                petriTool_.captionFont_);
                            caption__.setSelected(false);
                            captionVector_.addElement(caption__);
                            petriTool_.captionInProgress_ = false;
                            petriTool_.captionText_ = "";
                        }
                        else {
                            StatusMessage("Captions may not be drawn within 1 grid space of other elements");
                        }
                    }
                    else {
                        StatusMessage("Caption dimensions extend beyond border.");
                    }
                }
                else {
                    StatusMessage("Captions must be drawn within the border.");
                }
            }
            else if (petriTool_.pasteInProgress_) {
                if (pasteDesination(x,y)) {
                    petriTool_.pasteInProgress_ = false;
                    petriTool_.destroySimulation();
                }
            }
            else if (placeOccupies(x, y, true)) {
                if (tokenOccupies(x,y)) {
                    if (selectPlaceOverToken(xOriginal__, yOriginal__)) {
                        Place tempPlace__ = getPlace(x,y);
                        tempPlace__.toggleSelected();
                    }
                    else {
                        Token tempToken__ = getToken(x,y);
                        tempToken__.toggleSelected();
                    }
                }
                else {
                    Place tempPlace__ = getPlace(x,y);
                    tempPlace__.toggleSelected();
                }
            }
            else if (transitionOccupies(x, y, true)) {
                Transition tempTransition__ = getTransition(x,y);
                tempTransition__.toggleSelected();
            }
            else if (tokenOccupies(x, y)) {
                Token tempToken__ = getToken(x,y);
                tempToken__.toggleSelected();
            }
            // Inform Captions and Arcs of mouseDown event
            // so that they may determine if they were selected
            for (int i__ = 0; i__ < captionVector_.size(); i__++) {
                Caption tempCaption__ = (Caption) captionVector_.
                                        elementAt(i__);
                tempCaption__.mouseDownAt(xOriginal__, yOriginal__,
                                          gridStep__);
            }
            for (int i__ = 0; i__ < arcVector_.size(); i__++) {
                Arc tempArc__ = (Arc) arcVector_.elementAt(i__);
                tempArc__.mouseDownAt(xOriginal__, yOriginal__,
                                      gridStep__);
            }
        }
        else if (selectedButton_.equals("Place")) {
            if (validDimension(x, y)) {
                if (!gridSpaceOccupied(x, y)) {
                    placeVector_.addElement(new Place
                        (x / gridStep__, y / gridStep__,petriTool_.getPlaceLabel()));
                        petriTool_.destroySimulation();
                        setInitialMarking();
                }
                else {
                    StatusMessage("Places may not be drawn within 1 grid space of other elements");
                }
            }
            else {
                StatusMessage("Places must be drawn within the border.");
            }
        }
        else if (selectedButton_.equals("Token")) {
            if (validDimension(x, y)) {
                if (placeOccupies(x, y, true)) {
                    if (!tokenOccupies(x,y)) {
                        int numTokens__ = petriTool_.componentPanel_.
                            getNumTokens();
                        Token tempToken__ = new Token
                                (x / gridStep__, y / gridStep__,
                                numTokens__);
                        tokenVector_.addElement(tempToken__);
                        petriTool_.destroySimulation();
                        Place tempPlace__ = getPlace(x, y);
                        tempPlace__.setToken(tempToken__);
                        setInitialMarking();
                    }
                    else {
                        StatusMessage("Tokens already occupy this Place.");
                    }
                }
                else {
                    StatusMessage("Tokens must be drawn within Places.");
                }
            }
            else {
                StatusMessage("Tokens must be drawn within the border.");
            }
        }
        else if (selectedButton_.equals("Transition")) {
            if (validDimension(x, y)) {
                if (!gridSpaceOccupied(x, y)) {
                    transitionVector_.addElement(new Transition
                        (x / gridStep__, y / gridStep__,
                         petriTool_.getTransitionLabel()));
                    petriTool_.destroySimulation();
                }
                else {
                    StatusMessage("Transitions may not be drawn within 1 grid space of other elements");
                }
            }
            else {
                StatusMessage("Transitions must be drawn within the border.");
            }
        }
        else if (selectedButton_.equals("Arc")) {
            if (validDimension(x, y)) {
                // If no Arc started yet
                if (newArc_ == null) {
                    // Arcs must start at either a Place or Transition
                    if (placeOccupies (x, y, true)) {
                        newArc_ = new Arc (x / gridStep__, y / gridStep__);
                        newArc_.setStartComponent("Place");
                        arcVector_.addElement(newArc_);
                        StatusMessage("Select next Arc coordinate.");
                        return(true);
                    }
                    else if (transitionOccupies(x, y, true)) {
                        newArc_ = new Arc (x / gridStep__, y / gridStep__);
                        newArc_.setStartComponent("Transition");
                        arcVector_.addElement(newArc_);
                        StatusMessage("Select next Arc coordinate.");
                        return (true);
                    }
                    else {
                        StatusMessage("Arcs must start at either a Place or Transition.");
                        return (true);
                    }
                }
                else {
                    // Cannot start and end on same component
                    if (newArc_.getFirstXCoordinate() * gridStep__ == x &&
                        newArc_.getFirstYCoordinate() * gridStep__  == y) {
                            StatusMessage("Arcs cannot be drawn between the same component.");
                            return (true);
                    }


                    // Determine if a Place or Transition occupy the coordinate
                    if (placeOccupies (x, y, true)) {
                        newArc_.setEndComponent("Place");
                        newArc_.addCoordinates(x / gridStep__, y / gridStep__);
                        newArc_.setTokensToEnable(petriTool_.componentPanel_.
                            getTokensToEnable());
                        String start__ = newArc_.getStartComponent();
                        if (start__.equals("Place")) {
                            StatusMessage("Arcs cannot be drawn between like components.");
                            arcVector_.removeElementAt(arcVector_.size()-1);
                            newArc_= null;
                            return (true);
                        }
                        if (duplicateArc(newArc_)) {
                            StatusMessage("An Arc is already placed there.");
                            arcVector_.removeElementAt(arcVector_.size()-1);
                            newArc_ = null;
                            return (true);
                        }

                        // Arc completed, delete reference to newArc_
                        newArc_ = null;
                    }
                    else if (transitionOccupies(x, y, true)) {
                        newArc_.setEndComponent("Transition");
                        newArc_.addCoordinates(x / gridStep__, y / gridStep__);
                        newArc_.setTokensToEnable(petriTool_.componentPanel_.
                            getTokensToEnable());
                        String start__ = newArc_.getStartComponent();

                        if (start__.equals("Transition")) {
                            StatusMessage("Arcs cannot be drawn between like components.");
                            arcVector_.removeElementAt(arcVector_.size()-1);
                            newArc_= null;
                            return (true);
                        }

                        if (duplicateArc(newArc_)) {
                            StatusMessage("An Arc is already placed there.");
                            arcVector_.removeElementAt(arcVector_.size()-1);
                            newArc_ = null;
                            return (true);
                        }

                        // Arc completed, delete reference to newArc_
                        newArc_ = null;
                    }
                    else {
                        newArc_.addCoordinates(x / gridStep__, y / gridStep__);
                    }
                }
                petriTool_.destroySimulation();
            }
            else {
                StatusMessage("Arcs must be drawn within the border.");
            }
        }

        else if (selectedButton_.equals("Calc")) {

        }
        else if (selectedButton_.equals("Show")) {

        }
        else if (selectedButton_.equals("Prop")) {

        }
        else if (selectedButton_.equals("Help")) {

        }
        else {
        }

        return (true);
    }


    /**
      * Handle the event where the user releases the mouse button
    **/
    public synchronized boolean mouseUp(Event evt, int x, int y) {
        /*int gridStep__ = petriTool_.gridStep_;

        x += dx;
        y += dy;

        int xOriginal__ = x;
        int yOriginal__ = y;

        // Align coordinates so that component is
        // centered in a grid square
        x = x - (x % gridStep__);
        y = y - (y % gridStep__);


        */
        repaint();
        return (true);
    }

    /**
      * Handle the event where the user drags the mouse
      * (mouse button is down)
    **/
/*
    public synchronized boolean mouseDrag(Event evt, int x, int y) {
        int gridStep__ = petriTool_.gridStep_;

        x += dx;
        y += dy;

        if (x == -1 || y == -1) {
            return (true);
        }

        if (selectedButton_.equals("Arc")) {
            if (newArc_ != null) {
                // COMMENTED OUT FOR ARC UPGRADE
                //newArc_.set2ndCoordinate(x / gridStep__, y / gridStep__);
                //newArc_.setEndDrawCoordinates(0, 0);
                repaint();
                return (true);
            }
            repaint();
        }
        return (false);
    }
*/

    /**
      * Checks the design for validity.  The design is invalid if
      * there are Tokens outside of Places, or if there are Places,
      * Transitions, or Arcs that are unconnected.
    **/
    public boolean validDesign() {
        StatusMessage("Validating design, please wait...");

        if (danglingToken(tokenVector_, placeVector_)) {
            StatusMessage("The design contains a dangling Token at " +
                          "x = " + xDangle_ + ", y = " + yDangle_);
        }
        else if (danglingPlace(placeVector_, arcVector_)) {
            StatusMessage("The design contains an unconnected Place at " +
                          "x = " + xDangle_ + ", y = " + yDangle_);
        }
        else if (danglingTransition(transitionVector_, arcVector_)) {
            StatusMessage("The design contains an unconnected Transition at " +
                          "x = " + xDangle_ + ", y = " + yDangle_);
        }
        else if (danglingArc(arcVector_)) {
            StatusMessage("The design contains an unconnected Arc at " +
                          "x = " + xDangle_ + ", y = " + yDangle_);
        }
        else if (invalidArc(arcVector_)) {
            StatusMessage("The design contains an invalid Arc at " +
                          "x = " + xDangle_ + ", y = " + yDangle_);
        }
        else {
            StatusMessage("Design is valid.");
            validDesign_ = true;
        }
        return(validDesign_);
    }

    /**
      * Checks for Tokens which are not contained within Places
    **/
    private boolean danglingToken(Vector tokenVector, Vector placeVector) {
        for (int i__ = 0; i__ < tokenVector.size(); i__++) {
            Token tempToken__ = (Token) tokenVector.elementAt(i__);

            int x__ = tempToken__.getXCoordinate() * petriTool_.gridStep_;
            int y__ = tempToken__.getYCoordinate() * petriTool_.gridStep_;

            if (!petriTool_.designPanel_.placeOccupies(x__, y__, true)) {
                xDangle_ = x__ / petriTool_.gridStep_;
                yDangle_ = y__ / petriTool_.gridStep_;
                return (true);
            }
        }
        return(false);
    }

    /**
      * Checks for Places which do not have any input or output Arcs
    **/
    private boolean danglingPlace(Vector placeVector, Vector arcVector) {
        for (int i__ = 0; i__ < placeVector.size(); i__++) {
            Place tempPlace__ = (Place) placeVector.elementAt(i__);
            int x__ = tempPlace__.getXCoordinate() * petriTool_.gridStep_;
            int y__ = tempPlace__.getYCoordinate() * petriTool_.gridStep_;

            if (!petriTool_.designPanel_.arcStartsAt(x__, y__, true)) {
                if (!petriTool_.designPanel_.arcEndsAt(x__, y__, true)) {
                    xDangle_ = x__ / petriTool_.gridStep_;
                    yDangle_ = y__ / petriTool_.gridStep_;
                    return (true);
                }
            }
        }
        return(false);
    }

    /**
      * Checks for Transitions which do not have either an
      * input Arc or an output Arc
    **/
    private boolean danglingTransition(Vector transitionVector, Vector arcVector) {
        for (int i__ = 0; i__ < transitionVector.size(); i__++) {
            Transition tempTransition__ = (Transition) transitionVector.elementAt(i__);
            int x__ = tempTransition__.getXCoordinate() * petriTool_.gridStep_;
            int y__ = tempTransition__.getYCoordinate() * petriTool_.gridStep_;
            if (!petriTool_.designPanel_.arcStartsAt(x__, y__, true)) {
                xDangle_ = x__ / petriTool_.gridStep_;
                yDangle_ = y__ / petriTool_.gridStep_;
                return (true);
            }
            if (!petriTool_.designPanel_.arcEndsAt(x__, y__, true)) {
                xDangle_ = x__ / petriTool_.gridStep_;
                yDangle_ = y__ / petriTool_.gridStep_;
                return (true);
            }
        }
        return(false);
    }

    /**
      * Checks for Arcs which do not either start at a Place or
      * Transition or end at a Place or Transition
    **/
    private boolean danglingArc(Vector arcVector) {
        for (int i__ = 0; i__ < arcVector.size(); i__++) {
            Arc tempArc__ = (Arc) arcVector.elementAt(i__);
            int x__ = tempArc__.getFirstXCoordinate() * petriTool_.gridStep_;
            int y__ = tempArc__.getFirstYCoordinate() * petriTool_.gridStep_;
            if (!petriTool_.designPanel_.placeOccupies(x__, y__, true)) {
                if (!petriTool_.designPanel_.transitionOccupies(x__, y__, true)) {
                    xDangle_ = x__ / petriTool_.gridStep_;
                    yDangle_ = y__ / petriTool_.gridStep_;
                    return (true);
                }
            }
            x__ = tempArc__.getLastXCoordinate() * petriTool_.gridStep_;
            y__ = tempArc__.getLastYCoordinate() * petriTool_.gridStep_;
            if (!petriTool_.designPanel_.placeOccupies(x__, y__, true)) {
                if (!petriTool_.designPanel_.transitionOccupies(x__, y__, true)) {
                    xDangle_ = x__ / petriTool_.gridStep_;
                    yDangle_ = y__ / petriTool_.gridStep_;
                    return (true);
                }
            }
        }
        return(false);
    }

    /**
      * Checks for Arcs which span between two places or
      * between two transitions
    **/
    private boolean invalidArc(Vector arcVector) {
        boolean startPlace__;
        boolean endPlace__;
        boolean noStartComponent__;
        boolean noEndComponent__;

        for (int i__ = 0; i__ < arcVector.size(); i__++) {
            Arc tempArc__ = (Arc) arcVector.elementAt(i__);
            int x1__ = tempArc__.getFirstXCoordinate() * petriTool_.gridStep_;
            int y1__ = tempArc__.getFirstYCoordinate() * petriTool_.gridStep_;

            if (petriTool_.designPanel_.placeOccupies(x1__, y1__, true)) {
                startPlace__ = true;
            }
            else {
                startPlace__ = false;
            }

            int x2__ = tempArc__.getLastXCoordinate() * petriTool_.gridStep_;
            int y2__ = tempArc__.getLastYCoordinate() * petriTool_.gridStep_;

            if (petriTool_.designPanel_.placeOccupies(x2__, y2__, true)) {
                endPlace__ = true;
            }
            else {
                endPlace__ = false;
            }

            if (startPlace__ == endPlace__) {
                xDangle_ = x1__ / petriTool_.gridStep_;
                yDangle_ = y1__ / petriTool_.gridStep_;
                return (true);
            }
        }
        return(false);
    }

}
