package ij.gui;
import ij.*;
import ij.process.*;
import ij.plugin.frame.Recorder;
import java.awt.*;
public class PlotDialog {
public static final int SET_RANGE = 0, AXIS_OPTIONS = 1, LEGEND = 2, HI_RESOLUTION = 3;
private static final String[] HEADINGS = new String[] {"Plot Range...", "Axis Options...", "Add Legend...", "High-Resolution Plot..."};
private static final String[] LEGEND_POSITIONS = new String[] {"Auto", "Top-Left", "Top-Right", "Bottom-Left", "Bottom-Right", "No Legend"};
private static final int[] LEGEND_POSITION_N = new int[] {Plot.AUTO_POSITION, Plot.TOP_LEFT, Plot.TOP_RIGHT, Plot.BOTTOM_LEFT, Plot.BOTTOM_RIGHT, 0};
private Plot plot;
private int dialogType;
private static int legendPosNumber = 0;
private static boolean bottomUp;
private static boolean transparentBackground;
private static String xLabel, yLabel;
private static float plotFontSize;
private static boolean axisLabelBold;
private static float hiResFactor = 4.0f;
private static boolean hiResAntiAliased = true;
public PlotDialog(Plot plot, int dialogType) {
this.plot = plot;
this.dialogType = dialogType;
}
public void showDialog(Frame parent) {
GenericDialog gd = parent == null ? new GenericDialog(HEADINGS[dialogType]) :
new GenericDialog(HEADINGS[dialogType]);
if (dialogType == SET_RANGE) {
double[] currentMinMax = plot.currentMinMax;
boolean livePlot = plot.plotMaker != null;
int xDigits = plot.logXAxis ? -2 : Plot.getDigits(currentMinMax[0], currentMinMax[1], 0.005*Math.abs(currentMinMax[1]-currentMinMax[0]), 6);
int yDigits = plot.logYAxis ? -2 : Plot.getDigits(currentMinMax[2], currentMinMax[3], 0.005*Math.abs(currentMinMax[3]-currentMinMax[2]), 6);
gd.addNumericField("X_From*", currentMinMax[0], xDigits);
gd.addNumericField("X_To*", currentMinMax[1], xDigits);
gd.setInsets(0, 20, 0); if (livePlot)
gd.addCheckbox("Fix_X Range While Live", (plot.templateFlags & Plot.X_RANGE) != 0);
gd.addCheckbox("Log_X Axis", (plot.hasFlag(Plot.X_LOG_NUMBERS)));
gd.setInsets(20, 0, 3); gd.addNumericField("Y_From*", currentMinMax[2], yDigits);
gd.addNumericField("Y_To*", currentMinMax[3], yDigits);
if (livePlot)
gd.addCheckbox("Fix_Y Range While Live", (plot.templateFlags & Plot.Y_RANGE) != 0);
gd.addCheckbox("Log_Y Axis", (plot.hasFlag(Plot.Y_LOG_NUMBERS)));
gd.addMessage("*Leave empty for automatic range", new Font("SansSerif", Font.PLAIN, 12)); gd.showDialog();
if (gd.wasCanceled())
return;
plot.saveMinMax();
double linXMin = gd.getNextNumber();
if (gd.invalidNumber())
linXMin = Double.NaN;
double linXMax = gd.getNextNumber();
if (gd.invalidNumber())
linXMax = Double.NaN;
double linYMin = gd.getNextNumber();
if (gd.invalidNumber())
linYMin = Double.NaN;
double linYMax = gd.getNextNumber();
if (gd.invalidNumber())
linYMax = Double.NaN;
currentMinMax[0] = linXMin;
currentMinMax[1] = linXMax;
currentMinMax[2] = linYMin;
currentMinMax[3] = linYMax;
if (livePlot) plot.templateFlags = setFlag(plot.templateFlags, Plot.X_RANGE, gd.getNextBoolean());
boolean xLog = gd.getNextBoolean();
if (livePlot) plot.templateFlags = setFlag(plot.templateFlags, Plot.Y_RANGE, gd.getNextBoolean());
boolean yLog = gd.getNextBoolean();
plot.setAxisXLog(xLog);
plot.setAxisYLog(yLog);
plot.setLimits(linXMin, linXMax, linYMin, linYMax);
plot.updateImage();
if (Recorder.record) {
if (Recorder.scriptMode()) {
Recorder.recordCall("//plot = IJ.getImage().getProperty(Plot.PROPERTY_KEY)");
Recorder.recordCall("plot.setAxisXLog("+xLog+");");
Recorder.recordCall("plot.setAxisYLog("+yLog+");");
Recorder.recordCall("plot.setLimits("+IJ.d2s(linXMin,xDigits)+","+IJ.d2s(linXMax,xDigits)+","+IJ.d2s(linYMin,yDigits)+","+IJ.d2s(linYMax,yDigits)+");");
} else {
Recorder.recordString("Plot.setLogScaleX("+xLog+");\n");
Recorder.recordString("Plot.setLogScaleY("+yLog+");\n");
Recorder.recordString("Plot.setLimits("+IJ.d2s(linXMin,xDigits)+","+IJ.d2s(linXMax,xDigits)+","+IJ.d2s(linYMin,yDigits)+","+IJ.d2s(linYMax,yDigits)+");\n");
}
}
} else if (dialogType == AXIS_OPTIONS) {
int flags = plot.getFlags();
int columns = 2;
final String[] labels = new String[] {"Draw Grid", "Major Ticks", "Minor Ticks", "Ticks if Logarithmic", "Numbers"};
final int[] xFlags = new int[] {Plot.X_GRID, Plot.X_TICKS, Plot.X_MINOR_TICKS, Plot.X_LOG_TICKS, Plot.X_NUMBERS};
Panel panel = new Panel();
panel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.CENTER;
c.gridy = 0;
c.gridx = 1;
panel.add(new Label("X Axis"), c);
c.gridx = 2;
panel.add(new Label("Y Axis"), c);
Checkbox[] checkboxes = new Checkbox[labels.length*columns];
for (int l=0; l<labels.length; l++) {
c.gridy++;
c.gridx = 0;
c.anchor = GridBagConstraints.EAST;
panel.add(new Label(labels[l]), c);
c.anchor = GridBagConstraints.CENTER;
c.gridx = GridBagConstraints.RELATIVE;
checkboxes[l*columns] = new Checkbox(null, getFlag(flags, xFlags[l])); panel.add(checkboxes[l*columns], c);
checkboxes[l*columns+1] = new Checkbox(null, getFlag(flags, xFlags[l]<<1)); panel.add(checkboxes[l*columns+1], c);
}
gd.addPanel(panel);
gd.setInsets(15, 0, 3); Font plotFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont;
Font labelFont = (plot.xLabelFont != null) ? plot.xLabelFont : plotFont;
gd.addNumericField("Number Font Size", plotFont.getSize2D(), 1);
gd.addNumericField("Label Font Size", labelFont.getSize2D(), 1);
gd.addStringField("X Axis Label", xLabel != null ? xLabel : plot.xLabel, 15);
gd.addStringField("Y Axis Label", yLabel != null ? yLabel : plot.yLabel, 15);
gd.setInsets(0, 20, 0); gd.addCheckbox("Bold Labels", plotFontSize>0 ? axisLabelBold : (plotFont.isBold()));
gd.showDialog();
if (gd.wasCanceled()) return;
flags = 0;
for (int l=0; l<labels.length; l++) {
flags = setFlag(flags, xFlags[l], checkboxes[l*columns].getState());
flags = setFlag(flags, xFlags[l]<<1, checkboxes[l*columns+1].getState());
}
plot.setFormatFlags(flags);
float plotFontSize = (float)gd.getNextNumber();
if (gd.invalidNumber()) plotFontSize = plotFont.getSize2D();
float labelFontSize = (float)gd.getNextNumber();
if (gd.invalidNumber()) labelFontSize = labelFont.getSize2D();
xLabel = gd.getNextString();
yLabel = gd.getNextString();
axisLabelBold = gd.getNextBoolean();
plot.setFont(-1, plotFontSize);
plot.setAxisLabelFont(axisLabelBold ? Font.BOLD : Font.PLAIN, labelFontSize);
plot.setXYLabels(xLabel, yLabel);
plot.updateImage();
if (Recorder.record) {
if (Recorder.scriptMode()) {
Recorder.recordCall("//plot = IJ.getImage().getProperty(Plot.PROPERTY_KEY)");
Recorder.recordCall("plot.setFont(-1,"+IJ.d2s(plotFontSize,1)+");");
Recorder.recordCall("plot.setAxisLabelFont(Plot."+(axisLabelBold ? "BOLD" : "PLAIN")+","+IJ.d2s(labelFontSize,1)+");");
Recorder.recordCall("plot.setXYLabels(\""+xLabel+"\", \""+yLabel+"\");");
Recorder.recordCall("plot.setFormatFlags(0x"+Integer.toHexString(flags)+");");
} else {
Recorder.recordString("Plot.setFontSize("+IJ.d2s(plotFontSize,1)+");\n");
Recorder.recordString("Plot.setAxisLabelSize("+IJ.d2s(labelFontSize,1)+", \""+(axisLabelBold ? "bold" : "plain")+"\");\n");
Recorder.recordString("Plot.setXYLabels(\""+xLabel+"\", \""+yLabel+"\");\n");
Recorder.recordString("Plot.setFormatFlags(\""+Integer.toString(flags,2)+"\");\n");
}
}
} else if (dialogType == LEGEND) {
gd.addMessage("Enter Labels for the datasets, one per line.\n");
String labels = plot.getDataLabels();
int nLines = labels.split("\n", -1).length;
gd.addTextAreas(labels, null, Math.min(nLines+1, 20), 40);
gd.addChoice("Legend position", LEGEND_POSITIONS, LEGEND_POSITIONS[legendPosNumber]);
gd.addCheckbox("Transparent background", transparentBackground);
gd.addCheckbox("Bottom-to-top", bottomUp);
gd.showDialog();
if (gd.wasCanceled()) return;
labels = gd.getNextText();
legendPosNumber = gd.getNextChoiceIndex();
int flags = LEGEND_POSITION_N[legendPosNumber];
transparentBackground = gd.getNextBoolean();
bottomUp = gd.getNextBoolean();
if (bottomUp)
flags |= Plot.LEGEND_BOTTOM_UP;
if (transparentBackground)
flags |= Plot.LEGEND_TRANSPARENT;
plot.setColor(Color.black);
plot.setLineWidth(1);
plot.setLegend(labels, flags);
plot.updateImage();
if (Recorder.record) {
String options = LEGEND_POSITIONS[legendPosNumber];
if (bottomUp) options+=" Bottom-To-Top";
if (transparentBackground) options+=" Transparent";
labels = labels.replaceAll("\n","\\\\n");
if (Recorder.scriptMode()) {
Recorder.recordCall("//plot = IJ.getImage().getProperty(Plot.PROPERTY_KEY);");
Recorder.recordCall("plot.setColor(Color.black);");
Recorder.recordCall("plot.setLineWidth(1);");
Recorder.recordCall("plot.addLegend(\""+labels+"\", \""+options+"\");");
} else {
Recorder.recordString("Plot.addLegend(\""+labels+"\", \""+options+"\");\n");
}
}
} else if (dialogType == HI_RESOLUTION) {
String title = plot.getTitle() +"_HiRes";
title = WindowManager.makeUniqueName(title);
gd.addStringField("Title: ", title, 20);
gd.addNumericField("Scale factor", hiResFactor, 1);
gd.addCheckbox("Disable anti-aliased text", !hiResAntiAliased);
gd.showDialog();
if (gd.wasCanceled()) return;
title = gd.getNextString();
double scale = gd.getNextNumber();
if (!gd.invalidNumber() && scale>0) hiResFactor = (float)scale;
hiResAntiAliased = !gd.getNextBoolean();
final ImagePlus hiresImp = plot.makeHighResolution(title, hiResFactor, hiResAntiAliased, true);
EventQueue.invokeLater(new Runnable() {public void run() {IJ.selectWindow(hiresImp.getID());}});
if (Recorder.record) {
String options = !hiResAntiAliased ? "disable" : "";
if (options.length() > 0)
options = ",\""+options+"\"";
Recorder.recordString("Plot.makeHighResolution(\""+title+"\","+hiResFactor+options+");\n");
}
}
}
boolean getFlag(int flags, int bitMask) {
return (flags&bitMask) != 0;
}
int setFlag(int flags, int bitMask, boolean state) {
flags &= ~bitMask;
if (state) flags |= bitMask;
return flags;
}
}