//////////////////////////////////////////////////
package gui;			    // GUIManager is member of gui.

// Standard Packages imported.
import java.awt.*;
import java.net.*;
import java.applet.*;
import java.util.*;
import java.io.*;

// Network Design Tool Packages.
import general.*;
import network.*;

import gui.*;
//////////////////////////////////////////////////
public class GUIManager extends Frame {
  private static final String M_FILE = "File"; // M_ indicates menu option.
  private static final String M_FILE_NEW = "New";
  private static final String M_FILE_OPEN = "Open";
  private static final String M_FILE_SAVE = "Save";
  private static final String M_FILE_SAVE_ALL = "All";
  private static final String M_FILE_SAVE_PHYSICAL = "Physical";
  private static final String M_FILE_SAVE_NETWORK = "Network";
  private static final String M_FILE_SAVEAS = "Save As";
  // put a space after characters so as to distinguish between
  // SAVE options
  private static final String M_FILE_SAVEAS_ALL = "All ";
  private static final String M_FILE_SAVEAS_PHYSICAL = "Physical ";
  private static final String M_FILE_SAVEAS_NETWORK = "Network ";
  private static final String M_FILE_CLOSE = "Close";
  private static final String M_FILE_REVERT = "Revert to Saved";
  private static final String M_FILE_QUIT = "Quit";

  private static final String M_EDIT = "Edit";
  private static final String M_EDIT_LINK = "Link";
  private static final String M_EDIT_LINK_ADD = GUICanvas.ADD_LINK;
  private static final String M_EDIT_LINK_REMOVE = GUICanvas.REMOVE_LINK;
  private static final String M_EDIT_LINK_MODIFY = GUICanvas.EDIT_LINK;
  private static final String M_EDIT_LINK_CLEAR_ALL = "Clear All";
  private static final String M_EDIT_LINK_STAR = "Best Star";
  private static final String M_EDIT_LINK_MST = "Minimum Spanning Tree";
  private static final String M_EDIT_LINK_DELAUNAY = "Delaunay Triangulation";
  private static final String M_EDIT_LINK_COMPLETE = "Complete Graph";
  
  // there are a space at the end of some of the following word, 
  // so as to distinguish from that of the M_EDIT_LINK_***
  private static final String M_EDIT_SWITCH = "Switch";
  private static final String M_EDIT_SWITCH_ADD = GUICanvas.ADD_SWITCH;
  private static final String M_EDIT_SWITCH_REMOVE = GUICanvas.REMOVE_SWITCH;
  private static final String M_EDIT_SWITCH_MOVE = GUICanvas.MOVE_SWITCH;
  private static final String M_EDIT_SWITCH_MODIFY = GUICanvas.EDIT_SWITCH;
  private static final String M_EDIT_SWITCH_CLEAR_ALL = "Clear All ";

  private static final String M_EDIT_CONSTRAINT = "Constraint";
  private static final String M_EDIT_CONSTRAINT_ADD = "Add Constraint";
  private static final String M_EDIT_CONSTRAINT_REMOVE = "Remove Constraint";
  private static final String M_EDIT_CONSTRAINT_CLEAR_ALL = "Clear All  ";
  private static final String M_EDIT_CONSTRAINT_LOCAL = "localized Traffic";
  private static final String M_EDIT_CONSTRAINT_PAIR = "Pairwise Percentage Traffic";


  private static final String M_OPTIONS = "Options";
  private static final String M_OPTIONS_ZOOM_OUT = GUICanvas.ZOOM_OUT; 
  private static final String M_OPTIONS_ZOOM_IN = GUICanvas.ZOOM_IN;
  private static final String M_OPTIONS_SCALE = "Scale";

  private static final String M_NETWORK = "Network";
  private static final String M_NETWORK_DESCRIPTION = "Enter Description";
  private static final String M_NETWORK_INITIAL = "Set As Initial Network";
  private static final String M_NETWORK_SECOND = "Set As Secondary Network";
  private static final String M_NETWORK_ADJUST = "Adjust Initial Network";

  private static final String M_OPTIMIZE = "Optimize";
  private static final String M_OPTIMIZE_SHORTEST_PATH_ROUTE = "Shortest Path Route";
  private static final String M_OPTIMIZE_DISTRIBUTED_ROUTE = "Distributed Route";
  private static final String M_OPTIMIZE_LOWER_BOUND = "Lower Bound";

  private static final String M_WINDOW = "Window";
  private static final String M_WINDOW_LINKS = "Links";
  private static final String M_WINDOW_SWITCHES = "Switches";
  private static final String M_WINDOW_CONSTRAINTS = "Constraints";
  
  private static final String M_HELP = "Help";
  private static final String M_HELP_ABOUT = "About";
  private static final String M_HELP_USING = "Using Network Design Tool";
  private static final String M_HELP_ALGO_DOC = "Algorithm Documentation";

  private GeneralProperties gpData;
  private Scrollbar vScrollbar, hScrollbar;
  private boolean vScrollbarVisible = false, hScrollbarVisible = false;
  private FramedPanel pCenter;

  public CalcLinkDimension calcLinkDimensionThread = null;
  private CalcNetworkLowerBound calcLowerBoundThread = null;

  public GUIManager(Boolean InApplet, Applet app) throws GenericException {

    InitGeneralProperties(InApplet, app);

    MenuBar mb = new MenuBar();
    Menu m_file = new Menu(M_FILE);
    m_file.add(new MenuItem(M_FILE_NEW));
    m_file.add(new MenuItem(M_FILE_OPEN));

    // These options are not allowed for files on the server.
    if( ((Boolean)gpData.get("In Applet?")).equals(Boolean.FALSE) ) {
      m_file.add(new MenuItem(M_FILE_SAVE));
    }
    m_file.add(new MenuItem(M_FILE_CLOSE));
    //m_file.add(new MenuItem("-"));
    //m_file.add(new MenuItem(M_FILE_REVERT));
    m_file.add(new MenuItem("-"));
    m_file.add(new MenuItem(M_FILE_QUIT));
    mb.add(m_file);
  
    Menu m_edit = new Menu(M_EDIT);
    Menu m_edit_switch = new Menu(M_EDIT_SWITCH);
    m_edit_switch.add(new MenuItem(M_EDIT_SWITCH_ADD));
    m_edit_switch.add(new MenuItem(M_EDIT_SWITCH_REMOVE));
    m_edit_switch.add(new MenuItem(M_EDIT_SWITCH_MOVE));
    m_edit_switch.add(new MenuItem(M_EDIT_SWITCH_MODIFY));
    m_edit_switch.add(new MenuItem(M_EDIT_SWITCH_CLEAR_ALL));
    m_edit.add(m_edit_switch);

    Menu m_edit_link = new Menu(M_EDIT_LINK);
    m_edit_link.add(new MenuItem(M_EDIT_LINK_ADD));
    m_edit_link.add(new MenuItem(M_EDIT_LINK_REMOVE));
    m_edit_link.add(new MenuItem(M_EDIT_LINK_MODIFY));
    m_edit_link.add(new MenuItem("-"));
    m_edit_link.add(new MenuItem(M_EDIT_LINK_CLEAR_ALL));
    m_edit_link.add(new MenuItem(M_EDIT_LINK_STAR));
    m_edit_link.add(new MenuItem(M_EDIT_LINK_MST));
    m_edit_link.add(new MenuItem(M_EDIT_LINK_DELAUNAY));
    m_edit_link.add(new MenuItem(M_EDIT_LINK_COMPLETE));
    m_edit.add(m_edit_link);

    Menu m_edit_constraint = new Menu(M_EDIT_CONSTRAINT);
    m_edit_constraint.add(new MenuItem(M_EDIT_CONSTRAINT_ADD));
    m_edit_constraint.add(new MenuItem(M_EDIT_CONSTRAINT_REMOVE));
    m_edit_constraint.add(new MenuItem(M_EDIT_CONSTRAINT_CLEAR_ALL));
    m_edit_constraint.add(new MenuItem(M_EDIT_CONSTRAINT_LOCAL));
    m_edit_constraint.add(new MenuItem(M_EDIT_CONSTRAINT_PAIR));
    m_edit.add(m_edit_constraint);

    mb.add(m_edit);

    Menu m_options = new Menu(M_OPTIONS);
    m_options.add(new MenuItem(M_OPTIONS_SCALE));
    m_options.add(new MenuItem(M_OPTIONS_ZOOM_OUT));
    m_options.add(new MenuItem(M_OPTIONS_ZOOM_IN));
    mb.add(m_options);

    Menu m_network = new Menu(M_NETWORK);
    m_network.add(new MenuItem(M_NETWORK_DESCRIPTION));
    m_network.add(new MenuItem(M_NETWORK_INITIAL));
    m_network.add(new MenuItem(M_NETWORK_SECOND));
    m_network.add(new MenuItem(M_NETWORK_ADJUST));
    mb.add(m_network);

    Menu m_optimize = new Menu(M_OPTIMIZE);
    m_optimize.add(new MenuItem(M_OPTIMIZE_SHORTEST_PATH_ROUTE));
    m_optimize.add(new MenuItem(M_OPTIMIZE_DISTRIBUTED_ROUTE));
    m_optimize.add(new MenuItem(M_OPTIMIZE_LOWER_BOUND));
    mb.add(m_optimize);

    Menu m_window = new Menu(M_WINDOW);
    m_window.add(new MenuItem(M_WINDOW_LINKS));
    m_window.add(new MenuItem(M_WINDOW_SWITCHES));
    m_window.add(new MenuItem(M_WINDOW_CONSTRAINTS));
    mb.add(m_window);

    Menu m_help = new Menu(M_HELP);
    m_help.add(new MenuItem(M_HELP_ABOUT));
    m_help.add(new MenuItem("-"));
    m_help.add(new MenuItem(M_HELP_USING));
    m_help.add(new MenuItem(M_HELP_ALGO_DOC));
    mb.setHelpMenu(m_help);

    setMenuBar(mb);
    setBackground(Color.white);
    setForeground(Color.black);

    pCenter = new FramedPanel(FramedPanel.SINGLE_BORDER);
    //Put the canvas in the left column.
    pCenter.setLayout(new BorderLayout());
    GUICanvas c = (GUICanvas)gpData.get("Canvas");
    pCenter.add( "Center", c );
    vScrollbar = new Scrollbar(Scrollbar.VERTICAL);
    hScrollbar = new Scrollbar(Scrollbar.HORIZONTAL);
    setLayout(new BorderLayout());
    add("Center", pCenter);

    FramedPanel pBottom = new FramedPanel(FramedPanel.SINGLE_BORDER);
    pBottom.setLayout(new GridLayout(1, 2));
    pBottom.add((Label)gpData.get("Status Bar Message"));
    pBottom.add((Label)gpData.get("Edit Mode"));
    add("South", pBottom);

    pack();
    show();
  }

  //--------------------------------------------------
  public void setScrollbar() {
    GUICanvas c = (GUICanvas)gpData.get("Canvas");
    double scale = c.getScale();
    Dimension d = c.size();
    Dimension prevSize;
    Network n = (Network)gpData.get("Network");
    Rectangle r = n.getBounds();
    int border = 0;

    // if size and dimension and scale are not changed, then it's just a simple
    // WINDOW_MOVE without resize, so keep the scrollbars intact.
    if (r.equals(n.getPrevBounds()) && c.getPrevScale() == scale
	&& (prevSize = c.getPrevSize()) != null
	&& d.width == prevSize.width 
	&& d.height == prevSize.height)
      return;

    n.setPrevBounds(r);
    c.setPrevSize(d);
    c.setPrevScale(scale);
    //System.out.println("Canvas Size : " + d);
    //System.out.print("Scale = " + scale + " Network Area : " + r);
    if ( (int)Math.ceil(r.width*scale) <= d.width ) {
      // canvas area is larger than network area.
      // scrollbar should not appear
      int val = (int)(r.x*scale + r.width*scale/2 - d.width/2);
      hScrollbar.setValues( val, 1, val - 1, val + 1 );
      // if the scrollbar was there before, now remove it
      if (hScrollbarVisible != false) {
	pCenter.remove(hScrollbar);
	hScrollbarVisible = false;
      }
    }
    else { // scrollbar should appear
      hScrollbar.setValues
	( hScrollbar.getValue(),
	  d.width, (int)Math.floor(r.x * scale) - border, 
	  (int)Math.ceil((r.x + r.width)*scale) - d.width + border);
      if (c.editMode.equals(GUICanvas.ZOOM_IN) ||
	  c.editMode.equals(GUICanvas.ZOOM_OUT))
	hScrollbar.setValue(c.getDx());
      if (hScrollbarVisible == false) { // not visible before, then add it
	pCenter.add("South", hScrollbar);
	hScrollbarVisible = true;
      }
    }
    // same procedure to the vertical scrollbar
    if ( (int)Math.ceil(r.height*scale) <= d.height) {
      int val = (int)(r.y*scale + r.height*scale/2 - d.height/2);
      vScrollbar.setValues( val, 1, val - 1, val + 1 );
      if (vScrollbarVisible != false) {
	pCenter.remove(vScrollbar);
	vScrollbarVisible = false;
      }
    }
    else {
      vScrollbar.setValues(vScrollbar.getValue(),
			   d.height, (int)Math.floor(r.y * scale) - border,
			   (int)Math.ceil((r.y + r.height)*scale) - d.height + border);
      if (c.editMode.equals(GUICanvas.ZOOM_IN) ||
	  c.editMode.equals(GUICanvas.ZOOM_OUT))
	vScrollbar.setValue(c.getDy());
      if (vScrollbarVisible == false) {
	pCenter.add("East", vScrollbar);
	vScrollbarVisible = true;
      }
    }
    c.translate(hScrollbar.getValue(), vScrollbar.getValue());
    //System.out.println( hScrollbar + " , " + vScrollbar );
    show();
  }

  //-----------------------------------------------------
  private void InitGeneralProperties(Boolean InApplet, Applet app)
       throws GenericException {
	 // REQUIRES: Nothing.
	 // RETURNS: Nothing.
	 // PROMISES: 1. Puts in various data structures present in GUIManager but
	 // possibly of global importance in gpData. 

	 try {
	   gpData = new GeneralProperties();
	   gpData.put("In Applet?", InApplet);
    
	   if( InApplet.equals(Boolean.TRUE) ) 
	     gpData.put("Applet", app);

	   gpData.put("GUIManager", this);
	   gpData.put("Network", new Network("No Name"));

	   // used to adjust initial network
	   gpData.put("Order", dNetworkAdjust.INCREASING_ORDER);
	   gpData.put("Ratio", new Double(2.0));

	   gpData.put("Default Value of Alpha for a Place", new Double(0.1));
	   gpData.put("Default Value of Omega for a Place", new Double(0.1));

	   // GUI related data.
	   gpData.put("Canvas", new GUICanvas(gpData));
	   gpData.put("Inter GUI component gap", new Integer(5));
	   gpData.put("Default Dimensions of Canvas", new Dimension(400, 400));
	   gpData.put("Coordinates of Last Mouse Click", new Point(100, 100));
	   gpData.put("Status Bar Message", new Label("Network Design Tool"));
	   gpData.put("Edit Mode", new Label(M_EDIT_SWITCH_MOVE));

	   // Put Help URLs for all the dialog boxes in gpData.
	   gpData.put("Help URL for File|New Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#File|New");
	   gpData.put("Help URL for File|Open Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#File|Open");
	   gpData.put("Help URL for File|Save As|All Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#File|Save As|All");
	   gpData.put("Help URL for File|Save As|Physical Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#File|Save As|Physical");
	   gpData.put("Help URL for File|Save As|Network Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#File|Save As|Network");
	   gpData.put("Help URL for File|Close Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#File|Close");
	   gpData.put("Help URL for File|Revert to Saved Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#File|Revert");

	   gpData.put("Help URL for Edit|Add|Place Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#Edit|Add|Place");
	   gpData.put("Help URL for Edit|Add|Switch Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#Edit|Add|Switch");
	   gpData.put("Help URL for Edit|Add|Link Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#Edit|Add|Link");
	   gpData.put("Help URL for Edit|Delete|Place Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#Edit|Delete|Place");
	   gpData.put("Help URL for Edit|Delete|Switch Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#Edit|Delete|Switch");
	   gpData.put("Help URL for Window|Links Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#Window|Links");
	   gpData.put("Help URL for Window|Switches Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#Window|Switches");
	   gpData.put("Help URL for Window|Constraints Dialog Box", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html#Window|Constraints");
	   gpData.put("Help URL for Help|About", 
		      "http://www.cs.wustl.edu/~javagrp/help/introduction.html");
	   gpData.put("Help URL for Help|Using Network Design Tool", 
		      "http://www.cs.wustl.edu/~javagrp/help/menus.html");
	   gpData.put("Help URL for Help|Algorithm Documentation", 
		      "http://www.cs.wustl.edu/~javagrp/help/algorithms.html");
	 }
	 catch(Exception e) {
	   throw(new GenericException(this, "In InitGeneralProperties():" +
				      e.getMessage())); 
	 }
  }

  /** common for both shortest path and distributed route */
  public void dimensionLinks() {
    Network n = (Network)gpData.get("Network");
    // select links to be dimensioned
    dSelectLinks dsl = new dSelectLinks((Frame)this, n);
    dsl.show();
    Hashtable hLinks = n.getLinksToDimension();
    if (hLinks != null) {
      // array of Strings holding objective functions
      Vector objectives = n.linkDimensioningText(hLinks);
      // StringBuffer holding constraints
      String constraints = n.getConstraintsText();
      if (!gpData.containsKey("dLinkCosts")) {
	dLinkCosts dlc
	  = new dLinkCosts((Frame)this, gpData);
	dlc.hide();
	gpData.put("dLinkCosts", dlc);
      }
      if (calcLinkDimensionThread == null ||
	  !calcLinkDimensionThread.isAlive()) {
	calcLinkDimensionThread
	  = new CalcLinkDimension(objectives, constraints, gpData);
	calcLinkDimensionThread.start();
      }
      else
	DisplayMessageBox("Error", "Is CALCULATING Link Dimension!");
    }
  }

  //--------------------------------------------
  public boolean action(Event e, Object arg) {
    boolean ReturnValue = false;

    if(e.target instanceof MenuItem) {
      String label = (String)arg;
      if(label.equals(M_FILE_NEW)) {
	try {
	  gpData.put("Network", new Network(20));
	  GUICanvas c = (GUICanvas)gpData.get("Canvas");
	  Network n = (Network)gpData.get("Network");
	  Rectangle r = n.getBounds();
	  c.clear();
	  c.autoScale();
	  hScrollbar.setValue(r.x);
	  vScrollbar.setValue(r.y);
	  setScrollbar();
	}
	catch(ClassNotFoundException cnfe) {
	  throw(new GenericException(this, "In action(), ClassNotFoundException:"
+ cnfe.getMessage())); 
	}
      }
      else if(label.equals(M_FILE_OPEN)) {
	InputStream input = null;
	if( ((Boolean)gpData.get("In Applet?")).equals(Boolean.TRUE) ) {
	  // Opens URL of the server and brings in example files.
	  try {
	    URL u = new URL("http://siesta.wustl.edu/~javagrp/classes/samples/MetroAreas50.network");
	    input = u.openStream();
	  }
	  catch(MalformedURLException err) {
	    DisplayMessageBox("Error Open Sample Network File", 
			      "sample network file does not exist!");
	  }
	  catch(IOException err) {
	    DisplayMessageBox("Error Open Sample Network File", 
			      "can not read from sample network file!");
	  }
	}
	else {
	  // Opens files on the local disk.
	  FileDialog fd = new FileDialog(this, "Open Network", FileDialog.LOAD);
	  fd.setDirectory("~javagrp/.www-docs/classes/samples");
	  fd.show();
	  String dir = fd.getDirectory();
	  String filename = fd.getFile();

	  if (filename != null) {
	    try {
	      input = new FileInputStream(dir + filename);
	    }
	    catch (FileNotFoundException err) {
	      DisplayMessageBox("Error Open Network File", 
				"network file not found!");
	    }
	  }
	}

	// common code for both case
	if (input != null) {
	  try {
	    Network n = new Network(input);
	    input.close();
	    gpData.put("Network", n);
	    // c.paint(c.getGraphics());
	    Rectangle r = n.getBounds();
	    GUICanvas c = (GUICanvas)gpData.get("Canvas");
	    c.clear();
	    c.autoScale();
	    hScrollbar.setValue(r.x);
	    vScrollbar.setValue(r.y);
	    setScrollbar();
	  }
	  catch (IOException err) {
	    DisplayMessageBox("Error", 
			      "error reading input network file!");
	  }	
	  catch (GenericException err) {
	    DisplayMessageBox("Error", 
			      "error format of input network file!\n"
+ err.getMessage());
	  }
	  catch (ClassNotFoundException err) {
	    DisplayMessageBox("Error", 
			      "This menu option is currently unimplemented!");
	  }
	}
      }

      else if(label.equals(M_FILE_SAVE_ALL)) {
	DisplayMessageBox("Error", 
			  "This menu option is currently unimplemented!");
      }
      else if(label.equals(M_FILE_SAVE_PHYSICAL)) {
	DisplayMessageBox("Error", 
			  "This menu option is currently unimplemented!");
      }
      else if(label.equals(M_FILE_SAVE)) {
	FileOutputStream os;
	if( ((Boolean)gpData.get("In Applet?")).equals(Boolean.TRUE) ) {
	  // can not save to local disk
	  DisplayMessageBox("Error Save Network File", 
			    "can not save to local disk from an applet!");
	}
	else { // standalone application
	  FileDialog fd = new FileDialog(this, "Save Network", FileDialog.SAVE);
	  fd.setDirectory("~javagrp/.www-docs/classes/samples");
	  fd.show();
	  String dir = fd.getDirectory();
	  String filename = fd.getFile();

	  if (filename != null) {
	    try {
	      os = new FileOutputStream(dir + filename);
	      PrintStream ps = new PrintStream(os);
	      Network n = (Network)gpData.get("Network");
	      ps.print(n);
	      ps.close();
	    }
	    catch (IOException err) {
	      DisplayMessageBox("Error Saving Network File", 
				"can not create the network file!");
	    }
	  }
	}
      }
      else if(label.equals(M_FILE_CLOSE)) {
	DisplayMessageBox("Error", 
			  "This menu option is currently unimplemented!");
      }
      else if(label.equals(M_FILE_REVERT)) {
	DisplayMessageBox("Error", 
			  "This menu option is currently unimplemented!");
      }
      else if(label.equals(M_FILE_QUIT)) {
	return EndApplication();
      }
      else if(label.equals(M_EDIT_SWITCH_ADD) ||
	      label.equals(M_EDIT_SWITCH_REMOVE) ||
	      label.equals(M_EDIT_SWITCH_MOVE) ||
	      label.equals(M_EDIT_SWITCH_MODIFY) ||
	      label.equals(M_EDIT_LINK_ADD) ||
	      label.equals(M_EDIT_LINK_REMOVE) ||
	      label.equals(M_EDIT_LINK_MODIFY) ||
	      label.equals(M_OPTIONS_ZOOM_OUT) ||
	      label.equals(M_OPTIONS_ZOOM_IN)
	      ) {
	GUICanvas c = (GUICanvas)gpData.get("Canvas");
	c.setEditMode(label);
	Label l = (Label)gpData.get("Edit Mode");
	l.setText(label);
	layout();
      }
      else if(label.equals(M_EDIT_LINK_CLEAR_ALL)) {
	Network n = (Network)gpData.get("Network");
	n.removeAllLinks(n.links);
	GUICanvas c = (GUICanvas)gpData.get("Canvas");
	c.repaint();
      }
      else if(label.equals(M_EDIT_SWITCH_CLEAR_ALL)) {
	try {
	  gpData.put("Network", new Network("No Name"));
	  GUICanvas c = (GUICanvas)gpData.get("Canvas");
	  c.paint(c.getGraphics());
	} catch(ClassNotFoundException cnfe) {
	  throw(new GenericException(this, "In handleEvent(), ClassNotFoundException:" + cnfe.getMessage())); 
	}
      }
      else if(label.equals(M_EDIT_CONSTRAINT_ADD)) {
	new dEditAddConstraint( (Frame)this, gpData );
      }
      else if(label.equals(M_EDIT_CONSTRAINT_REMOVE)) {
	Network n = (Network)gpData.get("Network");
	if(n==null || n.constraints.isEmpty())
	  DisplayMessageBox("Error", "No constraints exists!");
	else
	  new dEditDelConstraint( (Frame)this, gpData );
      }
      else if(label.equals(M_EDIT_CONSTRAINT_CLEAR_ALL)) {
	Network n = (Network)gpData.get("Network");
	if(n!=null)
	  n.clearConstraints();
      }
      else if(label.equals(M_EDIT_CONSTRAINT_LOCAL)) {
	Network n = (Network)gpData.get("Network");
	if(n!=null)
	  new dEditConstraintsLocal( (Frame)this, gpData );
      }
      else if(label.equals(M_EDIT_CONSTRAINT_PAIR)) {
	Network n = (Network)gpData.get("Network");
	if(n!=null)
	  new dEditConstraintsPair( (Frame)this, gpData );
      }
      else if(label.equals(M_EDIT_LINK_STAR)) {
	Network n = (Network)gpData.get("Network");
	if( n==null || n.switches.isEmpty() ) {
	  DisplayMessageBox("Error", "No Switches exist!");
	}
	else {
	  n.setBestStar();
	  GUICanvas c = (GUICanvas)gpData.get("Canvas");
	  c.paint(c.getGraphics());
	}
      }
      else if(label.equals(M_EDIT_LINK_DELAUNAY)) {
	Network n = (Network)gpData.get("Network");
	if(n==null || n.switches.size() < 3)
	  DisplayMessageBox("Error", "Less than 3 switches!");
	else {
	  n.DelaunayTriangulation();
	  GUICanvas c = (GUICanvas)gpData.get("Canvas");
	  c.paint(c.getGraphics());
	}
      }    
      else if(label.equals(M_EDIT_LINK_MST)) {
	Network n = (Network)gpData.get("Network");
	if(n==null || n.switches.size() < 2)
	  DisplayMessageBox("Error", "Less than 2 switches!");
	else {
	  n.setMST();
	  GUICanvas c = (GUICanvas)gpData.get("Canvas");
	  c.paint(c.getGraphics());
	}
      }    
      else if(label.equals(M_EDIT_LINK_COMPLETE)) {
	Network n = (Network)gpData.get("Network");
	if(n==null || n.switches.size() < 2)
	  DisplayMessageBox("Error", "Less than 2 switches!");
	else {
	  n.setCompleteGraph();
	  GUICanvas c = (GUICanvas)gpData.get("Canvas");
	  c.paint(c.getGraphics());
	}
      }    
      else if(label.equals(M_OPTIONS_SCALE)) {
	GUICanvas c = (GUICanvas)gpData.get("Canvas");
	c.setEditMode(GUICanvas.EDIT_SWITCH);
	Label l = (Label)gpData.get("Edit Mode");
	l.setText(GUICanvas.EDIT_SWITCH);
	new dOptionScale( (Frame)this, gpData );
	setScrollbar();
      }
      else if(label.equals(M_NETWORK_DESCRIPTION)) {
	new dNetworkDescription( (Frame)this, gpData );
      }
      else if(label.equals(M_NETWORK_INITIAL)) {
	Network n = (Network)gpData.get("Network");
	n.setAsInitial();
      }
      else if(label.equals(M_NETWORK_SECOND)) {
	Network n = (Network)gpData.get("Network");
	n.setAsSecond();
      }
      else if(label.equals(M_NETWORK_ADJUST)) {
	new dNetworkAdjust( (Frame)this, gpData );
      }
      else if(label.equals(M_OPTIMIZE_SHORTEST_PATH_ROUTE)) {
	Network n = (Network)gpData.get("Network");
	ShortestRoute shtrt = new ShortestRoute(n.switches, n.links);
	shtrt.apply();
	dimensionLinks();
      }
      else if (label.equals(M_OPTIMIZE_DISTRIBUTED_ROUTE)) {
	if (!gpData.containsKey("dOptimizeDistributedRoute")) {
	  dOptimizeDistributedRoute dodr = 
	    new dOptimizeDistributedRoute((Frame)this, gpData);
	  gpData.put("dOptimizeDistributedRoute", dodr);
	}
	dOptimizeDistributedRoute dodr 
	  = (dOptimizeDistributedRoute)
	  gpData.get("dOptimizeDistributedRoute");
	dodr.show();
	dimensionLinks();
      }
      else if (label.equals(M_OPTIMIZE_LOWER_BOUND)) {
	Network n = (Network)gpData.get("Network");
	String s = n.getLowerBoundText();
	if (!gpData.containsKey("dOptimizeLowerBound")) {
	  dOptimizeLowerBound dolb
	    = new dOptimizeLowerBound((Frame)this, gpData, 0, "");
	  dolb.hide();
	  gpData.put("dOptimizeLowerBound", dolb);
	}
	if (calcLowerBoundThread == null ||
	    !calcLowerBoundThread.isAlive()) {
	  calcLowerBoundThread = new CalcNetworkLowerBound(s, gpData);
	  calcLowerBoundThread.start();
	}
	else 
	  DisplayMessageBox("Error", "Is CALCULATING Lower Bound!");
      }
      else if(label.equals(M_WINDOW_LINKS)) {
	if (!gpData.containsKey("dWindowLinks")) {
	  dWindowLinks dwl
	    = new dWindowLinks((Frame)this, gpData);
	  dwl.show();
	  gpData.put("dWindowLinks", dwl);
	}
	else {
	  dWindowLinks dwl = (dWindowLinks)gpData.get("dWindowLinks");
	  dwl.update();
	  dwl.show();
	}
      }
      else if(label.equals(M_WINDOW_SWITCHES)) {
	if (!gpData.containsKey("dWindowSwitches")) {
	  dWindowSwitches dws
	    = new dWindowSwitches((Frame)this, gpData);
	  dws.show();
	  gpData.put("dWindowSwitches", dws);
	}
	else {
	  dWindowSwitches dws = (dWindowSwitches)gpData.get("dWindowSwitches");
	  dws.update();
	  dws.show();
	}
      }
      else if(label.equals(M_WINDOW_CONSTRAINTS)) {
	if (!gpData.containsKey("dWindowConstraints")) {
	  dWindowConstraints dwc
	    = new dWindowConstraints((Frame)this, gpData);
	  dwc.show();
	  gpData.put("dWindowConstraints", dwc);
	}
	else {
	  dWindowConstraints dwc = (dWindowConstraints)gpData.get("dWindowConstraints");
	  dwc.update();
	  dwc.show();
	}
      }
      else if(label.equals(M_HELP_ABOUT)) {
	boolean ShowHelp = false;
	String HelpURL = null;
	if( ((Boolean)gpData.get("In Applet?")).equals(Boolean.TRUE) ) {
	  ShowHelp = true;
	  HelpURL = (String)gpData.get("Help URL for Help|About");
	}
	new dMessageBox(this, "About Network Design Tool", 
			"Network Design Group\n" + 
			"Computer Science Department\n" +
			"Washington University, St. Louis", 
			gpData, ShowHelp, HelpURL);
      }
      else if(label.equals(M_HELP_USING)) {
	String HelpURL = (String)gpData
	  .get("Help URL for Help|Using Network Design Tool");
	if( ((Boolean)gpData.get("In Applet?")).equals(Boolean.TRUE) ) {
	  try {
	    ((Applet)gpData.get("Applet")).getAppletContext()
	      .showDocument(new URL(HelpURL));           
	  }
	  catch(MalformedURLException mfue) {
	    DisplayMessageBox("Using Help", 
			      "Help URL "+ HelpURL +" doesn't exist!"); 
	  }
	}
	else			    // In standalone application.
	  DisplayMessageBox("Using Help", "Please visit " + HelpURL + 
			    " for help on using Network Design Tool.");
      }
      else if(label.equals(M_HELP_ALGO_DOC)) {
	String HelpURL = (String)gpData
	  .get("Help URL for Help|Algorithm Documentation");
	if( ((Boolean)gpData.get("In Applet?")).equals(Boolean.TRUE) ) {
	  try {
	    ((Applet)gpData.get("Applet")).getAppletContext()
	      .showDocument(new URL(HelpURL));
	  }
	  catch(MalformedURLException mfue) {
	    DisplayMessageBox("Help", "Help URL doesn't exist!"); 
	  }
	}
	else			    // In standalone application.
	  DisplayMessageBox("Using Help", "Please visit " + HelpURL + " for Documentation on algorithms used in Network Design Tool.");
      }
      ReturnValue = true;
    }
    return ReturnValue;
  }
  //-----------------------------------------------
  public boolean handleEvent(Event e) {
    boolean ReturnValue = false;

    if (e.id == Event.WINDOW_ICONIFY) {
      hide();
      ReturnValue = true;
    }
    else if (e.id == Event.WINDOW_DESTROY) {
      ReturnValue = EndApplication();
    }
    else if (e.id == Event.WINDOW_MOVED) {
      setScrollbar();
    }
    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) {
      ((GUICanvas)gpData.get("Canvas")).translate(hScrollbar.getValue(),
						  vScrollbar.getValue());
      return true;
    }
    else
      ReturnValue = super.handleEvent(e);

    return ReturnValue;
  }

  //-----------------------------------
  private boolean EndApplication() {
    // REQUIRES: nothing.
    // RETURNS: nothing.
    // PROMISES: terminates program.

    dispose();
    if( ((Boolean)gpData.get("In Applet?")).equals(Boolean.FALSE) ) {
      System.exit(0);
    }
    return true;
  }

  //-----------------------------------------------
  public GUICanvas GetCanvas() {
    return (GUICanvas)gpData.get("Canvas");
  }

  //-------------------------------------------------
  public Network GetNetwork() {
    return (Network)gpData.get("Network");
  }
  //-------------------------------------------------------
  public void DisplayMessageBox(String title, String msg) {
    // REQUIRES: nothing.
    // RETURNS: nothing.
    // PROMISES: 1. Displays msg in a dialog box with title.
    // 2. If not in an applet then writes the message on command line. 

    new dMessageBox((Frame)this, title, msg, gpData, false, null);
    if( ((Boolean)gpData.get("In Applet?")).equals(Boolean.FALSE) ) {
      System.out.println(msg);	    // To be removed finally from the code.
    }
  }

  //------------------------------------------------------
  private void openNetwork() {
    FileDialog fd = new FileDialog(this, "Open Network");
    fd.show();
    String dir = fd.getDirectory();
    String filename = fd.getFile();

    try {
      FileInputStream fis = new FileInputStream(dir + filename);
      Network n = new Network(fis);
      //n.print();
      gpData.put("Network", n);
      GUICanvas c = (GUICanvas)gpData.get("Canvas");
      c.paint(c.getGraphics());
    }
    catch (FileNotFoundException e) {
      System.out.println("File Not Found in GUIManager.openNetwork()"
+ e.getMessage());
    }
    catch (IOException e) {
      System.out.println("IOException reading the network file:"
+ e.getMessage());
    }
    catch (GenericException e) {
      System.out.println("File Format Error:" + e.getMessage());
    }
    catch (ClassNotFoundException e) {
      System.out.println("Classes needed to create Network not found:" + e.getMessage());
    }
  }

  public void stopCalcLinkDimensionThread() {
    if (calcLinkDimensionThread != null &&
	calcLinkDimensionThread.isAlive())
      calcLinkDimensionThread.stop();
  }

  public void stopCalcLowerBoundThread() {
    if (calcLowerBoundThread != null &&
	calcLowerBoundThread.isAlive())
      calcLowerBoundThread.stop();
  }

  public boolean calcLinkDimensionThreadIsAlive() {
    if (calcLinkDimensionThread == null || 
	!calcLinkDimensionThread.isAlive())
      return false;
    else
      return true;
  }

} // End of class GUIManager
//////////////////////////////////////////////////
