/*
 * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */
import java.awt.*;
import java.applet.Applet;

/* 
 * This displays a framed area.  When the user drags within
 * the area, this program displays a rectangle extending from
 * where the user first pressed the mouse button to the current
 * cursor location.
 */

public class RectangleDemo extends Applet {
    RFramedArea framedArea;
    Label label;

    public void init() {
	GridBagLayout gridBag = new GridBagLayout();
	GridBagConstraints c = new GridBagConstraints();

	setLayout(gridBag);

	framedArea = new RFramedArea(this);
	c.fill = GridBagConstraints.BOTH;
	c.weighty = 1.0;
	c.gridwidth = GridBagConstraints.REMAINDER; //end row
	gridBag.setConstraints(framedArea, c);
	add(framedArea);

	label = new Label("Drag within the framed area.");
	c.fill = GridBagConstraints.HORIZONTAL;
	c.weightx = 1.0;
	c.weighty = 0.0;
	gridBag.setConstraints(label, c);
	add(label);

	validate();
    }

    public void rectChanged(Rectangle rect) {
	label.setText("Rectangle goes from ("
		      + rect.x + ", " + rect.y + ") to ("
		      + (rect.x + rect.width - 1) + ", "
		      + (rect.y + rect.height - 1) + ").");
	repaint();
    }
}

/* This class exists solely to put a frame around the coordinate area. */
class RFramedArea extends Panel {
    public RFramedArea(RectangleDemo controller) {
	super();

	//Set layout to one that makes its contents as big as possible.
	setLayout(new GridLayout(1,0));

	add(new SelectionArea(controller));
	validate();
    }

    public Insets insets() {
	return new Insets(4,4,5,5);
    }

    public void paint(Graphics g) {
        Dimension d = size();
        Color bg = getBackground();
 
        g.setColor(bg);
        g.draw3DRect(0, 0, d.width - 1, d.height - 1, true);
        g.draw3DRect(3, 3, d.width - 7, d.height - 7, false);
    }
}

class SelectionArea extends Canvas {
    Rectangle currentRect;
    RectangleDemo controller;

    public SelectionArea(RectangleDemo controller) {
	super();
	this.controller = controller;
    }

    public boolean mouseDown(Event event, int x, int y) {
	currentRect = new Rectangle(x, y, 0, 0);
	repaint();
	return false;
    }

    public boolean mouseDrag(Event event, int x, int y) {
	currentRect.resize(x - currentRect.x, y - currentRect.y);
	repaint();
	return false;
    }

    public boolean mouseUp(Event event, int x, int y) {
	currentRect.resize(x - currentRect.x, y - currentRect.y);
	repaint();
	return false;
    }

    public void paint(Graphics g) {
	Dimension d = size();

	//If currentRect exists, paint a rectangle on top.
	if (currentRect != null) {
	    Rectangle box = getDrawableRect(currentRect, d);
	    controller.rectChanged(box);
    
	    //Draw the box outline.
	    g.drawRect(box.x, box.y, box.width - 1, box.height - 1);
	}
    }

    Rectangle getDrawableRect(Rectangle originalRect, Dimension drawingArea) {
	int x = originalRect.x;
	int y = originalRect.y;
	int width = originalRect.width;
	int height = originalRect.height;

	//Make sure rectangle width and height are positive.
	if (width < 0) {
	    width = 0 - width;
	    x = x - width + 1;
	    if (x < 0) {
		width += x;
		x = 0;
	    }
	}
	if (height < 0) {
	    height = 0 - height;
	    y = y - height + 1;
	    if (y < 0) {
		height += y;
		y = 0;
	    }
	}

	//The rectangle shouldn't extend past the drawing area.
	if ((x + width) > drawingArea.width) {
	    width = drawingArea.width - x;
	}
	if ((y + height) > drawingArea.height) {
	    height = drawingArea.height - y;
	}

	return new Rectangle(x, y, width, height);
    }
}
