/*
Violet - A program for editing UML diagrams.

Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package com.horstmann.violet;

import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.GeneralPath;

import com.horstmann.violet.framework.Graph;
import com.horstmann.violet.framework.Grid;
import com.horstmann.violet.framework.MultiLineString;
import com.horstmann.violet.framework.RectangularNode;

/**
   An actor node in a use case diagram.
*/
public class ActorNode extends RectangularNode
{
   /**
      Construct an actor node with a default size and name
   */
   public ActorNode()
   {
      name = new MultiLineString();
      name.setText("Actor");
      setBounds(new Rectangle2D.Double(0, 0,
         DEFAULT_WIDTH, DEFAULT_HEIGHT));
   }
   
   public void layout(Graph g, Graphics2D g2, Grid grid)
   {
      Rectangle2D top = new Rectangle2D.Double(0, 0,
         DEFAULT_WIDTH, DEFAULT_HEIGHT);
      Rectangle2D bot = name.getBounds(g2);
      Rectangle2D b = new Rectangle2D.Double(
            getBounds().getX(), getBounds().getY(),
            Math.max(top.getWidth(), bot.getWidth()), 
            top.getHeight() + bot.getHeight());
      grid.snap(b);
      setBounds(b);
   }
      
   public void draw(Graphics2D g2)
   {
      Rectangle2D bounds = getBounds();

      // Draw stick person

      GeneralPath path = new GeneralPath();
      float neckX = (float) (bounds.getX() + bounds.getWidth() / 2);
      float neckY = (float) (bounds.getY() + HEAD_SIZE + GAP_ABOVE);
      // head
      path.moveTo(neckX, neckY);
      path.quadTo(neckX + HEAD_SIZE / 2, neckY, neckX + HEAD_SIZE / 2, neckY - HEAD_SIZE / 2);
      path.quadTo(neckX + HEAD_SIZE / 2, neckY - HEAD_SIZE, neckX, neckY - HEAD_SIZE);
      path.quadTo(neckX - HEAD_SIZE / 2, neckY - HEAD_SIZE, neckX-HEAD_SIZE / 2, neckY - HEAD_SIZE / 2);
      path.quadTo(neckX - HEAD_SIZE / 2, neckY, neckX, neckY);
      // body
      float hipX = neckX;
      float hipY = neckY + BODY_SIZE;
      path.lineTo(hipX, hipY);
      // arms
      path.moveTo(neckX - ARMS_SIZE / 2, neckY + BODY_SIZE / 3);
      path.lineTo(neckX + ARMS_SIZE / 2, neckY + BODY_SIZE / 3);
      // legs
      float dx = (float) (LEG_SIZE / Math.sqrt(2));
      float feetX1 = hipX - dx;
      float feetX2 = hipX + dx + 1;
      float feetY  = hipY + dx + 1;
      path.moveTo(feetX1, feetY);
      path.lineTo(hipX, hipY);
      path.lineTo(feetX2, feetY);

      g2.draw(path);

      // Draw name
      Rectangle2D bot = name.getBounds(g2);

      Rectangle2D namebox = new Rectangle2D.Double(
         bounds.getX() + (bounds.getWidth() - bot.getWidth()) / 2, bounds.getY() + DEFAULT_HEIGHT,
         bot.getWidth(), bot.getHeight());
      name.draw(g2, namebox);
   }

   /**
      Sets the name property value.
      @param newValue the new actor name
   */
   public void setName(MultiLineString newValue)
   {
      name = newValue;
   }

   /**
      Gets the name property value.
      @param the actor name
   */
   public MultiLineString getName()
   {
      return name;
   }

   public Object clone()
   {
      ActorNode cloned = (ActorNode) super.clone();
      cloned.name = (MultiLineString) name.clone();
      return cloned;
   }

   private MultiLineString name;

   // Bounding rectangle
   private static int DEFAULT_WIDTH  = 48;
   private static int DEFAULT_HEIGHT = 64;
   // Stick man
   // Height = HEAD_SIZE + BODY_SIZE + LEG_SIZE/sqrt(2)
   private static int GAP_ABOVE = 4;
   private static int HEAD_SIZE = DEFAULT_WIDTH*4/12;
   private static int BODY_SIZE = DEFAULT_WIDTH*5/12;
   private static int LEG_SIZE  = DEFAULT_WIDTH*5/12;
   private static int ARMS_SIZE = DEFAULT_WIDTH*6/12;
   private static int NAME_HEIGHT = 12;
}
