/** SketchPad
 @version 0.2d
 Copyright (c) 1997-2008, @author Bruno Andrighetto
 All Rights Reserved

This applet allows the user to sketch pictures in several colours.

*/

// SketchPad for Java
// 21-05-08
// Version 0.2d
//		- changed xor-it colour, to (Color.white).darker() - which works at least
// 03-08-97
// Version 0.2c
//		- use canvas to show current colour
// Version 0.2b
//		- uses colour selector dialog via appropriate button
//		- therefore don't need colour option list
// Version 0.2a
//		- calls colour selector dialog via "Fill" button
// Version 0.1g
//		- made restart-safe; minor tweaks
// Version 0.1f
//		- fixed firstTime bug
// Version 0.1e
//		- added fill button
//		- added xor-it button
//		- minor tweaks, including removal of intro screen
// Version 0.1d
//		- improved performance, by drawing to both on- and off-screen gcs (no wasteful repaints)
// Version 0.1c
//		- added thickness selection option
// Version 0.1b
//		- added symmetry toggle option
//		- added clear button
// Version 0.1a
//		- added mouseDown method
// Version 0.1
//		- initial version allows selection of colours
//	Based on Deitel, Figure 10.27 - Drag.java


import java.awt.*;
import java.applet.Applet;

public class SketchPad extends Applet
{
	private int xValue, yValue;
	private boolean firstTime;

	private Graphics graphicsOb;	// on-screen graphics context

	private Graphics gContext;	// off-screen graphics context
	private Image offScrImg;	// buffer in which to paint image

	private Color color;
	private Color bgcolor;
	private int thickness;
	private boolean symmetry;

	private Panel Panel1;
	private Panel Panel2;
	private Button colourButton;
	private Canvas colourCanvas;
	private Choice chThickness;
	private Label thicknessLabel;
	private Choice chSymmetry;
	private Label symmetryLabel;

	private ColourSelector csd;


	public void init()
	{
		setBackground(Color.white);
		graphicsOb = this.getGraphics();

		// init global variables
		color = Color.blue;
		bgcolor = Color.white;
		thickness = 16;
		symmetry = false;
		SwatchCanvas.setSelectedColor(color);

		// setup off-screen stuff
		offScrImg = createImage(size().width, size().height);
		gContext = offScrImg.getGraphics();
		gContext.setColor(Color.white);
		gContext.fillRect(0, 0, size().width, size().height);

		// create some panels:
		Panel1 = new Panel();
		Panel2 = new Panel();

		// create a layout for the panels
		setLayout(new BorderLayout());
		add("North", Panel1);
		add("South", Panel2);

		Panel1.setBackground(new Color(223, 215, 255));
		Panel2.setBackground(new Color(223, 215, 255));

		// labels
		thicknessLabel = new Label("Size:");
		// thicknessLabel.setAlignment(Label.RIGHT);
		symmetryLabel = new Label("Symmetry:");
		// symmetryLabel.setAlignment(Label.RIGHT);

		colourButton = new Button("Change Colour");
		colourButton.setBackground(new Color(234, 234, 234));
		colourCanvas = new Canvas();
		colourCanvas.setBackground(color);
		colourCanvas.resize(60, 20);

		// some choice lists
		chThickness = new Choice();
		chThickness.addItem("1 pixel");
		chThickness.addItem("2 pixels");
		chThickness.addItem("3 pixels");
		chThickness.addItem("4 pixels");
		chThickness.addItem("8 pixels");
		chThickness.addItem("16 pixels");
		chThickness.addItem("24 pixels");

		chSymmetry = new Choice();
		chSymmetry.addItem("Off");
		chSymmetry.addItem("On");

		// add button, canvas, labels and choice lists to "North" panel
		Panel1.add(colourButton);
		Panel1.add(colourCanvas);
		Panel1.add(thicknessLabel);
		Panel1.add(chThickness);
		Panel1.add(symmetryLabel);
		Panel1.add(chSymmetry);

		// some more buttons
		Button fillButton = new Button("Fill");
		fillButton.setBackground(new Color(234, 234, 234));
		Button clearButton = new Button("Clear");
		clearButton.setBackground(new Color(234, 234, 234));
		Button xorButton = new Button("XOR-it");
		xorButton.setBackground(new Color(234, 234, 234));

		// add buttons to "South" panel
		Panel2.add(fillButton);
		Panel2.add(clearButton);
		Panel2.add(xorButton);

		chThickness.select("16 pixels");

		showStatus( "   SketchPad, by Bruno Andrighetto" );

		// first running of the applet
		firstTime = true;
	}

	public void paint( Graphics g )
	{
		// paint image in buffer
		g.drawImage( offScrImg, 0, 0, this );

		// browser fix
		postEvent( new Event( this, Event.MOUSE_ENTER, "" ) );

		// showStatus( "   SketchPad, by Bruno Andrighetto" );
	}

	// override Component class update to avoid flickering
	public void update( Graphics g )
	{
		// do not clear background
		// only call paint
		paint( g );
	}

	public void clearArea()
	{
		gContext.setColor(bgcolor);
		gContext.fillRect(0, 0, size().width, size().height);
		// gContext.setColor(Color.black);
		// gContext.drawRect(0, 0, size().width, size().height);
	}

	public void plotPoint( int x, int y )
	{
		xValue = x;
		yValue = y;

		int xAdjust = 0;
		int yAdjust = 0;

		if (thickness != 1)
		{
			xAdjust = thickness / 2;
			yAdjust = thickness / 2;
		}

		// clear drawing area the first time
		if ( firstTime )
		{
			// clearArea();
			// enable drawing
			firstTime = false;
		}

		// draw on-screen
		graphicsOb.setColor(color);
		graphicsOb.fillOval( xValue - xAdjust, yValue - yAdjust, thickness, thickness );

		// and draw off-screen
		gContext.setColor(color);
		gContext.fillOval( xValue - xAdjust, yValue - yAdjust, thickness, thickness );
		// gContext.drawLine( xValue, yValue, xValue, yValue );

		if (symmetry)
		{
			// draw on-screen
			graphicsOb.fillOval( size().width - xValue - xAdjust, yValue - yAdjust, thickness, thickness );
			graphicsOb.fillOval( xValue - xAdjust, size().height - yValue - yAdjust, thickness, thickness );
			graphicsOb.fillOval( size().width - xValue - xAdjust, size().height - yValue - yAdjust, thickness, thickness );

			// and draw off-screen
			gContext.fillOval( size().width - xValue - xAdjust, yValue - yAdjust, thickness, thickness );
			gContext.fillOval( xValue - xAdjust, size().height - yValue - yAdjust, thickness, thickness );
			gContext.fillOval( size().width - xValue - xAdjust, size().height - yValue - yAdjust, thickness, thickness );
		}

		showStatus( "   SketchPad, by Bruno Andrighetto" );
		// repaint();		// call repaint
	}

	public boolean mouseDown( Event e, int x, int y )
	{
		plotPoint( x, y );

		// showStatus( "Event: mouseDown" );

		return true;	// event handled;
	}

	public boolean mouseDrag( Event e, int x, int y )
	{
		plotPoint( x, y );

		// showStatus( "Event: mouseDrag" );

		return true;	// event handled;
	}

	public boolean handleEvent( Event evt )
	{
		if (colourButton != null)
		{
			if (color != SwatchCanvas.getSelectedColor())
			{
				color = SwatchCanvas.getSelectedColor();
				colourCanvas.setBackground(color);
				colourCanvas.repaint();
				// Panel1.repaint();
			}
		}
		return super.handleEvent(evt);
	}

	public boolean action(Event evt, Object arg)
	{
		if ("Change Colour".equals(arg))
		{
			SwatchCanvas.setSelectedColor(color);
			if (csd != null)
				csd.dispose();
			// if (csd == null)  // this test is really meant for modeless dialog
			// {
				csd = new ColourSelector("Dialog box", "Select the drawing colour:", true );
/*				color = SwatchCanvas.getSelectedColor();
				Panel1.repaint();
*/			//}
		}

		// check thickness
		if (chThickness.getSelectedItem().equals("1 pixel"))
			thickness = 1;
		else if (chThickness.getSelectedItem().equals("2 pixels"))
			thickness = 2;
		else if (chThickness.getSelectedItem().equals("3 pixels"))
			thickness = 3;
		else if (chThickness.getSelectedItem().equals("4 pixels"))
			thickness = 4;
		else if (chThickness.getSelectedItem().equals("8 pixels"))
			thickness = 8;
		else if (chThickness.getSelectedItem().equals("16 pixels"))
			thickness = 16;
		else if (chThickness.getSelectedItem().equals("24 pixels"))
			thickness = 24;

		// check symmetry
		if (chSymmetry.getSelectedItem().equals("Off"))
			symmetry = false;
		else if (chSymmetry.getSelectedItem().equals("On"))
			symmetry = true;

		// has user requested to clear the drawing area?
		if ("Clear".equals(arg))
		{
			gContext.setColor(bgcolor);
			gContext.fillRect(0, 0, size().width, size().height);
			repaint();
		}

		if ("Fill".equals(arg))
		{
			gContext.setColor(color);
			gContext.fillRect(0, 0, size().width, size().height);
			repaint();
		}

		if ("XOR-it".equals(arg))
		{
			gContext.setXORMode((Color.white).darker());
			gContext.setColor(color);
			gContext.fillRect(0, 0, size().width, size().height);
			gContext.setPaintMode();
			repaint();
		}

		return true;
	}
}
