//==================================================================================================
// G r a p h i c                                                                               Java
// A r r o w C o m p o n e n t
//                                                                                By Bruno Bachelet
//==================================================================================================
// Copyright (c) 1999-2016
// Bruno Bachelet - bruno@nawouak.net - http://www.nawouak.net
//
// This file is part of the B++ Library. This library is free software; you can redistribute it
// and/or modify it under the terms of the GNU Library General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This library 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 Library General Public License for more details (http://www.gnu.org).

/*DESCRIPTION*/
/* This module provides a class to manipulate an arrow as a graphical component. */

// Package //---------------------------------------------------------------------------------------
package bpp.graphic;

// Importation //-----------------------------------------------------------------------------------
import java.awt.*;
import java.awt.image.*;
import java.io.*;

// A r r o w C o m p o n e n t  Class //------------------------------------------------------------
/*CLASS ArrowComponent */ /* Represents an arrow embedded inside a graphical component. */
public class ArrowComponent extends Container {
 //---------------------------------------------------------------------------------------Attributes
 protected int   atArrowSize; // Size of the arrow.
 protected Color atColor;     // Color of the arrow.
 protected Point atSource;    // Source point of the arrow.
 protected Point atTarget;    // Target point of the arrow.
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD ArrowComponent */
 /* Builds a component with a black arrow between given source and target points. The size of the
    arrow will be <I>3</I>. */
 public ArrowComponent(int agSourceX,int agSourceY,int agTargetX,int agTargetY) {
  super();
  atArrowSize=3;
  atColor=Color.black;
  atSource=new Point(agSourceX,agSourceY);
  atTarget=new Point(agTargetX,agTargetY);
  setLocation(Math.min(atSource.x,atTarget.x),Math.min(atSource.y,atTarget.y));

  setSize(Math.abs(atTarget.x-atSource.x)+1+2*atArrowSize,
          Math.abs(atTarget.y-atSource.y)+1+2*atArrowSize);
 }
 //--------------------------------------------------------------------------------------Constructor
 /*METHOD ArrowComponent */
 /* Builds a component with a black arrow between given source and target points. The size of the
    arrow must be provided. */
 public ArrowComponent(int agSourceX,int agSourceY,int agTargetX,int agTargetY,int agArrowSize) {
  super();
  atArrowSize=agArrowSize;
  atColor=Color.black;
  atSource=new Point(agSourceX,agSourceY);
  atTarget=new Point(agTargetX,agTargetY);
  setLocation(Math.min(atSource.x,atTarget.x),Math.min(atSource.y,atTarget.y));

  setSize(Math.abs(atTarget.x-atSource.x)+1+2*atArrowSize,
          Math.abs(atTarget.y-atSource.y)+1+2*atArrowSize);
 }
 //--------------------------------------------------------------------------------------------Color
 /*METHOD ArrowComponent */ /* Returns the color of the arrow. */
 public Color color() { return (atColor); }
 //-------------------------------------------------------------------------------------------Source
 /*METHOD ArrowComponent */ /* Returns the source point of the arrow. */
 public Point source() { return (atSource); }
 //-------------------------------------------------------------------------------------------Target
 /*METHOD ArrowComponent */ /* Returns the target point of the arrow. */
 public Point target() { return (atTarget); }
 //-----------------------------------------------------------------------------------------SetColor
 /*METHOD ArrowComponent */ /* Sets the color of the arrow. */
 public void setColor(Color agColor) { atColor=agColor; }
 //--------------------------------------------------------------------------------------SetLocation
 /*METHOD ArrowComponent */
 /* Sets the position of the arrow component (i.e. the arrow is considered in a bounding box, and
    the method sets the location of the upper-left corner of this box). */
 public void setLocation(int agPositionX,int agPositionY)
 { super.setLocation(agPositionX-atArrowSize,agPositionY-atArrowSize); }
 //----------------------------------------------------------------------------------------SetSource
 /*METHOD ArrowComponent */ /* Sets the source point of the arrow. */
 public void setSource(Point agSource) {
  atSource=agSource;
  setLocation(Math.min(atSource.x,atTarget.x),Math.min(atSource.y,atTarget.y));

  setSize(Math.abs(atTarget.x-atSource.x)+1+2*atArrowSize,
          Math.abs(atTarget.y-atSource.y)+1+2*atArrowSize);
 }
 //----------------------------------------------------------------------------------------SetTarget
 /*METHOD ArrowComponent */ /* Sets the target point of the arrow. */
 public void setTarget(Point agTarget) {
  atTarget=agTarget;
  setLocation(Math.min(atSource.x,atTarget.x),Math.min(atSource.y,atTarget.y));

  setSize(Math.abs(atTarget.x-atSource.x)+1+2*atArrowSize,
          Math.abs(atTarget.y-atSource.y)+1+2*atArrowSize);
 }
 //--------------------------------------------------------------------------------------------Paint
 /*METHOD ArrowComponent */ /* Draws the component. */
 public void paint(Graphics agGraphic) {
  int    lcHeight   = atTarget.y-atSource.y;
  int    lcWidth    = atTarget.x-atSource.x;
  int    lcPoint1X  = (lcWidth>=0 ? 0 : -lcWidth)+atArrowSize;
  int    lcPoint1Y  = (lcHeight>=0 ? 0 : -lcHeight)+atArrowSize;
  int    lcPoint2X  = lcPoint1X+(int)Math.round(lcWidth*0.8);
  int    lcPoint2Y  = lcPoint1Y+(int)Math.round(lcHeight*0.8);
  double lcNorm     = Math.sqrt(lcWidth*lcWidth+lcHeight*lcHeight);
  int    lcVector1X = (int)Math.round(lcWidth*0.8-((lcHeight+1.75*lcWidth)*atArrowSize)/lcNorm);
  int    lcVector1Y = (int)Math.round(lcHeight*0.8+((lcWidth-1.75*lcHeight)*atArrowSize)/lcNorm);
  int    lcVector2X = (int)Math.round(lcWidth*0.8+((lcHeight-1.75*lcWidth)*atArrowSize)/lcNorm);
  int    lcVector2Y = (int)Math.round(lcHeight*0.8-((lcWidth+1.75*lcHeight)*atArrowSize)/lcNorm);

  agGraphic.setColor(atColor);
  agGraphic.drawLine(lcPoint1X,lcPoint1Y,lcPoint1X+lcWidth,lcPoint1Y+lcHeight);
  agGraphic.drawLine(lcPoint2X,lcPoint2Y,lcPoint1X+lcVector1X,lcPoint1Y+lcVector1Y);
  agGraphic.drawLine(lcPoint2X,lcPoint2Y,lcPoint1X+lcVector2X,lcPoint1Y+lcVector2Y);
 }
}

// End //-------------------------------------------------------------------------------------------