//     $Id: DrawableMap.java,v 3.1 1998/12/01 14:18:57 te3d Exp $    
 ////////////////////////////////////////////////////////////////////////////
 //
 // File: DrawableMap.java
 //
 // Purpose: A DrawableMap is a graphical representation of
 //          a Map.  Properties:
 // 
 //            o Rectangular shape
 //            o Modules - these form an internal circle
 //            o Depends - arcs between modules
 //
 //          This is a base class, and can used by several modules.
 //          For that reason, we don't specify the Invoking modules.
 //
 // Authors:
 //   txe  Travis Emmitt  emmitt@virginia.edu
 //
 // Modifications:
 //   28-OCT-1998  txe  (v1) Initial creation (was screen.Draw)
 //   29-OCT-1998  txe  Removed GetSelection
 //   03-NOV-1998  txe  Added comments, removed unused methods.
 //   06-NOV-1998  rgb  Added version control header info
 //
 //   12-NOV-1998  txe  (v2) Uses bounds
 //   13-NOV-1998  txe  Extends Map, added Exceptions, new layout
 //   14-NOV-1998  txe  Added zoom
 //   16-NOV-1998  txe  Improved exceptions, comments
 //   17-NOV-1998  txe  Added reverse_arrows, pretty updates, matrix
 //   19-NOV-1998  txe  Improved DrawMatrix(), added DrawArrow
 //   20-NOV-1998  txe  Now uses GetDepends()
 //   22-NOV-1998  txe  Limited matrix dot size (for low total_nodes)
 //
 //   30-NOV-1998  txe  (v3) Improved format, speed
 //
 ////////////////////////////////////////////////////////////////////////////
 import java.applet.*;
 import java.awt.*;
 public class DrawableMap extends Map {
   private DrawableModule drawable_modules[]; // set of DrawableModules
   private DrawableModule zoom_module;    // zoomed module
   private int x;             // X coordinate of northwest corner
   private int y;                         // Y coordinate of northwest corner
   private int w;                         // width
   private int h;                         // height
   private int edit_id;                 // which Module can I edit?
   private int zoom_id;                   // which Module is zoomed?
   private int    selected_module_id;      // which module to draw depends to/from
   private int selected_node_id;          // which node to draw depends to/from
   private int zoom_bounds[];             // bounds for zoomed node
   private boolean always_arrows  = true; // turn off if you don't want arrows
   private boolean reverse_arrows = false;// reverse dependency arrows
   private boolean pretty_updates = true; // show all nodes when not final
   private boolean draw_pie_piece = false;// draw zoom-in pie piece 
   private static final double
     DOT_SIZE                   = 0.7;    // size of dependency in cell
   private static final int
     ZOOM                   = -2,     // flag indicating the zoomed module
     MAX_MATRIX_NAME_LEN        = 20,     // maximum length of label in matrix
     WEDGE_DELTA                   = 75,     // "pie piece" wedge delta in degrees
     ARROW_LENGTH           = 10,     // length of dependency arrow-head
     NORMAL_MODE                   = 0,      // normal viewing mode
     SHOW_ALL_NODES           = 1,      // mode option: show all nodes
     DEPENDEE_MODE           = 2,      // mode option: we're a dependee
     DEPENDER_MODE           = 3;      // mode option: we're a depender
   private static final Color
     LABEL_COLOR               = new Color (0.0f, 0.0f, 0.0f), // black
     DIAGONAL_COLOR           = new Color (0.3f, 0.3f, 0.3f), // dk grey
     STABLE_FCOLOR           = new Color (0.3f, 0.6f, 0.3f), // dk green
     STABLE_BCOLOR           = new Color (0.7f, 0.9f, 0.7f), // lt green
     UNSTABLE_FCOLOR           = new Color (0.6f, 0.3f, 0.3f), // dk red
     UNSTABLE_BCOLOR           = new Color (0.8f, 0.5f, 0.5f), // lt red
     MODULE_TO_MODULE_COLOR     = new Color (0.0f, 0.0f, 0.0f), // black
     NODE_TO_NODE_COLOR           = new Color (0.0f, 0.0f, 0.8f), // dk blue
     NODE_TO_MODULE_COLOR       = new Color (0.2f, 0.2f, 1.0f); // lt blue
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  DrawableMap  [constructor]
   //
   // Purpose: This creates a new DrawableMap representing the
   //          specified Map at the specified coordinates, with
   //          an indication of which Module this Client owns.
   //
   //          This creates a new DrawableModule for each Module
   //          and a new DrawableDepend for each Depend.
   //   
   ///////////////////////////////////////////////////////////////////
   public DrawableMap (Map new_map, int new_bounds[], int new_edit_id)
   throws BoundsException, IndexException, NewException, NullException {
     if (new_map == null) {
       throw new NullException ("new_map");
     }
     if (new_bounds == null) {
       throw new NullException ("new_bounds");
     }
     Copy (new_map);
     int i = 0;
     try {
       x = new_bounds[i++];
       y = new_bounds[i++];
       w = new_bounds[i++];
       h = new_bounds[i++];
     }
     catch (Exception e) {
       throw new IndexException ("new_bounds", i);
     }
     edit_id            = new_edit_id;
     zoom_id            = new_edit_id;
     selected_module_id = -1;
     selected_node_id   = -1;
     if (num_modules < 1) {
       throw new BoundsException ("num_modules", num_modules, 1);
     }
     drawable_modules = new DrawableModule [num_modules];
     zoom_bounds      = new int [4];
     zoom_bounds[2]   = (int) (w * 0.60);
     zoom_bounds[3]   = (int) (h * 0.60);
     zoom_bounds[0]   = x + (w - zoom_bounds[2]) / 2;
     zoom_bounds[1]   = y + (h - zoom_bounds[3]) / 2;
     int module_w     = (w / 7);
     int module_h     = (h / 10);
     int base_x       = GetCenterX() - (module_w / 2);
     int base_y       = GetCenterY() - (module_h / 2);
     double radius    = (double) w * 0.42;
     double angle     = Math.PI / 2;
     double delta     = 2 * Math.PI / (double) Math.max (num_modules, 1);
     for (i = 0; i < num_modules; i++) {
       int module_x        = base_x + (int) (radius * Math.cos (angle));
       int module_y        = base_y - (int) (radius * Math.sin (angle));
       int module_bounds[] = { module_x, module_y, module_w, module_h };
       drawable_modules[i] =
     new DrawableModule (GetModule(i), module_bounds, (i==edit_id), false);
       angle -= delta;
     }
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Draw
   //
   // Purpose: This displays the Map on the screen.
   //                    If show_all_nodes is true, we show all nodes in
   //                    all modules, regardless of whether or not they
   //                    are in the zoomed module.
   //   
   ///////////////////////////////////////////////////////////////////
   public void Draw (Graphics graphics, boolean show_all_nodes)
   throws BoundsException, GraphicsException, IndexException,
      NewException, NullException {
     if (graphics == null) {
       throw new NullException ("graphics");
     }
     if (pretty_updates && !IsFinal ()) {
       show_all_nodes = true;
       Zoom (-1);    // zoom out
     }
     // First, determine which module is zoomed //
     if (zoom_id >= 0) {
       boolean editable = (zoom_id == edit_id);
       zoom_module = new DrawableModule (GetModule(zoom_id), zoom_bounds, editable, true);
       // draw zoomed module and its shaded "pie piece" //
       if (draw_pie_piece) {
     int small_x   = GetDrawableModule(zoom_id).GetCenterX ();
     int small_y   = GetDrawableModule(zoom_id).GetCenterY ();
     int big_x     = GetDrawableModule(ZOOM).GetCenterX ();
     int big_y     = GetDrawableModule(ZOOM).GetCenterY ();
     double dx     = (double) (big_x - small_x);
     double dy     = (double) (big_y - small_y);
     double distance = Math.max (Math.sqrt ((dx * dx) + (dy * dy)), 1);
     double delta  = Math.PI / 360.0 * (double) WEDGE_DELTA;
     double angle  = Math.atan2 (dy, dx);
     double angle1 = angle - delta;
     double angle2 = angle + delta;
     int x1        = small_x + (int) (distance * Math.cos (angle1));
     int y1        = small_y + (int) (distance * Math.sin (angle1));
     int x2        = small_x + (int) (distance * Math.cos (angle2));
     int y2        = small_y + (int) (distance * Math.sin (angle2));
     int xpts[]    = { small_x, x1, x2 };
     int ypts[]    = { small_y, y1, y2 };
     try {
       graphics.setColor (Color.pink);
       graphics.fillPolygon (xpts, ypts, 3);
     }
     catch (Exception e) {
       throw new GraphicsException (e);
     }
       }
       zoom_module.Draw (graphics, NORMAL_MODE);
     }
     // Draw orbiting (un-zoomed) modules //
     int mode = (show_all_nodes ? SHOW_ALL_NODES : NORMAL_MODE);
     for (int i = 0; i < num_modules; i++) {
       GetDrawableModule(i).Draw (graphics, mode);
     }
     // Draw whatever dependencies should be visible //
     if (selected_module_id >= 0) {
       DrawDepends (graphics, selected_module_id, ANY, ANY);
       DrawDepends (graphics, selected_module_id, ANY, ZOOM);
     }
     else if (selected_node_id >= 0) {
       DrawDepends (graphics, ZOOM, selected_node_id, ANY);
       DrawDepends (graphics, ZOOM, selected_node_id, ZOOM);
     }
     else if (zoom_id >= 0) {
       DrawDepends (graphics, ZOOM, ANY, ANY);
       for (int i = 0; i < GetDrawableModule(ZOOM).GetNumNodes(); i++) {
     DrawDepends (graphics, ZOOM, i, ZOOM);
       }
     }
     else {
       for (int i = 0; i < num_modules; i++) {
     DrawDepends (graphics, i, ANY, ANY);
       }
     }
   }
   ////////////////////////////////////////////////////////////////////////
   //
   // Method:  DrawArrow  (private)
   //
   // Purpose:    Draws an arrow from the specified source coordinate to
   //          to destination coordinate with the specified color.
   //
   ////////////////////////////////////////////////////////////////////////
   private void DrawArrow (Graphics graphics, int x1, int y1, int x2, int y2, Color color)
   throws GraphicsException {
     double distance = ARROW_LENGTH;
     double delta    = Math.PI / 8;
     double angle    = Math.atan2 (y2 - y1, x2 - x1);
     double angle1   = angle - delta;
     double angle2   = angle + delta;
     int x3        = x2 - (int) (distance * Math.cos (angle1));
     int y3        = y2 - (int) (distance * Math.sin (angle1));
     int x4          = x2 - (int) (distance * Math.cos (angle2));
     int y4          = y2 - (int) (distance * Math.sin (angle2));
     int xpts[]      = { x2, x3, x4 };
     int ypts[]      = { y2, y3, y4 };
     try {
       graphics.setColor    (color);
       graphics.drawLine    (x1, y1, x2, y2);
       graphics.fillPolygon (xpts, ypts, 3);
     }
     catch (Exception e) {
       throw new GraphicsException (e);
     }
   }
   ////////////////////////////////////////////////////////////////////////
   //
   // Method:  DrawDepend
   //
   // Purpose: Draws a dependency arc from specified source to specified
   //          destination.  This can handle all combinations of modular
   //          and nodal dependencies.     It also highlights the source
   //          and destination nodes by setting their colors to special
   //          values via the DEPENDEE_MODE and DEPENDER_MODE viewing
   //          options.
   //
   ////////////////////////////////////////////////////////////////////////
   public void DrawDepend (Graphics graphics, int source_module_id,
               int source_node_id, int dest_module_id, int dest_node_id)
   throws BoundsException, GraphicsException, IndexException, NullException {
     if (graphics == null) {
       throw new NullException ("graphics");
     }
     if ((source_module_id == ZOOM || dest_module_id == ZOOM) && zoom_id < 0) {
       throw new NullException ("zoom_module");
     }
     boolean source_is_zoom = (source_module_id == ZOOM &amp;&amp; source_node_id == ANY);
     boolean source_is_moon = (source_module_id != ZOOM &amp;&amp; source_node_id == ANY);
     boolean source_is_node = (source_module_id == ZOOM &amp;&amp; source_node_id != ANY);
     boolean dest_is_zoom   = (dest_module_id   == ZOOM &amp;&amp; dest_node_id   == ANY);
     boolean dest_is_moon   = (dest_module_id   != ZOOM &amp;&amp; dest_node_id   == ANY);
     boolean dest_is_node   = (dest_module_id   == ZOOM &amp;&amp; dest_node_id   != ANY);
     if ((source_module_id == dest_module_id
         &amp;&amp; (!source_is_node || !dest_is_node || source_node_id == dest_node_id))
      || (source_module_id == zoom_id &amp;&amp; dest_module_id == ZOOM)
      || (source_module_id == ZOOM    &amp;&amp; dest_module_id == zoom_id)) {
       return;
     }
     // If depend is not within the zoomed mode, light up dependents //
     if (zoom_id >= 0) {
       if (!source_is_node || !dest_is_node || selected_node_id >= 0 || selected_module_id >= 0) {
     if (source_is_node &amp;&amp; source_node_id != selected_node_id) {
       GetDrawableNode (source_module_id, source_node_id).Draw (graphics, DEPENDER_MODE);
     }
     if (dest_is_node &amp;&amp; dest_node_id != selected_node_id) {
       GetDrawableNode (dest_module_id, dest_node_id).Draw (graphics, DEPENDEE_MODE);
     }
     if (source_is_moon &amp;&amp; !dest_is_zoom &amp;&amp; source_module_id != selected_module_id) {
       GetDrawableModule (source_module_id).Draw (graphics, DEPENDER_MODE);
     }
     if (dest_is_moon &amp;&amp; !source_is_zoom &amp;&amp; dest_module_id != selected_module_id) {
       GetDrawableModule (dest_module_id).Draw (graphics, DEPENDEE_MODE);
     }
       }
       // Don't print any arcs //
       if (!always_arrows &amp;&amp; (!source_is_node || !dest_is_node)) {
     return;
       }
     }
     int source_x   = GetDrawableModule(source_module_id).GetCenterX (source_node_id);
     int source_y   = GetDrawableModule(source_module_id).GetCenterY (source_node_id);
     int dest_x     = GetDrawableModule(dest_module_id).GetCenterX   (dest_node_id);
     int dest_y     = GetDrawableModule(dest_module_id).GetCenterY   (dest_node_id);
     int step_size  = 3;
     int dx         = dest_x - source_x;
     int dy         = dest_y - source_y;
     double arc_len = (int) Math.max (Math.sqrt ((dx * dx) + (dy * dy)), 1);
     if (arc_len == 0) {
       return;
     }
     double step_dx = (double) (dx * step_size) / arc_len;
     double step_dy = (double) (dy * step_size) / arc_len;
     int start_x = source_x;
     int start_y = source_y;
     int end_x   = dest_x;
     int end_y   = dest_y;
     for (int i = 0; (!source_is_node &amp;&amp; InsideModule (source_module_id, start_x, start_y))
        || (source_is_node &amp;&amp; InsideNode (source_module_id, source_node_id, start_x, start_y));    i++) {
       start_x = source_x + (int) (i * step_dx);
       start_y = source_y + (int) (i * step_dy);
     }
     for (int i = 0; (!dest_is_node &amp;&amp; InsideModule (dest_module_id, end_x, end_y))
        || (dest_is_node &amp;&amp; InsideNode (dest_module_id, dest_node_id, end_x, end_y)); i++) {
       end_x = dest_x - (int) (i * step_dx);
       end_y = dest_y - (int) (i * step_dy);
     }
     Color color = null;
     if (!source_is_node &amp;&amp; !dest_is_node) {
       color = MODULE_TO_MODULE_COLOR;
     }
     else if (source_is_node &amp;&amp; dest_is_node) {
       color = NODE_TO_NODE_COLOR;
     }
     else {
       color = NODE_TO_MODULE_COLOR;
     }
     if (reverse_arrows) {
       DrawArrow (graphics, end_x, end_y, start_x, start_y, color);
     }
     else {
       DrawArrow (graphics, start_x, start_y, end_x, end_y, color);
     }
   }
   //////////////////////////////////////////////////////////////////////////
   //
   // Method:  DrawDepends
   //
   // Purpose: This displays dependencies from our Module/Node to
   //          other Modules (or nodes in the specified Module)
   //          and vice-versa.
   //   
   ///////////////////////////////////////////////////////////////////
   public void DrawDepends (Graphics graphics, int our_module_id,
                int our_node_id,   int his_module_id)
   throws BoundsException, GraphicsException, IndexException,
      NewException, NullException {
     if ((our_module_id == ZOOM || his_module_id == ZOOM) && zoom_id < 0) {
       return;
     }
     int our_real_id     = (our_module_id == ZOOM ? zoom_id : our_module_id);
     int his_real_id     = (his_module_id == ZOOM ? zoom_id : his_module_id);
     boolean any         = (his_module_id == ANY);
     Depend to_hits   [] = GetDepends (our_real_id, our_node_id, true);
     Depend from_hits [] = GetDepends (our_real_id, our_node_id, false);
     for (int i = 0; i < to_hits.length; i++) {
       int module_id = to_hits[i].GetSourceModuleID();
       int node_id   = (any ? ANY : to_hits[i].GetSourceNodeID());
       if (any || module_id == his_real_id) {
     module_id = (any ? module_id : his_module_id);
     DrawDepend (graphics, module_id, node_id, our_module_id, our_node_id);
       }
     }
     for (int i = 0; i < from_hits.length; i++) {
       int module_id = from_hits[i].GetDestModuleID();
       int node_id   = (any ? ANY : from_hits[i].GetDestNodeID());
       if (any || module_id == his_real_id) {
     module_id = (any ? module_id : his_module_id);
     DrawDepend (graphics, our_module_id, our_node_id, module_id, node_id);
       }
     }
   }
   ////////////////////////////////////////////////////////////////////////
   //
   // Method:  DrawMatrix
   //
   // Purpose:    Draws a matrix representation of the Map's current
   //          dependencies and stabilities.
   //
   // Note:    This has been optimized for speed, at the possible 
   //          expense of safety.                                 
   //
   ////////////////////////////////////////////////////////////////////////
   public void DrawMatrix (Graphics graphics)
   throws BoundsException, GraphicsException, IndexException, NullException {
     boolean stables[] = new boolean [total_nodes];
     int base_x     = x + (int) ((double) w * 0.01);
     int base_y     = y + (int) ((double) h * 0.05);
     int start_x    = x + (int) ((double) w * 0.20);
     int start_y    = y + (int) ((double) h * 0.10);
     int end_x      = x + (int) ((double) w * 1.00);
     int end_y      = y + (int) ((double) h * 0.90);
     double label_w = (double) (end_x - start_x) / (double) num_modules;
     double label_h = (double) (end_y - start_y) / (double) num_modules;
     double cell_w  = (double) (end_x - start_x) / (double) total_nodes;
     double cell_h  = (double) (end_y - start_y) / (double) total_nodes;
     int cell_x     = start_x;
     int cell_y     = start_y;
     int font1_size = 10;
     int font2_size = 8;
     Font left_font = new Font ("Helvetica", Font.PLAIN, font1_size);
     Font top_font  = new Font ("Helvetica", Font.PLAIN, font2_size);
     int edge       = 2;
     int max_dot_w  = (int) ((double) font1_size * 2.5);
     int max_dot_h  = (int) ((double) (max_dot_w * cell_h) / (double) cell_w);
     int dot_w      = Math.min ((int) (cell_w * DOT_SIZE), max_dot_w);
     int dot_h      = Math.min ((int) (cell_h * DOT_SIZE), max_dot_h);
     int dot_base_x = start_x + (int) ((cell_w - dot_w) / 2);
     int dot_base_y = start_y + (int) ((cell_h - dot_h) / 2);
     int x2         = start_x - (int) ((double) dot_w * 1.1);
     int y3         = base_y  + 2;
     int y4         = start_y;
     for (int i = 0, n = 0; i < num_modules; i++) {
       Module module = modules[i];
       String label  = module.GetName();
       int num_nodes = module.GetNumNodes();
       int label_x   = start_x  + (int) ((double) (i + 0.2) * label_w);
       int label_y   = start_y  + (int) ((double) (i + 0.5) * label_h + font1_size / 2);
       int module_x  = start_x  + (int) ((double) n * cell_w);
       int module_y  = start_y  + (int) ((double) n * cell_h);
       int x1        = base_x   + (int) (font1_size * label.length() * 0.6);
       int y1        = label_y  - (int) (font1_size * 0.5);
       int y2        = module_y + (int) (cell_h * (double) num_nodes * 0.5);
       int x3        = label_x  + (int) (font2_size * label.length() * 0.25);
       int x4        = module_x + (int) (cell_w * (double) num_nodes * 0.5);
       // draw module labels //
       graphics.setColor   (LABEL_COLOR);
       graphics.setFont    (left_font);
       graphics.drawString (label, base_x, label_y);
       graphics.setFont    (top_font);
       graphics.drawString (label, label_x, base_y);
       // draw module-delineating grid lines //
       graphics.drawLine   (module_x, start_y,  module_x, end_y);
       graphics.drawLine   (start_x,  module_y, end_x,    module_y);
       // draw lines from labels to corresponding grid range //
       graphics.drawLine   (x1, y1, x2, y2);
       graphics.drawLine   (x4, y4, x3, y3);
       // draw node stabilities on left //
       for (int j = 0; j < num_nodes; j++, n++) {
     int dot_y  = dot_base_y + (int) ((double) n * cell_h);
     stables[n] = module.GetNode(j).IsStable();
     graphics.setColor (stables[n] ? STABLE_FCOLOR : UNSTABLE_FCOLOR);
     graphics.fillOval (x2, dot_y, dot_w, dot_h);
     // draw dependencies in grid //
     Depend hits[] = GetDepends (i, j, false);
     for (int k = 0; k < hits.length; k++) {
       int module_id = hits[k].GetDestModuleID ();
       int node_id   = hits[k].GetDestNodeID   ();
       int m         = module_offsets[module_id] + node_id;
       int dot_x     = dot_base_x + (int) ((double) m * cell_w);
       graphics.fillOval (dot_x, dot_y, dot_w, dot_h);
     }
       }
     }
     // draw border grid lines //
     graphics.setColor (Color.black);
     graphics.drawLine (start_x,  start_y,  start_x, end_y);
     graphics.drawLine (end_x,    start_y,  end_x,   end_y);
     graphics.drawLine (start_x,  start_y,  end_x,   start_y);
     graphics.drawLine (start_x,  end_y,    end_x,   end_y);
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetCenterX
   //
   // Purpose: Returns X coordinate of center of DrawableMap.
   //   
   ///////////////////////////////////////////////////////////////////
   public int GetCenterX () {
     return x + (w / 2);
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetCenterX
   //
   // Purpose: Returns X coordinate of center of specified 
   //          DrawableModule.
   //   
   ///////////////////////////////////////////////////////////////////
   public int GetCenterX (int module_id)
   throws BoundsException, IndexException, NullException {
     return GetDrawableModule(module_id).GetCenterX ();
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetCenterY
   //
   // Purpose: Returns Y coordinate of center of DrawableMap.
   //   
   ///////////////////////////////////////////////////////////////////
   public int GetCenterY () {
     return y + (h / 2);
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetCenterY
   //
   // Purpose: Returns Y coordinate of center of specified 
   //          DrawableModule.
   //   
   ///////////////////////////////////////////////////////////////////
   public int GetCenterY (int module_id)
   throws BoundsException, IndexException, NullException {
     return GetDrawableModule(module_id).GetCenterY ();
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetDrawableModule
   //
   // Purpose: Returns reference to specified DrawableModule.
   //   
   ///////////////////////////////////////////////////////////////////
   public DrawableModule GetDrawableModule (int module_id)
   throws BoundsException, IndexException, NullException {
     DrawableModule drawable_module = null;
     if (module_id == ZOOM) {
       drawable_module = zoom_module;
       if (drawable_module == null) {
     throw new NullException ("zoom_module");
       }
     }
     else if (module_id < 0 || module_id >= num_modules) {
       throw new BoundsException ("module_id", module_id, 0, num_modules - 1);
     }
     else {
       try {
     drawable_module = drawable_modules[module_id];
       }
       catch (Exception e) {
     throw new IndexException ("drawable_modules", module_id);
       }
       if (drawable_module == null) {
     throw new NullException ("drawable_modules", module_id);
       }
     }
     return drawable_module;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetDrawableNode
   //
   // Purpose: Returns reference to specified DrawableNode.
   //   
   ///////////////////////////////////////////////////////////////////
   public DrawableNode GetDrawableNode (int module_id, int node_id)
   throws BoundsException, IndexException, NullException {
     return GetDrawableModule(module_id).GetDrawableNode (node_id);
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetPointedModuleID
   //
   // Purpose: This returns the id of the module selected by the
   //          coordinates, or -1 if no modules are selected.
   //   
   ///////////////////////////////////////////////////////////////////
   public int GetPointedModuleID (int new_x, int new_y)
   throws BoundsException, IndexException, NullException {
     for (int i = 0; i < num_modules; i++) {
       if (InsideModule (i, new_x, new_y)) {
     return i;
       }
     }
     return -1;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetPointedNodeID
   //
   // Purpose: This returns the id of the Node selected by the
   //          coordinates, or -1 if no modules are selected.
   //   
   ///////////////////////////////////////////////////////////////////
   public int GetPointedNodeID (int new_x, int new_y)
   throws BoundsException, IndexException, NullException {
     if (zoom_id < 0) {
       return -1;
     }
     for (int i = 0; i < GetDrawableModule(ZOOM).GetNumNodes(); i++) {
       if (InsideNode (ZOOM, i, new_x, new_y)) {
     return i;
       }
     }
     return -1;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  GetZoomID
   //
   // Purpose: This returns the id of the currently zoomed module, or
   //          -1 if no module is zoomed.
   //   
   ///////////////////////////////////////////////////////////////////
   public int GetZoomID () {
     return zoom_id;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Inside
   //
   // Purpose: This returns true if the specified coordinate is within
   //          the bounds of the Map, else false.
   //   
   ///////////////////////////////////////////////////////////////////
   public boolean Inside (int new_x, int new_y) {
     return (new_x >= x && new_x <= x + w
          && new_y >= y && new_y <= y + h);
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  InsideModule
   //
   // Purpose: This returns true if the specified coordinate is within
   //          the bounds of the specified DrawableModule, else false.
   //   
   ///////////////////////////////////////////////////////////////////
   public boolean InsideModule (int module_id, int new_x, int new_y)
   throws BoundsException, IndexException, NullException {
     return GetDrawableModule(module_id).Inside (new_x, new_y);
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  InsideNode
   //
   // Purpose: This returns true if the specified coordinate is within
   //          the bounds of the specified DrawableNode, else false.
   //   
   ///////////////////////////////////////////////////////////////////
   public boolean InsideNode (int module_id, int node_id, int new_x, int new_y)
   throws BoundsException, IndexException, NullException {
     return GetDrawableModule(module_id).InsideNode (node_id, new_x, new_y);
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  SelectModule
   //
   // Purpose: Allows map to keep track of which DrawableModule is
   //          selected (for displaying dependencies).
   //   
   ///////////////////////////////////////////////////////////////////
   public void SelectModule (int module_id)
   throws BoundsException, IndexException, NullException {
     if (module_id >= 0) {
       DrawableModule temp = GetDrawableModule (module_id);
     }
     selected_module_id  = module_id;
     selected_node_id    = -1;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  SelectNode
   //
   // Purpose: Allows map to keep track of which DrawableNode is
   //          selected (for displaying dependencies).
   //   
   ///////////////////////////////////////////////////////////////////
   public void SelectNode (int node_id)
   throws BoundsException, IndexException, NullException {
     if (node_id >= 0) {
       DrawableNode temp = GetDrawableNode (ZOOM, node_id);
     }
     selected_node_id   = node_id;
     selected_module_id = -1;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Zoom
   //
   // Purpose: If specified module is zoomed in, this zooms out;
   //          otherwise, it zooms in on the specified module.
   //   
   ///////////////////////////////////////////////////////////////////
   public void Zoom (int module_id)
   throws BoundsException, IndexException, NullException {
     if (module_id >= 0) {
       DrawableModule temp = GetDrawableModule (module_id);
     }
     zoom_id             = (module_id == zoom_id ? -1 : module_id);
     selected_module_id  = -1;
     selected_node_id    = -1;
   }
 }
 ////////////////////////////////////////////////////////////////////////////