package ij.plugin.tool;
import ij.*;
import ij.process.*;
import ij.gui.*;
import ij.plugin.Colors;
import java.awt.*;
import java.awt.event.*;
import java.awt.BasicStroke;
import java.awt.geom.*;
import java.util.Vector;
public class OverlayBrushTool extends PlugInTool implements Runnable {
private final static int UNCONSTRAINED=0, HORIZONTAL=1, VERTICAL=2, DO_RESIZE=3, RESIZED=4, IDLE=5; private static String WIDTH_KEY = "obrush.width";
private static final String LOC_KEY = "obrush.loc";
private float width = (float)Prefs.get(WIDTH_KEY, 5);
private int transparency;
private BasicStroke stroke;
private GeneralPath path;
private int mode; private float xStart, yStart;
private float oldWidth = width;
private boolean newPath;
private Options options;
private GenericDialog gd;
public void mousePressed(ImagePlus imp, MouseEvent e) {
ImageCanvas ic = imp.getCanvas();
float x = (float)ic.offScreenXD(e.getX());
float y = (float)ic.offScreenYD(e.getY());
xStart = x;
yStart = y;
oldWidth = width;
int ctrlMask = IJ.isMacintosh() ? InputEvent.META_MASK : InputEvent.CTRL_MASK;
int resizeMask = InputEvent.SHIFT_MASK | ctrlMask;
if ((e.getModifiers() & resizeMask) == resizeMask) {
mode = DO_RESIZE;
return;
} else if ((e.getModifiers() & ctrlMask) != 0) { int[] rgbValues = imp.flatten().getPixel((int)x,(int)y);
Color color = new Color(rgbValues[0],rgbValues[1],rgbValues[2]);
boolean altKeyDown = (e.getModifiers() & InputEvent.ALT_MASK) != 0;
if (altKeyDown)
Toolbar.setBackgroundColor(color);
else {
Toolbar.setForegroundColor(color);
if (gd != null)
options.setColor(color);
}
mode = IDLE;
return;
}
mode = UNCONSTRAINED; path = new GeneralPath();
path.moveTo(x, y);
newPath = true;
stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
}
public void mouseDragged(ImagePlus imp, MouseEvent e) {
if (mode == IDLE) return;
ImageCanvas ic = imp.getCanvas();
float x = (float)ic.offScreenXD(e.getX());
float y = (float)ic.offScreenYD(e.getY());
Overlay overlay = imp.getOverlay();
if (overlay==null)
overlay = new Overlay();
if (mode == DO_RESIZE || mode == RESIZED) {
changeBrushSize((float)(x-xStart), imp);
return;
}
if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0) { if (mode == UNCONSTRAINED) { if (Math.abs(x-xStart) > Math.abs(y-yStart))
mode = HORIZONTAL;
else if (Math.abs(x-xStart) < Math.abs(y-yStart))
mode = VERTICAL;
else return; }
if (mode == HORIZONTAL)
y = yStart;
else if (mode == VERTICAL)
x = xStart;
} else {
xStart = x;
yStart = y;
mode = UNCONSTRAINED;
}
path.lineTo(x, y);
ShapeRoi roi = new ShapeRoi(path);
boolean altKeyDown = (e.getModifiers() & InputEvent.ALT_MASK) != 0;
Color color = altKeyDown ? Toolbar.getBackgroundColor() : Toolbar.getForegroundColor();
float red = (float)(color.getRed()/255.0);
float green = (float)(color.getGreen()/255.0);
float blue = (float)(color.getBlue()/255.0);
float alpha = (float)((100-transparency)/100.0);
roi.setStrokeColor(new Color(red, green, blue, alpha));
roi.setStroke(stroke);
if (newPath) {
overlay.add(roi);
newPath = false;
} else {
overlay.remove(overlay.size()-1);
overlay.add(roi);
}
imp.setOverlay(overlay);
}
public void mouseReleased(ImagePlus imp, MouseEvent e) {
if (mode == RESIZED) {
Overlay overlay = imp.getOverlay();
overlay.remove(overlay.size()-1); imp.setOverlay(overlay);
Prefs.set(WIDTH_KEY, width);
if (gd!=null)
options.setWidth(width);
} else if (newPath) mouseDragged(imp, e);
}
private void changeBrushSize(float deltaWidth, ImagePlus imp) {
if (deltaWidth!=0) {
Overlay overlay = imp.getOverlay();
width = oldWidth + deltaWidth;
if (width < 0) width = 0;
Roi circle = new OvalRoi(xStart-width/2, yStart-width/2, width, width);
circle.setStrokeColor(Color.red);
overlay = imp.getOverlay();
if (overlay==null)
overlay = new Overlay();
if (mode == RESIZED)
overlay.remove(overlay.size()-1);
overlay.add(circle);
imp.setOverlay(overlay);
}
IJ.showStatus("Overlay Brush width: "+IJ.d2s(width));
mode = RESIZED;
}
public void showOptionsDialog() {
Thread thread = new Thread(this, "Brush Options");
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
public String getToolName() {
return "Overlay Brush Tool";
}
public String getToolIcon() {
return "C037La077Ld098L6859L4a2fL2f4fL3f99L5e9bL9b98L6888L5e8dL888cC123P2f7f9ebdcaf70";
}
public void run() {
new Options();
}
class Options implements DialogListener {
Options() {
if (gd != null) {
gd.toFront();
return;
}
options = this;
if (IJ.debugMode) IJ.log("Options: true");
showDialog();
}
void setWidth(float width) {
Vector numericFields = gd.getNumericFields();
TextField widthField = (TextField)numericFields.elementAt(0);
widthField.setText(IJ.d2s(width,1));
Vector sliders = gd.getSliders();
Scrollbar sb = (Scrollbar)sliders.elementAt(0);
sb.setValue((int)(width+0.5f));
}
void setColor(Color c) {
String name = Colors.getColorName(c, "");
if (name.length() > 0) {
Vector choices = gd.getChoices();
Choice ch = (Choice)choices.elementAt(0);
ch.select(name);
}
}
public void showDialog() {
Color color = Toolbar.getForegroundColor();
String colorName = Colors.colorToString2(color);
gd = new NonBlockingGenericDialog("Overlay Brush Options");
gd.addSlider("Brush width (pixels):", 0, 50, width);
gd.addSlider("Transparency (%):", 0, 100, transparency);
gd.addChoice("Color:", Colors.getColors(colorName), colorName);
gd.setInsets(10, 0, 0);
String ctrlString = IJ.isMacintosh()? "CMD":"CTRL";
gd.addMessage("SHIFT for horizontal or vertical lines\n"+
"ALT to draw in background color\n"+
ctrlString+"-SHIFT-drag to change brush width\n"+
ctrlString+"-(ALT) click to change foreground (background) color\n"+
"or use this dialog or the Color Picker (shift-k).", null, Color.darkGray);
gd.hideCancelButton();
gd.addHelp("");
gd.setHelpLabel("Undo");
gd.setOKLabel("Close");
gd.addDialogListener(this);
Point loc = Prefs.getLocation(LOC_KEY);
if (loc!=null) {
gd.centerDialog(false);
gd.setLocation (loc);
}
gd.showDialog();
Prefs.saveLocation(LOC_KEY, gd.getLocation());
if (IJ.debugMode) IJ.log("Options: false");
gd = null;
}
public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
if (e!=null && e.toString().contains("Undo")) {
ImagePlus imp = WindowManager.getCurrentImage();
if (imp==null) return true;
Overlay overlay = imp.getOverlay();
if (overlay!=null && overlay.size()>0) {
overlay.remove(overlay.size()-1);
imp.draw();
}
return true;
}
width = (float)gd.getNextNumber();
if (gd.invalidNumber() || width<0)
width = (float)Prefs.get(WIDTH_KEY, 5);
transparency = (int)gd.getNextNumber();
if (gd.invalidNumber() || transparency<0 || transparency>100)
transparency = 100;
String colorName = gd.getNextChoice();
Color color = Colors.decode(colorName, null);
Toolbar.setForegroundColor(color);
Prefs.set(WIDTH_KEY, width);
return true;
}
}
}