package ij.gui;
import ij.*;
import java.awt.*;

/** Implements the ROI Brush tool.*/
class RoiBrush implements Runnable {
	static int ADD=0, SUBTRACT=1;
	static int leftClick=16, alt=9, shift=1;
	private Polygon poly;
	private Point previousP;
	private int mode = ADD;
 
	RoiBrush() {
		Thread thread = new Thread(this, "RoiBrush");
		thread.start();
	}

	public void run() {
		int size = Toolbar.getBrushSize();
		ImagePlus img = WindowManager.getCurrentImage();
		if (img==null) return;
		ImageCanvas ic = img.getCanvas();
		if (ic==null) return;
		Roi roi = img.getRoi();
		if (roi!=null && !roi.isArea())
			img.killRoi();
		Point p = ic.getCursorLoc();
		if (roi!=null && !roi.contains(p.x, p.y))
			mode = SUBTRACT;
		int flags;
		while (true) {
			p = ic.getCursorLoc();
			if (p.equals(previousP))
				{IJ.wait(1); continue;}
			previousP = p;
			flags = ic.getModifiers();
			if ((flags&leftClick)==0) return;
			if ((flags&shift)!=0)
				mode = ADD;
			else if ((flags&alt)!=0)
				mode = SUBTRACT;
			if (mode==ADD)
				addCircle(img, p.x, p.y, size);
			else
				subtractCircle(img, p.x, p.y, size);
		}
	}

	void addCircle(ImagePlus img, int x, int y, int width) {
		Roi roi = img.getRoi();
		Roi roi2 = roi;
		if (roi2!=null) {
			if (!(roi2 instanceof ShapeRoi))
				roi2 = new ShapeRoi(roi2);
			((ShapeRoi)roi2).or(getCircularRoi(x, y, width));
			roi2.copyAttributes(roi);
		} else
			roi2 = new OvalRoi(x-width/2, y-width/2, width, width);
		img.setRoi(roi2);
	}

	void subtractCircle(ImagePlus img, int x, int y, int width) {
		Roi roi = img.getRoi();
		Roi roi2 = roi;
		if (roi2!=null) {
			if (!(roi2 instanceof ShapeRoi))
			roi2 = new ShapeRoi(roi2);
			((ShapeRoi)roi2).not(getCircularRoi(x, y, width));
			roi2.copyAttributes(roi);
			img.setRoi(roi2);
		}
	}

    
	ShapeRoi getCircularRoi(int x, int y, int width) {
		if (poly==null) {
			Roi roi = new OvalRoi(x-width/2, y-width/2, width, width);
			poly = roi.getPolygon();
			for (int i=0; i<poly.npoints; i++) {
				poly.xpoints[i] -= x;
				poly.ypoints[i] -= y;
			}
		}
		return new ShapeRoi(x, y, poly);
	}

}

