code: /**
   * Copyright (c) 2004-2005, Regents of the University of California
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * Redistributions of source code must retain the above copyright notice,
   * this list of conditions and the following disclaimer.
   *
   * Redistributions in binary form must reproduce the above copyright
   * notice, this list of conditions and the following disclaimer in the
   * documentation and/or other materials provided with the distribution.
   *
   * Neither the name of the University of California, Los Angeles nor the
   * names of its contributors may be used to endorse or promote products
   * derived from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  package avrora.gui;
  
  import avrora.sim.Simulation;
  import avrora.sim.Simulation.Node;
  import avrora.sim.Simulator;
  import java.util.*;
  
  /**
   * There are two types of visual monitors for the GUI.  First, there are single
   * node monitors.  Each time a monitor is added to a node, a new panel is created
   * and each "instance" of this monitor gets its chalkboard/panel to draw on.
   * Second, there are global monitors.  Every time a global monitor is attached 
   * to a new node, one one total chalkboard/diplay panel is created.  (e.g. a
   * global monitor might have five nodes attached to it, but each node only 
   * writes to one central chalkboard).
   * <p>
   * This class is for the first type: single node monitors.  It is a physical
   * implementation of a monitor factory -> thus once inited, it can create
   * nodes on command.
   * <p>
   * Since many of the single node monitors are very similar is data collection 
   * and display (just a few lines are different in the actual data collection),
   * most single node monitors can just use this class as a factory.
   *
   * @author Ben L. Titzer
   */
  public abstract class SingleNodeMonitor implements Simulation.GuiMonitor {
  
      final HashMap<Node, SingleNodePanel> panelMap; // maps VisualSimulation.Node -> SingleNodePanel
      final String monitorName;
  
      /**
       * Default constructor, will init the hash maps that store information
       * about the monitors in this node
       */
      public SingleNodeMonitor(String n) {
          panelMap = new HashMap<Node, SingleNodePanel>();
          monitorName = n;
      }
  
      /**
       * This actually informs our data structure that the list of
       * nodes passed to this function want this monitor.  A display 
       * panel is created.   Note that the monitors are NOT created
       * by attach - you need to call init
       *
       * @param nodes A list of the nodes that should be attached to the monitor
       */
      public void attach(Simulation sim, List<Simulation.Node> nodes) {
          for (Simulation.Node node : nodes) {
              if ( panelMap.containsKey(nodes) ) continue;
              MonitorPanel p = AvroraGui.instance.createMonitorPanel(monitorName+" - "+node.id);
              SingleNodePanel snp = newPanel(node, p);
              panelMap.put(node, snp);
              node.addGuiMonitor(this);
          }
      }
  
      /**
       * This is called at the beginning of the simulation to physically
       * create the nodes
       *
       * @param n The node the monitor is attached to
       * @param s The simulator that the monitor can be inserted into
       */
      public void construct(Simulation sim, Simulation.Node n, Simulator s) {
          panelMap.get(n).construct(s);
      }
  
      /**
       * This is called at the end of the simulation to remove any data structures
       * associated with the nodes.
       *
       * @param n The node the monitor is attached to
       * @param s The simulator that the monitor can be inserted into
       */
      public void destruct(Simulation sim, Simulation.Node n, Simulator s) {
          panelMap.get(n).destruct();
      }
  
      /**
       * You can multiple remove nodes from a monitor using this function
       *
       * @param nodes A <code> List </code> of nodes that should be removed.  If an 
       * element of the list is not already attached to the node, it will just
       * skip that element.
       */
      public void remove(Simulation sim, List<Simulation.Node> nodes) {
          for (Simulation.Node n : nodes) {
              removeOne(n);
          }
      }
  
      private void removeOne(Simulation.Node n) {
          SingleNodePanel snp = panelMap.get(n);
          if ( snp == null ) return;
  
          snp.remove();
          AvroraGui.instance.removeMonitorPanel(snp.panel);
          panelMap.remove(n);
          n.removeGuiMonitor(this);
      }
  
      protected abstract class SingleNodePanel {
          protected final Simulation.Node node;
          protected final MonitorPanel panel;
  
          SingleNodePanel(Simulation.Node n, MonitorPanel p) {
              node = n;
              panel = p;
          }
  
          protected abstract void construct(Simulator s);
          protected abstract void destruct();
          protected abstract void remove();
      }
  
      protected abstract SingleNodePanel newPanel(Simulation.Node n, MonitorPanel p);
  }
  