// ModLineBresenham v1998.10.30

import java.applet.*;
import java.awt.*;			// classes: Panel, Point, Rectangle, Image, Color, Graphics
import java.awt.event.*;	// interfaces: ItemListener, DrawPanel, MouseListener
import java.util.Vector;

class ModLineBresenham extends Applet implements ModuleInterface, MouseListener, MouseMotionListener {
	public final String strInfo = "Her kommer beskrivelse til Bresenham algoritmen...";
	public final String strTitle = "Linjetegningsalgoritme / Bresenham";
	public final String strListname = "Bresenham";

	final int gridSize = 15;
	Rectangle knott1 = new Rectangle(2*gridSize, 2*gridSize, gridSize, gridSize);
	Rectangle knott2 = new Rectangle(20*gridSize, 10*gridSize, gridSize, gridSize);
	boolean isDragging1 = false;
	boolean isDragging2 = false;
	Image offscreen;		// double buffering context

	// Tom vector som skal inneholde alle linjepunktene.
	// Oppdateres i drawVector som kalles fra Paint.
	Vector arrayLine = null;

	// Constructor
	public ModLineBresenham() {
		setBackground(Color.lightGray);
		addMouseMotionListener(this);
		addMouseListener(this);
	}

	// ModuleInterface implementasjon
	public String getInfo() { return strInfo; }
	public String getTitle() { return strTitle; }
	public String getListname() { return strListname; }
	public Applet getApplet() { return this; }

	// MouseListener implementasjon
	public void mouseMoved(MouseEvent e) { }
	public void mouseEntered(MouseEvent e) { }
	public void mouseExited(MouseEvent e) { }
	public void mouseClicked(MouseEvent e) { }
	public void mouseDragged(MouseEvent e) {
		e.consume();
		if (isDragging1) knott1.setLocation((e.getX()/gridSize)*gridSize, (e.getY()/gridSize)*gridSize);
		else if (isDragging2) knott2.setLocation((e.getX()/gridSize)*gridSize, (e.getY()/gridSize)*gridSize);
		repaint();
	}
	public void mousePressed(MouseEvent e) {
		e.consume();
		// Sjekk om vi har trykket på noen av kontrollknottene
		if (knott1.contains(e.getX(), e.getY())) isDragging1 = true;
		else if (knott2.contains(e.getX(), e.getY())) isDragging2 = true;
	}
	public void mouseReleased(MouseEvent e) {
		e.consume();
		isDragging1 = false;
		isDragging2 = false;
		repaint();
	}

	// Tegner en linje fra (x0,y0) til (x1,y1) i arrayLine med Bresenham metoden
	public void drawVector(int x0, int y0, int x1, int y1) {
		arrayLine = new Vector();			// Tom vector som skal inneholde alle linjepunktene
		int x, y, dx, dy, e, neg = 1, s = 0, temp;

		// if drawing towards left -> swap coordinates
		if (x0 > x1) { temp=x0; x0=x1; x1=temp; temp=y0; y0=y1; y1=temp; }

		x = x0;
		dx = x1 - x0;

		if (y0 <= y1) {
			y  = y0;
			dy = y1 - y0;
			if (dy > dx) {
				x = y0;
				y = x0;
				dx = y1 - y0;
				dy = x1 - x0;
				x1 = y1;
				s = 1;
			}
		} else {
			y = -y0;
			dy = y0 - y1;
			neg = -1;
			if (dy > dx) {
				x = -y0;
				y = x0;
				dx = y0 - y1;
				dy = x1 - x0;
				x1 = -y1;
				s = 1;
			}
		}

		e = 2 * dy - dx;

		while (x <= x1) {
			if (s != 0) arrayLine.addElement(new Point(y,neg*x));
			else arrayLine.addElement(new Point(x,neg*y));
			while (e >= 0) {
				y += 1;
				e -= 2 * dx;
			}
			x += 1;
			e += 2 * dy;
		}
	} // drawVector

	// null out the offscreen buffer as part of invalidation
	public void invalidate() {
		super.invalidate();
		offscreen = null;
	}

	// override update to not clear screen to avoid flicker
	public void update(Graphics g) {	paint(g); }

	public void paint(Graphics g) {
		int sizew = getSize().width;
		int sizeh = getSize().height;
		if(offscreen == null) offscreen = createImage(getSize().width, getSize().height);

		Graphics og = offscreen.getGraphics();
		og.setClip(0,0,sizew,sizeh);
		super.paint(og);

		og.clearRect(0,0,sizew,sizeh);

		// Tegn grid
		og.setColor(Color.gray);
		for (int h=0; h<sizeh; h+=gridSize) og.drawLine(0, h, sizew, h);
		for (int w=0; w<sizew; w += gridSize) og.drawLine(w, 0, w, sizeh);

		// Tegn linje ifølge algoritme
		og.setColor(Color.black);
		drawVector(knott1.x/gridSize, knott1.y/gridSize, knott2.x/gridSize, knott2.y/gridSize);
		for (int n=0; n < arrayLine.size(); n++) {
			Point pt = (Point)arrayLine.elementAt(n);
			pt.x = pt.x * gridSize;
			pt.y = pt.y * gridSize;
			og.fillRect(pt.x, pt.y, gridSize, gridSize);
		}

		// Tegn rød "perfekt" linje
		og.setColor(Color.red);
		og.drawLine(knott1.x+(knott1.width/2), knott1.y+(knott1.height/2), knott2.x+(knott2.width/2), knott2.y+(knott2.height/2));

		// Tegn kontrollknotter
		og.setColor(Color.darkGray);
		og.fillRect(knott1.x, knott1.y, knott1.width, knott1.height);
		og.fillRect(knott2.x, knott2.y, knott2.width, knott2.height);

		// Tegn offscreen bufferet til skjermen
		g.drawImage(offscreen, 0, 0, null);
		og.dispose();
	}//paint
}


