package plots;

import java.awt.*;
import java.util.Stack;

public class SliderCanvas extends Canvas {
	SliderListener sl;
	int id;
	
	int w, h;
	int loc;
	Image bg;
	Image button[];
	int cfg = 0;
	int bw = 8, bh;
	int leftEnd, rightEnd;
	Stack markStack = new Stack();
	
	public SliderCanvas(int w, int h, 
			SliderListener sl, int id) {
		this.sl = sl; 
		this.id = id;
		this.w = w; this.h = h;
		
		bg = ancestor().createImage(w, h);
		button = new Image[2];
		bh = h - 12;
		if (bh < bw) bh = bw;
		loc = w/2;
		button[0] = ancestor().createImage(bw, bh);
		button[1] = ancestor().createImage(bw, bh);
		mkImages();
		resize(w, h);
	}
	
	Component ancestor() {
		Component c = (Component) sl, d = null;
		while (c != null) {
			d = c;
			c = c.getParent(); 
		}
		return(d);
	}
	
	Color unpressedColor = Color.lightGray;
	// Color pressedColor = new Color(0.5f, 0.5f, 0.5f);
	Color pressedColor = new Color(1.0f, 1.0f, 0.0f);
	
	public void mkImages() {
		Graphics gr = bg.getGraphics();
		gr.setColor(new Color(0.9f, 0.9f, 0.9f));
		gr.fillRect(0, 0, w, h);
		gr.setColor(Color.gray);
		leftEnd = h/2; rightEnd = w - leftEnd;
		gr.drawLine(leftEnd, h/2, rightEnd, h/2);
		gr.fillRect(leftEnd-1, h/2-1, 3, 3);
		gr.fillRect(rightEnd-1, h/2-1, 3, 3);
		gr.drawRect(1, 1, w - 3, h - 3);
		
		 gr = button[0].getGraphics();
		gr.setColor(unpressedColor);
		gr.fillRect(0, 0, bw, bh);
		gr.setColor(Color.black);
		gr.setColor(new Color((float) 0.9, (float) 0.9, (float) 0.9));
		gr.drawLine(0, 0, bw, 0);
		gr.drawLine(1, 1, bw-1, 1);
		gr.drawLine(0, 1, 0, bh);
		gr.drawLine(1, 2, 1, bh-1);
		gr.setColor(Color.gray);
		gr.drawLine(1, bh-1, bw, bh-1);
		gr.drawLine(2, bh-2, bw-1, bh-2);
		gr.drawLine(bw-1, 1, bw-1, bh-1);
		gr.drawLine(bw-2, 2, bw-2, bh-2);
		
		 gr = button[1].getGraphics();
		gr.setColor(pressedColor);
		gr.fillRect(0, 0, bw, bh);
		gr.setColor(Color.black);
		gr.setColor(new Color((float) 0.9, (float) 0.9, (float) 0.9));
		gr.drawLine(0, 0, bw, 0);
		gr.drawLine(1, 1, bw-1, 1);
		gr.drawLine(0, 1, 0, bh);
		gr.drawLine(1, 2, 1, bh-1);
		gr.setColor(Color.gray);
		gr.drawLine(1, bh-1, bw, bh-1);
		gr.drawLine(2, bh-2, bw-1, bh-2);
		gr.drawLine(bw-1, 1, bw-1, bh-1);
		gr.drawLine(bw-2, 2, bw-2, bh-2);
	}
	
	/** Reverses the normal ordering of paint() and 
		update() for flicker-free performance. */
	public void paint(Graphics g) {
		update(g);
	}

	public void update(Graphics g) {
		g.drawImage(bg, 0, 0, null);
		g.setColor(Color.gray);
		for (int i=0;i<markStack.size();i++) {
			int[] x = (int[]) markStack.elementAt(i);
			g.fillRect(x[0]-1, x[1]/2-1, 3, 3);
		}
		g.drawImage(button[cfg], loc-bw/2, (h-bh)/2, null);
	}

	public void unsetMarks() {
		markStack.removeAllElements();
	}
	
	public void setMark(float x) {
		int w = leftEnd + (int) (x*(rightEnd - leftEnd));
		/* Graphics gr = bg.getGraphics();
		gr.setColor(Color.gray);
		gr.fillRect(w-1, h/2-1, 3, 3); */
		int[] p = { w, h };
		markStack.push(p);
	}
	
	// x between 0 and 1
	public void setValue(float x) {
		loc = leftEnd + (int) (x*(rightEnd - leftEnd));
	}
	
	public float getValue() {
		float x = (float) (loc - leftEnd)/ (float) (rightEnd - leftEnd);
		return(x);
	}
	
	boolean pressed = false;
	int delta;
	public boolean mouseDown(Event e, int x, int y) {
		if (loc - 4 < x && x < loc + 4 && cfg == 0) {
			pressed = true;
			sl.sliderPress(id);
			delta = x - (loc - 4);
			// loc = x - delta + 4
			cfg = 1;
			repaint();
			return(false);
		}
		return(true);
	}
	
	public boolean mouseDrag(Event e, int x, int y) {
		if (pressed) {
			x = x - delta + 4;
			if (x < leftEnd) x = leftEnd;
			else if (x > rightEnd) x = rightEnd;
			loc = x;
			repaint();
			sl.sliderMove(id, getValue());
			return(false);
		}
		return(true);
	}
	
	public boolean mouseUp(Event e, int x, int y) {
		if (cfg == 1 && pressed) {
			pressed = false;
			sl.sliderRelease(id);
			cfg = 0;
		}
		repaint();
		return(false);
	}
	
}
