// Copyright (c) 1995, 1996 Regents of the University of California.
// All rights reserved.
//
// This software was developed by the Arcadia project
// at the University of California, Irvine.
//
// Redistribution and use in source and binary forms are permitted
// provided that the above copyright notice and this paragraph are
// duplicated in all such forms and that any documentation,
// advertising materials, and other materials related to such
// distribution and use acknowledge that the software was developed
// by the University of California, Irvine.  The name of the
// University may not be used to endorse or promote products derived
// from this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

// File: Fig.java
// Classes: Fig
// Original Author: ics125b spring 1996
// $Id: Fig.java,v 1.10 1996/09/18 02:08:34 jrobbins Exp $

package EDU.neu.ccs.demeter.tools.apstudio.graphedit;

import java.awt.Rectangle;
import java.awt.Point;
import java.awt.Color;
import java.awt.Graphics;

/** This class is the abstract base class for basic drawing objects
 * such as rectangles, lines, text, circles, etc. Also, class FigList
 * implements a composite figure. Fig's are Diagram elements that can
 * be placed in any LayerDiagram. Fig's are also used to define the
 * look of Perspective's on NetNode's.<p>
 *
 * @see FigRect
 * @see FigLine
 * @see FigText
 * @see FigCircle
 **/

public abstract class Fig extends DiagramElement 
{
  /**  Height and width in pixels of (square) rectangles used for handle */
  public static final int HAND_SIZE = 8;

  /** When selecting a small or thin object it is useful to allow
   * nearby mouse clicks. GRIP_MARGIN specifies how near these clicks
   * have to be. needs-more-work: This should be a preference.  */
  public static final int GRIP_MARGIN = 1;

  /** The smallest size of any Fig. Is this really needed? To limiting?*/
  public static final int MIN_SIZE = 4;

  /** _handleRects[] and _numHandles together specify the number and
   * position of handles for directly manipulating a Fig. In the
   * future, this may be replaced with instances of a class
   * Handle. Needs-More-Work: More of this logic should be moved to
   * SelectionHandles. */
  protected Rectangle _handleRects[];
  private int _numHandles;

  public void set_position(Point s,Point d){}
  /** Graphical attributes of figures. Other code that is accessing
   * these attruibutes should use the get and set functions for
   * graphical attributes.
   * @see DiagramElement#getGraphicAttribute
   */
  protected int objectWidth;	   /*width of fig object*/
  protected int objectHeight;	   /*height of fig object*/
  protected Color objectLineColor;   /*outline color of fig object*/
  protected Color objectFillColor;   /*fill color of fig object*/
  protected Color handleColor;

  public String get_label(){ return null;}
  public void set_label(String s,Document d){}

  public Point get_dimensions(){
	  Point p = new Point(objectWidth,objectHeight);
	  return p;}

  /** Construct a new Fig with the given attributes and number of handles */
  Fig(int x, int y, int width, int height,
		Color line_color, Color fill_color,
	        int nHands) {
    position(x,y);
    objectWidth = width;
    objectHeight = height;
    objectLineColor = line_color;
    objectFillColor = fill_color;
    _numHandles = nHands;
    _handleRects = new Rectangle[_numHandles];
    for (int i = 0; i < _numHandles; ++i) {
      _handleRects[i] = new Rectangle(0, 0, HAND_SIZE, HAND_SIZE);
    }
    owner(null);
  }

  /** Return a handle ID for the handle under the mouse, or -1 if
   * none. Needs-More-Work: in the future, return a Handle instance or
   * null. */
  public int pickHandle(int x, int y) {
    for (int i = 0; i < _numHandles; ++i) {
      if (_handleRects[i].contains(x, y)) { return i; }
    }
    return -1;
  }

  /** Draw the handles on this Fig. Needs-More-Work: should be done in
   * class SelectionHandles and future class Handle. */
  public void drawHandles(Graphics g) {
    g.setColor(Globals.prefs().handleColor());
    for (int i = 0; i < _numHandles; ++i) {
      Rectangle handle = _handleRects[i];
      g.fillRect(handle.x, handle.y, handle.width, handle.height);
    }
  }

  /** Internal function to change the line color attribute. Other code
   * should use setGraphicAttribute. */
  protected void setLineColor(Color col) { objectLineColor = col; }

  /** Internal function to change the fill color attribute. Other code
   * should use setGraphicAttribute. */
  protected void setFillColor(Color col) { objectFillColor = col; }

  /** Get a graphical attribute of this Fig.
   * @see DiagramElement#getGraphicAttribute
   */
  public Object getGraphicAttribute(String k) {
    /* needs-more-work: linear comparison is too slow! */
    /* consider a global or local table of int constants... */
    if (k.equals("LineColor")) return objectLineColor;
    else if (k.equals("FillColor")) return objectFillColor;
    else if (k.equals("ObjectWidth")) return new Integer(objectWidth);
    else if (k.equals("ObjectHeight")) return new Integer(objectHeight);
    else return super.getGraphicAttribute(k);
  }

  /** Set a graphical attribute of this Fig.
   * @see DiagramElement#setGraphicAttribute
   */
  public void setGraphicAttribute(String k, Object v) {
    /* needs-more-work: linear comparison is too slow! */
    /* consider a global or local table of int constants... */
    if (k.equals("LineColor")) setLineColor((Color)v);
    else if (k.equals("FillColor")) {
      if ((v instanceof String) && ((String)v).equals("Transparent"))
	setFillColor(null);
      else setFillColor((Color)v);
    }
    else if (k.equals("ObjectWidth")) objectWidth = ((Integer)v).intValue();
    else if (k.equals("ObjectHeight")) objectHeight = ((Integer)v).intValue();
    //else super.setGraphicAttribute(k, v);
  }

  /** Abstract method to draw this Fig. */
  public abstract void draw(Graphics g);
  public void draw(Graphics g,Color l_color,Point dimension,Point d){}
  public void draw(Graphics g,Point dimension,Point d){}
  public void drawColored(Graphics g){}
  public void drawColoredArc(Graphics g,Point p1,Point p2){}
  /** Draw this item as the current selected item */
  public abstract void drawSelected(Graphics g);

  /** Return a Rectangle that completely encloses this Fig. */
  Rectangle getBoundingBox() {
    Point p = position();
    int minX = Math.min(p.x, p.x + objectWidth);
    int minY = Math.min(p.y, p.y + objectHeight);
    int maxX = Math.max(p.x, p.x + objectWidth);
    int maxY = Math.max(p.y, p.y + objectHeight);
    return new Rectangle(minX, minY, maxX - minX, maxY - minY);
  }	

  /** Change some attribute of this Fig when the user drags one of its
  * handles. By default, assume that every handle changes the position
  * of the Fig. */
/*  public void dragHandle(int mX, int mY, int anX, int anY, int handle) 
  {
	  System.out.println("In draghandle");
      translate(mX + anX, mY + anY);
  }*/

  public void translate(int dx,int dy){super.translate(dx,dy);}

  public void dragHandle(int mX, int mY, int handle){}
  /** Resize the object for drag on creation. It bypasses the things
   * done in resize so that the position of the object can be kept as
   * the anchor point. Needs-More-Work: do I really need this
   * function?
   * @see FigLine#drag
   */
  public void createDrag(int anchorX, int anchorY, int x, int y) {
    int newX = Math.min(anchorX, x);
    int newY = Math.min(anchorY, y);
    int newWidth = Math.max(anchorX, x) - newX;
    int newHeight = Math.max(anchorY, y) - newY;

    position(newX, newY);
    objectWidth = newWidth;
    objectHeight = newHeight;
  }
} /* end class Fig */

