/*
* JavASketch.java
*
* Version 2.0
*
* Written by: Mark Masse
* Date: 7-28-96 (original version: 12-23-95)
*
* This software is in the public domain, furnished "as is", without technical
* support, and with no warranty, express or implied, as to its usefulness for
* any purpose.
*/
import java.applet.Applet;
import java.awt.*;
/**
* An Applet that implements a JavASketch drawing "toy".
* @author Mark Masse
* @version 2.0
*/
public class JavASketch extends Applet {
//DATA MEMBERS
/**
* The current x coordinate of the sketch-point.
*/
protected int x;
/**
* The current y coordinate of the sketch-point.
*/
protected int y;
/**
* Is true when drawing up and false otherwise.
*/
protected boolean up;
/**
* Is true when drawing down and false otherwise.
*/
protected boolean down;
/**
* Is true when drawing left and false otherwise.
*/
protected boolean left;
/**
* Is true when drawing right and false otherwise.
*/
protected boolean right;
/**
* The image used to create the graphics.
*/
protected Image img;
/**
* The dimensions of the JavASketch.
*/
protected Dimension dim;
/**
* The graphic content of the JavASketch.
*/
protected Graphics gra;
/**
* The width of the JavASketch.
*/
protected int w;
/**
* The height of the JavASketch.
*/
protected int h;
/**
* The previous x-coordinate.
*/
protected int lastx;
/**
* The previous y-coordinate.
*/
protected int lasty;
/**
* Determines whether the first point has been added to the JavASketch.
*/
protected boolean gotFirstPoint;
/**
* Determines whether the JavASketch needs to be updated.
*/
protected boolean updateSketch = true;
/**
* Determines whether the Jav A Sketch was erased .
*/
protected boolean shaken;
/**
* The initial angle of the left knob's ridges.
*/
protected float leftKnobAngle;
/**
* The initial angle of the right knob's ridges.
*/
protected float rightKnobAngle;
//METHODS
/**
* Initialization of the JavASketch Applet
*/
public void init() {
// Set the bg color to white
setBackground(Color.white);
// Set the starting point
x = 200;
y = 100;
// Add the starting point to the JavASketch
addPoint(x,y);
showStatus("Jav A Sketch written by Mark Masse");
}
/**
* Info
* @return Info about the Applet's author
*/
public String getAppletInfo() {
return "JavASketch by Mark Masse";
}
/**
* The event-handler for the JavASketch Applet.
* @param evt The Event
*/
public boolean handleEvent(Event evt) {
switch(evt.id) {
case Event.KEY_PRESS:
case Event.KEY_ACTION:
// Bind Space to erase the Jav A Sketch
if(evt.key == ' ') {
showStatus("Shaking Jav A Sketch");
shake();
addPoint(x, y);
repaint();
}
//
// Bind the key press events to "turn on" direction
//
else if(evt.key == 'l' || evt.key == 'L' || evt.key == Event.UP) {
draw("UP", true);
}
else if(evt.key == 'k' || evt.key == 'K' || evt.key == Event.DOWN) {
draw("DOWN", true);
}
else if(evt.key == 'a' || evt.key == 'A' || evt.key == Event.LEFT) {
draw("LEFT", true);
}
else if(evt.key == 's' || evt.key == 'S' || evt.key == Event.RIGHT) {
draw("RIGHT", true);
}
break;
case Event.KEY_RELEASE:
case Event.KEY_ACTION_RELEASE:
//
// Bind the key release events to "turn off" direction
//
if(evt.key == 'a' || evt.key == 'A' || evt.key == Event.LEFT) {
draw("LEFT", false);
}
else if(evt.key == 's' || evt.key == 'S' || evt.key == Event.RIGHT) {
draw("RIGHT", false);
}
else if(evt.key == 'k' || evt.key == 'K' || evt.key == Event.DOWN) {
draw("DOWN", false);
}
else if(evt.key == 'l' || evt.key == 'L' || evt.key == Event.UP) {
draw("UP", false);
}
break;
case Event.MOUSE_DOWN:
showStatus("a = left, s = right, k = down, l = up," +
" and space = erase");
break;
}
return true;
}
/**
* Paints the JavASketch with the current graphic content
* @param g The graphics content
*/
public void paint(Graphics g) {
update(g);
}
/**
* Updates the graphic content of the JavASketch
* @param ig The graphics content
*/
public void update(Graphics igra) {
Dimension d = size();
if ((img == null) || (d.width != dim.width) || (d.height != dim.height)) {
w = d.width;
h = d.height;
img = createImage(w, h);
dim = d;
gra = img.getGraphics();
updateSketch = true;
}
// Check to see if the erasing "shake" should be performed
if(shaken) {
int i, j;
int distance = 50;
// Shake up and down
for(i=0; i < 3; i++) {
distance -= 10;
for(j=0; j >= -100; j-=distance) {
igra.drawImage(img, 0, j, null);
}
for(j=-100; j <= 100; j+=distance) {
igra.drawImage(img, 0, j, null);
}
for(j=100; j >= 0; j-=distance) {
igra.drawImage(img, 0, j, null);
}
}
shaken = false;
}
if(updateSketch) {
// Redraw the JavASketch
// NOTE: This will erase the current sketch
drawSketch();
updateSketch = false;
}
igra.drawImage(img, 0, 0, null);
}
/**
* Draws all of the graphics for the JavASketch. Including the
* red border, and the "Jav A sketch" title
*/
public void drawSketch() {
// Draw the red border
gra.setColor(Color.red);
gra.fillRoundRect(0, 0, w, h, 80, 80);
// Draw main rectangular drawing surface
gra.setColor(Color.gray);
gra.fillRoundRect(40, 40, w-80, h-130, 20, 20);
gra.setColor(Color.lightGray);
gra.fillRoundRect(43, 43, w-86, h-136, 20, 20);
// Create the color fdd017
Color Gold = new Color(253, 208, 23);
gra.setColor(Gold);
// Create Polygon for left arrow
Polygon leftArrow = new Polygon();
// Create Polygon for right arrow
Polygon rightArrow = new Polygon();
// Create Polygon for up arrow
Polygon upArrow = new Polygon();
// Create Polygon for down arrow
Polygon downArrow = new Polygon();
// Add points to leftArrow Polygon
leftArrow.addPoint(10,h-95);
leftArrow.addPoint(20,h-105);
leftArrow.addPoint(20,h-85);
// Add points to rightArrow Polygon
rightArrow.addPoint(34,h-95);
rightArrow.addPoint(24,h-105);
rightArrow.addPoint(24,h-85);
// Add points to downArrow Polygon
downArrow.addPoint(w-20,h-85);
downArrow.addPoint(w-10,h-95);
downArrow.addPoint(w-30,h-95);
// Add points to upArrow Polygon
upArrow.addPoint(w-20,h-109);
upArrow.addPoint(w-10,h-99);
upArrow.addPoint(w-30,h-99);
// Fill the Arrow Polygons
gra.fillPolygon(leftArrow);
gra.fillPolygon(rightArrow);
gra.fillPolygon(downArrow);
gra.fillPolygon(upArrow);
// Draw left knob
drawKnob(0, h - 80, 80, leftKnobAngle);
// Draw right knob
drawKnob(w - 80, h - 80, 80, rightKnobAngle);
// Print "Jav A sketch" at the top
Font JS = new Font("JS", Font.ITALIC, 25);
gra.setFont(JS);
FontMetrics fm = gra.getFontMetrics();
int sWidth = fm.stringWidth("Jav A Sketch");
gra.drawString("Jav A Sketch",(w - sWidth)/2, 25);
// If we didn't just erase then show author info.
if(!shaken) {
showStatus("Jav A Sketch written by Mark Masse");
}
}
/**
* Clears the JavASketch screen.
*/
public void shake() {
shaken = true;
updateSketch = true;
up = false;
down = false;
left = false;
right = false;
repaint();
}
public void drawKnob(int x, int y, int diameter, float startAngle) {
Color oldColor = gra.getColor();
// Draw the knob's border
gra.setColor(Color.lightGray);
gra.fillOval(x, y, diameter, diameter);
float radius = (float) diameter/2;
int centerX = x + (int) radius;
int centerY = y + (int) radius;
// Draw the knotches that will "move"
gra.setColor(Color.gray);
for(float angle = startAngle;
angle <= (360.0f + startAngle); angle += 10.0f) {
int borderX = centerX + (int) (radius *
((float) Math.cos((double) angle)));
int borderY = centerY + (int) (radius *
((float) Math.sin((double) angle)));
gra.drawLine(centerX, centerY, borderX, borderY);
}
gra.setColor(Color.white);
gra.fillOval(x + 4, y + 4, diameter - 8, diameter - 8);
// Draw a dot in the center
gra.setColor(Color.lightGray);
gra.fillOval(centerX - 1, centerY - 1, 2, 2);
gra.setColor(oldColor);
}
public void turnLeftKnob(String direction) {
if(direction.equalsIgnoreCase("RIGHT")) {
leftKnobAngle -= 2.5f;
}
else {
leftKnobAngle += 2.5f;
}
if(leftKnobAngle >= 360.0f) {
leftKnobAngle = 0.0f;
}
// Draw left knob
drawKnob(0, h - 80, 80, leftKnobAngle);
}
public void turnRightKnob(String direction) {
if(direction.equalsIgnoreCase("UP")) {
rightKnobAngle -= 2.5f;
}
else {
rightKnobAngle += 2.5f;
}
if(rightKnobAngle >= 360.0f) {
rightKnobAngle = 0.0f;
}
// Draw right knob
drawKnob(w - 80, h - 80, 80, rightKnobAngle);
}
/**
* First checks to make sure the point specified by the parameters x and y
* is in the sketching area, and if so it adds the point. If the point is
* outside the sketching area, the Applet's x and y values are reset to be
* inside the area.
* @param x The x coordinate of the point to be added
* @param y The y coordinate of the point to be added
*/
public void checkAndAdd(int X, int Y) {
int border = 45;
int bottomBorder = 95;
if((X > border && X < w - border) &&
(Y > border && Y < h - bottomBorder)) {
addPoint(X, Y);
repaint();
}
else if(X < border)
this.x = border + 2;
else if(X > w - border)
this.x = w - border - 2;
else if(Y < border)
this.y = border + 2;
else if(Y > h - bottomBorder)
this.y = h - bottomBorder - 2;
}
/**
* Adds a "sketch"-point to the JavASketch.
* @param x The x coordinate of the point to be added.
* @param y The y coordinate of the point to be added.
*/
public void addPoint(int x, int y) {
if(gotFirstPoint) {
// "Connect the dots"
gra.setColor(Color.black);
gra.drawLine(x , y, lastx, lasty);
// Draw the cursor as a light gray pixel
gra.setColor(Color.lightGray);
gra.drawLine(x, y, x, y);
}
// Set the "last" variables for the next call to this function
lastx = x;
lasty = y;
gotFirstPoint = true; // Set because this function has been called
}
public void draw(String direction, boolean state) {
if(state) {
if(direction.equalsIgnoreCase("UP") ||
direction.equalsIgnoreCase("DOWN")) {
if(direction.equalsIgnoreCase("UP")) {
up = true;
down = false;
y = y - 4;
turnRightKnob("UP");
}
else {
down = true;
up = false;
y = y + 4;
turnRightKnob("DOWN");
}
if(left) {
x = x - 4;
turnLeftKnob("LEFT");
}
else if(right) {
x = x + 4;
turnLeftKnob("RIGHT");
}
}
else if(direction.equalsIgnoreCase("LEFT") ||
direction.equalsIgnoreCase("RIGHT")) {
if(direction.equalsIgnoreCase("LEFT")) {
left = true;
right = false;
x = x - 4;
turnLeftKnob("LEFT");
}
else {
right = true;
left = false;
x = x + 4;
turnLeftKnob("RIGHT");
}
if(up) {
y = y - 4;
turnRightKnob("UP");
}
else if(down) {
y = y + 4;
turnRightKnob("DOWN");
}
}
checkAndAdd(x, y);
}
else {
if(direction.equalsIgnoreCase("UP")) {
up = false;
}
else if(direction.equalsIgnoreCase("DOWN")) {
down = false;
}
else if(direction.equalsIgnoreCase("LEFT")) {
left = false;
}
else if(direction.equalsIgnoreCase("RIGHT")) {
right = false;
}
}
}
}