gt:     bounds = getBounds();
context: /*
   * $Id$
   *
   * This software is provided by NOAA for full, free and open release.  It is
   * understood by the recipient/user that NOAA assumes no liability for any
   * errors contained in the code.  Although this software is released without
   * conditions or restrictions in its use, it is expected that appropriate
   * credit be given to its author and to the National Oceanic and Atmospheric
   * Administration should the software be included by the recipient as an
   * element in other product development.
   */
  
  package  gov.noaa.pmel.sgt;
  
  import gov.noaa.pmel.util.Point2D;
  import gov.noaa.pmel.util.Rectangle2D;
  import gov.noaa.pmel.util.Debug;
  
  import java.util.Vector;
  import java.util.Enumeration;
  import java.awt.Graphics;
  import java.awt.Graphics2D;
  import java.awt.Stroke;
  import java.awt.BasicStroke;
  import java.awt.geom.GeneralPath;
  import java.awt.Rectangle;
  import java.awt.Point;
  import java.text.DecimalFormat;
  
  import java.beans.PropertyChangeListener;
  import java.beans.PropertyChangeEvent;
  import java.beans.PropertyChangeSupport;
  
  /**
   * <code>VectorKey</code> is used to create a key for the
   * <code>VectorCartesianRenderer</code>. Multiple
   * lines can be included in the key.
   *
   * @author Donald Denbo
   * @version $Revision$, $Date$
   * @since 2.1
  **/
  public class VectorKey implements Cloneable,
      DataKey, Moveable, PropertyChangeListener {
    private String ident_;
    /** @directed */
    private Layer layer_;
    /** @link aggregation
     * @supplierCardinality *
     * @label vectors*/
    /*#VectorCartesianRenderer lnkVectorCartesianRenderer; */
    private Vector vectors_;
    /**
       *@link aggregation
       *     @associates <{SGLabel}>
       * @label label
       * @supplierCardinality *
       * @undirected
       */
    /* private Vector lnkSGLabel; */
    private Vector label_;
    private Vector scaleLabel_;
    private int columns_;
    private int style_;
    private int valign_;
    private int halign_;
    private Point2D.Double porigin_;
    private double vectorLengthP_;
    private int maxLabelLength_;
    private int maxLabelHeight_;
    private int maxScaleLength_;
    private String floatScaleFormat_ = "###.##";
    private String expScaleFormat_ = "0.####E0";
    private DecimalFormat floatFormat_;
    private DecimalFormat expFormat_;
    private float xoff_;
    private float yoff_;
    private float slope_;
    private boolean selected_;
    private boolean selectable_;
    private boolean visible_;
    private boolean moveable_;
    private PropertyChangeSupport changes_ = new PropertyChangeSupport(this);
    private static final int VERTICAL_BORDER_ = 3;
    private static final int HORIZONTAL_BORDER_ = 15;
    private static final int COLUMN_SPACE_ = 10;
    private static final int ROW_SPACE_ = 3;
    private static final int LABEL_SPACE_ = 10;
    private static final int SCALE_SPACE_ = 7;
    /**
     * Use plain line border.
     */
    public static final int PLAIN_LINE = 0;
    /**
     * Use raised border.
     */
    public static final int RAISED = 1;
    /**
     * Do not draw a border.
     */
    public static final int NO_BORDER = 2;
    /**
     * Align to top of key.
     */
    public static final int TOP = 0;
    /**
     * Align to middle of key.
     */
    public static final int MIDDLE = 1;
    /**
     * Align to bottom of key.
     */
    public static final int BOTTOM = 2;
    /**
     * Align to left of key.
     */
    public static final int LEFT = 0;
    /**
     * Align to center of key.
     */
    public static final int CENTER = 1;
    /**
     * Align to right of key.
     */
    public static final int RIGHT = 2;
  
  
    /**
     * Default constructor.
     */
    public VectorKey() {
      this(new Point2D.Double(0.0, 0.0), BOTTOM, LEFT);
    }
    /**
     * Create <code>VectorKey</code>.
     */
    public VectorKey(Point2D.Double loc,int valign,int halign) {
      porigin_ = loc;
      valign_ = valign;
      halign_ = halign;
      vectors_ = new Vector(2,2);
      label_ = new Vector(2,2);
      scaleLabel_ = new Vector(2,2);
      //
      // set defaults
      //
      style_ = PLAIN_LINE;
      columns_ = 1;
      ident_ = "";
      vectorLengthP_ = 0.3f;
      selected_ = false;
      selectable_ = true;
      visible_ = true;
      moveable_ = true;
  
      floatFormat_ = new DecimalFormat(floatScaleFormat_);
      expFormat_ = new DecimalFormat(expScaleFormat_);
    }
    /**
     * Create of copy of VectorKey.
     */
    public LayerChild copy() {
      VectorKey newKey;
      try {
        newKey = (VectorKey)clone();
      } catch (CloneNotSupportedException e) {
        newKey = new VectorKey();
      }
      newKey.vectors_ = new Vector(2,2);
      newKey.label_ = new Vector(2,2);
      return newKey;
    }
    public void setSelected(boolean sel) {
      selected_ = sel;
    }
    public boolean isSelected() {
      return selected_;
    }
    public void setSelectable(boolean select) {
      selectable_ = select;
    }
    public boolean isSelectable() {
      return selectable_;
    }
    public boolean isMoveable() {
      return moveable_;
    }
    public void setMoveable(boolean moveable) {
      moveable_ = moveable;
    }
    /**
     * Set parent layer.
     *
     * @param l parent layer
     */
    public void setLayer(Layer l) {
      layer_ = l;
    }
    /**
     * Get layer.
     *
     * @return layer
     */
    public Layer getLayer() {
      return layer_;
    }
  
    public AbstractPane getPane() {
      return layer_.getPane();
    }
  
    public void modified(String mess) {
      if(layer_ != null)
        layer_.modified(mess);
    }
    /**
     * Set VectorKey identifier.
     *
     * @param id key identifier
     */
    public void setId(String id) {
      ident_ = id;
    }
    /**
     * Get VectorKey identifier
     *
     * @return identifier
     */
    public String getId() {
      return ident_;
    }
    /**
     * Set line length.
     *
     * @param len line length
     */
    public void setVectorLengthP(double len) {
      if(vectorLengthP_ != len) {
        vectorLengthP_ = len;
        modified("VectorKey: setVectorLengthP()");
      }
    }
    /**
     * @since 3.0
     */
    public void setLineLengthP(double len) {
      setVectorLengthP(len);
    }
    /**
     * Get line length
     *
     * @return line length
     */
    public double getVectorLengthP() {
      return vectorLengthP_;
    }
    /**
     * Set the number of columns.
     *
     * @param col number of columns
     */
    public void setColumns(int col) {
      if(columns_ != col) {
        columns_ = col;
        modified("VectorKey: setColumms()");
      }
    }
    /**
     * Get the number of columns.
     *
     * @return number of columns
     */
    public int getColumns() {
      return columns_;
    }
    /**
     * Set border style.
     *
     * @param style border style
     * @see #PLAIN_LINE
     * @see #RAISED
     * @see #NO_BORDER
     */
    public void setBorderStyle(int style) {
      if(style_ != style) {
        style_ = style;
        modified("VectorKey: setBorderStyle()");
      }
    }
    /**
     * Get border style.
     *
     * @return border style
     */
    public int getBorderStyle() {
      return style_;
    }
    /**
     * Set alignment.
     *
     * @param vert vertical alignment
     * @param horz horizontal alignment
     */
    public void setAlign(int vert,int horz) {
      if(valign_ != vert || halign_ != horz) {
        valign_ = vert;
        halign_ = horz;
        modified("VectorKey: setAlign()");
      }
    }
    /**
     * Set vertical alignment
     *
     * @param vert vertical alignment
     */
    public void setVAlign(int vert) {
      if(valign_ != vert) {
        valign_ = vert;
        modified("VectorKey: setVAlign()");
      }
    }
    /**
     * Set horizontal alignment
     *
     * @param horz horizontal alignment
     */
    public void setHAlign(int horz) {
      if(halign_ != horz) {
        halign_ = horz;
        modified("VectorKey: setHAlign()");
      }
    }
    /**
     * Get vertical alignment
     *
     * @return vertical alignment
     */
    public int getVAlign() {
      return valign_;
    }
    /**
     * Get horizontal alignment
     *
     * @return horizontal alignment
     */
    public int getHAlign() {
      return halign_;
    }
    /**
     * Set location of key
     * <BR><B>Property Change:</B> <code>location</code>.
     *
     * @param loc key location
     */
    public void setLocationP(Point2D.Double loc) {
      if(porigin_ == null || !porigin_.equals(loc)) {
        Point2D.Double temp = porigin_;
        porigin_ = loc;
        changes_.firePropertyChange("location",
                                    temp,
                                    porigin_);
        modified("VectorKey: setLocationP()");
      }
    }
    /**
     * Set the bounds, in physical units, of the <code>VectorKey</code>
     */
    public void setBoundsP(Rectangle2D.Double r) {
      setLocationP(new Point2D.Double(r.x, r.y));
    }
    public Rectangle2D.Double getBoundsP() {
      throw new MethodNotImplementedError();
    }
    /**
     * Get location of key.
     *
     * @return Key location
     */
    public Point2D.Double getLocationP() {
      return porigin_;
    }
    /**
     * Add a VectorCartesianRenderer and label to the VectorKey.
     *
     * @param line VectorCartesianRenderer object
     * @param label descriptive label
     */
    public void addVectorGraph(VectorCartesianRenderer vector, SGLabel label) {
      vectors_.addElement(vector);
      label.setLayer(layer_);
      label.setMoveable(false);
      label.setSelectable(false);
      label_.addElement(label);
      SGLabel scale = new SGLabel("scale label",
                                  " ",
                                  label.getHeightP(),
                                  label.getLocationP(),
                                  label.getVAlign(),
                                  label.getHAlign());
      scale.setFont(label.getFont());
      scale.setLayer(label.getLayer());
      scale.setMoveable(false);
      scale.setSelectable(false);
      scaleLabel_.addElement(scale);
      ((VectorAttribute)vector.getAttribute()).addPropertyChangeListener(this);
      modified("VectorKey: addVectorGraph()");
    }
    /**
     * Add a VectorCartesianRenderer and label to the VectorKey.
     *
     * @param rend CartesianRenderer object
     * @param label descriptive label
     * @since 3.0
     */
    public void addGraph(CartesianRenderer rend, SGLabel label)
        throws IllegalArgumentException {
      if(!(rend instanceof VectorCartesianRenderer))
        throw new IllegalArgumentException("Renderer is not a VectorCartesianRenderer");
      addVectorGraph((VectorCartesianRenderer)rend, label);
    }
    /**
     * Remove a line from the VectorKey.
     *
     */
    public void removeVectorGraph(SGLabel label) {
    }
    /**
     * Remove a line from the VectorKey.
     *
     */
    public void removeVectorRenderer(VectorCartesianRenderer line) {
    }
    /**
     * Remove a line from the VectorKey.
     *
     */
    public void removeVectorGraph(String ident) {
    }
    /**
     * Remove all lines from the VectorKey.
     */
    public void clearAll() {
      VectorAttribute attr;
      for(Enumeration e = vectors_.elements(); e.hasMoreElements(); ) {
        attr = (VectorAttribute)((VectorCartesianRenderer)e.nextElement()).getAttribute();
        attr.removePropertyChangeListener(this);
      }
      vectors_.removeAllElements();
      label_.removeAllElements();
      modified("VectorKey: clearAll()");
    }
    /**
     * Remove data from key by id.
     */
    public void clear(String data_id) {
      VectorCartesianRenderer vcr;
      int indx = -1;
      for(Enumeration it = vectors_.elements(); it.hasMoreElements();) {
        indx++;
        vcr = (VectorCartesianRenderer)it.nextElement();
        //        if(pcr.getLine().getId().equals(data_id)) {
        //  	pcr.getAttribute().removePropertyChangeListener(this);
        //  	points_.removeElement(lcr);
        //  	label_.removeElementAt(indx);
        //  	modified("VectorKey: clear()");
        //  	break;
        //        }
      }
    }
    /**
     * Return height of key row in pixels.
     */
    public int getRowHeight() {
      Rectangle bounds;
      bounds = getBounds();
      return ROW_SPACE_ + maxLabelHeight_;
    }
    /**
     * Draw the Key.
     */
    public void draw(Graphics g) {
      double maxLabelLength, maxLabelHeight;
      int numLines, numRows, i;
      float vectorLength;
      float vectorLengthU;
      int col, row, ytemp;
      double xloc, labelSpace, scaleSpace, scaleLength;
      double[] xp, yp;
      int[] xd, yd;
      int[] xout, yout;
      float hx1, hx2;
      float hy1, hy2;
      float headX, headY;
      float orgX, orgY;
      float xphead, yphead;
      float tScale, fixedScale;
      float scale;
      float headScale;
      float minSize;
      float maxSize;
      Rectangle bounds;
      VectorCartesianRenderer render = null;
      SGLabel label;
      SGLabel scaleLabel;
      String scaleStr;
      VectorAttribute attr = null;
      Graphics2D g2 = (Graphics2D)g;
      GeneralPath gp;
      Stroke savedStroke = g2.getStroke();
      BasicStroke stroke;
      slope_ = (float)layer_.getXSlope();
      xoff_ = (float)layer_.getXOffset();
      yoff_ = (float)layer_.getYOffset();
      //
      numLines = vectors_.size();
      if((numLines <= 0) || !visible_) return;
  
      numRows = numLines/columns_;
      if(numLines%columns_ != 0) numRows++;
  
      xp = new double[columns_];
      xd = new int[columns_];
      yp = new double[numRows];
      yd = new int[numRows];
      xout = new int[2];
      yout = new int[2];
  
      g.setColor(layer_.getPane().getComponent().getForeground());
  