// (c) MIT 2003.  All rights reserved.

// $Id: SpatialWidget.java,v 1.13 2003/03/06 00:40:39 moltmans Exp $
// Time-stamp: <2000-07-17 22:23:53 moltmans>
package rec.sys;

import java.io.*;
import java.awt.*;
import java.util.*;
import rec.util.*;
import rec.geo.*;
import rec.core.widgets.*;

// LW: Widget used to be Registerable, but this makes no sense, so I cut it
//    out.  I left in the default methods though--so if you do implement it
//    you can selectively override them.
public abstract class SpatialWidget extends Widget implements Locatable
{

  private String m_defaultColor = "stroke";
  private Color m_Color = null;
  
  ///////////////////////////////////////////////////////////////////////////

  public SpatialWidget()
  {
  }

  public abstract double size();

  /** @param scaleFactor The amount to scale the widget by. **/
  public abstract void resize( double scaleFactor );

  /**
   * Override clone() for "intricate" Widgets.
   */
  public final SpatialWidget copy( GPoint p )
  {
    SpatialWidget w = (SpatialWidget)this.clone();

    w.move( p );

    return( w );
  }

  public boolean overlaps( SpatialWidget w )
  {
    GPoint w_center = w.getLocation().getCenter();
    double w_radius = w.getLocation().getRadius();
    GPoint center = getLocation().getCenter();
    double radius = getLocation().getRadius();

    if ( Geometry.distance( w_center, center ) <= w_radius + radius ) {
      return true;
    }
    else {
      return false;
    }
  }

  public abstract void move( GPoint gp );

  /**
   * @param p      The point of rotation.
   * @param angle  The angle to be rotated in radians.
   */
  public abstract void rotate( GPoint gp, double angle );

  public abstract Location getLocation();
  public abstract Rectangle getBounds();

  public abstract boolean includes( GPoint p, double offset );
  public abstract boolean contains( GPoint p );


  ///////////////////////////////////////////////////////////////////////////
  // Visible Widget stuff relocated here
  // ///////////////////////////////////
    /**
   * Guarantees that the graphics object keeps its color when it
   *     leaves this method.
   */
  public void display( Graphics g )
  {
    Color oldColor = g.getColor();
    g.setColor( getColor() );

    Surface s = getSurface();
    if( s == null ) {
      draw( g );
      g.setColor( oldColor );
      return;
    }
    
    if( s.isWidgetSquiggleShown() ) {
      drawSquiggles( g );
    }
    else {
      draw( g );
    }
    
    if( s.isWidgetNameShown() && getEnglishName() != null )
    {
      Font f = g.getFont();
      f = new Font( f.getName(), Font.BOLD, 14 );
      g.setFont( f );
      GPoint loc = getLocation().getCenter();
      g.setColor( Color.black );
      g.drawString( getEnglishName(), loc.getIntX(), loc.getIntY() );
    }

    g.setColor( oldColor );
  }

  public void drawSquiggles( Graphics g ) 
  {
    Iterator it = getAncestors().iterator();

    if( this instanceof Squiggle ) {
      ((Squiggle)this).drawPlain( g );
    }
    
    while( it.hasNext() ) {
      Widget w = (Widget)it.next();
      if( w instanceof Squiggle )
	((Squiggle)w).drawPlain( g );
    }
  }

  public final void setColor( Color c )
  {
    m_Color = c;
  }

  /** Set default color for this class. **/
  public void setDefaultColor( String name ) 
  {
    m_defaultColor = name;
  }

  /**
   * Set default color for this widget and suggest that name be bound
   * to color in the Colors database (if it isn't bound already).
   **/
  public void setDefaultColor( String name, String color ) 
  {
    m_defaultColor = name;
    Colors.setDefaultColor( name, color );
  }
  
  public final Color getColor()
  {
    if( m_Color == null ) {
      Color c = Colors.getColor( m_defaultColor );
      if( c == null )
	return Colors.getColor( "stroke" );
      return c;
    }
    return m_Color;
  }

  public final void unsetColor()
  {
    m_Color = null;
  }

  public abstract void draw( Graphics g );

  public Collection isa()
  {
    Class c = null;
    try {
      c = Class.forName( "rec.sys.SpatialWidget" );
    }
    catch( ClassNotFoundException e ) {

      Assert.error( "bad/unrecognized widget class name" );
    }

    Collection types = super.isa();
    types.add( c );
    
    return types;
  }

  
}
