diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef2885549..68abe1e8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,5 +17,10 @@ jobs: java-version: '25' java-package: 'jdk' + - name: Set up Maven + uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5 + with: + maven-version: '3.9.16' + - name: Build with Maven run: mvn -f com.eco.bio7.aggregator/pom.xml install --batch-mode --no-transfer-progress diff --git a/com.eco.bio7.WorldWind/src/com/eco/bio7/worldwind/WorldWindOptionsView.java b/com.eco.bio7.WorldWind/src/com/eco/bio7/worldwind/WorldWindOptionsView.java index 37d08558f..1fd033789 100644 --- a/com.eco.bio7.WorldWind/src/com/eco/bio7/worldwind/WorldWindOptionsView.java +++ b/com.eco.bio7.WorldWind/src/com/eco/bio7/worldwind/WorldWindOptionsView.java @@ -145,7 +145,7 @@ import worldw.Activator; -import com.eco.bio7.image.CanvasView; +import com.eco.bio7.image.ui.CanvasView; import com.eco.bio7.util.Util; import com.eco.bio7.worldwind.swt.WorldWindowNewtCanvasSWT; import com.swtdesigner.SWTResourceManager; diff --git a/com.eco.bio7.WorldWind/src/com/eco/bio7/worldwind/WorldWindView.java b/com.eco.bio7.WorldWind/src/com/eco/bio7/worldwind/WorldWindView.java index d1a13c1b0..3231f1c49 100644 --- a/com.eco.bio7.WorldWind/src/com/eco/bio7/worldwind/WorldWindView.java +++ b/com.eco.bio7.WorldWind/src/com/eco/bio7/worldwind/WorldWindView.java @@ -61,7 +61,7 @@ import org.eclipse.ui.part.ViewPart; import org.rosuda.REngine.Rserve.RConnection; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; import com.eco.bio7.worldwind.swt.NewtInputHandlerSWT; import com.eco.bio7.worldwind.swt.StatusBar; import com.eco.bio7.worldwind.swt.WorldWindowNewtAutoDrawableSWT; diff --git a/com.eco.bio7.ijmacro.editor/META-INF/MANIFEST.MF b/com.eco.bio7.ijmacro.editor/META-INF/MANIFEST.MF index fd4addc65..7c82f77d7 100644 --- a/com.eco.bio7.ijmacro.editor/META-INF/MANIFEST.MF +++ b/com.eco.bio7.ijmacro.editor/META-INF/MANIFEST.MF @@ -17,7 +17,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.text, org.eclipse.ui.ide, org.eclipse.core.resources, - com.eco.bio7.image + com.eco.bio7.image, + com.eco.bio7.util Eclipse-LazyStart: true Import-Package: org.eclipse.ui.views.contentoutline Bundle-ClassPath: bin/, diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenColorDialog.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenColorDialog.java index da6344c17..a7baba662 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenColorDialog.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenColorDialog.java @@ -14,7 +14,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; public class OpenColorDialog extends AbstractHandler { diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenColorDialogRGBToHex.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenColorDialogRGBToHex.java index a5dacb4ce..4c7bcbefd 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenColorDialogRGBToHex.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenColorDialogRGBToHex.java @@ -16,7 +16,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; public class OpenColorDialogRGBToHex extends AbstractHandler { diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenDirDialog.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenDirDialog.java index 6abfec7e1..df1ae30a4 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenDirDialog.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenDirDialog.java @@ -13,7 +13,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; public class OpenDirDialog extends AbstractHandler { private String dir; diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenFileDialog.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenFileDialog.java index b800f2188..0beb2e0de 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenFileDialog.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/OpenFileDialog.java @@ -14,7 +14,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; public class OpenFileDialog extends AbstractHandler { diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/SaveFileDialog.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/SaveFileDialog.java index 103f4718a..01aed5098 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/SaveFileDialog.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/SaveFileDialog.java @@ -14,7 +14,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; public class SaveFileDialog extends AbstractHandler { diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/color/OpenColorHexDialog.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/color/OpenColorHexDialog.java index a319929f2..6871bd00e 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/color/OpenColorHexDialog.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/actions/color/OpenColorHexDialog.java @@ -12,7 +12,7 @@ import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; /*For this class only a command is defined. It is used in the RColorInformationControl hover!*/ public class OpenColorHexDialog extends Action { diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/DebugSetVariableAction.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/DebugSetVariableAction.java index 97985188c..34c1ecccc 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/DebugSetVariableAction.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/DebugSetVariableAction.java @@ -18,7 +18,7 @@ import org.eclipse.swt.widgets.Shell; import com.eco.bio7.ijmacro.editor.IJMacroEditorPlugin; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; import ij.macro.Interpreter; diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/EditSelBreakpointAction.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/EditSelBreakpointAction.java index e7bc6c882..d8ef1cc9b 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/EditSelBreakpointAction.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/EditSelBreakpointAction.java @@ -32,7 +32,7 @@ import org.eclipse.ui.texteditor.AbstractRulerActionDelegate; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; public class EditSelBreakpointAction extends AbstractRulerActionDelegate implements IEditorActionDelegate { diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/SetDebugBreakpointMacroValueDialog.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/SetDebugBreakpointMacroValueDialog.java index c74911b49..64620d2c8 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/SetDebugBreakpointMacroValueDialog.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/SetDebugBreakpointMacroValueDialog.java @@ -16,7 +16,7 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/SetDebugMacroValueDialog.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/SetDebugMacroValueDialog.java index 13b218412..323c02970 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/SetDebugMacroValueDialog.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/SetDebugMacroValueDialog.java @@ -16,7 +16,7 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; /*Class from: http://www.vogella.com/tutorials/EclipseDialogs/article.html*/ diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/ToggleDebugConditionalBreakpointAction.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/ToggleDebugConditionalBreakpointAction.java index 823c53fef..e475b74f5 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/ToggleDebugConditionalBreakpointAction.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editor/toolbar/debug/ToggleDebugConditionalBreakpointAction.java @@ -30,7 +30,7 @@ import org.eclipse.ui.texteditor.AbstractRulerActionDelegate; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.ITextEditor; -import com.eco.bio7.image.Util; +import com.eco.bio7.util.Util; public class ToggleDebugConditionalBreakpointAction extends AbstractRulerActionDelegate implements IEditorActionDelegate { diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editors/IJMacroEditor.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editors/IJMacroEditor.java index ddccad5fb..207ef2d92 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editors/IJMacroEditor.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editors/IJMacroEditor.java @@ -112,8 +112,8 @@ import com.eco.bio7.ijmacro.editor.outline.IJMacroEditorOutlineNode; import com.eco.bio7.ijmacro.editor.outline.IJMacroEditorTreeContentProvider; import com.eco.bio7.ijmacro.editor.toolbar.debug.DebugVariablesView; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.Util; +import com.eco.bio7.image.ui.CanvasView; +import com.eco.bio7.util.Util; import ij.IJ; import ij.WindowManager; @@ -129,6 +129,10 @@ */ public class IJMacroEditor extends TextEditor implements IPropertyChangeListener, Debugger { + /* Bio7 debug mode (not available in the ImageJ Debugger interface)! */ + public static final int RUN_TO_EXPRESSION = 6; + + private static final String TEMPLATE_PROPOSALS = "template_proposals_action"; private ColorManager colorManager; diff --git a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editors/MacroRunner.java b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editors/MacroRunner.java index afb668e68..d58e4a7e6 100644 --- a/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editors/MacroRunner.java +++ b/com.eco.bio7.ijmacro.editor/src/com/eco/bio7/ijmacro/editors/MacroRunner.java @@ -172,7 +172,7 @@ public void run() { interp.run(macro); else { if ("Popup Menu".equals(name)) { - PopupMenu popup = Menus.getPopupMenu(); + org.eclipse.swt.widgets.Menu popup = Menus.getPopupMenu(); if (popup!=null) { ImagePlus imp = null; Object parent = popup.getParent(); diff --git a/com.eco.bio7.ijmacroedit.feature/feature.xml b/com.eco.bio7.ijmacroedit.feature/feature.xml index d02cd98fe..6f56d924e 100644 --- a/com.eco.bio7.ijmacroedit.feature/feature.xml +++ b/com.eco.bio7.ijmacroedit.feature/feature.xml @@ -231,6 +231,7 @@ litigation. + diff --git a/com.eco.bio7.image.feature/feature.xml b/com.eco.bio7.image.feature/feature.xml index ac25dff4d..ca1167aed 100644 --- a/com.eco.bio7.image.feature/feature.xml +++ b/com.eco.bio7.image.feature/feature.xml @@ -117,6 +117,10 @@ This Agreement is governed by the laws of the State of New York and the intellec + + @@ -132,6 +136,7 @@ This Agreement is governed by the laws of the State of New York and the intellec + ]",ij.plugin.Animator("next") -stacks04="Previous Slice [<]",ij.plugin.Animator("previous") -stacks05="Set Slice...",ij.plugin.Animator("set") -stacks06=- -stacks07="Images to Stack",ij.plugin.ImagesToStack -stacks08="Stack to Images",ij.plugin.StackEditor("toimages") -stacks09="Make Montage...",ij.plugin.MontageMaker -stacks10="Reslice [/]...",ij.plugin.Slicer -stacks11="Orthogonal Views[H]",ij.plugin.Orthogonal_Views -stacks12="Z Project...",ij.plugin.ZProjector -stacks13="3D Project...",ij.plugin.Projector -stacks14="Plot Z-axis Profile",ij.plugin.ZAxisProfiler -stacks15="Measure Stack...",ij.plugin.SimpleCommands("measure") -stacks16="Label...",ij.plugin.filter.StackLabeler -stacks17="Statistics",ij.plugin.Stack_Statistics - -# Plugins installed in the Image/Stacks/Animation submenu -animation_01="Start Animation [\\]",ij.plugin.Animator("start") -animation_02="Stop Animation",ij.plugin.Animator("stop") -animation_03="Animation Options...",ij.plugin.Animator("options") - -# Plugins installed in the Image/Stacks/Tools submenu -tools_01="Combine...",ij.plugin.StackCombiner -tools_02="Concatenate...",ij.plugin.Concatenator -tools_03="Grouped Z Project...",ij.plugin.GroupedZProjector -tools_04="Insert...",ij.plugin.StackInserter -tools_05="Magic Montage Tools",ij.plugin.SimpleCommands("magic") -tools_06="Make Substack...",ij.plugin.SubstackMaker -tools_07="Montage to Stack...",ij.plugin.StackMaker -tools_08="Plot XY Profile",ij.plugin.StackPlotter -tools_09="Reduce...",ij.plugin.StackReducer -tools_10="Remove Slice Labels",ij.plugin.SimpleCommands("remove") -tools_11="Reverse",ij.plugin.StackReverser -tools_12="Set Label...",ij.plugin.SimpleCommands("set") - -# Plugins installed in the Image/Hyperstacks submenu -hyperstacks01="New Hyperstack...",ij.plugin.HyperStackMaker -hyperstacks02="Stack to Hyperstack...",ij.plugin.HyperStackConverter("stacktohs") -hyperstacks03="Hyperstack to Stack",ij.plugin.HyperStackConverter("hstostack") -hyperstacks04="Reduce Dimensionality...",ij.plugin.HyperStackReducer -hyperstacks05="Make Subset...",ij.plugin.SubstackMaker - -# Plugins installed in the Image/Transform submenu -transform01="Flip Horizontally",ij.plugin.filter.Transformer("fliph") -transform02="Flip Vertically",ij.plugin.filter.Transformer("flipv") -transform03="Flip Z",ij.plugin.StackReverser -transform04="Rotate 90 Degrees Right",ij.plugin.filter.Transformer("right") -transform05="Rotate 90 Degrees Left",ij.plugin.filter.Transformer("left") -transform06="Rotate... ",ij.plugin.filter.Rotator -transform07="Translate...",ij.plugin.filter.Translator -transform08="Bin...",ij.plugin.Binner -transform09=- -transform10="Image to Results",ij.plugin.SimpleCommands("itor") -transform11="Results to Image",ij.plugin.SimpleCommands("rtoi") - -# Plugins installed in the Image/Zoom submenu -zoom01="In [+]",ij.plugin.Zoom("in") -zoom02="Out [-]",ij.plugin.Zoom("out") -zoom03="Original Scale[4]",ij.plugin.Zoom("orig") -zoom04="View 100%[5]",ij.plugin.Zoom("100%") -zoom05="To Selection",ij.plugin.Zoom("to") -zoom06="Scale to Fit",ij.plugin.Zoom("scale") -zoom07="Set... ",ij.plugin.Zoom("set") -zoom08="Maximize",ij.plugin.Zoom("max") - -# Plugins installed in the Image/Overlay submenu -overlay01="Add Selection...[b]",ij.plugin.OverlayCommands("add") -overlay02="Add Image...",ij.plugin.OverlayCommands("image") -overlay03="Hide Overlay",ij.plugin.OverlayCommands("hide") -overlay04="Show Overlay",ij.plugin.OverlayCommands("show") -overlay05="From ROI Manager",ij.plugin.OverlayCommands("from") -overlay06="To ROI Manager",ij.plugin.OverlayCommands("to") -overlay07="Remove Overlay",ij.plugin.OverlayCommands("remove") -overlay08="Toggle Overlay",ij.plugin.OverlayCommands("toggle") -overlay09="List Elements",ij.plugin.OverlayCommands("list") -overlay10="Flatten[F]",ij.plugin.OverlayCommands("flatten") -overlay11="Labels...",ij.plugin.OverlayLabels -overlay12="Measure Overlay",ij.plugin.OverlayCommands("measure") -overlay13="Overlay Options...[Y]",ij.plugin.OverlayCommands("options") - -# Plugins installed in the Image/Lookup Tables submenu -lookup01="Invert LUT",ij.plugin.LutLoader("invert") -lookup02="Apply LUT",ij.plugin.filter.LutApplier -lookup03=- -lookup04="Fire",ij.plugin.LutLoader("fire") -lookup05="Grays",ij.plugin.LutLoader("grays") -lookup06="Ice",ij.plugin.LutLoader("ice") -lookup07="Spectrum",ij.plugin.LutLoader("spectrum") -lookup08="3-3-2 RGB",ij.plugin.LutLoader("3-3-2 RGB") -lookup09="Red",ij.plugin.LutLoader("red") -lookup10="Green",ij.plugin.LutLoader("green") -lookup11="Blue",ij.plugin.LutLoader("blue") -lookup12="Cyan",ij.plugin.LutLoader("cyan") -lookup13="Magenta",ij.plugin.LutLoader("magenta") -lookup14="Yellow",ij.plugin.LutLoader("yellow") -lookup15="Red/Green",ij.plugin.LutLoader("redgreen") - -# Plug-ins installed in the Process/Noise submenu -noise01="Add Noise",ij.plugin.filter.Filters("add") -noise02="Add Specified Noise...",ij.plugin.filter.Filters("noise") -noise03="Salt and Pepper",ij.plugin.filter.SaltAndPepper -noise04=- -noise05="Despeckle",ij.plugin.filter.RankFilters("despeckle") -noise06="Remove Outliers...",ij.plugin.filter.RankFilters("outliers") -noise07="Remove NaNs...",ij.plugin.filter.RankFilters("nan") - -# Plugins installed in the Process/Shadows submenu -shadows01="North",ij.plugin.filter.Shadows("north") -shadows02="Northeast",ij.plugin.filter.Shadows("northeast") -shadows03="East",ij.plugin.filter.Shadows("east") -shadows04="Southeast",ij.plugin.filter.Shadows("southeast") -shadows05="South",ij.plugin.filter.Shadows("south") -shadows06="Southwest",ij.plugin.filter.Shadows("southwest") -shadows07="West",ij.plugin.filter.Shadows("west") -shadows08="Northwest",ij.plugin.filter.Shadows("northwest") -shadows09=- -shadows10="Shadows Demo",ij.plugin.filter.Shadows("demo") - -# Plugins installed in the Process/Binary submenu -binary01="Make Binary",ij.plugin.Thresholder -binary02="Convert to Mask",ij.plugin.Thresholder("mask") -binary03=- -binary04="Erode",ij.plugin.filter.Binary("erode") -binary05="Dilate",ij.plugin.filter.Binary("dilate") -binary06="Open",ij.plugin.filter.Binary("open") -# Can't use "Close" because it conflicts with File/Close -binary07="Close-",ij.plugin.filter.Binary("close") -binary08="Median",ij.plugin.filter.Binary("median") -binary09=- -binary10="Outline",ij.plugin.filter.Binary("outline") -binary11="Fill Holes",ij.plugin.filter.Binary("fill") -binary12="Skeletonize",ij.plugin.filter.Binary("skel") -binary13=- -binary14="Distance Map",ij.plugin.filter.EDM("edm") -binary15="Ultimate Points",ij.plugin.filter.EDM("points") -binary16="Watershed",ij.plugin.filter.EDM("watershed") -binary17="Voronoi",ij.plugin.filter.EDM("voronoi") -binary18="Dither...",ij.plugin.filter.Dithering - -binary19=- -binary20="Options...",ij.plugin.filter.Binary("options") - -# Plugins installed in the Process/Math submenu -math01="Add...",ij.plugin.filter.ImageMath("add") -math02="Subtract...",ij.plugin.filter.ImageMath("sub") -math03="Multiply...",ij.plugin.filter.ImageMath("mul") -math04="Divide...",ij.plugin.filter.ImageMath("div") -math05="AND...",ij.plugin.filter.ImageMath("and") -math06="OR...",ij.plugin.filter.ImageMath("or") -math07="XOR...",ij.plugin.filter.ImageMath("xor") -math08="Min...",ij.plugin.filter.ImageMath("min") -math09="Max...",ij.plugin.filter.ImageMath("max") -math10="Gamma...",ij.plugin.filter.ImageMath("gamma") -math11="Set...",ij.plugin.filter.ImageMath("set") -math12="Log",ij.plugin.filter.ImageMath("log") -math13="Exp",ij.plugin.filter.ImageMath("exp") -math14="Square",ij.plugin.filter.ImageMath("sqr") -math15="Square Root",ij.plugin.filter.ImageMath("sqrt") -math16="Reciprocal",ij.plugin.filter.ImageMath("reciprocal") -math17="NaN Background",ij.plugin.filter.ImageMath("nan") -math18="Abs",ij.plugin.filter.ImageMath("abs") -math19="Macro...",ij.plugin.filter.ImageMath("macro") - -# Plugins installed in the Process/FFT submenu -fft01="FFT",ij.plugin.FFT("fft") -fft02="Inverse FFT",ij.plugin.FFT("inverse") -fft03="Redisplay Power Spectrum",ij.plugin.FFT("redisplay") -fft04="FFT Options...",ij.plugin.FFT("options") -fft05=- -fft06="Bandpass Filter...",ij.plugin.filter.FFTFilter -fft07="Custom Filter...",ij.plugin.filter.FFTCustomFilter -fft08="FD Math...",ij.plugin.FFTMath -fft09="Swap Quadrants",ij.plugin.FFT("swap") -fft10="Make Circular Selection...",ij.plugin.CircularRoiMaker - -# Plugins installed in the Process/Filters submenu -filters01="Convolve...",ij.plugin.filter.Convolver -filters02="Gaussian Blur...",ij.plugin.filter.GaussianBlur -filters03="Median...",ij.plugin.filter.RankFilters("median") -filters04="Mean...",ij.plugin.filter.RankFilters("mean") -filters05="Minimum...",ij.plugin.filter.RankFilters("min") -filters06="Maximum...",ij.plugin.filter.RankFilters("max") -filters07="Unsharp Mask...",ij.plugin.filter.UnsharpMask -filters08="Variance...",ij.plugin.filter.RankFilters("variance") -filters09="Top Hat...",ij.plugin.filter.RankFilters("tophat") -filters10=- -filters11="Gaussian Blur 3D...",ij.plugin.GaussianBlur3D -filters12="Median 3D...",ij.plugin.Filters3D("median") -filters13="Mean 3D...",ij.plugin.Filters3D("mean") -filters14="Minimum 3D...",ij.plugin.Filters3D("min") -filters15="Maximum 3D...",ij.plugin.Filters3D("max") -filters16="Variance 3D...",ij.plugin.Filters3D("var") -filters17=- -filters18="Show Circular Masks...",ij.plugin.filter.RankFilters("masks") - -# Plugins installed in the File/Batch submenu -batch01="Measure...",ij.plugin.BatchMeasure -batch02="Convert...",ij.plugin.BatchConverter -batch03="Macro... ",ij.plugin.BatchProcessor -batch04="Virtual Stack...",ij.plugin.BatchProcessor("stack") - -# Plugins installed in the Analyze/Gels submenu -gels01="Select First Lane[1]",ij.plugin.GelAnalyzer("first") -gels02="Select Next Lane[2]",ij.plugin.GelAnalyzer("next") -gels03="Plot Lanes[3]",ij.plugin.GelAnalyzer("plot") -gels04="Re-plot Lanes",ij.plugin.GelAnalyzer("replot") -gels05="Reset",ij.plugin.GelAnalyzer("reset") -gels06="Label Peaks",ij.plugin.GelAnalyzer("label") -gels07="Gel Analyzer Options...",ij.plugin.GelAnalyzer("options") - -# Plugins installed in the Analyze/Tools submenu -tools01="Save XY Coordinates...",ij.plugin.XYCoordinates -tools02="Fractal Box Count...",ij.plugin.filter.FractalBoxCounter -tools03="Analyze Line Graph",ij.plugin.filter.LineGraphAnalyzer -tools04="Curve Fitting...",ij.plugin.frame.Fitter -tools05="ROI Manager...",ij.plugin.frame.RoiManager -tools06="Scale Bar...",ij.plugin.ScaleBar -tools07="Calibration Bar...",ij.plugin.CalibrationBar -tools08="Synchronize Windows",ij.plugin.frame.SyncWindows -tools09="Grid...",ij.plugin.Grid -tools10="Compare Images...",ij.plugin.ImageComparator - -# Plugins installed in the Plugins menu -plug-in01=>"Macros" -plug-in02=>"Shortcuts" -plug-in03=>"Utilities" -plug-in04=>"New_" -plug-in05="Compile and Run...",ij.plugin.Compiler -plug-in06="Install... [M]",ij.plugin.PluginInstaller -#plug-in07=- -#plug-in08=>"User_Plugins" - -# Install user plugins located in ij.jar to Plugins>User Plugins submenu -#user_plugins01="Red And Blue",RedAndBlue_ -#user_plugins02="Inverter",Inverter_ - - -# Plugins installed in the Plugins/Macros submenu -# 'MACROS_MENU_COMMANDS' in MacroInstaller must be updated when items are added -macros01="Install...",ij.plugin.MacroInstaller -macros02="Run...",ij.plugin.Macro_Runner -macros03="Edit...",ij.plugin.Compiler("edit") -macros04="Startup Macros...",ij.plugin.Commands("startup") -macros05="Interactive Interpreter...[j]",ij.plugin.SimpleCommands("interactive") -macros06="Record...[u]",ij.plugin.frame.Recorder -macros07=- - -# Plugins installed in the Plugins/Shortcuts submenu -shortcuts01="Add Shortcut... ",ij.plugin.Hotkeys("install") -shortcuts02="Add Shortcut by Name... ",ij.plugin.Hotkeys("install2") -shortcuts03="Remove Shortcut...",ij.plugin.Hotkeys("remove") -shortcuts04="List Shortcuts",ij.plugin.CommandLister("shortcuts") -shortcuts05="List Commands",ij.plugin.Hotkeys("list") -shortcuts06=- - -# Plugins installed in the Plugins/Utilities submenu -utilities01="Control Panel...[U]",ij.plugin.ControlPanel -utilities02="Find Commands...[l]",ij.plugin.CommandFinder -utilities03="Commands...[L]",ij.plugin.frame.Commands -utilities04="Search...",ij.plugin.SimpleCommands("search") -utilities05="Monitor Events...",ij.plugin.EventListener -utilities06="Monitor Memory...",ij.plugin.frame.MemoryMonitor -utilities07=- -utilities08="Capture Screen[G]",ij.plugin.ScreenGrabber -utilities09="Capture Delayed...",ij.plugin.ScreenGrabber("delay") -utilities10="Capture Image",ij.plugin.ScreenGrabber("image") -utilities11=- -utilities12="ImageJ Properties",ij.plugin.JavaProperties -utilities13="Threads",ij.plugin.ThreadLister -utilities14="Benchmark",ij.plugin.Benchmark -utilities15="Reset...",ij.plugin.SimpleCommands("reset") -utilities16="DICOM Metadata...",ij.plugin.DicomMetadata - -# Plugins installed in the Plugins/New submenu -new_01="Macro",ij.plugin.NewPlugin("macro") -new_02="Macro Tool",ij.plugin.NewPlugin("macro-tool") -new_03="JavaScript",ij.plugin.NewPlugin("javascript") -new_04=- -new_05="Plugin",ij.plugin.NewPlugin("plugin") -new_06="Plugin Filter",ij.plugin.NewPlugin("filter") -new_07="Plugin Frame",ij.plugin.NewPlugin("frame") -new_08="Plugin Tool",ij.plugin.NewPlugin("plugin-tool") -new_09=- -new_10="Text Window...",ij.plugin.NewPlugin("text+dialog") - -# Plugins installed in the Help/About submenu -about01="About This Submenu...",ij.plugin.SimpleCommands("about") -about02=- - -# URL of directory containing the sample images -# location2 is uses with Java 6, which does not support https -# 2022-06-30 (1.53t20): stopped using https due to Windows bug -images.location=http://imagej.net/images/ -images.location2=http://imagej.net/images/ - -# Images installed in the Open Samples submenu -# RawReader expects a string with "name width height nImages bitsPerPixel offset [white]" -open01="AuPbSn 40",ij.plugin.URLOpener("AuPbSn40.jpg") -open02="Bat Cochlea Volume",ij.plugin.URLOpener("bat-cochlea-volume.zip") -open03="Bat Cochlea Renderings",ij.plugin.URLOpener("bat-cochlea-renderings.zip") -open04="Blobs[B]",ij.plugin.URLOpener("blobs.gif") -open05="Boats",ij.plugin.URLOpener("boats.gif") -open06="Cardio (RGB DICOM)",ij.plugin.URLOpener("cardio.dcm.zip") -open07="Cell Colony",ij.plugin.URLOpener("Cell_Colony.jpg") -open08="Clown",ij.plugin.URLOpener("clown.jpg") -open09="Confocal Series",ij.plugin.URLOpener("confocal-series.zip") -open10="CT (16-bit DICOM)",ij.plugin.URLOpener("ct.dcm.zip") -open11="Dot Blot",ij.plugin.URLOpener("Dot_Blot.jpg") -open12="Embryos",ij.plugin.URLOpener("embryos.jpg") -open13="Fluorescent Cells",ij.plugin.URLOpener("FluorescentCells.zip") -open14="Fly Brain",ij.plugin.URLOpener("flybrain.zip") -open15="Gel",ij.plugin.URLOpener("gel.gif") -open16="HeLa Cells (48-bit RGB)",ij.plugin.URLOpener("hela-cells.zip") -open17="Image with Overlay",ij.plugin.URLOpener("ImageWithOverlay.zip") -open18="Leaf",ij.plugin.URLOpener("leaf.jpg") -open19="Line Graph",ij.plugin.URLOpener("LineGraph.jpg") -open20="Mitosis (5D stack)",ij.plugin.URLOpener("Spindly-GFP.zip") -open21="MRI Stack",ij.plugin.URLOpener("mri-stack.zip") -open22="M51 Galaxy (16-bits)",ij.plugin.URLOpener("m51.zip") -open23="Neuron (5 channels)",ij.plugin.URLOpener("Rat_Hippocampal_Neuron.zip") -open24="Nile Bend",ij.plugin.URLOpener("NileBend.jpg") -open25="Organ of Corti (4D stack)",ij.plugin.URLOpener("organ-of-corti.zip") -open26="Particles",ij.plugin.URLOpener("particles.gif") -open27="T1 Head (16-bits)",ij.plugin.URLOpener("t1-head.zip") -open28="T1 Head Renderings",ij.plugin.URLOpener("t1-rendering.zip") -open29="TEM Filter",ij.plugin.URLOpener("TEM_filter_sample.jpg") -open30="Tree Rings",ij.plugin.URLOpener("Tree_Rings.jpg") - diff --git a/com.eco.bio7.image/ImageJ.cfg b/com.eco.bio7.image/ImageJ.cfg deleted file mode 100644 index ee5eca1d5..000000000 --- a/com.eco.bio7.image/ImageJ.cfg +++ /dev/null @@ -1,3 +0,0 @@ -. -jre\bin\javaw.exe --Xmx1026m -cp ij.jar ij.ImageJ diff --git a/com.eco.bio7.image/META-INF/MANIFEST.MF b/com.eco.bio7.image/META-INF/MANIFEST.MF index 6b21eaa8a..3857ab31a 100644 --- a/com.eco.bio7.image/META-INF/MANIFEST.MF +++ b/com.eco.bio7.image/META-INF/MANIFEST.MF @@ -5,10 +5,11 @@ Bundle-ManifestVersion: 2 Bundle-Name: ImageJ Plug-in Bundle-SymbolicName: com.eco.bio7.image;singleton:=true Bundle-Version: 1.54.196 -Bundle-Activator: com.eco.bio7.image.Activator +Bundle-Activator: com.eco.bio7.image.ui.Activator Bundle-Vendor: ECO Bundle-Localization: plugin Eclipse-BuddyPolicy: ext +Eclipse-RegisterBuddy: org.eclipse.swt.imagej Eclipse-BundleShape: dir Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, @@ -22,28 +23,15 @@ Require-Bundle: org.eclipse.ui, org.eclipse.e4.core.contexts, org.eclipse.swt, org.eclipse.jdt.ui, - org.eclipse.text + org.eclipse.text, + com.eco.bio7.util, + org.eclipse.swt.imagej;bundle-version="0.7.0";visibility:=reexport Eclipse-LazyStart: true Bundle-RequiredExecutionEnvironment: JavaSE-25 Bundle-ClassPath: bin/, - commons-io-1.4.jar, - external:$java.home$/lib/tools.jar -Export-Package: ., - com.eco.bio7.ImageJPluginActions, - com.eco.bio7.image, - com.eco.bio7.image.thumbs, - ij, - ij.gui, - ij.io, - ij.macro, - ij.measure, - ij.plugin, - ij.plugin.filter, - ij.plugin.frame, - ij.plugin.tool, - ij.process, - ij.text, - ij.util + commons-io-1.4.jar +Export-Package: com.eco.bio7.ImageJPluginActions, + com.eco.bio7.image.ui, + com.eco.bio7.image.thumbs Bundle-ActivationPolicy: lazy -Import-Package: ij.gui diff --git a/com.eco.bio7.image/build.properties b/com.eco.bio7.image/build.properties index 1fc7ea0ba..bcebd2273 100644 --- a/com.eco.bio7.image/build.properties +++ b/com.eco.bio7.image/build.properties @@ -1,6 +1,5 @@ bin.includes = META-INF/,\ build.properties,\ - ImageJ.cfg,\ .classpath,\ plugin.xml,\ macros/,\ @@ -10,7 +9,6 @@ bin.includes = META-INF/,\ luts/,\ baseline.jar,\ swt-grouplayout.jar,\ - IJ_Props.txt,\ .FBCLockFolder/,\ .settings/,\ src/,\ diff --git a/com.eco.bio7.image/plugin.xml b/com.eco.bio7.image/plugin.xml index c2370075a..92fa2cb1f 100644 --- a/com.eco.bio7.image/plugin.xml +++ b/com.eco.bio7.image/plugin.xml @@ -6,7 +6,7 @@ @@ -19,14 +19,14 @@ mainMenuStack = new Stack();// Just for variable - private MenuItem menuBit; - + /** + * Adds the items of the ImageJ menu with the given label to the given menu. + * + * @param mainMenu the target menu. + * @param label the label of the ImageJ main menu (e.g., "File"). + */ public void addSubMenus(Menu mainMenu, String label) { - mainMenuStack.push(mainMenu); - MenuBar menuBar = Menus.getMenuBar(); - for (int i = 0; i < menuBar.getMenuCount(); i++) { - java.awt.Menu menu = menuBar.getMenu(i); - - if (menu.getLabel().equals(label)) - - recurseSubMenu(menu, mainMenu, label); + Menu menuBar = Menus.getMenuBar(); + if (menuBar == null || menuBar.isDisposed()) { + return; + } + for (MenuItem item : menuBar.getItems()) { + if (stripMnemonic(item.getText()).equals(label) && item.getMenu() != null) { + copyMenu(item.getMenu(), mainMenu, label); + } } } - private void recurseSubMenu(java.awt.Menu menu, Menu mainMenu, String mainMenuLabel) { - int items = menu.getItemCount(); - if (items == 0) - return; - for (int i = 0; i < items; i++) { - java.awt.MenuItem mItem = menu.getItem(i); - String label = mItem.getActionCommand(); - - if (mItem instanceof java.awt.Menu) { - Menu menuSub = new Menu(mainMenu); - MenuItem menuItem_stacks = new MenuItem(mainMenu, SWT.CASCADE); - menuItem_stacks.setMenu(menuSub); - menuItem_stacks.setText(mItem.getLabel()); - - /* Push Menu on the stack! */ - mainMenuStack.push(menuSub); - - recurseSubMenu((java.awt.Menu) mItem, menuSub, mainMenuLabel); - - mainMenuStack.pop(); - - } else if (mItem instanceof java.awt.MenuItem) { - - Menu currentSubMenu = mainMenuStack.peek(); - - if (mItem instanceof CheckboxMenuItem) { - if (mainMenuLabel.equals("Window")) { - /* Don't add images to the menu. We have already a list in the tabs menu! */ - String idString = mItem.getActionCommand(); - int id = (int) Tools.parseDouble(idString, 0); - ImagePlus imp = WindowManager.getImage(id); - if (imp != null) { - break; - } - } - - MenuItem it = new MenuItem(currentSubMenu, SWT.CHECK); - it.setSelection(false); - if ("Autorun Examples".equals(mItem.getLabel())) { - if (Prefs.autoRunExamples) { - - it.setSelection(true); - - } else { - - it.setSelection(false); - } - } - - String lab = mItem.getLabel(); - - it.setText(lab); - it.addSelectionListener(new SelectionListener() { - - public void widgetSelected(SelectionEvent e) { - String cmd = mItem.getActionCommand(); - - if ("Autorun Examples".equals(cmd)) { // Examples>Autorun Examples - - if (Prefs.autoRunExamples) { - Prefs.autoRunExamples = false; - it.setSelection(false); - - } else { - Prefs.autoRunExamples = true; - it.setSelection(true); - } - - - } - - else if (mainMenuLabel.equals("Window")) { - - /* Add the opened dialogs to the menu! */ - SwingUtilities.invokeLater(new Runnable() { - public void run() { - WindowManager.activateWindow(cmd, mItem); - } - }); - - } - - else { - - IJ.doCommand(cmd); - } - - } - - public void widgetDefaultSelected(SelectionEvent e) { - - } - }); - if (label.equals("8-bit") || label.equals("16-bit") || label.equals("32-bit") || label.equals("8-bit Color") || - label.equals("RGB Color") || label.equals("RGB Stack") || label.equals("HSB Stack") || label.equals("Lab Stack")) { - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp != null) { - - if (IJ.getImage().getType() == 0 && label.equals("8-bit")) { - - it.setSelection(true); - menuBit = it; - - } else if (IJ.getImage().getType() == 1 && label.equals("16-bit")) { - it.setSelection(true); - menuBit = it; - } else if (IJ.getImage().getType() == 2 && label.equals("32-bit")) { - it.setSelection(true); - menuBit = it; - } else if (IJ.getImage().getType() == 3 && label.equals("8-bit Color")) { - it.setSelection(true); - menuBit = it; - } - - else if (IJ.getImage().getType() == 4 && label.equals("RGB Color")) { - it.setSelection(true); - menuBit = it; - } else if (imp.getStack().isRGB() && label.equals("RGB Stack")) { - it.setSelection(true); - menuBit.setSelection(false); - } else if (imp.getStack().isHSB() && label.equals("HSB Stack")) { - it.setSelection(true); - menuBit.setSelection(false); - } else if (imp.getStack().isLab() && label.equals("Lab Stack")) { - it.setSelection(true); - menuBit.setSelection(false); - } - - else { - it.setSelection(false); - } - } - } + private static String stripMnemonic(String text) { + return text.replace("&", ""); + } + private void copyMenu(Menu source, Menu target, String mainMenuLabel) { + for (MenuItem sourceItem : source.getItems()) { + int style = sourceItem.getStyle(); + String text = sourceItem.getText(); + String label = stripMnemonic(text).split("\t")[0]; + if ((style & SWT.SEPARATOR) != 0) { + new MenuItem(target, SWT.SEPARATOR); + } else if ((style & SWT.CASCADE) != 0) { + MenuItem cascade = new MenuItem(target, SWT.CASCADE); + cascade.setText(text); + Menu subMenu = new Menu(target); + cascade.setMenu(subMenu); + if (sourceItem.getMenu() != null) { + copyMenu(sourceItem.getMenu(), subMenu, mainMenuLabel); } - - else { - /* If we have a menu seperator! */ - if (label.equals("-")) { - new MenuItem(currentSubMenu, SWT.SEPARATOR); - /* If we have a menu item! */ - } else if (!(label.equals("-"))) { - - /* Don't show unused actions! */ - String labelMenuItem = mItem.getLabel(); - - /* - * if (labelMenuItem.equals("Quit") || labelMenuItem.equals("Update ImageJ...")) - * { - * - * MenuItem it = new MenuItem(currentSubMenu, SWT.NONE); String lab = - * mItem.getLabel(); - * - * it.setText(lab); - * - * it.addSelectionListener(new SelectionListener() { - * - * public void widgetSelected(SelectionEvent e) { - * IJ.showMessage("Disabled for the Eclipse ImageJ plugin!"); - * - * } - * - * public void widgetDefaultSelected(SelectionEvent e) { - * - * } }); - * - * } - */ - /* Exclude the following menu items! */ - if (labelMenuItem.equals("Quit") || labelMenuItem.equals("Update ImageJ...") || labelMenuItem.equals("Show All") || labelMenuItem.startsWith("Main Window [") || labelMenuItem.startsWith("Put Behind [tab]") || labelMenuItem.startsWith("Cascade") - || labelMenuItem.startsWith("Tile")) { - - } - - else if (labelMenuItem.equals("Close All")) { - MenuItem it = new MenuItem(currentSubMenu, SWT.NONE); - String lab = mItem.getLabel(); - - it.setText(lab); - - it.addSelectionListener(new SelectionListener() { - - public void widgetSelected(SelectionEvent e) { - /* Close the tabs! */ - IJTabs.deleteAllTabs(); - - } - - public void widgetDefaultSelected(SelectionEvent e) { - - } - }); - - } - /* - * else if(labelMenuItem.equals("Open...")){ MenuItem it = new - * MenuItem(currentSubMenu, SWT.PUSH); String lab = mItem.getLabel(); if - * (mItem.getShortcut() != null) { //System.out.println(mItem.getShortcut() + - * " : " + mItem.getShortcut().getKey()); - * it.setAccelerator(mItem.getShortcut().getKey()); - * it.setText(lab+"\t"+mItem.getShortcut()); } else{ it.setText(lab); } - * it.addSelectionListener(new SelectionListener() { - * - * - * - * public void widgetSelected(SelectionEvent e) { SwingUtilities.invokeLater(new - * Runnable() { public void run() { - * - * IJ.getInstance().doCommand("Open..."); } }); - * - * } - * - * public void widgetDefaultSelected(SelectionEvent e) { - * - * } }); } - */ - - else { - - MenuItem it = new MenuItem(currentSubMenu, SWT.NONE); - String lab = mItem.getLabel(); - /* Create shortcuts if available! */ - if (mItem.getShortcut() != null) { - // System.out.println(mItem.getShortcut() + " : " + - // mItem.getShortcut().getKey()); - it.setAccelerator(mItem.getShortcut().getKey()); - it.setText(lab + "\t" + mItem.getShortcut()); - } else { - it.setText(lab); - } - - it.addSelectionListener(new SelectionListener() { - - public void widgetSelected(SelectionEvent e) { - String cmd = mItem.getActionCommand(); - IJ.doCommand(cmd); - - } - - public void widgetDefaultSelected(SelectionEvent e) { - - } - }); - } - } - + } else if (isExcluded(label)) { + /* Not useful in Bio7 (the main window is hidden)! */ + } else if (label.equals("Close All") && mainMenuLabel.equals("File")) { + MenuItem it = new MenuItem(target, SWT.PUSH); + it.setText(text); + it.addListener(SWT.Selection, e -> IJTabs.deleteAllTabs()); + } else { + int copyStyle = (style & SWT.CHECK) != 0 ? SWT.CHECK : (style & SWT.RADIO) != 0 ? SWT.RADIO : SWT.PUSH; + MenuItem it = new MenuItem(target, copyStyle); + it.setText(text); + it.setEnabled(sourceItem.getEnabled()); + if (copyStyle != SWT.PUSH) { + it.setSelection(sourceItem.getSelection()); } - + it.addListener(SWT.Selection, e -> forward(sourceItem, it, e)); } - } + } + /* Executes the command of the original ImageJ menu item! */ + private static void forward(MenuItem sourceItem, MenuItem copy, Event e) { + if (sourceItem.isDisposed()) { + return; + } + if ((copy.getStyle() & (SWT.CHECK | SWT.RADIO)) != 0) { + sourceItem.setSelection(copy.getSelection()); + } + Event event = new Event(); + event.stateMask = e.stateMask; + sourceItem.notifyListeners(SWT.Selection, event); } + private static boolean isExcluded(String label) { + return label.equals("Quit") || label.equals("Update ImageJ...") || label.equals("Show All") || label.startsWith("Main Window [") || label.startsWith("Put Behind [tab]") || label.startsWith("Cascade") + || label.startsWith("Tile"); + } } diff --git a/com.eco.bio7.image/src/com/eco/bio7/ImageJPluginActions/ImageJWindowAction.java b/com.eco.bio7.image/src/com/eco/bio7/ImageJPluginActions/ImageJWindowAction.java index a1f3ff370..a7a7bb412 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/ImageJPluginActions/ImageJWindowAction.java +++ b/com.eco.bio7.image/src/com/eco/bio7/ImageJPluginActions/ImageJWindowAction.java @@ -11,10 +11,7 @@ package com.eco.bio7.ImageJPluginActions; -import java.util.UUID; -import java.util.Vector; -import javax.swing.JPanel; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; @@ -23,7 +20,6 @@ import org.eclipse.jface.action.IMenuCreator; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.MenuListener; import org.eclipse.swt.events.SelectionEvent; @@ -31,7 +27,6 @@ import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.ui.IViewReference; @@ -39,15 +34,13 @@ import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.CustomDetachedImageJView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.Util; +import com.eco.bio7.image.ui.Activator; +import com.eco.bio7.image.ui.CanvasView; +import com.eco.bio7.image.ui.CustomDetachedImageJView; +import com.eco.bio7.image.ui.IJTabs; +import com.eco.bio7.image.ui.Util; import ij.ImagePlus; -import ij.WindowManager; -import ij.gui.ImageWindow; public class ImageJWindowAction extends Action implements IMenuCreator { @@ -186,43 +179,11 @@ public void widgetDefaultSelected(SelectionEvent e) { menuItemDetachTab.setText("Open Current Image as View"); menuItemDetachTab.addSelectionListener(new SelectionListener() { - public void widgetSelected(SelectionEvent e) { - CTabFolder ctab = CanvasView.getCanvas_view().tabFolder; - if (ctab.getItemCount() > 0) { - Vector ve = (Vector) ctab.getSelection().getData(); - ImagePlus plu = (ImagePlus) ve.get(0); - - ImageWindow win = (ImageWindow) ve.get(1); - /*In the menu action we also need to set the panel! Not necessary in the - *CanvasView action!*/ - // Wrap to avoid deadlock of awt frame access! - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - WindowManager.setTempCurrentImage(plu); - WindowManager.setCurrentWindow(win); - } - }); - - /* import to set current Panel for the menu action (as if we select a tab)! */ - CanvasView.setCurrent((JPanel) ve.get(2)); - - // JPanel current = (JPanel) ve.get(2); - - CustomDetachedImageJView custom = new CustomDetachedImageJView(); - /* Create ImageJ view with unique ID! */ - //String id = UUID.randomUUID().toString(); - /* Create ImageJ view with unique image ID of the ImagePlus image! */ - String id = Integer.toString(plu.getID()); - // detachedSecViewIDs.add(id); - custom.setPanel(CanvasView.getCurrent(), id, plu.getTitle()); - custom.setData(plu, win); - /* - * Only hide the tab without to close the ImagePlus object! - */ - IJTabs.hideTab(); + ImagePlus plu = IJTabs.getSelectedImagePlus(); + if (plu != null) { + CustomDetachedImageJView.detach(plu, null); } - } public void widgetDefaultSelected(SelectionEvent e) { @@ -234,103 +195,14 @@ public void widgetDefaultSelected(SelectionEvent e) { menuItemDetachAllTab.setText("Open All Images As Views "); menuItemDetachAllTab.addSelectionListener(new SelectionListener() { - public void widgetSelected(SelectionEvent e) { - CTabFolder ctab = CanvasView.getCanvas_view().tabFolder; - int itemCount = ctab.getItemCount(); - if (itemCount > 0) { - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - boolean detWindow = store.getBoolean("ENABLE_DETACHED_VIEW_WINDOWS"); - int xPosDefault = store.getInt("DETACHED_IMAGE_POSITION_X"); - int yPosDefault = store.getInt("DETACHED_IMAGE_POSITION_Y"); - int xWidth = store.getInt("DETACHED_IMAGE_WIDTH"); - int yHeight = store.getInt("DETACHED_IMAGE_HEIGHT"); - int xSpacing = store.getInt("DETACHED_IMAGE_SPACING_X"); - int ySpacing = store.getInt("DETACHED_IMAGE_SPACING_Y"); - int xMaxSpace = store.getInt("DETACHED_IMAGE_SPACING_X_MAX"); - int yMaxSpace = store.getInt("DETACHED_IMAGE_SPACING_Y_MAX"); - - int xPos = xPosDefault; - int yPos = yPosDefault; - String tempId = ""; - for (int i = 0; i < itemCount; i++) { - - IJTabs.setActive(i); - - Vector ve = (Vector) ctab.getSelection().getData(); - ImagePlus plu = (ImagePlus) ve.get(0); - - ImageWindow win = (ImageWindow) ve.get(1); - /*In the menu action we also need to set the panel! Not necessary in the - *CanvasView action!*/ - // Wrap to avoid deadlock of awt frame access! - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - WindowManager.setTempCurrentImage(plu); - WindowManager.setCurrentWindow(win); - } - }); - - /* import to set current Panel for the menu action (as if we select a tab)! */ - CanvasView.setCurrent((JPanel) ve.get(2)); - - // JPanel current = (JPanel) ve.get(2); - - CustomDetachedImageJView custom = new CustomDetachedImageJView(); - /* Create ImageJ view with unique ID! */ - //String id = UUID.randomUUID().toString(); - /* Create ImageJ view with unique image ID of the ImagePlus image! */ - String id = Integer.toString(plu.getID()); - tempId=id;//for the last detached view which nedds to be activated! - // detachedSecViewIDs.add(id); - if (detWindow) { - custom.setPanelFloatingDetached(CanvasView.getCurrent(), id, plu.getTitle(), - new Rectangle(xPos, yPos, xWidth, yHeight)); - custom.setData(plu, win); - if (xMaxSpace > 0) { - if ((xPos + xSpacing) > xMaxSpace) { - xPos = xPosDefault; - yPos = yPos + ySpacing; - } else { - xPos = xPos + xSpacing; - } - } - if (yMaxSpace > 0) { - if ((yPos + ySpacing) > yMaxSpace) { - yPos = yPosDefault; - xPos = xPos + xSpacing; - } else { - yPos = yPos + ySpacing; - } - } - } else { - custom.setPanel(CanvasView.getCurrent(), id, plu.getTitle()); - custom.setData(plu, win); - } - - - /* - * Only hide the tab without to close the ImagePlus object! - */ - IJTabs.hideTab(); - } - /*Import for Windows to activate the detached views for the close event!*/ - IJTabs.setSecondaryViewShellLocAndSize(tempId,null); - //SIJTabs.doSecondaryViewLayout(); - - /*for (int i = 0; i < itemCount; i++) { - IJTabs.setActive(i); - IJTabs.hideTab(); - }*/ - } - + openDetachedView(); } public void widgetDefaultSelected(SelectionEvent e) { } }); - MenuItem[] menuItems = fMenu.getItems(); int defaultMenuEntries = 4; /*If we use the plugin in the Bio7 RCP!*/ @@ -432,102 +304,44 @@ public void showtoolbar() { } + /** + * Opens all images of the ImageJ-Canvas view in detached views. + */ public static void openDetachedView() { - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - public void run() { - CTabFolder ctab = CanvasView.getCanvas_view().tabFolder; - int itemCount = ctab.getItemCount(); - if (itemCount > 0) { - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - boolean detWindow = store.getBoolean("ENABLE_DETACHED_VIEW_WINDOWS"); - int xPosDefault = store.getInt("DETACHED_IMAGE_POSITION_X"); - int yPosDefault = store.getInt("DETACHED_IMAGE_POSITION_Y"); - int xWidth = store.getInt("DETACHED_IMAGE_WIDTH"); - int yHeight = store.getInt("DETACHED_IMAGE_HEIGHT"); - int xSpacing = store.getInt("DETACHED_IMAGE_SPACING_X"); - int ySpacing = store.getInt("DETACHED_IMAGE_SPACING_Y"); - int xMaxSpace = store.getInt("DETACHED_IMAGE_SPACING_X_MAX"); - int yMaxSpace = store.getInt("DETACHED_IMAGE_SPACING_Y_MAX"); - - int xPos = xPosDefault; - int yPos = yPosDefault; - - for (int i = 0; i < itemCount; i++) { - - IJTabs.setActive(i); - - Vector ve = (Vector) ctab.getSelection().getData(); - ImagePlus plu = (ImagePlus) ve.get(0); - - ImageWindow win = (ImageWindow) ve.get(1); - /*In the menu action we also need to set the panel! Not necessary in the - *CanvasView action!*/ - // Wrap to avoid deadlock of awt frame access! - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - WindowManager.setTempCurrentImage(plu); - WindowManager.setCurrentWindow(win); - } - }); - - /* import to set current Panel for the menu action (as if we select a tab)! */ - CanvasView.setCurrent((JPanel) ve.get(2)); - - // JPanel current = (JPanel) ve.get(2); - - CustomDetachedImageJView custom = new CustomDetachedImageJView(); - /* Create ImageJ view with unique ID! */ - //String id = UUID.randomUUID().toString(); - /* Create ImageJ view with unique image ID of the ImagePlus image! */ - String id = Integer.toString(plu.getID()); - // detachedSecViewIDs.add(id); - if (detWindow) { - custom.setPanelFloatingDetached(CanvasView.getCurrent(), id, plu.getTitle(), - new Rectangle(xPos, yPos, xWidth, yHeight)); - custom.setData(plu, win); - if (xMaxSpace > 0) { - if ((xPos + xSpacing) > xMaxSpace) { - xPos = xPosDefault; - yPos = yPos + ySpacing; - } else { - xPos = xPos + xSpacing; - } - } - if (yMaxSpace > 0) { - if ((yPos + ySpacing) > yMaxSpace) { - yPos = yPosDefault; - xPos = xPos + xSpacing; - } else { - yPos = yPos + ySpacing; - } - } - } else { - custom.setPanel(CanvasView.getCurrent(), id, plu.getTitle()); - custom.setData(plu, win); - } - - /* - * Only hide the tab without to close the ImagePlus object! - */ - IJTabs.hideTab(); + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + boolean detWindow = store.getBoolean("ENABLE_DETACHED_VIEW_WINDOWS"); + int xPosDefault = store.getInt("DETACHED_IMAGE_POSITION_X"); + int yPosDefault = store.getInt("DETACHED_IMAGE_POSITION_Y"); + int xWidth = store.getInt("DETACHED_IMAGE_WIDTH"); + int yHeight = store.getInt("DETACHED_IMAGE_HEIGHT"); + int xSpacing = store.getInt("DETACHED_IMAGE_SPACING_X"); + int ySpacing = store.getInt("DETACHED_IMAGE_SPACING_Y"); + int xMaxSpace = store.getInt("DETACHED_IMAGE_SPACING_X_MAX"); + int yMaxSpace = store.getInt("DETACHED_IMAGE_SPACING_Y_MAX"); + int xPos = xPosDefault; + int yPos = yPosDefault; + for (ImagePlus plu : IJTabs.getImagePlusList()) { + if (detWindow) { + CustomDetachedImageJView.detach(plu, new Rectangle(xPos, yPos, xWidth, yHeight)); + if (xMaxSpace > 0) { + if ((xPos + xSpacing) > xMaxSpace) { + xPos = xPosDefault; + yPos = yPos + ySpacing; + } else { + xPos = xPos + xSpacing; } - //SIJTabs.doSecondaryViewLayout(); - - /*for (int i = 0; i < itemCount; i++) { - IJTabs.setActive(i); - IJTabs.hideTab(); - }*/ } - - - /* - * Only hide the tab without to close the ImagePlus object! - */ - + if (yMaxSpace > 0) { + if ((yPos + ySpacing) > yMaxSpace) { + yPos = yPosDefault; + xPos = xPos + xSpacing; + } else { + yPos = yPos + ySpacing; + } + } + } else { + CustomDetachedImageJView.detach(plu, null); } - }); - - + } } } \ No newline at end of file diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/Bio7DarkThemeAdditions.java b/com.eco.bio7.image/src/com/eco/bio7/image/Bio7DarkThemeAdditions.java deleted file mode 100644 index ac8397124..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/Bio7DarkThemeAdditions.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.eco.bio7.image; - -import java.awt.Color; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map.Entry; -import java.util.Set; - -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.border.CompoundBorder; -import javax.swing.border.EmptyBorder; -import javax.swing.border.LineBorder; -import javax.swing.plaf.ColorUIResource; - -import org.eclipse.swt.widgets.Composite; - -public class Bio7DarkThemeAdditions { - public static boolean isSet=false; - - public static boolean isSet() { - return isSet; - } - /*Do not load twice in the ImageJ plugin if Bio7 already loaded the LAF extension!*/ - public static void setSet(boolean isSet) { - Bio7DarkThemeAdditions.isSet = isSet; - } - - public void applyMacBlackThemeAdditions(Color colBackgr,Color colForegr) { - - - - //UIManager.getLookAndFeelDefaults().put("Button.border", "Raised"); - UIManager.put("Button.border", new CompoundBorder(new LineBorder(new Color(0, 0, 0)), new EmptyBorder(2, 2, 2, 2))); - - List colorKeys = new ArrayList(); - Set> entries = UIManager.getLookAndFeelDefaults().entrySet(); - for (Entry entry : entries) { - if (entry.getValue() instanceof Color) { - String key = ((String) entry.getKey()); - if (key.endsWith("background") || key.endsWith("Background")) { - UIManager.getLookAndFeelDefaults().put(key, Arrays.asList(new Object[] { new ColorUIResource(colBackgr), new ColorUIResource(colBackgr), new ColorUIResource(colBackgr) })); - } else if (key.endsWith("foreground") || key.endsWith("Foreground") || key.endsWith("gridColor") || key.endsWith("tickColor")) { - UIManager.getLookAndFeelDefaults().put(key, Arrays.asList(new Object[] { new ColorUIResource(colForegr), new ColorUIResource(colForegr), new ColorUIResource(colForegr) })); - } - } - } - UIManager.getLookAndFeelDefaults().put("ScrollBar.thumb", Arrays.asList(new Object[] { new ColorUIResource(colForegr), new ColorUIResource(colForegr), new ColorUIResource(colForegr) })); - - UIManager.getLookAndFeelDefaults().put("List.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("List.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("List.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("List.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextPane.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextPane.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextArea.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextArea.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextArea.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextArea.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextPane.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextPane.inactiveForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("EditorPane.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("EditorPane.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("EditorPane.inactiveForeground", colForegr); - UIManager.getLookAndFeelDefaults().put("Button.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("Button.foreground", colForegr); - UIManager.getLookAndFeelDefaults().put("Panel.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("Panel.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextArea.inactiveBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextArea.inactiveForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.inactiveBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.inactiveForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextArea.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextArea.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextComponent.selectionBackgroundInactive", colBackgr); - UIManager.getLookAndFeelDefaults().put("ComboBox.buttonBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("ComboBox.buttonHighlight", colBackgr); - - - } - - public void applyWinBlackThemeAdditions(Color colBackgr,Color colForegr) { - - - - - - UIManager.getLookAndFeelDefaults().put("ScrollBar.thumb", Arrays.asList(new Object[] { new ColorUIResource(colForegr), new ColorUIResource(colForegr), new ColorUIResource(colForegr) })); - - - UIManager.getLookAndFeelDefaults().put("List.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("List.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("List.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("List.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextPane.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextPane.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextPane.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextPane.inactiveForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("EditorPane.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("EditorPane.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("EditorPane.inactiveForeground", colForegr); - - - - } - - public void applyLinuxBlackThemeAdditions(Color colBackgr,Color colForegr) { - - UIManager.getLookAndFeelDefaults().put("Panel.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("Panel.foreground", colForegr); - UIManager.getLookAndFeelDefaults().put("Button.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("Button.foreground", colForegr); - UIManager.getLookAndFeelDefaults().put("Button.border", "Raised"); - - List colorKeys = new ArrayList(); - Set> entries = UIManager.getLookAndFeelDefaults().entrySet(); - for (Entry entry : entries) { - if (entry.getValue() instanceof Color) { - String key = ((String) entry.getKey()); - if (key.endsWith("background") || key.endsWith("Background")) { - UIManager.getLookAndFeelDefaults().put(key, Arrays.asList(new Object[] { new ColorUIResource(colBackgr), new ColorUIResource(colBackgr), new ColorUIResource(colBackgr) })); - } else if (key.endsWith("foreground") || key.endsWith("Foreground") || key.endsWith("gridColor") || key.endsWith("tickColor")) { - UIManager.getLookAndFeelDefaults().put(key, Arrays.asList(new Object[] { new ColorUIResource(colForegr), new ColorUIResource(colForegr), new ColorUIResource(colForegr) })); - } - } - } - UIManager.getLookAndFeelDefaults().put("ScrollBar.thumb", Arrays.asList(new Object[] { new ColorUIResource(colForegr), new ColorUIResource(colForegr), new ColorUIResource(colForegr) })); - - UIManager.getLookAndFeelDefaults().put("List.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("List.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("List.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("List.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextPane.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextPane.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextArea.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextArea.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextArea.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextArea.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextPane.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextPane.inactiveForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("EditorPane.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("EditorPane.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("EditorPane.inactiveForeground", colForegr); - UIManager.getLookAndFeelDefaults().put("Button.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("Button.foreground", colForegr); - UIManager.getLookAndFeelDefaults().put("Panel.background", colBackgr); - UIManager.getLookAndFeelDefaults().put("Panel.foreground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextArea.inactiveBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextArea.inactiveForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.inactiveBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.inactiveForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextField.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextField.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextArea.selectionBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("TextArea.selectionForeground", colForegr); - - UIManager.getLookAndFeelDefaults().put("TextComponent.selectionBackgroundInactive", colBackgr); - UIManager.getLookAndFeelDefaults().put("ComboBox.buttonBackground", colBackgr); - UIManager.getLookAndFeelDefaults().put("ComboBox.buttonHighlight", colBackgr); - - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/CanvasView.java b/com.eco.bio7.image/src/com/eco/bio7/image/CanvasView.java deleted file mode 100644 index de484270d..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/CanvasView.java +++ /dev/null @@ -1,976 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2004-2018 M. Austenfeld - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * M. Austenfeld - *******************************************************************************/ - -package com.eco.bio7.image; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.Frame; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.WindowEvent; -import java.io.File; -import java.util.Arrays; -import java.util.UUID; -import java.util.Vector; - -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; -import javax.swing.plaf.ColorUIResource; -import javax.swing.plaf.FontUIResource; -import javax.swing.plaf.metal.MetalLookAndFeel; -import javax.swing.plaf.metal.MetalTheme; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.IJobChangeEvent; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.core.runtime.jobs.JobChangeAdapter; -import org.eclipse.core.runtime.preferences.InstanceScope; -import org.eclipse.jface.action.IStatusLineManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.StatusLineManager; -import org.eclipse.jface.action.SubContributionManager; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.CLabel; -import org.eclipse.swt.custom.CTabFolder; -import org.eclipse.swt.custom.CTabFolder2Listener; -import org.eclipse.swt.custom.CTabFolderEvent; -import org.eclipse.swt.custom.CTabItem; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.DropTarget; -import org.eclipse.swt.dnd.DropTargetAdapter; -import org.eclipse.swt.dnd.DropTargetEvent; -import org.eclipse.swt.dnd.FileTransfer; -import org.eclipse.swt.dnd.Transfer; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.KeyAdapter; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.FontData; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IPartListener; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.part.ViewPart; -import org.eclipse.ui.preferences.ScopedPreferenceStore; -import com.eco.bio7.ImageJPluginActions.ImageJAnalyzeAction; -import com.eco.bio7.ImageJPluginActions.ImageJEditAction; -import com.eco.bio7.ImageJPluginActions.ImageJExtensionAction; -import com.eco.bio7.ImageJPluginActions.ImageJFileAction; -import com.eco.bio7.ImageJPluginActions.ImageJHelp; -import com.eco.bio7.ImageJPluginActions.ImageJImageAction; -import com.eco.bio7.ImageJPluginActions.ImageJPluginsAction; -import com.eco.bio7.ImageJPluginActions.ImageJProcessAction; -import com.eco.bio7.ImageJPluginActions.ImageJWindowAction; -import ij.IJ; -import ij.ImageJ; -import ij.ImagePlus; -import ij.Macro; -import ij.Menus; -import ij.WindowManager; -import ij.gui.GenericDialog; -import ij.gui.ImageWindow; -import ij.gui.Plot; -import ij.gui.PlotCanvas; -import ij.gui.PlotWindow; -import ij.io.DirectoryChooser; -import ij.io.OpenDialog; -import ij.io.Opener; -import ij.plugin.CommandLister; -import ij.plugin.DragAndDrop; -import ij.plugin.FileInfoVirtualStack; -import ij.plugin.FolderOpener; -import ij.plugin.TextReader; -import ij.plugin.frame.Recorder; -import ij.process.ImageProcessor; -import com.eco.bio7.image.swtawtutil.*; - -public class CanvasView extends ViewPart { - public static int insertMark = -1; - - public static final String ID = "com.eco.bio7.imagej"; - - public static Composite parent2; - - private static JPanel current; - - private ImageJFileAction file; - - private ImageJEditAction edit; - - private ImageJImageAction image; - - private ImageJProcessAction process; - - private ImageJAnalyzeAction analyze; - - private ImageJPluginsAction plugins; - - private ImageJWindowAction window; - - protected String[] fileList; - - protected ImagePlus plu; - - protected ImageWindow win; - - private ImageJHelp help; - - private String osname; - - private boolean isWin; - - private boolean isMac; - - private boolean isLinux; - - private static CanvasView canvas_view; - - public static CTabFolder tabFolder; - - // private ArrayList detachedSecViewIDs = new ArrayList(); - - public CanvasView() { - super(); - canvas_view = this; - - this.getViewSite(); - - } - - public void updatePlotCanvas() { - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the plot layout! */ - parent2.layout(); - - } - }); - current.doLayout(); - } - - public void recalculateLayout() { - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - public void run() { - /* - * Call parent layout before the plot layout! Here we add a workaround to layout - * the parent on high dpi displays and the SWT_AWT bridge by resizing the parent - * forth and back which seem to retrigger a layout Without HighDPI it also - * retriggers the layout!! - **/ - int x = parent2.getSize().x; - int y = parent2.getSize().y; - parent2.setSize(x - 1, y - 1); - parent2.setSize(x, y); - - /* - * For the following see: - * https://www.eclipse.org/eclipse/news/4.6/platform_isv.php#swt-requestlayout - */ - // parent2.requestLayout(); - - } - }); - } - - public void layoutParent(Composite parent) { - // Wrap to avoid deadlock of awt frame access! - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the plot layout! */ - /* - * The layout of tab items plots will be changed in the tab selection listener - * (see tab listener below)! This is by the way not so expansive as to relayout - * all PlotWindows. Only the visible tab item PlotWindows will be relayouted! - */ - parent.layout(); - - } - }); - } - - void resizePlotWindow(Composite parent, ImageWindow win) { - if (parent.isDisposed() == false) { - - if (win != null) { - - // plotWindowResize(win,current); - - int ids[] = WindowManager.getIDList(); - if (ids != null) { - for (int i = 0; i < ids.length; i++) { - ImagePlus ip = WindowManager.getImage(ids[i]); - // JPanel panel=(JPanel)win.getCanvas().getParent(); - if (ip.getWindow() instanceof PlotWindow) { - JPanel panel = (JPanel) ip.getCanvas().getParent(); - plotWindowResize(ip.getWindow(), panel); - - } - - } - } - /* - * IWorkbenchPage page = - * PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - * IViewReference[] ref = page.getViewReferences(); for (int i = 0; i < - * ref.length; i++) { String secondaryId = ref[i].getSecondaryId(); if - * (secondaryId != null) { IViewPart part=ref[i].getView(false); - * CustomDetachedImageJView customView=(CustomDetachedImageJView) part; - * if(customView.isDetached()==false) { if(customView.plus!=null) { JPanel - * panel=(JPanel)WindowManager.getImage(secondaryId).getCanvas().getParent(); - * System.out.println(WindowManager.getImage(secondaryId).getTitle()); - * plotWindowResize(win,panel); } - * - * } - * - * } } - */ - // Rectangle rec = parent.getClientArea(); - - } - } - } - - private void plotWindowResize(ImageWindow win, JPanel panel) { - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - - if (win instanceof PlotWindow) { - PlotWindow plo = (PlotWindow) win; - - if (plo != null) { - Dimension rec = panel.getSize(); - Plot plot = plo.getPlot(); - if (plot != null) { - int correctionX = plot.leftMargin + plot.rightMargin; - int correctionY = plot.topMargin + plot.bottomMargin; - plot.getImagePlus().getCanvas().setSize(rec.width + correctionX, rec.height + correctionY); - plot.setFrameSize(rec.width, rec.height); - plot.setSize(rec.width - correctionX, rec.height - correctionY); - panel.doLayout(); - } - } - } - - // plo.setLocationAndSize(rec.x, rec.y, rec.width, rec.height); - } - }); - } - - public void createPartControl(Composite parent) { - - osname = System.getProperty("os.name"); - isWin = osname.startsWith("Windows"); - isMac = !isWin && osname.startsWith("Mac"); - isLinux = osname.startsWith("Linux"); - /* - * A a dialog listener for modal dialogs. Works only for Windows. On Mac dialogs - * are modal in maximized mode! On Linux modal dialogs are not available by - * default! - */ - if (isWin) { - new AwtDialogListener(Util.getDisplay()); - } - setComponentFont(parent.getDisplay()); - if (isWin) { - - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - if (Util.isThemeBlack()) { - if (Bio7DarkThemeAdditions.isSet() == false) { - Color colBackgr = Util.getSWTBackgroundToAWT(parent); - Color colForegr = Util.getSWTForegroundToAWT(parent); - new Bio7DarkThemeAdditions().applyWinBlackThemeAdditions(colBackgr, colForegr); - } - } - } catch (ClassNotFoundException e) { - - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - - e.printStackTrace(); - } catch (UnsupportedLookAndFeelException e) { - e.printStackTrace(); - } - } else if (isMac) { - - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - if (Util.isThemeBlack()) { - if (Bio7DarkThemeAdditions.isSet() == false) { - Color colBackgr = Util.getSWTBackgroundToAWT(parent); - Color colForegr = Util.getSWTForegroundToAWT(parent); - new Bio7DarkThemeAdditions().applyMacBlackThemeAdditions(colBackgr, colForegr); - } - } - } catch (ClassNotFoundException e) { - - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - - e.printStackTrace(); - } catch (UnsupportedLookAndFeelException e) { - e.printStackTrace(); - } - - } - /* If Linux is the OS! */ - else if (isLinux) { - if (Bio7LinuxTheme.isSet() == false) { - MetalTheme theme = new Bio7LinuxTheme(); - - MetalLookAndFeel.setCurrentTheme(theme); - - try { - UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); //$NON-NLS-1$ - UIManager.getLookAndFeelDefaults().put("Panel.background", Util.getSWTBackgroundToAWT(parent)); - UIManager.getLookAndFeelDefaults().put("Panel.foreground", Util.getSWTForegroundToAWT(parent)); - - if (Util.isThemeBlack()) { - if (Bio7DarkThemeAdditions.isSet() == false) { - Color colBackgr = Util.getSWTBackgroundToAWT(parent); - Color colForegr = Util.getSWTForegroundToAWT(parent); - new Bio7DarkThemeAdditions().applyLinuxBlackThemeAdditions(colBackgr, colForegr); - } - } - // SwingUtilities.updateComponentTreeUI(this); - } catch (Exception e) { - System.out.println(e); - } - } - } - - parent.addDisposeListener(new DisposeListener() { - - @Override - public void widgetDisposed(DisposeEvent e) { - - /* Save the ImageJ preferences when the view is closed! */ - try { - ij.Prefs.savePreferences(); - } catch (RuntimeException ex) { - - ex.printStackTrace(); - } - - } - }); - - // AwtEnvironment awt = new AwtEnvironment(parent.getDisplay()); - - PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "com.eco.bio7.imagej"); - - parent.addControlListener(new ControlAdapter() { - @Override - public synchronized void controlResized(final ControlEvent e) { - /* - * Here we write the values in the com.eco.bio7 plugin preferences with the help - * of scoped preferences! - */ - Rectangle rec = parent.getClientArea(); - - IPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, "com.eco.bio7"); - if (store != null) { - String selection = store.getString("PLOT_DEVICE_SELECTION"); - String pathTo = store.getString("pathTempR"); - int correction = 0; - if (tabFolder.isDisposed() == false && tabFolder != null) { - /* Height correction for the plot! */ - correction = CanvasView.tabFolder.getTabHeight() + 40; - } - - if (selection.equals("PLOT_IMAGEJ_DISPLAYSIZE_CAIRO")) { - - store.setValue("DEVICE_DEFINITION", ".bio7Device <- function(filename = \"" + pathTo + "tempDevicePlot%05d.tiff" + "\") { tiff(filename,width = " + (rec.width - 20) - + ", height = " + (rec.height - correction) + ", type=\"cairo\")}; options(device=\".bio7Device\")"); - } else if (selection.equals("PLOT_IMAGEJ_DISPLAYSIZE")) { - store.setValue("DEVICE_DEFINITION", ".bio7Device <- function(filename = \"" + pathTo + "tempDevicePlot%05d.tiff" + "\") { tiff(filename,width = " + (rec.width - 20) - + ", height = " + (rec.height - correction) + ", units = \"px\")}; options(device=\".bio7Device\")"); - - } - } - /* Here we resize the ImageJ plot window! */ - // ImageWindow currentPlotWindow = WindowManager.getCurrentWindow(); - if (win != null) { - // if (win instanceof PlotWindow) { - /* Avoid the resizing of the CanvasView if a detached view is resized! */ - layoutParent(parent); - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - resizePlotWindow(parent, win); - } - }); - - // } - } - } - - }); - - getViewSite().getPage().addPartListener(new IPartListener() { - public void partActivated(IWorkbenchPart part) { - /* - * Focus necessary to made the key shortcuts work without an opened image. - * Wrapped in invokeLater to not deadlock when drag and drop many images on the - * GUI. syncExec to access the tabFolder! - */ - if (part instanceof CanvasView) { - if (Util.getOS().equals("Mac")) { - - // Wrap to avoid deadlock of awt frame access! - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - if (win != null) { - Frame frameSwtAwt = win.getSwtAwtMain().getFrame(); - if (frameSwtAwt != null) { - - if (frameSwtAwt != null) - // frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, - // WindowEvent.WINDOW_ACTIVATED)); - frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, WindowEvent.WINDOW_ACTIVATED)); - - } - } - } - }); - if (CanvasView.tabFolder != null && CanvasView.tabFolder.isDisposed() == false) { - CanvasView.tabFolder.setVisible(false); - - CanvasView.tabFolder.setVisible(true); - } - } - - /* - * CTabItem ciTemp = new CTabItem(CanvasView.tabFolder, SWT.CLOSE, - * CanvasView.insertMark + 1); // CanvasView.tabFolder.showItem(ci); CTabItem - * selItem = CanvasView.tabFolder.getSelection(); - * CanvasView.tabFolder.setSelection(ciTemp); - * - * ciTemp.dispose(); if (selItem != null) { - * CanvasView.tabFolder.showItem(selItem); - * CanvasView.tabFolder.setSelection(selItem); } - */ - - } - } - - public void partBroughtToTop(IWorkbenchPart part) { - - } - - public void partClosed(IWorkbenchPart part) { - - if (part instanceof CanvasView) { - - CTabItem[] items = tabFolder.getItems(); - - for (int i = 0; i < items.length; i++) { - Vector ve = (Vector) items[i].getData(); - if (ve.size() > 0) { - final ImageWindow win = (ImageWindow) ve.get(1); - /* - * Execute on the event dispatching thread! Important for WorldWind which uses - * ImageJ! (else deadlock situation occurs!!!) - */ - SwingUtilities.invokeLater(new Runnable() { - public void run() { - win.bio7TabClose(true); - } - }); - - } - - } - canvas_view = null; - } - } - - public void partDeactivated(IWorkbenchPart part) { - if (part instanceof CanvasView) { - - } - } - - public void partOpened(IWorkbenchPart part) { - if (part instanceof CanvasView) { - - } - } - }); - // Display display = Display.getDefault(); - this.parent2 = parent; - - new ImageJ(); - - file = new ImageJFileAction(); - edit = new ImageJEditAction(); - image = new ImageJImageAction(); - process = new ImageJProcessAction(); - analyze = new ImageJAnalyzeAction(); - plugins = new ImageJPluginsAction(); - window = new ImageJWindowAction(); - help = new ImageJHelp(); - - initializeToolBar(); - tabFolder = new CTabFolder(parent, SWT.TOP); - /* Get access to the ImageJ drag and drop methods! */ - DragAndDrop dragAndDrop = new DragAndDrop(); - DropTarget dt = new DropTarget(tabFolder, DND.DROP_DEFAULT | DND.DROP_MOVE); - dt.setTransfer(new Transfer[] { FileTransfer.getInstance() }); - dt.addDropListener(new DropTargetAdapter() { - public void drop(DropTargetEvent event) { - - FileTransfer ft = FileTransfer.getInstance(); - if (ft.isSupportedType(event.currentDataType)) { - fileList = (String[]) event.data; - Job job = new Job("Open...") { - @Override - protected IStatus run(IProgressMonitor monitor) { - monitor.beginTask("Opening...", fileList.length); - for (int i = 0; i < fileList.length; i++) { - - final int x = i; - - if (Util.getOS().equals("Mac") == false) { - dragAndDrop.openFile(new File(fileList[x].toString())); - recalculateLayout(); - } else { - - dragAndDrop.openFile(new File(fileList[x].toString())); - - } - - monitor.worked(1); - - } - monitor.done(); - return Status.OK_STATUS; - } - - }; - job.addJobChangeListener(new JobChangeAdapter() { - public void done(IJobChangeEvent event) { - if (event.getResult().isOK()) { - - } else { - - } - } - }); - // job.setUser(true); - job.schedule(); - - } - } - }); - - CommandLister hotkeys = new CommandLister(); - String[] shortcuts = hotkeys.getShortcuts(); - for (int i = 0; i < shortcuts.length; i++) { - if (shortcuts[i].contains("\t^")) { - shortcuts[i] += " (macro)"; - } - - } - - tabFolder.addKeyListener(new KeyAdapter() { - public void keyPressed(KeyEvent e) { - - for (int i = 0; i < shortcuts.length; i++) { - - String[] splitShortcut = shortcuts[i].split("\t"); - splitShortcut[0] = splitShortcut[0].trim(); - if (splitShortcut[0].equals("" + e.character)) { - IJ.doCommand(splitShortcut[1]); - } - /* Also allow the F keys for a shortcut! */ - if (splitShortcut[0].equals("F1") && e.keyCode == SWT.F1) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F2") && e.keyCode == SWT.F2) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F3") && e.keyCode == SWT.F3) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F4") && e.keyCode == SWT.F4) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F5") && e.keyCode == SWT.F5) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F6") && e.keyCode == SWT.F6) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F7") && e.keyCode == SWT.F7) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F8") && e.keyCode == SWT.F8) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F9") && e.keyCode == SWT.F9) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F10") && e.keyCode == SWT.F10) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F11") && e.keyCode == SWT.F11) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F12") && e.keyCode == SWT.F12) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F13") && e.keyCode == SWT.F13) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F14") && e.keyCode == SWT.F14) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F15") && e.keyCode == SWT.F15) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F16") && e.keyCode == SWT.F16) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F17") && e.keyCode == SWT.F17) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F18") && e.keyCode == SWT.F18) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F19") && e.keyCode == SWT.F19) { - IJ.doCommand(splitShortcut[1]); - } else if (splitShortcut[0].equals("F20") && e.keyCode == SWT.F20) { - IJ.doCommand(splitShortcut[1]); - } - - } - - } - }); - - tabFolder.setBorderVisible(true); - // tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH)); - tabFolder.setSimple(false); - - // tabFolder.setSelectionBackground(new Color[] { - // display.getSystemColor(SWT.COLOR_DARK_GREEN), - // display.getSystemColor(SWT.COLOR_DARK_GREEN) }, new int[] { 90 }, - // true); - // tabFolder.setSelectionForeground(display.getSystemColor(SWT.COLOR_WHITE)); - - tabFolder.addCTabFolder2Listener(new CTabFolder2Listener() { - - public void close(final CTabFolderEvent event) { - - Vector ve = (Vector) event.item.getData(); - ImagePlus plu = (ImagePlus) ve.get(0); - - final ImageWindow win = (ImageWindow) ve.get(1); - - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - win.bio7TabClose(true); - } - }); - - } - - public void maximize(CTabFolderEvent event) { - - } - - public void minimize(CTabFolderEvent event) { - - } - - public void restore(CTabFolderEvent event) { - - } - - public void showList(CTabFolderEvent event) { - - } - - }); - tabFolder.addSelectionListener(new SelectionListener() { - public void itemClosed(CTabFolderEvent event) { - - } - - public void widgetDefaultSelected(SelectionEvent e) { - - } - - public void widgetSelected(SelectionEvent e) { - Vector> ve = (Vector>) e.item.getData(); - plu = (ImagePlus) ve.get(0); - - win = (ImageWindow) ve.get(1); - // Wrap to avoid deadlock of awt frame access! - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - WindowManager.setTempCurrentImage(plu); - WindowManager.setCurrentWindow(win); - } - }); - - /* import to set current Panel! */ - current = (JPanel) ve.get(2); - // current.requestFocus(); - /* - * Here we resize a PlotWindow in thhe tabFolder when a tabItem has been - * selected the item plot windows have the same size! - */ - if (win instanceof PlotWindow) { - - layoutParent(parent); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - resizePlotWindow(parent, win); - } - }); - } - - } - - }); - tabFolder.addMouseListener(new MouseAdapter() { - - public void mouseDown(MouseEvent mouseevent) - - { - - /* - * Important to select the correct image and window when creating the new ImageJ - * view!The listener for the right-click on the tabitem will care about that! - */ - if (mouseevent.count == 1) { - - CTabFolder ctab = (CTabFolder) mouseevent.widget; - - if (ctab.getItemCount() <= 0) { - - CanvasView.tabFolder.setFocus(); - - } - - else if (ctab.getItemCount() > 0) { - Vector ve = (Vector) ctab.getSelection().getData(); - plu = (ImagePlus) ve.get(0); - - win = (ImageWindow) ve.get(1); - - // Wrap to avoid deadlock of awt frame access! - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - WindowManager.setTempCurrentImage(plu); - WindowManager.setCurrentWindow(win); - } - }); - - // important to set current Panel! - current = (JPanel) ve.get(2); // current.requestFocus(); - plu.getCanvas().repaint(); - /* To show the status message! */ - win.repaint(); - - } - - } else if (mouseevent.count == 2 && mouseevent.button == 1) { - - // IJ.getInstance().doCommand("Rename..."); - } else if (mouseevent.button == 3 && mouseevent.count > 1) { - CTabFolder ctab = (CTabFolder) mouseevent.widget; - if (ctab.getItemCount() > 0) { - Vector ve = (Vector) ctab.getSelection().getData(); - ImagePlus plu = (ImagePlus) ve.get(0); - - ImageWindow win = (ImageWindow) ve.get(1); - // JPanel current = (JPanel) ve.get(2); - - CustomDetachedImageJView custom = new CustomDetachedImageJView(); - /* Create ImageJ view with unique ID! */ - // String id = UUID.randomUUID().toString(); - /* Create ImageJ view with unique image ID of the ImagePlus image! */ - String id = Integer.toString(plu.getID()); - // System.out.println(id); - // detachedSecViewIDs.add(id); - custom.setPanel(current, id, plu.getTitle()); - custom.setData(plu, win); - /* - * Only hide the tab without to close the ImagePlus object! - */ - IJTabs.hideTab(); - } - - } - } - - }); - - } - - public void setstatusline(String message) { - IActionBars bars = getViewSite().getActionBars(); - bars.getStatusLineManager().setMessage(message); - - } - - public void setStatusLineColor(String message, org.eclipse.swt.graphics.Color col) { - IActionBars bars = getViewSite().getActionBars(); - bars.getStatusLineManager().setMessage(message); - IStatusLineManager statusLineManager = bars.getStatusLineManager(); - if (statusLineManager instanceof SubContributionManager) { - SubContributionManager sub = (SubContributionManager) statusLineManager; - StatusLineManager parent = (StatusLineManager) sub.getParent(); - Composite composite = (Composite) parent.getControl(); - Control[] controls = composite.getChildren(); - - for (Control control : controls) { - if (control instanceof CLabel) { - CLabel cLabel = (CLabel) control; - - // cLabel.setFont(null); - cLabel.setForeground(col); - break; - - } - } - } - } - - private void initializeToolBar() { - IToolBarManager tbm = getViewSite().getActionBars().getToolBarManager(); - - tbm.add(file); - tbm.add(edit); - tbm.add(image); - tbm.add(process); - tbm.add(analyze); - tbm.add(plugins); - tbm.add(window); - tbm.add(help); - // tbm.add(new PlaceholderLabel().getPlaceholderLabel()); - /* If we have a plugin which installs a main menu item! */ - Menus.updateBio7ImageJMenu(); - } - - public void setFocus() { - - } - - public void dispose() { - //IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - - } - - public static CanvasView getCanvas_view() { - return canvas_view; - } - - public static JPanel getCurrent() { - return current; - } - - public static void setCurrent(JPanel current) { - CanvasView.current = current; - } - - public static Composite getParent2() { - return parent2; - } - - /* - * public ArrayList getDetachedSecViewIDs() { return detachedSecViewIDs; - * } - */ - private void setComponentFont(Display dis) { - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - boolean antialiasedFonts = false; - antialiasedFonts = store.getBoolean("FONT_ANTIALIASED"); - if (antialiasedFonts) { - System.setProperty("awt.useSystemAAFontSettings", "on"); - System.setProperty("swing.aatext", "true"); - } - - assert EventQueue.isDispatchThread(); // On AWT event thread - - FontData fontData = dis.getSystemFont().getFontData()[0]; - - int resolution = Toolkit.getDefaultToolkit().getScreenResolution(); - - int awtFontSize = (int) Math.round((double) fontData.getHeight() * dis.getDPI().y / 72.0); - java.awt.Font awtFont = null; - - int fontSizeCorrection = 0; - fontSizeCorrection = store.getInt("FONT_SIZE_CORRECTION"); - /* Font size correction! */ - - awtFont = new java.awt.Font(fontData.getName(), fontData.getStyle(), awtFontSize + fontSizeCorrection); - - // Update the look and feel defaults to use new font. - updateLookAndFeel(awtFont); - - } - - private void updateLookAndFeel(java.awt.Font awtFont) { - assert awtFont != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - FontUIResource fontResource = new FontUIResource(awtFont); - - UIManager.put("Button.font", fontResource); //$NON-NLS-1$ - UIManager.put("CheckBox.font", fontResource); //$NON-NLS-1$ - UIManager.put("ComboBox.font", fontResource); //$NON-NLS-1$ - UIManager.put("EditorPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("Label.font", fontResource); //$NON-NLS-1$ - UIManager.put("List.font", fontResource); //$NON-NLS-1$ - UIManager.put("Panel.font", fontResource); //$NON-NLS-1$ - UIManager.put("ProgressBar.font", fontResource); //$NON-NLS-1$ - UIManager.put("RadioButton.font", fontResource); //$NON-NLS-1$ - UIManager.put("ScrollPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("TabbedPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("Table.font", fontResource); //$NON-NLS-1$ - UIManager.put("TableHeader.font", fontResource); //$NON-NLS-1$ - UIManager.put("TextField.font", fontResource); //$NON-NLS-1$ - UIManager.put("TextPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("TitledBorder.font", fontResource); //$NON-NLS-1$ - UIManager.put("ToggleButton.font", fontResource); //$NON-NLS-1$ - UIManager.put("TreeFont.font", fontResource); //$NON-NLS-1$ - UIManager.put("ViewportFont.font", fontResource); //$NON-NLS-1$ - UIManager.put("MenuItem.font", fontResource); //$NON-NLS-1$ - UIManager.put("CheckboxMenuItem.font", fontResource); //$NON-NLS-1$ - UIManager.put("PopupMenu.font", fontResource); // $NON-NLS-1 - - java.util.Enumeration keys = UIManager.getDefaults().keys(); - while (keys.hasMoreElements()) { - Object key = keys.nextElement(); - Object value = UIManager.get(key); - if (value instanceof javax.swing.plaf.FontUIResource) - UIManager.put(key, fontResource); - } - - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/CustomDetachedImageJView.java b/com.eco.bio7.image/src/com/eco/bio7/image/CustomDetachedImageJView.java deleted file mode 100644 index 3dcd417ae..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/CustomDetachedImageJView.java +++ /dev/null @@ -1,541 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007-2025 M. Austenfeld - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * M. Austenfeld - *******************************************************************************/ -package com.eco.bio7.image; - -import java.awt.Dimension; -import java.awt.Frame; -import java.awt.Panel; -import java.awt.event.ActionEvent; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.WindowEvent; -import java.util.Vector; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.core.runtime.preferences.InstanceScope; -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; -import org.eclipse.e4.ui.workbench.modeling.EModelService; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IPartListener2; -import org.eclipse.ui.ISaveablePart2; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchPartReference; -import org.eclipse.ui.IWorkbenchPartSite; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.part.ViewPart; -import org.eclipse.ui.preferences.ScopedPreferenceStore; -import ij.ImageJ; -import ij.ImagePlus; -import ij.WindowManager; -import ij.gui.ImageCanvas; -import ij.gui.ImageWindow; -import ij.gui.Plot; -import ij.gui.PlotWindow; - -/** - * This class provides some static methods for the creation of custom views - * inside the Bio7 application. - * - * @author Bio7 - * - */ -public class CustomDetachedImageJView extends ViewPart {//implements ISaveablePart2 - - protected int insertMark = -1; - - private static final String ID = "com.eco.bio7.custom_controls"; - - public Composite customViewParent; - - private Panel awtCurrent; - - private String secId; - - public ImagePlus plus; - - public ImageWindow win; - - public JPanel viewPanel; - - public IViewReference ref2; - - private CustomDetachedImageJView customView; - - protected ImageJPartListener2 palist; - - protected FXSwtAwtCustom swt; - - private boolean isDetached; - - protected IViewPart activated; - - public boolean isDetached() { - return isDetached; - } - - public CustomDetachedImageJView getCustomView() { - return customView; - } - - public CustomDetachedImageJView() { - // customView=this; - } - - public void setData(ImagePlus plu, ImageWindow win) { - this.plus = plu; - this.win = win; - - } - - /* Implement to overwrite function to set name! */ - public void setPartName(String partName) { - super.setPartName(partName); - } - - public void createPartControl(Composite parent) { - - PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "com.eco.bio7.imagej"); - - this.customViewParent = parent; - parent.addDisposeListener(new DisposeListener() { - - @Override - public void widgetDisposed(DisposeEvent e) { - Object data = customViewParent.getData(); - if (data instanceof Vector) { - Vector> ve = (Vector>) data; - closeTabPanels(ve); - } - - } - }); - - parent.addControlListener(new ControlAdapter() { - @Override - public synchronized void controlResized(final ControlEvent e) { - /* - * Here we write the values in the com.eco.bio7 plugin preferences with the help - * of scoped preferences! - */ - updateDetached(); - Rectangle rec = parent.getClientArea(); - - IPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, "com.eco.bio7"); - if (store != null) { - String selection = store.getString("PLOT_DEVICE_SELECTION"); - String pathTo = store.getString("pathTempR"); - int correction = 0; - if (CanvasView.tabFolder.isDisposed() == false && CanvasView.tabFolder != null) { - /* Height correction for the plot! */ - correction = CanvasView.tabFolder.getTabHeight(); - } - - if (selection.equals("PLOT_IMAGEJ_DISPLAYSIZE_CAIRO")) { - - store.setValue("DEVICE_DEFINITION", ".bio7Device <- function(filename = \"" + pathTo - + "tempDevicePlot%05d.tiff" + "\") { tiff(filename,width = " + rec.width + ", height = " - + (rec.height - correction) + ", type=\"cairo\")}; options(device=\".bio7Device\")"); - } else if (selection.equals("PLOT_IMAGEJ_DISPLAYSIZE")) { - store.setValue("DEVICE_DEFINITION", - ".bio7Device <- function(filename = \"" + pathTo + "tempDevicePlot%05d.tiff" - + "\") { tiff(filename,width = " + rec.width + ", height = " - + (rec.height - correction) - + ", units = \"px\")}; options(device=\".bio7Device\")"); - - } - } - /* Here we resize the ImageJ plot window! */ - ImageWindow currentPlotWindow = WindowManager.getCurrentWindow(); - - if (currentPlotWindow != null) { - //if (currentPlotWindow instanceof PlotWindow) { - - CanvasView view = CanvasView.getCanvas_view(); - view.layoutParent(parent); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - view.resizePlotWindow(parent, currentPlotWindow); - } - }); - //} else { - // parent.layout(); - //} - } else { - parent.layout(); - } - } - - }); - - updateDetached(); - - } - - private void updateDetached() { - isDetached = customViewParent.getShell().getText().length() == 0; - } - - public void setFocus() { - - } - - class ImageJPartListener2 implements IPartListener2 { - public void partActivated(IWorkbenchPartReference ref) { - - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - - if (page != null) { - - ref2 = page.findViewReference("com.eco.bio7.image.detachedImage", secId); - - if (ref.equals(ref2)) { - - // Wrap to avoid deadlock of awt frame access! - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - WindowManager.setTempCurrentImage(plus); - WindowManager.setCurrentWindow(win); - if (Util.getOS().equals("Mac")) { - if (swt != null) { - Frame frameSwtAwt = swt.getFrame(); - if (frameSwtAwt != null) { - - if (frameSwtAwt != null) - frameSwtAwt.dispatchEvent( - new WindowEvent(frameSwtAwt, WindowEvent.WINDOW_ACTIVATED)); - // frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, - // WindowEvent.WINDOW_GAINED_FOCUS)); - - } - } - - } - } - }); - - CanvasView.setCurrent(viewPanel); - //ImageJ.setCustomView(customView); - /*To show the status message!*/ - if (win != null) { - win.repaint(); - } - } - } - /* - * Workaround a bug on Mac which causes empty views when a perspective has been - * changed! Deactivated since it steals key focus of the detached view! - */ - if (Util.getOS().equals("Mac")) { - if (swt != null) { - /*Composite top = swt.getTop(); - if (top != null && top.isDisposed() == false) { - top.setVisible(false); - top.setVisible(true); - }*/ - } - - } - - } - - public void partBroughtToTop(IWorkbenchPartReference ref) { - - } - - public void partClosed(IWorkbenchPartReference ref) { - /* Important to control the references! */ - IWorkbenchPage page = ref.getPage(); - if (page != null) { - //page.getActivePart(); - - if (ref.equals(ref2)) { - /*Job job = new Job("Close Detached Images") { - @Override - protected IStatus run(IProgressMonitor monitor) { - monitor.beginTask("Close Detached Images ...", IProgressMonitor.UNKNOWN); - if (WindowManager.getImageCount() > 0) { - if (win != null) { - if (win.getImagePlus() != null) { - win.bio7TabClose(); - } - } - } - monitor.done(); - return Status.OK_STATUS; - } - - }; - - // job.setSystem(true); - job.schedule();*/ - if (Util.getOS().equals("Mac")) { - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - if (WindowManager.getImageCount() > 0) { - if (win != null) { - if (win.getImagePlus() != null) { - win.bio7TabClose(true); - } - } - } - } - }); - } - else { - if (WindowManager.getImageCount() > 0) { - if (win != null) { - if (win.getImagePlus() != null) { - win.bio7TabClose(false); - } - } - } - } - - /*Remove the part listener?*/ - page.removePartListener(palist); - - /* - * ArrayList arrL = CanvasView.getCanvas_view().getDetachedSecViewIDs(); - * System.out.println("prim: " + secId); for (int i = 0; i < arrL.size(); i++) { - * if (arrL.get(i).equals(secId)) { System.out.println("removed: " + - * arrL.get(i)); arrL.remove(i); } } - */ - - } - } - - } - - public void partDeactivated(IWorkbenchPartReference ref) { - - } - - public void partOpened(IWorkbenchPartReference ref) { - - } - - public void partHidden(IWorkbenchPartReference ref) { - - } - - public void partVisible(IWorkbenchPartReference ref) { - - } - - public void partInputChanged(IWorkbenchPartReference ref) { - - } - } - - /** - * Creates a given JPanel tab inside a custom view. - * - * @param jpanel a JPanel - * @param title the title of the tab. - */ - public void setPanel(final JPanel jpanel, final String id, final String name) { - secId = id; - - viewPanel = jpanel; - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - public void run() { - IViewPart activated = null; - try { - - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - activated = page.showView("com.eco.bio7.image.detachedImage", secId, IWorkbenchPage.VIEW_CREATE); - //IWorkbenchPartSite site = activated.getSite(); - - palist = new ImageJPartListener2(); - page.addPartListener(palist); - - } catch (PartInitException e) { - - e.printStackTrace(); - } - if (activated instanceof CustomDetachedImageJView) { - customView = (CustomDetachedImageJView) activated; - customView.setPartName(name); - display.update(); - swt = new FXSwtAwtCustom(viewPanel, customView); - swt.addTab(id); - //ImageJ.setCustomView(customView); - Composite top = swt.getTop(); - top.setParent(customView.getCustomViewParent()); - - } - - } - }); - - } - - /** - * Creates a given JPanel tab inside a custom view. - * - * @param jpanel a JPanel - * @param rec - * @param title the title of the tab. - * @param rec a Rectangle for the size and coordinates. - */ - public void setPanelFloatingDetached(final JPanel jpanel, final String id, final String name, Rectangle rec) { - secId = id; - viewPanel = jpanel; - try { - - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - activated = page.showView("com.eco.bio7.image.detachedImage", secId, IWorkbenchPage.VIEW_CREATE); - IWorkbenchPartSite site = activated.getSite(); - //activated = page.showView("com.eco.bio7.image.detachedImage", secId, IWorkbenchPage.VIEW_ACTIVATE); - EModelService s = (EModelService) site.getService(EModelService.class); - MPartSashContainerElement p = (MPart) site.getService(MPart.class); - - if (p.getCurSharedRef() != null) - p = p.getCurSharedRef(); - s.detach(p, rec.x, rec.y, rec.width, rec.height); - palist = new ImageJPartListener2(); - page.addPartListener(palist); - - } catch (PartInitException e) { - - e.printStackTrace(); - } - if (activated instanceof CustomDetachedImageJView) { - customView = (CustomDetachedImageJView) activated; - customView.setPartName(name); - //display.update(); - swt = new FXSwtAwtCustom(viewPanel, customView); - swt.addTab(id); - //ImageJ.setCustomView(customView); - Composite top = swt.getTop(); - top.setParent(customView.getCustomViewParent()); - - } - } - - public void dispose() { - customViewParent.dispose(); - super.dispose(); - } - - /** - * Creates a given Panel tab inside a custom view. - * - * @param panel a Panel - * @param title the title of the tab. - */ - - /** - * Returns the display of the view. - * - * @return the display of the view. - */ - public static Display getDisplay() { - Display display = PlatformUI.getWorkbench().getDisplay(); - return display; - - } - - protected void setAwtCurrent(Panel current) { - this.awtCurrent = current; - } - - protected Composite getCustomViewParent() { - return customViewParent; - } - - protected void setCustomViewParent(Composite parent2) { - this.customViewParent = parent2; - } - - /*public void doSave(IProgressMonitor monitor) { - - Object data = customViewParent.getData(); - if (data instanceof Vector) { - Vector> ve = (Vector>) data; - closeTabPanels(ve); - } - - } - - @Override - public void doSaveAs() { - - } - - @Override - public boolean isDirty() { - // Needed to save on close! - return true; - } - - @Override - public boolean isSaveAsAllowed() { - - return false; - } - - @Override - public boolean isSaveOnCloseNeeded() { - // Needed to save on close! - return true; - } - - @Override - public int promptToSaveOnClose() { - - return 0; - }*/ - - /* - * Close tab items and dispose different GUI references. Called if the view or a - * tab item is closed! - */ - private void closeTabPanels(Vector ve) { - if (ve != null) { - - if ((ve.get(0)) instanceof javax.swing.JPanel) { - JPanel panel = (JPanel) ve.get(0); - panel = null; - - } - - } - } - - public void setstatusline(String message) { - IActionBars bars = getViewSite().getActionBars(); - bars.getStatusLineManager().setMessage(message); - - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/FXSwtAwtCustom.java b/com.eco.bio7.image/src/com/eco/bio7/image/FXSwtAwtCustom.java deleted file mode 100644 index 89dd8d621..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/FXSwtAwtCustom.java +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007-2025 M. Austenfeld - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * M. Austenfeld - *******************************************************************************/ - -package com.eco.bio7.image; - -import java.awt.EventQueue; -import java.awt.Panel; -import java.util.Vector; -import javax.swing.JApplet; -import javax.swing.JPanel; -import javax.swing.JRootPane; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.SWT; -import org.eclipse.swt.awt.SWT_AWT; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -public class FXSwtAwtCustom { - - private JApplet panel; - - private Composite top; - - public Composite getTop() { - return top; - } - - private java.awt.Container contentPane; - - private java.awt.Frame frame; - - private JPanel jpanel; - - private Panel awtPanel; - - private Vector ve; - - private CustomDetachedImageJView view; - - protected Shell parent; - - public FXSwtAwtCustom(JPanel Jpanel, CustomDetachedImageJView view) { - this.view = view; - this.jpanel = Jpanel; - ve = new Vector(); - ve.add(Jpanel); - - } - - public java.awt.Frame getFrame() { - return frame; - } - - public void addTab(final String title) { - /* Add SWT_AWT to embed the ImageJ canvas! */ - Composite customViewParent = view.getCustomViewParent(); - Display dis = customViewParent.getDisplay(); - dis.syncExec(new Runnable() { - public void run() { - parent = new Shell(Util.getDisplay()); - top = new Composite(parent, SWT.NO_BACKGROUND | SWT.EMBEDDED); - try { - System.setProperty("sun.awt.noerasebackground", "true"); - } catch (NoSuchMethodError error) { - } - - customViewParent.setData(ve); - frame = SWT_AWT.new_Frame(top); - /* - * HighDPI fix for Windows frame layout which reverts the DPIUtil settings of - * the default implementation of the SWT_AWT class! - */ - if (Util.getOS().equals("Windows")) { - if (Util.getZoom() >= 175) { - customViewParent.getDisplay().asyncExec(() -> { - if (customViewParent.isDisposed()) - return; - final Rectangle clientArea = customViewParent.getClientArea(); // To Pixels - EventQueue.invokeLater(() -> { - frame.setSize(clientArea.width, clientArea.height); - frame.validate(); - }); - }); - } - - } - - // SwtAwt.setSwtAwtFocus(frame, top,Util.getDisplay()); - - panel = new JApplet() { - public void update(java.awt.Graphics g) { - // Do not erase the background - paint(g); - } - }; - - frame.add(panel); - - JRootPane root = new JRootPane(); - panel.add(root); - contentPane = root.getContentPane(); - - contentPane.add(jpanel); - - customViewParent.layout(); - - } - }); - - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/Fullscreen.java b/com.eco.bio7.image/src/com/eco/bio7/image/Fullscreen.java deleted file mode 100644 index d883482e6..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/Fullscreen.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.eco.bio7.image; - -import java.awt.Dimension; -import java.awt.DisplayMode; -import java.awt.EventQueue; -import java.awt.Frame; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - -import ij.WindowManager; -import ij.gui.ImageWindow; -import ij.gui.Plot; -import ij.gui.PlotWindow; - -public class Fullscreen extends JFrame { - - private static final long serialVersionUID = 1L; - private boolean fullscreen = false; - private boolean displayChanged = false; - private GraphicsEnvironment graphicEnvironment = null; - private GraphicsDevice graphicDevice = null; - private DisplayMode currentMode, oldMode; - private JPanel panel; - private static int refreshRate = 60; - private static Fullscreen screen; - private static int bit = 32; - private static int monitorHeight = 768; - private static int monitorWidth = 1024; - private Dimension temPlotSize; - - public Fullscreen(JPanel panel) { - this.panel = panel; - screen = this; - panel.requestFocus(); - graphicEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment(); - graphicDevice = graphicEnvironment.getDefaultScreenDevice(); - oldMode = graphicDevice.getDisplayMode(); - currentMode = oldMode; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - - init(); - - } - }); - this.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - - exit(); - - } - }); - add(panel); - - // this.pack(); - - } - - public boolean init() { - temPlotSize = CanvasView.getCurrent().getSize(); - setUndecorated(true); - if (graphicDevice.isFullScreenSupported()) { - - try { - graphicDevice.setFullScreenWindow(this); - fullscreen = true; - - ImageWindow win = WindowManager.getCurrentWindow(); - if (win instanceof PlotWindow) { - PlotWindow plo = (PlotWindow) win; - if (plo != null) { - Plot plot = plo.getPlot(); - if (plot != null) { - Dimension dim = panel.getSize(); - plot.setFrameSize(dim.width, dim.height); - int correctionX = plot.leftMargin + plot.rightMargin; - int correctionY = plot.topMargin + plot.bottomMargin; - plot.setSize(dim.width - correctionX, dim.height - correctionY); - CanvasView.getCurrent().doLayout(); - } - } - } - - } catch (Exception e) { - graphicDevice.setFullScreenWindow(null); - fullscreen = false; - } - /* Change the settings if it is supported! */ - - // switchDisplayMode(); - - } - return fullscreen; - } - - /* Switch to a different display mode! */ - private void switchDisplayMode() { - if (fullscreen && graphicDevice.isDisplayChangeSupported()) { // Change - - try { - - graphicDevice.setDisplayMode(new DisplayMode(monitorWidth, monitorHeight, bit, refreshRate)); - displayChanged = true; - } catch (RuntimeException e) { - graphicDevice.setDisplayMode(oldMode); - displayChanged = false; - - e.printStackTrace(); - } - - } - } - - public void exit() { - - if (fullscreen) { - - GraphicsEnvironment graphicEnvironment = null; - GraphicsDevice graphicsDevice = null; - graphicEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment(); - graphicsDevice = graphicEnvironment.getDefaultScreenDevice(); - if (graphicsDevice.isFullScreenSupported()) { - if (displayChanged) { - graphicDevice.setDisplayMode(oldMode); - } - - fullscreen = false; - - graphicsDevice.setFullScreenWindow(null); - - } - } - CanvasView.setCurrent(panel); - - this.remove(panel); - dispose(); - - ImageWindow win = WindowManager.getCurrentWindow(); - if (win instanceof PlotWindow) { - PlotWindow plo = (PlotWindow) win; - if (plo != null) { - Plot plot = plo.getPlot(); - if (plot != null) { - if (temPlotSize != null) { - Dimension dim = temPlotSize; - plot.setFrameSize(dim.width, dim.height); - int correctionX = plot.leftMargin + plot.rightMargin; - int correctionY = plot.topMargin + plot.bottomMargin; - plot.setSize(dim.width - correctionX, dim.height - correctionY); - //CanvasView.getCurrent().doLayout(); - } - } - } - } - } - - public void setBit(int bit) { - this.bit = bit; - } - - public void setMonitorHeight(int monitorHeight) { - this.monitorHeight = monitorHeight; - } - - public void setMonitorWidth(int monitorWidth) { - this.monitorWidth = monitorWidth; - } - - public static void setFullscreenOptions(int x, int y, int bitDepth, int refresh) { - bit = bitDepth; - monitorHeight = y; - monitorWidth = x; - refreshRate = refresh; - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/IJTabs.java b/com.eco.bio7.image/src/com/eco/bio7/image/IJTabs.java deleted file mode 100644 index 41eee920c..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/IJTabs.java +++ /dev/null @@ -1,543 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007-2025 M. Austenfeld - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * M. Austenfeld - *******************************************************************************/ - -package com.eco.bio7.image; - -import java.awt.Container; -import java.awt.Window; -import java.util.Vector; -import java.util.concurrent.atomic.AtomicReference; - -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - -import org.eclipse.e4.ui.model.application.ui.basic.MPart; -import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; -import org.eclipse.e4.ui.workbench.modeling.EModelService; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.custom.CTabFolder; -import org.eclipse.swt.custom.CTabItem; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.IWorkbenchPartSite; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; - -import ij.ImagePlus; -import ij.WindowManager; -import ij.gui.ImageCanvas; -import ij.gui.ImageWindow; - -/** - * A class for the control of the ImageJ tabs. - * - * @author Bio7 - * - */ -public class IJTabs { - - private static int id; - - /** - * Activates the tab with the specified number. - * - * @param number the number of the tab. - */ - public static void setActive(final int number) { - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - - if (items.length > 0 && number < items.length) { - - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - - CanvasView.tabFolder.showItem(items[number]); - CanvasView.tabFolder.setSelection(items[number]); - Vector ve = (Vector) items[number].getData(); - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - ImagePlus plu = (ImagePlus) ve.get(0); - ImageWindow win = (ImageWindow) ve.get(1); - WindowManager.setTempCurrentImage(plu); - WindowManager.setCurrentWindow(win); - CanvasView.setCurrent((JPanel) ve.get(2)); - } - }); - - } - }); - - } - - } - - /** - * Returns the amount of opened tabs in the ImageJ view. - * - * @return the amount of tabs as an integer value. - */ - public static int getAmountTabs() { - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - - return items.length; - - } - - public static void setSecondaryViewShellLocAndSize(String sec, Rectangle rec) { - - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - public void run() { - - IViewReference[] viewRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences(); - for (int i = 0; i < viewRefs.length; i++) { - String id = viewRefs[i].getId(); - if (id.equals("com.eco.bio7.image.detachedImage")) { - // IViewPart view = viewRefs[i].getView(false); - String secId = viewRefs[i].getSecondaryId(); - if (secId.equals(sec)) { - IViewPart view = viewRefs[i].getView(false); - CustomDetachedImageJView cdview = (CustomDetachedImageJView) view; - if (cdview.isDetached()) { - - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - IViewPart activated = null; - try { - activated = page.showView("com.eco.bio7.image.detachedImage", sec, IWorkbenchPage.VIEW_ACTIVATE); - } catch (PartInitException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - if (rec != null) { - IWorkbenchPartSite site = activated.getSite(); - // activated = page.showView("com.eco.bio7.image.detachedImage", secId, - // IWorkbenchPage.VIEW_ACTIVATE); - EModelService s = (EModelService) site.getService(EModelService.class); - MPartSashContainerElement p = (MPart) site.getService(MPart.class); - - if (p.getCurSharedRef() != null) - p = p.getCurSharedRef(); - s.detach(p, rec.x, rec.y, rec.width, rec.height); - - cdview.customViewParent.requestLayout(); - } - - } - } - } - } - } - }); - } - - /** - * Closes all tabs in the ImageJ view. - */ - public static void deleteAllTabs() { - /* Close all detached views if available! */ - IViewReference[] viewRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences(); - for (int i = 0; i < viewRefs.length; i++) { - String id = viewRefs[i].getId(); - if (id.equals("com.eco.bio7.image.detachedImage")) { - viewRefs[i].getPage().hideView(viewRefs[i]); - } - } - - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - WindowManager.closeAllWindows(); - } - }); - for (int i = 0; i < items.length; i++) { - final int tabcount = i; - - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* We have to delete the control and children, too! */ - Composite com = (Composite) items[tabcount].getControl(); - Control compo[] = com.getChildren(); - for (int i = 0; i < compo.length; i++) { - if (compo[i] != null && compo[i].isDisposed() == false) { - compo[i].dispose(); - } - } - com.dispose(); - items[tabcount].dispose(); - - } - }); - - } - - } - - /** - * Closes the tab with the specified number in the ImageJ view. - * - * @param number the number of the tab as an integer value. - */ - public static void deleteTab(int number) { - final int nrdel = number; - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - Vector ve = (Vector) items[nrdel].getData(); - - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - ImagePlus plu = (ImagePlus) ve.get(0); - - final ImageWindow win = (ImageWindow) ve.get(1); - - win.bio7TabClose(true); - } - }); - Composite com = (Composite) items[nrdel].getControl(); - Control compo[] = com.getChildren(); - for (int i = 0; i < compo.length; i++) { - if (compo[i] != null && compo[i].isDisposed() == false) { - compo[i].dispose(); - } - } - com.dispose(); - items[nrdel].dispose(); - - } - }); - - } - - /** - * Hides the active tab in the ImageJ view. - */ - public static void hideTab() { - - final CTabItem item = CanvasView.tabFolder.getSelection(); - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - if (item != null) { - Composite com = (Composite) item.getControl(); - Control compo[] = com.getChildren(); - for (int i = 0; i < compo.length; i++) { - if (compo[i] != null && compo[i].isDisposed() == false) { - compo[i].dispose(); - } - } - com.dispose(); - item.dispose(); - } - } - }); - - } - - /** - * Hides the tab with the specified number in the ImageJ view. - * - * @param number the tab number. - */ - public static void hideTabNumber(int number) { - - final int nrdel = number; - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - Composite com = (Composite) items[nrdel].getControl(); - Control compo[] = com.getChildren(); - for (int i = 0; i < compo.length; i++) { - if (compo[i] != null && compo[i].isDisposed() == false) { - compo[i].dispose(); - } - } - com.dispose(); - items[nrdel].dispose(); - } - }); - - } - - /** - * Deletes the active tab in the ImageJ view. - */ - public static void deleteActiveTab() { - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - - final CTabItem item = CanvasView.tabFolder.getSelection(); - if (item != null) { - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - Vector ve = (Vector) item.getData(); - - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - - final ImageWindow win = (ImageWindow) ve.get(1); - - win.bio7TabClose(true); - } - }); - Composite com = (Composite) item.getControl(); - Control compo[] = com.getChildren(); - for (int i = 0; i < compo.length; i++) { - if (compo[i] != null && compo[i].isDisposed() == false) { - compo[i].dispose(); - } - } - com.dispose(); - item.dispose(); - - } - }); - } - - } - - public static void setActiveTab(String title) { - - /* Changed for Bio7! */ - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - private int count; - - public void run() { - for (int i = 0; i < items.length; i++) { - count = i; - Vector ve = (Vector) items[i].getData(); - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - - final ImageWindow win2 = (ImageWindow) ve.get(1); - - /* Search for the tab which embeds this instance! */ - if (win2.getTitle().equals(title)) { - // calls bio7Tabclose! - CanvasView.getCanvas_view().tabFolder.setSelection(items[count]); - // System.out.println("closed"); - return; - - } - } - }); - - } - - } - }); - } - - public static void setActiveTabID(int theId) { - - if (id > 0) { - id = WindowManager.getNthImageID(id); - } - /* Changed for Bio7! */ - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - private int count; - - public void run() { - for (int i = 0; i < items.length; i++) { - count = i; - Vector ve = (Vector) items[i].getData(); - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - - final ImageWindow win2 = (ImageWindow) ve.get(1); - - ImagePlus plus = WindowManager.getImage(id); - /* Search for the tab which embeds this instance! */ - if (win2.getImagePlus() == plus) { - // calls the selection! - CanvasView.getCanvas_view().tabFolder.setSelection(items[count]); - // System.out.println("closed"); - return; - - } - } - }); - - } - - } - }); - } - - public static void setActiveTabWindow(Window win) { - - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - private int count; - - public void run() { - CTabFolder tabFolder = CanvasView.getCanvas_view().tabFolder; - CTabItem[] items = tabFolder.getItems(); - for (int i = 0; i < items.length; i++) { - count = i; - Vector> ve = (Vector>) items[i].getData(); - - final ImageWindow win2 = (ImageWindow) ve.get(1); - - /* Search for the tab which embeds this instance! */ - if (win == win2) { - // calls the selection! - tabFolder.setSelection(items[count]); - // System.out.println("closed"); - return; - - } - - } - - } - }); - } - - public static void hideTab(ImagePlus imagePlus) { - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - private int count; - - public void run() { - for (int i = 0; i < items.length; i++) { - count = i; - Vector ve = (Vector) items[i].getData(); - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - - final ImagePlus plus = (ImagePlus) ve.get(0); - - /* - * Search for the tab which embeds this ImagePlus instance! - */ - if (plus == imagePlus) { - // calls bio7Tabclose! - items[count].dispose(); - - } - } - }); - - } - - } - }); - - } - - /* - * A method to layout secondary ImageJ views (e.g. for orthogonal stack views)! - */ - public static void doSecondaryViewLayout() { - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - public void run() { - IViewReference[] viewRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences(); - for (int i = 0; i < viewRefs.length; i++) { - String id = viewRefs[i].getId(); - if (id.equals("com.eco.bio7.image.detachedImage")) { - IViewPart view = viewRefs[i].getView(false); - String secId = viewRefs[i].getSecondaryId(); - CustomDetachedImageJView cdview = (CustomDetachedImageJView) view; - - cdview.setFocus(); - ImagePlus ip = WindowManager.getImage(Integer.valueOf(secId)); - ImageCanvas canvas = ip.getCanvas(); - if (canvas != null) { - Container parentOfCanvas = canvas.getParent(); - if (parentOfCanvas != null) { - Container parent = parentOfCanvas; - parent.doLayout(); - parent.repaint(); - } - } - cdview.customViewParent.requestLayout(); - } - } - } - }); - } - - public static boolean closeDetachedWindowView(ImageWindow refWin) { - final AtomicReference result = new AtomicReference(); - result.set(false); - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Check for detached views! */ - IViewReference[] viewRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences(); - for (int i = 0; i < viewRefs.length; i++) { - String id = viewRefs[i].getId(); - if (id.equals("com.eco.bio7.image.detachedImage")) { - // IViewPart view = viewRefs[i].getView(false); - String secId = viewRefs[i].getSecondaryId(); - // CustomDetachedImageJView cdview = (CustomDetachedImageJView) view; - /* Get the image from the detached secondary view id (same id)! */ - ImagePlus plu = WindowManager.getImage(Integer.valueOf(secId)); - if (plu != null) { - ImagePlus ip = WindowManager.getImage(Integer.valueOf(secId)); - // ImageWindow currentWindow = WindowManager.getCurrentWindow(); - ImageWindow window = ip.getWindow(); - if (refWin.equals(window)) { - - viewRefs[i].getPage().hideView(viewRefs[i]); - result.set(true); - break; - } else { - result.set(false); - } - - } - - } - } - } - }); - return (boolean) result.get(); - - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/IJtoolbar.java b/com.eco.bio7.image/src/com/eco/bio7/image/IJtoolbar.java deleted file mode 100644 index 3eef598e9..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/IJtoolbar.java +++ /dev/null @@ -1,143 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007-2025 M. Austenfeld - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * M. Austenfeld - *******************************************************************************/ - -package com.eco.bio7.image; - -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IPartListener2; -import org.eclipse.ui.IWorkbenchPartReference; -import org.eclipse.ui.part.ViewPart; - -public class IJtoolbar extends ViewPart { - - private IJtoolbarSwtAwt toolBar; - private Composite topIJtoolbarSwtAwt; - public static IJtoolbar instance; - - public IJtoolbar() { - instance = this; - } - - public void createPartControl(Composite parent) { - - getViewSite().getPage().addPartListener(new IPartListener2() { - - public void partActivated(IWorkbenchPartReference partRef) { - if (partRef.getId().equals("com.eco.bio7.ijtoolbar")) { - if (Util.getOS().equals("Mac")) { - if (topIJtoolbarSwtAwt != null && topIJtoolbarSwtAwt.isDisposed() == false) { - - Display dis = Util.getDisplay(); - dis.asyncExec(new Runnable() { - - public void run() { - - toolBar.top.setVisible(false); - toolBar.top.setVisible(true); - } - }); - } - - } - - /* - * SwingUtilities.invokeLater(new Runnable() { // !! public void run() { if (jpp - * != null) { jpp.doLayout(); jpp.repaint(); } } }); - */ - - } - - } - - public void partBroughtToTop(IWorkbenchPartReference partRef) { - if (partRef.getId().equals("com.eco.bio7.ijtoolbar")) { - if (Util.getOS().equals("Mac")) { - if (topIJtoolbarSwtAwt != null && topIJtoolbarSwtAwt.isDisposed() == false) { - toolBar.top.setVisible(false); - toolBar.top.setVisible(true); - } - - } - - /* - * SwingUtilities.invokeLater(new Runnable() { // !! public void run() { if (jpp - * != null) { jpp.doLayout(); jpp.repaint(); } } }); - */ - } - - } - - public void partClosed(IWorkbenchPartReference partRef) { - - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* - * Composite top = toolBar.getTop(); Shell shell = toolBar.getParent(); - * top.setParent(shell); - */ - } - }); - } - - public void partDeactivated(IWorkbenchPartReference partRef) { - - } - - public void partHidden(IWorkbenchPartReference partRef) { - - } - - public void partInputChanged(IWorkbenchPartReference partRef) { - - } - - public void partOpened(IWorkbenchPartReference partRef) { - - } - - public void partVisible(IWorkbenchPartReference partRef) { - - } - }); - - /* - * We use the SWT_AWT bridge! - */ - - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - Color col = parent.getBackground(); - toolBar = new IJtoolbarSwtAwt(col); - topIJtoolbarSwtAwt = toolBar.getTop(); - topIJtoolbarSwtAwt.setParent(parent); - } - }); - - } - - public void setFocus() { - - } - - public void dispose() { - toolBar.getParent().dispose(); - super.dispose(); - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/IJtoolbarSwtAwt.java b/com.eco.bio7.image/src/com/eco/bio7/image/IJtoolbarSwtAwt.java deleted file mode 100644 index 6ae1ea37e..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/IJtoolbarSwtAwt.java +++ /dev/null @@ -1,147 +0,0 @@ -package com.eco.bio7.image; - -import java.awt.Color; -import java.awt.EventQueue; -import java.awt.Frame; -import java.awt.GridLayout; -import java.awt.Panel; - -import javax.swing.JApplet; -import javax.swing.JPanel; -import javax.swing.JRootPane; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.awt.SWT_AWT; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.MessageBox; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; - -import ij.IJ; - -public class IJtoolbarSwtAwt { - - public Composite top; - public Frame frame; - public Shell parent; - protected static Color col; - - public Composite getTop() { - return top; - } - - public Shell getParent() { - return parent; - } - - public IJtoolbarSwtAwt(org.eclipse.swt.graphics.Color colswt) { - /*If we have no ImageJ instance (e.g. inside an Eclipse installation) we open the ImageJ view first!*/ - if (IJ.getInstance() == null) { - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - public void run() { - try { - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - page.showView("com.eco.bio7.imagej"); - } catch (PartInitException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - }); - } - - parent = new Shell(Util.getDisplay()); - - top = new Composite(parent, SWT.NO_BACKGROUND | SWT.EMBEDDED); - - frame = SWT_AWT.new_Frame(top); - try { - System.setProperty("sun.awt.noerasebackground", "true"); - } catch (NoSuchMethodError error) { - } - /*HighDPI fix for Windows frame layout which reverts the DPIUtil settings of the default implementation of the SWT_AWT class!*/ - if (Util.getOS().equals("Windows")) { - if (Util.getZoom() >= 175) { - Composite parent = top.getParent(); - parent.getDisplay().asyncExec(() -> { - if (parent.isDisposed()) - return; - final Rectangle clientArea = parent.getClientArea(); // To Pixels - EventQueue.invokeLater(() -> { - frame.setSize(clientArea.width, clientArea.height); - frame.validate(); - }); - }); - } - - } - - /* - * final sun.awt.EmbeddedFrame ef = (sun.awt.EmbeddedFrame) frame; - * ef.addWindowListener(new WindowAdapter() { public void - * windowActivated(WindowEvent e) { ef.synthesizeWindowActivation(true); } }); - */ - // SwtAwt.setSwtAwtFocus(frame, parent,Util.getDisplay()); - Panel panel = new JApplet() { - public void update(java.awt.Graphics g) { - - paint(g); - } - }; - - frame.add(panel); - JRootPane roote = new JRootPane(); - panel.add(roote); - java.awt.Container contentPane = roote.getContentPane(); - JPanel jpp = new JPanel(); - - jpp.setLayout(new GridLayout(2, 1)); - - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - Color swtBackgroundToAWT = new Color(r, g, b); - - panel.setBackground(swtBackgroundToAWT); - roote.setBackground(swtBackgroundToAWT); - frame.setBackground(swtBackgroundToAWT); - jpp.setBackground(swtBackgroundToAWT); - jpp.add(IJ.getInstance().toolbar); - jpp.add(IJ.getInstance().statusBar); - - contentPane.add(jpp); - - /*else { - Display display = Util.getDisplay(); - display.syncExec(new Runnable() { - public void run() { - MessageBox messageBox = new MessageBox(Util.getShell(), - - SWT.ICON_WARNING); - messageBox.setText("Info!"); - messageBox.setMessage("Please reopen the ImageJ-Toolbar view!\n\n" + "Only a detached toolbar will be reopened automatically\n" + "in a saved and restored Eclipse session."); - messageBox.open(); - } - }); - - Close the stored toolbar layout (not valid in RCP) if the view is embedded in a perspective for the plugin version (the embedded view will be opened before the ImageJ instance is available!) - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - public void run() { - IWorkbenchPage wbp = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - - wbp.hideView(wbp.findView("com.eco.bio7.ijtoolbar")); - - } - - }); - }*/ - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ImageJPluginPerspective.java b/com.eco.bio7.image/src/com/eco/bio7/image/ImageJPluginPerspective.java deleted file mode 100644 index 261ecaa84..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/ImageJPluginPerspective.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.eco.bio7.image; - -import org.eclipse.ui.IFolderLayout; -import org.eclipse.ui.IPageLayout; -import org.eclipse.ui.IPerspectiveFactory; -import com.eco.bio7.image.thumbs.ThumbnailsView; - -public class ImageJPluginPerspective implements IPerspectiveFactory { - - public void createInitialLayout(IPageLayout layout) { - - String editorArea = layout.getEditorArea(); - layout.setEditorAreaVisible(false); - IFolderLayout Left = layout.createFolder( - "Left", IPageLayout.LEFT, (float) 0.7, editorArea);//$NON-NLS-1$ - Left.addPlaceholder(IPageLayout.ID_BOOKMARKS); - Left.addView(CanvasView.ID); - - IFolderLayout Right = layout.createFolder( - "Right", IPageLayout.RIGHT, (float) 0.3, editorArea);//$NON-NLS-1$ - - Right.addView(ThumbnailsView.ID); - - - - - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/MessagesThemeIDsSettings.java b/com.eco.bio7.image/src/com/eco/bio7/image/MessagesThemeIDsSettings.java deleted file mode 100644 index 3834e8f97..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/MessagesThemeIDsSettings.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.eco.bio7.image; - -import org.eclipse.osgi.util.NLS; - -public class MessagesThemeIDsSettings extends NLS { - private static final String BUNDLE_NAME = "com.eco.bio7.image.messages"; //$NON-NLS-1$ - public static String Theme_Black_1; - public static String Theme_Black_2; - public static String Theme_Black_3; - public static String Theme_Black_4; - public static String Theme_Black_5; - public static String Theme_Font_Color; - static { - // initialize resource bundle - NLS.initializeMessages(BUNDLE_NAME, MessagesThemeIDsSettings.class); - } - - private MessagesThemeIDsSettings() { - } -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/SwtAwtImageJ.java b/com.eco.bio7.image/src/com/eco/bio7/image/SwtAwtImageJ.java deleted file mode 100644 index 1b59692dd..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/SwtAwtImageJ.java +++ /dev/null @@ -1,240 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007-2025 M. Austenfeld - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * M. Austenfeld - *******************************************************************************/ - -package com.eco.bio7.image; - -import java.awt.Color; -import java.awt.EventQueue; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.Vector; - -import javax.swing.JApplet; -import javax.swing.JPanel; -import javax.swing.JRootPane; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.awt.SWT_AWT; -import org.eclipse.swt.custom.CTabItem; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; - -import ij.ImagePlus; -import ij.gui.ImageCanvas; -import ij.gui.ImageLayout; -import ij.gui.ImageWindow; -import ij.gui.ScrollbarWithLabel; - -public class SwtAwtImageJ { - - private JPanel a; - - private JApplet panel; - - public Composite top; - - private CTabItem ci; - - private java.awt.Container contentPane; - - public java.awt.Frame frame; - - private ImageCanvas im; - - private ImagePlus plus; - - private ImageWindow win; - - private Vector ve; - - private ScrollbarWithLabel sliceselect; - /* For Hyperstacks! */ - private ScrollbarWithLabel channelselect; - - private ScrollbarWithLabel frameselect; - - // protected SwingFxSwtView view; - - public SwtAwtImageJ(ScrollbarWithLabel channelSelector, ScrollbarWithLabel sliceSelector, ScrollbarWithLabel frameSelector, ImageCanvas ic, ImagePlus plusin, ImageWindow window) { - this.im = ic; - this.plus = plusin; - this.win = window; - this.channelselect = channelSelector; - this.frameselect = frameSelector; - - this.sliceselect = sliceSelector; - - ve = new Vector(); - ve.add(plus); - ve.add(win); - - - } - - public java.awt.Frame getFrame() { - return frame; - } - - public void setFrame(java.awt.Frame frame) { - this.frame = frame; - } - - public void addTab(final String title) { - /* Add SWT_AWT to embed the ImageJ canvas! */ - - Display dis = Util.getDisplay(); - // new AwtDialogListener(Util.getDisplay()); - if (Util.getOS().equals("Mac")) { - /* - * On Mac we had to use async (no sync) else we got no keyboard focus! We also - * have to change the StackEditor for Mac to avoid a deadlock when converting a - * stack to images! - */ - dis.syncExec(new Runnable() { - - public void run() { - - createSwingTabDisplay(title); - - } - }); - - } else { - dis.syncExec(new Runnable() { - - public void run() { - - createSwingTabDisplay(title); - - } - }); - } - - } - - public JPanel getPanel() { - return a; - } - - public JApplet getApplet() { - return panel; - } - - private void createSwingTabDisplay(final String title) { - - ci = new CTabItem(CanvasView.tabFolder, SWT.CLOSE, CanvasView.insertMark + 1); - // ci.setData(plus);// add a reference to the image for use - // as - // selected tab - ci.setData(ve);// add a vector with the data from the - // ImageWindow and the Image!! - ci.setText(title); - ci.isShowing(); - top = new Composite(CanvasView.tabFolder, SWT.NO_BACKGROUND | SWT.EMBEDDED); - try { - System.setProperty("sun.awt.noerasebackground", "true"); - } catch (NoSuchMethodError error) { - } - ci.setControl(top); - - frame = SWT_AWT.new_Frame(top); - /* - * HighDPI fix for Windows frame layout which reverts the DPIUtil settings of - * the default implementation of the SWT_AWT class! - */ - if (Util.getOS().equals("Windows")) { - if (Util.getZoom() >= 175) { - Composite parent = top.getParent(); - parent.getDisplay().asyncExec(() -> { - if (parent.isDisposed()) - return; - final Rectangle clientArea = parent.getClientArea(); // To Pixels - EventQueue.invokeLater(() -> { - frame.setSize(clientArea.width, clientArea.height); - frame.validate(); - }); - }); - } - - } - // SwtAwt.setSwtAwtFocus(frame, CanvasView.getCanvas_view().parent2); - panel = new JApplet() { - public void update(java.awt.Graphics g) { - // Do not erase the background - paint(g); - } - }; - // panel.addLayout(new java.awt.BorderLayout()); - frame.add(panel); - - JRootPane root = new JRootPane(); - panel.add(root); - contentPane = root.getContentPane(); - - a = new JPanel(); - a.addMouseListener(new MouseAdapter() { - - public void mousePressed(MouseEvent e) { - Util.activateView("com.eco.bio7.imagej"); - } - - }); - - Color swtBackgroundToAWT = Util.getSWTBackgroundToAWT(); - panel.setBackground(swtBackgroundToAWT); - frame.setBackground(swtBackgroundToAWT); - a.setBackground(swtBackgroundToAWT); - - contentPane.add(a); - a.add(im);// Add the Image canvas to the JPanel - a.setLayout(new ImageLayout(im)); - // a.setLayout(new java.awt.BorderLayout()); - if (channelselect != null) { - a.add(channelselect); - } - if (sliceselect != null) { - a.add(sliceselect); - } - if (frameselect != null) { - a.add(frameselect); - } - - ve.add(a); // Add to the vector for access - ve.add(frame); - CanvasView.tabFolder.setLayout(null); - CanvasView.tabFolder.showItem(ci); - CanvasView.tabFolder.setSelection(ci); - CanvasView.setCurrent(a); - CanvasView.getCanvas_view().win = win; - // CanvasView.getCurrent().doLayout(); - // a.doLayout(); - plus.setActivated(); // notify ImagePlus that image has been activated - /* - * if (Util.getOS().equals("Mac")) { plus.setTitle(plus.getTitle()); } else { - * EventQueue.invokeLater(() -> { plus.setTitle(plus.getTitle()); }); } - */ - ci.setText(plus.getTitle()); - /* Fix to display an image on MacOSX! */ - if (Util.getOS().equals("Mac")) { - Composite parent = top.getParent(); - final Rectangle clientArea = parent.getClientArea(); // To Pixels - EventQueue.invokeLater(() -> { - frame.setSize(clientArea.width, clientArea.height); - frame.validate(); - }); - } - - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/messages.properties b/com.eco.bio7.image/src/com/eco/bio7/image/messages.properties deleted file mode 100644 index ce75020c3..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/messages.properties +++ /dev/null @@ -1,6 +0,0 @@ -Theme_Black_1=org.eclipse.e4.ui.css.theme.e4_dark -Theme_Black_2=com.genuitec.eclipse.themes.dark -Theme_Black_3=darktheme3 -Theme_Black_4=darktheme4 -Theme_Black_5=darktheme5 -Theme_Font_Color=dark diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/popup/action/OpenImageThumbnailView.java b/com.eco.bio7.image/src/com/eco/bio7/image/popup/action/OpenImageThumbnailView.java index aa24a47a8..b74598348 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/popup/action/OpenImageThumbnailView.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/popup/action/OpenImageThumbnailView.java @@ -10,7 +10,7 @@ import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; -import com.eco.bio7.image.Util; +import com.eco.bio7.image.ui.Util; import com.eco.bio7.image.thumbs.ThumbnailAction; public class OpenImageThumbnailView extends Action implements IObjectActionDelegate { diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/preferences/Bio7ImageJPreferences.java b/com.eco.bio7.image/src/com/eco/bio7/image/preferences/Bio7ImageJPreferences.java index ba04978c0..b4f4238e1 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/preferences/Bio7ImageJPreferences.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/preferences/Bio7ImageJPreferences.java @@ -8,8 +8,8 @@ import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.Util; +import com.eco.bio7.image.ui.Activator; +import com.eco.bio7.image.ui.Util; import ij.Menus; @@ -41,25 +41,8 @@ public void createFieldEditors() { addField(new DirectoryFieldEditor("PLUGINS_PATH", "&Plugins Path", getFieldEditorParent())); - addField(new DirectoryFieldEditor("MACROS_PATH", "&Macros Path", getFieldEditorParent())); - - addField(new SpacerFieldEditor(getFieldEditorParent())); - - addField(new BooleanFieldEditor("ROI_MANAGER", "&ROI Manager window on top", getFieldEditorParent())); - - addField(new BooleanFieldEditor("RESULTS_TABLE", "&Results Table window on top", getFieldEditorParent())); - - addField(new BooleanFieldEditor("MACRO_RECORDER", "&Macro Recorder window on top", getFieldEditorParent())); - { - - IntegerFieldEditor integerFieldEditor = new IntegerFieldEditor("FONT_SIZE_CORRECTION", "Fontsize correction (Restart necessary)", getFieldEditorParent()); - integerFieldEditor.setValidRange(-50, 50); - addField(integerFieldEditor); - } - - addField(new BooleanFieldEditor("FONT_ANTIALIASED", "Antialiased Fonts", BooleanFieldEditor.DEFAULT, getFieldEditorParent())); - - addField(new BooleanFieldEditor("MAC_MENU_ENABLED", "Enable ImageJ Menu on MacOSX", BooleanFieldEditor.DEFAULT, getFieldEditorParent())); + /* SWTImageJ loads the macros from the folder 'macros' next to the plugins folder! */ + addField(new LabelFieldEditor("Macros are loaded from the 'macros' folder next to the plugins folder (restart necessary).", getFieldEditorParent())); addField(new SpacerFieldEditor(getFieldEditorParent())); addField(new LabelFieldEditor("Image Methods Dialog Size:", getFieldEditorParent())); diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/preferences/LabelFieldEditor.java b/com.eco.bio7.image/src/com/eco/bio7/image/preferences/LabelFieldEditor.java index 20c6e59df..9140dea9e 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/preferences/LabelFieldEditor.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/preferences/LabelFieldEditor.java @@ -7,7 +7,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; -import com.eco.bio7.image.Util; +import com.eco.bio7.image.ui.Util; class LabelFieldEditor extends FieldEditor { diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/preferences/PreferenceInitializer.java b/com.eco.bio7.image/src/com/eco/bio7/image/preferences/PreferenceInitializer.java index 3d1944dbe..6361871ab 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/preferences/PreferenceInitializer.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/preferences/PreferenceInitializer.java @@ -6,8 +6,8 @@ import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IntegerFieldEditor; -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.Util; +import com.eco.bio7.image.ui.Activator; +import com.eco.bio7.image.ui.Util; /** * Class used to initialize default preference values. @@ -28,9 +28,6 @@ public void initializeDefaultPreferences() { store.setDefault("PLUGINS_PATH", pluginsPath); store.setDefault("MACROS_PATH", macrosPath); - store.setDefault("ROI_MANAGER", false); - store.setDefault("RESULTS_TABLE", false); - store.setDefault("MACRO_RECORDER", false); /* Dialog Sizes for ImageJ dialogs! */ store.setDefault("IMAGE_METHODS_SIZE_X", 360);// 260 store.setDefault("IMAGE_METHODS_SIZE_Y", 450);// 790 @@ -46,26 +43,6 @@ public void initializeDefaultPreferences() { store.setDefault("DETACHED_IMAGE_SPACING_Y", 50); store.setDefault("DETACHED_IMAGE_SPACING_X_MAX", 300); store.setDefault("DETACHED_IMAGE_SPACING_Y_MAX", 0); - - - - store.setDefault("MAC_MENU_ENABLED", false); - - if (Util.getOS().equals("Windows")) { - store.setDefault("FONT_SIZE_CORRECTION", 0); - store.setDefault("FONT_ANTIALIASED", false); - } else if (Util.getOS().equals("Linux")) { - store.setDefault("FONT_SIZE_CORRECTION", 0); - store.setDefault("FONT_ANTIALIASED", true); - } else if (Util.getOS().equals("Mac")) { - /*Correct Swing fonts on Retina displays!*/ - if (Util.isMacRetinaDisplay()) { - store.setDefault("FONT_SIZE_CORRECTION", 0); - } else { - store.setDefault("FONT_SIZE_CORRECTION", 0); - } - store.setDefault("FONT_ANTIALIASED", false); - } } diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/AwtDialogListener.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/AwtDialogListener.java deleted file mode 100644 index 7f68076e5..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/AwtDialogListener.java +++ /dev/null @@ -1,225 +0,0 @@ -package com.eco.bio7.image.swtawtutil; - -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ - -import java.awt.AWTEvent; -import java.awt.Dialog; -import java.awt.EventQueue; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.AWTEventListener; -import java.awt.event.ComponentEvent; -import java.awt.event.ComponentListener; -import java.awt.event.WindowEvent; -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.swt.widgets.Display; - -/** - * A listener that insures the proper modal behavior of Swing dialogs when running - * within a SWT environment. When initialized, it blocks and unblocks SWT input - * as modal Swing dialogs are shown and hidden. - */ -public class AwtDialogListener implements AWTEventListener, ComponentListener { - - // modalDialogs should be accessed only from the AWT thread, so no - // synchronization is needed. - private final List modalDialogs = new ArrayList(); - private final Display display; - - /** - * Registers this object as an AWT event listener so that Swing dialogs have the - * proper modal behavior in the containing SWT environment. This is called automatically - * when you construct a {@link EmbeddedSwingComposite}, and it - * need not be called separately in that case. - * @param shell - */ - public AwtDialogListener(Display display) { - assert display != null; - - this.display = display; - Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.WINDOW_EVENT_MASK); - } - - private void handleRemovedDialog(Dialog awtDialog, boolean removeListener) { - assert awtDialog != null; - assert modalDialogs != null; - assert display != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("Remove dialog: " + awtDialog); - if (removeListener) { - awtDialog.removeComponentListener(this); - } - // Note: there is no isModal() check here because the dialog might - // have been changed from modal to non-modal after it was opened. In this case - // the currently visible dialog would still act modal and we'd need to unblock - // SWT here when it goes away. - if (modalDialogs.remove(awtDialog)) { - display.asyncExec(new Runnable() { - public void run() { - SwtInputBlocker.unblock(); - } - }); - } - } - - private void handleAddedDialog(final Dialog awtDialog) { - assert awtDialog != null; - assert modalDialogs != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("Add dialog: " + awtDialog); - if (modalDialogs.contains(awtDialog) || !awtDialog.isModal() || !awtDialog.isVisible()) { - return; - } - modalDialogs.add(awtDialog); - awtDialog.addComponentListener(this); - display.asyncExec(new Runnable() { - public void run() { - SwtInputBlocker.block(); - } - }); - } - - void requestFocus() { - // TODO: this does not always bring the dialog to the top - // under some Linux desktops/window managers (e.g. metacity under GNOME). - EventQueue.invokeLater(new Runnable() { - public void run() { - assert modalDialogs != null; - - int size = modalDialogs.size(); - if (size > 0) { - final Dialog awtDialog = (Dialog)modalDialogs.get(size - 1); - - // In one case, a call to requestFocus() alone does not - // bring the AWT dialog to the top. This happens if the - // dialog is given a null parent frame. When opened, the dialog - // can be hidden by the SWT window even when it obtains focus. - // Calling toFront() solves the problem, but... - // - // There are still problems if the Metal look and feel is in use. - // The SWT window will hide the dialog the first time it is - // selected. Once the dialog is brought back to the front by - // the user, there is no further problem. - // - // Why? It looks like SWT is not being notified of lost focus when - // the Metal dialog first opens; subsequently, when focus is regained, the - // focus gain event is not posted to the SwtInputBlocker. - // - // The workaround is to use Windows look and feel, rather than Metal. - // System.out.println("Bringing to front"); - - awtDialog.requestFocus(); - awtDialog.toFront(); - } - } - }); - } - - private void handleOpenedWindow(WindowEvent event) { - assert event != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - Window window = event.getWindow(); - if (window instanceof Dialog) { - handleAddedDialog((Dialog)window); - } - } - - private void handleClosedWindow(WindowEvent event) { - assert event != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // Dispose-based close - Window window = event.getWindow(); - if (window instanceof Dialog) { - // Remove dialog and component listener - handleRemovedDialog((Dialog)window, true); - } - } - - private void handleClosingWindow(WindowEvent event) { - assert event != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System-based close - Window window = event.getWindow(); - if (window instanceof Dialog) { - final Dialog dialog = (Dialog) window; - // Defer until later. Bad things happen if - // handleRemovedDialog() is called directly from - // this event handler. The Swing dialog does not close - // properly and its modality remains in effect. - EventQueue.invokeLater(new Runnable() { - public void run() { - // Remove dialog and component listener - handleRemovedDialog(dialog, true); - } - }); - } - } - - public void eventDispatched(AWTEvent event) { - assert event != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - switch (event.getID()) { - case WindowEvent.WINDOW_OPENED: - handleOpenedWindow((WindowEvent)event); - break; - - case WindowEvent.WINDOW_CLOSED: - handleClosedWindow((WindowEvent)event); - break; - - case WindowEvent.WINDOW_CLOSING: - handleClosingWindow((WindowEvent)event); - break; - - default: - break; - } - } - - public void componentHidden(ComponentEvent e) { - assert e != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("Component hidden"); - Object obj = e.getSource(); - if (obj instanceof Dialog) { - // Remove dialog but keep listener in place so that we know if/when it is set visible - handleRemovedDialog((Dialog)obj, false); - } - } - - public void componentShown(ComponentEvent e) { - assert e != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("Component shown"); - Object obj = e.getSource(); - if (obj instanceof Dialog) { - handleAddedDialog((Dialog)obj); - } - } - - public void componentResized(ComponentEvent e) { - } - - public void componentMoved(ComponentEvent e) { - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/AwtEnvironment.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/AwtEnvironment.java deleted file mode 100644 index ff016ffeb..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/AwtEnvironment.java +++ /dev/null @@ -1,339 +0,0 @@ -package com.eco.bio7.image.swtawtutil; - -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ - - -import java.awt.EventQueue; -import java.awt.Frame; -import java.lang.reflect.InvocationTargetException; - -import javax.swing.UIManager; -import javax.swing.UnsupportedLookAndFeelException; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.SWTException; -import org.eclipse.swt.awt.SWT_AWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - - - -/** - * An environment to enable the proper display of AWT/Swing windows within a SWT or RCP - * application. This class extends the base {@link org.eclipse.swt.awt.SWT_AWT Eclipse SWT/AWT integration} - * support by - * - * Using the platform-specific system Look and Feel. - * Ensuring AWT modal dialogs are modal across the SWT application. - * Working around various AWT/Swing bugs - * - * - * This class is most helpful to applications which create new AWT/Swing windows (e.g. dialogs) rather - * than those which embed AWT/Swing components in SWT windows. For support specific to embedding - * AWT/Swing components see {@link EmbeddedSwingComposite}. - * - * There is at most one instance of this class per SWT - * {@link org.eclipse.swt.widgets.Display Display}. In almost all applications - * this means that there is exactly one instance for the entire application. In fact, the - * current implementation always limits the number of instances to exactly one. - * - * An instance of this class can be obtained with the static - * {@link #getInstance(Display)} method. -*/ -public final class AwtEnvironment { - // TODO: add pop-up dismissal and font synchronization support to this level? - - private static final String GTK_LOOK_AND_FEEL_NAME = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; //$NON-NLS-1$ - - private static AwtEnvironment instance = null; - private static boolean isLookAndFeelInitialized = false; - - private final Display display; - private final AwtDialogListener dialogListener; - - /** - * Returns the single instance of AwtEnvironment for the given display. On - * the first call to this method, the necessary initialization to allow - * AWT/Swing code to run properly within an Eclipse application is done. - * This initialization includes setting the approprite look and feel and - * registering the necessary listeners to ensure proper behavior of modal - * dialogs. - * - * The first call to this method must occur before any AWT/Swing APIs are - * called. - * - * The current implementation limits the number of instances of - * AwtEnvironment to one. If this method is called with a display different - * to one used on a previous call, {@link UnsupportedOperationException} is - * thrown. - * - * @param display - * the non-null SWT display - * @return the AWT environment - * @exception IllegalArgumentException - * - * ERROR_NULL_ARGUMENT - if the display is null - * - * @exception UnsupportedOperationException - - * on attempt to use multiple displays. - */ - public static AwtEnvironment getInstance(Display display) { - // For now assume a single display. If necessary, this implementation - // can be changed to create multiple environments for multiple display - // applications. - // TODO: add multiple display support - if (display == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - if ((instance != null) && !display.equals(instance.display)) { - throw new UnsupportedOperationException("Multiple displays not supported"); - } - synchronized (AwtEnvironment.class) { - if (instance == null) { - instance = new AwtEnvironment(display); - } - } - return instance; - } - - // Private constructor - clients use getInstance() to obtain instances - private AwtEnvironment(Display display) { - assert display != null; - - /* - * This property removes a large amount of flicker from embedded swing - * components. Ideally it would not be set until EmbeddedSwingComposite - * is used, but since its value is read once and cached by AWT, it needs - * to be set before any AWT/Swing APIs are called. - */ - // TODO: this is effective only on Windows. - System.setProperty("sun.awt.noerasebackground", "true"); //$NON-NLS-1$//$NON-NLS-2$ - - /* - * RCP apps always want the standard platform look and feel It's - * important to wait for the L&F to be set so that any subsequent calls - * to createFrame() will be return a frame with the proper L&F (note - * that createFrame() happens on the SWT thread). - * - * The call to invokeAndWait is safe because - * the first call AwtEnvironment.getInstance should happen - * before any (potential deadlocking) activity occurs on the - * AWT thread. - */ - try { - EventQueue.invokeAndWait(new Runnable() { - public void run() { - setSystemLookAndFeel(); - } - }); - } catch (InterruptedException e) { - SWT.error(SWT.ERROR_FAILED_EXEC, e); - } catch (InvocationTargetException e) { - SWT.error(SWT.ERROR_FAILED_EXEC, e); - } - - this.display = display; - - // Listen for AWT modal dialogs to make them modal application-wide - dialogListener = new AwtDialogListener(display); - } - - /** - * Invokes the given runnable in the AWT event thread while blocking user - * input on the SWT event thread. The SWT event thread will remain blocked - * until the runnable task completes, at which point this method will - * return. - * - * This method is useful for displayng modal AWT/Swing dialogs from the SWT - * event thread. The modal AWT/Swing dialog will always block input across - * the whole application, but not until it appears. By calling this method, - * it is guaranteed that SWT input is blocked immediately, even before the - * AWT/Swing dialog appears. - * - * To avoid unnecessary flicker, AWT/Swing dialogs should have their parent - * set to a frame returned by {@link #createDialogParentFrame()}. - * - * This method must be called from the SWT event thread. - * - * @param runnable - * the code to schedule on the AWT event thread - * @exception IllegalArgumentException - * - * ERROR_NULL_ARGUMENT - if the runnable is null - * - * @exception SWTException - * - * ERROR_THREAD_INVALID_ACCESS - if not called from the - * SWT event thread - * - */ - public void invokeAndBlockSwt(final Runnable runnable) { - assert display != null; - - /* - * This code snippet is based on the following thread on - * news.eclipse.platform.swt: - * http://dev.eclipse.org/newslists/news.eclipse.platform.swt/msg24234.html - */ - if (runnable == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - if (display != Display.getCurrent()) { - SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS); - } - - // Switch to the AWT thread... - EventQueue.invokeLater(new Runnable() { - public void run() { - try { - // do swing work... - runnable.run(); - } finally { - display.asyncExec(new Runnable() { - public void run() { - // Unblock SWT - SwtInputBlocker.unblock(); - } - }); - } - } - }); - - // Prevent user input on SWT components - SwtInputBlocker.block(); - } - - /** - * Creates an AWT frame suitable as a parent for AWT/Swing dialogs. - * - * This method must be called from the SWT event thread. There must be an active - * shell associated with the environment's display. - * - * The created frame is a non-visible child of the active shell and will be disposed when that shell - * is disposed. - * - * See {@link #createDialogParentFrame(Shell)} for more details. - * - * @return a {@link java.awt.Frame} to be used for parenting dialogs - * @exception SWTException - * - * ERROR_THREAD_INVALID_ACCESS - if not called from the - * SWT event thread - * - * @exception IllegalStateException - * if the current display has no shells - */ - public Frame createDialogParentFrame() { - if (display != Display.getCurrent()) { - SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS); - } - Shell parent = display.getActiveShell(); - if (parent == null) { - throw new IllegalStateException("No Active Shell"); - } - return createDialogParentFrame(parent); - } - - /** - * Creates an AWT frame suitable as a parent for AWT/Swing dialogs. - * - * This method must be called from the SWT event thread. There must be an active - * shell associated with the environment's display. - * - * The created frame is a non-visible child of the given shell and will be disposed when that shell - * is disposed. - * - * This method is useful for creating a frame to parent any AWT/Swing - * dialogs created for use inside a SWT application. A modal AWT/Swing - * dialogs will flicker less if its parent is set to the returned frame - * rather than to null or to an independently created {@link java.awt.Frame}. - * - * @return a {@link java.awt.Frame} to be used for parenting dialogs - * @exception SWTException - * - * ERROR_THREAD_INVALID_ACCESS - if not called from the - * SWT event thread - * - * @exception IllegalStateException - * if the current display has no shells - */ - public Frame createDialogParentFrame(Shell parent) { - if (parent == null) { - SWT.error(SWT.ERROR_NULL_ARGUMENT); - } - if (display != Display.getCurrent()) { - SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS); - } - Shell shell = new Shell(parent); - shell.setVisible(false); - Composite composite = new Composite(shell, SWT.EMBEDDED); - return SWT_AWT.new_Frame(composite); - } - - // Find a shell to use, giving preference to the active shell. - Shell getShell() { - Shell shell = display.getActiveShell(); - if (shell == null) { - Shell[] allShells = display.getShells(); - if (allShells.length > 0) { - shell = allShells[0]; - } - } - return shell; - } - - void requestAwtDialogFocus() { - assert dialogListener != null; - - dialogListener.requestFocus(); - } - - private void setSystemLookAndFeel() { - assert EventQueue.isDispatchThread(); // On AWT event thread - - if (!isLookAndFeelInitialized) { - isLookAndFeelInitialized = true; - try { - String systemLaf = UIManager.getSystemLookAndFeelClassName(); - String xplatLaf = UIManager.getCrossPlatformLookAndFeelClassName(); - - // Java makes metal the system look and feel if running under a - // non-gnome Linux desktop. Fix that here, if the RCP itself is - // running - // with the GTK windowing system set. - if (xplatLaf.equals(systemLaf) && Platform.isGtk()) { - systemLaf = GTK_LOOK_AND_FEEL_NAME; - } - UIManager.setLookAndFeel(systemLaf); - } catch (ClassNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InstantiationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (UnsupportedLookAndFeelException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - // This method is called by unit tests - static void reset() { - instance = null; - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/AwtFocusHandler.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/AwtFocusHandler.java deleted file mode 100644 index d307ecff4..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/AwtFocusHandler.java +++ /dev/null @@ -1,254 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import java.awt.Component; -import java.awt.Container; -import java.awt.EventQueue; -import java.awt.FocusTraversalPolicy; -import java.awt.Frame; -import java.awt.Window; -import java.awt.event.ContainerEvent; -import java.awt.event.ContainerListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; -import java.awt.event.WindowEvent; -import java.awt.event.WindowFocusListener; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.swing.JPopupMenu; -import javax.swing.text.Caret; -import javax.swing.text.JTextComponent; - -class AwtFocusHandler implements FocusListener, ContainerListener, - WindowFocusListener { - - private final Frame frame; - private SwtFocusHandler swtHandler; - private boolean awtHasFocus = false; - private Component currentComponent = null; - - AwtFocusHandler(Frame frame) { - assert frame != null; - - this.frame = frame; - frame.addContainerListener(new RecursiveContainerListener(this)); - frame.addWindowFocusListener(this); - } - - void setSwtHandler(SwtFocusHandler handler) { - assert handler != null; - assert swtHandler == null; // this method is meant to be called once - - swtHandler = handler; - } - - void gainFocus() { - assert frame != null; - // assert !awtHasFocus; - assert EventQueue.isDispatchThread(); // On AWT event thread - - FocusTraversalPolicy policy = frame.getFocusTraversalPolicy(); - Component component; - if (policy instanceof EmbeddedChildFocusTraversalPolicy) { - EmbeddedChildFocusTraversalPolicy embeddedPolicy = (EmbeddedChildFocusTraversalPolicy) policy; - component = embeddedPolicy.getCurrentComponent(frame); - } else { - // TODO: direction based? - component = policy.getDefaultComponent(frame); - } - if (component != null) { - // System.out.println("Requesting focus for component: " + component); - component.requestFocus(); - // TODO: else case error? If not, consider moving flag setting below into this if - } - awtHasFocus = true; - } - - /** - * Moves focus back to the next SWT component - */ - void transferFocusNext() { - assert swtHandler != null; - assert awtHasFocus; - - awtHasFocus = false; - swtHandler.gainFocusNext(); - } - - /** - * Moves focus back to the previous SWT component - */ - void transferFocusPrevious() { - assert swtHandler != null; - assert awtHasFocus; - - awtHasFocus = false; - swtHandler.gainFocusPrevious(); - } - - boolean awtHasFocus() { - return awtHasFocus; - } - - Component getCurrentComponent() { - return currentComponent; - } - - // ..................... Listener implementations - - public void focusGained(FocusEvent e) { - assert e != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("gained (awt). component = " + e.getComponent() + ", opposite = " + e.getOppositeComponent()); - currentComponent = e.getComponent(); - } - - public void focusLost(FocusEvent e) { - // System.out.println("component focus lost (awt). opposite = " + e.getOppositeComponent()); - - // Intentionally leaving currentComponent set. When window focus is lost, - // it will be needed. - } - - public void componentAdded(ContainerEvent e) { - assert e != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - e.getChild().addFocusListener(this); - } - - public void componentRemoved(ContainerEvent e) { - assert e != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - e.getChild().removeFocusListener(this); - } - - public void windowGainedFocus(WindowEvent e) { - assert EventQueue.isDispatchThread(); // On AWT event thread - // System.out.println("WindowFocusListener.windowGainedFocus"); - awtHasFocus = true; - } - - public void windowLostFocus(WindowEvent e) { - assert e != null; - assert swtHandler != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("WindowFocusListener.windowLostFocus"); - - // Dismiss any popup menus that are - // open when losing focus. This prevents situations where - // multiple popup menus are visible at the same time. In JDK 1.4 and earlier, - // the dismissal is not done automatically. In JDK 1.5, this code is - // unnecessary, but it doesn't seem to hurt anything. - // TODO: verify this is OK on other windowing systems - // TODO: disable in post-1.4 environments - /* boolean popupShown = */hidePopups(); - - // If focus is being lost to the parent SWT composite, then - // grab it back for AWT and return. Normally the parent SWT composite will - // do this for us, but it will not see a focus gained event when focus - // is transferred to it from its AWT frame child. - // This happens, for example, if an AWT control has focus and the - // tab of a containing (already active) view is clicked. - // - // However, don't grab back focus if a popup was hidden above. The popup - // area will not be properly redrawn (the popup, or part of it, will - // appear to be still there. - //if (!popupShown && swtHandler.hasFocus()) { - // System.out.println("**** Taking back focus: " + e); - // This seems to have side effects, so it's commented out for now. - // (Sometimes, it forces the workbench window to the foreground when another - // program's window is selected.) - // TODO: find an alternate approach to reassert focus - // gainFocus(); - // return; - //} - - // On a normal change of focus, Swing will turn off any selection - // in a text field to help indicate focus is lost. This won't happen - // automatically when transferring to SWT, so turn off the selection - // manually. - if (currentComponent instanceof JTextComponent) { - Caret caret = ((JTextComponent)currentComponent).getCaret(); - if (caret != null) { - caret.setSelectionVisible(false); - } - } - awtHasFocus = false; - } - - // Returns true if any popup has been hidden - private boolean hidePopups() { - boolean result = false; - List popups = new ArrayList(); - assert EventQueue.isDispatchThread(); // On AWT event thread - - // Look for popups inside the frame's component hierarchy. - // Lightweight popups will be found here. - findContainedPopups(frame, popups); - - // Also look for popups in the frame's window hierachy. - // Heavyweight popups will be found here. - findOwnedPopups(frame, popups); - - // System.out.println("Hiding popups, count=" + popups.size()); - for (Iterator iter = popups.iterator(); iter.hasNext();) { - Component popup = (Component)iter.next(); - if (popup.isVisible()) { - result = true; - popup.setVisible(false); - } - } - return result; - } - - private void findOwnedPopups(Window window, List popups) { - assert window != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - Window[] ownedWindows = window.getOwnedWindows(); - for (int i = 0; i < ownedWindows.length; i++) { - findContainedPopups(ownedWindows[i], popups); - findOwnedPopups(ownedWindows[i], popups); - } - } - - private void findContainedPopups(Container container, List popups) { - assert container != null; - assert popups != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - Component[] components = container.getComponents(); - for (int i = 0; i < components.length; i++) { - Component c = components[i]; - // JPopupMenu is a container, so check for it first - if (c instanceof JPopupMenu) { - popups.add(c); - } else if (c instanceof Container) { - findContainedPopups((Container)c, popups); - } - } - } - - void postHidePopups() { - EventQueue.invokeLater(new Runnable() { - public void run() { - hidePopups(); - } - }); - } -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/CleanResizeListener.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/CleanResizeListener.java deleted file mode 100644 index d37d00128..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/CleanResizeListener.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.eco.bio7.image.swtawtutil; - -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ - -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; - -class CleanResizeListener extends ControlAdapter { - private Rectangle oldRect = null; - public void controlResized(ControlEvent e) { - assert e != null; - assert Display.getCurrent() != null; // On SWT event thread - - // Prevent garbage from Swing lags during resize. Fill exposed areas - // with background color. - Composite composite = (Composite)e.widget; - //Rectangle newRect = composite.getBounds(); - //newRect = composite.getDisplay().map(composite.getParent(), composite, newRect); - Rectangle newRect = composite.getClientArea(); - if (oldRect != null) { - int heightDelta = newRect.height - oldRect.height; - int widthDelta = newRect.width - oldRect.width; - if ((heightDelta > 0) || (widthDelta > 0)) { - GC gc = new GC(composite); - try { - gc.fillRectangle(newRect.x, oldRect.height, newRect.width, heightDelta); - gc.fillRectangle(oldRect.width, newRect.y, widthDelta, newRect.height); - } finally { - gc.dispose(); - } - } - } - oldRect = newRect; - } -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/EmbeddedChildFocusTraversalPolicy.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/EmbeddedChildFocusTraversalPolicy.java deleted file mode 100644 index 3a4aa9b22..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/EmbeddedChildFocusTraversalPolicy.java +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import java.awt.Component; -import java.awt.Container; -import java.awt.EventQueue; - -import javax.swing.LayoutFocusTraversalPolicy; - -class EmbeddedChildFocusTraversalPolicy extends LayoutFocusTraversalPolicy { - - private static final long serialVersionUID = -7708166698501335927L; - private final AwtFocusHandler awtHandler; - - EmbeddedChildFocusTraversalPolicy(AwtFocusHandler handler) { - assert handler != null; - awtHandler = handler; - } - - public Component getComponentAfter(Container container, Component component) { - assert container != null; - assert component != null; - assert awtHandler != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - if (component.equals(getLastComponent(container))) { - // Instead of cycling around to the first component, transfer to the next SWT component - awtHandler.transferFocusNext(); - return null; - } else { - return super.getComponentAfter(container, component); - } - } - - public Component getComponentBefore(Container container, Component component) { - assert container != null; - assert component != null; - assert awtHandler != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - if (component.equals(getFirstComponent(container))) { - // Instead of cycling around to the last component, transfer to the previous SWT component - awtHandler.transferFocusPrevious(); - return null; - } else { - return super.getComponentBefore(container, component); - } - } - - public Component getDefaultComponent(Container container) { - assert container != null; - assert awtHandler != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // This is a hack which depends on knowledge of current JDK implementation to - // work. The implementation above of getComponentBefore/After - // properly returns null when transferring to SWT. However, the calling AWT container - // will then immediately try this method to find the next recipient of - // focus. But we don't want *any* AWT component to receive focus... it's just - // been transferred to SWT. So, this method must return null when AWT does - // not own the focus. When AWT *does* own the focus, behave normally. - if (awtHandler.awtHasFocus()) { - // System.out.println("getDefault: super"); - return super.getDefaultComponent(container); - } else { - // System.out.println("getDefault: null"); - return null; - } - } - - public Component getCurrentComponent(Container container) { - assert container != null; - assert awtHandler != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - Component currentAwtComponent = awtHandler.getCurrentComponent(); - if ((currentAwtComponent != null) && container.isAncestorOf(currentAwtComponent)){ - return currentAwtComponent; - } else { - return getDefaultComponent(container); - } - } -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/EmbeddedSwingComposite.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/EmbeddedSwingComposite.java deleted file mode 100644 index 5d7c610bc..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/EmbeddedSwingComposite.java +++ /dev/null @@ -1,480 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import java.awt.Container; -import java.awt.EventQueue; -import java.awt.Frame; -import java.awt.Toolkit; - -import javax.swing.JApplet; -import javax.swing.JComponent; -import javax.swing.RootPaneContainer; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.plaf.FontUIResource; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.SWTException; -import org.eclipse.swt.awt.SWT_AWT; -import org.eclipse.swt.graphics.Font; -import org.eclipse.swt.graphics.FontData; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Widget; - -/** - * A SWT composite widget for embedding Swing components in a SWT composite within an RCP or standalone-SWT application. The Eclipse platform - * provides limited support for embedding Swing components through {@link org.eclipse.swt.awt.SWT_AWT}. - * This class extends that support by - * - * Using the platform-specific system Look and Feel. - * Ensuring AWT modal dialogs are modal across the SWT application. - * Reducing flicker, especially on window resizes - * Allowing Tab Traversal to and from the Embedded Frame - * Dismissing most Pop-Up Menus when focus leaves the AWT frame. - * Synchronizing Font Changes from system settings - * Working around various AWT/Swing bugs - * - * - * If, rather than embedding Swing components, you are integrating with Swing by opening - * Swing dialogs, see the {@link AwtEnvironment} class. - * - * This is an abstract that is normally used by extending it and implementing the {@link #createSwingComponent()} method. For example, - * - * embeddedComposite = new EmbeddedSwingComposite(parent, SWT.NONE) { - * protected JComponent createSwingComponent() { - * scrollPane = new JScrollPane(); - * table = new JTable(); - * scrollPane.setViewportView(table); - * return scrollPane; - * } - * }; - * embeddedComposite.populate(); - * - * - * The Swing component is created inside a standard Swing containment hierarchy, rooted in - * a {@link javax.swing.RootPaneContainer}. The root pane container is placed inside an AWT frame, as - * returned by {@link org.eclipse.swt.awt.SWT_AWT#new_Frame(Composite)} - * - * Note: When you mix components from Swing/AWT and SWT toolkits, there will be two UI event threads, - * one for AWT, one for SWT. Most SWT APIs require that you call them from the SWT thread. Swing - * has similar restrictions though it does not enforce them as much as SWT. - * - * Applications need to be aware of the current thread, and, where necessary, schedule tasks to run - * on another thread. This has always been required in the pure Swing or SWT environments, but when - * mixing Swing and SWT, more of this scheduling will be necessary. - * - * To schedule work on the AWT event - * thread, you can use: - * - * {@link javax.swing.SwingUtilities#invokeLater(Runnable)} - * {@link javax.swing.SwingUtilities#invokeAndWait(Runnable)} - * - * - * (or similar methods in {@link java.awt.EventQueue}) - * - * To schedule work on the SWT event thread, use: - * - * {@link org.eclipse.swt.widgets.Display#asyncExec(Runnable)} - * {@link org.eclipse.swt.widgets.Display#syncExec(Runnable)} - * - * - * Of course, as in single-toolkit environments, long-running tasks should be offloaded from either UI - * thread to a background thread. The Eclipse jobs API can be used for this purpose. - */ -public abstract class EmbeddedSwingComposite extends Composite { - private static class AwtContext { - private Frame frame; - private JComponent swingComponent; - - AwtContext(Frame frame) { - assert frame != null; - this.frame = frame; - } - - Frame getFrame() { - return frame; - } - - void setSwingComponent(JComponent swingComponent) { - this.swingComponent = swingComponent; - } - - JComponent getSwingComponent() { - return swingComponent; - } - - } - private Font currentSystemFont; - private AwtContext awtContext; - private AwtFocusHandler awtHandler; - - private Listener settingsListener = new Listener() { - public void handleEvent(Event event) { - handleSettingsChange(); - } - }; - - // This listener helps ensure that Swing popup menus are properly dismissed when - // a menu item off the SWT main menu bar is shown. - private final Listener menuListener = new Listener() { - public void handleEvent(Event event) { - assert awtHandler != null; - - awtHandler.postHidePopups(); - } - }; - - /** - * Constructs a new instance of this class given its parent - * and a style value describing its behavior and appearance. - * - * This method must be called from the SWT event thread. - * - * The style value is either one of the style constants defined in - * class SWT which is applicable to instances of this - * class, or must be built by bitwise OR'ing together - * (that is, using the int "|" operator) two or more - * of those SWT style constants. The class description - * lists the style constants that are applicable to the class. - * Style bits are also inherited from superclasses. - * - * - * The styles SWT.EMBEDDED and SWT.NO_BACKGROUND will be added - * to the specified style. Usually, no other style bits are needed. - * - * @param parent a widget which will be the parent of the new instance (cannot be null) - * @param style the style of widget to construct - * - * @exception IllegalArgumentException - * ERROR_NULL_ARGUMENT - if the parent is null - * - * @exception SWTException - * ERROR_THREAD_INVALID_ACCESS - if not called from the SWT event thread - * - * - * @see Widget#getStyle - */ - public EmbeddedSwingComposite(Composite parent, int style) { - super(parent, style | SWT.EMBEDDED | SWT.NO_BACKGROUND); - getDisplay().addListener(SWT.Settings, settingsListener); - setLayout(new FillLayout()); - currentSystemFont = getFont(); - } - - /** - * Populates the embedded composite with the Swing component. - * - * This method must be called from the - * SWT event thread. - * - * The Swing component will be created by calling {@link #createSwingComponent()}. The creation is - * scheduled asynchronously on the AWT event thread. This method does not wait for completion of this - * asynchronous task, so it may return before createSwingComponent() is complete. - * - * The Swing component is created inside a standard Swing containment hierarchy, rooted in - * a {@link javax.swing.RootPaneContainer}. Clients can override {@link #addRootPaneContainer(Frame)} - * to provide their own root pane container implementation. - * - * This method can be called multiple times for a single instance. If an embedded frame exists from - * a previous call, it is disposed. - * - * @exception SWTException - * ERROR_WIDGET_DISPOSED - if the receiver has been disposed - * ERROR_THREAD_INVALID_ACCESS - if not called from the SWT event thread - * - */ - public void populate() { - checkWidget(); - createFrame(); - scheduleComponentCreation(); - } - - /** - * Creates the embedded Swing component. This method is called from the AWT event thread. - * - * Implement this method to provide the Swing component that will be shown inside this composite. - * The returned component will be added to the Swing content pane. At least one component must - * be created by this method; null is not a valid return value. - * - * @return a non-null Swing component - */ - protected abstract JComponent createSwingComponent(); - - /** - * Adds a root pane container to the embedded AWT frame. Override this to provide your own - * {@link javax.swing.RootPaneContainer} implementation. In most cases, it is not necessary - * to override this method. - * - * This method is called from the AWT event thread. - * - * If you are defining your own root pane container, make sure that there is at least one - * heavyweight (AWT) component in the frame's containment hierarchy; otherwise, event - * processing will not work correctly. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4982522 - * for more information. - * - * @param frame the frame to which the root pane container is added - * @return a non-null Swing component - */ - protected RootPaneContainer addRootPaneContainer(Frame frame) { - assert EventQueue.isDispatchThread(); // On AWT event thread - assert frame != null; - - // It is important to set up the proper top level components in the frame: - // 1) For Swing to work properly, Sun documents that there must be an implementor of - // javax.swing.RootPaneContainer at the top of the component hierarchy. - // 2) For proper event handling there must be a heavyweight - // an AWT frame must contain a heavyweight component (see - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4982522) - // 3) The Swing implementation further narrows the options by expecting that the - // top of the hierarchy be a JFrame, JDialog, JWindow, or JApplet. See javax.swing.PopupFactory. - // All this drives the choice of JApplet for the top level Swing component. It is the - // only single component that satisfies all the above. This does not imply that - // we have a true applet; in particular, there is no notion of an applet lifecycle in this - // context. - JApplet applet = new JApplet(); - - // In JRE 1.4, the JApplet makes itself a focus cycle root. This - // interferes with the focus handling installed on the parent frame, so - // change it back to a non-root here. - // TODO: consider moving the focus policy from the Frame down to the JApplet - applet.setFocusCycleRoot(false); - - frame.add(applet); - - return applet; - } - - /** - * Performs custom updates to newly set fonts. This method is called whenever a change - * to the system font through the system settings (i.e. control panel) is detected. - * - * This method is called from the AWT event thread. - * - * In most cases it is not necessary to override this method. Normally, the implementation - * of this class will automatically propogate font changes to the embedded Swing components - * through Swing's Look and Feel support. However, if additional - * special processing is necessary, it can be done inside this method. - * - * @param newFont New AWT font - */ - protected void updateAwtFont(java.awt.Font newFont) { - } - - /** - * Returns the embedded AWT frame. The returned frame is the root of the AWT containment - * hierarchy for the embedded Swing component. This method can be called from - * any thread. - * - * @return the embedded frame - */ - public Frame getFrame() { - // Intentionally leaving out checkWidget() call. This may need to be called from within user's - // createSwingComponent() method. Accessing from a non-SWT thread is OK, but we still check - // for disposal - if (getDisplay() == null || isDisposed()) { - SWT.error(SWT.ERROR_WIDGET_DISPOSED); - } - - return (awtContext != null) ? awtContext.getFrame() : null; - } - - private void createFrame() { - assert Display.getCurrent() != null; // On SWT event thread - - // Make sure Awt environment is initialized. - AwtEnvironment.getInstance(getDisplay()); - - if (awtContext != null) { - final Frame oldFrame = awtContext.getFrame(); - // Schedule disposal of old frame on AWT thread so that there are no problems with - // already-scheduled operations that have not completed. - // Note: the implementation of Frame.dispose() would schedule the use of the AWT - // thread even if it was not done here, but it uses invokeAndWait() which is - // prone to deadlock (and not necessary for this case). - EventQueue.invokeLater(new Runnable() { - public void run() { - oldFrame.dispose(); - } - }); - } - Frame frame = SWT_AWT.new_Frame(this); - awtContext = new AwtContext(frame); - - // Glue the two frameworks together. Do this before anything is added to the frame - // so that all necessary listeners are in place. - createFocusHandlers(); - - // This listener clears garbage during resizing, making it looker much cleaner - addControlListener(new CleanResizeListener()); - } - - private void createFocusHandlers() { - assert awtContext != null; - assert Display.getCurrent() != null; // On SWT event thread - - Frame frame = awtContext.getFrame(); - awtHandler = new AwtFocusHandler(frame); - SwtFocusHandler swtHandler = new SwtFocusHandler(this); - awtHandler.setSwtHandler(swtHandler); - swtHandler.setAwtHandler(awtHandler); - - // Ensure that AWT popups are dimissed whenever a SWT menu is shown - getDisplay().addFilter(SWT.Show, menuListener); - - EmbeddedChildFocusTraversalPolicy policy = new EmbeddedChildFocusTraversalPolicy(awtHandler); - frame.setFocusTraversalPolicy(policy); - } - - private void scheduleComponentCreation() { - assert awtContext != null; - - // Create AWT/Swing components on the AWT thread. This is - // especially necessary to avoid an AWT leak bug (6411042). - final AwtContext currentContext = awtContext; - EventQueue.invokeLater(new Runnable() { - public void run() { - - RootPaneContainer container = addRootPaneContainer(currentContext.getFrame()); - JComponent swingComponent = createSwingComponent(); - currentContext.setSwingComponent(swingComponent); - container.getRootPane().getContentPane().add(swingComponent); - setComponentFont(); - } - }); - } - - private void setComponentFont() { - assert currentSystemFont != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - JComponent swingComponent = (awtContext != null) ? awtContext.getSwingComponent() : null; - if ((swingComponent != null) && !currentSystemFont.getDevice().isDisposed()) { - FontData fontData = currentSystemFont.getFontData()[0]; - - // AWT font sizes assume a 72 dpi resolution, always. The true screen resolution must be - // used to convert the platform font size into an AWT point size that matches when displayed. - int resolution = Toolkit.getDefaultToolkit().getScreenResolution(); - int awtFontSize = (int)Math.round((double)fontData.getHeight() * resolution / 72.0); - - // The style constants for SWT and AWT map exactly, and since they are int constants, they should - // never change. So, the SWT style is passed through as the AWT style. - java.awt.Font awtFont = new java.awt.Font(fontData.getName(), fontData.getStyle(), awtFontSize); - - // Update the look and feel defaults to use new font. - updateLookAndFeel(awtFont); - - // Allow subclasses to react to font change if necessary. - updateAwtFont(awtFont); - - // Allow components to update their UI based on new font - // TODO: should the update method be called on the root pane instead? - Container contentPane = swingComponent.getRootPane().getContentPane(); - SwingUtilities.updateComponentTreeUI(contentPane); - } - } - - private void updateLookAndFeel(java.awt.Font awtFont) { - assert awtFont != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // The FontUIResource class marks the font as replaceable by the look and feel - // implementation if font settings are later changed. - FontUIResource fontResource = new FontUIResource(awtFont); - - // Assign the new font to the relevant L&F font properties. These are - // the properties that are initially assigned to the system font - // under the Windows look and feel. - // TODO: It's possible that other platforms will need other assignments. - // TODO: This does not handle fonts other than the "system" font. - // Other fonts may change, and the Swing L&F may not be adjusting. - - UIManager.put("Button.font", fontResource); //$NON-NLS-1$ - UIManager.put("CheckBox.font", fontResource); //$NON-NLS-1$ - UIManager.put("ComboBox.font", fontResource); //$NON-NLS-1$ - UIManager.put("EditorPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("Label.font", fontResource); //$NON-NLS-1$ - UIManager.put("List.font", fontResource); //$NON-NLS-1$ - UIManager.put("Panel.font", fontResource); //$NON-NLS-1$ - UIManager.put("ProgressBar.font", fontResource); //$NON-NLS-1$ - UIManager.put("RadioButton.font", fontResource); //$NON-NLS-1$ - UIManager.put("ScrollPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("TabbedPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("Table.font", fontResource); //$NON-NLS-1$ - UIManager.put("TableHeader.font", fontResource); //$NON-NLS-1$ - UIManager.put("TextField.font", fontResource); //$NON-NLS-1$ - UIManager.put("TextPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("TitledBorder.font", fontResource); //$NON-NLS-1$ - UIManager.put("ToggleButton.font", fontResource); //$NON-NLS-1$ - UIManager.put("TreeFont.font", fontResource); //$NON-NLS-1$ - UIManager.put("ViewportFont.font", fontResource); //$NON-NLS-1$ - } - - private void handleSettingsChange() { - Font newFont = getDisplay().getSystemFont(); - if (!newFont.equals(currentSystemFont)) { - currentSystemFont = newFont; - EventQueue.invokeLater(new Runnable() { - public void run() { - setComponentFont(); - } - }); - } - } - - private boolean isFocusable() { - if (awtContext == null) { - return false; - } - JComponent swingComponent = awtContext.getSwingComponent(); - return (swingComponent != null) && swingComponent.isFocusable(); - } - - /* (non-Javadoc) - * @see org.eclipse.swt.widgets.Control#setFocus() - */ - public boolean setFocus() { - checkWidget(); - - if (!isFocusable()) { - return false; - } - return super.setFocus(); - } - - /* (non-Javadoc) - * @see org.eclipse.swt.widgets.Control#forceFocus() - */ - public boolean forceFocus() { - checkWidget(); - - if (!isFocusable()) { - return false; - } - return super.forceFocus(); - } - - /* (non-Javadoc) - * @see org.eclipse.swt.widgets.Widget#dispose() - */ - public void dispose() { - if (!isDisposed()) { - getDisplay().removeListener(SWT.Settings, settingsListener); - getDisplay().removeFilter(SWT.Show, menuListener); - super.dispose(); - } - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/Platform.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/Platform.java deleted file mode 100644 index 0c511ca97..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/Platform.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import org.eclipse.swt.SWT; - -class Platform { - private static String platformString = SWT.getPlatform(); - - // prevent instantiation - private Platform() { - } - - public static boolean isWin32() { - return "win32".equals(platformString); //$NON-NLS-1$ - } - - public static boolean isGtk() { - return "gtk".equals(platformString); //$NON-NLS-1$ - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/RecursiveContainerListener.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/RecursiveContainerListener.java deleted file mode 100644 index cd9ddd12a..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/RecursiveContainerListener.java +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import java.awt.Component; -import java.awt.Container; -import java.awt.EventQueue; -import java.awt.event.ContainerEvent; -import java.awt.event.ContainerListener; - -class RecursiveContainerListener implements ContainerListener { - private final ContainerListener listener; - - RecursiveContainerListener(ContainerListener listener) { - assert listener != null; - - this.listener = listener; - } - - private void handleAdd(Container source, Component c) { - assert source != null; - assert c != null; - assert listener != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("Listening to: " + c); - listener.componentAdded(new ContainerEvent(source, ContainerEvent.COMPONENT_ADDED, c)); - if (c instanceof Container) { - ((Container)c).addContainerListener(this); - } - } - - private void handleRemove(Container source, Component c) { - assert source != null; - assert c != null; - assert listener != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("Stopped Listening to: " + c); - listener.componentRemoved(new ContainerEvent(source, ContainerEvent.COMPONENT_REMOVED, c)); - if (c instanceof Container) { - ((Container)c).removeContainerListener(this); - } - } - - private void handleAllAdds(Container source, Component child) { - assert source != null; - assert child != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - if (child instanceof Container) { - Container container = (Container)child; - Component[] children = container.getComponents(); - for (int i = 0; i < children.length; i++) { - handleAllAdds(container, children[i]); - } - } - handleAdd(source, child); - } - - private void handleAllRemoves(Container source, Component child) { - assert source != null; - assert child != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - if (child instanceof Container) { - Container container = (Container)child; - Component[] children = container.getComponents(); - for (int i = 0; i < children.length; i++) { - handleAllRemoves(container, children[i]); - } - } - handleRemove(source, child); - - } - - public void componentAdded(ContainerEvent e) { - assert e != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - Container source = (Container)e.getSource(); - handleAllAdds(source, e.getChild()); - } - - public void componentRemoved(ContainerEvent e) { - assert e != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - Container source = (Container)e.getSource(); - handleAllRemoves(source, e.getChild()); - } -} - diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtFocusHandler.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtFocusHandler.java deleted file mode 100644 index 055386166..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtFocusHandler.java +++ /dev/null @@ -1,153 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import java.awt.EventQueue; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -public class SwtFocusHandler implements FocusListener, KeyListener { - - private final Composite composite; - private final Display display; - private AwtFocusHandler awtHandler; - - public SwtFocusHandler(Composite composite) { - assert composite != null; - assert Display.getCurrent() != null; // On SWT event thread - - this.composite = composite; - display = composite.getDisplay(); - composite.addFocusListener(this); - composite.addKeyListener(this); - } - - void setAwtHandler(AwtFocusHandler handler) { - assert handler != null; - assert awtHandler == null; // this method is meant to be called once - assert composite != null; - assert Display.getCurrent() != null; // On SWT event thread - - awtHandler = handler; - - // Dismiss Swing popups when the main window is moved. (It would be - // better to dismiss popups whenever the titlebar is clicked, but - // there does not seem to be a way.) - final ControlAdapter controlAdapter = new ControlAdapter() { - public void controlMoved(ControlEvent e) { - assert awtHandler != null; - awtHandler.postHidePopups(); - } - }; - final Shell shell = composite.getShell(); - shell.addControlListener(controlAdapter); - - // Cleanup listeners on dispose - composite.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - shell.removeControlListener(controlAdapter); - } - }); - } - - void gainFocusNext() { - traverse(SWT.TRAVERSE_TAB_NEXT); - } - - void gainFocusPrevious() { - traverse(SWT.TRAVERSE_TAB_PREVIOUS); - } - - private void traverse(final int traversal) { - assert composite != null; - - // Tab from the containing SWT component while - // running on the SWT thread - Runnable r = new Runnable() { - public void run() { - composite.traverse(traversal); - } - }; - display.asyncExec(r); - } - -// boolean hasFocus() { -// assert composite != null; -// -// // This will return true if the composite has focus, or if any -// // foreign (e.g. AWT) child of the composite has focus. -// if (display.isDisposed()) { -// return false; -// } -// final boolean[] result = new boolean[1]; -// display.syncExec(new Runnable() { -// public void run() { -// result[0] = (!composite.isDisposed() && -// (display.getFocusControl() == composite)); -// } -// }); -// return result[0]; -// } - - // ..................... Listener implementations - - public void focusGained(FocusEvent e) { - assert awtHandler != null; - assert Display.getCurrent() != null; // On SWT event thread - - // System.out.println("Gained: " + e.toString() + " (" + e.widget.getClass().getName() + ")"); - EventQueue.invokeLater(new Runnable() { - public void run() { - awtHandler.gainFocus(); - } - }); - } - - public void focusLost(FocusEvent e) { - // System.out.println("Lost: " + e.toString() + " (" + e.widget.getClass().getName() + ")"); - } - - public void keyPressed(KeyEvent e) { - assert Display.getCurrent() != null; // On SWT event thread - - // If the embedded swing root pane has no components to receive focus, - // then there will be cases where the parent SWT composite will keep - // focus. (For example, when tabbing into the root pane container). - // By default, in these cases, the focus is swallowed by the Composite - // and never escapes. This code allows tab and back-tab to do the - // proper traversal to other SWT components from the composite. - // TODO: other keys? - if (e.keyCode == SWT.TAB) { - // TODO: In some cases, this gobbles up all the tabs, even from AWT children. Find a more selective way. - /*if (e.stateMask == SWT.NONE) { - traverse(SWT.TRAVERSE_TAB_NEXT); - } else if (e.stateMask == SWT.SHIFT) { - traverse(SWT.TRAVERSE_TAB_PREVIOUS); - }*/ - } - } - - public void keyReleased(KeyEvent e) { - } - - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtInputBlocker.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtInputBlocker.java deleted file mode 100644 index 94de23801..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtInputBlocker.java +++ /dev/null @@ -1,111 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusAdapter; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.widgets.Dialog; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - - - -class SwtInputBlocker extends Dialog { - static private SwtInputBlocker instance = null; - static private int blockCount = 0; - private Shell shell; - - private SwtInputBlocker(Shell parent) { - super(parent, SWT.NONE); - } - - private Object open() { - assert Display.getCurrent() != null; // On SWT event thread - - final Shell parent = getParent(); - shell = new Shell(parent, SWT.APPLICATION_MODAL); - shell.setSize(0, 0); - shell.addFocusListener(new FocusAdapter() { - public void focusGained(FocusEvent e) { - // On some platforms (e.g. Linux/GTK), the 0x0 shell still appears as a dot - // on the screen, so make it invisible by moving it below other windows. This - // is unnecessary under Windows and causes a flash, so only make the call when necessary. - if (Platform.isGtk()) { - shell.moveBelow(null); - } - AwtEnvironment.getInstance(shell.getDisplay()).requestAwtDialogFocus(); - } - }); - shell.open(); - - Display display = parent.getDisplay(); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - return null; - } - - private void close() { - assert shell != null; - - shell.dispose(); - } - - static void unblock() { - assert blockCount >= 0; - assert Display.getCurrent() != null; // On SWT event thread - - - // System.out.println("Deleting SWT blocker"); - if (blockCount == 0) { - return; - } - if ((blockCount == 1) && (instance != null)) { - instance.close(); - instance = null; - } - blockCount--; - } - - static void block() { - assert blockCount >= 0; - - // System.out.println("Creating SWT blocker"); - final Display display = Display.getCurrent(); - assert display != null; // On SWT event thread - - blockCount++; - if (blockCount == 1) { - assert instance == null; // should be no existing blocker - - // get a shell to parent the blocking dialog - Shell shell = AwtEnvironment.getInstance(display).getShell(); - - // If there is a shell to block, block input now. If there are no shells, - // then there is no input to block. In the case of no shells, we are not - // protecting against a shell that might get created later. This is a rare - // enough case to skip, at least for now. In the future, a listener could be - // added to cover it. - // TODO: if (shell==null) add listener to block shells created later? - // - // Block is implemented with a hidden modal dialog. Using setEnabled(false) is another option, but - // on some platforms that will grey the disabled controls. - if (shell != null) { - instance = new SwtInputBlocker(shell); - instance.open(); - } - } - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/Thumbnail.java b/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/Thumbnail.java index a354c6094..93ac402e0 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/Thumbnail.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/Thumbnail.java @@ -31,7 +31,7 @@ public class Thumbnail extends Figure implements UpdateListener { // Bug on Mac - images are cached - private static final boolean useMacFix = Util.isMac() && com.eco.bio7.image.Util.compareOSVersion("10.14") >= 0;; + private static final boolean useMacFix = Util.isMac() && com.eco.bio7.image.ui.Util.compareOSVersion("10.14") >= 0;; // Hack for Mac Mojave drawing issue diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/ThumbnailsView.java b/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/ThumbnailsView.java index 504a55804..72aa19cba 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/ThumbnailsView.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/ThumbnailsView.java @@ -27,7 +27,6 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import javax.swing.JPanel; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -72,8 +71,8 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.Util; +import com.eco.bio7.image.ui.CanvasView; +import com.eco.bio7.image.ui.Util; import ij.IJ; import ij.ImagePlus; import ij.ImageStack; @@ -421,11 +420,10 @@ public void run() { } else if (fileExtension.equals(".lut")) { ImagePlus plus = null; ImageData imageData = null; - Opener.setErrorMessage(false); setThumbSize(); String pathParent = Util.getImageJPath().replace("\\", "/"); /* Apply a LUT on the example image. Will be scaled afterwards! */ - plus = IJ.openImage(pathParent + "/src/images/lut200.tif"); + plus = openSilent(pathParent + "/src/images/lut200.tif"); if (plus != null) { LUT lut = Opener.openLut(files[i].getAbsolutePath()); @@ -460,7 +458,6 @@ public void run() { plus = null; imageData = null; - Opener.setErrorMessage(true); /* We handle *.zip files extra to also detect ROI Sets! */ } else if (fileExtension.equals(".zip")) { boolean zipRoi = false; @@ -485,8 +482,7 @@ public void run() { } } else { - Opener.setErrorMessage(false); - ImagePlus plus = IJ.openImage(files[i].getAbsolutePath()); + ImagePlus plus = openSilent(files[i].getAbsolutePath()); createFromImagePlus(plus, fileExtension, files[i]); } } @@ -495,16 +491,14 @@ public void run() { * stack! */ else if (fileExtension.equals(".tif") || fileExtension.equals(".TIF") || fileExtension.equals(".TIFF")) { - Opener.setErrorMessage(false); // ImagePlus plus = IJ.openImage(files[i].getAbsolutePath(), 1); not used since // the conversion results in a single images, no stack anymore and wrong color! - ImagePlus plus = IJ.openImage(files[i].getAbsolutePath()); + ImagePlus plus = openSilent(files[i].getAbsolutePath()); createFromImagePlus(plus, fileExtension, files[i]); } /* All other supported image types are handled here! */ else { - Opener.setErrorMessage(false); - ImagePlus plus = IJ.openImage(files[i].getAbsolutePath()); + ImagePlus plus = openSilent(files[i].getAbsolutePath()); createFromImagePlus(plus, fileExtension, files[i]); } @@ -516,7 +510,7 @@ else if (fileExtension.equals(".tif") || fileExtension.equals(".TIF") || fileExt * type! */ public void actionPerformed(ActionEvent arg0) { - if (com.eco.bio7.image.CanvasView.getCanvas_view() != null) { + if (com.eco.bio7.image.ui.CanvasView.getCanvas_view() != null) { Job job = new Job("Open...") { @Override protected IStatus run(IProgressMonitor monitor) { @@ -544,10 +538,6 @@ public void run() { } }); - JPanel current = CanvasView.getCurrent(); - if (current != null) { - current.doLayout(); - } } monitor.done(); @@ -617,8 +607,14 @@ public void run() { } + /* Opens an image without error dialogs (unsupported files are skipped)! */ + private static ImagePlus openSilent(String path) { + Opener opener = new Opener(); + opener.setSilentMode(true); + return opener.openImage(path); + } + public void createFromImagePlus(ImagePlus plus, String fileExtension, File file) { - Opener.setErrorMessage(true); ImageData imageData; Image im = null; if (plus != null) { diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/Activator.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Activator.java similarity index 94% rename from com.eco.bio7.image/src/com/eco/bio7/image/Activator.java rename to com.eco.bio7.image/src/com/eco/bio7/image/ui/Activator.java index 0553cdb43..a74e27e10 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/Activator.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Activator.java @@ -10,7 +10,7 @@ *******************************************************************************/ -package com.eco.bio7.image; +package com.eco.bio7.image.ui; import org.eclipse.ui.plugin.*; import org.eclipse.core.resources.IWorkspace; diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/Bio7ImageJ.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Bio7ImageJ.java new file mode 100644 index 000000000..b06e9155e --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Bio7ImageJ.java @@ -0,0 +1,332 @@ +/******************************************************************************* + * Copyright (c) 2007-2026 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ +package com.eco.bio7.image.ui; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.osgi.framework.Bundle; + +import ij.IJ; +import ij.ImageJ; +import ij.ImageListener; +import ij.ImagePlus; +import ij.Menus; +import ij.Prefs; +import ij.gui.ImageWindow; +import ij.swt.ImageJHost; + +/** + * Embeds SWTImageJ in Bio7. Image windows are created inside a holder composite + * which is displayed in a tab of the ImageJ-Canvas view ({@link CanvasView}) or + * in a detached view ({@link CustomDetachedImageJView}). The holder composite is + * the editor parent of the image (see {@link ImagePlus#getEditorParent()}) and + * is moved, not recreated, when an image is detached. + * + * @author M. Austenfeld + */ +public class Bio7ImageJ implements ImageJHost, ImageListener { + + private static Bio7ImageJ instance; + + /* See ij.plugin.Compiler! */ + private static final String COMPILER_TARGET_KEY = "javac.target"; + + private static final int COMPILER_TARGET = 25; + + private Bio7ImageJ() { + } + + /** + * Installs ImageJ in Bio7 (host callbacks, plugins path, ImageJ instance). Can + * be called several times. Must be called in the SWT UI thread. + */ + public static synchronized void install() { + if (instance != null) { + return; + } + instance = new Bio7ImageJ(); + setPluginsDirectory(); + addBundlesToCompilerClassPath(); + IJ.setHost(instance); + ImagePlus.addImageListener(instance); + /* F2 displays the current image in fullscreen mode (ESC closes it)! */ + Util.getDisplay().addFilter(SWT.KeyDown, Fullscreen.KEY_FILTER); + if (IJ.getInstance() == null) { + /* The ImageJ shell is never shown. Bio7 displays toolbar and menus! */ + new ImageJ(ImageJ.NO_SHOW); + } + setCompilerTarget(); + } + + /* + * SWTImageJ uses /plugins and /macros. The Bio7 + * preferences store the plugins folder itself. + */ + private static void setPluginsDirectory() { + if (System.getProperty("plugins.dir") != null) { + return; + } + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + File plugins = new File(store.getString("PLUGINS_PATH")); + if (plugins.isDirectory() && plugins.getParentFile() != null) { + System.setProperty("plugins.dir", plugins.getParentFile().getAbsolutePath()); + } else { + System.setProperty("plugins.dir", Util.getImageJPath()); + } + } + + /* + * Plugins are compiled for Java 25 by default (SWTImageJ uses Java 8). The + * preference must be set after ImageJ has loaded the preferences and before + * the compiler class is loaded. A target selected in "Compile and Run" options + * (other than the old default 8) is kept! + */ + private static void setCompilerTarget() { + int target = (int) Prefs.get(COMPILER_TARGET_KEY, 0); + if (target == 0 || target == 8) { + Prefs.set(COMPILER_TARGET_KEY, COMPILER_TARGET); + } + } + + /* + * The ImageJ compiler (Compile and Run, Script Explorer) uses the + * "java.class.path" property which only contains the OSGi launcher. Add the + * ImageJ, SWT and Bio7 image bundles so that plugins can be compiled! + */ + private static void addBundlesToCompilerClassPath() { + Bundle self = Activator.getDefault().getBundle(); + for (Bundle bundle : self.getBundleContext().getBundles()) { + String name = bundle.getSymbolicName(); + if (name == null || !(name.startsWith("org.eclipse.swt") || bundle == self)) { + continue; + } + try { + File file = FileLocator.getBundleFile(bundle); + if (file.isDirectory()) { + /* A bundle in the workspace (development) or an unpacked bundle! */ + boolean classes = false; + for (String folder : new String[] { "bin", "target/classes" }) { + File dir = new File(file, folder); + if (dir.isDirectory()) { + Menus.addExtraClassPathDirectory(dir.getAbsolutePath()); + classes = true; + } + } + if (!classes) { + Menus.addExtraClassPathDirectory(file.getAbsolutePath()); + } + } else { + Menus.addExtraClassPathDirectory(file.getAbsolutePath()); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * Returns the holder composite of an image displayed in Bio7 or null. + */ + public static Composite getHolder(ImagePlus imp) { + if (imp == null) { + return null; + } + Composite holder = imp.getEditorParent(); + if (holder == null || holder.isDisposed()) { + return null; + } + return holder; + } + + /** + * Returns the tab of the ImageJ-Canvas view which displays the image or null + * (e.g., if the image is displayed in a detached view). Must be called in the + * SWT UI thread. + */ + public static CTabItem getTab(ImagePlus imp) { + Composite holder = getHolder(imp); + if (holder == null || CanvasView.tabFolder == null || CanvasView.tabFolder.isDisposed()) { + return null; + } + for (CTabItem item : CanvasView.tabFolder.getItems()) { + if (item.getControl() == holder) { + return item; + } + } + return null; + } + + /** + * Creates a new holder composite for an image in the given parent. + */ + static Composite createHolder(Composite parent, ImagePlus imp) { + Composite holder = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, true); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + holder.setLayout(layout); + /* Close the image if the holder is disposed (tab or view closed)! */ + holder.addDisposeListener(e -> { + ImageWindow win = imp.getWindow(); + if (win != null && !win.isClosed() && imp.getEditorParent() == holder) { + win.close(); + } + }); + return holder; + } + + @Override + public Composite getImageParent(ImagePlus imp) { + CanvasView view = CanvasView.getCanvas_view(); + if (view == null || CanvasView.tabFolder == null || CanvasView.tabFolder.isDisposed()) { + showView(CanvasView.ID); + view = CanvasView.getCanvas_view(); + } + if (view == null || CanvasView.tabFolder == null || CanvasView.tabFolder.isDisposed()) { + /* Fallback: ImageJ opens a separate shell! */ + return null; + } + return view.createImageTab(imp); + } + + @Override + public void titleChanged(ImageWindow win, String title) { + ImagePlus imp = win.getImagePlus(); + CTabItem item = getTab(imp); + if (item != null) { + item.setText(title); + return; + } + CustomDetachedImageJView detached = CustomDetachedImageJView.find(imp); + if (detached != null) { + detached.setPartName(title); + } + } + + @Override + public void toFront(ImageWindow win) { + ImagePlus imp = win.getImagePlus(); + CTabItem item = getTab(imp); + IWorkbenchPage page = getPage(); + if (item != null) { + CanvasView.tabFolder.setSelection(item); + CanvasView.getCanvas_view().tabSelected(item); + if (page != null) { + page.bringToTop(CanvasView.getCanvas_view()); + } + return; + } + CustomDetachedImageJView detached = CustomDetachedImageJView.find(imp); + if (detached != null && page != null) { + page.bringToTop(detached); + } + } + + @Override + public void showStatus(String message) { + Display display = Util.getDisplay(); + display.asyncExec(() -> { + CanvasView view = CanvasView.getCanvas_view(); + if (view != null) { + view.setstatusline(message); + } + }); + } + + @Override + public void imageOpened(ImagePlus imp) { + } + + @Override + public void imageClosed(ImagePlus imp) { + /* Remove the tab or detached view of a closed image! */ + Util.getDisplay().asyncExec(() -> { + Composite holder = getHolder(imp); + if (holder == null) { + return; + } + ImageWindow win = imp.getWindow(); + /* ImageJ also calls this if a window has been replaced (e.g., RGB to stack)! */ + if (win != null && !win.isClosed()) { + return; + } + if (Fullscreen.isFullscreen(holder)) { + Fullscreen.exit(); + } + CTabItem item = getTab(imp); + CustomDetachedImageJView detached = CustomDetachedImageJView.find(imp); + if (item != null) { + item.dispose(); + } + if (detached != null) { + IWorkbenchPage page = detached.getSite().getPage(); + page.hideView(detached); + } + if (!holder.isDisposed()) { + holder.dispose(); + } + }); + } + + @Override + public void imageUpdated(ImagePlus imp) { + /* Display the image information (size, type, etc.) in the status line! */ + Util.getDisplay().asyncExec(() -> { + CanvasView view = CanvasView.getCanvas_view(); + ImageWindow win = imp.getWindow(); + if (view != null && win != null && !win.isClosed() && ij.WindowManager.getCurrentImage() == imp) { + view.setstatusline(win.createSubtitle()); + } + }); + } + + static IWorkbenchPage getPage() { + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) { + IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); + if (windows.length == 0) { + return null; + } + window = windows[0]; + } + return window.getActivePage(); + } + + private static IViewPart showView(String id) { + IWorkbenchPage page = getPage(); + if (page == null) { + return null; + } + try { + return page.showView(id, null, IWorkbenchPage.VIEW_VISIBLE); + } catch (PartInitException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/CanvasView.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/CanvasView.java new file mode 100644 index 000000000..59e6d7f79 --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/CanvasView.java @@ -0,0 +1,423 @@ +/******************************************************************************* + * Copyright (c) 2004-2026 M. Austenfeld + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ + +package com.eco.bio7.image.ui; + +import java.io.File; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.StatusLineManager; +import org.eclipse.jface.action.SubContributionManager; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.custom.CTabFolder; +import org.eclipse.swt.custom.CTabFolder2Adapter; +import org.eclipse.swt.custom.CTabFolderEvent; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.dnd.DropTargetAdapter; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.ViewPart; +import org.eclipse.ui.preferences.ScopedPreferenceStore; + +import com.eco.bio7.ImageJPluginActions.ImageJAnalyzeAction; +import com.eco.bio7.ImageJPluginActions.ImageJEditAction; +import com.eco.bio7.ImageJPluginActions.ImageJFileAction; +import com.eco.bio7.ImageJPluginActions.ImageJHelp; +import com.eco.bio7.ImageJPluginActions.ImageJImageAction; +import com.eco.bio7.ImageJPluginActions.ImageJPluginsAction; +import com.eco.bio7.ImageJPluginActions.ImageJProcessAction; +import com.eco.bio7.ImageJPluginActions.ImageJWindowAction; + +import ij.IJ; +import ij.ImagePlus; +import ij.WindowManager; +import ij.gui.ImageWindow; +import ij.plugin.CommandLister; +import ij.plugin.DragAndDrop; + +/** + * The ImageJ-Canvas view. Each image is displayed in a tab. The control of a + * tab is the holder composite of the image (see {@link Bio7ImageJ}) and the tab + * data is the {@link ImagePlus}. + */ +public class CanvasView extends ViewPart { + public static int insertMark = -1; + + public static final String ID = "com.eco.bio7.imagej"; + + public static Composite parent2; + + private ImageJFileAction file; + + private ImageJEditAction edit; + + private ImageJImageAction image; + + private ImageJProcessAction process; + + private ImageJAnalyzeAction analyze; + + private ImageJPluginsAction plugins; + + private ImageJWindowAction window; + + private ImageJHelp help; + + protected String[] fileList; + + protected ImagePlus plu; + + protected ImageWindow win; + + private static CanvasView canvas_view; + + public static CTabFolder tabFolder; + + public CanvasView() { + super(); + canvas_view = this; + } + + /** + * Lays out the view (kept for compatibility). + */ + public void updatePlotCanvas() { + recalculateLayout(); + } + + /** + * Lays out the view and the displayed image. + */ + public void recalculateLayout() { + Util.getDisplay().syncExec(() -> { + if (parent2 != null && !parent2.isDisposed()) { + parent2.layout(true, true); + } + }); + } + + public void layoutParent(Composite parent) { + Util.getDisplay().syncExec(() -> { + if (!parent.isDisposed()) { + parent.layout(true, true); + } + }); + } + + public void createPartControl(Composite parent) { + parent2 = parent; + /* Creates the ImageJ instance and registers Bio7 as the ImageJ host! */ + Bio7ImageJ.install(); + + parent.addDisposeListener(e -> { + /* Save the ImageJ preferences when the view is closed! */ + try { + ij.Prefs.savePreferences(); + } catch (RuntimeException ex) { + ex.printStackTrace(); + } + }); + + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "com.eco.bio7.imagej"); + + parent.addControlListener(new ControlAdapter() { + @Override + public void controlResized(final ControlEvent e) { + updatePlotDeviceSize(parent.getClientArea(), tabFolder != null && !tabFolder.isDisposed() ? tabFolder.getTabHeight() + 40 : 0); + } + }); + + file = new ImageJFileAction(); + edit = new ImageJEditAction(); + image = new ImageJImageAction(); + process = new ImageJProcessAction(); + analyze = new ImageJAnalyzeAction(); + plugins = new ImageJPluginsAction(); + window = new ImageJWindowAction(); + help = new ImageJHelp(); + + initializeToolBar(); + tabFolder = new CTabFolder(parent, SWT.TOP); + /* Get access to the ImageJ drag and drop methods! */ + DragAndDrop dragAndDrop = new DragAndDrop(); + DropTarget dt = new DropTarget(tabFolder, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY); + dt.setTransfer(new Transfer[] { FileTransfer.getInstance() }); + dt.addDropListener(new DropTargetAdapter() { + public void drop(DropTargetEvent event) { + FileTransfer ft = FileTransfer.getInstance(); + if (ft.isSupportedType(event.currentDataType)) { + fileList = (String[]) event.data; + Job job = new Job("Open...") { + @Override + protected IStatus run(IProgressMonitor monitor) { + monitor.beginTask("Opening...", fileList.length); + for (int i = 0; i < fileList.length; i++) { + dragAndDrop.openFile(new File(fileList[i])); + monitor.worked(1); + } + monitor.done(); + return Status.OK_STATUS; + } + }; + job.schedule(); + } + } + }); + + CommandLister hotkeys = new CommandLister(); + String[] shortcuts = hotkeys.getShortcuts(); + + tabFolder.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + runShortcut(shortcuts, e); + } + }); + + tabFolder.setBorderVisible(true); + + tabFolder.addCTabFolder2Listener(new CTabFolder2Adapter() { + public void close(final CTabFolderEvent event) { + /* Disposing the holder closes the image (see Bio7ImageJ)! */ + Control holder = ((CTabItem) event.item).getControl(); + if (holder != null && !holder.isDisposed()) { + holder.dispose(); + } + } + }); + tabFolder.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + tabSelected((CTabItem) e.item); + } + }); + tabFolder.addMouseListener(new MouseAdapter() { + + public void mouseDown(MouseEvent mouseevent) { + CTabFolder ctab = (CTabFolder) mouseevent.widget; + if (mouseevent.count == 1) { + if (ctab.getItemCount() <= 0) { + tabFolder.setFocus(); + } else if (ctab.getSelection() != null) { + tabSelected(ctab.getSelection()); + } + } else if (mouseevent.button == 3 && mouseevent.count > 1) { + /* Detach the image of the selected tab in a view! */ + CTabItem item = ctab.getSelection(); + if (item != null && item.getData() instanceof ImagePlus) { + CustomDetachedImageJView.detach((ImagePlus) item.getData(), null); + } + } + } + }); + } + + /* + * Here we write the values in the com.eco.bio7 plugin preferences with the help + * of scoped preferences (R plots are created with the size of the view)! + */ + static void updatePlotDeviceSize(Rectangle rec, int correction) { + IPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, "com.eco.bio7"); + String selection = store.getString("PLOT_DEVICE_SELECTION"); + String pathTo = store.getString("pathTempR"); + if (selection.equals("PLOT_IMAGEJ_DISPLAYSIZE_CAIRO")) { + store.setValue("DEVICE_DEFINITION", ".bio7Device <- function(filename = \"" + pathTo + "tempDevicePlot%05d.tiff" + "\") { tiff(filename,width = " + (rec.width - 20) + + ", height = " + (rec.height - correction) + ", type=\"cairo\")}; options(device=\".bio7Device\")"); + } else if (selection.equals("PLOT_IMAGEJ_DISPLAYSIZE")) { + store.setValue("DEVICE_DEFINITION", ".bio7Device <- function(filename = \"" + pathTo + "tempDevicePlot%05d.tiff" + "\") { tiff(filename,width = " + (rec.width - 20) + + ", height = " + (rec.height - correction) + ", units = \"px\")}; options(device=\".bio7Device\")"); + } + } + + private void runShortcut(String[] shortcuts, KeyEvent e) { + for (int i = 0; i < shortcuts.length; i++) { + String[] splitShortcut = shortcuts[i].split("\t"); + if (splitShortcut.length < 2) { + continue; + } + String key = splitShortcut[0].trim(); + if (key.equals("" + e.character)) { + IJ.doCommand(splitShortcut[1]); + } + /* Also allow the F keys for a shortcut! */ + for (int f = 1; f <= 20; f++) { + if (key.equals("F" + f) && e.keyCode == SWT.F1 + f - 1) { + IJ.doCommand(splitShortcut[1]); + } + } + } + } + + /** + * Creates a new tab for the given image and returns the holder composite in + * which the image window is created. + */ + Composite createImageTab(ImagePlus imp) { + CTabItem item = new CTabItem(tabFolder, SWT.CLOSE, Math.max(0, Math.min(insertMark + 1, tabFolder.getItemCount()))); + Composite holder = Bio7ImageJ.createHolder(tabFolder, imp); + item.setControl(holder); + item.setData(imp); + item.setText(imp.getTitle()); + tabFolder.showItem(item); + tabFolder.setSelection(item); + plu = imp; + return holder; + } + + /** + * Makes the image of the given tab the current ImageJ image. + */ + public void tabSelected(CTabItem item) { + if (item == null || !(item.getData() instanceof ImagePlus)) { + return; + } + plu = (ImagePlus) item.getData(); + win = plu.getWindow(); + if (win != null && !win.isClosed()) { + WindowManager.setTempCurrentImage(plu); + WindowManager.setCurrentWindow(win); + setstatusline(win.createSubtitle()); + } + } + + public void setstatusline(String message) { + IActionBars bars = getViewSite().getActionBars(); + bars.getStatusLineManager().setMessage(message); + } + + public void setStatusLineColor(String message, org.eclipse.swt.graphics.Color col) { + IActionBars bars = getViewSite().getActionBars(); + bars.getStatusLineManager().setMessage(message); + IStatusLineManager statusLineManager = bars.getStatusLineManager(); + if (statusLineManager instanceof SubContributionManager) { + SubContributionManager sub = (SubContributionManager) statusLineManager; + StatusLineManager parent = (StatusLineManager) sub.getParent(); + Composite composite = (Composite) parent.getControl(); + Control[] controls = composite.getChildren(); + for (Control control : controls) { + if (control instanceof CLabel) { + CLabel cLabel = (CLabel) control; + cLabel.setForeground(col); + break; + } + } + } + } + + private void initializeToolBar() { + IToolBarManager tbm = getViewSite().getActionBars().getToolBarManager(); + tbm.add(file); + tbm.add(edit); + tbm.add(image); + tbm.add(process); + tbm.add(analyze); + tbm.add(plugins); + tbm.add(window); + tbm.add(help); + /* If we have a plugin which installs a main menu item! */ + updateBio7ImageJMenu(); + } + + private static boolean isDefaultMenu(String name) { + return name.equals("File") || name.equals("Edit") || name.equals("Image") || name.equals("Process") || name.equals("Analyze") || name.equals("Plugins") || name.equals("Window") + || name.equals("Help"); + } + + /** + * Adds the additional ImageJ main menus (e.g., installed by a plugin) to the + * toolbar of the view. + */ + public static void updateBio7ImageJMenu() { + Util.getDisplay().asyncExec(() -> { + CanvasView canvasView = getCanvas_view(); + org.eclipse.swt.widgets.Menu menuBar = ij.Menus.getMenuBar(); + if (canvasView == null || menuBar == null || menuBar.isDisposed()) { + return; + } + IToolBarManager tbm = canvasView.getViewSite().getActionBars().getToolBarManager(); + for (org.eclipse.jface.action.IContributionItem item : tbm.getItems()) { + if (item.getId() != null && !isDefaultMenu(item.getId())) { + tbm.remove(item); + } + } + for (org.eclipse.swt.widgets.MenuItem item : menuBar.getItems()) { + String name = item.getText().replace("&", ""); + if (!name.isEmpty() && !isDefaultMenu(name)) { + tbm.add(new com.eco.bio7.ImageJPluginActions.ImageJExtensionAction(name)); + } + } + tbm.update(true); + }); + } + + public void setFocus() { + if (tabFolder != null && !tabFolder.isDisposed()) { + tabFolder.setFocus(); + } + } + + public void dispose() { + if (canvas_view == this) { + canvas_view = null; + } + super.dispose(); + } + + public static CanvasView getCanvas_view() { + return canvas_view; + } + + /** + * Returns the holder composite of the selected tab or null. + * + * @return the composite which embeds the selected image. + */ + public static Composite getCurrent() { + if (tabFolder == null || tabFolder.isDisposed()) { + return null; + } + Display display = tabFolder.getDisplay(); + Composite[] current = new Composite[1]; + display.syncExec(() -> { + if (!tabFolder.isDisposed() && tabFolder.getSelection() != null) { + current[0] = (Composite) tabFolder.getSelection().getControl(); + } + }); + return current[0]; + } + + public static Composite getParent2() { + return parent2; + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/CustomDetachedImageJView.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/CustomDetachedImageJView.java new file mode 100644 index 000000000..52db19be3 --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/CustomDetachedImageJView.java @@ -0,0 +1,198 @@ +/******************************************************************************* + * Copyright (c) 2007-2026 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ +package com.eco.bio7.image.ui; + +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; +import org.eclipse.e4.ui.workbench.modeling.EModelService; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.ViewPart; + +import ij.ImagePlus; +import ij.WindowManager; +import ij.gui.ImageWindow; + +/** + * A view which displays a single image detached from the ImageJ-Canvas view. + * The secondary id of the view is the ImageJ id of the image. Closing the view + * closes the image. + * + * @author Bio7 + * + */ +public class CustomDetachedImageJView extends ViewPart { + + public static final String ID = "com.eco.bio7.image.detachedImage"; + + public Composite customViewParent; + + public ImagePlus plus; + + public ImageWindow win; + + private boolean isDetached; + + public boolean isDetached() { + return isDetached; + } + + public CustomDetachedImageJView() { + } + + /* Implement to overwrite function to set name! */ + public void setPartName(String partName) { + super.setPartName(partName); + } + + public void createPartControl(Composite parent) { + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "com.eco.bio7.imagej"); + this.customViewParent = parent; + parent.setLayout(new FillLayout()); + parent.addControlListener(new ControlAdapter() { + @Override + public void controlResized(final ControlEvent e) { + updateDetached(); + CanvasView.updatePlotDeviceSize(parent.getClientArea(), 0); + } + }); + updateDetached(); + } + + private void updateDetached() { + isDetached = customViewParent.getShell().getText().length() == 0; + } + + public void setFocus() { + if (plus != null) { + win = plus.getWindow(); + if (win != null && !win.isClosed()) { + WindowManager.setTempCurrentImage(plus); + WindowManager.setCurrentWindow(win); + setstatusline(win.createSubtitle()); + } + } + customViewParent.setFocus(); + } + + /** + * Lays out the view and the image. + */ + public void layout() { + if (customViewParent != null && !customViewParent.isDisposed()) { + customViewParent.layout(true, true); + } + } + + /** + * Returns the detached view which displays the image or null. Must be called + * in the SWT UI thread. + */ + public static CustomDetachedImageJView find(ImagePlus imp) { + if (imp == null) { + return null; + } + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (page == null) { + return null; + } + IViewPart view = findBySecondaryId(page, Integer.toString(imp.getID())); + if (view instanceof CustomDetachedImageJView) { + return (CustomDetachedImageJView) view; + } + return null; + } + + private static IViewPart findBySecondaryId(IWorkbenchPage page, String secId) { + org.eclipse.ui.IViewReference ref = page.findViewReference(ID, secId); + return ref != null ? ref.getView(false) : null; + } + + /** + * Moves the image from its tab into a new view. + * + * @param imp the image displayed in a tab of the ImageJ-Canvas view. + * @param rec location and size of a floating (detached) view or null. + * @return the view or null. + */ + public static CustomDetachedImageJView detach(ImagePlus imp, Rectangle rec) { + CustomDetachedImageJView[] result = new CustomDetachedImageJView[1]; + Util.getDisplay().syncExec(() -> { + CTabItem item = Bio7ImageJ.getTab(imp); + Composite holder = Bio7ImageJ.getHolder(imp); + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (item == null || holder == null || page == null) { + return; + } + try { + IViewPart activated = page.showView(ID, Integer.toString(imp.getID()), IWorkbenchPage.VIEW_ACTIVATE); + if (!(activated instanceof CustomDetachedImageJView)) { + return; + } + CustomDetachedImageJView view = (CustomDetachedImageJView) activated; + if (rec != null) { + IWorkbenchPartSite site = activated.getSite(); + EModelService s = site.getService(EModelService.class); + MPartSashContainerElement p = site.getService(MPart.class); + if (p.getCurSharedRef() != null) + p = p.getCurSharedRef(); + s.detach(p, rec.x, rec.y, rec.width, rec.height); + } + view.setImage(imp, item, holder); + result[0] = view; + } catch (PartInitException e) { + e.printStackTrace(); + } + }); + return result[0]; + } + + /* Moves the holder (with the ImageJ window) from the tab into this view! */ + private void setImage(ImagePlus imp, CTabItem item, Composite holder) { + this.plus = imp; + this.win = imp.getWindow(); + setPartName(imp.getTitle()); + item.setControl(null); + holder.setParent(customViewParent); + item.dispose(); + holder.setVisible(true); + customViewParent.layout(true, true); + setFocus(); + } + + public void dispose() { + /* Disposing the holder closes the image (see Bio7ImageJ)! */ + if (customViewParent != null && !customViewParent.isDisposed()) { + for (Control child : customViewParent.getChildren()) { + child.dispose(); + } + } + super.dispose(); + } + + public void setstatusline(String message) { + IActionBars bars = getViewSite().getActionBars(); + bars.getStatusLineManager().setMessage(message); + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/Fullscreen.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Fullscreen.java new file mode 100644 index 000000000..5d9ba6b9f --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Fullscreen.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2007-2026 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ +package com.eco.bio7.image.ui; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; + +import ij.ImagePlus; +import ij.WindowManager; + +/** + * Displays the current image in a fullscreen shell (toggled with F2, closed + * with ESC). The holder composite of the image is moved into the shell and back + * to the tab or view when the fullscreen mode is closed. + */ +public class Fullscreen { + + private static Shell shell; + private static Composite holder; + private static Composite oldParent; + private static CTabItem oldItem; + + /* Installed once by Bio7ImageJ! */ + static final Listener KEY_FILTER = new Listener() { + public void handleEvent(Event e) { + if (e.keyCode == SWT.F2) { + if (isActive()) { + exit(); + e.doit = false; + } else if (e.widget instanceof Control && isImageControl((Control) e.widget)) { + ImagePlus imp = WindowManager.getCurrentImage(); + if (imp != null) { + enter(imp); + e.doit = false; + } + } + } else if (e.keyCode == SWT.ESC && isActive()) { + /* The ESC key is also forwarded to ImageJ (abort macro or plugin)! */ + Display.getCurrent().asyncExec(Fullscreen::exit); + } + } + }; + + /* Returns true if the control is part of an embedded image window! */ + private static boolean isImageControl(Control control) { + for (Control c = control; c != null; c = c.getParent()) { + if (c instanceof ij.gui.ImageCanvas) { + return true; + } + } + return false; + } + + public static boolean isActive() { + return shell != null && !shell.isDisposed(); + } + + /** Returns true if the given holder is displayed in fullscreen mode. */ + static boolean isFullscreen(Composite imageHolder) { + return isActive() && holder == imageHolder; + } + + /** + * Displays the image in fullscreen mode. Must be called in the SWT UI thread. + */ + public static void enter(ImagePlus imp) { + if (isActive()) { + return; + } + holder = Bio7ImageJ.getHolder(imp); + if (holder == null) { + return; + } + oldParent = holder.getParent(); + oldItem = Bio7ImageJ.getTab(imp); + shell = new Shell(holder.getDisplay(), SWT.NO_TRIM | SWT.ON_TOP); + shell.setLayout(new FillLayout()); + shell.setBackground(holder.getDisplay().getSystemColor(SWT.COLOR_BLACK)); + shell.addListener(SWT.Close, e -> restore()); + if (oldItem != null) { + oldItem.setControl(null); + } + holder.setParent(shell); + holder.setVisible(true); + shell.setBounds(holder.getMonitor().getBounds()); + shell.setFullScreen(true); + shell.open(); + shell.layout(true, true); + if (imp.getCanvas() != null) { + imp.getCanvas().setFocus(); + } + } + + /** + * Closes the fullscreen mode. + */ + public static void exit() { + if (isActive()) { + shell.close(); + } + } + + /* Moves the holder back to the tab or view! */ + private static void restore() { + if (holder != null && !holder.isDisposed()) { + if (oldParent != null && !oldParent.isDisposed()) { + holder.setParent(oldParent); + if (oldItem != null && !oldItem.isDisposed()) { + oldItem.setControl(holder); + oldItem.getParent().setSelection(oldItem); + } + oldParent.layout(true, true); + } else { + /* The tab or view has been closed. Disposing closes the image! */ + holder.dispose(); + } + } + holder = null; + oldParent = null; + oldItem = null; + shell = null; + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJTabs.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJTabs.java new file mode 100644 index 000000000..d0ff63d0e --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJTabs.java @@ -0,0 +1,362 @@ +/******************************************************************************* + * Copyright (c) 2007-2026 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ + +package com.eco.bio7.image.ui; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; +import org.eclipse.e4.ui.workbench.modeling.EModelService; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IViewReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.PartInitException; + +import ij.ImagePlus; +import ij.WindowManager; +import ij.gui.ImageWindow; + +/** + * A class for the control of the ImageJ tabs. + * + * @author Bio7 + * + */ +public class IJTabs { + + private static Display getDisplay() { + return Util.getDisplay(); + } + + private static CTabItem[] getItems() { + if (CanvasView.tabFolder == null || CanvasView.tabFolder.isDisposed()) { + return new CTabItem[0]; + } + return CanvasView.tabFolder.getItems(); + } + + /** + * Returns the image displayed in the given tab. + * + * @param item a tab of the ImageJ view. + * @return the image or null. + */ + public static ImagePlus getImagePlus(CTabItem item) { + if (item != null && !item.isDisposed() && item.getData() instanceof ImagePlus) { + return (ImagePlus) item.getData(); + } + return null; + } + + /** + * Returns the image window displayed in the given tab. + * + * @param item a tab of the ImageJ view. + * @return the image window or null. + */ + public static ImageWindow getImageWindow(CTabItem item) { + ImagePlus imp = getImagePlus(item); + return imp != null ? imp.getWindow() : null; + } + + /** + * Returns the image of the selected tab. + * + * @return the image or null. + */ + public static ImagePlus getSelectedImagePlus() { + AtomicReference imp = new AtomicReference(); + getDisplay().syncExec(() -> { + if (CanvasView.tabFolder != null && !CanvasView.tabFolder.isDisposed()) { + imp.set(getImagePlus(CanvasView.tabFolder.getSelection())); + } + }); + return imp.get(); + } + + /** + * Returns the images of all tabs. + * + * @return a list of images. + */ + public static List getImagePlusList() { + List list = new ArrayList(); + getDisplay().syncExec(() -> { + for (CTabItem item : getItems()) { + ImagePlus imp = getImagePlus(item); + if (imp != null) { + list.add(imp); + } + } + }); + return list; + } + + /** + * Activates the tab with the specified number. + * + * @param number the number of the tab. + */ + public static void setActive(final int number) { + getDisplay().syncExec(() -> { + CTabItem[] items = getItems(); + if (number >= 0 && number < items.length) { + selectTab(items[number]); + } + }); + } + + private static void selectTab(CTabItem item) { + CanvasView.tabFolder.showItem(item); + CanvasView.tabFolder.setSelection(item); + CanvasView view = CanvasView.getCanvas_view(); + if (view != null) { + view.tabSelected(item); + } + } + + /** + * Returns the amount of opened tabs in the ImageJ view. + * + * @return the amount of tabs as an integer value. + */ + public static int getAmountTabs() { + AtomicReference count = new AtomicReference(0); + getDisplay().syncExec(() -> count.set(getItems().length)); + return count.get(); + } + + /** + * Detaches the view with the given secondary id (the image id) at the given + * location and size. + */ + public static void setSecondaryViewShellLocAndSize(String sec, Rectangle rec) { + getDisplay().syncExec(() -> { + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (page == null) { + return; + } + IViewReference ref = page.findViewReference(CustomDetachedImageJView.ID, sec); + if (ref == null) { + return; + } + try { + IViewPart activated = page.showView(CustomDetachedImageJView.ID, sec, IWorkbenchPage.VIEW_ACTIVATE); + if (rec != null && activated != null) { + IWorkbenchPartSite site = activated.getSite(); + EModelService s = site.getService(EModelService.class); + MPartSashContainerElement p = site.getService(MPart.class); + if (p.getCurSharedRef() != null) + p = p.getCurSharedRef(); + s.detach(p, rec.x, rec.y, rec.width, rec.height); + } + } catch (PartInitException e) { + e.printStackTrace(); + } + }); + } + + /** + * Closes all tabs in the ImageJ view (and all detached image views). + */ + public static void deleteAllTabs() { + getDisplay().syncExec(() -> { + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (page != null) { + for (IViewReference ref : page.getViewReferences()) { + if (ref.getId().equals(CustomDetachedImageJView.ID)) { + page.hideView(ref); + } + } + } + for (CTabItem item : getItems()) { + closeTab(item); + } + }); + } + + /* Disposing the holder closes the image (see Bio7ImageJ)! */ + private static void closeTab(CTabItem item) { + Control holder = item.getControl(); + if (holder != null && !holder.isDisposed()) { + holder.dispose(); + } + if (!item.isDisposed()) { + item.dispose(); + } + } + + /** + * Closes the tab (and the image) with the specified number in the ImageJ view. + * + * @param number the number of the tab as an integer value. + */ + public static void deleteTab(int number) { + getDisplay().syncExec(() -> { + CTabItem[] items = getItems(); + if (number >= 0 && number < items.length) { + closeTab(items[number]); + } + }); + } + + /** + * Closes the active tab in the ImageJ view. + * + * @deprecated Since the SWT port tabs can't be hidden without closing the + * image. Same as {@link #deleteActiveTab()}. + */ + @Deprecated + public static void hideTab() { + deleteActiveTab(); + } + + /** + * Closes the tab with the specified number in the ImageJ view. + * + * @param number the tab number. + * @deprecated Since the SWT port tabs can't be hidden without closing the + * image. Same as {@link #deleteTab(int)}. + */ + @Deprecated + public static void hideTabNumber(int number) { + deleteTab(number); + } + + /** + * Closes the tab which displays the given image. + * + * @param imagePlus the image. + * @deprecated Since the SWT port tabs can't be hidden without closing the + * image. Use {@link ImagePlus#close()}. + */ + @Deprecated + public static void hideTab(ImagePlus imagePlus) { + getDisplay().syncExec(() -> { + CTabItem item = Bio7ImageJ.getTab(imagePlus); + if (item != null) { + closeTab(item); + } + }); + } + + /** + * Deletes the active tab in the ImageJ view. + */ + public static void deleteActiveTab() { + getDisplay().syncExec(() -> { + if (CanvasView.tabFolder != null && !CanvasView.tabFolder.isDisposed()) { + CTabItem item = CanvasView.tabFolder.getSelection(); + if (item != null) { + closeTab(item); + } + } + }); + } + + /** + * Selects the tab which displays the image with the given title. + */ + public static void setActiveTab(String title) { + getDisplay().syncExec(() -> { + for (CTabItem item : getItems()) { + ImagePlus imp = getImagePlus(item); + if (imp != null && imp.getTitle().equals(title)) { + selectTab(item); + return; + } + } + }); + } + + /** + * Selects the tab which displays the image with the given ImageJ id (or index + * if the value is positive). + */ + public static void setActiveTabID(int theId) { + int id = theId > 0 ? WindowManager.getNthImageID(theId) : theId; + ImagePlus plus = WindowManager.getImage(id); + if (plus != null) { + getDisplay().syncExec(() -> { + CTabItem item = Bio7ImageJ.getTab(plus); + if (item != null) { + selectTab(item); + } + }); + } + } + + /** + * Selects the tab which displays the given image window. + */ + public static void setActiveTabWindow(ImageWindow win) { + if (win == null || win.getImagePlus() == null) { + return; + } + getDisplay().syncExec(() -> { + CTabItem item = Bio7ImageJ.getTab(win.getImagePlus()); + if (item != null) { + selectTab(item); + } + }); + } + + /** + * Lays out the detached image views (e.g. for orthogonal stack views)! + */ + public static void doSecondaryViewLayout() { + getDisplay().syncExec(() -> { + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (page == null) { + return; + } + for (IViewReference ref : page.getViewReferences()) { + if (ref.getId().equals(CustomDetachedImageJView.ID)) { + IViewPart view = ref.getView(false); + if (view instanceof CustomDetachedImageJView) { + ((CustomDetachedImageJView) view).layout(); + } + } + } + }); + } + + /** + * Closes the detached view which displays the given window. + * + * @return true if a detached view has been closed. + */ + public static boolean closeDetachedWindowView(ImageWindow refWin) { + AtomicBoolean result = new AtomicBoolean(false); + if (refWin == null) { + return false; + } + getDisplay().syncExec(() -> { + CustomDetachedImageJView view = CustomDetachedImageJView.find(refWin.getImagePlus()); + if (view != null) { + view.getSite().getPage().hideView(view); + result.set(true); + } + }); + return result.get(); + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJtoolbar.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJtoolbar.java new file mode 100644 index 000000000..99baf797d --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJtoolbar.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2007-2025 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ + +package com.eco.bio7.image.ui; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.part.ViewPart; + +import ij.IJ; +import ij.ImageJ; + +/** + * The ImageJ-Toolbar view. Displays the SWT toolbar, status line and progress + * bar of the ImageJ instance. The composite is moved back to the (hidden) + * ImageJ shell when the view is closed. + */ +public class IJtoolbar extends ViewPart { + + public static IJtoolbar instance; + + private Composite ijComposite; + + public IJtoolbar() { + instance = this; + } + + public void createPartControl(Composite parent) { + Bio7ImageJ.install(); + parent.setLayout(new FillLayout()); + ImageJ ij = IJ.getInstance(); + if (ij == null || ij.getComposite() == null || ij.getComposite().isDisposed()) { + return; + } + ijComposite = ij.getComposite(); + ijComposite.setParent(parent); + parent.layout(true, true); + /* The CSS theme is applied to the view after creation! */ + parent.getDisplay().asyncExec(() -> applyThemeColors(parent)); + /* The dispose event is sent before the children are disposed! */ + parent.addDisposeListener(e -> { + if (ijComposite != null && !ijComposite.isDisposed() && ij.getShell() != null && !ij.getShell().isDisposed()) { + ijComposite.setParent(ij.getShell()); + } + }); + } + + public void setFocus() { + if (ijComposite != null && !ijComposite.isDisposed()) { + applyThemeColors(ijComposite.getParent()); + ijComposite.setFocus(); + } + } + + /* + * The ImageJ toolbar uses the colors of its control. Apply the colors of the + * (themed) view, e.g., for the Bio7 dark theme! + */ + private void applyThemeColors(Composite parent) { + if (parent.isDisposed() || ijComposite == null || ijComposite.isDisposed()) { + return; + } + Color background = parent.getBackground(); + Color foreground = parent.getForeground(); + RGB b = background.getRGB(); + boolean darkBackground = (0.299 * b.red + 0.587 * b.green + 0.114 * b.blue) < 128; + if (Util.isThemeBlack() && !darkBackground) { + /* The view is not styled (yet). Use dark default colors! */ + background = new Color(47, 47, 47); + foreground = new Color(220, 220, 220); + } + setColors(ijComposite, background, foreground); + ijComposite.redraw(); + ijComposite.update(); + } + + private static void setColors(Control control, Color background, Color foreground) { + control.setBackground(background); + control.setForeground(foreground); + control.redraw(); + if (control instanceof Composite) { + for (Control child : ((Composite) control).getChildren()) { + setColors(child, background, foreground); + } + } + } + + public void dispose() { + if (instance == this) { + instance = null; + } + super.dispose(); + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ImageJBio7OpenEditor.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/ImageJBio7OpenEditor.java similarity index 94% rename from com.eco.bio7.image/src/com/eco/bio7/image/ImageJBio7OpenEditor.java rename to com.eco.bio7.image/src/com/eco/bio7/image/ui/ImageJBio7OpenEditor.java index 92ddb2acb..04963b422 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/ImageJBio7OpenEditor.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/ImageJBio7OpenEditor.java @@ -1,4 +1,4 @@ -package com.eco.bio7.image; +package com.eco.bio7.image.ui; import java.io.File; @@ -34,6 +34,7 @@ public class ImageJBio7OpenEditor extends EditorPart { public void createPartControl(Composite parent) { + Bio7ImageJ.install(); IFile file = ResourceUtil.getFile(input); fi = file.getRawLocation().toString(); diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/Util.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Util.java similarity index 66% rename from com.eco.bio7.image/src/com/eco/bio7/image/Util.java rename to com.eco.bio7.image/src/com/eco/bio7/image/ui/Util.java index ac01c330c..44e38d340 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/Util.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Util.java @@ -1,8 +1,5 @@ -package com.eco.bio7.image; +package com.eco.bio7.image.ui; -import java.awt.Color; -import java.awt.Font; -import java.awt.Toolkit; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -46,9 +43,6 @@ */ public class Util { - private static Font awtFont; - private static Color col = null; - /** * A method to get the ImageJ path. * @@ -70,112 +64,6 @@ public static String getImageJPath() { return path; } - /** - * A method to get the default OS font from SWT to AWT. - * - * @return the OS font as an AWT font. - */ - public static java.awt.Font getOSFontToAwt() { - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - int fontSizeCorrection = store.getInt("FONT_SIZE_CORRECTION"); - - Display dis = getDisplay(); - - dis.syncExec(new Runnable() { - - public void run() { - - FontData fontData = dis.getSystemFont().getFontData()[0]; - - // int resolution = Toolkit.getDefaultToolkit().getScreenResolution(); - int awtFontSize = (int) Math.round((double) fontData.getHeight() * dis.getDPI().y / 72.0); - - /* Font size correction! */ - - awtFont = new java.awt.Font(fontData.getName(), fontData.getStyle(), awtFontSize + fontSizeCorrection); - } - }); - - return awtFont; - } - - public static Color getSWTBackgroundToAWT() { - col = new Color(0, 0, 0); - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - - public void run() { - IViewSite viewSite = CanvasView.getCanvas_view().getViewSite(); - IWorkbenchWindow workbenchWindow = viewSite.getWorkbenchWindow(); - org.eclipse.swt.graphics.Color colswt = workbenchWindow.getShell().getBackground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - } - }); - return col; - - } - - public static Color getSWTForegroundToAWT() { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - public void run() { - IViewSite viewSite = CanvasView.getCanvas_view().getViewSite(); - IWorkbenchWindow workbenchWindow = viewSite.getWorkbenchWindow(); - org.eclipse.swt.graphics.Color colswt = workbenchWindow.getShell().getForeground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - } - }); - return col; - - } - - public static Color getSWTBackgroundToAWT(Composite parent) { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - - public void run() { - - org.eclipse.swt.graphics.Color colswt = parent.getParent().getBackground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - } - }); - return col; - - } - - public static Color getSWTForegroundToAWT(Composite parent) { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - - public void run() { - - org.eclipse.swt.graphics.Color colswt = parent.getParent().getForeground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - } - }); - return col; - - } - /** * A method to detect the current OS. * @@ -349,31 +237,7 @@ public static Display getDisplay() { * @return a boolean value. */ public static boolean isThemeBlack() { - boolean themeBlack = false; - IWorkbench workbench = PlatformUI.getWorkbench(); - MApplication application = workbench.getService(MApplication.class); - IEclipseContext context = application.getContext(); - IThemeEngine engine = context.get(IThemeEngine.class); - ITheme theme = engine.getActiveTheme(); - // System.out.println(theme.getLabel()); - - // IPreferenceStore workbenchStore = - // IDEWorkbenchPlugin.getDefault().getPreferenceStore(); - // System.out.print(ThemeHelper.getEngine().getActiveTheme().getId()); - if (theme != null) { - String activeTheme = theme.getId(); - /* - * We use a black style if the CSS is the dark theme or the darkest dark theme! - */ - if (activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_1) || activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_2) - || activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_3) || activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_4) - || activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_5)) { - - themeBlack = true; - - } - } - return themeBlack; + return com.eco.bio7.util.Util.isThemeBlack(); } // The source for the following method from: diff --git a/com.eco.bio7.image/src/ij/CommandListener.java b/com.eco.bio7.image/src/ij/CommandListener.java deleted file mode 100644 index e1a88bce2..000000000 --- a/com.eco.bio7.image/src/ij/CommandListener.java +++ /dev/null @@ -1,16 +0,0 @@ -package ij; - - /** Plugins that implement this interface are notified when ImageJ - is about to run a menu command. There is an example plugin at - http://imagej.net/ij/plugins/download/misc/Command_Listener.java - */ - public interface CommandListener { - - /* The method is called when ImageJ is about to run a menu command, - where 'command' is the name of the command. Return this string - and ImageJ will run the command, return a different command name - and ImageJ will run that command, or return null to not run a command. - */ - public String commandExecuting(String command); - -} diff --git a/com.eco.bio7.image/src/ij/CompositeImage.java b/com.eco.bio7.image/src/ij/CompositeImage.java deleted file mode 100644 index 47b016fc2..000000000 --- a/com.eco.bio7.image/src/ij/CompositeImage.java +++ /dev/null @@ -1,779 +0,0 @@ -package ij; -import ij.process.*; -import ij.gui.*; -import ij.plugin.*; -import ij.plugin.frame.*; -import ij.io.FileInfo; -import java.awt.*; -import java.awt.image.*; - -public class CompositeImage extends ImagePlus { - - /** Display modes (note: TRANSPARENT mode has not yet been implemented) */ - public static final int COMPOSITE=1, COLOR=2, GRAYSCALE=3, TRANSPARENT=4; - public static final int MAX_CHANNELS = 8; - public static final Color[] colors = {Color.red, Color.green, Color.blue, Color.white, Color.cyan, Color.magenta, Color.yellow, Color.white}; - - int[] rgbPixels; - boolean newPixels; - MemoryImageSource imageSource; - Image awtImage; - WritableRaster rgbRaster; - SampleModel rgbSampleModel; - BufferedImage rgbImage; - ColorModel rgbCM; - ImageProcessor[] cip; - LUT[] lut; - int currentChannel = -1; - int previousChannel; - int currentSlice = 1; - int currentFrame = 1; - boolean singleChannel; - boolean[] active = new boolean[MAX_CHANNELS]; - int mode = COLOR; - int bitDepth; - double[] displayRanges; - byte[][] channelLuts; - boolean customLuts; - boolean syncChannels; - - public CompositeImage(ImagePlus imp) { - this(imp, COLOR); - } - - public CompositeImage(ImagePlus imp, int mode) { - if (modeGRAYSCALE) - mode = COLOR; - this.mode = mode; - int channels = imp.getNChannels(); - bitDepth = getBitDepth(); - if (IJ.debugMode) IJ.log("CompositeImage: "+imp+" "+mode+" "+channels); - ImageStack stack2; - boolean isRGB = imp.getBitDepth()==24; - if (isRGB) { - if (imp.getImageStackSize()>1) - throw new IllegalArgumentException("RGB stacks not supported"); - stack2 = getRGBStack(imp); - } else - stack2 = imp.getImageStack(); - int stackSize = stack2.getSize(); - if (channels==1 && isRGB) - channels = 3; - if (channels==1 && stackSize<=MAX_CHANNELS && !imp.dimensionsSet) - channels = stackSize; - if (channels<1 || (stackSize%channels)!=0) - throw new IllegalArgumentException("stacksize not multiple of channels"); - if (mode==COMPOSITE && channels>MAX_CHANNELS) - this.mode = COLOR; - compositeImage = true; - int z = imp.getNSlices(); - int t = imp.getNFrames(); - if (channels==stackSize || channels*z*t!=stackSize) - setDimensions(channels, stackSize/channels, 1); - else - setDimensions(channels, z, t); - setStack(imp.getTitle(), stack2); - setCalibration(imp.getCalibration()); - FileInfo fi = imp.getOriginalFileInfo(); - if (fi!=null) { - displayRanges = fi.displayRanges; - channelLuts = fi.channelLuts; - } - setFileInfo(fi); - Object info = imp.getProperty("Info"); - if (info!=null) - setProperty("Info", imp.getProperty("Info")); - setProperties(imp.getPropertiesAsArray()); - if (mode==COMPOSITE) { - for (int i=0; i0 && (stack2.getProcessor(1) instanceof ColorProcessor)) { // RGB? - cip = null; - lut = null; - return; - } - setupLuts(channels); - if (mode==COMPOSITE) { - cip = new ImageProcessor[channels]; - for (int i=0; iMAX_CHANNELS?createLutFromColor(Color.white):null; - for (int i=0; istack2.getSize() || channels>MAX_CHANNELS) - return; - for (int i=0; inChannels) ch = nChannels; - boolean newChannel = false; - if (ch-1!=currentChannel) { - previousChannel = currentChannel; - currentChannel = ch-1; - newChannel = true; - } - - ImageProcessor ip = getProcessor(); - if (mode!=COMPOSITE) { - if (newChannel) { - setupLuts(nChannels); - LUT cm = lut[currentChannel]; - if (ip!=null && !(ip instanceof ColorProcessor)) { - if (mode==COLOR) - ip.setLut(cm); - if (!(cm.min==0.0&&cm.max==0.0)) - ip.setMinAndMax(cm.min, cm.max); - } - if (!IJ.isMacro()) ContrastAdjuster.update(); - for (int i=0; i=nChannels) { - setSlice(1); - currentChannel = 0; - newChannel = true; - } - bitDepth = getBitDepth(); - } - - if (newChannel) { - getProcessor().setMinAndMax(cip[currentChannel].getMin(), cip[currentChannel].getMax()); - if (!IJ.isMacro()) ContrastAdjuster.update(); - } - //IJ.log(nChannels+" "+ch+" "+currentChannel+" "+newChannel); - - if (getSlice()!=currentSlice || getFrame()!=currentFrame) { - currentSlice = getSlice(); - currentFrame = getFrame(); - int position = getStackIndex(1, currentSlice, currentFrame); - if (cip==null) return; - for (int i=0; icip.length) - return; - for (int i=1; icip.length) - return null; - else - return cip[channel-1]; - } - - public boolean[] getActiveChannels() { - return active; - } - - public synchronized void setMode(int mode) { - if (modeGRAYSCALE) - return; - if (mode==COMPOSITE && getNChannels()>MAX_CHANNELS) - mode = COLOR; - if (!(mode==COMPOSITE && mode==this.mode)) { - for (int i=0; ilut.length) - throw new IllegalArgumentException("Channel out of range: "+channel); - return lut[channel-1]; - } - - /* Returns the LUT used by the current channel. */ - public LUT getChannelLut() { - int c = getChannelIndex(); - return lut[c]; - } - - /* Returns a copy of this image's channel LUTs as an array. */ - public LUT[] getLuts() { - int channels = getNChannels(); - if (lut==null) - setupLuts(channels); - LUT[] luts = new LUT[channels]; - for (int i=0; iMAX_CHANNELS && getMode()==COMPOSITE) - setMode(COLOR); - setup(nChannels, getImageStack()); - } - - public void completeReset() { - cip = null; - lut = null; - } - - /* Sets the LUT of the current channel. */ - public void setChannelLut(LUT table) { - int c = getChannelIndex(); - double min = lut[c].min; - double max = lut[c].max; - lut[c] = table; - lut[c].min = min; - lut[c].max = max; - if (mode==COMPOSITE && cip!=null && clut.length) - throw new IllegalArgumentException("Channel out of range"); - lut[channel-1] = (LUT)table.clone(); - if (getWindow()!=null && channel==getChannel()) - getProcessor().setLut(lut[channel-1]); - if (cip!=null && cip.length>=channel && cip[channel-1]!=null) - cip[channel-1].setLut(lut[channel-1]); - else - cip = null; - customLuts = true; - } - - /* Sets the IndexColorModel of the current channel. */ - public void setChannelColorModel(IndexColorModel cm) { - setChannelLut(new LUT(cm,0.0,0.0)); - } - - public void setDisplayRange(double min, double max) { - ip.setMinAndMax(min, max); - int c = getChannelIndex(); - lut[c].min = min; - lut[c].max = max; - if (getWindow()==null && cip!=null && c0) synchronized (listeners) { - for (int i=0; i0 && command.charAt(len-1)!=']') - IJ.setKeyUp(IJ.ALL_KEYS); // set keys up except for "<", ">", "+" and "-" shortcuts - } catch(Throwable e) { - IJ.showStatus(""); - IJ.showProgress(1, 1); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp!=null) imp.unlock(); - String msg = e.getMessage(); - if (e instanceof OutOfMemoryError) - IJ.outOfMemory(command); - else if (e instanceof RuntimeException && msg!=null && msg.equals(Macro.MACRO_CANCELED)) - ; //do nothing - else { - CharArrayWriter caw = new CharArrayWriter(); - PrintWriter pw = new PrintWriter(caw); - e.printStackTrace(pw); - String s = caw.toString(); - if (IJ.isMacintosh()) { - if (s.indexOf("ThreadDeath")>0) - return; - s = Tools.fixNewLines(s); - } - int w=500, h=340; - if (s.indexOf("UnsupportedClassVersionError")!=-1) { - if (s.indexOf("version 49.0")!=-1) { - s = e + "\n \nThis plugin requires Java 1.5 or later."; - w=700; h=150; - } - if (s.indexOf("version 50.0")!=-1) { - s = e + "\n \nThis plugin requires Java 1.6 or later."; - w=700; h=150; - } - if (s.indexOf("version 51.0")!=-1) { - s = e + "\n \nThis plugin requires Java 1.7 or later."; - w=700; h=150; - } - if (s.indexOf("version 52.0")!=-1) { - s = e + "\n \nThis plugin requires Java 1.8 or later."; - w=700; h=150; - } - } - if (IJ.getInstance()!=null) { - s = IJ.getInstance().getInfo()+"\n \n"+s; - new TextWindow("Exception", s, w, h); - } else - IJ.log(s); - } - } finally { - if (thread!=null) - WindowManager.setTempCurrentImage(null); - } - } - - void runCommand(String cmd) { - Hashtable table = Menus.getCommands(); - String className = (String)table.get(cmd); - if (className!=null) { - String arg = ""; - if (className.endsWith("\")")) { - // extract string argument (e.g. className("arg")) - int argStart = className.lastIndexOf("(\""); - if (argStart>0) { - arg = className.substring(argStart+2, className.length()-2); - className = className.substring(0, argStart); - } - } - if (Prefs.nonBlockingFilterDialogs) { - // we have the plugin class name, let us see whether it is allowed to run it - ImagePlus imp = WindowManager.getCurrentImage(); - boolean imageLocked = imp!=null && imp.isLockedByAnotherThread(); - if (imageLocked && !allowedWithLockedImage(className)) { - IJ.beep(); - IJ.showStatus("\""+cmd + "\" blocked because \"" + imp.getTitle() + "\" is locked"); - return; - } - } - // run the plugin - if (IJ.shiftKeyDown() && className.startsWith("ij.plugin.Macro_Runner") && !Menus.getShortcuts().contains("*"+cmd)) - IJ.open(IJ.getDirectory("plugins")+arg); - else - IJ.runPlugIn(cmd, className, arg); - } else { // command is not a plugin - // is command in the Plugins>Macros menu? - if (MacroInstaller.runMacroCommand(cmd)) - return; - // is it in the Image>Lookup Tables menu? - if (loadLut(cmd)) - return; - // is it in the File>Open Recent menu? - if (openRecent(cmd)) - return; - // is it an example in Help>Examples menu? - if (IJ.getInstance()!=null && !GraphicsEnvironment.isHeadless()) { - if (Editor.openExample(cmd)) - return; - } - if ("Auto Threshold".equals(cmd)&&(String)table.get("Auto Threshold...")!=null) - runCommand("Auto Threshold..."); - else if ("Enhance Local Contrast (CLAHE)".equals(cmd)&&(String)table.get("CLAHE ")!=null) - runCommand("CLAHE "); - else { - if ("Table...".equals(cmd)) - IJ.runPlugIn("ij.plugin.NewPlugin", "table"); - else { - if (repeatingCommand) - IJ.runMacro(previousCommand); - else { - if (!extraCommand(cmd)) - IJ.error("Unrecognized command: \"" + cmd+"\""); - } - } - } - } - } - - private boolean extraCommand(String cmd) { - if (cmd!=null && cmd.equals("Duplicate Image...")) { - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp!=null) { - Duplicator.ignoreNextSelection(); - IJ.run(imp, "Duplicate...", ""); - } else - IJ.noImage(); - return true; - } else - return false; - } - - /** If the foreground image is locked during a filter operation with NonBlockingGenericDialog, - * the following plugins are allowed */ - boolean allowedWithLockedImage(String className) { - return className.equals("ij.plugin.Zoom") || - className.equals("ij.plugin.frame.ContrastAdjuster") || - className.equals("ij.plugin.SimpleCommands") || //includes Plugins>Utiltites>Reset (needed to reset a locked image) - className.equals("ij.plugin.WindowOrganizer") || - className.equals("ij.plugin.URLOpener"); - } - - /** Opens a .lut file from the ImageJ/luts directory and returns 'true' if successful. */ - public static boolean loadLut(String name) { - String path = IJ.getDirectory("luts")+name.replace(" ","_")+".lut"; - File f = new File(path); - if (!f.exists()) { - path = IJ.getDirectory("luts")+name+".lut"; - f = new File(path); - } - if (!f.exists()) { - path = IJ.getDirectory("luts")+name.toLowerCase().replace(" ","_")+".lut"; - f = new File(path); - } - if (!f.exists() && Character.isLowerCase(name.charAt(0))) { - String name2 = name.substring(0,1).toUpperCase()+name.substring(1); - path = IJ.getDirectory("luts")+name2+".lut"; - f = new File(path); - } - if (!f.exists() && name.toLowerCase().equals("viridis")) { - path = IJ.getDirectory("luts")+"mpl-viridis.lut"; //Fiji version - f = new File(path); - } - if (f.exists()) { - String dir = OpenDialog.getLastDirectory(); - IJ.open(path); - OpenDialog.setLastDirectory(dir); - return true; - } - return false; - } - - /** Opens a file from the File/Open Recent menu - and returns 'true' if successful. */ - boolean openRecent(String cmd) { - Menu menu = Menus.getOpenRecentMenu(); - if (menu==null) return false; - for (int i=0; imacro on the current - * thread. Returns any string value returned by the macro, null if the macro - * does not return a value, or "[aborted]" if the macro was aborted due to an - * error. The equivalent macro function is eval(). - */ - public static String runMacro(String macro) { - return runMacro(macro, ""); - } - - /** - * Runs the macro contained in the string macro on the current - * thread. The optional string argument can be retrieved in the called macro - * using the getArgument() macro function. Returns any string value returned by - * the macro, null if the macro does not return a value, or "[aborted]" if the - * macro was aborted due to an error. - */ - public static String runMacro(String macro, String arg) { - Macro_Runner mr = new Macro_Runner(); - return mr.runMacro(macro, arg); - } - - /** - * Runs the specified macro or script file in the current thread. The file is - * assumed to be in the macros folder unless name is a full path. - * The optional string argument (arg) can be retrieved in the - * called macro or script using the getArgument() function. Returns any string - * value returned by the macro, or null. Scripts always return null. The - * equivalent macro function is runMacro(). - */ - public static String runMacroFile(String name, String arg) { - Macro_Runner mr = new Macro_Runner(); - return mr.runMacroFile(name, arg); - } - - /** Runs the specified macro file. */ - public static String runMacroFile(String name) { - return runMacroFile(name, null); - } - - /** Runs the specified plugin using the specified image. */ - public static Object runPlugIn(ImagePlus imp, String className, String arg) { - if (imp != null) { - ImagePlus temp = WindowManager.getTempCurrentImage(); - WindowManager.setTempCurrentImage(imp); - Object o = runPlugIn("", className, arg); - WindowManager.setTempCurrentImage(temp); - return o; - } else - return runPlugIn(className, arg); - } - - /** Runs the specified plugin and returns a reference to it. */ - public static Object runPlugIn(String className, String arg) { - return runPlugIn("", className, arg); - } - - /** Runs the specified plugin and returns a reference to it. */ - public static Object runPlugIn(String commandName, String className, String arg) { - if (arg == null) - arg = ""; - if (IJ.debugMode) - IJ.log("runPlugIn: " + className + argument(arg)); - // Load using custom classloader if this is a user - // plugin and we are not running as an applet - if (!className.startsWith("ij.") && applet == null) - return runUserPlugIn(commandName, className, arg, false); - Object thePlugIn = null; - try { - Class c = Class.forName(className); - thePlugIn = c.newInstance(); - if (thePlugIn instanceof PlugIn) - ((PlugIn) thePlugIn).run(arg); - else - new PlugInFilterRunner(thePlugIn, commandName, arg); - } catch (ClassNotFoundException e) { - if (!(className != null && className.startsWith("ij.plugin.MacAdapter"))) { - log("Plugin or class not found: \"" + className + "\"\n(" + e + ")"); - String path = Prefs.getCustomPropsPath(); - if (path != null) - ; - log("Error may be due to custom properties at " + path); - } - } catch (InstantiationException e) { - log("Unable to load plugin (ins)"); - } catch (IllegalAccessException e) { - log("Unable to load plugin, possibly \nbecause it is not public."); - } - redirectErrorMessages = false; - return thePlugIn; - } - - static Object runUserPlugIn(String commandName, String className, String arg, boolean createNewLoader) { - if (IJ.debugMode) - IJ.log("runUserPlugIn: " + className + ", arg=" + argument(arg)); - if (applet != null) - return null; - if (createNewLoader) - classLoader = null; - ClassLoader loader = getClassLoader(); - Object thePlugIn = null; - try { - thePlugIn = (loader.loadClass(className)).newInstance(); - if (thePlugIn instanceof PlugIn) - ((PlugIn) thePlugIn).run(arg); - else if (thePlugIn instanceof PlugInFilter) - new PlugInFilterRunner(thePlugIn, commandName, arg); - } catch (ClassNotFoundException e) { - if (className.startsWith("macro:")) - runMacro(className.substring(6)); - else if (className.contains("_") && !suppressPluginNotFoundError) - error("Plugin or class not found: \"" + className + "\"\n(" + e + ")"); - } catch (NoClassDefFoundError e) { - int dotIndex = className.indexOf('.'); - if (dotIndex >= 0 && className.contains("_")) { - // rerun plugin after removing folder name - if (debugMode) - IJ.log("runUserPlugIn: rerunning " + className); - return runUserPlugIn(commandName, className.substring(dotIndex + 1), arg, createNewLoader); - } - if (className.contains("_") && !suppressPluginNotFoundError) - error("Run User Plugin", "Class not found while attempting to run \"" + className + "\"\n \n " + e); - } catch (InstantiationException e) { - error("Unable to load plugin (ins)"); - } catch (IllegalAccessException e) { - error("Unable to load plugin, possibly \nbecause it is not public."); - } - if (thePlugIn != null && !"HandleExtraFileTypes".equals(className)) - redirectErrorMessages = false; - suppressPluginNotFoundError = false; - return thePlugIn; - } - - private static String argument(String arg) { - return arg != null && !arg.equals("") && !arg.contains("\n") ? "(\"" + arg + "\")" : ""; - } - - static void wrongType(int capabilities, String cmd) { - String s = "\"" + cmd + "\" requires an image of type:\n \n"; - if ((capabilities & PlugInFilter.DOES_8G) != 0) - s += " 8-bit grayscale\n"; - if ((capabilities & PlugInFilter.DOES_8C) != 0) - s += " 8-bit color\n"; - if ((capabilities & PlugInFilter.DOES_16) != 0) - s += " 16-bit grayscale\n"; - if ((capabilities & PlugInFilter.DOES_32) != 0) - s += " 32-bit (float) grayscale\n"; - if ((capabilities & PlugInFilter.DOES_RGB) != 0) - s += " RGB color\n"; - error(s); - } - - /** Runs a menu command on a separete thread and returns immediately. */ - public static void doCommand(String command) { - new Executer(command, null); - } - - /** Runs a menu command on a separete thread, using the specified image. */ - public static void doCommand(ImagePlus imp, String command) { - new Executer(command, imp); - } - - /** - * Runs an ImageJ command. Does not return until the command has finished - * executing. To avoid "image locked", errors, plugins that call this method - * should implement the PlugIn interface instead of PlugInFilter. - */ - public static void run(String command) { - run(command, null); - } - - /** - * Runs an ImageJ command, with options that are passed to the GenericDialog and - * OpenDialog classes. Does not return until the command has finished executing. - * To generate run() calls, start the recorder (Plugins/Macro/Record) and run - * commands from the ImageJ menu bar. - */ - public static void run(String command, String options) { - // IJ.log("run1: "+command+" "+Thread.currentThread().hashCode()+" - // "+options); - if (ij == null && Menus.getCommands() == null) - init(); - Macro.abort = false; - Macro.setOptions(options); - Thread thread = Thread.currentThread(); - if (previousThread == null || thread != previousThread) { - String name = thread.getName(); - if (!name.startsWith("Run$_")) - thread.setName("Run$_" + name); - } - command = convert(command); - previousThread = thread; - macroRunning = true; - Executer e = new Executer(command); - e.run(); - macroRunning = false; - Macro.setOptions(null); - testAbort(); - macroInterpreter = null; - // IJ.log("run2: "+command+" "+Thread.currentThread().hashCode()); - } - - /** The macro interpreter uses this method to run commands. */ - public static void run(Interpreter interpreter, String command, String options) { - macroInterpreter = interpreter; - run(command, options); - macroInterpreter = null; - } - - /** - * Converts commands that have been renamed so macros using the old names - * continue to work. - */ - private static String convert(String command) { - if (commandTable == null) { - commandTable = new Hashtable(30); - commandTable.put("New...", "Image..."); - commandTable.put("Threshold", "Make Binary"); - commandTable.put("Display...", "Appearance..."); - commandTable.put("Start Animation", "Start Animation [\\]"); - commandTable.put("Convert Images to Stack", "Images to Stack"); - commandTable.put("Convert Stack to Images", "Stack to Images"); - commandTable.put("Convert Stack to RGB", "Stack to RGB"); - commandTable.put("Convert to Composite", "Make Composite"); - commandTable.put("RGB Split", "Split Channels"); - commandTable.put("RGB Merge...", "Merge Channels..."); - commandTable.put("Channels...", "Channels Tool..."); - commandTable.put("New... ", "Table..."); - commandTable.put("Arbitrarily...", "Rotate... "); - commandTable.put("Measurements...", "Results... "); - commandTable.put("List Commands...", "Find Commands..."); - commandTable.put("Capture Screen ", "Capture Screen"); - commandTable.put("Add to Manager ", "Add to Manager"); - commandTable.put("In", "In [+]"); - commandTable.put("Out", "Out [-]"); - commandTable.put("Enhance Contrast", "Enhance Contrast..."); - commandTable.put("XY Coodinates... ", "XY Coordinates... "); - commandTable.put("Statistics...", "Statistics"); - commandTable.put("Channels Tool... ", "Channels Tool..."); - commandTable.put("Profile Plot Options...", "Plots..."); - commandTable.put("AuPbSn 40 (56K)", "AuPbSn 40"); - commandTable.put("Bat Cochlea Volume (19K)", "Bat Cochlea Volume"); - commandTable.put("Bat Cochlea Renderings (449K)", "Bat Cochlea Renderings"); - commandTable.put("Blobs (25K)", "Blobs"); - commandTable.put("Boats (356K)", "Boats"); - commandTable.put("Cardio (768K, RGB DICOM)", "Cardio (RGB DICOM)"); - commandTable.put("Cell Colony (31K)", "Cell Colony"); - commandTable.put("Clown (14K)", "Clown"); - commandTable.put("Confocal Series (2.2MB)", "Confocal Series"); - commandTable.put("CT (420K, 16-bit DICOM)", "CT (16-bit DICOM)"); - commandTable.put("Dot Blot (7K)", "Dot Blot"); - commandTable.put("Embryos (42K)", "Embryos"); - commandTable.put("Fluorescent Cells (400K)", "Fluorescent Cells"); - commandTable.put("Fly Brain (1MB)", "Fly Brain"); - commandTable.put("Gel (105K)", "Gel"); - commandTable.put("HeLa Cells (1.3M, 48-bit RGB)", "HeLa Cells (48-bit RGB)"); - commandTable.put("Leaf (36K)", "Leaf"); - commandTable.put("Line Graph (21K)", "Line Graph"); - commandTable.put("Mitosis (26MB, 5D stack)", "Mitosis (5D stack)"); - commandTable.put("MRI Stack (528K)", "MRI Stack"); - commandTable.put("M51 Galaxy (177K, 16-bits)", "M51 Galaxy (16-bits)"); - commandTable.put("Neuron (1.6M, 5 channels)", "Neuron (5 channels)"); - commandTable.put("Nile Bend (1.9M)", "Nile Bend"); - commandTable.put("Organ of Corti (2.8M, 4D stack)", "Organ of Corti (4D stack)"); - commandTable.put("Particles (75K)", "Particles"); - commandTable.put("T1 Head (2.4M, 16-bits)", "T1 Head (16-bits)"); - commandTable.put("T1 Head Renderings (736K)", "T1 Head Renderings"); - commandTable.put("TEM Filter (112K)", "TEM Filter"); - commandTable.put("Tree Rings (48K)", "Tree Rings"); - } - String command2 = (String) commandTable.get(command); - if (command2 != null) - return command2; - else - return command; - } - - /** - * Runs an ImageJ command using the specified image and options. To generate - * run() calls, start the recorder (Plugins/Macro/Record) and run commands from - * the ImageJ menu bar. - */ - public static void run(ImagePlus imp, String command, String options) { - if (ij == null && Menus.getCommands() == null) - init(); - if (imp != null) { - ImagePlus temp = WindowManager.getTempCurrentImage(); - WindowManager.setTempCurrentImage(imp); - run(command, options); - WindowManager.setTempCurrentImage(temp); - } else - run(command, options); - } - - static void init() { - Menus m = new Menus(null, null); - Prefs.load(m, null); - m.addMenuBar(); - } - - private static void testAbort() { - if (Macro.abort) - abort(); - } - - /** Returns true if the run(), open() or newImage() method is executing. */ - public static boolean macroRunning() { - return macroRunning; - } - - /** - * Returns true if a macro is running, or if the run(), open() or newImage() - * method is executing. - */ - public static boolean isMacro() { - return macroRunning || Interpreter.getInstance() != null; - } - - /** - * Returns the Applet that created this ImageJ or null if running as an - * application. - */ - public static java.applet.Applet getApplet() { - return applet; - } - - /** - * Displays a message in the ImageJ status bar. If 's' starts with '!', - * subsequent showStatus() calls in the current thread (without "!" in the - * message) are suppressed. - */ - public static void showStatus(String s) { - if ((Interpreter.getInstance() == null && statusBarThread == null) - || (statusBarThread != null && Thread.currentThread() != statusBarThread)) - protectStatusBar(false); - boolean doProtect = s.startsWith("!"); // suppress subsequent showStatus() calls - if (doProtect) { - protectStatusBar(true); - statusBarThread = Thread.currentThread(); - s = s.substring(1); - } - if (doProtect || !protectStatusBar) { - if (ij != null) - ij.showStatus(s); - ImagePlus imp = WindowManager.getCurrentImage(); - ImageCanvas ic = imp != null ? imp.getCanvas() : null; - if (ic != null) - ic.setShowCursorStatus(s.length() == 0 ? true : false); - } - } - - /** - * Displays a message in the status bar and flashes either the status bar or the - * active image. - * See: http://wsr.imagej.net/macros/FlashingStatusMessages.txt - */ - public static void showStatus(String message, String options) { - showStatus(message); - if (options == null) - return; - options = options.replace("flash", ""); - options = options.replace("ms", ""); - Color optionalColor = null; - int index1 = options.indexOf("#"); - if (index1 >= 0) { // hex color? - int index2 = options.indexOf(" ", index1); - if (index2 == -1) - index2 = options.length(); - String hexColor = options.substring(index1, index2); - optionalColor = Colors.decode(hexColor, null); - options = options.replace(hexColor, ""); - } - if (optionalColor == null) { // "red", "green", etc. - for (String c : Colors.colors) { - if (options.contains(c)) { - optionalColor = Colors.getColor(c, ImageJ.backgroundColor); - options = options.replace(c, ""); - break; - } - } - } - boolean flashImage = options.contains("image"); - Color defaultColor = new Color(255, 255, 245); - int defaultDelay = 500; - ImagePlus imp = WindowManager.getCurrentImage(); - if (flashImage) { - options = options.replace("image", ""); - if (imp != null && imp.getWindow() != null) { - defaultColor = Color.black; - defaultDelay = 100; - } else - flashImage = false; - } - Color color = optionalColor != null ? optionalColor : defaultColor; - int delay = (int) Tools.parseDouble(options, defaultDelay); - if (delay > 8000) - delay = 8000; - ImageJ ij = IJ.getInstance(); - if (flashImage) { - // Color previousColor = imp.getWindow().getBackground(); - /*Changed for Bio7!*/ - Color previousColor = Util.getSWTBackgroundToAWT(); - - Display display = Util.getDisplay(); - display.asyncExec(new Runnable() { - public void run() { - previousTabForegColor = CanvasView.tabFolder.getSelectionForeground(); - } - }); - imp.getWindow().setBackground(color); - // g.setColor(c); - setTabItemColor(color); - if (delay > 0) { - wait(delay); - imp.getWindow().setBackground(previousColor); - setTabItemColor(previousTabForegColor); - // current.setBackground(previousColor); - } - - } else if (ij != null) { - Color previousColor = ij.getStatusBar().getBackground(); - ij.getStatusBar().setBackground(color); - wait(delay); - ij.getStatusBar().setBackground(previousColor); - } - } - - public static void setTabItemColor(org.eclipse.swt.graphics.Color col) { - Display display = Util.getDisplay(); - display.asyncExec(new Runnable() { - public void run() { - CanvasView.tabFolder.setSelectionForeground(col); - CanvasView.tabFolder.setForeground(col); - - } - }); - } - - public static void setTabItemColor(Color col) { - int red = col.getRed(); - int green = col.getGreen(); - int blue = col.getBlue(); - Display display = Util.getDisplay(); - display.asyncExec(new Runnable() { - public void run() { - CanvasView.tabFolder - .setSelectionForeground(new org.eclipse.swt.graphics.Color(display, new RGB(red, green, blue))); - - } - }); - } - - /** - * @deprecated replaced by IJ.log(), ResultsTable.setResult() and - * TextWindow.append(). There are examples at - * http://imagej.net/ij/plugins/sine-cosine.html - */ - public static void write(String s) { - if (textPanel == null && ij != null) - showResults(); - if (textPanel != null) - textPanel.append(s); - else - System.out.println(s); - } - - private static void showResults() { - TextWindow resultsWindow = new TextWindow("Results", "", 400, 250); - textPanel = resultsWindow.getTextPanel(); - textPanel.setResultsTable(Analyzer.getResultsTable()); - } - - public static synchronized void log(String s) { - if (s == null) - return; - if (logPanel == null && ij != null) { - TextWindow logWindow = new TextWindow("Log", "", 400, 250); - logPanel = logWindow.getTextPanel(); - logPanel.setFont(new Font("SansSerif", Font.PLAIN, 16)); - } - if (logPanel != null) { - if (s.startsWith("\\")) - handleLogCommand(s); - else { - if (s.endsWith("\n")) { - if (s.equals("\n\n")) - s = "\n \n "; - else if (s.endsWith("\n\n")) - s = s.substring(0, s.length() - 2) + "\n \n "; - else - s = s + " "; - } - logPanel.append(s); - } - } else { - LogStream.redirectSystem(false); - System.out.println(s); - } - } - - static void handleLogCommand(String s) { - if (s.equals("\\Closed")) - logPanel = null; - else if (s.startsWith("\\Update:")) { - int n = logPanel.getLineCount(); - String s2 = s.substring(8, s.length()); - if (n == 0) - logPanel.append(s2); - else - logPanel.setLine(n - 1, s2); - } else if (s.startsWith("\\Update")) { - int cindex = s.indexOf(":"); - if (cindex == -1) { - logPanel.append(s); - return; - } - String nstr = s.substring(7, cindex); - int line = (int) Tools.parseDouble(nstr, -1); - if (line < 0 || line > 25) { - logPanel.append(s); - return; - } - int count = logPanel.getLineCount(); - while (line >= count) { - log(""); - count++; - } - String s2 = s.substring(cindex + 1, s.length()); - logPanel.setLine(line, s2); - } else if (s.equals("\\Clear")) { - logPanel.clear(); - } else if (s.startsWith("\\Heading:")) { - logPanel.updateColumnHeadings(s.substring(10)); - } else if (s.equals("\\Close")) { - Frame f = WindowManager.getFrame("Log"); - if (f != null && (f instanceof TextWindow)) - ((TextWindow) f).close(); - } else - logPanel.append(s); - } - - /** - * Returns the contents of the Log window or null if the Log window is not open. - */ - public static synchronized String getLog() { - if (logPanel == null || ij == null) - return null; - else - return logPanel.getText(); - } - - /** - * Clears the "Results" window and sets the column headings to those in the - * tab-delimited 'headings' String. Writes to System.out.println if the "ImageJ" - * frame is not present. - */ - public static void setColumnHeadings(String headings) { - if (textPanel == null && ij != null) - showResults(); - if (textPanel != null) - textPanel.setColumnHeadings(headings); - else - System.out.println(headings); - } - - /** Returns true if the "Results" window is open. */ - public static boolean isResultsWindow() { - return textPanel != null; - } - - /** Renames a results window. */ - public static void renameResults(String title) { - Frame frame = WindowManager.getFrontWindow(); - if (frame != null && (frame instanceof TextWindow)) { - TextWindow tw = (TextWindow) frame; - if (tw.getResultsTable() == null) { - IJ.error("Rename", "\"" + tw.getTitle() + "\" is not a results table"); - return; - } - tw.rename(title); - } else if (isResultsWindow()) { - TextPanel tp = getTextPanel(); - TextWindow tw = (TextWindow) tp.getParent(); - tw.rename(title); - } - } - - /** Changes the name of a table window from 'oldTitle' to 'newTitle'. */ - public static void renameResults(String oldTitle, String newTitle) { - Frame frame = WindowManager.getFrame(oldTitle); - if (frame == null) { - error("Rename", "\"" + oldTitle + "\" not found"); - return; - } else if (frame instanceof TextWindow) { - TextWindow tw = (TextWindow) frame; - if (tw.getResultsTable() == null) { - error("Rename", "\"" + oldTitle + "\" is not a table"); - return; - } - tw.rename(newTitle); - } else - error("Rename", "\"" + oldTitle + "\" is not a table"); - } - - /** - * Deletes 'row1' through 'row2' of the "Results" window, where 'row1' and - * 'row2' must be in the range 0-Analyzer.getCounter()-1. - */ - public static void deleteRows(int row1, int row2) { - - ResultsTable rt = Analyzer.getResultsTable(); - int tableSize = rt.size(); - rt.deleteRows(row1, row2); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp != null) - Overlay.updateTableOverlay(imp, row1, row2, tableSize); - rt.show("Results"); - } - - /** - * Returns a measurement result, where 'measurement' is "Area", "Mean", - * "StdDev", "Mode", "Min", "Max", "X", "Y", "XM", "YM", "Perim.", "BX", "BY", - * "Width", "Height", "Major", "Minor", "Angle", "Circ.", "Feret", "IntDen", - * "Median", "Skew", "Kurt", "%Area", "RawIntDen", "Ch", "Slice", "Frame", - * "FeretX", "FeretY", "FeretAngle", "MinFeret", "AR", "Round", "Solidity", - * "MinThr" or "MaxThr". Add " raw" to the argument to disable calibration, for - * example IJ.getValue("Mean raw"). Add " limit" to enable the "limit to - * threshold" option. - */ - public static double getValue(ImagePlus imp, String measurement) { - String options = ""; - int index = measurement.indexOf(" "); - if (index > 0) { - if (index < measurement.length() - 1) - options = measurement.substring(index + 1, measurement.length()); - measurement = measurement.substring(0, index); - } - int measurements = Measurements.ALL_STATS + Measurements.SLICE; - if (options.contains("limit")) - measurements += Measurements.LIMIT; - Calibration cal = null; - if (options.contains("raw")) { - cal = imp.getCalibration(); - imp.setCalibration(null); - } - ResultsTable rt = new ResultsTable(); - Analyzer analyzer = new Analyzer(imp, measurements, rt); - analyzer.measure(); - double value = Double.NaN; - try { - value = rt.getValue(measurement, 0); - } catch (Exception e) { - } - ; - if (cal != null) - imp.setCalibration(cal); - return value; - } - - /** - * Returns a reference to the "Results" window TextPanel. Opens the "Results" - * window if it is currently not open. Returns null if the "ImageJ" window is - * not open. - */ - public static TextPanel getTextPanel() { - if (textPanel == null && ij != null) - showResults(); - return textPanel; - } - - /** - * TextWindow calls this method with a null argument when the "Results" window - * is closed. - */ - public static void setTextPanel(TextPanel tp) { - textPanel = tp; - } - - /** Displays a "no images are open" dialog box. */ - public static void noImage() { - String msg = "There are no images open"; - if (macroInterpreter != null) { - macroInterpreter.abort(msg); - macroInterpreter = null; - } else - error("No Image", msg); - } - - /** Displays an "out of memory" message to the "Log" window. */ - public static void outOfMemory(String name) { - Undo.reset(); - System.gc(); - lastErrorMessage = "out of memory"; - String tot = Runtime.getRuntime().maxMemory() / 1048576L + "MB"; - if (!memMessageDisplayed) - log(">>>>>>>>>>>>>>>>>>>>>>>>>>>"); - log(""); - if (!memMessageDisplayed) { - log(""); - log(""); - log("Options>Memory & Threads command.>"); - log(">>>>>>>>>>>>>>>>>>>>>>>>>>>"); - memMessageDisplayed = true; - } - Macro.abort(); - } - - /** - * Updates the progress bar, where 0<=progress<=1.0. The progress bar is not - * shown in BatchMode and erased if progress>=1.0. The progress bar is updated - * only if more than 90 ms have passes since the last call. Does nothing if the - * ImageJ window is not present. - */ - public static void showProgress(double progress) { - if (progressBar != null) - progressBar.show(progress, false); - } - - /** - * Updates the progress bar, where the length of the bar is set to ( - * (currentValue+1)/finalValue of the maximum bar length. The bar - * is erased if currentValue>=finalValue. The bar is updated - * only if more than 90 ms have passed since the last call. Displays subordinate - * progress bars as dots if 'currentIndex' is negative (example: - * Plugins/Utilities/Benchmark). - */ - public static void showProgress(int currentIndex, int finalIndex) { - if (progressBar != null) { - progressBar.show(currentIndex, finalIndex); - if (currentIndex == finalIndex) - progressBar.setBatchMode(false); - } - } - - /** - * Displays a message in a dialog box titled "Message". Writes the Java console - * if ImageJ is not present. - */ - public static void showMessage(String msg) { - showMessage("Message", msg); - } - - /** - * Displays a message in a dialog box with the specified title. Displays HTML - * formatted text if 'msg' starts with "". There are examples at - * "http://imagej.net/ij/macros/HtmlDialogDemo.txt". Writes to the Java - * console if ImageJ is not present. - */ - public static void showMessage(String title, String msg) { - /* Changed for Bio7! */ - - if (ij != null) { - if (msg != null && (msg.startsWith("") || msg.startsWith(""))) { - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - HTMLDialog hd = new HTMLDialog(title, msg); - - if (isMacro() && hd.escapePressed()) - throw new RuntimeException(Macro.MACRO_CANCELED); - } - }); - } - }); - } else { - /*Already wrapped in dis.syncExec!*/ - MessageDialog md = new MessageDialog(ij, title, msg); - if (isMacro() && md.escapePressed()) - throw new RuntimeException(Macro.MACRO_CANCELED); - } - IJ.wait(25); // fix GenericDialog non-editable text field - } else - System.out.println(msg); - - } - - /** - * Displays a message in a dialog box titled "ImageJ". If a macro or JavaScript - * is running, it is aborted. Writes to the Java console if the ImageJ window is - * not present. - */ - - public static void error(String msg) { - error(null, msg); - if (Thread.currentThread().getName().endsWith("JavaScript")) - throw new RuntimeException(Macro.MACRO_CANCELED); - else - Macro.abort(); - } - - /** - * Displays a message in a dialog box with the specified title. If a macro or - * JavaScript is running, it is aborted. Writes to the Java console if the - * ImageJ window is not present. - */ - public static void error(String title, String msg) { - if (macroInterpreter != null) { - macroInterpreter.abort(msg); - macroInterpreter = null; - return; - } - if (msg != null && msg.endsWith(Macro.MACRO_CANCELED)) - return; - String title2 = title != null ? title : "ImageJ"; - boolean abortMacro = title != null; - lastErrorMessage = msg; - if (redirectErrorMessages) { - IJ.log(title2 + ": " + msg); - if (abortMacro && (title.contains("Open") || title.contains("Reader"))) - abortMacro = false; - } else - showMessage(title2, msg); - redirectErrorMessages = false; - if (abortMacro) - Macro.abort(); - } - - /** - * Aborts any currently running JavaScript, or use IJ.error(string) to abort a - * JavaScript with a message. - */ - public static void exit() { - if (Thread.currentThread().getName().endsWith("JavaScript")) - throw new RuntimeException(Macro.MACRO_CANCELED); - } - - /** - * Returns the last error message written by IJ.error() or null if there was no - * error since the last time this method was called. - * - * @see #error(String) - */ - public static String getErrorMessage() { - String msg = lastErrorMessage; - lastErrorMessage = null; - return msg; - } - - /** - * Displays a message in a dialog box with the specified title. Returns false if - * the user pressed "Cancel". - */ - public static boolean showMessageWithCancel(String title, String msg) { - GenericDialog gd = new GenericDialog(title); - gd.addMessage(msg); - gd.showDialog(); - return !gd.wasCanceled(); - } - - public static final int CANCELED = Integer.MIN_VALUE; - - /** - * Allows the user to enter a number in a dialog box. Returns the value - * IJ.CANCELED (-2,147,483,648) if the user cancels the dialog box. Returns - * 'defaultValue' if the user enters an invalid number. - */ - public static double getNumber(String prompt, double defaultValue) { - GenericDialog gd = new GenericDialog(""); - int decimalPlaces = (int) defaultValue == defaultValue ? 0 : 2; - gd.addNumericField(prompt, defaultValue, decimalPlaces); - gd.showDialog(); - if (gd.wasCanceled()) - return CANCELED; - double v = gd.getNextNumber(); - if (gd.invalidNumber()) - return defaultValue; - else - return v; - } - - /** - * Allows the user to enter a string in a dialog box. Returns "" if the user - * cancels the dialog box. - */ - public static String getString(String prompt, String defaultString) { - GenericDialog gd = new GenericDialog(""); - gd.addStringField(prompt, defaultString, 20); - gd.showDialog(); - if (gd.wasCanceled()) - return ""; - return gd.getNextString(); - } - - /** Delays 'msecs' milliseconds. */ - public static void wait(int msecs) { - try { - Thread.sleep(msecs); - } catch (InterruptedException e) { - } - } - - /** Emits an audio beep. */ - public static void beep() { - java.awt.Toolkit.getDefaultToolkit().beep(); - } - - /** - * Returns a string something like "64K of 256MB (25%)" that shows how much of - * the available memory is in use. This is the string displayed when the user - * clicks in the status bar. - */ - public static String freeMemory() { - long inUse = currentMemory(); - String inUseStr = inUse < 10000 * 1024 ? inUse / 1024L + "K" : inUse / 1048576L + "MB"; - String maxStr = ""; - long max = maxMemory(); - if (max > 0L) { - double percent = inUse * 100 / max; - maxStr = " of " + max / 1048576L + "MB (" + (percent < 1.0 ? "<1" : d2s(percent, 0)) + "%)"; - } - return inUseStr + maxStr; - } - - /** Returns the amount of memory currently being used by ImageJ. */ - public static long currentMemory() { - long freeMem = Runtime.getRuntime().freeMemory(); - long totMem = Runtime.getRuntime().totalMemory(); - return totMem - freeMem; - } - - /** - * Returns the maximum amount of memory available to ImageJ or zero if ImageJ is - * unable to determine this limit. - */ - public static long maxMemory() { - if (maxMemory == 0L) { - Memory mem = new Memory(); - maxMemory = mem.getMemorySetting(); - if (maxMemory == 0L) - maxMemory = mem.maxMemory(); - } - return maxMemory; - } - - public static void showTime(ImagePlus imp, long start, String str) { - showTime(imp, start, str, 1); - } - - public static void showTime(ImagePlus imp, long start, String str, int nslices) { - if (Interpreter.isBatchMode()) - return; - double seconds = (System.currentTimeMillis() - start) / 1000.0; - if (seconds <= 0.5 && macroRunning()) - return; - double pixels = (double) imp.getWidth() * imp.getHeight(); - double rate = pixels * nslices / seconds; - String str2; - if (rate > 1000000000.0) - str2 = ""; - else if (rate < 1000000.0) - str2 = ", " + d2s(rate, 0) + " pixels/second"; - else - str2 = ", " + d2s(rate / 1000000.0, 1) + " million pixels/second"; - showStatus(str + seconds + " seconds" + str2); - } - - /** Experimental */ - public static String time(ImagePlus imp, long startNanoTime) { - double planes = imp.getStackSize(); - double seconds = (System.nanoTime() - startNanoTime) / 1000000000.0; - double mpixels = imp.getWidth() * imp.getHeight() * planes / 1000000.0; - String time = seconds < 1.0 ? d2s(seconds * 1000.0, 0) + " ms" : d2s(seconds, 1) + " seconds"; - return time + ", " + d2s(mpixels / seconds, 1) + " million pixels/second"; - } - - /** - * Converts a number to a formatted string using 2 digits to the right of the - * decimal point. - */ - public static String d2s(double n) { - return d2s(n, 2); - } - - /** - * Converts a number to a rounded formatted string. The 'decimalPlaces' argument - * specifies the number of digits to the right of the decimal point (0-9). Uses - * scientific notation if 'decimalPlaces is negative. - */ - public static String d2s(double n, int decimalPlaces) { - if (Double.isNaN(n) || Double.isInfinite(n)) - return "" + n; - if (n == Float.MAX_VALUE) // divide by 0 in FloatProcessor - return "3.4e38"; - double np = n; - if (n < 0.0) - np = -n; - if (decimalPlaces < 0) - synchronized (IJ.class) { - decimalPlaces = -decimalPlaces; - if (decimalPlaces > 9) - decimalPlaces = 9; - if (sf == null) { - if (dfs == null) - dfs = new DecimalFormatSymbols(Locale.US); - sf = new DecimalFormat[10]; - sf[1] = new DecimalFormat("0.0E0", dfs); - sf[2] = new DecimalFormat("0.00E0", dfs); - sf[3] = new DecimalFormat("0.000E0", dfs); - sf[4] = new DecimalFormat("0.0000E0", dfs); - sf[5] = new DecimalFormat("0.00000E0", dfs); - sf[6] = new DecimalFormat("0.000000E0", dfs); - sf[7] = new DecimalFormat("0.0000000E0", dfs); - sf[8] = new DecimalFormat("0.00000000E0", dfs); - sf[9] = new DecimalFormat("0.000000000E0", dfs); - } - return sf[decimalPlaces].format(n); // use scientific notation - } - if (decimalPlaces < 0) - decimalPlaces = 0; - if (decimalPlaces > 9) - decimalPlaces = 9; - - return df[decimalPlaces].format(n); - } - - /** - * Converts a number to a rounded formatted string. The 'significantDigits' - * argument specifies the minimum number of significant digits, which is also - * the preferred number of digits behind the decimal. Fewer decimals are shown - * if the number would have more than 'maxDigits'. Exponential notation is used - * if more than 'maxDigits' would be needed. - */ - public static String d2s(double x, int significantDigits, int maxDigits) { - double log10 = Math.log10(Math.abs(x)); - double roundErrorAtMax = 0.223 * Math.pow(10, -maxDigits); - int magnitude = (int) Math.ceil(log10 + roundErrorAtMax); - int decimals = x == 0 ? 0 : maxDigits - magnitude; - if (decimals < 0 || magnitude < significantDigits + 1 - maxDigits) - return IJ.d2s(x, -significantDigits); // exp notation for large and - // small numbers - else { - if (decimals > significantDigits) - decimals = Math.max(significantDigits, decimals - maxDigits + significantDigits); - return IJ.d2s(x, decimals); - } - } - - /** Pad 'n' with leading zeros to the specified number of digits. */ - public static String pad(int n, int digits) { - String str = "" + n; - while (str.length() < digits) - str = "0" + str; - return str; - } - - /** Pad 's' with leading zeros to the specified number of digits. */ - public static String pad(String s, int digits) { - String str = "" + s; - while (str.length() < digits) - str = "0" + str; - return str; - } - - /** Obsolete */ - public static void register(Class c) { - if (ij != null) - ij.register(c); - } - - /** Returns true if the space bar is down. */ - public static boolean spaceBarDown() { - return spaceDown; - } - - /** Returns true if the control key is down. */ - public static boolean controlKeyDown() { - return controlDown; - } - - /** Returns true if the alt key is down. */ - public static boolean altKeyDown() { - return altDown; - } - - /** Returns true if the shift key is down. */ - public static boolean shiftKeyDown() { - return shiftDown; - } - - /* Sets the specified key "down", where 'key' - * is KeyEvent.VK_CONTROL, KeyEvent.VK_META, - * KeyEvent.VK_ALT, KeyEvent.VK_SHIFT, - * KeyEvent.VK_SPACE or KeyEvent.VK_ESCAPE. - */ - public static void setKeyDown(int key) { - switch (key) { - case KeyEvent.VK_CONTROL: - controlDown = true; - break; - case KeyEvent.VK_META: - if (isMacintosh()) - controlDown = true; - break; - case KeyEvent.VK_ALT: - altDown = true; - updateStatus(); - break; - case KeyEvent.VK_SHIFT: - shiftDown = true; - if (debugMode) - beep(); - break; - case KeyEvent.VK_SPACE: { - spaceDown = true; - ImageWindow win = WindowManager.getCurrentWindow(); - // if (win != null) win.getCanvas().setCursor(-1, -1, -1, -1); - break; - } - case KeyEvent.VK_ESCAPE: { - escapePressed = true; - break; - } - } - } - - /* Sets the specified key "up", where 'key' - * is KeyEvent.VK_CONTROL, KeyEvent.VK_META, - * KeyEvent.VK_ALT, KeyEvent.VK_SHIFT, - * KeyEvent.VK_SPACE or IJ.ALL_KEYS (-1). - */ - public static void setKeyUp(int key) { - switch (key) { - case KeyEvent.VK_CONTROL: - controlDown = false; - break; - case KeyEvent.VK_META: - if (isMacintosh()) - controlDown = false; - break; - case KeyEvent.VK_ALT: - altDown = false; - updateStatus(); - break; - case KeyEvent.VK_SHIFT: - shiftDown = false; - if (debugMode) - beep(); - break; - - case KeyEvent.VK_SPACE: - spaceDown = false; - ImageWindow win = WindowManager.getCurrentWindow(); - // if (win != null) win.getCanvas().setCursor(-1, -1, -1, -1); - break; - case ALL_KEYS: - shiftDown = controlDown = altDown = spaceDown = false; - break; - } - } - - private static void updateStatus() { - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp != null) { - Roi roi = imp.getRoi(); - if (roi != null && imp.getCalibration().scaled()) { - roi.showStatus(); - } - } - } - - public static void setInputEvent(InputEvent e) { - altDown = e.isAltDown(); - shiftDown = e.isShiftDown(); - } - - /** Returns true if this machine is a Macintosh. */ - public static boolean isMacintosh() { - return isMac; - } - - /** Returns true if this machine is a Macintosh running OS X. */ - public static boolean isMacOSX() { - return isMacintosh(); - } - - /** Returns true if this machine is running Windows. */ - public static boolean isWindows() { - return isWin; - } - - /** Returns the Java version (6, 7, 8, 9, 10, etc.). */ - public static int javaVersion() { - return javaVersion; - } - - /** Always returns true. */ - public static boolean isJava2() { - return true; - } - - /** Always returns true. */ - public static boolean isJava14() { - return true; - } - - /** Always returns true. */ - public static boolean isJava15() { - return true; - } - - /** Returns true if ImageJ is running on a Java 1.6 or greater JVM. */ - public static boolean isJava16() { - return javaVersion >= 6; - } - - /** Returns true if ImageJ is running on a Java 1.7 or greater JVM. */ - public static boolean isJava17() { - return javaVersion >= 7; - } - - /** Returns true if ImageJ is running on a Java 1.8 or greater JVM. */ - public static boolean isJava18() { - return javaVersion >= 8; - } - - /** Returns true if ImageJ is running on a Java 1.9 or greater JVM. */ - public static boolean isJava19() { - return javaVersion >= 9; - } - - /** Returns true if ImageJ is running on Linux. */ - public static boolean isLinux() { - return isLinux; - } - - /** Obsolete; always returns false. */ - public static boolean isVista() { - return false; - } - - /** Returns true if ImageJ is running a 64-bit version of Java. */ - public static boolean is64Bit() { - if (osarch == null) - osarch = System.getProperty("os.arch"); - return osarch != null && osarch.indexOf("64") != -1; - } - - /** - * Displays an error message and returns true if the ImageJ version is less than - * the one specified. - */ - public static boolean versionLessThan(String version) { - boolean lessThan = ImageJ.VERSION.compareTo(version) < 0; - if (lessThan) - error("This plugin or macro requires ImageJ " + version - + " or later. Use\nHelp>Update ImageJ to upgrade to the latest version."); - return lessThan; - } - - /** - * Displays a "Process all images?" dialog. Returns - * 'flags'+PlugInFilter.DOES_STACKS if the user selects "Yes", 'flags' if the - * user selects "No" and PlugInFilter.DONE if the user selects "Cancel". - */ - public static int setupDialog(ImagePlus imp, int flags) { - if (imp == null || (ij != null && ij.hotkey)) { - if (ij != null) - ij.hotkey = false; - return flags; - } - int stackSize = imp.getStackSize(); - if (stackSize > 1) { - String macroOptions = Macro.getOptions(); - if (imp.isComposite() && ((CompositeImage) imp).getMode() == IJ.COMPOSITE) { - if (macroOptions == null || !macroOptions.contains("slice")) - return flags | PlugInFilter.DOES_STACKS; - } - if (macroOptions != null) { - if (macroOptions.indexOf("stack ") >= 0) - return flags | PlugInFilter.DOES_STACKS; - else - return flags; - } - if (hideProcessStackDialog) - return flags; - String note = ((flags & PlugInFilter.NO_CHANGES) == 0) ? " There is\nno Undo if you select \"Yes\"." : ""; - YesNoCancelDialog d = new YesNoCancelDialog(getInstance(), "Process Stack?", - "Process all " + stackSize + " images?" + note); - if (d.cancelPressed()) - return PlugInFilter.DONE; - else if (d.yesPressed()) { - if (imp.getStack().isVirtual() && ((flags & PlugInFilter.NO_CHANGES) == 0)) { - int size = (stackSize * imp.getWidth() * imp.getHeight() * imp.getBytesPerPixel() + 524288) - / 1048576; - String msg = "Use the Process>Batch>Virtual Stack command\n" - + "to process a virtual stack or convert it into a\n" - + "normal stack using Image>Duplicate, which\n" + "will require " + size - + "MB of additional memory."; - error(msg); - return PlugInFilter.DONE; - } - if (IJ.recording()) - Recorder.recordOption("stack"); - return flags | PlugInFilter.DOES_STACKS; - } - if (IJ.recording()) - Recorder.recordOption("slice"); - } - return flags; - } - - /** - * Creates a rectangular selection. Removes any existing selection if width or - * height are less than 1. - */ - public static void makeRectangle(int x, int y, int width, int height) { - if (width <= 0 || height < 0) - getImage().deleteRoi(); - else { - ImagePlus img = getImage(); - if (Interpreter.isBatchMode()) - img.setRoi(new Roi(x, y, width, height), false); - else - img.setRoi(x, y, width, height); - } - } - - /** Creates a subpixel resolution rectangular selection. */ - public static void makeRectangle(double x, double y, double width, double height) { - if (width <= 0 || height < 0) - getImage().deleteRoi(); - else - getImage().setRoi(new Roi(x, y, width, height), !Interpreter.isBatchMode()); - } - - /** - * Creates an oval selection. Removes any existing selection if width or height - * are less than 1. - */ - public static void makeOval(int x, int y, int width, int height) { - if (width <= 0 || height < 0) - getImage().deleteRoi(); - else { - ImagePlus img = getImage(); - img.setRoi(new OvalRoi(x, y, width, height)); - } - } - - /** Creates an subpixel resolution oval selection. */ - public static void makeOval(double x, double y, double width, double height) { - if (width <= 0 || height < 0) - getImage().deleteRoi(); - else - getImage().setRoi(new OvalRoi(x, y, width, height)); - } - - /** Creates a straight line selection. */ - public static void makeLine(int x1, int y1, int x2, int y2) { - getImage().setRoi(new Line(x1, y1, x2, y2)); - } - - /** Creates a straight line selection using floating point coordinates. */ - public static void makeLine(double x1, double y1, double x2, double y2) { - getImage().setRoi(new Line(x1, y1, x2, y2)); - } - - /** Creates a point selection using integer coordinates.. */ - public static void makePoint(int x, int y) { - ImagePlus img = getImage(); - Roi roi = img.getRoi(); - if (shiftKeyDown() && roi != null && roi.getType() == Roi.POINT) { - ((PointRoi)roi).addUserPoint(null, x, y); - IJ.setKeyUp(KeyEvent.VK_SHIFT); - } else if (altKeyDown() && roi != null && roi.getType() == Roi.POINT) { - ((PolygonRoi) roi).deleteHandle(x, y); - IJ.setKeyUp(KeyEvent.VK_ALT); - } else - img.setRoi(new PointRoi(x, y)); - } - - /** Creates a point selection using floating point coordinates. */ - public static void makePoint(double x, double y) { - ImagePlus img = getImage(); - Roi roi = img.getRoi(); - if (shiftKeyDown() && roi != null && roi.getType() == Roi.POINT) { - ((PointRoi)roi).addUserPoint(null, x, y); - IJ.setKeyUp(KeyEvent.VK_SHIFT); - } else if (altKeyDown() && roi != null && roi.getType() == Roi.POINT) { - ((PolygonRoi) roi).deleteHandle(x, y); - IJ.setKeyUp(KeyEvent.VK_ALT); - } else - img.setRoi(new PointRoi(x, y)); - } - - /** Creates an Roi. */ - public static Roi Roi(double x, double y, double width, double height) { - return new Roi(x, y, width, height); - } - - /** Creates an OvalRoi. */ - public static OvalRoi OvalRoi(double x, double y, double width, double height) { - return new OvalRoi(x, y, width, height); - } - - /** - * Sets the display range (minimum and maximum displayed pixel values) of the - * current image. - */ - public static void setMinAndMax(double min, double max) { - setMinAndMax(getImage(), min, max, 7); - } - - /** - * Sets the display range (minimum and maximum displayed pixel values) of the - * specified image. - */ - public static void setMinAndMax(ImagePlus img, double min, double max) { - setMinAndMax(img, min, max, 7); - } - - /** - * Sets the minimum and maximum displayed pixel values on the specified RGB - * channels, where 4=red, 2=green and 1=blue. - */ - public static void setMinAndMax(double min, double max, int channels) { - setMinAndMax(getImage(), min, max, channels); - } - - private static void setMinAndMax(ImagePlus img, double min, double max, int channels) { - Calibration cal = img.getCalibration(); - min = cal.getRawValue(min); - max = cal.getRawValue(max); - if (channels == 7) - img.setDisplayRange(min, max); - else - img.setDisplayRange(min, max, channels); - img.updateAndDraw(); - } - - /** - * Resets the minimum and maximum displayed pixel values of the current image to - * be the same as the min and max pixel values. - */ - public static void resetMinAndMax() { - resetMinAndMax(getImage()); - } - - /** - * Resets the minimum and maximum displayed pixel values of the specified image - * to be the same as the min and max pixel values. - */ - public static void resetMinAndMax(ImagePlus img) { - img.resetDisplayRange(); - img.updateAndDraw(); - } - - /** - * Sets the lower and upper threshold levels and displays the image using red to - * highlight thresholded pixels. May not work correctly on 16 and 32 bit images - * unless the display range has been reset using IJ.resetMinAndMax(). - */ - public static void setThreshold(double lowerThreshold, double upperThresold) { - setThreshold(lowerThreshold, upperThresold, null); - } - - /** - * Sets the lower and upper threshold levels and displays the image using the - * specified displayMode ("Red", "Black & White", "Over/Under" or - * "No Update"). - */ - public static void setThreshold(double lowerThreshold, double upperThreshold, String displayMode) { - setThreshold(getImage(), lowerThreshold, upperThreshold, displayMode); - } - - /** Sets the lower and upper threshold levels of the specified image. */ - public static void setThreshold(ImagePlus img, double lowerThreshold, double upperThreshold) { - setThreshold(img, lowerThreshold, upperThreshold, "Red"); - } - - /** - * Sets the lower and upper threshold levels of the specified image and updates - * the display using the specified displayMode ("Red", "Black & - * White", "Over/Under" or "No Update"). With calibrated images, - * 'lowerThreshold' and 'upperThreshold' must be density calibrated values. Use - * setRawThreshold() to set the threshold using raw (uncalibrated) values. - */ - public static void setThreshold(ImagePlus img, double lowerThreshold, double upperThreshold, String displayMode) { - Calibration cal = img.getCalibration(); - if (displayMode == null || !displayMode.contains("raw")) { - lowerThreshold = cal.getRawValue(lowerThreshold); - upperThreshold = cal.getRawValue(upperThreshold); - } - setRawThreshold(img, lowerThreshold, upperThreshold, displayMode); - } - - /** - * This is a version of setThreshold() that uses raw (uncalibrated) values in - * the range 0-255 for 8-bit images and 0-65535 for 16-bit images and the "Red" - * LUT display mode. - */ - public static void setRawThreshold(ImagePlus img, double lowerThreshold, double upperThreshold) { - setRawThreshold(img, lowerThreshold, upperThreshold, null); - } - - /** - * This is a version of setThreshold() that always uses raw (uncalibrated) - * values * in the range 0-255 for 8-bit images and 0-65535 for 16-bit images. - */ - - public static void setRawThreshold(ImagePlus img, double lowerThreshold, double upperThreshold, - String displayMode) { - int mode = ImageProcessor.RED_LUT; - if (displayMode != null) { - displayMode = displayMode.toLowerCase(Locale.US); - if (displayMode.contains("black")) - mode = ImageProcessor.BLACK_AND_WHITE_LUT; - else if (displayMode.contains("over")) - mode = ImageProcessor.OVER_UNDER_LUT; - else if (displayMode.contains("no")) - mode = ImageProcessor.NO_LUT_UPDATE; - } - img.getProcessor().setThreshold(lowerThreshold, upperThreshold, mode); - if (mode != ImageProcessor.NO_LUT_UPDATE && img.getWindow() != null) { - img.getProcessor().setLutAnimation(true); - img.updateAndDraw(); - ThresholdAdjuster.update(); - } - } - /** Replaced by ImagePlus.setAutoThreshold(). */ - public static void setAutoThreshold(ImagePlus imp, String method) { - ImageProcessor ip = imp.getProcessor(); - if (ip instanceof ColorProcessor) - throw new IllegalArgumentException("Non-RGB image required"); - ip.setRoi(imp.getRoi()); - if (method != null) { - try { - if (method.indexOf("stack") != -1) - setStackThreshold(imp, ip, method); - else - ip.setAutoThreshold(method); - } catch (Exception e) { - log(e.getMessage()); - } - } else - ip.setAutoThreshold(ImageProcessor.ISODATA2, ImageProcessor.RED_LUT); - ThresholdAdjuster.setMethod(method); - imp.updateAndDraw(); - } - - private static void setStackThreshold(ImagePlus imp, ImageProcessor ip, String method) { - boolean darkBackground = method.contains("dark"); - boolean histo16 = imp.getBitDepth()==16 && method.contains("16"); - //IJ.log("setStackThreshold: "+histo16+" "+method); - boolean addOne = !method.contains("16"); - int measurements = Analyzer.getMeasurements(); - Analyzer.setMeasurements(Measurements.AREA + Measurements.MIN_MAX); - ImageStatistics stats = new StackStatistics(imp); - Analyzer.setMeasurements(measurements); - AutoThresholder thresholder = new AutoThresholder(); - double min = 0.0, max = 255.0; - if (imp.getBitDepth() != 8) { - min = stats.min; - max = stats.max; - } - int[] histogram = stats.histogram; - if (histo16) - histogram = stats.histogram16; - int threshold = thresholder.getThreshold(method, histogram); - double lower, upper; - double tmax = 255.0; - if (histogram.length>256) - tmax = 65535.0; - if (darkBackground) { - if (ip.isInvertedLut()) { - lower = 0.0; - upper = threshold; - } else { - {lower=threshold+(addOne?1:0); upper=tmax;} - } - } else { - if (ip.isInvertedLut()) { - {lower=threshold+(addOne?1:0); upper=tmax;} - } else { - lower = 0.0; - upper = threshold; - } - } - if (!histo16) { - if (lower>255) lower = 255; - if (max>min) { - lower = min + (lower/255.0)*(max-min); - upper = min + (upper/255.0)*(max-min); - } else - lower = upper = min; - ip.setMinAndMax(min, max); - } - ip.setThreshold(lower, upper, ImageProcessor.RED_LUT); - imp.updateAndDraw(); - } - - /** Disables thresholding on the current image. */ - public static void resetThreshold() { - resetThreshold(getImage()); - } - - /** Disables thresholding on the specified image. */ - public static void resetThreshold(ImagePlus img) { - ImageProcessor ip = img.getProcessor(); - ip.resetThreshold(); - ip.setLutAnimation(true); - img.updateAndDraw(); - ThresholdAdjuster.update(); - } - - /** - * For IDs less than zero, activates the image with the specified ID. For IDs - * greater than zero, activates the Nth image. - */ - public static void selectWindow(int id) { - if (id > 0) - id = WindowManager.getNthImageID(id); - ImagePlus imp = WindowManager.getImage(id); - if (imp == null) - error("Macro Error", "Image " + id + " not found or no images are open."); - if (Interpreter.isBatchMode()) { - ImagePlus impT = WindowManager.getTempCurrentImage(); - ImagePlus impC = WindowManager.getCurrentImage(); - if (impC != null && impC != imp && impT != null) - impC.saveRoi(); - WindowManager.setTempCurrentImage(imp); - Interpreter.activateImage(imp); - WindowManager.setWindow(null); - } else { - if (imp == null) - return; - ImageWindow win = imp.getWindow(); - if (win != null) { - win.toFront(); - win.setState(Frame.NORMAL); - /*Changed for Bio7 to open the specified tab!*/ - IJTabs.setActiveTabWindow(win); - - WindowManager.setWindow(win); - } - long start = System.currentTimeMillis(); - // timeout after 1 second unless current thread is event dispatch thread - // thread - String thread = Thread.currentThread().getName(); - /*We run in an Eclipse job here so we don't have an "EventQueue"*/ - // int timeout = thread != null && thread.indexOf("EventQueue") != -1 ? 0 : - // 1000; - int timeout = thread != null ? 0 : 1000; - if (IJ.isMacOSX() && IJ.isJava18() && timeout > 0) - timeout = 250; // work around OS X/Java 8 window activation bug - while (true) { - wait(10); - imp = WindowManager.getCurrentImage(); - if (imp != null && imp.getID() == id) - return; // specified image is now active - if ((System.currentTimeMillis() - start) > timeout && win != null) { - WindowManager.setCurrentWindow(win); - return; - } - } - } - } - - /** Activates the window with the specified title. */ - public static void selectWindow(String title) { - if (title.equals("ImageJ") && ij != null) { - ij.toFront(); - return; - } - long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < 3000) { // 3 sec timeout - Window win = WindowManager.getWindow(title); - if (win != null && !(win instanceof ImageWindow)) { - selectWindow(win); - return; - } - int[] wList = WindowManager.getIDList(); - int len = wList != null ? wList.length : 0; - for (int i = 0; i < len; i++) { - ImagePlus imp = WindowManager.getImage(wList[i]); - if (imp != null) { - if (imp.getTitle().equals(title)) { - selectWindow(imp.getID()); - return; - } - } - } - wait(10); - } - error("Macro Error", "No window with the title \"" + title + "\" found."); - } - - static void selectWindow(Window win) { - /*Changed for Bio7 to JFrame!*/ - if (win instanceof JFrame) { - ((JFrame) win).toFront(); - // IJTabs.setActiveTabWindow(win); - } else if (win instanceof Frame) { - ((Frame) win).toFront(); - ((Frame) win).setState(Frame.NORMAL); - } else - ((Dialog) win).toFront(); - long start = System.currentTimeMillis(); - while (true) { - wait(10); - if (WindowManager.getActiveWindow() == win) - return; // specified window is now in front - if ((System.currentTimeMillis() - start) > 100) { - WindowManager.setWindow(win); - return; // 1 second timeout - } - } - } - - /** Sets the foreground color. */ - public static void setForegroundColor(int red, int green, int blue) { - setColor(red, green, blue, true); - } - - /** Sets the background color. */ - public static void setBackgroundColor(int red, int green, int blue) { - setColor(red, green, blue, false); - } - - static void setColor(int red, int green, int blue, boolean foreground) { - Color c = Colors.toColor(red, green, blue); - if (foreground) { - Toolbar.setForegroundColor(c); - ImagePlus img = WindowManager.getCurrentImage(); - if (img != null) - img.getProcessor().setColor(c); - } else - Toolbar.setBackgroundColor(c); - } - - /** - * Switches to the specified tool, where id = Toolbar.RECTANGLE (0), - * Toolbar.OVAL (1), etc. - */ - public static void setTool(int id) { - Toolbar.getInstance().setTool(id); - } - - /** - * Switches to the specified tool, where 'name' is "rect", "elliptical", - * "brush", etc. Returns 'false' if the name is not recognized. - */ - public static boolean setTool(String name) { - return Toolbar.getInstance().setTool(name); - } - - /** Returns the name of the current tool. */ - public static String getToolName() { - return Toolbar.getToolName(); - } - - /** - * Equivalent to clicking on the current image at (x,y) with the wand tool. - * Returns the number of points in the resulting ROI. - */ - public static int doWand(int x, int y) { - return doWand(getImage(), x, y, 0, null); - } - - /** - * Traces the boundary of the area with pixel values within 'tolerance' of the - * value of the pixel at the starting location. 'tolerance' is in uncalibrated - * units. 'mode' can be "4-connected", "8-connected" or "Legacy". "Legacy" is - * for compatibility with previous versions of ImageJ; it is ignored if - * 'tolerance' > 0. - */ - public static int doWand(int x, int y, double tolerance, String mode) { - return doWand(getImage(), x, y, tolerance, mode); - } - - /** This version of doWand adds an ImagePlus argument. */ - public static int doWand(ImagePlus img, int x, int y, double tolerance, String mode) { - ImageProcessor ip = img.getProcessor(); - if ((img.getType() == ImagePlus.GRAY32) && Double.isNaN(ip.getPixelValue(x, y))) - return 0; - int imode = Wand.LEGACY_MODE; - boolean smooth = false; - if (mode != null) { - if (mode.startsWith("4")) - imode = Wand.FOUR_CONNECTED; - else if (mode.startsWith("8")) - imode = Wand.EIGHT_CONNECTED; - smooth = mode.contains("smooth"); - - } - Wand w = new Wand(ip); - if (!ip.isThreshold() || (ip.getLutUpdateMode()==ImageProcessor.NO_LUT_UPDATE&& tolerance>0.0)) { - w.autoOutline(x, y, tolerance, imode); - smooth = false; - } else { - w.autoOutline(x, y, ip.getMinThreshold(), ip.getMaxThreshold(), imode); - } - if (w.npoints > 0) { - Roi previousRoi = img.getRoi(); - Roi roi = new PolygonRoi(w.xpoints, w.ypoints, w.npoints, Roi.TRACED_ROI); - img.deleteRoi(); - img.setRoi(roi); - if (previousRoi != null) - roi.update(shiftKeyDown(), altKeyDown()); // add/subtract ROI to previous one if shift/alt key down - Roi roi2 = img.getRoi(); - if (smooth && roi2 != null && roi2.getType() == Roi.TRACED_ROI) { - Rectangle bounds = roi2.getBounds(); - if (bounds.width > 1 && bounds.height > 1) { - if (smoothMacro == null) - smoothMacro = BatchProcessor.openMacroFromJar("SmoothWandTool.txt"); - if (EventQueue.isDispatchThread()) - new MacroRunner(smoothMacro); // run on separate thread - else - Macro.eval(smoothMacro); - } - } - } - return w.npoints; - } - - /** - * Sets the transfer mode used by the Edit/Paste command, where mode is - * "Copy", "Blend", "Average", "Difference", "Transparent", "Transparent2", - * "AND", "OR", "XOR", "Add", "Subtract", "Multiply", or "Divide". - */ - public static void setPasteMode(String mode) { - Roi.setPasteMode(stringToPasteMode(mode)); - } - - public static int stringToPasteMode(String mode) { - if (mode == null) - return Blitter.COPY; - mode = mode.toLowerCase(Locale.US); - int m = Blitter.COPY; - if (mode.startsWith("ble") || mode.startsWith("ave")) - m = Blitter.AVERAGE; - else if (mode.startsWith("diff")) - m = Blitter.DIFFERENCE; - else if (mode.indexOf("zero") != -1) - m = Blitter.COPY_ZERO_TRANSPARENT; - else if (mode.startsWith("tran")) - m = Blitter.COPY_TRANSPARENT; - else if (mode.startsWith("and")) - m = Blitter.AND; - else if (mode.startsWith("or")) - m = Blitter.OR; - else if (mode.startsWith("xor")) - m = Blitter.XOR; - else if (mode.startsWith("sub")) - m = Blitter.SUBTRACT; - else if (mode.startsWith("add")) - m = Blitter.ADD; - else if (mode.startsWith("div")) - m = Blitter.DIVIDE; - else if (mode.startsWith("mul")) - m = Blitter.MULTIPLY; - else if (mode.startsWith("min")) - m = Blitter.MIN; - else if (mode.startsWith("max")) - m = Blitter.MAX; - return m; - } - - /** - * Returns a reference to the active image, or displays an error message and - * aborts the plugin or macro if no images are open. - */ - public static ImagePlus getImage() { - ImagePlus img = WindowManager.getCurrentImage(); - if (img == null) { - IJ.noImage(); - if (ij == null) - System.exit(0); - else - abort(); - } - return img; - } - - /** The macro interpreter uses this method to call getImage(). */ - public static ImagePlus getImage(Interpreter interpreter) { - macroInterpreter = interpreter; - ImagePlus imp = getImage(); - macroInterpreter = null; - return imp; - } - - /** - * Returns the active image or stack slice as an ImageProcessor, or displays an - * error message and aborts the plugin or macro if no images are open. - */ - public static ImageProcessor getProcessor() { - ImagePlus imp = IJ.getImage(); - return imp.getProcessor(); - } - - /** Switches to the specified stack slice, where 1<='slice'<=stack-size. */ - public static void setSlice(int slice) { - getImage().setSlice(slice); - } - - /** Returns the ImageJ version number as a string. */ - public static String getVersion() { - return ImageJ.VERSION; - } - - /** - * Returns the ImageJ version and build number as a String, for example - * "1.46n05", or 1.46n99 if there is no build number. - */ - public static String getFullVersion() { - String build = ImageJ.BUILD; - if (build.length() == 0) - build = "99"; - else if (build.length() == 1) - build = "0" + build; - return ImageJ.VERSION + build; - } - - /** - * Returns the path to the specified directory if title is "home" - * ("user.home"), "downloads", "startup", "imagej" (ImageJ directory), - * "plugins", "macros", "luts", "temp", "current", "default", "image" (directory - * active image was loaded from), "file" (directory most recently used to open - * or save a file), "cwd" (current working directory) or "preferences" (location - * of "IJ_Prefs.txt" file), otherwise displays a dialog and returns the path to - * the directory selected by the user. Returns null if the specified directory - * is not found or the user cancels the dialog box. Also aborts the macro if the - * user cancels the dialog box. - */ - public static String getDirectory(String title) { - String dir = null; - String title2 = title.toLowerCase(Locale.US); - if (title2.equals("plugins")) - dir = Menus.getPlugInsPath(); - else if (title2.equals("macros")) - dir = Menus.getMacrosPath(); - else if (title2.equals("luts")) { - String ijdir = Prefs.getImageJDir(); - if (ijdir != null) - dir = ijdir + "luts" + File.separator; - else - dir = null; - } else if (title2.equals("home")) - dir = System.getProperty("user.home"); - else if (title2.equals("downloads")) - dir = System.getProperty("user.home") + File.separator + "Downloads"; - else if (title2.equals("startup")) - dir = Prefs.getImageJDir(); - else if (title2.equals("imagej")) - dir = Prefs.getImageJDir(); - else if (title2.equals("current") || title2.equals("default")) - dir = OpenDialog.getDefaultDirectory(); - else if (title2.equals("preferences")) - dir = Prefs.getPrefsDir(); - else if (title2.equals("temp")) { - dir = System.getProperty("java.io.tmpdir"); - if (isMacintosh()) - dir = "/tmp/"; - } else if (title2.equals("image")) { - ImagePlus imp = WindowManager.getCurrentImage(); - FileInfo fi = imp != null ? imp.getOriginalFileInfo() : null; - if (fi != null && fi.directory != null) { - dir = fi.directory; - } else - dir = null; - } else if (title2.equals("file")) - dir = OpenDialog.getLastDirectory(); - else if (title2.equals("cwd")) - dir = System.getProperty("user.dir"); - else { - String defaultDir = OpenDialog.getDefaultDirectory(); - DirectoryChooser dc = new DirectoryChooser(title); - dir = dc.getDirectory(); - OpenDialog.setDefaultDirectory(defaultDir); - if (dir == null) - Macro.abort(); - - } - dir = addSeparator(dir); - return dir; - } - - public static String addSeparator(String path) { - if (path == null) - return null; - if (path.length() > 0 && !(path.endsWith(File.separator) || path.endsWith("/"))) { - if (IJ.isWindows() && path.contains(File.separator)) - path += File.separator; - else - path += "/"; - } - return path; - } - - /** Alias for getDirectory(). */ - public static String getDir(String title) { - return getDirectory(title); - } - - /** - * Displays an open file dialog and returns the path to the choosen file, or - * returns null if the dialog is canceled. - */ - public static String getFilePath(String dialogTitle) { - OpenDialog od = new OpenDialog(dialogTitle); - return od.getPath(); - } - - /** - * Displays a file open dialog box and then opens the tiff, dicom, fits, pgm, - * jpeg, bmp, gif, lut, roi, or text file selected by the user. Displays an - * error message if the selected file is not in one of the supported formats, or - * if it is not found. - */ - public static void open() { - open(null); - } - - /** - * Opens and displays a tiff, dicom, fits, pgm, jpeg, bmp, gif, lut, roi, or - * text file. Displays an error message if the specified file is not in one of - * the supported formats, or if it is not found. With 1.41k or later, opens - * images specified by a URL. - */ - public static void open(String path) { - if (ij == null && Menus.getCommands() == null) - init(); - Opener o = new Opener(); - macroRunning = true; - if (path == null || path.equals("")) - o.open(); - else - o.open(path); - macroRunning = false; - } - - /** Opens and displays the nth image in the specified tiff stack. */ - public static void open(String path, int n) { - if (ij == null && Menus.getCommands() == null) - init(); - ImagePlus imp = openImage(path, n); - if (imp != null) - imp.show(); - } - - /** - * Opens the specified file as a tiff, bmp, dicom, fits, pgm, gif, jpeg * or text image and returns an ImagePlus object if successful. - * Calls HandleExtraFileTypes plugin if the file type is not recognised. - * Displays a file open dialog if 'path' is null or an empty string. - * Note that 'path' can also be a URL. Some reader plugins, including - * the Bio-Formats plugin, display the image and return null. - * Use IJ.open() to display a file open dialog box. - * @see ij.io.Opener#openUsingBioFormats(String) - */ - public static ImagePlus openImage(String path) { - macroRunning = true; - ImagePlus imp = (new Opener()).openImage(path); - macroRunning = false; - return imp; - } - - /** Opens the nth image of the specified tiff stack. */ - public static ImagePlus openImage(String path, int n) { - Opener opener = new Opener(); - opener.doNotUseBioFormats(); - return opener.openImage(path, n); - } - - /** Opens the specified tiff file as a virtual stack. */ - public static ImagePlus openVirtual(String path) { - return FileInfoVirtualStack.openVirtual(path); - } - - /** - * Opens an image using a file open dialog and returns it as an ImagePlus - * object. - */ - public static ImagePlus openImage() { - return openImage(null); - } - - /** - * Opens a URL and returns the contents as a string. Returns "" - * if there an error, including host or file not found. - */ - public static String openUrlAsString(String url) { - // if (!trustManagerCreated && url.contains("nih.gov")) trustAllCerts(); - url = Opener.updateUrl(url); - if (debugMode) - log("OpenUrlAsString: " + url); - StringBuffer sb = null; - url = url.replaceAll(" ", "%20"); - try { - // if (url.contains("nih.gov")) addRootCA(); - URL u = new URL(url); - URLConnection uc = u.openConnection(); - long len = uc.getContentLength(); - if (len > 5242880L) - return ""; - InputStream in = u.openStream(); - BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF-8")); - sb = new StringBuffer(); - String line; - while ((line = br.readLine()) != null) - sb.append(line + "\n"); - in.close(); - } catch (Exception e) { - return (""); - } - if (sb != null) - return new String(sb); - else - return ""; - } - - /** - * Saves the current image, lookup table, selection or text window to the - * specified file path. The path must end in ".tif", ".jpg", ".gif", ".zip", - * ".raw", ".avi", ".bmp", ".fits", ".pgm", ".png", ".lut", ".roi" or ".txt". - */ - public static void save(String path) { - save(null, path); - } - - /** - * Saves the specified image, lookup table or selection to the specified file - * path. The file path should end with ".tif", ".jpg", ".gif", ".zip", ".raw", - * ".avi", ".bmp", ".fits", ".pgm", ".png", ".lut", ".roi" or ".txt". The - * specified image is saved in TIFF format if there is no extension. - */ - - public static void save(ImagePlus imp, String path) { - ImagePlus imp2 = imp; - if (imp2 == null) - imp2 = WindowManager.getCurrentImage(); - int dotLoc = path.lastIndexOf('.'); - if (dotLoc == -1 && imp2 != null) { - path = path + ".tif"; // save as TIFF if file name does not have an - // extension - dotLoc = path.lastIndexOf('.'); - } - - if (dotLoc != -1) { - - String title = imp2 != null ? imp2.getTitle() : null; - saveAs(imp, path.substring(dotLoc + 1), path); - if (title != null) - imp2.setTitle(title); - } else - error("The file path passed to IJ.save() method or save()\nmacro function is missing the required extension.\n \n\"" - + path + "\""); - } - - /* - * Saves the active image, lookup table, selection, measurement results, - * selection XY coordinates or text window to the specified file path. The - * format argument must be "tiff", "jpeg", "gif", "zip", "raw", "avi", "bmp", - * "fits", "pgm", "png", "text image", "lut", "selection", "measurements", - * "xy Coordinates" or "text". If path is null or an emply string, - * a file save dialog is displayed. - */ - public static void saveAs(String format, String path) { - saveAs(null, format, path); - } - - /* - * Saves the specified image. The format argument must be "tiff", "jpeg", "gif", - * "zip", "raw", "avi", "bmp", "fits", "pgm", "png", "text image", "lut", - * "selection" or "xy Coordinates". - */ - public static void saveAs(ImagePlus imp, String format, String path) { - if (format == null) - return; - if (path != null && path.length() == 0) - path = null; - format = format.toLowerCase(Locale.US); - Roi roi2 = imp != null ? imp.getRoi() : null; - if (roi2 != null) - roi2.endPaste(); - if (format.indexOf("tif") != -1) { - saveAsTiff(imp, path); - return; - } else if (format.indexOf("jpeg") != -1 || format.indexOf("jpg") != -1) { - path = updateExtension(path, ".jpg"); - JpegWriter.save(imp, path, FileSaver.getJpegQuality()); - return; - } else if (format.indexOf("gif") != -1) { - path = updateExtension(path, ".gif"); - GifWriter.save(imp, path); - return; - } else if (format.indexOf("text image") != -1) { - String extension = ".txt"; - if (path!=null && (path.endsWith(".csv")||path.endsWith(".CSV"))) - extension = ".csv"; - path = updateExtension(path, extension); - format = "Text Image..."; - } else if (format.indexOf("text") != -1 || format.indexOf("txt") != -1) { - if (path != null && !path.endsWith(".xls") && !path.endsWith(".csv") && !path.endsWith(".tsv")) - path = updateExtension(path, ".txt"); - format = "Text..."; - } else if (format.indexOf("zip") != -1) { - path = updateExtension(path, ".zip"); - format = "ZIP..."; - } else if (format.indexOf("raw") != -1) { - // path = updateExtension(path, ".raw"); - format = "Raw Data..."; - } else if (format.indexOf("avi") != -1) { - path = updateExtension(path, ".avi"); - format = "AVI... "; - } else if (format.indexOf("bmp") != -1) { - path = updateExtension(path, ".bmp"); - format = "BMP..."; - } else if (format.indexOf("fits") != -1) { - path = updateExtension(path, ".fits"); - format = "FITS..."; - } else if (format.indexOf("png") != -1) { - path = updateExtension(path, ".png"); - format = "PNG..."; - } else if (format.indexOf("pgm") != -1) { - path = updateExtension(path, ".pgm"); - format = "PGM..."; - } else if (format.indexOf("lut") != -1) { - path = updateExtension(path, ".lut"); - format = "LUT..."; - } else if (format.contains("results") || format.contains("measurements") || format.contains("table")) { - format = "Results..."; - } else if (format.contains("selection") || format.contains("roi")) { - path = updateExtension(path, ".roi"); - format = "Selection..."; - } else if (format.indexOf("xy") != -1 || format.indexOf("coordinates") != -1) { - path = updateExtension(path, ".txt"); - format = "XY Coordinates..."; - } else - error("Unsupported save() or saveAs() file format: \"" + format + "\"\n \n\"" + path + "\""); - if (path == null) - run(format); - else { - if (path.contains(" ")) - run(imp, format, "save=[" + path + "]"); - else - run(imp, format, "save=" + path); - } - } - - /** - * Saves the specified image in TIFF format. Displays a file save dialog if - * 'path' is null or an empty string. Returns 'false' if there is an error or if - * the user selects "Cancel" in the file save dialog. - */ - public static boolean saveAsTiff(ImagePlus imp, String path) { - if (imp == null) - imp = getImage(); - if (path == null || path.equals("")) - return (new FileSaver(imp)).saveAsTiff(); - if (!path.endsWith(".tiff")) - path = updateExtension(path, ".tif"); - FileSaver fs = new FileSaver(imp); - boolean ok; - if (imp.getStackSize() > 1) - ok = fs.saveAsTiffStack(path); - else - ok = fs.saveAsTiff(path); - if (ok) - fs.updateImagePlus(path, FileInfo.TIFF); - return ok; - } - - static String updateExtension(String path, String extension) { - if (path == null) - return null; - int dotIndex = path.lastIndexOf("."); - int separatorIndex = path.lastIndexOf(File.separator); - if (dotIndex >= 0 && dotIndex > separatorIndex && (path.length() - dotIndex) <= 5) { - if (dotIndex + 1 < path.length() && Character.isDigit(path.charAt(dotIndex + 1))) - path += extension; - else - path = path.substring(0, dotIndex) + extension; - } else - path += extension; - return path; - } - - /** - * Saves a string as a file. Displays a file save dialog if 'path' is null or - * blank. Returns an error message if there is an exception, otherwise returns - * null. - */ - public static String saveString(String string, String path) { - return write(string, path, false); - } - - /** - * Appends a string to the end of a file. A newline character ("\n") is added to - * the end of the string before it is written. Returns an error message if there - * is an exception, otherwise returns null. - */ - public static String append(String string, String path) { - return write(string + "\n", path, true); - } - - private static String write(String string, String path, boolean append) { - if (path == null || path.equals("")) { - String msg = append ? "Append String..." : "Save String..."; - SaveDialog sd = new SaveDialog(msg, "Untitled", ".txt"); - String name = sd.getFileName(); - if (name == null) - return null; - path = sd.getDirectory() + name; - } - try { - BufferedWriter out = new BufferedWriter(new FileWriter(path, append)); - out.write(string); - out.close(); - } catch (IOException e) { - return "" + e; - } - return null; - } - - /** - * Opens a text file as a string. Displays a file open dialog if path is null or - * blank. Returns null if the user cancels the file open dialog. If there is an - * error, returns a message in the form "Error: message". - */ - public static String openAsString(String path) { - if (path == null || path.equals("")) { - OpenDialog od = new OpenDialog("Open Text File", ""); - String directory = od.getDirectory(); - String name = od.getFileName(); - if (name == null) - return null; - path = directory + name; - } - String str = ""; - File file = new File(path); - if (!file.exists()) - return "Error: file not found"; - try { - StringBuffer sb = new StringBuffer(5000); - BufferedReader r = new BufferedReader(new FileReader(file)); - while (true) { - String s = r.readLine(); - if (s == null) - break; - else - sb.append(s + "\n"); - } - r.close(); - str = new String(sb); - } catch (Exception e) { - str = "Error: " + e.getMessage(); - } - return str; - } - - public static ByteBuffer openAsByteBuffer(String path) { - if (path == null || path.equals("")) { - OpenDialog od = new OpenDialog("Open as ByteBuffer", ""); - String directory = od.getDirectory(); - String name = od.getFileName(); - if (name == null) - return null; - path = directory + name; - } - File file = new File(path); - if (!file.exists()) { - error("OpenAsByteBuffer", "File not found"); - return null; - } - int len = (int) file.length(); - byte[] buffer = new byte[len]; - try { - InputStream in = new BufferedInputStream(new FileInputStream(path)); - DataInputStream dis = new DataInputStream(in); - dis.readFully(buffer); - dis.close(); - } catch (Exception e) { - error("OpenAsByteBuffer", e.getMessage()); - return null; - } - return ByteBuffer.wrap(buffer); - } - - /** - * Creates a new image. - * - * @param title image name - * @param width image width in pixels - * @param height image height in pixels - * @param depth number of stack images - * @param bitdepth 8, 16, 32 (float) or 24 (RGB) - */ - public static ImagePlus createImage(String title, int width, int height, int depth, int bitdepth) { - return NewImage.createImage(title, width, height, depth, bitdepth, NewImage.FILL_BLACK); - } - - /** - * Creates a new imagePlus. Type should contain "8-bit", "16-bit", - * "32-bit" or "RGB". In addition, it can contain "white", "black" or "ramp". - * Width and height specify the width and height of - * the image in pixels. Depth specifies the number of stack slices. - */ - public static ImagePlus createImage(String title, String type, int width, int height, int depth) { - type = type.toLowerCase(Locale.US); - int bitDepth = 8; - if (type.contains("16")) - bitDepth = 16; - boolean signedInt = type.contains("32-bit int"); - if (type.contains("32")) - bitDepth = 32; - if (type.contains("24") || type.contains("rgb") || signedInt) - bitDepth = 24; - int options = NewImage.FILL_WHITE; - if (bitDepth == 16 || bitDepth == 32) - options = NewImage.FILL_BLACK; - if (type.contains("white")) - options = NewImage.FILL_WHITE; - else if (type.contains("black")) - options = NewImage.FILL_BLACK; - else if (type.contains("ramp")) - options = NewImage.FILL_RAMP; - else if (type.contains("noise") || type.contains("random")) - options = NewImage.FILL_NOISE; - options += NewImage.CHECK_AVAILABLE_MEMORY; - if (signedInt) - options += NewImage.SIGNED_INT; - return NewImage.createImage(title, width, height, depth, bitDepth, options); - } - - /** - * Creates a new hyperstack. - * - * @param title image name - * @param type "8-bit", "16-bit", "32-bit" or "RGB". May also contain - * "white" , "black" (the default), "ramp", "composite-mode", - * "color-mode", "grayscale-mode or "label". - * @param width image width in pixels - * @param height image height in pixels - * @param channels number of channels - * @param slices number of slices - * @param frames number of frames - */ - public static ImagePlus createImage(String title, String type, int width, int height, int channels, int slices, - int frames) { - if (type.contains("label")) - type += "ramp"; - if (!(type.contains("white") || type.contains("ramp"))) - type += "black"; - ImagePlus imp = IJ.createImage(title, type, width, height, channels * slices * frames); - imp.setDimensions(channels, slices, frames); - int mode = IJ.COLOR; - if (type.contains("composite")) - mode = IJ.COMPOSITE; - if (type.contains("grayscale")) - mode = IJ.GRAYSCALE; - if (channels > 1 && imp.getBitDepth() != 24) - imp = new CompositeImage(imp, mode); - imp.setOpenAsHyperStack(true); - if (type.contains("label")) - HyperStackMaker.labelHyperstack(imp); - return imp; - } - - /** - * Creates a new hyperstack. - * - * @param title image name - * @param width image width in pixels - * @param height image height in pixels - * @param channels number of channels - * @param slices number of slices - * @param frames number of frames - * @param bitdepth 8, 16, 32 (float) or 24 (RGB) - */ - public static ImagePlus createHyperStack(String title, int width, int height, int channels, int slices, int frames, - int bitdepth) { - ImagePlus imp = createImage(title, width, height, channels * slices * frames, bitdepth); - imp.setDimensions(channels, slices, frames); - if (channels > 1 && bitdepth != 24) - imp = new CompositeImage(imp, IJ.COMPOSITE); - imp.setOpenAsHyperStack(true); - return imp; - } - - /** - * Opens a new image. Type should contain "8-bit", "16-bit", - * "32-bit" or "RGB". In addition, it can contain "white", "black" or "ramp". - * Width and height specify the width and height of - * the image in pixels. Depth specifies the number of stack slices. - */ - public static void newImage(String title, String type, int width, int height, int depth) { - ImagePlus imp = createImage(title, type, width, height, depth); - if (imp != null) { - macroRunning = true; - imp.show(); - macroRunning = false; - } - } - - /** - * Returns true if the Esc key was pressed since the last ImageJ - * command started to execute or since resetEscape() was called. - */ - public static boolean escapePressed() { - return escapePressed; - } - - /** - * This method sets the Esc key to the "up" position. The Executer - * class calls this method when it runs an ImageJ command in a separate thread. - */ - public static void resetEscape() { - escapePressed = false; - } - - /** - * Causes IJ.error() output to be temporarily redirected to the "Log" window. - */ - public static void redirectErrorMessages() { - redirectErrorMessages = true; - lastErrorMessage = null; - } - - /** - * Set 'true' and IJ.error() output will be temporarily redirected to the "Log" - * window. - */ - public static void redirectErrorMessages(boolean redirect) { - redirectErrorMessages = redirect; - lastErrorMessage = null; - } - - /** - * Returns the state of the 'redirectErrorMessages' flag, which is set by - * File/Import/Image Sequence. - */ - public static boolean redirectingErrorMessages() { - return redirectErrorMessages; - } - - /** Temporarily suppress "plugin not found" errors. */ - public static void suppressPluginNotFoundError() { - suppressPluginNotFoundError = true; - } - - /** - * Returns the class loader ImageJ uses to run plugins or the system class - * loader if Menus.getPlugInsPath() returns null. - */ - public static ClassLoader getClassLoader() { - if (classLoader == null) { - String pluginsDir = Menus.getPlugInsPath(); - if (pluginsDir == null) { - String home = System.getProperty("plugins.dir"); - if (home != null) { - if (!home.endsWith(Prefs.separator)) - home += Prefs.separator; - pluginsDir = home + "plugins" + Prefs.separator; - if (!(new File(pluginsDir)).isDirectory()) - pluginsDir = home; - } - } - if (pluginsDir == null) - return IJ.class.getClassLoader(); - else { - if (Menus.jnlp) - classLoader = new PluginClassLoader(pluginsDir, true); - else - classLoader = new PluginClassLoader(pluginsDir); - } - } - return classLoader; - } - - /** Returns the size, in pixels, of the primary display. */ - public static Dimension getScreenSize() { - Rectangle bounds = GUI.getScreenBounds(); - return new Dimension(bounds.width, bounds.height); - } - - /** - * Returns, as an array of strings, a list of the LUTs in the Image/Lookup - * Tables menu. - * - * @see ij.plugin.LutLoader#getLut See also: Help>Examples>JavaScript/Show all - * LUTs and Image/Color/Display LUTs - */ - public static String[] getLuts() { - ArrayList list = new ArrayList(); - Hashtable commands = Menus.getCommands(); - Menu lutsMenu = Menus.getImageJMenu("Image>Lookup Tables"); - if (commands == null || lutsMenu == null) - return new String[0]; - for (int i = 0; i < lutsMenu.getItemCount(); i++) { - MenuItem menuItem = lutsMenu.getItem(i); - String label = menuItem.getLabel(); - if (label.equals("-") || label.equals("Invert LUT") || label.equals("Apply LUT")) - continue; - String command = (String) commands.get(label); - if (command == null || command.startsWith("ij.plugin.LutLoader")) - list.add(label); - } - return (String[]) list.toArray(new String[list.size()]); - } - - static void abort() { - if ((ij != null || Interpreter.isBatchMode()) && macroInterpreter == null) - throw new RuntimeException(Macro.MACRO_CANCELED); - } - - static void setClassLoader(ClassLoader loader) { - classLoader = loader; - } - - public static void resetClassLoader() { - setClassLoader(null); - } - - /** - * Displays a stack trace. Use the setExceptionHandler method() to override with - * a custom exception handler. - */ - public static void handleException(Throwable e) { - if (exceptionHandler != null) { - exceptionHandler.handle(e); - return; - } - if (Macro.MACRO_CANCELED.equals(e.getMessage())) - return; - CharArrayWriter caw = new CharArrayWriter(); - PrintWriter pw = new PrintWriter(caw); - e.printStackTrace(pw); - String s = caw.toString(); - String lineNumber = ""; - if (s != null && s.contains("ThreadDeath")) - return; - Interpreter interpreter = Thread.currentThread().getName().endsWith("Macro$") ? Interpreter.getInstance() : null; - if (interpreter!=null) - lineNumber = "\nMacro line number: " + interpreter.getLineNumber(); - if (getInstance() != null) { - s = IJ.getInstance().getInfo()+lineNumber+"\n \n"+s; - new TextWindow("Exception", s, 500, 340); - } else - log(s); - } - - /** - * Installs a custom exception handler that overrides the handleException() - * method. - */ - public static void setExceptionHandler(ExceptionHandler handler) { - exceptionHandler = handler; - } - - public interface ExceptionHandler { - public void handle(Throwable e); - } - - static ExceptionHandler exceptionHandler; - - public static void addEventListener(IJEventListener listener) { - eventListeners.addElement(listener); - } - - public static void removeEventListener(IJEventListener listener) { - eventListeners.removeElement(listener); - } - - public static void notifyEventListeners(int eventID) { - synchronized (eventListeners) { - for (int i = 0; i < eventListeners.size(); i++) { - IJEventListener listener = (IJEventListener) eventListeners.elementAt(i); - listener.eventOccurred(eventID); - } - } - } - - /** - * Adds a key-value pair to IJ.properties. The key and value are removed if - * 'value' is null. - */ - public static void setProperty(String key, Object value) { - if (properties == null) - properties = new Properties(); - if (value == null) - properties.remove(key); - else - properties.put(key, value); - } - - /** - * Returns the object in IJ.properties associated with 'key', or null if 'key' - * is not found. - */ - public static Object getProperty(String key) { - if (properties == null) - return null; - else - return properties.get(key); - } - - public static boolean statusBarProtected() { - return protectStatusBar; - } - - public static void protectStatusBar(boolean protect) { - protectStatusBar = protect; - if (!protectStatusBar) - statusBarThread = null; - } - - /** Returns 'true' if the Recorder is running and ImageJ is not in headless mode. */ - public static boolean recording() { - return (!GraphicsEnvironment.isHeadless()&&Recorder.record); - } - - -} diff --git a/com.eco.bio7.image/src/ij/IJEventListener.java b/com.eco.bio7.image/src/ij/IJEventListener.java deleted file mode 100644 index f5af9b5ca..000000000 --- a/com.eco.bio7.image/src/ij/IJEventListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package ij; - - /** Plugins that implement this interface are notified when the user - changes the foreground color, changes the background color, - closes the color picker, closes the Log window or switches to - another tool. - */ - public interface IJEventListener { - public static final int FOREGROUND_COLOR_CHANGED = 0; - public static final int BACKGROUND_COLOR_CHANGED = 1; - public static final int COLOR_PICKER_CLOSED= 2; - public static final int LOG_WINDOW_CLOSED= 3; - public static final int TOOL_CHANGED= 4; - - public void eventOccurred(int eventID); - -} diff --git a/com.eco.bio7.image/src/ij/ImageJ.java b/com.eco.bio7.image/src/ij/ImageJ.java deleted file mode 100644 index e9563010b..000000000 --- a/com.eco.bio7.image/src/ij/ImageJ.java +++ /dev/null @@ -1,1205 +0,0 @@ -package ij; - -import ij.gui.*; -import ij.process.*; -import ij.io.*; -import ij.plugin.*; -import ij.plugin.filter.*; -import ij.plugin.frame.*; -import ij.text.*; -import ij.macro.Interpreter; -import ij.io.Opener; -import ij.util.*; -import java.awt.*; -import java.util.*; -import java.awt.event.*; -import java.io.*; -import java.net.*; -import java.awt.image.*; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JLabel; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.PlatformUI; -import com.eco.bio7.ImageJPluginActions.ImageJContextMenuAction; -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.CustomDetachedImageJView; -import com.eco.bio7.image.Fullscreen; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.Util; - -/** - * This frame is the main ImageJ class. - * - * ImageJ is a work of the United States Government. It is in the public domain - * and open source. There is no copyright. You are free to do anything you want - * with this source but I like to get credit for my work and I would like you to - * offer your changes to me so I can possibly add them to the "official" - * version. - * - * - * The following command line options are recognized by ImageJ: - * - * "file-name" - * Opens a file - * Example 1: blobs.tif - * Example 2: /Users/wayne/images/blobs.tif - * Example 3: e81*.tif - * - * -macro path [arg] - * Runs a macro or script (JavaScript, BeanShell or Python), passing an - * optional string argument, which the macro or script can be retrieve - * using the getArgument() function. The macro or script is assumed to - * be in the ImageJ/macros folder if 'path' is not a full directory path. - * Example 1: -macro analyze.ijm - * Example 2: -macro script.js /Users/wayne/images/stack1 - * Example 2: -macro script.py '1.2 2.4 3.8' - * - * -batch path [arg] - * Runs a macro or script (JavaScript, BeanShell or Python) in - * batch (no GUI) mode, passing it an optional argument. - * ImageJ exits when the macro finishes. - * - * -eval "macro code" - * Evaluates macro code - * Example 1: -eval "print('Hello, world');" - * Example 2: -eval "return getVersion();" - * - * -run command - * Runs an ImageJ menu command - * Example: -run "About ImageJ..." - * - * -ijpath path - * Specifies the path to the directory containing the plugins directory - * Example: -ijpath /Applications/ImageJ - * - * -port - * Specifies the port ImageJ uses to determine if another instance is running - * Example 1: -port1 (use default port address + 1) - * Example 2: -port2 (use default port address + 2) - * Example 3: -port0 (don't check for another instance) - * - * -debug - * Runs ImageJ in debug mode - * - * - * @author Wayne Rasband (rasband@gmail.com) - */ -public class ImageJ extends Frame implements ActionListener, MouseListener, KeyListener, WindowListener, ItemListener, Runnable { - - /** - * Plugins should call IJ.getVersion() or IJ.getFullVersion() to get the version - * string. - */ - - public static final String VERSION = "1.54u"; - public static final String BUILD = "8"; - public static Color backgroundColor; - /** SansSerif, 12-point, plain font. */ - public static final Font SansSerif12 = new Font("SansSerif", Font.PLAIN, 12); - /** SansSerif, 14-point, plain font. */ - public static final Font SansSerif14 = new Font("SansSerif", Font.PLAIN, 14); - /** Address of socket where Image accepts commands */ - public static final int DEFAULT_PORT = 57294; - - /** Run as normal application. */ - public static final int STANDALONE = 0; - - /** Run embedded in another application. */ - public static final int EMBEDDED = 1; - - /** Run embedded and invisible in another application. */ - public static final int NO_SHOW = 2; - - /** Run as the ImageJ application. */ - public static final int IMAGEJ_APP = 3; - - /** Run ImageJ in debug mode. */ - public static final int DEBUG = 256; - - private static final String IJ_X = "ij.x", IJ_Y = "ij.y"; - private static int port = DEFAULT_PORT; - private static String[] arguments; - - public Toolbar toolbar;// Changed for Bio7 to public! - public JPanel statusBar;// Changed for Bio7 to public! - private ProgressBar progressBar; - public JLabel statusLine; - private boolean firstTime = true; - private java.applet.Applet applet; // null if not running as an applet - private Vector classes = new Vector(); - private boolean exitWhenQuitting; - private boolean quitting; - private boolean quitMacro; - private long keyPressedTime, actionPerformedTime; - private String lastKeyCommand; - private boolean embedded; - private boolean windowClosed; - private static String commandName; - /* Changed for Bio7! -> Bio7 variables! */ - public static Fullscreen full; - private JPanel currentPanel; - private JPanel root; - private int index; - private int tabsBefore; - private int tabsAfter; - private org.eclipse.swt.graphics.Point p; - private static boolean batchMode; - boolean hotkey; - private ImageJContextMenuAction imageContextMenuAction; - - public ImageJContextMenuAction getImageContextMenuAction() { - return imageContextMenuAction; - } - - private static Color primaryColor; - - public static Color getPrimarySWTToAwtColor() { - return primaryColor; - } - - /** Creates a new ImageJ frame that runs as an application. */ - public ImageJ() { - this(null, STANDALONE); - } - - /** - * Creates a new ImageJ frame that runs as an application in the specified mode. - */ - public ImageJ(int mode) { - this(null, mode); - } - - /** Creates a new ImageJ frame that runs as an applet. */ - public ImageJ(java.applet.Applet applet) { - this(applet, STANDALONE); - } - - /** - * If 'applet' is not null, creates a new ImageJ frame that runs as an applet. - * If 'mode' is ImageJ.EMBEDDED and 'applet is null, creates an embedded - * (non-standalone) version of ImageJ. - */ - public ImageJ(java.applet.Applet applet, int mode) { - super("ImageJ"); - if ((mode & DEBUG) != 0) - IJ.setDebugMode(true); - mode = mode & 255; - boolean useExceptionHandler = false; - if (mode == IMAGEJ_APP) { - mode = STANDALONE; - useExceptionHandler = true; - } - if (IJ.debugMode) - IJ.log("ImageJ starting in debug mode: " + mode); - embedded = applet == null && (mode == EMBEDDED || mode == NO_SHOW); - this.applet = applet; - String err1 = Prefs.load(this, applet); - backgroundColor = Util.getSWTBackgroundToAWT(); - setBackground(backgroundColor); - Menus m = new Menus(this, applet); - String err2 = m.addMenuBar(); - m.installPopupMenu(this); - setLayout(new BorderLayout()); - - // Tool bar - toolbar = new Toolbar(); - toolbar.addKeyListener(this); - add("Center", toolbar); - primaryColor = getSystemColour(); - // Status bar - statusBar = new JPanel(); - statusBar.setLayout(new BorderLayout()); - statusBar.setForeground(Color.black); - statusBar.setBackground(getSystemColour());// Changed for Bio7! - statusLine = new JLabel(); - double scale = Prefs.getGuiScale(); - statusLine.setFont(new Font("SansSerif", Font.PLAIN, (int) (13 * scale))); - // Changed for Bio7! - if (Util.isThemeBlack()) { - statusLine.setForeground(Color.white); - } else { - statusLine.setForeground(Color.black); - } - statusLine.setFont(new Font("SansSerif", Font.PLAIN, 13)); - statusLine.addKeyListener(this); - statusLine.addMouseListener(this); - statusBar.add("Center", statusLine); - progressBar = new ProgressBar((int) (ProgressBar.WIDTH * scale), (int) (ProgressBar.HEIGHT * scale)); - progressBar.addKeyListener(this); - progressBar.addMouseListener(this); - statusBar.add("East", progressBar); - add("South", statusBar); - - IJ.init(this, applet); - addKeyListener(this); - addWindowListener(this); - setFocusTraversalKeysEnabled(false); - m.installStartupMacroSet(); // add custom tools - - Point loc = getPreferredLocation(); - Dimension tbSize = toolbar.getPreferredSize(); - setCursor(Cursor.getDefaultCursor()); // work-around for JDK 1.1.8 bug - if (mode != NO_SHOW) { - if (IJ.isWindows()) - try { - setIcon(); - } catch (Exception e) { - } - - setResizable(false); - setAlwaysOnTop(Prefs.alwaysOnTop); - pack(); - /* Changed for Bio7! */ - // setLocation(loc.x, loc.y); - // setVisible(true); - /* - * Dimension size = getSize(); if (size!=null) { if (IJ.debugMode) - * IJ.log("size: "+size); if (IJ.isWindows() && - * (size.height>108||IJ.javaVersion()>=10)) { { // workaround for IJ window - * layout and FileDialog freeze problems with Windows 10 Creators Update - * IJ.wait(10); pack(); if (IJ.debugMode) IJ.log("pack()"); if - * (!Prefs.jFileChooserSettingChanged) Prefs.useJFileChooser = true; } else if - * (IJ.isMacOSX()) { Rectangle maxBounds = GUI.getMaxWindowBounds(this); if - * (loc.x+size.width>maxBounds.x+maxBounds.width) setLocation(loc.x, loc.y); } - */ - } - if (err1 != null) - IJ.error(err1); - if (err2 != null) { - IJ.error(err2); - // IJ.runPlugIn("ij.plugin.ClassChecker", ""); - } - // Changed for Bio7. Adapter not needed anymore! - /* - * if (IJ.isMacintosh() && applet == null) { - * - * try { if (IJ.javaVersion()>8) // newer JREs use different drag-drop, about - * mechanism IJ.runPlugIn("ij.plugin.MacAdapter9", ""); else - * IJ.runPlugIn("ij.plugin.MacAdapter", ""); } catch (Throwable e) { - * - * } - * - * - * - * } - */ - if (applet == null) - IJ.runPlugIn("ij.plugin.DragAndDrop", ""); - if (!getTitle().contains("Fiji") && useExceptionHandler) { - Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler()); - System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName()); - } - String str = m.getMacroCount() == 1 ? " macro" : " macros"; - configureProxy(); - if (applet == null) - loadCursors(); - (new ij.macro.StartupRunner()).run(batchMode); // run RunAtStartup and AutoRun macros - IJ.showStatus(version() + m.getPluginCount() + " commands; " + m.getMacroCount() + str); - imageContextMenuAction = new ImageJContextMenuAction(); - } - - /* Changed for Bio7! */ - public static java.awt.Color getSystemColour() { - Color col = null; - org.eclipse.swt.graphics.Color colswt = CanvasView.getCanvas_view().getParent2().getBackground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - return col; - } - - private void loadCursors() { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - String path = Prefs.getImageJDir() + "images/crosshair-cursor.gif"; - File f = new File(path); - if (!f.exists()) - return; - // Image image = toolkit.getImage(path); - ImageIcon icon = new ImageIcon(path); - Image image = icon.getImage(); - if (image == null) - return; - int width = icon.getIconWidth(); - int height = icon.getIconHeight(); - Point hotSpot = new Point(width / 2, height / 2); - Cursor crosshairCursor = toolkit.createCustomCursor(image, hotSpot, "crosshair-cursor.gif"); - ImageCanvas.setCursor(crosshairCursor, 0); - } - - void configureProxy() { - if (Prefs.useSystemProxies) { - try { - System.setProperty("java.net.useSystemProxies", "true"); - } catch (Exception e) { - } - } else { - String server = Prefs.get("proxy.server", null); - if (server == null || server.equals("")) - return; - int port = (int) Prefs.get("proxy.port", 0); - if (port == 0) - return; - Properties props = System.getProperties(); - props.put("proxySet", "true"); - props.put("http.proxyHost", server); - props.put("http.proxyPort", "" + port); - props.put("https.proxyHost", server); - props.put("https.proxyPort", "" + port); - } - // new ProxySettings().logProperties(); - } - - void setIcon() throws Exception { - URL url = this.getClass().getResource("/microscope.gif"); - if (url == null) - return; - Image img = createImage((ImageProducer) url.getContent()); - if (img != null) - setIconImage(img); - } - - public Point getPreferredLocation() { - - int ijX = Prefs.getInt(IJ_X, -99); - int ijY = Prefs.getInt(IJ_Y, -99); - Rectangle maxBounds = GUI.getMaxWindowBounds(); - // System.out.println("getPreferredLoc1: "+ijX+" "+ijY+" "+maxBounds); - if (ijX >= maxBounds.x && ijY >= maxBounds.y && ijX < (maxBounds.x + maxBounds.width - 75) && ijY < (maxBounds.y + maxBounds.height - 75)) - return new Point(ijX, ijY); - Dimension tbsize = toolbar.getPreferredSize(); - int ijWidth = tbsize.width + 10; - double percent = maxBounds.width > 832 ? 0.8 : 0.9; - ijX = (int) (percent * (maxBounds.width - ijWidth)); - if (ijX < 10) - ijX = 10; - return new Point(ijX, maxBounds.y); - } - - /* Changed for Bio7! */ - void showStatus(final String s) { - statusLine.setText(s); - Display display = Util.getDisplay(); - /* - * MacOSX only seems to work with async method! Also on Windows async works best - * (avoids deadlocks when mouse moved in and out the canvas opening several - * images at once in the background!). - */ - - display.asyncExec(new Runnable() { - - public void run() { - if (CanvasView.getCanvas_view() != null) { - CanvasView.getCanvas_view().setstatusline(s); - } - - /* - * if (customImageJView != null) { customImageJView.setstatusline(s); } - */ - IViewReference[] viewRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences(); - for (int i = 0; i < viewRefs.length; i++) { - String id = viewRefs[i].getId(); - if (id.equals("com.eco.bio7.image.detachedImage")) { - IViewPart view = viewRefs[i].getView(false); - String secId = viewRefs[i].getSecondaryId(); - CustomDetachedImageJView cdview = (CustomDetachedImageJView) view; - /* Get the image from the detached secondary view id (same id)! */ - ImagePlus plu = WindowManager.getImage(Integer.valueOf(secId)); - if (plu != null) { - ImagePlus ip = WindowManager.getImage(Integer.valueOf(secId)); - ImageWindow currentWindow = WindowManager.getCurrentWindow(); - ImageWindow window = ip.getWindow(); - if (currentWindow != null && window != null) { - if (currentWindow.equals(window)) { - cdview.setstatusline(s); - } - } - } - - } - } - - } - }); - - } - - /* - * void showStatus(String s) { statusLine.setText(s); } - */ - - public ProgressBar getProgressBar() { - return progressBar; - } - - public JPanel getStatusBar() { - return statusBar; - } - - public static String getStatusBarText() { - ImageJ ij = IJ.getInstance(); - return ij != null ? ij.statusLine.getText() : ""; - } - - /** Starts executing a menu command in a separate thread. */ - /* Changed for Bio7 to public! */ - public void doCommand(String name) { - new Executer(name, null); - } - - public void runFilterPlugIn(Object theFilter, String cmd, String arg) { - new PlugInFilterRunner(theFilter, cmd, arg); - } - - public Object runUserPlugIn(String commandName, String className, String arg, boolean createNewLoader) { - return IJ.runUserPlugIn(commandName, className, arg, createNewLoader); - } - - /** Return the current list of modifier keys. */ - public static String modifiers(int flags) { // ?? needs to be moved - String s = " [ "; - if (flags == 0) - return ""; - if ((flags & Event.SHIFT_MASK) != 0) - s += "Shift "; - if ((flags & Event.CTRL_MASK) != 0) - s += "Control "; - if ((flags & Event.META_MASK) != 0) - s += "Meta "; - if ((flags & Event.ALT_MASK) != 0) - s += "Alt "; - s += "] "; - return s; - } - - /** Handle menu events. */ - public void actionPerformed(ActionEvent e) { - if ((e.getSource() instanceof MenuItem)) { - MenuItem item = (MenuItem) e.getSource(); - String cmd = e.getActionCommand(); - Frame frame = WindowManager.getFrontWindow(); - if (frame != null && (frame instanceof Fitter)) { - ((Fitter) frame).actionPerformed(e); - return; - } - commandName = cmd; - ImagePlus imp = null; - if (item.getParent() == Menus.getOpenRecentMenu()) { - new RecentOpener(cmd); // open image in separate thread - return; - } else if (item.getParent() == Menus.getPopupMenu()) { - Object parent = Menus.getPopupMenu().getParent(); - if (parent instanceof ImageCanvas) - imp = ((ImageCanvas) parent).getImage(); - } - int flags = e.getModifiers(); - hotkey = false; - actionPerformedTime = System.currentTimeMillis(); - long ellapsedTime = actionPerformedTime - keyPressedTime; - if (cmd != null && (ellapsedTime >= 200L || !cmd.equals(lastKeyCommand))) { - if ((flags & Event.ALT_MASK) != 0) - IJ.setKeyDown(KeyEvent.VK_ALT); - if ((flags & Event.SHIFT_MASK) != 0) - IJ.setKeyDown(KeyEvent.VK_SHIFT); - new Executer(cmd, imp); - } - lastKeyCommand = null; - if (IJ.debugMode) - IJ.log("actionPerformed: time=" + ellapsedTime + ", " + e); - } - } - - /** Handles CheckboxMenuItem state changes. */ - public void itemStateChanged(ItemEvent e) { - MenuItem item = (MenuItem) e.getSource(); - MenuComponent parent = (MenuComponent) item.getParent(); - String cmd = e.getItem().toString(); - if ("Autorun Examples".equals(cmd)) // Examples>Autorun Examples - Prefs.autoRunExamples = e.getStateChange() == 1; - else if ((Menu) parent == Menus.window) - WindowManager.activateWindow(cmd, item); - else - doCommand(cmd); - } - - public void mousePressed(MouseEvent e) { - Undo.reset(); - if (!Prefs.noClickToGC) - System.gc(); - IJ.showStatus(version() + IJ.freeMemory()); - if (IJ.debugMode) - IJ.log("Windows: " + WindowManager.getWindowCount()); - } - - public String getInfo() { - return version() + System.getProperty("os.name") + " " + System.getProperty("os.version") + "; " + IJ.freeMemory(); - } - - private String version() { - return "ImageJ " + VERSION + BUILD + "; " + "Java " + System.getProperty("java.version") + (IJ.is64Bit() ? " [64-bit]; " : " [32-bit]; "); - } - - public void mouseReleased(MouseEvent e) { - } - - public void mouseExited(MouseEvent e) { - } - - public void mouseClicked(MouseEvent e) { - } - - public void mouseEntered(MouseEvent e) { - } - - public void keyPressed(KeyEvent e) { - if (e.isConsumed()) - return; - int keyCode = e.getKeyCode(); - IJ.setKeyDown(keyCode); - hotkey = false; - if (keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_SHIFT) - return; - char keyChar = e.getKeyChar(); - int flags = e.getModifiers(); - if (IJ.debugMode) - IJ.log("keyPressed: code=" + keyCode + " (" + KeyEvent.getKeyText(keyCode) + "), char=\"" + keyChar + "\" (" + (int) keyChar + "), flags=" + KeyEvent.getKeyModifiersText(flags)); - boolean shift = (flags & KeyEvent.SHIFT_MASK) != 0; - boolean control = (flags & KeyEvent.CTRL_MASK) != 0; - boolean alt = (flags & KeyEvent.ALT_MASK) != 0; - boolean meta = (flags & KeyEvent.META_MASK) != 0; - if (keyCode == KeyEvent.VK_H && meta && IJ.isMacOSX()) - return; // Allow macOS to run ImageJ>Hide ImageJ command - String cmd = null; - ImagePlus imp = WindowManager.getCurrentImage(); - boolean isStack = (imp!=null) && (imp.getStackSize()>1); - if (imp != null && !meta && ((keyChar >= 32 && keyChar <= 255) || keyChar == '\b' || keyChar == '\n')) { - Roi roi = imp.getRoi(); - if (roi != null && roi instanceof TextRoi) { - if (imp.getOverlay() != null && (control || alt || meta) && (keyCode == KeyEvent.VK_BACK_SPACE || keyCode == KeyEvent.VK_DELETE)) { - if (deleteOverlayRoi(imp)) - return; - } - if ((flags & KeyEvent.META_MASK) != 0 && IJ.isMacOSX()) - return; - if (alt) { - switch (keyChar) { - case 'u': - case 'm': - keyChar = IJ.micronSymbol; - break; - case 'A': - keyChar = IJ.angstromSymbol; - break; - default: - } - } - ((TextRoi) roi).addChar(keyChar); - return; - } - } - - // Handle one character macro shortcuts - if (!control && !meta) { - Hashtable macroShortcuts = Menus.getMacroShortcuts(); - if (macroShortcuts.size() > 0) { - if (shift) - cmd = (String) macroShortcuts.get(Integer.valueOf(keyCode + 200)); - else - cmd = (String) macroShortcuts.get(Integer.valueOf(keyCode)); - if (cmd != null) { - - commandName = cmd; - MacroInstaller.runMacroShortcut(cmd); - return; - } - } - } - - if (keyCode == KeyEvent.VK_SEPARATOR) - keyCode = KeyEvent.VK_DECIMAL; - boolean functionKey = keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12; - boolean arrowKey = keyCode==37 || keyCode==38 || keyCode==39 || keyCode==40; - if (Interpreter.getInstance()==null) - arrowKey = false; - boolean numPad = keyCode == KeyEvent.VK_DIVIDE || keyCode == KeyEvent.VK_MULTIPLY || keyCode == KeyEvent.VK_DECIMAL || (keyCode >= KeyEvent.VK_NUMPAD0 && keyCode <= KeyEvent.VK_NUMPAD9); - if ((!Prefs.requireControlKey||control||meta||functionKey||numPad||arrowKey) && keyChar!='+') { - Hashtable shortcuts = Menus.getShortcuts(); - if (shift && !functionKey) - cmd = (String) shortcuts.get(Integer.valueOf(keyCode + 200)); - else - cmd = (String) shortcuts.get(Integer.valueOf(keyCode)); - } - - if (cmd == null) { - switch (keyChar) { - case '<': - case ',': - if (isStack) - cmd = "Previous Slice [<]"; - break; - case '>': - case '.': - case ';': - if (isStack) - cmd = "Next Slice [>]"; - break; - case '+': - case '=': - cmd = "In [+]"; - break; - case '-': - cmd = "Out [-]"; - break; - case '/': - cmd = "Reslice [/]..."; - break; - default: - } - } - - if (cmd == null) { - switch (keyCode) { - case KeyEvent.VK_TAB: - WindowManager.putBehind(); - return; - case KeyEvent.VK_BACK_SPACE: - case KeyEvent.VK_DELETE: - if (!(shift || control || alt || meta)) { - if (deleteOverlayRoi(imp)) - return; - if (imp != null && imp.getOverlay() != null && imp == GelAnalyzer.getGelImage()) - return; - cmd = "Clear"; - hotkey = true; - } - break; - // case KeyEvent.VK_BACK_SLASH: - // cmd=IJ.altKeyDown()?"Animation Options...":"Start Animation"; - // break; - case KeyEvent.VK_EQUALS: - cmd = "In [+]"; - break; - case KeyEvent.VK_MINUS: - cmd = "Out [-]"; - break; - case KeyEvent.VK_SLASH: - case 0xbf: - cmd = "Reslice [/]..."; - break; - case KeyEvent.VK_COMMA: - case 0xbc: - if (isStack) - cmd = "Previous Slice [<]"; - break; - case KeyEvent.VK_PERIOD: - case 0xbe: - if (isStack) - cmd = "Next Slice [>]"; - break; - case KeyEvent.VK_LEFT: - case KeyEvent.VK_RIGHT: - case KeyEvent.VK_UP: - case KeyEvent.VK_DOWN: // arrow keys - if (imp == null) - return; - Roi roi = imp.getRoi(); - if (shift && imp == Orthogonal_Views.getImage()) - return; - if (IJ.isMacOSX() && IJ.isJava18()) { - RoiManager rm = RoiManager.getInstance(); - boolean rmActive = rm != null && rm == WindowManager.getActiveWindow(); - if (rmActive && (keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_UP)) - rm.repaint(); - } - boolean stackKey = imp.getStackSize() > 1 && (roi == null || shift); - boolean zoomKey = roi == null || shift || control; - if (stackKey && keyCode == KeyEvent.VK_RIGHT) - cmd = "Next Slice [>]"; - else if (stackKey && keyCode == KeyEvent.VK_LEFT) - cmd = "Previous Slice [<]"; - //else if (zoomKey && keyCode==KeyEvent.VK_DOWN && !ignoreArrowKeys(imp,control) && Toolbar.getToolId() 1 && win != null && win.getClass().getName().startsWith("loci")) - return true; - if (Prefs.requireControlKey && !control) - return true; - return false; - } - - public void keyTyped(KeyEvent e) { - char keyChar = e.getKeyChar(); - int flags = e.getModifiers(); - // if (IJ.debugMode) IJ.log("keyTyped: char=\"" + keyChar + "\" (" + - // (int)keyChar - // + "), flags= "+Integer.toHexString(flags)+ " - // ("+KeyEvent.getKeyModifiersText(flags)+")"); - if (keyChar == '\\' || keyChar == 171 || keyChar == 223) { - if (((flags & Event.ALT_MASK) != 0)) - doCommand("Animation Options..."); - else - doCommand("Start Animation [\\]"); - } - } - - public void keyReleased(KeyEvent e) { - IJ.setKeyUp(e.getKeyCode()); - } - - /** called when escape pressed */ - void abortPluginOrMacro(ImagePlus imp) { - if (imp != null) { - ImageWindow win = imp.getWindow(); - if (win != null) { - win.running = false; - win.running2 = false; - Roi roi = imp.getRoi(); - if (roi != null && roi.getState() != Roi.NORMAL) { - roi.abortModification(imp); - return; - } else { - win.running = false; - win.running2 = false; - } - } - } - Macro.abort(); - Interpreter.abort(); - if (Interpreter.getInstance() != null) - IJ.beep(); - } - - public void windowClosing(WindowEvent e) { - if (Executer.getListenerCount() > 0) - doCommand("Quit"); - else { - quit(); - windowClosed = true; - } - } - - public void windowActivated(WindowEvent e) { - if (IJ.isMacintosh() && !quitting) { - IJ.wait(10); // may be needed for Java 1.4 on OS X - MenuBar mb = Menus.getMenuBar(); - if (mb != null && mb != getMenuBar() && !IJ.isMacro()) { - setMenuBar(mb); - Menus.setMenuBarCount++; - if (IJ.debugMode) - IJ.log("setMenuBar: " + Menus.setMenuBarCount); - } - } - } - - public void windowClosed(WindowEvent e) { - } - - public void windowDeactivated(WindowEvent e) { - } - - public void windowDeiconified(WindowEvent e) { - } - - public void windowIconified(WindowEvent e) { - } - - public void windowOpened(WindowEvent e) { - } - - /** - * Adds the specified class to a Vector to keep it from being garbage collected, - * causing static fields to be reset. - */ - public void register(Class c) { - if (!classes.contains(c)) - classes.addElement(c); - } - - /** Called by ImageJ when the user selects Quit. */ - public void quit() { - quitMacro = IJ.macroRunning(); - Thread thread = new Thread(this, "Quit"); - thread.setPriority(Thread.NORM_PRIORITY); - thread.start(); - IJ.wait(10); - } - - /** Returns true if ImageJ is exiting. */ - public boolean quitting() { - return quitting; - } - - /** - * Returns true if ImageJ is quitting as a result of a run("Quit") macro call. - */ - public boolean quittingViaMacro() { - return quitting && quitMacro; - } - - /** Called once when ImageJ quits. */ - public void savePreferences(Properties prefs) { - Point loc = getLocation(); - prefs.put(IJ_X, Integer.toString(loc.x)); - prefs.put(IJ_Y, Integer.toString(loc.y)); - - } - - public static void main(String args[]) { - boolean noGUI = false; - int mode = IMAGEJ_APP; - arguments = args; - int nArgs = args != null ? args.length : 0; - boolean commandLine = false; - for (int i = 0; i < nArgs; i++) { - String arg = args[i]; - if (arg == null) - continue; - if (arg.startsWith("-batch")) { - noGUI = true; - batchMode = true; - } else if (arg.startsWith("-macro") || arg.endsWith(".ijm") || arg.endsWith(".txt")) - batchMode = true; - else if (arg.startsWith("-debug")) - IJ.setDebugMode(true); - else if (arg.startsWith("-ijpath") && i + 1 < nArgs) { - if (IJ.debugMode) - IJ.log("-ijpath: " + args[i + 1]); - Prefs.setHomeDir(args[i + 1]); - commandLine = true; - args[i + 1] = null; - } else if (arg.startsWith("-port")) { - int delta = (int) Tools.parseDouble(arg.substring(5, arg.length()), 0.0); - commandLine = true; - if (delta == 0) - mode = EMBEDDED; - else if (delta > 0 && DEFAULT_PORT + delta < 65536) - port = DEFAULT_PORT + delta; - } - } - // If existing ImageJ instance, pass arguments to it and quit. - boolean passArgs = (mode == IMAGEJ_APP || mode == STANDALONE) && !noGUI; - if (IJ.isMacOSX() && !commandLine) - passArgs = false; - if (passArgs && isRunning(args)) - return; - ImageJ ij = IJ.getInstance(); - if (!noGUI && (ij == null || (ij != null && !ij.isShowing()))) { - ij = new ImageJ(null, mode); - ij.exitWhenQuitting = true; - } else if (batchMode && noGUI) - Prefs.load(null, null); - int macros = 0; - for (int i = 0; i < nArgs; i++) { - String arg = args[i]; - if (arg == null) - continue; - if (arg.startsWith("-")) { - if ((arg.startsWith("-macro") || arg.startsWith("-batch")) && i + 1 < nArgs) { - String arg2 = i + 2 < nArgs ? args[i + 2] : null; - Prefs.commandLineMacro = true; - if (noGUI && args[i + 1].endsWith(".js")) - Interpreter.batchMode = true; - IJ.runMacroFile(args[i + 1], arg2); - break; - } else if (arg.startsWith("-eval") && i + 1 < nArgs) { - String rtn = IJ.runMacro(args[i + 1]); - if (rtn != null) - System.out.print(rtn); - args[i + 1] = null; - } else if (arg.startsWith("-run") && i + 1 < nArgs) { - IJ.run(args[i + 1]); - args[i + 1] = null; - } - } else if (macros == 0 && (arg.endsWith(".ijm") || arg.endsWith(".txt"))) { - IJ.runMacroFile(arg); - macros++; - } else if (arg.length() > 0 && arg.indexOf("ij.ImageJ") == -1) { - File file = new File(arg); - IJ.open(file.getAbsolutePath()); - } - } - if (IJ.debugMode && IJ.getInstance() == null && !GraphicsEnvironment.isHeadless()) - new JavaProperties().run(""); - if (noGUI) - System.exit(0); - } - - // Is there another instance of ImageJ? If so, send it the arguments and - // quit. - static boolean isRunning(String args[]) { - return OtherInstance.sendArguments(args); - } - - /** - * Returns the port that ImageJ checks on startup to see if another instance is - * running. - * - * @see ij.OtherInstance - */ - public static int getPort() { - return port; - } - - /** Returns the command line arguments passed to ImageJ. */ - public static String[] getArgs() { - return arguments; - } - - /** - * ImageJ calls System.exit() when qutting when 'exitWhenQuitting' is true. - */ - public void exitWhenQuitting(boolean ewq) { - exitWhenQuitting = ewq; - } - - /** Quit using a separate thread, hopefully avoiding thread deadlocks. */ - public void run() { - quitting = true; - boolean changes = false; - int[] wList = WindowManager.getIDList(); - if (wList != null) { - for (int i = 0; i < wList.length; i++) { - ImagePlus imp = WindowManager.getImage(wList[i]); - if (imp != null && imp.changes == true) { - changes = true; - break; - } - } - } - Frame[] frames = WindowManager.getNonImageWindows(); - if (frames != null) { - for (int i = 0; i < frames.length; i++) { - if (frames[i] != null && (frames[i] instanceof Editor)) { - if (((Editor) frames[i]).fileChanged()) { - changes = true; - break; - } - } - } - } - if (windowClosed && !changes && Menus.window.getItemCount() > Menus.WINDOW_MENU_ITEMS && !(IJ.macroRunning() && WindowManager.getImageCount() == 0)) { - GenericDialog gd = new GenericDialog("ImageJ", this); - gd.addMessage("Are you sure you want to quit ImageJ?"); - gd.showDialog(); - quitting = !gd.wasCanceled(); - windowClosed = false; - } - if (!quitting) - return; - if (!WindowManager.closeAllWindows()) { - quitting = false; - return; - } - if (applet == null) { - saveWindowLocations(); - Prefs.set(ImageWindow.LOC_KEY, null); // don't save image window location - Prefs.savePreferences(); - } - IJ.cleanup(); - dispose(); - if (exitWhenQuitting) - System.exit(0); - } - - void saveWindowLocations() { - Window win = WindowManager.getWindow("B&C"); - if (win != null) - Prefs.saveLocation(ContrastAdjuster.LOC_KEY, win.getLocation()); - win = WindowManager.getWindow("Threshold"); - if (win != null) - Prefs.saveLocation(ThresholdAdjuster.LOC_KEY, win.getLocation()); - win = WindowManager.getWindow("Results"); - if (win != null) { - Prefs.saveLocation(TextWindow.LOC_KEY, win.getLocation()); - Dimension d = win.getSize(); - Prefs.set(TextWindow.WIDTH_KEY, d.width); - Prefs.set(TextWindow.HEIGHT_KEY, d.height); - } - win = WindowManager.getWindow("Log"); - if (win != null) { - Prefs.saveLocation(TextWindow.LOG_LOC_KEY, win.getLocation()); - Dimension d = win.getSize(); - Prefs.set(TextWindow.LOG_WIDTH_KEY, d.width); - Prefs.set(TextWindow.LOG_HEIGHT_KEY, d.height); - } - win = WindowManager.getWindow("ROI Manager"); - if (win != null) - Prefs.saveLocation(RoiManager.LOC_KEY, win.getLocation()); - } - - /* - * Changed for Bio7! Overrides the default Frame settings since Bio7 Gui uses - * swt for the primary frame! - */ - public Point getLocationOnScreen() { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - - public void run() { - p = CanvasView.getCanvas_view().tabFolder.getShell().getLocation(); - } - }); - - return new Point(p.x, p.y); - } - - public static String getCommandName() { - return commandName != null ? commandName : "null"; - } - - public static void setCommandName(String name) { - commandName = name; - } - - public void resize() { - double scale = Prefs.getGuiScale(); - toolbar.init(); - statusLine.setFont(new Font("SansSerif", Font.PLAIN, (int) (13 * scale))); - progressBar.init((int) (ProgressBar.WIDTH * scale), (int) (ProgressBar.HEIGHT * scale)); - pack(); - } - - /** Handles exceptions on the EDT. */ - public static class ExceptionHandler implements Thread.UncaughtExceptionHandler { - - // for EDT exceptions - public void handle(Throwable thrown) { - handleException(Thread.currentThread().getName(), thrown); - } - - // for other uncaught exceptions - public void uncaughtException(Thread thread, Throwable thrown) { - handleException(thread.getName(), thrown); - } - - protected void handleException(String tname, Throwable e) { - if (Macro.MACRO_CANCELED.equals(e.getMessage())) - return; - CharArrayWriter caw = new CharArrayWriter(); - PrintWriter pw = new PrintWriter(caw); - e.printStackTrace(pw); - String s = caw.toString(); - if (s != null && s.contains("ij.")) { - if (IJ.getInstance() != null) - s = IJ.getInstance().getInfo() + "\n" + s; - IJ.log(s); - } - } - - } // inner class ExceptionHandler - -} diff --git a/com.eco.bio7.image/src/ij/ImageJApplet.java b/com.eco.bio7.image/src/ij/ImageJApplet.java deleted file mode 100644 index db5cb6e4f..000000000 --- a/com.eco.bio7.image/src/ij/ImageJApplet.java +++ /dev/null @@ -1,44 +0,0 @@ -package ij; -import java.applet.Applet; - -/** - Runs ImageJ as an applet and optionally opens up to - nine images using URLs passed as a parameters. - - Here is an example applet tag that launches ImageJ as an applet - and passes it the URLs of two images: - - <applet archive="../ij.jar" code="ij.ImageJApplet.class" width=0 height=0> - <param name=url1 value="http://imagej.nih.gov/ij/images/FluorescentCells.jpg"> - <param name=url2 value="http://imagej.nih.gov/ij/images/blobs.gif"> - </applet> - - To use plugins, add them to ij.jar and add entries to IJ_Props.txt file (in ij.jar) that will - create commands for them in the Plugins menu, or a submenu. There are examples - of such entries in IJ.Props.txt, in the "Plugins installed in the Plugins menu" section. - - Macros contained in a file named "StartupMacros.txt", in the same directory as the HTML file - containing the applet tag, will be installed on startup. -*/ -public class ImageJApplet extends Applet { - - /** Starts ImageJ if it's not already running. */ - public void init() { - ImageJ ij = IJ.getInstance(); - if (ij==null || (ij!=null && !ij.isShowing())) - new ImageJ(this); - for (int i=1; i<=9; i++) { - String url = getParameter("url"+i); - if (url==null) break; - ImagePlus imp = new ImagePlus(url); - if (imp!=null) imp.show(); - } - } - - public void destroy() { - ImageJ ij = IJ.getInstance(); - if (ij!=null) ij.quit(); - } - -} - diff --git a/com.eco.bio7.image/src/ij/ImageListener.java b/com.eco.bio7.image/src/ij/ImageListener.java deleted file mode 100644 index ae8faacd6..000000000 --- a/com.eco.bio7.image/src/ij/ImageListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package ij; - - /** Plugins that implement this interface are notified when - an image is opened, closed or updated. The - Plugins/Utilities/Monitor Events command uses this interface. - */ - public interface ImageListener { - - public void imageOpened(ImagePlus imp); - - public void imageClosed(ImagePlus imp); - - public void imageUpdated(ImagePlus imp); - - //default void imageSaved(ImagePlus imp) { } - -} diff --git a/com.eco.bio7.image/src/ij/ImageListenerAdapter.java b/com.eco.bio7.image/src/ij/ImageListenerAdapter.java deleted file mode 100644 index 231b2ed51..000000000 --- a/com.eco.bio7.image/src/ij/ImageListenerAdapter.java +++ /dev/null @@ -1,34 +0,0 @@ -package ij; - -/** -* An Adapter class for the ImageListener interface. Note ImageListenerAdapter -* supports notification when an ImagePlus gets saved. -* -* With this adapter you need only override the methods that you require -* notification for. -* -* TODO When ImageJ has a minimum support of Java8 consider updating -* ImageListener to provide default methods for all these callbacks as this will -* allow ImageListener interface to be used as mix-in class whereas Java single -* inheritance precludes that for this ImageListenerAdapter class. -* -* @author Michael Ellis -*/ -public class ImageListenerAdapter implements ImageListener { - - @Override - public void imageOpened(ImagePlus imp) { - } - - @Override - public void imageClosed(ImagePlus imp) { - } - - @Override - public void imageUpdated(ImagePlus imp) { - } - - public void imageSaved(ImagePlus imp) { - } - -} diff --git a/com.eco.bio7.image/src/ij/ImagePlus.java b/com.eco.bio7.image/src/ij/ImagePlus.java deleted file mode 100644 index caa63874b..000000000 --- a/com.eco.bio7.image/src/ij/ImagePlus.java +++ /dev/null @@ -1,3547 +0,0 @@ -package ij; -import java.awt.*; -import java.awt.image.*; -import java.net.URL; -import java.util.*; -import ij.process.*; -import ij.io.*; -import ij.gui.*; - -import ij.measure.*; -import ij.plugin.filter.Analyzer; -import ij.util.*; -import ij.macro.Interpreter; -import ij.plugin.*; -import ij.plugin.frame.*; - - -/** -An ImagePlus contain an ImageProcessor (2D image) or an ImageStack (3D, 4D or 5D image). -It also includes metadata (spatial calibration and possibly the directory/file where -it was read from). The ImageProcessor contains the pixel data (8-bit, 16-bit, float or RGB) -of the 2D image and some basic methods to manipulate it. An ImageStack is essentually -a list ImageProcessors of same type and size. -@see ij.process.ImageProcessor -@see ij.ImageStack -@see ij.gui.ImageWindow -@see ij.gui.ImageCanvas -*/ - -public class ImagePlus implements ImageObserver, Measurements, Cloneable { - - /** 8-bit grayscale (unsigned)*/ - public static final int GRAY8 = 0; - - /** 16-bit grayscale (unsigned) */ - public static final int GRAY16 = 1; - - /** 32-bit floating-point grayscale */ - public static final int GRAY32 = 2; - - /** 8-bit indexed color */ - public static final int COLOR_256 = 3; - - /** 32-bit RGB color */ - public static final int COLOR_RGB = 4; - - /** Title of image used by Flatten command */ - public static final String flattenTitle = "flatten~canvas"; - - /** True if any changes have been made to this image. */ - public boolean changes; - - protected Image img; - protected ImageProcessor ip; - protected ImageWindow win; - protected Roi roi; - protected int currentSlice; // current stack index (one-based) - protected static final int OPENED=0, CLOSED=1, UPDATED=2, SAVED=3; - protected boolean compositeImage; - protected int width; - protected int height; - protected boolean locked; - private int lockedCount; - private Thread lockingThread; - protected int nChannels = 1; - protected int nSlices = 1; - protected int nFrames = 1; - protected boolean dimensionsSet; - - private ImageJ ij = IJ.getInstance(); - private String title; - private String url; - private FileInfo fileInfo; - private int imageType = GRAY8; - private boolean typeSet; - private ImageStack stack; - private static int currentID = -1; - private int ID; - private static Component comp; - private boolean imageLoaded; - private int imageUpdateY, imageUpdateW; - private Properties properties; - private long startTime; - private Calibration calibration; - private static Calibration globalCalibration; - private boolean activated; - private boolean ignoreFlush; - private boolean errorLoadingImage; - private static ImagePlus clipboard; - private static Vector listeners = new Vector(); - private boolean openAsHyperStack; - private int[] position = {1,1,1}; - private boolean noUpdateMode; - private ImageCanvas flatteningCanvas; - private Overlay overlay; - private boolean compositeChanges; - private boolean hideOverlay; - private static int default16bitDisplayRange; - private boolean antialiasRendering = true; - private boolean ignoreGlobalCalibration; - private boolean oneSliceStack; - public boolean setIJMenuBar = Prefs.setIJMenuBar; - private Plot plot; - private Properties imageProperties; - private Color borderColor; - private boolean temporary; - private double defaultMin, defaultMax; - - - /** Constructs an uninitialized ImagePlus. */ - public ImagePlus() { - title = (this instanceof CompositeImage)?"composite":"null"; - setID(); - } - - /** Constructs an ImagePlus from an Image or BufferedImage. The first - argument will be used as the title of the window that displays the image. - Throws an IllegalStateException if an error occurs while loading the image. */ - public ImagePlus(String title, Image image) { - this.title = title; - if (image!=null) - setImage(image); - setID(); - } - - /** Constructs an ImagePlus from an ImageProcessor. */ - public ImagePlus(String title, ImageProcessor ip) { - setProcessor(title, ip); - setID(); - } - - /** Constructs an ImagePlus from a TIFF, BMP, DICOM, FITS, - PGM, GIF or JPRG specified by a path or from a TIFF, DICOM, - GIF or JPEG specified by a URL. */ - public ImagePlus(String pathOrURL) { - Opener opener = new Opener(); - ImagePlus imp = null; - boolean isURL = pathOrURL.indexOf("://")>0; - if (isURL) - imp = opener.openURL(pathOrURL); - else - imp = opener.openImage(pathOrURL); - if (imp!=null) { - if (imp.getStackSize()>1) - setStack(imp.getTitle(), imp.getStack()); - else - setProcessor(imp.getTitle(), imp.getProcessor()); - setCalibration(imp.getCalibration()); - properties = imp.getProperties(); - setFileInfo(imp.getOriginalFileInfo()); - setDimensions(imp.getNChannels(), imp.getNSlices(), imp.getNFrames()); - setOverlay(imp.getOverlay()); - setRoi(imp.getRoi()); - if (isURL) - this.url = pathOrURL; - setID(); - } - } - - /** Constructs an ImagePlus from a stack. */ - public ImagePlus(String title, ImageStack stack) { - setStack(title, stack); - setID(); - } - - private void setID() { - ID = --currentID; - } - - public void setTemporary() { - if (!temporary) { - temporary = true; - currentID++; - ID = -Integer.MAX_VALUE; - } - } - - /** Locks the image so other threads can test to see if it is in use. - * One thread can lock an image multiple times, then it has to unlock - * it as many times until it is unlocked. This allows nested locking - * within a thread. - * Returns true if the image was successfully locked. - * Beeps, displays a message in the status bar, and returns - * false if the image is already locked by another thread. - */ - public synchronized boolean lock() { - return lock(true); - } - - /** Similar to lock, but doesn't beep and display an error - * message if the attempt to lock the image fails. - */ - public synchronized boolean lockSilently() { - return lock(false); - } - - private synchronized boolean lock(boolean loud) { - if (locked) { - if (Thread.currentThread()==lockingThread) { - lockedCount++; //allow locking multiple times by the same thread - return true; - } else { - if (loud) { - IJ.beep(); - IJ.showStatus("\"" + title + "\" is locked"); - if (IJ.debugMode) IJ.log(title + " is locked by " + lockingThread + "; refused locking by " + Thread.currentThread().getName()); - if (IJ.macroRunning()) - IJ.wait(500); - } - return false; - } - } else { - locked = true; //we could use 'lockedCount instead, but subclasses might use - lockedCount = 1; - lockingThread = Thread.currentThread(); - if (win instanceof StackWindow) - ((StackWindow)win).setSlidersEnabled(false); - if (IJ.debugMode) IJ.log(title + ": locked" + (loud ? "" : "silently") + " by " + Thread.currentThread().getName()); - return true; - } - } - - /** Unlocks the image. - * In case the image had been locked several times by the current thread, - * it gets unlocked only after as many unlock operations as there were - * previous lock operations. - */ - public synchronized void unlock() { - if (Thread.currentThread()==lockingThread && lockedCount>1) - lockedCount--; - else { - locked = false; - lockedCount = 0; - lockingThread = null; - if (win instanceof StackWindow) - ((StackWindow)win).setSlidersEnabled(true); - if (IJ.debugMode) IJ.log(title + ": unlocked"); - } - } - - /** Returns 'true' if the image is locked. */ - public boolean isLocked() { - return locked; - } - - /** Returns 'true' if the image was locked on another thread. */ - public boolean isLockedByAnotherThread() { - return locked && Thread.currentThread()!=lockingThread; - } - - private void waitForImage(Image image) { - if (comp==null) { - comp = IJ.getInstance(); - if (comp==null) - comp = new Canvas(); - } - imageLoaded = false; - if (!comp.prepareImage(image, this)) { - double progress; - waitStart = System.currentTimeMillis(); - while (!imageLoaded && !errorLoadingImage) { - IJ.wait(30); - if (imageUpdateW>1) { - progress = (double)imageUpdateY/imageUpdateW; - if (!(progress<1.0)) { - progress = 1.0 - (progress-1.0); - if (progress<0.0) progress = 0.9; - } - showProgress(progress); - } - } - showProgress(1.0); - } - } - - long waitStart; - private void showProgress(double percent) { - if ((System.currentTimeMillis()-waitStart)>500L) - IJ.showProgress(percent); - } - - /** Draws the image. If there is an ROI, its - outline is also displayed. Does nothing if there - is no window associated with this image (i.e. show() - has not been called).*/ - public void draw() { - if (win!=null) - win.getCanvas().repaint(); - } - - /** Draws image and roi outline using a clip rect. */ - public void draw(int x, int y, int width, int height){ - if (win!=null) { - ImageCanvas ic = win.getCanvas(); - double mag = ic.getMagnification(); - x = ic.screenX(x); - y = ic.screenY(y); - width = (int)(width*mag); - height = (int)(height*mag); - ic.repaint(x, y, width, height); - if (listeners.size()>0 && roi!=null && roi.getPasteMode()!=Roi.NOT_PASTING) - notifyListeners(UPDATED); - } - } - - /** Updates this image from the pixel data in its - associated ImageProcessor, then displays it. Does - nothing if there is no window associated with - this image (i.e. show() has not been called).*/ - public synchronized void updateAndDraw() { - if (win==null) { - img = null; - return; - } - if (stack!=null && !stack.isVirtual() && currentSlice>=1 && currentSlice<=stack.size()) { - if (stack.size()>1 && win!=null && !(win instanceof StackWindow)) { - setStack(stack); //adds scroll bar if stack size has changed to >1 - return; - } - Object pixels = stack.getPixels(currentSlice); - if (ip!=null && pixels!=null && pixels!=ip.getPixels()) { // was stack updated? - try { - ip.setPixels(pixels); - ip.setSnapshotPixels(null); - } catch(Exception e) {} - } - } - if (win!=null) { - win.getCanvas().setImageUpdated(); - if (listeners.size()>0) notifyListeners(UPDATED); - } - draw(); - } - - /** Use to update the image when the underlying virtual stack changes. */ - public void updateVirtualSlice() { - ImageStack vstack = getStack(); - if (vstack.isVirtual()) { - double min=getDisplayRangeMin(), max=getDisplayRangeMax(); - setProcessor(vstack.getProcessor(getCurrentSlice())); - setDisplayRange(min,max); - } else - throw new IllegalArgumentException("Virtual stack required"); - } - - /** Sets the display mode of composite color images, where 'mode' - should be IJ.COMPOSITE, IJ.COLOR or IJ.GRAYSCALE. */ - public void setDisplayMode(int mode) { - if (this instanceof CompositeImage) { - ((CompositeImage)this).setMode(mode); - updateAndDraw(); - } - } - - /** Returns the display mode (IJ.COMPOSITE, IJ.COLOR - or IJ.GRAYSCALE) if this is a composite color - image, or 0 if it not. */ - public int getDisplayMode() { - if (this instanceof CompositeImage) - return ((CompositeImage)this).getMode(); - else - return 0; - } - - /** Controls which channels in a composite color image are displayed, - where 'channels' is a list of ones and zeros that specify the channels to - display. For example, "101" causes channels 1 and 3 to be displayed. */ - public void setActiveChannels(String channels) { - if (!(this instanceof CompositeImage)) - return; - boolean[] active = ((CompositeImage)this).getActiveChannels(); - for (int i=0; ii && channels.charAt(i)=='1') - b = true; - active[i] = b; - } - updateAndDraw(); - Channels.updateChannels(); - } - - /** Updates this image from the pixel data in its - associated ImageProcessor, then displays it. - The CompositeImage class overrides this method - to only update the current channel. */ - public void updateChannelAndDraw() { - updateAndDraw(); - } - - /** Returns a reference to the current ImageProcessor. The - CompositeImage class overrides this method to return - the processor associated with the current channel. */ - public ImageProcessor getChannelProcessor() { - return getProcessor(); - } - - /** Returns an array containing the lookup tables used by this image, - * one per channel, or an empty array if this is an RGB image. - * @see #getNChannels - * @see #isComposite - * @see #getCompositeMode - * - * Javascript example: - * - * luts = imp.getLuts(); - * for (i=0; i - * IJ.log((i+1)+“: “+luts[i].min+”-”+luts[i].max); - * - */ - public LUT[] getLuts() { - ImageProcessor ip2 = getProcessor(); - if (ip2==null) - return new LUT[0]; - LUT lut = ip2.getLut(); - if (lut==null) - return new LUT[0]; - LUT[] luts = new LUT[1]; - luts[0] = lut; - return luts; - } - - /** Calls draw to draw the image and also repaints the - image window to force the information displayed above - the image (dimension, type, size) to be updated. */ - public void repaintWindow() { - if (win!=null) { - draw(); - win.repaint(); - } - } - - /** Calls updateAndDraw to update from the pixel data - and draw the image, and also repaints the image - window to force the information displayed above - the image (dimension, type, size) to be updated. */ - public void updateAndRepaintWindow() { - if (win!=null) { - updateAndDraw(); - win.repaint(); - } - } - - /** ImageCanvas.paint() calls this method when the - * ImageProcessor has generated a new image. - */ - public void updateImage() { - if (win==null) { - img = null; - return; - } - if (ip!=null) - img = ip.createImage(); - } - - /** Closes the window, if any, that is displaying this image. */ - public void hide() { - if (win==null) { - img = null; - Interpreter.removeBatchModeImage(this); - return; - } - boolean unlocked = lockSilently(); - Overlay overlay2 = getOverlay(); - changes = false; - win.close(); - win = null; - setOverlay(overlay2); - if (unlocked) unlock(); - } - - /** Closes this image and sets the ImageProcessor to null. To avoid the - "Save changes?" dialog, first set the public 'changes' variable to false. */ - public void close() { - ImageWindow win = getWindow(); - if (win!=null) - win.close(); - else { - if (WindowManager.getCurrentImage()==this) - WindowManager.setTempCurrentImage(null); - deleteRoi(); //save any ROI so it can be restored later - Interpreter.removeBatchModeImage(this); - } - } - - /** Opens a window to display this image and clears the status bar. */ - public void show() { - show(""); - } - - /** Opens a window to display this image and displays - 'statusMessage' in the status bar. */ - public void show(String statusMessage) { - if (isVisible() || temporary) - return; - win = null; - if ((IJ.isMacro() && ij==null) || Interpreter.isBatchMode()) { - if (isComposite()) ((CompositeImage)this).reset(); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp!=null) imp.saveRoi(); - WindowManager.setTempCurrentImage(this); - Interpreter.addBatchModeImage(this); - return; - } - if (Prefs.useInvertingLut && getBitDepth()==8 && ip!=null && !ip.isInvertedLut()&& !ip.isColorLut()) - invertLookupTable(); - img = getImage(); - if ((img!=null) && (width>=0) && (height>=0)) { - activated = false; - int stackSize = getStackSize(); - if (stackSize>1) - win = new StackWindow(this); // displays the window and (if macro) waits for window to be activated - else if (getProperty(Plot.PROPERTY_KEY) != null) - win = new PlotWindow(this, (Plot)(getProperty(Plot.PROPERTY_KEY))); - else - win = new ImageWindow(this); - if (roi!=null) roi.setImage(this); - if (overlay!=null && getCanvas()!=null) - getCanvas().setOverlay(overlay); - IJ.showStatus(statusMessage); - if (IJ.isMacro() && stackSize==1) // for non-stacks, wait for window to be activated - waitTillActivated(); - if (imageType==GRAY16 && default16bitDisplayRange!=0) { - resetDisplayRange(); - updateAndDraw(); - } - if (stackSize>1) { - int c = getChannel(); - int z = getSlice(); - int t = getFrame(); - if (c>1 || z>1 || t>1) - setPosition(c, z, t); - } - if (setIJMenuBar) - IJ.wait(25); - notifyListeners(OPENED); - } - } - - void invertLookupTable() { - int nImages = getStackSize(); - ip.invertLut(); - if (nImages==1) - ip.invert(); - else { - ImageStack stack2 = getStack(); - for (int i=1; i<=nImages; i++) - stack2.getProcessor(i).invert(); - stack2.setColorModel(ip.getColorModel()); - } - } - - /** Waits until the image window becomes activated. This is necessary in - * macros or other programs if an ImagePlus is shown on the screen, - * because displaying the window is asynchronous (happens later) - * and will make the image the active one. Without waiting, in the - * meanwhile another window could be already the active one and would - * become deactivated. - * If the ImagePlus may have been displayed previously, first call - * setDeactivated(). - * ImagePlus.show() and new StackWindow(ImagePlus) - * call this method if IJ.isMacro() is true, i.e., when running a macro or - * executing an IJ.run(...) call. - */ - public void waitTillActivated() { - if (win == null) return; - if (EventQueue.isDispatchThread()) { //'activated' is set in the EventQueue, we can't wait for it in the EventQueue - WindowManager.setTempCurrentImage(this); - return; - } - long start = System.currentTimeMillis(); - while (!activated) { - IJ.wait(5); - if (ij != null && ij.quitting()) return; - if ((System.currentTimeMillis()-start)>2000) { - WindowManager.setTempCurrentImage(this); - break; // 2 second timeout - } - } - } - - /** Called by ImageWindow.windowActivated(); to end waiting in waitTillActivated. */ - public void setActivated() { - activated = true; - if (borderColor!=null && win!=null) - win.setBackground(borderColor); - } - - /** Called by new StackWindow(ImagePlus) - * before showing the StackWindow, to prepare for - * waitTillActivated(). - */ - public void setDeactivated() { - activated = false; - } - - /** Returns this image as a AWT image. */ - public Image getImage() { - if (img==null && ip!=null) - img = ip.createImage(); - return img; - } - - /** Returns a copy of this image as an 8-bit or RGB BufferedImage. - * @see ij.process.ShortProcessor#get16BitBufferedImage - */ - public BufferedImage getBufferedImage() { - if (isComposite()) - return (new ColorProcessor(getImage())).getBufferedImage(); - else - return ip.getBufferedImage(); - } - - /** Returns this image's unique numeric ID. */ - public int getID() { - return ID; - } - - /** Replaces the image, if any, with the one specified. - * Throws an IllegalStateException if an error occurs - * while loading the image. - */ - public void setImage(Image image) { - if (image instanceof BufferedImage) { - BufferedImage bi = (BufferedImage)image; - int nBands = bi.getSampleModel().getNumBands(); - int type = bi.getType(); - boolean rgb = type==BufferedImage.TYPE_3BYTE_BGR||type==BufferedImage.TYPE_INT_RGB - ||type==BufferedImage.TYPE_4BYTE_ABGR||type==BufferedImage.TYPE_BYTE_INDEXED - ||type==BufferedImage.TYPE_INT_ARGB||type==BufferedImage.TYPE_INT_BGR; - int dataType = bi.getSampleModel().getDataType(); - if (IJ.debugMode) IJ.log("setImage: type="+type+", bands="+nBands+", rgb="+rgb+", datatype="+dataType); - if (nBands>1 && !rgb) { - ImageStack biStack = new ImageStack(bi.getWidth(), bi.getHeight()); - for (int b=0; b0?GRAY8:COLOR_RGB; - if (image!=null && type==COLOR_RGB) - ip = new ColorProcessor(image); - if (ip==null && image!=null) - ip = new ByteProcessor(image); - setType(type); - this.img = ip.createImage(); - if (win!=null) { - if (dimensionsChanged) - win = new ImageWindow(this); - else - repaintWindow(); - } - } - - /** - * Extract pixels as an ImageProcessor from a single band of a BufferedImage. - * @param img - * @param band - * @return - */ - public static ImageProcessor convertToImageProcessor(BufferedImage img, int band) { - int w = img.getWidth(); - int h = img.getHeight(); - int dataType = img.getSampleModel().getDataType(); - // Read data as float (no matter what it is - it's the most accuracy ImageJ can provide) - FloatProcessor fp = new FloatProcessor(w, h); - float[] pixels = (float[])fp.getPixels(); - img.getRaster().getSamples(0, 0, w, h, band, pixels); - // Convert to 8 or 16-bit, if appropriate - if (dataType == DataBuffer.TYPE_BYTE) { - ByteProcessor bp = new ByteProcessor(w, h); - bp.setPixels(0, fp); - return bp; - } else if (dataType == DataBuffer.TYPE_USHORT) { - ShortProcessor sp = new ShortProcessor(w, h); - sp.setPixels(0, fp); - return sp; - } else - return fp; - } - - /** Replaces this image with the specified ImagePlus. May - not work as expected if 'imp' is a CompositeImage - and this image is not. */ - public void setImage(ImagePlus imp) { - Properties newProperties = imp.getProperties(); - if (newProperties!=null) - newProperties = (Properties)(newProperties.clone()); - if (imp.getWindow()!=null) - imp = imp.duplicate(); - ImageStack stack2 = imp.getStack(); - if (imp.isHyperStack()) - setOpenAsHyperStack(true); - LUT[] luts = null; - if (imp.isComposite() && (this instanceof CompositeImage)) { - if (((CompositeImage)imp).getMode()!=((CompositeImage)this).getMode()) - ((CompositeImage)this).setMode(((CompositeImage)imp).getMode()); - luts = ((CompositeImage)imp).getLuts(); - } - LUT lut = !imp.isComposite()?imp.getProcessor().getLut():null; - setStack(stack2, imp.getNChannels(), imp.getNSlices(), imp.getNFrames()); - compositeImage = imp.isComposite(); - if (luts!=null) { - ((CompositeImage)this).setLuts(luts); - ((CompositeImage)this).setMode(((CompositeImage)imp).getMode()); - updateAndRepaintWindow(); - } else if (lut!=null) { - getProcessor().setLut(lut); - updateAndRepaintWindow(); - } - setTitle(imp.getTitle()); - setCalibration(imp.getCalibration()); - setOverlay(imp.getOverlay()); - properties = newProperties; - if (getProperty(Plot.PROPERTY_KEY)!=null && win instanceof PlotWindow) { - Plot plot = (Plot)(getProperty(Plot.PROPERTY_KEY)); - ((PlotWindow)win).setPlot(plot); - plot.setImagePlus(this); - } - setFileInfo(imp.getOriginalFileInfo()); - setProperty ("Info", imp.getProperty ("Info")); - setProperties(imp.getPropertiesAsArray()); - } - - /** Replaces the ImageProcessor with the one specified and updates the - display. With stacks, the ImageProcessor must be the same type as the - other images in the stack and it must be the same width and height. */ - public void setProcessor(ImageProcessor ip) { - setProcessor(null, ip); - } - - /** Replaces the ImageProcessor with the one specified and updates the display. With - stacks, the ImageProcessor must be the same type as other images in the stack and - it must be the same width and height. Set 'title' to null to leave the title unchanged. */ - public void setProcessor(String title, ImageProcessor ip) { - if (ip==null || ip.getPixels()==null) - throw new IllegalArgumentException("ip null or ip.getPixels() null"); - if (getStackSize()>1) { - if (ip.getWidth()!=width || ip.getHeight()!=height) - throw new IllegalArgumentException("Wrong dimensions for this stack"); - int ipBitDepth = ip.getBitDepth(); - int stackBitDepth = stack!=null?stack.getBitDepth():0; - if (ipBitDepth>0 && stackBitDepth>0 && ipBitDepth!=stackBitDepth) { - String info = " \nsize="+getStackSize()+", ipBitDepth="+ipBitDepth+", stackBitDepth="+stackBitDepth; - throw new IllegalArgumentException("Wrong type for this stack"+info); - } - } else { - setStackNull(); - setCurrentSlice(1); - } - setProcessor2(title, ip, null); - } - - void setProcessor2(String title, ImageProcessor ip, ImageStack newStack) { - if (title!=null) setTitle(title); - if (ip==null) - return; - this.ip = ip; - if (this.ip!=null && getWindow()!=null) - notifyListeners(UPDATED); - if (ij!=null) - ip.setProgressBar(ij.getProgressBar()); - int stackSize = 1; - boolean dimensionsChanged = width>0 && height>0 && (width!=ip.getWidth() || height!=ip.getHeight()); - if (stack!=null) { - stackSize = stack.size(); - if (currentSlice>stackSize) - setCurrentSlice(stackSize); - if (currentSlice>=1 && currentSlice<=stackSize && !dimensionsChanged) - stack.setPixels(ip.getPixels(),currentSlice); - } - img = null; - if (dimensionsChanged) roi = null; - int type; - if (ip instanceof ByteProcessor) - type = GRAY8; - else if (ip instanceof ColorProcessor) - type = COLOR_RGB; - else if (ip instanceof ShortProcessor) - type = GRAY16; - else - type = GRAY32; - if (width==0) - imageType = type; - else - setType(type); - width = ip.getWidth(); - height = ip.getHeight(); - if (win!=null) { - if (dimensionsChanged && stackSize==1) - win.updateImage(this); - else if (newStack==null) - repaintWindow(); - draw(); - } - } - - /** Replaces the image with the specified stack and updates the display. */ - public void setStack(ImageStack stack) { - setStack(null, stack); - } - - /** Replaces the image with the specified stack and updates - the display. Set 'title' to null to leave the title unchanged. */ - public void setStack(String title, ImageStack newStack) { - int bitDepth1 = getBitDepth(); - int previousStackSize = getStackSize(); - int newStackSize = newStack.getSize(); - if (newStackSize==0) - throw new IllegalArgumentException("Stack is empty"); - if (!newStack.isVirtual()) { - Object[] arrays = newStack.getImageArray(); - if (arrays==null || (arrays.length>0&&arrays[0]==null)) - throw new IllegalArgumentException("Stack pixel array null"); - } - boolean sliderChange = false; - if (win!=null && (win instanceof StackWindow)) { - int nScrollbars = ((StackWindow)win).getNScrollbars(); - if (nScrollbars>0 && newStackSize==1) - sliderChange = true; - else if (nScrollbars==0 && newStackSize>1) - sliderChange = true; - } - if (currentSlice<1) setCurrentSlice(1); - boolean resetCurrentSlice = currentSlice>newStackSize; - if (resetCurrentSlice) setCurrentSlice(newStackSize); - ImageProcessor newIP = newStack.getProcessor(currentSlice); - boolean dimensionsChanged = width>0 && height>0 && (width!=newIP.getWidth()||height!=newIP.getHeight()); - if (this.stack==null) - newStack.viewers(+1); - this.stack = newStack; - oneSliceStack = false; - setProcessor2(title, newIP, newStack); - if (bitDepth1!=0 && bitDepth1!=getBitDepth()) - compositeChanges = true; - if (compositeChanges && (this instanceof CompositeImage)) { - this.compositeImage = getStackSize()!=getNSlices(); - ((CompositeImage)this).completeReset(); - if (bitDepth1!=0 && bitDepth1!=getBitDepth()) - ((CompositeImage)this).resetDisplayRanges(); - } - compositeChanges = false; - if (win==null) { - if (resetCurrentSlice) setSlice(currentSlice); - return; - } - boolean invalidDimensions = (isDisplayedHyperStack()||(this instanceof CompositeImage)) && (win instanceof StackWindow) && !((StackWindow)win).validDimensions(); - if (newStackSize>1 && !(win instanceof StackWindow)) { - if (isDisplayedHyperStack()) - setOpenAsHyperStack(true); - activated = false; - win = new StackWindow(this, dimensionsChanged?null:getCanvas()); // replaces this window - if (IJ.isMacro()) waitTillActivated(); // wait for stack window to be activated - setPosition(1, 1, 1); - } else if (newStackSize>1 && invalidDimensions) { - if (isDisplayedHyperStack()) - setOpenAsHyperStack(true); - win = new StackWindow(this); // replaces this window - setPosition(1, 1, 1); - } else if (dimensionsChanged || sliderChange) { - win.updateImage(this); - } else { - if (win!=null && win instanceof StackWindow) - ((StackWindow)win).updateSliceSelector(); - if (isComposite()) { - ((CompositeImage)this).reset(); - updateAndDraw(); - } - repaintWindow(); - } - if (resetCurrentSlice) - setSlice(currentSlice); - } - - public void setStack(ImageStack newStack, int channels, int slices, int frames) { - if (newStack==null || channels*slices*frames!=newStack.getSize()) - throw new IllegalArgumentException("channels*slices*frames!=stackSize"); - if (IJ.debugMode) IJ.log("setStack: "+newStack.getSize()+" "+channels+" "+slices+" "+frames+" "+isComposite()); - compositeChanges = channels!=this.nChannels; - this.nChannels = channels; - this.nSlices = slices; - this.nFrames = frames; - setStack(null, newStack); - } - - private synchronized void setStackNull() { - if (oneSliceStack && stack!=null && stack.size()>0) { - String label = stack.getSliceLabel(1); - setProp("Slice_Label", label); - } - stack = null; - oneSliceStack = false; - } - - /** Saves this image's FileInfo so it can be later - retieved using getOriginalFileInfo(). */ - public void setFileInfo(FileInfo fi) { - if (fi!=null) { - fi.pixels = null; - if (fi.imageSaved) { - notifyListeners(SAVED); - fi.imageSaved = false; - } - } - fileInfo = fi; - } - - /** Returns the ImageWindow that is being used to display - this image. Returns null if show() has not be called - or the ImageWindow has been closed. */ - public ImageWindow getWindow() { - return win; - } - - /** Returns true if this image is currently being displayed in a window. */ - public boolean isVisible() { - return win!=null && win.isVisible(); - } - - /** This method should only be called from an ImageWindow. */ - public void setWindow(ImageWindow win) { - this.win = win; - if (roi!=null) - roi.setImage(this); // update roi's 'ic' field - } - - /** Returns the ImageCanvas being used to - display this image, or null. */ - public ImageCanvas getCanvas() { - return win!=null?win.getCanvas():flatteningCanvas; - } - - /** Sets current foreground color. */ - public void setColor(Color c) { - if (ip!=null) - ip.setColor(c); - } - - void setupProcessor() { - } - - public boolean isProcessor() { - return ip!=null; - } - - /** Returns a reference to the current ImageProcessor. If there - is no ImageProcessor, it creates one. Returns null if this - ImagePlus contains no ImageProcessor and no AWT Image. - Sets the line width to the current line width and sets the - calibration table if the image is density calibrated. */ - public ImageProcessor getProcessor() { - if (ip==null) - return null; - if (roi!=null && roi.isArea()) - ip.setRoi(roi.getBounds()); - else - ip.resetRoi(); - if (!compositeImage) - ip.setLineWidth(Line.getWidth()); - if (ij!=null) - ip.setProgressBar(ij.getProgressBar()); - Calibration cal = getCalibration(); - if (cal.calibrated()) - ip.setCalibrationTable(cal.getCTable()); - else - ip.setCalibrationTable(null); - if (IJ.recording()) { - Recorder recorder = Recorder.getInstance(); - if (recorder!=null) recorder.imageUpdated(this); - } - return ip; - } - - /** Frees RAM by setting the snapshot (undo) buffer in - the current ImageProcessor to null. */ - public void trimProcessor() { - ImageProcessor ip2 = ip; - if (!locked && ip2!=null) { - if (IJ.debugMode) IJ.log(title + ": trimProcessor"); - Roi roi2 = getRoi(); - if (roi2!=null && roi2.getPasteMode()!=Roi.NOT_PASTING) - roi2.endPaste(); - ip2.setSnapshotPixels(null); - } - } - - /** For images with irregular ROIs, returns a byte mask, otherwise, returns - * null. Mask pixels have a non-zero value.and the dimensions of the - * mask are equal to the width and height of the ROI. - * @see ij.ImagePlus#createRoiMask - * @see ij.ImagePlus#createThresholdMask - */ - public ImageProcessor getMask() { - if (roi==null) { - if (ip!=null) ip.resetRoi(); - return null; - } - ImageProcessor mask = roi.getMask(); - if (mask==null) - return null; - if (ip!=null && roi!=null) { - ip.setMask(mask); - ip.setRoi(roi.getBounds()); - } - return mask; - } - - /** Returns an 8-bit binary (foreground=255, background=0) - * ROI or overlay mask that has the same dimensions - * as this image. Creates an ROI mask If the image has both - * both an ROI and an overlay. Set the threshold of the mask to 255. - * @see #createThresholdMask - * @see ij.gui.Roi#getMask - */ - public ByteProcessor createRoiMask() { - Roi roi2 = getRoi(); - Overlay overlay2 = getOverlay(); - if (roi2==null && overlay2==null) - throw new IllegalArgumentException("ROI or overlay required"); - ByteProcessor mask = new ByteProcessor(getWidth(),getHeight()); - mask.setColor(255); - if (roi2!=null) - mask.fill(roi2); - else if (overlay2!=null) { - if (overlay2.size()==1 && (overlay2.get(0) instanceof ImageRoi)) { - ImageRoi iRoi = (ImageRoi)overlay2.get(0); - ImageProcessor ip = iRoi.getProcessor(); - if (ip.getWidth()!=mask.getWidth() || ip.getHeight()!=mask.getHeight()) - return mask; - for (int i=0; i - imp = IJ.getImage(); - stats = imp.getStatistics(); - IJ.log("Area: "+stats.area); - IJ.log("Mean: "+stats.mean); - IJ.log("Max: "+stats.max); - - @return an {@link ij.process.ImageStatistics} object - @see #getAllStatistics - @see #getRawStatistics - @see ij.process.ImageProcessor#getStats - */ - public ImageStatistics getStatistics() { - return getStatistics(AREA+MEAN+STD_DEV+MODE+MIN_MAX+RECT); - } - - /** This method returns complete calibrated statistics for this - * image or ROI (with "Limit to threshold"), but it is up to 70 times - * slower than getStatistics(). - * @return an {@link ij.process.ImageStatistics} object - * @see #getStatistics - * @see ij.process.ImageProcessor#getStatistics - */ - public ImageStatistics getAllStatistics() { - return getStatistics(ALL_STATS+LIMIT); - } - - /* Returns uncalibrated statistics for this image or ROI, including - 256 bin histogram, pixelCount, mean, mode, standard deviation, - min and max. - */ - public ImageStatistics getRawStatistics() { - if (roi!=null && roi.isArea()) - ip.setRoi(roi); - else - ip.resetRoi(); - return ImageStatistics.getStatistics(ip, AREA+MEAN+MODE+STD_DEV+MIN_MAX, null); - } - - /** Returns an ImageStatistics object generated using the - specified measurement options. - @see ij.measure.Measurements - */ - public ImageStatistics getStatistics(int mOptions) { - return getStatistics(mOptions, 256, 0.0, 0.0); - } - - /** Returns an ImageStatistics object generated using the - specified measurement options and histogram bin count. */ - public ImageStatistics getStatistics(int mOptions, int nBins) { - return getStatistics(mOptions, nBins, 0.0, 0.0); - } - - /** Returns an ImageStatistics object generated using the - specified measurement options, histogram bin count - and histogram range. */ - public ImageStatistics getStatistics(int mOptions, int nBins, double histMin, double histMax) { - ImageProcessor ip2 = ip; - int bitDepth = getBitDepth(); - if (nBins!=256 && (bitDepth==8||bitDepth==24)) - ip2 =ip.convertToShort(false); - Roi roi2 = roi; - if (roi2==null) - ip2.resetRoi(); - else if (roi2.isArea()) - ip2.setRoi(roi2); - else if ((roi2 instanceof PointRoi) && roi2.size()==1) { - // needed to be consistent with ImageProcessor.getStatistics() - FloatPolygon p = roi2.getFloatPolygon(); - ip2.setRoi((int)p.xpoints[0], (int)p.ypoints[0], 1, 1); - } - ip2.setHistogramSize(nBins); - Calibration cal = getCalibration(); - if (getType()==GRAY16&& !(histMin==0.0&&histMax==0.0)) { - histMin = cal.getRawValue(histMin); - histMax=cal.getRawValue(histMax); - } - ip2.setHistogramRange(histMin, histMax); - ImageStatistics stats = ImageStatistics.getStatistics(ip2, mOptions, cal); - ip2.setHistogramSize(256); - ip2.setHistogramRange(0.0, 0.0); - return stats; - } - - /** Returns the image name. */ - public String getTitle() { - if (title==null) - return ""; - else - return title; - } - - /** If the image title is a file name, returns the name - without the extension and with spaces removed, - otherwise returns the title shortened to the first space. - */ - public String getShortTitle() { - String title = getTitle().trim(); - int index = title.lastIndexOf('.'); - boolean fileName = index>0; - if (fileName) { - title = title.substring(0, index); - title = title.replaceAll(" ",""); - } else { - index = title.indexOf(' '); - if (index>-1 && !fileName) - title = title.substring(0, index); - } - return title; - } - - /** Sets the image name. */ - public void setTitle(String title) { - if (title==null) - return; - if (win!=null) { - if (ij!=null) - Menus.updateWindowMenuItem(this, this.title, title); - String virtual = stack!=null && stack.isVirtual()?" (V)":""; - String global = getGlobalCalibration()!=null?" (G)":""; - String scale = ""; - double magnification = win.getCanvas().getMagnification(); - if (magnification!=1.0) { - double percent = magnification*100.0; - int digits = percent>100.0||percent==(int)percent?0:1; - scale = " (" + IJ.d2s(percent,digits) + "%)"; - } - win.setTitle(title+virtual+global+scale); - } - boolean titleChanged = !title.equals(this.title); - this.title = title; - if (titleChanged && listeners.size()>0) - notifyListeners(UPDATED); - } - - /** Returns the width of this image in pixels. */ - public int getWidth() { - return width; - } - - /** Returns the height of this image in pixels. */ - public int getHeight() { - return height; - } - - /** Returns the size of this image in bytes. */ - public double getSizeInBytes() { - double size = ((double)getWidth()*getHeight()*getStackSize()); - int type = getType(); - switch (type) { - case ImagePlus.GRAY16: size *= 2.0; break; - case ImagePlus.GRAY32: size *= 4.0; break; - case ImagePlus.COLOR_RGB: size *= 4.0; break; - } - return size; - } - - /** Returns the number of stack images. */ - public int getStackSize() { - if (stack==null || oneSliceStack) - return 1; - else { - int slices = stack.size(); - if (slices<=0) slices = 1; - return slices; - } - } - - /** If this is a stack, returns the actual number of images in the stack, else returns 1. */ - public int getImageStackSize() { - if (stack==null) - return 1; - else { - int slices = stack.size(); - if (slices==0) slices = 1; - return slices; - } - } - - /** Sets the 3rd, 4th and 5th dimensions, where - nChannels*nSlices*nFrames - must be equal to the stack size. */ - public void setDimensions(int nChannels, int nSlices, int nFrames) { - //IJ.log("setDimensions: "+nChannels+" "+nSlices+" "+nFrames+" "+getImageStackSize()); - if (nChannels*nSlices*nFrames!=getImageStackSize() && ip!=null) { - //throw new IllegalArgumentException("channels*slices*frames!=stackSize"); - nChannels = 1; - nSlices = getImageStackSize(); - nFrames = 1; - if (isDisplayedHyperStack()) { - setOpenAsHyperStack(false); - new StackWindow(this); - setSlice(1); - } - } - boolean updateWin = isDisplayedHyperStack() && (this.nChannels!=nChannels||this.nSlices!=nSlices||this.nFrames!=nFrames); - boolean newSingleImage = win!=null && (win instanceof StackWindow) && nChannels==1&&nSlices==1&&nFrames==1; - if (newSingleImage) updateWin = true; - this.nChannels = nChannels; - this.nSlices = nSlices; - this.nFrames = nFrames; - if (updateWin) { - if (nSlices!=getImageStackSize()) - setOpenAsHyperStack(true); - ip = null; - img = null; - setPositionWithoutUpdate(getChannel(), getSlice(), getFrame()); - if (isComposite()) ((CompositeImage)this).reset(); - new StackWindow(this); - } - dimensionsSet = true; - } - - /** Returns 'true' if this image has more - * than three dimensions. - */ - public boolean isHyperStack() { - return getNDimensions()>3; - } - - /** Returns the number of dimensions (2, 3, 4 or 5). */ - public int getNDimensions() { - int dimensions = 2; - int[] dim = getDimensions(true); - if (dim[2]>1) dimensions++; - if (dim[3]>1) dimensions++; - if (dim[4]>1) dimensions++; - return dimensions; - } - - /** Returns 'true' if this is a hyperstack currently being displayed in a StackWindow. */ - public boolean isDisplayedHyperStack() { - return win!=null && win instanceof StackWindow && ((StackWindow)win).isHyperStack(); - } - - /** Returns the number of channels. */ - public int getNChannels() { - verifyDimensions(); - return nChannels; - } - - /** Returns the image depth (number of z-slices). */ - public int getNSlices() { - verifyDimensions(); - return nSlices; - } - - /** Returns the number of frames (time-points). */ - public int getNFrames() { - verifyDimensions(); - return nFrames; - } - - /** Returns the dimensions of this image (width, height, nChannels, - nSlices, nFrames) as a 5 element int array. */ - public int[] getDimensions() { - return getDimensions(true); - } - - public int[] getDimensions(boolean varify) { - if (varify) - verifyDimensions(); - int[] d = new int[5]; - d[0] = width; - d[1] = height; - d[2] = nChannels; - d[3] = nSlices; - d[4] = nFrames; - return d; - } - - void verifyDimensions() { - int stackSize = getImageStackSize(); - if (nSlices==1) { - if (nChannels>1 && nFrames==1) - nChannels = stackSize; - else if (nFrames>1 && nChannels==1) - nFrames = stackSize; - } - if (nChannels*nSlices*nFrames!=stackSize) { - nSlices = stackSize; - nChannels = 1; - nFrames = 1; - } - } - - /** Returns the current image type (ImagePlus.GRAY8, ImagePlus.GRAY16, - ImagePlus.GRAY32, ImagePlus.COLOR_256 or ImagePlus.COLOR_RGB). - @see #getBitDepth - */ - public int getType() { - return imageType; - } - - /** Returns the bit depth, 8, 16, 24 (RGB) or 32, or 0 if the bit depth - is unknown. RGB images actually use 32 bits per pixel. */ - public int getBitDepth() { - ImageProcessor ip2 = ip; - if (ip2==null) { - int bitDepth = 0; - switch (imageType) { - case GRAY8: bitDepth=typeSet?8:0; break; - case COLOR_256: bitDepth=8; break; - case GRAY16: bitDepth=16; break; - case GRAY32: bitDepth=32; break; - case COLOR_RGB: bitDepth=24; break; - } - return bitDepth; - } - if (ip2 instanceof ByteProcessor) - return 8; - else if (ip2 instanceof ShortProcessor) - return 16; - else if (ip2 instanceof ColorProcessor) - return 24; - else if (ip2 instanceof FloatProcessor) - return 32; - return 0; - } - - /** Returns the number of bytes per pixel. */ - public int getBytesPerPixel() { - switch (imageType) { - case GRAY16: return 2; - case GRAY32: case COLOR_RGB: return 4; - default: return 1; - } - } - - protected void setType(int type) { - if ((type<0) || (type>COLOR_RGB)) - return; - int previousType = imageType; - imageType = type; - if (imageType!=previousType) { - if (win!=null) - Menus.updateMenus(); - getLocalCalibration().setImage(this); - } - typeSet = true; - } - - public void setTypeToColor256() { - if (imageType==ImagePlus.GRAY8) { - ImageProcessor ip2 = getProcessor(); - if (ip2!=null && !ip2.isThreshold() && ip2.isColorLut() && !ip2.isPseudoColorLut()) { - imageType = COLOR_256; - typeSet = true; - } - } - } - - - /** Returns the string value from the "Info" property string - * associated with 'key', or null if the key is not found. - * Works with DICOM tags and Bio-Formats metadata. - * @see #getNumericProperty - * @see #getInfoProperty - * @see #getProp - * @see #setProp - */ - public String getStringProperty(String key) { - if (key==null) - return null; - if (isDicomTag(key)) - return DicomTools.getTag(this, key); - if (getStackSize()>1) { - ImageStack stack2 = getStack(); - String label = stack2.getSliceLabel(getCurrentSlice()); - if (label!=null && label.indexOf('\n')>0) { - String value = getStringProperty(key, label); - if (value!=null) - return value; - } - } - Object obj = getProperty("Info"); - if (obj==null || !(obj instanceof String)) - return null; - String info = (String)obj; - return getStringProperty(key, info); - } - - private boolean isDicomTag(String key) { - if (key.length()!=9 || key.charAt(4)!=',') - return false; - key = key.toLowerCase(); - for (int i=0; i<9; i++) { - char c = i!=4?key.charAt(i):'0'; - if (!(Character.isDigit(c)||(c=='a'||c=='b'||c=='c'||c=='d'||c=='e'||c=='f'))) - return false; - } - return true; - } - - /** Returns the numeric value from the "Info" property string - * associated with 'key', or NaN if the key is not found or the - * value associated with the key is not numeric. Works with - * DICOM tags and Bio-Formats metadata. - * @see #getStringProperty - * @see #getInfoProperty - */ - public double getNumericProperty(String key) { - return Tools.parseDouble(getStringProperty(key)); - } - - private String getStringProperty(String key, String info) { - int index1 = -1; - index1 = findKey(info, key+": "); // standard 'key: value' pair? - if (index1<0) // Bio-Formats metadata? - index1 = findKey(info, key+" = "); - if (index1<0) // '=' with no spaces - index1 = findKey(info, key+"="); - if (index1<0) // otherwise not found - return null; - if (index1==info.length()) - return ""; //empty value at the end - int index2 = info.indexOf("\n", index1); - if (index2==-1) - index2=info.length(); - String value = info.substring(index1, index2); - return value; - } - - /** Find a key in a String (words merely ending with 'key' don't qualify). - * @return index of first character after the key, or -1 if not found - */ - private int findKey(String s, String key) { - int i = s.indexOf(key); - if (i<0) - return -1; //key not found - while (i>0 && Character.isLetterOrDigit(s.charAt(i-1))) - i = s.indexOf(key, i+key.length()); - if (i>=0) - return i + key.length(); - else - return -1; - } - - /** Adds a key-value pair to this image's string properties. - * The key-value pair is removed if 'value' is null. The - * properties persist if the image is saved in TIFF format. - * Add a "HideInfo" property (e.g. set("HideInfo","true")) to - * prevent the properties from being displayed by the - * Image/Show Info command. - */ - public void setProp(String key, String value) { - if (key==null) - return; - if (imageProperties==null) - imageProperties = new Properties(); - if (value==null || value.length()==0) - imageProperties.remove(key); - else { - imageProperties.setProperty(key, value); - if (key.equals("CompositeProjection")) - Channels.updateChannels(); - } - } - - /** Saves a persistent numeric propery. The property is - * removed if 'value' is NaN. - * @see #getNumericProp - */ - public void setProp(String key, double value) { - String svalue = ""+value; - if (svalue.endsWith(".0")) - svalue = svalue.substring(0,svalue.length()-2); - setProp(key, Double.isNaN(value)?null:svalue); - } - - /** Returns as a string the image property associated with the - * specified key or null if the property is not found. - * @see #setProp - * @see #getNumericProp - * @see #getStringProperty - */ - public String getProp(String key) { - if (imageProperties==null) - return getStringProperty(key); - else { - String value = imageProperties.getProperty(key); - if (value==null) - value = getStringProperty(key); - return value; - } - } - - /** Returns the numeric property associated with the specified key - * or NaN if the property is not found. - * @see #setProp(String,double) - * @see #getProp - */ - public double getNumericProp(String key) { - if (imageProperties==null) - return Double.NaN; - else - return Tools.parseDouble(getProp(key), Double.NaN); - } - - /** Used for saving string properties in TIFF header. */ - public String[] getPropertiesAsArray() { - if (imageProperties==null || imageProperties.size()==0) - return null; - String props[] = new String[imageProperties.size()*2]; - int index = 0; - for (Enumeration en=imageProperties.keys(); en.hasMoreElements();) { - String key = (String)en.nextElement(); - String value = imageProperties.getProperty(key); - props[index++] = key; - props[index++] = value; - } - return props; - } - - /** Returns information displayed by Image/Show Info command. */ - public String getPropsInfo() { - if (imageProperties==null || imageProperties.size()==0) - return "0"; - String info2 = ""; - for (Enumeration en=imageProperties.keys(); en.hasMoreElements();) { - String key = (String)en.nextElement(); - if (info2.length()>50) { - info2 += "..."; - break; - } else - info2 += " " + key; - } - if (info2.length()>1) - info2 = " (" + info2.substring(1) + ")"; - return imageProperties.size() + info2; - } - - /** Creates a set of image properties from an array of strings. - * @see #getPropertiesAsArray - * @see #getProp(String) - * @see #setProp(String,String) - */ - public void setProperties(String[] props) { - imageProperties = null; - if (props==null) - return; - //IJ.log("setProperties: "+props.length+" "+getTitle()); - for (int i=0; i>16; - int g = (c&0xff00)>>8; - int b = c&0xff; - pvalue[0] = r; - pvalue[1] = g; - pvalue[2] = b; - break; - case GRAY16: case GRAY32: - if (ip!=null) pvalue[0] = ip.getPixel(x, y); - break; - } - return pvalue; - } - - /** Returns an empty image stack that has the same - width, height and color table as this image. */ - public ImageStack createEmptyStack() { - ColorModel cm; - if (ip!=null) - cm = ip.getColorModel(); - else - cm = createLut().getColorModel(); - return new ImageStack(width, height, cm); - } - - /** Returns the image stack. The stack may have only - one slice. After adding or removing slices, call - setStack() to update the image and - the window that is displaying it. - @see #setStack - */ - public ImageStack getStack() { - ImageStack s; - if (stack==null) { - s = createEmptyStack(); - ImageProcessor ip2 = getProcessor(); - if (ip2==null) - return s; - String label = getProp("Slice_Label"); - if (label==null) { - String info = (String)getProperty("Info"); - label = info!=null?getTitle()+"\n"+info:null; // DICOM metadata - } - s.addSlice(label, ip2); - s.update(ip2); - this.stack = s; - ip = ip2; - oneSliceStack = true; - setCurrentSlice(1); - } else { - s = stack; - if (ip!=null) { - Calibration cal = getCalibration(); - if (cal.calibrated()) - ip.setCalibrationTable(cal.getCTable()); - else - ip.setCalibrationTable(null); - } - s.update(ip); - } - if (roi!=null) - s.setRoi(roi.getBounds()); - else - s.setRoi(null); - return s; - } - - /** Returns the base image stack. */ - public ImageStack getImageStack() { - if (stack==null) - return getStack(); - else { - stack.update(ip); - return stack; - } - } - - /** Returns the current stack index (one-based) or 1 if this is a single image. */ - public int getCurrentSlice() { - if (currentSlice<1) setCurrentSlice(1); - if (currentSlice>getStackSize()) - setCurrentSlice(getStackSize()); - return currentSlice; - } - - final void setCurrentSlice(int slice) { - currentSlice = slice; - int stackSize = getStackSize(); - if (nChannels==stackSize) updatePosition(currentSlice, 1, 1); - if (nSlices==stackSize) updatePosition(1, currentSlice, 1); - if (nFrames==stackSize) updatePosition(1, 1, currentSlice); - } - - public int getChannel() { - return position[0]; - } - - public int getSlice() { - return position[1]; - } - - public int getFrame() { - return position[2]; - } - - public void killStack() { - setStackNull(); - trimProcessor(); - } - - /** Sets the current hyperstack position and updates the display, - where 'channel', 'slice' and 'frame' are one-based indexes. */ - public void setPosition(int channel, int slice, int frame) { - //IJ.log("setPosition: "+channel+" "+slice+" "+frame+" "+noUpdateMode); - verifyDimensions(); - if (channel<0) channel=0; - if (slice<0) slice=0; - if (frame<0) frame=0; - if (channel==0) channel=getC(); - if (slice==0) slice=getZ(); - if (frame==0) frame=getT(); - if (channel>nChannels) channel=nChannels; - if (slice>nSlices) slice=nSlices; - if (frame>nFrames) frame=nFrames; - if (isDisplayedHyperStack()) { - if (noUpdateMode) { - setSlice((frame-1)*nChannels*nSlices + (slice-1)*nChannels + channel); - updatePosition(channel, slice, frame); - } else - ((StackWindow)win).setPosition(channel, slice, frame); - } else { - boolean channelChanged = channel!=getChannel(); - setSlice((frame-1)*nChannels*nSlices + (slice-1)*nChannels + channel); - updatePosition(channel, slice, frame); - if (channelChanged && isComposite() && !noUpdateMode) - updateImage(); - } - } - - /** Sets the current hyperstack position without updating the display, - where 'channel', 'slice' and 'frame' are one-based indexes. */ - public void setPositionWithoutUpdate(int channel, int slice, int frame) { - noUpdateMode = true; - setPosition(channel, slice, frame); - noUpdateMode = false; - } - - /** Sets the hyperstack channel position (one based). */ - public void setC(int channel) { - setPosition(channel, getZ(), getT()); - } - - /** Sets the hyperstack slice position (one based). */ - public void setZ(int slice) { - setPosition(getC(), slice, getT()); - } - - /** Sets the hyperstack frame position (one based). */ - public void setT(int frame) { - setPosition(getC(), getZ(), frame); - } - - /** Returns the current hyperstack channel position. */ - public int getC() { - return position[0]; - } - - /** Returns the current hyperstack slice position. */ - public int getZ() { - return position[1]; - } - - /** Returns the current hyperstack frame position. */ - public int getT() { - return position[2]; - } - - /** Returns that stack index (one-based) corresponding to the specified position. */ - public int getStackIndex(int channel, int slice, int frame) { - if (channel<1) channel = 1; - if (channel>nChannels) channel = nChannels; - if (slice<1) slice = 1; - if (slice>nSlices) slice = nSlices; - if (frame<1) frame = 1; - if (frame>nFrames) frame = nFrames; - return (frame-1)*nChannels*nSlices + (slice-1)*nChannels + channel; - } - - /* Hack needed to make the HyperStackReducer work. */ - public void resetStack() { - if (currentSlice==1 && stack!=null && stack.size()>0) { - ColorModel cm = ip.getColorModel(); - double min = ip.getMin(); - double max = ip.getMax(); - ImageProcessor ip2 = stack.getProcessor(1); - if (ip2!=null) { - ip = ip2; - ip.setColorModel(cm); - ip.setMinAndMax(min, max); - } - } - } - - /** Set the current hyperstack position based on the stack index 'n' (one-based). */ - public void setPosition(int n) { - int[] pos = convertIndexToPosition(n); - setPosition(pos[0], pos[1], pos[2]); - } - - /** Converts the stack index 'n' (one-based) into a hyperstack position (channel, slice, frame). */ - public int[] convertIndexToPosition(int n) { - if (n<1 || n>getStackSize()) - throw new IllegalArgumentException("n out of range: "+n); - int[] position = new int[3]; - int[] dim = getDimensions(); - position[0] = ((n-1)%dim[2])+1; - position[1] = (((n-1)/dim[2])%dim[3])+1; - position[2] = (((n-1)/(dim[2]*dim[3]))%dim[4])+1; - return position; - } - - /** Displays the specified stack image, where {@literal 1<=n<=stackSize}. - * Does nothing if this image is not a stack. - * @see #setPosition - * @see #setC - * @see #setZ - * @see #setT - */ - public synchronized void setSlice(int n) { - if (stack==null || (n==currentSlice&&ip!=null)) { - if (!noUpdateMode) - updateAndRepaintWindow(); - return; - } - if (n>=1 && n<=stack.size()) { - Roi roi = getRoi(); - if (roi!=null) - roi.endPaste(); - if (isProcessor()) { - if (currentSlice==0) currentSlice=1; - stack.setPixels(ip.getPixels(),currentSlice); - } - setCurrentSlice(n); - Object pixels = null; - Overlay overlay2 = null; - if (stack.isVirtual() && !((stack instanceof FileInfoVirtualStack)||(stack instanceof AVI_Reader))) { - ImageProcessor ip2 = stack.getProcessor(currentSlice); - overlay2 = ip2!=null?ip2.getOverlay():null; - if (overlay2!=null) - setOverlay(overlay2); - if (stack instanceof VirtualStack) { - Properties props = ((VirtualStack)stack).getProperties(); - if (props!=null) - setProperty("FHT", props.get("FHT")); - } - if (ip2!=null) pixels=ip2.getPixels(); - } else - pixels = stack.getPixels(currentSlice); - if (ip!=null && pixels!=null) { - try { - ip.setPixels(pixels); - ip.setSnapshotPixels(null); - } catch(Exception e) {} - } else { - ImageProcessor ip2 = stack.getProcessor(n); - if (ip2!=null) ip = ip2; - } - if (compositeImage && getCompositeMode()==IJ.COMPOSITE && ip!=null) { - int channel = getC(); - if (channel>0 && channel<=getNChannels()) - ip.setLut(((CompositeImage)this).getChannelLut(channel)); - } - if (win!=null && win instanceof StackWindow) - ((StackWindow)win).updateSliceSelector(); - if (Prefs.autoContrast && nChannels==1 && imageType!=COLOR_RGB) { - (new ContrastEnhancer()).stretchHistogram(ip,0.35,ip.getStats()); - ContrastAdjuster.update(); - //IJ.showStatus(n+": min="+ip.getMin()+", max="+ip.getMax()); - } - if (imageType==COLOR_RGB) - ContrastAdjuster.update(); - if (!noUpdateMode) - updateAndRepaintWindow(); - else - img = null; - if (ip!=null) - ip.setSliceNumber(n); - } - } - - /** Displays the specified stack image ({@literal 1<=n<=stackSize}) - without updating the display. */ - public void setSliceWithoutUpdate(int n) { - noUpdateMode = true; - setSlice(n); - noUpdateMode = false; - } - - /** Returns the current selection, or null if there is no selection. */ - public Roi getRoi() { - return roi; - } - - /** Assigns the specified ROI to this image and displays it. Any existing - ROI is deleted if roi is null or its width or height is zero. */ - public void setRoi(Roi newRoi) { - setRoi(newRoi, true); - } - - /** Assigns 'newRoi' to this image and displays it if 'updateDisplay' is true. */ - public void setRoi(Roi newRoi, boolean updateDisplay) { - if (newRoi==null) { - deleteRoi(); - return; - } - if (IJ.recording()) { - Recorder recorder = Recorder.getInstance(); - if (recorder!=null) recorder.imageUpdated(this); - } - Rectangle bounds = newRoi.getBounds(); - if (newRoi.isVisible()) { - if ((newRoi instanceof Arrow) && newRoi.getState()==Roi.CONSTRUCTING && bounds.width==0 && bounds.height==0) { - deleteRoi(); - roi = newRoi; - return; - } - if (newRoi==null) { - deleteRoi(); - return; - } - ImagePlus imp = newRoi.getImage(); - if (imp!=null && imp.getID()!=getID()) - newRoi = (Roi)newRoi.clone(); - newRoi.setImage(null); - } - if (bounds.width==0 && bounds.height==0 && !(newRoi.getType()==Roi.POINT||newRoi.getType()==Roi.LINE)) { - deleteRoi(); - return; - } - roi = newRoi; - if (ip!=null) { - ip.setMask(null); - if (roi.isArea()) - ip.setRoi(bounds); - else - ip.resetRoi(); - } - roi.setImage(this); - if ((roi instanceof PointRoi) && ((PointRoi)roi).addToOverlay()) { - IJ.run(this, "Add Selection...", ""); - roi = null; - return; - } - if (updateDisplay) - draw(); - if (roi!=null) - roi.notifyListeners(RoiListener.CREATED); - } - - /** Creates a rectangular selection. */ - public void setRoi(int x, int y, int width, int height) { - setRoi(new Rectangle(x, y, width, height)); - } - - /** Creates a rectangular selection. */ - public void setRoi(Rectangle r) { - setRoi(new Roi(r.x, r.y, r.width, r.height)); - } - - /** Starts the process of creating a new selection, where sx and sy are the - starting screen coordinates. The selection type is determined by which tool in - the tool bar is active. The user interactively sets the selection size and shape. */ - public void createNewRoi(int sx, int sy) { - Roi previousRoi = roi; - deleteRoi(); //also saves the roi as Roi.previousRoi if non-null - Roi prevRoi = Roi.getPreviousRoi(); - if (prevRoi != null) - prevRoi.setImage(previousRoi==null ? null : this); //with 'this' it will be recalled in case of ESC - switch (Toolbar.getToolId()) { - case Toolbar.RECTANGLE: - if (Toolbar.getRectToolType()==Toolbar.ROTATED_RECT_ROI) - roi = new RotatedRectRoi(sx, sy, this); - else - roi = new Roi(sx, sy, this, Toolbar.getRoundRectArcSize()); - break; - case Toolbar.OVAL: - if (Toolbar.getOvalToolType()==Toolbar.ELLIPSE_ROI) - roi = new EllipseRoi(sx, sy, this); - else - roi = new OvalRoi(sx, sy, this); - break; - case Toolbar.POLYGON: - case Toolbar.POLYLINE: - case Toolbar.ANGLE: - roi = new PolygonRoi(sx, sy, this); - break; - case Toolbar.FREEROI: - case Toolbar.FREELINE: - roi = new FreehandRoi(sx, sy, this); - break; - case Toolbar.LINE: - if ("arrow".equals(Toolbar.getToolName())) - roi = new Arrow(sx, sy, this); - else - roi = new Line(sx, sy, this); - break; - case Toolbar.TEXT: - roi = new TextRoi(sx, sy, this); - ((TextRoi)roi).setPreviousTextRoi(previousRoi); - break; - case Toolbar.POINT: - roi = new PointRoi(sx, sy, this); - if (Prefs.pointAddToOverlay) { - int measurements = Analyzer.getMeasurements(); - if (!(Prefs.pointAutoMeasure && (measurements&Measurements.ADD_TO_OVERLAY)!=0)) - IJ.run(this, "Add Selection...", ""); - Overlay overlay2 = getOverlay(); - if (overlay2!=null) - overlay2.drawLabels(!Prefs.noPointLabels); - Prefs.pointAddToManager = false; - } - if (Prefs.pointAutoMeasure || (Prefs.pointAutoNextSlice&&!Prefs.pointAddToManager)) - IJ.run(this, "Measure", ""); - if (Prefs.pointAddToManager) { - IJ.run(this, "Add to Manager ", ""); - ImageCanvas ic = getCanvas(); - if (ic!=null) { - RoiManager rm = RoiManager.getInstance(); - if (rm!=null) { - if (Prefs.noPointLabels) - rm.runCommand("show all without labels"); - else - rm.runCommand("show all with labels"); - } - } - } - if (Prefs.pointAutoNextSlice && getStackSize()>1) { - boolean order = Prefs.reverseNextPreviousOrder; - Prefs.reverseNextPreviousOrder = true; - IJ.run(this, "Next Slice [>]", ""); - Prefs.reverseNextPreviousOrder = order; - deleteRoi(); - } - break; - } - if (roi!=null) - roi.notifyListeners(RoiListener.CREATED); - } - - /** Deletes the current region of interest. Makes a copy of the ROI - so it can be recovered by Edit/Selection/Restore Selection. */ - public void deleteRoi() { - if (roi==null) - return; - saveRoi(); - if (!(IJ.altKeyDown()||IJ.shiftKeyDown())) { - RoiManager rm = RoiManager.getRawInstance(); - if (rm!=null) - rm.deselect(roi); - } - if (roi!=null) - roi.notifyListeners(RoiListener.DELETED); - roi = null; - if (ip!=null) - ip.resetRoi(); - draw(); - } - - /** Removes the spatial scaling of this image. */ - public void removeScale() { - Calibration cal = getCalibration(); - cal.pixelWidth = 1.0; - cal.pixelHeight = 1.0; - cal.pixelDepth = 1.0; - cal.setUnit("pixel"); - ImageWindow win = getWindow(); - if (win!=null) - win.repaint(); - } - - public boolean okToDeleteRoi() { - if (roi!=null && (roi instanceof PointRoi) && getWindow()!=null && ((PointRoi)roi).promptBeforeDeleting()) { - int npoints = ((PolygonRoi)roi).getNCoordinates(); - int counters = ((PointRoi)roi).getNCounters(); - String msg = "Delete this multi-point selection ("+npoints+" points, "+counters+" counter"+(counters>1?"s":"")+")?"; - GenericDialog gd=new GenericDialog("Delete Points?"); - gd.addMessage(msg+"\nRestore using Edit>Selection>Restore Selection."); - gd.addHelp(PointToolOptions.help); - gd.setOKLabel("Keep"); - gd.setCancelLabel("Delete"); - gd.showDialog(); - if (gd.wasOKed()) - return false; - } - return true; - } - - /** Deletes the current region of interest. */ - public void killRoi() { - deleteRoi(); - } - - /** Deletes the current region of interest. */ - public void resetRoi() { - deleteRoi(); - } - - public void saveRoi() { - Roi roi2 = roi; - if (roi2!=null) { - roi2.endPaste(); - Rectangle r = roi2.getBounds(); - if ((r.width>0 || r.height>0)) { - Roi.setPreviousRoi(roi2); - if (IJ.debugMode) IJ.log("saveRoi: "+roi2); - } - if ((roi2 instanceof PointRoi) && ((PointRoi)roi2).promptBeforeDeleting()) { - PointRoi.savedPoints = (PointRoi)roi2.clone(); - if (IJ.debugMode) IJ.log("saveRoi: saving multi-point selection"); - } - } - } - - public void restoreRoi() { - if (Toolbar.getToolId()==Toolbar.POINT && PointRoi.savedPoints!=null) { - roi = (Roi)PointRoi.savedPoints.clone(); - draw(); - roi.notifyListeners(RoiListener.MODIFIED); - return; - } - Roi previousRoi = Roi.getPreviousRoi(); - if (previousRoi!=null) { - Roi pRoi = previousRoi; - Rectangle r = pRoi.getBounds(); - if (r.width<=width||r.height<=height||(r.x=width || r.y>=height || (r.x+r.width)<0 || (r.y+r.height)<0) // does it need to be moved? - roi.setLocation((width-r.width)/2, (height-r.height)/2); - else if (r.width==width && r.height==height) // is it the same size as the image - roi.setLocation(0, 0); - draw(); - roi.notifyListeners(RoiListener.MODIFIED); - } - } - } - - boolean isSmaller(Roi r) { - ImageProcessor mask = r.getMask(); - if (mask==null) return false; - mask.setThreshold(255, 255, ImageProcessor.NO_LUT_UPDATE); - ImageStatistics stats = ImageStatistics.getStatistics(mask, MEAN+LIMIT, null); - return stats.area<=width*height; - } - - /** Implements the File/Revert command. */ - public void revert() { - if (getStackSize()>1 && getStack().isVirtual()) { - int thisSlice = currentSlice; - currentSlice = 0; - setSlice(thisSlice); - return; - } - FileInfo fi = getOriginalFileInfo(); - boolean isFileInfo = fi!=null && fi.fileFormat!=FileInfo.UNKNOWN; - if (!isFileInfo && url==null) - return; - if (fi.directory==null && url==null) - return; - if (ij!=null && changes && isFileInfo && !Interpreter.isBatchMode() && !IJ.isMacro() && !IJ.altKeyDown()) { - if (!IJ.showMessageWithCancel("Revert?", "Revert to saved version of\n\""+getTitle()+"\"?")) - return; - } - Roi saveRoi = null; - if (roi!=null) { - roi.endPaste(); - saveRoi = (Roi)roi.clone(); - } - trimProcessor(); - new FileOpener(fi).revertToSaved(this); - if (Prefs.useInvertingLut && getBitDepth()==8 && ip!=null && !ip.isInvertedLut()&& !ip.isColorLut()) - invertLookupTable(); - if (getProperty("FHT")!=null) { - properties.remove("FHT"); - if (getTitle().startsWith("FFT of ")) - setTitle(getTitle().substring(7)); - } - ContrastAdjuster.update(); - if (saveRoi!=null) setRoi(saveRoi); - repaintWindow(); - IJ.showStatus(""); - changes = false; - notifyListeners(UPDATED); - } - - void revertStack(FileInfo fi) { - String path = null; - String url2 = null; - if (url!=null && !url.equals("")) { - path = url; - url2 = url; - } else if (fi!=null && !((fi.directory==null||fi.directory.equals("")))) { - path = fi.getFilePath(); - } else if (fi!=null && fi.url!=null && !fi.url.equals("")) { - path = fi.url; - url2 = fi.url; - } else - return; - IJ.showStatus("Loading: " + path); - ImagePlus imp = IJ.openImage(path); - if (imp!=null) { - int n = imp.getStackSize(); - int c = imp.getNChannels(); - int z = imp.getNSlices(); - int t = imp.getNFrames(); - if (z==n || t==n || (c==getNChannels()&&z==getNSlices()&&t==getNFrames())) { - setCalibration(imp.getCalibration()); - setStack(imp.getStack(), c, z, t); - } else { - ImageWindow win = getWindow(); - Point loc = null; - if (win!=null) loc = win.getLocation(); - changes = false; - close(); - FileInfo fi2 = imp.getOriginalFileInfo(); - if (fi2!=null && (fi2.url==null || fi2.url.length()==0)) { - fi2.url = url2; - imp.setFileInfo(fi2); - } - ImageWindow.setNextLocation(loc); - imp.show(); - } - } - } - - /** Returns a FileInfo object containing information, including the - pixel array, needed to save this image. Use getOriginalFileInfo() - to get a copy of the FileInfo object used to open the image. - @see ij.io.FileInfo - @see #getOriginalFileInfo - @see #setFileInfo - */ - public FileInfo getFileInfo() { - FileInfo fi = new FileInfo(); - fi.width = width; - fi.height = height; - fi.nImages = getStackSize(); - if (compositeImage) - fi.nImages = getImageStackSize(); - fi.whiteIsZero = isInvertedLut(); - fi.intelByteOrder = false; - if (fi.nImages==1 && ip!=null) - fi.pixels = ip.getPixels(); - else if (stack!=null) - fi.pixels = stack.getImageArray(); - Calibration cal = getCalibration(); - if (cal.scaled()) { - fi.pixelWidth = cal.pixelWidth; - fi.pixelHeight = cal.pixelHeight; - fi.unit = cal.getUnit(); - } - if (fi.nImages>1) - fi.pixelDepth = cal.pixelDepth; - fi.frameInterval = cal.frameInterval; - if (cal.calibrated()) { - fi.calibrationFunction = cal.getFunction(); - fi.coefficients = cal.getCoefficients(); - fi.valueUnit = cal.getValueUnit(); - } else if (!Calibration.DEFAULT_VALUE_UNIT.equals(cal.getValueUnit())) - fi.valueUnit = cal.getValueUnit(); - - switch (imageType) { - case GRAY8: case COLOR_256: - LookUpTable lut = createLut(); - boolean customLut = !lut.isGrayscale() || (ip!=null&&!ip.isDefaultLut()); - if (imageType==COLOR_256 || customLut) - fi.fileType = FileInfo.COLOR8; - else - fi.fileType = FileInfo.GRAY8; - addLut(lut, fi); - break; - case GRAY16: - if (compositeImage && fi.nImages==3) { - if ("Red".equals(getStack().getSliceLabel(1))) - fi.fileType = fi.RGB48; - else - fi.fileType = fi.GRAY16_UNSIGNED; - } else - fi.fileType = fi.GRAY16_UNSIGNED; - if (!compositeImage) { - lut = createLut(); - if (!lut.isGrayscale() || (ip!=null&&!ip.isDefaultLut())) - addLut(lut, fi); - } - break; - case GRAY32: - fi.fileType = fi.GRAY32_FLOAT; - if (!compositeImage) { - lut = createLut(); - if (!lut.isGrayscale() || (ip!=null&&!ip.isDefaultLut())) - addLut(lut, fi); - } - break; - case COLOR_RGB: - fi.fileType = fi.RGB; - break; - default: - } - return fi; - } - - private void addLut(LookUpTable lut, FileInfo fi) { - fi.lutSize = lut.getMapSize(); - fi.reds = lut.getReds(); - fi.greens = lut.getGreens(); - fi.blues = lut.getBlues(); - } - - /** Returns the FileInfo object that was used to open this image. - Returns null for images created using the File/New command. - @see ij.io.FileInfo - @see #getFileInfo - */ - public FileInfo getOriginalFileInfo() { - if (fileInfo==null & url!=null) { - fileInfo = new FileInfo(); - fileInfo.width = width; - fileInfo.height = height; - fileInfo.url = url; - fileInfo.directory = null; - } - return fileInfo; - } - - /** Used by ImagePlus to monitor loading of images. */ - public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) { - imageUpdateY = y; - imageUpdateW = w; - if ((flags & ERROR) != 0) { - errorLoadingImage = true; - return false; - } - imageLoaded = (flags & (ALLBITS|FRAMEBITS|ABORT)) != 0; - return !imageLoaded; - } - - /** Sets the ImageProcessor, Roi, AWT Image and stack image - arrays to null. Does nothing if the image is locked. */ - public synchronized void flush() { - notifyListeners(CLOSED); - if (locked || ignoreFlush) return; - ip = null; - if (roi!=null) roi.setImage(null); - roi = null; - if (stack!=null && stack.viewers(-1)<=0) { - Object[] arrays = stack.getImageArray(); - if (arrays!=null) { - for (int i=0; istackSize) s2 = stackSize; - if (s1>s2) {s1=1; s2=stackSize;} - return new Duplicator().run(this, (int)s1, (int)s2); - } - } - - /** Returns an array of cropped images based on the provided - * list of rois. 'options' applies with stacks and can be "stack", - * "slice" or a range (e.g., "20-30"). - * @see #crop(ij.gui.Roi[]) - */ - public ImagePlus[] crop(Roi[] rois, String options) { - int nRois = rois.length; - ImagePlus[] cropImps = new ImagePlus[nRois]; - for (int i=0; i1) { - int position = cropRoi.getPosition(); - this.setSlice(position); // no effect if roi position is undefined (=0), ok - } - this.setRoi(cropRoi); - ImagePlus cropped = this.crop(options); - if (cropRoi.getType()!=Roi.RECTANGLE) { - Roi cropRoi2 = (Roi)cropRoi.clone(); - cropRoi2.setLocation(0,0); - cropped.setRoi(cropRoi2); - } - String name2 = IJ.pad(i+1,3)+"_"+this.getTitle(); - cropped.setTitle(name!=null?name:name2); - cropped.setOverlay(null); - cropImps[i] = cropped; - } - return cropImps; - } - - /** Multi-roi cropping with default "slice" option. */ - public ImagePlus[] crop(Roi[] rois) { - return this.crop(rois, "slice"); - } - - /** Saves the contents of the ROIs in this overlay as separate images, - * where 'directory' is the directory path and 'format' is "tif", "png" or "jpg". - * Set 'format' to "show" and the images will be displayed in a stack - * and not saved. - */ - public void cropAndSave(Roi[] rois, String directory, String format) { - ImagePlus[] images = crop(rois); - if (format==null) format = ""; - if (format.contains("show")) { - ImageStack stack = ImageStack.create(images); - new ImagePlus("CROPPED_"+getTitle(),stack).show(); - return; - } - String fileFormat = "tif"; - if (format.contains("png")) fileFormat = "png"; - if (format.contains("jpg")) fileFormat = "jpg"; - for (int i=0; icut is true. */ - public void copy(boolean cut) { - Roi roi = getRoi(); - if (roi!=null && !roi.isArea()) - roi = null; - if (cut && roi==null && !IJ.isMacro()) { - IJ.error("Edit>Cut", "This command requires an area selection"); - return; - } - boolean batchMode = Interpreter.isBatchMode(); - String msg = (cut)?"Cut":"Copy"; - if (!batchMode) IJ.showStatus(msg+ "ing..."); - ImageProcessor ip = getProcessor(); - ImageProcessor ip2; - ip2 = ip.crop(); - clipboard = new ImagePlus("Clipboard", ip2); - if (roi!=null) - clipboard.setRoi((Roi)roi.clone()); - if (cut) { - ip.snapshot(); - ip.setColor(Toolbar.getBackgroundColor()); - ip.fill(); - if (roi!=null && roi.getType()!=Roi.RECTANGLE) { - getMask(); - ip.reset(ip.getMask()); - } setColor(Toolbar.getForegroundColor()); - Undo.setup(Undo.FILTER, this); - updateAndDraw(); - } - int bytesPerPixel = 1; - switch (clipboard.getType()) { - case ImagePlus.GRAY16: bytesPerPixel = 2; break; - case ImagePlus.GRAY32: case ImagePlus.COLOR_RGB: bytesPerPixel = 4; - } - if (!batchMode) { - msg = (cut)?"Cut":"Copy"; - IJ.showStatus(msg + ": " + (clipboard.getWidth()*clipboard.getHeight()*bytesPerPixel)/1024 + "k"); - } - } - - /** Inserts the contents of the internal clipboard into this image. If there - is a selection the same size as the image on the clipboard, the image is inserted - into that selection, otherwise the selection is inserted into the center of the image.*/ - public void paste() { - if (clipboard==null) - return; - int cType = clipboard.getType(); - int iType = getType(); - int w = clipboard.getWidth(); - int h = clipboard.getHeight(); - Roi cRoi = clipboard.getRoi(); - Rectangle r = null; - Rectangle cr = null; - Roi roi = getRoi(); - if (roi!=null) - r = roi.getBounds(); - if (cRoi!=null) - cr = cRoi.getBounds(); - if (cr==null) - cr = new Rectangle(0, 0, w, h); - if (r==null || (cr.width!=r.width || cr.height!=r.height)) { - // Create a new roi centered on visible part of image, or centered on image if clipboard is >= image - ImageCanvas ic = win!=null?ic = win.getCanvas():null; - Rectangle srcRect = ic!=null?ic.getSrcRect():new Rectangle(0,0,width,height); - int xCenter = w>=width ? width/2 : srcRect.x + srcRect.width/2; - int yCenter = h>=height ? height/2 : srcRect.y + srcRect.height/2; - if (cRoi!=null && cRoi.getType()!=Roi.RECTANGLE) { - cRoi.setImage(this); - cRoi.setLocation(xCenter-w/2, yCenter-h/2); - setRoi(cRoi); - } else - setRoi(xCenter-w/2, yCenter-h/2, w, h); - roi = getRoi(); - } - if (IJ.isMacro()) { - //non-interactive paste - int pasteMode = Roi.getCurrentPasteMode(); - boolean nonRect = roi.getType()!=Roi.RECTANGLE; - ImageProcessor ip = getProcessor(); - if (nonRect) ip.snapshot(); - r = roi.getBounds(); - int xoffset = cr.x<0?-cr.x:0; - int yoffset = cr.y<0?-cr.y:0; - ip.copyBits(clipboard.getProcessor(), r.x+xoffset, r.y+yoffset, pasteMode); - if (nonRect) { - ImageProcessor mask = roi.getMask(); - ip.setMask(mask); - ip.setRoi(roi.getBounds()); - ip.reset(ip.getMask()); - } - updateAndDraw(); - } else if (roi!=null) { - roi.startPaste(clipboard); - Undo.setup(Undo.PASTE, this); - } - changes = true; - } - - /** Inserts the contents of the internal clipboard at the - specified location, without updating the display. */ - public void paste(int x, int y) { - paste(x, y, null); - } - - /** Copies the contents of the internal clipboard to the - * specified location using the specified transfer mode - * ("Copy", "Blend", "Average", "Difference", "Transparent", - * "Transparent2", "AND", "OR", "XOR", "Add", "Subtract", - * "Multiply", or "Divide"). The display is not updating. - */ - public void paste(int x, int y, String mode) { - if (clipboard==null) - return; - Roi roi = clipboard.getRoi(); - boolean nonRect = roi!=null && roi.getType()!=Roi.RECTANGLE; - if (nonRect) - ip.snapshot(); - if (mode==null) - ip.insert(clipboard.getProcessor(), x, y); - else { - int pasteMode = IJ.stringToPasteMode(mode); - ip.copyBits(clipboard.getProcessor(), x, y, pasteMode); - } - if (nonRect) { - ImageProcessor mask = roi.getMask(); - ip.setRoi(x, y, mask.getWidth(), mask.getHeight()); - ip.setMask(mask); - ip.reset(ip.getMask()); - } - } - - /** Returns the internal clipboard or null if the internal clipboard is empty. */ - public static ImagePlus getClipboard() { - return clipboard; - } - - /** Clears the internal clipboard. */ - public static void resetClipboard() { - clipboard = null; - } - - /** Copies the contents of the current selection, or the entire - image if there is no selection, to the system clipboard. */ - public void copyToSystem() { - Clipboard.copyToSystem(this); - } - - protected void notifyListeners(final int id) { - if (temporary) - return; - final ImagePlus imp = this; - EventQueue.invokeLater(new Runnable() { - public void run() { - for (int i=0; i=1 && imageType!=COLOR_RGB && (this instanceof CompositeImage); - } - - /** Returns the display mode (IJ.COMPOSITE, IJ.COLOR - or IJ.GRAYSCALE) if this is a CompositeImage, otherwise returns -1. */ - public int getCompositeMode() { - if (isComposite()) - return ((CompositeImage)this).getMode(); - else - return -1; - } - - /** Sets the display range of the current channel. With non-composite - * images it is identical to ip.setMinAndMax(min, max). - * Call updateAndDraw() to update the display. - */ - public void setDisplayRange(double min, double max) { - if (ip!=null) - ip.setMinAndMax(min, max); - } - - /** Returns the display range minimum of the current channel. - * @see ij.process.ImageProcessor#getMin - * @see #getLuts - */ - public double getDisplayRangeMin() { - return ip.getMin(); - } - - /** Returns the display range maximum of the current channel. - * @see ij.process.ImageProcessor#getMax - * @see #getLuts - */ - public double getDisplayRangeMax() { - return ip.getMax(); - } - - /** Sets the display range of specified channels in an RGB image, where 4=red, - 2=green, 1=blue, 6=red+green, etc. With non-RGB images, this method is - identical to setDisplayRange(min, max). This method is used by the - Image/Adjust/Color Balance tool . - */ - public void setDisplayRange(double min, double max, int channels) { - if (ip instanceof ColorProcessor) - ((ColorProcessor)ip).setMinAndMax(min, max, channels); - else - ip.setMinAndMax(min, max); - } - - public void resetDisplayRange() { - if (defaultMin!=0.0 || defaultMax!=0.0) - setDisplayRange(defaultMin, defaultMax); - else if (imageType==GRAY16 && default16bitDisplayRange>=8 && default16bitDisplayRange<=16 && !(getCalibration().isSigned16Bit())) - ip.setMinAndMax(0, Math.pow(2,default16bitDisplayRange)-1); - else - ip.resetMinAndMax(); - } - - public void setDefaultDisplayRange(double min, double max) { - this.defaultMin = min; - this.defaultMax = max; - } - - /** Uses the specified method to set the threshold levels - * of this image. Use AutoThresholder.getMethods() - * to get a list of the available methods. Add " dark" - * to the method name if the image has a dark background. - * Add " 16-bit" to use the full 16-bit histogram - * when calculating the threshold of 16-bit images. - * Add " stack" to use the histogram of the entire - * stack when calculating the threshold. - */ - public void setAutoThreshold(String method) { - IJ.setAutoThreshold(this, method); - } - - /** Returns 'true' if this image is thresholded. - * @see ij.process.ImageProcessor#isThreshold - */ - public boolean isThreshold() { - return ip!=null && ip.getMinThreshold()!=ImageProcessor.NO_THRESHOLD; - } - - /** Set the default 16-bit display range, where 'bitDepth' must be 0 (auto-scaling), - 8 (0-255), 10 (0-1023), 12 (0-4095, 14 (0-16383), 15 (0-32767) or 16 (0-65535). */ - public static void setDefault16bitRange(int bitDepth) { - if (!(bitDepth==8 || bitDepth==10 || bitDepth==12 || bitDepth==14 || bitDepth==15 || bitDepth==16)) - bitDepth = 0; - default16bitDisplayRange = bitDepth; - } - - /** Returns the default 16-bit display range, 0 (auto-scaling), 8, 10, 12, 14, 15 or 16. */ - public static int getDefault16bitRange() { - return default16bitDisplayRange; - } - - public void updatePosition(int c, int z, int t) { - position[0] = c; - position[1] = z; - position[2] = t; - } - - /** Returns a "flattened" version of this image, or stack slice, in RGB format. */ - public ImagePlus flatten() { - if (IJ.debugMode) IJ.log("flatten"); - ImagePlus impCopy = this; - if (getStackSize()>1) - impCopy = crop("whole-slice"); - ImagePlus imp2 = impCopy.createImagePlus(); - imp2.setOverlay(impCopy.getOverlay()); - imp2.setTitle(flattenTitle); - ImageCanvas ic2 = new ImageCanvas(imp2); - imp2.flatteningCanvas = ic2; - imp2.setRoi(getRoi()); - Overlay overlay2 = getOverlay(); - if (overlay2!=null && imp2.getRoi()!=null && !(imp2.getRoi() instanceof PointRoi)) { - imp2.deleteRoi(); - if (getWindow()!=null) IJ.wait(100); - } - setPointScale(imp2.getRoi(), overlay2); - ImageCanvas ic = getCanvas(); - if (ic!=null) - ic2.setShowAllList(ic.getShowAllList()); - BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D)bi.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - antialiasRendering?RenderingHints.VALUE_ANTIALIAS_ON:RenderingHints.VALUE_ANTIALIAS_OFF); - g.drawImage(getImage(), 0, 0, null); - ic2.paint(g); - imp2.flatteningCanvas = null; - ImagePlus imp3 = new ImagePlus("Flat_"+getTitle(), new ColorProcessor(bi)); - imp3.copyScale(this); - imp3.setProperty("Info", getProperty("Info")); - imp3.setProperties(getPropertiesAsArray()); - return imp3; - } - - /** Flattens all slices of this stack or HyperStack. - * @throws UnsupportedOperationException if this image - * does not have an overlay and the RoiManager overlay is null. - * Non-RGB stacks are converted to RGB. - * Copied from OverlayCommands and modified by Marcel Boeglin - * on 2014.01.08 to work with HyperStacks. - */ - public void flattenStack() { - if (IJ.debugMode) IJ.log("flattenStack"); - boolean composite = isComposite(); - if (getBitDepth()!=24) - new ImageConverter(this).convertToRGB(); - Overlay overlay1 = getOverlay(); - Overlay roiManagerOverlay = null; - boolean roiManagerShowAllMode = !Prefs.showAllSliceOnly; - ImageCanvas ic = getCanvas(); - if (ic!=null) - roiManagerOverlay = ic.getShowAllList(); - setOverlay(null); - if (roiManagerOverlay!=null) { - RoiManager rm = RoiManager.getInstance(); - if (rm!=null) - rm.runCommand("show none"); - } - Overlay overlay2 = overlay1!=null?overlay1:roiManagerOverlay; - if (composite && overlay2==null) - return; - if (overlay2==null || overlay2.size()==0) - throw new UnsupportedOperationException("A non-empty overlay is required"); - ImageStack stack2 = getStack(); - boolean showAll = overlay1!=null?false:roiManagerShowAllMode; - if (isHyperStack()) { - int Z = getNSlices(); - for (int z=1; z<=Z; z++) { - for (int t=1; t<=getNFrames(); t++) { - int image = z + (t-1)*Z; - flattenImage(stack2, image, overlay2.duplicate(), showAll, z, t); - } - } - } else { - for (int s=1; s<=stack2.getSize(); s++) { - flattenImage(stack2, s, overlay2.duplicate(), showAll); - } - } - setStack(stack2); - } - - /** Flattens Overlay 'overlay' on slice 'slice' of ImageStack 'stack'. - * Copied from OverlayCommands by Marcel Boeglin 2014.01.08. - */ - private void flattenImage(ImageStack stack, int slice, Overlay overlay, boolean showAll) { - ImageProcessor ips = stack.getProcessor(slice); - ImagePlus imp1 = new ImagePlus("temp", ips); - int w = imp1.getWidth(); - int h = imp1.getHeight(); - for (int i=0; i1) { - if (!IJ.isMacro()) rm.toFront(); - rm.runCommand("show all with labels"); - } - } - } - return hideOverlay; - } - - /** Enable/disable use of antialiasing by the flatten() method. */ - public void setAntialiasRendering(boolean antialiasRendering) { - this.antialiasRendering = antialiasRendering; - } - - /** Returns a shallow copy of this ImagePlus. */ - public synchronized Object clone() { - try { - ImagePlus copy = (ImagePlus)super.clone(); - copy.win = null; - return copy; - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** Plots a 256 bin histogram of this image and returns the PlotWindow. */ - public PlotWindow plotHistogram() { - return plotHistogram(256); - } - - /** Plots a histogram of this image using the specified - number of bins and returns the PlotWindow. */ - public PlotWindow plotHistogram(int bins) { - ImageStatistics stats = getStatistics(AREA+MEAN+MODE+MIN_MAX, bins); - Plot plot = new Plot("Hist_"+getTitle(), "Value", "Frequency"); - plot.setColor("black", "#999999"); - plot.setFont(new Font("SansSerif",Font.PLAIN,14)); - double[] y = stats.histogram(); - int n = y.length; - double[] x = new double[n]; - int bits = getBitDepth(); - boolean eightBit = bits==8 || bits==24; - double min = !eightBit?stats.min:0; - for (int i=0; i=size) { - Object[] tmp1 = new Object[size*2]; - System.arraycopy(stack, 0, tmp1, 0, size); - stack = tmp1; - String[] tmp2 = new String[size*2]; - System.arraycopy(label, 0, tmp2, 0, size); - label = tmp2; - } - stack[nSlices-1] = pixels; - this.label[nSlices-1] = sliceLabel; - if (this.bitDepth==0) - setBitDepth(pixels); - } - - private void setBitDepth(Object pixels) { - if (pixels==null) - return; - if (pixels instanceof byte[]) - this.bitDepth = 8; - else if (pixels instanceof short[]) - this.bitDepth = 16; - else if (pixels instanceof float[]) - this.bitDepth = 32; - else if (pixels instanceof int[]) - this.bitDepth = 24; - } - - /** - * @deprecated - * Short images are always unsigned. - */ - public void addUnsignedShortSlice(String sliceLabel, Object pixels) { - addSlice(sliceLabel, pixels); - } - - /** Adds the image in 'ip' to the end of the stack. */ - public void addSlice(ImageProcessor ip) { - addSlice(null, ip); - } - - /** Adds the image in 'ip' to the end of the stack, setting - the string 'sliceLabel' as the slice metadata. */ - public void addSlice(String sliceLabel, ImageProcessor ip) { - ip = convertType(ip); - if (ip.getWidth()!=this.width || ip.getHeight()!=this.height) { - if (this.width==0 && this.height==0) - init(ip.getWidth(), ip.getHeight()); - else { - ImageProcessor ip2 = ip.createProcessor(this.width,this.height); - ip2.insert(ip, 0, 0); - ip = ip2; - } - } - if (nSlices==0) { - cm = ip.getColorModel(); - min = ip.getMin(); - max = ip.getMax(); - } - addSlice(sliceLabel, ip.getPixels()); - } - - private void init(int width, int height) { - this.width = width; - this.height = height; - stack = new Object[INITIAL_SIZE]; - label = new String[INITIAL_SIZE]; - } - - private ImageProcessor convertType(ImageProcessor ip) { - int newBitDepth = ip.getBitDepth(); - if (this.bitDepth==0) - this.bitDepth = newBitDepth; - if (this.bitDepth!=newBitDepth) { - switch (this.bitDepth) { - case 8: ip=ip.convertToByte(true); break; - case 16: ip=ip.convertToShort(true); break; - case 24: ip=ip.convertToRGB(); break; - case 32: ip=ip.convertToFloat(); break; - } - } - return ip; - } - - /** Adds the image in 'ip' to the stack following slice 'n'. Adds - the slice to the beginning of the stack if 'n' is zero. */ - public void addSlice(String sliceLabel, ImageProcessor ip, int n) { - if (n<0 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - addSlice(sliceLabel, ip); - Object tempSlice = stack[nSlices-1]; - String tempLabel = label[nSlices-1]; - int first = n>0?n:1; - for (int i=nSlices-1; i>=first; i--) { - stack[i] = stack[i-1]; - label[i] = label[i-1]; - } - stack[n] = tempSlice; - label[n] = tempLabel; - } - - /** Deletes the specified slice, where {@literal 1<=n<=nslices}. */ - public void deleteSlice(int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - if (nSlices<1) - return; - for (int i=n; i0) - deleteSlice(nSlices); - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public void setRoi(Rectangle roi) { - this.roi = roi; - } - - public Rectangle getRoi() { - if (roi==null) - return new Rectangle(0, 0, width, height); - else - return(roi); - } - - /** Updates this stack so its attributes, such as min, max, - calibration table and color model, are the same as 'ip'. */ - public void update(ImageProcessor ip) { - if (ip!=null) { - min = ip.getMin(); - max = ip.getMax(); - cTable = ip.getCalibrationTable(); - cm = ip.getColorModel(); - } - } - - /** Returns the pixel array for the specified slice, where {@literal 1<=n<=nslices}. */ - public Object getPixels(int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - return stack[n-1]; - } - - /** Assigns a pixel array to the specified slice, where {@literal 1<=n<=nslices}. */ - public void setPixels(Object pixels, int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - stack[n-1] = pixels; - if (this.bitDepth==0) - setBitDepth(pixels); - } - - /** Returns the stack as an array of 1D pixel arrays. Note - that the size of the returned array may be greater than - the number of slices currently in the stack, with - unused elements set to null. */ - public Object[] getImageArray() { - return stack; - } - - /** Returns the number of slices in this stack. */ - public int size() { - return getSize(); - } - - public int getSize() { - return nSlices; - } - - /** Returns the slice labels as an array of Strings. Note - that the size of the returned array may be greater than - the number of slices currently in the stack. Returns null - if the stack is empty or the label of the first slice is null. */ - public String[] getSliceLabels() { - if (nSlices==0) - return null; - else - return label; - } - - /** Returns the label of the specified slice, where {@literal 1<=n<=nslices}. - Returns null if the slice does not have a label or 'n'; - is out of range. For DICOM and FITS stacks, labels may - contain header information. - */ - public String getSliceLabel(int n) { - if (n<1 || n>nSlices) - return null; - else - return label[n-1]; - } - - /** Returns a shortened version (up to the first 60 characters - * or first newline), with the extension removed, of the specified - * slice label, or null if the slice does not have a label. - */ - public String getShortSliceLabel(int n) { - return getShortSliceLabel(n, 60); - } - - /** Returns a shortened version (up to the first 'max' characters - * or first newline), with the extension removed, of the specified - * slice label, or null if the slice does not have a label. - */ - public String getShortSliceLabel(int n, int max) { - String shortLabel = getSliceLabel(n); - if (shortLabel==null) return null; - int newline = shortLabel.indexOf('\n'); - if (newline==0) return null; - if (newline>0) - shortLabel = shortLabel.substring(0, newline); - int len = shortLabel.length(); - if (len>4 && shortLabel.charAt(len-4)=='.' && !Character.isDigit(shortLabel.charAt(len-1))) - shortLabel = shortLabel.substring(0,len-4); - if (shortLabel.length()>max) - shortLabel = shortLabel.substring(0, max); - return shortLabel; - } - - /** Sets the label of the specified slice, where {@literal 1<=n<=nslices}. */ - public void setSliceLabel(String label, int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - this.label[n-1] = label; - } - - /** Returns an ImageProcessor for the specified slice, - * where {@literal 1<=n<=nslices}. - * Returns null if the stack is empty. - */ - public ImageProcessor getProcessor(int n) { - ImageProcessor ip; - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - if (nSlices==0) - return null; - if (stack[n-1]==null) - throw new IllegalArgumentException("Pixel array is null"); - if (stack[n-1] instanceof byte[]) - ip = new ByteProcessor(width, height, null, cm); - else if (stack[n-1] instanceof short[]) - ip = new ShortProcessor(width, height, null, cm); - else if (stack[n-1] instanceof int[]) { - if (signedInt) - ip = new IntProcessor(width, height); - else - ip = new ColorProcessor(width, height, null); - } else if (stack[n-1] instanceof float[]) - ip = new FloatProcessor(width, height, null, cm); - else - throw new IllegalArgumentException("Unknown stack type"); - ip.setPixels(stack[n-1]); - if (min!=Double.MAX_VALUE && ip!=null && !(ip instanceof ColorProcessor)) - ip.setMinAndMax(min, max); - if (cTable!=null) - ip.setCalibrationTable(cTable); - ip.setSliceNumber(n); - return ip; - } - - /** Assigns the pixel array of an ImageProcessor to the specified slice, - * where {@literal 1<=n<=nslices}. - */ - public void setProcessor(ImageProcessor ip, int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - ip = convertType(ip); - if (ip.getWidth()!=width || ip.getHeight()!=height) - throw new IllegalArgumentException("Wrong dimensions for this stack"); - stack[n-1] = ip.getPixels(); - } - - /** Assigns a new color model to this stack. */ - public void setColorModel(ColorModel cm) { - this.cm = cm; - } - - /** Returns this stack's color model. May return null. */ - public ColorModel getColorModel() { - return cm; - } - - /** Returns true if this is a 3-slice, 8-bit RGB stack. */ - public boolean isRGB() { - return getSize()==3 && (stack[0] instanceof byte[]) && getSliceLabel(1)!=null && getSliceLabel(1).equals("Red"); - } - - /** Returns true if this is a 3-slice HSB stack. */ - public boolean isHSB() { - return getSize()==3 && bitDepth==8 && getSliceLabel(1)!=null && getSliceLabel(1).equals("Hue"); - } - - /** Returns true if this is a 3-slice 32-bit HSB stack. */ - public boolean isHSB32() { - return getSize()==3 && bitDepth==32 && getSliceLabel(1)!=null && getSliceLabel(1).equals("Hue"); - } - - /** Returns true if this is a Lab stack. */ - public boolean isLab() { - return getSize()==3 && getSliceLabel(1)!=null && getSliceLabel(1).equals("L*"); - } - - /** Returns true if this is a virtual (disk resident) stack. - This method is overridden by the VirtualStack subclass. */ - public boolean isVirtual() { - return false; - } - - /** Frees memory by deleting a few slices from the end of the stack. */ - public void trim() { - int n = (int)Math.round(Math.log(nSlices)+1.0); - for (int i=0; i=0 && x=0 && y=0 && z=0 && x=0 && y=0 && z255.0) - value = 255.0; - else if (value<0.0) - value = 0.0; - bytes[y*width+x] = (byte)(value+0.5); - break; - case 16: - short[] shorts = (short[])stack[z]; - if (value>65535.0) - value = 65535.0; - else if (value<0.0) - value = 0.0; - shorts[y*width+x] = (short)(value+0.5); - break; - case 32: - float[] floats = (float[])stack[z]; - floats[y*width+x] = (float)value; - break; - case 24: - int[] ints = (int[])stack[z]; - ints[y*width+x] = (int)value; - break; - } - } - } - - public float[] getVoxels(int x0, int y0, int z0, int w, int h, int d, float[] voxels) { - boolean inBounds = x0>=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - voxels = new float[w*h*d]; - int i = 0; - int offset; - for (int z=z0; z=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - voxels = new float[w*h*d]; - int i = 0; - for (int z=z0; z>16; break; - case 1: value=(value&0xff00)>>8; break; - case 2: value=value&0xff;; break; - } - voxels[i++] = (float)value; - } - } - } - return voxels; - } - - /** Experimental */ - public void setVoxels(int x0, int y0, int z0, int w, int h, int d, float[] voxels) { - boolean inBounds = x0>=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - ; - int i = 0; - float value; - for (int z=z0; z255f) - value = 255f; - else if (value<0f) - value = 0f; - bytes[y*width+x] = (byte)(value+0.5f); - } - break; - case 16: - short[] shorts = (short[])stack[z]; - for (int x=x0; x65535f) - value = 65535f; - else if (value<0f) - value = 0f; - shorts[y*width+x] = (short)(value+0.5f); - } - break; - case 32: - float[] floats = (float[])stack[z]; - for (int x=x0; x=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - ; - int i = 0; - for (int z=z0; z0) - setBitDepth(stack[0]); - return this.bitDepth; - } - - /** Sets the bit depth (8=byte, 16=short, 24=RGB, 32=float). */ - public void setBitDepth(int depth) { - if (size()==0 && (depth==8||depth==16||depth==24||depth==32)) - this.bitDepth = depth; - } - - /** Creates a new ImageStack. - * @param width width in pixels - * @param height height in pixels - * @param depth number of images - * @param bitdepth 8, 16, 32 (float) or 24 (RGB) - */ - public static ImageStack create(int width, int height, int depth, int bitdepth) { - ImageStack stack = IJ.createImage("", width, height, depth, bitdepth).getStack(); - if (bitdepth==16 || bitdepth==32) { - stack.min = Double.MAX_VALUE; - stack.max = 0.0; - } - return stack; - } - - /** Creates an ImageStack from an ImagePlus array. */ - public static ImageStack create(ImagePlus[] images) { - int w = 0; - int h = 0; - for (int i=0; iw) w=images[i].getWidth(); - if (images[i].getHeight()>h) h=images[i].getHeight(); - } - ImageStack stack = new ImageStack(w, h); - stack.init(w, h); - for (int i=0; ithis.width||y+height>this.height||z+depth>size()) - throw new IllegalArgumentException("Argument out of range"); - ImageStack stack2 = new ImageStack(width, height, getColorModel()); - for (int i=z; itrue if this is a 256 entry grayscale LUT. - @see ij.process.ImageProcessor#isColorLut - */ - public boolean isGrayscale() { - boolean isGray = true; - if (mapSize < 256) - return false; - for (int i=0; i 1) - return fs.saveAsTiffStack(path); - else - return fs.saveAsTiff(path); - } - - public static String getName(String path) { - int i = path.lastIndexOf('/'); - if (i == -1) - i = path.lastIndexOf('\\'); - if (i > 0) - return path.substring(i + 1); - else - return path; - } - - public static String getDir(String path) { - int i = path.lastIndexOf('/'); - if (i == -1) - i = path.lastIndexOf('\\'); - if (i > 0) - return path.substring(0, i + 1); - else - return ""; - } - - /** Aborts the currently running macro or any plugin using IJ.run(). */ - public static void abort() { - // IJ.log("Abort: "+Thread.currentThread().getName()); - abort = true; - if (Thread.currentThread().getName().endsWith("Macro$")) { - table.remove(Thread.currentThread()); - /* Changed for Bio7 to get a message instead of the stack trace! */ - try { - throw new RuntimeException(MACRO_CANCELED); - } catch (Exception e) { - System.out.println(MACRO_CANCELED); - } - - } - } - - /** - * If a command started using run(name, options) is running, and the current - * thread is the same thread, returns the options string, otherwise, returns - * null. - * - * @see ij.gui.GenericDialog - * @see ij.io.OpenDialog - */ - public static String getOptions() { - String threadName = Thread.currentThread().getName(); - - // IJ.log("getOptions: "+threadName+" "+Thread.currentThread().hashCode()); //ts - /*Changed for Bio7. Added Eclipse 'Worker' thread name!*/ - if (threadName.startsWith("Run$_") || threadName.contains("Worker")||threadName.startsWith("RMI TCP")) { - Object options = table.get(Thread.currentThread()); - return options == null ? null : options + " "; - } else - return null; - } - - /** Define a set of Macro options for the current Thread. */ - public static void setOptions(String options) { - // IJ.log("setOptions: "+Thread.currentThread().getName()+" - // "+Thread.currentThread().hashCode()+" "+options); //ts - if (options == null || options.equals("")) - table.remove(Thread.currentThread()); - else - table.put(Thread.currentThread(), options); - } - - /** Define a set of Macro options for a Thread. */ - public static void setOptions(Thread thread, String options) { - if (null == thread) - throw new RuntimeException("Need a non-null thread instance"); - if (null == options) - table.remove(thread); - else - table.put(thread, options); - } - - public static String getValue(String options, String key, String defaultValue) { - key = trimKey(key); - if (!options.endsWith(" ")) - options = options + " "; - key += '='; - int index = -1; - do { // Require that key not be preceded by a letter - index = options.indexOf(key, ++index); - if (index < 0) - return defaultValue; - } while (index != 0 && Character.isLetter(options.charAt(index - 1))); - options = options.substring(index + key.length(), options.length()); - if (options.charAt(0) == '\'') { - index = options.indexOf("'", 1); - if (index < 0) - return defaultValue; - else - return options.substring(1, index); - } else if (options.charAt(0) == '[') { - int count = 1; - index = -1; - for (int i = 1; i < options.length(); i++) { - char ch = options.charAt(i); - if (ch == '[') - count++; - else if (ch == ']') - count--; - if (count == 0) { - index = i; - break; - } - } - if (index < 0) - return defaultValue; - else - return options.substring(1, index); - } else { - index = options.indexOf(" "); - if (index < 0) - return defaultValue; - else - return options.substring(0, index); - } - } - - public static String trimKey(String key) { - if (key==null) - return key; - int index = key.indexOf(" "); - if (index > -1) - key = key.substring(0, index); - index = key.indexOf(":"); - if (index > -1) - key = key.substring(0, index); - key = key.toLowerCase(Locale.US); - return key; - } - - /** - * Evaluates 'code' and returns the output, or any error, as a String (e.g., - * Macro.eval("2+2") returns "4"). - */ - public static String eval(String code) { - return new Interpreter().eval(code); - } - -} diff --git a/com.eco.bio7.image/src/ij/Menus.java b/com.eco.bio7.image/src/ij/Menus.java deleted file mode 100644 index 6546f62fc..000000000 --- a/com.eco.bio7.image/src/ij/Menus.java +++ /dev/null @@ -1,1946 +0,0 @@ -package ij; - -import ij.process.*; -import ij.util.*; -import ij.gui.ImageWindow; -import ij.plugin.MacroInstaller; -import ij.gui.Toolbar; -import ij.macro.Interpreter; -import java.awt.*; -import java.awt.image.*; -import java.awt.event.*; -import java.util.*; -import java.io.*; -import java.net.URL; -import java.applet.Applet; -import java.awt.event.*; -import java.util.zip.*; - -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Platform; -import org.eclipse.jface.action.IContributionItem; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IViewSite; -import org.osgi.framework.Bundle; - -import com.eco.bio7.ImageJPluginActions.ImageJExtensionAction; -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.Util; - -/** - * This class installs and updates ImageJ's menus. Note that menu labels, even - * in submenus, must be unique. This is because ImageJ uses a single hash table - * for all menu labels. If you look closely, you will see that - * File->Import->Text Image... and File->Save As->Text Image... do not use the - * same label. One of the labels has an extra space. - * - * @see ImageJ - */ - -public class Menus { - - public static final char PLUGINS_MENU = 'p'; - public static final char IMPORT_MENU = 'i'; - public static final char SAVE_AS_MENU = 's'; - public static final char SHORTCUTS_MENU = 'h'; // 'h'=hotkey - public static final char ABOUT_MENU = 'a'; - public static final char FILTERS_MENU = 'f'; - public static final char TOOLS_MENU = 't'; - public static final char UTILITIES_MENU = 'u'; - - public static final int WINDOW_MENU_ITEMS = 6; // fixed items at top of - // Window menu - public static final int NORMAL_RETURN = 0; - public static final int COMMAND_IN_USE = -1; - public static final int INVALID_SHORTCUT = -2; - public static final int SHORTCUT_IN_USE = -3; - public static final int NOT_INSTALLED = -4; - public static final int COMMAND_NOT_FOUND = -5; - - public static final int MAX_OPEN_RECENT_ITEMS = 15; - - private static Menus instance; - private static MenuBar mbar; - private static CheckboxMenuItem gray8Item, gray16Item, gray32Item, color256Item, colorRGBItem, RGBStackItem, - HSBStackItem, LabStackItem, HSB32Item; - private static PopupMenu popup; - - private static ImageJ ij; - private static Applet applet; - private Hashtable demoImagesTable = new Hashtable(); - private static String ImageJPath, pluginsPath, macrosPath; - private static Properties menus; - private static Properties menuSeparators; - private static Menu pluginsMenu, saveAsMenu, shortcutsMenu, utilitiesMenu, macrosMenu; - static Menu window, openRecentMenu; - private static Hashtable pluginsTable; - - private static int nPlugins, nMacros; - private static Hashtable shortcuts; - private static Hashtable macroShortcuts; - private static Vector pluginsPrefs; // commands saved in IJ_Prefs - static int windowMenuItems2; // non-image windows listed in Window menu + - // separator - private String error; - private String jarError; - private String pluginError; - private boolean isJarErrorHeading; - private static boolean installingJars, duplicateCommand; - private static Vector jarFiles; // JAR files in plugins folder with "_" in - // their name - private Map menuEntry2jarFile = new HashMap(); - private static Vector macroFiles; // Macros and scripts in the plugins - // folder - private static int userPluginsIndex; // First user plugin or submenu in - // Plugins menu - private static boolean addSorted; - private static int defaultFontSize = IJ.isWindows() ? 15 : 0; - private static int fontSize; - private static double scale = 1.0; - private static Font cachedFont;//Not used since we are using SWT menus! - - static boolean jnlp; // true when using Java WebStart - public static int setMenuBarCount; - /* Changed for Bio7! */ - public static Vector bio7JarAllCommand; - - Menus(ImageJ ijInstance, Applet appletInstance) { - ij = ijInstance; - String title = ij != null ? ij.getTitle() : null; - applet = appletInstance; - instance = this; - fontSize = Prefs.getInt(Prefs.MENU_SIZE, defaultFontSize); - - } - - String addMenuBar() { - - scale = Prefs.getGuiScale(); - //if ((scale >= 1.5 && scale < 2.0) || (scale >= 2.5 && scale < 3.0)) - // scale = (int) Math.round(scale); - nPlugins = nMacros = userPluginsIndex = 0; - addSorted = installingJars = duplicateCommand = false; - error = null; - mbar = null; - menus = new Properties(); - pluginsTable = new Hashtable(); - - /* Changed for Bio7! */ - bio7JarAllCommand = new Vector(); - - shortcuts = new Hashtable(); - pluginsPrefs = new Vector(); - macroShortcuts = null; - setupPluginsAndMacrosPaths(); - Menu file = getMenu("File"); - Menu newMenu = getMenu("File>New", true); - addPlugInItem(file, "Open...", "ij.plugin.Commands(\"open\")", KeyEvent.VK_O, false); - addPlugInItem(file, "Open Next", "ij.plugin.NextImageOpener", KeyEvent.VK_O, true); - Menu openSamples = getMenu("File>Open Samples", true); - openSamples.addSeparator(); - addPlugInItem(openSamples, "Cache Sample Images ", "ij.plugin.URLOpener(\"cache\")", 0, false); - addOpenRecentSubMenu(file); - Menu importMenu = getMenu("File>Import", true); - Menu showFolderMenu = new Menu("Show Folder"); - file.add(showFolderMenu); - addPlugInItem(showFolderMenu, "Image", "ij.plugin.SimpleCommands(\"showdirImage\")", 0, false); - addPlugInItem(showFolderMenu, "Plugins", "ij.plugin.SimpleCommands(\"showdirPlugins\")", 0, false); - addPlugInItem(showFolderMenu, "Macros", "ij.plugin.SimpleCommands(\"showdirMacros\")", 0, false); - addPlugInItem(showFolderMenu, "LUTs", "ij.plugin.SimpleCommands(\"showdirLuts\")", 0, false); - addPlugInItem(showFolderMenu, "ImageJ", "ij.plugin.SimpleCommands(\"showdirImageJ\")", 0, false); - addPlugInItem(showFolderMenu, "temp", "ij.plugin.SimpleCommands(\"showdirTemp\")", 0, false); - addPlugInItem(showFolderMenu, "Home", "ij.plugin.SimpleCommands(\"showdirHome\")", 0, false); - file.addSeparator(); - addPlugInItem(file, "Close", "ij.plugin.Commands(\"close\")", KeyEvent.VK_W, false); - addPlugInItem(file, "Close All", "ij.plugin.Commands(\"close-all\")", KeyEvent.VK_W, true); - addPlugInItem(file, "Save", "ij.plugin.Commands(\"save\")", KeyEvent.VK_S, false); - saveAsMenu = getMenu("File>Save As", true); - addPlugInItem(file, "Revert", "ij.plugin.Commands(\"revert\")", KeyEvent.VK_R, true); - file.addSeparator(); - addPlugInItem(file, "Page Setup...", "ij.plugin.filter.Printer(\"setup\")", 0, false); - addPlugInItem(file, "Print...", "ij.plugin.filter.Printer(\"print\")", KeyEvent.VK_P, false); - - Menu edit = getMenu("Edit"); - addPlugInItem(edit, "Undo", "ij.plugin.Commands(\"undo\")", KeyEvent.VK_Z, false); - edit.addSeparator(); - addPlugInItem(edit, "Cut", "ij.plugin.Clipboard(\"cut\")", KeyEvent.VK_X, false); - addPlugInItem(edit, "Copy", "ij.plugin.Clipboard(\"copy\")", KeyEvent.VK_C, false); - addPlugInItem(edit, "Copy to System", "ij.plugin.Clipboard(\"scopy\")", 0, false); - addPlugInItem(edit, "Paste", "ij.plugin.Clipboard(\"paste\")", KeyEvent.VK_V, false); - addPlugInItem(edit, "Paste Control...", "ij.plugin.frame.PasteController", 0, false); - edit.addSeparator(); - addPlugInItem(edit, "Clear", "ij.plugin.filter.Filler(\"clear\")", 0, false); - addPlugInItem(edit, "Clear Outside", "ij.plugin.filter.Filler(\"outside\")", 0, false); - addPlugInItem(edit, "Fill", "ij.plugin.filter.Filler(\"fill\")", KeyEvent.VK_F, false); - addPlugInItem(edit, "Draw", "ij.plugin.filter.Filler(\"draw\")", KeyEvent.VK_D, false); - addPlugInItem(edit, "Invert", "ij.plugin.filter.Filters(\"invert\")", KeyEvent.VK_I, true); - edit.addSeparator(); - getMenu("Edit>Selection", true); - Menu optionsMenu = getMenu("Edit>Options", true); - - Menu image = getMenu("Image"); - Menu imageType = getMenu("Image>Type"); - gray8Item = addCheckboxItem(imageType, "8-bit", "ij.plugin.Converter(\"8-bit\")"); - gray16Item = addCheckboxItem(imageType, "16-bit", "ij.plugin.Converter(\"16-bit\")"); - gray32Item = addCheckboxItem(imageType, "32-bit", "ij.plugin.Converter(\"32-bit\")"); - color256Item = addCheckboxItem(imageType, "8-bit Color", "ij.plugin.Converter(\"8-bit Color\")"); - colorRGBItem = addCheckboxItem(imageType, "RGB Color", "ij.plugin.Converter(\"RGB Color\")"); - imageType.add(new MenuItem("-")); - RGBStackItem = addCheckboxItem(imageType, "RGB Stack", "ij.plugin.Converter(\"RGB Stack\")"); - HSBStackItem = addCheckboxItem(imageType, "HSB Stack", "ij.plugin.Converter(\"HSB Stack\")"); - HSB32Item = addCheckboxItem(imageType, "HSB (32-bit)", "ij.plugin.Converter(\"HSB (32-bit)\")"); - LabStackItem = addCheckboxItem(imageType, "Lab Stack", "ij.plugin.Converter(\"Lab Stack\")"); - image.add(imageType); - - image.addSeparator(); - getMenu("Image>Adjust", true); - addPlugInItem(image, "Show Info...", "ij.plugin.ImageInfo", KeyEvent.VK_I, false); - addPlugInItem(image, "Properties...", "ij.plugin.filter.ImageProperties", KeyEvent.VK_P, true); - getMenu("Image>Color", true); - getMenu("Image>Stacks", true); - getMenu("Image>Stacks>Animation_", true); - getMenu("Image>Stacks>Tools_", true); - Menu hyperstacksMenu = getMenu("Image>Hyperstacks", true); - image.addSeparator(); - addPlugInItem(image, "Crop", "ij.plugin.Resizer(\"crop\")", KeyEvent.VK_X, true); - addPlugInItem(image, "Duplicate...", "ij.plugin.Duplicator", KeyEvent.VK_D, true); - addPlugInItem(image, "Rename...", "ij.plugin.SimpleCommands(\"rename\")", 0, false); - addPlugInItem(image, "Scale...", "ij.plugin.Scaler", KeyEvent.VK_E, false); - getMenu("Image>Transform", true); - getMenu("Image>Zoom", true); - getMenu("Image>Overlay", true); - image.addSeparator(); - getMenu("Image>Lookup Tables", true); - - Menu process = getMenu("Process"); - addPlugInItem(process, "Smooth", "ij.plugin.filter.Filters(\"smooth\")", KeyEvent.VK_S, true); - addPlugInItem(process, "Sharpen", "ij.plugin.filter.Filters(\"sharpen\")", 0, false); - addPlugInItem(process, "Find Edges", "ij.plugin.filter.Filters(\"edge\")", 0, false); - addPlugInItem(process, "Find Maxima...", "ij.plugin.filter.MaximumFinder", 0, false); - addPlugInItem(process, "Enhance Contrast...", "ij.plugin.ContrastEnhancer", 0, false); - getMenu("Process>Noise", true); - getMenu("Process>Shadows", true); - getMenu("Process>Binary", true); - getMenu("Process>Math", true); - getMenu("Process>FFT", true); - Menu filtersMenu = getMenu("Process>Filters", true); - process.addSeparator(); - getMenu("Process>Batch", true); - addPlugInItem(process, "Image Calculator...", "ij.plugin.ImageCalculator", 0, false); - addPlugInItem(process, "Subtract Background...", "ij.plugin.filter.BackgroundSubtracter", 0, false); - addItem(process, "Repeat Command", KeyEvent.VK_R, false); - - Menu analyzeMenu = getMenu("Analyze"); - addPlugInItem(analyzeMenu, "Measure", "ij.plugin.filter.Analyzer", KeyEvent.VK_M, false); - addPlugInItem(analyzeMenu, "Analyze Particles...", "ij.plugin.filter.ParticleAnalyzer", 0, false); - addPlugInItem(analyzeMenu, "Summarize", "ij.plugin.filter.Analyzer(\"sum\")", 0, false); - addPlugInItem(analyzeMenu, "Distribution...", "ij.plugin.Distribution", 0, false); - addPlugInItem(analyzeMenu, "Label", "ij.plugin.filter.Filler(\"label\")", 0, false); - addPlugInItem(analyzeMenu, "Clear Results", "ij.plugin.filter.Analyzer(\"clear\")", 0, false); - addPlugInItem(analyzeMenu, "Set Measurements...", "ij.plugin.filter.Analyzer(\"set\")", 0, false); - analyzeMenu.addSeparator(); - addPlugInItem(analyzeMenu, "Set Scale...", "ij.plugin.filter.ScaleDialog", 0, false); - addPlugInItem(analyzeMenu, "Calibrate...", "ij.plugin.filter.Calibrator", 0, false); - if (IJ.isMacOSX()) { - addPlugInItem(analyzeMenu, "Histogram", "ij.plugin.Histogram", 0, false); - shortcuts.put(Integer.valueOf(KeyEvent.VK_H), "Histogram"); - } else - addPlugInItem(analyzeMenu, "Histogram", "ij.plugin.Histogram", KeyEvent.VK_H, false); - addPlugInItem(analyzeMenu, "Plot Profile", "ij.plugin.Profiler(\"plot\")", KeyEvent.VK_K, false); - addPlugInItem(analyzeMenu, "Surface Plot...", "ij.plugin.SurfacePlotter", 0, false); - getMenu("Analyze>Gels", true); - Menu toolsMenu = getMenu("Analyze>Tools", true); - - // the plugins will be added later, after a separator - addPluginsMenu(); - - Menu window = getMenu("Window"); - /*Changed for Bio7. We have a tabbed structure!*/ - addPlugInItem(window, "Show All", "ij.plugin.WindowOrganizer(\"show\")", KeyEvent.VK_CLOSE_BRACKET, false); - String key = IJ.isWindows() ? "enter" : "return"; - addPlugInItem(window, "Main Window [" + key + "]", "ij.plugin.WindowOrganizer(\"imagej\")", 0, false); - addPlugInItem(window, "Put Behind [tab]", "ij.plugin.Commands(\"tab\")", 0, false); - addPlugInItem(window, "Cascade", "ij.plugin.WindowOrganizer(\"cascade\")", 0, false); - addPlugInItem(window, "Tile", "ij.plugin.WindowOrganizer(\"tile\")", 0, false); - window.addSeparator(); - - Menu help = getMenu("Help"); - addPlugInItem(help, "ImageJ Website...", "ij.plugin.BrowserLauncher", 0, false); - help.addSeparator(); - addPlugInItem(help, "Dev. Resources...", "ij.plugin.BrowserLauncher(\"" + IJ.URL2 + "/developer/index.html\")", - 0, false); - addPlugInItem(help, "Macro Functions...", "ij.plugin.BrowserLauncher(\"https://wsr.imagej.net/developer/macro/functions.html\")", 0, false); - Menu examplesMenu = getExamplesMenu(ij); - addPlugInItem(examplesMenu, "Open as Panel", "ij.plugin.SimpleCommands(\"opencp\")", 0, false); - help.add(examplesMenu); - help.addSeparator(); - /* Changed for Bio7! Left out ImageJ update! */ - // addPlugInItem(help, "Update ImageJ...", "ij.plugin.ImageJ_Updater", - // 0, false); - addPlugInItem(help, "Release Notes...", "ij.plugin.BrowserLauncher(\"https://wsr.imagej.net/notes.html\")", 0, false); - addPlugInItem(help, "Refresh Menus", "ij.plugin.ImageJ_Updater(\"menus\")", 0, false); - help.addSeparator(); - Menu aboutMenu = getMenu("Help>About Plugins", true); - addPlugInItem(help, "About ImageJ...", "ij.plugin.AboutBox", 0, false); - - if (applet == null) { - menuSeparators = new Properties(); - installPlugins(); - } - - // make sure "Quit" is the last item in the File menu - file.addSeparator(); - addPlugInItem(file, "Quit", "ij.plugin.Commands(\"quit\")", 0, false); - - // System.out.println("MenuBar.setFont: "+fontSize+" "+scale+" "+getFont()); - if (fontSize != 0 || scale > 1.0) - mbar.setFont(getFont()); - if (ij != null) { - ij.setMenuBar(mbar); - Menus.setMenuBarCount++; - } - // Add deleted sample images to commands table - pluginsTable.put("Lena (68K)", "ij.plugin.URLOpener(\"lena-std.tif\")"); - pluginsTable.put("Bridge (174K)", "ij.plugin.URLOpener(\"bridge.gif\")"); - - if (pluginError != null) - error = error != null ? error += "\n" + pluginError : pluginError; - if (jarError != null) - error = error != null ? error += "\n" + jarError : jarError; - return error; - } - - public static Menu getExamplesMenu(ActionListener listener) { - Menu menu = new Menu("Examples"); - Menu submenu = new Menu("Plots"); - - addExample(submenu, "Example Plot", "Example_Plot_.ijm"); - addExample(submenu, "Semi-log Plot", "Semi-log_Plot_.ijm"); - addExample(submenu, "Arrow Plot", "Arrow_Plot_.ijm"); - addExample(submenu, "Damped Wave Plot", "Damped_Wave_Plot_.ijm"); - addExample(submenu, "Dynamic Plot", "Dynamic_Plot_.ijm"); - addExample(submenu, "Dynamic Plot 2D", "Dynamic_Plot_2D_.ijm"); - addExample(submenu, "Custom Plot Symbols", "Custom_Plot_Symbols_.ijm"); - addExample(submenu, "Histograms", "Histograms_.ijm"); - addExample(submenu, "Bar Charts", "Bar_Charts_.ijm"); - addExample(submenu, "Shapes", "Plot_Shapes_.ijm"); - addExample(submenu, "Plot Styles", "Plot_Styles_.ijm"); - addExample(submenu, "Random Data", "Random_Data_.ijm"); - addExample(submenu, "Plot Results", "Plot_Results_.ijm"); - addExample(submenu, "Plot With Spectrum", "Plot_With_Spectrum_.ijm"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Tools"); - addExample(submenu, "Annular Selection", "Annular_Selection_Tool.ijm"); - addExample(submenu, "Big Cursor", "Big_Cursor_Tool.ijm"); - addExample(submenu, "Circle Tool", "Circle_Tool.ijm"); - addExample(submenu, "Point Picker", "Point_Picker_Tool.ijm"); - addExample(submenu, "Star Tool", "Star_Tool.ijm"); - addExample(submenu, "Animated Icon Tool", "Animated_Icon_Tool.ijm"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Macro"); - addExample(submenu, "Sphere", "Sphere.ijm"); - addExample(submenu, "Dialog Box", "Dialog_Box.ijm"); - addExample(submenu, "Process Folder", "Batch_Process_Folder.ijm"); - addExample(submenu, "OpenDialog Demo", "OpenDialog_Demo.ijm"); - addExample(submenu, "Save All Images", "Save_All_Images.ijm"); - addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.ijm"); - addExample(submenu, "Non-numeric Table", "Non-numeric_Table.ijm"); - addExample(submenu, "Overlay", "Overlay.ijm"); - addExample(submenu, "Stack Overlay", "Stack_Overlay.ijm"); - addExample(submenu, "Array Functions", "Array_Functions.ijm"); - addExample(submenu, "Dual Progress Bars", "Dual_Progress_Bars.ijm"); - addExample(submenu, "Grab Viridis Colormap", "Grab_Viridis_Colormap.ijm"); - addExample(submenu, "Custom Measurement", "Custom_Measurement.ijm"); - addExample(submenu, "Synthetic Images", "Synthetic_Images.ijm"); - addExample(submenu, "Spiral Rotation", "Spiral_Rotation.ijm"); - addExample(submenu, "Curve Fitting", "Curve_Fitting.ijm"); - addExample(submenu, "Colors of 2021", "Colors_of_2021.ijm"); - addExample(submenu, "Turtle Graphics", "Turtle_Graphics.ijm"); - addExample(submenu, "Easter Eggs", "Easter_Eggs.ijm"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("JavaScript"); - addExample(submenu, "Sphere", "Sphere.js"); - addExample(submenu, "Plasma Cloud", "Plasma_Cloud.js"); - addExample(submenu, "Cloud Debugger", "Cloud_Debugger.js"); - addExample(submenu, "Synthetic Images", "Synthetic_Images.js"); - addExample(submenu, "Points", "Points.js"); - addExample(submenu, "Spiral Rotation", "Spiral_Rotation.js"); - addExample(submenu, "Example Plot", "Example_Plot.js"); - addExample(submenu, "Semi-log Plot", "Semi-log_Plot.js"); - addExample(submenu, "Arrow Plot", "Arrow_Plot.js"); - addExample(submenu, "Dynamic Plot", "Dynamic_Plot.js"); - addExample(submenu, "Plot Styles", "Plot_Styles.js"); - addExample(submenu, "Plot Random Data", "Plot_Random_Data.js"); - addExample(submenu, "Histogram Plots", "Histogram_Plots.js"); - addExample(submenu, "JPEG Quality Plot", "JPEG_Quality_Plot.js"); - addExample(submenu, "Process Folder", "Batch_Process_Folder.js"); - addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.js"); - addExample(submenu, "Non-numeric Table", "Non-numeric_Table.js"); - addExample(submenu, "Overlay", "Overlay.js"); - addExample(submenu, "Stack Overlay", "Stack_Overlay.js"); - addExample(submenu, "Dual Progress Bars", "Dual_Progress_Bars.js"); - addExample(submenu, "Gamma Adjuster", "Gamma_Adjuster.js"); - addExample(submenu, "Custom Measurement", "Custom_Measurement.js"); - addExample(submenu, "Terabyte VirtualStack", "Terabyte_VirtualStack.js"); - addExample(submenu, "Event Listener", "Event_Listener.js"); - addExample(submenu, "FFT Filter", "FFT_Filter.js"); - addExample(submenu, "Curve Fitting", "Curve_Fitting.js"); - addExample(submenu, "Overlay Text", "Overlay_Text.js"); - addExample(submenu, "Crop Multiple Rois", "Crop_Multiple_Rois.js"); - addExample(submenu, "Show all LUTs", "Show_all_LUTs.js"); - addExample(submenu, "Dialog Demo", "Dialog_Demo.js"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("BeanShell"); - addExample(submenu, "Sphere", "Sphere.bsh"); - addExample(submenu, "Example Plot", "Example_Plot.bsh"); - addExample(submenu, "Semi-log Plot", "Semi-log_Plot.bsh"); - addExample(submenu, "Arrow Plot", "Arrow_Plot.bsh"); - addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.bsh"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Python"); - addExample(submenu, "Sphere", "Sphere.py"); - addExample(submenu, "Animated Gaussian Blur", "Animated_Gaussian_Blur.py"); - addExample(submenu, "Spiral Rotation", "Spiral_Rotation.py"); - addExample(submenu, "Overlay", "Overlay.py"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Java"); - addExample(submenu, "Sphere", "Sphere_.java"); - addExample(submenu, "Plasma Cloud", "Plasma_Cloud.java"); - addExample(submenu, "Gamma Adjuster", "Gamma_Adjuster.java"); - addExample(submenu, "Plugin", "My_Plugin.java"); - addExample(submenu, "Plugin Filter", "Filter_Plugin.java"); - addExample(submenu, "Plugin Frame", "Plugin_Frame.java"); - addExample(submenu, "Plugin Tool", "Prototype_Tool.java"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Games"); - addExample(submenu, "2048", "2048.ijm"); - addExample(submenu, "Asteroids", "Asteroids.js"); - addExample(submenu, "Breakout", "Breakout.ijm"); - addExample(submenu, "Life", "GameOfLife.js"); - addExample(submenu, "Pong", "Pong.ijm"); - addExample(submenu, "Snake", "Snake.ijm"); - addExample(submenu, "Tetris", "Tetris.js"); - submenu.addActionListener(listener); - menu.add(submenu); - menu.addSeparator(); - CheckboxMenuItem item = new CheckboxMenuItem("Autorun Examples"); - menu.add(item); - item.addItemListener(ij); - item.setState(Prefs.autoRunExamples); - return menu; - } - - private static void addExample(Menu menu, String label, String command) { - MenuItem item = new MenuItem(label); - menu.add(item); - item.setActionCommand(command); - } - - void addOpenRecentSubMenu(Menu menu) { - openRecentMenu = getMenu("File>Open Recent"); - for (int i = 0; i < MAX_OPEN_RECENT_ITEMS; i++) { - String path = Prefs.getString("recent" + (i / 10) % 10 + i % 10); - if (path == null) - break; - MenuItem item = new MenuItem(path); - openRecentMenu.add(item); - item.addActionListener(ij); - } - menu.add(openRecentMenu); - } - - static void addItem(Menu menu, String label, int shortcut, boolean shift) { - if (menu == null) - return; - MenuItem item; - if (shortcut == 0) - item = new MenuItem(label); - else { - if (shift) { - item = new MenuItem(label, new MenuShortcut(shortcut, true)); - shortcuts.put(Integer.valueOf(shortcut + 200), label); - } else { - item = new MenuItem(label, new MenuShortcut(shortcut)); - shortcuts.put(Integer.valueOf(shortcut), label); - } - } - if (addSorted) { - if (menu == pluginsMenu) - addItemSorted(menu, item, userPluginsIndex); - else - addOrdered(menu, item); - } else - menu.add(item); - item.addActionListener(ij); - } - - void addPlugInItem(Menu menu, String label, String className, int shortcut, boolean shift) { - pluginsTable.put(label, className); - nPlugins++; - addItem(menu, label, shortcut, shift); - } - - CheckboxMenuItem addCheckboxItem(Menu menu, String label, String className) { - pluginsTable.put(label, className); - nPlugins++; - CheckboxMenuItem item = new CheckboxMenuItem(label); - menu.add(item); - item.addItemListener(ij); - item.setState(false); - return item; - } - - static Menu addSubMenu(Menu menu, String name) { - String value; - String key = name.toLowerCase(Locale.US); - int index; - Menu submenu = new Menu(name.replace('_', ' ')); - index = key.indexOf(' '); - if (index > 0) - key = key.substring(0, index); - for (int count = 1; count < 100; count++) { - value = Prefs.getString(key + (count / 10) % 10 + count % 10); - if (value == null) - break; - if (count == 1) - menu.add(submenu); - if (value.equals("-")) - submenu.addSeparator(); - else - addPluginItem(submenu, value); - } - if (name.equals("Lookup Tables") && applet == null) - addLuts(submenu); - return submenu; - } - - static void addLuts(Menu submenu) { - String path = IJ.getDirectory("luts"); - if (path == null) - return; - File f = new File(path); - String[] list = null; - if (applet == null && f.exists() && f.isDirectory()) - list = f.list(); - if (list == null) - return; - if (IJ.isLinux() || IJ.isMacOSX()) - Arrays.sort(list); - submenu.addSeparator(); - for (int i = 0; i < list.length; i++) { - String name = list[i]; - if (name.endsWith(".lut")) { - name = name.substring(0, name.length() - 4); - if (name.contains("_") && !name.contains(" ")) - name = name.replace("_", " "); - MenuItem item = new MenuItem(name); - submenu.add(item); - item.addActionListener(ij); - nPlugins++; - } - } - } - - static void addPluginItem(Menu submenu, String s) { - if (s.startsWith("\"-\"")) { - // add menu separator if command="-" - addSeparator(submenu); - return; - } - int lastComma = s.lastIndexOf(','); - if (lastComma <= 0) - return; - String command = s.substring(1, lastComma - 1); - int keyCode = 0; - boolean shift = false; - if (command.endsWith("]")) { - int openBracket = command.lastIndexOf('['); - if (openBracket > 0) { - String shortcut = command.substring(openBracket + 1, command.length() - 1); - keyCode = convertShortcutToCode(shortcut); - boolean functionKey = keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12; - if (keyCode > 0 && !functionKey) - command = command.substring(0, openBracket); - } - } - if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12) { - shortcuts.put(Integer.valueOf(keyCode), command); - keyCode = 0; - } else if (keyCode >= 265 && keyCode <= 290) { - keyCode -= 200; - shift = true; - } - addItem(submenu, command, keyCode, shift); - while (s.charAt(lastComma + 1) == ' ' && lastComma + 2 < s.length()) - lastComma++; // remove leading spaces - String className = s.substring(lastComma + 1, s.length()); - // IJ.log(command+" "+className); - if (installingJars) - duplicateCommand = pluginsTable.get(command) != null; - pluginsTable.put(command, className); - nPlugins++; - } - - void checkForDuplicate(String command) { - if (pluginsTable.get(command) != null) { - } - } - - void addPluginsMenu() { - String value, label, className; - int index; - // pluginsMenu = new Menu("Plugins"); - pluginsMenu = getMenu("Plugins"); - for (int count = 1; count < 100; count++) { - value = Prefs.getString("plug-in" + (count / 10) % 10 + count % 10); - if (value == null) - break; - char firstChar = value.charAt(0); - if (firstChar == '-') - pluginsMenu.addSeparator(); - else if (firstChar == '>') { - String submenu = value.substring(2, value.length() - 1); - // Menu menu = getMenu("Plugins>" + submenu, true); - Menu menu = addSubMenu(pluginsMenu, submenu); - if (submenu.equals("Shortcuts")) - shortcutsMenu = menu; - else if (submenu.equals("Utilities")) - utilitiesMenu = menu; - else if (submenu.equals("Macros")) - macrosMenu = menu; - } else - addPluginItem(pluginsMenu, value); - } - userPluginsIndex = pluginsMenu.getItemCount(); - if (userPluginsIndex < 0) - userPluginsIndex = 0; - } - - /** - * Install plugins using "pluginxx=" keys in IJ_Prefs.txt. Plugins not listed in - * IJ_Prefs are added to the end of the Plugins menu. - */ - void installPlugins() { - int nPlugins0 = nPlugins; - String value, className; - char menuCode; - Menu menu; - String[] pluginList = getPlugins(); - String[] pluginsList2 = null; - Hashtable skipList = new Hashtable(); - for (int index = 0; index < 100; index++) { - value = Prefs.getString("plugin" + (index / 10) % 10 + index % 10); - if (value == null) - break; - menuCode = value.charAt(0); - switch (menuCode) { - case PLUGINS_MENU: - default: - menu = pluginsMenu; - break; - case IMPORT_MENU: - menu = getMenu("File>Import"); - break; - case SAVE_AS_MENU: - menu = getMenu("File>Save As"); - break; - case SHORTCUTS_MENU: - menu = shortcutsMenu; - break; - case ABOUT_MENU: - menu = getMenu("Help>About Plugins"); - break; - case FILTERS_MENU: - menu = getMenu("Process>Filters"); - break; - case TOOLS_MENU: - menu = getMenu("Analyze>Tools"); - break; - case UTILITIES_MENU: - menu = utilitiesMenu; - break; - } - String prefsValue = value; - value = value.substring(2, value.length()); // remove menu code and - // coma - className = value.substring(value.lastIndexOf(',') + 1, value.length()); - boolean found = className.startsWith("ij."); - if (!found && pluginList != null) { // does this plugin exist? - if (pluginsList2 == null) - pluginsList2 = getStrippedPlugins(pluginList); - for (int i = 0; i < pluginsList2.length; i++) { - if (className.startsWith(pluginsList2[i])) { - found = true; - break; - } - } - } - if (found && menu != pluginsMenu) { - addPluginItem(menu, value); - pluginsPrefs.addElement(prefsValue); - if (className.endsWith("\")")) { // remove any argument - int argStart = className.lastIndexOf("(\""); - if (argStart > 0) - className = className.substring(0, argStart); - } - skipList.put(className, ""); - } - } - if (pluginList != null) { - for (int i = 0; i < pluginList.length; i++) { - if (!skipList.containsKey(pluginList[i])) - installUserPlugin(pluginList[i]); - } - } - if ((nPlugins - nPlugins0) <= 1 && IJ.getDir("imagej") != null && IJ.getDir("imagej").startsWith("/private")) { - pluginsMenu.addSeparator(); - addPlugInItem(pluginsMenu, "Why are Plugins Missing?", "ij.plugin.SimpleCommands(\"missing\")", 0, false); - } - installJarPlugins(); - installMacros(); - } - - /** Installs macros and scripts located in the plugins folder. */ - void installMacros() { - if (macroFiles == null) - return; - for (int i = 0; i < macroFiles.size(); i++) { - String name = (String) macroFiles.elementAt(i); - installMacro(name); - } - } - - /** - * Installs a macro or script in the Plugins menu, or submenu, with with - * underscores in the file name replaced by spaces. - */ - void installMacro(String name) { - Menu menu = pluginsMenu; - String dir = null; - int slashIndex = name.indexOf('/'); - if (slashIndex > 0) { - dir = name.substring(0, slashIndex); - name = name.substring(slashIndex + 1, name.length()); - menu = getPluginsSubmenu(dir); - slashIndex = name.indexOf('/'); - if (slashIndex > 0) { - String dir2 = name.substring(0, slashIndex); - name = name.substring(slashIndex + 1, name.length()); - String menuName = "Plugins>" + dir + ">" + dir2; - menu = getMenu(menuName); - dir += File.separator + dir2; - } - } - String command = name.replace('_', ' '); - if (command.endsWith(".js") || command.endsWith(".py")) - command = command.substring(0, command.length() - 3); // remove - // ".js" or - // ".py" - else - command = command.substring(0, command.length() - 4); // remove - // ".txt", - // ".ijm" or - // ".bsh" - command = command.trim(); - if (pluginsTable.get(command) != null) // duplicate command? - command = command + " Macro"; - MenuItem item = new MenuItem(command); - addOrdered(menu, item); - item.addActionListener(ij); - String path = (dir != null ? dir + File.separator : "") + name; - pluginsTable.put(command, "ij.plugin.Macro_Runner(\"" + path + "\")"); - nMacros++; - } - - static int addPluginSeparatorIfNeeded(Menu menu) { - if (menuSeparators == null) - return 0; - Integer i = (Integer) menuSeparators.get(menu); - if (i == null) { - if (menu.getItemCount() > 0) - addSeparator(menu); - i = Integer.valueOf(menu.getItemCount()); - menuSeparators.put(menu, i); - } - return i.intValue(); - } - - /** Inserts 'item' into 'menu' in alphanumeric order. */ - static void addOrdered(Menu menu, MenuItem item) { - String label = item.getLabel(); - int start = addPluginSeparatorIfNeeded(menu); - for (int i = start; i < menu.getItemCount(); i++) { - if (label.compareTo(menu.getItem(i).getLabel()) < 0) { - menu.insert(item, i); - return; - } - } - menu.add(item); - } - - public static String getJarFileForMenuEntry(String menuEntry) { - if (instance == null) - return null; - return (String) instance.menuEntry2jarFile.get(menuEntry); - } - - /** Install plugins located in JAR files. */ - void installJarPlugins() { - if (jarFiles == null) - return; - installingJars = true; - for (int i = 0; i < jarFiles.size(); i++) { - isJarErrorHeading = false; - String jar = (String) jarFiles.elementAt(i); - InputStream is = getConfigurationFile(jar); - if (is == null) - continue; - ArrayList entries = new ArrayList(20); - LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is)); - try { - while (true) { - String s = lnr.readLine(); - if (s == null) - break; - - if (s.length() >= 3 && !s.startsWith("#")) - entries.add(s); - } - } catch (IOException e) { - } finally { - try { - if (lnr != null) - lnr.close(); - } catch (IOException e) { - } - } - - for (int j = 0; j < entries.size(); j++) { - installJarPlugin(jar, (String) entries.get(j)); - /* Changed for Bio7! */ - bio7JarAllCommand.add((String) entries.get(j)); - - } - } - } - - /** Install a plugin located in a JAR file. */ - void installJarPlugin(String jar, String s) { - addSorted = false; - Menu menu; - s = s.trim(); - // System.out.println(s); - if (s.startsWith("Plugins>")) { - // extract name after Plugins> - int firstComma = s.indexOf(','); - // no comma or smaller than word plugins - if (firstComma == -1 || firstComma <= 8) - menu = null; - else { - // Extract name to first comma (before name of plugin) - String name = s.substring(8, firstComma); - menu = getPluginsSubmenu(name); - } - // Plugins>FeatureJ, "FeatureJ Derivatives", featurej.FJ_Derivatives - // give the name of the jar is description is empty or is 'plugins' - } else if (s.startsWith("\"") || s.startsWith("Plugins")) { - String name = getSubmenuName(jar); - if (name != null) - menu = getPluginsSubmenu(name); - else - menu = pluginsMenu; - addSorted = true; - } else { - // Creates a menu from the text! - int firstQuote = s.indexOf('"'); - String name = firstQuote < 0 ? s : s.substring(0, firstQuote).trim(); - int comma = name.indexOf(','); - if (comma >= 0) - name = name.substring(0, comma); - if (name.startsWith("Help>About")) // for backward compatibility - name = "Help>About Plugins"; - menu = getMenu(name); - } - int firstQuote = s.indexOf('"'); - if (firstQuote == -1) - return; - s = s.substring(firstQuote, s.length()); // remove menu - if (menu != null) { - addPluginSeparatorIfNeeded(menu); - // Adds the command to the hashtable and create a menuItem! - addPluginItem(menu, s); - addSorted = false; - } - String menuEntry = s; - if (s.startsWith("\"")) { - int quote = s.indexOf('"', 1); - menuEntry = quote < 0 ? s.substring(1) : s.substring(1, quote); - } else { - int comma = s.indexOf(','); - if (comma > 0) - menuEntry = s.substring(0, comma); - } - if (duplicateCommand) { - if (jarError == null) - jarError = ""; - addJarErrorHeading(jar); - String jar2 = (String) menuEntry2jarFile.get(menuEntry); - if (jar2 != null && jar2.startsWith(pluginsPath)) - jar2 = jar2.substring(pluginsPath.length()); - jarError += " Duplicate command: " + s + (jar2 != null ? " (already in " + jar2 + ")" : "") + "\n"; - } else - menuEntry2jarFile.put(menuEntry, jar); - duplicateCommand = false; - } - - void addJarErrorHeading(String jar) { - if (!isJarErrorHeading) { - if (!jarError.equals("")) - jarError += " \n"; - jarError += "Plugin configuration error: " + jar + "\n"; - isJarErrorHeading = true; - } - } - - /** - * Returns the specified ImageJ menu (e.g., "File>New") or null if it is not - * found. - */ - public static Menu getImageJMenu(String menuPath) { - if (menus==null && !GraphicsEnvironment.isHeadless()) - IJ.init(); - if (menus == null) - return null; - if (menus.get(menuPath) != null) - return getMenu(menuPath, false); - else - return null; - } - - private static Menu getMenu(String menuPath) { - if (GraphicsEnvironment.isHeadless()) - return null; - else - return getMenu(menuPath, false); - } - - /* Creates the menu and adds menus for the jar plugins! */ - private static Menu getMenu(String menuName, boolean readFromProps) { - if (menuName.endsWith(">")) - menuName = menuName.substring(0, menuName.length() - 1); - - Menu result = (Menu) menus.get(menuName); - if (result == null) { - int offset = menuName.lastIndexOf('>'); - if (offset < 0) { - result = new Menu(menuName); - if (mbar == null) - mbar = new MenuBar(); - if (menuName.equals("Help")) - mbar.setHelpMenu(result); - else - mbar.add(result); - if (menuName.equals("Window")) - window = result; - else if (menuName.equals("Plugins")) - pluginsMenu = result; - } else { - // B identifying the last index of > we can get the parent menu. - // Names are store as e.g. 'plugins>submenu' - String parentName = menuName.substring(0, offset); - String menuItemName = menuName.substring(offset + 1); - // Recursive call to get all parent menus! - Menu parentMenu = getMenu(parentName); - - result = new Menu(menuItemName); - addPluginSeparatorIfNeeded(parentMenu); - if (readFromProps) - result = addSubMenu(parentMenu, menuItemName); - else if (parentName.startsWith("Plugins") && menuSeparators != null) - addItemSorted(parentMenu, result, parentName.equals("Plugins") ? userPluginsIndex : 0); - else - parentMenu.add(result); - if (menuName.equals("File>Open Recent")) - openRecentMenu = result; - } - menus.put(menuName, result); - } - return result; - } - - Menu getPluginsSubmenu(String submenuName) { - return getMenu("Plugins>" + submenuName); - } - - String getSubmenuName(String jarPath) { - // IJ.log("getSubmenuName: \n"+jarPath+"\n"+pluginsPath); - if (pluginsPath == null) - return null; - if (jarPath.startsWith(pluginsPath)) - jarPath = jarPath.substring(pluginsPath.length() - 1); - int index = jarPath.lastIndexOf(File.separatorChar); - if (index < 0) - return null; - String name = jarPath.substring(0, index); - index = name.lastIndexOf(File.separatorChar); - if (index < 0) - return null; - name = name.substring(index + 1); - if (name.equals("plugins")) - return null; - return name; - } - - static void addItemSorted(Menu menu, MenuItem item, int startingIndex) { - String itemLabel = item.getLabel(); - int count = menu.getItemCount(); - boolean inserted = false; - for (int i = startingIndex; i < count; i++) { - MenuItem mi = menu.getItem(i); - String label = mi.getLabel(); - // IJ.log(i+ " "+itemLabel+" "+label + - // " "+(itemLabel.compareTo(label))); - if (itemLabel.compareTo(label) < 0) { - menu.insert(item, i); - inserted = true; - break; - } - } - if (!inserted) - menu.add(item); - } - - static void addSeparator(Menu menu) { - menu.addSeparator(); - } - - /** - * Opens the configuration file ("plugins.config") from a JAR file and returns - * it as an InputStream. - */ - InputStream getConfigurationFile(String jar) { - try { - ZipFile jarFile = new ZipFile(jar); - Enumeration entries = jarFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - if (entry.getName().endsWith("plugins.config")) - return jarFile.getInputStream(entry); - } - jarFile.close(); - } catch (Throwable e) { - IJ.log(jar + ": " + e); - } - return autoGenerateConfigFile(jar); - } - - /** Creates a configuration file for JAR/ZIP files that do not have one. */ - InputStream autoGenerateConfigFile(String jar) { - StringBuffer sb = null; - try { - ZipFile jarFile = new ZipFile(jar); - Enumeration entries = jarFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - String name = entry.getName(); - if (name.endsWith(".class") && name.indexOf("_") > 0 && name.indexOf("$") == -1 - && name.indexOf("/_") == -1 && !name.startsWith("_")) { - if (Character.isLowerCase(name.charAt(0)) && name.indexOf("/") != -1) - continue; - if (sb == null) - sb = new StringBuffer(); - String className = name.substring(0, name.length() - 6); - int slashIndex = className.lastIndexOf('/'); - String plugins = "Plugins"; - if (slashIndex >= 0) { - plugins += ">" + className.substring(0, slashIndex).replace('/', '>').replace('_', ' '); - name = className.substring(slashIndex + 1); - } else - name = className; - name = name.replace('_', ' '); - className = className.replace('/', '.'); - sb.append(plugins + ", \"" + name + "\", " + className + "\n"); - } - } - jarFile.close(); - } catch (Throwable e) { - IJ.log(jar + ": " + e); - } - if (sb == null) - return null; - else - return new ByteArrayInputStream(sb.toString().getBytes()); - } - - /** Returns a list of the plugins with directory names removed. */ - String[] getStrippedPlugins(String[] plugins) { - String[] plugins2 = new String[plugins.length]; - int slashPos; - for (int i = 0; i < plugins2.length; i++) { - plugins2[i] = plugins[i]; - slashPos = plugins2[i].lastIndexOf('/'); - if (slashPos >= 0) - plugins2[i] = plugins[i].substring(slashPos + 1, plugins2[i].length()); - } - return plugins2; - } - - void setupPluginsAndMacrosPaths() { - /* - * ImageJPath = pluginsPath = macrosPath = null; String currentDir = - * Prefs.getHomeDir(); // "user.dir" if (currentDir==null) return; if - * (currentDir.endsWith("plugins")) ImageJPath = pluginsPath = - * currentDir+File.separator; else { String pluginsDir = - * System.getProperty("plugins.dir"); if (pluginsDir!=null) { if - * (pluginsDir.endsWith("/")||pluginsDir.endsWith("\\")) pluginsDir = - * pluginsDir.substring(0, pluginsDir.length()-1); if - * (pluginsDir.endsWith("/plugins")||pluginsDir.endsWith("\\plugins")) - * pluginsDir = pluginsDir.substring(0, pluginsDir.length()-8); } if - * (pluginsDir==null) pluginsDir = currentDir; else if - * (pluginsDir.equals("user.home")) { pluginsDir = - * System.getProperty("user.home"); if (!(new - * File(pluginsDir+File.separator+"plugins")).isDirectory()) pluginsDir = - * pluginsDir + File.separator + "ImageJ"; // needed to run plugins when ImageJ - * launched using Java WebStart if (applet==null) - * System.setSecurityManager(null); jnlp = true; } pluginsPath = - * pluginsDir+File.separator+"plugins"+File.separator; macrosPath = - * pluginsDir+File.separator+"macros"+File.separator; ImageJPath = - * pluginsDir+File.separator; } - */ - - /* Changed for Bio7! */ - - pluginsPath = macrosPath = null; - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - /* We need an extra seperator here else the plugins are not found! */ - pluginsPath = store.getString("PLUGINS_PATH") + File.separator; - macrosPath = store.getString("MACROS_PATH") + File.separator; - /* Get the installation directory of the ImageJ plugin! */ - String currentDir = Util.getImageJPath(); - ImageJPath = Util.getImageJPath() + File.separator; - - File f = pluginsPath != null ? new File(pluginsPath) : null; - if (f == null || !f.isDirectory()) { - ImageJPath = currentDir + File.separator; - pluginsPath = ImageJPath + "plugins" + File.separator; - f = new File(pluginsPath); - if (!f.isDirectory()) { - String altPluginsPath = System.getProperty("plugins.dir"); - if (altPluginsPath != null) { - f = new File(altPluginsPath); - if (!f.isDirectory()) - altPluginsPath = null; - else { - ImageJPath = f.getParent() + File.separator; - pluginsPath = ImageJPath + f.getName() + File.separator; - macrosPath = ImageJPath + "macros" + File.separator; - } - } - if (altPluginsPath == null) - ImageJPath = pluginsPath = null; - } - } - f = macrosPath != null ? new File(macrosPath) : null; - if (f != null && !f.isDirectory()) { - macrosPath = currentDir + File.separator + "macros" + File.separator; - f = new File(macrosPath); - if (!f.isDirectory()) - macrosPath = null; - } - if (IJ.debugMode) { - IJ.log("Menus.setupPluginsAndMacrosPaths"); - IJ.log(" user.dir: " + currentDir); - IJ.log(" plugins.dir: " + System.getProperty("plugins.dir")); - IJ.log(" ImageJPath: " + ImageJPath); - IJ.log(" pluginsPath: " + pluginsPath); - } - } - - /** Returns a list of the plugins in the plugins menu. */ - public static synchronized String[] getPlugins() { - File f = pluginsPath != null ? new File(pluginsPath) : null; - if (f == null || (f != null && !f.isDirectory())) - return null; - String[] list = f.list(); - if (list == null) - return null; - Vector v = new Vector(); - jarFiles = null; - macroFiles = null; - for (int i = 0; i < list.length; i++) { - String name = list[i]; - boolean isClassFile = name.endsWith(".class"); - boolean hasUnderscore = name.indexOf('_') >= 0; - if (hasUnderscore && isClassFile && name.indexOf('$') < 0) { - name = name.substring(0, name.length() - 6); // remove ".class" - v.addElement(name); - } else if (hasUnderscore && (name.endsWith(".jar") || name.endsWith(".zip"))) { - if (jarFiles == null) - jarFiles = new Vector(); - jarFiles.addElement(pluginsPath + name); - } else if (validMacroName(name, hasUnderscore)) { - if (macroFiles == null) - macroFiles = new Vector(); - macroFiles.addElement(name); - } else { - if (!isClassFile) - checkSubdirectory(pluginsPath, name, v); - } - } - list = new String[v.size()]; - v.copyInto((String[]) list); - StringSorter.sort(list); - return list; - } - - /** - * Looks for plugins and jar files in a subdirectory of the plugins directory. - */ - private static void checkSubdirectory(String path, String dir, Vector v) { - if (dir.endsWith(".java")) - return; - File f = new File(path, dir); - if (!f.isDirectory()) - return; - String[] list = f.list(); - if (list == null) - return; - dir += "/"; - int classCount = 0, otherCount = 0; - String className = null; - for (int i = 0; i < list.length; i++) { - String name = list[i]; - boolean hasUnderscore = name.indexOf('_') >= 0; - if (hasUnderscore && name.endsWith(".class") && name.indexOf('$') < 0) { - name = name.substring(0, name.length() - 6); // remove ".class" - v.addElement(dir + name); - classCount++; - className = name; - } else if (hasUnderscore && (name.endsWith(".jar") || name.endsWith(".zip"))) { - if (jarFiles == null) - jarFiles = new Vector(); - jarFiles.addElement(f.getPath() + File.separator + name); - otherCount++; - } else if (validMacroName(name, hasUnderscore)) { - if (macroFiles == null) - macroFiles = new Vector(); - macroFiles.addElement(dir + name); - otherCount++; - } else { - File f2 = new File(f, name); - if (f2.isDirectory()) - installSubdirectorMacros(f2, dir + name); - } - } - if (Prefs.moveToMisc && classCount == 1 && otherCount == 0 && dir.indexOf("_") == -1) - v.setElementAt("Miscellaneous/" + className, v.size() - 1); - } - - /** Installs macros and scripts located in subdirectories. */ - private static void installSubdirectorMacros(File f2, String dir) { - if (dir.endsWith("Launchers")) - return; - String[] list = f2.list(); - if (list == null) - return; - for (int i = 0; i < list.length; i++) { - String name = list[i]; - boolean hasUnderscore = name.indexOf('_') >= 0; - if (validMacroName(name, hasUnderscore)) { - if (macroFiles == null) - macroFiles = new Vector(); - macroFiles.addElement(dir + "/" + name); - } - } - } - - private static boolean validMacroName(String name, boolean hasUnderscore) { - return (hasUnderscore && name.endsWith(".txt")) || name.endsWith(".ijm") || name.endsWith(".js") - || name.endsWith(".bsh") || name.endsWith(".py"); - } - - /** - * Installs a plugin in the Plugins menu using the class name, with underscores - * replaced by spaces, as the command. - */ - void installUserPlugin(String className) { - installUserPlugin(className, false); - } - - public void installUserPlugin(String className, boolean force) { - int slashIndex = className.indexOf('/'); - String menuName = slashIndex < 0 ? "Plugins" - : "Plugins>" + className.substring(0, slashIndex).replace('/', '>'); - Menu menu = getMenu(menuName); - String command = className; - if (slashIndex > 0) { - command = className.substring(slashIndex + 1); - } - command = command.replace('_', ' '); - //command = command.trim(); - boolean itemExists = (pluginsTable.get(command) != null); - if (force && itemExists) - return; - - if (!force && itemExists) // duplicate command? - command = command + " Plugin"; - MenuItem item = new MenuItem(command); - if (force) - addItemSorted(menu, item, 0); - else - addOrdered(menu, item); - item.addActionListener(ij); - pluginsTable.put(command, className.replace('/', '.')); - nPlugins++; - } - - void installPopupMenu(ImageJ ij) { - String s; - int count = 0; - MenuItem mi; - popup = new PopupMenu(""); - if (fontSize != 0 || scale > 1.0) - popup.setFont(getFont()); - - while (true) { - count++; - s = Prefs.getString("popup" + (count / 10) % 10 + count % 10); - if (s == null) - break; - if (s.equals("-")) - popup.addSeparator(); - else if (!s.equals("")) { - mi = new MenuItem(s); - mi.addActionListener(ij); - popup.add(mi); - } - } - } - - public static MenuBar getMenuBar() { - return mbar; - } - - public static Menu getMacrosMenu() { - return macrosMenu; - } - - public static Menu getOpenRecentMenu() { - return openRecentMenu; - } - - public int getMacroCount() { - return nMacros; - } - - public int getPluginCount() { - return nPlugins; - } - - static final int RGB_STACK = 10, HSB_STACK = 11, LAB_STACK = 12, HSB32_STACK = 13; - - /** Updates the Image/Type and Window menus. */ - public static void updateMenus() { - if (ij == null) - return; - gray8Item.setState(false); - gray16Item.setState(false); - gray32Item.setState(false); - color256Item.setState(false); - colorRGBItem.setState(false); - RGBStackItem.setState(false); - HSBStackItem.setState(false); - LabStackItem.setState(false); - HSB32Item.setState(false); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp == null) - return; - int type = imp.getType(); - if (imp.getStackSize() > 1) { - ImageStack stack = imp.getStack(); - if (stack.isRGB()) - type = RGB_STACK; - else if (stack.isHSB()) - type = HSB_STACK; - else if (stack.isLab()) - type = LAB_STACK; - else if (stack.isHSB32()) - type = HSB32_STACK; - } - - switch (type) { - case ImagePlus.GRAY8: - gray8Item.setState(true); - break; - case ImagePlus.GRAY16: - gray16Item.setState(true); - break; - case ImagePlus.GRAY32: - gray32Item.setState(true); - break; - case ImagePlus.COLOR_256: - color256Item.setState(true); - break; - case ImagePlus.COLOR_RGB: - colorRGBItem.setState(true); - break; - case RGB_STACK: - RGBStackItem.setState(true); - break; - case HSB_STACK: - HSBStackItem.setState(true); - break; - case LAB_STACK: - LabStackItem.setState(true); - break; - case HSB32_STACK: - HSB32Item.setState(true); - break; - - } - - // update Window menu - int nItems = window.getItemCount(); - int start = WINDOW_MENU_ITEMS + windowMenuItems2; - int index = start + WindowManager.getCurrentIndex(); - try { // workaround for Linux/Java 5.0/bug - for (int i = start; i < nItems; i++) { - CheckboxMenuItem item = (CheckboxMenuItem) window.getItem(i); - item.setState(i == index); - } - } catch (Exception e) { - } - } - - static boolean isColorLut(ImagePlus imp) { - ImageProcessor ip = imp.getProcessor(); - IndexColorModel cm = (IndexColorModel) ip.getColorModel(); - if (cm == null) - return false; - int mapSize = cm.getMapSize(); - byte[] reds = new byte[mapSize]; - byte[] greens = new byte[mapSize]; - byte[] blues = new byte[mapSize]; - cm.getReds(reds); - cm.getGreens(greens); - cm.getBlues(blues); - boolean isColor = false; - for (int i = 0; i < mapSize; i++) { - if ((reds[i] != greens[i]) || (greens[i] != blues[i])) { - isColor = true; - break; - } - } - return isColor; - } - - /** Use Prefs.getImageJDir() to get the path to the ImageJ directory. */ - static String getImageJPath() { - return ImageJPath; - } - - /** - * Returns the path to the user plugins directory or null if the plugins - * directory was not found. - */ - public static String getPlugInsPath() { - return pluginsPath; - } - - /** - * Returns the path to the macros directory or null if the macros directory was - * not found. - */ - public static String getMacrosPath() { - return macrosPath; - } - - /** Returns the hashtable that associates commands with plugins. */ - public static Hashtable getCommands() { - if (pluginsTable==null && !GraphicsEnvironment.isHeadless()) - IJ.init(); - return pluginsTable; - } - - /** - * Returns the hashtable that associates shortcuts with commands. The keys in - * the hashtable are Integer keycodes, or keycode+200 for uppercase. - */ - public static Hashtable getShortcuts() { - return shortcuts; - } - - /** - * Returns the hashtable that associates keyboard shortcuts with macros. The - * keys in the hashtable are Integer keycodes, or keycode+200 for uppercase. - */ - public static Hashtable getMacroShortcuts() { - if (macroShortcuts == null) - macroShortcuts = new Hashtable(); - return macroShortcuts; - } - - /** Inserts one item (a non-image window) into the Window menu. */ - static synchronized void insertWindowMenuItem(Window win) { - if (ij == null || win == null) - return; - String title = win instanceof Frame ? ((Frame) win).getTitle() : ((Dialog) win).getTitle(); - CheckboxMenuItem item = new CheckboxMenuItem(title); - item.addItemListener(ij); - int index = WINDOW_MENU_ITEMS + windowMenuItems2; - if (windowMenuItems2 >= 2) - index--; - window.insert(item, index); - windowMenuItems2++; - if (windowMenuItems2 == 1) { - window.insertSeparator(WINDOW_MENU_ITEMS + windowMenuItems2); - windowMenuItems2++; - } - } - - /** Adds one image to the end of the Window menu. */ - static synchronized void addWindowMenuItem(ImagePlus imp) { - if (ij==null) - return; - String name = imp.getTitle(); - String size = ImageWindow.getImageSize(imp); - CheckboxMenuItem item = new CheckboxMenuItem(name + " " + size); - item.setActionCommand("" + imp.getID()); - window.add(item); - item.addItemListener(ij); - } - - /** Removes the specified item from the Window menu. */ - static synchronized void removeWindowMenuItem(int index) { - // IJ.log("removeWindowMenuItem: "+index+" "+windowMenuItems2+" - // "+window.getItemCount()); - if (ij == null) - return; - try { - if (index >= 0 && index < window.getItemCount()) { - window.remove(WINDOW_MENU_ITEMS + index); - if (index < windowMenuItems2) { - windowMenuItems2--; - if (windowMenuItems2 == 1) { - window.remove(WINDOW_MENU_ITEMS); - windowMenuItems2 = 0; - } - } - } - } catch (Exception e) { - } - } - - /** Changes the name of an item in the Window menu. */ - public static synchronized void updateWindowMenuItem(String oldLabel, String newLabel) { - updateWindowMenuItem(null, oldLabel, newLabel); - } - - /** Changes the name of an item in the Window menu. */ - public static synchronized void updateWindowMenuItem(ImagePlus imp, String oldLabel, String newLabel) { - if (oldLabel == null || newLabel == null) - return; - int first = WINDOW_MENU_ITEMS; - int count = window.getItemCount(); - try { // workaround for Linux/Java 5.0/bug - for (int i = first; i < count; i++) { - MenuItem item = window.getItem(i); - String label = item.getLabel(); - String cmd = item.getActionCommand(); - if (imp != null) { // remove size (e.g. " 24MB") - int index = label.lastIndexOf(" "); - if (index > -1) - label = label.substring(0, index); - } - if (item!=null && label.equals(oldLabel) && (imp==null||(""+imp.getID()).equals(cmd))) { - String size = ""; - if (imp != null) - size = " " + ImageWindow.getImageSize(imp); - item.setLabel(newLabel + size); - return; - } - } - } catch (Exception e) { - } - } - - /** Adds a file path to the beginning of the File/Open Recent submenu. */ - public static synchronized void addOpenRecentItem(String path) { - if (ij == null) - return; - int count = openRecentMenu.getItemCount(); - for (int i = 0; i < count;) { - if (openRecentMenu.getItem(i).getLabel().equals(path)) { - openRecentMenu.remove(i); - count--; - } else - i++; - } - if (count == MAX_OPEN_RECENT_ITEMS) - openRecentMenu.remove(MAX_OPEN_RECENT_ITEMS - 1); - MenuItem item = new MenuItem(path); - openRecentMenu.insert(item, 0); - item.addActionListener(ij); - } - - public static PopupMenu getPopupMenu() { - return popup; - } - - public static Menu getSaveAsMenu() { - return saveAsMenu; - } - - /** - * Adds a plugin based command to the end of a specified menu. - * - * @param plugin the plugin (e.g. "Inverter_", "Inverter_("arg")") - * @param menuCode PLUGINS_MENU, IMPORT_MENU, SAVE_AS_MENU or HOT_KEYS - * @param command the menu item label (set to "" to uninstall) - * @param shortcut the keyboard shortcut (e.g. "y", "Y", "F1") - * @param ij ImageJ (the action listener) - * - * @return returns an error code(NORMAL_RETURN,COMMAND_IN_USE_ERROR, etc.) - */ - public static int installPlugin(String plugin, char menuCode, String command, String shortcut, ImageJ ij) { - if (command.equals("")) // uninstall - return NORMAL_RETURN; - - if (commandInUse(command)) - return COMMAND_IN_USE; - if (!validShortcut(shortcut)) - return INVALID_SHORTCUT; - if (shortcutInUse(shortcut)) - return SHORTCUT_IN_USE; - - Menu menu; - switch (menuCode) { - case PLUGINS_MENU: - menu = pluginsMenu; - break; - case IMPORT_MENU: - menu = getMenu("File>Import"); - break; - case SAVE_AS_MENU: - menu = getMenu("File>Save As"); - break; - case SHORTCUTS_MENU: - menu = shortcutsMenu; - break; - case ABOUT_MENU: - menu = getMenu("Help>About Plugins"); - break; - case FILTERS_MENU: - menu = getMenu("Process>Filters"); - break; - case TOOLS_MENU: - menu = getMenu("Analyze>Tools"); - break; - case UTILITIES_MENU: - menu = utilitiesMenu; - break; - default: - return 0; - } - int code = convertShortcutToCode(shortcut); - MenuItem item; - boolean functionKey = code >= KeyEvent.VK_F1 && code <= KeyEvent.VK_F12; - if (code == 0) - item = new MenuItem(command); - else if (functionKey) { - command += " [F" + (code - KeyEvent.VK_F1 + 1) + "]"; - shortcuts.put(Integer.valueOf(code), command); - item = new MenuItem(command); - } else { - shortcuts.put(Integer.valueOf(code), command); - int keyCode = code; - boolean shift = false; - if (keyCode >= 265 && keyCode <= 290) { - keyCode -= 200; - shift = true; - } - item = new MenuItem(command, new MenuShortcut(keyCode, shift)); - } - menu.add(item); - item.addActionListener(ij); - pluginsTable.put(command, plugin); - shortcut = code > 0 && !functionKey ? "[" + shortcut + "]" : ""; - pluginsPrefs.addElement(menuCode + ",\"" + command + shortcut + "\"," + plugin); - return NORMAL_RETURN; - } - - /** Deletes a command installed by Plugins/Shortcuts/Add Shortcut. */ - public static int uninstallPlugin(String command) { - boolean found = false; - for (Enumeration en = pluginsPrefs.elements(); en.hasMoreElements();) { - String cmd = (String) en.nextElement(); - if (cmd.contains(command)) { - boolean ok = pluginsPrefs.removeElement((Object) cmd); - found = true; - break; - } - } - if (found) - return NORMAL_RETURN; - else - return COMMAND_NOT_FOUND; - - } - - public static boolean commandInUse(String command) { - if (pluginsTable.get(command) != null) - return true; - else - return false; - } - - public static int convertShortcutToCode(String shortcut) { - int code = 0; - int len = shortcut.length(); - if (len==2 && shortcut.charAt(0)=='A') { //arrow key shortcuts - if (shortcut.charAt(1)=='L') code=37; - if (shortcut.charAt(1)=='U') code=38; - if (shortcut.charAt(1)=='R') code=39; - if (shortcut.charAt(1)=='D') code=40; - return code; - } - if (len == 2 && shortcut.charAt(0) == 'F') { - code = KeyEvent.VK_F1 + (int) shortcut.charAt(1) - 49; - if (code >= KeyEvent.VK_F1 && code <= KeyEvent.VK_F9) - return code; - else - return 0; - } - if (len == 3 && shortcut.charAt(0) == 'F') { - code = KeyEvent.VK_F10 + (int) shortcut.charAt(2) - 48; - if (code >= KeyEvent.VK_F10 && code <= KeyEvent.VK_F12) - return code; - else - return 0; - } - if (len == 2 && shortcut.charAt(0) == 'N') { // numeric keypad - code = KeyEvent.VK_NUMPAD0 + (int) shortcut.charAt(1) - 48; - if (code >= KeyEvent.VK_NUMPAD0 && code <= KeyEvent.VK_NUMPAD9) - return code; - switch (shortcut.charAt(1)) { - case '/': - return KeyEvent.VK_DIVIDE; - case '*': - return KeyEvent.VK_MULTIPLY; - case '-': - return KeyEvent.VK_SUBTRACT; - case '+': - return KeyEvent.VK_ADD; - case '.': - return KeyEvent.VK_DECIMAL; - default: - return 0; - } - } - if (len != 1) - return 0; - int c = (int) shortcut.charAt(0); - if (c >= 65 && c <= 90) // A-Z - code = KeyEvent.VK_A + c - 65 + 200; - else if (c >= 97 && c <= 122) // a-z - code = KeyEvent.VK_A + c - 97; - else if (c >= 48 && c <= 57) // 0-9 - code = KeyEvent.VK_0 + c - 48; - return code; - } - - void installStartupMacroSet() { - if (macrosPath == null) { - MacroInstaller.installFromJar("/macros/StartupMacros.txt"); - return; - } - String path = macrosPath + "StartupMacros.txt"; - File f = new File(path); - if (!f.exists()) { - path = macrosPath + "StartupMacros.ijm"; - f = new File(path); - if (!f.exists()) { - (new MacroInstaller()).installFromIJJar("/macros/StartupMacros.txt"); - return; - } - } else { - if ("StartupMacros.fiji.ijm".equals(f.getName())) - path = f.getPath(); - } - String libraryPath = macrosPath + "Library.txt"; - f = new File(libraryPath); - boolean isLibrary = f.exists(); - try { - MacroInstaller mi = new MacroInstaller(); - if (isLibrary) - mi.installLibrary(libraryPath); - mi.installStartupMacros(path); - nMacros += mi.getMacroCount(); - } catch (Exception e) { - } - } - - static boolean validShortcut(String shortcut) { - int len = shortcut.length(); - if (shortcut.equals("")) - return true; - else if (len == 1) - return true; - else if (shortcut.startsWith("F") && (len == 2 || len == 3)) - return true; - else - return false; - } - - /** Returns 'true' if this keyboard shortcut is in use. */ - public static boolean shortcutInUse(String shortcut) { - int code = convertShortcutToCode(shortcut); - if (shortcuts.get(Integer.valueOf(code)) != null) - return true; - else - return false; - } - - /** - * Set the size (in points) used for the fonts in ImageJ menus. Set the size to - * 0 to use the Java default size. - */ - public static void setFontSize(int size) { - if (size < 9 && size != 0) - size = 9; - if (size > 24) - size = 24; - fontSize = size; - } - - /** - * Returns the size (in points) used for the fonts in ImageJ menus. Returns 0 if - * the default font size is being used or if this is a Macintosh. - */ - public static int getFontSize() { - return fontSize; - } - - public static Font getFont() { - return getFont(true); - } - - public static Font getFont(boolean checkSize) { - int size = fontSize==0?13:fontSize; - size = (int)Math.round(size*scale); - int size0 = size; - if (checkSize && IJ.isWindows() && scale>1.0 && size>17) - size = 17; // Java resets size to 12 if you try to set it to 18 or greater - Font menuFont = new Font("SanSerif", Font.PLAIN, size); - //System.out.println("getFont: "+checkSize+" "+scale+" "+size0+" "+size+" "+menuFont); - return menuFont; - } - - /** Called once when ImageJ quits. */ - public static void savePreferences(Properties prefs) { - if (pluginsPrefs==null) - return; - int index = 0; - for (Enumeration en = pluginsPrefs.elements(); en.hasMoreElements();) { - String key = "plugin" + (index / 10) % 10 + index % 10; - String value = (String) en.nextElement(); - prefs.put(key, value); - index++; - } - int n = openRecentMenu.getItemCount(); - for (int i = 0; i < n; i++) { - String key = "" + i; - if (key.length() == 1) - key = "0" + key; - key = "recent" + key; - prefs.put(key, openRecentMenu.getItem(i).getLabel()); - } - prefs.put(Prefs.MENU_SIZE, Integer.toString(fontSize)); - } - - public static void updateImageJMenus() { - jarFiles = macroFiles = null; - Menus m = new Menus(IJ.getInstance(), IJ.getApplet()); - String err = m.addMenuBar(); - if (err != null) - IJ.error(err); - m.installStartupMacroSet(); - IJ.resetClassLoader(); - //IJ.runPlugIn("ij.plugin.ClassChecker", ""); - IJ.showStatus("Menus updated: " + m.nPlugins + " commands, " + m.nMacros + " macros"); - /*Changed for Bio7!*/ - updateBio7ImageJMenu(); - - } - - public static void updateBio7ImageJMenu() { - Display dis = Util.getDisplay(); - dis.asyncExec(new Runnable() { - public void run() { - CanvasView canvasView = CanvasView.getCanvas_view(); - IViewSite viewSite = canvasView.getViewSite(); - IActionBars actionBars = viewSite.getActionBars(); - IContributionItem[] it = actionBars.getToolBarManager().getItems(); - for (int j = 0; j < it.length; j++) { - //String name = Menus.getMenuBar().getMenu(j).getName(); - String name = it[j].getId(); - if (name.equals("File") == false && name.equals("Edit") == false && name.equals("Image") == false - && name.equals("Process") == false && name.equals("Analyze") == false - && name.equals("Plugins") == false && name.equals("Window") == false - && name.equals("Help") == false) { - - actionBars.getToolBarManager().remove(name); - actionBars.getToolBarManager().update(true); - } - } - int count = Menus.getMenuBar().getMenuCount(); - for (int i = 0; i < count; i++) { - String name = Menus.getMenuBar().getMenu(i).getLabel(); - if (name.equals("File") == false && name.equals("Edit") == false && name.equals("Image") == false - && name.equals("Process") == false && name.equals("Analyze") == false - && name.equals("Plugins") == false && name.equals("Window") == false - && name.equals("Help") == false) { - if (name.isEmpty() == false) { - actionBars.getToolBarManager().add(new ImageJExtensionAction(name)); - actionBars.getToolBarManager().update(true); - } - } - } - } - }); - } - - public static void updateFont() { - scale = (int) Math.round(Prefs.getGuiScale()); - Font font = getFont(); - mbar.setFont(font); - if (ij != null) - ij.setMenuBar(mbar); - popup.setFont(font); - } - - /** Adds a command to the ImageJ menu bar. */ - public static void add(String menuPath, String plugin) { - if (pluginsTable == null) - return; - int index = menuPath.lastIndexOf(">"); - if (index == -1 || index == menuPath.length() - 1) - return; - String label = menuPath.substring(index + 1, menuPath.length()); - menuPath = menuPath.substring(0, index); - pluginsTable.put(label, plugin); - addItem(getMenu(menuPath), label, 0, false); - } - -} diff --git a/com.eco.bio7.image/src/ij/OtherInstance.java b/com.eco.bio7.image/src/ij/OtherInstance.java deleted file mode 100644 index a440dab69..000000000 --- a/com.eco.bio7.image/src/ij/OtherInstance.java +++ /dev/null @@ -1,243 +0,0 @@ -package ij; - -import ij.IJ; -import ij.ImageJ; -import ij.Prefs; - -import ij.io.OpenDialog; -import ij.io.Opener; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import java.lang.reflect.Method; - -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.server.UnicastRemoteObject; - -import java.util.Properties; - -/* - * This class tries to contact another instance on the same machine, started - * by the current user. If such an instance is found, the arguments are - * sent to that instance. If no such an instance is found, listen for clients. - * - * No need for extra security, as the stub (and its serialization) contain - * a hard-to-guess hash code. - * - * @author Johannes Schindelin - */ -public class OtherInstance { - private static final String DELIMETER = "~!~"; // Separates macro name and argument - - interface ImageJInstance extends Remote { - void sendArgument(String arg) throws RemoteException; - } - - static class Implementation implements ImageJInstance { - int counter = 0; - - public void sendArgument(String cmd) { - if (IJ.debugMode) IJ.log("SocketServer.sendArgument: \""+ cmd+"\""); - if (cmd.startsWith("open ")) - (new Opener()).openAndAddToRecent(cmd.substring(5)); - else if (cmd.startsWith("macro ")) { - String name = cmd.substring(6); - String name2 = name; - String arg = null; - int index = name2.indexOf(DELIMETER); - if (index!=-1) { - name = name2.substring(0, index); - arg = name2.substring(index+DELIMETER.length(), name2.length()); - } - IJ.runMacroFile(name, arg); - } else if (cmd.startsWith("run ")) - IJ.run(cmd.substring(4)); - else if (cmd.startsWith("eval ")) { - String rtn = IJ.runMacro(cmd.substring(5)); - if (rtn!=null) - System.out.print(rtn); - } else if (cmd.startsWith("user.dir ")) { - OpenDialog.setDefaultDirectory(cmd.substring(9)); - System.setProperty("user.dir", cmd.substring(9)); - } - } - } - - public static String getStubPath() { - String display = System.getenv("DISPLAY"); - if (display!=null) { - display = display.replace(':', '_'); - display = display.replace('/', '_'); - } - String tmpDir = System.getProperty("java.io.tmpdir"); - tmpDir = IJ.addSeparator(tmpDir); - return tmpDir + "ImageJ-" - + System.getProperty("user.name") + "-" - + (display == null ? "" : display + "-") - + ImageJ.getPort() + ".stub"; - } - - public static void makeFilePrivate(String path) { - try { - File file = new File(path); - file.deleteOnExit(); - - // File.setReadable() is Java 6 - Class[] types = { boolean.class, boolean.class }; - Method m = File.class.getMethod("setReadable", types); - Object[] arguments = { Boolean.FALSE, Boolean.FALSE }; - m.invoke(file, arguments); - arguments = new Object[] { Boolean.TRUE, Boolean.TRUE }; - m.invoke(file, arguments); - types = new Class[] { boolean.class }; - m = File.class.getMethod("setWritable", types); - arguments = new Object[] { Boolean.FALSE }; - m.invoke(file, arguments); - return; - } catch (Exception e) { - if (IJ.debugMode) - System.err.println("Java < 6 detected," - + " trying chmod 0600 " + path); - } - if (!IJ.isWindows()) { - try { - String[] command = { - "chmod", "0600", path - }; - Runtime.getRuntime().exec(command); - } catch (Exception e) { - if (IJ.debugMode) - System.err.println("Even chmod failed."); - } - } - } - - public static boolean sendArguments(String[] args) { - if (!isRMIEnabled()) - return false; - String file = getStubPath(); - try { - FileInputStream in = new FileInputStream(file); - ImageJInstance instance = (ImageJInstance) new ObjectInputStream(in).readObject(); - in.close(); - if (instance==null) - return false; - instance.sendArgument("user.dir "+System.getProperty("user.dir")); - int macros = 0; - for (int i=0; itext in the preferences file using - * the keyword key. The string can be retrieved using the - * appropriate get() method. - * - * @see #get(String,String) - */ - public static void set(String key, String text) { - if (key.indexOf('.') < 1) - throw new IllegalArgumentException("Key must have a prefix"); - if (text == null) - ijPrefs.remove(KEY_PREFIX + key); - else - ijPrefs.put(KEY_PREFIX + key, text); - } - - /** - * Saves the value of the integer value in the preferences file - * using the keyword key. The value can be retrieved using the - * appropriate get() method. - * - * @see #get(String,double) - */ - public static void set(String key, int value) { - set(key, Integer.toString(value)); - } - - /** - * Saves the value of the double value in the preferences file - * using the keyword key. The value can be retrieved using the - * appropriate get() method. - * - * @see #get(String,double) - */ - public static void set(String key, double value) { - set(key, "" + value); - } - - /** - * Saves the value of the boolean value in the preferences file - * using the keyword key. The value can be retrieved using the - * appropriate get() method. - * - * @see #get(String,boolean) - */ - public static void set(String key, boolean value) { - set(key, "" + value); - } - - /** - * Uses the keyword key to retrieve a string from the preferences - * file. Returns defaultValue if the key is not found. - */ - public static String get(String key, String defaultValue) { - String value = ijPrefs.getProperty(KEY_PREFIX + key); - if (value == null) - return defaultValue; - else - return value; - } - - /** - * Uses the keyword key to retrieve a number from the preferences - * file. Returns defaultValue if the key is not found. - */ - public static double get(String key, double defaultValue) { - String s = ijPrefs.getProperty(KEY_PREFIX + key); - Double d = null; - if (s != null) { - try { - d = Double.valueOf(s); - } catch (NumberFormatException e) { - d = null; - } - if (d != null) - return (d.doubleValue()); - } - return defaultValue; - } - - /** - * Uses the keyword key to retrieve a boolean from the preferences - * file. Returns defaultValue if the key is not found. - */ - public static boolean get(String key, boolean defaultValue) { - String value = ijPrefs.getProperty(KEY_PREFIX + key); - if (value == null) - return defaultValue; - else - return value.equals("true"); - } - - /** - * Finds and loads the configuration file ("IJ_Props.txt") and the preferences - * file ("IJ_Prefs.txt"). - * - * @return an error message if "IJ_Props.txt" not found. - */ - public static String load(Object ij, Applet applet) { - /* Changed for Bio7! */ - - String path = Util.getImageJPath(); - - InputStream f = ij.getClass().getResourceAsStream(path + PROPS_NAME); - if (applet != null) - return loadAppletProps(f, applet); - if (ImageJDir == null) - /* /*Changed for Bio7! */ - ImageJDir = path;// System.getProperty("user.dir"); - /* - * String userHome = path;// System.getProperty("user.home"); if - * (IJ.isWindows()) { prefsDir = homeDir; // ImageJ folder on Windows if - * (prefsDir.endsWith("Desktop")) prefsDir = userHome; } else { prefsDir = - * homeDir; // prefsDir = userHome; // Mac Preferences folder or Unix home dir - * if (IJ.isMacOSX()) // prefsDir += "/Library/Preferences"; prefsDir = homeDir; - * // else // prefsDir += File.separator + ".imagej"; } - */ - if (f == null) { - try { - f = new FileInputStream(ImageJDir + "/" + PROPS_NAME); - propertiesPath = ImageJDir + "/" + PROPS_NAME; - } catch (FileNotFoundException e) { - f = null; - } - } - if (f == null) - return PROPS_NAME + " not found in ij.jar or in " + ImageJDir; - f = new BufferedInputStream(f); - try { - props.load(f); - f.close(); - } catch (IOException e) { - return ("Error loading " + PROPS_NAME); - } - imagesURL = props.getProperty(IJ.isJava18() ? "images.location" : "images.location2"); - loadPreferences(); - loadOptions(); - guiScale = get(GUI_SCALE, 1.0); - return null; - } - - /* - * static void dumpPrefs(String title) { IJ.log(""); IJ.log(title); static void - * dumpPrefs() { System.out.println(""); Enumeration e = ijPrefs.keys(); while - * (e.hasMoreElements()) { String key = (String) e.nextElement(); - * IJ.log(key+": "+ijPrefs.getProperty(key)); - * System.out.println(key+": "+ijPrefs.getProperty(key)); } } - */ - - static String loadAppletProps(InputStream f, Applet applet) { - if (f == null) - return PROPS_NAME + " not found in ij.jar"; - try { - props.load(f); - f.close(); - } catch (IOException e) { - return ("Error loading " + PROPS_NAME); - } - try { - URL url = new URL(applet.getDocumentBase(), "images/"); - imagesURL = url.toString(); - } catch (Exception e) { - } - return null; - } - - /** - * Returns the URL of the directory that contains the ImageJ sample images. - */ - public static String getImagesURL() { - return imagesURL; - } - - /** Sets the URL of the directory that contains the ImageJ sample images. */ - public static void setImagesURL(String url) { - imagesURL = url; - } - - /** - * Obsolete, replaced by getImageJDir(), which, unlike this method, returns a - * path that ends with File.separator. - */ - public static String getHomeDir() { - return ImageJDir; - } - - /** Returns the path, ending in File.separator, to the ImageJ directory. */ - public static String getImageJDir() { - /* Changed for Bio7! */ - String path = Util.getImageJPath(); - if (path == null) - return ImageJDir + File.separator; - else - return path + File.separator; - } - - public static String getPluginsDirProperty() { - if (pluginsDirProperty==null) { - String ijDir = System.getProperty("plugins.dir"); - if (ijDir!=null) { - if (ijDir.endsWith("/")||ijDir.endsWith("\\")) - ijDir = ijDir.substring(0, ijDir.length()-1); - if (ijDir.endsWith("/plugins")||ijDir.endsWith("\\plugins")) - ijDir = ijDir.substring(0, ijDir.length()-8); - pluginsDirProperty = ijDir; - } else - pluginsDirProperty = ""; - } - return pluginsDirProperty.length()>0?pluginsDirProperty:null; - } - - /** - * Returns the path to the directory where the preferences file (IJPrefs.txt) is - * saved. - */ - public static String getPrefsDir() { - /* Changed for Bio7! */ - String path = Util.getImageJPath(); - if (prefsDir == null) { - - /* - * if (IJ.isMacOSX()) dir += "/Library/Preferences"; else dir += - * File.separator+".imagej"; - */ - prefsDir = path; - preferencesPath = path + "/" + PREFS_NAME; - } - return prefsDir; - } - - /** Sets the path to the ImageJ directory. */ - static void setHomeDir(String path) { - if (path.endsWith(File.separator) || path.endsWith("/")) - path = path.substring(0, path.length() - 1); - ImageJDir = path; - } - - /** Returns the default directory, if any, or null. */ - public static String getDefaultDirectory() { - if (commandLineMacro) - return null; - else - return getString(DIR_IMAGE); - } - - /** Returns the file.separator system property. */ - public static String getFileSeparator() { - return separator; - } - - /** Opens the ImageJ preferences file ("IJ_Prefs.txt") file. */ - static void loadPreferences() { - String path = getPrefsDir() + separator + PREFS_NAME; - boolean ok = loadPrefs(path); - if (!ok) { // not found - if (IJ.isWindows()) - path = ImageJDir + separator + PREFS_NAME; - else - path = System.getProperty("user.home") + separator + PREFS_NAME; // User's - // home - // dir - ok = loadPrefs(path); - if (ok) - new File(path).delete(); - } - - } - - static boolean loadPrefs(String path) { - try { - InputStream is = new BufferedInputStream(new FileInputStream(path)); - ijPrefs.load(is); - is.close(); - return true; - } catch (Exception e) { - return false; - } - } - - /** Saves user preferences in the IJ_Prefs.txt properties file. */ - public static void savePreferences() { - String path = null; - commandLineMacro = false; - try { - Properties prefs = new Properties(); - String dir = OpenDialog.getDefaultDirectory(); - if (dir != null) - prefs.put(DIR_IMAGE, dir); - prefs.put(ROICOLOR, Tools.c2hex(Roi.getColor())); - prefs.put(SHOW_ALL_COLOR, Tools.c2hex(ImageCanvas.getShowAllColor())); - prefs.put(FCOLOR, Tools.c2hex(Toolbar.getForegroundColor())); - prefs.put(BCOLOR, Tools.c2hex(Toolbar.getBackgroundColor())); - prefs.put(JPEG, Integer.toString(FileSaver.getJpegQuality())); - prefs.put(FPS, Double.toString(Animator.getFrameRate())); - prefs.put(DIV_BY_ZERO_VALUE, Double.toString(FloatBlitter.divideByZeroValue)); - prefs.put(NOISE_SD, Double.toString(Filters.getSD())); - if (threads > 1) - prefs.put(THREADS, Integer.toString(threads)); - if (IJ.isMacOSX()) - useJFileChooser = false; - if (!IJ.isLinux()) - dialogCancelButtonOnRight = false; - saveOptions(prefs); - savePluginPrefs(prefs); - ImageJ ij = IJ.getInstance(); - if (ij!=null) - ij.savePreferences(prefs); - Menus.savePreferences(prefs); - ParticleAnalyzer.savePreferences(prefs); - Analyzer.savePreferences(prefs); - ImportDialog.savePreferences(prefs); - PlotWindow.savePreferences(prefs); - NewImage.savePreferences(prefs); - String prefsDir = getPrefsDir(); - path = prefsDir + separator + PREFS_NAME; - if (prefsDir.endsWith(".imagej")) { - File f = new File(prefsDir); - if (!f.exists()) - f.mkdir(); // create .imagej directory - } - if (resetPreferences) { - File f = new File(path); - if (!f.exists()) - IJ.error("Edit>Options>Reset", "Unable to reset preferences. File not found at\n" + path); - boolean rtn = f.delete(); - resetPreferences = false; - } else - savePrefs(prefs, path); - } catch (Throwable t) { - String msg = t.getMessage(); - if (msg == null) - msg = "" + t; - int delay = 4000; - try { - new TextWindow("Error Saving Preferences:\n" + path, msg, 500, 200); - IJ.wait(delay); - } catch (Throwable t2) { - } - } - } - - /** Delete the preferences file when ImageJ quits. */ - public static void resetPreferences() { - resetPreferences = true; - } - - static void loadOptions() { - // Changed for Bio7. On Win 10 we use the SWT file dialog by default. No need to - // switch to JFileChooser! - int defaultOptions = ANTIALIASING + AVOID_RESLICE_INTERPOLATION + ANTIALIASED_TOOLS + MULTI_POINT_MODE - + (!IJ.isMacOSX() ? RUN_SOCKET_LISTENER : 0) + BLACK_BACKGROUND; - int options = getInt(OPTIONS, defaultOptions); - usePointerCursor = (options & USE_POINTER) != 0; - // antialiasedText = (options&ANTIALIASING)!=0; - antialiasedText = false; - interpolateScaledImages = (options & INTERPOLATE) != 0; - open100Percent = (options & ONE_HUNDRED_PERCENT) != 0; - //blackBackground = (options&BLACK_BACKGROUND)!=0; - useJFileChooser = (options & JFILE_CHOOSER) != 0; - weightedColor = (options & WEIGHTED) != 0; - if (weightedColor) - ColorProcessor.setWeightingFactors(0.299, 0.587, 0.114); - blackCanvas = (options & BLACK_CANVAS) != 0; - requireControlKey = (options & REQUIRE_CONTROL) != 0; - useInvertingLut = (options & USE_INVERTING_LUT) != 0; - antialiasedTools = (options & ANTIALIASED_TOOLS) != 0; - intelByteOrder = (options & INTEL_BYTE_ORDER) != 0; - noBorder = (options & NO_BORDER) != 0; - //showAllSliceOnly = (options & SHOW_ALL_SLICE_ONLY) != 0; - copyColumnHeaders = (options & COPY_HEADERS) != 0; - noRowNumbers = (options & NO_ROW_NUMBERS) != 0; - moveToMisc = (options & MOVE_TO_MISC) != 0; - runSocketListener = (options & RUN_SOCKET_LISTENER) != 0; - multiPointMode = (options & MULTI_POINT_MODE) != 0; - rotateYZ = (options & ROTATE_YZ) != 0; - flipXZ = (options & FLIP_XZ) != 0; - // dontSaveHeaders = (options&DONT_SAVE_HEADERS)!=0; - // dontSaveRowNumbers = (options&DONT_SAVE_ROW_NUMBERS)!=0; - noClickToGC = (options & NO_CLICK_TO_GC) != 0; - avoidResliceInterpolation = (options & AVOID_RESLICE_INTERPOLATION) != 0; - keepUndoBuffers = (options & KEEP_UNDO_BUFFERS) != 0; - - defaultOptions = (!IJ.isMacOSX() ? USE_FILE_CHOOSER : 0); - int options2 = getInt(OPTIONS2, defaultOptions); - useSystemProxies = (options2 & USE_SYSTEM_PROXIES) != 0; - useFileChooser = (options2 & USE_FILE_CHOOSER) != 0; - subPixelResolution = (options2 & SUBPIXEL_RESOLUTION) != 0; - enhancedLineTool = (options2 & ENHANCED_LINE_TOOL) != 0; - skipRawDialog = (options2 & SKIP_RAW_DIALOG) != 0; - reverseNextPreviousOrder = (options2 & REVERSE_NEXT_PREVIOUS_ORDER) != 0; - autoRunExamples = (options2 & AUTO_RUN_EXAMPLES) != 0; - showAllPoints = (options2 & SHOW_ALL_POINTS) != 0; - doNotSaveWindowLocations = (options2 & DO_NOT_SAVE_WINDOW_LOCS) != 0; - jFileChooserSettingChanged = (options2 & JFILE_CHOOSER_CHANGED) != 0; - dialogCancelButtonOnRight = (options2 & CANCEL_BUTTON_ON_RIGHT) != 0; - ignoreRescaleSlope = (options2 & IGNORE_RESCALE_SLOPE) != 0; - nonBlockingFilterDialogs = (options2 & NON_BLOCKING_DIALOGS) != 0; - fixedDicomScaling = (options2&FIXED_DICOM_SCALING)!=0; - //calibrateConversions = (options2&CALIBRATE_CONVERSIONS)!=0; - } - - static void saveOptions(Properties prefs) { - int options = (usePointerCursor ? USE_POINTER : 0) + (antialiasedText ? ANTIALIASING : 0) - + (interpolateScaledImages ? INTERPOLATE : 0) + (open100Percent ? ONE_HUNDRED_PERCENT : 0) - + (blackBackground ? BLACK_BACKGROUND : 0) + (useJFileChooser ? JFILE_CHOOSER : 0) - + (blackCanvas ? BLACK_CANVAS : 0) + (weightedColor ? WEIGHTED : 0) - + (requireControlKey ? REQUIRE_CONTROL : 0) + (useInvertingLut ? USE_INVERTING_LUT : 0) - + (intelByteOrder ? INTEL_BYTE_ORDER : 0) + (doubleBuffer ? DOUBLE_BUFFER : 0) - + (noPointLabels ? NO_POINT_LABELS : 0) + (noBorder ? NO_BORDER : 0) - + (showAllSliceOnly ? SHOW_ALL_SLICE_ONLY : 0) + (copyColumnHeaders ? COPY_HEADERS : 0) - + (noRowNumbers ? NO_ROW_NUMBERS : 0) + (moveToMisc ? MOVE_TO_MISC : 0) - + (runSocketListener ? RUN_SOCKET_LISTENER : 0) + (multiPointMode ? MULTI_POINT_MODE : 0) - + (rotateYZ ? ROTATE_YZ : 0) + (flipXZ ? FLIP_XZ : 0) + (dontSaveHeaders ? DONT_SAVE_HEADERS : 0) - + (dontSaveRowNumbers ? DONT_SAVE_ROW_NUMBERS : 0) + (noClickToGC ? NO_CLICK_TO_GC : 0) - + (avoidResliceInterpolation ? AVOID_RESLICE_INTERPOLATION : 0) - + (keepUndoBuffers ? KEEP_UNDO_BUFFERS : 0); - prefs.put(OPTIONS, Integer.toString(options)); - - int options2 = (useSystemProxies ? USE_SYSTEM_PROXIES : 0) + (useFileChooser ? USE_FILE_CHOOSER : 0) - + (subPixelResolution ? SUBPIXEL_RESOLUTION : 0) + (enhancedLineTool ? ENHANCED_LINE_TOOL : 0) - + (skipRawDialog ? SKIP_RAW_DIALOG : 0) + (reverseNextPreviousOrder ? REVERSE_NEXT_PREVIOUS_ORDER : 0) - + (autoRunExamples ? AUTO_RUN_EXAMPLES : 0) + (showAllPoints ? SHOW_ALL_POINTS : 0) - + (doNotSaveWindowLocations ? DO_NOT_SAVE_WINDOW_LOCS : 0) - + (jFileChooserSettingChanged ? JFILE_CHOOSER_CHANGED : 0) - + (dialogCancelButtonOnRight ? CANCEL_BUTTON_ON_RIGHT : 0) - + (ignoreRescaleSlope ? IGNORE_RESCALE_SLOPE : 0) - + (nonBlockingFilterDialogs?NON_BLOCKING_DIALOGS:0) - + (fixedDicomScaling?FIXED_DICOM_SCALING:0); - //+ (calibrateConversions?CALIBRATE_CONVERSIONS:0); - prefs.put(OPTIONS2, Integer.toString(options2)); - } - - /** - * Saves the Point loc in the preferences file as a string using - * the keyword key. - */ - public static void saveLocation(String key, Point loc) { - if (!doNotSaveWindowLocations) - set(key, loc != null ? loc.x + "," + loc.y : null); - } - - /** - * Uses the keyword key to retrieve a location from the preferences - * file. Returns null if the key is not found or the location is not valid - * (e.g., offscreen). - */ - public static Point getLocation(String key) { - String value = ijPrefs.getProperty(KEY_PREFIX + key); - if (value == null) - return null; - int index = value.indexOf(","); - if (index == -1) - return null; - double xloc = Tools.parseDouble(value.substring(0, index)); - if (Double.isNaN(xloc) || index == value.length() - 1) - return null; - double yloc = Tools.parseDouble(value.substring(index + 1)); - if (Double.isNaN(yloc)) - return null; - Point p = new Point((int) xloc, (int) yloc); - Rectangle bounds = GUI.getScreenBounds(p); // get bounds of screen that contains p - if (bounds != null && p.x + 100 <= bounds.x + bounds.width && p.y + 40 <= bounds.y + bounds.height) { - if (locKeys.get(key) == null) { // first time for this key? - locKeys.setProperty(key, ""); - Rectangle primaryScreen = GUI.getMaxWindowBounds(); - ImageJ ij = IJ.getInstance(); - Point ijLoc = ij != null ? ij.getLocation() : null; - //System.out.println("getLoc: "+key+" "+(ijLoc!=null&&primaryScreen.contains(ijLoc)) + " "+!primaryScreen.contains(p)); - if ((ijLoc != null && primaryScreen.contains(ijLoc)) && !primaryScreen.contains(p)) - return null; // return null if "ImageJ" window on primary screen and this location is not - } - return p; - } else - return null; - } - - /** Save plugin preferences. */ - static void savePluginPrefs(Properties prefs) { - Enumeration e = ijPrefs.keys(); - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - if (key.indexOf(KEY_PREFIX) == 0) - prefs.put(key, ijPrefs.getProperty(key)); - } - } - - public static void savePrefs(Properties prefs, String path) throws IOException { - FileOutputStream fos = new FileOutputStream(path); - BufferedOutputStream bos = new BufferedOutputStream(fos); - prefs.store(bos, "ImageJ " + ImageJ.VERSION + " Preferences"); - bos.close(); - } - - /** - * Returns the number of threads used by PlugInFilters to process images and - * stacks. - */ - public static int getThreads() { - if (threads == 0) { - threads = getInt(THREADS, 0); - int processors = Runtime.getRuntime().availableProcessors(); - if (threads < 1 || threads > processors) - threads = processors; - } - return threads; - } - - /** - * Sets the number of threads (1-32) used by PlugInFilters to process stacks. - */ - public static void setThreads(int n) { - if (n < 1) - n = 1; - threads = n; - } - - /** - * Sets the transparent index (0-255), or set to -1 to disable transparency. - */ - public static void setTransparentIndex(int index) { - if (index < -1 || index > 255) - index = -1; - transparentIndex = index; - } - - /** - * Returns the transparent index (0-255), or -1 if transparency is disabled. - */ - public static int getTransparentIndex() { - return transparentIndex; - } - - public static Properties getControlPanelProperties() { - return ijPrefs; - } - - public static String defaultResultsExtension() { - return get("options.ext", ".csv"); - } - - /** Sets the GenericDialog and Command Finder text scale (0.5 to 3.0). */ - public static void setGuiScale(double scale) { - if (scale >= 0.5 && scale <= 3.0) { - guiScale = scale; - set(GUI_SCALE, guiScale); - Roi.resetDefaultHandleSize(); - } - } - - /** Returns the GenericDialog and Command Finder text scale. */ - public static double getGuiScale() { - return guiScale; - } - - /** Returns the custom properties (IJ_Props.txt) file path. */ - public static String getCustomPropsPath() { - return propertiesPath; - } - - /** Returns the custom preferences (IJ_Prefs.txt) file path. */ - public static String getCustomPrefsPath() { - return preferencesPath; - } - - /** - * Retrieves a string from IJ_Props or IJ_Prefs.txt. Does not retrieve strings - * set using Prefs.set(). - */ - public static String getString(String key, String defaultString) { - if (props == null) - return defaultString; - String s = props.getProperty(key); - if (s == null) - return defaultString; - else - return s; - } - - /** Retrieves a string from string in IJ_Props or IJ_Prefs.txt. */ - public static String getString(String key) { - return props.getProperty(key); - } - - /** - * Retrieves a number from IJ_Props or IJ_Prefs.txt. Does not retrieve numbers - * set using Prefs.set(). - */ - public static int getInt(String key, int defaultValue) { - if (props == null) //workaround for Netscape JIT bug - return defaultValue; - String s = props.getProperty(key); - if (s != null) { - try { - return Integer.decode(s).intValue(); - } catch (NumberFormatException e) { - IJ.log("" + e); - } - } - return defaultValue; - } - - /** - * Retrieves a number from IJ_Props or IJ_Prefs.txt. Does not retrieve numbers - * set using Prefs.set(). - */ - public static double getDouble(String key, double defaultValue) { - if (props == null) - return defaultValue; - String s = props.getProperty(key); - Double d = null; - if (s != null) { - try { - d = Double.valueOf(s); - } catch (NumberFormatException e) { - d = null; - } - if (d != null) - return (d.doubleValue()); - } - return defaultValue; - } - - /** - * Retrieves a boolean from IJ_Props or IJ_Prefs.txt. Does not retrieve boolean - * set using Prefs.set(). - */ - public static boolean getBoolean(String key, boolean defaultValue) { - if (props == null) - return defaultValue; - String s = props.getProperty(key); - if (s == null) - return defaultValue; - else - return s.equals("true"); - } - - /** Finds a color in IJ_Props or IJ_Prefs.txt. */ - public static Color getColor(String key, Color defaultColor) { - int i = getInt(key, 0xaaa); - if (i == 0xaaa) - return defaultColor; - return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF); - } - - public static boolean commandLineMacro() { - return commandLineMacro; - } - -} diff --git a/com.eco.bio7.image/src/ij/RecentOpener.java b/com.eco.bio7.image/src/ij/RecentOpener.java deleted file mode 100644 index 8f0416209..000000000 --- a/com.eco.bio7.image/src/ij/RecentOpener.java +++ /dev/null @@ -1,37 +0,0 @@ -package ij; -import ij.io.*; -import java.awt.*; -import java.io.*; - -/** Opens, in a separate thread, files selected from the File/Open Recent submenu.*/ -public class RecentOpener implements Runnable { - private String path; - - RecentOpener(String path) { - this.path = path; - Thread thread = new Thread(this, "RecentOpener"); - thread.start(); - } - - /** Open the file and move the path to top of the submenu. */ - public void run() { - Opener o = new Opener(); - o.open(path); - Menu menu = Menus.getOpenRecentMenu(); - int n = menu.getItemCount(); - int index = 0; - for (int i=0; i0) { - MenuItem item = menu.getItem(index); - menu.remove(index); - menu.insert(item, 0); - } - } - -} - diff --git a/com.eco.bio7.image/src/ij/Undo.java b/com.eco.bio7.image/src/ij/Undo.java deleted file mode 100644 index ebdfcc64b..000000000 --- a/com.eco.bio7.image/src/ij/Undo.java +++ /dev/null @@ -1,233 +0,0 @@ -/**Implements the Edit/Undo command.*/ - -package ij; -import ij.process.*; -import ij.gui.*; -import ij.measure.Calibration; -import java.awt.*; -import java.awt.image.*; - -/** This class consists of static methods and - fields that implement ImageJ's Undo command. */ -public class Undo { - - public static final int NOTHING = 0; - /** Undo using ImageProcessor.snapshot. */ - public static final int FILTER = 1; - /** Undo using an ImageProcessor copy. */ - public static final int TYPE_CONVERSION = 2; - public static final int PASTE = 3; - public static final int COMPOUND_FILTER = 4; - public static final int COMPOUND_FILTER_DONE = 5; - /** Undo using a single image, or composite color stack, copy (limited to 200MB). */ - public static final int TRANSFORM = 6; - public static final int OVERLAY_ADDITION = 7; - public static final int ROI = 8; - public static final int MACRO = 9; - /** Undo of overlay modification */ - public static final int OVERLAY = 10; - - private static int whatToUndo = NOTHING; - private static int imageID; - private static ImageProcessor ipCopy = null; - private static ImagePlus impCopy; - private static Calibration calCopy; - private static Roi roiCopy; - private static double displayRangeMin, displayRangeMax; - private static LUT lutCopy; - private static Overlay overlayCopy; - private static int overlayImageID; - - public static void setup(int what, ImagePlus imp) { - if (imp==null) { - whatToUndo = NOTHING; - reset(); - return; - } - if (IJ.debugMode) IJ.log("Undo.setup: "+what+" "+imp); - if (what==FILTER && whatToUndo==COMPOUND_FILTER) - return; - if (what==COMPOUND_FILTER_DONE) { - if (whatToUndo==COMPOUND_FILTER) - whatToUndo = what; - return; - } - whatToUndo = what; - imageID = imp.getID(); - if (what==TYPE_CONVERSION) { - ipCopy = imp.getProcessor(); - calCopy = (Calibration)imp.getCalibration().clone(); - } else if (what==TRANSFORM) { - if ((!IJ.macroRunning()||Prefs.supportMacroUndo) && (imp.getStackSize()==1||imp.getDisplayMode()==IJ.COMPOSITE) && imp.getSizeInBytes()<209715200) - impCopy = imp.duplicate(); - else - reset(); - } else if (what==MACRO) { - ipCopy = imp.getProcessor().duplicate(); - calCopy = (Calibration)imp.getCalibration().clone(); - impCopy = null; - } else if (what==COMPOUND_FILTER) { - ImageProcessor ip = imp.getProcessor(); - if (ip!=null) - ipCopy = ip.duplicate(); - else - ipCopy = null; - } else if (what==OVERLAY_ADDITION) { - impCopy = null; - ipCopy = null; - } else if (what==ROI) { - impCopy = null; - ipCopy = null; - Roi roi = imp.getRoi(); - if (roi!=null) { - roiCopy = (Roi)roi.clone(); - roiCopy.setImage(null); - } else - whatToUndo = NOTHING; - } else if (what==OVERLAY) { - saveOverlay(imp); - } else { - ipCopy = null; - //ImageProcessor ip = imp.getProcessor(); - //lutCopy = (LUT)ip.getLut().clone(); - } - } - - /** This function should be called from PlugInFilters that modify the overlay prior to the operation. - * For the type 'FILTER', undo of overlays requires that the modified image also has an overlay. */ - public static void saveOverlay(ImagePlus imp) { - Overlay overlay = imp!=null?imp.getOverlay():null; - if (overlay!=null) { - overlayCopy = overlay.duplicate(); - overlayImageID = imp.getID(); - } else - overlayCopy = null; - } - - public static void reset() { - //if (IJ.debugMode) IJ.log("Undo.reset: "+ whatToUndo+" "+impCopy); - if (whatToUndo==COMPOUND_FILTER || whatToUndo==OVERLAY_ADDITION) - return; - whatToUndo = NOTHING; - imageID = 0; - ipCopy = null; - impCopy = null; - calCopy = null; - roiCopy = null; - lutCopy = null; - overlayCopy = null; - } - - public static void undo() { - ImagePlus imp = WindowManager.getCurrentImage(); - if (IJ.debugMode) IJ.log("Undo.undo: "+ whatToUndo+" "+imp+" "+impCopy); - if (imp==null || imageID!=imp.getID()) { - if (imp!=null && !IJ.macroRunning()) { // does foreground image still have an undo buffer? - ImageProcessor ip2 = imp.getProcessor(); - ip2.swapPixelArrays(); - imp.updateAndDraw(); - } else - reset(); - return; - } - switch (whatToUndo) { - case FILTER: - undoOverlay(imp, true); - ImageProcessor ip = imp.getProcessor(); - if (ip!=null) { - if (!IJ.macroRunning()) { - ip.swapPixelArrays(); - imp.updateAndDraw(); - return; // don't reset - } else { - ip.reset(); - imp.updateAndDraw(); - } - } - break; - case TYPE_CONVERSION: - case COMPOUND_FILTER: - case COMPOUND_FILTER_DONE: - if (ipCopy!=null) { - if (whatToUndo==TYPE_CONVERSION && calCopy!=null) - imp.setCalibration(calCopy); - if (swapImages(new ImagePlus("",ipCopy), imp)) { - imp.updateAndDraw(); - return; - } else - imp.setProcessor(null, ipCopy); - if (whatToUndo==COMPOUND_FILTER_DONE || whatToUndo==TYPE_CONVERSION) - undoOverlay(imp, true); - } - break; - case TRANSFORM: - if (impCopy!=null) - imp.setStack(impCopy.getStack()); - break; - case PASTE: - Roi roi = imp.getRoi(); - if (roi!=null) - roi.abortPaste(); - break; - case ROI: - Roi roiCopy2 = roiCopy; - setup(ROI, imp); // setup redo - imp.setRoi(roiCopy2); - return; //don't reset - case MACRO: - if (ipCopy!=null) { - imp.setProcessor(ipCopy); - if (calCopy!=null) imp.setCalibration(calCopy); - } - break; - case OVERLAY_ADDITION: - Overlay overlay = imp.getOverlay(); - if (overlay==null) - {IJ.beep(); return;} - int size = overlay.size(); - if (size>0) { - overlay.remove(size-1); - imp.draw(); - } else { - IJ.beep(); - return; - } - return; //don't reset; successive undo removes further rois - case OVERLAY: - undoOverlay(imp, false); - imp.draw(); - break; - } - reset(); - } - - /** Reverts the overlay to the saved version. */ - private static void undoOverlay(ImagePlus imp, boolean onlyModifyOvly) { - if (overlayCopy!=null && imp.getID()==overlayImageID) { - Overlay overlay = imp.getOverlay(); - imp.setOverlay(overlayCopy); - if (overlay != null) - overlayCopy = overlay.duplicate(); //swap - } - } - - static boolean swapImages(ImagePlus imp1, ImagePlus imp2) { - if (imp1.getWidth()!=imp2.getWidth() || imp1.getHeight()!=imp2.getHeight() - || imp1.getBitDepth()!=imp2.getBitDepth() || IJ.macroRunning()) - return false; - ImageProcessor ip1 = imp1.getProcessor(); - ImageProcessor ip2 = imp2.getProcessor(); - double min1 = ip1.getMin(); - double max1 = ip1.getMax(); - double min2 = ip2.getMin(); - double max2 = ip2.getMax(); - ip2.setSnapshotPixels(ip1.getPixels()); - ip2.swapPixelArrays(); - ip1.setPixels(ip2.getSnapshotPixels()); - ip2.setSnapshotPixels(null); - ip1.setMinAndMax(min2, max2); - ip2.setMinAndMax(min1, max1); - return true; - } - -} diff --git a/com.eco.bio7.image/src/ij/VirtualStack.java b/com.eco.bio7.image/src/ij/VirtualStack.java deleted file mode 100644 index 72a5ebd64..000000000 --- a/com.eco.bio7.image/src/ij/VirtualStack.java +++ /dev/null @@ -1,433 +0,0 @@ -package ij; -import ij.process.*; -import ij.io.*; -import ij.gui.ImageCanvas; -import ij.util.Tools; -import ij.plugin.FolderOpener; -import java.io.*; -import java.awt.*; -import java.awt.image.ColorModel; -import java.util.Properties; - -/** This class represents an array of disk-resident images. */ -public class VirtualStack extends ImageStack { - private static final int INITIAL_SIZE = 100; - private String path; - private int nSlices; - private String[] names; - private String[] labels; - private int bitDepth; - private int delay; - private Properties properties; - private boolean generateData; - private int[] indexes; // used to translate non-CZT hyperstack slice numbers (0-based) - /** subclasses that support translation of slice indices (by calling translate) should set this to true */ - protected boolean canTranslate; - - - /** Default constructor. */ - public VirtualStack() { } - - public VirtualStack(int width, int height) { - super(width, height); - } - - /** Creates an empty virtual stack. - * @param width image width - * @param height image height - * @param cm ColorModel or null - * @param path file path of directory containing the images - * @see #addSlice(String) - * @see OpenAsVirtualStack.js - */ - public VirtualStack(int width, int height, ColorModel cm, String path) { - super(width, height, cm); - path = IJ.addSeparator(path); - this.path = path; - if (path != null) - canTranslate = true; - names = new String[INITIAL_SIZE]; - labels = new String[INITIAL_SIZE]; - } - - /** Creates a virtual stack with no backing storage. - * See: Help>Examples>JavaScript>Terabyte VirtualStack - */ - public VirtualStack(int width, int height, int slices) { - this(width, height, slices, "8-bit"); - } - - /** Creates a virtual stack with no backing storage. - * See: Help>Examples>JavaScript>Terabyte VirtualStack - */ - public VirtualStack(int width, int height, int slices, String options) { - super(width, height, null); - nSlices = slices; - int depth = 8; - if (options.contains("16-bit")) depth=16; - if (options.contains("RGB")) depth=24; - if (options.contains("32-bit")) depth=32; - if (options.contains("delay")) delay=250; - this.generateData = options.contains("fill"); - this.bitDepth = depth; - } - - /** Adds an image to the end of a virtual stack created using the - * VirtualStack(w,h,cm,path) constructor. The argument - * can be a full file path (e.g., "C:/Users/wayne/dir1/image.tif") - * if the 'path' argument in the constructor is "". File names - * that start with '.' are ignored. - */ - public void addSlice(String fileName) { - if (fileName==null) - throw new IllegalArgumentException("'fileName' is null!"); - if (fileName.startsWith(".")) - return; - if (names==null) - throw new IllegalArgumentException("This Virtual Stack cannot be modified [VirtualStack(w,h,cm,path) constructor not used]"); - if (isTranslatingIndices()) - throw new IllegalArgumentException("Virtual hyperstack with non-czt order cannot be modified"); - nSlices++; - expandArrays(nSlices); - names[nSlices-1] = fileName; - } - - /** Expands the 'names' and 'labels' arrays if existing and smaller than minSize. - * This should be called each time the stack is enlarged */ - protected void expandArrays(int minSize) { - if (indexes != null && minSize < indexes.length) - minSize = indexes.length; //min size if slices were deleted previously - if (names != null && names.length < minSize) { - String[] tmp = new String[minSize*2]; - System.arraycopy(names, 0, tmp, 0, names.length); - names = tmp; - } - if (labels != null && labels.length < minSize) { - String[] tmp = new String[minSize*2]; - System.arraycopy(labels, 0, tmp, 0, labels.length); - labels = tmp; - } - } - - /** Does nothing. */ - public void addSlice(String sliceLabel, Object pixels) { - } - - /** Does nothing.. */ - public void addSlice(String sliceLabel, ImageProcessor ip) { - } - - /** Does nothing. */ - public void addSlice(String sliceLabel, ImageProcessor ip, int n) { - } - - /** Deletes the specified slice, where {@literal 1<=n<=nslices}. */ - public void deleteSlice(int n) { - if (nSlices==0) - return; - if (n<1 || n>nSlices) - throw new IllegalArgumentException("Argument out of range: "+n); - if (names==null) - throw new IllegalArgumentException("This Virtual Stack cannot be modified [VirtualStack(w,h,cm,path) constructor not used]"); - if (isTranslatingIndices()) - throw new IllegalArgumentException("Virtual hyperstack with non-czt order cannot be modified"); - for (int i=n; i0) - deleteSlice(n); - } - - /** Returns the pixel array for the specified slice, where {@literal 1<=n<=nslices}. */ - public Object getPixels(int n) { - ImageProcessor ip = getProcessor(n); - if (ip!=null) - return ip.getPixels(); - else - return null; - } - - public void setPixels(Object pixels, int n) { - } - - /** Returns an ImageProcessor for the specified slice, - * where {@literal 1<=n<=nslices}. Returns null if - * the stack is empty. - * When overriding this function, note that the ImageProcessor - * may be modified at a later time. Its pixel array - * can get replaced by the pixel array of another slice. - * This is because the ImageProcessor may be re-used when a - * different slice is accessed via ImagePlus.setSlice. - * {@link Example} - */ - public ImageProcessor getProcessor(int n) { - if (path==null) { //Help>Examples>JavaScript>Terabyte VirtualStack - ImageProcessor ip = null; - int w=getWidth(), h=getHeight(); - switch (bitDepth) { - case 8: ip = new ByteProcessor(w,h); break; - case 16: ip = new ShortProcessor(w,h); break; - case 24: ip = new ColorProcessor(w,h); break; - case 32: ip = new FloatProcessor(w,h); break; - } - String hlabel = null; - if (generateData) { - int value = 0; - ImagePlus img = WindowManager.getCurrentImage(); - if (img!=null && img.getStackSize()==nSlices) - value = img.getCurrentSlice()-1; - if (bitDepth==16) - value *= 256; - if (bitDepth!=32) { - for (int i=0; i0) - IJ.wait(delay); - return ip; - } - n = translate(n); // update n for hyperstacks not in the default CZT order - Opener opener = new Opener(); - opener.setSilentMode(true); - IJ.redirectErrorMessages(true); - ImagePlus imp = opener.openTempImage(path, names[n-1]); - IJ.redirectErrorMessages(false); - ImageProcessor ip = null; - int depthThisImage = 0; - if (imp!=null) { - int w = imp.getWidth(); - int h = imp.getHeight(); - int type = imp.getType(); - ColorModel cm = imp.getProcessor().getColorModel(); - String info = (String)imp.getProperty("Info"); - if (info!=null) { - if (FolderOpener.useInfo(info)) - setSliceLabel(info, n); - } else { - String sliceLabel = imp.getStack().getSliceLabel(1); - if (FolderOpener.useInfo(sliceLabel)) - setSliceLabel("Label: "+sliceLabel, n); - } - depthThisImage = imp.getBitDepth(); - ip = imp.getProcessor(); - ip.setOverlay(imp.getOverlay()); - properties = imp.getProperty("FHT")!=null?imp.getProperties():null; - } else { - File f = new File(path, names[n-1]); - String msg = f.exists()?"Error opening ":"File not found: "; - ip = new ByteProcessor(getWidth(), getHeight()); - ip.invert(); - label(ip, msg+names[n-1], Color.black); - depthThisImage = 8; - } - if (depthThisImage!=bitDepth) { - switch (bitDepth) { - case 8: ip=ip.convertToByte(true); break; - case 16: ip=ip.convertToShort(true); break; - case 24: ip=ip.convertToRGB(); break; - case 32: ip=ip.convertToFloat(); break; - } - } - if (ip.getWidth()!=getWidth() || ip.getHeight()!=getHeight()) { - ImageProcessor ip2 = ip.createProcessor(getWidth(), getHeight()); - ip2.insert(ip, 0, 0); - ip = ip2; - } - if (cTable!=null) - ip.setCalibrationTable(cTable); - ip.setSliceNumber(n); - return ip; - } - - /** Draw label for Help>Examples>JavaScript>Terabyte VirtualStack */ - private void label(ImageProcessor ip, String msg, Color color) { - int size = getHeight()/20; - if (size<9) size=9; - Font font = new Font("Helvetica", Font.PLAIN, size); - ip.setFont(font); - ip.setAntialiasedText(true); - ip.setColor(color); - ip.drawString(msg, size, size*2); - } - - /** Currently not implemented */ - public int saveChanges(int n) { - return -1; - } - - /** Returns the number of slices in this stack. */ - public int size() { - return getSize(); - } - - /** Returns the number of slices in this stack. Subclasses shold override this function. */ - public int getSize() { - return nSlices; - } - - /** Returns the label of the Nth image. */ - public String getSliceLabel(int n) { - if (isTranslatingIndices()) - n = translate(n); - if (labels==null) - return null; - String label = (n<=labels.length) ? labels[n-1] : null; //subclass may have grown stack without adding labels - if (names == null) - return label; - if (label==null) - return names[n-1]; - else { - if (label.startsWith("Label: ")) // slice label - return label.substring(7,label.length()); - else - return names[n-1]+"\n"+label; - } - } - - /** Returns null. */ - public Object[] getImageArray() { - return null; - } - - /** Sets the label of the specified slice, where {@literal 1<=n<=nSlices}. */ - public void setSliceLabel(String label, int n) { - if (n <= 0 || n > getSize()) - throw new IllegalArgumentException(outOfRange+n); - if (isTranslatingIndices()) - n = translate(n); - if (labels == null) - labels = new String[getSize()]; - expandArrays(getSize()); - labels[n-1] = label; - } - - /** Sets the array of slice labels. The array size must be the stack size or larger */ - protected void setSliceLabels(String[] labels) { - if (labels != null && labels.length < getSize()) - throw new IllegalArgumentException("Labels array too short: "+labels.length); - this.labels = labels; - } - - /** Always returns true. */ - public boolean isVirtual() { - return true; - } - - /** Does nothing. */ - public void trim() { - } - - /** Returns the path to the directory containing the images. */ - public String getDirectory() { - return IJ.addSeparator(path); - } - - /** Returns the file name of the specified slice, where {@literal 1<=n<=nslices}. */ - public String getFileName(int n) { - return names[n-1]; - } - - /** Sets the bit depth (8, 16, 24 or 32). */ - public void setBitDepth(int bitDepth) { - this.bitDepth = bitDepth; - } - - /** Returns the bit depth (8, 16, 24 or 32), or 0 if the bit depth is not known. */ - public int getBitDepth() { - return bitDepth; - } - - public ImageStack sortDicom(String[] strings, String[] info, int maxDigits) { - int n = size(); - String[] names2 = new String[n]; - for (int i=0; ihyperstack>stack>hyperstack to reshuffle) - indexes = indexes.clone(); - for (int i=0; i 0) { - ImagePlus imp = getFocusManagerActiveImage(); - if (imp != null) - return imp; - ImageWindow win = (ImageWindow) imageList.get(imageList.size() - 1); - return win.getImagePlus(); - } else - return Interpreter.getLastBatchModeImage(); - } - - private static ImagePlus getFocusManagerActiveImage() { - if (IJ.isMacro()) - return null; - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Window win = kfm.getActiveWindow(); - ImagePlus imp = null; - if (win != null && (win instanceof ImageWindow)) - imp = ((ImageWindow) win).getImagePlus(); - return imp; - } - - /** Returns the number of open image windows. */ - public static int getWindowCount() { - int count = imageList.size(); - return count; - } - - /** Returns the number of open images. */ - public static int getImageCount() { - int count = imageList.size(); - count += Interpreter.getBatchModeImageCount(); - if (count == 0 && getCurrentImage() != null) - count = 1; - return count; - } - - /** Returns the front most window or null. */ - public static Window getActiveWindow() { - return frontWindow; - } - - /** Returns the Window containing the active table, or null. - * @see ij.measure.ResultsTable#getActiveTable - */ - public static Window getActiveTable() { - return frontTable; - } - - - - /** Obsolete; replaced by getActiveWindow. */ - public static Frame getFrontWindow() { - return frontFrame; - } - - /** - * Returns a list of the IDs of open images. Returns null if no image windows - * are open. - */ - public synchronized static int[] getIDList() { - int nWindows = imageList.size(); - int[] batchModeImages = Interpreter.getBatchModeImageIDs(); - int nBatchImages = batchModeImages.length; - if ((nWindows + nBatchImages) == 0) - return null; - int[] list = new int[nWindows + nBatchImages]; - for (int i=0; i 0) - imageID = getNthImageID(imageID); - if (imageID == 0 || getImageCount() == 0) - return null; - ImagePlus imp2 = Interpreter.getBatchModeImage(imageID); - if (imp2 != null) - return imp2; - ImagePlus imp = null; - for (int i = 0; i < imageList.size(); i++) { - ImageWindow win = (ImageWindow) imageList.get(i); - imp2 = win.getImagePlus(); - if (imageID == imp2.getID()) { - imp = imp2; - break; - } - } - imp2 = getCurrentImage(); - if (imp == null && imp2 != null && imp2.getID() == imageID) - return imp2; - return imp; - } - - /** - * Returns the ID of the Nth open image. Returns zero if n<=0 or n greater than - * the number of open image windows. - */ - public synchronized static int getNthImageID(int n) { - if (n <= 0) - return 0; - if (Interpreter.isBatchMode()) { - int[] list = getIDList(); - if (n > list.length) - return 0; - else - return list[n - 1]; - } else { - if (n > imageList.size()) - return 0; - ImageWindow win = (ImageWindow) imageList.get(n - 1); - if (win != null) - return win.getImagePlus().getID(); - else - return 0; - } - } - - /** - * Returns the first image that has the specified title or null if it is not - * found. - */ - public synchronized static ImagePlus getImage(String title) { - int[] wList = getIDList(); - if (wList == null) - return null; - for (int i = 0; i < wList.length; i++) { - ImagePlus imp = getImage(wList[i]); - if (imp != null && imp.getTitle().equals(title)) - return imp; - } - return null; - } - - /** Adds the specified window to the Window menu. */ - public synchronized static void addWindow(Window win) { - if (win == null) - return; - else if (win instanceof ImageWindow) - addImageWindow((ImageWindow) win); - else { - /* Changed for Bio7! */ - Menus.insertWindowMenuItem(win); - nonImageList.add(win); - } - } - - /** Adds the specified Frame to the Window menu. */ - public static void addWindow(Frame win) { - addWindow((Window) win); - } - - private static void addImageWindow(ImageWindow win) { - ImagePlus imp = win.getImagePlus(); - if (imp == null) - return; - checkForDuplicateName(imp); - imageList.add(win); - Menus.addWindowMenuItem(imp); - setCurrentWindow(win); - } - - static void checkForDuplicateName(ImagePlus imp) { - if (checkForDuplicateName) { - String name = imp.getTitle(); - if (isDuplicateName(name)) - imp.setTitle(getUniqueName(name)); - } - checkForDuplicateName = false; - } - - static boolean isDuplicateName(String name) { - if (name==null) - return false; - int n = imageList.size(); - for (int i = 0; i < n; i++) { - ImageWindow win = (ImageWindow) imageList.get(i); - String name2 = win.getImagePlus().getTitle(); - if (name.equals(name2)) - return true; - } - return false; - } - - /* - static boolean isDuplicateBatchModeName(String name) { - int[] list = getIDList(); - for (int i=0; i= 0) { - Menus.removeWindowMenuItem(index); - nonImageList.removeElement(win); - } - if (win!=null && win==frontTable) - frontTable = null; - } - setWindow(null); - } - - /** Removes the specified Frame from the Window menu. */ - public static void removeWindow(Frame win) { - removeWindow((Window) win); - } - - private static void removeImageWindow(ImageWindow win) { - int index = imageList.indexOf(win); - if (index == -1) - return; // not on the window list - try { - synchronized(WindowManager.class) { - imageList.remove(win); - } - activations.remove(win); - if (imageList.size() > 1 && !Prefs.closingAll) { - ImageWindow win2 = activations.size() > 0 ? (ImageWindow) activations.get(activations.size() - 1) : null; - setCurrentWindow(win2); - } else - currentWindow = null; - setTempCurrentImage(null); // ??? - int nonImageCount = nonImageList.size(); - if (nonImageCount > 0) - nonImageCount++; - Menus.removeWindowMenuItem(nonImageCount + index); - Menus.updateMenus(); - Undo.reset(); - } catch (Exception e) { - } - } - - /** The specified Window becomes the front window. */ - public static void setWindow(Window win) { - /* Changed for Bio7? - Probably not necessary! */ - // System.out.println("setWindow(W): "+win); - frontWindow = win; - if (win instanceof Frame) - frontFrame = (Frame) win; - - - } - - /** - * The specified frame becomes the front window, the one returnd by - * getFrontWindow(). - */ - public static void setWindow(Frame win) { - /* Changed for Bio7? - Probably not necessary! */ - - frontWindow = win; - frontFrame = win; - if (win!=null && win instanceof TextWindow && !(win instanceof Editor) && !"Log".equals(((TextWindow)win).getTitle())) - frontTable = win; - - // System.out.println("Set window(F): "+(win!=null?win.getTitle():"null")); - } - - /** - * Closes all windows. Stops and returns false if an image or Editor "save - * changes" dialog is canceled. - */ - public synchronized static boolean closeAllWindows() { - Prefs.closingAll = true; - while (imageList.size() > 0) { - /* Changed for Bio7! */ - if (!((ImageWindow) imageList.get(0)).bio7TabClose(true)) { - Prefs.closingAll = false; - return false; - } - if (!quittingViaMacro()) - IJ.wait(100); - } - Prefs.closingAll = false; - JFrame[] nonImages = getNonImageWindows(); - for (int i = 0; i < nonImages.length; i++) { - Frame frame = nonImages[i]; - if (frame != null && frame instanceof Commands) - ((Commands) frame).close(); - else if (frame != null && (frame instanceof Editor)) { - ((Editor) frame).close(); - if (((Editor) frame).fileChanged()) - return false; - if (!quittingViaMacro()) - IJ.wait(100); - } - } - ImageJ ij = IJ.getInstance(); - if (ij != null && ij.quitting() && IJ.getApplet() == null) - return true; - for (int i = 0; i < nonImages.length; i++) { - Frame frame = nonImages[i]; - if ((frame instanceof PlugInFrame) && !(frame instanceof Editor)) - ((PlugInFrame) frame).close(); - else if (frame instanceof TextWindow) - ((TextWindow) frame).close(); - else { - // frame.setVisible(false); - frame.dispose(); - } - } - return true; - } - - private static boolean quittingViaMacro() { - ImageJ ij = IJ.getInstance(); - return ij != null && ij.quittingViaMacro(); - } - - /** Activates the next image window on the window list. */ - public static void putBehind() { - if (IJ.debugMode) - IJ.log("putBehind"); - if (imageList.size() < 1 || currentWindow == null) - return; - int index = imageList.indexOf(currentWindow); - ImageWindow win = null; - int count = 0; - do { - index--; - if (index < 0) - index = imageList.size() - 1; - win = (ImageWindow) imageList.get(index); - if (++count == imageList.size()) - return; - } while (win instanceof HistogramWindow || win instanceof PlotWindow); - if (win == null) - return; - ImagePlus imp = win.getImagePlus(); - if (imp != null) - IJ.selectWindow(imp.getID()); - } - - /** Returns the temporary current image for this thread, or null. */ - public static ImagePlus getTempCurrentImage() { - return (ImagePlus) tempImageTable.get(Thread.currentThread()); - } - - /** - * Returns the window (a Frame or a Dialog) with the specified title, or null if - * a window with that title is not found. - */ - public static Window getWindow(String title) { - for (int i = 0; i < nonImageList.size(); i++) { - Object win = nonImageList.get(i); - String winTitle = win instanceof Frame ? ((Frame) win).getTitle() : ((Dialog) win).getTitle(); - if (title.equals(winTitle)) - return (Window) win; - } - return getImageWindow(title); - } - - /** Obsolete; replaced by getWindow(). */ - public static Frame getFrame(String title) { - for (int i = 0; i < nonImageList.size(); i++) { - Object win = nonImageList.get(i); - String winTitle = win instanceof Frame ? ((Frame) win).getTitle() : null; - if (title.equals(winTitle)) - return (Frame) win; - } - Frame frame = getImageWindow(title); - if (frame == null) { - Window win = getWindow(title); - if (win != null) - frame = new Frame("Proxy"); - } - return frame; - } - - private static Frame getImageWindow(String title) { - int[] wList = getIDList(); - int len = wList != null ? wList.length : 0; - for (int i = 0; i < len; i++) { - ImagePlus imp = getImage(wList[i]); - if (imp != null) { - if (imp.getTitle().equals(title)) - return imp.getWindow(); - } - } - return null; - } - - /** Activates a window selected from the Window menu. */ - public synchronized static void activateWindow(String menuItemLabel, MenuItem item) { - for (int i = 0; i < nonImageList.size(); i++) { - Object win = nonImageList.get(i); - String title = win instanceof Frame ? ((Frame) win).getTitle() : ((Dialog) win).getTitle(); - if (menuItemLabel.equals(title)) { - if (win instanceof Frame) { - toFront((Frame) win); - /* Changed for Bio7! */ - // IJTabs.setActiveTab(menuItemLabel); - } else - ((Dialog) win).toFront(); - ((CheckboxMenuItem) item).setState(false); - if (IJ.recording() && !IJ.isMacro()) - Recorder.record("selectWindow", title); - return; - } - } - int lastSpace = menuItemLabel.lastIndexOf(' '); - if (lastSpace > 0) // remove image size (e.g., " 90K") - menuItemLabel = menuItemLabel.substring(0, lastSpace); - String idString = item.getActionCommand(); - int id = (int) Tools.parseDouble(idString, 0); - ImagePlus imp = WindowManager.getImage(id); - if (imp == null) - return; - ImageWindow win1 = imp.getWindow(); - if (win1 == null) - return; - setCurrentWindow(win1); - toFront(win1); - /* Changed for Bio7! */ - // IJTabs.setActiveTabWindow(win1); - int index = imageList.indexOf(win1); - int n = Menus.window.getItemCount(); - int start = Menus.WINDOW_MENU_ITEMS + Menus.windowMenuItems2; - for (int j = start; j < n; j++) { - MenuItem mi = Menus.window.getItem(j); - if (mi instanceof CheckboxMenuItem) - ((CheckboxMenuItem) mi).setState((j - start) == index); - } - } - - /** Repaints all open image windows. */ - public synchronized static void repaintImageWindows() { - int[] list = getIDList(); - if (list == null) - return; - for (int i = 0; i < list.length; i++) { - ImagePlus imp2 = getImage(list[i]); - if (imp2 != null) { - imp2.setTitle(imp2.getTitle()); // update "(G)" flag (global - // calibration) - ImageWindow win = imp2.getWindow(); - if (win != null) - win.repaint(); - } - } - } - - public static void showList() { - for (int i = 0; i < imageList.size(); i++) { - ImageWindow win = (ImageWindow) imageList.get(i); - ImagePlus imp = win.getImagePlus(); - IJ.log(i + " " + imp.getTitle() + (win == currentWindow ? "*" : "") + " " + imp.getID()); - } - for (int i = 0; i < activations.size(); i++) { - ImageWindow win = (ImageWindow) activations.get(i); - ImagePlus imp = win.getImagePlus(); - IJ.log(i + " " + imp.getTitle() + " " + imp.getID()); - } - if (imageList.size() == 0) - IJ.log("imageList is empty"); - if (activations.size() == 0) - IJ.log("activations list is empty"); - IJ.log(" "); - } - - public static void toFront(Frame frame) { - if (frame == null) - return; - if (frame.getState() == Frame.ICONIFIED) - frame.setState(Frame.NORMAL); - frame.toFront(); - } - - public static void toFront(Window window) { - if (window == null) - return; - if (window instanceof Frame && ((Frame) window).getState() == Frame.ICONIFIED) - ((Frame) window).setState(Frame.NORMAL); - window.toFront(); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/Arrow.java b/com.eco.bio7.image/src/ij/gui/Arrow.java deleted file mode 100644 index 4427a0903..000000000 --- a/com.eco.bio7.image/src/ij/gui/Arrow.java +++ /dev/null @@ -1,421 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import java.awt.*; -import java.awt.geom.*; - - -/** This is an Roi subclass for creating and displaying arrows. */ -public class Arrow extends Line { - public static final String STYLE_KEY = "arrow.style"; - public static final String WIDTH_KEY = "arrow.width"; - public static final String SIZE_KEY = "arrow.size"; - public static final String DOUBLE_HEADED_KEY = "arrow.double"; - public static final String OUTLINE_KEY = "arrow.outline"; - public static final int FILLED=0, NOTCHED=1, OPEN=2, HEADLESS=3, BAR=4; - public static final String[] styles = {"Filled", "Notched", "Open", "Headless", "Bar"}; - private static int defaultStyle = (int)Prefs.get(STYLE_KEY, FILLED); - private static float defaultWidth = (float)Prefs.get(WIDTH_KEY, 2); - private static double defaultHeadSize = (int)Prefs.get(SIZE_KEY, 10); // 0-30; - private static boolean defaultDoubleHeaded = Prefs.get(DOUBLE_HEADED_KEY, false); - private static boolean defaultOutline = Prefs.get(OUTLINE_KEY, false); - private int style; - private double headSize = 10; // 0-30 - private boolean doubleHeaded; - private boolean outline; - private float[] points = new float[2*5]; - private GeneralPath path = new GeneralPath(); - private static Stroke defaultStroke = new BasicStroke(); - double headShaftRatio; - - static { - if (defaultStyleHEADLESS) - defaultStyle = FILLED; - } - - public Arrow(double ox1, double oy1, double ox2, double oy2) { - super(ox1, oy1, ox2, oy2); - setStrokeWidth(2); - } - - public Arrow(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - setStrokeWidth(defaultWidth); - style = defaultStyle; - headSize = defaultHeadSize; - doubleHeaded = defaultDoubleHeaded; - outline = defaultOutline; - setStrokeColor(Toolbar.getForegroundColor()); - } - - /** Draws this arrow on the image. */ - public void draw(Graphics g) { - Shape shape2 = null; - if (doubleHeaded) { - flipEnds(); - shape2 = getShape(); - flipEnds(); - } - Shape shape = getShape(); - if (shape==null) - return; - Color color = strokeColor!=null? strokeColor:ROIColor; - if (fillColor!=null) color = fillColor; - g.setColor(color); - Graphics2D g2 = (Graphics2D)g; - setRenderingHint(g2); - AffineTransform at = g2.getDeviceConfiguration().getDefaultTransform(); - double mag = getMagnification(); - int xbase=0, ybase=0; - if (ic!=null) { - Rectangle r = ic.getSrcRect(); - xbase = r.x; ybase = r.y; - } - at.setTransform(mag, 0.0, 0.0, mag, (-xbase+0.5)*mag, (-ybase+0.5)*mag); //0.5: int coordinate at pixel center - if (outline) { - float lineWidth = (float)(getOutlineWidth()*mag); - g2.setStroke(new BasicStroke(lineWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); - g2.draw(at.createTransformedShape(shape)); - if (doubleHeaded) g2.draw(at.createTransformedShape(shape2)); - g2.setStroke(defaultStroke); - } else { - g2.fill(at.createTransformedShape(shape)); - if (doubleHeaded) g2.fill(at.createTransformedShape(shape2)); - } - if (!overlay) { - handleColor=Color.white; - drawHandle(g, screenXD(x1d), screenYD(y1d)); - drawHandle(g, screenXD(x2d), screenYD(y2d)); - drawHandle(g, screenXD(x1d+(x2d-x1d)/2.0), screenYD(y1d+(y2d-y1d)/2.0)); - } - if (state!=NORMAL && imp!=null && imp.getRoi()!=null) - showStatus(); - if (updateFullWindow) - {updateFullWindow = false; imp.draw();} - } - - private void flipEnds() { - double tmp = x1R; - x1R=x2R; - x2R=tmp; - tmp=y1R; - y1R=y2R; - y2R=tmp; - } - - private Shape getPath() { - path.reset(); - path = new GeneralPath(); - calculatePoints(); - float tailx = points[0]; - float taily = points[1]; - float headbackx = points[2*1]; - float headbacky = points[2*1+1]; - float headtipx = points[2*3]; - float headtipy = points[2*3+1]; - if (outline) { - double dx = headtipx - tailx; - double dy = headtipy - taily; - double shaftLength = Math.sqrt(dx*dx+dy*dy); - dx = headtipx - headbackx; - dy = headtipy- headbacky; - double headLength = Math.sqrt(dx*dx+dy*dy); - headShaftRatio = headLength/shaftLength; - if (headShaftRatio>1.0) - headShaftRatio = 1.0; - //IJ.log(headShaftRatio+" "+(int)shaftLength+" "+(int)headLength+" "+(int)tailx+" "+(int)taily+" "+(int)headtipx+" "+(int)headtipy); - } - path.moveTo(tailx, taily); // tail - path.lineTo(headbackx, headbacky); // head back - path.moveTo(headbackx, headbacky); // head back - if (style==OPEN) - path.moveTo(points[2 * 2], points[2 * 2 + 1]); - else - path.lineTo(points[2 * 2], points[2 * 2 + 1]); // left point - path.lineTo(headtipx, headtipy); // head tip - path.lineTo(points[2 * 4], points[2 * 4 + 1]); // right point - path.lineTo(headbackx, headbacky); // back to the head back - return path; - } - - /** Based on the method with the same name in Fiji's Arrow plugin, - written by Jean-Yves Tinevez and Johannes Schindelin. */ - private void calculatePoints() { - double tip = 0.0; - double base; - double shaftWidth = getStrokeWidth(); - double length = 8+10*shaftWidth*0.5; - length = length*(headSize/10.0); - length -= shaftWidth*1.42; - if (style==NOTCHED) length*=0.74; - if (style==OPEN) length*=1.32; - if (length<0.0 || style==HEADLESS) length=0.0; - double x = getXBase(); - double y = getYBase(); - x1d=x+x1R; y1d=y+y1R; x2d=x+x2R; y2d=y+y2R; - x1=(int)x1d; y1=(int)y1d; x2=(int)x2d; y2=(int)y2d; - double dx=x2d-x1d, dy=y2d-y1d; - double arrowLength = Math.sqrt(dx*dx+dy*dy); - dx=dx/arrowLength; dy=dy/arrowLength; - if (doubleHeaded && style!=HEADLESS) { - points[0] = (float)(x1d+dx*shaftWidth*2.0); - points[1] = (float)(y1d+dy*shaftWidth*2.0); - } else { - points[0] = (float)x1d; - points[1] = (float)y1d; - } - if (length>0) { - double factor = style==OPEN?1.3:1.42; - points[2*3] = (float)(x2d-dx*shaftWidth*factor); - points[2*3+1] = (float)(y2d-dy*shaftWidth*factor); - if (style==BAR) { - points[2*3] = (float)(x2d-dx*shaftWidth*0.5); - points[2*3+1] = (float)(y2d-dy*shaftWidth*0.5); - } - } else { - points[2*3] = (float)x2d; - points[2*3+1] = (float)y2d; - } - final double alpha = Math.atan2(points[2*3+1]-points[1], points[2*3]-points[0]); - double SL = 0.0; - switch (style) { - case FILLED: case HEADLESS: - tip = Math.toRadians(20.0); - base = Math.toRadians(90.0); - points[1*2] = (float) (points[2*3] - length*Math.cos(alpha)); - points[1*2+1] = (float) (points[2*3+1] - length*Math.sin(alpha)); - SL = length*Math.sin(base)/Math.sin(base+tip);; - break; - case NOTCHED: - tip = Math.toRadians(20); - base = Math.toRadians(120); - points[1*2] = (float) (points[2*3] - length*Math.cos(alpha)); - points[1*2+1] = (float) (points[2*3+1] - length*Math.sin(alpha)); - SL = length*Math.sin(base)/Math.sin(base+tip);; - break; - case OPEN: - tip = Math.toRadians(25); //30 - points[1*2] = points[2*3]; - points[1*2+1] = points[2*3+1]; - SL = length; - break; - case BAR: - tip = Math.toRadians(90); //30 - points[1*2] = points[2*3]; - points[1*2+1] = points[2*3+1]; - SL = length; - updateFullWindow = true; - break; - } - // P2 = P3 - SL*alpha+tip - points[2*2] = (float) (points[2*3] - SL*Math.cos(alpha+tip)); - points[2*2+1] = (float) (points[2*3+1] - SL*Math.sin(alpha+tip)); - // P4 = P3 - SL*alpha-tip - points[2*4] = (float) (points[2*3] - SL*Math.cos(alpha-tip)); - points[2*4+1] = (float) (points[2*3+1] - SL*Math.sin(alpha-tip)); - } - - private Shape getShape() { - try { - Shape arrow = getPath(); - BasicStroke stroke = new BasicStroke((float)getStrokeWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); - Shape outlineShape = stroke.createStrokedShape(arrow); - Area a1 = new Area(arrow); - Area a2 = new Area(outlineShape); - a1.add(a2); - return a1; - } catch(Exception e) {}; - return null; - } - - private ShapeRoi getShapeRoi() { - try { - Shape arrow = getPath(); - BasicStroke stroke = new BasicStroke(getStrokeWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); - ShapeRoi sroi = new ShapeRoi(arrow); - Shape outlineShape = stroke.createStrokedShape(arrow); - sroi.or(new ShapeRoi(outlineShape)); - return sroi; - } catch(Exception e) {}; - return null; - } - - public ImageProcessor getMask() { - Roi roi = getShapeRoi(); - if ((width==0 && height==0) || roi==null) - return null; - else - return roi.getMask(); - } - - private double getOutlineWidth() { - double width = getStrokeWidth()/8.0; - double head = headSize/7.0; - double lineWidth = width + head + headShaftRatio; - if (lineWidth<1.0) lineWidth = 1.0; - //if (width<1) width=1; - //if (head<1) head=1; - //IJ.log(getStrokeWidth()+" "+IJ.d2s(width,2)+" "+IJ.d2s(head,2)+" "+IJ.d2s(headShaftRatio,2)+" "+IJ.d2s(lineWidth,2)+" "+IJ.d2s(width*head,2)); - return lineWidth; - } - - public void drawPixels(ImageProcessor ip) { - ShapeRoi shapeRoi = getShapeRoi(); - if (shapeRoi==null) - return; - ShapeRoi shapeRoi2 = null; - if (doubleHeaded) { - flipEnds(); - shapeRoi2 = getShapeRoi(); - flipEnds(); - } - if (outline) { - int lineWidth = ip.getLineWidth(); - ip.setLineWidth((int)Math.round(getOutlineWidth())); - shapeRoi.drawPixels(ip); - if (doubleHeaded) shapeRoi2.drawPixels(ip); - ip.setLineWidth(lineWidth); - } else { - ip.fill(shapeRoi); - if (doubleHeaded) ip.fill(shapeRoi2); - } - } - - public boolean contains(int x, int y) { - Roi roi = getShapeRoi(); - return roi!=null?roi.contains(x,y):false; - } - - /** Return the bounding rectangle of this arrow. */ - public Rectangle getBounds() { - Roi roi = getShapeRoi(); - if (roi!=null) - return roi.getBounds(); - else - return super.getBounds(); - } - - protected void handleMouseDown(int sx, int sy) { - super.handleMouseDown(sx, sy); - startxd = ic!=null?ic.offScreenXD(sx):sx; - startyd = ic!=null?ic.offScreenYD(sy):sy; - } - - protected int clipRectMargin() { - double mag = getMagnification(); - double arrowWidth = getStrokeWidth(); - double size = 8+10*arrowWidth*mag*0.5; - return (int)Math.max(size*2.0, headSize); - } - - public boolean isDrawingTool() { - return true; - } - - public static void setDefaultWidth(double width) { - defaultWidth = (float)width; - } - - public static double getDefaultWidth() { - return defaultWidth; - } - - public void setStyle(int style) { - this.style = style; - } - - /* Set the style, where 'style' is "filled", "notched", "open", "headless" or "bar", - plus optionial modifiers of "outline", "double", "small", "medium" and "large". */ - public void setStyle(String style) { - style = style.toLowerCase(); - int newStyle = Arrow.FILLED; - if (style.contains("notched")) - newStyle = Arrow.NOTCHED; - else if (style.contains("open")) - newStyle = Arrow.OPEN; - else if (style.contains("headless")) - newStyle = Arrow.HEADLESS; - else if (style.contains("bar")) - newStyle = Arrow.BAR; - setStyle(newStyle); - setOutline(style.contains("outline")); - setDoubleHeaded(style.contains("double")); - if (style.contains("small")) - setHeadSize(5); - else if (style.contains("large")) - setHeadSize(15); - } - - public int getStyle() { - return style; - } - - public static void setDefaultStyle(int style) { - defaultStyle = style; - } - - public static int getDefaultStyle() { - return defaultStyle; - } - - public void setHeadSize(double headSize) { - this.headSize = headSize; - } - - public double getHeadSize() { - return headSize; - } - - public static void setDefaultHeadSize(double size) { - defaultHeadSize = size; - } - - public static double getDefaultHeadSize() { - return defaultHeadSize; - } - - public void setDoubleHeaded(boolean b) { - doubleHeaded = b; - } - - public boolean getDoubleHeaded() { - return doubleHeaded; - } - - public static void setDefaultDoubleHeaded(boolean b) { - defaultDoubleHeaded = b; - } - - public static boolean getDefaultDoubleHeaded() { - return defaultDoubleHeaded; - } - - public void setOutline(boolean b) { - outline = b; - } - - public boolean getOutline() { - return outline; - } - - public static void setDefaultOutline(boolean b) { - defaultOutline = b; - } - - public static boolean getDefaultOutline() { - return defaultOutline; - } - - @Override - public void copyAttributes(Roi roi2) { - super.copyAttributes(roi2); - if (roi2 instanceof Arrow) { - Arrow a2 = (Arrow)roi2; - this.style = a2.getStyle(); - this.headSize = a2.getHeadSize(); - this.doubleHeaded = a2.getDoubleHeaded(); - this.outline = a2.getOutline(); - } - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ColorChooser.java b/com.eco.bio7.image/src/ij/gui/ColorChooser.java deleted file mode 100644 index eb2c3ad47..000000000 --- a/com.eco.bio7.image/src/ij/gui/ColorChooser.java +++ /dev/null @@ -1,121 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.util.*; -import ij.plugin.Colors; -import java.awt.*; -import java.util.Vector; -import java.awt.event.*; - - - /** Displays a dialog that allows the user to select a color using three sliders. */ -public class ColorChooser implements TextListener, AdjustmentListener { - Vector colors, sliders; - ColorPanel panel; - Color initialColor; - int red, green, blue; - boolean useHSB; - String title; - Frame frame; - double scale = Prefs.getGuiScale(); - - /** Constructs a ColorChooser using the specified title and initial color. */ - public ColorChooser(String title, Color initialColor, boolean useHSB) { - this(title, initialColor, useHSB, null); - } - - public ColorChooser(String title, Color initialColor, boolean useHSB, Frame frame) { - this.title = title; - if (initialColor==null) initialColor = Color.black; - this.initialColor = initialColor; - red = initialColor.getRed(); - green = initialColor.getGreen(); - blue = initialColor.getBlue(); - this.useHSB = useHSB; - this.frame = frame; - } - - /** Displays a color selection dialog and returns the color selected by the user. */ - public Color getColor() { - GenericDialog gd = frame!=null?new GenericDialog(title, frame):new GenericDialog(title); - gd.addSlider("Red:", 0, 255, red); - gd.addSlider("Green:", 0, 255, green); - gd.addSlider("Blue:", 0, 255, blue); - panel = new ColorPanel(initialColor, scale); - gd.addPanel(panel, GridBagConstraints.CENTER, new Insets(10, 0, 0, 0)); - colors = gd.getNumericFields(); - for (int i=0; i255) red=255; - if (green<0) green=0; if (green>255) green=255; - if (blue<0) blue=0; if (blue>255) blue=255; - panel.setColor(new Color(red, green, blue)); - panel.repaint(); - } - - public synchronized void adjustmentValueChanged(AdjustmentEvent e) { - Object source = e.getSource(); - for (int i=0; ie is null if the - * dialogItemChanged method is called after the user has pressed the - * OK button or if the GenericDialog has read its parameters from a - * macro. - * @param gd A reference to the GenericDialog. - * @return Should be true if the dialog input is valid. False disables the - * OK button and preview (if any). - */ - boolean dialogItemChanged(GenericDialog gd, AWTEvent e); -} diff --git a/com.eco.bio7.image/src/ij/gui/EllipseRoi.java b/com.eco.bio7.image/src/ij/gui/EllipseRoi.java deleted file mode 100644 index c7dc16823..000000000 --- a/com.eco.bio7.image/src/ij/gui/EllipseRoi.java +++ /dev/null @@ -1,270 +0,0 @@ -package ij.gui; -import java.awt.*; -import java.awt.image.*; -import java.awt.event.*; -import ij.*; -import ij.plugin.frame.Recorder; -import ij.process.FloatPolygon; -import ij.measure.Calibration; - -/** This class implements the ellipse selection tool. */ -public class EllipseRoi extends PolygonRoi { - private static final int vertices = 72; - private static double defaultRatio = 0.6; - private double xstart, ystart; - private double aspectRatio = defaultRatio; - private int[] handle = {0, vertices/4, vertices/2, vertices/2+vertices/4}; - - public EllipseRoi(double x1, double y1, double x2, double y2, double aspectRatio) { - super(new float[vertices], new float[vertices], vertices, FREEROI); - if (aspectRatio<0.0) aspectRatio = 0.0; - if (aspectRatio>1.0) aspectRatio = 1.0; - this.aspectRatio = aspectRatio; - makeEllipse(x1, y1, x2, y2); - state = NORMAL; - bounds = null; - } - - public EllipseRoi(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - type = FREEROI; - xstart = offScreenXD(sx); - ystart = offScreenYD(sy); - setDrawOffset(false); - bounds = null; - } - - public void draw(Graphics g) { - super.draw(g); - if (!overlay) { - for (int i=0; i1.0) aspectRatio = 1.0; - defaultRatio = aspectRatio; - } - - public int isHandle(int sx, int sy) { - int size = getHandleSize()+5; - int halfSize = size/2; - int index = -1; - for (int i=0; i=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) { - index = i; - break; - } - } - return index; - } - - /** Returns the perimeter of this ellipse. */ - public double getLength() { - double length = 0.0; - double dx, dy; - double w2=1.0, h2=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - w2 = cal.pixelWidth*cal.pixelWidth; - h2 = cal.pixelHeight*cal.pixelHeight; - } - for (int i=0; i<(nPoints-1); i++) { - dx = xpf[i+1]-xpf[i]; - dy = ypf[i+1]-ypf[i]; - length += Math.sqrt(dx*dx*w2+dy*dy*h2); - } - dx = xpf[0]-xpf[nPoints-1]; - dy = ypf[0]-ypf[nPoints-1]; - length += Math.sqrt(dx*dx*w2+dy*dy*h2); - return length; - } - - /** Returns x1, y1, x2, y2 and aspectRatio as a 5 element array. */ - public double[] getParams() { - double[] params = new double[5]; - params[0] = xpf[handle[2]]+x; - params[1] = ypf[handle[2]]+y; - params[2] = xpf[handle[0]]+x; - params[3] = ypf[handle[0]]+y; - params[4] = aspectRatio; - return params; - } - - public double[] getFeretValues() { - double a[] = super.getFeretValues(); - double pw=1.0, ph=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - pw = cal.pixelWidth; - ph = cal.pixelHeight; - } - if (pw != ph) //the following calculation holds only for pixel aspect ratio == 1 (otherwise different axes in distorted ellipse) - return a; - double[] p = getParams(); - double dx = p[2] - p[0]; //this is always major axis; aspect ratio p[4] is limited to <= 1 - double dy = p[3] - p[1]; - double major = Math.sqrt(dx*dx + dy*dy); - double minor = major*p[4]; - a[0] = major*pw; //Feret from convex hull should be accurate anyhow - a[2] = minor*pw; //here our own calculation is better - System.arraycopy(p, 0, a, 8, 4); //MaxFeret endpoints - double xCenter = 0.5*(p[2] + p[0]); - double yCenter = 0.5*(p[3] + p[1]); - double semiMinorX = dy * 0.5 * p[4]; - double semiMinorY = dx * (-0.5) * p[4]; - a[12] = xCenter + semiMinorX; a[14] = xCenter - semiMinorX; - a[13] = yCenter + semiMinorY; a[15] = yCenter - semiMinorY; - return a; - } - - /** Always returns true. */ - public boolean subPixelResolution() { - return true; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/FreehandRoi.java b/com.eco.bio7.image/src/ij/gui/FreehandRoi.java deleted file mode 100644 index 7cf4c463c..000000000 --- a/com.eco.bio7.image/src/ij/gui/FreehandRoi.java +++ /dev/null @@ -1,98 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.image.*; -import ij.*; - -/** Freehand region of interest or freehand line of interest*/ -public class FreehandRoi extends PolygonRoi { - - public FreehandRoi(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - if (Toolbar.getToolId()==Toolbar.FREEROI) - type = FREEROI; - else - type = FREELINE; - if (nPoints==2) nPoints--; - } - - protected void grow(int sx, int sy) { - if (subPixelResolution() && xpf!=null) { - growFloat(sx, sy); - return; - } - int ox = offScreenX(sx); - int oy = offScreenY(sy); - if (ox<0) ox = 0; - if (oy<0) oy = 0; - if (ox>xMax) ox = xMax; - if (oy>yMax) oy = yMax; - if (ox!=xp[nPoints-1]+x || oy!=yp[nPoints-1]+y) { - xp[nPoints] = ox-x; - yp[nPoints] = oy-y; - nPoints++; - if (IJ.altKeyDown()) - wipeBack(); - if (nPoints==xp.length) - enlargeArrays(); - drawLine(); - } - } - - private void growFloat(int sx, int sy) { - double ox = offScreenXD(sx); - double oy = offScreenYD(sy); - if (ox<0.0) ox = 0.0; - if (oy<0.0) oy = 0.0; - if (ox>xMax) ox = xMax; - if (oy>yMax) oy = yMax; - double xbase = getXBase(); - double ybase = getYBase(); - if (ox!=xpf[nPoints-1]+xbase || oy!=ypf[nPoints-1]+ybase) { - xpf[nPoints] = (float)(ox-xbase); - ypf[nPoints] = (float)(oy-ybase); - nPoints++; - if (nPoints==xpf.length) - enlargeArrays(); - drawLine(); - } - } - - void drawLine() { - int x1, y1, x2, y2; - if (xpf!=null) { - x1 = (int)Math.round(xpf[nPoints-2]+x); - y1 = (int)Math.round(ypf[nPoints-2]+y); - x2 = (int)Math.round(xpf[nPoints-1]+x); - y2 = (int)Math.round(ypf[nPoints-1]+y); - } else { - x1 = xp[nPoints-2]+x; - y1 = yp[nPoints-2]+y; - x2 = xp[nPoints-1]+x; - y2 = yp[nPoints-1]+y; - } - int xmin = Math.min(x1, x2); - int xmax = Math.max(x1, x2); - int ymin = Math.min(y1, y2); - int ymax = Math.max(y1, y2); - int margin = 4; - if (lineWidth>margin && isLine()) - margin = lineWidth; - if (ic!=null) { - double mag = ic.getMagnification(); - if (mag<1.0) margin = (int)(margin/mag); - } - if (IJ.altKeyDown()) - margin += 20; // for wipeBack - imp.draw(xmin-margin, ymin-margin, (xmax-xmin)+margin*2, (ymax-ymin)+margin*2); - } - - protected void handleMouseUp(int screenX, int screenY) { - if (state==CONSTRUCTING) { - addOffset(); - finishPolygon(); - } - state = NORMAL; - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/GUI.java b/com.eco.bio7.image/src/ij/gui/GUI.java deleted file mode 100644 index d687725ba..000000000 --- a/com.eco.bio7.image/src/ij/gui/GUI.java +++ /dev/null @@ -1,323 +0,0 @@ -package ij.gui; - -import ij.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JScrollBar; -import javax.swing.JTable; -import javax.swing.UIManager; - -/** This class consists of static GUI utility methods. */ -public class GUI { - private static final Font DEFAULT_FONT = ImageJ.SansSerif12; - private static Color lightGray = new Color(240, 240, 240); - private static boolean isWindows8; - private static Color scrollbarBackground = new Color(245, 245, 245); - - static { - if (IJ.isWindows()) { - String osname = System.getProperty("os.name"); - isWindows8 = osname.contains("unknown") || osname.contains("8"); - } - } - - /** - * Positions the specified window in the center of the screen that contains - * target. - */ - public static void center(Window win, Component target) { - if (win == null) - return; - Rectangle bounds = getMaxWindowBounds(target); - Dimension window = win.getSize(); - if (window.width == 0) - return; - int left = bounds.x + Math.max(0, (bounds.width - window.width) / 2); - int top = bounds.y + Math.max(0, (bounds.height - window.height) / 4); - win.setLocation(left, top); - } - - /** - * Positions the specified window in the center of the screen containing the - * "ImageJ" window. - */ - public static void centerOnImageJScreen(Window win) { - center(win, IJ.getInstance()); - } - - public static void center(Window win) { - center(win, win); - } - - private static java.util.List getScreenConfigs() { - java.util.ArrayList configs = new java.util.ArrayList(); - for (GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) { - configs.add(device.getDefaultConfiguration()); - } - return configs; - } - - /** - * Get maximum bounds for the screen that contains a given point. - * - * @param point Coordinates of point. - * @param accountForInsets Deduct the space taken up by menu and status bars, - * etc. (after point is found to be inside bonds) - * @return Rectangle of bounds or null if point not inside of any - * screen. - */ - public static Rectangle getScreenBounds(Point point, boolean accountForInsets) { - if (GraphicsEnvironment.isHeadless()) - return new Rectangle(0, 0, 0, 0); - for (GraphicsConfiguration config : getScreenConfigs()) { - Rectangle bounds = config.getBounds(); - if (bounds != null && bounds.contains(point)) { - Insets insets = accountForInsets ? Toolkit.getDefaultToolkit().getScreenInsets(config) : null; - return shrinkByInsets(bounds, insets); - } - } - return null; - } - - /** - * Get maximum bounds for the screen that contains a given component. - * - * @param component An AWT component located on the desired screen. If - * null is provided, the default screen is - * used. - * @param accountForInsets Deduct the space taken up by menu and status bars, - * etc. - * @return Rectangle of bounds. - */ - public static Rectangle getScreenBounds(Component component, boolean accountForInsets) { - if (GraphicsEnvironment.isHeadless()) - return new Rectangle(0, 0, 0, 0); - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsConfiguration gc = component == null ? ge.getDefaultScreenDevice().getDefaultConfiguration() - : component.getGraphicsConfiguration(); - Insets insets = accountForInsets ? Toolkit.getDefaultToolkit().getScreenInsets(gc) : null; - return shrinkByInsets(gc.getBounds(), insets); - } - - public static Rectangle getScreenBounds(Point point) { - return getScreenBounds(point, false); - } - - public static Rectangle getScreenBounds(Component component) { - return getScreenBounds(component, false); - } - - public static Rectangle getScreenBounds() { - return getScreenBounds((Component) null); - } - - public static Rectangle getMaxWindowBounds(Point point) { - return getScreenBounds(point, true); - } - - public static Rectangle getMaxWindowBounds(Component component) { - return getScreenBounds(component, true); - } - - public static Rectangle getMaxWindowBounds() { - return getMaxWindowBounds((Component) null); - } - - private static Rectangle shrinkByInsets(Rectangle bounds, Insets insets) { - Rectangle shrunk = new Rectangle(bounds); - if (insets == null) - return shrunk; - shrunk.x += insets.left; - shrunk.y += insets.top; - shrunk.width -= insets.left + insets.right; - shrunk.height -= insets.top + insets.bottom; - return shrunk; - } - - public static Rectangle getZeroBasedMaxBounds() { - for (GraphicsConfiguration config : getScreenConfigs()) { - Rectangle bounds = config.getBounds(); - if (bounds != null && bounds.x == 0 && bounds.y == 0) - return bounds; - } - return null; - } - - public static Rectangle getUnionOfBounds() { - Rectangle unionOfBounds = new Rectangle(); - for (GraphicsConfiguration config : getScreenConfigs()) { - unionOfBounds = unionOfBounds.union(config.getBounds()); - } - return unionOfBounds; - } - - static private Frame frame; - - /** Obsolete */ - public static Image createBlankImage(int width, int height) { - if (width == 0 || height == 0) - throw new IllegalArgumentException(""); - if (frame == null) { - frame = new Frame(); - frame.pack(); - frame.setBackground(Color.white); - } - Image img = frame.createImage(width, height); - return img; - } - - /** Lightens overly dark scrollbar background on Windows 8. */ - public static void fix(Scrollbar sb) { - } - - public static boolean showCompositeAdvisory(ImagePlus imp, String title) { - if (imp == null || imp.getCompositeMode() != IJ.COMPOSITE || imp.getNChannels() == 1 || IJ.macroRunning()) - return true; - String msg = "Channel " + imp.getC() + " of this color composite image will be processed."; - GenericDialog gd = new GenericDialog(title); - gd.addMessage(msg); - gd.showDialog(); - return !gd.wasCanceled(); - } - - /** - * Scales an AWT component according to {@link Prefs#getGuiScale()}. - * - * @param component the AWT component to be scaled. If a container, scaling is - * applied to all its child components - */ - public static void scale(final Component component) { - final float scale = (float) Prefs.getGuiScale(); - if (scale == 1f) - return; - if (component instanceof Container) - scaleComponents((Container) component, scale); - else - scaleComponent(component, scale); - } - - private static void scaleComponents(final Container container, final float scale) { - for (final Component child : container.getComponents()) { - if (child instanceof Container) - scaleComponents((Container) child, scale); - else - scaleComponent(child, scale); - } - } - - private static void scaleComponent(final Component component, final float scale) { - Font font = component.getFont(); - if (font == null) - font = DEFAULT_FONT; - font = font.deriveFont(scale * font.getSize()); - component.setFont(font); - } - - public static void scalePopupMenu(final PopupMenu popup) { - //System.out.println("scalePopupMenu1: "+popup); - if (Menus.getFontSize()!=0) { - popup.setFont(Menus.getFont(false)); - //System.out.println("scalePopupMenu2: "+popup.getFont()); - return; - } - final float scale = (float)Prefs.getGuiScale(); - if (scale == 1f) - return; - Font font=popup.getFont(); - if (font==null) - font = new Font("SansSerif", Font.PLAIN, (int)(scale*13)); - else - font = font.deriveFont(scale*font.getSize()); - popup.setFont(font); - //System.out.println("scalePopupMenu3: "+popup.getFont()); - } - - /** - * Tries to detect if a Swing component is unscaled and scales it it according - * to {@link #getGuiScale()}. - * - * This is mainly relevant to linux: Swing components scale automatically on - * most platforms, specially since Java 8. However there are still exceptions to - * this on linux: e.g., In Ubuntu, Swing components do scale, but only under the - * GTK L&F. (On the other hand AWT components do not scale at all on - * hiDPI screens on linux). - * - * - * This method tries to avoid exaggerated font sizes by detecting if a component - * has been already scaled by the UIManager, applying only - * {@link #getGuiScale()} to the component's font if not. - * - * - * @param component the component to be scaled - * @return true, if component's font was resized - */ - public static boolean scale(final JComponent component) { - final double guiScale = Prefs.getGuiScale(); - if (guiScale == 1d) - return false; - Font font = component.getFont(); - if (font == null && component instanceof JList) - font = UIManager.getFont("List.font"); - else if (font == null && component instanceof JTable) - font = UIManager.getFont("Table.font"); - else if (font == null) - font = UIManager.getFont("Label.font"); - if (font.getSize() > DEFAULT_FONT.getSize()) - return false; - if (component instanceof JTable) - ((JTable) component).setRowHeight((int) (((JTable) component).getRowHeight() * guiScale * 0.9)); - else if (component instanceof JList) - ((JList>) component) - .setFixedCellHeight((int) (((JList>) component).getFixedCellHeight() * guiScale * 0.9)); - component.setFont(font.deriveFont((float) guiScale * font.getSize())); - return true; - } - - /** - * Works around an OpenJDK bug on Windows that causes the scrollbar thumb color - * and background color to be almost identical. - */ - public static final void fixScrollbar(Scrollbar sb) { - if (IJ.isWindows()) - sb.setBackground(scrollbarBackground); - } - - /*Changed for Bio7!*/ - /** - * Works around an OpenJDK bug on Windows that causes the scrollbar thumb color - * and background color to be almost identical. - */ - public static final void fixScrollbar(JScrollBar sb) { - if (IJ.isWindows()) - sb.setBackground(scrollbarBackground); - } - - /** - * Returns a new NonBlockingGenericDialog with the given title, except when Java - * is running in headless mode, in which case a GenericDialog is be returned. - */ - public static GenericDialog newNonBlockingDialog(String title) { - if (GraphicsEnvironment.isHeadless()) - return new GenericDialog(title); - else - return new NonBlockingGenericDialog(title); - } - - /** Returns a new NonBlockingGenericDialog with the given title - * if Prefs.nonBlockingFilterDialogs is 'true' and 'imp' is - * displayed, otherwise returns a GenericDialog. - * - * @param title Dialog title - * @param imp The image associated with this dialog - */ - public static GenericDialog newNonBlockingDialog(String title, ImagePlus imp) { - if (Prefs.nonBlockingFilterDialogs && imp != null && imp.getWindow() != null) { - NonBlockingGenericDialog gd = new NonBlockingGenericDialog(title); - gd.imp = imp; - return gd; - } else - return new GenericDialog(title); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/GenericDialog.java b/com.eco.bio7.image/src/ij/gui/GenericDialog.java deleted file mode 100644 index 82fb76716..000000000 --- a/com.eco.bio7.image/src/ij/gui/GenericDialog.java +++ /dev/null @@ -1,2345 +0,0 @@ -package ij.gui; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JPanel; -import com.eco.bio7.image.Util; -import ij.*; -import ij.plugin.frame.Recorder; -import ij.plugin.ScreenGrabber; -import ij.plugin.filter.PlugInFilter; -import ij.plugin.filter.PlugInFilterRunner; -import ij.util.Tools; -import ij.macro.*; -import ij.io.OpenDialog; -import java.awt.*; -import java.io.*; -import java.awt.event.*; -import java.util.*; -import java.awt.datatransfer.*; -import java.awt.dnd.*; - -/** - * This class is a customizable modal dialog box. Here is an example - * GenericDialog with one string field and two numeric fields: - * - * - * public class Generic_Dialog_Example implements PlugIn { - * static String title = "Example"; - * static int width = 512, height = 512; - * - * public void run(String arg) { - * GenericDialog gd = new GenericDialog("New Image"); - * gd.addStringField("Title: ", title); - * gd.addNumericField("Width: ", width, 0); - * gd.addNumericField("Height: ", height, 0); - * gd.showDialog(); - * if (gd.wasCanceled()) - * return; - * title = gd.getNextString(); - * width = (int) gd.getNextNumber(); - * height = (int) gd.getNextNumber(); - * IJ.newImage(title, "8-bit", width, height, 1); - * } - * } - * - * - * To work with macros, the first word of each component label must be unique. - * If this is not the case, add underscores, which will be converted to spaces - * when the dialog is displayed. For example, change the checkbox labels "Show - * Quality" and "Show Residue" to "Show_Quality" and "Show_Residue". - */ -public class GenericDialog extends Dialog implements ActionListener, TextListener, FocusListener, ItemListener, KeyListener, AdjustmentListener, WindowListener, ComponentListener { - - protected Vector numberField, stringField, checkbox, choice, slider, radioButtonGroups; - protected TextArea textArea1, textArea2; - protected Vector defaultValues, defaultText, defaultStrings, defaultChoiceIndexes; - protected Component theLabel; - private Button okay; - private Button cancel; - private Button no, help; - private String helpLabel = "Help"; - private boolean wasCanceled, wasOKed; - private int nfIndex, sfIndex, cbIndex, choiceIndex, textAreaIndex, radioButtonIndex; - private GridBagConstraints c; - private boolean firstNumericField = true; - private boolean firstSlider = true; - private boolean invalidNumber; - private String errorMessage; - private Hashtable labels; - private boolean macro; - private String macroOptions; - private boolean addToSameRow; - private boolean addToSameRowCalled; - private int topInset, leftInset, bottomInset; - private boolean customInsets; - private Vector sliderIndexes, sliderScales, sliderDigits; - private Checkbox previewCheckbox; // the "Preview" Checkbox, if any - private Vector dialogListeners; // the Objects to notify on user input - private PlugInFilterRunner pfr; // the PlugInFilterRunner for automatic preview - private String previewLabel = " Preview"; - private final static String previewRunning = "wait..."; - private boolean recorderOn; // whether recording is allowed (after the dialog is closed) - private char echoChar; - private boolean hideCancelButton; - private boolean centerDialog = true; - private String helpURL; - private boolean smartRecording; - private Vector imagePanels; - protected static GenericDialog instance; - private boolean firstPaint = true; - private boolean fontSizeSet; - private boolean showDialogCalled; - private boolean optionsRecorded; // have dialogListeners been called to record options? - private Label lastLabelAdded; - private int[] windowIDs; - private String[] windowTitles; - - /** - * Creates a new GenericDialog with the specified title. Uses the current image - * image window as the parent frame or the ImageJ frame if no image windows are - * open. Dialog parameters are recorded by ImageJ's command recorder but this - * requires that the first word of each label be unique. - */ - public GenericDialog(String title) { - this(title, null); - } - - private static Frame getParentFrame() { - return null; - } - - /** Creates a new GenericDialog using the specified title and parent frame. */ - public GenericDialog(String title, Frame parent) { - super(parent, title, true); - ImageJ ij = IJ.getInstance(); - if (ij != null) - setFont(ij.getFont()); - okay = new Button(" OK "); - cancel = new Button("Cancel"); - if (Prefs.blackCanvas) { - setForeground(SystemColor.controlText); - setBackground(SystemColor.control); - } - // if (IJ.isMacOSX() && System.getProperty("java.vendor").contains("Azul")) - // setForeground(Color.black); // work around bug on Azul Java 8 on Apple - // Silicon - GridBagLayout grid = new GridBagLayout(); - c = new GridBagConstraints(); - setLayout(grid); - macroOptions = Macro.getOptions(); - macro = macroOptions != null; - addKeyListener(this); - addWindowListener(this); - // Added for Bio7! - addComponentListener(this); - /* Changed for Bio7! */ - Font font = Util.getOSFontToAwt(); - if (font != null) { - setFont(Util.getOSFontToAwt()); - } - /* - * Changed for Bio7! AWT must be colored per component. All JPanels will get the - * SWT background from the definition of the CanvasView (UIManager)! - */ - - if (Util.isThemeBlack()) { - if (Util.getOS().equals("Linux") || Util.getOS().equals("Mac")) { - setBackground(Util.getSWTBackgroundToAWT()); - setForeground(Util.getSWTForegroundToAWT()); - - } - } - } - - /** - * Adds a numeric field. The first word of the label must be unique or command - * recording will not work. - * - * @param label the label - * @param defaultValue value to be initially displayed - */ - public void addNumericField(String label, double defaultValue) { - int decimalPlaces = (int) defaultValue == defaultValue ? 0 : 3; - int columnWidth = decimalPlaces == 3 ? 8 : 6; - addNumericField(label, defaultValue, decimalPlaces, columnWidth, null); - } - - /** - * Adds a numeric field. The first word of the label must be unique or command - * recording will not work. - * - * @param label the label - * @param defaultValue value to be initially displayed - * @param digits number of digits to right of decimal point - */ - public void addNumericField(String label, double defaultValue, int digits) { - addNumericField(label, defaultValue, digits, 6, null); - } - - /** - * Adds a numeric field. The first word of the label must be unique or command - * recording will not work. - * - * @param label the label - * @param defaultValue value to be initially displayed - * @param digits number of digits to right of decimal point - * @param columns width of field in characters - * @param units a string displayed to the right of the field - */ - public void addNumericField(String label, double defaultValue, int digits, int columns, String units) { - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - c.insets.left = 10; - } else { - c.gridx = 0; - c.gridy++; - if (firstNumericField) - c.insets = getInsets(5, 0, 3, 0); // top, left, bottom, right - else - c.insets = getInsets(0, 0, 3, 0); - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - // IJ.log("x="+c.gridx+", y= "+c.gridy+", width="+c.gridwidth+", ancher= - // "+c.anchor+" "+c.insets); - add(fieldLabel, c); - if (addToSameRow) { - c.insets.left = 0; - addToSameRow = false; - } - if (numberField == null) { - numberField = new Vector(5); - defaultValues = new Vector(5); - defaultText = new Vector(5); - } - if (IJ.isWindows()) - columns -= 2; - if (columns < 1) - columns = 1; - boolean scientificNotationAsNeeded = false; - if (digits < 0) { - digits = -digits; - scientificNotationAsNeeded = true; - } - String defaultString = IJ.d2s(defaultValue, digits); - if (scientificNotationAsNeeded) - defaultString = ij.measure.ResultsTable.d2s(defaultValue, digits); - if (Double.isNaN(defaultValue)) - defaultString = ""; - TextField tf = newTextField(defaultString, columns); - if (IJ.isLinux()) - tf.setBackground(Color.white); - tf.addActionListener(this); - tf.addTextListener(this); - tf.addFocusListener(this); - tf.addKeyListener(this); - numberField.addElement(tf); - defaultValues.addElement(Double.valueOf(defaultValue)); - defaultText.addElement(tf.getText()); - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - tf.setEditable(true); - // if (firstNumericField) tf.selectAll(); - firstNumericField = false; - if (units == null || units.equals("")) { - add(tf, c); - } else { - JPanel panel = new JPanel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - panel.add(tf); - panel.add(new Label(" " + units)); - add(panel, c); - } - if (IJ.recording() || macro) - saveLabel(tf, label); - } - - private Label makeLabel(String label) { - if (IJ.isMacintosh()) - label += " "; - return new Label(label); - } - - /** - * Saves the label for given component, for macro recording and for accessing - * the component in macros. - */ - private void saveLabel(Object component, String label) { - if (labels == null) - labels = new Hashtable(); - if (label.length() > 0) - label = Macro.trimKey(label.trim()); - if (label.length() > 0 && hasLabel(label)) { // not a unique label? - label += "_0"; - for (int n = 1; hasLabel(label); n++) { // while still not a unique label - label = label.substring(0, label.lastIndexOf('_')); // remove counter - label += "_" + n; - } - } - labels.put(component, label); - } - - /** - * Returns whether the list of labels for macro recording or macro creation - * contains a given label. - */ - private boolean hasLabel(String label) { - for (Object o : labels.keySet()) - if (labels.get(o).equals(label)) - return true; - return false; - } - - /** - * Adds an 8 column text field. - * - * @param label the label - * @param defaultText the text initially displayed - */ - public void addStringField(String label, String defaultText) { - addStringField(label, defaultText, 8); - } - - /** - * Adds a text field. - * - * @param label the label - * @param defaultText text initially displayed - * @param columns width of the text field. If columns is 8 or more, - * additional items may be added to this line with - * addToSameRow() - */ - public void addStringField(String label, String defaultText, int columns) { - if (addToSameRow && label.equals("_")) - label = ""; - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - boolean custom = customInsets; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - if (stringField == null) - c.insets = getInsets(5, 0, 5, 0); // top, left, bottom, right - else - c.insets = getInsets(0, 0, 5, 0); - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - add(fieldLabel, c); - if (stringField == null) { - stringField = new Vector(4); - defaultStrings = new Vector(4); - } - - TextField tf = newTextField(defaultText, columns); - if (IJ.isLinux()) - tf.setBackground(Color.white); - - tf.setEchoChar(echoChar); - echoChar = 0; - tf.addActionListener(this); - tf.addTextListener(this); - tf.addFocusListener(this); - tf.addKeyListener(this); - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - c.gridwidth = columns <= 8 ? 1 : GridBagConstraints.REMAINDER; - c.insets.left = 0; - tf.setEditable(true); - add(tf, c); - stringField.addElement(tf); - defaultStrings.addElement(defaultText); - tf.setDropTarget(null); - new DropTarget(tf, new TextDropTarget(tf)); - if (IJ.recording() || macro) - saveLabel(tf, label); - } - - /** Sets the echo character for the next string field. */ - public void setEchoChar(char echoChar) { - this.echoChar = echoChar; - } - - /** - * Adds a directory text field and "Browse" button, where the field width is - * determined by the length of 'defaultPath', with a minimum of 25 columns. Use - * getNextString to retrieve the directory path. Call - * OpenDialog.setDefaultDirectory() to set the default directory used when the - * user clicks on "Browse". Based on the addDirectoryField() method in Fiji's - * GenericDialogPlus class. * @see ij.io.OpenDialog#setDefaultDirectory(String) - */ - public void addDirectoryField(String label, String defaultPath) { - int columns = defaultPath != null ? Math.max(defaultPath.length(), 25) : 25; - if (columns > 60) - columns = 60; - addDirectoryField(label, defaultPath, columns); - } - - public void addDirectoryField(String label, String defaultPath, int columns) { - defaultPath = IJ.addSeparator(defaultPath); - addStringField(label, defaultPath, columns); - if (GraphicsEnvironment.isHeadless()) - return; - TextField text = (TextField) stringField.lastElement(); - GridBagLayout layout = (GridBagLayout) getLayout(); - GridBagConstraints constraints = layout.getConstraints(text); - JButton button = new TrimmedButton("Browse", IJ.isMacOSX() ? 10 : 0); - BrowseButtonListener listener = new BrowseButtonListener(label, text, "dir"); - button.addActionListener(listener); - Panel panel = new Panel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - panel.add(text); - panel.add(button); - layout.setConstraints(panel, constraints); - add(panel); - if (IJ.recording() || macro) - saveLabel(panel, label); - } - - /** - * Adds a file text field and "Browse" button, where the field width is - * determined by the length of 'defaultPath', with a minimum of 25 columns. Use - * getNextString to retrieve the file path. Based on the addFileField() method - * in Fiji's GenericDialogPlus class. - */ - public void addFileField(String label, String defaultPath) { - int columns = defaultPath != null ? Math.max(defaultPath.length(), 25) : 25; - if (columns > 60) - columns = 60; - addFileField(label, defaultPath, columns); - } - - public void addFileField(String label, String defaultPath, int columns) { - addStringField(label, defaultPath, columns); - if (GraphicsEnvironment.isHeadless()) - return; - TextField text = (TextField) stringField.lastElement(); - GridBagLayout layout = (GridBagLayout) getLayout(); - GridBagConstraints constraints = layout.getConstraints(text); - JButton button = new TrimmedButton("Browse", IJ.isMacOSX() ? 10 : 0); - BrowseButtonListener listener = new BrowseButtonListener(label, text, "file"); - button.addActionListener(listener); - Panel panel = new Panel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - panel.add(text); - panel.add(button); - layout.setConstraints(panel, constraints); - add(panel); - if (IJ.recording() || macro) - saveLabel(panel, label); - } - - /** - * Add button to the dialog - * - * @param label button label - * @param listener listener to handle the action when pressing the button - */ - public void addButton(String label, ActionListener listener) { - if (GraphicsEnvironment.isHeadless()) - return; - Button button = new Button(label); - button.addActionListener(listener); - button.addKeyListener(this); - GridBagLayout layout = (GridBagLayout) getLayout(); - Panel panel = new Panel(); - addPanel(panel); - GridBagConstraints constraints = layout.getConstraints(panel); - remove(panel); - layout.setConstraints(button, constraints); - add(button); - } - - /** - * Adds a popup menu that lists the currently open images. Call getNextImage() - * to retrieve the selected image. Based on the addImageChoice() method in - * Fiji's GenericDialogPlus class. - * - * @param label the label - * @param defaultImage the image title initially selected in the menu or the - * first image if null - */ - public void addImageChoice(String label, String defaultImage) { - if (windowTitles == null) { - windowIDs = WindowManager.getIDList(); - if (windowIDs == null) - windowIDs = new int[0]; - windowTitles = new String[windowIDs.length]; - for (int i = 0; i < windowIDs.length; i++) { - ImagePlus image = WindowManager.getImage(windowIDs[i]); - windowTitles[i] = image == null ? "" : image.getTitle(); - } - } - addChoice(label, windowTitles, defaultImage); - } - - public ImagePlus getNextImage() { - int index = getNextChoiceIndex(); - return index < 0 ? null : WindowManager.getImage(windowIDs[index]); - } - - /** - * Adds a group of choices to the dialog with menu items taken from the - * enum class of the specified default item (enum constant). The - * default item is automatically set. Calls the original (string-based) - * {@link GenericDialog#addChoice(String, String[], String)} method. Usage - * example: - * - * - * import ij.process.AutoThresholder.Method; - * ... - * Method method = Method.Otsu; - * - * GenericDialog gd = new GenericDialog("Select AutoThresholder Method"); - * gd.addEnumChoice("All threshold methods", method); - * ... - * gd.showDialog(); - * ... - * method = gd.getNextEnumChoice(Method.class); - * - * - * @param the generic enum type containing the items to chose from - * @param label the label displayed for this choice group - * @param defaultItem the menu item initially selected - * - * @see #addEnumChoice(String, Enum[], Enum) - * @see #getNextEnumChoice(Class) - */ - public > void addEnumChoice(String label, E defaultItem) { - Class enumClass = defaultItem.getDeclaringClass(); - E[] enums = enumClass.getEnumConstants(); - String[] items = new String[enums.length]; - for (int i = 0; i < enums.length; i++) { - items[i] = enums[i].name(); - } - this.addChoice(label, items, defaultItem.name()); - } - - /** - * Adds a group of choices to the dialog with menu items taken from the supplied - * array of enum elements. This allows to present only a subset of - * enum choices in a specified order. A default item (enum constant) must be - * specified which, if {@code null} of not contained in the enum array, is - * replaced by the first element of the enum array. Calls the original - * (string-based) {@link GenericDialog#addChoice(String, String[], String)} - * method. Usage example: - * - * - * import ij.process.AutoThresholder.Method; - * ... - * Method[] selectMethods = {Method.Triangle, Method.Otsu, Method.Huang}; - * Method method = Method.Otsu; - * - * GenericDialog gd = new GenericDialog("Select AutoThresholder Method"); - * gd.addEnumChoice("Select threshold methods", selectMethods, method); - * ... - * gd.showDialog(); - * ... - * method = gd.getNextEnumChoice(Method.class); - * - * - * @param the generic enum type containing the items to choose from - * @param label the label displayed for this choice group - * @param enumArray an array of enum items (of type E) - * @param defaultItem the menu item initially selected (of type E, may be - * {@code null}) - * - * @see #addEnumChoice(String, Enum) - * @see #getNextEnumChoice(Class) - */ - public > void addEnumChoice(String label, E[] enumArray, E defaultItem) { - String[] items = new String[enumArray.length]; - boolean contained = false; // to check if defaultItem is contained in enumArray - for (int i = 0; i < enumArray.length; i++) { - if (enumArray[i] == defaultItem) { - contained = true; - } - items[i] = enumArray[i].name(); - } - if (!contained) { - defaultItem = enumArray[0]; - } - this.addChoice(label, items, defaultItem.name()); - } - - /** - * Returns the selected item in the next enum choice menu. Note that 'enumClass' - * is required to infer the proper enum type. Throws - * {@code IllegalArgumentException} if the selected item is not a defined - * constant in the specified enum class. - * - * @param the generic enum type - * @param enumClass the enum type - * @return the selected item - */ - public > E getNextEnumChoice(Class enumClass) { - String choiceString = this.getNextChoice(); - return Enum.valueOf(enumClass, choiceString); - } - - /** - * Adds a checkbox. - * - * @param label the label - * @param defaultValue the initial state - */ - public void addCheckbox(String label, boolean defaultValue) { - addCheckbox(label, defaultValue, false); - } - - /** - * Adds a checkbox; does not make it recordable if isPreview is true. With - * isPreview true, the checkbox can be referred to as previewCheckbox from - * hereon. - */ - private void addCheckbox(String label, boolean defaultValue, boolean isPreview) { - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - c.insets.left = 10; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - if (checkbox == null) - c.insets = getInsets(15, 20, 0, 0); // top, left, bottom, right - else - c.insets = getInsets(0, 20, 0, 0); - } - c.anchor = GridBagConstraints.WEST; - c.gridwidth = 2; - if (checkbox == null) - checkbox = new Vector(4); - Checkbox cb = new Checkbox(label2); - cb.setState(defaultValue); - cb.addItemListener(this); - cb.addKeyListener(this); - add(cb, c); - c.insets.left = 0; - checkbox.addElement(cb); - if (!isPreview && (Recorder.record || macro)) // preview checkbox is not recordable - saveLabel(cb, label); - if (isPreview) - previewCheckbox = cb; - } - - /** - * Adds a checkbox labelled "Preview" for "automatic" preview. The reference to - * this checkbox can be retrieved by getPreviewCheckbox() and it provides the - * additional method previewRunning for optical feedback while preview is - * prepared. PlugInFilters can have their "run" method automatically called for - * preview under the following conditions: - the PlugInFilter must pass a - * reference to itself (i.e., "this") as an argument to the AddPreviewCheckbox - - * it must implement the DialogListener interface and set the filter parameters - * in the dialogItemChanged method. - it must have DIALOG and PREVIEW set in its - * flags. A previewCheckbox is always off when the filter is started and does - * not get recorded by the Macro Recorder. - * - * @param pfr A reference to the PlugInFilterRunner calling the PlugInFilter if - * automatic preview is desired, null otherwise. - */ - public void addPreviewCheckbox(PlugInFilterRunner pfr) { - if (previewCheckbox != null) - return; - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp != null && imp.isComposite() && ((CompositeImage) imp).getMode() == IJ.COMPOSITE) - return; - this.pfr = pfr; - addCheckbox(previewLabel, false, true); - } - - /** - * Add the preview checkbox with user-defined label; for details see the - * addPreviewCheckbox method with standard "Preview" label. Adds the checkbox - * when the current image is a CompositeImage in "Composite" mode, unlike the - * one argument version. Note that a GenericDialog can have only one - * PreviewCheckbox. - */ - public void addPreviewCheckbox(PlugInFilterRunner pfr, String label) { - if (previewCheckbox != null) - return; - previewLabel = label; - this.pfr = pfr; - addCheckbox(previewLabel, false, true); - } - - /** - * Adds a group of checkboxs using a grid layout. - * - * @param rows the number of rows - * @param columns the number of columns - * @param labels the labels - * @param defaultValues the initial states - */ - public void addCheckboxGroup(int rows, int columns, String[] labels, boolean[] defaultValues) { - addCheckboxGroup(rows, columns, labels, defaultValues, null); - } - - /** - * Adds a group of checkboxs using a grid layout. - * - * @param rows the number of rows - * @param columns the number of columns - * @param labels the labels - * @param defaultValues the initial states - * @param headings the column headings Example: Example: - * http://imagej.net/ij/plugins/multi-column-dialog/index.html - */ - public void addCheckboxGroup(int rows, int columns, String[] labels, boolean[] defaultValues, String[] headings) { - JPanel panel = new JPanel(); - int nRows = headings != null ? rows + 1 : rows; - panel.setLayout(new GridLayout(nRows, columns, 6, 0)); - int startCBIndex = cbIndex; - if (checkbox == null) - checkbox = new Vector(12); - if (headings != null) { - Font font = new Font("SansSerif", Font.BOLD, 12); - for (int i = 0; i < columns; i++) { - if (i > headings.length - 1 || headings[i] == null) - panel.add(new Label("")); - else { - Label label = new Label(headings[i]); - label.setFont(font); - panel.add(label); - } - } - } - int i1 = 0; - int[] index = new int[labels.length]; - for (int row = 0; row < rows; row++) { - for (int col = 0; col < columns; col++) { - int i2 = col * rows + row; - if (i2 >= labels.length) - break; - index[i1] = i2; - String label = labels[i1]; - if (label == null || label.length() == 0) { - Label lbl = new Label(""); - panel.add(lbl); - i1++; - continue; - } - if (label.indexOf('_') != -1) - label = label.replace('_', ' '); - Checkbox cb = new Checkbox(label); - checkbox.addElement(cb); - cb.setState(defaultValues[i1]); - cb.addItemListener(this); - if (IJ.recording() || macro) - saveLabel(cb, labels[i1]); - if (IJ.isLinux()) { - JPanel panel2 = new JPanel(); - panel2.setLayout(new BorderLayout()); - panel2.add("West", cb); - panel.add(panel2); - } else - panel.add(cb); - i1++; - } - } - c.gridx = 0; - c.gridy++; - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.insets = getInsets(10, 0, 0, 0); - addToSameRow = false; - add(panel, c); - } - - /** - * Adds a radio button group. - * - * @param label group label (or null) - * @param items radio button labels - * @param rows number of rows - * @param columns number of columns - * @param defaultItem button initially selected - */ - public void addRadioButtonGroup(String label, String[] items, int rows, int columns, String defaultItem) { - addToSameRow = false; - JPanel panel = new JPanel(); - int n = items.length; - panel.setLayout(new GridLayout(rows, columns, 0, 0)); - CheckboxGroup cg = new CheckboxGroup(); - for (int i = 0; i < n; i++) { - Checkbox cb = new Checkbox(items[i], cg, items[i].equals(defaultItem)); - cb.addItemListener(this); - panel.add(cb); - } - if (radioButtonGroups == null) - radioButtonGroups = new Vector(); - radioButtonGroups.addElement(cg); - Insets insets = getInsets(5, 10, 0, 0); - if (label == null || label.equals("")) { - label = "rbg" + radioButtonGroups.size(); - insets.top += 5; - } else { - setInsets(10, insets.left, 0); - addMessage(label); - insets.top = 2; - insets.left += 10; - } - c.gridx = 0; - c.gridy++; - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.insets = new Insets(insets.top, insets.left, 0, 0); - add(panel, c); - if (IJ.recording() || macro) - saveLabel(cg, label); - } - - /** - * Adds a popup menu. - * - * @param label the label - * @param items the menu items - * @param defaultItem the menu item initially selected - */ - public void addChoice(String label, String[] items, String defaultItem) { - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - if (choice == null) - c.insets = getInsets(5, 0, 5, 0); - else - c.insets = getInsets(0, 0, 5, 0); - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - if (choice == null) { - choice = new Vector(4); - defaultChoiceIndexes = new Vector(4); - } - add(fieldLabel, c); - Choice thisChoice = new Choice(); - thisChoice.addKeyListener(this); - thisChoice.addItemListener(this); - for (int i = 0; i < items.length; i++) - thisChoice.addItem(items[i]); - if (defaultItem != null) - thisChoice.select(defaultItem); - else - thisChoice.select(0); - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - add(thisChoice, c); - choice.addElement(thisChoice); - int index = thisChoice.getSelectedIndex(); - defaultChoiceIndexes.addElement(Integer.valueOf(index)); - if (IJ.recording() || macro) - saveLabel(thisChoice, label); - } - - /** Adds a message consisting of one or more lines of text. */ - public void addMessage(String text) { - addMessage(text, null, null); - } - - /** - * Adds a message consisting of one or more lines of text, which will be - * displayed using the specified font. - */ - public void addMessage(String text, Font font) { - addMessage(text, font, null); - } - - /** - * Adds a message consisting of one or more lines of text, which will be - * displayed using the specified font and color. - */ - public void addMessage(String text, Font font, Color color) { - theLabel = null; - if (text.indexOf('\n') >= 0) - theLabel = new MultiLineLabel(text); - else - theLabel = new Label(text); - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - c.insets = getInsets("".equals(text) ? 0 : 10, 20, 0, 0); // top, left, bottom, right - } - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.HORIZONTAL; - if (font != null) { - if (Prefs.getGuiScale() > 1.0) - font = font.deriveFont((float) (font.getSize() * Prefs.getGuiScale())); - theLabel.setFont(font); - } - if (color != null) - theLabel.setForeground(color); - add(theLabel, c); - c.fill = GridBagConstraints.NONE; - } - - /** - * Adds one or two (side by side) text areas. Append "SCROLLBARS_VERTICAL_ONLY" - * to the text of the first text area to get vertical scrollbars and - * "SCROLLBARS_BOTH" to get both vertical and horizontal scrollbars. - * - * @param text1 initial contents of the first text area - * @param text2 initial contents of the second text area or null - * @param rows the number of rows - * @param columns the number of columns - */ - public void addTextAreas(String text1, String text2, int rows, int columns) { - if (textArea1 != null) - return; - Panel panel = new Panel(); - int scrollbars = TextArea.SCROLLBARS_NONE; - if (text1 != null && text1.endsWith("SCROLLBARS_BOTH")) { - scrollbars = TextArea.SCROLLBARS_BOTH; - text1 = text1.substring(0, text1.length() - 15); - } - if (text1 != null && text1.endsWith("SCROLLBARS_VERTICAL_ONLY")) { - scrollbars = TextArea.SCROLLBARS_VERTICAL_ONLY; - text1 = text1.substring(0, text1.length() - 24); - } - Font font = new Font("SansSerif", Font.PLAIN, (int) (14 * Prefs.getGuiScale())); - textArea1 = new TextArea(text1, rows, columns, scrollbars); - if (IJ.isLinux()) - textArea1.setBackground(Color.white); - /* Changed for Bio7! */ - if (Util.isThemeBlack()) { - textArea1.setBackground(Util.getSWTBackgroundToAWT()); - textArea1.setForeground(Util.getSWTForegroundToAWT()); - } - if (Util.isThemeBlack()) { - Util.getSWTBackgroundToAWT(); - } - textArea1.setFont(font); - textArea1.addTextListener(this); - panel.add(textArea1); - if (text2 != null) { - textArea2 = new TextArea(text2, rows, columns, scrollbars); - if (IJ.isLinux()) - textArea2.setBackground(Color.white); - - /* Changed for Bio7! */ - if (Util.isThemeBlack()) { - textArea2.setBackground(Util.getSWTBackgroundToAWT()); - textArea2.setForeground(Util.getSWTForegroundToAWT()); - - } - textArea2.setFont(font); - panel.add(textArea2); - } - - c.gridx = 0; - c.gridy++; - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.insets = getInsets(15, 20, 0, 0); - addToSameRow = false; - add(panel, c); - } - - /** - * Adds a slider (scroll bar) to the dialog box. Floating point values are used - * if (maxValue-minValue)<=5.0 and either defaultValue or minValue are - * non-integer. - * - * @param label the label - * @param minValue the minimum value of the slider - * @param maxValue the maximum value of the slider - * @param defaultValue the initial value of the slider - */ - public void addSlider(String label, double minValue, double maxValue, double defaultValue) { - if (defaultValue < minValue) - defaultValue = minValue; - if (defaultValue > maxValue) - defaultValue = maxValue; - int digits = 0; - double scale = 1.0; - if ((maxValue - minValue) <= 5.0 && (minValue != (int) minValue || maxValue != (int) maxValue || defaultValue != (int) defaultValue)) { - scale = 50.0; - minValue *= scale; - maxValue *= scale; - defaultValue *= scale; - digits = 2; - } - addSlider(label, minValue, maxValue, defaultValue, scale, digits); - } - - /** - * This vesion of addSlider() adds a 'stepSize' argument. - * Example: http://wsr.imagej.net/macros/SliderDemo.txt - */ - public void addSlider(String label, double minValue, double maxValue, double defaultValue, double stepSize) { - if (stepSize <= 0) - stepSize = 1; - int digits = digits(stepSize); - if (digits == 1 && "Angle:".equals(label)) - digits = 2; - double scale = 1.0 / Math.abs(stepSize); - if (scale <= 0) - scale = 1; - if (defaultValue < minValue) - defaultValue = minValue; - if (defaultValue > maxValue) - defaultValue = maxValue; - minValue *= scale; - maxValue *= scale; - defaultValue *= scale; - addSlider(label, minValue, maxValue, defaultValue, scale, digits); - } - - /** Author: Michael Kaul */ - private static int digits(double d) { - if (d == (int) d) - return 0; - String s = Double.toString(d); - int ePos = s.indexOf("E"); - if (ePos == -1) - ePos = s.indexOf("e"); - int dotPos = s.indexOf("."); - int digits = 0; - if (ePos == -1) - digits = s.substring(dotPos + 1).length(); - else { - String number = s.substring(dotPos + 1, ePos); - if (!number.equals("0")) - digits += number.length(); - digits = digits - Integer.valueOf(s.substring(ePos + 1)); - } - return digits; - } - - private void addSlider(String label, double minValue, double maxValue, double defaultValue, double scale, int digits) { - int columns = 4 + digits - 2; - if (columns < 4) - columns = 4; - if (minValue < 0.0) - columns++; - String mv = IJ.d2s(maxValue, 0); - if (mv.length() > 4 && digits == 0) - columns += mv.length() - 4; - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - c.insets.bottom += 3; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - c.insets = getInsets(0, 0, 3, 0); // top, left, bottom, right - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - add(fieldLabel, c); - - if (slider == null) { - slider = new Vector(5); - sliderIndexes = new Vector(5); - sliderScales = new Vector(5); - sliderDigits = new Vector(5); - } - Scrollbar s = new Scrollbar(Scrollbar.HORIZONTAL, (int) defaultValue, 1, (int) minValue, (int) maxValue + 1); - if (IJ.debugMode) - IJ.log("Scrollbar: " + scale + " " + defaultValue + " " + minValue + " " + maxValue); - GUI.fixScrollbar(s); - slider.addElement(s); - s.addAdjustmentListener(this); - s.setUnitIncrement(1); - if (IJ.isMacOSX()) - s.addKeyListener(this); - s.addMouseWheelListener(new MouseWheelListener() { - public void mouseWheelMoved(MouseWheelEvent e) { - Scrollbar sb = (Scrollbar) e.getSource(); - int value = sb.getValue() + e.getWheelRotation(); - sb.setValue(value); - for (int i = 0; i < slider.size(); i++) { - if (sb == slider.elementAt(i)) { - int index = ((Integer) sliderIndexes.get(i)).intValue(); - TextField tf = (TextField) numberField.elementAt(index); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - int digits = ((Integer) sliderDigits.get(i)).intValue(); - tf.setText("" + IJ.d2s(sb.getValue() / scale, digits)); - } - } - } - }); - - if (numberField == null) { - numberField = new Vector(5); - defaultValues = new Vector(5); - defaultText = new Vector(5); - } - if (IJ.isWindows()) - columns -= 2; - if (columns < 1) - columns = 1; - // IJ.log("scale=" + scale + ", columns=" + columns + ", digits=" + digits); - TextField tf = newTextField(IJ.d2s(defaultValue / scale, digits), columns); - // if (IJ.isLinux()) tf.setBackground(Color.white); - tf.setBackground(Color.white); - tf.addActionListener(this); - tf.addTextListener(this); - tf.addFocusListener(this); - tf.addKeyListener(this); - numberField.addElement(tf); - sliderIndexes.add(Integer.valueOf(numberField.size() - 1)); - sliderScales.add(Double.valueOf(scale)); - sliderDigits.add(Integer.valueOf(digits)); - defaultValues.addElement(Double.valueOf(defaultValue / scale)); - defaultText.addElement(tf.getText()); - tf.setEditable(true); - firstSlider = false; - - JPanel panel = new JPanel(); - GridBagLayout pgrid = new GridBagLayout(); - GridBagConstraints pc = new GridBagConstraints(); - panel.setLayout(pgrid); - pc.gridx = 0; - pc.gridy = 0; - pc.gridwidth = 1; - pc.ipadx = 85; - pc.anchor = GridBagConstraints.WEST; - panel.add(s, pc); - pc.ipadx = 0; // reset - // text field - pc.gridx = 1; - pc.insets = new Insets(5, 5, 0, 0); - pc.anchor = GridBagConstraints.EAST; - panel.add(tf, pc); - - c.gridx = GridBagConstraints.RELATIVE; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - c.insets.left = 0; - c.insets.bottom -= 3; - add(panel, c); - if (IJ.recording() || macro) - saveLabel(tf, label); - } - - private TextField newTextField(String txt, int columns) { - if (IJ.isLinux()) - return new TrimmedTextField(txt, columns); - else - return new TextField(txt, columns); - } - - /* Changed for Bio7! -> Added JPanel method! */ - public void addPanel(JPanel panel) { - addPanel(panel, GridBagConstraints.WEST, addToSameRow ? c.insets : getInsets(5, 0, 0, 0)); - } - - /** Adds a Panel to the dialog. */ - /** Adds a Panel to the dialog. */ - public void addPanel(Panel panel) { - addPanel(panel, GridBagConstraints.WEST, addToSameRow ? c.insets : getInsets(5, 0, 0, 0)); - } - - /* - * public void addPanel(Panel panel) { addPanel(panel , GridBagConstraints.WEST, - * new Insets(5, 0, 0, 0)); } - */ - // extra method to avoid plugin mistake - /* - * public void addPanel(Panel panel) { JPanel panel2 = new JPanel(); Component[] - * comp = panel.getComponents(); for (int i = 0; i < comp.length; i++) { - * panel2.add(comp[i]); } - * - * addPanel(panel, GridBagConstraints.WEST, addToSameRow ? c.insets : - * getInsets(5, 0, 0, 0)); } - */ - - /* Changed for Bio7! -> Extra method for plugins! */ - public void addPanel(Panel panel, int constraints, Insets insets) { - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - } - c.gridwidth = 2; - c.anchor = constraints; - c.insets = insets; - add(panel, c); - } - - /** - * Adds a Panel to the dialog with custom contraint and insets. The defaults are - * GridBagConstraints.WEST (left justified) and "new Insets(5, 0, 0, 0)" (5 - * pixels of padding at the top). - */ - public void addPanel(JPanel panel, int constraints, Insets insets) { - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - } - c.gridwidth = 2; - c.anchor = constraints; - c.insets = insets; - add(panel, c); - } - - /** Adds an image to the dialog. */ - public void addImage(ImagePlus image) { - if (image == null) - return; - ImagePanel imagePanel = new ImagePanel(image); - addPanel(imagePanel); - if (imagePanels == null) - imagePanels = new Vector(); - imagePanels.add(imagePanel); - } - - /** - * Set the insets (margins), in pixels, that will be used for the next component - * added to the dialog (except components added to the same row with - * addToSameRow) - * - * - Default insets: - addMessage: 0,20,0 (empty string) or 10,20,0 - addCheckbox: 15,20,0 (first checkbox) or 0,20,0 - addCheckboxGroup: 10,0,0 - addRadioButtonGroup: 5,10,0 - addNumericField: 5,0,3 (first field) or 0,0,3 - addStringField: 5,0,5 (first field) or 0,0,5 - addChoice: 5,0,5 (first field) or 0,0,5 - * - */ - public void setInsets(int top, int left, int bottom) { - topInset = top; - leftInset = left; - bottomInset = bottom; - customInsets = true; - } - - /** - * Makes the next item appear in the same row as the previous. May be used for - * addNumericField, addSlider, addChoice, addCheckbox, addStringField, - * addMessage, addPanel, and before the showDialog() method (in the latter case, - * the buttons appear to the right of the previous item). Note that addMessage - * (and addStringField, if its column width is more than 8) use the remaining - * width, so it must be the last item of a row. - */ - public void addToSameRow() { - addToSameRow = true; - addToSameRowCalled = true; - } - - /** Sets a replacement label for the "OK" button. */ - public void setOKLabel(String label) { - okay.setLabel(label); - } - - /** Sets a replacement label for the "Cancel" button. */ - public void setCancelLabel(String label) { - cancel.setLabel(label); - } - - /** Sets a replacement label for the "Help" button. */ - public void setHelpLabel(String label) { - helpLabel = label; - } - - /** Unchanged parameters are not recorder in 'smart recording' mode. */ - public void setSmartRecording(boolean smartRecording) { - this.smartRecording = smartRecording; - } - - /** Make this a "Yes No Cancel" dialog. */ - public void enableYesNoCancel() { - enableYesNoCancel(" Yes ", " No "); - } - - /** - * Make this a "Yes No Cancel" dialog with custom labels. Here is an example: - * - * - * GenericDialog gd = new GenericDialog("YesNoCancel Demo"); - * gd.addMessage("This is a custom YesNoCancel dialog"); - * gd.enableYesNoCancel("Do something", "Do something else"); - * gd.showDialog(); - * if (gd.wasCanceled()) - * IJ.log("User clicked 'Cancel'"); - * else if (gd.wasOKed()) - * IJ.log("User clicked 'Yes'"); - * else - * IJ.log("User clicked 'No'"); - * - */ - public void enableYesNoCancel(String yesLabel, String noLabel) { - okay.setLabel(yesLabel); - if (no != null) - no.setLabel(noLabel); - else if (noLabel != null) - no = new Button(noLabel); - } - - /** Do not display "Cancel" button. */ - public void hideCancelButton() { - hideCancelButton = true; - } - - Insets getInsets(int top, int left, int bottom, int right) { - if (customInsets) { - customInsets = false; - return new Insets(topInset, leftInset, bottomInset, 0); - } else - return new Insets(top, left, bottom, right); - } - - /** - * Add an Object implementing the DialogListener interface. This object will be - * notified by its dialogItemChanged method of input to the dialog. The first - * DialogListener will be also called after the user has typed 'OK' or if the - * dialog has been invoked by a macro; it should read all input fields of the - * dialog. For other listeners, the OK button will not cause a call to - * dialogItemChanged; the CANCEL button will never cause such a call. - * - * @param dl the Object that wants to listen. - */ - public void addDialogListener(DialogListener dl) { - if (dialogListeners == null) - dialogListeners = new Vector(); - dialogListeners.addElement(dl); - } - - /** Returns true if the user clicked on "Cancel". */ - public boolean wasCanceled() { - if (wasCanceled && !Thread.currentThread().getName().endsWith("Script_Macro$")) - Macro.abort(); - return wasCanceled; - } - - /** Returns true if the user has clicked on "OK" or a macro is running. */ - public boolean wasOKed() { - return wasOKed || macro; - } - - /** - * Returns the contents of the next numeric field, or NaN if the field does not - * contain a number. - */ - public double getNextNumber() { - if (numberField == null) - return -1.0; - TextField tf = (TextField) numberField.elementAt(nfIndex); - String theText = tf.getText(); - String label = null; - if (macro) { - label = (String) labels.get((Object) tf); - theText = Macro.getValue(macroOptions, label, theText); - } - String originalText = (String) defaultText.elementAt(nfIndex); - double defaultValue = ((Double) (defaultValues.elementAt(nfIndex))).doubleValue(); - double value; - boolean skipRecording = false; - if (theText.equals(originalText)) { - value = defaultValue; - if (smartRecording) - skipRecording = true; - } else if (theText.startsWith("0x")) { - value = parseHex(theText.substring(2)); - } else { - Double d = getValue(theText); - if (d != null) - value = d.doubleValue(); - else { - // Is the value a macro variable? - if (theText.startsWith("&")) - theText = theText.substring(1); - Interpreter interp = Interpreter.getInstance(); - value = interp != null ? interp.getVariable2(theText) : Double.NaN; - if (Double.isNaN(value)) { - invalidNumber = true; - errorMessage = "\"" + theText + "\" is an invalid number"; - value = Double.NaN; - if (macro) { - IJ.error("Macro Error", "Numeric value expected in run() function\n \n" + " Dialog box title: \"" + getTitle() + "\"\n" + " Key: \"" + label.toLowerCase(Locale.US) + "\"\n" - + " Value or variable name: \"" + theText + "\""); - } - } - } - } - if (recorderOn && !skipRecording) { - recordOption(tf, trim(theText)); - } - nfIndex++; - return value; - } - - int parseHex(String hexString) { - int n = 0; - ; - try { - n = Integer.parseInt(hexString, 16); - } catch (NumberFormatException e) { - } - return n; - } - - private String trim(String value) { - if (value.endsWith(".0")) - value = value.substring(0, value.length() - 2); - if (value.endsWith(".00")) - value = value.substring(0, value.length() - 3); - return value; - } - - private void recordOption(Object component, String value) { - if (labels == null) - return; - String label = (String) labels.get(component); - if (value.equals("")) - value = "[]"; - Recorder.recordOption(label, value); - } - - private void recordCheckboxOption(Checkbox cb) { - if (labels == null) - return; - String label = (String) labels.get((Object) cb); - if (label != null) { - if (cb.getState()) // checked - Recorder.recordOption(label); - else if (Recorder.getCommandOptions() == null) - Recorder.recordOption(" "); - } - } - - /* Bio7 extra method! */ - private void recordCheckboxOption(JCheckBox cb) { - if (labels == null) - return; - String label = (String) labels.get((Object) cb); - if (label != null) { - if (cb.isSelected()) // checked - Recorder.recordOption(label); - else if (Recorder.getCommandOptions() == null) - Recorder.recordOption(" "); - } - } - - protected Double getValue(String text) { - Double d; - try { - d = Double.valueOf(text); - } catch (NumberFormatException e) { - d = null; - } - return d; - } - - public double parseDouble(String s) { - if (s == null) - return Double.NaN; - double value = Tools.parseDouble(s); - if (Double.isNaN(value)) { - if (s.startsWith("&")) - s = s.substring(1); - Interpreter interp = Interpreter.getInstance(); - value = interp != null ? interp.getVariable2(s) : Double.NaN; - } - return value; - } - - /** - * Returns true if one or more of the numeric fields contained an invalid - * number. Must be called after one or more calls to getNextNumber(). - */ - public boolean invalidNumber() { - boolean wasInvalid = invalidNumber; - invalidNumber = false; - return wasInvalid; - } - - /** - * Returns an error message if getNextNumber was unable to convert a string into - * a number, otherwise, returns null. - */ - public String getErrorMessage() { - return errorMessage; - } - - /** Returns the contents of the next text field. */ - public String getNextString() { - String theText; - if (stringField == null) - return ""; - TextField tf = (TextField) (stringField.elementAt(sfIndex)); - theText = tf.getText(); - String label = labels != null ? (String) labels.get((Object) tf) : ""; - boolean numberExpected = theText != null && theText.length() > 0 && (Character.isDigit(theText.charAt(0)) || theText.startsWith("-")); - if (macro) { - theText = Macro.getValue(macroOptions, label, theText); - if (theText != null && (theText.startsWith("&") || numberExpected || label.toLowerCase(Locale.US).startsWith(theText))) { - // Is the value a macro variable? - if (theText.startsWith("&")) - theText = theText.substring(1); - Interpreter interp = Interpreter.getInstance(); - String s = interp != null ? interp.getVariableAsString(theText) : null; - if (s != null) - theText = s; - } - } - if (recorderOn && !label.equals("")) { - String s = theText; - if (s != null && s.length() >= 3 && Character.isLetter(s.charAt(0)) && s.charAt(1) == ':' && s.charAt(2) == '\\') - s = s.replaceAll("\\\\", "/"); // replace "\" with "/" in Windows file paths - s = Recorder.fixString(s); - if (!smartRecording || !s.equals((String) defaultStrings.elementAt(sfIndex))) - recordOption(tf, s); - else if (Recorder.getCommandOptions() == null) - Recorder.recordOption(" "); - } - sfIndex++; - return theText; - } - - /** Returns the state of the next checkbox. */ - public boolean getNextBoolean() { - if (checkbox == null) - return false; - /* Bio7 extra check for JCheckBox! */ - if (checkbox.elementAt(cbIndex) instanceof JCheckBox) { - JCheckBox cb = (JCheckBox) (checkbox.elementAt(cbIndex)); - if (recorderOn) - recordCheckboxOption(cb); - boolean state = cb.isSelected(); - if (macro) { - String label = (String) labels.get((Object) cb); - String key = Macro.trimKey(label); - state = isMatch(macroOptions, key + " "); - } - cbIndex++; - return state; - } else { - Checkbox cb = (Checkbox) (checkbox.elementAt(cbIndex)); - if (recorderOn) - recordCheckboxOption(cb); - boolean state = cb.getState(); - if (macro) { - String label = (String) labels.get((Object) cb); - String key = Macro.trimKey(label); - state = isMatch(macroOptions, key + " "); - } - cbIndex++; - return state; - - } - - } - - // Returns true if s2 is in s1 and not in a bracketed literal (e.g., - // "[literal]") - boolean isMatch(String s1, String s2) { - if (s1.startsWith(s2)) - return true; - s2 = " " + s2; - int len1 = s1.length(); - int len2 = s2.length(); - boolean match, inLiteral = false; - char c; - for (int i = 0; i < len1 - len2 + 1; i++) { - c = s1.charAt(i); - if (inLiteral && c == ']') - inLiteral = false; - else if (c == '[') - inLiteral = true; - if (c != s2.charAt(0) || inLiteral || (i > 1 && s1.charAt(i - 1) == '=')) - continue; - match = true; - for (int j = 0; j < len2; j++) { - if (s2.charAt(j) != s1.charAt(i + j)) { - match = false; - break; - } - } - if (match) - return true; - } - return false; - } - - /** Returns the selected item in the next popup menu. */ - public String getNextChoice() { - if (choice == null) - return ""; - Choice thisChoice = (Choice) (choice.elementAt(choiceIndex)); - String item = thisChoice.getSelectedItem(); - if (macro) { - String label = (String) labels.get((Object) thisChoice); - item = Macro.getValue(macroOptions, label, item); - if (item != null && item.startsWith("&")) // value is macro variable - item = getChoiceVariable(item); - } - if (recorderOn) - recordOption(thisChoice, item); - choiceIndex++; - return item; - } - - /** Returns the index of the selected item in the next popup menu. */ - public int getNextChoiceIndex() { - if (choice == null) - return -1; - Choice thisChoice = (Choice) (choice.elementAt(choiceIndex)); - int index = thisChoice.getSelectedIndex(); - if (macro) { - String label = (String) labels.get((Object) thisChoice); - String oldItem = thisChoice.getSelectedItem(); - int oldIndex = thisChoice.getSelectedIndex(); - String item = Macro.getValue(macroOptions, label, oldItem); - if (item != null && item.startsWith("&")) // value is macro variable - item = getChoiceVariable(item); - thisChoice.select(item); - index = thisChoice.getSelectedIndex(); - if (index == oldIndex && !item.equals(oldItem)) { - // is value a macro variable? - Interpreter interp = Interpreter.getInstance(); - String s = interp != null ? interp.getStringVariable(item) : null; - if (s == null) - IJ.error(getTitle(), "\"" + item + "\" is not a valid choice for \"" + label + "\""); - else - item = s; - } - } - if (recorderOn) { - int defaultIndex = ((Integer) (defaultChoiceIndexes.elementAt(choiceIndex))).intValue(); - if (!(smartRecording && index == defaultIndex)) { - String item = thisChoice.getSelectedItem(); - if (!(item.equals("*None*") && getTitle().equals("Merge Channels"))) - recordOption(thisChoice, thisChoice.getSelectedItem()); - } - } - choiceIndex++; - return index; - } - - /** Returns the selected item in the next radio button group. */ - public String getNextRadioButton() { - if (radioButtonGroups == null) - return null; - CheckboxGroup cg = (CheckboxGroup) (radioButtonGroups.elementAt(radioButtonIndex)); - radioButtonIndex++; - Checkbox checkbox = cg.getSelectedCheckbox(); - String item = "null"; - if (checkbox != null) - item = checkbox.getLabel(); - if (macro) { - String label = (String) labels.get((Object) cg); - item = Macro.getValue(macroOptions, label, item); - } - if (recorderOn) - recordOption(cg, item); - return item; - } - - private String getChoiceVariable(String item) { - item = item.substring(1); - Interpreter interp = Interpreter.getInstance(); - String s = interp != null ? interp.getStringVariable(item) : null; - if (s == null) { - double value = interp != null ? interp.getVariable2(item) : Double.NaN; - if (!Double.isNaN(value)) { - if ((int) value == value) - s = "" + (int) value; - else - s = "" + value; - } - } - if (s != null) - item = s; - return item; - } - - /** Returns the contents of the next text area. */ - public String getNextText() { - String text = null; - String key = "text1"; - if (textAreaIndex == 0 && textArea1 != null) { - text = textArea1.getText(); - if (macro) - text = Macro.getValue(macroOptions, "text1", text); - } else if (textAreaIndex == 1 && textArea2 != null) { - text = textArea2.getText(); - if (macro) - text = Macro.getValue(macroOptions, "text2", text); - key = "text2"; - } - textAreaIndex++; - if (recorderOn && text != null) { - String text2 = text; - String cmd = Recorder.getCommand(); - if (cmd != null && cmd.equals("Calibrate...")) - text2 = text2.replace('\n', ' '); - if (cmd != null && cmd.equals("Convolve...")) { - if (!text2.endsWith("\n")) - text2 += "\n"; - } - text2 = Recorder.fixString(text2); - Recorder.recordOption(key, text2); - } - return text; - } - - /** Displays this dialog box. */ - public void showDialog() { - showDialogCalled = true; - addToSameRow = false; - if (macro) { - dispose(); - recorderOn = Recorder.record && Recorder.recordInMacros; - } else { - if (pfr != null) // prepare preview (not in macro mode): tell the PlugInFilterRunner to listen - pfr.setDialog(this); - JPanel buttons = new JPanel(); - buttons.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 0)); - okay.addActionListener(this); - okay.addKeyListener(this); - if (!hideCancelButton) { - cancel.addActionListener(this); - cancel.addKeyListener(this); - } - if (no != null) { - no.addActionListener(this); - no.addKeyListener(this); - } - - boolean addHelp = helpURL != null; - if (addHelp) { - help.setLabel(helpLabel); - help.addActionListener(this); - help.addKeyListener(this); - } - if (IJ.isWindows() || Prefs.dialogCancelButtonOnRight) { - buttons.add(okay); - if (no != null) - buttons.add(no); - ; - if (!hideCancelButton) - buttons.add(cancel); - if (addHelp) - buttons.add(help); - } else { - if (addHelp) - buttons.add(help); - if (no != null) - buttons.add(no); - if (!hideCancelButton) - buttons.add(cancel); - buttons.add(okay); - } - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - } else { - c.gridx = 0; - c.gridy++; - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = addToSameRowCalled ? GridBagConstraints.REMAINDER : 2; - c.insets = new Insets(15, 0, 0, 0); - add(buttons, c); - instance = this; - Font font = getFont(); - if (!fontSizeSet && font != null && Prefs.getGuiScale() != 1.0) { - fontSizeSet = true; - setFont(font.deriveFont((float) (font.getSize() * Prefs.getGuiScale()))); - } - pack(); - if (okay != null && numberField == null && stringField == null && checkbox == null && choice == null && slider == null && radioButtonGroups == null && textArea1 == null) - okay.requestFocusInWindow(); - setup(); - if (centerDialog) - GUI.centerOnImageJScreen(this); - resetCounters(); - setVisible(true); // except for NonBlockingGenericDialog, returns after 'dispose' by OK or Cancel - } - } - - /** - * For plugins that read their input only via dialogItemChanged, call it at - * least once, then stop recording - */ - void finalizeRecording() { - if (optionsRecorded) - return; - optionsRecorded = true; - if (!wasCanceled && dialogListeners != null && dialogListeners.size() > 0) { - try { - resetCounters(); - ((DialogListener) dialogListeners.elementAt(0)).dialogItemChanged(this, null); - } catch (Exception err) { // for exceptions, don't cover the input by a window - IJ.beep(); // but show them at in the "Log" - IJ.log("ERROR: " + err + "\nin DialogListener of " + dialogListeners.elementAt(0) + "\nat " + (err.getStackTrace()[0]) + "\nfrom " + (err.getStackTrace()[1])); - } - recorderOn = false; - } - resetCounters(); - } - - @Override - public void setFont(Font font) { - super.setFont(!fontSizeSet && Prefs.getGuiScale() != 1.0 && font != null ? font.deriveFont((float) (font.getSize() * Prefs.getGuiScale())) : font); - fontSizeSet = true; - } - - /** Reset the counters before reading the dialog parameters */ - public void resetCounters() { - nfIndex = 0; // prepare for readout - sfIndex = 0; - cbIndex = 0; - choiceIndex = 0; - textAreaIndex = 0; - radioButtonIndex = 0; - invalidNumber = false; - } - - /** Returns the Vector containing the numeric TextFields. */ - public Vector getNumericFields() { - return numberField; - } - - /** Returns the Vector containing the string TextFields. */ - public Vector getStringFields() { - return stringField; - } - - /** Returns the Vector containing the Checkboxes. */ - public Vector getCheckboxes() { - return checkbox; - } - - /** Returns the Vector containing the Choices. */ - public Vector getChoices() { - return choice; - } - - /** Returns the Vector containing the sliders (Scrollbars). */ - public Vector getSliders() { - return slider; - } - - /** Returns the Vector that contains the RadioButtonGroups. */ - public Vector getRadioButtonGroups() { - return radioButtonGroups; - } - - /** Returns a reference to textArea1. */ - public TextArea getTextArea1() { - return textArea1; - } - - /** Returns a reference to textArea2. */ - public TextArea getTextArea2() { - return textArea2; - } - - /** - * Returns a reference to the Label or MultiLineLabel created by the last - * addMessage() call. Otherwise returns null. - */ - public Component getMessage() { - return theLabel; - } - - /** Returns a reference to the Preview checkbox. */ - public Checkbox getPreviewCheckbox() { - return previewCheckbox; - } - - /** Returns 'true' if this dialog has a "Preview" checkbox and it is enabled. */ - public boolean isPreviewActive() { - return previewCheckbox != null && previewCheckbox.getState(); - } - - /** - * Returns references to the "OK" ("Yes"), "Cancel", * "No", and "Help" buttons - * as an array of length 4. If a button is not present, the corresponding array - * element is null. - */ - public Button[] getButtons() { - return new Button[] { okay, cancel, no, help }; - } - - /** - * Used by PlugInFilterRunner to provide visable feedback whether preview is - * running or not by switching from "Preview" to "wait..." - */ - public void previewRunning(boolean isRunning) { - if (previewCheckbox != null) { - previewCheckbox.setLabel(isRunning ? previewRunning : previewLabel); - if (IJ.isMacOSX()) - repaint(); // workaround OSX 10.4 refresh bug - } - } - - /** Display dialog centered on the primary screen. */ - public void centerDialog(boolean b) { - centerDialog = b; - } - - /* Display the dialog at the specified location. */ - public void setLocation(int x, int y) { - super.setLocation(x, y); - centerDialog = false; - } - - public void setDefaultString(int index, String str) { - if (defaultStrings != null && index >= 0 && index < defaultStrings.size()) - defaultStrings.set(index, str); - } - - protected void setup() { - } - - public void actionPerformed(ActionEvent e) { - Object source = e.getSource(); - if (source == okay || source == cancel | source == no) { - wasCanceled = source == cancel; - wasOKed = source == okay; - dispose(); - } else if (source == help) { - if (hideCancelButton) { - if (helpURL != null && helpURL.equals("")) { - notifyListeners(e); - return; - } else { - wasOKed = true; - dispose(); - } - } - showHelp(); - } else - notifyListeners(e); - } - - public void textValueChanged(TextEvent e) { - notifyListeners(e); - if (slider == null) - return; - Object source = e.getSource(); - for (int i = 0; i < slider.size(); i++) { - int index = ((Integer) sliderIndexes.get(i)).intValue(); - if (source == numberField.elementAt(index)) { - TextField tf = (TextField) numberField.elementAt(index); - double value = Tools.parseDouble(tf.getText()); - if (!Double.isNaN(value)) { - Scrollbar sb = (Scrollbar) slider.elementAt(i); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - sb.setValue((int) Math.round(value * scale)); - } - } - } - } - - public void itemStateChanged(ItemEvent e) { - notifyListeners(e); - } - - public void focusGained(FocusEvent e) { - Component c = e.getComponent(); - // IJ.log("focusGained: "+c); - if (c instanceof TextField) - ((TextField) c).selectAll(); - } - - public void focusLost(FocusEvent e) { - Component c = e.getComponent(); - if (c instanceof TextField) - ((TextField) c).select(0, 0); - } - - public void keyPressed(KeyEvent e) { - Component component = e.getComponent(); - int keyCode = e.getKeyCode(); - IJ.setKeyDown(keyCode); - if ((component instanceof Scrollbar) && (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT)) { - Scrollbar sb = (Scrollbar) component; - int value = sb.getValue(); - if (keyCode == KeyEvent.VK_RIGHT) - sb.setValue(value + 1); - else - sb.setValue(value - 1); - for (int i = 0; i < slider.size(); i++) { - if (sb == slider.elementAt(i)) { - int index = ((Integer) sliderIndexes.get(i)).intValue(); - TextField tf = (TextField) numberField.elementAt(index); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - int digits = ((Integer) sliderDigits.get(i)).intValue(); - tf.setText("" + IJ.d2s(sb.getValue() / scale, digits)); - } - } - notifyListeners(e); - return; - } - if (keyCode == KeyEvent.VK_ENTER && textArea1 == null && okay != null && okay.isEnabled()) { - wasOKed = true; - if (IJ.isMacOSX()) - accessTextFields(); - dispose(); - } else if (keyCode == KeyEvent.VK_ESCAPE) { - wasCanceled = true; - dispose(); - IJ.resetEscape(); - } else if (keyCode == KeyEvent.VK_W && (e.getModifiers() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0) { - wasCanceled = true; - dispose(); - } - } - - void accessTextFields() { - if (stringField != null) { - for (int i = 0; i < stringField.size(); i++) - ((TextField) (stringField.elementAt(i))).getText(); - } - if (numberField != null) { - for (int i = 0; i < numberField.size(); i++) - ((TextField) (numberField.elementAt(i))).getText(); - } - } - - public void keyReleased(KeyEvent e) { - int keyCode = e.getKeyCode(); - IJ.setKeyUp(keyCode); - int flags = e.getModifiers(); - boolean control = (flags & KeyEvent.CTRL_MASK) != 0; - boolean meta = (flags & KeyEvent.META_MASK) != 0; - boolean shift = (flags & e.SHIFT_MASK) != 0; - if (keyCode == KeyEvent.VK_G && shift && (control || meta)) - new ScreenGrabber().run(""); - } - - public void keyTyped(KeyEvent e) { - } - - public Insets getInsets() { - Insets i = super.getInsets(); - return new Insets(i.top + 10, i.left + 10, i.bottom + 10, i.right + 10); - } - - /** Callback for sliders */ - public void adjustmentValueChanged(AdjustmentEvent e) { - Object source = e.getSource(); - for (int i = 0; i < slider.size(); i++) { - if (source == slider.elementAt(i)) { - Scrollbar sb = (Scrollbar) source; - int index = ((Integer) sliderIndexes.get(i)).intValue(); - TextField tf = (TextField) numberField.elementAt(index); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - int digits = ((Integer) sliderDigits.get(i)).intValue(); - tf.setText("" + IJ.d2s(sb.getValue() / scale, digits)); - } - } - } - - /** - * Notify any DialogListeners of changes having occurred If a listener returns - * false, do not call further listeners and disable the OK button and preview - * Checkbox (if it exists). For PlugInFilters, this ensures that the - * PlugInFilterRunner, which listens as the last one, is not called if the - * PlugInFilter has detected invalid parameters. Thus, unnecessary calling the - * run(ip) method of the PlugInFilter for preview is avoided in that case. - */ - private void notifyListeners(AWTEvent e) { - if (dialogListeners == null) - return; - boolean everythingOk = true; - for (int i = 0; everythingOk && i < dialogListeners.size(); i++) { - try { - resetCounters(); - if (this instanceof NonBlockingGenericDialog) - Recorder.resetCommandOptions(); - if (!((DialogListener) dialogListeners.elementAt(i)).dialogItemChanged(this, e)) - everythingOk = false; // disable further listeners if false (invalid parameters) returned - } catch (Exception err) { // for exceptions, don't cover the input by a window but - IJ.beep(); // show them at in the "Log" - IJ.log("ERROR: " + err + "\nin DialogListener of " + dialogListeners.elementAt(i) + "\nat " + (err.getStackTrace()[0]) + "\nfrom " + (err.getStackTrace()[1])); - } - } - resetCounters(); - boolean workaroundOSXbug = IJ.isMacOSX() && okay != null && !okay.isEnabled() && everythingOk; - if (everythingOk && recorderOn) - optionsRecorded = true; - if (previewCheckbox != null) - previewCheckbox.setEnabled(everythingOk); - if (okay != null) - okay.setEnabled(everythingOk); - if (workaroundOSXbug) - repaint(); // OSX 10.4 bug delays update of enabled until the next input - } - - public void repaint() { - super.repaint(); - if (imagePanels != null) { - for (int i = 0; i < imagePanels.size(); i++) - ((ImagePanel) imagePanels.get(i)).repaint(); - } - } - - public void paint(Graphics g) { - super.paint(g); - if (firstPaint && IJ.isMacOSX() && IJ.isJava18()) { // fix for incompletely drawn dialogs on Macs - EventQueue.invokeLater(new Runnable() { - public void run() { - IJ.wait(50); - Dimension size = getSize(); - if (size != null) - setSize(size.width + 2, size.height + 2); - firstPaint = false; - } - }); - } - } - - public void windowClosing(WindowEvent e) { - wasCanceled = true; - dispose(); - } - - /** - * Adds a "Help" button that opens the specified URL in the default browser. - * With v1.46b or later, displays an HTML formatted message if 'url' starts with - * "". There is an example at - * http://imagej.net/ij/macros/js/DialogWithHelp.js If url is an empty String, - * pressing the "Help" button does nothing except calling the DialogListeners - * (if any). See also: setHelpLabel. - */ - public void addHelp(String url) { - help = new Button(helpLabel); - helpURL = url; - } - - void showHelp() { - if (helpURL.startsWith("")) { - String title = getTitle() + " " + helpLabel; - if (this instanceof NonBlockingGenericDialog) - new HTMLDialog(title, helpURL, false); // non blocking - else - new HTMLDialog(this, title, helpURL); // modal - } else { - String macro = "call('ij.plugin.BrowserLauncher.open', '" + helpURL + "');"; - new MacroRunner(macro); // open on separate thread using BrowserLauncher - } - } - - protected boolean isMacro() { - return macro; - } - - public static GenericDialog getInstance() { - return instance; - } - - /** Closes the dialog; records the options */ - public void dispose() { - super.dispose(); - instance = null; - if (!macro) { - recorderOn = Recorder.record; - IJ.wait(25); - } - resetCounters(); - finalizeRecording(); - resetCounters(); - } - - /** - * Returns a reference to the label of the most recently added numeric field, - * string field, choice or slider. - */ - public Label getLabel() { - return lastLabelAdded; - } - - public void windowActivated(WindowEvent e) { - } - - public void windowOpened(WindowEvent e) { - } - - public void windowClosed(WindowEvent e) { - } - - public void windowIconified(WindowEvent e) { - } - - public void windowDeiconified(WindowEvent e) { - } - - public void windowDeactivated(WindowEvent e) { - } - - @SuppressWarnings("unchecked") - static String getString(DropTargetDropEvent event) throws IOException, UnsupportedFlavorException { - String text = null; - DataFlavor fileList = DataFlavor.javaFileListFlavor; - - if (event.isDataFlavorSupported(fileList)) { - event.acceptDrop(DnDConstants.ACTION_COPY); - java.util.List list = (java.util.List) event.getTransferable().getTransferData(fileList); - text = list.get(0).getAbsolutePath(); - } else if (event.isDataFlavorSupported(DataFlavor.stringFlavor)) { - event.acceptDrop(DnDConstants.ACTION_COPY); - text = (String) event.getTransferable().getTransferData(DataFlavor.stringFlavor); - if (text.startsWith("file://")) - text = text.substring(7); - text = stripSuffix(stripSuffix(text, "\n"), "\r").replaceAll("%20", " "); - } else { - event.rejectDrop(); - return null; - } - - event.dropComplete(text != null); - return text; - } - - static String stripSuffix(String s, String suffix) { - return !s.endsWith(suffix) ? s : s.substring(0, s.length() - suffix.length()); - } - - static class TextDropTarget extends DropTargetAdapter { - TextField text; - DataFlavor flavor = DataFlavor.stringFlavor; - - public TextDropTarget(TextField text) { - this.text = text; - } - - @Override - public void drop(DropTargetDropEvent event) { - try { - String path = getString(event); - path = Recorder.fixPath(path); - if (!path.endsWith("/") && (new File(path)).isDirectory()) - path = path + "/"; - text.setText(path); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - private class BrowseButtonListener implements ActionListener { - private String label; - private TextField textField; - private String mode; - - public BrowseButtonListener(String label, TextField textField, String mode) { - this.label = label; - this.textField = textField; - this.mode = mode; - } - - public void actionPerformed(ActionEvent e) { - String path = null; - String dialogTitle = label; - if (dialogTitle == null || dialogTitle.length() == 0) - dialogTitle = mode.equals("dir") ? "a Folder" : "a File"; - else if (dialogTitle.endsWith(":")) // remove trailing colon - dialogTitle = dialogTitle.substring(0, dialogTitle.length() - 1); - dialogTitle = "Select " + dialogTitle; - if (mode.equals("dir")) { - String saveDefaultDir = OpenDialog.getDefaultDirectory(); - String dir = this.textField.getText(); - boolean setDefaultDir = dir != null && !dir.equals(""); - if (setDefaultDir) - OpenDialog.setDefaultDirectory(dir); - path = IJ.getDir(dialogTitle); - if (setDefaultDir) - OpenDialog.setDefaultDirectory(saveDefaultDir); - } else { - OpenDialog od = new OpenDialog(dialogTitle, null); - String directory = od.getDirectory(); - String name = od.getFileName(); - if (name != null) - path = directory + name; - } - if (path != null) { - // if (IJ.isWindows()) - // path = path.replaceAll("\\\\", "/"); // replace "\" with "/" - this.textField.setText(path); - } - } - - } - - private class TrimmedTextField extends TextField { - - public TrimmedTextField(String text, int columns) { - super(text, columns); - } - - public Dimension getMinimumSize() { - Dimension d = super.getMinimumSize(); - if (d != null) { - d.width = d.width; - d.height = d.height * 3 / 4; - } - return d; - } - - public Dimension getPreferredSize() { - return getMinimumSize(); - } - - } - - /* Changed for Bio7! */ - - public void componentResized(ComponentEvent e) { - // TODO Auto-generated method stub - validate(); - repaint(); - - } - - @Override - public void componentMoved(ComponentEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void componentShown(ComponentEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void componentHidden(ComponentEvent e) { - // TODO Auto-generated method stub - - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/HTMLDialog.java b/com.eco.bio7.image/src/ij/gui/HTMLDialog.java deleted file mode 100644 index eb3e98866..000000000 --- a/com.eco.bio7.image/src/ij/gui/HTMLDialog.java +++ /dev/null @@ -1,154 +0,0 @@ -package ij.gui; -import ij.*; -import ij.plugin.URLOpener; -import ij.macro.MacroRunner; -import ij.util.Java2; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.text.*; -import javax.swing.text.html.*; -import javax.swing.event.HyperlinkListener; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkEvent.EventType; -import java.net.URL; - -/** This is modal or non-modal dialog box that displays HTML formated text. */ -public class HTMLDialog extends JDialog implements ActionListener, KeyListener, HyperlinkListener, WindowListener { - private boolean escapePressed; - private JEditorPane editorPane; - private boolean modal = true; - - public HTMLDialog(String title, String message) { - super(ij.IJ.getInstance(), title, true); - init(message); - } - - public HTMLDialog(Dialog parent, String title, String message) { - super(parent, title, true); - init(message); - } - - public HTMLDialog(String title, String message, boolean modal) { - super(ij.IJ.getInstance(), title, modal); - this.modal = modal; - init(message); - } - - private void init(String message) { - LookAndFeel saveLookAndFeel = Java2.getLookAndFeel(); - Java2.setSystemLookAndFeel(); - Container container = getContentPane(); - container.setLayout(new BorderLayout()); - if (message==null) message = ""; - editorPane = new JEditorPane("text/html",""); - editorPane.setEditable(false); - HTMLEditorKit kit = new HTMLEditorKit(); - editorPane.setEditorKit(kit); - StyleSheet styleSheet = kit.getStyleSheet(); - styleSheet.addRule("body{font-family:Verdana,sans-serif; font-size:11.5pt; margin:5px 10px 5px 10px;}"); //top right bottom left - styleSheet.addRule("h1{font-size:18pt;}"); - styleSheet.addRule("h2{font-size:15pt;}"); - styleSheet.addRule("dl dt{font-face:bold;}"); - editorPane.setText(message); //display the html text with the above style - editorPane.getActionMap().put("insert-break", new AbstractAction(){ - public void actionPerformed(ActionEvent e) {} - }); //suppress beep on key - JScrollPane scrollPane = new JScrollPane(editorPane); - container.add(scrollPane); - JButton button = new JButton("OK"); - button.addActionListener(this); - button.addKeyListener(this); - editorPane.addKeyListener(this); - editorPane.addHyperlinkListener(this); - JPanel panel = new JPanel(); - panel.add(button); - container.add(panel, "South"); - setForeground(Color.black); - addWindowListener(this); - pack(); - Dimension screenD = IJ.getScreenSize(); - Dimension dialogD = getSize(); - int maxWidth = (int)(Math.min(0.70*screenD.width, 800)); //max 70% of screen width, but not more than 800 pxl - if (maxWidth>400 && dialogD.width>maxWidth) - dialogD.width = maxWidth; - if ("Channels".equals(getTitle())) - dialogD.height = 1000; - if (dialogD.height>0.80*screenD.height && screenD.height>400) //max 80% of screen height - dialogD.height = (int)(0.80*screenD.height); - setSize(dialogD); - GUI.centerOnImageJScreen(this); - if (!modal) { - WindowManager.addWindow(this); - show(); - } - final JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar(); - if (verticalScrollBar!=null) { - EventQueue.invokeLater(new Runnable() { - public void run() { - verticalScrollBar.setValue(verticalScrollBar.getMinimum()); //start scrollbar at top - } - }); - } - if (modal) show(); - Java2.setLookAndFeel(saveLookAndFeel); - } - - public void actionPerformed(ActionEvent e) { - dispose(); - } - - public void keyPressed(KeyEvent e) { - int keyCode = e.getKeyCode(); - ij.IJ.setKeyDown(keyCode); - escapePressed = keyCode==KeyEvent.VK_ESCAPE; - if (keyCode==KeyEvent.VK_C) { - if (editorPane.getSelectedText()==null || editorPane.getSelectedText().length()==0) - editorPane.selectAll(); - editorPane.copy(); - editorPane.select(0,0); - } else if (keyCode==KeyEvent.VK_ENTER || keyCode==KeyEvent.VK_W || escapePressed) - dispose(); - } - - public void keyReleased(KeyEvent e) { - int keyCode = e.getKeyCode(); - ij.IJ.setKeyUp(keyCode); - } - - public void keyTyped(KeyEvent e) {} - - public boolean escapePressed() { - return escapePressed; - } - - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - String url = e.getDescription(); //getURL does not work for relative links within document such as "#top" - if (url==null) return; - if (url.startsWith("#")) - editorPane.scrollToReference(url.substring(1)); - else { - String macro = "run('URL...', 'url="+url+"');"; - new MacroRunner(macro); - } - } - } - - public void dispose() { - super.dispose(); - if (!modal) WindowManager.removeWindow(this); - } - - public void windowClosing(WindowEvent e) { - dispose(); - } - - public void windowActivated(WindowEvent e) {} - public void windowOpened(WindowEvent e) {} - public void windowClosed(WindowEvent e) {} - public void windowIconified(WindowEvent e) {} - public void windowDeiconified(WindowEvent e) {} - public void windowDeactivated(WindowEvent e) {} - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/HistogramPlot.java b/com.eco.bio7.image/src/ij/gui/HistogramPlot.java deleted file mode 100644 index 9271aef4c..000000000 --- a/com.eco.bio7.image/src/ij/gui/HistogramPlot.java +++ /dev/null @@ -1,409 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.plugin.filter.Analyzer; -import ij.measure.*; -import ij.macro.Interpreter; -import java.awt.*; -import java.awt.image.*; - -public class HistogramPlot extends ImagePlus { - static final double SCALE = Prefs.getGuiScale(); - static final int HIST_WIDTH = (int)(SCALE*256); - static final int HIST_HEIGHT = (int)(SCALE*128); - static final int XMARGIN = (int)(20*SCALE); - static final int YMARGIN = (int)(10*SCALE); - /* Changed for Bio7! Correction for the width else no plot is drawn! */ - static final int WIN_WIDTH = HIST_WIDTH + (int) (41 * SCALE); - static final int WIN_HEIGHT = HIST_HEIGHT + (int)(118*SCALE); - static final int BAR_HEIGHT = (int)(SCALE*12); - static final int INTENSITY1=0, INTENSITY2=1, RGB=2, RED=3, GREEN=4, BLUE=5; - static final Color frameColor = new Color(30,60,120); - - int rgbMode = -1; - ImageStatistics stats; - boolean stackHistogram; - Calibration cal; - long[] histogram; - LookUpTable lut; - int decimalPlaces; - int digits; - long newMaxCount; - boolean logScale; - int yMax; - int srcImageID; - Rectangle frame; - Font font = new Font("SansSerif",Font.PLAIN,(int)(12*SCALE)); - boolean showBins; - int col1, col2, row1, row2, row3, row4, row5; - - public HistogramPlot() { - setImage(NewImage.createRGBImage("Histogram", WIN_WIDTH, WIN_HEIGHT, 1, NewImage.FILL_WHITE)); - } - - /** Plots a histogram using the specified title and number of bins. - Currently, the number of bins must be 256 expect for 32 bit images. */ - public void draw(String title, ImagePlus imp, int bins) { - draw(imp, bins, 0.0, 0.0, 0); - } - - /** Plots a histogram using the specified title, number of bins and histogram range. - Currently, the number of bins must be 256 and the histogram range range must be - the same as the image range expect for 32 bit images. */ - public void draw(ImagePlus imp, int bins, double histMin, double histMax, int yMax) { - boolean limitToThreshold = (Analyzer.getMeasurements()&LIMIT)!=0; - ImageProcessor ip = imp.getProcessor(); - if (ip.isThreshold() && ip.getLutUpdateMode()==ImageProcessor.NO_LUT_UPDATE) - limitToThreshold = false; // ignore invisible thresholds - if (imp.isRGB() && rgbMode maxCount2) && (i != stats.mode)) { - maxCount2 = histogram[i]; - mode2 = i; - } - } - newMaxCount = histogram[stats.mode]; - if ((newMaxCount>(maxCount2 * 2)) && (maxCount2 != 0)) - newMaxCount = (int)(maxCount2 * 1.5); - if (logScale) - drawLogPlot(yMax>0?yMax:newMaxCount, ip); - drawPlot(yMax>0?yMax:newMaxCount, ip); - histogram[stats.mode] = saveModalCount; - x = XMARGIN + 1; - y = YMARGIN + HIST_HEIGHT + 2; - if (imp==null) - lut.drawUnscaledColorBar(ip, x-1, y, HIST_WIDTH, BAR_HEIGHT); - else - drawAlignedColorBar(imp, xMin, xMax, ip, x-1, y, HIST_WIDTH, BAR_HEIGHT); - y += BAR_HEIGHT+(int)(15*SCALE); - drawText(ip, x, y); - srcImageID = imp.getID(); - } - - void drawAlignedColorBar(ImagePlus imp, double xMin, double xMax, ImageProcessor ip, int x, int y, int width, int height) { - ImageProcessor ipSource = imp.getProcessor(); - float[] pixels = null; - ImageProcessor ipRamp = null; - if (rgbMode>=INTENSITY1) { - ipRamp = new FloatProcessor(width, height); - if (rgbMode==RED) - ipRamp.setColorModel(LUT.createLutFromColor(Color.red)); - else if (rgbMode==GREEN) - ipRamp.setColorModel(LUT.createLutFromColor(Color.green)); - else if (rgbMode==BLUE) - ipRamp.setColorModel(LUT.createLutFromColor(Color.blue)); - pixels = (float[])ipRamp.getPixels(); - } else - pixels = new float[width*height]; - for (int j=0; jipSource.getPixelCount()) { // stack histogram - cm = LUT.createLutFromColor(Color.white); - min = stats.min; - max = stats.max; - } else - cm = ((CompositeImage)imp).getChannelLut(); - } else if (!ipSource.isThreshold()) - cm = ipSource.getColorModel(); - else - cm = ipSource.getCurrentColorModel(); - ipRamp = new FloatProcessor(width, height, pixels, cm); - } - ipRamp.setMinAndMax(min,max); - ImageProcessor bar = null; - if (ip instanceof ColorProcessor) - bar = ipRamp.convertToRGB(); - else - bar = ipRamp.convertToByte(true); - ip.insert(bar, x,y); - ip.setColor(Color.black); - ip.drawRect(x-1, y, width+2, height); - } - - /** Scales a threshold level to the range 0-255. */ - int scaleDown(ImageProcessor ip, double threshold) { - double min = ip.getMin(); - double max = ip.getMax(); - if (max>min) - return (int)(((threshold-min)/(max-min))*255.0); - else - return 0; - } - - void drawPlot(long maxCount, ImageProcessor ip) { - if (frame == null) - frame = getDefaultFrame(); - drawPlot(histogram, maxCount, ip, frame, frameColor); - } - - /** Draws the histogram with linear scaling and the frame. - * Also used by HistogramWindow */ - static void drawPlot(long[] histogram, long maxCount, ImageProcessor ip, Rectangle frame, Color frameColor) { - if (maxCount==0) maxCount = 1; - if (histogram.length==256) { - double scale2 = HIST_WIDTH/256.0; - int barWidth = 1; - if (SCALE>1) barWidth=2; - if (SCALE>2) barWidth=3; - for (int i = 0; i < 256; i++) { - int x =(int)(i*scale2); - int y = (int)(((double)HIST_HEIGHT*(double)histogram[i])/maxCount); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - for (int j = 0; jHIST_HEIGHT) y = HIST_HEIGHT; - ip.drawLine(i+XMARGIN, YMARGIN+HIST_HEIGHT, i+XMARGIN, YMARGIN+HIST_HEIGHT-y); - } - } else { - double xscale = (double)HIST_WIDTH/histogram.length; - for (int i=0; i0L) { - int y = (int)(((double)HIST_HEIGHT*(double)value)/maxCount); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - int x = (int)(i*xscale)+XMARGIN; - ip.drawLine(x, YMARGIN+HIST_HEIGHT, x, YMARGIN+HIST_HEIGHT-y); - } - } - } - ip.setColor(frameColor); - ip.drawRect(frame.x-1, frame.y, frame.width+2, frame.height+1); - ip.setColor(Color.black); - } - - void drawLogPlot (long maxCount, ImageProcessor ip) { - if (frame == null) - frame = getDefaultFrame(); - drawLogPlot(histogram, maxCount, ip, frame); - } - - /** Draws the logarithm of histogram values in gray. To be called before the regular plot, - * which is then in the foreground. - * Also used by HistogramWindow */ - static void drawLogPlot(long[] histogram, long maxCount, ImageProcessor ip, Rectangle frame) { - ip.drawRect(frame.x-1, frame.y, frame.width+2, frame.height+1); - double max = Math.log(maxCount + 0.5); - ip.setColor(Color.gray); - if (histogram.length==256) { - double scale2 = HIST_WIDTH/256.0; - int barWidth = 1; - if (SCALE>1) barWidth=2; - if (SCALE>2) barWidth=3; - for (int i=0; i < 256; i++) { - int x =(int)(i*scale2); - int y = histogram[i]==0?0:(int)Math.max(HIST_HEIGHT*Math.log(histogram[i]+0.5)/max, 1); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - for (int j = 0; jHIST_HEIGHT) y = HIST_HEIGHT; - ip.drawLine(i+XMARGIN, YMARGIN+HIST_HEIGHT, i+XMARGIN, YMARGIN+HIST_HEIGHT-y); - } - } else { - double xscale = (double)HIST_WIDTH/histogram.length; - for (int i=0; i0L) { - int y = (int)Math.max(HIST_HEIGHT*Math.log(value+0.5)/max, 1); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - int x = (int)(i*xscale)+XMARGIN; - ip.drawLine(x, YMARGIN+HIST_HEIGHT, x, YMARGIN+HIST_HEIGHT-y); - } - } - } - ip.setColor(Color.black); - } - - void drawText(ImageProcessor ip, int x, int y) { - ip.setFont(font); - ip.setAntialiasedText(true); - double hmin = cal.getCValue(stats.histMin); - double hmax = cal.getCValue(stats.histMax); - ip.drawString(d2s(hmin), x - 4, y); - ip.drawString(d2s(hmax), x + HIST_WIDTH - getWidth(hmax, ip) + 10, y); - if (rgbMode>=INTENSITY1) { - x += HIST_WIDTH/2; - y += 1; - ip.setJustification(ImageProcessor.CENTER_JUSTIFY); - boolean weighted = ((ColorProcessor)ip).weightedHistogram(); - switch (rgbMode) { - case INTENSITY1: ip.drawString((weighted?"Intensity (weighted)":"Intensity (unweighted)"), x, y); break; - case INTENSITY2: ip.drawString((weighted?"Intensity (unweighted)":"Intensity (weighted)"), x, y); break; - case RGB: ip.drawString("R+G+B", x, y); break; - case RED: ip.drawString("Red", x, y); break; - case GREEN: ip.drawString("Green", x, y); break; - case BLUE: ip.drawString("Blue", x, y); break; - } - ip.setJustification(ImageProcessor.LEFT_JUSTIFY); - } - //double range = hmax-hmin; - //if (fixedRange&&!cal.calibrated()&&hmin==0&&hmax==255) - // range = 256; - double binWidth = stats.binSize; - binWidth = Math.abs(binWidth); - showBins = binWidth!=1.0; - col1 = XMARGIN + 5; - col2 = XMARGIN + HIST_WIDTH/2; - row1 = y+(int)(25*SCALE); - if (showBins) row1 -= (int)(8*SCALE); - row2 = row1 + (int)(15*SCALE); - row3 = row2 + (int)(15*SCALE); - row4 = row3 + (int)(15*SCALE); - row5 = row4 + (int)(15*SCALE); - long count = stats.longPixelCount>0?stats.longPixelCount:stats.pixelCount; - String modeCount = " (" + stats.maxCount + ")"; - if (histogram!=null) {// Add '*' if multi-modal histogram - int mcount = 0;; - for (int i=0; i1) break; - } - if (mcount>1) modeCount=modeCount+"*"; - } - if (modeCount.length()>12) modeCount = ""; - ip.drawString("N: " + count, col1, row1); - ip.drawString("Min: " + d2s(stats.min), col2, row1); - ip.drawString("Mean: " + d2s(stats.mean), col1, row2); - ip.drawString("Max: " + d2s(stats.max), col2, row2); - ip.drawString("StdDev: " + d2s(stats.stdDev), col1, row3); - ip.drawString("Mode: " + d2s(stats.dmode) + modeCount, col2, row3); - if (showBins) { - ip.drawString("Bins: " + d2s(stats.nBins), col1, row4); - ip.drawString("Bin Width: " + d2s(binWidth), col2, row4); - } - } - - /** Returns the default frame size. This is the size of the plot area excluding the - * line around. */ - static Rectangle getDefaultFrame() { - return new Rectangle(XMARGIN, YMARGIN, HIST_WIDTH, HIST_HEIGHT); - } - - private String d2s(double d) { - if ((int)d==d) - return IJ.d2s(d, 0); - else - return IJ.d2s(d, 3, 8); - } - - int getWidth(double d, ImageProcessor ip) { - return ip.getStringWidth(d2s(d)); - } - - public int[] getHistogram() { - int[] hist = new int[histogram.length]; - for (int i=0; i) ctab.getSelection().getData(); - JPanel current = (JPanel) ve.get(2); - current.add(buttons); - GUI.scale(buttons); - } - }); - CanvasView.getCanvas_view().getCurrent().validate(); - - } - - public void setup() { - setup(null); - } - - public void mouseMoved(int x, int y) { - ImageProcessor ip = this.imp != null ? this.imp.getProcessor() : null; - if (ip == null) - return; - if ((frame != null) && x >= frame.x && x <= (frame.x + frame.width)) { - /* Changed for Bio7! We have no frame margin! */ - x = x + 20 - frame.x; - x = (x - frame.x); - int index = (int) (x * (SCALE * histogram.length) / HIST_WIDTH / SCALE); - if (index < 0) - index = 0; - if (index >= histogram.length) - index = histogram.length - 1; - double value = cal.getCValue(stats.histMin + index * stats.binSize); - drawValueAndCount(ip, value, histogram[index]); - } else - drawValueAndCount(ip, Double.NaN, -1); - this.imp.updateAndDraw(); - } - - protected void drawHistogram(ImageProcessor ip, boolean fixedRange) { - drawHistogram(null, ip, fixedRange, 0.0, 0.0); - } - - void drawHistogram(ImagePlus imp, ImageProcessor ip, boolean fixedRange, double xMin, double xMax) { - if (frame == null) - frame = HistogramPlot.getDefaultFrame(); - int x, y; - long maxCount2 = 0; - int mode2 = 0; - long saveModalCount; - ip.setColor(Color.black); - ip.setLineWidth(1); - decimalPlaces = Analyzer.getPrecision(); - digits = cal.calibrated() || stats.binSize != 1.0 ? decimalPlaces : 0; - saveModalCount = histogram[stats.mode]; - for (int i = 0; i < histogram.length; i++) { - if ((histogram[i] > maxCount2) && (i != stats.mode)) { - maxCount2 = histogram[i]; - mode2 = i; - } - } - newMaxCount = histogram[stats.mode]; - if ((newMaxCount > (maxCount2 * 2)) && (maxCount2 != 0)) - newMaxCount = (int) (maxCount2 * 1.5); - if (logScale || IJ.shiftKeyDown() && !liveMode()) - HistogramPlot.drawLogPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame); - HistogramPlot.drawPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame, Color.BLACK); - histogram[stats.mode] = saveModalCount; - x = XMARGIN + 1; - y = YMARGIN + HIST_HEIGHT + 2; - if (imp == null) - lut.drawUnscaledColorBar(ip, x - 1, y, HIST_WIDTH, BAR_HEIGHT); - else - drawAlignedColorBar(imp, xMin, xMax, ip, x - 1, y, HIST_WIDTH, BAR_HEIGHT); - y += BAR_HEIGHT + (int) (15 * SCALE); - drawText(ip, x, y, fixedRange); - srcImageID = imp.getID(); - } - - void drawAlignedColorBar(ImagePlus imp, double xMin, double xMax, ImageProcessor ip, int x, int y, int width, int height) { - ImageProcessor ipSource = imp.getProcessor(); - float[] pixels = null; - ImageProcessor ipRamp = null; - if (rgbMode >= INTENSITY1) { - ipRamp = new FloatProcessor(width, height); - if (rgbMode == RED) - ipRamp.setColorModel(LUT.createLutFromColor(Color.red)); - else if (rgbMode == GREEN) - ipRamp.setColorModel(LUT.createLutFromColor(Color.green)); - else if (rgbMode == BLUE) - ipRamp.setColorModel(LUT.createLutFromColor(Color.blue)); - pixels = (float[]) ipRamp.getPixels(); - } else - pixels = new float[width * height]; - for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i++) - pixels[i + width * j] = (float) (xMin + i * (xMax - xMin) / (width - 1)); - } - double min = ipSource.getMin(); - double max = ipSource.getMax(); - if (ipSource.getNChannels() == 1) { - ColorModel cm = null; - if (imp.isComposite()) { - if (stats != null && stats.pixelCount > ipSource.getPixelCount()) { // stack histogram - cm = LUT.createLutFromColor(Color.white); - min = stats.min; - max = stats.max; - } else - cm = ((CompositeImage) imp).getChannelLut(); - } else if (!ipSource.isThreshold()) - cm = ipSource.getColorModel(); - else - cm = ipSource.getCurrentColorModel(); - ipRamp = new FloatProcessor(width, height, pixels, cm); - } - ipRamp.setMinAndMax(min, max); - ImageProcessor bar = null; - if (ip instanceof ColorProcessor) - bar = ipRamp.convertToRGB(); - else - bar = ipRamp.convertToByte(true); - ip.insert(bar, x, y); - ip.setColor(Color.black); - ip.drawRect(x - 1, y, width + 2, height); - } - - /** Scales a threshold level to the range 0-255. */ - int scaleDown(ImageProcessor ip, double threshold) { - double min = ip.getMin(); - double max = ip.getMax(); - if (max > min) - return (int) (((threshold - min) / (max - min)) * 255.0); - else - return 0; - } - - void drawText(ImageProcessor ip, int x, int y, boolean fixedRange) { - ip.setFont(font); - ip.setAntialiasedText(true); - double hmin = cal.getCValue(stats.histMin); - double hmax = cal.getCValue(stats.histMax); - ip.drawString(d2s(hmin), x - 4, y); - ip.drawString(d2s(hmax), x + HIST_WIDTH - getWidth(hmax, ip) + 10, y); - if (rgbMode >= INTENSITY1) { - x += HIST_WIDTH / 2; - y += 1; - ip.setJustification(ImageProcessor.CENTER_JUSTIFY); - boolean weighted = ((ColorProcessor) ip).weightedHistogram(); - switch (rgbMode) { - case INTENSITY1: - ip.drawString((weighted ? "Intensity (weighted)" : "Intensity (unweighted)"), x, y); - break; - case INTENSITY2: - ip.drawString((weighted ? "Intensity (unweighted)" : "Intensity (weighted)"), x, y); - break; - case RGB: - ip.drawString("R+G+B", x, y); - break; - case RED: - ip.drawString("Red", x, y); - break; - case GREEN: - ip.drawString("Green", x, y); - break; - case BLUE: - ip.drawString("Blue", x, y); - break; - } - ip.setJustification(ImageProcessor.LEFT_JUSTIFY); - } - double binWidth = stats.binSize; - binWidth = Math.abs(binWidth); - showBins = binWidth != 1.0 || !fixedRange; - col1 = XMARGIN + 5; - col2 = XMARGIN + HIST_WIDTH / 2; - row1 = y + (int) (25 * SCALE); - if (showBins) - row1 -= (int) (8 * SCALE); - row2 = row1 + (int) (15 * SCALE); - row3 = row2 + (int) (15 * SCALE); - row4 = row3 + (int) (15 * SCALE); - row5 = row4 + (int) (15 * SCALE); - long count = stats.longPixelCount > 0 ? stats.longPixelCount : stats.pixelCount; - String modeCount = " (" + stats.maxCount + ")"; - if (histogram != null) {// Add '*' if multi-modal histogram - int mcount = 0; - ; - for (int i = 0; i < histogram.length; i++) - if (histogram[i] == stats.maxCount) - mcount++; - if (mcount > 1) - modeCount = modeCount + "*"; - } - if (modeCount.length() > 12) - modeCount = ""; - - ip.drawString("N: " + count, col1, row1); - ip.drawString("Min: " + d2s(stats.min), col2, row1); - ip.drawString("Mean: " + d2s(stats.mean), col1, row2); - ip.drawString("Max: " + d2s(stats.max), col2, row2); - ip.drawString("StdDev: " + d2s(stats.stdDev), col1, row3); - ip.drawString("Mode: " + d2s(stats.dmode) + modeCount, col2, row3); - if (showBins) { - ip.drawString("Bins: " + d2s(stats.nBins), col1, row4); - ip.drawString("Bin Width: " + d2s(binWidth), col2, row4); - } - drawValueAndCount(ip, Double.NaN, -1); - } - - private void drawValueAndCount(ImageProcessor ip, double value, long count) { - int y = showBins ? row4 : row3; - ip.setRoi(0, y, WIN_WIDTH, WIN_HEIGHT - y); - ip.setColor(Color.white); - ip.fill(); - ip.setColor(Color.black); - String sValue = Double.isNaN(value) ? "---" : d2s(value); - String sCount = count == -1 ? "---" : "" + count; - int row = showBins ? row5 : row4; - ip.drawString("Value: " + sValue, col1, row); - ip.drawString("Count: " + sCount, col2, row); - } - - private String d2s(double d) { - if ((int) d == d) - return IJ.d2s(d, 0); - else - return IJ.d2s(d, 3, 8); - } - - int getWidth(double d, ImageProcessor ip) { - return ip.getStringWidth(d2s(d)); - } - - /** Returns the histogram values as a ResultsTable. */ - public ResultsTable getResultsTable() { - int decimalPlaces = Analyzer.getPrecision(); - if (digits == 0 && stats.binSize != 1.0) - digits = decimalPlaces; - ResultsTable rt = new ResultsTable(); - rt.setPrecision(digits); - String vheading = stats.binSize == 1.0 ? "value" : "bin start"; - if (cal.calibrated() && !cal.isSigned16Bit()) { - for (int i = 0; i < stats.nBins; i++) { - rt.setValue("level", i, i); - rt.setValue(vheading, i, cal.getCValue(stats.histMin + i * stats.binSize)); - rt.setValue("count", i, histogram[i]); - } - } else { - for (int i = 0; i < stats.nBins; i++) { - if (stats.binSize != 1.0) - rt.setValue("index", i, i); - rt.setValue(vheading, i, cal.getCValue(stats.histMin + i * stats.binSize)); - rt.setValue("count", i, histogram[i]); - } - } - return rt; - } - - public void showList() { - ResultsTable rt = getResultsTable(); - rt.show(getTitle()); - } - - protected void copyToClipboard() { - Clipboard systemClipboard = null; - try { - systemClipboard = getToolkit().getSystemClipboard(); - } catch (Exception e) { - systemClipboard = null; - } - if (systemClipboard == null) { - IJ.error("Unable to copy to Clipboard."); - return; - } - IJ.showStatus("Copying histogram values..."); - CharArrayWriter aw = new CharArrayWriter(stats.nBins * 4); - PrintWriter pw = new PrintWriter(aw); - for (int i = 0; i < stats.nBins; i++) - pw.print(ResultsTable.d2s(cal.getCValue(stats.histMin + i * stats.binSize), digits) + "\t" + histogram[i] + "\n"); - String text = aw.toString(); - pw.close(); - StringSelection contents = new StringSelection(text); - systemClipboard.setContents(contents, this); - IJ.showStatus(text.length() + " characters copied to Clipboard"); - } - - void replot() { - ImageProcessor ip = this.imp.getProcessor(); - frame = new Rectangle(XMARGIN, YMARGIN, HIST_WIDTH, HIST_HEIGHT); - ip.setColor(Color.white); - ip.setRoi(frame.x - 1, frame.y, frame.width + 2, frame.height); - ip.fill(); - ip.resetRoi(); - ip.setColor(Color.black); - ip.setLineWidth(1); - if (logScale) - HistogramPlot.drawLogPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame); - HistogramPlot.drawPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame, Color.BLACK); - this.imp.updateAndDraw(); - } - - public void actionPerformed(ActionEvent e) { - Object b = e.getSource(); - if (b == live) - toggleLiveMode(); - else if (b == rgb) - changeChannel(); - else if (b == list) { - showList(); - if (!Recorder.scriptMode()) - Recorder.record("Table.showHistogramTable"); - } else if (b == copy) - copyToClipboard(); - else if (b == log) { - logScale = !logScale; - replot(); - } - } - - public void lostOwnership(Clipboard clipboard, Transferable contents) { - } - - public int[] getHistogram() { - int[] hist = new int[histogram.length]; - for (int i = 0; i < histogram.length; i++) - hist[i] = (int) histogram[i]; - return hist; - } - - public double[] getXValues() { - double[] values = new double[stats.nBins]; - for (int i = 0; i < stats.nBins; i++) - values[i] = cal.getCValue(stats.histMin + i * stats.binSize); - return values; - } - - private void toggleLiveMode() { - if (liveMode()) - removeListeners(); - else - enableLiveMode(); - } - - private void changeChannel() { - ImagePlus imp = WindowManager.getImage(srcImageID); - if (imp == null || !imp.isRGB()) - return; - else { - rgbMode++; - if (rgbMode > BLUE) - rgbMode = INTENSITY1; - ColorProcessor cp = (ColorProcessor) imp.getProcessor(); - boolean weighted = cp.weightedHistogram(); - if (rgbMode == INTENSITY2) { - double[] weights = cp.getRGBWeights(); - if (weighted) - cp.setRGBWeights(1d / 3d, 1d / 3d, 1d / 3d); - else - cp.setRGBWeights(0.299, 0.587, 0.114); - showHistogram(imp, 256); - cp.setRGBWeights(weights); - } else - showHistogram(imp, 256); - } - } - - private boolean liveMode() { - return live != null && live.getForeground() == Color.red; - } - - private void enableLiveMode() { - if (bgThread == null) { - srcImp = WindowManager.getImage(srcImageID); - if (srcImp == null) - return; - bgThread = new Thread(this, "Live Histogram"); - bgThread.setPriority(Math.max(bgThread.getPriority() - 3, Thread.MIN_PRIORITY)); - bgThread.start(); - imageUpdated(srcImp); - } - createListeners(); - if (srcImp != null) - imageUpdated(srcImp); - } - - // Unused - public void imageOpened(ImagePlus imp) { - } - - // This listener is called if the source image content is changed - public synchronized void imageUpdated(ImagePlus imp) { - if (imp == srcImp) { - doUpdate = true; - notify(); - } - } - - public synchronized void roiModified(ImagePlus img, int id) { - if (img == srcImp) { - doUpdate = true; - notify(); - } - } - - // If either the source image or this image are closed, exit - public void imageClosed(ImagePlus imp) { - if (imp == srcImp || imp == this.imp) { - if (bgThread != null) - bgThread.interrupt(); - bgThread = null; - removeListeners(); - srcImp = null; - } - } - - // the background thread for live plotting. - public void run() { - while (true) { - if (doUpdate && srcImp != null) { - if (srcImp.getRoi() != null) - IJ.wait(50); // delay to make sure the roi has been updated - if (srcImp != null) { - if (srcImp.getBitDepth() == 16 && ImagePlus.getDefault16bitRange() != 0) - showHistogram(srcImp, 256, 0, Math.pow(2, ImagePlus.getDefault16bitRange()) - 1); - else - showHistogram(srcImp, 256); - } - } - synchronized (this) { - if (doUpdate) { - doUpdate = false; // and loop again - } else { - try { - wait(); - } // notify wakes up the thread - catch (InterruptedException e) { // interrupted tells the thread to exit - return; - } - } - } - } - } - - private void createListeners() { - if (srcImp == null) - return; - ImagePlus.addImageListener(this); - Roi.addRoiListener(this); - if (live != null) { - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); - live.setForeground(Color.red); - } - } - - private void removeListeners() { - if (srcImp == null) - return; - ImagePlus.removeImageListener(this); - Roi.removeRoiListener(this); - if (live != null) { - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.PLAIN, font.getSize())); - // live.setForeground(Color.black); - Color swtForegroundToAWT = Util.getSWTForegroundToAWT(); - live.setForeground(swtForegroundToAWT); - } - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImageCanvas.java b/com.eco.bio7.image/src/ij/gui/ImageCanvas.java deleted file mode 100644 index 70d1014fd..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageCanvas.java +++ /dev/null @@ -1,2236 +0,0 @@ -package ij.gui; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Event; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Frame; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Insets; -import java.awt.MenuItem; -import java.awt.Point; -import java.awt.PopupMenu; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.event.InputEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; -import java.awt.event.WindowEvent; -import java.awt.image.IndexColorModel; -import java.util.Timer; -import java.util.TimerTask; -import java.util.Vector; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.swing.JPanel; - -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; - -import com.eco.bio7.ImageJPluginActions.ImageJContextMenuAction; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.Util; - -import ij.IJ; -import ij.ImageJ; -import ij.ImagePlus; -import ij.Menus; -import ij.Prefs; -import ij.WindowManager; -import ij.macro.MacroRunner; -import ij.measure.ResultsTable; -import ij.plugin.PointToolOptions; -import ij.plugin.WandToolOptions; -import ij.plugin.frame.Recorder; -import ij.plugin.frame.RoiManager; -import ij.plugin.tool.PlugInTool; -import ij.process.FloatPolygon; -import ij.util.Tools; - -/** This is a Canvas used to display images in a Window. */ -public class ImageCanvas extends JPanel implements MouseListener, MouseWheelListener, MouseMotionListener, Cloneable { - - protected static Cursor defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR); - protected static Cursor handCursor = new Cursor(Cursor.HAND_CURSOR); - protected static Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR); - protected static Cursor crosshairCursor = new Cursor(Cursor.CROSSHAIR_CURSOR); - - public static boolean usePointer = Prefs.usePointerCursor; - - protected ImagePlus imp; - protected boolean imageUpdated; - protected Rectangle srcRect; - protected int imageWidth, imageHeight; - protected int xMouse; // current cursor offscreen x location - protected int yMouse; // current cursor offscreen y location - - private boolean showCursorStatus = true; - private int sx2, sy2; - private boolean disablePopupMenu; - private static Color zoomIndicatorColor; - private static Font smallFont, largeFont; - private Font font; - private Rectangle[] labelRects; - private boolean maxBoundsReset; - private Overlay showAllOverlay; - private static final int LIST_OFFSET = 100000; - private static Color showAllColor = Prefs.getColor(Prefs.SHOW_ALL_COLOR, new Color(0, 255, 255)); - private Color defaultColor = showAllColor; - private static Color labelColor, bgColor; - private int resetMaxBoundsCount; - private Roi currentRoi; - private int mousePressedX, mousePressedY; - private long mousePressedTime; - private boolean overOverlayLabel; - private Shell tempShell; - - /** - * If the mouse moves less than this in screen pixels, successive zoom - * operations are on the same image pixel - */ - protected final static int MAX_MOUSEMOVE_ZOOM = 10; - /** - * Screen coordinates where the last zoom operation was done (initialized to - * impossible value) - */ - protected int lastZoomSX = -9999999; - protected int lastZoomSY = -9999999; - /** - * Image (=offscreen) coordinates where the cursor was moved to for zooming - */ - protected int zoomTargetOX = -1; - protected int zoomTargetOY; - - protected ImageJ ij; - protected double magnification; - protected int dstWidth, dstHeight; - - protected int xMouseStart; - protected int yMouseStart; - protected int xSrcStart; - protected int ySrcStart; - protected int flags; - - private Image offScreenImage; - private int offScreenWidth = 0; - private int offScreenHeight = 0; - private boolean mouseExited = true; - private boolean customRoi; - private boolean drawNames; - private AtomicBoolean paintPending; - private boolean scaleToFit; - private boolean painted; - private boolean hideZoomIndicator; - private boolean flattening; - private Timer pressTimer; - private PopupMenu roiPopupMenu; - private static int longClickDelay = 1000; // ms - - public ImageCanvas(ImagePlus imp) { - this.imp = imp; - paintPending = new AtomicBoolean(false); - ij = IJ.getInstance(); - int width = imp.getWidth(); - int height = imp.getHeight(); - imageWidth = width; - imageHeight = height; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize(imageWidth, imageHeight); - magnification = 1.0; - addMouseListener(this); - addMouseMotionListener(this); - /* Changed for Bio7! */ - addMouseWheelListener(this); - addKeyListener(ij); // ImageJ handles keyboard shortcuts - setFocusTraversalKeysEnabled(false); - setFocusable(true); - } - - void updateImage(ImagePlus imp) { - this.imp = imp; - int width = imp.getWidth(); - int height = imp.getHeight(); - imageWidth = width; - imageHeight = height; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize(imageWidth, imageHeight); - magnification = 1.0; - } - - /** - * Update this ImageCanvas to have the same zoom and scale settings as the one - * specified. - */ - void update(ImageCanvas ic) { - if (ic == null || ic == this || ic.imp == null) - return; - if (ic.imp.getWidth() != imageWidth || ic.imp.getHeight() != imageHeight) - return; - srcRect = new Rectangle(ic.srcRect.x, ic.srcRect.y, ic.srcRect.width, ic.srcRect.height); - setMagnification(ic.magnification); - setSize(ic.dstWidth, ic.dstHeight); - } - - /** Sets the region of the image (in pixels) to be displayed. */ - public void setSourceRect(Rectangle r) { - if (r == null) - return; - r = new Rectangle(r.x, r.y, r.width, r.height); - imageWidth = imp.getWidth(); - imageHeight = imp.getHeight(); - if (r.x < 0) - r.x = 0; - if (r.y < 0) - r.y = 0; - if (r.width < 1) - r.width = 1; - if (r.height < 1) - r.height = 1; - if (r.width > imageWidth) - r.width = imageWidth; - if (r.height > imageHeight) - r.height = imageHeight; - if (r.x + r.width > imageWidth) - r.x = imageWidth - r.width; - if (r.y + r.height > imageHeight) - r.y = imageHeight - r.height; - if (srcRect == null) - srcRect = r; - else { - srcRect.x = r.x; - srcRect.y = r.y; - srcRect.width = r.width; - srcRect.height = r.height; - } - if (dstWidth == 0) { - Dimension size = getSize(); - dstWidth = size.width; - dstHeight = size.height; - } - magnification = (double) dstWidth / srcRect.width; - imp.setTitle(imp.getTitle()); - if (IJ.debugMode) - IJ.log("setSourceRect: " + magnification + " " + (int) (srcRect.height * magnification + 0.5) + " " + dstHeight + " " + srcRect); - } - - void setSrcRect(Rectangle srcRect) { - setSourceRect(srcRect); - } - - public Rectangle getSrcRect() { - return srcRect; - } - - /** Obsolete; replaced by setSize() */ - public void setDrawingSize(int width, int height) { - dstWidth = width; - dstHeight = height; - setSize(dstWidth, dstHeight); - } - - public void setSize(int width, int height) { - super.setSize(width, height); - dstWidth = width; - dstHeight = height; - } - - /** - * ImagePlus.updateAndDraw calls this method to force the paint() method to - * update the image from the ImageProcessor. - */ - public void setImageUpdated() { - imageUpdated = true; - } - - public void setPaintPending(boolean state) { - paintPending.set(state); - } - - public boolean getPaintPending() { - return paintPending.get(); - } - - /* Changed for Bio7! */ - /* - * public void update(Graphics g) { paint(g); } - */ - /* Changed for Bio7! */ - public void paintComponent(Graphics g) { - super.paintComponent(g); - painted = true; - Roi roi = imp.getRoi(); - - Overlay overlay = imp.getOverlay(); - if (roi != null || overlay != null || showAllOverlay != null || Prefs.paintDoubleBuffered || (IJ.isLinux() && magnification < 0.25)) { - if (roi != null) - roi.updatePaste(); - } - - /* Changed for Bio7! */ - // Already double buffered because we use a JPanel here! - - /* - * if (roi != null || overlay != null || showAllOverlay != null || - * Prefs.paintDoubleBuffered || (IJ.isLinux() && magnification < 0.25)) { // Use - * double buffering to avoid flickering of ROIs and to work around // a Linux - * problem with large images not showing at low magnification. if (roi != null) - * roi.updatePaste(); if (imageWidth != 0) { paintDoubleBuffered(g); - * setPaintPending(false); return; } } - */ - try { - if (imageUpdated) { - imageUpdated = false; - imp.updateImage(); - } - setInterpolation(g, Prefs.interpolateScaledImages); - Image img = imp.getImage(); - if (img != null) - g.drawImage(img, 0, 0, (int) (srcRect.width * magnification + 0.5), (int) (srcRect.height * magnification + 0.5), srcRect.x, srcRect.y, srcRect.x + srcRect.width, - srcRect.y + srcRect.height, null); - if (overlay != null) - drawOverlay(overlay, g); - if (showAllOverlay != null) - drawOverlay(showAllOverlay, g); - if (roi != null) - drawRoi(roi, g); - if (srcRect.width < imageWidth || srcRect.height < imageHeight) - drawZoomIndicator(g); - /* Changed for Bio7! */ - JPanel current = CanvasView.getCanvas_view().getCurrent(); - if (current != null) { - Rectangle maxWindow = current.getBounds(); - if (maxWindow.width / magnification < imageWidth || maxWindow.height / magnification < imageHeight) - drawZoomIndicator(g); - // if (IJ.debugMode) - // showFrameRate(g); - } - } catch (OutOfMemoryError e) { - IJ.outOfMemory("Paint"); - } - setPaintPending(false); - } - - private void setInterpolation(Graphics g, boolean interpolate) { - if (magnification == 1) - return; - else if (magnification < 1.0 || interpolate) { - Object value = RenderingHints.VALUE_RENDER_QUALITY; - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, value); - } else if (magnification > 1.0) { - Object value = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, value); - } - } - - private void drawRoi(Roi roi, Graphics g) { - if (roi == currentRoi) { - Color lineColor = roi.getStrokeColor(); - Color fillColor = roi.getFillColor(); - float lineWidth = roi.getStrokeWidth(); - roi.setStrokeColor(null); - roi.setFillColor(null); - boolean strokeSet = roi.getStroke() != null; - if (strokeSet) - roi.setStrokeWidth(1); - roi.draw(g); - roi.setStrokeColor(lineColor); - if (strokeSet) - roi.setStrokeWidth(lineWidth); - roi.setFillColor(fillColor); - currentRoi = null; - } else - roi.draw(g); - } - - public int getSliceNumber(String label) { - if (label == null) - return 0; - int slice = 0; - if (label.length() >= 14 && label.charAt(4) == '-' && label.charAt(9) == '-') - slice = (int) Tools.parseDouble(label.substring(0, 4), 0); - else if (label.length() >= 17 && label.charAt(5) == '-' && label.charAt(11) == '-') - slice = (int) Tools.parseDouble(label.substring(0, 5), 0); - else if (label.length() >= 20 && label.charAt(6) == '-' && label.charAt(13) == '-') - slice = (int) Tools.parseDouble(label.substring(0, 6), 0); - return slice; - } - - private void drawOverlay(Overlay overlay, Graphics g) { - if (imp != null && imp.getHideOverlay() && overlay != showAllOverlay) - return; - flattening = imp != null && ImagePlus.flattenTitle.equals(imp.getTitle()); - if (imp != null && showAllOverlay != null && overlay != showAllOverlay) - overlay.drawLabels(false); - Color labelColor = overlay.getLabelColor(); - if (labelColor == null) - labelColor = Color.white; - initGraphics(overlay, g, labelColor, Roi.getColor()); - int n = overlay.size(); - int currentImage = imp != null ? imp.getCurrentSlice() : -1; - int stackSize = imp.getStackSize(); - if (stackSize == 1) - currentImage = -1; - int channel = 0, slice = 0, frame = 0; - boolean hyperstack = imp.isHyperStack(); - if (imp.getNChannels() > 1) - hyperstack = true; - if (hyperstack) { - channel = imp.getChannel(); - slice = imp.getSlice(); - frame = imp.getFrame(); - } - drawNames = overlay.getDrawNames() && overlay.getDrawLabels(); - boolean drawLabels = drawNames || overlay.getDrawLabels(); - if (drawLabels) - labelRects = new Rectangle[n]; - else - labelRects = null; - font = overlay.getLabelFont(); - if (overlay.scalableLabels() && font != null) { - double mag = getMagnification(); - if (mag != 1.0) - font = font.deriveFont((float) (font.getSize() * mag)); - } - Roi activeRoi = imp.getRoi(); - boolean roiManagerShowAllMode = overlay == showAllOverlay && !Prefs.showAllSliceOnly; - for (int i = 0; i < n; i++) { - if (overlay == null) - break; - Roi roi = overlay.get(i); - if (roi == null) - break; - int c = roi.getCPosition(); - int z = roi.getZPosition(); - int t = roi.getTPosition(); - if (hyperstack) { - int position = roi.getPosition(); - if (position > 0) { - if (imp.getNChannels() == stackSize) { - c = position; - z = t = 0; - - } else if (imp.getNSlices() == stackSize) { - z = position; - c = t = 0; - } else if (imp.getNFrames() == stackSize) { - t = position; - c = z = 0; - - } - } - boolean match = (c == 0 || c == channel) && (z == 0 || z == slice) && (t == 0 || t == frame); - // IJ.log("drawOverlay1: i="+i+", pos="+roi.getPosition()+" "+c+" "+z+" "+t+" - // "+match+" "+roiManagerShowAllMode); - if (match || roiManagerShowAllMode || position == PointRoi.POINTWISE_POSITION) - drawRoi(g, roi, drawLabels ? i + LIST_OFFSET : -1); - } else { - int position = stackSize > 1 ? roi.getPosition() : 0; - if (stackSize > 1 && position == 0 && c == 1) { - if (z == 1) - position = t; - else if (t == 1) - position = z; - } - if (position == 0 && stackSize > 1) - position = getSliceNumber(roi.getName()); - if (position > 0 && imp.getCompositeMode() == IJ.COMPOSITE) - position = 0; - if (position == PointRoi.POINTWISE_POSITION) - position = 0; - if ((roi instanceof PointRoi) && Prefs.showAllPoints) - position = 0; - if (position == 0 || position == currentImage || roiManagerShowAllMode) - drawRoi(g, roi, drawLabels ? i + LIST_OFFSET : -1); - } - } - ((Graphics2D) g).setStroke(Roi.onePixelWide); - drawNames = false; - font = null; - } - - void drawOverlay(Graphics g) { - drawOverlay(imp.getOverlay(), g); - } - - private void initGraphics(Overlay overlay, Graphics g, Color textColor, Color defaultColor) { - if (smallFont == null) { - smallFont = new Font("SansSerif", Font.PLAIN, 9); - largeFont = IJ.font12; - } - if (textColor != null) { - labelColor = textColor; - if (overlay != null && overlay.getDrawBackgrounds()) { - double brightness = (labelColor.getRed() + labelColor.getGreen() + labelColor.getBlue()) / 3.0; - if (labelColor == Color.green) - brightness = 255; - bgColor = brightness <= 85 ? Color.white : Color.black; - } else - bgColor = null; - } else { - int red = defaultColor.getRed(); - int green = defaultColor.getGreen(); - int blue = defaultColor.getBlue(); - if ((red + green + blue) / 3 < 128) - labelColor = Color.white; - else - labelColor = Color.black; - bgColor = defaultColor; - } - this.defaultColor = defaultColor; - Font font = overlay != null ? overlay.getLabelFont() : null; - if (font != null && font.getSize() > 12) - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - g.setColor(defaultColor); - } - - void drawRoi(Graphics g, Roi roi, int index) { - ImagePlus imp2 = roi.getImage(); - roi.setImage(imp); - Color saveColor = roi.getStrokeColor(); - if (saveColor == null && roi.getFillColor() == null) - roi.setStrokeColor(defaultColor); - if (roi.getStroke() == null) - ((Graphics2D) g).setStroke(Roi.onePixelWide); - if (roi instanceof TextRoi) - ((TextRoi) roi).drawText(g); - else - roi.drawOverlay(g); - roi.setStrokeColor(saveColor); - if (index >= 0) { - if (roi == currentRoi) - g.setColor(Roi.getColor()); - else - g.setColor(defaultColor); - drawRoiLabel(g, index, roi); - } - if (imp2 != null) - roi.setImage(imp2); - else - roi.setImage(null); - } - - void drawRoiLabel(Graphics g, int index, Roi roi) { - if (roi.isCursor()) - return; - boolean pointRoi = roi instanceof PointRoi; - Rectangle r = roi.getBounds(); - int x = screenX(r.x); - int y = screenY(r.y); - double mag = getMagnification(); - int width = (int) (r.width * mag); - int height = (int) (r.height * mag); - int size = width > 40 || height > 40 ? 12 : 9; - int pointSize = 0; - int crossSize = 0; - if (pointRoi) { - pointSize = ((PointRoi) roi).getSize(); - switch (pointSize) { - case 0: - case 1: - size = 9; - break; - case 2: - case 3: - size = 10; - break; - case 4: - size = 12; - break; - } - crossSize = pointSize + 10 + 2 * pointSize; - } - if (font != null) { - g.setFont(font); - size = font.getSize(); - } else if (size == 12) - g.setFont(largeFont); - else - g.setFont(smallFont); - boolean drawingList = index >= LIST_OFFSET; - if (drawingList) - index -= LIST_OFFSET; - String label = "" + (index + 1); - if (drawNames) - label = roi.getName(); - if (label == null) - return; - FontMetrics metrics = g.getFontMetrics(); - int w = metrics.stringWidth(label); - x = x + width / 2 - w / 2; - y = y + height / 2 + Math.max(size / 2, 6); - int h = metrics.getAscent() + metrics.getDescent(); - int xoffset = 0, yoffset = 0; - if (pointRoi) { - xoffset = 6 + pointSize; - yoffset = h - 6 + pointSize; - } - if (bgColor != null) { - int h2 = h; - if (font != null && font.getSize() > 14) - h2 = (int) (h2 * 0.8); - g.setColor(bgColor); - g.fillRoundRect(x - 1 + xoffset, y - h2 + 2 + yoffset, w + 1, h2 - 2, 5, 5); - } - if (labelRects != null && index < labelRects.length) { - if (pointRoi) { - int x2 = screenX(r.x); - int y2 = screenY(r.y); - int crossSize2 = crossSize / 2; - labelRects[index] = new Rectangle(x2 - crossSize2, y2 - crossSize2, crossSize, crossSize); - } else - labelRects[index] = new Rectangle(x - 3, y - h + 1, w + 4, h); - } - g.setColor(labelColor); - g.drawString(label, x + xoffset, y - 2 + yoffset); - g.setColor(defaultColor); - } - - void drawZoomIndicator(Graphics g) { - if (hideZoomIndicator) - return; - int x1 = 10; - int y1 = 10; - double aspectRatio = (double) imageHeight / imageWidth; - int w1 = 64; - if (aspectRatio > 1.0) - w1 = (int) (w1 / aspectRatio); - int h1 = (int) (w1 * aspectRatio); - if (w1 < 4) - w1 = 4; - if (h1 < 4) - h1 = 4; - int w2 = (int) (w1 * ((double) srcRect.width / imageWidth)); - int h2 = (int) (h1 * ((double) srcRect.height / imageHeight)); - if (w2 < 1) - w2 = 1; - if (h2 < 1) - h2 = 1; - int x2 = (int) (w1 * ((double) srcRect.x / imageWidth)); - int y2 = (int) (h1 * ((double) srcRect.y / imageHeight)); - if (zoomIndicatorColor == null) - zoomIndicatorColor = new Color(128, 128, 255); - g.setColor(zoomIndicatorColor); - ((Graphics2D) g).setStroke(Roi.onePixelWide); - g.drawRect(x1, y1, w1, h1); - if (w2 * h2 <= 200 || w2 < 10 || h2 < 10) - g.fillRect(x1 + x2, y1 + y2, w2, h2); - else - g.drawRect(x1 + x2, y1 + y2, w2, h2); - } - - // Use double buffer to reduce flicker when drawing complex ROIs. - // Author: Erik Meijering - void paintDoubleBuffered(Graphics g) { - final int srcRectWidthMag = (int) (srcRect.width * magnification + 0.5); - final int srcRectHeightMag = (int) (srcRect.height * magnification + 0.5); - if (offScreenImage == null || offScreenWidth != srcRectWidthMag || offScreenHeight != srcRectHeightMag) { - offScreenImage = createImage(srcRectWidthMag, srcRectHeightMag); - offScreenWidth = srcRectWidthMag; - offScreenHeight = srcRectHeightMag; - } - Roi roi = imp.getRoi(); - try { - if (imageUpdated) { - imageUpdated = false; - imp.updateImage(); - } - Graphics offScreenGraphics = offScreenImage.getGraphics(); - setInterpolation(offScreenGraphics, Prefs.interpolateScaledImages); - Image img = imp.getImage(); - if (img != null) - offScreenGraphics.drawImage(img, 0, 0, srcRectWidthMag, srcRectHeightMag, srcRect.x, srcRect.y, srcRect.x + srcRect.width, srcRect.y + srcRect.height, null); - Overlay overlay = imp.getOverlay(); - if (overlay != null) - drawOverlay(overlay, offScreenGraphics); - if (showAllOverlay != null) - drawOverlay(showAllOverlay, offScreenGraphics); - if (roi != null) - drawRoi(roi, offScreenGraphics); - if (srcRect.width < imageWidth || srcRect.height < imageHeight) - drawZoomIndicator(offScreenGraphics); - // if (IJ.debugMode) - // showFrameRate(offScreenGraphics); - g.drawImage(offScreenImage, 0, 0, null); - } catch (OutOfMemoryError e) { - IJ.outOfMemory("Paint"); - } - } - - public void resetDoubleBuffer() { - offScreenImage = null; - } - - long firstFrame; - int frames, fps; - - void showFrameRate(Graphics g) { - frames++; - if (System.currentTimeMillis() > firstFrame + 1000) { - firstFrame = System.currentTimeMillis(); - fps = frames; - frames = 0; - } - g.setColor(Color.white); - g.fillRect(10, 12, 50, 15); - g.setColor(Color.black); - g.drawString((int) (fps + 0.5) + " fps", 10, 25); - } - - public Dimension getPreferredSize() { - return new Dimension(dstWidth, dstHeight); - } - - /** Returns the current cursor location in image coordinates. */ - public Point getCursorLoc() { - return new Point(xMouse, yMouse); - } - - /** Returns 'true' if the cursor is over this image. */ - public boolean cursorOverImage() { - return !mouseExited; - } - - /** Returns the mouse event modifiers. */ - public int getModifiers() { - return flags; - } - - /** - * Returns the ImagePlus object that is associated with this ImageCanvas. - */ - public ImagePlus getImage() { - return imp; - } - - /** Sets the cursor based on the current tool and cursor location. */ - public void setCursor(int sx, int sy, int ox, int oy) { - xMouse = ox; - yMouse = oy; - mouseExited = false; - Roi roi = imp.getRoi(); - ImageWindow win = imp.getWindow(); - overOverlayLabel = false; - if (win == null) - return; - if (IJ.spaceBarDown()) { - setCursor(handCursor); - return; - } - int id = Toolbar.getToolId(); - switch (id) { - case Toolbar.MAGNIFIER: - setCursor(moveCursor); - break; - case Toolbar.HAND: - setCursor(handCursor); - break; - default: // selection tool - PlugInTool tool = Toolbar.getPlugInTool(); - boolean arrowTool = roi != null && (roi instanceof Arrow) && tool != null && "Arrow Tool".equals(tool.getToolName()); - if ((id >= Toolbar.CUSTOM1) && !arrowTool) { - if (Prefs.usePointerCursor) - setCursor(defaultCursor); - else - setCursor(crosshairCursor); - } else if (roi != null && roi.getState() != roi.CONSTRUCTING && roi.isHandle(sx, sy) >= 0) { - setCursor(handCursor); - } else if ((imp.getOverlay() != null || showAllOverlay != null) && overOverlayLabel(sx, sy, ox, oy) && (roi == null || roi.getState() != roi.CONSTRUCTING)) { - overOverlayLabel = true; - setCursor(handCursor); - } else if (Prefs.usePointerCursor || (roi != null && roi.getState() != roi.CONSTRUCTING && roi.contains(ox, oy))) - setCursor(defaultCursor); - else - setCursor(crosshairCursor); - } - } - - private boolean overOverlayLabel(int sx, int sy, int ox, int oy) { - Overlay o = showAllOverlay; - if (o == null) - o = imp.getOverlay(); - if (o == null || !o.isSelectable() || !o.isDraggable() || !o.getDrawLabels() || labelRects == null) - return false; - for (int i = o.size() - 1; i >= 0; i--) { - if (labelRects != null && labelRects[i] != null && labelRects[i].contains(sx, sy)) { - Roi roi = imp.getRoi(); - if (roi == null || !roi.contains(ox, oy)) - return true; - else - return false; - } - } - return false; - } - - /** - * Converts a screen x-coordinate to an offscreen x-coordinate (nearest pixel - * center). - */ - public int offScreenX(int sx) { - return srcRect.x + (int) (sx / magnification); - } - - /** - * Converts a screen y-coordinate to an offscreen y-coordinate (nearest pixel - * center). - */ - public int offScreenY(int sy) { - return srcRect.y + (int) (sy / magnification); - } - - /** - * Converts a screen x-coordinate to an offscreen x-coordinate (Roi coordinate - * of nearest pixel border). - */ - public int offScreenX2(int sx) { - return srcRect.x + (int) Math.round(sx / magnification); - } - - /** - * Converts a screen y-coordinate to an offscreen y-coordinate (Roi coordinate - * of nearest pixel border). - */ - public int offScreenY2(int sy) { - return srcRect.y + (int) Math.round(sy / magnification); - } - - /** - * Converts a screen x-coordinate to a floating-point offscreen x-coordinate. - */ - public double offScreenXD(int sx) { - return srcRect.x + sx / magnification; - } - - /** - * Converts a screen y-coordinate to a floating-point offscreen y-coordinate. - */ - public double offScreenYD(int sy) { - return srcRect.y + sy / magnification; - - } - - /** Converts an offscreen x-coordinate to a screen x-coordinate. */ - public int screenX(int ox) { - return (int) ((ox - srcRect.x) * magnification); - } - - /** Converts an offscreen y-coordinate to a screen y-coordinate. */ - public int screenY(int oy) { - return (int) ((oy - srcRect.y) * magnification); - } - - /** - * Converts a floating-point offscreen x-coordinate to a screen x-coordinate. - */ - public int screenXD(double ox) { - return (int) ((ox - srcRect.x) * magnification); - } - - /** - * Converts a floating-point offscreen x-coordinate to a screen x-coordinate. - */ - public int screenYD(double oy) { - return (int) ((oy - srcRect.y) * magnification); - } - - public double getMagnification() { - return magnification; - } - - public void setMagnification(double magnification) { - setMagnification2(magnification); - } - - void setMagnification2(double magnification) { - if (magnification > 32.0) - magnification = 32.0; - if (magnification < zoomLevels[0]) - magnification = zoomLevels[0]; - this.magnification = magnification; - imp.setTitle(imp.getTitle()); - } - - /** Resizes the canvas when the user resizes the window. */ - void resizeCanvas(int width, int height) { - ImageWindow win = imp.getWindow(); - if (!maxBoundsReset && (width > dstWidth || height > dstHeight) && win != null && win.maxBounds != null && width != win.maxBounds.width - 10) { - if (resetMaxBoundsCount != 0) - resetMaxBounds(); // Works around problem that prevented window - // from being larger than maximized size - resetMaxBoundsCount++; - } - if (scaleToFit || IJ.altKeyDown()) { - fitToWindow(); - return; - } - if (width > imageWidth * magnification) - width = (int) (imageWidth * magnification); - if (height > imageHeight * magnification) - height = (int) (imageHeight * magnification); - Dimension size = getSize(); - if (srcRect.width < imageWidth || srcRect.height < imageHeight || (painted && (width != size.width || height != size.height))) { - setSize(width, height); - srcRect.width = (int) (dstWidth / magnification); - srcRect.height = (int) (dstHeight / magnification); - if ((srcRect.x + srcRect.width) > imageWidth) - srcRect.x = imageWidth - srcRect.width; - if ((srcRect.y + srcRect.height) > imageHeight) - srcRect.y = imageHeight - srcRect.height; - repaint(); - } - } - - public void fitToWindow() { - ImageWindow win = imp.getWindow(); - if (win == null) - return; - Rectangle bounds = win.getBounds(); - Insets insets = win.getInsets(); // do not include small window padding - int sliderHeight = win.getSliderHeight(); - double xmag = (double) (bounds.width - (insets.left + insets.right + ImageWindow.HGAP * 2)) / srcRect.width; - double ymag = (double) (bounds.height - (ImageWindow.VGAP * 2 + insets.top + insets.bottom + sliderHeight)) / srcRect.height; - setMagnification(Math.min(xmag, ymag)); - int width = (int) (imageWidth * magnification); - int height = (int) (imageHeight * magnification); - if (width == dstWidth && height == dstHeight) - return; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize(width, height); - // getParent().validate(); - /* Changed for Bio7 */ - CanvasView.getCurrent().validate(); - } - - void setMaxBounds() { - if (maxBoundsReset) { - maxBoundsReset = false; - ImageWindow win = imp.getWindow(); - if (win != null && !IJ.isLinux() && win.maxBounds != null) { - win.setMaximizedBounds(win.maxBounds); - win.setMaxBoundsTime = System.currentTimeMillis(); - } - } - } - - void resetMaxBounds() { - ImageWindow win = imp.getWindow(); - if (win != null && (System.currentTimeMillis() - win.setMaxBoundsTime) > 500L) { - win.setMaximizedBounds(win.maxWindowBounds); - maxBoundsReset = true; - } - } - - private static final double[] zoomLevels = { 1 / 72.0, 1 / 48.0, 1 / 32.0, 1 / 24.0, 1 / 16.0, 1 / 12.0, 1 / 8.0, 1 / 6.0, 1 / 4.0, 1 / 3.0, 1 / 2.0, 0.75, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, - 16.0, 24.0, 32.0 }; - - public static double getLowerZoomLevel(double currentMag) { - double newMag = zoomLevels[0]; - for (int i = 0; i < zoomLevels.length; i++) { - if (zoomLevels[i] < currentMag) - newMag = zoomLevels[i]; - else - break; - } - return newMag; - } - - public static double getHigherZoomLevel(double currentMag) { - double newMag = 32.0; - for (int i = zoomLevels.length - 1; i >= 0; i--) { - if (zoomLevels[i] > currentMag) - newMag = zoomLevels[i]; - else - break; - } - return newMag; - } - - /** - * Zooms in by making the window bigger. If it can't be made bigger, then makes - * the source rectangle (srcRect) smaller and centers it on the position in the - * image where the cursor was when zooming has started. Note that sx and sy are - * screen coordinates. - */ - public void zoomIn(int sx, int sy) { - - if (magnification >= 32) - return; - scaleToFit = false; - boolean mouseMoved = sqr(sx - lastZoomSX) + sqr(sy - lastZoomSY) > MAX_MOUSEMOVE_ZOOM * MAX_MOUSEMOVE_ZOOM; - lastZoomSX = sx; - lastZoomSY = sy; - if (mouseMoved || zoomTargetOX < 0) { - boolean cursorInside = sx >= 0 && sy >= 0 && sx < dstWidth && sy < dstHeight; - zoomTargetOX = offScreenX(cursorInside ? sx : dstWidth / 2); // where to zoom, offscreen (image) coordinates - zoomTargetOY = offScreenY(cursorInside ? sy : dstHeight / 2); - } - double newMag = getHigherZoomLevel(magnification); - int newWidth = (int) (imageWidth * newMag); - int newHeight = (int) (imageHeight * newMag); - Rectangle dim = CanvasView.getCurrent().getBounds(); - Dimension newSize = new Dimension(newWidth, newHeight); - // System.out.println(newWidth+" "+dim.width+" "+newHeight+" "+dim.height); - if (newWidth < dim.width && newHeight < dim.height) { - - setSize(newSize.width, newSize.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - - if (newSize.width != newWidth || newSize.height != newHeight) - adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); - else - setMagnification(newMag); - - } else if (newWidth > dim.width && newHeight < dim.height) { - setSize(newSize.width, newSize.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - setMagnification(newMag); - - } else if (newWidth < dim.width && newHeight > dim.height) { - setSize(newSize.width, newSize.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - setMagnification(newMag); - - } - - // Dimension newSize = canEnlarge(newWidth, newHeight); - else // can't enlarge window - setSize(dim.width, dim.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); - // CanvasView.getCurrent().validate(); - repaint(); - if (srcRect.width < imageWidth || srcRect.height < imageHeight) - resetMaxBounds(); - // fitToWindow(); - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the layout! */ - CanvasView.parent2.layout(); - - } - }); - CanvasView.getCurrent().validate(); - IJTabs.doSecondaryViewLayout(); - } - - /** Centers the viewable area on offscreen (image) coordinates x, y */ - void adjustSourceRect(double newMag, int x, int y) { - int w = (int) Math.round(dstWidth / newMag); - if (w * newMag < dstWidth) - w++; - int h = (int) Math.round(dstHeight / newMag); - if (h * newMag < dstHeight) - h++; - Rectangle r = new Rectangle(x - w / 2, y - h / 2, w, h); - if (r.x < 0) - r.x = 0; - if (r.y < 0) - r.y = 0; - if (r.x + w > imageWidth) - r.x = imageWidth - w; - if (r.y + h > imageHeight) - r.y = imageHeight - h; - srcRect = r; - setMagnification(newMag); - } - - /** - * Zooms in by making the window bigger. If it can't be made bigger, then makes - * the source rectangle (srcRect) smaller and centers it on the position in the - * image where the cursor was when zooming has started. Note that sx and sy are - * screen coordinates. - */ - /* - * public void zoomIn(int sx, int sy) { - * - * if (magnification >= 32) return; scaleToFit = false; boolean mouseMoved = - * sqr(sx - lastZoomSX) + sqr(sy - lastZoomSY) > MAX_MOUSEMOVE_ZOOM * - * MAX_MOUSEMOVE_ZOOM; lastZoomSX = sx; lastZoomSY = sy; if (mouseMoved || - * zoomTargetOX < 0) { boolean cursorInside = sx >= 0 && sy >= 0 && sx < - * dstWidth && sy < dstHeight; zoomTargetOX = offScreenX(cursorInside ? sx : - * dstWidth / 2); // where to zoom, offscreen (image) coordinates zoomTargetOY = - * offScreenY(cursorInside ? sy : dstHeight / 2); } double newMag = - * getHigherZoomLevel(magnification); // System.out.println(newMag); int - * newWidth = (int) (imageWidth * newMag); int newHeight = (int) (imageHeight * - * newMag); Dimension newSize = canEnlarge(newWidth, newHeight); Rectangle - * clientArea = CanvasView.getCurrent().getBounds(); if (newSize != null) { - * setSize(newSize.width, newSize.height); - * //imp.getWindow().scResizeEvent(newSize.width, newSize.height); - * - * if (newSize.width != newWidth || newSize.height != newHeight) { - * - * Changed for the SWT parent. If the next zoom level runs out of the max width - * we increase the size to the max of the parent! - * - * if (newSize.width != newWidth) { newSize = new Dimension(clientArea.width, - * newSize.height); setSize(newSize.width, newSize.height); // - * System.out.println("resize"); //imp.getWindow().scResizeEvent(newSize.width, - * newSize.height); } - * - * If the next zoom level runs out of the max height we increase the height to - * the max of the parent! - * - * else { Changed for the SWT parent. Resize to max parent! newSize = new - * Dimension(newSize.width, clientArea.height); setSize(newSize.width, - * newSize.height); // System.out.println("resize"); - * //imp.getWindow().scResizeEvent(newSize.width, newSize.height); - * - * } adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); } else { - * - * setMagnification(newMag); } imp.getWindow().pack(); - * //imp.getWindow().parentComposite.layout(); } else { // can't enlarge window. - * Maximize it! - * - * newSize = new Dimension(clientArea.width, clientArea.height); - * setSize(newSize.width, newSize.height); // System.out.println("resize"); - * //imp.getWindow().scResizeEvent(newSize.width, newSize.height); - * adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); // - * System.out.println("this is null"); } repaint(); - * - * - * - * } - */ - - /** - * Returns the size to which the window can be enlarged, or null if it can't be - * enlarged. newWidth, newHeight is the size needed for showing the - * full image at the magnification needed - */ - protected Dimension canEnlarge(int newWidth, int newHeight) { - if (IJ.altKeyDown()) - return null; - ImageWindow win = imp.getWindow(); - if (win == null) - return null; - Rectangle r1 = win.getBounds(); - Insets insets = win.getInsets(); - Point loc = getLocation(); - if (loc.x > insets.left + 5 || loc.y > insets.top + 5) { - r1.width = newWidth + insets.left + insets.right + ImageWindow.HGAP * 2; - r1.height = newHeight + insets.top + insets.bottom + ImageWindow.VGAP * 2 + win.getSliderHeight(); - } else { - r1.width = r1.width - dstWidth + newWidth; - r1.height = r1.height - dstHeight + newHeight; - } - Rectangle max = GUI.getMaxWindowBounds(win); - boolean fitsHorizontally = r1.x + r1.width < max.x + max.width; - boolean fitsVertically = r1.y + r1.height < max.y + max.height; - if (fitsHorizontally && fitsVertically) - return new Dimension(newWidth, newHeight); - else if (fitsVertically && newHeight < dstWidth) - return new Dimension(dstWidth, newHeight); - else if (fitsHorizontally && newWidth < dstHeight) - return new Dimension(newWidth, dstHeight); - /* - * else return null; - */ - /* Changed for Bio7! */ - else - return new Dimension(max.width, max.height); - } - - /** - * Zooms out by making the source rectangle (srcRect) larger and centering it on - * (x,y). If we can't make it larger, then make the window smaller. Note that sx - * and sy are screen coordinates. - */ - public void zoomOut(int sx, int sy) { - if (magnification <= zoomLevels[0]) - return; - boolean mouseMoved = sqr(sx - lastZoomSX) + sqr(sy - lastZoomSY) > MAX_MOUSEMOVE_ZOOM * MAX_MOUSEMOVE_ZOOM; - lastZoomSX = sx; - lastZoomSY = sy; - if (mouseMoved || zoomTargetOX < 0) { - boolean cursorInside = sx >= 0 && sy >= 0 && sx < dstWidth && sy < dstHeight; - zoomTargetOX = offScreenX(cursorInside ? sx : dstWidth / 2); // where - // to - // zoom, - // offscreen - // (image) - // coordinates - zoomTargetOY = offScreenY(cursorInside ? sy : dstHeight / 2); - } - double oldMag = magnification; - double newMag = getLowerZoomLevel(magnification); - double srcRatio = (double) srcRect.width / srcRect.height; - double imageRatio = (double) imageWidth / imageHeight; - double initialMag = imp.getWindow().getInitialMagnification(); - if (Math.abs(srcRatio - imageRatio) > 0.05) { - double scale = oldMag / newMag; - int newSrcWidth = (int) Math.round(srcRect.width * scale); - int newSrcHeight = (int) Math.round(srcRect.height * scale); - if (newSrcWidth > imageWidth) - newSrcWidth = imageWidth; - if (newSrcHeight > imageHeight) - newSrcHeight = imageHeight; - int newSrcX = srcRect.x - (newSrcWidth - srcRect.width) / 2; - int newSrcY = srcRect.y - (newSrcHeight - srcRect.height) / 2; - if (newSrcX + newSrcWidth > imageWidth) - newSrcX = imageWidth - newSrcWidth; - if (newSrcY + newSrcHeight > imageHeight) - newSrcY = imageHeight - newSrcHeight; - if (newSrcX < 0) - newSrcX = 0; - if (newSrcY < 0) - newSrcY = 0; - srcRect = new Rectangle(newSrcX, newSrcY, newSrcWidth, newSrcHeight); - int newDstWidth = (int) (srcRect.width * newMag); - int newDstHeight = (int) (srcRect.height * newMag); - setMagnification(newMag); - setMaxBounds(); - if (newDstWidth < dstWidth || newDstHeight < dstHeight) { - setSize(newDstWidth, newDstHeight); - imp.getWindow().pack(); - } else - repaint(); - /* Changes for Bio7! */ - // CanvasView.getCurrent().invalidate(); - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the layout! */ - CanvasView.parent2.layout(); - - } - }); - CanvasView.getCurrent().validate(); - // adjustSourceRect(newMag, sx, sy); - - return; - } - if (imageWidth * newMag > dstWidth) { - int w = (int) Math.round(dstWidth / newMag); - if (w * newMag < dstWidth) - w++; - int h = (int) Math.round(dstHeight / newMag); - if (h * newMag < dstHeight) - h++; - Rectangle r = new Rectangle(zoomTargetOX - w / 2, zoomTargetOY - h / 2, w, h); - if (r.x < 0) - r.x = 0; - if (r.y < 0) - r.y = 0; - if (r.x + w > imageWidth) - r.x = imageWidth - w; - if (r.y + h > imageHeight) - r.y = imageHeight - h; - srcRect = r; - setMagnification(newMag); - } else { - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize((int) (imageWidth * newMag), (int) (imageHeight * newMag)); - setMagnification(newMag); - imp.getWindow().pack(); - } - setMaxBounds(); - repaint(); - /* Changes for Bio7! */ - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the layout! */ - CanvasView.parent2.layout(); - - } - - }); - CanvasView.getCurrent().doLayout(); - IJTabs.doSecondaryViewLayout(); - // adjustSourceRect(newMag, sx, sy); - } - - int sqr(int x) { - return x * x; - } - - /** Implements the Image/Zoom/Original Scale command. */ - public void unzoom() { - double imag = imp.getWindow().getInitialMagnification(); - if (magnification == imag) - return; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - ImageWindow win = imp.getWindow(); - setSize((int) (imageWidth * imag), (int) (imageHeight * imag)); - setMagnification(imag); - setMaxBounds(); - win.pack(); - setMaxBounds(); - repaint(); - /* Changed for Bio7! */ - CanvasView.getCurrent().validate(); - } - - /** Implements the Image/Zoom/View 100% command. */ - public void zoom100Percent() { - if (magnification == 1.0) - return; - double imag = imp.getWindow().getInitialMagnification(); - if (magnification != imag) - unzoom(); - if (magnification == 1.0) - return; - if (magnification < 1.0) { - while (magnification < 1.0) - zoomIn(imageWidth / 2, imageHeight / 2); - } else if (magnification > 1.0) { - while (magnification > 1.0) - zoomOut(imageWidth / 2, imageHeight / 2); - } else - return; - int x = xMouse, y = yMouse; - if (mouseExited) { - x = imageWidth / 2; - y = imageHeight / 2; - } - int sx = screenX(x); - int sy = screenY(y); - adjustSourceRect(1.0, sx, sy); - repaint(); - /* Changed for Bio7! */ - CanvasView.getCurrent().validate(); - } - - protected void scroll(int sx, int sy) { - int ox = xSrcStart + (int) (sx / magnification); // convert to offscreen - // coordinates - int oy = ySrcStart + (int) (sy / magnification); - int newx = xSrcStart + (xMouseStart - ox); - int newy = ySrcStart + (yMouseStart - oy); - if (newx < 0) - newx = 0; - if (newy < 0) - newy = 0; - if ((newx + srcRect.width) > imageWidth) - newx = imageWidth - srcRect.width; - if ((newy + srcRect.height) > imageHeight) - newy = imageHeight - srcRect.height; - srcRect.x = newx; - srcRect.y = newy; - imp.draw(); - Thread.yield(); - } - - Color getColor(int index) { - IndexColorModel cm = (IndexColorModel) imp.getProcessor().getColorModel(); - // IJ.write(""+index+" "+(new Color(cm.getRGB(index)))); - return new Color(cm.getRGB(index)); - } - - /** - * Sets the foreground drawing color (or background color if 'setBackground' is - * true) to the color of the pixel at (ox,oy). - */ - public void setDrawingColor(int ox, int oy, boolean setBackground) { - int type = imp.getType(); - int[] v = imp.getPixel(ox, oy); - switch (type) { - case ImagePlus.GRAY8: { - if (setBackground) - setBackgroundColor(getColor(v[0])); - else - setForegroundColor(getColor(v[0])); - break; - } - case ImagePlus.GRAY16: - case ImagePlus.GRAY32: { - double min = imp.getProcessor().getMin(); - double max = imp.getProcessor().getMax(); - double value = (type == ImagePlus.GRAY32) ? Float.intBitsToFloat(v[0]) : v[0]; - int index = (int) (255.0 * ((value - min) / (max - min))); - if (index < 0) - index = 0; - if (index > 255) - index = 255; - if (setBackground) - setBackgroundColor(getColor(index)); - else - setForegroundColor(getColor(index)); - break; - } - case ImagePlus.COLOR_RGB: - case ImagePlus.COLOR_256: { - Color c = new Color(v[0], v[1], v[2]); - if (setBackground) - setBackgroundColor(c); - else - setForegroundColor(c); - break; - } - } - Color c; - if (setBackground) - c = Toolbar.getBackgroundColor(); - else { - c = Toolbar.getForegroundColor(); - imp.setColor(c); - } - IJ.showStatus("(" + c.getRed() + ", " + c.getGreen() + ", " + c.getBlue() + ")"); - } - - private void setForegroundColor(Color c) { - Toolbar.setForegroundColor(c); - if (IJ.recording()) - Recorder.record("setForegroundColor", c.getRed(), c.getGreen(), c.getBlue()); - } - - private void setBackgroundColor(Color c) { - Toolbar.setBackgroundColor(c); - if (IJ.recording()) - Recorder.record("setBackgroundColor", c.getRed(), c.getGreen(), c.getBlue()); - } - - public void mousePressed(final MouseEvent e) { - /* Changed for Bio7! */ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - ImageWindow wind = imp.getWindow(); - if (wind != null) { - Frame frameSwtAwt = wind.getSwtAwtMain().getFrame(); - if (frameSwtAwt != null) { - - if (frameSwtAwt != null) - frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, WindowEvent.WINDOW_ACTIVATED)); - // frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, - // WindowEvent.WINDOW_GAINED_FOCUS)); - - if (ImageCanvas.this.isFocusOwner() == false) { - ImageCanvas.this.requestFocus(); - - } - } - } - } - }); - /* Search for detached views and activate them on mouse pressed events! */ - Util.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - String secId = Integer.toString(ImageCanvas.this.getImage().getID()); - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - IViewReference ref2 = page.findViewReference("com.eco.bio7.image.detachedImage", secId); - if (ref2 != null) { - IViewPart activated = null; - try { - - activated = page.showView("com.eco.bio7.image.detachedImage", secId, IWorkbenchPage.VIEW_ACTIVATE); - } catch (PartInitException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - // CustomDetachedImageJView customView = (CustomDetachedImageJView) activated; - // ImageJ.setCustomView(customView); - } - } - }); - - showCursorStatus = true; - int toolID = Toolbar.getToolId(); - ImageWindow win = imp.getWindow(); - if (win != null && win.running2 && toolID != Toolbar.MAGNIFIER) { - if (win instanceof StackWindow) - ((StackWindow) win).setAnimate(false); - else - win.running2 = false; - return; - } - - int x = e.getX(); - int y = e.getY(); - flags = e.getModifiers(); - - if (toolID != Toolbar.MAGNIFIER && (e.isPopupTrigger() || (!IJ.isMacintosh() && (flags & Event.META_MASK) != 0))) { - handlePopupMenu(e); - return; - } - - int ox = offScreenX(x); - int oy = offScreenY(y); - xMouse = ox; - yMouse = oy; - if (IJ.spaceBarDown()) { - // temporarily switch to "hand" tool of space bar down - setupScroll(ox, oy); - return; - } - - if (overOverlayLabel && (imp.getOverlay() != null || showAllOverlay != null)) { - if (activateOverlayRoi(ox, oy)) - return; - } - - if ((System.currentTimeMillis() - mousePressedTime) < 300L && !drawingTool()) { - if (activateOverlayRoi(ox, oy)) - return; - } - - mousePressedX = ox; - mousePressedY = oy; - mousePressedTime = System.currentTimeMillis(); - - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mousePressed(imp, e); - if (e.isConsumed()) - return; - } - if (customRoi && imp.getOverlay() != null) - return; - - if (toolID >= Toolbar.CUSTOM1) { - if (tool != null && "Arrow Tool".equals(tool.getToolName())) - handleRoiMouseDown(e); - else - Toolbar.getInstance().runMacroTool(toolID); - return; - } - - final Roi roi1 = imp.getRoi(); - final int size1 = roi1 != null ? roi1.size() : 0; - final Rectangle r1 = roi1 != null ? roi1.getBounds() : null; - - switch (toolID) { - case Toolbar.MAGNIFIER: - if (IJ.shiftKeyDown()) - zoomToSelection(ox, oy); - else if ((flags & (Event.ALT_MASK | Event.META_MASK | Event.CTRL_MASK)) != 0) { - - zoomOut(x, y); - if (getMagnification() < 1.0) - imp.repaintWindow(); - } else { - - zoomIn(x, y); - if (getMagnification() <= 1.0) - imp.repaintWindow(); - } - break; - case Toolbar.HAND: - setupScroll(ox, oy); - break; - case Toolbar.DROPPER: - setDrawingColor(ox, oy, IJ.altKeyDown()); - break; - case Toolbar.WAND: - double tolerance = WandToolOptions.getTolerance(); - Roi roi = imp.getRoi(); - if (roi != null && (tolerance == 0.0 || imp.isThreshold()) && roi.contains(ox, oy)) { - Rectangle r = roi.getBounds(); - if (r.width == imageWidth && r.height == imageHeight) - imp.deleteRoi(); - else if (!e.isAltDown()) { - handleRoiMouseDown(e); - return; - } - } - if (roi != null) { - int handle = roi.isHandle(x, y); - if (handle >= 0) { - roi.mouseDownInHandle(handle, x, y); - return; - } - } - if (!imp.okToDeleteRoi()) - break; - setRoiModState(e, roi, -1); - String mode = WandToolOptions.getMode(); - if (Prefs.smoothWand) - mode = mode + " smooth"; - int npoints = IJ.doWand(imp, ox, oy, tolerance, mode); - if (IJ.recording() && npoints > 0) { - if (Recorder.scriptMode()) - Recorder.recordCall("IJ.doWand(imp, " + ox + ", " + oy + ", " + tolerance + ", \"" + mode + "\");"); - else { - if (tolerance == 0.0 && mode.equals("Legacy")) - Recorder.record("doWand", ox, oy); - else - Recorder.recordString("doWand(" + ox + ", " + oy + ", " + tolerance + ", \"" + mode + "\");\n"); - } - } - break; - case Toolbar.OVAL: - if (Toolbar.getBrushSize() > 0) - new RoiBrush(); - else - handleRoiMouseDown(e); - break; - default: // selection tool - handleRoiMouseDown(e); - } - if (longClickDelay > 0) { - if (pressTimer == null) - pressTimer = new java.util.Timer(); - final Point cursorLoc = getCursorLoc(); - pressTimer.schedule(new TimerTask() { - public void run() { - if (pressTimer != null) { - pressTimer.cancel(); - pressTimer = null; - } - Roi roi2 = imp.getRoi(); - int size2 = roi2 != null ? roi2.size() : 0; - Rectangle r2 = roi2 != null ? roi2.getBounds() : null; - boolean empty = r2 != null && r2.width == 0 && r2.height == 0; - int state = roi2 != null ? roi2.getState() : -1; - boolean unchanged = state != Roi.MOVING_HANDLE && r1 != null && r2 != null && r2.x == r1.x && r2.y == r1.y && r2.width == r1.width && r2.height == r1.height && size2 == size1 - && !(size2 > 1 && state == Roi.CONSTRUCTING); - boolean cursorMoved = !getCursorLoc().equals(cursorLoc); - if ((roi1 == null && (size2 <= 1 || empty)) || unchanged) { - if (roi1 == null) - imp.deleteRoi(); - if (!cursorMoved && Toolbar.getToolId() != Toolbar.HAND) - handlePopupMenu(e); - } - } - }, longClickDelay); - } - } - - private boolean drawingTool() { - int id = Toolbar.getToolId(); - return id == Toolbar.POLYLINE || id == Toolbar.FREELINE || id >= Toolbar.CUSTOM1; - } - - void zoomToSelection(int x, int y) { - IJ.setKeyUp(IJ.ALL_KEYS); - String macro = "args = split(getArgument);\n" + "x1=parseInt(args[0]); y1=parseInt(args[1]); flags=20;\n" + "while (flags&20!=0) {\n" + "getCursorLoc(x2, y2, z, flags);\n" - + "if (x2>=x1) x=x1; else x=x2;\n" + "if (y2>=y1) y=y1; else y=y2;\n" + "makeRectangle(x, y, abs(x2-x1), abs(y2-y1));\n" + "wait(10);\n" + "}\n" + "run('To Selection');\n"; - new MacroRunner(macro, x + " " + y); - } - - protected void setupScroll(int ox, int oy) { - xMouseStart = ox; - yMouseStart = oy; - xSrcStart = srcRect.x; - ySrcStart = srcRect.y; - } - - protected void handlePopupMenu(MouseEvent e) { - if (disablePopupMenu) - return; - if (IJ.debugMode) - IJ.log("show popup: " + (e.isPopupTrigger() ? "true" : "false")); - int sx = e.getX(); - int sy = e.getY(); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - Roi roi = imp.getRoi(); - if (roi != null && roi.getType() == Roi.COMPOSITE && Toolbar.getToolId() == Toolbar.OVAL && Toolbar.getBrushSize() > 0) - return; // selection brush tool - if (roi != null && (roi.getType() == Roi.POLYGON || roi.getType() == Roi.POLYLINE || roi.getType() == Roi.ANGLE) && roi.getState() == roi.CONSTRUCTING) { - roi.handleMouseUp(sx, sy); // simulate double-click to finalize - roi.handleMouseUp(sx, sy); // polygon or polyline selection - return; - } - if (roi != null && !(e.isAltDown() || e.isShiftDown())) { // show ROI popup? - if (roi.contains(ox, oy)) { - if (roiPopupMenu == null) - addRoiPopupMenu(); - if (IJ.isMacOSX()) - IJ.wait(10); - /* Changed for Bio7! */ - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction imageContextMenuAction = instance.getImageContextMenuAction(); - imageContextMenuAction.swtPopupMenu(e, roiPopupMenu, this); - // roiPopupMenu.show(this, sx, sy); - return; - } - } - PopupMenu popup = Menus.getPopupMenu(); - if (popup != null) { - add(popup); - if (IJ.isMacOSX()) - IJ.wait(10); - /* Changed for Bio7! SWT Popup Menu! */ - // popup.show(this, x, y); - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction imageContextMenuAction = instance.getImageContextMenuAction(); - imageContextMenuAction.swtPopupMenu(e, popup, this); - } - } - - public void mouseExited(MouseEvent e) { - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseExited(imp, e); - if (e.isConsumed()) - return; - } - ImageWindow win = imp.getWindow(); - if (win != null) - setCursor(defaultCursor); - IJ.showStatus(""); - mouseExited = true; - /* - * Change for Bio7! On Linux the editors don't receive key events when the - * ImageCanvas receives focus. We workaround this by open and close a SWT Shell - * to transfer back the focus to SWT. This could also solve the problem of a - * broken editor hoover in the Bio7 editors! - */ - /* - * if (Util.getOS().equals("Linux")) { Display dis = Util.getDisplay(); - * dis.syncExec(new Runnable() { - * - * public void run() { - * - * if (tempShell != null) { if (tempShell.isDisposed() == false) { - * tempShell.dispose(); } } tempShell = new Shell(); tempShell.setVisible(true); - * tempShell.setVisible(false); } }); } - */ - - } - - public void mouseDragged(MouseEvent e) { - int x = e.getX(); - int y = e.getY(); - xMouse = offScreenX(x); - yMouse = offScreenY(y); - flags = e.getModifiers(); - mousePressedX = mousePressedY = -1; - if (flags == 0) // workaround for Mac OS 9 bug - flags = InputEvent.BUTTON1_MASK; - if (Toolbar.getToolId() == Toolbar.HAND || IJ.spaceBarDown()) - scroll(x, y); - else { - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseDragged(imp, e); - if (e.isConsumed()) - return; - } - IJ.setInputEvent(e); - Roi roi = imp.getRoi(); - if (roi != null) - roi.handleMouseDrag(x, y, flags); - } - } - - protected void handleRoiMouseDown(MouseEvent e) { - int sx = e.getX(); - int sy = e.getY(); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - Roi roi = imp.getRoi(); - int tool = Toolbar.getToolId(); - int handle = roi != null ? roi.isHandle(sx, sy) : -1; - boolean multiPointMode = roi != null && (roi instanceof PointRoi) && handle == -1 && tool == Toolbar.POINT && Toolbar.getMultiPointMode(); - if (multiPointMode) { - double oxd = roi.offScreenXD(sx); - double oyd = roi.offScreenYD(sy); - if (e.isShiftDown() && !IJ.isMacro()) { - FloatPolygon points = roi.getFloatPolygon(); - if (points.npoints > 0) { - double x0 = points.xpoints[0]; - double y0 = points.ypoints[0]; - double slope = Math.abs((oxd - x0) / (oyd - y0)); - if (slope >= 1.0) - oyd = points.ypoints[0]; - else - oxd = points.xpoints[0]; - } - } - ((PointRoi) roi).addUserPoint(imp, oxd, oyd); - imp.setRoi(roi); - return; - } - - if (roi != null && (roi instanceof PointRoi)) { - int npoints = ((PolygonRoi) roi).getNCoordinates(); - if (npoints > 1 && handle == -1 && !IJ.altKeyDown() && !(tool == Toolbar.POINT && !Toolbar.getMultiPointMode() && IJ.shiftKeyDown())) { - String msg = "Type shift-a (Edit>Selection>Select None) to delete\npoints. Use multi-point tool to add points."; - GenericDialog gd = new GenericDialog("Point Selection"); - gd.addMessage(msg); - gd.addHelp(PointToolOptions.help); - gd.hideCancelButton(); - gd.showDialog(); - return; - } - } - - setRoiModState(e, roi, handle); - if (roi != null) { - if (handle >= 0) { - roi.mouseDownInHandle(handle, sx, sy); - return; - } - Rectangle r = roi.getBounds(); - int type = roi.getType(); - if (type == Roi.RECTANGLE && r.width == imp.getWidth() && r.height == imp.getHeight() && roi.getPasteMode() == Roi.NOT_PASTING && !(roi instanceof ImageRoi)) { - imp.deleteRoi(); - return; - } - if (roi.contains(ox, oy)) { - if (roi.modState == Roi.NO_MODS) - roi.handleMouseDown(sx, sy); - else { - imp.deleteRoi(); - imp.createNewRoi(sx, sy); - } - return; - } - boolean segmentedTool = tool == Toolbar.POLYGON || tool == Toolbar.POLYLINE || tool == Toolbar.ANGLE; - if (segmentedTool && (type == Roi.POLYGON || type == Roi.POLYLINE || type == Roi.ANGLE) && roi.getState() == roi.CONSTRUCTING) - return; - - if (segmentedTool && !(IJ.shiftKeyDown() || IJ.altKeyDown())) { - imp.deleteRoi(); - return; - } - } - imp.createNewRoi(sx, sy); - } - - void setRoiModState(MouseEvent e, Roi roi, int handle) { - if (roi == null || (handle >= 0 && roi.modState == Roi.NO_MODS)) - return; - if (roi.state == Roi.CONSTRUCTING) - return; - int tool = Toolbar.getToolId(); - if (tool > Toolbar.FREEROI && tool != Toolbar.WAND && tool != Toolbar.POINT) { - roi.modState = Roi.NO_MODS; - return; - } - if (e.isShiftDown()) - roi.modState = Roi.ADD_TO_ROI; - else if (e.isAltDown()) - roi.modState = Roi.SUBTRACT_FROM_ROI; - else - roi.modState = Roi.NO_MODS; - } - - /** Disable/enable popup menu. */ - public void disablePopupMenu(boolean status) { - disablePopupMenu = status; - } - - public void setShowAllList(Overlay showAllList) { - this.showAllOverlay = showAllList; - labelRects = null; - } - - public Overlay getShowAllList() { - return showAllOverlay; - } - - /** Obsolete */ - public void setShowAllROIs(boolean showAllROIs) { - RoiManager rm = RoiManager.getInstance(); - if (rm != null) - rm.runCommand(showAllROIs ? "show all" : "show none"); - } - - /** Obsolete */ - public boolean getShowAllROIs() { - return getShowAllList() != null; - } - - /** Obsolete */ - public static Color getShowAllColor() { - if (showAllColor != null && showAllColor.getRGB() == 0xff80ffff) - showAllColor = Color.cyan; - return showAllColor; - } - - /** Obsolete */ - public static void setShowAllColor(Color c) { - if (c == null) - return; - showAllColor = c; - labelColor = null; - } - - /** Experimental */ - public static void setCursor(Cursor cursor, int type) { - crosshairCursor = cursor; - } - - /** Use ImagePlus.setOverlay(ij.gui.Overlay). */ - public void setOverlay(Overlay overlay) { - imp.setOverlay(overlay); - } - - /** Use ImagePlus.getOverlay(). */ - public Overlay getOverlay() { - return imp.getOverlay(); - } - - /** - * @deprecated replaced by ImagePlus.setOverlay(ij.gui.Overlay) - */ - public void setDisplayList(Vector list) { - if (list != null) { - Overlay list2 = new Overlay(); - list2.setVector(list); - imp.setOverlay(list2); - } else - imp.setOverlay(null); - Overlay overlay = imp.getOverlay(); - if (overlay != null) - overlay.drawLabels(overlay.size() > 0 && overlay.get(0).getStrokeColor() == null); - else - customRoi = false; - repaint(); - } - - /** - * @deprecated replaced by ImagePlus.setOverlay(Shape, Color, BasicStroke) - */ - public void setDisplayList(Shape shape, Color color, BasicStroke stroke) { - imp.setOverlay(shape, color, stroke); - } - - /** - * @deprecated replaced by ImagePlus.setOverlay(Roi, Color, int, Color) - */ - public void setDisplayList(Roi roi, Color color) { - roi.setStrokeColor(color); - Overlay list = new Overlay(); - list.add(roi); - imp.setOverlay(list); - } - - /** - * @deprecated replaced by ImagePlus.getOverlay() - */ - public Vector getDisplayList() { - Overlay overlay = imp.getOverlay(); - if (overlay == null) - return null; - Vector displayList = new Vector(); - for (int i = 0; i < overlay.size(); i++) - displayList.add(overlay.get(i)); - return displayList; - } - - /** - * Allows plugins (e.g., Orthogonal_Views) to create a custom ROI using a - * display list. - */ - public void setCustomRoi(boolean customRoi) { - this.customRoi = customRoi; - } - - public boolean getCustomRoi() { - return customRoi; - } - - /** - * Called by IJ.showStatus() to prevent status bar text from being overwritten - * until the cursor moves at least 12 pixels. - */ - public void setShowCursorStatus(boolean status) { - showCursorStatus = status; - if (status == true) - sx2 = sy2 = -1000; - else { - sx2 = screenX(xMouse); - sy2 = screenY(yMouse); - } - } - - public void mouseReleased(MouseEvent e) { - - if (pressTimer != null) { - pressTimer.cancel(); - pressTimer = null; - } - - int ox = offScreenX(e.getX()); - int oy = offScreenY(e.getY()); - Overlay overlay = imp.getOverlay(); - if ((overlay != null || showAllOverlay != null) && ox == mousePressedX && oy == mousePressedY) { - boolean cmdDown = IJ.isMacOSX() && e.isMetaDown(); - Roi roi = imp.getRoi(); - if (roi != null && roi.getBounds().width == 0) - roi = null; - if ((e.isAltDown() || e.isControlDown() || cmdDown) && roi == null) { - if (activateOverlayRoi(ox, oy)) - return; - } else if ((System.currentTimeMillis() - mousePressedTime) > 250L && !drawingTool()) { // long press - if (activateOverlayRoi(ox, oy)) - return; - } - - } - - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseReleased(imp, e); - if (e.isConsumed()) - return; - } - flags = e.getModifiers(); - flags &= ~InputEvent.BUTTON1_MASK; // make sure button 1 bit is not set - flags &= ~InputEvent.BUTTON2_MASK; // make sure button 2 bit is not set - flags &= ~InputEvent.BUTTON3_MASK; // make sure button 3 bit is not set - Roi roi = imp.getRoi(); - if (roi != null) { - Rectangle r = roi.getBounds(); - int type = roi.getType(); - if ((r.width == 0 || r.height == 0) && !(type == Roi.POLYGON || type == Roi.POLYLINE || type == Roi.ANGLE || type == Roi.LINE) && !(roi instanceof TextRoi) - && roi.getState() == roi.CONSTRUCTING && type != roi.POINT) - imp.deleteRoi(); - else - roi.handleMouseUp(e.getX(), e.getY()); - } - } - - private boolean activateOverlayRoi(int ox, int oy) { - int currentImage = -1; - int stackSize = imp.getStackSize(); - if (stackSize > 1) - currentImage = imp.getCurrentSlice(); - int channel = 0, slice = 0, frame = 0; - boolean hyperstack = imp.isHyperStack(); - if (hyperstack) { - channel = imp.getChannel(); - slice = imp.getSlice(); - frame = imp.getFrame(); - } - Overlay o = showAllOverlay; - if (o == null) - o = imp.getOverlay(); - if (o == null || !o.isSelectable()) - return false; - boolean roiManagerShowAllMode = o == showAllOverlay && !Prefs.showAllSliceOnly; - boolean labels = o.getDrawLabels(); - int sx = screenX(ox); - int sy = screenY(oy); - for (int i = o.size() - 1; i >= 0; i--) { - Roi roi = o.get(i); - if (roi == null) - continue; - boolean containsMousePoint = false; - if (roi instanceof Line) { // grab line roi near its center - double grabLineWidth = 1.1 + 5. / magnification; - containsMousePoint = (((Line) roi).getFloatPolygon(grabLineWidth)).contains(ox, oy); - } else - containsMousePoint = roi.contains(ox, oy); - if (containsMousePoint || (labels && labelRects != null && labelRects[i] != null && labelRects[i].contains(sx, sy))) { - if (hyperstack && roi.getPosition() == 0) { - int c = roi.getCPosition(); - int z = roi.getZPosition(); - int t = roi.getTPosition(); - if (!((c == 0 || c == channel) && (z == 0 || z == slice) && (t == 0 || t == frame) || roiManagerShowAllMode)) - continue; - } else { - int position = stackSize > 1 ? roi.getPosition() : 0; - if (!(position == 0 || position == currentImage || roiManagerShowAllMode)) - continue; - } - if (!IJ.altKeyDown() && roi.getType() == Roi.COMPOSITE && roi.getBounds().width == imp.getWidth() && roi.getBounds().height == imp.getHeight()) - return false; - // if (Toolbar.getToolId()==Toolbar.OVAL && Toolbar.getBrushSize()>0) - // Toolbar.getInstance().setTool(Toolbar.RECTANGLE); - roi.setImage(null); - imp.setRoi(roi); - roi.handleMouseDown(sx, sy); - roiManagerSelect(roi, false); - ResultsTable.selectRow(roi); - return true; - } - } - return false; - } - - public boolean roiManagerSelect(Roi roi, boolean delete) { - RoiManager rm = RoiManager.getInstance(); - if (rm == null) - return false; - int index = rm.getRoiIndex(roi); - if (index < 0) - return false; - if (delete) { - rm.select(imp, index); - rm.runCommand("delete"); - } else - rm.selectAndMakeVisible(imp, index); - return true; - } - - public void mouseMoved(MouseEvent e) { - // if (ij==null) return; - int sx = e.getX(); - int sy = e.getY(); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - flags = e.getModifiers(); - setCursor(sx, sy, ox, oy); - mousePressedX = mousePressedY = -1; - IJ.setInputEvent(e); - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseMoved(imp, e); - if (e.isConsumed()) - return; - } - Roi roi = imp.getRoi(); - int type = roi != null ? roi.getType() : -1; - if (type > 0 && (type == Roi.POLYGON || type == Roi.POLYLINE || type == Roi.ANGLE || type == Roi.LINE) && roi.getState() == roi.CONSTRUCTING) - roi.mouseMoved(e); - else { - if (ox < imageWidth && oy < imageHeight) { - ImageWindow win = imp.getWindow(); - // Cursor must move at least 12 pixels before text - // displayed using IJ.showStatus() is overwritten. - if ((sx - sx2) * (sx - sx2) + (sy - sy2) * (sy - sy2) > 144) - showCursorStatus = true; - if (win != null && showCursorStatus) - win.mouseMoved(ox, oy); - } else - IJ.showStatus(""); - } - } - - public void mouseEntered(MouseEvent e) { - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) - tool.mouseEntered(imp, e); - } - - public void mouseClicked(MouseEvent e) { - Util.activateView("com.eco.bio7.imagej"); - /* Changed for Bio7! */ - if (this.isFocusOwner() == false) { - this.requestFocus(); - - } - WindowManager.setTempCurrentImage(imp); - WindowManager.setCurrentWindow(imp.getWindow()); - - /* import to set current Panel! */ - CanvasView.setCurrent((JPanel) this.getParent()); - - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) - tool.mouseClicked(imp, e); - } - - /* Changed for Bio7! */ - public void mouseWheelMoved(MouseWheelEvent e) { - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - if (IJ.debugMode) { - IJ.log("mouseWheelMoved: " + e); - IJ.log(" type: " + e.getScrollType()); - IJ.log(" ctrl: " + ctrl); - IJ.log(" rotation: " + rotation); - IJ.log(" amount: " + amount); - } - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - int width = imp.getWidth(); - int height = imp.getHeight(); - Rectangle srcRect = getSrcRect(); - int xstart = srcRect.x; - int ystart = srcRect.y; - if ((ctrl || IJ.shiftKeyDown()) && this != null) { - int ox = offScreenX(e.getX()); - int oy = offScreenY(e.getX()); - if (IJ.debugMode) - IJ.log(" x,y: " + ox + "," + oy); - if (rotation < 0) - zoomIn(ox, oy); - else - zoomOut(ox, oy); - return; - } else if (IJ.spaceBarDown() || srcRect.height == height) { - srcRect.x += rotation * amount * Math.max(width / 200, 1); - if (srcRect.x < 0) - srcRect.x = 0; - if (srcRect.x + srcRect.width > width) - srcRect.x = width - srcRect.width; - } else { - srcRect.y += rotation * amount * Math.max(height / 200, 1); - if (srcRect.y < 0) - srcRect.y = 0; - if (srcRect.y + srcRect.height > height) - srcRect.y = height - srcRect.height; - } - if (srcRect.x != xstart || srcRect.y != ystart) - repaint(); - - } - - public void setScaleToFit(boolean scaleToFit) { - this.scaleToFit = scaleToFit; - } - - public boolean getScaleToFit() { - return scaleToFit; - } - - public boolean hideZoomIndicator(boolean hide) { - boolean hidden = this.hideZoomIndicator; - if (!(srcRect.width < imageWidth || srcRect.height < imageHeight)) - return hidden; - this.hideZoomIndicator = hide; - setPaintPending(true); - repaint(); - long t0 = System.currentTimeMillis(); - while (getPaintPending() && (System.currentTimeMillis() - t0) < 500L) - IJ.wait(10); - return hidden; - } - - public void repaintOverlay() { - labelRects = null; - repaint(); - } - - /** - * Sets the context menu long click delay in milliseconds (default is 1000). Set - * to 0 to disable long click triggering. - */ - public static void setLongClickDelay(int delay) { - longClickDelay = delay; - } - - void addRoiPopupMenu() { - ImageJ ij = IJ.getInstance(); - if (ij == null) - return; - roiPopupMenu = new PopupMenu(); - GUI.scalePopupMenu(roiPopupMenu); - addPopupItem("ROI Properties... ", "Properties... ", roiPopupMenu, ij); - addPopupItem("Roi Defaults...", null, roiPopupMenu, ij); - addPopupItem("Add to Overlay", "Add Selection...", roiPopupMenu, ij); - addPopupItem("Add to ROI Manager", "Add to Manager", roiPopupMenu, ij); - addPopupItem("Duplicate...", null, roiPopupMenu, ij); - addPopupItem("Fit Spline", null, roiPopupMenu, ij); - addPopupItem("Create Mask", null, roiPopupMenu, ij); - addPopupItem("Measure", null, roiPopupMenu, ij); - add(roiPopupMenu); - } - - private void addPopupItem(String label, String command, PopupMenu pm, ImageJ ij) { - MenuItem mi = new MenuItem(label); - if (command != null) - mi.setActionCommand(command); - mi.addActionListener(ij); - pm.add(mi); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImageLayout.java b/com.eco.bio7.image/src/ij/gui/ImageLayout.java deleted file mode 100644 index 7888616c7..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageLayout.java +++ /dev/null @@ -1,113 +0,0 @@ -package ij.gui; -import java.awt.*; -import ij.*; - -/** This is a custom layout manager that supports resizing of zoomed -images. It's based on FlowLayout, but with vertical and centered flow. */ -public class ImageLayout implements LayoutManager { - - int hgap = ImageWindow.HGAP; - int vgap = ImageWindow.VGAP; - ImageCanvas ic; - boolean ignoreNonImageWidths; - - /** Creates a new ImageLayout with center alignment. */ - public ImageLayout(ImageCanvas ic) { - this.ic = ic; - } - - /** Not used by this class. */ - public void addLayoutComponent(String name, Component comp) { - } - - /** Not used by this class. */ - public void removeLayoutComponent(Component comp) { - } - - /** Returns the preferred dimensions for this layout. */ - public Dimension preferredLayoutSize(Container target) { - Dimension dim = new Dimension(0,0); - int nmembers = target.getComponentCount(); - for (int i=0; i0) dim.height += vgap; - dim.height += d.height; - } - Insets insets = target.getInsets(); - dim.width += insets.left + insets.right + hgap*2; - dim.height += insets.top + insets.bottom + vgap*2; - return dim; - } - - /** Returns the minimum dimensions for this layout. */ - public Dimension minimumLayoutSize(Container target) { - return preferredLayoutSize(target); - } - - /** Determines whether to ignore the width of non-image components when calculating - * the preferred width (default false, i.e. the maximum of the widths of all components is used). - * When true, components that do not fit the window will be truncated at the right. - * The width of the 0th component (the ImageCanvas) is always taken into account. */ - public void ignoreNonImageWidths(boolean ignoreNonImageWidths) { - this.ignoreNonImageWidths = ignoreNonImageWidths; - } - - /** Centers the elements in the specified column, if there is any slack.*/ - private void moveComponents(Container target, int x, int y, int width, int height, int nmembers) { - int x2 = 0; - y += height / 2; - for (int i=0; i60) - x2 = x + (width - d.width)/2; - m.setLocation(x2, y); - y += vgap + d.height; - } - } - - /** Lays out the container and calls ImageCanvas.resizeCanvas() - to adjust the image canvas size as needed. */ - public void layoutContainer(Container target) { - Insets insets = target.getInsets(); - int nmembers = target.getComponentCount(); - Dimension d; - int extraHeight = 0; - for (int i=1; i 0) y += vgap; - y += d.height; - if (i==0 || !ignoreNonImageWidths) - colw = Math.max(colw, d.width); - } - moveComponents(target, x, insets.top + vgap, colw, maxheight - y, nmembers); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImagePanel.java b/com.eco.bio7.image/src/ij/gui/ImagePanel.java deleted file mode 100644 index 13481eedb..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImagePanel.java +++ /dev/null @@ -1,25 +0,0 @@ -package ij.gui; -import java.awt.*; -import ij.*; - -/** This class is used by GenericDialog to add images to dialogs. */ -public class ImagePanel extends Panel { - private ImagePlus img; - - public ImagePanel(ImagePlus img) { - this.img = img; - } - - public Dimension getPreferredSize() { - return new Dimension(img.getWidth(), img.getHeight()); - } - - public Dimension getMinimumSize() { - return new Dimension(img.getWidth(), img.getHeight()); - } - - public void paint(Graphics g) { - g.drawImage(img.getProcessor().createImage(), 0, 0, null); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImageRoi.java b/com.eco.bio7.image/src/ij/gui/ImageRoi.java deleted file mode 100644 index 1f2bd6e2f..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageRoi.java +++ /dev/null @@ -1,152 +0,0 @@ -package ij.gui; -import ij.ImagePlus; -import ij.process.*; -import ij.io.FileSaver; -import java.awt.*; -import java.awt.image.*; - -/** An ImageRoi is an Roi that overlays an image. -* @see ij.ImagePlus#setOverlay(ij.gui.Overlay) -*/ -public class ImageRoi extends Roi { - private Image img; - private Composite composite; - private double opacity = 1.0; - private double angle = 0.0; - private boolean zeroTransparent; - private ImageProcessor ip; - - /** Creates a new ImageRoi from a BufferedImage.*/ - public ImageRoi(int x, int y, BufferedImage bi) { - super(x, y, bi.getWidth(), bi.getHeight()); - img = bi; - setStrokeColor(Color.black); - } - - /** Creates a new ImageRoi from a ImageProcessor.*/ - public ImageRoi(int x, int y, ImageProcessor ip) { - super(x, y, ip.getWidth(), ip.getHeight()); - img = ip.createImage(); - this.ip = ip; - setStrokeColor(Color.black); - } - - public void draw(Graphics g) { - Graphics2D g2d = (Graphics2D)g; - double mag = getMagnification(); - int sx2 = screenX(x+width); - int sy2 = screenY(y+height); - Composite saveComposite = null; - if (composite!=null) { - saveComposite = g2d.getComposite(); - g2d.setComposite(composite); - } - Image img2 = img; - if (angle!=0.0) { - ImageProcessor ip = new ColorProcessor(img); - ip.setInterpolate(true); - ip.setBackgroundValue(0.0); - ip.rotate(angle); - if (zeroTransparent) - ip = makeZeroTransparent(ip, true); - img2 = ip.createImage(); - } - g.drawImage(img2, screenX(x), screenY(y), sx2, sy2, 0, 0, img.getWidth(null), img.getHeight(null), null); - if (composite!=null) g2d.setComposite(saveComposite); - if (isActiveOverlayRoi() && !overlay) - super.draw(g); - } - - /** Sets the composite mode. */ - public void setComposite(Composite composite) { - this.composite = composite; - } - - /** Sets the composite mode using the specified opacity (alpha), in the - range 0.0-1.0, where 0.0 is fully transparent and 1.0 is fully opaque. */ - public void setOpacity(double opacity) { - if (opacity<0.0) opacity = 0.0; - if (opacity>1.0) opacity = 1.0; - this.opacity = opacity; - if (opacity!=1.0) - composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)opacity); - else - composite = null; - } - - /** Returns a serialized version of the image. */ - public byte[] getSerializedImage() { - ImagePlus imp = new ImagePlus("",img); - return new FileSaver(imp).serialize(); - } - - /** Returns the current opacity. */ - public double getOpacity() { - return opacity; - } - - public void rotate(double angle) { - this.angle += angle; - } - - public void setAngle(double angle) { - this.angle = angle; - } - - public void setZeroTransparent(boolean zeroTransparent) { - if (this.zeroTransparent!=zeroTransparent) { - ip = makeZeroTransparent(new ColorProcessor(img), zeroTransparent); - img = ip.createImage(); - } - this.zeroTransparent = zeroTransparent; - } - - public boolean getZeroTransparent() { - return zeroTransparent; - } - - private ImageProcessor makeZeroTransparent(ImageProcessor ip, boolean transparent) { - if (transparent) { - ip.setColorModel(new DirectColorModel(32,0x00ff0000,0x0000ff00,0x000000ff,0xff000000)); - for (int x=0; x1) - ip.set(x, y, ip.get(x,y)|0xff000000); // set alpha bits - else - ip.set(x, y, ip.get(x,y)&0xffffff); // clear alpha bits - } - } - } - return ip; - } - - public synchronized Object clone() { - ImageRoi roi2 = (ImageRoi)super.clone(); - ImagePlus imp = new ImagePlus("", img); - roi2.setProcessor(imp.getProcessor()); - roi2.setOpacity(getOpacity()); - return roi2; - } - - public ImageProcessor getProcessor() { - if (ip!=null) - return ip; - else { - ip = new ColorProcessor(img); - return ip; - } - } - - public void setProcessor(ImageProcessor ip) { - img = ip.createImage(); - this.ip = ip; - if (zeroTransparent) { - setZeroTransparent(false); - setZeroTransparent(true); - } - width = ip.getWidth(); - height = ip.getHeight(); - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/ImageWindow.java b/com.eco.bio7.image/src/ij/gui/ImageWindow.java deleted file mode 100644 index a7fbf16bd..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageWindow.java +++ /dev/null @@ -1,1120 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.image.*; -import java.util.Properties; -import java.util.Vector; - -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - -import java.awt.event.*; - -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.custom.CTabItem; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.PlatformUI; - -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.CustomDetachedImageJView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.SwtAwtImageJ; -import com.eco.bio7.image.Util; - -import ij.*; -import ij.process.*; -import ij.io.*; -import ij.measure.*; -import ij.plugin.frame.*; -import ij.plugin.PointToolOptions; -import ij.macro.Interpreter; -import ij.util.*; - -/** A frame for displaying images. */ -public class ImageWindow extends JFrame - implements FocusListener, WindowListener, WindowStateListener, MouseWheelListener { - - public static final int MIN_WIDTH = 128; - public static final int MIN_HEIGHT = 32; - public static final int HGAP = 5; - public static final int VGAP = 5; - public static final String LOC_KEY = "image.loc"; - - protected ImagePlus imp; - protected ImageJ ij; - protected ImageCanvas ic; - private double initialMagnification = 1; - private int newWidth, newHeight; - protected boolean closed; - private boolean newCanvas; - private boolean unzoomWhenMinimizing = true; - Rectangle maxWindowBounds; // largest possible window on this screen - Rectangle maxBounds; // Size of this window after it is maximized - long setMaxBoundsTime; - private int sliderHeight; - private static final int XINC = 12; - private static final int YINC = 16; - private final double SCALE = Prefs.getGuiScale(); - private int TEXT_GAP = 11; - private static int xbase = -1; - private static int ybase; - private static int xloc; - private static int yloc; - private static int count; - private static boolean centerOnScreen; - private static Point nextLocation; - public static long setMenuBarTime; - private int textGap = centerOnScreen ? 0 : TEXT_GAP; - private int screenHeight, screenWidth; - public SwtAwtImageJ swtAwtMain;// Changed for Bio7! - public boolean running2; - protected boolean imageInTab; - protected ImageWindow win2; - /** - * This variable is set false if the user presses the escape key or closes the - * window. - */ - public boolean running; - - /** - * This variable is set false if the user clicks in this window, presses the - * escape key, or closes the window. - */ - - // private ImageWindow windowInstance;// Changed for Bio7! - public SwtAwtImageJ getSwtAwtMain() { - return swtAwtMain; - } - - public void setSwtAwtMain(SwtAwtImageJ swtAwtMainFrame) { - this.swtAwtMain = swtAwtMainFrame; - } - - public ImageWindow(String title) { - super(title); - } - - public ImageWindow(ImagePlus imp) { - this(imp, null); - /// * Changed for Bio7! */ - // windowInstance = this; - } - - /* Changed for Bio7 setting the tab title and not the JFrame title! */ - public void setTitle(String title) { - - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - for (int i = 0; i < items.length; i++) { - - Vector ve = (Vector) items[i].getData(); - - final ImageWindow win2 = (ImageWindow) ve.get(1); - - /* Search for the tab which embeds this instance! */ - if (ImageWindow.this.equals(win2)) { - // Rename the tab! - CanvasView.tabFolder.getItem(i).setText(title); - - return; - - } - - } - - /* - * CustomDetachedImageJView customImageJView = ImageJ.customImageJView; if - * (customImageJView != null) { customImageJView.setPartName(title); } - */ - - IViewReference[] viewRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() - .getViewReferences(); - for (int i = 0; i < viewRefs.length; i++) { - String id = viewRefs[i].getId(); - if (id.equals("com.eco.bio7.image.detachedImage")) { - IViewPart view = viewRefs[i].getView(false); - String secId = viewRefs[i].getSecondaryId(); - CustomDetachedImageJView cdview = (CustomDetachedImageJView) view; - /* Get the image from the detached secondary view id (same id)! */ - ImagePlus ip = WindowManager.getImage(Integer.valueOf(secId)); - if (ip != null) { - if (ImageWindow.this.equals(ip.getWindow())) { - cdview.setPartName(title); - } - } - - } - } - - } - }); - - } - - public ImageWindow(ImagePlus imp, ImageCanvas ic) { - super(imp.getTitle()); - if (SCALE > 1.0) { - TEXT_GAP = (int) (TEXT_GAP * SCALE); - textGap = centerOnScreen ? 0 : TEXT_GAP; - } - boolean openAsHyperStack = imp.getOpenAsHyperStack(); - ij = IJ.getInstance(); - this.imp = imp; - if (ic == null) { - ic = (this instanceof PlotWindow) ? new PlotCanvas(imp) : new ImageCanvas(imp); - newCanvas = true; - } - this.ic = ic; - ImageWindow previousWindow = imp.getWindow(); - - setLayout(new ImageLayout(ic)); - add(ic); - addFocusListener(this); - addWindowListener(this); - addWindowStateListener(this); - addKeyListener(ij); - - setFocusTraversalKeysEnabled(false); - if (!(this instanceof StackWindow)) - addMouseWheelListener(this); - - setResizable(true); - if (!(this instanceof HistogramWindow && IJ.isMacro() && Interpreter.isBatchMode())) { - WindowManager.addWindow(this); - imp.setWindow(this); - } - if (previousWindow != null) { - /* Hide the tab without to close the image! */ - IJTabs.hideTab(); - if (newCanvas) - setLocationAndSize(false); - else - ic.update(previousWindow.getCanvas()); - - if (!(this instanceof StackWindow || this instanceof PlotWindow)) { // layout now unless components will be - // added later - swtAwtMain = new SwtAwtImageJ(null, null, null, ic, imp, this); - /* Add the panel to the tab folder with the image */ - swtAwtMain.addTab(imp.getTitle()); - imp.setWindow(this); - - /* - * The next seems to be important for Mac. Else at the first zoom level the - * image disapears! - */ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - pack(); - } - }); - /* Necessary for highDPI layout SWT_AWT! */ - CanvasView canvasView = CanvasView.getCanvas_view(); - canvasView.recalculateLayout(); - /* - * The next seems to be important for Mac. Else at the first zoom level the - * image disapears! - */ - if (IJ.isMacro()) - imp.setDeactivated(); // prepare for waitTillActivated (imp may have been activated before if it - // gets a new Window now) - // show(); - } - if (ic.getMagnification() != 0.0) - imp.setTitle(imp.getTitle()); - boolean unlocked = imp.lockSilently(); - boolean changes = imp.changes; - imp.changes = false; - /* - * Changed for Bio7. We have to call the default ImageJ close function which is - * renamed to bio7TabClose because we have hidden the tab already (close - * searches for the tab and closes it)! - */ - previousWindow.bio7TabClose(true); - imp.changes = changes; - if (unlocked) - imp.unlock(); - if (this.imp != null) - this.imp.setOpenAsHyperStack(openAsHyperStack); - WindowManager.setCurrentWindow(this); - } else { - // setLocationAndSize(false); - /* - * if (ij != null && !IJ.isMacintosh()) { Image img = ij.getIconImage(); if (img!=null) try { - setIconImage(img); - } catch (Exception e) {} - */ - - if (Interpreter.isBatchMode() || (IJ.getInstance() == null && this instanceof HistogramWindow)) { - WindowManager.setTempCurrentImage(imp); - Interpreter.addBatchModeImage(imp); - } - - else { - if (IJ.isMacro()) - imp.setDeactivated(); // prepare for waitTillActivated (imp may have been activated previously and - // gets a new Window now) - - if (!(this instanceof StackWindow)) { - swtAwtMain = new SwtAwtImageJ(null, null, null, ic, imp, this); - /* Add the panel to the tab folder with the image */ - swtAwtMain.addTab(imp.getTitle()); - imp.setWindow(this); - /* - * The next seems to be important for Mac. Else at the first zoom level the - * image disapears! - */ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - pack(); - } - }); - /* Necessary for highDPI layout SWT_AWT! */ - CanvasView canvasView = CanvasView.getCanvas_view(); - canvasView.recalculateLayout(); - - } - - } - - } - - } - - private void setLocationAndSize(boolean updating) { - if (imp == null) - return; - int width = imp.getWidth(); - int height = imp.getHeight(); - - // load preferences file location - Point loc = Prefs.getLocation(LOC_KEY); - Rectangle bounds = null; - if (loc != null) { - bounds = GUI.getMaxWindowBounds(loc); - if (bounds != null && (loc.x > bounds.x + bounds.width / 3 || loc.y > bounds.y + bounds.height / 3) - && (loc.x + width > bounds.x + bounds.width || loc.y + height > bounds.y + bounds.height)) { - loc = null; - bounds = null; - } - } - // if loc not valid, use screen bounds of visible window (this) or of main - // window (ij) if not visible yet (updating == false) - Rectangle maxWindow = bounds != null ? bounds : GUI.getMaxWindowBounds(updating ? this : ij); - - if (WindowManager.getWindowCount() <= 1) - xbase = -1; - if (width > maxWindow.width / 2 && xbase > maxWindow.x + 5 + XINC * 6) - xbase = -1; - if (xbase == -1) { - count = 0; - if (loc != null) { - xbase = loc.x; - ybase = loc.y; - } else if (ij != null) { - Rectangle ijBounds = ij.getBounds(); - if (ijBounds.y - maxWindow.x < maxWindow.height / 8) { - xbase = ijBounds.x; - if (xbase + width > maxWindow.x + maxWindow.width) { - xbase = maxWindow.x + maxWindow.width - width - 10; - if (xbase < maxWindow.x) - xbase = maxWindow.x + 5; - ; - } - ybase = ijBounds.y + ijBounds.height + 5; - } else { - xbase = maxWindow.x + (maxWindow.width - width) / 2; - ybase = maxWindow.y + (maxWindow.height - height) / 4; - } - } else { - xbase = maxWindow.x + (maxWindow.width - width) / 2; - ybase = maxWindow.y + (maxWindow.height - height) / 4; - } - xbase = Math.max(xbase, maxWindow.x); - ybase = Math.max(ybase, maxWindow.y); - //if (IJ.debugMode) - //IJ.log("ImageWindow.xbase: " + xbase); - xloc = xbase; - yloc = ybase; - } - int x = xloc; - int y = yloc; - xloc += XINC; - yloc += YINC; - count++; - if (count % 6 == 0) { - xloc = xbase; - yloc = ybase; - } - - screenHeight = maxWindow.y + maxWindow.height - sliderHeight; - screenWidth = maxWindow.x + maxWindow.width; - double mag = 1; - if (!(this instanceof PlotWindow)) { // unless a plot (always at 100%), zoom out to show all of image - while (xbase + width * mag > screenWidth || ybase + height * mag >= screenHeight) { - double mag2 = ImageCanvas.getLowerZoomLevel(mag); - if (mag2 == mag) - break; - mag = mag2; - } - } - - if (mag < 1.0) { - initialMagnification = mag; - ic.setSize((int) (width * mag), (int) (height * mag)); - } - ic.setMagnification(mag); - if (y + height * mag > screenHeight) - y = ybase; - if (Prefs.open100Percent && ic.getMagnification() < 1.0) { - while (ic.getMagnification() < 1.0) - ic.zoomIn(0, 0); - setSize(Math.min(width, screenWidth - x), Math.min(height, screenHeight - y)); - validate(); - } else - pack(); - if (!updating) - setLocation(x, y); - } - - Rectangle getMaxWindow(int xloc, int yloc) { - - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - /* Changed for Bio7! */ - Rectangle bounds = CanvasView.getCanvas_view().getCurrent().getBounds(); - - // return GUI.getMaxWindowBounds(new Point(xloc, yloc)); - - return bounds; - } - - /* - * public Rectangle getBounds() { - * - * Changed for Bio7! Rectangle bounds = - * CanvasView.getCanvas_view().getCurrent().getBounds(); - * - * return bounds; } - */ - - public double getInitialMagnification() { - return initialMagnification; - } - - /** - * Override Container getInsets() to make room for some text above the image. - */ - /* - * public Insets getInsets() { Insets insets = super.getInsets(); if (imp == - * null) return insets; double mag = ic.getMagnification(); int extraWidth = - * (int) ((MIN_WIDTH - imp.getWidth() * mag) / 2.0); if (extraWidth < 0) - * extraWidth = 0; int extraHeight = (int) ((MIN_HEIGHT - imp.getHeight() * mag) - * / 2.0); if (extraHeight < 0) extraHeight = 0; insets = new Insets(insets.top - * + textGap + extraHeight, insets.left + extraWidth, insets.bottom + - * extraHeight, insets.right + extraWidth); return insets; } - */ - - /** Draws the subtitle. */ - public void drawInfo(Graphics g) { - if (imp == null) - return; - if (textGap != 0) { - Insets insets = super.getInsets(); - Color savec = null; - if (imp.isComposite()) { - CompositeImage ci = (CompositeImage) imp; - if (ci.getMode() == IJ.COMPOSITE) { - savec = g.getColor(); - Color c = ci.getChannelColor(); - if (Color.green.equals(c)) - c = new Color(0, 180, 0); - g.setColor(c); - } - } - Java2.setAntialiasedText(g, true); - if (SCALE > 1.0) { - Font font = new Font("SansSerif", Font.PLAIN, (int) (12 * SCALE)); - g.setFont(font); - } - g.drawString(createSubtitle(), insets.left + 5, insets.top + TEXT_GAP); - if (savec != null) - g.setColor(savec); - } - } - - /** Creates the subtitle. */ - public String createSubtitle() { - String s = ""; - if (imp == null) - return s; - int stackSize = imp.getStackSize(); - if (stackSize > 1) { - ImageStack stack = imp.getStack(); - int currentSlice = imp.getCurrentSlice(); - s += currentSlice + "/" + stackSize; - String label = stack.getShortSliceLabel(currentSlice); - if (label != null && label.length() > 0) { - if (imp.isHyperStack()) - label = label.replace(';', ' '); - s += " (" + label + ")"; - } - if ((this instanceof StackWindow) && running2) { - return s; - } - s += "; "; - } else { - String label = imp.getProp("Slice_Label"); - if (label==null && imp.hasImageStack()) - label = imp.getStack().getSliceLabel(1); - if (label != null && label.length() > 0) { - int newline = label.indexOf('\n'); - if (newline > 0) - label = label.substring(0, newline); - int len = label.length(); - if (len > 4 && label.charAt(len - 4) == '.' && !Character.isDigit(label.charAt(len - 1))) - label = label.substring(0, len - 4); - if (label.length() > 60) - label = label.substring(0, 60) + "..."; - s = "\"" + label + "\"; "; - } - } - int type = imp.getType(); - Calibration cal = imp.getCalibration(); - if (cal.scaled()) { - boolean unitsMatch = cal.getXUnit().equals(cal.getYUnit()); - double cwidth = imp.getWidth() * cal.pixelWidth; - double cheight = imp.getHeight() * cal.pixelHeight; - int digits = Tools.getDecimalPlaces(cwidth, cheight); - if (digits > 2) - digits = 2; - if (unitsMatch) { - s += IJ.d2s(cwidth, digits) + "x" + IJ.d2s(cheight, digits) + " " + cal.getUnits() + " (" - + imp.getWidth() + "x" + imp.getHeight() + "); "; - } else { - s += d2s(cwidth) + " " + cal.getXUnit() + " x " + d2s(cheight) + " " + cal.getYUnit() + " (" - + imp.getWidth() + "x" + imp.getHeight() + "); "; - } - } else - s += imp.getWidth() + "x" + imp.getHeight() + " pixels; "; - switch (type) { - case ImagePlus.GRAY8: - case ImagePlus.COLOR_256: - s += "8-bit"; - break; - case ImagePlus.GRAY16: - s += "16-bit"; - break; - case ImagePlus.GRAY32: - s += "32-bit"; - break; - case ImagePlus.COLOR_RGB: - s += imp.isRGB() ? "RGB" : "32-bit (int)"; - break; - } - if (imp.isInvertedLut()) - s += " (inverting LUT)"; - return s + "; " + getImageSize(imp); - } - - public static String getImageSize(ImagePlus imp) { - if (imp == null) - return null; - double size = imp.getSizeInBytes() / 1024.0; - String s2 = null, s3 = null; - if (size < 1024.0) { - s2 = IJ.d2s(size, 0); - s3 = "K"; - } else if (size < 10000.0) { - s2 = IJ.d2s(size / 1024.0, 1); - s3 = "MB"; - } else if (size < 1048576.0) { - s2 = IJ.d2s(Math.round(size / 1024.0), 0); - s3 = "MB"; - } else { - s2 = IJ.d2s(size / 1048576.0, 1); - s3 = "GB"; - } - if (s2.endsWith(".0")) - s2 = s2.substring(0, s2.length() - 2); - return s2 + s3; - } - - private String d2s(double n) { - int digits = Tools.getDecimalPlaces(n); - if (digits > 2) - digits = 2; - return IJ.d2s(n, digits); - } - - /* Changed for Bio7! */ - /* - * public Rectangle getBounds(){ GraphicsEnvironment ge = - * GraphicsEnvironment.getLocalGraphicsEnvironment(); Changed for Bio7! - * Rectangle bounds = CanvasView.getCanvas_view().getCurrent().getBounds(); - * return bounds; } - */ - - public void paintComponents(Graphics g) { - super.paintComponents(g); - drawInfo(g); - Rectangle r = ic.getBounds(); - int extraWidth = MIN_WIDTH - r.width; - int extraHeight = MIN_HEIGHT - r.height; - if (extraWidth <= 0 && extraHeight <= 0 && !Prefs.noBorder && !IJ.isLinux()) - g.drawRect(r.x - 1, r.y - 1, r.width + 1, r.height + 1); - } - - /** - * Removes this window from the window list and disposes of it. Returns false if - * the user cancels the "save changes" dialog. - */ - public boolean close() { - /* - * boolean isRunning = running || running2; running = running2 = false; if - * (imp==null) return true; boolean virtual = imp.getStackSize()>1 && - * imp.getStack().isVirtual(); if (isRunning) IJ.wait(500); if (ij==null || - * IJ.getApplet()!=null || Interpreter.isBatchMode() || IJ.macroRunning() || - * virtual) imp.changes = false; if (imp.changes) { String msg; String name = - * imp.getTitle(); if (name.length()>22) msg = "Save changes to\n" + "\"" + name - * + "\"?"; else msg = "Save changes to \"" + name + "\"?"; YesNoCancelDialog d - * = new YesNoCancelDialog(this, "ImageJ", msg); if (d.cancelPressed()) return - * false; else if (d.yesPressed()) { FileSaver fs = new FileSaver(imp); if - * (!fs.save()) return false; } } closed = true; if - * (WindowManager.getWindowCount()==0) {xloc = 0; yloc = 0;} if - * (firstSmallWindow) Prefs.saveLocation(LOC_KEY, getLocation()); - * WindowManager.removeWindow(this); - if (ij!=null && ij.quitting()) // this may help avoid thread deadlocks - return true; - Rectangle bounds = getBounds(); - if (initialLoc!=null && !bounds.equals(initialLoc) && !IJ.isMacro() - && bounds.y 1 && imp.getStack().isVirtual(); - if (isRunning) - IJ.wait(500); - if (ij == null || ij.quittingViaMacro() || IJ.getApplet() != null || Interpreter.isBatchMode() - || IJ.macroRunning() || virtual) - imp.changes = false; - /* Changed for Bio7! */ - /* - * if (imp.changes) { String msg; String name = imp.getTitle(); if - * (name.length()>22) msg = "Save changes to\n" + "\"" + name + "\"?"; else msg - * = "Save changes to \"" + name + "\"?"; YesNoCancelDialog d = new - * YesNoCancelDialog(this, "ImageJ", msg); if (d.cancelPressed()) return false; - * else if (d.yesPressed()) { FileSaver fs = new FileSaver(imp); if (!fs.save()) - * return false; } } - */ - closed = true; - if (WindowManager.getWindowCount() == 0) { - xloc = 0; - yloc = 0; - } - Point currentLoc = getLocation(); - if (!IJ.isMacro()) { - Prefs.saveLocation(LOC_KEY, currentLoc); - xbase = -1; - } - WindowManager.removeWindow(this); - setVisible(false); - if (ij != null && ij.quitting()) // this may help avoid thread deadlocks - return true; - /*Changed for Bio7! - Avoid deadlock situation by disposing the JFrame!*/ - if (disposeFrame) { - dispose(); - } - if (imp != null) - imp.flush(); - imp = null; - return true; - } - - public ImagePlus getImagePlus() { - return imp; - } - - public void setImage(ImagePlus imp2) { - ImageCanvas ic = getCanvas(); - if (ic == null || imp2 == null) - return; - imp = imp2; - imp.setWindow(this); - ic.updateImage(imp); - ic.setImageUpdated(); - ic.repaint(); - repaint(); - } - - /*Changed for Bio7. Overwrite repaint to send a message to the swt statusline!*/ - public void repaint() { - Display display = Util.getDisplay(); - /* - * MacOSX only seems to work with async method! Also on Windows async works best - * (avoids deadlocks when mouse moved in and out the canvas opening several - * images at once in the background!). - */ - - display.asyncExec(new Runnable() { - public void run() { - if (imp != null) { - - if (imp.isComposite()) { - CompositeImage ci = (CompositeImage) imp; - if (ci.getMode() == IJ.COMPOSITE) { - Color c = ci.getChannelColor(); - if (Color.green.equals(c)) - c = new Color(0, 180, 0); - // g.setColor(c); - int red = c.getRed(); - int green = c.getGreen(); - int blue = c.getBlue(); - org.eclipse.swt.graphics.Color color = new org.eclipse.swt.graphics.Color(display, - new RGB(red, green, blue)); - // CanvasView.tabFolder.setSelectionForeground(color); - /*On MacOSX we get NullPointerException when we call the status line first. - * So we place the call to the status line here!*/ - CanvasView canvasView = CanvasView.getCanvas_view(); - if (canvasView != null) { - canvasView.setStatusLineColor(createSubtitle(), color); - } - - } - - } else { - CanvasView canvasView = CanvasView.getCanvas_view(); - if (canvasView != null) { - canvasView.setstatusline(createSubtitle()); - } - } - - } - } - }); - super.repaint(); - } - - public void show() { - /*Changed for Bio7! - * Empty function. - * The overwrite implementation avoids the opening - * of a JFrame ImageWindow and a reference to the image from the - * Functions class method: displayBatchModeImage in a macro when calling - * setBatchMode(false) - * */ - // System.out.println("Show"); - } - - public void updateImage(ImagePlus imp) { - if (imp != this.imp) - throw new IllegalArgumentException("imp!=this.imp"); - this.imp = imp; - ic.updateImage(imp); - setLocationAndSize(true); - if (this instanceof StackWindow) { - StackWindow sw = (StackWindow) this; - int stackSize = imp.getStackSize(); - int nScrollbars = sw.getNScrollbars(); - if (stackSize == 1 && nScrollbars > 0) - sw.removeScrollbars(); - else if (stackSize > 1 && nScrollbars == 0) - sw.addScrollbars(imp); - } - pack(); - repaint(); - maxBounds = getMaximumBounds(); - setMaximizedBounds(maxBounds); - setMaxBoundsTime = System.currentTimeMillis(); - } - - public ImageCanvas getCanvas() { - return ic; - } - - static ImagePlus getClipboard() { - return ImagePlus.getClipboard(); - } - - public Rectangle getBounds() { - Rectangle rec; - JPanel current = CanvasView.getCanvas_view().getCurrent(); - JPanel pan = current; - if (pan != null) { - rec = current.getBounds(); - } else { - rec = new Rectangle(400, 400); - } - - return rec; - - } - - public Rectangle getMaximumBounds() { - Rectangle rec; - JPanel pan = CanvasView.getCanvas_view().getCurrent(); - if (pan != null) { - rec = CanvasView.getCanvas_view().getCurrent().getBounds(); - } else { - rec = new Rectangle(400, 400); - } - - /* - * Rectangle maxWindow = GUI.getMaxWindowBounds(); if (imp == null) return - * maxWindow; double width = imp.getWidth(); double height = imp.getHeight(); - * double iAspectRatio = width / height; - * - * maxWindowBounds = maxWindow; if (iAspectRatio / ((double) maxWindow.width / - * maxWindow.height) > 0.75) { maxWindow.y += 22; // uncover ImageJ menu bar - * maxWindow.height -= 22; } Dimension extraSize = getExtraSize(); double - * maxWidth = maxWindow.width - extraSize.width; double maxHeight = - * maxWindow.height - extraSize.height; double mAspectRatio = maxWidth / - * maxHeight; int wWidth, wHeight; double mag; if (iAspectRatio >= mAspectRatio) - * { mag = maxWidth / width; wWidth = maxWindow.width; wHeight = (int) (height * - * mag + extraSize.height); } else { mag = maxHeight / height; wHeight = - * maxWindow.height; wWidth = (int) (width * mag + extraSize.width); } int xloc - * = (int) (maxWidth - wWidth) / 2; if (xloc < 0) xloc = 0; - */ - return rec; - } - - Dimension getExtraSize() { - Insets insets = getInsets(); - int extraWidth = insets.left + insets.right + 10; - int extraHeight = insets.top + insets.bottom + 10; - if (extraHeight == 20) - extraHeight = 42; - int members = getComponentCount(); - for (int i = 1; i < members; i++) { - Component m = getComponent(i); - Dimension d = m.getPreferredSize(); - extraHeight += d.height + 5; - if (IJ.debugMode) - IJ.log(i + " " + d.height + " " + extraHeight); - } - return new Dimension(extraWidth, extraHeight); - } - - public Component add(Component comp) { - comp = super.add(comp); - maxBounds = getMaximumBounds(); - setMaximizedBounds(maxBounds); - setMaxBoundsTime = System.currentTimeMillis(); - return comp; - } - - public void maximize() { - if (GenericDialog.getInstance() != null && IJ.isMacOSX() && IJ.isJava18()) - return; // workaround for OSX/Java 8 maximize bug - Rectangle rect = getMaximumBounds(); - if (IJ.debugMode) - IJ.log("maximize: " + rect); - setLocationAndSize(rect.x, rect.y, rect.width, rect.height); - } - - public void minimize() { - if (IJ.debugMode) - IJ.log("minimize: " + unzoomWhenMinimizing); - if (unzoomWhenMinimizing) - ic.unzoom(); - unzoomWhenMinimizing = true; - } - - /** Has this window been closed? */ - public boolean isClosed() { - return closed; - } - - public void focusGained(FocusEvent e) { - if (!Interpreter.isBatchMode() && ij != null && !ij.quitting() && imp != null) { - //if (IJ.debugMode) - //IJ.log("focusGained: " + imp); - WindowManager.setCurrentWindow(this); - } - } - - public void windowActivated(WindowEvent e) { - if (IJ.debugMode) - IJ.log("windowActivated: " + imp.getTitle()); - if (IJ.isMacOSX() && Prefs.setIJMenuBar && !IJ.isMacro()) - setImageJMenuBar(this); - if (imp == null) - return; - ImageJ ij = IJ.getInstance(); - if (ij != null && !closed && !ij.quitting() && !Interpreter.isBatchMode()) - WindowManager.setCurrentWindow(this); - Roi roi = imp.getRoi(); - if (roi != null && (roi instanceof PointRoi)) - PointToolOptions.update(); - if (imp.isComposite()) - Channels.updateChannels(); - imp.setActivated(); // notify ImagePlus that image has been activated - } - - public void windowClosing(WindowEvent e) { - if (closed) - return; - if (ij != null) { - WindowManager.setCurrentWindow(this); - IJ.doCommand("Close"); - } else { - dispose(); - WindowManager.removeWindow(this); - } - } - - public void windowStateChanged(WindowEvent e) { - int oldState = e.getOldState(); - int newState = e.getNewState(); - if (IJ.debugMode) - IJ.log("windowStateChanged: " + oldState + " " + newState); - if ((oldState & Frame.MAXIMIZED_BOTH) == 0 && (newState & Frame.MAXIMIZED_BOTH) != 0) - maximize(); - - } - - public void windowClosed(WindowEvent e) { - } - - public void windowDeactivated(WindowEvent e) { - } - - public void focusLost(FocusEvent e) { - } - - public void windowDeiconified(WindowEvent e) { - } - - public void windowIconified(WindowEvent e) { - } - - public void windowOpened(WindowEvent e) { - } - - public synchronized void mouseWheelMoved(MouseWheelEvent e) { - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - //if (IJ.debugMode) { - // IJ.log("mouseWheelMoved: "+e); - // IJ.log(" type: "+e.getScrollType()); - // IJ.log(" ctrl: "+ctrl); - // IJ.log(" rotation: "+rotation); - // IJ.log(" amount: "+amount); - //} - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - int width = imp.getWidth(); - int height = imp.getHeight(); - Rectangle srcRect = ic.getSrcRect(); - int xstart = srcRect.x; - int ystart = srcRect.y; - if ((ctrl || IJ.shiftKeyDown()) && ic != null) { - int ox = ic.offScreenX(e.getX()); - int oy = ic.offScreenY(e.getX()); - if (IJ.debugMode) - IJ.log(" x,y: " + ox + "," + oy); - if (rotation < 0) - ic.zoomIn(ox, oy); - else - ic.zoomOut(ox, oy); - return; - } else if (IJ.spaceBarDown() || srcRect.height == height) { - srcRect.x += rotation * amount * Math.max(width / 200, 1); - if (srcRect.x < 0) - srcRect.x = 0; - if (srcRect.x + srcRect.width > width) - srcRect.x = width - srcRect.width; - } else { - srcRect.y += rotation * amount * Math.max(height / 200, 1); - if (srcRect.y < 0) - srcRect.y = 0; - if (srcRect.y + srcRect.height > height) - srcRect.y = height - srcRect.height; - } - if (srcRect.x != xstart || srcRect.y != ystart) - ic.repaint(); - } - - /** - * Copies the current ROI to the clipboard. The entire image is copied if there - * is no ROI. - */ - public void copy(boolean cut) { - imp.copy(cut); - } - - public void paste() { - imp.paste(); - } - - /** - * This method is called by ImageCanvas.mouseMoved(MouseEvent). - * - * @see ij.gui.ImageCanvas#mouseMoved - */ - public void mouseMoved(int x, int y) { - imp.mouseMoved(x, y); - } - - public String toString() { - return imp != null ? imp.getTitle() : ""; - } - - /** - * Causes the next image to be opened to be centered on the screen and displayed - * without informational text above the image. - */ - public static void centerNextImage() { - centerOnScreen = true; - } - - /** Causes the next image to be displayed at the specified location. */ - public static void setNextLocation(Point loc) { - nextLocation = loc; - } - - /** Causes the next image to be displayed at the specified location. */ - public static void setNextLocation(int x, int y) { - nextLocation = new Point(x, y); - } - - /** - * Moves and resizes this window. Changes the magnification so the image fills - * the window. - */ - public void setLocationAndSize(int x, int y, int width, int height) { - /*Changed for Bio7 for detached views only!*/ - String idValue = Integer.toString(getImagePlus().getID()); - IJTabs.setSecondaryViewShellLocAndSize(idValue, new org.eclipse.swt.graphics.Rectangle(x, y, width, height)); - } - - @Override - public void setLocation(int x, int y) { - super.setLocation(x, y); - } - - public void setSliderHeight(int height) { - sliderHeight = height; - } - - public int getSliderHeight() { - return sliderHeight; - } - - public static void setImageJMenuBar(ImageWindow win) { - ImageJ ij = IJ.getInstance(); - boolean setMenuBar = true; - ImagePlus imp = win.getImagePlus(); - if (imp != null) - setMenuBar = imp.setIJMenuBar(); - MenuBar mb = Menus.getMenuBar(); - if (mb != null && mb == win.getMenuBar()) - setMenuBar = false; - setMenuBarTime = 0L; - if (setMenuBar && ij!=null && !ij.quitting()) { - IJ.wait(10); // may be needed for Java 1.4 on OS X - long t0 = System.currentTimeMillis(); - win.setMenuBar(mb); - long time = System.currentTimeMillis() - t0; - setMenuBarTime = time; - Menus.setMenuBarCount++; - if (time > 2000L) - Prefs.setIJMenuBar = false; - - } - if (imp != null) - imp.setIJMenuBar(true); - } - -} // class ImageWindow diff --git a/com.eco.bio7.image/src/ij/gui/Line.java b/com.eco.bio7.image/src/ij/gui/Line.java deleted file mode 100644 index 3149cffd0..000000000 --- a/com.eco.bio7.image/src/ij/gui/Line.java +++ /dev/null @@ -1,841 +0,0 @@ -package ij.gui; - -import ij.*; -import ij.process.*; -import ij.measure.*; -import ij.plugin.Straightener; -import ij.plugin.frame.Recorder; -import ij.plugin.CalibrationBar; -import java.awt.*; -import java.awt.image.*; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.awt.event.*; -import java.awt.geom.*; - -/** This class represents a straight line selection. */ -public class Line extends Roi { - public int x1, y1, x2, y2; // the line end points as integer coordinates, for compatibility only - public double x1d, y1d, x2d, y2d; // the line using sub-pixel coordinates - protected double x1R, y1R, x2R, y2R; // the line, relative to base of subpixel bounding rect 'bounds' - protected double startxd, startyd; - static boolean widthChanged; - private boolean dragged; - private int mouseUpCount; - - /** - * Creates a new straight line selection using the specified starting and ending - * offscreen integer coordinates. - */ - public Line(int ox1, int oy1, int ox2, int oy2) { - this((double) ox1, (double) oy1, (double) ox2, (double) oy2); - } - - /** - * Creates a new straight line selection using the specified starting and ending - * offscreen double coordinates. - */ - public Line(double ox1, double oy1, double ox2, double oy2) { - super((int) (ox1 + 0.5), (int) (oy1 + 0.5), 0, 0); - type = LINE; - updateCoordinates(ox1, oy1, ox2, oy2); - if (!(this instanceof Arrow) && lineWidth > 1) - updateWideLine(lineWidth); - updateClipRect(); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - state = NORMAL; - } - - /** - * Creates a new straight line selection using the specified starting and ending - * offscreen coordinates. - */ - public static Line create(double x1, double y1, double x2, double y2) { - return new Line(x1, y1, x2, y2); - } - - /** - * Starts the process of creating a new user-generated straight line selection. - * 'sx' and 'sy' are screen coordinates that specify the start of the line. The - * user will determine the end of the line interactively using rubber banding. - */ - public Line(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - type = LINE; - startxd = offScreenXD(sx); - startyd = offScreenYD(sy); - if (!magnificationForSubPixel()) { - startxd = Math.round(startxd); - startyd = Math.round(startyd); - } - updateCoordinates(startxd, startyd, startxd, startyd); - if (!(this instanceof Arrow) && lineWidth > 1) - updateWideLine(lineWidth); - } - - /** - * @deprecated replaced by Line(int, int, int, int) - */ - public Line(int ox1, int oy1, int ox2, int oy2, ImagePlus imp) { - this(ox1, oy1, ox2, oy2); - setImage(imp); - } - - protected void grow(int sx, int sy) { // mouseDragged - drawLine(sx, sy); - dragged = true; - } - - public void mouseMoved(MouseEvent e) { - drawLine(e.getX(), e.getY()); - } - - protected void handleMouseUp(int screenX, int screenY) { - mouseUpCount++; - if (Prefs.enhancedLineTool && mouseUpCount == 1 && !dragged) - return; - state = NORMAL; - if (imp == null) - return; - imp.draw(clipX - 5, clipY - 5, clipWidth + 10, clipHeight + 10); - if (IJ.recording()) { - String method = (this instanceof Arrow) ? "makeArrow" : "makeLine"; - Recorder.record(method, x1, y1, x2, y2); - } - if (getLength() == 0.0) - imp.deleteRoi(); - } - - protected void drawLine(int sx, int sy) { - double xend = offScreenXD(sx); - double yend = offScreenYD(sy); - if (xend < 0.0) - xend = 0.0; - if (yend < 0.0) - yend = 0.0; - if (xend > xMax - 1) - xend = xMax - 1; - if (yend > yMax - 1) - yend = yMax - 1; - double xstart = getXBase() + x1R, ystart = getYBase() + y1R; - if (constrain) { - int i = 0; - double dy = Math.abs(yend - ystart); - double dx = Math.abs(xend - xstart); - double comp = dy / dx; - for (; i < PI_SEARCH.length; i++) { - if (comp < PI_SEARCH[i]) { - break; - } - } - if (i < PI_SEARCH.length) { - if (yend > ystart) { - yend = ystart + dx * PI_MULT[i]; - } else { - yend = ystart - dx * PI_MULT[i]; - } - } else { - xend = xstart; - } - } - if (!magnificationForSubPixel() || IJ.controlKeyDown()) { // during creation, CTRL enforces integer coordinates - xstart = Math.round(xstart); - ystart = Math.round(ystart); - xend = Math.round(xend); - yend = Math.round(yend); - } - updateCoordinates(xstart, ystart, xend, yend); - updateClipRect(); - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - } - - /** - * Used for angle searches in line ROI creation: tan = y/x for angle limits - * 1/2*45 degrees, and 3/2*45 deg - */ - private static final double[] PI_SEARCH = { Math.tan(Math.PI / 8), Math.tan((3 * Math.PI) / 8) }; - private static final double[] PI_MULT = { 0, 1 }; // y/x for horizontal (0 degrees) and 45 deg - - void move(int sx, int sy) { - int xNew = offScreenX(sx); - int yNew = offScreenY(sy); - x += xNew - startxd; - y += yNew - startyd; - clipboard = null; - startxd = xNew; - startyd = yNew; - updateClipRect(); - if (ignoreClipRect) - imp.draw(); - else - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - } - - protected void moveHandle(int sx, int sy) { - if (constrain && activeHandle == 2) { // constrain translation in 90deg steps - int dx = sx - previousSX; - int dy = sy - previousSY; - if (Math.abs(dx) > Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - double ox = offScreenXD(sx); - double oy = offScreenYD(sy); - double x1d = getXBase() + x1R, y1d = getYBase() + y1R; - double x2d = getXBase() + x2R, y2d = getYBase() + y2R; - double length = Math.sqrt(sqr(x2d - x1d) + sqr(y2d - y1d)); - switch (activeHandle) { - case 0: - double dx = ox - x1d; - double dy = oy - y1d; - x1d = ox; - y1d = oy; - if (center) { - x2d -= dx; - y2d -= dy; - } - if (aspect) { - double ratio = length / (Math.sqrt(sqr(x2d - x1d) + sqr(y2d - y1d))); - double xcd = x1d + (x2d - x1d) / 2; - double ycd = y1d + (y2d - y1d) / 2; - - if (center) { - x1d = xcd - ratio * (xcd - x1d); - x2d = xcd + ratio * (x2d - xcd); - y1d = ycd - ratio * (ycd - y1d); - y2d = ycd + ratio * (y2d - ycd); - } else { - x1d = x2d - ratio * (x2d - x1d); - y1d = y2d - ratio * (y2d - y1d); - } - - } - break; - case 1: - dx = ox - x2d; - dy = oy - y2d; - x2d = ox; - y2d = oy; - if (center) { - x1d -= dx; - y1d -= dy; - } - if (aspect) { - double ratio = length / (Math.sqrt((x2d - x1d) * (x2d - x1d) + (y2d - y1d) * (y2d - y1d))); - double xcd = x1d + (x2d - x1d) / 2; - double ycd = y1d + (y2d - y1d) / 2; - - if (center) { - x1d = xcd - ratio * (xcd - x1d); - x2d = xcd + ratio * (x2d - xcd); - y1d = ycd - ratio * (ycd - y1d); - y2d = ycd + ratio * (y2d - ycd); - } else { - x2d = x1d + ratio * (x2d - x1d); - y2d = y1d + ratio * (y2d - y1d); - } - - } - break; - case 2: - dx = ox - (x1d + (x2d - x1d) / 2); - dy = oy - (y1d + (y2d - y1d) / 2); - x1d += dx; - y1d += dy; - x2d += dx; - y2d += dy; - break; - } - if (constrain) { - double dx = Math.abs(x1d - x2d); - double dy = Math.abs(y1d - y2d); - double xcd = Math.min(x1d, x2d) + dx / 2; - double ycd = Math.min(y1d, y2d) + dy / 2; - - // double ratio = length/(Math.sqrt((x2d-x1d)*(x2d-x1d) + (y2d-y1d)*(y2d-y1d))); - if (activeHandle == 0) { - if (dx >= dy) { - if (aspect) { - if (x2d > x1d) - x1d = x2d - length; - else - x1d = x2d + length; - } - y1d = y2d; - if (center) { - y1d = y2d = ycd; - if (aspect) { - if (xcd > x1d) { - x1d = xcd - length / 2; - x2d = xcd + length / 2; - } else { - x1d = xcd + length / 2; - x2d = xcd - length / 2; - } - } - } - } else { - if (aspect) { - if (y2d > y1d) - y1d = y2d - length; - else - y1d = y2d + length; - } - x1d = x2d; - if (center) { - x1d = x2d = xcd; - if (aspect) { - if (ycd > y1d) { - y1d = ycd - length / 2; - y2d = ycd + length / 2; - } else { - y1d = ycd + length / 2; - y2d = ycd - length / 2; - } - } - } - } - } else if (activeHandle == 1) { - if (dx >= dy) { - if (aspect) { - if (x1d > x2d) - x2d = x1d - length; - else - x2d = x1d + length; - } - y2d = y1d; - if (center) { - y1d = y2d = ycd; - if (aspect) { - if (xcd > x1d) { - x1d = xcd - length / 2; - x2d = xcd + length / 2; - } else { - x1d = xcd + length / 2; - x2d = xcd - length / 2; - } - } - } - } else { - if (aspect) { - if (y1d > y2d) - y2d = y1d - length; - else - y2d = y1d + length; - } - x2d = x1d; - if (center) { - x1d = x2d = xcd; - if (aspect) { - if (ycd > y1d) { - y1d = ycd - length / 2; - y2d = ycd + length / 2; - } else { - y1d = ycd + length / 2; - y2d = ycd - length / 2; - } - } - } - } - } - } - if (!magnificationForSubPixel()) { - x1d = Math.round(x1d); - y1d = Math.round(y1d); - x2d = Math.round(x2d); - y2d = Math.round(y2d); - } - updateCoordinates(x1d, y1d, x2d, y2d); - updateClipRect(); - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - } - - protected void mouseDownInHandle(int handle, int sx, int sy) { - super.mouseDownInHandle(handle, sx, sy); // sets state, activeHandle, previousSX&Y - if (getStrokeWidth() <= 3) - ic.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); - } - - /** - * Sets the x1d, y1d, x2d, y2d line end points, the (legacy) integer coordinates - * of the end points x1, y1, x2, y2 the 'bounds' subpixel rectangle of the Roi - * superclass (spanned by the end points), the int x, y, width, height integer - * bounds of the superclass (these enclose the 'draw' area for 1 pixel width), - * and the coordinates x1R, y1R, x2R, y2R relative to the base x, y of the - * 'bounds' - */ - void updateCoordinates(double x1d, double y1d, double x2d, double y2d) { - this.x1d = x1d; - this.y1d = y1d; - this.x2d = x2d; - this.y2d = y2d; - Rectangle2D.Double bounds = this.bounds; // local variable (this.bounds may become null asynchronously upon nudge) - if (bounds == null) - bounds = new Rectangle2D.Double(); - bounds.x = Math.min(x1d, x2d); - bounds.y = Math.min(y1d, y2d); - bounds.width = Math.abs(x2d - x1d); - bounds.height = Math.abs(y2d - y1d); - setIntBounds(bounds); // sets x, y, width, height - x1R = x1d - bounds.x; - y1R = y1d - bounds.y; - x2R = x2d - bounds.x; - y2R = y2d - bounds.y; - x1 = (int) x1d; - y1 = (int) y1d; - x2 = (int) x2d; - y2 = (int) y2d; - this.bounds = bounds; - } - - /** Draws this line on the image. */ - public void draw(Graphics g) { - Color color = strokeColor != null ? strokeColor : ROIColor; - boolean isActiveOverlayRoi = !overlay && isActiveOverlayRoi(); - mag = getMagnification(); - if (isActiveOverlayRoi) { - if (color == Color.cyan) - color = Color.magenta; - else - color = Color.cyan; - } - g.setColor(color); - x1d = getXBase() + x1R; - y1d = getYBase() + y1R; - x2d = getXBase() + x2R; - y2d = getYBase() + y2R; - x1 = (int) x1d; - y1 = (int) y1d; - x2 = (int) x2d; - y2 = (int) y2d; - int sx1 = screenXD(x1d); - int sy1 = screenYD(y1d); - int sx2 = screenXD(x2d); - int sy2 = screenYD(y2d); - int sx3 = sx1 + (sx2 - sx1) / 2; - int sy3 = sy1 + (sy2 - sy1) / 2; - Graphics2D g2d = (Graphics2D) g; - setRenderingHint(g2d); - boolean cbar = overlay && mag < 1.0 && Math.abs(getStrokeWidth() - CalibrationBar.STROKE_WIDTH) < 0.0001; - if (stroke != null && !isActiveOverlayRoi && !cbar) - g2d.setStroke(getScaledStroke()); - else if (cbar) - g2d.setStroke(onePixelWide); - if (wideLine && !isActiveOverlayRoi && !cbar) { - double dx = sx2 - sx1; - double dy = sy2 - sy1; - double len = length(dx, dy); - dx *= 0.5 * mag / len; // half-pixel extension, corresponding to getFloatPolygon or convertLineToArea - dy *= 0.5 * mag / len; - g2d.draw(new Line2D.Double(sx1 - dx, sy1 - dy, sx2 + dx, sy2 + dy)); - } else - g.drawLine(sx1, sy1, sx2, sy2); - if (wideLine && !overlay) { - g2d.setStroke(onePixelWide); - g.setColor(getColor()); - g.drawLine(sx1, sy1, sx2, sy2); - } - if (!overlay) { - handleColor = strokeColor != null ? strokeColor : ROIColor; - drawHandle(g, sx1, sy1); - handleColor = Color.white; - drawHandle(g, sx2, sy2); - drawHandle(g, sx3, sy3); - } - if (state != NORMAL) - showStatus(); - if (updateFullWindow) { - updateFullWindow = false; - imp.draw(); - } - } - - public void showStatus() { - IJ.showStatus(imp.getLocationAsString((int) Math.round(x2d), (int) Math.round(y2d)) + ", angle=" + IJ.d2s(getAngle()) + ", length=" + IJ.d2s(getLength())); - } - - public double getAngle() { - return getFloatAngle(x1d, y1d, x2d, y2d); - } - - /** Returns the length of this line. */ - public double getLength() { - if (imp == null || IJ.altKeyDown()) - return getRawLength(); - else { - Calibration cal = imp.getCalibration(); - return Math.sqrt(sqr((x2d - x1d) * cal.pixelWidth) + sqr((y2d - y1d) * cal.pixelHeight)); - } - } - - /** Returns the length of this line in pixels. */ - public double getRawLength() { - return Math.sqrt(sqr(x2d - x1d) + sqr(y2d - y1d)); - } - - /** - * Returns the pixel values along this line. The line roi must have an - * associated ImagePlus. - */ - public double[] getPixels() { - double[] profile; - if (getStrokeWidth() <= 1) { - ImageProcessor ip = imp.getProcessor(); - profile = ip.getLine(x1d, y1d, x2d, y2d); - } else { - Straightener s = new Straightener(); - ImageProcessor ip2 = s.straightenLine(imp, this, 0); - if (ip2 == null) - return new double[0]; - int width = ip2.getWidth(); - int height = ip2.getHeight(); - if (ip2 instanceof FloatProcessor) - return ProfilePlot.getColumnAverageProfile(new Rectangle(0, 0, width, height), ip2); - profile = new double[width]; - double[] aLine; - ip2.setInterpolate(false); - for (int y = 0; y < height; y++) { - aLine = ip2.getLine(0, y, width - 1, y); - for (int i = 0; i < width; i++) - profile[i] += aLine[i]; - } - for (int i = 0; i < width; i++) - profile[i] /= height; - } - return profile; - } - - /** Returns, as a Polygon, the two points that define this line. */ - public Polygon getPoints() { - Polygon p = new Polygon(); - p.addPoint((int) Math.round(x1d), (int) Math.round(y1d)); - p.addPoint((int) Math.round(x2d), (int) Math.round(y2d)); - return p; - } - - /** Returns, as a FloatPolygon, the two points that define this line. */ - public FloatPolygon getFloatPoints() { - FloatPolygon p = new FloatPolygon(); - p.addPoint((float) x1d, (float) y1d); - p.addPoint((float) x2d, (float) y2d); - return p; - } - - /** - * If the width of this line is less than or equal to one, returns the starting - * and ending coordinates as a 2-point Polygon, or, if the width is greater than - * one, returns an outline of the line as a 4-point Polygon. - * - * @see #getFloatPolygon - * @see #getPoints - */ - public Polygon getPolygon() { - FloatPolygon p = getFloatPolygon(); - return new Polygon(toIntR(p.xpoints), toIntR(p.ypoints), p.npoints); - } - - /** - * If the width of this line is less than or equal to one, returns the starting - * and ending coordinates as a 2-point FloatPolygon, or, if the width is greater - * than one, returns an outline of the line as a 4-point FloatPolygon. - * - * @see #getFloatPoints - */ - public FloatPolygon getFloatPolygon() { - return getFloatPolygon(getStrokeWidth()); - } - - /** Obsolete */ - public FloatPolygon getFloatPolygon(double strokeWidth) { - FloatPolygon p = new FloatPolygon(); - if (strokeWidth <= 1) { - p.addPoint((float) x1d, (float) y1d); - p.addPoint((float) x2d, (float) y2d); - } else { - double dx = x2d - x1d; - double dy = y2d - y1d; - double len = length(dx, dy); - dx *= 0.5 / len; // half unit vector in the direction of the line - dy *= 0.5 / len; // when rotated 90 deg cw, this yields the vector (-dx, dy) - double p1x = x1d + 0.5 - dx + dy * strokeWidth; // 0.5 pxl shift: area vs. line coordinate convention - double p1y = y1d + 0.5 - dy - dx * strokeWidth; - double p2x = x1d + 0.5 - dx - dy * strokeWidth; - double p2y = y1d + 0.5 - dy + dx * strokeWidth; - double p3x = x2d + 0.5 + dx - dy * strokeWidth; - double p3y = y2d + 0.5 + dy + dx * strokeWidth; - double p4x = x2d + 0.5 + dx + dy * strokeWidth; - double p4y = y2d + 0.5 + dy - dx * strokeWidth; - p.addPoint((float) p1x, (float) p1y); - p.addPoint((float) p2x, (float) p2y); - p.addPoint((float) p3x, (float) p3y); - p.addPoint((float) p4x, (float) p4y); - } - return p; - } - - /** - * Returns the number of points in this selection; equivalent to - * getPolygon().npoints. - */ - public int size() { - return getStrokeWidth() <= 1 ? 2 : 4; - } - - /** - * If the width of this line is less than or equal to one, draws the line. - * Otherwise draws the outline of the area of this line. - */ - public void drawPixels(ImageProcessor ip) { - boolean fillLine = getStrokeWidth() > 1 && getWidth() <= 1; - if (fillLine) - ip.setLineWidth((int) Math.round(getStrokeWidth())); - else - ip.setLineWidth(1); - double x = getXBase(); - double y = getYBase(); - x1d = getXBase() + x1R; - y1d = getYBase() + y1R; - x2d = getXBase() + x2R; - y2d = getYBase() + y2R; - if (getStrokeWidth() <= 1 || fillLine) { - ip.moveTo((int) Math.round(x1d), (int) Math.round(y1d)); - ip.lineTo((int) Math.round(x2d), (int) Math.round(y2d)); - } else { - Polygon p = getPolygon(); - ip.drawPolygon(p); - updateFullWindow = true; - } - } - - public boolean contains(int x, int y) { - if (getStrokeWidth() > 1) { - if ((x == x1 && y == y1) || (x == x2 && y == y2)) - return true; - else - return getPolygon().contains(x, y); - } else - return false; - } - - protected void handleMouseDown(int sx, int sy) { - super.handleMouseDown(sx, sy); - startxd = ic.offScreenXD(sx); - startyd = ic.offScreenYD(sy); - } - - /** - * Returns a handle number if the specified screen coordinates are inside or - * near a handle, otherwise returns -1. - */ - public int isHandle(int sx, int sy) { - int size = HANDLE_SIZE + 5; - if (getStrokeWidth() > 1) - size += (int) Math.log(getStrokeWidth()); - int halfSize = size / 2; - int sx1 = screenXD(getXBase() + x1R) - halfSize; - int sy1 = screenYD(getYBase() + y1R) - halfSize; - int sx2 = screenXD(getXBase() + x2R) - halfSize; - int sy2 = screenYD(getYBase() + y2R) - halfSize; - int sx3 = sx1 + (sx2 - sx1) / 2 - 1; - int sy3 = sy1 + (sy2 - sy1) / 2 - 1; - if (sx >= sx1 && sx <= sx1 + size && sy >= sy1 && sy <= sy1 + size) - return 0; - if (sx >= sx2 && sx <= sx2 + size && sy >= sy2 && sy <= sy2 + size) - return 1; - if (sx >= sx3 && sx <= sx3 + size + 2 && sy >= sy3 && sy <= sy3 + size + 2) - return 2; - return -1; - } - - /** - * Returns the default line width. Use getStrokeWidth()to get the width of a - * Line instance. - * - * @see #getStrokeWidth - */ - public static int getWidth() { - return lineWidth; - } - - /** - * Sets the default line width. Use setStrokeWidth() to set the width of a Line - * instance. - * - * @see #setStrokeWidth - */ - public static void setWidth(int w) { - if (w < 1) - w = 1; - int max = 500; - if (w > max) { - ImagePlus imp2 = WindowManager.getCurrentImage(); - if (imp2 != null) { - max = Math.max(max, imp2.getWidth()); - max = Math.max(max, imp2.getHeight()); - } - if (w > max) - w = max; - } - lineWidth = w; - widthChanged = true; - } - - /* Sets the width of this line. */ - public void setStrokeWidth(float width) { - super.setStrokeWidth(width); - if (getStrokeColor() == Roi.getColor()) - wideLine = true; - } - - protected int clipRectMargin() { - return 4; - } - - /** Nudge end point of line by one pixel. */ - public void nudgeCorner(int key) { - if (ic == null) - return; - double inc = 1.0 / ic.getMagnification(); - switch (key) { - case KeyEvent.VK_UP: - y2R -= inc; - break; - case KeyEvent.VK_DOWN: - y2R += inc; - break; - case KeyEvent.VK_LEFT: - x2R -= inc; - break; - case KeyEvent.VK_RIGHT: - x2R += inc; - break; - } - grow(screenXD(x + x2R), screenYD(y + y2R)); - notifyListeners(RoiListener.MOVED); - showStatus(); - } - - /** Always returns true. */ - public boolean subPixelResolution() { - return true; - } - - public void setLocation(int x, int y) { - setLocation((double) x, (double) y); - } - - /** - * Sets the x coordinate of the leftmost and y coordinate of the topmost end - * point - */ - public void setLocation(double x, double y) { - updateCoordinates(x + x1R, y + y1R, x + x2R, y + y2R); - } - - public FloatPolygon getRotationCenter() { - double xcenter = x1d + (x2d - x1d) / 2.0; - double ycenter = y1d + (y2d - y1d) / 2.0; - FloatPolygon p = new FloatPolygon(); - p.addPoint(xcenter, ycenter); - return p; - } - - /** - * Dedicated point iterator for thin lines. The iterator is based on (an - * improved version of) the algorithm used by the original method - * {@code ImageProcessor.getLine(double, double, double, double)}. Improvements - * are (a) that the endpoint is drawn too and (b) every line point is visited - * only once, duplicates are skipped. - * - * Author: Wilhelm Burger (04/2017) - */ - public static class PointIterator implements Iterator { - private double x1, y1; - private final int n; - private final double xinc, yinc; - private double x, y; - private int u, v; - private int u_prev, v_prev; - private int i; - - public PointIterator(Line line) { - this(line.x1d, line.y1d, line.x2d, line.y2d); - } - - public PointIterator(double x1, double y1, double x2, double y2) { - this.x1 = x1; - this.y1 = y1; - double dx = x2 - x1; - double dy = y2 - y1; - this.n = (int) Math.ceil(Math.sqrt(dx * dx + dy * dy)); - this.xinc = dx / n; - this.yinc = dy / n; - x = x1; - y = y1; - u = (int) Math.round(x - 0.5); - v = (int) Math.round(y - 0.5); - u_prev = Integer.MIN_VALUE; - v_prev = Integer.MIN_VALUE; - i = 0; - } - - @Override - public boolean hasNext() { - return i <= n; // needs to be '<=' to include last segment (point)! - } - - @Override - public Point next() { - if (i > n) - throw new NoSuchElementException(); - Point p = new Point(u, v); // the current (next) point - moveToNext(); - return p; - } - - // move to next point by skipping duplicate points - private void moveToNext() { - do { - i = i + 1; - x = x1 + i * xinc; - y = y1 + i * yinc; - u_prev = u; - v_prev = v; - u = (int) Math.round(x - 0.5); - v = (int) Math.round(y - 0.5); - } while (i <= n && u == u_prev && v == v_prev); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - @Override - public Iterator iterator() { - if (getStrokeWidth() <= 1.0) - return new PointIterator(this); // use the specific thin-line iterator - else - return super.iterator(); // fall back on Roi's iterator - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/MessageDialog.java b/com.eco.bio7.image/src/ij/gui/MessageDialog.java deleted file mode 100644 index 3f02e1b55..000000000 --- a/com.eco.bio7.image/src/ij/gui/MessageDialog.java +++ /dev/null @@ -1,62 +0,0 @@ -/*Message Dialog copied from the Bio7 project. - * Author: Marcel Austenfeld*/ -package ij.gui; - -import java.awt.Frame; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.MessageBox; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; - -/* Changed for Bio7! A modal dialog base on SWT as a replacement for the ImageJ message dialog! */ - -public class MessageDialog { - protected MultiLineLabel label; - private boolean escapePressed; - protected int result; - - public MessageDialog(Frame parent, String title, String message) { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - public void run() { - MessageBox messageBox = new MessageBox(getShell(), - - SWT.ICON_WARNING); - - messageBox.setText(title); - messageBox.setMessage(message); - result = messageBox.open(); - if (result == SWT.OK) { - escapePressed = true; - } - } - }); - - } - - /** - * Returns a platform shell for dialogs, etc. - * - * @return a shell - */ - public static Shell getShell() { - IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (window == null) { - IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); - if (windows.length > 0) { - return windows[0].getShell(); - } - } else { - return window.getShell(); - } - return null; - } - - public boolean escapePressed() { - return escapePressed; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/MultiLineLabel.java b/com.eco.bio7.image/src/ij/gui/MultiLineLabel.java deleted file mode 100644 index 4aed7d6e9..000000000 --- a/com.eco.bio7.image/src/ij/gui/MultiLineLabel.java +++ /dev/null @@ -1,111 +0,0 @@ -package ij.gui; -import java.awt.*; -import java.util.*; - -import javax.swing.JPanel; - -/**Custom component for displaying multiple lines. Based on - MultiLineLabel class from "Java in a Nutshell" by David Flanagan.*/ -public class MultiLineLabel extends JPanel { - String[] lines; - int num_lines; - int margin_width = 6; - int margin_height = 6; - int line_height; - int line_ascent; - int[] line_widths; - int min_width, max_width; - - // Breaks the specified label up into an array of lines. - public MultiLineLabel(String label) { - init(label); - } - - public MultiLineLabel(String label, int minimumWidth) { - init(label); - min_width = minimumWidth; - } - - private void init(String text) { - StringTokenizer t = new StringTokenizer(text, "\n"); - num_lines = t.countTokens(); - lines = new String[num_lines]; - line_widths = new int[num_lines]; - for (int i=0; i max_width) max_width = line_widths[i]; - } - } - - - public void setText(String text) { - init(text); - measure(); - repaint(); - } - - public void setFont(Font f) { - super.setFont(f); - measure(); - repaint(); - } - - - // This method is invoked after our Canvas is first created - // but before it can actually be displayed. After we've - // invoked our superclass's addNotify() method, we have font - // metrics and can successfully call measure() to figure out - // how big the label is. - public void addNotify() { - super.addNotify(); - measure(); - } - - - // Called by a layout manager when it wants to - // know how big we'd like to be. - public Dimension getPreferredSize() { - return new Dimension(Math.max(min_width, max_width + 2*margin_width), - num_lines * line_height + 2*margin_height); - } - - - // Called when the layout manager wants to know - // the bare minimum amount of space we need to get by. - public Dimension getMinimumSize() { - return new Dimension(Math.max(min_width, max_width), num_lines * line_height); - } - - // Draws the label - public void paintComponent(Graphics g) { - super.paintComponent(g); - int x, y; - Dimension d = this.getSize(); - if (!ij.IJ.isLinux()) setAntialiasedText(g); - y = line_ascent + (d.height - num_lines * line_height)/2; - for(int i = 0; i < num_lines; i++, y += line_height) { - x = margin_width; - g.drawString(lines[i], x, y); - } - } - - void setAntialiasedText(Graphics g) { - Graphics2D g2d = (Graphics2D)g; - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/NewImage.java b/com.eco.bio7.image/src/ij/gui/NewImage.java deleted file mode 100644 index 2075ac427..000000000 --- a/com.eco.bio7.image/src/ij/gui/NewImage.java +++ /dev/null @@ -1,466 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.image.*; -import java.io.*; -import java.awt.event.*; -import java.util.*; -import ij.*; -import ij.process.*; - -/** New image dialog box plus several static utility methods for creating images.*/ -public class NewImage { - - public static final int GRAY8=0, GRAY16=1, GRAY32=2, RGB=3; - public static final int FILL_BLACK=1, FILL_RAMP=2, FILL_NOISE=3, FILL_RANDOM=3, - FILL_WHITE=4, CHECK_AVAILABLE_MEMORY=8, SIGNED_INT=16; - private static final int OLD_FILL_WHITE=0; - - static final String TYPE = "new.type"; - static final String FILL = "new.fill"; - static final String WIDTH = "new.width"; - static final String HEIGHT = "new.height"; - static final String SLICES = "new.slices"; - - private static String name = "Untitled"; - private static int staticWidth = Prefs.getInt(WIDTH, 512); - private static int staticHeight = Prefs.getInt(HEIGHT, 512); - private static int staticSlices = Prefs.getInt(SLICES, 1); - private static int staticType = Prefs.getInt(TYPE, GRAY8); - private static int staticFillWith = Prefs.getInt(FILL, FILL_BLACK); - private static String[] types = {"8-bit", "16-bit", "32-bit", "RGB"}; - private static String[] fill = {"White", "Black", "Ramp", "Noise"}; - private int gwidth, gheight, gslices, gtype, gfill; - - public NewImage() { - openImage(); - } - - static boolean createStack(ImagePlus imp, ImageProcessor ip, int nSlices, int type, int options) { - int fill = getFill(options); - int width = imp.getWidth(); - int height = imp.getHeight(); - long bytesPerPixel = 1; - if (type==GRAY16) bytesPerPixel = 2; - else if (type==GRAY32||type==RGB) bytesPerPixel = 4; - long size = (long)width*height*nSlices*bytesPerPixel; - int sizeThreshold = fill==FILL_NOISE?10:250; - boolean bigStack = size/(1024*1024)>=sizeThreshold; - String size2 = size/(1024*1024)+"MB ("+width+"x"+height+"x"+nSlices+")"; - if ((options&CHECK_AVAILABLE_MEMORY)!=0) { - long max = IJ.maxMemory(); // - 100*1024*1024; - if (max>0) { - long inUse = IJ.currentMemory(); - long available = max - inUse; - if (size>available) - System.gc(); - inUse = IJ.currentMemory(); - available = max-inUse; - if (size>available) { - IJ.error("Insufficient Memory", "There is not enough free memory to allocate a \n" - + size2+" stack.\n \n" - + "Memory available: "+available/(1024*1024)+"MB\n" - + "Memory in use: "+IJ.freeMemory()+"\n \n" - + "More information can be found in the \"Memory\"\n" - + "sections of the ImageJ installation notes at\n" - + "\""+IJ.URL2+"/docs/install/\"."); - return false; - } - } - } - ImageStack stack = imp.createEmptyStack(); - boolean signedInt = (options&SIGNED_INT)!=0; - if (type==RGB && signedInt) - stack.setOptions("32-bit int"); - int inc = nSlices/40; - if (inc<1) inc = 1; - if (bigStack) - IJ.showStatus("Allocating "+size2+". Press 'Esc' to abort."); - IJ.resetEscape(); - try { - stack.addSlice(null, ip); - for (int i=2; i<=nSlices; i++) { - if ((i%inc)==0 && bigStack) - IJ.showProgress(i, nSlices); - Object pixels2 = null; - switch (type) { - case GRAY8: pixels2 = new byte[width*height]; - if (fill==FILL_NOISE) - fillNoiseByte(new ByteProcessor(width,height,(byte[])pixels2)); - break; - case GRAY16: pixels2 = new short[width*height]; - if (fill==FILL_NOISE) - fillNoiseShort(new ShortProcessor(width,height,(short[])pixels2,null)); - break; - case GRAY32: pixels2 = new float[width*height]; - if (fill==FILL_NOISE) - fillNoiseFloat(new FloatProcessor(width,height,(float[])pixels2,null)); - break; - case RGB: pixels2 = new int[width*height]; - if (fill==FILL_NOISE) { - if (signedInt) - fillNoiseInt(new IntProcessor(width,height,(int[])pixels2)); - else - fillNoiseRGB(new ColorProcessor(width,height,(int[])pixels2), false); - } - break; - } - if (fill==FILL_WHITE||fill==FILL_RAMP) - System.arraycopy(ip.getPixels(), 0, pixels2, 0, width*height); - stack.addSlice(null, pixels2); - if (IJ.escapePressed()) {IJ.beep(); break;}; - } - } - catch(OutOfMemoryError e) { - IJ.outOfMemory(imp.getTitle()); - stack.trim(); - } - IJ.showStatus(""); - if (bigStack) - IJ.showProgress(nSlices, nSlices); - if (stack.size()>1) - imp.setStack(null, stack); - return true; - } - - static int getFill(int options) { - int fill = options&7; - if (fill==OLD_FILL_WHITE) - fill = FILL_WHITE; - if (fill==7||fill==6||fill==5) - fill = FILL_BLACK; - return fill; - } - - public static ImagePlus createByteImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - byte[] pixels = new byte[size]; - ImageProcessor ip = new ByteProcessor(width, height, pixels, null); - switch (fill) { - case FILL_WHITE: - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, GRAY8, options); - if (!ok) imp = null; - } - return imp; - } - - private static void fillNoiseByte(ImageProcessor ip) { - ip.add(127); - ip.noise(31); - } - - public static ImagePlus createRGBImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - int[] pixels = new int[size]; - ColorProcessor ip = new ColorProcessor(width, height, pixels); - switch (fill) { - case FILL_WHITE: - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, RGB, options); - if (!ok) imp = null; - } - return imp; - } - - public static ImagePlus createIntImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - int[] pixels = new int[size]; - IntProcessor ip = new IntProcessor(width, height, pixels); - switch (fill) { - case FILL_RAMP: - int[] ramp = new int[width]; - double inc = ((double)Integer.MAX_VALUE - (double)Integer.MIN_VALUE)/width; - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, RGB, options); - if (!ok) imp = null; - } - return imp; - } - - private static void fillNoiseRGB(ColorProcessor ip, boolean sp) { - int width = ip.getWidth(); - int height = ip.getHeight(); - ByteProcessor rr = new ByteProcessor(width, height); - ByteProcessor gg = new ByteProcessor(width, height); - ByteProcessor bb = new ByteProcessor(width, height); - if (sp) IJ.showProgress(0.0); - rr.add(127); if (sp) IJ.showProgress(0.05); - gg.add(127); if (sp) IJ.showProgress(0.10); - bb.add(127); if (sp) IJ.showProgress(0.15); - rr.noise(31); if (sp) IJ.showProgress(0.40); - gg.noise(31); if (sp) IJ.showProgress(0.65); - bb.noise(31); if (sp) IJ.showProgress(0.90); - if (sp) IJ.showProgress(1.0); - ip.setChannel(1,rr); ip.setChannel(2,gg); ip.setChannel(3,bb); - } - - private static void fillNoiseInt(ImageProcessor ip) { - Random rnd = new Random(); - int n = ip.getPixelCount(); - double std =((double)Integer.MAX_VALUE - (double)Integer.MIN_VALUE)*0.12; - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, GRAY16, options); - if (!ok) imp = null; - } - imp.getProcessor().setMinAndMax(0, 65535); // default display range - return imp; - } - - private static void fillNoiseShort(ImageProcessor ip) { - ip.add(32767); - ip.noise(7940); - } - - /** - * @deprecated - * Short images are always unsigned. - */ - public static ImagePlus createUnsignedShortImage(String title, int width, int height, int slices, int options) { - return createShortImage(title, width, height, slices, options); - } - - public static ImagePlus createFloatImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - float[] pixels = new float[size]; - ImageProcessor ip = new FloatProcessor(width, height, pixels, null); - switch (fill) { - case FILL_WHITE: case FILL_BLACK: - break; - case FILL_RAMP: - float[] ramp = new float[width]; - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, GRAY32, options); - if (!ok) imp = null; - } - if (fill!=FILL_NOISE) - imp.getProcessor().setMinAndMax(0.0, 1.0); // default display range - return imp; - } - - private static void fillNoiseFloat(ImageProcessor ip) { - ip.noise(1); - } - - private static int getSize(int width, int height) { - long size = (long)width*height; - if (size>Integer.MAX_VALUE) { - IJ.error("Image is too large. ImageJ does not support\nsingle images larger than 2 gigapixels."); - return -1; - } else - return (int)size; - } - - public static void open(String title, int width, int height, int nSlices, int type, int options) { - int bitDepth = 8; - if (type==GRAY16) bitDepth = 16; - else if (type==GRAY32) bitDepth = 32; - else if (type==RGB) bitDepth = 24; - long startTime = System.currentTimeMillis(); - ImagePlus imp = createImage(title, width, height, nSlices, bitDepth, options); - if (imp!=null) { - WindowManager.checkForDuplicateName = true; - imp.show(); - IJ.showStatus(IJ.d2s(((System.currentTimeMillis()-startTime)/1000.0),2)+" seconds"); - } - } - - public static ImagePlus createImage(String title, int width, int height, int nSlices, int bitDepth, int options) { - ImagePlus imp = null; - switch (bitDepth) { - case 8: imp = createByteImage(title, width, height, nSlices, options); break; - case 16: imp = createShortImage(title, width, height, nSlices, options); break; - case 32: imp = createFloatImage(title, width, height, nSlices, options); break; - case 24: - if ((options&SIGNED_INT)!=0) - imp = createIntImage(title, width, height, nSlices, options); - else - imp = createRGBImage(title, width, height, nSlices, options); - break; - default: throw new IllegalArgumentException("Invalid bitDepth: "+bitDepth); - } - return imp; - } - - boolean showDialog() { - if (staticTypeRGB) - staticType = GRAY8; - if (staticFillWithFILL_NOISE) - staticFillWith = FILL_WHITE; - GenericDialog gd = new GenericDialog("New Image..."); - gd.addStringField("Name:", name, 12); - gd.addChoice("Type:", types, types[staticType]); - gd.addChoice("Fill with:", fill, fill[staticFillWith]); - gd.addNumericField("Width:", staticWidth, 0, 5, "pixels"); - gd.addNumericField("Height:", staticHeight, 0, 5, "pixels"); - gd.addNumericField("Slices:", staticSlices, 0, 5, ""); - gd.showDialog(); - if (gd.wasCanceled()) - return false; - name = gd.getNextString(); - String s = gd.getNextChoice(); - if (s.startsWith("8")) - gtype = GRAY8; - else if (s.startsWith("16")) - gtype = GRAY16; - else if (s.endsWith("RGB") || s.endsWith("rgb")) - gtype = RGB; - else - gtype = GRAY32; - gfill = gd.getNextChoiceIndex(); - gwidth = (int)gd.getNextNumber(); - gheight = (int)gd.getNextNumber(); - gslices = (int)gd.getNextNumber(); - if (gslices<1) gslices = 1; - if (gwidth<1 || gheight<1) { - IJ.error("New Image", "Width and height must be >0"); - return false; - } else { - if (!IJ.isMacro()) { - staticWidth = gwidth; - staticHeight = gheight; - staticSlices = gslices; - staticType = gtype; - staticFillWith = gfill; - } - return true; - } - } - - void openImage() { - if (!showDialog()) - return; - try { - open(name, gwidth, gheight, gslices, gtype, gfill); - } catch(OutOfMemoryError e) { - IJ.outOfMemory("New Image..."); - } - } - - /** Called when ImageJ quits. */ - public static void savePreferences(Properties prefs) { - prefs.put(TYPE, Integer.toString(staticType)); - prefs.put(FILL, Integer.toString(staticFillWith)); - prefs.put(WIDTH, Integer.toString(staticWidth)); - prefs.put(HEIGHT, Integer.toString(staticHeight)); - prefs.put(SLICES, Integer.toString(staticSlices)); - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/NonBlockingGenericDialog.java b/com.eco.bio7.image/src/ij/gui/NonBlockingGenericDialog.java deleted file mode 100644 index 44381da6d..000000000 --- a/com.eco.bio7.image/src/ij/gui/NonBlockingGenericDialog.java +++ /dev/null @@ -1,104 +0,0 @@ -package ij.gui; -import ij.*; -import java.awt.event.*; -import java.awt.EventQueue; -import java.awt.GraphicsEnvironment; -import java.awt.Frame; - -/** This is an extension of GenericDialog that is non-modal. - * @author Johannes Schindelin - */ -public class NonBlockingGenericDialog extends GenericDialog { - ImagePlus imp; //when non-null, this dialog gets closed when the image is closed - WindowListener windowListener; //checking for whether the associated window gets closed - - public NonBlockingGenericDialog(String title) { - super(title, null); - setModal(false); - IJ.protectStatusBar(false); - instance = this; - } - - public synchronized void showDialog() { - super.showDialog(); - if (isMacro()) - return; - if (EventQueue.isDispatchThread()) - throw new RuntimeException("To avoid a deadlock, NonBlockingGenericDialog must not be called from the Event Queue"); - if (!IJ.macroRunning()) { // add to Window menu on event dispatch thread - final NonBlockingGenericDialog thisDialog = this; - EventQueue.invokeLater(new Runnable() { - public void run() { - WindowManager.addWindow(thisDialog); - } - }); - } - if (imp != null) { - ImageWindow win = imp.getWindow(); - if (win != null) { //when the associated image closes, also close the dialog - final NonBlockingGenericDialog gd = this; - windowListener = new WindowAdapter() { - public void windowClosed(WindowEvent e) { - cancelDialogAndClose(); - } - }; - win.addWindowListener(windowListener); - } - } - try { - wait(); - } catch (InterruptedException e) { } - } - - /** Gets called if the associated image window is closed */ - private void cancelDialogAndClose() { - super.windowClosing(null); // sets wasCanceled=true and does dispose() - } - - public synchronized void actionPerformed(ActionEvent e) { - super.actionPerformed(e); - if (!isVisible()) - notify(); - } - - public synchronized void keyPressed(KeyEvent e) { - super.keyPressed(e); - if (wasOKed() || wasCanceled()) - notify(); - } - - public synchronized void windowClosing(WindowEvent e) { - super.windowClosing(e); - if (wasOKed() || wasCanceled()) - notify(); - } - - public void dispose() { - super.dispose(); - WindowManager.removeWindow(this); - if (imp != null) { - ImageWindow win = imp.getWindow(); - if (win != null && windowListener != null) - win.removeWindowListener(windowListener); - } - } - - /** Obsolete, replaced by GUI.newNonBlockingDialog(String,ImagePlus). */ - public static GenericDialog newDialog(String title, ImagePlus imp) { - return GUI.newNonBlockingDialog(title, imp); - } - - /** Obsolete, replaced by GUI.newNonBlockingDialog(String). */ - public static GenericDialog newDialog(String title) { - return GUI.newNonBlockingDialog(title); - } - - /** Put the dialog into the foreground when the image we work on gets into the foreground */ - @Override - public void windowActivated(WindowEvent e) { - if ((e.getWindow() instanceof ImageWindow) && e.getOppositeWindow()!=this) - toFront(); - WindowManager.setWindow(this); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/OvalRoi.java b/com.eco.bio7.image/src/ij/gui/OvalRoi.java deleted file mode 100644 index fc1770808..000000000 --- a/com.eco.bio7.image/src/ij/gui/OvalRoi.java +++ /dev/null @@ -1,440 +0,0 @@ -package ij.gui; -import java.awt.*; -import java.awt.image.*; -import java.awt.geom.*; -import ij.*; -import ij.process.*; -import ij.measure.Calibration; - -/** Oval region of interest */ -public class OvalRoi extends Roi { - - /** Creates an OvalRoi.*/ - public OvalRoi(int x, int y, int width, int height) { - super(x, y, width, height); - type = OVAL; - } - - /** Creates an OvalRoi using double arguments.*/ - public OvalRoi(double x, double y, double width, double height) { - super(x, y, width, height); - type = OVAL; - } - - /** Creates an OvalRoi. */ - public static OvalRoi create(double x, double y, double width, double height) { - return new OvalRoi(x, y, width, height); - } - - /** Starts the process of creating a user-defined OvalRoi. */ - public OvalRoi(int x, int y, ImagePlus imp) { - super(x, y, imp); - type = OVAL; - } - - /** @deprecated */ - public OvalRoi(int x, int y, int width, int height, ImagePlus imp) { - this(x, y, width, height); - setImage(imp); - } - - /** Feret (caliper width) values, see ij.gui.Roi.getFeretValues(). - * The superclass method of calculating this via the convex hull is less accurate for the MinFeret - * because it does not get the exact minor axis. */ - public double[] getFeretValues() { - double[] a = new double[FERET_ARRAYSIZE]; - double pw=1.0, ph=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - pw = cal.pixelWidth; - ph = cal.pixelHeight; - } - boolean highAspect = ph*height > pw*width; - a[0] = highAspect ? height*ph : width*pw; // (max)Feret - a[1] = highAspect ? 90.0 : 0.0; // (max)Feret angle - a[2] = highAspect ? width*pw : height*ph; // MinFeret - a[3] = (x + (highAspect ? 0.5*width : 0)) * pw; //FeretX scaled - a[4] = (y + (highAspect ? height : 0.5*height)) * ph;//FeretY scaled - int i = FERET_ARRAY_POINTOFFSET; - a[i++] = x + (highAspect ? 0.5*width : 0); //MaxFeret start - a[i++] = y + (highAspect ? height : 0.5*height); - a[i++] = x + (highAspect ? 0.5*width : width); //MaxFeret end - a[i++] = y + (highAspect ? 0 : 0.5*height); - a[i++] = x + (highAspect ? 0 : 0.5*width); //MinFeret start - a[i++] = y + (highAspect ? 0.5*height : height); - a[i++] = x + (highAspect ? width : 0.5*width); //MinFeret end - a[i++] = y + (highAspect ? 0.5*height : 0); - return a; - } - - protected void moveHandle(int sx, int sy) { - double asp; - if (clipboard!=null) return; - int ox = offScreenX(sx); - int oy = offScreenY(sy); - //IJ.log("moveHandle: "+activeHandle+" "+ox+" "+oy); - int x1=x, y1=y, x2=x+width, y2=y+height, xc=x+width/2, yc=y+height/2; - int w2 = (int)(0.14645*width); - int h2 = (int)(0.14645*height); - if (width > 7 && height > 7) { - asp = (double)width/(double)height; - asp_bk = asp; - } else - asp = asp_bk; - switch (activeHandle) { - case 0: x=ox-w2; y=oy-h2; break; - case 1: y=oy; break; - case 2: x2=ox+w2; y=oy-h2; break; - case 3: x2=ox; break; - case 4: x2=ox+w2; y2=oy+h2; break; - case 5: y2=oy; break; - case 6: x=ox-w2; y2=oy+h2; break; - case 7: x=ox; break; - } - //if (x<0) x=0; if (y<0) y=0; - if (x=x2) { - width=1; - x=x2=xc; - } - if (y>=y2) { - height=1; - y=y2=yc; - } - - } - - if (constrain) { - if (activeHandle==1 || activeHandle==5) width=height; - else height=width; - - if (x>=x2) { - width=1; - x=x2=xc; - } - if (y>=y2) { - height=1; - y=y2=yc; - } - switch(activeHandle){ - case 0: - x=x2-width; - y=y2-height; - break; - case 1: - x=xc-width/2; - y=y2-height; - break; - case 2: - y=y2-height; - break; - case 3: - y=yc-height/2; - break; - case 5: - x=xc-width/2; - break; - case 6: - x=x2-width; - break; - case 7: - y=yc-height/2; - x=x2-width; - break; - } - if (center){ - x=xc-width/2; - y=yc-height/2; - } - } - - if (aspect && !constrain) { - if (activeHandle==1 || activeHandle==5) width=(int)Math.rint((double)height*asp); - else height=(int)Math.rint((double)width/asp); - - switch (activeHandle) { - case 0: - x=x2-width; - y=y2-height; - break; - case 1: - x=xc-width/2; - y=y2-height; - break; - case 2: - y=y2-height; - break; - case 3: - y=yc-height/2; - break; - case 5: - x=xc-width/2; - break; - case 6: - x=x2-width; - break; - case 7: - y=yc-height/2; - x=x2-width; - break; - } - if (center) { - x=xc-width/2; - y=yc-height/2; - } - // Attempt to preserve aspect ratio when roi very small: - if (width<8) { - if (width<1) width = 1; - height=(int)Math.rint((double)width/asp_bk); - } - if (height<8) { - if (height<1) height =1; - width=(int)Math.rint((double)height*asp_bk); - } - } - - updateClipRect(); - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX=x; oldY=y; - oldWidth=width; oldHeight=height; - cachedMask = null; - bounds = null; - } - - public void draw(Graphics g) { - Color color = strokeColor!=null? strokeColor:ROIColor; - if (fillColor!=null) color = fillColor; - g.setColor(color); - mag = getMagnification(); - int sw = (int)(width*mag); - int sh = (int)(height*mag); - int sx1 = screenX(x); - int sy1 = screenY(y); - if (subPixelResolution() && bounds!=null) { - sw = (int)(bounds.width*mag); - sh = (int)(bounds.height*mag); - sx1 = screenXD(bounds.x); - sy1 = screenYD(bounds.y); - } - int sw2 = (int)(0.14645*width*mag); - int sh2 = (int)(0.14645*height*mag); - int sx2 = sx1+sw/2; - int sy2 = sy1+sh/2; - int sx3 = sx1+sw; - int sy3 = sy1+sh; - Graphics2D g2d = (Graphics2D)g; - if (stroke!=null) - g2d.setStroke(getScaledStroke()); - setRenderingHint(g2d); - if (fillColor!=null) { - if (!overlay && isActiveOverlayRoi()) { - g.setColor(Color.cyan); - g.drawOval(sx1, sy1, sw, sh); - } else { - g.fillOval(sx1, sy1, sw, sh); - if (strokeColor!=null) { - g.setColor(strokeColor); - g.drawOval(sx1, sy1, sw, sh); - } - } - } else - g.drawOval(sx1, sy1, sw, sh); - if (clipboard==null && !overlay) { - drawHandle(g, sx1+sw2, sy1+sh2); - drawHandle(g, sx3-sw2, sy1+sh2); - drawHandle(g, sx3-sw2, sy3-sh2); - drawHandle(g, sx1+sw2, sy3-sh2); - drawHandle(g, sx2, sy1); - drawHandle(g, sx3, sy2); - drawHandle(g, sx2, sy3); - drawHandle(g, sx1, sy2); - } - drawPreviousRoi(g); - if (updateFullWindow) - {updateFullWindow = false; imp.draw();} - if (state!=NORMAL) showStatus(); - } - - /** Draws an outline of this OvalRoi on the image. */ - public void drawPixels(ImageProcessor ip) { - Polygon p = getPolygon(); - if (p.npoints>0) { - int saveWidth = ip.getLineWidth(); - if (getStrokeWidth()>1f) - ip.setLineWidth((int)Math.round(getStrokeWidth())); - ip.drawPolygon(p); - ip.setLineWidth(saveWidth); - } - if (Line.getWidth()>1 || getStrokeWidth()>1) - updateFullWindow = true; - } - - /** Returns this OvalRoi as a Polygon that outlines the mask, in image pixel coordinates. */ - public Polygon getPolygon() { - return getPolygon(true); - } - - /** Returns this OvalRoi as a Polygon that outlines the mask. - * @param absoluteCoordinates determines whether to use image pixel coordinates - * instead of coordinates relative to roi origin. */ - Polygon getPolygon(boolean absoluteCoordinates) { - ImageProcessor mask = getMask(); - Wand wand = new Wand(mask); - wand.autoOutline(width/2,height/2, 255, 255); - if (absoluteCoordinates) - for (int i=0; i=sx1+sw2&&sx<=sx1+sw2+size&&sy>=sy1+sh2&&sy<=sy1+sh2+size) return 0; - if (sx>=sx2&&sx<=sx2+size&&sy>=sy1&&sy<=sy1+size) return 1; - if (sx>=sx3-sw2&&sx<=sx3-sw2+size&&sy>=sy1+sh2&&sy<=sy1+sh2+size) return 2; - if (sx>=sx3&&sx<=sx3+size&&sy>=sy2&&sy<=sy2+size) return 3; - if (sx>=sx3-sw2&&sx<=sx3-sw2+size&&sy>=sy3-sh2&&sy<=sy3-sh2+size) return 4; - if (sx>=sx2&&sx<=sx2+size&&sy>=sy3&&sy<=sy3+size) return 5; - if (sx>=sx1+sw2&&sx<=sx1+sw2+size&&sy>=sy3-sh2&&sy<=sy3-sh2+size) return 6; - if (sx>=sx1&&sx<=sx1+size&&sy>=sy2&&sy<=sy2+size) return 7; - return -1; - } - - public ImageProcessor getMask() { - ImageProcessor mask = cachedMask; - if (mask!=null && mask.getPixels()!=null && mask.getWidth()==width && mask.getHeight()==height) - return mask; - mask = new ByteProcessor(width, height); - double a=width/2.0, b=height/2.0; - double a2=a*a, b2=b*b; - a -= 0.5; b -= 0.5; - double xx, yy; - int offset; - byte[] pixels = (byte[])mask.getPixels(); - for (int y=0; y { - private Vector list; - private boolean label; - private boolean drawNames; - private boolean drawBackgrounds; - private Color labelColor; - private Font labelFont; - private boolean scalableLabels; - private boolean isCalibrationBar; - private boolean selectable = true; - private boolean draggable = true; - - /** Constructs an empty Overlay. */ - public Overlay() { - list = new Vector(); - } - - /** Constructs an Overlay and adds the specified ROI. */ - public Overlay(Roi roi) { - list = new Vector(); - if (roi!=null) - list.add(roi); - } - - /** Adds an ROI to this Overlay. */ - public void add(Roi roi) { - if (roi!=null) - list.add(roi); - } - - /** Adds an ROI to this Overlay using the specified name. */ - public void add(Roi roi, String name) { - roi.setName(name); - add(roi); - } - - /** Adds the ROIs in 'overlay2' to this overlay. */ - public Overlay add(Overlay overlay2) { - for (int i=0; i=list.size()) - throw new IllegalArgumentException("set: index out of range"); - if (roi!=null) - list.set(index, roi); - } - - /** Removes the ROI with the specified index from this Overlay. */ - public void remove(int index) { - if (index>=0) - list.remove(index); - } - - /** Removes the specified ROI from this Overlay. */ - public void remove(Roi roi) { - list.remove(roi); - } - - /** Removes all ROIs that have the specified name. */ - public void remove(String name) { - if (name==null) return; - for (int i=size()-1; i>=0; i--) { - if (name.equals(get(i).getName())) - remove(i); - } - } - - /** Removes all the ROIs in this Overlay. */ - public void clear() { - list.clear(); - } - - /** Returns the ROI with the specified index or null if the index is invalid. */ - public Roi get(int index) { - try { - return (Roi)list.get(index); - } catch(Exception e) { - return null; - } - } - - /** Returns the ROI with the specified name or null if not found. */ - public Roi get(String name) { - int index = getIndex(name); - if (index==-1) - return null; - else - return get(index); - } - - /** Returns the index of the ROI with the specified name, or -1 if not found. */ - public int getIndex(String name) { - if (name==null) return -1; - Roi[] rois = toArray(); - for (int i=rois.length-1; i>=0; i--) { - if (name.equals(rois[i].getName())) - return i; - } - return -1; - } - - /** Returns the index of the last ROI that contains the point (x,y) - or null if no ROI contains the point. */ - public int indexAt(int x, int y) { - Roi[] rois = toArray(); - for (int i=rois.length-1; i>=0; i--) { - if (contains(rois[i],x,y)) - return i; - } - return -1; - } - - private boolean contains(Roi roi, int x, int y) { - if (roi==null) return false; - if (roi instanceof Line) - return (((Line)roi).getFloatPolygon(10)).contains(x,y); - else - return roi.contains(x,y); - } - - /** Returns 'true' if this Overlay contains the specified ROI. */ - public boolean contains(Roi roi) { - return list.contains(roi); - } - - /** Returns the number of ROIs in this Overlay. */ - public int size() { - return list.size(); - } - - /** Returns on array containing the ROIs in this Overlay. */ - public Roi[] toArray() { - Roi[] array = new Roi[list.size()]; - return (Roi[])list.toArray(array); - } - - /** Returns on array containing the ROIs with the specified indexes. */ - public Roi[] toArray(int[] indexes) { - ArrayList rois = new ArrayList(); - for (int i=0; i=0 && indexes[i]0?bounds.x:0; - int dy = bounds.y>0?bounds.y:0; - if (dx>0 || dy>0) - overlay2.translate(-dx, -dy); - return overlay2; - } - - /** Removes ROIs having positions outside of the - * interval defined by firstSlice and lastSlice. - * Marcel Boeglin, September 2013 - */ - public void crop(int firstSlice, int lastSlice) { - for (int i=size()-1; i>=0; i--) { - Roi roi = get(i); - int position = roi.getPosition(); - if (position>0) { - if (positionlastSlice) - remove(i); - else - roi.setPosition(position-firstSlice+1); - } - } - } - - /** Removes ROIs having a C, Z or T coordinate outside the volume - * defined by firstC, lastC, firstZ, lastZ, firstT and lastT. - * Marcel Boeglin, September 2013 - */ - public void crop(int firstC, int lastC, int firstZ, int lastZ, int firstT, int lastT) { - int nc = lastC-firstC+1, nz = lastZ-firstZ+1, nt = lastT-firstT+1; - boolean toCStack = nz==1 && nt==1; - boolean toZStack = nt==1 && nc==1; - boolean toTStack = nc==1 && nz==1; - Roi roi; - int c, z, t, c2, z2, t2; - for (int i=size()-1; i>=0; i--) { - roi = get(i); - c = roi.getCPosition(); - z = roi.getZPosition(); - t = roi.getTPosition(); - c2 = c-firstC+1; - z2 = z-firstZ+1; - t2 = t-firstT+1; - if (toCStack) - roi.setPosition(c2); - else if (toZStack) - roi.setPosition(z2); - else if (toTStack) - roi.setPosition(t2); - else - roi.setPosition(c2, z2, t2); - if ((c2<1||c2>nc) && c>0 || (z2<1||z2>nz) && z>0 || (t2<1||t2>nt) && t>0) - remove(i); - } - } - - /** Returns the bounds of this overlay. */ - /* - public Rectangle getBounds() { - if (size()==0) - return new Rectangle(0,0,0,0); - int xmin = Integer.MAX_VALUE; - int xmax = -Integer.MAX_VALUE; - int ymin = Integer.MAX_VALUE; - int ymax = -Integer.MAX_VALUE; - Roi[] rois = toArray(); - for (int i=0; ixmax) xmax = r.x+r.width; - if (r.y+r.height>ymax) ymax = r.y+r.height; - } - return new Rectangle(xmin, ymin, xmax-xmin, ymax-ymin); - } - */ - - /* Returns the Roi that results from XORing all the ROIs - * in this overlay that have an index in the array ‘indexes’. - */ - public Roi xor(int[] indexes) { - return Roi.xor(toArray(indexes)); - } - - /** Returns a new Overlay that has the same properties as this one. */ - public Overlay create() { - Overlay overlay2 = new Overlay(); - overlay2.drawLabels(label); - overlay2.drawNames(drawNames); - overlay2.drawBackgrounds(drawBackgrounds); - overlay2.setLabelColor(labelColor); - overlay2.setLabelFont(labelFont, scalableLabels); - overlay2.setIsCalibrationBar(isCalibrationBar); - overlay2.selectable(selectable); - overlay2.setDraggable(draggable); - return overlay2; - } - - /** Returns a clone of this Overlay. */ - public Overlay duplicate() { - Roi[] rois = toArray(); - Overlay overlay2 = create(); - for (int i=0; i v) {list = v;} - - Vector getVector() {return list;} - - /** Set 'false' to prevent ROIs in this overlay from being activated - by clicking on their labels or by a long clicking. */ - public void selectable(boolean selectable) { - this.selectable = selectable; - } - - /** Returns 'true' if ROIs in this overlay can be activated - by clicking on their labels or by a long press. */ - public boolean isSelectable() { - return selectable; - } - - /** Set 'false' to prevent ROIs in this overlay from being dragged by their labels. */ - public void setDraggable(boolean draggable) { - this.draggable = draggable; - } - - /** Returns 'true' if ROIs in this overlay can be dragged by their labels. */ - public boolean isDraggable() { - return draggable; - } - - public boolean scalableLabels() { - return scalableLabels; - } - - public String toString() { - return "Overlay[size="+size()+" "+(scalableLabels?"scale":"")+" "+Colors.colorToString(getLabelColor())+"]"; - } - - /** Updates overlays created by the particle analyzer - after rows are deleted from the Results table. */ - public static void updateTableOverlay(ImagePlus imp, int first, int last, int tableSize) { - if (imp==null) - return; - Overlay overlay = imp.getOverlay(); - if (overlay==null) - return; - if (overlay.size()!=tableSize) - return; - if (first<0) - first = 0; - if (last>tableSize-1) - last = tableSize-1; - if (first>last) - return; - String name1 = overlay.get(0).getName(); - String name2 = overlay.get(overlay.size()-1).getName(); - if (!"1".equals(name1) || !(""+tableSize).equals(name2)) - return; - int count = last-first+1; - if (overlay.size()==count && !IJ.isMacro()) { - if (count==1 || IJ.showMessageWithCancel("ImageJ", "Delete "+overlay.size()+" element overlay? ")) - imp.setOverlay(null); - return; - } - for (int i=0; i iterator() { - final Overlay overlay = this; - - Iterator it = new Iterator() { - private int index = -1; - - /** Returns 'true' if next element exists. */ - @Override - public boolean hasNext() { - if (index+12 - private static final int LEGEND_PADDING = 4; //pixels around legend text etc - private static final int LEGEND_LINELENGTH = 20; //length of lines in legend - private static final int USUALLY_ENLARGE = 1, ALWAYS_ENLARGE = 2; //enlargeRange settings - private static final double RELATIVE_ARROWHEAD_SIZE = 0.2; //arrow heads have 1/5 of vector length - private static final int MIN_ARROWHEAD_LENGTH = 3; - private static final int MAX_ARROWHEAD_LENGTH = 20; - private static final String MULTIPLY_SYMBOL = "\u00B7"; //middot, default multiplication symbol for scientific notation. Use setOptions("msymbol=\\u00d7") for '×' - - PlotProperties pp = new PlotProperties(); //size, range, formatting etc, for easy serialization - PlotProperties ppSnapshot; //copy for reverting - Vector allPlotObjects = new Vector(); //all curves, labels etc., also serialized for saving/reading - Vector allPlotObjectsSnapshot; //copy for reverting - private PlotVirtualStack stack; - /** For high-resolution plots, everything will be scaled with this number. Otherwise, must be 1.0. - * (creating margins, saving PlotProperties etc only supports scale=1.0) */ - float scale = 1.0f; - Rectangle frame = null; //the clip frame, do not use for image scale - //The following are the margin sizes actually used. They are modified for font size and also scaled for high-resolution plots - public int leftMargin = LEFT_MARGIN; - public int rightMargin = RIGHT_MARGIN; - public int topMargin = TOP_MARGIN; - public int bottomMargin = BOTTOM_MARGIN; - int frameWidth; //width corresponding to plot range; frame.width is larger by 1 - int frameHeight; //height corresponding to plot range; frame.height is larger by 1 - int preferredPlotWidth = PlotWindow.plotWidth; //default size of plot frame (not taking 'High-Resolution' scale factor into account) - int preferredPlotHeight = PlotWindow.plotHeight; - - double xMin = Double.NaN, xMax, yMin, yMax; //current plot range, logarithm if log axis - double[] currentMinMax = new double[]{Double.NaN, 0, Double.NaN, 0}; //current plot range, xMin, xMax, yMin, yMax (values, not logarithm if log axis) - double[] defaultMinMax = new double[]{Double.NaN, 0, Double.NaN, 0}; //default plot range - double[] savedMinMax = new double[]{Double.NaN, 0, Double.NaN, 0}; //keeps previous range for revert - int[] enlargeRange; // whether to enlarge the range slightly to avoid values at the border (0=off, USUALLY_ENLARGE, ALWAYS_ENLARGE) - boolean logXAxis, logYAxis; // whether to really use log axis (never for small relative range) - //for passing on what should be kept when 'live' plotting (PlotMaker), but note that 'COPY_EXTRA_OBJECTS' is also on for live plotting: - int templateFlags = COPY_SIZE | COPY_LABELS | COPY_AXIS_STYLE | COPY_CONTENTS_STYLE | COPY_LEGEND; - private int dsize = PlotWindow.getDefaultFontSize(); - Font defaultFont = FontUtil.getFont("Arial",Font.PLAIN,dsize); //default font for labels, axis, etc. - Font currentFont = defaultFont; // font as changed by setFont or setFontSize, must never be null - private double xScale, yScale; // pixels per data unit - private int xBasePxl, yBasePxl; // pixel coordinates corresponding to 0 - private int maxIntervals = 12; // maximum number of intervals between ticks or grid lines - private int tickLength = 7; // length of major ticks - private int minorTickLength = 3; // length of minor ticks - private Color gridColor = new Color(0xc0c0c0); // light gray - private ImageProcessor ip; - private ImagePlus imp; // if we have an ImagePlus, updateAndDraw on changes - private String title; - private boolean invertedLut; // grayscale plots only, set in Edit>Options>Appearance - private boolean plotDrawn; - PlotMaker plotMaker; // for PlotMaker interface, handled by PlotWindow - private Color currentColor; // for next objects added - private Color currentColor2; // 2nd color for next object added (e.g. line for CONNECTED_CIRCLES) - float currentLineWidth; - private int currentJustification = LEFT; - private boolean ignoreForce2Grid; // after explicit setting of range (limits), ignore 'FORCE2GRID' flags - //private boolean snapToMinorGrid; // snap to grid when zooming to selection - private static double SEPARATED_BAR_WIDTH=0.5; // for plots with separate bars (e.g. categories), fraction of space, 0.1-1.0 - double[] steps; // x & y interval between numbers, major ticks & grid lines, remembered for redrawing the grid - private int objectToReplace = -1; // index in allPlotObjects, for replace - //private Point2D.Double textLoc; // remembers position of previous addLabel call (replaces text if at the same position) - //private int textIndex; // remembers index of previous addLabel call (for replacing if at the same position) - - /** Constructs a new Plot with the default options. - * Use add(shape,xvalues,yvalues) to add curves. - * @param title the window title - * @param xLabel the x-axis label; see setXYLabels for seting categories on an axis via the label - * @param yLabel the y-axis label; see setXYLabels for seting categories on an axis via the label - * @see #add(String,double[],double[]) - * @see #add(String,double[]) - */ - public Plot(String title, String xLabel, String yLabel) { - this(title, xLabel, yLabel, (float[])null, (float[])null, getDefaultFlags()); - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, float[] x, float[] y) { - this(title, xLabel, yLabel, x, y, getDefaultFlags()); - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, double[] x, double[] y) { - this(title, xLabel, yLabel, x!=null?Tools.toFloat(x):null, y!=null?Tools.toFloat(y):null, getDefaultFlags()); - } - - /** This version of the constructor has a 'flags' argument for - controlling whether ticks, grid, etc. are present and whether - the axes are logarithmic */ - public Plot(String title, String xLabel, String yLabel, int flags) { - this(title, xLabel, yLabel, (float[])null, (float[])null, flags); - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel,flags); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, float[] xValues, float[] yValues, int flags) { - this.title = title; - pp.axisFlags = flags; - setXYLabels(xLabel, yLabel); - if (yValues != null && yValues.length>0) { - addPoints(xValues, yValues, /*yErrorBars=*/null, LINE, /*label=*/null); - allPlotObjects.get(0).flags = PlotObject.CONSTRUCTOR_DATA; - } - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel,flags); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, double[] x, double[] y, int flags) { - this(title, xLabel, yLabel, x!=null?Tools.toFloat(x):null, y!=null?Tools.toFloat(y):null, flags); - } - - /** Constructs a new plot from an InputStream and closes the stream. If the ImagePlus is - * non-null, its title and ImageProcessor are used, but the image displayed is not modified. - */ - public Plot(ImagePlus imp, InputStream is) throws IOException, ClassNotFoundException { - ObjectInputStream in = new ObjectInputStream(is); - pp = (PlotProperties)in.readObject(); - allPlotObjects = (Vector)in.readObject(); - in.close(); - if (pp.xLabel.type==8) { - pp.xLabel.updateType(); //convert old (pre-1.52i) type codes for the PlotObjects - pp.yLabel.updateType(); - pp.frame.updateType(); - if (pp.legend != null) pp.legend.updateType(); - for (PlotObject plotObject : allPlotObjects) - plotObject.updateType(); - } - - defaultMinMax = pp.rangeMinMax; - currentFont = nonNullFont(pp.frame.getFont(), currentFont); // best guess in case we want to add a legend - getProcessor(); //prepares scale, calibration etc, but does not plot it yet - this.title = imp != null ? imp.getTitle() : "Untitled Plot"; - if (imp != null) { - this.imp = imp; - ip = imp.getProcessor(); - imp.setIgnoreGlobalCalibration(true); - adjustCalibration(imp.getCalibration()); - imp.setProperty(PROPERTY_KEY, this); - } - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel); add(shape,x,y);". - * @deprecated - */ - public Plot(String dummy, String title, String xLabel, String yLabel, float[] x, float[] y) { - this(title, xLabel, yLabel, x, y, getDefaultFlags()); - } - - /** Writes this plot into an OutputStream containing (1) the serialized PlotProperties and - * (2) the serialized Vector of all 'added' PlotObjects. The stream is NOT closed. - * The plot should have been drawn already. - */ - // Conversion to Streams can be also used to clone plots (not a shallow clone), but this is rather slow. - // Sample code: - // try { - // final PipedOutputStream pos = new PipedOutputStream(); - // final PipedInputStream pis = new PipedInputStream(pos); - // new Thread(new Runnable() { - // final public void run() { - // try { - // Plot p = new Plot(null, pis); - // pis.close(); - // pos.close(); - // p.show(); - // } catch(Exception e) {IJ.handleException(e);}; - // } - // }, "threadMakingPlotFromStream").start(); - // toStream(pos); - // } catch(Exception e) {IJ.handleException(e);} - void toStream(OutputStream os) throws IOException { - //prepare - for (PlotObject plotObject : pp.getAllPlotObjects()) //make sure all fonts are set properly - if (plotObject != null) - plotObject.setFont(nonNullFont(plotObject.getFont(), currentFont)); - pp.rangeMinMax = currentMinMax; - //write - ObjectOutputStream out = new ObjectOutputStream(os); - out.writeObject(pp); - out.writeObject(allPlotObjects); - } - - /** Writes this plot into a byte array containing (1) the serialized PlotProperties and - * (2) the serialized Vector of all 'added' PlotObjects. - * The plot should have been drawn already. Returns null on error (which should never happen). */ - public byte[] toByteArray() { - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - toStream(bos); - bos.close(); - return bos.toByteArray(); - } catch (Exception e) { - IJ.handleException(e); - return null; - } - } - - /** Returns the title of the image showing the plot (if any) or title of the plot */ - public String getTitle() { - return imp == null ? title : imp.getTitle(); - } - - /** Sets the x-axis and y-axis range. Saves the new limits as default (so the 'R' field sets the limits to these). - * Updates the image if existing. - * Accepts NaN values to indicate auto-range. */ - public void setLimits(double xMin, double xMax, double yMin, double yMax) { - setLimitsNoUpdate(xMin, xMax, yMin, yMax); - makeLimitsDefault(); - ignoreForce2Grid = true; - if (plotDrawn) - setLimitsToDefaults(true); - } - - /** Sets the x-axis and y-axis range. Accepts NaN values to indicate auto range. - * Does not update the image and leaves the default limits (for reset via the 'R' field) untouched. */ - void setLimitsNoUpdate(double xMin, double xMax, double yMin, double yMax) { - boolean containsNaN = (Double.isNaN(xMin + xMax + yMin + yMax)); - if (containsNaN && getNumPlotObjects(PlotObject.XY_DATA|PlotObject.ARROWS, false)==0)//can't apply auto-range without data - return; - double[] range = {xMin, xMax, yMin, yMax}; - if (containsNaN) { //auto range for at least one limit - double[] extrema = getMinAndMax(true, ALL_AXES_RANGE); - boolean[] auto = new boolean[range.length]; - for (int i = 0; i < range.length; i++) - if (Double.isNaN(range[i])) { - auto[i] = true; - range[i] = extrema[i]; - } - for (int a = 0; aOptions>Plots. - * @see #setFrameSize(int,int) - * @see #setWindowSize(int,int) - */ - public void setSize(int width, int height) { - if (ip != null && width == ip.getWidth() && height == ip.getHeight()) - return; - Dimension minSize = getMinimumSize(); - pp.width = Math.max(width, minSize.width); - pp.height = Math.max(height, minSize.height); - scale = 1.0f; - ip = null; - if (plotDrawn) updateImage(); - } - - /** The size of the plot including borders with axis labels etc., in pixels */ - public Dimension getSize() { - if (ip == null) - getBlankProcessor(); - return new Dimension(ip.getWidth(), ip.getHeight()); - } - - /** Sets the plot frame size in (unscaled) pixels. This size does not include the - * borders with the axis labels. Also sets the scale to 1.0. - * This frame size in pixels divided by the data range defines the image scale. - * This method does not check for the minimum size MIN_FRAMEWIDTH, MIN_FRAMEHEIGHT. - * Note that the black frame will have an outer size that is one pixel larger - * (when plotted with a linewidth of one pixel). - * @see #setWindowSize(int,int) - */ - public void setFrameSize(int width, int height) { - if (pp.width <= 0) { //plot not drawn yet? Just remember as preferred size - preferredPlotWidth = width; - preferredPlotHeight = height; - scale = 1.0f; - } else { - makeMarginValues(); - width += leftMargin+rightMargin; - height += topMargin+bottomMargin; - setSize(width, height); - } - } - - /** Sets the plot window size in pixels. - * @see #setFrameSize(int,int) - */ - public void setWindowSize(int width, int height) { - scale = 1.0f; - makeMarginValues(); - int titleBarHeight = 22; - int infoHeight = 11; - double scale = Prefs.getGuiScale(); - if (scale>1.0) - infoHeight = (int)(infoHeight*scale); - int buttonPanelHeight = 45; - if (pp.width <= 0) { //plot not drawn yet? - int extraWidth = leftMargin+rightMargin+ImageWindow.HGAP*2; - int extraHeight = topMargin+bottomMargin+titleBarHeight+infoHeight+buttonPanelHeight; - if (extraWidthplot may be null; then the call has no effect. */ - public void useTemplate(Plot plot) { - useTemplate(plot, templateFlags); - } - - /** Adjusts the format (style) with another plot as a template. Flags determine what to - * copy from the template; these can be X_RANGE, Y_RANGE, COPY_SIZE, COPY_LABELS, COPY_AXIS_STYLE, - * COPY_CONTENTS_STYLE (hidden items are ignored), and COPY_LEGEND. - * plot may be null; then the call has no effect. */ - public void useTemplate(Plot plot, int templateFlags) { - if (plot == null) return; - this.defaultFont = plot.defaultFont; - this.currentFont = plot.currentFont; - this.currentLineWidth = plot.currentLineWidth; - this.currentColor = plot.currentColor; - if ((templateFlags & COPY_AXIS_STYLE) != 0) { - this.pp.axisFlags = plot.pp.axisFlags; - this.pp.frame = plot.pp.frame.deepClone(); - } - if ((templateFlags & COPY_LABELS) != 0) { - this.pp.xLabel.label = plot.pp.xLabel.label; - this.pp.yLabel.label = plot.pp.yLabel.label; - this.pp.xLabel.setFont(plot.pp.xLabel.getFont()); - this.pp.yLabel.setFont(plot.pp.yLabel.getFont()); - } - for (int i=0; i>(i/2)&0x1) != 0) { - currentMinMax[i] = plot.currentMinMax[i]; - if (!plotDrawn) defaultMinMax[i] = plot.currentMinMax[i]; - } - if ((templateFlags & COPY_LEGEND) != 0 && plot.pp.legend != null) - this.pp.legend = plot.pp.legend.deepClone(); - if ((templateFlags & (COPY_LEGEND | COPY_CONTENTS_STYLE)) != 0) { - int plotPObjectIndex = 0; //points to PlotObjects of the templatePlot - int plotPObjectsSize = plot.allPlotObjects.size(); - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN)) { - while(plotPObjectIndex=plotPObjectsSize) break; - if ((templateFlags & COPY_LEGEND) != 0) - plotObject.label = plot.allPlotObjects.get(plotPObjectIndex).label; - if ((templateFlags & COPY_CONTENTS_STYLE) != 0) - setPlotObjectStyle(plotObject, getPlotObjectStyle(plot.allPlotObjects.get(plotPObjectIndex))); - plotPObjectIndex++; - } - } - } - if ((templateFlags & COPY_SIZE) != 0) - setSize(plot.pp.width, plot.pp.height); - - if ((templateFlags & COPY_EXTRA_OBJECTS) != 0) - for (int p = allPlotObjects.size(); p < plot.allPlotObjects.size(); p++) - allPlotObjects.add(plot.allPlotObjects.get(p)); - this.templateFlags = templateFlags; - } - - /** Sets the scale. Everything, including labels, line thicknesses, etc will be scaled by this factor. - * Also multiplies the plot size by this value. Used for 'Create high-resolution plot'. - * Should be called before creating the plot. - * Note that plots with a scale different from 1.0 must not be shown in a PlotWindow, but only as - * simple image in a normal ImageWindow. */ - public void setScale(float scale) { - this.scale = scale; - if (scale > 20f) scale = 20f; - if (scale < 0.7f) scale = 0.7f; - pp.width = sc(pp.width); - pp.height = sc(pp.height); - plotDrawn = false; - } - - /** Sets the labels of the x and y axes. 'xLabel', 'yLabel' may be null. - * If a label has the form {txt1,txt2,txt3}, the corresponding axis will be labeled - * not by numbers but rather with the texts "txt1", "txt2" ... instead of 0, 1, ... - * In this special case, there will be no label for the axis on the plot. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setXYLabels(String xLabel, String yLabel) { - pp.xLabel.label = xLabel!=null ? xLabel : ""; - pp.yLabel.label = yLabel!=null ? yLabel : ""; - } - - /** Sets the maximum number of intervals in a plot. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setMaxIntervals(int intervals) { - maxIntervals = intervals; - } - - /** Sets the length of the major tick in pixels. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setTickLength(int tickLength) { - this.tickLength = tickLength; - } - - /** Sets the length of the minor tick in pixels. */ - public void setMinorTickLength(int minorTickLength) { - this.minorTickLength = minorTickLength; - } - - /** Sets the flags that control the axes format. - * Does not modify the flags for logarithmic axes on/off and the FORCE2GRID flags. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setFormatFlags(int flags) { - int unchangedFlags = X_LOG_NUMBERS | Y_LOG_NUMBERS | X_FORCE2GRID | Y_FORCE2GRID; - flags = flags & (~unchangedFlags); //remove flags that should not be affected - pp.axisFlags = (pp.axisFlags & unchangedFlags) | flags; - } - - /** Returns the flags that control the axes */ - public int getFlags() { - return pp.axisFlags; - } - - /** Sets the X Axis format to Log or Linear. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setAxisXLog(boolean axisXLog) { - pp.axisFlags = axisXLog ? pp.axisFlags | X_LOG_NUMBERS : pp.axisFlags & (~X_LOG_NUMBERS); - } - - /** Sets the Y Axis format to Log or Linear. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setAxisYLog(boolean axisYLog) { - pp.axisFlags = axisYLog ? pp.axisFlags | Y_LOG_NUMBERS : pp.axisFlags & (~Y_LOG_NUMBERS); - } - - /** Sets whether to show major ticks at the x axis. - * Call update() thereafter to make the change visible (if the image is shown already). */ - - public void setXTicks(boolean xTicks) { - pp.axisFlags = xTicks ? pp.axisFlags | X_TICKS : pp.axisFlags & (~X_TICKS); - } - - /** Sets whether to show major ticks at the y axis. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setYTicks(boolean yTicks) { - pp.axisFlags = yTicks ? pp.axisFlags | Y_TICKS : pp.axisFlags & (~Y_TICKS); - } - - /** Sets whether to show minor ticks on the x axis (if linear). Also sets major ticks if true and no grid is set. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setXMinorTicks(boolean xMinorTicks) { - pp.axisFlags = xMinorTicks ? pp.axisFlags | X_MINOR_TICKS : pp.axisFlags & (~X_MINOR_TICKS); - if (xMinorTicks && !hasFlag(X_GRID)) - pp.axisFlags |= X_TICKS; - } - - /** Sets whether to show minor ticks on the y axis (if linear). Also sets major ticks if true and no grid is set. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setYMinorTicks(boolean yMinorTicks) { - pp.axisFlags = yMinorTicks ? pp.axisFlags | Y_MINOR_TICKS : pp.axisFlags & (~Y_MINOR_TICKS); - if (yMinorTicks && !hasFlag(Y_GRID)) - pp.axisFlags |= Y_TICKS; - } - - /** Sets the properties of the axes. Call update() thereafter to make the change visible - * (if the image is shown already). */ - public void setAxes(boolean xLog, boolean yLog, boolean xTicks, boolean yTicks, boolean xMinorTicks, boolean yMinorTicks, - int tickLenght, int minorTickLenght) { - setAxisXLog (xLog); - setAxisYLog (yLog); - setXMinorTicks (xMinorTicks); - setYMinorTicks (yMinorTicks); - setXTicks (xTicks); - setYTicks (yTicks); - setTickLength (tickLenght); - setMinorTickLength(minorTickLenght); - } - - /** Sets log scale in x. Call update() thereafter to make the change visible - * (if the image is shown already). */ - - public void setLogScaleX() { - setAxisXLog(true); - } - - public void setLogScaleY() { - setAxisYLog(true); - } - - /** The default flags, taking PlotWindow.noGridLines, PlotWindow.noTicks into account */ - public static int getDefaultFlags() { - int defaultFlags = 0; - if (!PlotWindow.noGridLines) //note that log ticks are also needed because the range may span less than a decade, then no grid is visible - defaultFlags |= X_GRID | Y_GRID | X_NUMBERS | Y_NUMBERS | X_LOG_TICKS | Y_LOG_TICKS; - if (!PlotWindow.noTicks) - defaultFlags |= X_TICKS | Y_TICKS | X_MINOR_TICKS | Y_MINOR_TICKS | X_NUMBERS | Y_NUMBERS | X_LOG_TICKS | Y_LOG_TICKS; - return defaultFlags; - } - - /** Adds a curve or set of points to this plot, where 'type' is - * "line", "connected circle", "filled", "bar", "separated bar", "circle", "box", "triangle", "diamond", "cross", - * "x" or "dot". Run Help>Examples>JavaScript>Graph Types to see examples. - * If 'type' is in the form "code: ", the macro given is executed to draw the symbol; - * macro variables 'x' and 'y' are the pixel coordinates of the point, 'xval' and 'yval' are the plot data - * and 'i' is the index of the data point (starting with 0 for the first point in the array). - * The drawing including line thickness, font size, etc. be scaled by scale factor 's' (to make high-resolution plots work). - * Example: "code: setFont('sanserif',12*s,'bold anti');drawString(d2s(yval,1),x-14*s,y-4*s);" - * writes the y value for each point above the point. - */ - public void add(String type, double[] xvalues, double[] yvalues) { - int iShape = toShape(type); - addPoints(Tools.toFloat(xvalues), Tools.toFloat(yvalues), null, iShape, iShape==CUSTOM?type.substring(5, type.length()):null); - } - - /** Replaces the specified plot object (curve or set of points). - * Equivalent to add() if there are no plot objects. */ - public void replace(int index, String type, double[] xvalues, double[] yvalues) { - if (index>=0 && index0?index:-1; - add(type, xvalues, yvalues); - } - } - - /** Adds a curve, set of points or error bars to this plot, where 'type' is - * "line", "connected circle", "filled", "bar", "separated bar", "circle", "box", - * "triangle", "diamond", "cross", "x", "dot", "error bars" or "xerror bars". - */ - public void add(String type, double[] yvalues) { - int iShape = toShape(type); - if (iShape==-1) - addErrorBars(yvalues); - else if (iShape==-2) - addHorizontalErrorBars(yvalues); - else - addPoints(null, Tools.toFloat(yvalues), null, iShape, iShape==CUSTOM?type.substring(5, type.length()):null); - } - - /** Adds a set of points to the plot or adds a curve if shape is set to LINE. - * @param xValues the x coordinates, or null. If null, integers starting at 0 will be used for x. - * @param yValues the y coordinates (must not be null) - * @param yErrorBars error bars in y, may be null - * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS, DIAMOND, DOT, LINE, CONNECTED_CIRCLES - * @param label Label for this curve or set of points, used for a legend and for listing the plots. - * For shape type CUSTOM, the 'label' String should contain the macro code as in "Custom Plot Symbols" - * example macro and in add(String, double[], double[]) (without the 'code:') - */ - public void addPoints(float[] xValues, float[] yValues, float[] yErrorBars, int shape, String label) { - if (xValues==null || xValues.length==0) { - xValues = new float[yValues.length]; - for (int i=0; i=0) - allPlotObjects.set(objectToReplace, new PlotObject(xValues, yValues, yErrorBars, shape, currentLineWidth, currentColor, currentColor2, label)); - else - allPlotObjects.add(new PlotObject(xValues, yValues, yErrorBars, shape, currentLineWidth, currentColor, currentColor2, label)); - objectToReplace = -1; - if (plotDrawn) updateImage(); - } - - /** Adds a set of points to the plot or adds a curve if shape is set to LINE. - * @param x the x coordinates - * @param y the y coordinates - * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS, DIAMOND, DOT, LINE, CONNECTED_CIRCLES - */ - public void addPoints(float[] x, float[] y, int shape) { - addPoints(x, y, null, shape, null); - } - - /** Adds a set of points to the plot using double arrays. */ - public void addPoints(double[] x, double[] y, int shape) { - addPoints(Tools.toFloat(x), Tools.toFloat(y), shape); - } - - /** Returns the number for a given plot symbol shape, -1 for xError and -2 for yError (all case-insensitive) */ - public static int toShape(String str) { - str = str.toLowerCase(Locale.US); - int shape = Plot.CIRCLE; - if (str.contains("curve") || str.contains("line")) - shape = Plot.LINE; - else if (str.contains("connected")) - shape = Plot.CONNECTED_CIRCLES; - else if (str.contains("filled")) - shape = Plot.FILLED; - else if (str.contains("circle")) - shape = Plot.CIRCLE; - else if (str.contains("box")) - shape = Plot.BOX; - else if (str.contains("triangle")) - shape = Plot.TRIANGLE; - else if (str.contains("cross") || str.contains("+")) - shape = Plot.CROSS; - else if (str.contains("diamond")) - shape = Plot.DIAMOND; - else if (str.contains("dot")) - shape = Plot.DOT; - else if (str.contains("xerror")) - shape = -2; - else if (str.contains("error")) - shape = -1; - else if (str.contains("x")) - shape = Plot.X; - else if (str.contains("separate")) - shape = Plot.SEPARATED_BAR; - else if (str.contains("bar")) - shape = Plot.BAR; - if (str.startsWith("code:")) - shape = CUSTOM; - return shape; - } - - /** Adds a set of points to the plot using double ArrayLists. - * Must be called before the plot is displayed. */ - public void addPoints(ArrayList x, ArrayList y, int shape) { - addPoints(getDoubleFromArrayList(x), getDoubleFromArrayList(y), shape); - } - - /** Adds a set of points to the plot or adds a curve if shape is set to LINE. - * @param x the x-coodinates - * @param y the y-coodinates - * @param errorBars half-lengths of the vertical error bars, may be null - * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS, DIAMOND, DOT or LINE - */ - public void addPoints(double[] x, double[] y, double[] errorBars, int shape) { - addPoints(Tools.toFloat(x), Tools.toFloat(y), Tools.toFloat(errorBars), shape, null); - } - - /** Adds a set of points to the plot using double ArrayLists. - * Must be called before the plot is displayed. */ - public void addPoints(ArrayList x, ArrayList y, ArrayList errorBars, int shape) { - addPoints(getDoubleFromArrayList(x), getDoubleFromArrayList(y), getDoubleFromArrayList(errorBars), shape); - } - - public double[] getDoubleFromArrayList(ArrayList list) { - if (list == null) return null; - double[] targ = new double[list.size()]; - for (int i = 0; i < list.size(); i++) - targ[i] = ((Double) list.get(i)).doubleValue(); - return targ; - } - - /** Adds a set of points that will be drawn as ARROWs. - * @param x1 the x-coodinates of the beginning of the arrow - * @param y1 the y-coodinates of the beginning of the arrow - * @param x2 the x-coodinates of the end of the arrow - * @param y2 the y-coodinates of the end of the arrow - */ - public void drawVectors(double[] x1, double[] y1, double[] x2, double[] y2) { - allPlotObjects.add(new PlotObject(Tools.toFloat(x1), Tools.toFloat(y1), - Tools.toFloat(x2), Tools.toFloat(y2), currentLineWidth, currentColor)); - } - - /** - * Adds a set of 'shapes' such as boxes and whiskers - * - * @param shapeType e.g. "boxes width=20" - * @param floatCoords eg[6][3] holding 1 Xval + 5 Yvals for 3 boxes - */ - public void drawShapes(String shapeType, ArrayList floatCoords) { - allPlotObjects.add(new PlotObject(shapeType, floatCoords, currentLineWidth, currentColor, currentColor2)); - } - - public static double calculateDistance(int x1, int y1, int x2, int y2) { - return java.lang.Math.sqrt((x2 - x1)*(double)(x2 - x1) + (y2 - y1)*(double)(y2 - y1)); - } - - /** Adds a set of vectors to the plot using double ArrayLists. - * Does not support logarithmic axes. - * Must be called before the plot is displayed. */ - public void drawVectors(ArrayList x1, ArrayList y1, ArrayList x2, ArrayList y2) { - drawVectors(getDoubleFromArrayList(x1), getDoubleFromArrayList(y1), getDoubleFromArrayList(x2), getDoubleFromArrayList(y2)); - } - - /** Adds vertical error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addErrorBars(float[] errorBars) { - PlotObject mainObject = getLastCurveObject(); - if (mainObject != null) - mainObject.yEValues = errorBars; - else throw new RuntimeException("Plot can't add y error bars without data"); - } - - /** Adds vertical error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addErrorBars(double[] errorBars) { - addErrorBars(Tools.toFloat(errorBars)); - } - - /** Adds horizontal error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addHorizontalErrorBars(float[] xErrorBars) { - PlotObject mainObject = getLastCurveObject(); - if (mainObject != null) - mainObject.xEValues = xErrorBars; - else throw new RuntimeException("Plot can't add x error bars without data"); - } - - /** Adds horizontal error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addHorizontalErrorBars(double[] xErrorBars) { - addHorizontalErrorBars(Tools.toFloat(xErrorBars)); - } - - /** Draws text at the specified location, where (0,0) - * is the upper left corner of the the plot frame and (1,1) is - * the lower right corner. Uses the justification specified by setJustification(). - * When called with the same position as the previous addLabel call, the text of that previous call is replaced */ - public void addLabel(double x, double y, String label) { - for (int i=allPlotObjects.size()-1; i>=0; i--) { - PlotObject plotObject = allPlotObjects.get(i); - if (plotObject.type == PlotObject.NORMALIZED_LABEL) { //result of previous addLabel - if (plotObject.x == x && plotObject.y == y) { - allPlotObjects.set(i, new PlotObject(label, x, y, currentJustification, - currentFont, currentColor, PlotObject.NORMALIZED_LABEL)); - return; - } - break; - } - } - allPlotObjects.add(new PlotObject(label, x, y, currentJustification, currentFont, currentColor, PlotObject.NORMALIZED_LABEL)); - } - - /* Draws text at the specified location, using the coordinate system defined - * by setLimits() and the justification specified by setJustification(). */ - public void addText(String label, double x, double y) { - allPlotObjects.add(new PlotObject(label, x, y, currentJustification, currentFont, currentColor, PlotObject.LABEL)); - } - - /** Adds an automatically positioned legend, where 'labels' can be a tab-delimited or - newline-delimited list of curve or point labels in the sequence these data were added. - Hidden data sets are ignored. - If 'labels' is null or empty, the labels of the data set previously (if any) are used. - To modify the legend's style, call 'setFont' and 'setLineWidth' before 'addLegend'. */ - public void addLegend(String labels) { - addLegend(labels, "auto"); - } - - /** Adds a legend at the position given in 'options', where 'labels' can be tab-delimited or - * newline-delimited list of curve or point labels in the sequence these data were added. - * Hidden data sets are ignored; no labels (and no delimiters) should be provided for these. - * Apart from top to bottom and bottom to top (controlled by "bottom-to-top" in the options), - * the sequence may be altered by preceding numbers followed by double underscores, such as - * "1__Other Data Set\t0__First Data Set" (the number and double underscore won't be displayed). - * When this possibility is used, only items with double underscores will be shown in the legend - * (preceding double underscores without a number make the item appear in the legend without altering the sequence). - * If 'labels' is null or empty, the labels of the data set previously (if any) are used. - To modify the legend's style, call 'setFont' and 'setLineWidth' before 'addLegend'. */ - public void addLegend(String labels, String options) { - int flags = 0; - if (options!=null) { - options = options.toLowerCase(); - if (options.contains("top-left")) - flags |= Plot.TOP_LEFT; - else if (options.contains("top-right")) - flags |= Plot.TOP_RIGHT; - else if (options.contains("bottom-left")) - flags |= Plot.BOTTOM_LEFT; - else if (options.contains("bottom-right")) - flags |= Plot.BOTTOM_RIGHT; - else if (!options.contains("off") && !options.contains("no")) - flags |= Plot.AUTO_POSITION; - if (options.contains("bottom-to-top")) - flags |= Plot.LEGEND_BOTTOM_UP; - if (options.contains("transparent")) - flags |= Plot.LEGEND_TRANSPARENT; - } - setLegend(labels, flags); - } - - /** Adds a legend. The legend will be always drawn last (on top of everything). - * To modify the legend's style, call 'setFont' and 'setLineWidth' before 'addLegend' - * @param labels labels of the points or curves in the sequence of the data were added, tab-delimited or linefeed-delimited. - * The labels of the datasets will be set to these values. If null or not given, the labels set - * previously (if any) will be used. - * Hidden data sets are ignored; no labels (and no delimiters) should be provided for these. - * Apart from top to bottom and bottom to top (controlled by the LEGEND_BOTTOM_UP flag), - * the sequence may be altered by preceding numbers followed by double underscores, such as - * "1__Other Data Set\t0__First Data Set" (the number and double underscore won't be displayed). - * When this possibility is used, only items with double underscores will be shown in the legend - * (preceding double underscores without a number make the item appear in the legend without altering the sequence). - * @param flags Bitwise or of position (AUTO_POSITION, TOP_LEFT etc.), LEGEND_TRANSPARENT, and LEGEND_BOTTOM_UP if desired. - * Updates the image (if it is shown already). */ - public void setLegend(String labels, int flags) { - if (labels != null && labels.length()>0) { - String[] allLabels = labels.split("[\n\t]"); - int iPart = 0; - for (PlotObject plotObject : allPlotObjects) - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN)) - if (iPart < allLabels.length) { - String label = allLabels[iPart++]; - if (label!=null && label.length()>0) - plotObject.label = label; - } - } - pp.legend = new PlotObject(currentLineWidth == 0 ? 1 : currentLineWidth, - currentFont, currentColor == null ? Color.black : currentColor, flags); - if (plotDrawn) updateImage(); - } - - /** Sets the label for the plot object number 'index' in the sequence they were added. - * With index=-1, sets the label for the last object added. - * For x/y data, the label is used for the legend and as header in getResultsTableWithLabels. - * For Text/Label objects, it affects the label shown (but the plot is not redisplayed). - */ - public void setLabel(int index, String label) { - if (index < 0) index = allPlotObjects.size() + index; - allPlotObjects.get(index).label = label; - } - - /** Removes NaNs from the xValues and yValues arrays of all plot objects. */ - public void removeNaNs() { - for (PlotObject plotObj : allPlotObjects){ - if(plotObj != null && plotObj.xValues!= null && plotObj.yValues != null ){ - int oldSize = plotObj.xValues.length; - float[] xVals = new float[oldSize]; - float[] yVals = new float[oldSize]; - int newSize = 0; - for (int kk = 0; kk < oldSize; kk++) { - if (!Float.isNaN(plotObj.xValues[kk] + plotObj.yValues[kk])) { - xVals[newSize] = plotObj.xValues[kk]; - yVals[newSize] = plotObj.yValues[kk]; - newSize++; - } - } - if (newSize < oldSize) { - plotObj.xValues = new float[newSize]; - plotObj.yValues = new float[newSize]; - System.arraycopy(xVals, 0, plotObj.xValues, 0, newSize); - System.arraycopy(yVals, 0, plotObj.yValues, 0, newSize); - } - } - } - } - - /** Returns an array of the available curve types ("Line", "Bar", "Circle", etc). */ - public String[] getTypes() { - return SORTED_SHAPES; - } - - /** Sets the justification used by addLabel(), where justification - * is Plot.LEFT, Plot.CENTER or Plot.RIGHT. Default is LEFT. */ - public void setJustification(int justification) { - currentJustification = justification; - } - - /** Changes the drawing color for the next objects that will be added to the plot. - * For selecting the color of the curve passed with the constructor, - * use setColor before draw. - * The frame and labels are always drawn in black. */ - public void setColor(Color c) { - currentColor = c; - currentColor2 = null; - } - - public void setColor(String color) { - setColor(Colors.decode(color, Color.black)); - } - - /** Changes the drawing color for the next objects that will be added to the plot. - * It also sets secondary color: This is the color of the line for CONNECTED_CIRCLES, - * and the color for filling open symbols (CIRCLE, BOX, TRIANGLE). - * Set it to null or use the one-argument call setColor(color) to disable filling. - * For selecting the color of the curve passed with the constructor, - * use setColor before draw. - * The frame and labels are always drawn in black. */ - public void setColor(Color c, Color c2) { - currentColor = c; - currentColor2 = c2; - } - - /** Sets the drawing colors for the next objects that will be added to the plot. */ - public void setColor(String c1, String c2) { - setColor(Colors.decode(c1, Color.black), Colors.decode(c2, null)); - } - - /** Set the plot frame background color. */ - public void setBackgroundColor(Color c) { - pp.frame.color2 = c; - } - - /** Set the plot frame background color. */ - public void setBackgroundColor(String c) { - setBackgroundColor(Colors.decode(c,Color.white)); - } - - /** Changes the line width for the next objects that will be added to the plot. */ - public void setLineWidth(int lineWidth) { - currentLineWidth = lineWidth > 0 ? lineWidth : 0.01f; - } - - /** Changes the line width for the next objects that will be added to the plot. - * After all objects have been added, set the line width to the width desired - * for the frame around the plot (max. 3) */ - public void setLineWidth(float lineWidth) { - currentLineWidth = lineWidth > 0.01 ? lineWidth : 0.01f; - } - - /** Draws a line using the coordinate system defined by setLimits(). */ - public void drawLine(double x1, double y1, double x2, double y2) { - allPlotObjects.add(new PlotObject(x1, y1, x2, y2, currentLineWidth, 0, currentColor, PlotObject.LINE)); - } - - /** Draws a line using a normalized 0-1, 0-1 coordinate system, - * with (0,0) at the top left and (1,1) at the lower right corner. - * This is the same coordinate system used by addLabel(x,y,label). - */ - public void drawNormalizedLine(double x1, double y1, double x2, double y2) { - allPlotObjects.add(new PlotObject(x1, y1, x2, y2, currentLineWidth, 0, currentColor, PlotObject.NORMALIZED_LINE)); - } - - /** Draws a line using the coordinate system defined by setLimits(). */ - public void drawDottedLine(double x1, double y1, double x2, double y2, int step) { - allPlotObjects.add(new PlotObject(x1, y1, x2, y2, currentLineWidth, step, currentColor, PlotObject.DOTTED_LINE)); - } - - /** Sets the font size for all following addLabel() etc. operations. The currently set font when - * displaying the plot determines the font of all labels & numbers. - * After the plot has been shown, sets the font for the numbers and the legend (if present). - * If the plot is hown already, call update() thereafter to make the change visible. */ - public void setFontSize(int size) { - setFont(-1, (float)size); - } - - /** Sets the font for all following addLabel() etc. operations. The currently set font when - * displaying the plot determines the font of all labels & numbers. - * After the plot has been shown, sets the font for the numbers and the legend (if present); - * use setFont(char, Font) to set these fonts individually. - * If the plot is hown already, call update() thereafter to make the change visible. */ - public void setFont(Font font) { - if (font == null) font = defaultFont; - currentFont = font; - if (plotDrawn) { - pp.frame.setFont(font); - if (pp.legend != null) - pp.legend.setFont(font); - } - } - - /** Sets the font size and style for all following addLabel() etc. operations. This leaves - * the font name and style of the previously used fonts unchanged. The currently set font - * when displaying the plot determines the font of the numbers at the axes. - * That font also sets the default label font size, which may be overridden by - * setAxisLabelFontSize or setXLabelFont, setYLabelFont. - * After the plot has been shown, sets the font for the numbers and the legend (if present); - * use setFont(char, Font) to set these fonts individually. - * Styles are defined in the Font class, e.g. Font.PLAIN, Font.BOLD. - * Set style to -1 to leave the style unchanged. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setFont(int style, float size) { - if (size < 9) size = 9f; - if (size > 36) size = 36f; - Font previousFont = nonNullFont(pp.frame.getFont(), currentFont); - if (style < 0) style = previousFont.getStyle(); - setFont(previousFont.deriveFont(style, size)); - } - - /** Sets the x and y label font size and style. Styles are defined - * in the Font class, e.g. Font.PLAIN, Font.BOLD. - * Set style to -1 to leave the style unchanged. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setAxisLabelFont(int style, float size) { - if (size < 9) size = 9f; - if (size > 33) size = 33f; - pp.xLabel.setFont(nonNullFont(pp.xLabel.getFont(), currentFont)); - pp.yLabel.setFont(nonNullFont(pp.yLabel.getFont(), currentFont)); - setXLabelFont(pp.xLabel.getFont().deriveFont(style < 0 ? pp.xLabel.getFont().getStyle() : style, size)); - setYLabelFont(pp.xLabel.getFont().deriveFont(style < 0 ? pp.yLabel.getFont().getStyle() : style, size)); - } - - /** Sets the xLabelFont; must not be null. If this method is not used, the last setFont - * of setFontSize call before displaying the plot determines the font, or if neither - * was called, the font size of the Plot Options is used. */ - public void setXLabelFont(Font font) { - pp.xLabel.setFont(font); - } - - /** Sets the yLabelFont; must not be null. */ - public void setYLabelFont(Font font) { - pp.yLabel.setFont(font); - } - - /** Determines whether to use antialiased text (default true) */ - public void setAntialiasedText(boolean antialiasedText) { - pp.antialiasedText = antialiasedText; - } - - /** Returns the font currently used (e.g. for the next 'addLabel') */ - public Font getCurrentFont() { - return currentFont != null ? currentFont : defaultFont; - } - - /** Returns the default font for the plot */ - public Font getDefaultFont() { - return defaultFont; - } - - /** Gets the font for xLabel ('x'), yLabel('y'), numbers ('f' for 'frame') or the legend ('l'). - * Returns null if the given PlotObject does not exist or its font is null */ - public Font getFont(char c) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - return plotObject.getFont(); - else - return null; - } - - /** Sets the font for xLabel ('x'), yLabel('y'), numbers ('f' for 'frame') or the legend ('l') */ - public void setFont(char c, Font font) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - plotObject.setFont(font); - } - - /** Gets the label String of the xLabel ('x'), yLabel('y') or the legend ('l'). - * Returns null if the given PlotObject does not exist or its label is null */ - public String getLabel(char c) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - return plotObject.label; - else - return null; - } - - /** Gets the flags of the xLabel ('x'), yLabel('y') or the legend ('l'). - * Returns -1 if the given PlotObject does not exist */ - public int getObjectFlags(char c) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - return plotObject.flags; - else - return -1; - } - - /** Get the x coordinates of the data set passed with the constructor (if not null) - * or otherwise of the data set of the first 'addPoints'. Returns null if neither exists */ - public float[] getXValues() { - PlotObject p = getMainCurveObject(); - return p==null ? null : p.xValues; - } - - /** Get the y coordinates of the data set passed with the constructor (if not null) - * or otherwise of the data set of the first 'addPoints'. Returns null if neither exists */ - public float[] getYValues() { - PlotObject p = getMainCurveObject(); - return p==null ? null : p.yValues; - } - - /** Get the data of the n-th Plot Object containing xy data in the sequence they were added - * (Other Plot Objects such as labels, arrows, lines, shapes and hidden PlotObjects are not counted). - * The array returned has elements [0] x data, [1] y data, [2] x error bars, [3] y error bars. - * If no error bars are given, the corresponding arrays are null. - * Returns null if there is no Plot Object with xy data with this index. - * @see #getDataObjectDesignations() - **/ - public float[][] getDataObjectArrays(int index) { - int i = 0; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type != PlotObject.XY_DATA || plotObject.hasFlag(PlotObject.HIDDEN)) continue; - if (index == i) - return new float[][] {plotObject.xValues, plotObject.yValues, plotObject.xEValues, plotObject.yEValues}; - i++; - } - return null; - } - - /** Gets an array with human-readable designations of the PlotObjects (curves, labels, ...) - * in the sequence they were added (the object passed with the constructor is first, - * even though it is plotted last). Hidden PlotObjects are included. **/ - public String[] getPlotObjectDesignations() { - return getPlotObjectDesignations(-1, true); - } - - /** Gets an array with human-readable designations of the PlotObjects containing xy data - * in the sequence they were added. Other Plot Objects such as labels, arrows, lines, - * shapes and hidden PlotObjects are not counted. - * (the object passed with the constructor is first, even though it is plotted last). */ - public String[] getDataObjectDesignations() { - return getPlotObjectDesignations(PlotObject.XY_DATA, false); - } - - /** Returns the number of PlotObjects (curves, labels, ...) passed with the constructor or added by 'add' or 'draw' methods. - * Legend, frame and axes (though internally PlotObjects) are not included */ - public int getNumPlotObjects() { - return allPlotObjects.size(); - } - - /** Returns the number of PlotObjects fitting the mask. - * Legend, frame and axes (though internally PlotObjects) are not included */ - int getNumPlotObjects(int mask, boolean includeHidden) { - int nObjects = 0; - for (PlotObject plotObject : allPlotObjects) - if ((plotObject.type & mask) != 0 && (includeHidden || !plotObject.hasFlag(PlotObject.HIDDEN))) - nObjects++; - return nObjects; - } - - /** Gets an array with human-readable designations of the PlotObjects with types fitting the mask - * (i.e., 'mask' should be a bitwise or of the types desired: XY_DATA = 1, ARROWS = 2, LINE = 4, - * NORMALIZED_LINE = 8, DOTTED_LINE = 16, LABEL = 32, NORMALIZED_LABEL = 64, LEGEND = 128) */ - String[] getPlotObjectDesignations(int mask, boolean includeHidden) { - int nObjects = getNumPlotObjects(mask, includeHidden); - String[] names = new String[nObjects]; - if (names.length == 0) return names; - int iData = 1, iArrow = 1, iLine = 1, iText = 1, iBox = 1, iShape = 1; //Human readable counters of each object type - int i = 0; - for (PlotObject plotObject : allPlotObjects) { - int type = plotObject.type; - if ((type & mask) == 0 || (!includeHidden && plotObject.hasFlag(PlotObject.HIDDEN))) continue; - String label = plotObject.label; - switch (type) { - case PlotObject.XY_DATA: - names[i] = "Data Set "+iData+": "+(plotObject.label != null ? - plotObject.label : "(" + plotObject.yValues.length + " data points)"); - iData++; - break; - case PlotObject.ARROWS: - names[i] = "Arrow Set "+iArrow+" ("+ plotObject.xValues.length + ")"; - iArrow++; - break; - case PlotObject.LINE: case PlotObject.NORMALIZED_LINE: case PlotObject.DOTTED_LINE: - String detail = ""; - if (type == PlotObject.DOTTED_LINE) detail = "dotted "; - if (plotObject.x ==plotObject.xEnd) detail += "vertical"; - else if (plotObject.y ==plotObject.yEnd) detail += "horizontal"; - if (detail.length()>0) detail = " ("+detail.trim()+")"; - names[i] = "Straight Line "+iLine+detail; - iLine++; - break; - case PlotObject.LABEL: case PlotObject.NORMALIZED_LABEL: - String text = plotObject.label.replaceAll("\n"," "); - if (text.length()>45) text = text.substring(0, 40)+"..."; - names[i] = "Text "+iText+": \""+text+'"'; - iText++; - break; - case PlotObject.SHAPES: - String s = plotObject.shapeType; - String[] words = s.split(" "); - names[i] = "Shapes (" + words[0] +") " + iShape; - iShape++; - break; - } - i++; - } - return names; - } - - /** Add the i-th PlotObject (in the sequence how they were added, including hidden ones) - * from another plot to this one. PlotObjects here refers to curves, arrows, labels etc. - * (not legend, axes and frame, though implemented as PlotObjects) - * Use 'update' to update the plot thereafter. - * @return Index of the plotObject added in the sequence they were added */ - public int addObjectFromPlot(Plot plot, int i) { - PlotObject plotObject = plot.getPlotObjectDeepClone(i); - plotObject.unsetFlag(PlotObject.CONSTRUCTOR_DATA); - allPlotObjects.add(plotObject); - int index = allPlotObjects.size() - 1; - return index; - } - - /** Get the style of the i-th PlotObject (curve, label, ...) in the sequence - * they were added (including hidden ones), as String with comma delimiters: - * Main Color, Secondary Color (or "none"), Line Width [, Symbol shape for XY_DATA] [,hidden] - * PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public String getPlotObjectStyle(int i) { - return getPlotObjectStyle(allPlotObjects.get(i)); - } - - String getPlotObjectStyle(PlotObject plotObject) { - String styleString = Colors.colorToString(plotObject.color) + "," + - Colors.colorToString(plotObject.color2) + "," + - plotObject.lineWidth; - if (plotObject.type == PlotObject.XY_DATA) - styleString += ","+SHAPE_NAMES[plotObject.shape]; - if (plotObject.hasFlag(PlotObject.HIDDEN)) - styleString += ",hidden"; - return styleString; - } - - /** Get the label the i-th PlotObject (in the sequence how they were added, including hidden ones). - * Returns null if no label. PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public String getPlotObjectLabel(int i) { - return allPlotObjects.get(i).label; - } - - /** Set the label the i-th PlotObject (in the sequence how they were added, including hidden ones) - * PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public void setPlotObjectLabel(int i, String label) { - allPlotObjects.get(i).label = label; - } - - /** Sets the style of the specified PlotObject (curve, label, etc.) from a - * comma-delimited string ("color1,color2,lineWidth[,symbol][,hidden]"), - * where "color2" can be "none" and "symbol" and "hidden" are optional. - * PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public void setStyle(int index, String style) { - if (index<0 || index>=allPlotObjects.size()) - throw new IllegalArgumentException("Index out of range"); - setPlotObjectStyle(allPlotObjects.get(index), style); - } - - public void setPlotObjectStyle(int i, String styleString) { - setStyle(i, styleString); - } - - void setPlotObjectStyle(PlotObject plotObject, String styleString) { - String[] items = styleString.split(","); - int nItems = items.length; - if (items[nItems-1].indexOf("hidden") >= 0) { - plotObject.setFlag(PlotObject.HIDDEN); - nItems = items.length - 1; - } else - plotObject.unsetFlag(PlotObject.HIDDEN); - plotObject.color = Colors.decode(items[0].trim(), plotObject.color); - plotObject.color2 = Colors.decode(items[1].trim(), null); - float lineWidth = plotObject.lineWidth; - if (items.length >= 3) try { - plotObject.lineWidth = Float.parseFloat(items[2].trim()); - } catch (NumberFormatException e) {}; - if (items.length >= 4 && plotObject.shape!=CUSTOM) - plotObject.shape = toShape(items[3].trim()); - updateImage(); - return; - } - - /** Returns the index of the first plot object with x,y data (points, line) or arrows - * with all data equal to those given. Returns or -1 is no such plot object exists. - * The array 'values' should contain the x, y, x error bar, yerror bar data. The 'values' array may have any size; - * only the data given are compared (e.g. for an array with length 2, there is no check for erro bars). - * Used when adding data from a table not to suggest the same data twice. */ - public int getPlotObjectIndex(float[][] values) { - return getPlotObjectIndex(PlotObject.XY_DATA|PlotObject.ARROWS, values); - } - - /** Returns the index of the first plot object fitting the type mask and with all data equal to those given. - * ('mask' should be a bitwise or of the types desired) - * Returns or -1 is no such plot object exists. - * The array 'values' should contain the x, y, x error bar, yerror bar data. The 'values' array may have any size; - * only the data given are compared (e.g. for an array with length 2, there is no check for erro bars). - * Used when adding data from a table not to suggest the same data twice. */ - int getPlotObjectIndex(int typeMask, float[][] values) { - for (int i=0; i(allPlotObjects.size()); - copyPlotObjectsVector(allPlotObjects, allPlotObjectsSnapshot); - } - - /** Restores the plot contents (not including axis formats etc) from the snapshot - * previously created by savePlotObjects(). See also killPlotObjectsSnapshot - * Use 'update' to update the plot thereafter. */ - public void restorePlotObjects() { - if (allPlotObjectsSnapshot != null) - copyPlotObjectsVector(allPlotObjectsSnapshot, allPlotObjects); - } - - /** Deletes the snapshot of the plot contents to make space */ - public void killPlotObjectsSnapshot() { - allPlotObjectsSnapshot = null; - } - - /** Creates a snapshot of the plot properties (formatting, range etc., not PlotObjects such as data and corresponding curves etc.), - * for later undo by restorePlotProperties. See also killPlotPropertiesSnapshot */ - public void savePlotPlotProperties() { - pp.rangeMinMax = currentMinMax; - ppSnapshot = pp.deepClone(); - } - - /** Restores the plot properties (formatting, range etc., not PlotObjects such as data and corresponding curves etc.) - * from a snapshot previously created by savePlotPlotProperties. See also killPlotPropertiesSnapshot. - * Use 'update' to update the plot thereafter. */ - public void restorePlotProperties() { - pp = ppSnapshot.deepClone(); - System.arraycopy(pp.rangeMinMax, 0, currentMinMax, 0, Math.min(pp.rangeMinMax.length, currentMinMax.length)); - } - - /** Deletes the snapshot of the plot properties to make space */ - public void killPlotPropertiesSnapshot() { - ppSnapshot = null; - } - - private void copyPlotObjectsVector(Vector src, Vectordest) { - if (dest.size() > 0) dest.removeAllElements(); - for (PlotObject plotObject : src) - dest.add(plotObject.deepClone()); - } - - PlotObject getPlotObjectDeepClone(int i) { - return allPlotObjects.get(i).deepClone(); - } - - /** Sets the plot range to the initial value determined from minima&maxima or given by setLimits. - * Updates the image if existing and updateImg is true */ - public void setLimitsToDefaults(boolean updateImg) { - saveMinMax(); - System.arraycopy(defaultMinMax, 0, currentMinMax, 0, defaultMinMax.length); - if (plotDrawn && updateImg) updateImage(); - } - - /** Sets the plot range to encompass all data. Updates the image if existing and updateImg is true. */ - public void setLimitsToFit(boolean updateImg) { - saveMinMax(); - currentMinMax = getMinAndMax(true, ALL_AXES_RANGE); - if (Double.isNaN(defaultMinMax[0]) && Double.isNaN(defaultMinMax[2])) //no range at all so far - System.arraycopy(currentMinMax, 0, defaultMinMax, 0, Math.min(currentMinMax.length, defaultMinMax.length)); - - enlargeRange(currentMinMax); //avoid points exactly at the border - //System.arraycopy(currentMinMax, 0, defaultMinMax, 0, currentMinMax.length); - if (plotDrawn && updateImg) updateImage(); - } - - /** reverts plot range to previous values and updates the image */ - public void setPreviousMinMax() { - if (Double.isNaN(savedMinMax[0])) return; //no saved values yet - double[] swap = new double[currentMinMax.length]; - System.arraycopy(currentMinMax, 0, swap, 0, currentMinMax.length); - System.arraycopy(savedMinMax, 0, currentMinMax, 0, currentMinMax.length); - System.arraycopy(swap, 0, savedMinMax, 0, currentMinMax.length); - updateImage(); - } - - /** Draws the plot (if not done before) in an ImageProcessor and returns the ImageProcessor with the plot. */ - public ImageProcessor getProcessor() { - draw(); - return ip; - } - - /** Returns the plot as an ImagePlus. - * If an ImagePlus for this plot already exists, displays the plot in that ImagePlus and returns it. */ - public ImagePlus getImagePlus() { - if (stack != null) { - if (imp != null) - return imp; - else { - imp = new ImagePlus(title, stack); - adjustCalibration(imp.getCalibration()); - return imp; - } - } - if (plotDrawn) - updateImage(); - else - draw(); - if (imp != null) { - if (imp.getProcessor() != ip) - imp.setProcessor(ip); - return imp; - } else { - ImagePlus imp = new ImagePlus(title, ip); - setImagePlus(imp); - return imp; - } - } - - /** Sets the ImagePlus where the plot will be displayed. If the ImagePlus is not - * known otherwise (e.g. from getImagePlus), this is needed for changes such as - * zooming in to work correctly. It also sets the calibration of the ImagePlus. - * The ImagePlus is not displayed or updated unless its ImageProcessor is - * no that of the current Plot (then it gets this ImageProcessor). - * Does nothing if imp is unchanged and has the ImageProcessor of this plot. - * 'imp' may be null to disconnect the plot from its ImagePlus. - * Does nothing for Plot Stacks. */ - public void setImagePlus(ImagePlus imp) { - if (imp != null && imp == this.imp && imp.getProcessor() == ip) - return; - if (stack != null) - return; - if (this.imp != null) - this.imp.setProperty(PROPERTY_KEY, null); - this.imp = imp; - if (imp != null) { - imp.setIgnoreGlobalCalibration(true); - adjustCalibration(imp.getCalibration()); - imp.setProperty(PROPERTY_KEY, this); - if (ip != null && imp.getProcessor() != ip) - imp.setProcessor(ip); - } - } - - /** Adjusts a Calibration object to fit the current axes. - * For log axes, the calibration refers to the base-10 logarithm of the value */ - public void adjustCalibration(Calibration cal) { - if (xMin == xMax) //tiff images can't handle infinity in scale, see TiffEncoder.writeScale - xScale = 1e6; - if (yMin == yMax) - yScale = 1e6; - cal.xOrigin = xBasePxl-xMin*xScale; - cal.pixelWidth = 1.0/Math.abs(xScale); //Calibration must not have negative pixel size - cal.yOrigin = yBasePxl+yMin*yScale; - cal.pixelHeight = 1.0/Math.abs(yScale); - cal.setInvertY(yScale >= 0); - cal.setXUnit(" "); // avoid 'pixels' for scaled units - if (xMin == xMax) - xScale = Double.POSITIVE_INFINITY; - if (yMin == yMax) - yScale = Double.POSITIVE_INFINITY; - } - - /** Displays the plot in a PlotWindow. - * Plot stacks are shown in a StackWindow, not in a PlotWindow; - * in this case the return value is null (use getImagePlus().getWindow() instead). - * Also returns null in BatchMode. Note that the PlotWindow might get closed - * immediately if its 'listValues' and 'autoClose' flags are set. - * @see #update() - */ - public PlotWindow show() { - PlotVirtualStack stack = getStack(); - if (stack!=null) { - getImagePlus().show(); - return null; - } - if ((IJ.macroRunning() && IJ.getInstance()==null) || Interpreter.isBatchMode()) { - imp = getImagePlus(); - imp.setPlot(this); - WindowManager.setTempCurrentImage(imp); - if (getMainCurveObject() != null) { - imp.setProperty("XValues", getXValues()); // Allows values to be retrieved by - imp.setProperty("YValues", getYValues()); // by Plot.getValues() macro function - } - Interpreter.addBatchModeImage(imp); - return null; - } - if (imp != null) { - Window win = imp.getWindow(); - if (win instanceof PlotWindow && win.isVisible()) { - updateImage(); // show in existing window - return (PlotWindow)win; - } else - setImagePlus(null); - } - PlotWindow pw = new PlotWindow(this); //note: this may set imp to null if pw has listValues and autoClose are set - if (IJ.isMacro() && imp!=null) // wait for plot to be displayed - IJ.selectWindow(imp.getID()); - return pw; - } - - /** - * Appends the current plot to a virtual stack and resets allPlotObjects - * for next slice - * N. Vischer - */ - public void addToStack() { - if (stack==null) - stack = new PlotVirtualStack(getSize().width,getSize().height); - draw(); - stack.addPlot(this); - IJ.showStatus("addToPlotStack: "+stack.size()); - allPlotObjects.clear(); - } - - /** Alias for addToStack(). */ - public void appendToStack() { - addToStack(); - } - - /** Returns the virtual stack created by addToStack(). */ - public PlotVirtualStack getStack() { - IJ.showStatus(""); - return stack; - } - - /** Draws the plot specified for the first time. Does nothing if the plot has been drawn already. - * Call getProcessor to retrieve the ImageProcessor with it. - * Does no action with respect to the ImagePlus (if any) */ - public void draw() { - //IJ.log("draw(); plotDrawn="+plotDrawn); - if (plotDrawn) return; - getInitialMinAndMax(); - pp.frame.setFont(nonNullFont(pp.frame.getFont(), currentFont)); //make sure we have a number font for calculating the margins - getBlankProcessor(); - drawContents(ip); - } - - /** Freezes or unfreezes the plot. In the frozen state, the plot cannot be resized or updated, - * and the Plot class does no modifications to the ImageProcessor. - * Changes are recorded nevertheless and become effective with setFrozen(false). */ - public void setFrozen(boolean frozen) { - pp.isFrozen = frozen; - if (!pp.isFrozen) { // unfreeze operations ... - if (imp != null && ip != null) { - ImageCanvas ic = imp.getCanvas(); - if (ic instanceof PlotCanvas) { - ((PlotCanvas)ic).resetMagnification(); - imp.setTitle(imp.getTitle()); //update magnification in title - } - Undo.setup(Undo.TRANSFORM, imp); - } - updateImage(); - ImageWindow win = imp == null ? null : imp.getWindow(); - if (win != null) win.updateImage(imp); //show any changes made during the frozen state - } - } - - public boolean isFrozen() { - return pp.isFrozen; - } - - /** Draws the plot again, ignored if the plot has not been drawn before or the plot is frozen. */ - public void update() { - updateImage(); - } - - /** Draws the plot again, ignored if the plot has not been drawn before or the plot is frozen. - * If the ImagePlus exist, updates it and its calibration. */ - public void updateImage() { - if (!plotDrawn || pp.isFrozen) return; - getBlankProcessor(); - drawContents(ip); - if (imp == null || stack != null) return; - adjustCalibration(imp.getCalibration()); - imp.updateAndDraw(); - if (ip != imp.getProcessor()) - imp.setProcessor(ip); - } - - /** Returns the rectangle where the data are plotted. - * This rectangle includes the black outline frame at the top and left, but not at the bottom - * and right (when the frame is plotted with 1 pxl width). - * The image scale is its width or height in pixels divided by the data range in x or y. */ - public Rectangle getDrawingFrame() { - if (frame == null) - getBlankProcessor(); //setup frame if not done yet - return new Rectangle(frame.x, frame.y, frameWidth, frameHeight); - } - - /** Creates a new high-resolution plot by scaling it and displays that plot if showIt is true. - * title may be null, then a default title is used. */ - public ImagePlus makeHighResolution(String title, float scale, boolean antialiasedText, boolean showIt) { - Plot hiresPlot = null; - try { - hiresPlot = (Plot)clone(); //shallow clone, thus arrays&objects are not cloned, but they will be used only now - } catch (Exception e) {return null;} - hiresPlot.ip = null; - hiresPlot.imp = null; - hiresPlot.pp = pp.clone(); - if (!plotDrawn) hiresPlot.getInitialMinAndMax(); - hiresPlot.setScale(scale); - hiresPlot.setAntialiasedText(antialiasedText); - hiresPlot.defaultMinMax = currentMinMax.clone(); - ImageProcessor hiresIp = hiresPlot.getProcessor(); - if (title == null || title.length() == 0) - title = getTitle()+"_HiRes"; - title = WindowManager.makeUniqueName(title); - ImagePlus hiresImp = new ImagePlus(title, hiresIp); - Calibration cal = hiresImp.getCalibration(); - hiresPlot.adjustCalibration(cal); - if (showIt) { - hiresImp.setIgnoreGlobalCalibration(true); - hiresImp.show(); - } - hiresPlot.dispose(); //after drawing, we don't need the plot of the high-resolution image any more - return hiresImp; - } - - /** Releases the ImageProcessor and ImagePlus associated with the plot. - * May help garbage collection because some garbage collectors - * are said to be inefficient with circular references. */ - public void dispose() { - if (imp != null) - imp.setProperty(PROPERTY_KEY, null); - imp = null; - ip = null; - } - - /** Converts pixels to calibrated coordinates. In contrast to the image calibration, also - * works with log axes and inverted x axes */ - public double descaleX(int x) { - if (xMin == xMax) return xMin; - double xv = (x-xBasePxl)/xScale + xMin; - if (logXAxis) xv = Math.pow(10, xv); - return xv; - } - - /** Converts pixels to calibrated coordinates. In contrast to the image calibration, also - * works with log axes */ - public double descaleY(int y) { - if (yMin == yMax) return yMin; - double yv = (yBasePxl-y)/yScale +yMin; - if (logYAxis) yv = Math.pow(10, yv); - return yv; - } - - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log x axis and inverted x axis */ - public double scaleXtoPxl(double x) { - if (xMin == xMax) { - if (x==xMin) return xBasePxl; - else return x>xMin ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; - } - if (logXAxis) - return xBasePxl+(Math.log10(x)-xMin)*xScale; - else - return xBasePxl+(x-xMin)*xScale; - } - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log y axis */ - public double scaleYtoPxl(double y) { - if (yMin == yMax) { - if (y==xMin) return yBasePxl; - else return y>yMin ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; - } - if (logYAxis) - return yBasePxl-(Math.log10(y)-yMin)*yScale; - else - return yBasePxl-(y-yMin)*yScale; - } - - /** Converts calibrated coordinates to integer pixel coordinates. */ - private int scaleX(double x) { - double xPxl = scaleXtoPxl(x); - return pxlToInt(xPxl); - } - - /** Converts calibrated coordinates to integer pixel coordinates. */ - private int scaleY(double y) { - double yPxl = scaleYtoPxl(y); - return pxlToInt(yPxl); - } - - /** Converts a double-precision pixel coordinate value 'v' to integer, - * with overflow handling: Limits are +/-Integer.MAX_VALUE/2. - * This ensures that the difference between two points is in the range - * that can be handled by ImageProcessor.moveTo. - * NaN values are converted to -Integer.MAX_VALUE (negative). - **/ - private int pxlToInt(double v) { - if (Double.isNaN(v)) - return -Integer.MAX_VALUE; - else if (v > -Integer.MAX_VALUE/2 && v < Integer.MAX_VALUE/2) - return (int)Math.round(v); - else - return v > 0 ? Integer.MAX_VALUE/2 : -Integer.MAX_VALUE/2; - } - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log axes and inverted x axes. Returns a large number instead NaN for log x axis and zero or negative x */ - private int scaleXWithOverflow(double x) { - if (!logXAxis || x>0) - return scaleX(x); - else - return xScale > 0 ? -1000000 : 1000000; - } - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log axes and inverted x axes. Returns a large number instead NaN for log y axis and zero or negative y */ - private int scaleYWithOverflow(double y) { - if (!logYAxis || y>0) - return scaleY(y); - else - return yScale > 0 ? 1000000 : -1000000; - } - - /** Scales a value of the original plot for a high-resolution plot. Returns an integer number of pixels >=1 */ - int sc(float length) { - int pixels = (int)(length*scale + 0.5); - if (pixels < 1) pixels = 1; - return pixels; - } - - /** Scales a font of the original plot for a high-resolution plot. */ - Font scFont(Font font) { - float size = font.getSize2D(); - return scale==1 ? font : font.deriveFont(size*scale); - } - - /** Returns whether the plot requires color (not grayscale) */ - boolean isColored() { - for (PlotObject plotObject : allPlotObjects) - if (isColored(plotObject.color) || isColored(plotObject.color2)) - return true; - for (PlotObject plotObject : pp.getAllPlotObjects()) - if (plotObject != null && (isColored(plotObject.color) || isColored(plotObject.color2))) - return true; - return false; - } - - /** Whether a color is non-grayscale, which requires color (not grayscale) for the plot */ - boolean isColored(Color c) { - if (c == null) return false; - return c.getRed() != c.getGreen() || c.getGreen() != c.getBlue(); - } - - /** Draws the plot contents (all PlotObjects and the frame and legend), without axes etc. */ - void drawContents(ImageProcessor ip) { - makeRangeGetSteps(); - ip.setColor(Color.black); - ip.setLineWidth(sc(1)); - float lineWidth = 1; - Color color = Color.black; - Font font = defaultFont; - - // draw all the plot objects in the sequence they were added, except for the one of the constructor - for (PlotObject plotObject : allPlotObjects) - if (!plotObject.hasFlag(PlotObject.CONSTRUCTOR_DATA)) { - //properties lineWidth, Font, Color set for one object remain for the next object unless changed - if (plotObject.lineWidth > 0) - lineWidth = plotObject.lineWidth; - else - plotObject.lineWidth = lineWidth; - if (plotObject.color != null) - color = plotObject.color; - else - plotObject.color = color; - if (plotObject.getFont() != null) - font = plotObject.getFont(); - else - plotObject.setFont(font); - //IJ.log("type="+plotObject.type+" color="+plotObject.color); - drawPlotObject(plotObject, ip); - } - - // draw the line passed with the constructor last, using the settings present when calling 'draw' - if (allPlotObjects.size()>0 && allPlotObjects.get(0).hasFlag(PlotObject.CONSTRUCTOR_DATA)) { - PlotObject mainPlotObject = allPlotObjects.get(0); - if (mainPlotObject.lineWidth == 0) - mainPlotObject.lineWidth = currentLineWidth == 0 ? 1 : currentLineWidth; - lineWidth = mainPlotObject.lineWidth; - if (mainPlotObject.color == null) - mainPlotObject.color = currentColor == null ? Color.black : currentColor; - drawPlotObject(mainPlotObject, ip); - } else { - if (currentLineWidth > 0) lineWidth = currentLineWidth; //linewidth when drawing determines frame linewidth - } - - // finally draw the frame & legend - if (!plotDrawn && pp.frame.lineWidth==DEFAULT_FRAME_LINE_WIDTH) { //when modifying PlotObjects styles later, don't change the frame line width any more - pp.frame.lineWidth = lineWidth; - if (pp.frame.lineWidth == 0) pp.frame.lineWidth = 1; - if (pp.frame.lineWidth > 3) pp.frame.lineWidth = 3; - } - ip.setLineWidth(sc(pp.frame.lineWidth)); - ip.setColor(pp.frame.color); - int x2 = frame.x + frame.width - 1; - int y2 = frame.y + frame.height - 1; - ip.moveTo(frame.x, frame.y); // draw the frame. Can't use ip.drawRect because it is inconsistent for different lineWidths - ip.lineTo(x2, frame.y); - ip.lineTo(x2, y2); - ip.lineTo(frame.x, y2); - ip.lineTo(frame.x, frame.y); - if (pp.legend != null && (pp.legend.flags & LEGEND_POSITION_MASK) != 0) - drawPlotObject(pp.legend, ip); - - plotDrawn = true; - } - - /** Creates the processor if not existing, clears the background and prepares - * it for plotting. Also called by the PlotWindow class to prepare the window. */ - ImageProcessor getBlankProcessor() { - makeMarginValues(); - //IJ.log("Plot.getBlankPr preferredH="+preferredPlotHeight+" pp.h="+pp.height); - if (pp.width <= 0 || pp.height <= 0) { - pp.width = sc(preferredPlotWidth) + leftMargin + rightMargin; - pp.height = sc(preferredPlotHeight) + topMargin + bottomMargin; - } - frameWidth = pp.width - (leftMargin + rightMargin); - frameHeight = pp.height - (topMargin + bottomMargin); - boolean isColored = isColored(); //color, not grayscale required? - if (ip == null || pp.width != ip.getWidth() || pp.height != ip.getHeight() || (isColored != (ip instanceof ColorProcessor))) { - if (isColored) { - ip = new ColorProcessor(pp.width, pp.height); - } else { - ip = new ByteProcessor(pp.width, pp.height); - invertedLut = Prefs.useInvertingLut && !Interpreter.isBatchMode() && IJ.getInstance()!=null; - if (invertedLut) ip.invertLut(); - } - if (imp != null && stack == null) - imp.setProcessor(ip); - } - if (ip instanceof ColorProcessor) - Arrays.fill((int[])(ip.getPixels()), 0xffffff); - else - Arrays.fill((byte[])(ip.getPixels()), invertedLut ? (byte)0 : (byte)0xff); - - ip.setFont(scFont(defaultFont)); - ip.setLineWidth(sc(1)); - ip.setAntialiasedText(pp.antialiasedText); - frame = new Rectangle(leftMargin, topMargin, frameWidth+1, frameHeight+1); - if (pp.frame.color2 != null) { //background color - ip.setColor(pp.frame.color2); - ip.setRoi(frame); - ip.fill(); - ip.resetRoi(); - } - ip.setColor(Color.black); - return ip; - } - - /** Calculates the margin sizes and sets the class variables accordingly */ - void makeMarginValues() { - Font font = nonNullFont(pp.frame.getFont(), currentFont); - float marginScale = 0.1f + 0.9f*font.getSize2D()/12f; - if (marginScale < 0.7f) marginScale = 0.7f; - if (marginScale > 2f) marginScale = 2f; - int addHspace = (int)Tools.getNumberFromList(pp.frame.options, "addhspace="); //user-defined extra space - int addVspace = (int)Tools.getNumberFromList(pp.frame.options, "addvspace="); - leftMargin = sc(LEFT_MARGIN*marginScale + addHspace); - rightMargin = sc(RIGHT_MARGIN*marginScale + addHspace); - topMargin = sc(TOP_MARGIN*marginScale + addVspace); - bottomMargin = sc(BOTTOM_MARGIN*marginScale + 2 + addVspace); - if(pp != null && pp.xLabel != null && pp.xLabel.getFont() != null){ - float numberSize = font.getSize2D(); - float labelSize = pp.xLabel.getFont().getSize2D(); - float extraHeight = 1.5f *(labelSize - numberSize); - if(extraHeight > 0){ - bottomMargin += sc(extraHeight); - leftMargin += sc(extraHeight); - } - } - } - - /** Calculate the actual range, major step interval and set variables for data <-> pixels scaling */ - double[] makeRangeGetSteps() { - steps = new double[2]; - logXAxis = hasFlag(X_LOG_NUMBERS); - logYAxis = hasFlag(Y_LOG_NUMBERS); - - for (int i=0; i MIN_LOG_RATIO || 1./rangeRatio > MIN_LOG_RATIO) || - !(currentMinMax[i] > 10*Float.MIN_VALUE) || !(currentMinMax[i+1] > 10*Float.MIN_VALUE)) - logAxis = false; - } - //for log axes, temporarily work on the logarithm - if (logAxis) { - currentMinMax[i] = Math.log10(currentMinMax[i]); - currentMinMax[i+1] = Math.log10(currentMinMax[i+1]); - } - // calculate grid or major tick interval - if ((i==0 && !simpleXAxis()) || (i==2 && !simpleYAxis())) { - int minGridspacing = i==0 ? MIN_X_GRIDSPACING : MIN_Y_GRIDSPACING; - int frameSize = i==0 ? frameWidth : frameHeight; - double step = Tools.getNumberFromList(pp.frame.options, i==0 ? "xinterval=" : "yinterval="); //user-defined interval - if (!Double.isNaN(step)) { - int nSteps = (int)(Math.floor(currentMinMax[i+1]/step+1e-10) - Math.ceil(currentMinMax[i]/step-1e-10)); - if (nSteps < 1) step = Double.NaN; //user-suppied interval too large, less than two numbers would be shown - if ((i==0 && nSteps*sc(minGridspacing)*0.5 > frameSize) || i!=0 && nSteps*sc(pp.frame.getFont().getSize()) > frameSize) - step = Double.NaN; //user-suppied interval too small, too many numbers would be shown - } - if (Double.isNaN(step)) { //automatic interval - step = Math.abs((currentMinMax[i+1] - currentMinMax[i]) * - Math.max(1.0/maxIntervals, (float)sc(minGridspacing)/frameSize+(maxIntervals>12 ? 0.02 : 0.06))); //the smallest allowable step - step = niceNumber(step); - } - if (logAxis && step < 1) - step = 1; - steps[i/2] = step; - //modify limits to grid or minor ticks if desired - boolean force2grid = hasFlag(i==0 ? X_FORCE2GRID : Y_FORCE2GRID) && !ignoreForce2Grid; - if (force2grid) { - int i1 = (int)Math.floor(Math.min(currentMinMax[i],currentMinMax[i+1])/step+1.e-10); - int i2 = (int)Math.ceil (Math.max(currentMinMax[i],currentMinMax[i+1])/step-1.e-10); - if (currentMinMax[i+1] > currentMinMax[i]) { // care about inverted axes with max= 0.999) { //don't snap on log axis if minor ticks are not full decades - // currentMinMax[i] = stepForSnap * Math.round(currentMinMax[i]/stepForSnap); - // currentMinMax[i+1] = stepForSnap * Math.round(currentMinMax[i+1]/stepForSnap); - // } - } - } - if (i==0) { - xMin = currentMinMax[i]; - xMax = currentMinMax[i+1]; - logXAxis = logAxis; - } else { - yMin = currentMinMax[i]; - yMax = currentMinMax[i+1]; - logYAxis = logAxis; - } - if (logAxis) { - currentMinMax[i] = Math.pow(10, currentMinMax[i]); - currentMinMax[i+1] = Math.pow(10, currentMinMax[i+1]); - } - } - //snapToMinorGrid = false; - ignoreForce2Grid = false; - - // calculate what we need to convert the data to screen pixels - xBasePxl = leftMargin; - yBasePxl = topMargin + frameHeight; - xScale = frameWidth/(xMax-xMin); - if (!(xMax-xMin!=0.0)) //if range==0 (all data the same), or NaN shift zero level so one can see the curve - xBasePxl += sc(10); - yScale = frameHeight/(yMax-yMin); - if (!(yMax-yMin!=0.0)) - yBasePxl -= sc(10); - //IJ.log("x,yScale="+(float)xScale+","+(float)yScale+" xMin,max="+(float)xMin+","+(float)xMax+" yMin.max="+(float)yMin+","+(float)yMax); - - drawAxesTicksGridNumbers(steps); - return steps; - } - - public void redrawGrid(){ - if (ip != null) { - ip.setColor(Color.black); - drawAxesTicksGridNumbers(steps); - ip.setColor(Color.black); - } - } - - /** Gets the initial plot limits (i.e., x&y ranges). For compatibility with previous versions of ImageJ, - * only the first PlotObject (with numeric data) is used to determine the limits. */ - void getInitialMinAndMax() { - int axisRangeFlags = 0; - if (Double.isNaN(defaultMinMax[0])) axisRangeFlags |= X_RANGE; - if (Double.isNaN(defaultMinMax[2])) axisRangeFlags |= Y_RANGE; - if (axisRangeFlags != 0) { - defaultMinMax = getMinAndMax(false, axisRangeFlags); - enlargeRange(defaultMinMax); - } - setLimitsToDefaults(false); //use the range values to start with, but don't draw yet - } - - /** Gets the minimum and maximum values from the first XY_DATA or ARROWS plotObject or all such plotObjects; - * axisRangeFlags determine for which axis to calculate the min&max (X_RANGE for x axis, Y_RANGE for y axis); - * for the other axes the limit is taken from defaultMinMax - * Array elements returned are xMin, xMax, yMin, yMax. Also sets enlargeRange to tell which limits should be enlarged - * beyond the minimum or maximum of the data */ - double[] getMinAndMax(boolean allObjects, int axisRangeFlags) { - boolean invertedXAxis = currentMinMax[1] < currentMinMax[0]; - boolean invertedYAxis = currentMinMax[3] < currentMinMax[2]; - double xSign = invertedXAxis ? -1 : 1; - double ySign = invertedYAxis ? -1 : 1; - double[] allMinMax = new double[]{xSign*Double.MAX_VALUE, -xSign*Double.MAX_VALUE, ySign*Double.MAX_VALUE, -ySign*Double.MAX_VALUE}; - for (int i=0; i>i/2) & 1)==0) //keep default min & max for this axis - allMinMax[i] = defaultMinMax[i]; - enlargeRange = new int[allMinMax.length]; - for (PlotObject plotObject : allPlotObjects) { - if ((plotObject.type == PlotObject.XY_DATA || plotObject.type == PlotObject.ARROWS) && !plotObject.hasFlag(PlotObject.HIDDEN)) { - getMinAndMax(allMinMax, enlargeRange, plotObject, axisRangeFlags); - if (!allObjects) break; - } - } - if ((axisRangeFlags & X_RANGE) != 0) { - String[] xCats = labelsInBraces('x'); // if we have categories at the axis, make some space for this text - if (xCats != null) { - allMinMax[0] = Math.min(allMinMax[0], -0.5); - allMinMax[1] = Math.min(allMinMax[1], xCats.length+0.5); - } - } - if ((axisRangeFlags & Y_RANGE) != 0) { - String[] yCats = labelsInBraces('y'); - if (yCats != null) { - allMinMax[2] = Math.min(allMinMax[2], -0.5); - allMinMax[3] = Math.min(allMinMax[3], yCats.length+0.5); - } - } - if (allMinMax[0]==Double.MAX_VALUE && allMinMax[1]==-Double.MAX_VALUE) { // no x values at all? keep previous - allMinMax[0] = defaultMinMax[0]; - allMinMax[1] = defaultMinMax[1]; - } - if (allMinMax[2]==Double.MAX_VALUE && allMinMax[3]==-Double.MAX_VALUE) { // no y values at all? keep previous - allMinMax[2] = defaultMinMax[2]; - allMinMax[3] = defaultMinMax[3]; - } - return allMinMax; - } - - /** Enlarges the current minimum and maximum ranges to include the data range of the last plotObject added, - * if it is an XY_DATA or ARROWS plotObject. - * Does not set the new limits as default, does not redraw the plot. */ - void fitRangeToLastPlotObject() { - if (allPlotObjects.size() < 1) return; - PlotObject plotObject = allPlotObjects.lastElement(); - if (Double.isNaN(currentMinMax[0]) || Double.isNaN(currentMinMax[2])) { // no range determined yet? - setLimitsToFit(false); - } else { //we have min&max already, just extend the range if necessary - enlargeRange = new int[currentMinMax.length]; - getMinAndMax(currentMinMax, enlargeRange, plotObject, ALL_AXES_RANGE); - enlargeRange(currentMinMax); - } - } - - /** Gets the minimum and maximum values from an XY_DATA or ARROWS plotObject; - * axisRangeFlags determine for which axis (X_RANGE for x axis, Y_RANGE for y axis) - * The minimum modifies allMinAndMax[0] (x), allMinAndMax[2] (y); the maximum modifies [1], [3]. - * If allMinAndMax values are modified, the corresponding enlargeRange array elements are also set */ - void getMinAndMax(double[] allMinAndMax, int[] enlargeRange, PlotObject plotObject, int axisRangeFlags) { - boolean invertedXAxis = currentMinMax[1] < currentMinMax[0]; - boolean invertedYAxis = currentMinMax[3] < currentMinMax[2]; - if (plotObject.type == PlotObject.XY_DATA) { - if ((axisRangeFlags & X_RANGE) != 0) { - int suggestedEnlarge = 0; - if (!(plotObject.shape == LINE || plotObject.shape == FILLED) || plotObject.yEValues != null) - suggestedEnlarge = ALWAYS_ENLARGE; //enlarge to make space at the obrders (we don't try to keep x=0 at the frame border) - getMinAndMax(allMinAndMax, enlargeRange, suggestedEnlarge, 0, plotObject.xValues, plotObject.xEValues, invertedXAxis); - if ((plotObject.shape == BAR || plotObject.shape == SEPARATED_BAR)&& plotObject.xValues.length > 1) { - int n = plotObject.xValues.length; - allMinAndMax[0] -= 0.5 * Math.abs(plotObject.xValues[1] - plotObject.xValues[0]); - allMinAndMax[1] += 0.5 * Math.abs(plotObject.xValues[n - 1] - plotObject.xValues[n - 2]); - } - } - if ((axisRangeFlags & Y_RANGE) != 0) { - int suggestedEnlarge = 0; - if (plotObject.shape==DOT || plotObject.xEValues != null) //these can't be seen if merging with the frame - suggestedEnlarge = ALWAYS_ENLARGE; - else if (!(plotObject.shape == LINE || plotObject.shape == FILLED)) - suggestedEnlarge = USUALLY_ENLARGE; - getMinAndMax(allMinAndMax, enlargeRange, suggestedEnlarge, 2, plotObject.yValues, plotObject.yEValues, invertedYAxis); - if ((plotObject.shape == BAR || plotObject.shape == SEPARATED_BAR) && - (allMinAndMax[2] > 0 && allMinAndMax[3]/allMinAndMax[2] >= 2) && !logYAxis) - allMinAndMax[2] = 0; // for bar plots, y min = 0 unless values differ less than a factor of 2 - } - } else if (plotObject.type == PlotObject.ARROWS) { - if ((axisRangeFlags & X_RANGE) != 0) { - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 0, plotObject.xValues, null, invertedXAxis); - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 0, plotObject.xEValues, null, invertedXAxis); - } - if ((axisRangeFlags & Y_RANGE) != 0) { - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 2, plotObject.yValues, null, invertedYAxis); - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 2, plotObject.yEValues, null, invertedYAxis); - } - } - } - - /** Gets the minimum and maximum values for a dataset (one direction, x or y), - * taking error bars (if not null) into account. - * The minimum modifies allMinAndMax[axisIndex] the maximum modifies allMinAndMax[axisIndex+1]. - * Also cares about whether the range should be enlarged to avoid hiding markers at the borders: - * suggestedEnlarge is 0 for lines or a suggestion for the data type; if the allMinAndMax is - * range is extended, the corresponding enlargeRange item is set accordingly */ - void getMinAndMax(double[] allMinAndMax, int[] enlargeRange, int suggestedEnlarge, - int axisIndex, float[] data, float[] errorBars, boolean invertedAxis) { - int nMinEqual = 0, nMaxEqual = 0; - int minIndex = invertedAxis ? axisIndex+1 : axisIndex; // index of 'min' value in allMinAndMax, enlargeRange - int maxIndex = invertedAxis ? axisIndex : axisIndex+1; - for (int i=0; i0 && i allMinAndMax[maxIndex] && !Double.isInfinite(v1)) { - allMinAndMax[maxIndex] = v2; - nMaxEqual = 1; - enlargeRange[maxIndex] = suggestedEnlarge; - if (suggestedEnlarge == 0 && ((i>0 && i10%) at min or max? Add extra space at borders ('usually', i.e. unless limit is zero) - if (enlargeRange[minIndex] == 0 && nMinEqual > 2 && nMinEqual*10 > data.length) - enlargeRange[minIndex] = USUALLY_ENLARGE; - if (enlargeRange[maxIndex] == 0 && nMaxEqual > 2 && nMaxEqual*10 > data.length) - enlargeRange[maxIndex] = USUALLY_ENLARGE; - //all data at min or max? Always add space to avoid hiding the line behind the frame - if (nMinEqual == data.length) - enlargeRange[minIndex] = ALWAYS_ENLARGE; - if (nMaxEqual == data.length) - enlargeRange[maxIndex] = ALWAYS_ENLARGE; - //same min or max as for current data set found already previously, but not asking yet for added space at borders? - if (nMinEqual>0 && enlargeRange[minIndex]0 && enlargeRange[maxIndex] frame.x && x < frame.x + frame.width; - boolean insideY = y > frame.y && y < frame.y + frame.height; - if (!insideX && !insideY) { - insideX = true; - insideY = true; - x = frame.x + frame.width / 2; - y = frame.y + frame.height / 2; - } - int leftPart = x - frame.x; - int rightPart = frame.x + frame.width - x; - int highPart = y - frame.y; - int lowPart = frame.y + frame.height - y; - - if (insideX) { - currentMinMax[0] = descaleX((int) (x - leftPart / zoomFactor)); - currentMinMax[1] = descaleX((int) (x + rightPart / zoomFactor)); - } - if (insideY) { - currentMinMax[2] = descaleY((int) (y + lowPart / zoomFactor)); - currentMinMax[3] = descaleY((int) (y - highPart / zoomFactor)); - } - updateImage(); - if (wasLogX != logXAxis ){//log-lin was automatically changed - int changedX = (int) scaleXtoPxl(plotX); - int left = changedX - leftPart; - int right = changedX + rightPart; - currentMinMax[0] = descaleX(left); - currentMinMax[1] = descaleX(right); - updateImage(); - } - if (wasLogY != logYAxis){//log-lin was automatically changed - int changedY = (int) scaleYtoPxl(plotY); - int bottom = changedY + lowPart; - int top = changedY + highPart; - currentMinMax[2] = descaleY(bottom); - currentMinMax[3] = descaleY(top); - updateImage(); - } - } - - /** Moves the plot range by a given number of pixels and updates the image */ - void scroll(int dx, int dy) { - if (logXAxis) { - currentMinMax[0] /= Math.pow(10, dx/xScale); - currentMinMax[1] /= Math.pow(10, dx/xScale); - } else { - currentMinMax[0] -= dx/xScale; - currentMinMax[1] -= dx/xScale; - } - if (logYAxis) { - currentMinMax[2] *= Math.pow(10, dy/yScale); - currentMinMax[3] *= Math.pow(10, dy/yScale); - } else { - currentMinMax[2] += dy/yScale; - currentMinMax[3] += dy/yScale; - } - updateImage(); - } - - /** Whether to draw simple axes without ticks, grid and numbers only for min, max*/ - private boolean simpleXAxis() { - return !hasFlag(X_TICKS | X_MINOR_TICKS | X_LOG_TICKS | X_GRID | X_NUMBERS); - } - - private boolean simpleYAxis() { - return !hasFlag(Y_TICKS | Y_MINOR_TICKS | Y_LOG_TICKS | Y_GRID | Y_NUMBERS); - } - - /** Draws ticks, grid and axis label for each tick/grid line. - * The grid or major tick spacing in each direction is given by steps */ - void drawAxesTicksGridNumbers(double[] steps) { - - if (ip==null) - return; - String[] xCats = labelsInBraces('x'); // create categories for the axes (if any) - String[] yCats = labelsInBraces('y'); - String multiplySymbol = getMultiplySymbol(); // for scientific notation - Font scFont = scFont(pp.frame.getFont()); - Font scFontMedium = scFont.deriveFont(scFont.getSize2D()*10f/12f); //for axis numbers if full size does not fit - Font scFontSmall = scFont.deriveFont(scFont.getSize2D()*9f/12f); //for subscripts - ip.setFont(scFont); - FontMetrics fm = ip.getFontMetrics(); - int fontAscent = fm.getAscent(); - ip.setJustification(LEFT); - // --- A l o n g X A x i s - int yOfXAxisNumbers = topMargin + frameHeight + fm.getHeight()*5/4 + sc(2); - if (hasFlag(X_NUMBERS | (logXAxis ? (X_TICKS | X_MINOR_TICKS) : X_LOG_TICKS) + X_GRID)) { - Font baseFont = scFont; - boolean majorTicks = logXAxis ? hasFlag(X_LOG_TICKS) : hasFlag(X_TICKS); - boolean minorTicks = hasFlag(X_MINOR_TICKS); - minorTicks = minorTicks && (xCats == null); - double step = steps[0]; - int i1 = (int)Math.ceil (Math.min(xMin, xMax)/step-1.e-10); - int i2 = (int)Math.floor(Math.max(xMin, xMax)/step+1.e-10); - int suggestedDigits = (int)Tools.getNumberFromList(pp.frame.options, "xdecimals="); //is not given, NaN cast to 0 - int digits = getDigits(xMin, xMax, step, 7, suggestedDigits); - int y1 = topMargin; - int y2 = topMargin + frameHeight; - if (xMin==xMax) { - if (hasFlag(X_NUMBERS)) { - String s = IJ.d2s(xMin,getDigits(xMin, 0.001*xMin, 5, suggestedDigits)); - int y = yBasePxl; - ip.drawString(s, xBasePxl-ip.getStringWidth(s)/2, yOfXAxisNumbers); - } - } else { - if (hasFlag(X_NUMBERS)) { - int w1 = ip.getStringWidth(IJ.d2s(currentMinMax[0], logXAxis ? -1 : digits)); - int w2 = ip.getStringWidth(IJ.d2s(currentMinMax[1], logXAxis ? -1 : digits)); - int wMax = Math.max(w1,w2); - if (wMax > Math.abs(step*xScale)-sc(8)) { - baseFont = scFontMedium; //small font if there is not enough space for the numbers - ip.setFont(baseFont); - } - } - - for (int i=0; i<=(i2-i1); i++) { - double v = (i+i1)*step; - int x = (int)Math.round((v - xMin)*xScale) + leftMargin; - - if (xCats!= null) { - int index = (int) v; - double remainder = Math.abs(v - Math.round(v)); - if(index >= 0 && index < xCats.length && remainder < 1e-9){ - String s = xCats[index]; - String[] parts = s.split("\n"); - int w = 0; - for(int jj = 0; jj < parts.length; jj++) - w = Math.max(w, ip.getStringWidth(parts[jj])); - - ip.drawString(s, x-w/2, yOfXAxisNumbers); - //ip.drawString(s, x-ip.getStringWidth(s)/2, yOfXAxisNumbers); - } - continue; - } - - if (hasFlag(X_GRID)) { - ip.setColor(gridColor); - ip.drawLine(x, y1, x, y2); - ip.setColor(Color.black); - } - if (majorTicks) { - ip.drawLine(x, y1, x, y1+sc(tickLength)); - ip.drawLine(x, y2, x, y2-sc(tickLength)); - } - if (hasFlag(X_NUMBERS)) { - if (logXAxis || digits<0) { - drawExpString(logXAxis ? Math.pow(10,v) : v, logXAxis ? -1 : -digits, - x, yOfXAxisNumbers-fontAscent/2, CENTER, fontAscent, baseFont, scFontSmall, multiplySymbol); - } else { - String s = IJ.d2s(v,digits); - ip.drawString(s, x-ip.getStringWidth(s)/2, yOfXAxisNumbers); - } - } - } - boolean haveMinorLogNumbers = i2-i1 < 2; //nunbers on log minor ticks only if < 2 decades - if (minorTicks && (!logXAxis || step > 1.1)) { //'standard' log minor ticks only for full decades - double mstep = niceNumber(step*0.19); //non-log: 4 or 5 minor ticks per major tick - double minorPerMajor = step/mstep; - if (Math.abs(minorPerMajor-Math.round(minorPerMajor)) > 1e-10) //major steps are not an integer multiple of minor steps? (e.g. user step 90 deg) - mstep = step/4; - if (logXAxis && mstep < 1) mstep = 1; - i1 = (int)Math.ceil (Math.min(xMin,xMax)/mstep-1.e-10); - i2 = (int)Math.floor(Math.max(xMin,xMax)/mstep+1.e-10); - for (int i=i1; i<=i2; i++) { - double v = i*mstep; - int x = (int)Math.round((v - xMin)*xScale) + leftMargin; - ip.drawLine(x, y1, x, y1+sc(minorTickLength)); - ip.drawLine(x, y2, x, y2-sc(minorTickLength)); - } - } else if (logXAxis && majorTicks && Math.abs(xScale)>sc(MIN_X_GRIDSPACING)) { //minor ticks for log - int minorNumberLimit = haveMinorLogNumbers ? (int)(0.12*Math.abs(xScale)/(fm.charWidth('0')+sc(2))) : 0; //more numbers on minor ticks when zoomed in - i1 = (int)Math.floor(Math.min(xMin,xMax)-1.e-10); - i2 = (int)Math.ceil (Math.max(xMin,xMax)+1.e-10); - for (int i=i1; i<=i2; i++) { - for (int m=2; m<10; m++) { - double v = i+Math.log10(m); - if (v > Math.min(xMin,xMax) && v < Math.max(xMin,xMax)) { - int x = (int)Math.round((v - xMin)*xScale) + leftMargin; - ip.drawLine(x, y1, x, y1+sc(minorTickLength)); - ip.drawLine(x, y2, x, y2-sc(minorTickLength)); - if (m<=minorNumberLimit) - drawExpString(Math.pow(10,v), 0, x, yOfXAxisNumbers-fontAscent/2, CENTER, - fontAscent, baseFont, scFontSmall, multiplySymbol); - } - } - } - } - } - } - // --- A l o n g Y A x i s - ip.setFont(scFont); - int maxNumWidth = 0; - int xNumberRight = leftMargin-sc(2)-ip.getStringWidth("0")/2; - Rectangle rect = ip.getStringBounds("0169"); - int yNumberOffset = -rect.y-rect.height/2; - if (hasFlag(Y_NUMBERS | (logYAxis ? (Y_TICKS | Y_MINOR_TICKS) : Y_LOG_TICKS) + Y_GRID)) { - ip.setJustification(RIGHT); - Font baseFont = scFont; - boolean majorTicks = logYAxis ? hasFlag(Y_LOG_TICKS) : hasFlag(Y_TICKS); - boolean minorTicks = logYAxis ? hasFlag(Y_LOG_TICKS) : hasFlag(Y_MINOR_TICKS); - minorTicks = minorTicks && (yCats == null); - double step = steps[1]; - int i1 = (int)Math.ceil (Math.min(yMin, yMax)/step-1.e-10); - int i2 = (int)Math.floor(Math.max(yMin, yMax)/step+1.e-10); - int suggestedDigits = (int)Tools.getNumberFromList(pp.frame.options, "ydecimals="); //is not given, NaN cast to 0 - int digits = getDigits(yMin, yMax, step, 5, suggestedDigits); - int x1 = leftMargin; - int x2 = leftMargin + frameWidth; - if (yMin==yMax) { - if (hasFlag(Y_NUMBERS)) { - String s = IJ.d2s(yMin,getDigits(yMin, 0.001*yMin, 5, suggestedDigits)); - maxNumWidth = ip.getStringWidth(s); - int y = yBasePxl; - ip.drawString(s, xNumberRight, y+fontAscent/2+sc(1)); - } - } else { - int digitsForWidth = logYAxis ? -1 : digits; - if (digitsForWidth < 0) { - digitsForWidth--; //"1.0*10^5" etc. needs more space than 1.0*5, simulate by adding one decimal - xNumberRight += sc(1)+ip.getStringWidth("0")/4; - } - String str1 = IJ.d2s(currentMinMax[2], digitsForWidth); - String str2 = IJ.d2s(currentMinMax[3], digitsForWidth); - if (digitsForWidth < 0) { - str1 = str1.replaceFirst("E",multiplySymbol); - str2 = str2.replaceFirst("E",multiplySymbol); - } - int w1 = ip.getStringWidth(str1); - int w2 = ip.getStringWidth(str2); - int wMax = Math.max(w1,w2); - if (hasFlag(Y_NUMBERS)) { - if (wMax > xNumberRight - sc(4) - (pp.yLabel.label.length()>0 ? fm.getHeight() : 0)) { - baseFont = scFontMedium; //small font if there is not enough space for the numbers - ip.setFont(baseFont); - } - } - //IJ.log(IJ.d2s(currentMinMax[2],digits)+": w="+w1+"; "+IJ.d2s(currentMinMax[3],digits)+": w="+w2+baseFont+" Space="+(leftMargin-sc(4+5)-fm.getHeight())); - for (int i=i1; i<=i2; i++) { - double v = step==0 ? yMin : i*step; - int y = topMargin + frameHeight - (int)Math.round((v - yMin)*yScale); - - if (yCats != null){ - int index = (int) v; - double remainder = Math.abs(v - Math.round(v)); - if(index >= 0 && index < yCats.length && remainder < 1e-9){ - String s = yCats[index]; - int multiLineOffset = 0; // multi-line cat labels - for(int jj = 0; jj < s.length(); jj++) - if(s.charAt(jj) == '\n') - multiLineOffset -= rect.height/2; - - ip.drawString(s, xNumberRight, y+yNumberOffset+ multiLineOffset); - } - continue; - } - - if (hasFlag(Y_GRID)) { - ip.setColor(gridColor); - ip.drawLine(x1, y, x2, y); - ip.setColor(Color.black); - } - if (majorTicks) { - ip.drawLine(x1, y, x1+sc(tickLength), y); - ip.drawLine(x2, y, x2-sc(tickLength), y); - } - if (hasFlag(Y_NUMBERS)) { - int w = 0; - if (logYAxis || digits<0) { - w = drawExpString(logYAxis ? Math.pow(10,v) : v, logYAxis ? -1 : -digits, - xNumberRight, y, RIGHT, fontAscent, baseFont, scFontSmall, multiplySymbol); - } else { - String s = IJ.d2s(v,digits); - w = ip.getStringWidth(s); - ip.drawString(s, xNumberRight, y+yNumberOffset); - } - if (w > maxNumWidth) maxNumWidth = w; - } - } - boolean haveMinorLogNumbers = i2-i1 < 2; //numbers on log minor ticks only if < 2 decades - if (minorTicks && (!logYAxis || step > 1.1)) { //'standard' log minor ticks only for full decades - double mstep = niceNumber(step*0.19); //non-log: 4 or 5 minor ticks per major tick - double minorPerMajor = step/mstep; - if (Math.abs(minorPerMajor-Math.round(minorPerMajor)) > 1e-10) //major steps are not an integer multiple of minor steps? (e.g. user step 90 deg) - mstep = step/4; - if (logYAxis && step < 1) mstep = 1; - i1 = (int)Math.ceil (Math.min(yMin,yMax)/mstep-1.e-10); - i2 = (int)Math.floor(Math.max(yMin,yMax)/mstep+1.e-10); - for (int i=i1; i<=i2; i++) { - double v = i*mstep; - int y = topMargin + frameHeight - (int)Math.round((v - yMin)*yScale); - ip.drawLine(x1, y, x1+sc(minorTickLength), y); - ip.drawLine(x2, y, x2-sc(minorTickLength), y); - } - } - if (logYAxis && majorTicks && Math.abs(yScale)>sc(MIN_X_GRIDSPACING)) { //minor ticks for log within the decade - int minorNumberLimit = haveMinorLogNumbers ? (int)(0.4*Math.abs(yScale)/fm.getHeight()) : 0; //more numbers on minor ticks when zoomed in - i1 = (int)Math.floor(Math.min(yMin,yMax)-1.e-10); - i2 = (int)Math.ceil(Math.max(yMin,yMax)+1.e-10); - for (int i=i1; i<=i2; i++) { - for (int m=2; m<10; m++) { - double v = i+Math.log10(m); - if (v > Math.min(yMin,yMax) && v < Math.max(yMin,yMax)) { - int y = topMargin + frameHeight - (int)Math.round((v - yMin)*yScale); - ip.drawLine(x1, y, x1+sc(minorTickLength), y); - ip.drawLine(x2, y, x2-sc(minorTickLength), y); - if (m<=minorNumberLimit) { - int w = drawExpString(Math.pow(10,v), 0, xNumberRight, y, RIGHT, - fontAscent, baseFont, scFontSmall, multiplySymbol); - if (w > maxNumWidth) maxNumWidth = w; - } - } - } - } - } - } - } - // --- Write min&max of range if simple style without any axis format flags - ip.setFont(scFont); - ip.setJustification(LEFT); - String xLabelToDraw = pp.xLabel.label; - String yLabelToDraw = pp.yLabel.label; - if (simpleYAxis()) { // y-axis min&max - int digits = getDigits(yMin, yMax, 0.001*(yMax-yMin), 6, 0); - String s = IJ.d2s(yMax, digits); - int sw = ip.getStringWidth(s); - if ((sw+sc(4)) > leftMargin) - ip.drawString(s, sc(4), topMargin-sc(4)); - else - ip.drawString(s, leftMargin-ip.getStringWidth(s)-sc(4), topMargin+10); - s = IJ.d2s(yMin, digits); - sw = ip.getStringWidth(s); - if ((sw+4)>leftMargin) - ip.drawString(s, sc(4), topMargin+frame.height); - else - ip.drawString(s, leftMargin-ip.getStringWidth(s)-sc(4), topMargin+frame.height); - if (logYAxis) yLabelToDraw += " (LOG)"; - } - int y = yOfXAxisNumbers; - if (simpleXAxis()) { // x-axis min&max - int digits = getDigits(xMin, xMax, 0.001*(xMax-xMin), 7, 0); - ip.drawString(IJ.d2s(xMin,digits), leftMargin, y); - String s = IJ.d2s(xMax,digits); - ip.drawString(s, leftMargin + frame.width-ip.getStringWidth(s)+6, y); - y -= fm.getHeight(); - if (logXAxis) xLabelToDraw += " (LOG)"; - } else - y += sc(1); - // --- Write x and y axis text labels - if (xCats == null) { - ip.setFont(pp.xLabel.getFont() == null ? scFont : scFont(pp.xLabel.getFont())); - ImageProcessor xLabel = stringToPixels(xLabelToDraw); - if(xLabel != null){ - int xpos = leftMargin+(frame.width-xLabel.getWidth())/2; - int ypos = y + scFont.getSize()/3;//topMargin + frame.height + bottomMargin-xLabel.getHeight(); - ip.insert(xLabel, xpos, ypos); - } - } - if (yCats == null) { - ip.setFont(pp.yLabel.getFont() == null ? scFont : scFont(pp.yLabel.getFont())); - ImageProcessor yLabel = stringToPixels(yLabelToDraw); - if(yLabel != null){ - yLabel = yLabel.rotateLeft(); - int xRightOfYLabel = xNumberRight - maxNumWidth - sc(2); - int xpos = xRightOfYLabel - yLabel.getWidth() - sc(2); - int ypos = topMargin + (frame.height -yLabel.getHeight())/2; - ip.insert(yLabel, xpos, ypos); - } - } - } - - /** Returns the array of categories from an axis label in the form {cat1,cat2,cat3}, or null if not this form - * @param labelCode can be 'x' or 'y', for the x or y axis label*/ - String[] labelsInBraces(char labelCode) { - String s = getLabel(labelCode); - if (s.startsWith("{") && s.endsWith("}")) { - String inBraces = s.substring(1, s.length() - 1); - String[] catLabels = inBraces.split(","); - return catLabels; - } else { - return null; - } - } - - /** Returns the smallest "nice" number >= v. "Nice" numbers are .. 0.5, 1, 2, 5, 10, 20 ... */ - double niceNumber(double v) { - double base = Math.pow(10,Math.floor(Math.log10(v)-1.e-6)); - if (v > 5.0000001*base) return 10*base; - else if (v > 2.0000001*base) return 5*base; - else return 2*base; - } - - /** draw something like 1.2 10^-9; returns the width of the string drawn. - * 'Digits' should be >=0 for drawing the mantissa (=1.38 in this example), negative to draw only 10^exponent - * Currently only supports center justification and right justification (y of center line) - * Fonts baseFont, smallFont should be scaled already - * Returns the width of the String */ - int drawExpString(double value, int digits, int x, int y, int justification, - int fontAscent, Font baseFont, Font smallFont, String multiplySymbol) { - String base = "10"; - String exponent = null; - String s = IJ.d2s(value, digits<=0 ? -1 : -digits); - if (Tools.parseDouble(s) == 0) s = "0"; //don't write 0 as 0*10^0 - int ePos = s.indexOf('E'); - if (ePos < 0) - base = s; //can't have exponential format, e.g. NaN - else { - if (digits>=0) { - base = s.substring(0,ePos); - if (digits == 0) - base = Integer.toString((int)Math.round(Tools.parseDouble(base))); - base += multiplySymbol+"10"; - } - exponent = s.substring(ePos+1); - } - //IJ.log(s+" -> "+base+"^"+exponent+" maxAsc="+fontAscent+" font="+baseFont); - ip.setJustification(RIGHT); - int width = ip.getStringWidth(base); - if (exponent != null) { - ip.setFont(smallFont); - int wExponent = ip.getStringWidth(exponent); - width += wExponent; - if (justification == CENTER) x += width/2; - ip.drawString(exponent, x, y+fontAscent*3/10); - x -= wExponent; - ip.setFont(baseFont); - } - ip.drawString(base, x, y+fontAscent*7/10); - return width; - } - - /** Returns the user-supplied (via setOptions) or default multiplication symbol (middot) */ - String getMultiplySymbol() { - String multiplySymbol = Tools.getStringFromList(pp.frame.options, "msymbol="); - if (multiplySymbol==null) - multiplySymbol = Tools.getStringFromList(pp.frame.options, "multiplysymbol="); - return multiplySymbol != null ? multiplySymbol : MULTIPLY_SYMBOL; - } - - //Returns a pixelMap containting labelStr. - //Uses font of current ImageProcessor. - //Returns null for empty or blank-only strings - //Supports !!subscript!! and ^^superscript^^ - ByteProcessor stringToPixels(String labelStr) { - Font bigFont = ip.getFont(); - Rectangle rect = ip.getStringBounds(labelStr); - int ww = rect.width * 2; - int hh = rect.height * 3;//enough space, will be cropped later - int y0 = rect.height * 2;//base line - if (ww <= 0 || hh <= 0) { - return null; - } - ByteProcessor box = new ByteProcessor(ww, hh); - box.setColor(Color.WHITE); - //box.setColor(Color.LIGHT_GRAY); //make box visible for test - box.fill(); - box.setColor(Color.black); - box.setAntialiasedText(pp.antialiasedText); - if (invertedLut) { - box.invertLut(); - } - box.setFont(bigFont); - - FontMetrics fm = box.getFontMetrics(); - int ascent = fm.getAscent(); - int offSub = ascent / 6; - int offSuper = -ascent / 2; - Font smallFont = bigFont.deriveFont((float) (bigFont.getSize() * 0.7)); - - Rectangle bigBounds = box.getStringBounds(labelStr); - boolean doParse = (labelStr.indexOf("^^") >= 0 || labelStr.indexOf("!!") >= 0); - doParse = doParse && (labelStr.indexOf("^^^") < 0 && labelStr.indexOf("!!!") < 0); - if (!doParse) { - box.drawString(labelStr, 0, y0); - Rectangle cropRect = new Rectangle(bigBounds); - cropRect.y += y0; - box.setRoi(cropRect); - ImageProcessor boxI = box.crop(); - box = boxI.convertToByteProcessor(); - return box; - } - - if (labelStr.endsWith("^^") || labelStr.endsWith("!!")) { - labelStr = labelStr.substring(0, labelStr.length() - 2); - } - if (labelStr.startsWith("^^") || labelStr.startsWith("!!")) { - labelStr = " " + labelStr; - } - - box.setFont(smallFont); - Rectangle smallBounds = box.getStringBounds(labelStr); - box.setFont(bigFont); - int upperBound = y0 + smallBounds.y + offSuper; - int lowerBound = y0 + smallBounds.y + smallBounds.height + offSub; - - int h = fm.getHeight(); - int len = labelStr.length(); - int[] tags = new int[len]; - int nTags = 0; - - for (int jj = 0; jj < len - 2; jj++) {//get positions where font size changes - if (labelStr.substring(jj, jj + 2).equals("^^")) { - tags[nTags++] = jj; - } - if (labelStr.substring(jj, jj + 2).equals("!!")) { - tags[nTags++] = -jj; - } - } - tags[nTags++] = len; - tags = Arrays.copyOf(tags, nTags); - - int leftIndex = 0; - int xRight = 0; - int y2 = y0; - - boolean subscript = labelStr.startsWith("!!"); - for (int pp = 0; pp < tags.length; pp++) {//draw all text fragments - int rightIndex = tags[pp]; - rightIndex = Math.abs(rightIndex); - String part = labelStr.substring(leftIndex, rightIndex); - boolean small = pp % 2 == 1;//toggle odd/even - if (small) { - box.setFont(smallFont); - if (subscript) { - y2 = y0 + offSub; - } else {//superscript: - y2 = y0 + offSuper; - } - } else { - box.setFont(bigFont); - y2 = y0; - } - xRight++; - int partWidth = box.getStringWidth(part); - box.drawString(part, xRight, y2); - leftIndex = rightIndex + 2; - subscript = tags[pp] < 0;//negative positions = subscript - xRight += partWidth; - } - xRight += h / 4; - Rectangle cropRect = new Rectangle(0, upperBound, xRight, lowerBound - upperBound); - box.setRoi(cropRect); - ImageProcessor boxI = box.crop(); - box = boxI.convertToByteProcessor(); - return box; - } - - /** Returns the number of digits to display the number n with resolution 'resolution'; - * (if n is integer and small enough to display without scientific notation, - * no decimals are needed, irrespective of 'resolution') - * Scientific notation is used for more than 'maxDigits' (must be >=3), and indicated - * by a negative return value, or if suggestedDigits is negative - * Returns 'suggestedDigits' if not 0 and compatible with the resolution; negative values of - * 'suggestedDigits' switch to scientific notation. */ - static int getDigits(double n, double resolution, int maxDigits, int suggestedDigits) { - if (n==Math.round(n) && Math.abs(n) < Math.pow(10,maxDigits-1)-1) //integers and not too big - return suggestedDigits; - else - return getDigits2(n, resolution, maxDigits, suggestedDigits); - } - - /** Number of digits to display the range between n1 and n2 with resolution 'resolution'; - * Scientific notation is used for more than 'maxDigits' (must be >=3), and indicated - * by a negative return value - * Returns 'suggestedDigits' if not 0 and compatible with the resolution; negative values of - * 'suggestedDigits' switch to sceintific notation. */ - static int getDigits(double n1, double n2, double resolution, int maxDigits, int suggestedDigits) { - if (n1==0 && n2==0) return suggestedDigits; - return getDigits2(Math.max(Math.abs(n1),Math.abs(n2)), resolution, maxDigits, suggestedDigits); - } - - static int getDigits2(double n, double resolution, int maxDigits, int suggestedDigits) { - if (Double.isNaN(n) || Double.isInfinite(n)) - return 0; //no scientific notation - int log10ofN = (int)Math.floor(Math.log10(Math.abs(n))+1e-7); - int digits = resolution != 0 ? - -(int)Math.floor(Math.log10(Math.abs(resolution))+1e-7) : - Math.max(0, -log10ofN+maxDigits-2); - int sciDigits = -Math.max((log10ofN+digits),1); - //IJ.log("n="+(float)n+"digitsRaw="+digits+" log10ofN="+log10ofN+" sciDigits="+sciDigits); - if ((digits < -2 && log10ofN >= maxDigits) || suggestedDigits < 0) - digits = sciDigits; //scientific notation for large numbers or if desired via suggestedDigits (plot.setOptions) - else if (digits < 0) - digits = 0; - else if (digits > maxDigits-1 && log10ofN < -2) - digits = sciDigits; // scientific notation for small numbers - return digits < 0 ? Math.min(sciDigits, suggestedDigits) : Math.max(digits, suggestedDigits); - } - - static boolean isInteger(double n) { - return n==Math.round(n); - } - - private void drawPlotObject(PlotObject plotObject, ImageProcessor ip) { - //IJ.log("DRAWING type="+plotObject.type+" lineWidth="+plotObject.lineWidth+" shape="+plotObject.shape); - if (plotObject.hasFlag(PlotObject.HIDDEN)) return; - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - int type = plotObject.type; - switch (type) { - case PlotObject.XY_DATA: - ip.setClipRect(frame); - int nPoints = Math.min(plotObject.xValues.length, plotObject.yValues.length); - - if (plotObject.shape==BAR || plotObject.shape==SEPARATED_BAR) - drawBarChart(plotObject); // (separated) bars - - if (plotObject.shape == FILLED) { // filling below line - ip.setColor(plotObject.color2 != null ? plotObject.color2 : plotObject.color); - drawFloatPolyLineFilled(ip, plotObject.xValues, plotObject.yValues, nPoints); - } - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - - if (plotObject.yEValues != null) // error bars in front of bars and fill area below the line, but behind lines and marker symbols - drawVerticalErrorBars(plotObject.xValues, plotObject.yValues, plotObject.yEValues); - if (plotObject.xEValues != null) - drawHorizontalErrorBars(plotObject.xValues, plotObject.yValues, plotObject.xEValues); - - if (plotObject.hasFilledMarker()) { // fill markers with secondary color - int markSize = plotObject.getMarkerSize(); - ip.setColor(plotObject.color2); - ip.setLineWidth(1); - for (int i=0; i0) && (!logYAxis || plotObject.yValues[i]>0) - && !Double.isNaN(plotObject.xValues[i]) && !Double.isNaN(plotObject.yValues[i])) - fillShape(plotObject.shape, scaleX(plotObject.xValues[i]), scaleY(plotObject.yValues[i]), markSize); - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - } - if (plotObject.hasCurve()) { // draw the lines between the points - if (plotObject.shape == CONNECTED_CIRCLES) - ip.setColor(plotObject.color2 == null ? Color.black : plotObject.color2); - drawFloatPolyline(ip, plotObject.xValues, plotObject.yValues, nPoints); - ip.setColor(plotObject.color); - } - if (plotObject.hasMarker()) { // draw the marker symbols - int markSize = plotObject.getMarkerSize(); - ip.setColor(plotObject.color); - Font saveFont = ip.getFont(); - for (int i=0; i0) && (!logYAxis || plotObject.yValues[i]>0) - && !Double.isNaN(plotObject.xValues[i]) && !Double.isNaN(plotObject.yValues[i])) - drawShape(plotObject, scaleX(plotObject.xValues[i]), scaleY(plotObject.yValues[i]), plotObject.shape, markSize, i); - } - if (plotObject.shape==CUSTOM) - ip.setFont(saveFont); - } - ip.setClipRect(null); - break; - case PlotObject.ARROWS: - ip.setClipRect(frame); - for (int i=0; i sc(MAX_ARROWHEAD_LENGTH)) arrowHeadLength = sc(MAX_ARROWHEAD_LENGTH); - if (arrowHeadLength < sc(MIN_ARROWHEAD_LENGTH)) arrowHeadLength = sc(MIN_ARROWHEAD_LENGTH); - drawArrow(xt1, yt1, xt2, yt2, arrowHeadLength); - } - } - ip.setClipRect(null); - break; - - case PlotObject.SHAPES: - int iBoxWidth = 20; - ip.setClipRect(frame); - String shType = plotObject.shapeType.toLowerCase(); - if (shType.contains("rectangles")) { - int nShapes = plotObject.shapeData.size(); - - for (int i = 0; i < nShapes; i++) { - float[] corners = (float[])(plotObject.shapeData.get(i)); - int x1 = scaleX(corners[0]); - int y1 = scaleY(corners[1]); - int x2 = scaleX(corners[2]); - int y2 = scaleY(corners[3]); - - ip.setLineWidth(sc(plotObject.lineWidth)); - int left = Math.min(x1, x2); - int right = Math.max(x1, x2); - int top = Math.min(y1, y2); - int bottom = Math.max(y1, y2); - - Rectangle r1 = new Rectangle(left, top, right-left, bottom - top); - Rectangle cBox = frame.intersection(r1); - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - ip.fillRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setColor(plotObject.color); - ip.drawRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setClipRect(null); - break; - } - if (shType.equals("redraw_grid")) { - ip.setLineWidth(sc(1)); - redrawGrid(); - ip.setClipRect(null); - break; - } - if (shType.contains("boxes")) { - - String[] parts = Tools.split(shType); - for (int jj = 0; jj < parts.length; jj++) { - String[] pairs = parts[jj].split("="); - if ((pairs.length == 2) && pairs[0].equals("width")) { - iBoxWidth = Integer.parseInt(pairs[1]); - } - } - boolean horizontal = shType.contains("boxesx"); - int nShapes = plotObject.shapeData.size(); - int halfWidth = Math.round(sc(iBoxWidth / 2)); - for (int i = 0; i < nShapes; i++) { - - float[] coords = (float[])(plotObject.shapeData.get(i)); - - if (!horizontal) { - - int x = scaleX(coords[0]); - int y1 = scaleY(coords[1]); - int y2 = scaleY(coords[2]); - int y3 = scaleY(coords[3]); - int y4 = scaleY(coords[4]); - int y5 = scaleY(coords[5]); - ip.setLineWidth(sc(plotObject.lineWidth)); - - Rectangle r1 = new Rectangle(x - halfWidth, y4, halfWidth * 2, y2 - y4); - Rectangle cBox = frame.intersection(r1); - if (y1 != y2 || y4 != y5)//otherwise omit whiskers - { - ip.drawLine(x, y1, x, y5);//whiskers - } - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - ip.fillRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setColor(plotObject.color); - ip.drawRect(cBox.x, cBox.y, cBox.width, cBox.height); - ip.setClipRect(frame); - ip.drawLine(x - halfWidth, y3, x + halfWidth - 1, y3); - } - - if (horizontal) { - - int y = scaleY(coords[0]); - int x1 = scaleX(coords[1]); - int x2 = scaleX(coords[2]); - int x3 = scaleX(coords[3]); - int x4 = scaleX(coords[4]); - int x5 = scaleX(coords[5]); - ip.setLineWidth(sc(plotObject.lineWidth)); - if(x1 !=x2 || x4 != x5)//otherwise omit whiskers - ip.drawLine(x1, y, x5, y);//whiskers - Rectangle r1 = new Rectangle(x2, y - halfWidth, x4 - x2, halfWidth * 2); - Rectangle cBox = frame.intersection(r1); - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - ip.fillRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setColor(plotObject.color); - ip.drawRect(cBox.x, cBox.y, cBox.width, cBox.height); - ip.setClipRect(frame); - ip.drawLine(x3, y - halfWidth, x3, y + halfWidth - 1); - } - } - ip.setClipRect(null); - break; - } - case PlotObject.LINE: - if (Double.isNaN(plotObject.x) || Double.isNaN(plotObject.y)) break; - ip.setClipRect(frame); - ip.drawLine(scaleX(plotObject.x), scaleY(plotObject.y), scaleX(plotObject.xEnd), scaleY(plotObject.yEnd)); - ip.setClipRect(null); - break; - case PlotObject.NORMALIZED_LINE: - ip.setClipRect(frame); - int ix1 = leftMargin + (int)(plotObject.x*frameWidth); - int iy1 = topMargin + (int)(plotObject.y*frameHeight); - int ix2 = leftMargin + (int)(plotObject.xEnd*frameWidth); - int iy2 = topMargin + (int)(plotObject.yEnd*frameHeight); - ip.drawLine(ix1, iy1, ix2, iy2); - ip.setClipRect(null); - break; - case PlotObject.DOTTED_LINE: - ip.setClipRect(frame); - ix1 = scaleX(plotObject.x); - iy1 = scaleY(plotObject.y); - ix2 = scaleX(plotObject.xEnd); - iy2 = scaleY(plotObject.yEnd); - double length = calculateDistance(ix1, ix2, iy1, iy2) + 0.1; - int n = (int)(length/plotObject.step); - for (int i = 0; i<=n; i++) - ip.drawDot(ix1 + (int)Math.round((ix2-ix1)*(double)i/n), iy1 + (int)Math.round((iy2-iy1)*(double)i/n)); - ip.setClipRect(null); - break; - case PlotObject.LABEL: - case PlotObject.NORMALIZED_LABEL: - ip.setJustification(plotObject.justification); - if (plotObject.getFont() != null) - ip.setFont(scFont(plotObject.getFont())); - int xt = type==PlotObject.LABEL ? scaleX(plotObject.x) : leftMargin + (int)(plotObject.x*frameWidth); - int yt = type==PlotObject.LABEL ? scaleY(plotObject.y) : topMargin + (int)(plotObject.y*frameHeight); - ip.drawString(plotObject.label, xt, yt); - break; - case PlotObject.LEGEND: - drawLegend(plotObject, ip); - break; - } - } - - /** Draw a bar at each point */ - void drawBarChart(PlotObject plotObject) { - int n = Math.min(plotObject.xValues.length, plotObject.yValues.length); - String[] xCats = labelsInBraces('x'); // do we have categories at the x axis instead of numbers? - boolean separatedBars = plotObject.shape == SEPARATED_BAR || xCats != null; - int halfBarWidthInPixels = n <= 1 ? Math.max(1, frameWidth/2-2) : 0; - if (separatedBars && n > 1) - halfBarWidthInPixels = Math.max(1, (int)Math.round(Math.abs - (0.5*(plotObject.xValues[n-1] - plotObject.xValues[0])/(n-1) * xScale * SEPARATED_BAR_WIDTH))); - int y0 = scaleYWithOverflow(0); - boolean yZeroInFrame = !logYAxis && yBasePxl>frame.y && yBasePxl 0 ? 0.5f*(plotObject.xValues[i-1]+plotObject.xValues[i]) : - 1.5f*plotObject.xValues[i] - 0.5f*plotObject.xValues[i+1]); - right = scaleX(i < n-1 ? 0.5f*(plotObject.xValues[i]+plotObject.xValues[i+1]) : - 1.5f*plotObject.xValues[i] - 0.5f*plotObject.xValues[i-1]); - } else { - int x = scaleX(plotObject.xValues[i]); - left = x - halfBarWidthInPixels; //separated bars or n<=1 : fixed bar width - right = x + halfBarWidthInPixels; - } - if (left < frame.x) left = frame.x; - if (left > frame.x+frame.width) left = frame.x+frame.width; - if (right < frame.x) right = frame.x; - if (right > frame.x+frame.width) right = frame.x+frame.width; - int y = scaleYWithOverflow(plotObject.yValues[i]); - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - for (int x2 = Math.min(left,right); x2 <= Math.max(left,right); x2++) - ip.drawLine(x2, y0, x2, y); //cant use ip.fillRect (ignores the clipRect), so we it fill line by line - } - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - if (separatedBars) { - ip.drawLine(left, y0, left, y); //up - ip.drawLine(left, y, right, y); //right - ip.drawLine(right, y, right, y0); //down - if (yZeroInFrame) - ip.drawLine(left, y0, right, y0);//baseline - } else { - ip.drawLine(left, prevY, left, y); //up or down - ip.drawLine(left, y, right, y); //right - if (i == n - 1) - ip.drawLine(right, y, right, y0);//last down - prevY = y; - } - } - } - - /** Draw the symbol for the data point number 'pointIndex' (pointIndex < 0 when drawing the legend) */ - void drawShape(PlotObject plotObject, int x, int y, int shape, int size, int pointIndex) { - if (ip==null) - return; - int lineWidth = ip.getLineWidth(); - if (shape == DIAMOND) - size = (int)(size*1.21); - int xbase = x-sc(size/2); - int ybase = y-sc(size/2); - int xend = x+sc(size/2); - int yend = y+sc(size/2); - if (lineWidth>3) { - int newLineWidth = 3; - ip.setLineWidth(newLineWidth); - } - //IJ.log("drawShape: "+size+" "+size); - switch(shape) { - case X: - ip.drawLine(xbase,ybase,xend,yend); - ip.drawLine(xend,ybase,xbase,yend); - break; - case BOX: - ip.drawLine(xbase,ybase,xend,ybase); - ip.drawLine(xend,ybase,xend,yend); - ip.drawLine(xend,yend,xbase,yend); - ip.drawLine(xbase,yend,xbase,ybase); - break; - case TRIANGLE: - ip.drawLine(x,ybase-sc(1),xend+sc(1),yend); //height must be odd, otherwise rounding leads to asymmetric shape - ip.drawLine(x,ybase-sc(1),xbase-sc(1),yend); - ip.drawLine(xend+sc(1),yend,xbase-sc(1),yend); - break; - case CROSS: - ip.drawLine(xbase,y,xend,y); - ip.drawLine(x,ybase,x,yend); - break; - case DIAMOND: - ip.drawLine(xbase,y,x,ybase); - ip.drawLine(x,ybase,xend,y); - ip.drawLine(xend,y,x,yend); - ip.drawLine(x,yend,xbase,y); - break; - case DOT: - ip.drawDot(x, y); //uses current line width - break; - case CUSTOM: - if (plotObject.macroCode==null || frame==null) - break; - if (x=frame.x+frame.width || y>=frame.y+frame.height) - break; - ImagePlus imp = new ImagePlus("", ip); - WindowManager.setTempCurrentImage(imp); - StringBuilder sb = new StringBuilder(140+plotObject.macroCode.length()); - sb.append("x="); sb.append(x); - sb.append(";y="); sb.append(y); - sb.append(";setColor('"); - sb.append(Tools.c2hex(plotObject.color)); - sb.append("');s="); sb.append(sc(1)); - boolean drawingLegend = pointIndex < 0; - double xVal = 0; - double yVal = 0; - if (!drawingLegend) { - xVal = plotObject.xValues[pointIndex]; - yVal = plotObject.yValues[pointIndex]; - } - sb.append(";i="); sb.append(drawingLegend ? 0 : pointIndex); - sb.append(";xval=" + xVal); - sb.append(";yval=" + yVal); - sb.append(";"); - sb.append(plotObject.macroCode); - if (!drawingLegend ||!sb.toString().contains("d2s") ) {// a graphical symbol won't contain "d2s" .. - String rtn = IJ.runMacro(sb.toString());//.. so it can go to the legend - if ("[aborted]".equals(rtn)) - plotObject.macroCode = null; - } - WindowManager.setTempCurrentImage(null); - break; - default: // CIRCLE, CONNECTED_CIRCLES: 5x5 oval approximated by 5x5 square without corners - if (sc(size) < 5.01) { - ip.drawLine(x-1, y-2, x+1, y-2); - ip.drawLine(x-1, y+2, x+1, y+2); - ip.drawLine(x+2, y+1, x+2, y-1); - ip.drawLine(x-2, y+1, x-2, y-1); - } else { - int r = sc(0.5f*size-0.5f); - ip.drawOval(x-r, y-r, 2*r, 2*r); - } - break; - } - ip.setLineWidth(lineWidth); - } - - /** Fill the area of the symbols for data points (except for shape=DOT) - * Note that ip.fill, ip.fillOval etc. can't be used here: they do not care about the clip rectangle */ - void fillShape(int shape, int x0, int y0, int size) { - if (shape == DIAMOND) size = (int)(size*1.21); - int r = sc(size/2)-1; - switch(shape) { - case BOX: - for (int dy=-r; dy<=r; dy++) - for (int dx=-r; dx<=r; dx++) - ip.drawDot(x0+dx, y0+dy); - break; - case TRIANGLE: - int ybase = y0 - r - sc(1); - int yend = y0 + r; - double halfWidth = sc(size/2)+sc(1)-1; - double hwStep = halfWidth/(yend-ybase+1); - for (int y=yend; y>=ybase; y--, halfWidth -= hwStep) { - int dx = (int)(Math.round(halfWidth)); - for (int x=x0-dx; x<=x0+dx; x++) - ip.drawDot(x,y); - } - break; - case DIAMOND: - ybase = y0 - r - sc(1); - yend = y0 + r; - halfWidth = sc(size/2)+sc(1)-1; - hwStep = halfWidth/(yend-ybase+1); - for (int y=yend; y>=ybase; y--) { - int dx = (int)(Math.round(halfWidth-(hwStep+1)*Math.abs(y-y0))); - for (int x=x0-dx; x<=x0+dx; x++) - ip.drawDot(x,y); - } - break; - case CIRCLE: case CONNECTED_CIRCLES: - int rsquare = (r+1)*(r+1); - for (int dy=-r; dy<=r; dy++) - for (int dx=-r; dx<=r; dx++) - if (dx*dx + dy*dy <= rsquare) - ip.drawDot(x0+dx, y0+dy); - break; - } - } - - /** Adds an arrow from position 1 to 2 given in pixels; 'size' is the length of the arrowhead - * @deprecated Use as a public method is not supported any more because it is incompatible with rescaling */ - @Deprecated - public void drawArrow(int x1, int y1, int x2, int y2, double size) { - double dx = x2 - x1; - double dy = y2 - y1; - double ra = Math.sqrt(dx * dx + dy * dy); - dx /= ra; - dy /= ra; - int x3 = (int) Math.round(x2 - dx * size); //arrow base - int y3 = (int) Math.round(y2 - dy * size); - double r = 0.3 * size; - int x4 = (int) Math.round(x3 + dy * r); - int y4 = (int) Math.round(y3 - dx * r); - int x5 = (int) Math.round(x3 - dy * r); - int y5 = (int) Math.round(y3 + dx * r); - ip.moveTo(x1, y1); ip.lineTo(x2, y2); - ip.moveTo(x4, y4); ip.lineTo(x2, y2); ip.lineTo(x5, y5); - } - - private void drawVerticalErrorBars(float[] x, float[] y, float[] e) { - int nPoints = Math.min(Math.min(x.length, y.length), e.length); - for (int i=0; i0))) continue; - int x0 = scaleX(x[i]); - int yPlus = scaleYWithOverflow(y[i] + e[i]); - int yMinus = scaleYWithOverflow(y[i] - e[i]); - ip.moveTo(x0,yMinus); - ip.lineTo(x0, yPlus); - } - } - - private void drawHorizontalErrorBars(float[] x, float[] y, float[] e) { - int nPoints = Math.min(Math.min(x.length, y.length), e.length); - float[] xpoints = new float[2]; - float[] ypoints = new float[2]; - for (int i=0; i0))) continue; - int y0 = scaleY(y[i]); - int xPlus = scaleXWithOverflow(x[i] + e[i]); - int xMinus = scaleXWithOverflow(x[i] - e[i]); - ip.moveTo(xMinus,y0); - ip.lineTo(xPlus, y0); - } - } - - /** Draw a polygon line; NaN values interrupt it. */ - void drawFloatPolyline(ImageProcessor ip, float[] x, float[] y, int n) { - if (x==null || x.length==0) return; - int x1, y1; - boolean isNaN0; - boolean isNaN1 = true; //no previous point - int x2 = scaleX(x[0]); - int y2 = scaleY(y[0]); - boolean isNaN2 = Float.isNaN(x[0]) || Float.isNaN(y[0]) || (logXAxis && x[0]<=0) || (logYAxis && y[0]<=0); - for (int i=1; i= frame.x+frame.width && right >= frame.x+frame.width) continue; - if (left < frame.x) left = frame.x; - if (left >= frame.x+frame.width) left = frame.x+frame.width-1; - if (right < frame.x) right = frame.x; - if (right >= frame.x+frame.width) right = frame.x+frame.width-1; - if (left != right) { - for (int xi = Math.min(left,right); xi <= Math.max(left,right); xi++) { - int yi = (int)Math.round(y1 + (double)(y2 - y1)*(double)(xi - x1)/(double)(x2 - x1)); - /* double yMin = Math.min(yF[i-1], yF[i]); - double yMax = Math.max(yF[i-1], yF[i]); - if (y < yMin) y = yMin; // dont extrapolate (in case rounding to pixels falls outside [xi, xi+1] interval) - if (y > yMax) y = yMax;*/ - ip.drawLine(xi, y0, xi, yi); - } - } else { - ip.drawLine(left, y0, left, y2); - } - } - } - - /** Returns only indexed and sorted plot objects, if at least one label is indexed like "1__MyLabel" */ - Vector getIndexedPlotObjects(){ - boolean withIndex = false; - int len = allPlotObjects.size(); - String[] labels = new String[len]; - Vector indexedObjects = new Vector(); - for(int jj = 0; jj < len; jj++){ - PlotObject plotObject = allPlotObjects.get(jj); - labels[jj] = ""; - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN) && plotObject.label != null) { - String label = plotObject.label; - if(label.indexOf("__") >=0 && label.indexOf("__") <= 2){ - labels[jj]= plotObject.label; - withIndex = true; - } - } - } - int[] ranks = Tools.rank(labels); - for(int jj = 0; jj < len; jj++){ - if(labels[ranks[jj]] != ""){ - int index = ranks[jj]; - indexedObjects.add(allPlotObjects.get(index)); - } - } - if(!withIndex) - return null; - return indexedObjects; - } - - /** Draw the legend */ - void drawLegend(PlotObject legendObject, ImageProcessor ip) { - ip.setFont(scFont(legendObject.getFont())); - int nLabels = 0; - int maxStringWidth = 0; - float maxLineThickness = 0; - Vector usedPlotObjects = allPlotObjects; - Vector indexedObjects = getIndexedPlotObjects(); - if(indexedObjects != null) - usedPlotObjects= indexedObjects; - - for (PlotObject plotObject : usedPlotObjects) - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN) && plotObject.label != null) { //label exists: was set now or previously - nLabels++; - String label = plotObject.label; - if (indexedObjects != null) - label = label.substring(label.indexOf("__") + 2); - int w = ip.getStringWidth(label); - if (w > maxStringWidth) maxStringWidth = w; - if (plotObject.lineWidth > maxLineThickness) maxLineThickness = plotObject.lineWidth; - } - if (nLabels == 0) return; - if (pp.antialiasedText && scale > 1) //fix incorrect width of large fonts - maxStringWidth = (int)((1 + 0.004*scale) * maxStringWidth); - int frameThickness = sc(legendObject.lineWidth > 0 ? legendObject.lineWidth : 1); - FontMetrics fm = ip.getFontMetrics(); - ip.setJustification(LEFT); - int lineHeight = fm.getHeight(); - int height = nLabels*lineHeight + 2*sc(LEGEND_PADDING); - int width = maxStringWidth + sc(3*LEGEND_PADDING + LEGEND_LINELENGTH + maxLineThickness); - int positionCode = legendObject.flags & LEGEND_POSITION_MASK; - if (positionCode == AUTO_POSITION) - positionCode = autoLegendPosition(width, height, frameThickness); - Rectangle rect = legendRect(positionCode, width, height, frameThickness); - int x0 = rect.x; - int y0 = rect.y; - - ip.setColor(Color.white); - ip.setLineWidth(1); - if (!legendObject.hasFlag(LEGEND_TRANSPARENT)) { - ip.setRoi(x0, y0, width, height); - ip.fill(); - } else if (hasFlag(X_GRID | Y_GRID)) { //erase grid - int grid = ip instanceof ColorProcessor ? (gridColor.getRGB() & 0xffffff) : ip.getBestIndex(gridColor); - for (int y=y0; y=0) - label = label.substring(start+2); - } - ip.drawString(label, xText, y+ lineHeight/2); - y += bottomUp ? -lineHeight : lineHeight; - } - } - - /** The legend area; positionCode should be TOP_LEFT, TOP_RIGHT, etc. */ - Rectangle legendRect(int positionCode, int width, int height, int frameThickness) { - boolean leftPosition = positionCode == TOP_LEFT || positionCode == BOTTOM_LEFT; - boolean topPosition = positionCode == TOP_LEFT || positionCode == TOP_RIGHT; - int x0 = (leftPosition) ? - leftMargin + sc(2*LEGEND_PADDING) + frameThickness/2 : - leftMargin + frameWidth - width - sc(2*LEGEND_PADDING) - frameThickness/2; - int y0 = (topPosition) ? - topMargin + sc(LEGEND_PADDING) + frameThickness/2 : - topMargin + frameHeight - height - sc(LEGEND_PADDING) + frameThickness/2; - if (hasFlag(Y_TICKS)) - x0 += (leftPosition ? 1 : -1) * sc(tickLength - LEGEND_PADDING); - if (hasFlag(X_TICKS)) - y0 += (topPosition ? 1 : -1) * sc(tickLength - LEGEND_PADDING/2); - return new Rectangle(x0, y0, width, height); - } - - /** The position code of the legend position where the smallest amount of foreground pixels is covered */ - int autoLegendPosition(int width, int height, int frameThickness) { - int background = ip instanceof ColorProcessor ? (0xffffff) : (ip.isInvertedLut() ? 0 : 0xff); - int grid = ip instanceof ColorProcessor ? (gridColor.getRGB() & 0xffffff) : ip.getBestIndex(gridColor); - int bestPosition = 0; - int minCoveredPixels = Integer.MAX_VALUE; - for (int positionCode : new int[]{TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT}) { - Rectangle rect = legendRect(positionCode, width, height, frameThickness); - int coveredPixels = 0; - for (int y = rect.y - frameThickness/2; y <= rect.y + rect.height + frameThickness/2; y++) - for (int x = rect.x - frameThickness/2; x <= rect.x + rect.width + frameThickness/2; x++) { - int pixel = ip.getPixel(x, y) & 0xffffff; - if (pixel != background && pixel != grid) - coveredPixels ++; - } - if (coveredPixels < minCoveredPixels) { - minCoveredPixels = coveredPixels; - bestPosition = positionCode; - } - } - return bestPosition; - } - - /** Returns the x, y coordinates at the cursor position or the nearest point as a String */ - String getCoordinates(int x, int y) { - if (frame==null) return ""; - String text = ""; - if (!frame.contains(x, y)) - return text; - double xv = descaleX(x); // cursor location - double yv = descaleY(y); - boolean yIsValue = false; - if (!hasMultiplePlots()) { - PlotObject p = getMainCurveObject(); // display x and f(x) instead of cursor y - if (p != null) { - double bestDx = Double.MAX_VALUE; - double xBest = 0, yBest = 0; - for (int i=0; i=0; i--) { - if (allPlotObjects.get(i).type == PlotObject.XY_DATA) - return allPlotObjects.get(i); - } - return null; - } - - /** returns whether there are several plots so that one cannot give a single y value for a given x value */ - private boolean hasMultiplePlots() { - int nPlots = 0; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type == PlotObject.ARROWS) - return true; - else if (plotObject.type == PlotObject.XY_DATA) { - nPlots ++; - if (nPlots > 1) return true; - } - } - return nPlots > 1; - } - - public void setPlotMaker(PlotMaker plotMaker) { - this.plotMaker = plotMaker; - } - - PlotMaker getPlotMaker() { - return plotMaker; - } - - /** Returns the labels of the (non-hidden) datasets as linefeed-delimited String. - * If the label is not set, a blank line is added. */ - String getDataLabels() { - String labels = ""; - boolean first = true; - for (PlotObject plotObject : allPlotObjects) - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN)) { - if (first) - first = false; - else - labels += '\n'; - if (plotObject.label != null) labels += plotObject.label; - } - return labels; - } - - /** Creates a ResultsTable with the plot data. Returns an empty table if no data. */ - public ResultsTable getResultsTable() { - return getResultsTable(true); - } - - /** Creates a ResultsTable with the data of the plot. Returns null if no data. - * Does not write the first x column if writeFirstXColumn is false. - * When all columns are the same length, x columns equal to the first x column are - * not written, independent of writeFirstXColumn. - * Column headings are "X", "Y", "X1", "Y1", etc, irrespective of any labels of the data sets - */ - public ResultsTable getResultsTable(boolean writeFirstXColumn) { - return getResultsTable(writeFirstXColumn, false); - } - - /** Creates a ResultsTable with the data of the plot. Returns null if no data. - * When all columns are the same length, x columns equal to the first x column are - * not written, independent of writeFirstXColumn. - * When the data sets have labels, they are used for column headings - */ - public ResultsTable getResultsTableWithLabels() { - return getResultsTable(true, true); - } - - /** Creates a ResultsTable with the data of the plot. Returns null if no data. - * Does not write the first x column if writeFirstXColumn is false. - * When all columns are the same length, x columns equal to the first x column are - * not written, independent of writeFirstXColumn. - * When the data sets have labels and useLabels is true, they are used for column headings, - * otherwise columns are named X, Y, X1, Y1, ... */ - ResultsTable getResultsTable(boolean writeFirstXColumn, boolean useLabels) { - ResultsTable rt = new ResultsTable(); - // find the longest x-value data set and count the data sets - int nDataSets = 0; - int tableLength = 0; - for (PlotObject plotObject : allPlotObjects) - if (plotObject.xValues != null) { - nDataSets++; - tableLength = Math.max(tableLength, plotObject.xValues.length); - } - if (nDataSets == 0) - return null; - // enter columns one by one to lists of data and headings - ArrayList headings = new ArrayList(2*nDataSets); - ArrayList data = new ArrayList(2*nDataSets); - int dataSetNumber = 0; - int arrowsNumber = 0; - PlotObject firstXYobject = null; - boolean allSameLength = true; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type==PlotObject.XY_DATA) { - if (firstXYobject != null && firstXYobject.xValues.length!=plotObject.xValues.length) { - allSameLength = false; - break; - } - if (firstXYobject==null) - firstXYobject = plotObject; - } - } - firstXYobject = null; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type==PlotObject.XY_DATA) { - boolean sameX = firstXYobject!=null && Arrays.equals(firstXYobject.xValues, plotObject.xValues) && allSameLength; - boolean sameXY = sameX && Arrays.equals(firstXYobject.yValues, plotObject.yValues); //ignore duplicates (e.g. Markers plus Curve) - boolean writeX = firstXYobject==null ? writeFirstXColumn : !sameX; - addToLists(headings, data, plotObject, dataSetNumber, writeX, /*writeY=*/!sameXY, /*multipleSets=*/nDataSets>1, useLabels); - if (firstXYobject == null) - firstXYobject = plotObject; - dataSetNumber++; - } else if (plotObject.type==PlotObject.ARROWS) { - addToLists(headings, data, plotObject, arrowsNumber, /*writeX=*/true, /*writeY=*/true, /*multipleSets=*/nDataSets>1, /*useLabels=*/false); - arrowsNumber++; - } - } - // populate the ResultsTable - int nColumns = headings.size(); - for (int line=0; line headings, ArrayListdata, PlotObject plotObject, - int dataSetNumber, boolean writeX, boolean writeY, boolean multipleSets, boolean useLabels) { - String plotObjectLabel = useLabels ? replaceSpacesEtc(plotObject.label) : null; - if (writeX) { - String label = null; // column header for x column - if (plotObject.type!=PlotObject.ARROWS) { - String plotXLabel = getLabel('x'); - if (dataSetNumber==0 && plotXLabel!=null) { // use x axis label for 1st dataset if permitted - if (useLabels) - label = replaceSpacesEtc(plotXLabel); - else if (plotXLabel.startsWith(" ") && plotXLabel.endsWith(" ")) // legacy: always use axis label for 1st data if spaces at start&end - label = plotXLabel.substring(1,plotXLabel.length()-1); - } else if (plotObjectLabel != null && dataSetNumber>0) - label = "X_"+plotObjectLabel; // use "X_" + dataset label - if (label != null && headings.contains(label)) - label = null; // avoid duplicate labels (not possible in ResultsTable) - } - if (label == null) { // create default label if no specific label yet - label = plotObject.type == PlotObject.ARROWS ? "XStart" : "X"; - if (multipleSets) label += dataSetNumber; - } - headings.add(label); - data.add(plotObject.xValues); - } - if (writeY) { - String label = null;; // column header for y column - if (plotObject.type!=PlotObject.ARROWS) { - String plotYLabel = getLabel('y'); - if (dataSetNumber==0 && plotYLabel!=null) { - if (useLabels && plotObjectLabel == null) // use y axis label for 1st dataset if no data set label - label = replaceSpacesEtc(plotYLabel); - else if (plotYLabel.startsWith(" ") && plotYLabel.endsWith(" ")) // legacy: always use axis label for 1st data if spaces at start&end - label = plotYLabel.substring(1,plotYLabel.length()-1); - } - if (plotObjectLabel != null) - label = plotObjectLabel; - if (label != null && headings.contains(label)) - label = null; // avoid duplicate labels (not possible in ResultsTable) - } - if (label == null) { // create default label if no specific label yet - label = plotObject.type == PlotObject.ARROWS ? "YStart" : "Y"; - if (multipleSets) label += dataSetNumber; - } - headings.add(label); - data.add(plotObject.yValues); - } - if (plotObject.xEValues != null) { - String label = plotObject.type == PlotObject.ARROWS ? "XEnd" : "XERR"; - if (multipleSets) label += dataSetNumber; - headings.add(label); - data.add(plotObject.xEValues); - } - if (plotObject.yEValues != null) { - String label = plotObject.type == PlotObject.ARROWS ? "YEnd" : "ERR"; - if (multipleSets) label += dataSetNumber; - headings.add(label); - data.add(plotObject.yEValues); - } - } - - /** Convert a string to a label suitable for a ResultsTable without whitespace, quotes or commas, - * to avoid problems when saving and reading the table. Returns null if an empty string or null. */ - static String replaceSpacesEtc(String s) { - if (s == null) return null; - s = s.trim().replaceAll("[\\s,]", "_").replace("\"","''"); - if (s.length() == 0) return null; - return s; - } - - /** get the number of digits for writing a column to the results table or the clipboard */ - static int getPrecision(float[] values) { - int setDigits = Analyzer.getPrecision(); - int measurements = Analyzer.getMeasurements(); - boolean scientificNotation = (measurements&Measurements.SCIENTIFIC_NOTATION)!=0; - if (scientificNotation) { - if (setDigits max) max = values[i]; - } - } - if (allInteger) - return 0; - int digits = (max - min) > 0 ? getDigits(min, max, MIN_FLOAT_PRECISION*(max-min), 15, 0) : - getDigits(max, MIN_FLOAT_PRECISION*Math.abs(max), 15, 0); - if (setDigits>Math.abs(digits)) - digits = setDigits * (digits < 0 ? -1 : 1); //use scientific notation if needed - return digits; - } - - /** Whether a given flag 'what' is set */ - boolean hasFlag(int what) { - return (pp.axisFlags&what) != 0; - } - - /* Obsolete, replaced by add(shape,x,y). */ - public void addPoints(String dummy, float[] x, float[] y, int shape) { - addPoints(x, y, shape); - } - - /** Plots a histogram from an array using auto-binning. - * @param values array containing the population - * N.Vischer - */ - public void addHistogram(double[] values) { - addHistogram(values, 0, 0); - } - - /** Plots a histogram from an array using the specified bin width. - * @param values array containing the population - * @param binWidth set zero for auto-binning - * N.Vischer - */ - public void addHistogram(double[] values, double binWidth) { - addHistogram(values, binWidth, 0); - } - - /** Plots a histogram of the value distribution (bin counts) from an array - * @param values array containing the values for the population - * @param binWidth set zero for auto-binning - * @param binCenter any x value can be the center of a bin - * N.Vischer - */ - public void addHistogram(double[] values, double binWidth, double binCenter) { - int len = values.length; - double min = Double.POSITIVE_INFINITY; - double max = Double.NEGATIVE_INFINITY; - double[] cleanVals = new double[len]; - int count = 0; - double sum = 0, sum2 = 0; - for (int i = 0; i < len; i++) { - double val = values[i]; - if (!Double.isNaN(val)) { - cleanVals[count++] = val; - sum += val; - sum2 += val * val; - if (val < min) - min = val; - if (val > max) - max = val; - } - } - if (binWidth <= 0) {//autobinning - double stdDev = Math.sqrt(((count * sum2 - sum * sum) / count) / count);//not count - 1 - // use Scott's method (1979 Biometrika, 66:605-610) for optimal binning: 3.49*sd*N^-1/3 - binWidth = 3.49 * stdDev * (Math.pow(count, -1.0 / 3)); - - } - double modCenter = binCenter % binWidth; - double modMin = min % binWidth; - double diff = modMin - modCenter; - double firstBin = min-diff; - while(firstBin - binWidth * 0.499 > min) - firstBin -= binWidth; - int nBins = (int) ((max - firstBin)/binWidth); - double lastBin = firstBin + nBins * binWidth; - while(lastBin + binWidth * 0.499 < max) - lastBin += binWidth; - nBins = (int) Math.round((lastBin - firstBin)/binWidth) + 1; - if (nBins == 1) - nBins = 2; - if (nBins > 9999) { - IJ.error("max bins > 9999"); - return; - } - double[] histo = new double[nBins]; - double[] xValues = new double[nBins]; - for (int i = 0; i < nBins; i++) - xValues[i] = firstBin + i * binWidth; - for (int i = 0; i < count; i++) { - double val = cleanVals[i]; - double indexD = (val - firstBin) / binWidth; - int index = (int) Math.round(indexD); - if (index < 0 || index >= nBins) { - IJ.error("index out of range"); - return; - } else - histo[index]++; - } - add("bar", xValues, histo); - } - - /* Obsolete, replaced by add("error bars",errorBars). */ - public void addErrorBars(String dummy, float[] errorBars) { - addErrorBars(errorBars); - } - - /* Obsolete; replaced by setFont(). */ - public void changeFont(Font font) { - setFont(font); - } - -} - -/** This class contains the properties of the plot, such as size, format, range, etc, except for the data+format (plot contents). - * To enable reading serialized PlotObjects of plots created with previous versions of ImageJ, - * the variable names MUST NEVER be changed! Also any additions should be made after careful thought, - * since they have to be kept for all future versions. */ -class PlotProperties implements Cloneable, Serializable { - /** The serialVersionUID should not be modified, otherwise saved plots won't be readable any more */ - static final long serialVersionUID = 1L; - // - PlotObject frame = new PlotObject(Plot.DEFAULT_FRAME_LINE_WIDTH); //the frame, including background color and axis numbering - PlotObject xLabel = new PlotObject(PlotObject.AXIS_LABEL); //the x axis label (string & font) - PlotObject yLabel = new PlotObject(PlotObject.AXIS_LABEL); //the x axis label (string & font) - PlotObject legend; //the legend (if any) - int width = 0; //canvas width (note: when stored, this must fit the image) - int height = 0; - int axisFlags; //these define axis layout - double[] rangeMinMax; //currentMinMax when writing, sets defaultMinMax when reading - boolean antialiasedText = true; - boolean isFrozen; //modifications (size, range, contents) don't update the ImageProcessor - - /** Returns an array of all PlotObjects defined as PlotProperties. Note that some may be null */ - PlotObject[] getAllPlotObjects() { - return new PlotObject[]{frame, xLabel, xLabel, legend}; - } - - /** Returns the PlotObject for xLabel ('x'), yLabel('y'), frame ('f'; includes number font) or the legend ('l'). */ - PlotObject getPlotObject(char c) { - switch(c) { - case 'x': return xLabel; - case 'y': return yLabel; - case 'f': return frame; - case 'l': return legend; - default: return null; - } - } - - /** A shallow clone that does not duplicate arrays or objects */ - public PlotProperties clone() { - try { - return (PlotProperties)(super.clone()); - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** A deep clone; it also duplicates arrays and pPlotObjects */ - public PlotProperties deepClone() { - PlotProperties pp2 = clone(); //shallow clone - if (frame != null) pp2.frame = frame.deepClone(); - if (xLabel != null) pp2.xLabel = xLabel.deepClone(); - if (yLabel != null) pp2.yLabel = yLabel.deepClone(); - if (legend != null) pp2.legend = legend.deepClone(); - if (rangeMinMax != null) pp2.rangeMinMax = rangeMinMax.clone(); - return pp2; - } - -} // class PlotProperties - -/** This class contains the data and properties for displaying a curve, a set of arrows, a line or a label in a plot, - * as well as the legend, axis labels, and frame (including background and fonts of axis numbering). - * Note that all properties such as lineWidths and Fonts have to be scaled up for high-resolution plots. - * This class allows serialization for writing into tiff files. - * To enable reading serialized PlotObjects of plots created with previous versions of ImageJ, - * the variable names MUST NEVER be changed! Also any additions should be made after careful thought, - * since they have to be kept for all future versions. */ -class PlotObject implements Cloneable, Serializable { - /** The serialVersionUID should not be modified, otherwise saved plots won't be readable any more */ - static final long serialVersionUID = 1L; - /** Constants for the type of objects. These are powers of two so one can use them as masks */ - public final static int XY_DATA = 1, ARROWS = 2, LINE = 4, NORMALIZED_LINE = 8, DOTTED_LINE = 16, - LABEL = 32, NORMALIZED_LABEL = 64, LEGEND = 128, AXIS_LABEL = 256, FRAME = 512, SHAPES = 1024; - /** mask for recovering font style from the flags */ - final static int FONT_STYLE_MASK = 0x0f; - /** flag for the data set passed with the constructor. Note that 0 to 0x0f are reserved for fonts modifiers, 0x010-0x800 are reserved for legend modifiers */ - public final static int CONSTRUCTOR_DATA = 0x1000; - /** flag for hiding a PlotObject */ - public final static int HIDDEN = 0x2000; - /** Type of the object; XY_DATA stands for curve or markers, can be also ARROWS ... SHAPES */ - public int type = XY_DATA; - /** bitwise combination of flags, or the position of a legend */ - public int flags; - /** Options, currently only for FRAME, see Plot.setOptions */ - public String options; - /** The x and y data arrays and the error bars (if non-null). These arrays also serve as x0, y0, x1, y1 - * arrays for plotting arrays of arrows */ - public float[] xValues, yValues, xEValues, yEValues; - /** For SHAPES: For boxplots with whiskers ('boxes'), elements of the ArrayList are float[6] with x and all 5 y values - * (for 'boxesx', y and all 5 x values), for 'rectangles', float[4] with x1, y1, x2, y2. */ - public ArrayList shapeData; - /** For SHAPES only, shape type & options. Currently implemented: 'boxes', 'boxesx' (box plots with whiskers), 'rectangles', 'redraw_grid' */ - public String shapeType; //e.g. "boxes width=20" - /** Type of the points, such as Plot.LINE, Plot.CROSS etc. (for type = XY_DATA) */ - public int shape; - /** The line width in pixels for 'normal' plots (for high-resolution plots, to be multiplied by a scale factor) */ - public float lineWidth; - /** The color of the object, must not be null */ - public Color color; - /** The secondary color (for filling closed symbols and for the line of CIRCLES_AND_LINE, may be null for unfilled/default */ - public Color color2; - /** Labels and lines: Position (NORMALIZED objects: relative units 0...1). */ - public double x, y; - /** Lines only: End position */ - public double xEnd, yEnd; - /** Dotted lines only: step */ - public int step; - /** A label for the y data of the curve, a text to draw, or the text of a legend (tab-delimited lines) */ - public String label; - /** Labels only: Justification can be Plot.LEFT, Plot.CENTER or Plot.RIGHT */ - public int justification; - /** Macro code for drawing symbols */ - public String macroCode; - /** Text objects (labels, legend, axis labels) only: the font; maybe null for default. This is not serialized (transient) */ - private transient Font font; - /** String for representation of the font family (for Serialization); may be null for default. Font style is in flags, font size in fontSize. */ - private String fontFamily; - /** Font size (for Serialization), for 'normal' plots (for high-resolution plots, to be multiplied by a scale factor) */ - private float fontSize; - - - /** Generic constructor */ - PlotObject(int type) { - this.type = type; - } - - /** Constructor for XY_DATA, i.e., a curve or set of points */ - PlotObject(float[] xValues, float[] yValues, float[] yErrorBars, int shape, float lineWidth, Color color, Color color2, String yLabel) { - this.type = XY_DATA; - this.xValues = xValues; - this.yValues = yValues; - this.yEValues = yErrorBars; - this.shape = shape; - this.lineWidth = lineWidth; - this.color = color; - this.color2 = color2; - this.label = yLabel; - if (shape==Plot.CUSTOM) - this.macroCode = yLabel; - } - - /** Constructor for a set of arrows */ - PlotObject(float[] x1, float[] y1, float[] x2, float[] y2, float lineWidth, Color color) { - this.type = ARROWS; - this.xValues = x1; - this.yValues = y1; - this.xEValues = x2; - this.yEValues = y2; - this.lineWidth = lineWidth; - this.color = color; - } - - /** Constructor for a set of shapes */ - PlotObject(String shapeType, ArrayList shapeData, float lineWidth, Color color, Color color2) { - this.type = SHAPES; - this.shapeData = shapeData; - this.shapeType = shapeType; - this.lineWidth = lineWidth; - this.color = color; - this.color2 = color2; - } - - /** Constructor for a line */ - PlotObject(double x, double y, double xEnd, double yEnd, float lineWidth, int step, Color color, int type) { - this.type = type; - this.x = x; - this.y = y; - this.xEnd = xEnd; - this.yEnd = yEnd; - this.lineWidth = lineWidth; - this.step = step; - this.color = color; - } - - /** Constructor for a label or NORMALIZED_LABEL */ - PlotObject(String label, double x, double y, int justification, Font font, Color color, int type) { - this.type = type; - this.label = label; - this.x = x; - this.y = y; - this.justification = justification; - setFont(font); - this.color = color; - } - - /** Constructor for the legend. flags is bitwise or of TOP_LEFT etc. and LEGEND_TRANSPARENT if desired. - * Note that the labels in the legend are those of the data plotObjects */ - PlotObject(float lineWidth, Font font, Color color, int flags) { - this.type = LEGEND; - this.lineWidth = lineWidth; - setFont(font); - this.color = color; - this.flags = flags; - } - - /** Constructor for the frame, including axis numbers. In the current version, the primary color (line color) is always black */ - PlotObject(float lineWidth) { - this.type = FRAME; - this.color = Color.black; - this.lineWidth = lineWidth; - } - - /** Whether a given flag 'what' is set */ - boolean hasFlag(int what) { - return (flags&what) != 0; - } - - /** Sets a given flag */ - void setFlag(int what) { - flags |= what; - } - - /** Unsets a given flag */ - void unsetFlag(int what) { - flags = flags & (~what); - } - - /** Whether an XY_DATA object has a curve to draw */ - boolean hasCurve() { - return type == XY_DATA && (shape == Plot.LINE || shape == Plot.CONNECTED_CIRCLES || shape == Plot.FILLED); - } - - /** Whether an XY_DATA object has markers to draw */ - boolean hasMarker() { - return type == XY_DATA && (shape == Plot.CIRCLE || shape == Plot.X || shape == Plot.BOX || shape == Plot.TRIANGLE - || shape == Plot.CROSS || shape == Plot.DIAMOND || shape == Plot.DOT || shape == Plot.CONNECTED_CIRCLES - || shape == Plot.CUSTOM); - } - - /** Whether an XY_DATA object has markers that can be filled */ - boolean hasFilledMarker() { - return type == XY_DATA && color2 != null && (shape == Plot.CIRCLE || shape == Plot.BOX || shape == Plot.TRIANGLE || - shape == Plot.DIAMOND || shape == Plot.CONNECTED_CIRCLES); - } - - /** Size of the markers for an XY_DATA object with markers */ - int getMarkerSize() { - if (lineWidth<=1) - return 5; - else if (lineWidth<=3) - return 7; - else - return (int)(lineWidth+4); - } - - /** Sets the font. Also writes font properties for serialization. */ - void setFont(Font font) { - if (font == this.font) return; - this.font = font; - if (font == null) { - fontFamily = null; - } else { - fontFamily = font.getFamily(); - flags = (flags & ~FONT_STYLE_MASK) | font.getStyle(); - fontSize = font.getSize2D(); - } - } - - /** Returns the font, or null if none specified */ - Font getFont() { - if (font == null && fontFamily != null) //after recovery from serialization, create the font from its description - font = FontUtil.getFont(fontFamily, flags&FONT_STYLE_MASK, fontSize); - return font; - } - - /** Returns the font size */ - float getFontSize() { - return fontSize; - } - - /** Returns all data xValues, yValues, xEValues, yEValues as a float[][] array. Note that future versions may have more data. */ - float[][] getAllDataValues() { - return new float[][] {xValues, yValues, xEValues, yEValues}; - } - - /** A shallow clone that does not duplicate arrays or objects */ - public PlotObject clone() { - try { - return (PlotObject)(super.clone()); - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** A deep clone, which duplicates arrays etc. - * Note that colors & font are not cloned; it is assumed that these wil not be modified but replaced, - * so the clone remains unaffected */ - public PlotObject deepClone() { - PlotObject po2 = clone(); - if (xValues != null) po2.xValues = xValues.clone(); - if (yValues != null) po2.yValues = yValues.clone(); - if (xEValues != null) po2.xEValues = xEValues.clone(); - if (yEValues != null) po2.yEValues = yEValues.clone(); - if (shapeData != null) po2.shapeData = cloneArrayList(shapeData); - return po2; - } - - /** A clone of an array list one level deeper than a shallow clone. - * The clone() method of the objects in the list must be accessible */ - private ArrayList cloneArrayList(ArrayList src) { - ArrayList dest = (ArrayList)(src.clone()); //shallow clone - Class[] noClasses = new Class[0]; - Object[] noObjects = new Object[0]; - for (int i=0; i 1) - super.zoomIn(sx, sy); - else - super.zoomOut(sx, sy); - return; - } - plot.zoom(sx, sy, zoomFactor); - } - - /** - * Implements the Image/Zoom/Original Scale command. Sets the original range of - * the x, y axes (unless the plot is frozen) - */ - public void unzoom() { - if (plot == null || plot.isFrozen()) { - super.unzoom(); - return; - } - resetMagnification(); - plot.setLimitsToDefaults(true); - } - - /** - * Implements the Image/Zoom/View 100% command: Sets the original frame size as - * specified in Edit/Options/Plots (unless the plot is frozen) - */ - public void zoom100Percent() { - if (plot == null || plot.isFrozen()) { - super.zoom100Percent(); - return; - } - resetMagnification(); - plot.setFrameSize(PlotWindow.plotWidth, PlotWindow.plotHeight); - } - - /** Resizes the plot (unless frozen) to fit the window */ - public void fitToWindow() { - if (plot == null || plot.isFrozen()) { - super.fitToWindow(); - return; - } - ImageWindow win = imp.getWindow(); - if (win == null) - return; - Rectangle bounds = win.getBounds(); - Dimension extraSize = win.getExtraSize(); - int width = bounds.width - extraSize.width;// (insets.left+insets.right+ImageWindow.HGAP*2); - int height = bounds.height - extraSize.height;// (insets.top+insets.bottom+ImageWindow.VGAP*2); - // IJ.log("fitToWindow "+bounds+"-> w*h="+width+"*"+height); - resizeCanvas(width, height); - getParent().doLayout(); - } - - /** - * Resizes the canvas when the user resizes the window. To avoid a race - * condition while creating a new window, this is ignored if no window exists or - * the window has not been activated yet. - */ - void resizeCanvas(int width, int height) { - if (plot == null || plot.isFrozen()) { - super.resizeCanvas(width, height); - return; - } - resetMagnification(); - if (width == oldWidth && height == oldHeight) - return; - if (plot == null) - return; - ImageWindow win = imp.getWindow(); - if (win == null || !(win instanceof PlotWindow)) - return; - if (!win.isVisible()) - return; - if (!((PlotWindow) win).wasActivated) - return; // window layout not finished yet? - Dimension minSize = plot.getMinimumSize(); - int plotWidth = width < minSize.width ? minSize.width : width; - int plotHeight = height < minSize.height ? minSize.height : height; - plot.setSize(plotWidth, plotHeight); - setSize(width, height); - oldWidth = width; - oldHeight = height; - ((PlotWindow)win).canvasResized(); - } - - /** - * The image of a PlotCanvas is always shown at 100% magnification unless the - * plot is frozen - */ - public void setMagnification(double magnification) { - if (plot == null || plot.isFrozen()) - super.setMagnification(magnification); - else - resetMagnification(); - } - - /** - * Scrolling a PlotCanvas is updating the plot, not viewing part of the plot, - * unless the plot is frozen - */ - public void setSourceRect(Rectangle r) { - if (plot.isFrozen()) - super.setSourceRect(r); - else - resetMagnification(); - } - - void resetMagnification() { - magnification = 1.0; - srcRect.x = 0; - srcRect.y = 0; - } - - /** - * overrides ImageCanvas.setupScroll; if plot is not frozen, scrolling modifies - * the plot data range - */ - protected void setupScroll(int ox, int oy) { - if (plot.isFrozen()) { - super.setupScroll(ox, oy); - return; - } - xMouseStart = ox; - yMouseStart = oy; - xScrolled = 0; - yScrolled = 0; - } - - /** - * overrides ImageCanvas.scroll; if plot is not frozen, scrolling modifies the - * plot data range - */ - protected void scroll(int sx, int sy) { - if (plot.isFrozen()) { - super.scroll(sx, sy); - return; - } - if (sx == 0 && sy == 0) - return; - if (xScrolled == 0 && yScrolled == 0) - plot.saveMinMax(); - int dx = sx - xMouseStart; - int dy = sy - yMouseStart; - plot.scroll(dx - xScrolled, dy - yScrolled); - xScrolled = dx; - yScrolled = dy; - Thread.yield(); - } - - /** overrides ImageCanvas.mouseExited; removes 'range' arrows */ - public void mouseExited(MouseEvent e) { - ImageWindow win = imp.getWindow(); - if (win instanceof PlotWindow) - ((PlotWindow) win).mouseExited(e); - super.mouseExited(e); - } - - /** - * overrides ImageCanvas.mousePressed: no further processing of clicks on - * 'range' arrows - */ - public void mousePressed(MouseEvent e) { - /* Changed for Bio7! */ - - WindowManager.setTempCurrentImage(imp); - WindowManager.setCurrentWindow(imp.getWindow()); - - /* import to set current Panel! */ - CanvasView.setCurrent((JPanel) this.getParent()); - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - ImageWindow wind = imp.getWindow(); - if (wind != null) { - Frame frameSwtAwt = wind.getSwtAwtMain().getFrame(); - if (frameSwtAwt != null) { - - if (frameSwtAwt != null) - frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, WindowEvent.WINDOW_ACTIVATED)); - // frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, - // WindowEvent.WINDOW_GAINED_FOCUS)); - - if (PlotCanvas.this.isFocusOwner() == false) { - PlotCanvas.this.requestFocus(); - - } - } - } - } - }); - - rangeArrowIndexWhenPressed = getRangeArrowIndex(e); - if (rangeArrowIndexWhenPressed < 0) - super.mousePressed(e); - } - - /** Overrides ImageCanvas.mouseReleased, handles clicks on 'range' arrows */ - public void mouseReleased(MouseEvent e) { - if (rangeArrowIndexWhenPressed >= 0 && rangeArrowIndexWhenPressed == getRangeArrowIndex(e)) - plot.zoomOnRangeArrow(rangeArrowIndexWhenPressed); - else - super.mouseReleased(e); - } - - /* - * Changed for Bio7! We have no visible PlotWindow so we implement the mouse - * listener here! - */ - - public void mouseWheelMoved(MouseWheelEvent e) { - ImageCanvas ic = imp.getCanvas(); - if (plot.isFrozen() || !(ic instanceof PlotCanvas)) { // frozen plots are like normal images - super.mouseWheelMoved(e); - return; - } - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - if (e.getX() < plot.leftMargin || e.getX() > plot.leftMargin + plot.frameWidth)// n__ - return; - if (e.getY() < plot.topMargin || e.getY() > plot.topMargin + plot.frameHeight) - return; - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - if (ctrl || IJ.shiftKeyDown()) { - double zoomFactor = rotation < 0 ? Math.pow(2, 0.2) : Math.pow(0.5, 0.2); - Point loc = ic.getCursorLoc(); - int x = ic.screenX(loc.x); - int y = ic.screenY(loc.y); - ((PlotCanvas) ic).zoom(x, y, zoomFactor); - } else if (IJ.spaceBarDown()) - plot.scroll(rotation * amount * Math.max(ic.imageWidth / 50, 1), 0); - else - plot.scroll(0, rotation * amount * Math.max(ic.imageHeight / 50, 1)); - } - - /** - * Returns the index of the arrow for modifying the range when the mouse click - * was at such an arrow, otherwise -1 - */ - int getRangeArrowIndex(MouseEvent e) { - ImageWindow win = imp.getWindow(); - int rangeArrowIndex = -1; - if (win instanceof PlotWindow) { - int x = e.getX(); - int y = e.getY(); - rangeArrowIndex = ((PlotWindow) win).getRangeArrowIndex(x, y); - } - return rangeArrowIndex; - } -} diff --git a/com.eco.bio7.image/src/ij/gui/PlotContentsDialog.java b/com.eco.bio7.image/src/ij/gui/PlotContentsDialog.java deleted file mode 100644 index 5fe72bfed..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotContentsDialog.java +++ /dev/null @@ -1,670 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.measure.CurveFitter; -import ij.measure.Minimizer; -import ij.text.TextWindow; -import ij.measure.ResultsTable; -import ij.plugin.Colors; -import ij.plugin.frame.Recorder; -import ij.util.Tools; -import java.awt.*; -import java.awt.event.*; -import java.util.Arrays; -import java.util.Vector; -import java.util.ArrayList; - -/** This class implements the Plot Window's Data>"Add from Plot", "Add form Table", "Add Fit" and - * "More>Contents Style" dialogs - */ -public class PlotContentsDialog implements DialogListener { - /** Types of dialog (ERROR suppresses the dialog after an invalid call of a constructor) */ - public final static int ERROR=-1, STYLE=0, ADD_FROM_PLOT=1, ADD_FROM_TABLE=2, ADD_FROM_ARRAYS=3, ADD_FIT=4; - /** Dialog headings for each dialogType >= 0 */ - private static final String[] HEADINGS = new String[] {"Plot Contents Style", "Add From Plot", "Plot From Table", "Add Plot Data", "Add Fit"}; - private Plot plot; // the plot we work on - private int dialogType; // determines what to do: ADD_FORM_PLOT, etc. - private double[] savedLimits; // previous plot range, for undo upon cancel - GenericDialog gd; - private int currentObjectIndex = -1; - private Choice objectChoice; - private Choice symbolChoice; - private TextField colorField, color2Field, labelField, widthField; - private Checkbox visibleCheckbox; - private boolean creatingPlot; // for creating plots; dialogType determines source - private Choice plotChoice; // for "Add from Plot" - private Plot[] allPlots; - private String[] allPlotNames; - private static Plot previousPlot; - private static int previousPlotObjectIndex; - private int defaultPlotIndex, defaultObjectIndex; - private int currentPlotNumObjects; - private Choice tableChoice; // for "Add from Table" - final static int N_COLUMNS = 4; // number of data columns that we can have; x, y, xE, yE - private int nColumnsToUse = N_COLUMNS; // user may restrict to 2, for not having error bars - private Choice[] columnChoice = new Choice[N_COLUMNS]; - private final static String[] COLUMN_NAMES = new String[] {"X:", "Y:", "X Error:", "Y Error:"}; - private final static boolean[] COLUMN_ALLOW_NONE = new boolean[] {true, false, true, true}; //y data cannot be null - private ResultsTable[] allTables; - private String[] allTableNames; - private static String previousTableName; - private static int[] previousColumns = new int[]{1, 1, 0, 0}; //must be N_COLUMNS elements - private static int defaultTableIndex; - private static int[] defaultColumnIndex = new int[N_COLUMNS]; - private String[] arrayHeadings; // for "Add from Arrays" - private ArrayList arrayData; - private Choice fitDataChoice; // for "Add Fit" - private Choice fitFunctionChoice; - private Thread fittingThread; - private static String lastFitFunction = CurveFitter.fitList[0]; - private String curveFitterStatusString; - private static String previousColor="blue", previousColor2="#a0a0ff", previousSymbol="Circle"; - private static double previousLineWidth = 1; - private static final String[] PLOT_COLORS = new String[] {"blue", "red", "black", "#00c0ff", "#00e000", "gray", "#c08060", "magenta"}; - - - /** Prepares a new PlotContentsDialog for an existing plot. Use showDialog thereafter. - * @param dialogType may be STYLE (contents style), ADD_FROM_PLOT (add object from other plot), ADD_FROM_TABLE, and ADD_FIT */ - public PlotContentsDialog(Plot plot, int dialogType) { - this.plot = plot; - this.dialogType = plot == null ? ERROR : dialogType; - if (plot != null) currentPlotNumObjects = plot.getNumPlotObjects(); - } - - /** Prepares a new PlotContentsDialog for creating a new plot using data from a ResultsTable. - * Use showDialog thereafter. */ - public PlotContentsDialog(String title, ResultsTable rt) { - creatingPlot = true; - dialogType = ADD_FROM_TABLE; - if (rt == null || !isValid(rt)) { - IJ.error("Cant Create Plot","No (results) table or no data in "+title); - dialogType = ERROR; - } - plot = new Plot("Plot of "+title, "x", "y"); - allTables = new ResultsTable[] {rt}; - allTableNames = new String[] {title}; - } - - /** Prepares a new PlotContentsDialog for creating a new plot using float[] arrays as data. - * Each 'data' array in the ArrayList must have a corresponding element in the 'headings' array. - * 'defaultHeadings' may contain the headings of the items selected initially for x, y, x error and y error, respectively. - * 'defaultHeadings' and each of its entries may be null, and the array may have any length. */ - public PlotContentsDialog(String title, String[] headings, String[] defaultHeadings, ArrayList data) { - creatingPlot = true; - dialogType = ADD_FROM_ARRAYS; - this.arrayHeadings = headings; - this.arrayData = data; - plot = new Plot(title, "x", "y"); - setDefaultColumns(defaultHeadings); - } - - /** Prepares a new PlotContentsDialog for adding data from float[] arrays to a plot. - * Each 'data' array in the ArrayList must have a corresponding element in the 'headings' array. - * 'defaultHeadings' may contain the headings of the items selected initially for x, y, x error and y error, respectively. - * 'defaultHeadings' and each of its entries may be null, and the array may have any length. */ - public PlotContentsDialog(Plot plot, String[] headings, String[] defaultHeadings, ArrayList data) { - dialogType = ADD_FROM_ARRAYS; - this.plot = plot; - this.arrayHeadings = headings; - this.arrayData = data; - setDefaultColumns(defaultHeadings); - } - - /** Avoids showing a selection for the error bars; must be called before showDialog. */ - public void noErrorBars() { - nColumnsToUse = 2; // only x, y columns can be selected - } - - /** Shows the dialog, with a given parent Frame (may be null) */ - public void showDialog(Frame parent) { - if (dialogType == ERROR) return; - if (!creatingPlot) savedLimits = plot.getLimits(); - plot.savePlotObjects(); - String[] designations = plot.getPlotObjectDesignations(); - if (dialogType == STYLE && designations.length==0) { - IJ.error("Empty Plot"); - return; - } else if (dialogType == ADD_FROM_PLOT) { - prepareAddFromPlot(); - if (allPlots.length == 0) return; //should never happen; we have at least the current plot - } else if (dialogType == ADD_FROM_TABLE && !creatingPlot) { - prepareAddFromTable(); - if (allTables.length == 0) return; //should never happen; PlotWindow should not enable if no table - } - if ((dialogType == ADD_FROM_TABLE || dialogType == ADD_FROM_ARRAYS) && !creatingPlot) - suggestColor(); - if (parent == null && plot.getImagePlus() != null) - parent = plot.getImagePlus().getWindow(); - gd = parent == null ? new GenericDialog(HEADINGS[dialogType]) : - new GenericDialog(HEADINGS[dialogType], parent); - IJ.wait(100); //sometimes needed to avoid hanging? - if (dialogType == STYLE) { - gd.addChoice("Item:", designations, designations[0]); - objectChoice = (Choice)(gd.getChoices().get(0)); - currentObjectIndex = objectChoice.getSelectedIndex(); - } else if (dialogType == ADD_FROM_PLOT) { - gd.addChoice("Select Plot:", allPlotNames, allPlotNames[defaultPlotIndex]); - gd.addChoice("Item to Add:", new String[]{""}, ""); // will be set up by makeSourcePlotObjects - Vector choices = gd.getChoices(); - plotChoice = (Choice)(choices.get(0)); - objectChoice = (Choice)(choices.get(1)); - makeSourcePlotObjects(); - } else if (dialogType == ADD_FROM_TABLE) { - gd.addChoice("Select Table:", allTableNames, allTableNames[defaultTableIndex]); - tableChoice = (Choice)(gd.getChoices().get(0)); - if (creatingPlot) tableChoice.setEnabled(false); // we can't select the table, we have only one - } else if (dialogType == ADD_FIT) { - String[] dataSources = plot.getDataObjectDesignations(); - if (dataSources.length == 0) { - IJ.error("No Data For Fitting"); - return; - } - gd.addChoice("Fit Data Set:", dataSources, dataSources[0]); - gd.addChoice("Fit Function:", new String[0], ""); - Vector choices = gd.getChoices(); - fitDataChoice = (Choice)(choices.get(0)); - fitFunctionChoice = (Choice)(choices.get(1)); - if (dataSources.length == 1) - fitDataChoice.setEnabled(false); - for (int i=0; i 0) - Recorder.recordString("Plot.add(\"xerror\", Table.getColumn(\""+ - columnChoice[2].getSelectedItem()+"\", \""+tableChoice.getSelectedItem()+"\"));\n"); - if (columnChoice[3].getSelectedIndex() > 0) - Recorder.recordString("Plot.add(\"error\", Table.getColumn(\""+ - columnChoice[3].getSelectedItem()+"\", \""+tableChoice.getSelectedItem()+"\"));\n"); - } - Recorder.recordString("Plot.setStyle("+currentObjectIndex+", \""+getStyleString()+"\");\n"); - } - } - - public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { - if (e==null) - return true; //gets called with e=null upon OK - boolean setStyle = false; - if (dialogType == STYLE) { - int objectIndex = objectChoice.getSelectedIndex(); // no getNextChoice since Choices depend on dialog type - setStyle = (e.getSource() != objectChoice); - if (e.getSource() == objectChoice) { - setDialogStyleFields(objectIndex); - currentObjectIndex = objectIndex; - } else - setStyle = true; - } else if (dialogType == ADD_FROM_PLOT) { - if (e.getSource() == plotChoice) { - makeSourcePlotObjects(); - addObjectFromPlot(); - } else if (e.getSource() == objectChoice) { - addObjectFromPlot(); - } else - setStyle = true; - } else if (dialogType == ADD_FROM_TABLE || dialogType == ADD_FROM_ARRAYS) { - if (e.getSource() == tableChoice) { - makeSourceColumns(); - addObjectFromTable(); - } else { - boolean columnChanged = false; - for (int c=0; c 0 ? label : null); - } - } - - /** Returns the style String for Plot.setPlotObjectStyle from the dialog fields */ - private String getStyleString() { - String color = colorField.getText(); - String color2 = color2Field.getText(); - double width = Tools.parseDouble(widthField.getText()); - String symbol = symbolChoice.getSelectedItem(); - Boolean visible = visibleCheckbox.getState(); - String style = color.trim()+","+color2.trim()+","+(float)width+","+ symbol+(visible?"":"hidden"); - return style; - } - - /** Sets the style fields of the dialog according to the style of the PlotObject having the - * index given. Does nothing with index < 0 */ - private void setDialogStyleFields(int index) { - if (index < 0) return; - Checkbox visibleC = (Checkbox)gd.getCheckboxes().get(0); - String styleString = plot.getPlotObjectStyle(index); - String designation = plot.getPlotObjectDesignations()[index].toLowerCase(); - boolean isData = designation.startsWith("data"); - boolean isText = designation.startsWith("text"); - boolean isBox = designation.startsWith("shapes") && - (designation.contains("boxes") || designation.contains("rectangles")); - boolean isGrid = designation.startsWith("shapes") && designation.contains("redraw_grid"); - - String[] items = styleString.split(","); - colorField.setText(items[0]); - color2Field.setText(items[1]); - widthField.setText(items[2]); - if (items.length >= 4) - symbolChoice.select(items[3]); - labelField.setText(isData ? plot.getPlotObjectLabel(index) : ""); - visibleC.setState(!styleString.contains("hidden")); - - colorField.setEnabled(!isGrid); //grid color is fixed - color2Field.setEnabled(isData || isBox);//only (some) data symbols and boxes have secondary (fill) color - widthField.setEnabled(!isText && !isGrid); //all non-Text types have line width - // visibleC.setEnabled(!isGrid); //allow to hide everything - symbolChoice.setEnabled(isData); //only data have a symbol to choose - labelField.setEnabled(isData); //only data have a label in the legend - } - - - /** Prepare the lists 'allPlots', 'allPlotNames' for the "Add from Plot" dialog. - * Also sets 'defaultPlotIndex', 'defaultObjectIndex' */ - private void prepareAddFromPlot() { - int[] windowIDlist = WindowManager.getIDList(); - ArrayList plotImps = new ArrayList(); - ImagePlus currentPlotImp = null; - for (int windowID : windowIDlist) { - ImagePlus imp = WindowManager.getImage(windowID); - if (imp == null || imp.getWindow() == null) continue; - Plot thePlot = (Plot)(imp.getProperty(Plot.PROPERTY_KEY)); - if (thePlot != null) { - if (thePlot == plot) - currentPlotImp = imp; - else - plotImps.add(imp); - } - } - if (currentPlotImp != null) - plotImps.add(currentPlotImp); // add current plot as the last one (usually not used) - if (plotImps.size() == 0) return; // should never happen; we have at least the current plot - - allPlots = new Plot[plotImps.size()]; - allPlotNames = new String[plotImps.size()]; - defaultPlotIndex = 0; - for (int i=0; i tableWindows = new ArrayList(); - Frame[] windows = WindowManager.getNonImageWindows(); - for (Frame win : windows) { - if (!(win instanceof TextWindow)) continue; - ResultsTable rt = ((TextWindow)win).getResultsTable(); - if (isValid(rt)) - tableWindows.add((TextWindow)win); - } - allTables = new ResultsTable[tableWindows.size()]; - allTableNames = new String[tableWindows.size()]; - defaultTableIndex = 0; - for (int i=0; i 0) { - String[] newHeadings = new String[columnHeadings.length - nBadColumns]; - int i=0; - for (String heading : columnHeadings) //copy 'good' headings - if (heading != null) - newHeadings[i++] = heading; - columnHeadings = newHeadings; - } - } else { // if (dialogType == ADD_FROM_ARRAYS) - columnHeadings = new String[arrayHeadings.length+1]; - System.arraycopy(arrayHeadings, 0, columnHeadings, 1, arrayHeadings.length); - } - columnHeadings[0] = "---"; - for (int c=0; c 0 && previousColumns[c] >= 0) - columnChoice[c].select(Math.min(columnChoice[c].getItemCount()-1, previousColumns[c])); - } - } - - /** For "Add from Table" and "Add from Arrays" adds item to the plot according to the current Choice settings - * and sets the Style fields for it. */ - private void addObjectFromTable() { - float[][] data = getDataArrays(); - if (data[1] == null) return; //no y data? then can't plot - String label = columnChoice[1].getSelectedItem(); //take label from y - int shape = Plot.toShape(symbolChoice.getSelectedItem()); - float lineWidth = (float)(Tools.parseDouble(widthField.getText())); - if (lineWidth > 0) - plot.setLineWidth(lineWidth); - plot.restorePlotObjects(); - if (savedLimits != null) - plot.setLimits(savedLimits); - plot.setColor(colorField.getText(), color2Field.getText()); - plot.addPoints(data[0], data[1], data[3], shape, label); - if (data[2] != null) - plot.addHorizontalErrorBars(data[2]); - if (creatingPlot) { - plot.setXYLabels(data[0]==null ? "x" : columnChoice[0].getSelectedItem(), columnChoice[1].getSelectedItem()); - plot.setLimitsToFit(false); - } else - plot.fitRangeToLastPlotObject(); - currentObjectIndex = plot.getNumPlotObjects()-1; - setDialogStyleFields(currentObjectIndex); - if (dialogType == ADD_FROM_TABLE) - previousTableName = allTableNames[tableChoice.getSelectedIndex()]; - } - - /** For "Add from Table" and "Add from Arrays", tries to set a 'y' data column that has not been plotted yet. */ - private void suggestNewYColumn() { - int nYcolumns = columnChoice[1].getItemCount(); - int currentIndex = columnChoice[1].getSelectedIndex(); - for (int i=0; i= 0) - data[c] = rt.getColumn(index); - previousColumns[c] = columnChoice[c].getSelectedIndex(); - } - } else { //if (dialogType == ADD_FROM_ARRAYS) - for (int c=0; c= 0) - data[c] = arrayData.get(index); - previousColumns[c] = columnChoice[c].getSelectedIndex(); - } - } - return data; - } - - /** Does the curve fit and adds the fit curve to the plot */ - private void addFitCurve() { - plot.restorePlotObjects(); - if (savedLimits != null) - plot.setLimits(savedLimits); - int dataIndex = fitDataChoice.getSelectedIndex(); - float[][] data = plot.getDataObjectArrays(dataIndex); - String fitName = fitFunctionChoice.getSelectedItem(); - int fitType = getIndex(CurveFitter.fitList, fitName); - CurveFitter cf = new CurveFitter(Tools.toDouble(data[0]), Tools.toDouble(data[1])); - cf.doFit(fitType); - String statusString = "Fit: "+Minimizer.STATUS_STRING[cf.getStatus()]; - if (cf.getStatus() == Minimizer.SUCCESS) - statusString += ", sum residuals ^2 = "+(float)(cf.getSumResidualsSqr()); - IJ.showStatus(statusString); - curveFitterStatusString = "Fit for "+plot.getTitle()+": "+fitDataChoice.getSelectedItem()+cf.getResultString(); //will be shown in Log when done - - double[] plotMinMax = plot.getLimits(); - double[] dataMinMax = Tools.getMinMax(data[0]); - double min = Math.min(plotMinMax[0], dataMinMax[0]); - double max = Math.max(plotMinMax[1], dataMinMax[1]); - double plotSpan = Math.abs(plotMinMax[1] - plotMinMax[0]); - double dataSpan = Math.abs(dataMinMax[1] - dataMinMax[0]); - double rangeFactor = Math.max(plotSpan/dataSpan, dataSpan/plotSpan); - if (rangeFactor > 20) rangeFactor = 20; - int nPoints = (int)(1000*rangeFactor); //finer data point spacing if we will want to zoom out or in - float[] xFit = new float[nPoints]; - float[] yFit = new float[nPoints]; - for (int i=0; i=3; - else - return columnHeadingStr.length() >= 1; - - } - - /** For "Add from Arrays", sets default columns from the colums titles */ - private void setDefaultColumns(String[] defaultHeadings) { - if (defaultHeadings == null) return; - for (int i=0; i 190 ? 255 : 255 - (int)(0.4*(255-v)); - } -} diff --git a/com.eco.bio7.image/src/ij/gui/PlotDialog.java b/com.eco.bio7.image/src/ij/gui/PlotDialog.java deleted file mode 100644 index bad6e4e9e..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotDialog.java +++ /dev/null @@ -1,606 +0,0 @@ -package ij.gui; - -import ij.*; -import ij.process.*; -import ij.plugin.frame.Recorder; -import java.awt.*; -import java.util.Vector; - -import org.eclipse.swt.widgets.Display; - -import com.eco.bio7.image.Util; - -/* - * This class contains dialogs for formatting of plots (range, axes, labels, legend, creating a high-resolution plot) - * Adding and formatting of contents (curves, symbols, ...) is in PlotContentsStyleDialog - */ - -public class PlotDialog implements DialogListener { - - /** - * Types of dialog. Note that 10-14 must be the same as the corresponding - * PlotWindow.rangeArrow numbers - */ - public static final int SET_RANGE = 0, AXIS_OPTIONS = 1, LEGEND = 2, HI_RESOLUTION = 3, TEMPLATE = 4, //5-9 spare - X_LEFT = 10, X_RIGHT = 11, Y_BOTTOM = 12, Y_TOP = 13, X_AXIS = 14, Y_AXIS = 15; - /** Dialog headings for the dialogTypes */ - private static final String[] HEADINGS = new String[] { "Plot Range", "Axis Options", "Add Legend", "High-Resolution Plot", "Use Template", null, null, null, null, null, // 5-9 spare - "X Left", "X Right", "Y Bottom", "Y Top", "X Axis", "Y Axis" }; - /** Positions and corresponding codes for legend position */ - 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 }; - /** - * Template "copy what" flag: dialog texts and corresponding bit masks, in the - * sequence as they appear in the dialog - */ - private static final String[] TEMPLATE_FLAG_NAMES = new String[] { "X Range", "Y Range", "Axis Style", "Labels", "Legend", "Contents Style", "Extra Objects (Curves...)", "Window Size" }; - private static final int[] TEMPLATE_FLAGS = new int[] { Plot.X_RANGE, Plot.Y_RANGE, Plot.COPY_AXIS_STYLE, Plot.COPY_LABELS, Plot.COPY_LEGEND, Plot.COPY_CONTENTS_STYLE, Plot.COPY_EXTRA_OBJECTS, - Plot.COPY_SIZE }; - - private Plot plot; - private int dialogType; - private boolean minMaxSaved; //whether plot min&max has been saved for "previous range" - private boolean dialogShowing; //when the dialog is showing, ignore the last call with event null - private Plot[] templatePlots; - - private Checkbox xLogCheckbox, yLogCheckbox; - - //saved dialog options: legend - private static int legendPosNumber = 0; - private static boolean bottomUp; - private static boolean transparentBackground; - //saved dialog options: Axis labels - private static String lastXLabel, lastYLabel; - private static float plotFontSize; - //saved dialog options: High-resolution plot - private static float hiResFactor = 4.0f; - private static boolean hiResAntiAliased = true; - //saved dialog options: Use Template - private static int templateID; - private static int lastTemplateFlags = Plot.COPY_AXIS_STYLE | Plot.COPY_CONTENTS_STYLE; - - /** Constructs a new PlotDialog for a given plot and sets the type of dialog */ - public PlotDialog(Plot plot, int dialogType) { - this.plot = plot; - this.dialogType = dialogType; - } - - /** - * Asks the user for axis scaling; then replot with new scale on the same - * ImageProcessor. The 'parent' frame may be null - */ - public void showDialog(Frame parent) { - if (dialogType == HI_RESOLUTION) { //'make high-resolution plot' dialog has no preview, handled separately - doHighResolutionDialog(parent); - return; - } - plot.savePlotPlotProperties(); - if (dialogType == TEMPLATE) - plot.savePlotObjects(); - - String dialogTitle = dialogType >= X_LEFT && dialogType <= Y_TOP ? "Set Axis Limit..." : (HEADINGS[dialogType] + "..."); - GenericDialog gd = parent == null ? new GenericDialog(dialogTitle) : new GenericDialog(dialogTitle, parent); - if (!setupDialog(gd)) - return; - gd.addDialogListener(this); - dialogItemChanged(gd, null); //preview immediately - dialogShowing = true; - gd.showDialog(); - if (gd.wasCanceled()) { - plot.restorePlotProperties(); - if (dialogType == TEMPLATE) - plot.restorePlotObjects(); - plot.update(); - } else { - if (IJ.recording()) - record(); - String xAxisLabel = plot.getLabel('x'); - if ((dialogType == AXIS_OPTIONS || dialogType == X_AXIS) && xAxisLabel != null && xAxisLabel.length() > 0) - lastXLabel = xAxisLabel; //remember for next time, in case we have none - String yAxisLabel = plot.getLabel('y'); - if ((dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) && yAxisLabel != null && yAxisLabel.length() > 0) - lastYLabel = yAxisLabel; - if (dialogType == SET_RANGE || dialogType == X_AXIS || dialogType == Y_AXIS) - plot.makeLimitsDefault(); - if (dialogType == TEMPLATE) - lastTemplateFlags = plot.templateFlags; - - } - plot.killPlotPropertiesSnapshot(); - if (dialogType == TEMPLATE) - plot.killPlotObjectsSnapshot(); - - ImagePlus imp = plot.getImagePlus(); - ImageWindow win = imp == null ? null : imp.getWindow(); - if (win instanceof PlotWindow) - ((PlotWindow) win).hideRangeArrows(); // arrows etc might be still visible, but the mouse maybe elsewhere - - if (!gd.wasCanceled() && !gd.wasOKed()) { // user has pressed "Set all limits" or "Set Axis Options" button - int newDialogType = (dialogType == SET_RANGE) ? AXIS_OPTIONS : SET_RANGE; - new PlotDialog(plot, newDialogType).showDialog(parent); - } - } - - /** - * Setting up the dialog fields and initial parameters. The input is read in the - * dialogItemChanged method, which must have exactly the same structure of 'if' - * blocks and matching 'get' methods for each input field. - * - * @return false on error - */ - private boolean setupDialog(GenericDialog gd) { - double[] currentMinMax = plot.getLimits(); - 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, 0); - if (dialogType == SET_RANGE || dialogType == X_AXIS) { - gd.addNumericField("X_From", currentMinMax[0], xDigits, 6, "*"); - gd.addToSameRow(); - gd.addNumericField("To", currentMinMax[1], xDigits, 6, "*"); - gd.setInsets(0, 20, 0); //top, left, bottom - 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))); - xLogCheckbox = lastCheckboxAdded(gd); - enableDisableLogCheckbox(xLogCheckbox, currentMinMax[0], currentMinMax[1]); - } - int yDigits = plot.logYAxis ? -2 : Plot.getDigits(currentMinMax[2], currentMinMax[3], 0.005 * Math.abs(currentMinMax[3] - currentMinMax[2]), 6, 0); - if (dialogType == SET_RANGE || dialogType == Y_AXIS) { - gd.setInsets(20, 0, 3); //top, left, bottom - gd.addNumericField("Y_From", currentMinMax[2], yDigits, 6, "*"); - gd.addToSameRow(); - gd.addNumericField("To", currentMinMax[3], yDigits, 6, "*"); - 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))); - yLogCheckbox = lastCheckboxAdded(gd); - enableDisableLogCheckbox(yLogCheckbox, currentMinMax[2], currentMinMax[3]); - } - if (dialogType >= X_LEFT && dialogType <= Y_TOP) { - int digits = dialogType < Y_BOTTOM ? xDigits : yDigits; - gd.addNumericField(HEADINGS[dialogType], currentMinMax[dialogType - X_LEFT], digits, 6, "*"); - } - - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS || dialogType == Y_AXIS) { - int flags = plot.getFlags(); - 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 }; - int rows = xFlags.length; - int columns = dialogType == AXIS_OPTIONS ? 2 : 1; - String[] allLabels = new String[rows * columns]; - boolean[] defaultValues = new boolean[rows * columns]; - String[] headings = dialogType == AXIS_OPTIONS ? new String[] { "X Axis", "Y Axis" } : null; - int i = 0; - for (int l = 0; l < xFlags.length; l++) { - String label = labels[l]; - boolean xFlag = getFlag(flags, xFlags[l]); - boolean yFlag = getFlag(flags, xFlags[l] << 1); //y flags are shifted up one bit - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) { - allLabels[i] = labels[l]; - defaultValues[i++] = xFlag; - } - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) { - allLabels[i] = labels[l]; - defaultValues[i++] = yFlag; - } - } - if (dialogType == X_AXIS || dialogType == Y_AXIS) - gd.setInsets(15, 20, 0); //top, left, bottom - gd.addCheckboxGroup(rows, columns, allLabels, defaultValues, headings); - if (dialogType == AXIS_OPTIONS) - gd.setInsets(15, 0, 5); //top, left, bottom - - String plotXLabel = plot.getLabel('x'); - String plotYLabel = plot.getLabel('y'); - if ((plotXLabel == null || plotXLabel.equals("Distance (pixels)") || plotXLabel.equals("Distance ( )")) && lastXLabel != null) - plotXLabel = lastXLabel; // suggest last dialog entry if default profile label - if ((plotYLabel == null || plotYLabel.equals("Gray Value")) && lastYLabel != null) - plotYLabel = lastYLabel; - int nChars = 20; - if ((plotXLabel != null && plotXLabel.startsWith("{")) || (plotYLabel != null && plotYLabel.startsWith("{"))) { - nChars = Math.max(nChars, plotXLabel.length()); - nChars = Math.max(nChars, plotYLabel.length()); - } - if (nChars > 80) - nChars = 80; - //plotXLabel = plotXLabel.replace("\n", "|"); //multiline label currently no supported by Plot class - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) - gd.addStringField("X Axis Label", plotXLabel, nChars); - //plotYLabel = plotYLabel.replace("\n", "|"); - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) - gd.addStringField("Y Axis Label", plotYLabel, nChars); - } - if (dialogType == SET_RANGE || dialogType == X_AXIS || dialogType == Y_AXIS) { - Font smallFont = IJ.font10; - gd.setInsets(10, 0, 0); //top, left, bottom - gd.addMessage("* Leave empty for automatic range", smallFont, Color.gray); - gd.setInsets(0, 0, 0); - gd.addMessage("** Requires limits > 0 and max/min > 3", smallFont, Color.gray); - if (dialogType == X_AXIS || dialogType == Y_AXIS) { - gd.setInsets(0, 0, 0); - gd.addMessage(" Label supports !!sub-!! and ^^superscript^^", smallFont, Color.gray); - } - } - - if (dialogType == AXIS_OPTIONS) { - Font plotFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - Font labelFont = plot.getFont('x'); - if (labelFont == null) - labelFont = plotFont; - Font numberFont = plot.getFont('f'); - if (numberFont == null) - numberFont = plotFont; - gd.addNumericField("Number Font Size", numberFont.getSize2D(), 1); - gd.addNumericField("Label Font Size", labelFont.getSize2D(), 1); - //gd.setInsets(0, 20, 0); // no extra space - gd.addToSameRow(); - gd.addCheckbox("Bold", labelFont.isBold()); - } - if (dialogType == LEGEND) { - String labels = plot.getDataLabels(); - int nLines = labels.split("\n", -1).length; - Font legendFont = plot.getFont('l'); - if (legendFont == null) - legendFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - int lFlags = plot.getObjectFlags('l'); - if (lFlags != -1) { //if we have a legend already - for (int i = 0; i < LEGEND_POSITION_N.length; i++) //determine the position option from the flags - if ((lFlags & Plot.LEGEND_POSITION_MASK) == LEGEND_POSITION_N[i]) { - legendPosNumber = i; - break; - } - transparentBackground = getFlag(lFlags, Plot.LEGEND_TRANSPARENT); - bottomUp = getFlag(lFlags, Plot.LEGEND_BOTTOM_UP); - } - gd.addMessage("Enter Labels for the datasets, one per line.\n"); - - Font smallFont = IJ.font10; - gd.setInsets(0, 20, 0); //top, left, bottom - String msg = "Prepend index plus dual underscore (e.g. '1__MyLabel' )\nto control legend order and to hide non-indexed labels"; - gd.addMessage(msg, smallFont, Color.darkGray); - gd.setInsets(0, 0, 0); - - gd.addTextAreas(labels, null, Math.min(nLines + 1, 20), 40); - gd.addChoice("Legend position", LEGEND_POSITIONS, LEGEND_POSITIONS[legendPosNumber]); - gd.addNumericField("Font Size", legendFont.getSize2D(), 1); - - gd.addCheckbox("Transparent background", transparentBackground); - gd.addCheckbox("Bottom-to-top", bottomUp); - } - if (dialogType == TEMPLATE) { - int[] idList = WindowManager.getIDList(); //create list of plots to use as template - int[] plotIdList = new int[idList.length]; - templatePlots = new Plot[idList.length]; - int nPlots = 0; - for (int id : idList) { - ImagePlus imp = WindowManager.getImage(id); - if (imp == null) - continue; - Plot impPlot = (Plot) (imp.getProperty(Plot.PROPERTY_KEY)); - if (impPlot != null && impPlot != this.plot) { - templatePlots[nPlots] = impPlot; - plotIdList[nPlots++] = id; - } - } - if (nPlots == 0) { - IJ.error("No plot to use as template"); - return false; - } - String[] plotImpTitles = new String[nPlots]; - int defaultTemplateIndex = 0; - for (int i = 0; i < nPlots; i++) { - ImagePlus imp = WindowManager.getImage(plotIdList[i]); - plotImpTitles[i] = imp == null ? "" : imp.getTitle(); - if (imp.getID() == templateID) - defaultTemplateIndex = i; - } - gd.addChoice("Template Plot", plotImpTitles, plotImpTitles[defaultTemplateIndex]); - gd.setInsets(10, 0, 0); //top, left, bottom - gd.addMessage("Copy From Template:"); - gd.setInsets(5, 20, 0); //top, left, bottom - if (lastTemplateFlags == 0) - lastTemplateFlags = Plot.COPY_AXIS_STYLE | Plot.COPY_CONTENTS_STYLE; - for (int i = 0; i < TEMPLATE_FLAGS.length; i++) { - boolean flag = getFlag(lastTemplateFlags, TEMPLATE_FLAGS[i]); - gd.addCheckbox(TEMPLATE_FLAG_NAMES[i], flag); - } - } - // Add a button to access another dialog that might be also desired - if (dialogType >= X_LEFT && dialogType <= Y_TOP) - gd.enableYesNoCancel("OK", "Set All Limits..."); - else if (dialogType == AXIS_OPTIONS) - gd.enableYesNoCancel("OK", "Set Range..."); - else if (dialogType == SET_RANGE) - gd.enableYesNoCancel("OK", "Set Axis Options..."); - return true; - } //setupDialog - - /** - * This method is called when the user changes something in the dialog. Note - * that the 'if's for reading the fields must be exactly the same as those for - * setting up the fields in 'setupDialog' (fields must be also read in the same - * sequence). - */ - public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { - if (dialogShowing && e==null) - return true; //gets called with e=null upon OK; ignore this - boolean livePlot = plot.plotMaker != null; - - if (dialogType == SET_RANGE || dialogType == X_AXIS) { - double[] currentMinMax = plot.getLimits(); - double linXMin = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linXMin = Double.NaN; - double linXMax = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linXMax = Double.NaN; - if (linXMin == linXMax) - return false; - if (!minMaxSaved) { - plot.saveMinMax(); //save for 'Previous Range' in plot menu - minMaxSaved = true; - } - if (livePlot) - plot.templateFlags = setFlag(plot.templateFlags, Plot.X_RANGE, gd.getNextBoolean()); - boolean xLog = gd.getNextBoolean(); - plot.setAxisXLog(xLog); - plot.setLimitsNoUpdate(linXMin, linXMax, currentMinMax[2], currentMinMax[3]); - currentMinMax = plot.getLimits(); - enableDisableLogCheckbox(xLogCheckbox, currentMinMax[0], currentMinMax[1]); - } - if (dialogType == SET_RANGE || dialogType == Y_AXIS) { - double[] currentMinMax = plot.getLimits(); - double linYMin = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linYMin = Double.NaN; - double linYMax = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linYMax = Double.NaN; - if (linYMin == linYMax) - return false; - if (!minMaxSaved) { - plot.saveMinMax(); //save for 'Previous Range' in plot menu - minMaxSaved = true; - } - - if (livePlot) - plot.templateFlags = setFlag(plot.templateFlags, Plot.Y_RANGE, gd.getNextBoolean()); - boolean yLog = gd.getNextBoolean(); - plot.setAxisYLog(yLog); - plot.setLimitsNoUpdate(currentMinMax[0], currentMinMax[1], linYMin, linYMax); - currentMinMax = plot.getLimits(); - enableDisableLogCheckbox(yLogCheckbox, currentMinMax[2], currentMinMax[3]); - } - if (dialogType >= X_LEFT && dialogType <= Y_TOP) { - double newLimit = gd.getNextNumber(); - double[] minMaxCopy = (double[]) (plot.getLimits().clone()); - minMaxCopy[dialogType - X_LEFT] = newLimit; - plot.setLimitsNoUpdate(minMaxCopy[0], minMaxCopy[1], minMaxCopy[2], minMaxCopy[3]); - } - - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS || dialogType == Y_AXIS) { - final int[] xFlags = new int[] { Plot.X_GRID, Plot.X_TICKS, Plot.X_MINOR_TICKS, Plot.X_LOG_TICKS, Plot.X_NUMBERS }; - int rows = xFlags.length; - int columns = dialogType == AXIS_OPTIONS ? 2 : 1; - int flags = 0; - if (dialogType == X_AXIS) - flags = plot.getFlags() & 0xaaaaaaaa; //keep y flags, i.e., odd bits - if (dialogType == Y_AXIS) - flags = plot.getFlags() & 0x55555555; //keep x flags, i.e., even bits - for (int l = 0; l < xFlags.length; l++) { - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) - if (gd.getNextBoolean()) - flags |= xFlags[l]; - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) - if (gd.getNextBoolean()) - flags |= xFlags[l] << 1; //y flags are shifted up one bit; - } - plot.setFormatFlags(flags); - - String xAxisLabel = plot.getLabel('x'); - String yAxisLabel = plot.getLabel('y'); - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) { - xAxisLabel = gd.getNextString(); - //xAxisLabel = xAxisLabel.replace("|", "\n"); //multiline label currently not supported by Plot class - } - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) { - yAxisLabel = gd.getNextString(); - //yAxisLabel = yAxisLabel.replace("|", "\n"); - } - plot.setXYLabels(xAxisLabel, yAxisLabel); - } - if (dialogType == AXIS_OPTIONS) { - Font plotFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - Font labelFont = plot.getFont('x'); - if (labelFont == null) - labelFont = plotFont; - Font numberFont = plot.getFont('f'); - if (numberFont == null) - numberFont = plotFont; - - float numberFontSize = (float) gd.getNextNumber(); - if (gd.invalidNumber()) - numberFontSize = numberFont.getSize2D(); - if (numberFontSize < 9) - numberFontSize = 9f; - if (numberFontSize > 24) - numberFontSize = 24f; - float labelFontSize = (float) gd.getNextNumber(); - if (gd.invalidNumber()) - labelFontSize = labelFont.getSize2D(); - boolean axisLabelBold = gd.getNextBoolean(); - plot.setFont('f', numberFont.deriveFont(numberFont.getStyle(), numberFontSize)); - plot.setAxisLabelFont(axisLabelBold ? Font.BOLD : Font.PLAIN, labelFontSize); - Font smallFont = new Font("SansSerif", Font.PLAIN, (int) (10 * Prefs.getGuiScale())); - gd.addMessage("Labels support !!sub-!! and ^^superscript^^", smallFont, Color.gray); - } - if (dialogType == LEGEND) { - Font legendFont = plot.getFont('l'); - if (legendFont == null) - legendFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - - String labels = gd.getNextText(); - legendPosNumber = gd.getNextChoiceIndex(); - int lFlags = LEGEND_POSITION_N[legendPosNumber]; - float legendFontSize = (float) gd.getNextNumber(); - transparentBackground = gd.getNextBoolean(); - bottomUp = gd.getNextBoolean(); - if (bottomUp) - lFlags |= Plot.LEGEND_BOTTOM_UP; - if (transparentBackground) - lFlags |= Plot.LEGEND_TRANSPARENT; - plot.setColor(Color.black); - plot.setLineWidth(1); - plot.setLegend(labels, lFlags); - plot.setFont('l', legendFont.deriveFont(legendFont.getStyle(), legendFontSize)); - } - if (dialogType == TEMPLATE) { - Plot templatePlot = templatePlots[gd.getNextChoiceIndex()]; - ImagePlus imp = templatePlot.getImagePlus(); - if (imp != null) - templateID = imp.getID(); //remember for next time - int templateFlags = 0; - for (int i = 0; i < TEMPLATE_FLAGS.length; i++) - if (gd.getNextBoolean()) - templateFlags |= TEMPLATE_FLAGS[i]; - plot.restorePlotProperties(); - plot.restorePlotObjects(); - plot.useTemplate(templatePlot, templateFlags); - } - - plot.updateImage(); - return true; - } //dialogItemChanged - - /** Macro recording */ - private void record() { - if (Recorder.scriptMode()) - Recorder.recordCall("//plot = IJ.getImage().getProperty(Plot.PROPERTY_KEY);"); - String plotDot = Recorder.scriptMode() ? "plot." : "Plot."; - - if (dialogType == SET_RANGE || dialogType == X_AXIS) - Recorder.recordString(plotDot + (Recorder.scriptMode() ? "setAxisXLog(" : "setLogScaleX(") + plot.hasFlag(Plot.X_LOG_NUMBERS) + ");\n"); - if (dialogType == SET_RANGE || dialogType == Y_AXIS) - Recorder.recordString(plotDot + (Recorder.scriptMode() ? "setAxisYLog(" : "setLogScaleY(") + plot.hasFlag(Plot.Y_LOG_NUMBERS) + ");\n"); - if (dialogType == SET_RANGE || dialogType == X_AXIS || dialogType == Y_AXIS) { - double[] currentMinMax = plot.getLimits(); - int xDigits = plot.logXAxis ? -2 : Plot.getDigits(currentMinMax[0], currentMinMax[1], 0.005 * Math.abs(currentMinMax[1] - currentMinMax[0]), 6, 0); - int yDigits = plot.logYAxis ? -2 : Plot.getDigits(currentMinMax[2], currentMinMax[3], 0.005 * Math.abs(currentMinMax[3] - currentMinMax[2]), 6, 0); - Recorder.recordString(plotDot + "setLimits(" + IJ.d2s(currentMinMax[0], xDigits) + "," + IJ.d2s(currentMinMax[1], xDigits) + "," + IJ.d2s(currentMinMax[2], yDigits) + "," - + IJ.d2s(currentMinMax[3], yDigits) + ");\n"); - } - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS || dialogType == Y_AXIS) { - int flags = plot.getFlags(); - String xAxisLabel = Recorder.fixString(plot.getLabel('x')); - String yAxisLabel = Recorder.fixString(plot.getLabel('y')); - Font labelFont = plot.getFont('x'); - Font numberFont = plot.getFont('f'); - if (labelFont != null) { - if (Recorder.scriptMode()) - Recorder.recordString("plot.setAxisLabelFont(" + (labelFont.isBold() ? "Font.BOLD," : "Font.PLAIN,") + IJ.d2s(labelFont.getSize2D(), 1) + ");\n"); - else - Recorder.recordString("Plot.setAxisLabelSize(" + IJ.d2s(labelFont.getSize2D(), 1) + ", \"" + (labelFont.isBold() ? "bold" : "plain") + "\");\n"); - } - if (numberFont != null) - Recorder.recordString(plotDot + (Recorder.scriptMode() ? "setFont(-1, " : "setFontSize(") + IJ.d2s(numberFont.getSize2D(), 1) + ");\n"); - Recorder.recordString(plotDot + "setXYLabels(\"" + xAxisLabel + "\", \"" + yAxisLabel + "\");\n"); - Recorder.recordString(plotDot + "setFormatFlags(" + (Recorder.scriptMode() ? "0x" + Integer.toHexString(flags) : '\"' + Integer.toString(flags, 2) + '\"') + ");\n"); - } - if (dialogType == LEGEND) { - String labels = Recorder.fixString(plot.getDataLabels()); - int lFlags = plot.getObjectFlags('l'); - if (Recorder.scriptMode()) { - Recorder.recordCall("plot.setColor(Color.black);"); - Recorder.recordCall("plot.setLineWidth(1);"); - Recorder.recordCall("plot.addLegend(\"" + labels + "\", 0x" + Integer.toHexString(lFlags) + ");"); - } else { - String options = LEGEND_POSITIONS[legendPosNumber]; - if (getFlag(lFlags, Plot.LEGEND_BOTTOM_UP)) - options += " Bottom-To-Top"; - if (getFlag(lFlags, Plot.LEGEND_TRANSPARENT)) - options += " Transparent"; - Recorder.recordString("Plot.addLegend(\"" + labels + "\", \"" + options + "\");\n"); - } - } - - if (Recorder.scriptMode()) - Recorder.recordCall("plot.update();"); - } - - /** The dialog for "Make High Resolution Plot"; it has no preview */ - private void doHighResolutionDialog(Frame parent) { - GenericDialog gd = parent == null ? new GenericDialog(HEADINGS[dialogType]) : new GenericDialog(HEADINGS[dialogType], parent); - String title = plot.getTitle(); - if (title.toLowerCase().endsWith(".tif") || title.toLowerCase().endsWith(".zip")) - title = title.substring(0, title.length()-4); - title += "_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) //more range checking is done in Plot.setScale - hiResFactor = (float) scale; - hiResAntiAliased = !gd.getNextBoolean(); - /*final ImagePlus hiresImp = plot.makeHighResolution(title, hiResFactor, hiResAntiAliased, showIt=true); - *//** - * The following command is needed to have the high-resolution plot as front - * window. Otherwise, as the dialog is owned by the original PlotWindow, the - * WindowManager will see the original plot as active, but the user interface - * will show the high-res plot as foreground window - *//* - EventQueue.invokeLater(new Runnable() {public void run() {IJ.selectWindow(hiresImp.getID());}});*/ - /* Changed for Bio7. Deadlock with activate tab function! */ - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - String title = plot.getTitle() + "_HiRes"; - - final ImagePlus hiresImp = plot.makeHighResolution(title, hiResFactor, hiResAntiAliased, /* showIt= */true); - IJ.selectWindow(hiresImp.getID()); - } - }); - - if (IJ.recording()) { - if (Recorder.scriptMode()) { - Recorder.recordCall("plot.makeHighResolution(\"" + title + "\"," + hiResFactor + "," + hiResAntiAliased + ",true);"); - } else { - String options = !hiResAntiAliased ? "disable" : ""; - if (options.length() > 0) - options = ",\"" + options + "\""; - Recorder.recordString("Plot.makeHighResolution(\"" + title + "\"," + hiResFactor + options + ");\n"); - } - } - } - - /** - * Disables switching on a checkbox for log range if the axis limits do not - * allow it. The checkbox can be always switched off. - */ - void enableDisableLogCheckbox(Checkbox checkbox, double limit1, double limit2) { - boolean logPossible = limit1 > 0 && limit2 > 0 && (limit1 > 3 * limit2 || limit2 > 3 * limit1); - checkbox.setEnabled(logPossible); - } - - 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; - } - - Checkbox lastCheckboxAdded(GenericDialog gd) { - Vector checkboxes = gd.getCheckboxes(); - return (Checkbox) (checkboxes.get(checkboxes.size() - 1)); - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/PlotMaker.java b/com.eco.bio7.image/src/ij/gui/PlotMaker.java deleted file mode 100644 index ddaef8a3b..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotMaker.java +++ /dev/null @@ -1,15 +0,0 @@ -package ij.gui; -import ij.ImagePlus; - -/** Plugins that generate "Live" profile plots (Profiler and ZAxisProfiler) - displayed in PlotWindows implement this interface. */ -public interface PlotMaker { - - /** Returns a profile plot. */ - public Plot getPlot(); - - /** Returns the ImagePlus used to generate the profile plots. */ - public ImagePlus getSourceImage(); - -} - diff --git a/com.eco.bio7.image/src/ij/gui/PlotVirtualStack.java b/com.eco.bio7.image/src/ij/gui/PlotVirtualStack.java deleted file mode 100644 index 7bac94ed2..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotVirtualStack.java +++ /dev/null @@ -1,84 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import java.util.*; -import java.io.*; - -/** This is a virtual stack of frozen plots. */ -public class PlotVirtualStack extends VirtualStack { - private Vector plots = new Vector(50); - private int bitDepth = 8; - - public PlotVirtualStack(int width, int height) { - super(width, height); - } - - /** Adds a plot to the end of the stack. */ - public void addPlot(Plot plot) { - plots.add(plot.toByteArray()); - if (plot.isColored()) - bitDepth = 24; - } - - /** Returns the pixel array for the specified slice, where {@literal 1<=n<=nslices}. */ - public Object getPixels(int n) { - ImageProcessor ip = getProcessor(n); - if (ip!=null) - return ip.getPixels(); - else - return null; - } - - /** Returns an ImageProcessor for the specified slice, - where {@literal 1<=n<=nslices}. Returns null if the stack is empty. */ - public ImageProcessor getProcessor(int n) { - byte[] bytes = (byte[])plots.get(n-1); - if (bytes!=null) { - try { - Plot plot = new Plot(null, new ByteArrayInputStream(bytes)); - ImageProcessor ip = plot.getProcessor(); - if (bitDepth==24) - ip = ip.convertToRGB(); - else if (bitDepth==8) - ip = ip.convertToByte(false); - ip.setSliceNumber(n); - return ip; - } catch (Exception e) { - IJ.handleException(e); - } - } - return null; - } - - /** Returns the number of slices in this stack. */ - public int getSize() { - return plots.size(); - } - - /** Returns either 24 (RGB) or 8 (grayscale). */ - public int getBitDepth() { - return bitDepth; - } - - public void setBitDepth(int bitDepth) { - this.bitDepth = bitDepth; - } - - public String getSliceLabel(int n) { - return null; - } - - public void setPixels(Object pixels, int n) { - } - - /** Deletes the specified slice, where {@literal 1<=n<=nslices}. */ - public void deleteSlice(int n) { - if (n<1 || n>plots.size()) - throw new IllegalArgumentException("Argument out of range: "+n); - if (plots.size()<1) - return; - plots.remove(n-1); - } - - -} // PlotVirtualStack \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/PlotWindow.java b/com.eco.bio7.image/src/ij/gui/PlotWindow.java deleted file mode 100644 index 7236b2045..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotWindow.java +++ /dev/null @@ -1,1156 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import java.awt.datatransfer.*; -import java.util.*; - -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import ij.*; -import ij.process.*; -import ij.util.*; -import ij.text.TextWindow; -import ij.plugin.filter.Analyzer; -import ij.plugin.filter.PlugInFilterRunner; -import ij.measure.*; -import ij.io.SaveDialog; -import org.eclipse.swt.custom.CTabFolder; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.PlatformUI; - -import com.eco.bio7.ImageJPluginActions.ImageJContextMenuAction; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.CustomDetachedImageJView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.Util; - -/** - * This class implements the Analyze/Plot Profile command. - * - * @author Michael Schmid - * @author Wayne Rasband - */ -public class PlotWindow extends ImageWindow - implements ActionListener, ItemListener, ClipboardOwner, ImageListener, RoiListener, Runnable { - - private static final int WIDTH = 600; - private static final int HEIGHT = 340; - private static final int FONT_SIZE = 14; - private static final String PREFS_WIDTH = "pp.width"; - private static final String PREFS_HEIGHT = "pp.height"; - private static final String PREFS_FONT_SIZE = "pp.fontsize"; - - /** @deprecated */ - public static final int CIRCLE = Plot.CIRCLE; - /** @deprecated */ - public static final int X = Plot.X; - /** @deprecated */ - public static final int BOX = Plot.BOX; - /** @deprecated */ - public static final int TRIANGLE = Plot.TRIANGLE; - /** @deprecated */ - public static final int CROSS = Plot.CROSS; - /** @deprecated */ - public static final int LINE = Plot.LINE; - /** Write first X column when listing or saving. */ - public static boolean saveXValues = true; - /** - * Automatically close window after saving values. To set, use - * Edit/Options/Plots. - */ - public static boolean autoClose; - /** - * Display the XY coordinates in a separate window. To set, use - * Edit/Options/Plots. - */ - public static boolean listValues; - /** - * Interpolate line profiles. To set, use Edit/Options/Plots or - * setOption("InterpolateLines",boolean). - */ - public static boolean interpolate = true; - // default values for new installations; values will be then saved in prefs - private static int defaultFontSize = Prefs.getInt(PREFS_FONT_SIZE, FONT_SIZE); - /** The width of the plot (without frame) in pixels. */ - public static int plotWidth = WIDTH; - /** The height of the plot in pixels. */ - public static int plotHeight = HEIGHT; - /** - * The plot text size, can be overridden by Plot.setFont, Plot.setFontSize, - * Plot.setXLabelFont etc. - */ - public static int fontSize = defaultFontSize; - /** - * Have axes with no grid lines. If both noGridLines and noTicks are true, only - * min&max value of the axes are given - */ - public static boolean noGridLines; - /** - * Have axes with no ticks. If both noGridLines and noTicks are true, only - * min&max value of the axes are given - */ - public static boolean noTicks; - private static final String OPTIONS = "pp.options"; - private static final int SAVE_X_VALUES = 1; - private static final int AUTO_CLOSE = 2; - private static final int LIST_VALUES = 4; - private static final int INTERPOLATE = 8; - private static final int NO_GRID_LINES = 16; - private static final int NO_TICKS = 32; - private static String moreButtonLabel = "More " + '\u00bb'; - private static String dataButtonLabel = "Data " + '\u00bb'; - - boolean wasActivated; // true after window has been activated once, needed by PlotCanvas - - JButton list; - private JButton data, more, live; - private PopupMenu dataPopupMenu, morePopupMenu; - private static final int NUM_MENU_ITEMS = 20; // how many menu items we have in total - private MenuItem[] menuItems = new MenuItem[NUM_MENU_ITEMS]; - private JLabel statusLabel; - private String userStatusText; - private static String defaultDirectory = null; - private static int options; - private int defaultDigits = -1; - private int markSize = 5; - private static Plot staticPlot; - private Plot plot; - - private PlotMaker plotMaker; - private ImagePlus srcImp; // the source image for live plotting - private Thread bgThread; // thread for plotting (in the background) - private boolean doUpdate; // tells the background thread to update - - private Roi[] rangeArrowRois; // the overlays (arrows etc) for changing the range. Note: #10-15 must - // correspond to PlotDialog.dialogType! - private boolean rangeArrowsVisible; - private int activeRangeArrow = -1; - private static Color inactiveRangeArrowColor = Color.GRAY; - private static Color inactiveRangeRectColor = new Color(0x20404040, true); // transparent gray - private static Color activeRangeArrowColor = Color.RED; - private static Color activeRangeRectColor = new Color(0x18ff0000, true); // transparent red - protected Vector ve; - - // static initializer - static { - options = Prefs.getInt(OPTIONS, SAVE_X_VALUES); - autoClose = (options & AUTO_CLOSE) != 0; - plotWidth = Prefs.getInt(PREFS_WIDTH, WIDTH); - plotHeight = Prefs.getInt(PREFS_HEIGHT, HEIGHT); - Dimension screen = IJ.getScreenSize(); - if (plotWidth > screen.width && plotHeight > screen.height) { - plotWidth = WIDTH; - plotHeight = HEIGHT; - } - } - - /** - * @deprecated replaced by the Plot class. - */ - public PlotWindow(String title, String xLabel, String yLabel, float[] xValues, float[] yValues) { - super(createImage(title, xLabel, yLabel, xValues, yValues)); - plot = staticPlot; - // Changed for Bio7! - ((PlotCanvas) getCanvas()).setPlot(plot); - } - - /** - * @deprecated replaced by the Plot class. - */ - public PlotWindow(String title, String xLabel, String yLabel, double[] xValues, double[] yValues) { - this(title, xLabel, yLabel, Tools.toFloat(xValues), Tools.toFloat(yValues)); - } - - /** - * Creates a PlotWindow from a given ImagePlus with a Plot object. (called when - * reading an ImagePlus with an associated plot from a file) - */ - public PlotWindow(ImagePlus imp, Plot plot) { - super(imp); - // Changed for Bio7! - ((PlotCanvas) getCanvas()).setPlot(plot); - this.plot = plot; - draw(); - } - - /** Creates a PlotWindow from a Plot object. */ - PlotWindow(Plot plot) { - super(plot.getImagePlus()); - // Changed for Bio7! - ((PlotCanvas) getCanvas()).setPlot(plot); - this.plot = plot; - draw(); - } - - /** - * Called by the constructor to generate the image the plot will be drawn on. - * This is a static method because constructors cannot call instance methods. - */ - static ImagePlus createImage(String title, String xLabel, String yLabel, float[] xValues, float[] yValues) { - staticPlot = new Plot(title, xLabel, yLabel, xValues, yValues); - return new ImagePlus(title, staticPlot.getBlankProcessor()); - } - - /** - * Sets the x-axis and y-axis range. - * - * @deprecated use the corresponding method of the Plot class - */ - public void setLimits(double xMin, double xMax, double yMin, double yMax) { - plot.setLimits(xMin, xMax, yMin, yMax); - } - - /** - * Adds a set of points to the plot or adds a curve if shape is set to LINE. - * Note that there are more options available by using the methods of the Plot - * class instead. - * - * @param x the x-coodinates - * @param y the y-coodinates - * @param shape Plot.CIRCLE, X, BOX, TRIANGLE, CROSS, LINE etc. - * @deprecated use the corresponding method of the Plot class - */ - public void addPoints(float[] x, float[] y, int shape) { - plot.addPoints(x, y, shape); - } - - /** - * Adds a set of points to the plot using double arrays. Must be called before - * the plot is displayed. Note that there are more options available by using - * the methods of the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void addPoints(double[] x, double[] y, int shape) { - addPoints(Tools.toFloat(x), Tools.toFloat(y), shape); - } - - /** - * Adds vertical error bars to the plot. Must be called before the plot is - * displayed. Note that there are more options available by using the methods of - * the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void addErrorBars(float[] errorBars) { - plot.addErrorBars(errorBars); - } - - /** - * Draws a label. Note that there are more options available by using the - * methods of the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void addLabel(double x, double y, String label) { - plot.addLabel(x, y, label); - } - - /** - * Changes the drawing color. The frame and labels are always drawn in black. - * Must be called before the plot is displayed. Note that there are more options - * available by using the methods of the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void setColor(Color c) { - plot.setColor(c); - } - - /** - * Changes the line width. Must be called before the plot is displayed. Note - * that there are more options available by using the methods of the Plot class - * instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void setLineWidth(int lineWidth) { - plot.setLineWidth(lineWidth); - } - - /** - * Changes the font. Must be called before the plot is displayed. Note that - * there are more options available by using the methods of the Plot class - * instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void changeFont(Font font) { - plot.changeFont(font); - } - - /** Displays the plot. */ - public void draw() { - JPanel bottomPanel = new JPanel(); - Color primarySWTToAwtColor = ImageJ.getPrimarySWTToAwtColor(); - /* - * Changed for Bio7! AWT must be colored per component. All JPanels will get the - * SWT background from the definition of the CanvasView (UIManager)! - */ - Color swtBackgroundToAWT = Util.getSWTBackgroundToAWT(); - Color swtForegroundToAWT = Util.getSWTForegroundToAWT(); - //if (Util.getOS().equals("Linux")) { - bottomPanel.setBackground(swtBackgroundToAWT); - bottomPanel.setForeground(swtForegroundToAWT); - //} - //bottomPanel.setBackground(primarySWTToAwtColor); - int hgap = IJ.isMacOSX() ? 1 : 5; - - list = new JButton(" List "); - list.setBackground(swtBackgroundToAWT); - list.setForeground(swtForegroundToAWT); - list.setBorderPainted(false); - list.addActionListener(this); - bottomPanel.add(list); - bottomPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, hgap, 0)); - data = new JButton(dataButtonLabel); - data.setBackground(swtBackgroundToAWT); - data.setForeground(swtForegroundToAWT); - data.setBorderPainted(false); - data.addActionListener(this); - bottomPanel.add(data); - more = new JButton(moreButtonLabel); - more.setBackground(swtBackgroundToAWT); - more.setForeground(swtForegroundToAWT); - more.setBorderPainted(false); - more.addActionListener(this); - bottomPanel.add(more); - if (plot != null && plot.getPlotMaker() != null) { - live = new JButton("Live"); - live.setBorderPainted(false); - live.setBackground(swtBackgroundToAWT); - live.setForeground(swtForegroundToAWT); - live.addActionListener(this); - bottomPanel.add(live); - } - statusLabel = new JLabel(); - statusLabel.setFont(new Font("Monospaced", Font.PLAIN, 12)); - statusLabel.setBackground(new Color(220, 220, 220)); - // bottomPanel.add(statusLabel); - - // Changed for Bio7! - //statusLabel.setBackground(primarySWTToAwtColor); - /* - * Changed for Bio7! AWT must be colored per component. All JPanels will get the - * SWT background from the definition of the CanvasView (UIManager)! - */ - //if (Util.getOS().equals("Linux")) { - statusLabel.setBackground(swtBackgroundToAWT); - statusLabel.setForeground(swtForegroundToAWT); - //} - - bottomPanel.add(statusLabel); - add(bottomPanel); - data.add(getDataPopupMenu()); - more.add(getMorePopupMenu()); - plot.draw(); - LayoutManager lm = getLayout(); - if (lm instanceof ImageLayout) - ((ImageLayout) lm).ignoreNonImageWidths(true); // don't expand size to make the panel fit - GUI.scale(bottomPanel); - maximizeCoordinatesLabelWidth(); - /* Changed for Bio7. Pack causes deadlock on MacOSX with detached view! */ - // pack(); - /* Changed for Bio7. Introduced a pause for the plot display!*/ - IJ.wait(200); - ImageProcessor ip = plot.getProcessor(); - boolean ipIsColor = ip instanceof ColorProcessor; - boolean impIsColor = imp.getProcessor() instanceof ColorProcessor; - if (ipIsColor != impIsColor) - imp.setProcessor(null, ip); - else - imp.updateAndDraw(); - if (listValues) - showList(/*useLabels=*/false); - else - ic.requestFocus(); // have focus on the canvas, not the button, so that pressing the space bar - // allows panning - if (Prefs.autoLivePlots && bgThread==null) - enableLivePlot(); - /* - * Changed for Bio7! - */ - - Display display = Util.getDisplay(); - display.syncExec(new Runnable() { - public void run() { - CanvasView.parent2.layout(); - CTabFolder ctab = CanvasView.getCanvas_view().tabFolder; - ve = (Vector>) ctab.getSelection().getData(); - JPanel current = (JPanel) ve.get(2); - current.add(bottomPanel); - } - }); - CanvasView.getCanvas_view().getCurrent().validate(); - } - - /** - * Sets the Plot object shown in this PlotWindow. Does not update the window. - */ - public void setPlot(Plot plot) { - this.plot = plot; - ((PlotCanvas) getCanvas()).setPlot(plot); - } - - /** Releases the resources used by this PlotWindow */ - public void dispose() { - if (plot != null) - plot.dispose(); - disableLivePlot(); - plot = null; - plotMaker = null; - srcImp = null; - super.dispose(); - } - - /** - * Called when the window is activated (WindowListener) Window layout is - * finished at latest a few millisec after windowActivated, then the - * 'wasActivated' boolean is set to tell the ImageCanvas that resize events - * should lead to resizing the canvas (before, creating the layout can lead to - * resize events) - */ - public void windowActivated(WindowEvent e) { - super.windowActivated(e); - if (!wasActivated) { - new Thread(new Runnable() { - public void run() { - IJ.wait(50); // sometimes, window layout is done only a few millisec after windowActivated - wasActivated = true; - } - }).start(); - } - } - - /** Called when the canvas is resized */ - void canvasResized() { - if (plot == null) - return; - /*Dimension d1 = getExtraSize(); - Dimension d2 = plot.getMinimumSize(); - setMinimumSize(new Dimension(d1.width + d2.width, d1.height + d2.height));*/ - maximizeCoordinatesLabelWidth(); - } - - /** - * Maximizes the width for the coordinate&status readout field and its parent - * bottomPanel - */ - void maximizeCoordinatesLabelWidth() { - Insets insets = getInsets(); // by default, left & right insets are 0 anyhow - Component parent = statusLabel.getParent(); // the bottomPanel, has insets of 0 - if (!parent.isValid()) - parent.validate(); - int cWidth = getWidth() - 2 * HGAP - statusLabel.getX() - insets.left - insets.right; - int cHeight = statusLabel.getPreferredSize().height; - statusLabel.setPreferredSize(new Dimension(cWidth, cHeight)); - parent.setSize(getWidth() - 2 * HGAP, parent.getHeight()); - } - - /** - * Shows the text in the coordinate&status readout field at the bottom. This - * text may get temporarily replaced for 'tooltips' (mouse over range arrows - * etc.). Call with a null argument to enable coordinate readout again. - */ - public void showStatus(String text) { - userStatusText = text; - if (statusLabel != null) - statusLabel.setText(text == null ? "" : text); - } - - /** - * Names for popupMenu items. Update NUM_MENU_ITEMS at the top when adding new - * ones! - */ - private static int SAVE = 0, COPY = 1, COPY_ALL = 2, LIST_SIMPLE = 3, ADD_FROM_TABLE = 4, ADD_FROM_PLOT = 5, - ADD_FIT = 6, // data menu - SET_RANGE = 7, PREV_RANGE = 8, RESET_RANGE = 9, FIT_RANGE = 10, // the rest is in the more menu - ZOOM_SELECTION = 11, AXIS_OPTIONS = 12, LEGEND = 13, STYLE = 14, TEMPLATE = 15, RESET_PLOT = 16, - FREEZE = 17, HI_RESOLUTION = 18, PROFILE_PLOT_OPTIONS = 19; - // the following commands are disabled when the plot is frozen - private static int[] DISABLED_WHEN_FROZEN = new int[] { ADD_FROM_TABLE, ADD_FROM_PLOT, ADD_FIT, SET_RANGE, - PREV_RANGE, RESET_RANGE, FIT_RANGE, ZOOM_SELECTION, AXIS_OPTIONS, LEGEND, STYLE, RESET_PLOT }; - - /** Prepares and returns the popupMenu of the Data>> button */ - PopupMenu getDataPopupMenu() { - dataPopupMenu = new PopupMenu(); - GUI.scalePopupMenu(dataPopupMenu); - menuItems[SAVE] = addPopupItem(dataPopupMenu, "Save Data..."); - menuItems[COPY] = addPopupItem(dataPopupMenu, "Copy 1st Data Set"); - menuItems[COPY_ALL] = addPopupItem(dataPopupMenu, "Copy All Data"); - menuItems[LIST_SIMPLE] = addPopupItem(dataPopupMenu, "List (Simple Headings)"); - dataPopupMenu.addSeparator(); - menuItems[ADD_FROM_TABLE] = addPopupItem(dataPopupMenu, "Add from Table..."); - menuItems[ADD_FROM_PLOT] = addPopupItem(dataPopupMenu, "Add from Plot..."); - menuItems[ADD_FIT] = addPopupItem(dataPopupMenu, "Add Fit..."); - return dataPopupMenu; - } - - /** Prepares and returns the popupMenu of the More>> button */ - PopupMenu getMorePopupMenu() { - morePopupMenu = new PopupMenu(); - GUI.scalePopupMenu(morePopupMenu); - menuItems[SET_RANGE] = addPopupItem(morePopupMenu, "Set Range..."); - menuItems[PREV_RANGE] = addPopupItem(morePopupMenu, "Previous Range"); - menuItems[RESET_RANGE] = addPopupItem(morePopupMenu, "Reset Range"); - menuItems[FIT_RANGE] = addPopupItem(morePopupMenu, "Set Range to Fit All"); - menuItems[ZOOM_SELECTION] = addPopupItem(morePopupMenu, "Zoom to Selection"); - morePopupMenu.addSeparator(); - menuItems[AXIS_OPTIONS] = addPopupItem(morePopupMenu, "Axis Options..."); - menuItems[LEGEND] = addPopupItem(morePopupMenu, "Legend..."); - menuItems[STYLE] = addPopupItem(morePopupMenu, "Contents Style..."); - menuItems[TEMPLATE] = addPopupItem(morePopupMenu, "Use Template..."); - menuItems[RESET_PLOT] = addPopupItem(morePopupMenu, "Reset Format"); - menuItems[FREEZE] = addPopupItem(morePopupMenu, "Freeze Plot", true); - menuItems[HI_RESOLUTION] = addPopupItem(morePopupMenu, "High-Resolution Plot..."); - morePopupMenu.addSeparator(); - menuItems[PROFILE_PLOT_OPTIONS] = addPopupItem(morePopupMenu, "Plot Defaults..."); - return morePopupMenu; - } - - MenuItem addPopupItem(PopupMenu popupMenu, String s) { - return addPopupItem(popupMenu, s, false); - } - - MenuItem addPopupItem(PopupMenu popupMenu, String s, boolean isCheckboxItem) { - MenuItem mi = null; - if (isCheckboxItem) { - mi = new CheckboxMenuItem(s); - ((CheckboxMenuItem) mi).addItemListener(this); - } else { - mi = new MenuItem(s); - mi.addActionListener(this); - } - popupMenu.add(mi); - return mi; - } - - /*Changed for Bio7*/ - public void actionPerformed(ActionEvent e) { - // String label = e.getActionCommand(); - Object b = e.getSource(); - if (b == live) { - toggleLivePlot(); - } else if (b == data) { - enableDisableMenuItems(); - Component c = (Component) b; - Point loc = c.getLocationOnScreen(); - // dataPopupMenu.show((Component) b, 1, 1); - /*Changed for Bio7*/ - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction icma = instance.getImageContextMenuAction(); - icma.swtPopupMenu(e, dataPopupMenu, new Point(loc.x, loc.y), this); - } else if (b == more) { - enableDisableMenuItems(); - Component c = (Component) b; - Point loc = c.getLocationOnScreen(); - // morePopupMenu.show((Component) b, 1, 1); - /*Changed for Bio7*/ - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction imageContextMenuAction = instance.getImageContextMenuAction(); - imageContextMenuAction.swtPopupMenu(e, morePopupMenu, new Point(loc.x, loc.y), this); - } - - actionPerformed(b); - } - - /*Changed for Bio7 - see above!*/ - /** Called if user has activated a button or popup menu item */ - public void actionPerformed(Object b) { - try { - //System.out.println(b.toString()); - // Object b = e.getSource(); - // if (b == live) - // toggleLiveProfiling(); - if (b == list) - showList(/*useLabels=*/true); - else if (b == data) { - // enableDisableMenuItems(); - // dataPopupMenu.show((Component) b, 1, 1); - } else if (b == more) { - // enableDisableMenuItems(); - // morePopupMenu.show((Component) b, 1, 1); - } else if (b == menuItems[SAVE]) - saveAsText(); - else if (b == menuItems[COPY]) - copyToClipboard(false); - else if (b == menuItems[COPY_ALL]) - copyToClipboard(true); - else if (b == menuItems[LIST_SIMPLE]) - showList(/*useLabels=*/false); - else if (b == menuItems[ADD_FROM_TABLE]) - new PlotContentsDialog(plot, PlotContentsDialog.ADD_FROM_TABLE).showDialog(this); - else if (b == menuItems[ADD_FROM_PLOT]) - new PlotContentsDialog(plot, PlotContentsDialog.ADD_FROM_PLOT).showDialog(this); - else if (b == menuItems[ADD_FIT]) - new PlotContentsDialog(plot, PlotContentsDialog.ADD_FIT).showDialog(this); - else if (b == menuItems[ZOOM_SELECTION]) { - if (imp != null && imp.getRoi() != null && imp.getRoi().isArea()) - plot.zoomToRect(imp.getRoi().getBounds()); - } else if (b == menuItems[SET_RANGE]) - new PlotDialog(plot, PlotDialog.SET_RANGE).showDialog(this); - else if (b == menuItems[PREV_RANGE]) - plot.setPreviousMinMax(); - else if (b == menuItems[RESET_RANGE]) - plot.setLimitsToDefaults(true); - else if (b == menuItems[FIT_RANGE]) - plot.setLimitsToFit(true); - else if (b == menuItems[AXIS_OPTIONS]) - new PlotDialog(plot, PlotDialog.AXIS_OPTIONS).showDialog(this); - else if (b == menuItems[LEGEND]) - new PlotDialog(plot, PlotDialog.LEGEND).showDialog(this); - else if (b == menuItems[STYLE]) - new PlotContentsDialog(plot, PlotContentsDialog.STYLE).showDialog(this); - else if (b == menuItems[TEMPLATE]) - new PlotDialog(plot, PlotDialog.TEMPLATE).showDialog(this); - else if (b == menuItems[RESET_PLOT]) { - plot.setFont(Font.PLAIN, fontSize); - plot.setAxisLabelFont(Font.PLAIN, fontSize); - plot.setFormatFlags(Plot.getDefaultFlags()); - plot.setFrameSize(plotWidth, plotHeight); // updates the image only when size changed - int correctionX = plot.leftMargin + plot.rightMargin; - int correctionY = plot.topMargin + plot.bottomMargin; - /* Changed for Bio7. We have no window and have to resize the canvas! */ - plot.getImagePlus().getCanvas().setSize(plotWidth + correctionX, plotHeight + correctionY); - plot.updateImage(); - /* Changed for Bio7 */ - CanvasView view = CanvasView.getCanvas_view(); - if (view != null) { - view.updatePlotCanvas(); - } - } else if (b == menuItems[HI_RESOLUTION]) - new PlotDialog(plot, PlotDialog.HI_RESOLUTION).showDialog(this); - else if (b == menuItems[PROFILE_PLOT_OPTIONS]) - IJ.doCommand("Plots..."); - ic.requestFocus(); // have focus on the canvas, not the button, so that pressing the space bar - // allows panning - } catch (Exception ex) { - IJ.handleException(ex); - } - } - - private void enableDisableMenuItems() { - boolean frozen = plot.isFrozen(); // prepare menu according to 'frozen' state of plot - ((CheckboxMenuItem) menuItems[FREEZE]).setState(frozen); - for (int i : DISABLED_WHEN_FROZEN) - menuItems[i].setEnabled(!frozen); - if (!PlotContentsDialog.tableWindowExists()) - menuItems[ADD_FROM_TABLE].setEnabled(false); - if (plot.getDataObjectDesignations().length == 0) - menuItems[ADD_FIT].setEnabled(false); - } - - /** Called if the user activates/deactivates a CheckboxMenuItem */ - public void itemStateChanged(ItemEvent e) { - if (e.getSource() == menuItems[FREEZE]) { - boolean frozen = ((CheckboxMenuItem) menuItems[FREEZE]).getState(); - plot.setFrozen(frozen); - } - } - - /** - * Updates the X and Y values when the mouse is moved and, if appropriate, - * shows/hides the overlay with the triangular buttons for changing the axis - * range limits. Overrides mouseMoved() in ImageWindow. - * - * @see ij.gui.ImageWindow#mouseMoved - */ - public void mouseMoved(int x, int y) { - super.mouseMoved(x, y); - if (plot == null) - return; - String statusText = null; // coordinate readout, status or tooltip, will be shown in coordinate&status - // line - - // arrows and other symbols for modifying the plot range - if (x < plot.leftMargin || y > plot.topMargin + plot.frameHeight) { - if (!rangeArrowsVisible && !plot.isFrozen()) - showRangeArrows(); - if (activeRangeArrow < 0) // mouse is not on one of the symbols, ignore (nothing to display) - { - } else if (activeRangeArrow < 8) // mouse over an arrow: 0,3,4,7 for increase, 1,2,5,6 for decrease - statusText = ((activeRangeArrow + 1) & 0x02) != 0 ? "Decrease Range" : "Increase Range"; - else if (activeRangeArrow == 8) // it's the 'R' icon - statusText = "Reset Range"; - else if (activeRangeArrow == 9) // it's the 'F' icon - statusText = "Full Range (Fit All)"; - else if (activeRangeArrow >= 10 && activeRangeArrow < 14) // space between arrow-pairs for single number - statusText = "Set limit..."; - else if (activeRangeArrow >= 14) - statusText = "Axis Range & Options..."; - boolean repaint = false; - if (activeRangeArrow >= 0 && !rangeArrowRois[activeRangeArrow].contains(x, y)) { - rangeArrowRois[activeRangeArrow] - .setFillColor(activeRangeArrow < 10 ? inactiveRangeArrowColor : inactiveRangeRectColor); - repaint = true; // de-highlight arrow where cursor has moved out - activeRangeArrow = -1; - } - if (activeRangeArrow < 0) { // no currently highlighted arrow, do we have a new one? - int i = getRangeArrowIndex(x, y); - if (i >= 0) { // we have an arrow or symbol at cursor position - rangeArrowRois[i].setFillColor(i < 14 ? activeRangeArrowColor : activeRangeRectColor); - activeRangeArrow = i; - repaint = true; - } - } - if (repaint) - ic.repaint(); - } else if (rangeArrowsVisible) - hideRangeArrows(); - if (statusText == null) - statusText = userStatusText != null ? userStatusText : plot.getCoordinates(x, y); - if (statusLabel != null) - statusLabel.setText(statusText); - } - - /** Called by PlotCanvas */ - void mouseExited(MouseEvent e) { - if (rangeArrowsVisible) - hideRangeArrows(); - } - - /** - * Mouse wheel: zooms when shift or ctrl is pressed, scrolls in x if space bar - * down, in y otherwise. - */ - public synchronized void mouseWheelMoved(MouseWheelEvent e) { - if (plot.isFrozen() || !(ic instanceof PlotCanvas)) { // frozen plots are like normal images - super.mouseWheelMoved(e); - return; - } - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - if (e.getX() < plot.leftMargin || e.getX() > plot.leftMargin + plot.frameWidth)// n__ - return; - if (e.getY() < plot.topMargin || e.getY() > plot.topMargin + plot.frameHeight) - return; - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - if (ctrl || IJ.shiftKeyDown()) { - double zoomFactor = rotation < 0 ? Math.pow(2, 0.2) : Math.pow(0.5, 0.2); - Point loc = ic.getCursorLoc(); - int x = ic.screenX(loc.x); - int y = ic.screenY(loc.y); - ((PlotCanvas) ic).zoom(x, y, zoomFactor); - } else if (IJ.spaceBarDown()) - plot.scroll(rotation * amount * Math.max(ic.imageWidth / 50, 1), 0); - else - plot.scroll(0, rotation * amount * Math.max(ic.imageHeight / 50, 1)); - } - - /** - * Creates an overlay with triangular buttons and other symbols for changing the - * axis range limits and shows it - */ - void showRangeArrows() { - if (imp == null) - return; - hideRangeArrows(); // in case we have old arrows from a different plot size or so - rangeArrowRois = new Roi[4 * 2 + 2 + 4 + 2]; // 4 arrows per axis, + 'Reset' and 'Fit All' icons, + 4 numerical - // input boxes + 2 axes - int i = 0; - int height = imp.getHeight(); - int arrowH = plot.topMargin < 14 ? 6 : 8; // height of arrows and distance between them; base is twice that - // value - float[] yP = new float[] { height - arrowH / 2, height - 3 * arrowH / 2, height - 5 * arrowH / 2 - 0.1f }; - - for (float x : new float[] { plot.leftMargin, plot.leftMargin + plot.frameWidth }) { // create arrows for x axis - float[] x0 = new float[] { x - arrowH / 2, x - 3 * arrowH / 2 - 0.1f, x - arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(x0, yP, 3, Roi.POLYGON); - float[] x1 = new float[] { x + arrowH / 2, x + 3 * arrowH / 2 + 0.1f, x + arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(x1, yP, 3, Roi.POLYGON); - } - float[] xP = new float[] { arrowH / 2 - 0.1f, 3 * arrowH / 2, 5 * arrowH / 2 + 0.1f }; - for (float y : new float[] { plot.topMargin + plot.frameHeight, plot.topMargin }) { // create arrows for y axis - float[] y0 = new float[] { y + arrowH / 2, y + 3 * arrowH / 2 + 0.1f, y + arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(xP, y0, 3, Roi.POLYGON); - float[] y1 = new float[] { y - arrowH / 2, y - 3 * arrowH / 2 - 0.1f, y - arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(xP, y1, 3, Roi.POLYGON); - } - Font theFont = new Font("SansSerif", Font.BOLD, 13); - - TextRoi txtRoi = new TextRoi(1, height - 19, "\u2009R\u2009", theFont); // thin spaces to make roi slightly - // wider - rangeArrowRois[8] = txtRoi; - TextRoi txtRoi2 = new TextRoi(20, height - 19, "\u2009F\u2009", theFont); - rangeArrowRois[9] = txtRoi2; - - rangeArrowRois[10] = new Roi(plot.leftMargin - arrowH / 2 + 1, height - 5 * arrowH / 2, arrowH - 2, arrowH * 2);// numerical - // box - // left - rangeArrowRois[11] = new Roi(plot.leftMargin + plot.frameWidth - arrowH / 2 + 1, height - 5 * arrowH / 2, - arrowH - 2, arrowH * 2);// numerical box right - rangeArrowRois[12] = new Roi(arrowH / 2, plot.topMargin + plot.frameHeight - arrowH / 2 + 1, arrowH * 2, - arrowH - 2);// numerical box bottom - rangeArrowRois[13] = new Roi(arrowH / 2, plot.topMargin - arrowH / 2 + 1, arrowH * 2, arrowH - 2);// numerical - // box top - - int topMargin = plot.topMargin; - int bottomMargin = topMargin + plot.frameHeight; - int leftMargin = plot.leftMargin; - int rightMargin = plot.leftMargin + plot.frameWidth; - rangeArrowRois[14] = new Roi(leftMargin, bottomMargin + 2, // area to click for x axis options - rightMargin - leftMargin + 1, 2 * arrowH); - rangeArrowRois[15] = new Roi(leftMargin - 2 * arrowH - 2, topMargin, // area to click for y axis options - 2 * arrowH, bottomMargin - topMargin + 1); - - Overlay ovly = imp.getOverlay(); - if (ovly == null) - ovly = new Overlay(); - for (Roi roi : rangeArrowRois) { - if (roi instanceof PolygonRoi) - roi.setFillColor(inactiveRangeArrowColor); - else if (roi instanceof TextRoi) { - roi.setStrokeColor(Color.WHITE); - roi.setFillColor(inactiveRangeArrowColor); - } else - roi.setFillColor(inactiveRangeRectColor); // transparent gray for single number boxes and axis range - ovly.add(roi); - } - imp.setOverlay(ovly); - ic.repaint(); - rangeArrowsVisible = true; - } - - public void hideRangeArrows() { - if (imp == null || rangeArrowRois == null) - return; - Overlay ovly = imp.getOverlay(); - if (ovly == null) - return; - for (Roi roi : rangeArrowRois) - ovly.remove(roi); - ic.repaint(); - rangeArrowsVisible = false; - activeRangeArrow = -1; - } - - /** - * Returns the index of the range-modifying symbol or axis at the cursor - * position x,y, or -1 of none. Index numbers for arrows start with 0 at the - * 'down' arrow of the lower side of the x axis and end with 7 the up arrow at - * the upper side of the y axis. Numbers 8 & 9 are for "Reset Range" and "Fit - * All"; numbers 10-13 for a dialog to set a single limit, and 14-15 for the - * axis options. - */ - - int getRangeArrowIndex(int x, int y) { - if (!rangeArrowsVisible) - return -1; - for (int i = 0; i < rangeArrowRois.length; i++) - if (rangeArrowRois[i].getBounds().contains(x, y)) - return i; - return -1; - } - - /** Shows the data of the backing plot in a Textwindow with columns */ - void showList(boolean useLabels) { - ResultsTable rt = plot.getResultsTable(saveXValues, useLabels); - if (rt == null) - return; - rt.show("Plot Values"); - if (autoClose) { - imp.changes = false; - close(); - } - } - - /** - * Returns the plot values with simple headings (X, Y, Y1 etc, not the labels) - * as a ResultsTable. Use plot.getResultsTableWithLabels for a table with data - * set labels as column headings - */ - public ResultsTable getResultsTable() { - return plot.getResultsTable(saveXValues); - } - - /** creates the data that fills the showList() function values */ - private String getValuesAsString() { - ResultsTable rt = getResultsTable(); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < rt.size(); i++) { - sb.append(rt.getRowAsString(i)); - sb.append("\n"); - } - return sb.toString(); - } - - /** Saves the data of the plot in a text file */ - void saveAsText() { - if (plot.getXValues() == null) { - IJ.error("Plot has no data"); - return; - } - SaveDialog sd = new SaveDialog("Save as Text", "Values", Prefs.defaultResultsExtension()); - String name = sd.getFileName(); - if (name == null) - return; - String directory = sd.getDirectory(); - IJ.wait(250); // give system time to redraw ImageJ window - IJ.showStatus("Saving plot values..."); - ResultsTable rt = plot.getResultsTable(/*writeFirstXColumn=*/saveXValues, /*useLabels=*/true); - try { - rt.saveAs(directory + name); - } catch (IOException e) { - IJ.error("" + e); - return; - } - if (autoClose) { - imp.changes = false; - close(); - } - } - - /** Copy the first dataset or all values to the clipboard */ - void copyToClipboard(boolean writeAllColumns) { - float[] xValues = plot.getXValues(); - float[] yValues = plot.getYValues(); - if (xValues == null) - return; - Clipboard systemClipboard = null; - try { - systemClipboard = getToolkit().getSystemClipboard(); - } catch (Exception e) { - systemClipboard = null; - } - if (systemClipboard == null) { - IJ.error("Unable to copy to Clipboard."); - return; - } - IJ.showStatus("Copying plot values..."); - CharArrayWriter aw = new CharArrayWriter(10 * xValues.length); - PrintWriter pw = new PrintWriter(aw); // uses platform's line termination characters - - if (writeAllColumns) { - ResultsTable rt = plot.getResultsTableWithLabels(); - if (!Prefs.dontSaveHeaders) { - String headings = rt.getColumnHeadings(); - pw.println(headings); - } - for (int i = 0; i < rt.size(); i++) - pw.println(rt.getRowAsString(i)); - } else { - int xdigits = 0; - if (saveXValues) - xdigits = plot.getPrecision(xValues); - int ydigits = plot.getPrecision(yValues); - for (int i = 0; i < Math.min(xValues.length, yValues.length); i++) { - if (saveXValues) - pw.println(IJ.d2s(xValues[i], xdigits) + "\t" + IJ.d2s(yValues[i], ydigits)); - else - pw.println(IJ.d2s(yValues[i], ydigits)); - } - } - String text = aw.toString(); - pw.close(); - StringSelection contents = new StringSelection(text); - systemClipboard.setContents(contents, this); - IJ.showStatus(text.length() + " characters copied to Clipboard"); - if (autoClose) { - imp.changes = false; - close(); - } - } - - public void lostOwnership(Clipboard clipboard, Transferable contents) { - } - - public float[] getXValues() { - return plot.getXValues(); - } - - public float[] getYValues() { - return plot.getYValues(); - } - - /** Draws a new plot in this window. */ - public void drawPlot(Plot plot) { - this.plot = plot; - if (imp != null) { - if (ic instanceof PlotCanvas) - ((PlotCanvas) ic).setPlot(plot); - imp.setProcessor(null, plot.getProcessor()); - plot.setImagePlus(imp); // also adjusts the calibration of imp - } - } - - /** Called once when ImageJ quits. */ - public static void savePreferences(Properties prefs) { - double min = ProfilePlot.getFixedMin(); - double max = ProfilePlot.getFixedMax(); - prefs.put(PREFS_WIDTH, Integer.toString(plotWidth)); - prefs.put(PREFS_HEIGHT, Integer.toString(plotHeight)); - prefs.put(PREFS_FONT_SIZE, Integer.toString(defaultFontSize)); - int options = 0; - if (!interpolate) - options |= INTERPOLATE; // true=0, false=1 - prefs.put(OPTIONS, Integer.toString(options)); - } - - /** Enables or disables live plotting. - * Does nothing if the plot has no PlotMaker (then there is no 'live' button). */ - public void enableLivePlot(boolean b) { - if (plot==null || plot.getPlotMaker()==null || live == null) - return; - if (b && bgThread == null) - enableLivePlot(); - else if (!b && bgThread != null) - disableLivePlot(); - } - - private void toggleLivePlot() { - boolean liveMode = bgThread != null; - enableLivePlot(!liveMode); - } - - /** Enables live plotting. - * This requires that the PlotWindow has been initialized with a Plot having a PlotMaker. - * Live plotting runs in a background thread. */ - private void enableLivePlot() { - if (plotMaker == null) - plotMaker = plot != null ? plot.getPlotMaker() : null; - if (plotMaker == null) - return; - srcImp = plotMaker.getSourceImage(); - if (srcImp == null) - return; - if (bgThread == null) { - bgThread = new Thread(this, "Live Plot"); - bgThread.setPriority(Math.max(bgThread.getPriority() - 3, Thread.MIN_PRIORITY)); - doUpdate = true; - bgThread.start(); - } - if (IJ.debugMode) - IJ.log("PlotWindow.createListeners"); - ImagePlus.addImageListener(this); - Roi.addRoiListener(this); - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); - live.setForeground(Color.red); - } - - /** Disables live plotting (when currently active) */ - private void disableLivePlot() { - if (IJ.debugMode) - IJ.log("PlotWindow.disableLivePlot: " + srcImp); - if (srcImp == null) - return; - if (bgThread != null) - bgThread.interrupt(); - bgThread = null; - ImagePlus.removeImageListener(this); - Roi.removeRoiListener(this); - if (live != null) { - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.PLAIN, font.getSize())); - //live.setForeground(Color.black); - /*Changed for Bio7!*/ - //Color swtBackgroundToAWT = Util.getSWTBackgroundToAWT(); - Color swtForegroundToAWT = Util.getSWTForegroundToAWT(); - //live.setBackground(swtBackgroundToAWT); - live.setForeground(swtForegroundToAWT); - } - } - - /** For live plots, update the plot if the ROI of the source image changes */ - public synchronized void roiModified(ImagePlus img, int id) { - if (IJ.debugMode) - IJ.log("PlotWindow.roiModified: " + img + " " + id); - if (img == srcImp) { - doUpdate = true; - notify(); - } - } - - // Unused - public void imageOpened(ImagePlus imp) { - } - - /** - * For live plots, this method is called if the source image content is changed. - */ - public synchronized void imageUpdated(ImagePlus imp) { - if (imp == srcImp) { - doUpdate = true; - notify(); - } - } - - /** - * For live plots, if either the source image or this image are closed, exit - * live mode - */ - public void imageClosed(ImagePlus imp) { - if (imp == srcImp || imp == this.imp) { - disableLivePlot(); - srcImp = null; - plotMaker = null; - } - } - - // the background thread for live plotting. - public void run() { - while (true) { - IJ.wait(50); // delay to make sure the roi has been updated - Plot plot = plotMaker != null ? plotMaker.getPlot() : null; - if (doUpdate && plot != null && plot.getNumPlotObjects() > 0) { - plot.useTemplate(this.plot, this.plot.templateFlags | Plot.COPY_SIZE | Plot.COPY_LABELS - | Plot.COPY_AXIS_STYLE | Plot.COPY_CONTENTS_STYLE | Plot.COPY_LEGEND | Plot.COPY_EXTRA_OBJECTS); - plot.setPlotMaker(plotMaker); - this.plot = plot; - /* Changed for Bio7! */ - // ((PlotCanvas)ic).setPlot(plot); - ImageProcessor ip = plot.getProcessor(); - if (ip != null && imp != null) { - imp.setProcessor(null, ip); - plot.setImagePlus(imp); - } - } - synchronized (this) { - if (doUpdate) { - doUpdate = false; // and loop again - } else { - try { - wait(); - } // notify wakes up the thread - catch (InterruptedException e) { // interrupted tells the thread to exit - return; - } - } - } - } - } - - /** Returns the Plot associated with this PlotWindow. */ - public Plot getPlot() { - return plot; - } - - /** - * Freezes the active plot window, so the image does not get redrawn for - * zooming, setting the range, etc. - */ - public static void freeze() { - Window win = WindowManager.getActiveWindow(); - if (win != null && (win instanceof PlotWindow)) - ((PlotWindow) win).getPlot().setFrozen(true); - } - - public static void setDefaultFontSize(int size) { - if (size < 9) - size = 9; - defaultFontSize = size; - } - - public static int getDefaultFontSize() { - return defaultFontSize; - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/PointRoi.java b/com.eco.bio7.image/src/ij/gui/PointRoi.java deleted file mode 100644 index d349965b3..000000000 --- a/com.eco.bio7.image/src/ij/gui/PointRoi.java +++ /dev/null @@ -1,1064 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.measure.*; -import ij.plugin.Colors; -import ij.plugin.PointToolOptions; -import ij.plugin.filter.Analyzer; -import ij.plugin.frame.Recorder; -import ij.util.Tools; -import ij.util.Java2; -import java.awt.*; -import java.awt.image.*; -import java.awt.event.KeyEvent; -import java.util.*; -import java.awt.geom.*; - -/** This class represents a collection of points that can be associated - * with counters. Use the getPolygon() or getFloatPolygon() methods - * to retrieve the coordinates of the points. - * @see PointProperties.js -*/ -public class PointRoi extends PolygonRoi { - public static final String[] sizes = {"Tiny", "Small", "Medium", "Large", "Extra Large", "XXL", "XXXL"}; - public static final String[] types = {"Hybrid", "Cross", "Dot", "Circle"}; - public static final int HYBRID=0, CROSS=1, CROSSHAIR=1, DOT=2, CIRCLE=3; - /** Returned by getPosition if point stack positions are different */ - public static final int POINTWISE_POSITION = -2; - private static final String TYPE_KEY = "point.type"; - private static final String SIZE_KEY = "point.size"; - private static final String CROSS_COLOR_KEY = "point.cross.color"; - private static final int TINY=1, SMALL=3, MEDIUM=5, LARGE=7, EXTRA_LARGE=11, XXL=17, XXXL=25; - private static final BasicStroke twoPixelsWide = new BasicStroke(2); - private static final BasicStroke threePixelsWide = new BasicStroke(3); - private static final BasicStroke fivePixelsWide = new BasicStroke(5); - private static int defaultType = HYBRID; - private static int defaultSize = SMALL; - private static Font font; - private static Color defaultCrossColor = Color.white; - private static int fontSize = 9; - public static final int MAX_COUNTERS = 100; - private static String[] counterChoices; - private static Color[] colors; - private boolean showLabels; - private int type = HYBRID; - private int size = SMALL; - private static int defaultCounter; - private int counter; - private int nCounters = 1; - private short[] counters; //for each point, 0-100 for counter (=category that can be defined by the user) - private int[] positions; //for each point, the stack slice, or 0 for 'show on all' - private int[] counts = new int[MAX_COUNTERS]; - private ResultsTable rt; - private long lastPointTime; - private int[] counterInfo; - private boolean promptBeforeDeleting; - private boolean promptBeforeDeletingCalled; - private int nMarkers; - private boolean addToOverlay; - public static PointRoi savedPoints; - - static { - setDefaultType((int)Prefs.get(TYPE_KEY, HYBRID)); - setDefaultSize((int)Prefs.get(SIZE_KEY, 1)); - } - - public PointRoi() { - this(0.0, 0.0); - deletePoint(0); - } - - /** Creates a new PointRoi using the specified int arrays of offscreen coordinates. */ - public PointRoi(int[] ox, int[] oy, int points) { - super(itof(ox), itof(oy), points, POINT); - updateCounts(); - } - - /** Creates a new PointRoi using the specified float arrays of offscreen coordinates. */ - public PointRoi(float[] ox, float[] oy, int points) { - super(ox, oy, points, POINT); - updateCounts(); - } - - /** Creates a new PointRoi using the specified float arrays of offscreen coordinates. */ - public PointRoi(float[] ox, float[] oy) { - this(ox, oy, ox.length); - } - - /** Creates a new PointRoi using the specified coordinate arrays and options. */ - public PointRoi(float[] ox, float[] oy, String options) { - this(ox, oy, ox.length); - setOptions(options); - } - - /** Creates a new PointRoi from a FloatPolygon. */ - public PointRoi(FloatPolygon poly) { - this(poly.xpoints, poly.ypoints, poly.npoints); - } - - /** Creates a new PointRoi from a Polygon. */ - public PointRoi(Polygon poly) { - this(itof(poly.xpoints), itof(poly.ypoints), poly.npoints); - } - - /** Creates a new PointRoi using the specified coordinates and options. */ - public PointRoi(double ox, double oy, String options) { - super(makeXorYArray(ox, null, false), makeXorYArray(oy, null, true), 1, POINT); - width=1; height=1; - incrementCounter(null); - setOptions(options); - } - - /** Creates a new PointRoi using the specified offscreen int coordinates. */ - public PointRoi(int ox, int oy) { - super(makeXorYArray(ox, null, false), makeXorYArray(oy, null, true), 1, POINT); - width=1; height=1; - incrementCounter(null); - } - - /** Creates a new PointRoi using the specified offscreen double coordinates. */ - public PointRoi(double ox, double oy) { - super(makeXorYArray(ox, null, false), makeXorYArray(oy, null, true), 1, POINT); - width=1; height=1; - incrementCounter(null); - } - - /** Creates a new PointRoi using the specified screen coordinates. */ - public PointRoi(int sx, int sy, ImagePlus imp) { - super(makeXorYArray(sx, imp, false), makeXorYArray(sy, imp, true), 1, POINT); - //defaultCounter = 0; - setImage(imp); - width=1; height=1; - type = defaultType; - size = defaultSize; - showLabels = !Prefs.noPointLabels; - if (imp!=null) { - int r = 10 + size; - double mag = ic!=null?ic.getMagnification():1; - if (mag<1) - r = (int)(r/mag); - imp.draw(x-r, y-r, 2*r, 2*r); - } - setCounter(Toolbar.getMultiPointMode()?defaultCounter:0); - incrementCounter(imp); - enlargeArrays(50); - record(x, y, false); - } - - private void record(int xx, int yy, boolean addingPoint) { - if (!IJ.recording()) - return; - String add = Prefs.pointAddToOverlay?" add":""; - String options = sizes[convertSizeToIndex(size)]+" "+Colors.colorToString(getColor())+" "+types[type]+add; - options = options.toLowerCase(); - if (addingPoint) - options = "add"; - if (Recorder.scriptMode()) - Recorder.recordCall("imp.setRoi(new PointRoi("+xx+","+yy+",\""+options+"\"));"); - else - Recorder.record("makePoint", xx, yy, options); - } - - public void setOptions(String options) { - if (options==null) - return; - if (options.contains("tiny")) size=TINY; - else if (options.contains("medium")) size=MEDIUM; - else if (options.contains("extra")) size=EXTRA_LARGE; - else if (options.contains("large")) size=LARGE; - else if (options.contains("xxxl")) size=XXXL; - else if (options.contains("xxl")) size=XXL; - if (options.contains("cross")) type=CROSS; - else if (options.contains("dot")) type=DOT; - else if (options.contains("circle")) type=CIRCLE; - if (options.contains("nolabel")) setShowLabels(false); - else if (options.contains("label")) setShowLabels(true); - setStrokeColor(Colors.getColor(options,Roi.getColor())); - addToOverlay = options.contains("add"); - } - - static float[] itof(int[] arr) { - if (arr==null) - return null; - int n = arr.length; - float[] temp = new float[n]; - for (int i=0; i1) { - fontSize = 8; - double scale = size>=XXL?2:1.5; - fontSize += scale*convertSizeToIndex(size); - fontSize = (int)Math.round(fontSize); - font = new Font("SansSerif", Font.PLAIN, fontSize); - g.setFont(font); - if (fontSize>9) - Java2.setAntialiasedText(g, true); - } - int[] positions = this.positions; //use a copy to avoid NullPointerException on asynchronous change to null - int slice = imp!=null && positions!=null && imp.getStackSize()>1?imp.getCurrentSlice():0; - ImageCanvas ic = imp!=null?imp.getCanvas():null; - if (ic!=null && overlay && ic.getShowAllList()!=null && ic.getShowAllList().contains(this) && !Prefs.showAllSliceOnly) - slice = 0; // In RoiManager's "show all" mode and not "associate with slice", draw point irrespective of currently selected slice - if (Prefs.showAllPoints) - slice = 0; // "Show on all slices" in Point tool options - for (int i=0; i1.0) { - saveXform = g2d.getTransform(); - g2d.translate(x, y); - g2d.scale(flattenScale, flattenScale); - x = y = 0; - } - Color color = strokeColor!=null?strokeColor:ROIColor; - if (!overlay && isActiveOverlayRoi()) { - if (color==Color.cyan) - color = Color.magenta; - else - color = Color.cyan; - } - if (nCounters>1 && counters!=null && n<=counters.length) - color = getColor(counters[n-1]); - if (type==HYBRID || type==CROSS) { - if (type==HYBRID) - g.setColor(Color.white); - else { - g.setColor(color); - colorSet = true; - } - if (size>XXL) - g2d.setStroke(fivePixelsWide); - else if (size>LARGE) - g2d.setStroke(threePixelsWide); - g.drawLine(x-(size+2), y, x+size+2, y); - g.drawLine(x, y-(size+2), x, y+size+2); - } - if (type!=CROSS && size>SMALL) - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - if (type==HYBRID || type==DOT) { - if (!colorSet) { - g.setColor(color); - colorSet = true; - } - if (size>LARGE) - g2d.setStroke(onePixelWide); - if (size>LARGE && type==DOT) - g.fillOval(x-size2, y-size2, size, size); - else if (size>LARGE && type==HYBRID) - g.fillRect(x-(size2-2), y-(size2-2), size-4, size-4); - else if (size>SMALL && type==HYBRID) - g.fillRect(x-(size2-1), y-(size2-1), size-2, size-2); - else - g.fillRect(x-size2, y-size2, size, size); - } - if (showLabels && nPoints>1) { - int xoffset = 2; - if (size==LARGE) xoffset=3; - if (size==EXTRA_LARGE) xoffset=4; - if (size==XXL) xoffset=5; - if (size==XXXL) xoffset=7; - int yoffset = xoffset; - if (size>=LARGE) yoffset=yoffset-1; - if (nCounters==1) { - if (!colorSet) - g.setColor(color); - g.drawString(""+n, x+xoffset, y+yoffset+fontSize); - } else if (counters!=null) { - g.setColor(getColor(counters[n-1])); - g.drawString(""+counters[n-1], x+xoffset, y+yoffset+fontSize); - } - } - if ((size>TINY||type==DOT) && (type==HYBRID||type==DOT)) { - g.setColor(Color.black); - if (size>LARGE && type==HYBRID) - g.drawOval(x-(size2-1), y-(size2-1), size-3, size-3); - else if (size>SMALL && type==HYBRID) - g.drawOval(x-size2, y-size2, size-1, size-1); - else - g.drawOval(x-(size2+1), y-(size2+1), size+1, size+1); - } - if (type==CIRCLE) { - int scaledSize = (int)Math.round(size+1); - g.setColor(color); - if (size>LARGE) - g2d.setStroke(twoPixelsWide); - g.drawOval(x-scaledSize/2, y-scaledSize/2, scaledSize, scaledSize); - } - if (saveXform!=null) - g2d.setTransform(saveXform); - } - - public void drawPixels(ImageProcessor ip) { - ip.setLineWidth(Analyzer.markWidth); - double x0 = bounds == null ? x : bounds.x; - double y0 = bounds == null ? y : bounds.y; - for (int i=0; i=0 && index<=nPoints && counters!=null) { - counts[counters[index]]--; - for (int i=index; i1; - if (counter!=0 || isStack || counters!=null) { - if (counters==null) { - int size = nPoints*2; - if (size<100) size=100; - counters = new short[size]; - positions = new int[size]; - } - if (nPoints>=counters.length) { - short[] temp = new short[counters.length*2]; - System.arraycopy(counters, 0, temp, 0, counters.length); - counters = temp; - int[] temp1 = new int[counters.length*2]; - System.arraycopy(positions, 0, temp1, 0, positions.length); - positions = temp1; - } - counters[nPoints-1] = (short)counter; - if (imp!=null) - positions[nPoints-1] = imp.getStackSize()>1 ? imp.getCurrentSlice() : 0; - } - if (rt!=null && WindowManager.getFrame(getCountsTitle())!=null) - displayCounts(); - } - - /** Returns the index of the current counter. */ - public int getCounter() { - return counter; - } - - /** Returns the count associated with the specified counter index. - * @see #getLastCounter - * @see PointProperties.js - */ - public int getCount(int counter) { - if (counter==0 && counters==null) - return nPoints; - else - return counts[counter]; - } - - /** Returns the index of the last counter. */ - public int getLastCounter() { - return nCounters - 1; - } - - /** Returns the number of counters. */ - public int getNCounters() { - int n = 0; - for (int counter=0; counter0) n++; - } - return n; - } - - /** Returns the counter assocated with the specified point. */ - public int getCounter(int index) { - if (counters==null || index>=counters.length) - return 0; - else - return counters[index]; - } - - /** Deletes all counters and stack position associations */ - public void resetCounters() { - for (int i=0; iroi if keepContained is true (false). */ - PointRoi checkContained(Roi roi, boolean keepContained) { - if (!roi.isArea()) return null; - FloatPolygon points = getFloatPolygon(); - FloatPolygon points2 = new FloatPolygon(); - for (int i=0; i=0 && type=0 && type=0 && index=0 && sizenCounters-1 && nCounters8||getNCounters()>1) && imp!=null && imp.getWindow()!=null; - } - - public void promptBeforeDeleting(Boolean prompt) { - promptBeforeDeleting = prompt; - promptBeforeDeletingCalled = true; - } - - public static void setDefaultCounter(int counter) { - defaultCounter = counter; - } - - /** Returns an array containing for each point: - * The counter number (0-100) in the lower 8 bits, and the slice number - * (or 0, if the point appears on all slices) in the higher 24 bits. - * Used when writing a Roi to file (RoiEncoder) */ - public int[] getCounters() { - if (nPoints>65535) - return null; - int[] temp = new int[nPoints]; - if (counters!=null) { - for (int i=0; i>8; - this.counters[i] = (short)counter; - this.positions[i] = position; - if (counternCounters-1) - nCounters = counter + 1; - } - updateCounts(); - } - } - - /** Updates the counts for each category in 'counters' */ - public void updateCounts() { - Arrays.fill(counts, 0); - for (int i=0; i=counts.length) ? 0 : counters[i]] ++; - } - - /** Sets the stack position (image number) of all points in this Roi. - * The points are only displayed when the stack is at the specified position. - * Set to zero to have the points displayed on all images in the stack. - * The stack position, when set, determines the visibility of this Roi - * (i) if it is part of an overlay (normal overlay or the RoiManager's - * 'Show All' overlay), or - * (ii) if it is the currently active Roi and Prefs.showAllPoints - * ('Show an all slices' in the Point Tool Options dialog) is off. - * Clears any association of this Roi to a hyperstack position. - * Stack positions of individual points are overwritten. - * - * Note that the behavior differs from that of the other Roi types: - * For the other Roi types, setPosition does not restrict the visibility - * to stack slice 'n' if that roi is the currently active Roi; it only - * affects the visibility if that Roi is part of an overlay. - */ - public void setPosition(int n) { - if (n<0 && n!=POINTWISE_POSITION) - n = 0; - if (n == 0) { - positions = null; - } else { - if (positions == null) { - if (counters == null) - counters = new short[nPoints*2]; - positions = new int[counters.length]; - } - if (n != POINTWISE_POSITION) - Arrays.fill(positions, n); - } - super.setPosition(nPoints>1?0:n); - } - - /** Returns the stack position (image number) of the points in this Roi, if - * all points have the same position. Returns 0 if none of the points is - * associated with a particular stack image, and PointRoi.POINTWISE_POSITION = -2 - * if there are different stack positions for different points. - */ - public int getPosition() { - int position = 0; - if (positions==null || nPoints<1) - position = 0; - else if (nPoints==1) - return super.getPosition(); - else { - position = positions[0]; - for (int i=1; i= 0; - } - - public void displayCounts() { - ImagePlus imp = getImage(); - String firstColumnHdr = "Slice"; - rt = new ResultsTable(); - int row = 0; - if (imp!=null && imp.getStackSize()>1 && positions!=null) { - int nChannels = 1; - int nSlices = 1; - int nFrames = 1; - boolean isHyperstack = true; - if (imp.isComposite() || imp.isHyperStack()) { - nChannels = imp.getNChannels(); - nSlices = imp.getNSlices(); - nFrames = imp.getNFrames(); - int nDimensions = 2; - if (nChannels>1) nDimensions++; - if (nSlices>1) nDimensions++; - if (nFrames>1) nDimensions++; - if (nDimensions==3) { - isHyperstack = false; - if (nChannels>1) - firstColumnHdr = "Channel"; - } else - firstColumnHdr = "Image"; - } - int firstSlice = Integer.MAX_VALUE; - for (int i=0; i0 && positions[i]0) { - for (int i=0; ilastSlice) - lastSlice = positions[i]; - } - } - if (firstSlice>0) { - for (int slice=firstSlice; slice<=lastSlice; slice++) { - rt.setValue(firstColumnHdr, row, slice); - if (isHyperstack) { - int[] position = imp.convertIndexToPosition(slice); - if (nChannels>1) - rt.setValue("Channel", row, position[0]); - if (nSlices>1) - rt.setValue("Slice", row, position[1]); - if (nFrames>1) - rt.setValue("Frame", row, position[2]); - } - for (int counter=0; counter1?imp.getCurrentSlice():0; - for (int i=0; i=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) { - handle = i; - break; - } - } - return handle; - } - - /** Returns the points as an array of Points. - * Wilhelm Burger: modified to use FloatPolygon for correct point positions. - */ - public Point[] getContainedPoints() { - FloatPolygon p = getFloatPolygon(); - Point[] points = new Point[p.npoints]; - for (int i=0; i iterator() { - return new Iterator() { - final Point[] pnts = getContainedPoints(); - final int n = pnts.length; - int next = (n == 0) ? 1 : 0; - @Override - public boolean hasNext() { - return next < n; - } - @Override - public Point next() { - if (next >= n) { - throw new NoSuchElementException(); - } - Point pnt = pnts[next]; - next = next + 1; - return pnt; - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - protected int getClosestPoint(double x, double y, FloatPolygon points) { - int index = -1; - double distance = Double.MAX_VALUE; - int slice = imp!=null&&positions!=null&&imp.getStackSize()>1?imp.getCurrentSlice():0; - if (Prefs.showAllPoints) - slice = 0; - for (int i=0; i=0; i--) { - if (!roi.contains(p.xpoints[i],p.ypoints[i])) { - points.deletePoint(i); - } - } - return points; - } - - @Override - public void copyAttributes(Roi roi2) { - super.copyAttributes(roi2); - if (roi2 instanceof PointRoi) { - PointRoi p2 = (PointRoi)roi2; - this.type = p2.type; - this.size = p2.size; - this.showLabels = p2.showLabels; - this.fontSize = p2.fontSize; - } - } - - public void setCounterInfo(int[] info) { - counterInfo = info; - } - - public int[] getCounterInfo() { - return counterInfo; - } - - public boolean addToOverlay() { - return addToOverlay; - } - - public String toString() { - if (nPoints>1) - return ("Roi[Points, count="+nPoints+", pos="+getPositionAsString()+", psize="+size+"]"); - else - return ("Roi[Point, x="+x+", y="+y+", pos="+getPositionAsString()+", psize="+size+"]"); - } - - /** @deprecated */ - public void setHideLabels(boolean hideLabels) { - this.showLabels = !hideLabels; - } - - /** @deprecated */ - public static void setDefaultMarkerSize(String size) { - } - - /** @deprecated */ - public static String getDefaultMarkerSize() { - return sizes[defaultSize]; - } - - /** Deprecated */ - public static void setDefaultCrossColor(Color color) { - } - - /** Deprecated */ - public static Color getDefaultCrossColor() { - return null; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/PolygonRoi.java b/com.eco.bio7.image/src/ij/gui/PolygonRoi.java deleted file mode 100644 index 2b58adde9..000000000 --- a/com.eco.bio7.image/src/ij/gui/PolygonRoi.java +++ /dev/null @@ -1,1705 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.measure.*; -import ij.plugin.frame.*; -import ij.util.Tools; -import ij.util.FloatArray; -import java.awt.*; -import java.awt.image.*; -import java.awt.geom.*; -import java.awt.event.*; - -/** This class represents a polygon region of interest or polyline of interest. */ -public class PolygonRoi extends Roi { - - protected int maxPoints = 1000; // will be increased if necessary - protected int[] xp, yp; // image coordinates relative to origin of roi bounding box - protected float[] xpf, ypf; // or alternative sub-pixel coordinates - protected int[] xp2, yp2; // absolute screen coordinates - protected int nPoints; - protected float[] xSpline,ySpline; // relative image coordinates - protected int splinePoints = 200; - Rectangle clip; - - private double angle1, degrees=Double.NaN; - private int xClipMin, yClipMin, xClipMax, yClipMax; - private boolean userCreated; - private int boxSize = 8; - - long mouseUpTime = 0; - - /** Creates a new polygon or polyline ROI from x and y coordinate arrays. - Type must be Roi.POLYGON, Roi.FREEROI, Roi.TRACED_ROI, Roi.POLYLINE, Roi.FREELINE or Roi.ANGLE.*/ - public PolygonRoi(int[] xPoints, int[] yPoints, int nPoints, int type) { - super(0, 0, null); - init1(nPoints, type); - xp = xPoints; - yp = yPoints; - if (type!=TRACED_ROI) { - xp = new int[nPoints]; - yp = new int[nPoints]; - for (int i=0; i1 && isLine()) - updateWideLine(lineWidth); - finishPolygon(); - } - - /** Creates a new polygon or polyline ROI from a Polygon. Type must be Roi.POLYGON, - Roi.FREEROI, Roi.TRACED_ROI, Roi.POLYLINE, Roi.FREELINE or Roi.ANGLE.*/ - public PolygonRoi(Polygon p, int type) { - this(p.xpoints, p.ypoints, p.npoints, type); - } - - /** Creates a new polygon or polyline ROI from a FloatPolygon. Type must be Roi.POLYGON, - Roi.FREEROI, Roi.TRACED_ROI, Roi.POLYLINE, Roi.FREELINE or Roi.ANGLE.*/ - public PolygonRoi(FloatPolygon p, int type) { - this(p.xpoints, p.ypoints, p.npoints, type); - } - - /** @deprecated */ - public PolygonRoi(int[] xPoints, int[] yPoints, int nPoints, ImagePlus imp, int type) { - this(xPoints, yPoints, nPoints, type); - setImage(imp); - } - - /** Starts the process of creating a new user-generated polygon or polyline ROI. */ - public PolygonRoi(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - int tool = Toolbar.getToolId(); - switch (tool) { - case Toolbar.POLYGON: - type = POLYGON; - break; - case Toolbar.FREEROI: - type = FREEROI; - break; - case Toolbar.FREELINE: - type = FREELINE; - break; - case Toolbar.ANGLE: - type = ANGLE; - break; - default: - type = POLYLINE; - break; - } - if (magnificationForSubPixel()) - enableSubPixelResolution(); - previousSX = sx; - previousSY = sy; - x = offScreenX(sx); - y = offScreenY(sy); - startXD = offScreenXD(sx); - startYD = offScreenYD(sy); - if (subPixelResolution()) { - setLocation(startXD, startYD); - xpf = new float[maxPoints]; - ypf = new float[maxPoints]; - double xbase = getXBase(); - double ybase = getYBase(); - xpf[0] = (float)(startXD-xbase); - ypf[0] = (float)(startYD-ybase); - xpf[1] = xpf[0]; - ypf[1] = ypf[0]; - } else { - xp = new int[maxPoints]; - yp = new int[maxPoints]; - } - xp2 = new int[maxPoints]; - yp2 = new int[maxPoints]; - nPoints = 2; - width=1; - height=1; - clipX = x; - clipY = y; - clipWidth = 1; - clipHeight = 1; - state = CONSTRUCTING; - userCreated = true; - if (lineWidth>1 && isLine()) - updateWideLine(lineWidth); - boxSize = (int)(boxSize*Prefs.getGuiScale()); - } - - private void drawStartBox(Graphics g) { - if (type!=ANGLE) - g.drawRect(screenXD(startXD)-4, screenYD(startYD)-4, 8, 8); - } - - public void draw(Graphics g) { - updatePolygon(); - Color color = strokeColor!=null?strokeColor:ROIColor; - boolean hasHandles = xSpline!=null||type==POLYGON||type==POLYLINE||type==ANGLE; - boolean isActiveOverlayRoi = !overlay && isActiveOverlayRoi(); - if (isActiveOverlayRoi) { - if (color==Color.cyan) - color = Color.magenta; - else - color = Color.cyan; - } - boolean fill = false; - mag = getMagnification(); - if (fillColor!=null && !isLine() && state!=CONSTRUCTING) { - color = fillColor; - fill = true; - } - g.setColor(color); - Graphics2D g2d = (Graphics2D)g; - setRenderingHint(g2d); - if (stroke!=null && !isActiveOverlayRoi) - g2d.setStroke(getScaledStroke()); - if (xSpline!=null) { - if (type==POLYLINE || type==FREELINE) { - drawSpline(g, xSpline, ySpline, splinePoints, false, fill, isActiveOverlayRoi); - if (wideLine && !overlay) { - g2d.setStroke(onePixelWide); - g.setColor(getColor()); - drawSpline(g, xSpline, ySpline, splinePoints, false, fill, isActiveOverlayRoi); - } - } else - drawSpline(g, xSpline, ySpline, splinePoints, true, fill, isActiveOverlayRoi); - } else { - if (type==POLYLINE || type==FREELINE || type==ANGLE || (state==CONSTRUCTING && !(this instanceof RotatedRectRoi))) { g.drawPolyline(xp2, yp2, nPoints); - if (wideLine && !overlay) { - g2d.setStroke(onePixelWide); - g.setColor(getColor()); - g.drawPolyline(xp2, yp2, nPoints); - } - } else { - if (fill) { - if (isActiveOverlayRoi) { - g.setColor(Color.cyan); - g.drawPolygon(xp2, yp2, nPoints); - } else - g.fillPolygon(xp2, yp2, nPoints); - if (strokeColor!=null) { - g.setColor(strokeColor); - g.drawPolygon(xp2, yp2, nPoints); - } - } else - g.drawPolygon(xp2, yp2, nPoints); - } - if (state==CONSTRUCTING && type!=FREEROI && type!=FREELINE) - drawStartBox(g); - } - if (hasHandles && clipboard==null && !overlay) { - if (activeHandle>0) - drawHandle(g, xp2[activeHandle-1], yp2[activeHandle-1]); - if (activeHandle1f) - ip.setLineWidth((int)Math.round(getStrokeWidth())); - double xbase = getXBase(); - double ybase = getYBase(); - if (xSpline!=null) { - ip.moveTo((int)Math.round(xbase+xSpline[0]), (int)Math.round(ybase+ySpline[0])); - for (int i=1; i Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - - // Do rubber banding - int tool = Toolbar.getToolId(); - if (!(tool==Toolbar.POLYGON || tool==Toolbar.POLYLINE || tool==Toolbar.ANGLE)) { - imp.deleteRoi(); - imp.draw(); - return; - } - if (IJ.altKeyDown()) - wipeBack(); - - drawRubberBand(sx, sy); - - // show status: length & angle - degrees = Double.NaN; - double len = -1; - if (nPoints>1) { - double x1, y1, x2, y2; - if (xpf!=null) { - x1 = xpf[nPoints-2]; - y1 = ypf[nPoints-2]; - x2 = xpf[nPoints-1]; - y2 = ypf[nPoints-1]; - } else { - x1 = xp[nPoints-2]; - y1 = yp[nPoints-2]; - x2 = xp[nPoints-1]; - y2 = yp[nPoints-1]; - } - degrees = getFloatAngle(x1, y1, x2, y2); - if (tool!=Toolbar.ANGLE) { - Calibration cal = imp.getCalibration(); - double pw=cal.pixelWidth, ph=cal.pixelHeight; - if (IJ.altKeyDown()) {pw=1.0; ph=1.0;} - len = Math.sqrt((x2-x1)*pw*(x2-x1)*pw + (y2-y1)*ph*(y2-y1)*ph); - } - } - if (tool==Toolbar.ANGLE) { - if (nPoints==2) - angle1 = degrees; - else if (nPoints==3) { - double angle2 = xpf != null ? getFloatAngle(xpf[1], ypf[1], xpf[2], ypf[2]) : - getAngle(xp[1], yp[1], xp[2], yp[2]); - degrees = Math.abs(180-Math.abs(angle1-angle2)); - if (degrees>180.0) - degrees = 360.0-degrees; - } - } - String length = len!=-1?", length=" + IJ.d2s(len):""; - double degrees2 = tool==Toolbar.ANGLE&&nPoints==3&&Prefs.reflexAngle?360.0-degrees:degrees; - String angle = !Double.isNaN(degrees)?", angle=" + IJ.d2s(degrees2):""; - int ox = ic.offScreenX(sx); - int oy = ic.offScreenY(sy); - IJ.showStatus(imp.getLocationAsString(ox,oy) + length + angle); - } - - //Mouse behaves like an eraser when moved backwards with alt key down. - //Within correction circle, all vertices with sharp angles are removed. - //Norbert Vischer - protected void wipeBack() { - Roi prevRoi = Roi.getPreviousRoi(); - if (prevRoi!=null && prevRoi.modState==SUBTRACT_FROM_ROI) - return; - double correctionRadius = 20; - if (ic!=null) - correctionRadius /= ic.getMagnification(); - boolean found = false; - int p3 = nPoints - 1; - int p1 = p3; - while (p1 > 0 && !found) { - p1--; - double dx = xpf != null ? xpf[p3] - xpf[p1] : xp[p3] - xp[p1]; - double dy = xpf != null ? ypf[p3] - ypf[p1] : yp[p3] - yp[p1]; - double dist = Math.sqrt(dx * dx + dy * dy); - if (dist > correctionRadius) - found = true; - } - //examine all angles p1-p2-p3 - boolean killed = false; - int safety = 10; //don't delete more than this number of points at once - do { - killed = false; - safety--; - for (int p2 = p1 + 1; p2 < p3; p2++) { - double dx1 = xpf != null ? xpf[p2] - xpf[p1] : xp[p2] - xp[p1]; - double dy1 = xpf != null ? ypf[p2] - ypf[p1] : yp[p2] - yp[p1]; - double dx2 = xpf != null ? xpf[p3] - xpf[p1] : xp[p3] - xp[p1]; - double dy2 = xpf != null ? ypf[p3] - ypf[p1] : yp[p3] - yp[p1]; - double kk = 1;//allowed sharpness - if (this instanceof FreehandRoi) - kk = 0.8; - if ((dx1 * dx1 + dy1 * dy1) > kk * (dx2 * dx2 + dy2 * dy2)) { - if (xpf != null) { - xpf[p2] = xpf[p3]; ypf[p2] = ypf[p3]; //replace sharp vertex with end point - } else { - xp[p2] = xp[p3]; yp[p2] = yp[p3]; - } - p3 = p2; - nPoints = p2 + 1; //shorten array - killed = true; - } - } - } while (killed && safety > 0); - } - - void drawRubberBand(int sx, int sy) { - double oxd = offScreenXD(sx); - double oyd = offScreenYD(sy); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - int x1, y1, x2, y2; - if (xpf!=null) { - x1 = (int)xpf[nPoints-2]+x; - y1 = (int)ypf[nPoints-2]+y; - x2 = (int)xpf[nPoints-1]+x; - y2 = (int)ypf[nPoints-1]+y; - } else { - x1 = xp[nPoints-2]+x; - y1 = yp[nPoints-2]+y; - x2 = xp[nPoints-1]+x; - y2 = yp[nPoints-1]+y; - } - int xmin=Integer.MAX_VALUE, ymin=Integer.MAX_VALUE, xmax=0, ymax=0; - if (x1xmax) xmax=x1; - if (x2>xmax) xmax=x2; - if (ox>xmax) xmax=ox; - if (y1ymax) ymax=y1; - if (y2>ymax) ymax=y2; - if (oy>ymax) ymax=oy; - int margin = boxSize; - if (ic!=null) { - double mag = ic.getMagnification(); - if (mag<1.0) margin = (int)(margin/mag); - } - margin = (int)(margin+getStrokeWidth()); - if (IJ.altKeyDown()) - margin+=20; - if (xpf!=null) { - xpf[nPoints-1] = (float)(oxd-getXBase()); - ypf[nPoints-1] = (float)(oyd-getYBase()); - } else { - xp[nPoints-1] = ox-x; - yp[nPoints-1] = oy-y; - } - if (type==POLYLINE && Prefs.splineFitLines) { - fitSpline(); - imp.draw(); - } else - imp.draw(xmin-margin, ymin-margin, (xmax-xmin)+margin*2, (ymax-ymin)+margin*2); - } - - void finishPolygon() { - if (xpf!=null) { - double xbase0 = getXBase(); - double ybase0 = getYBase(); - FloatPolygon poly = new FloatPolygon(xpf, ypf, nPoints); - bounds = poly.getFloatBounds(); - for (int i=0; i Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - - if (clipboard!=null) return; - - int ox = offScreenX(sx); - int oy = offScreenY(sy); - if (xpf!=null) { - xpf[activeHandle] = (float)(offScreenXD(sx)-getXBase()); - ypf[activeHandle] = (float)(offScreenYD(sy)-getYBase()); - } else { - xp[activeHandle] = ox-x; - yp[activeHandle] = oy-y; - } - if (xSpline!=null) { - fitSpline(splinePoints); - imp.draw(); - } else { - if (!subPixelResolution() || (type==POINT&&nPoints==1)) - resetBoundingRect(); - if (type==POINT && width==0 && height==0) - {width=1; height=1;} - updateClipRectAndDraw(); - } - String angle = type==ANGLE?getAngleAsString():""; - IJ.showStatus(imp.getLocationAsString(ox,oy) + angle); - } - - /** After handle is moved, find clip rect and repaint. */ - void updateClipRectAndDraw() { - if (xpf!=null) { - xp = toInt(xpf, xp, nPoints); - yp = toInt(ypf, yp, nPoints); - } - int xmin=Integer.MAX_VALUE, ymin=Integer.MAX_VALUE, xmax=0, ymax=0; - int x2, y2; - if (activeHandle>0) - {x2=x+xp[activeHandle-1]; y2=y+yp[activeHandle-1];} - else - {x2=x+xp[nPoints-1]; y2=y+yp[nPoints-1];} - if (x2xmax) xmax = x2; - if (y2>ymax) ymax = y2; - x2=x+xp[activeHandle]; y2=y+yp[activeHandle]; - if (x2xmax) xmax = x2; - if (y2>ymax) ymax = y2; - if (activeHandlexmax) xmax = x2; - if (y2>ymax) ymax = y2; - int xmin2=xmin, ymin2=ymin, xmax2=xmax, ymax2=ymax; - if (xClipMinxmax2) xmax2 = xClipMax; - if (yClipMax>ymax2) ymax2 = yClipMax; - xClipMin=xmin; yClipMin=ymin; xClipMax=xmax; yClipMax=ymax; - double mag = ic.getMagnification(); - int handleSize = type==POINT?getHandleSize()+25:getHandleSize(); - double strokeWidth = getStrokeWidth(); - if (strokeWidth<1.0) strokeWidth=1.0; - if (handleSizexmax) xmax=xx; - yy = yp[i]; - if (yyymax) ymax=yy; - } - if (xmin!=0) { - for (int i=0; i180.0) - degrees = 360.0-degrees; - double degrees2 = Prefs.reflexAngle&&type==ANGLE?360.0-degrees:degrees; - return ", angle=" + IJ.d2s(degrees2); - } - - protected void mouseDownInHandle(int handle, int sx, int sy) { - if (state==CONSTRUCTING) - return; - int ox = offScreenX(sx); - int oy = offScreenY(sy); - double oxd = offScreenXD(sx); - double oyd = offScreenYD(sy); - if ((IJ.altKeyDown()||IJ.controlKeyDown()) && !(nPoints<=3 && type!=POINT) && !(this instanceof RotatedRectRoi)) { - deleteHandle(oxd, oyd); - return; - } else if (IJ.shiftKeyDown() && type!=POINT && !(this instanceof RotatedRectRoi)) { - addHandle(oxd, oyd); - return; - } - super.mouseDownInHandle(handle, sx, sy); //sets state, activeHandle, previousSX&Y - int m = ic!=null?(int)(10.0/ic.getMagnification()):1; - xClipMin=ox-m; yClipMin=oy-m; xClipMax=ox+m; yClipMax=oy+m; - } - - public void deleteHandle(double ox, double oy) { - if (imp==null) - return; - if (nPoints<=1) { - imp.deleteRoi(); - return; - } - boolean splineFit = xSpline!=null; - if (splineFit) - removeSplineFit(); - FloatPolygon points = getFloatPolygon(); - int pointToDelete = getClosestPoint(ox, oy, points); - if (pointToDelete>=0) { - deletePoint(pointToDelete); - if (splineFit) - fitSpline(splinePoints); - imp.draw(); - } - } - - protected void deletePoint(int index) { - if (index<0 || index>=nPoints) - return; - for (int i=index; i=maxPoints) - enlargeArrays(); - float xbase = (float)getXBase(); - float ybase = (float)getYBase(); - if (xp==null) { - xp = new int[maxPoints]; - yp = new int[maxPoints]; - } - for (int i=0; i= 0.0 || i==npoints-1) && pointsWritten < npOut) { // we have to write a new point - double fractionOverNextWrite = distanceOverNextWrite/distance; - if (distance==0) fractionOverNextWrite = 0; - xpOut[pointsWritten] = (float)(x2 - fractionOverNextWrite*dx); - ypOut[pointsWritten] = (float)(y2 - fractionOverNextWrite*dy); - distanceOverNextWrite -= step; - pointsWritten++; - } - } - return new float[][] {xpOut, ypOut, new float[] {(float)step}}; - } - - /** With segmented selections, ignore first mouse up and finalize - when user double-clicks, control-clicks or clicks in start box. */ - protected void handleMouseUp(int sx, int sy) { - if (state==MOVING) { - state = NORMAL; - return; - } - if (state==MOVING_HANDLE) { - cachedMask = null; //mask is no longer valid - state = NORMAL; - updateClipRect(); - oldX=x; oldY=y; - oldWidth=width; oldHeight=height; - if (subPixelResolution()) - resetBoundingRect(); - return; - } - if (state!=CONSTRUCTING) - return; - if (IJ.spaceBarDown()) // is user scrolling image? - return; - boolean samePoint = false; - if (xpf!=null) - samePoint = (xpf[nPoints-2]==xpf[nPoints-1] && ypf[nPoints-2]==ypf[nPoints-1]); - else - samePoint = (xp[nPoints-2]==xp[nPoints-1] && yp[nPoints-2]==yp[nPoints-1]); - boolean doubleClick = (System.currentTimeMillis()-mouseUpTime)<=300; - int size = boxSize+2; - int size2 = boxSize/2 +1; - Rectangle biggerStartBox = new Rectangle(screenXD(startXD)-5, screenYD(startYD)-5, 10, 10); - if (nPoints>2 && (biggerStartBox.contains(sx, sy) - || (offScreenXD(sx)==startXD && offScreenYD(sy)==startYD) - || (samePoint && doubleClick))) { - boolean okayToFinish = true; - if (type==POLYGON && samePoint && doubleClick && nPoints>25) { - okayToFinish = IJ.showMessageWithCancel("Polygon Tool", "Complete the selection?"); - } - if (okayToFinish) { - nPoints--; - addOffset(); - finishPolygon(); - return; - } - } else if (!samePoint) { - mouseUpTime = System.currentTimeMillis(); - if (type==ANGLE && nPoints==3) { - addOffset(); - finishPolygon(); - return; - } - //add point to polygon - if (xpf!=null) { - xpf[nPoints] = xpf[nPoints-1]; - ypf[nPoints] = ypf[nPoints-1]; - nPoints++; - if (nPoints==xpf.length) - enlargeArrays(); - } else { - xp[nPoints] = xp[nPoints-1]; - yp[nPoints] = yp[nPoints-1]; - nPoints++; - if (nPoints==xp.length) - enlargeArrays(); - } - if (constrain) { // this point was constrained in 90deg steps; correct coordinates - int dx = sx - previousSX; - int dy = sy - previousSY; - if (Math.abs(dx) > Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - previousSX = sx; //save for constraining next line if desired - previousSY = sy; - notifyListeners(RoiListener.EXTENDED); - } - } - - protected void addOffset() { - if (xpf!=null) { - float xbase = (float)getXBase(); - float ybase = (float)getYBase(); - for (int i=0; i=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) { - handle = i; - break; - } - } - return handle; - } - - public ImageProcessor getMask() { - ImageProcessor mask = cachedMask; - if (mask!=null && mask.getPixels()!=null - && mask.getWidth()==width && mask.getHeight()==height) - return mask; - PolygonFiller pf = new PolygonFiller(); - if (xSpline!=null) - pf.setPolygon(xSpline, ySpline, splinePoints, getXBase()-x, getYBase()-y); - else if (xpf!=null) - pf.setPolygon(xpf, ypf, nPoints, getXBase()-x, getYBase()-y); - else - pf.setPolygon(xp, yp, nPoints); - mask = pf.getMask(width, height); - cachedMask = mask; - return mask; - } - - /** Returns the length of this line selection after - smoothing using a 3-point running average.*/ - double getSmoothedLineLength(ImagePlus imp) { - if (subPixelResolution() && xpf!=null) - return getFloatSmoothedLineLength(imp); - double length = 0.0; - double w2 = 1.0; - double h2 = 1.0; - double dx, dy; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - w2 = cal.pixelWidth*cal.pixelWidth; - h2 = cal.pixelHeight*cal.pixelHeight; - } - dx = (xp[0]+xp[1]+xp[2])/3.0-xp[0]; - dy = (yp[0]+yp[1]+yp[2])/3.0-yp[0]; - length += Math.sqrt(dx*dx*w2+dy*dy*h2); - for (int i=1; i1 || !corner) { - corner = true; - nCorners++; - } else - corner = false; - dx1 = dx2; - dy1 = dy2; - side1 = side2; - } - double w=1.0,h=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - w = cal.pixelWidth; - h = cal.pixelHeight; - } - return sumdx*w+sumdy*h-(nCorners*((w+h)-Math.sqrt(w*w+h*h))); - } - - /** Returns the perimeter (for ROIs) or length (for lines).*/ - public double getLength() { - return getLength(imp); - } - - public double getUncalibratedLength() { - return getLength(null); - } - - /** Returns the perimeter (for ROIs) or length (for lines), using calibration if imp is not null */ - double getLength(ImagePlus imp) { - if (isTraced()) - return getTracedPerimeter(imp); - - if (nPoints>2) { - if (type==FREEROI) - return getSmoothedPerimeter(imp); - else if (type==FREELINE && !(width==0 || height==0)) - return getSmoothedLineLength(imp); - } - - boolean closeShape = isArea(); - if (xSpline!=null) - return getLength(xSpline, ySpline, splinePoints, closeShape, imp); - else if (xpf!=null) - return getLength(xpf, ypf, nPoints, closeShape, imp); - else - return getLength(xp, yp, nPoints, closeShape, imp); - } - - /** Returns 'true' if this ROI was created using - * the wand tool or the particle analyzer. - */ - private boolean isTraced() { - if (type==TRACED_ROI) - return true; - else if (type!=POLYGON || (this instanceof RotatedRectRoi)) - return false; - else if (xp==null) { - if (xpf==null) - return false; - for (int i=0; i "+newSize); - maxPoints = newSize; - } - - public void setLocation(double x, double y) { - super.setLocation(x, y); - if ((int)x!=x || (int)y!=y) - enableSubPixelResolution(); - } - - public void enableSubPixelResolution() { - super.enableSubPixelResolution(); - if (xpf==null && xp!=null) { - xpf = toFloat(xp); - ypf = toFloat(yp); - } - } - - public String getDebugInfo() { - String s = "ROI Debug Properties\n"; - s += " bounds: "+bounds+"\n"; - s += " x,y,w,h: "+x+","+y+","+width+","+height+"\n"; - if (xpf!=null && xpf.length>0) - s += " xpf[0],ypf[0]: "+xpf[0]+","+ypf[0]+"\n"; - return s; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ProfilePlot.java b/com.eco.bio7.image/src/ij/gui/ProfilePlot.java deleted file mode 100644 index 1bc063da9..000000000 --- a/com.eco.bio7.image/src/ij/gui/ProfilePlot.java +++ /dev/null @@ -1,340 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.util.ArrayList; -import ij.*; -import ij.process.*; -import ij.util.*; -import ij.measure.*; -import ij.plugin.Straightener; - -/** Creates a density profile plot of a line or rectangular selection. */ -public class ProfilePlot { - - static final int MIN_WIDTH = 350; - static final double ASPECT_RATIO = 0.5; - private double min, max; - private boolean minAndMaxCalculated; - private static double fixedMin; - private static double fixedMax; - - protected ImagePlus imp; - protected double[] profile; - protected double magnification; - protected double xInc; - protected String units; - protected String yLabel; - protected float[] xValues; - - - public ProfilePlot() { - } - - /** Based on the current line or rectangular selection, - * creates a profile plot that can be retrieved using - * the getPlot() method. - */ - public ProfilePlot(ImagePlus imp) { - this(imp, false); - } - - /** Based on the current rectangular selection, - * creates profile plot, which is a vertical if - * verticalPlot is 'true'. Use the getPlot() method - * to retrieve the plot. - */ - public ProfilePlot(ImagePlus imp, boolean verticalPlot) { - this.imp = imp; - boolean averageHorizontally = verticalPlot; - Roi roi = imp.getRoi(); - if (roi==null) { - IJ.error("Profile Plot", "Selection required."); - return; - } - int roiType = roi.getType(); - boolean rotatedRect = roi!=null && (roi instanceof RotatedRectRoi); - if (!(roi.isLine()||roiType==Roi.RECTANGLE||rotatedRect)) { - IJ.error("Line or rectangular selection required."); - return; - } - if (rotatedRect) { - double[] p = ((RotatedRectRoi)roi).getParams(); - roi = new Line(p[0], p[1], p[2], p[3]); - roi.setStrokeWidth(p[4]); - roi.setImage(imp); - roiType = Roi.LINE; - } - Calibration cal = imp.getCalibration(); - xInc = cal.pixelWidth; - units = cal.getUnits(); - yLabel = cal.getValueUnit(); - ImageProcessor ip = imp.getProcessor(); - if (roiType==Roi.LINE) - profile = getStraightLineProfile(roi, cal, ip); - else if (roiType==Roi.POLYLINE || roiType==Roi.FREELINE) { - int lineWidth = (int)Math.round(roi.getStrokeWidth()); - if (lineWidth<=1) - profile = getIrregularProfile(roi, ip, cal); - else - profile = getWideLineProfile(imp, lineWidth); - } else if (averageHorizontally) - profile = getRowAverageProfile(roi.getBounds(), cal, ip); - else - profile = getColumnAverageProfile(roi.getBounds(), ip); - ip.setCalibrationTable(null); - ImageCanvas ic = imp.getCanvas(); - if (ic!=null) - magnification = ic.getMagnification(); - else - magnification = 1.0; - } - - /** Returns the size of the plot that createWindow() creates. */ - public Dimension getPlotSize() { - if (profile==null) return null; - int width = (int)(profile.length*magnification); - int height = (int)(width*ASPECT_RATIO); - if (widthmaxWidth) { - width = maxWidth; - height = (int)(width*ASPECT_RATIO); - } - return new Dimension(width, height); - } - - /** Displays this profile plot in a window. */ - public void createWindow() { - Plot plot = getPlot(); - if (plot!=null) - plot.show(); - } - - /** Returns the profile plot as a Plot object. */ - public Plot getPlot() { - if (profile==null) - return null; - String xLabel = "Distance ("+units+")"; - int n = profile.length; - if (xValues==null) { - xValues = new float[n]; - for (int i=0; i0 && (title.length()-index)<=5) - title = title.substring(0, index); - return title; - } - - /** Returns the profile plot data. */ - public double[] getProfile() { - return profile; - } - - /** Returns the calculated minimum value. */ - public double getMin() { - if (!minAndMaxCalculated) - findMinAndMax(); - return min; - } - - /** Returns the calculated maximum value. */ - public double getMax() { - if (!minAndMaxCalculated) - findMinAndMax(); - return max; - } - - /** Sets the y-axis min and max. Specify (0,0) to autoscale. */ - public static void setMinAndMax(double min, double max) { - fixedMin = min; - fixedMax = max; - IJ.register(ProfilePlot.class); - } - - /** Returns the profile plot y-axis min. Auto-scaling is used if min=max=0. */ - public static double getFixedMin() { - return fixedMin; - } - - /** Returns the profile plot y-axis max. Auto-scaling is used if min=max=0. */ - public static double getFixedMax() { - return fixedMax; - } - - double[] getStraightLineProfile(Roi roi, Calibration cal, ImageProcessor ip) { - ip.setInterpolate(PlotWindow.interpolate); - Line line = (Line)roi; - double[] values = line.getPixels(); - if (values==null) return null; - if (cal!=null && cal.pixelWidth!=cal.pixelHeight) { - FloatPolygon p = line.getFloatPoints(); - double dx = p.xpoints[1] - p.xpoints[0]; - double dy = p.ypoints[1] - p.ypoints[0]; - double pixelLength = Math.sqrt(dx*dx + dy*dy); - dx = cal.pixelWidth*dx; - dy = cal.pixelHeight*dy; - double calibratedLength = Math.sqrt(dx*dx + dy*dy); - xInc = calibratedLength * 1.0/pixelLength; - } - return values; - } - - double[] getRowAverageProfile(Rectangle rect, Calibration cal, ImageProcessor ip) { - double[] profile = new double[rect.height]; - int[] counts = new int[rect.height]; - double[] aLine; - ip.setInterpolate(false); - for (int x=rect.x; xsubpixel resolution), - * the line coordinates are interpreted as the roi line shown at high zoom level, - * i.e., integer (x,y) is at the top left corner of pixel (x,y). - * Thus, the coordinates of the pixel center are taken as (x+0.5, y+0.5). - * If subpixel resolution if off, the coordinates of the pixel centers are taken - * as integer (x,y). */ - double[] getIrregularProfile(Roi roi, ImageProcessor ip, Calibration cal) { - boolean interpolate = PlotWindow.interpolate; - boolean calcXValues = cal!=null && cal.pixelWidth!=cal.pixelHeight; - FloatPolygon p = roi.getFloatPolygon(); - int n = p.npoints; - float[] xpoints = p.xpoints; - float[] ypoints = p.ypoints; - ArrayList values = new ArrayList(); - int n2; - double inc = 0.01; - double distance=0.0, distance2=0.0, dx=0.0, dy=0.0, xinc, yinc; - double x, y, lastx=0.0, lasty=0.0, x1, y1, x2=xpoints[0], y2=ypoints[0]; - double value; - for (int i=1; i=1.0-inc/2.0) { - if (interpolate) - value = ip.getInterpolatedValue(x, y); - else - value = ip.getPixelValue((int)Math.round(x), (int)Math.round(y)); - values.add(Double.valueOf(value)); - lastx=x; lasty=y; - } - x += xinc; - y += yinc; - } while (--n2>0); - } - double[] values2 = new double[values.size()]; - for (int i=0; imax) - max = value; - } - this.min = min; - this.max = max; - } - - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/ProgressBar.java b/com.eco.bio7.image/src/ij/gui/ProgressBar.java deleted file mode 100644 index 87e7cfd9f..000000000 --- a/com.eco.bio7.image/src/ij/gui/ProgressBar.java +++ /dev/null @@ -1,174 +0,0 @@ -package ij.gui; - -import ij.IJ; -import ij.ImageJ; -import ij.macro.Interpreter; - -import java.awt.*; -import java.awt.image.*; - -import javax.swing.JPanel; - -/** - * This is the progress bar that is displayed in the lower right hand corner of - * the ImageJ window. Use one of the static IJ.showProgress() methods to display - * and update the progress bar. - */ -public class ProgressBar extends JPanel { - public static final int WIDTH = 120; - public static final int HEIGHT = 20; - private int canvasWidth, canvasHeight; - private int x, y, width, height; - private long lastTime = 0; - private boolean showBar; - private boolean batchMode; - - private Color barColor = Color.gray; - private Color fillColor = new Color(204, 204, 255); - private Color backgroundColor = ImageJ.getSystemColour();// Changed for Bio7! - private Color frameBrighter = backgroundColor.brighter(); - private Color frameDarker = backgroundColor.darker(); - private boolean dualDisplay = false; - private double slowX = 0.0;// box - private double fastX = 0.0;// dot - - /** - * This constructor is called once by ImageJ at startup. - */ - public ProgressBar(int canvasWidth, int canvasHeight) { - init(canvasWidth, canvasHeight); - } - - public void init(int canvasWidth, int canvasHeight) { - this.canvasWidth = canvasWidth; - this.canvasHeight = canvasHeight; - x = 3; - y = 5; - width = canvasWidth - 8; - height = canvasHeight - 7; - /* Changed for Bio7! */ - this.setBackground(ImageJ.getSystemColour()); - } - - void fill3DRect(Graphics g, int x, int y, int width, int height) { - g.setColor(fillColor); - g.fillRect(x + 1, y + 1, width - 2, height - 2); - g.setColor(frameDarker); - g.drawLine(x, y, x, y + height); - g.drawLine(x + 1, y, x + width - 1, y); - g.setColor(frameBrighter); - g.drawLine(x + 1, y + height, x + width, y + height); - g.drawLine(x + width, y, x + width, y + height - 1); - } - - /** - * Updates the progress bar, where abs(progress) should run from 0 to 1. If - * abs(
- * This class is most helpful to applications which create new AWT/Swing windows (e.g. dialogs) rather - * than those which embed AWT/Swing components in SWT windows. For support specific to embedding - * AWT/Swing components see {@link EmbeddedSwingComposite}. - *
- * There is at most one instance of this class per SWT - * {@link org.eclipse.swt.widgets.Display Display}. In almost all applications - * this means that there is exactly one instance for the entire application. In fact, the - * current implementation always limits the number of instances to exactly one. - *
- * An instance of this class can be obtained with the static - * {@link #getInstance(Display)} method. -*/ -public final class AwtEnvironment { - // TODO: add pop-up dismissal and font synchronization support to this level? - - private static final String GTK_LOOK_AND_FEEL_NAME = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; //$NON-NLS-1$ - - private static AwtEnvironment instance = null; - private static boolean isLookAndFeelInitialized = false; - - private final Display display; - private final AwtDialogListener dialogListener; - - /** - * Returns the single instance of AwtEnvironment for the given display. On - * the first call to this method, the necessary initialization to allow - * AWT/Swing code to run properly within an Eclipse application is done. - * This initialization includes setting the approprite look and feel and - * registering the necessary listeners to ensure proper behavior of modal - * dialogs. - *
- * The first call to this method must occur before any AWT/Swing APIs are - * called. - *
- * The current implementation limits the number of instances of - * AwtEnvironment to one. If this method is called with a display different - * to one used on a previous call, {@link UnsupportedOperationException} is - * thrown. - * - * @param display - * the non-null SWT display - * @return the AWT environment - * @exception IllegalArgumentException - *
- * This method is useful for displayng modal AWT/Swing dialogs from the SWT - * event thread. The modal AWT/Swing dialog will always block input across - * the whole application, but not until it appears. By calling this method, - * it is guaranteed that SWT input is blocked immediately, even before the - * AWT/Swing dialog appears. - *
- * To avoid unnecessary flicker, AWT/Swing dialogs should have their parent - * set to a frame returned by {@link #createDialogParentFrame()}. - *
- * This method must be called from the SWT event thread. - * - * @param runnable - * the code to schedule on the AWT event thread - * @exception IllegalArgumentException - *
- * This method must be called from the SWT event thread. There must be an active - * shell associated with the environment's display. - *
- * The created frame is a non-visible child of the active shell and will be disposed when that shell - * is disposed. - *
- * See {@link #createDialogParentFrame(Shell)} for more details. - * - * @return a {@link java.awt.Frame} to be used for parenting dialogs - * @exception SWTException - *
- * The created frame is a non-visible child of the given shell and will be disposed when that shell - * is disposed. - *
- * This method is useful for creating a frame to parent any AWT/Swing - * dialogs created for use inside a SWT application. A modal AWT/Swing - * dialogs will flicker less if its parent is set to the returned frame - * rather than to null or to an independently created {@link java.awt.Frame}. - * - * @return a {@link java.awt.Frame} to be used for parenting dialogs - * @exception SWTException - *
- * If, rather than embedding Swing components, you are integrating with Swing by opening - * Swing dialogs, see the {@link AwtEnvironment} class. - *
- * This is an abstract that is normally used by extending it and implementing the {@link #createSwingComponent()} method. For example, - *
- * embeddedComposite = new EmbeddedSwingComposite(parent, SWT.NONE) { - * protected JComponent createSwingComponent() { - * scrollPane = new JScrollPane(); - * table = new JTable(); - * scrollPane.setViewportView(table); - * return scrollPane; - * } - * }; - * embeddedComposite.populate(); - *
- * The Swing component is created inside a standard Swing containment hierarchy, rooted in - * a {@link javax.swing.RootPaneContainer}. The root pane container is placed inside an AWT frame, as - * returned by {@link org.eclipse.swt.awt.SWT_AWT#new_Frame(Composite)} - *
- * Note: When you mix components from Swing/AWT and SWT toolkits, there will be two UI event threads, - * one for AWT, one for SWT. Most SWT APIs require that you call them from the SWT thread. Swing - * has similar restrictions though it does not enforce them as much as SWT. - *
- * Applications need to be aware of the current thread, and, where necessary, schedule tasks to run - * on another thread. This has always been required in the pure Swing or SWT environments, but when - * mixing Swing and SWT, more of this scheduling will be necessary. - *
- * To schedule work on the AWT event - * thread, you can use: - *
- * (or similar methods in {@link java.awt.EventQueue}) - *
- * To schedule work on the SWT event thread, use: - *
- * This method must be called from the SWT event thread. - *
- * The style value is either one of the style constants defined in - * class SWT which is applicable to instances of this - * class, or must be built by bitwise OR'ing together - * (that is, using the int "|" operator) two or more - * of those SWT style constants. The class description - * lists the style constants that are applicable to the class. - * Style bits are also inherited from superclasses. - *
SWT
int
- * The styles SWT.EMBEDDED and SWT.NO_BACKGROUND will be added - * to the specified style. Usually, no other style bits are needed. - * - * @param parent a widget which will be the parent of the new instance (cannot be null) - * @param style the style of widget to construct - * - * @exception IllegalArgumentException
- * This method must be called from the - * SWT event thread. - *
- * The Swing component will be created by calling {@link #createSwingComponent()}. The creation is - * scheduled asynchronously on the AWT event thread. This method does not wait for completion of this - * asynchronous task, so it may return before createSwingComponent() is complete. - *
- * The Swing component is created inside a standard Swing containment hierarchy, rooted in - * a {@link javax.swing.RootPaneContainer}. Clients can override {@link #addRootPaneContainer(Frame)} - * to provide their own root pane container implementation. - *
- * This method can be called multiple times for a single instance. If an embedded frame exists from - * a previous call, it is disposed. - * - * @exception SWTException
- * Implement this method to provide the Swing component that will be shown inside this composite. - * The returned component will be added to the Swing content pane. At least one component must - * be created by this method; null is not a valid return value. - * - * @return a non-null Swing component - */ - protected abstract JComponent createSwingComponent(); - - /** - * Adds a root pane container to the embedded AWT frame. Override this to provide your own - * {@link javax.swing.RootPaneContainer} implementation. In most cases, it is not necessary - * to override this method. - *
- * This method is called from the AWT event thread. - *
- * If you are defining your own root pane container, make sure that there is at least one - * heavyweight (AWT) component in the frame's containment hierarchy; otherwise, event - * processing will not work correctly. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4982522 - * for more information. - * - * @param frame the frame to which the root pane container is added - * @return a non-null Swing component - */ - protected RootPaneContainer addRootPaneContainer(Frame frame) { - assert EventQueue.isDispatchThread(); // On AWT event thread - assert frame != null; - - // It is important to set up the proper top level components in the frame: - // 1) For Swing to work properly, Sun documents that there must be an implementor of - // javax.swing.RootPaneContainer at the top of the component hierarchy. - // 2) For proper event handling there must be a heavyweight - // an AWT frame must contain a heavyweight component (see - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4982522) - // 3) The Swing implementation further narrows the options by expecting that the - // top of the hierarchy be a JFrame, JDialog, JWindow, or JApplet. See javax.swing.PopupFactory. - // All this drives the choice of JApplet for the top level Swing component. It is the - // only single component that satisfies all the above. This does not imply that - // we have a true applet; in particular, there is no notion of an applet lifecycle in this - // context. - JApplet applet = new JApplet(); - - // In JRE 1.4, the JApplet makes itself a focus cycle root. This - // interferes with the focus handling installed on the parent frame, so - // change it back to a non-root here. - // TODO: consider moving the focus policy from the Frame down to the JApplet - applet.setFocusCycleRoot(false); - - frame.add(applet); - - return applet; - } - - /** - * Performs custom updates to newly set fonts. This method is called whenever a change - * to the system font through the system settings (i.e. control panel) is detected. - *
- * In most cases it is not necessary to override this method. Normally, the implementation - * of this class will automatically propogate font changes to the embedded Swing components - * through Swing's Look and Feel support. However, if additional - * special processing is necessary, it can be done inside this method. - * - * @param newFont New AWT font - */ - protected void updateAwtFont(java.awt.Font newFont) { - } - - /** - * Returns the embedded AWT frame. The returned frame is the root of the AWT containment - * hierarchy for the embedded Swing component. This method can be called from - * any thread. - * - * @return the embedded frame - */ - public Frame getFrame() { - // Intentionally leaving out checkWidget() call. This may need to be called from within user's - // createSwingComponent() method. Accessing from a non-SWT thread is OK, but we still check - // for disposal - if (getDisplay() == null || isDisposed()) { - SWT.error(SWT.ERROR_WIDGET_DISPOSED); - } - - return (awtContext != null) ? awtContext.getFrame() : null; - } - - private void createFrame() { - assert Display.getCurrent() != null; // On SWT event thread - - // Make sure Awt environment is initialized. - AwtEnvironment.getInstance(getDisplay()); - - if (awtContext != null) { - final Frame oldFrame = awtContext.getFrame(); - // Schedule disposal of old frame on AWT thread so that there are no problems with - // already-scheduled operations that have not completed. - // Note: the implementation of Frame.dispose() would schedule the use of the AWT - // thread even if it was not done here, but it uses invokeAndWait() which is - // prone to deadlock (and not necessary for this case). - EventQueue.invokeLater(new Runnable() { - public void run() { - oldFrame.dispose(); - } - }); - } - Frame frame = SWT_AWT.new_Frame(this); - awtContext = new AwtContext(frame); - - // Glue the two frameworks together. Do this before anything is added to the frame - // so that all necessary listeners are in place. - createFocusHandlers(); - - // This listener clears garbage during resizing, making it looker much cleaner - addControlListener(new CleanResizeListener()); - } - - private void createFocusHandlers() { - assert awtContext != null; - assert Display.getCurrent() != null; // On SWT event thread - - Frame frame = awtContext.getFrame(); - awtHandler = new AwtFocusHandler(frame); - SwtFocusHandler swtHandler = new SwtFocusHandler(this); - awtHandler.setSwtHandler(swtHandler); - swtHandler.setAwtHandler(awtHandler); - - // Ensure that AWT popups are dimissed whenever a SWT menu is shown - getDisplay().addFilter(SWT.Show, menuListener); - - EmbeddedChildFocusTraversalPolicy policy = new EmbeddedChildFocusTraversalPolicy(awtHandler); - frame.setFocusTraversalPolicy(policy); - } - - private void scheduleComponentCreation() { - assert awtContext != null; - - // Create AWT/Swing components on the AWT thread. This is - // especially necessary to avoid an AWT leak bug (6411042). - final AwtContext currentContext = awtContext; - EventQueue.invokeLater(new Runnable() { - public void run() { - - RootPaneContainer container = addRootPaneContainer(currentContext.getFrame()); - JComponent swingComponent = createSwingComponent(); - currentContext.setSwingComponent(swingComponent); - container.getRootPane().getContentPane().add(swingComponent); - setComponentFont(); - } - }); - } - - private void setComponentFont() { - assert currentSystemFont != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - JComponent swingComponent = (awtContext != null) ? awtContext.getSwingComponent() : null; - if ((swingComponent != null) && !currentSystemFont.getDevice().isDisposed()) { - FontData fontData = currentSystemFont.getFontData()[0]; - - // AWT font sizes assume a 72 dpi resolution, always. The true screen resolution must be - // used to convert the platform font size into an AWT point size that matches when displayed. - int resolution = Toolkit.getDefaultToolkit().getScreenResolution(); - int awtFontSize = (int)Math.round((double)fontData.getHeight() * resolution / 72.0); - - // The style constants for SWT and AWT map exactly, and since they are int constants, they should - // never change. So, the SWT style is passed through as the AWT style. - java.awt.Font awtFont = new java.awt.Font(fontData.getName(), fontData.getStyle(), awtFontSize); - - // Update the look and feel defaults to use new font. - updateLookAndFeel(awtFont); - - // Allow subclasses to react to font change if necessary. - updateAwtFont(awtFont); - - // Allow components to update their UI based on new font - // TODO: should the update method be called on the root pane instead? - Container contentPane = swingComponent.getRootPane().getContentPane(); - SwingUtilities.updateComponentTreeUI(contentPane); - } - } - - private void updateLookAndFeel(java.awt.Font awtFont) { - assert awtFont != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // The FontUIResource class marks the font as replaceable by the look and feel - // implementation if font settings are later changed. - FontUIResource fontResource = new FontUIResource(awtFont); - - // Assign the new font to the relevant L&F font properties. These are - // the properties that are initially assigned to the system font - // under the Windows look and feel. - // TODO: It's possible that other platforms will need other assignments. - // TODO: This does not handle fonts other than the "system" font. - // Other fonts may change, and the Swing L&F may not be adjusting. - - UIManager.put("Button.font", fontResource); //$NON-NLS-1$ - UIManager.put("CheckBox.font", fontResource); //$NON-NLS-1$ - UIManager.put("ComboBox.font", fontResource); //$NON-NLS-1$ - UIManager.put("EditorPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("Label.font", fontResource); //$NON-NLS-1$ - UIManager.put("List.font", fontResource); //$NON-NLS-1$ - UIManager.put("Panel.font", fontResource); //$NON-NLS-1$ - UIManager.put("ProgressBar.font", fontResource); //$NON-NLS-1$ - UIManager.put("RadioButton.font", fontResource); //$NON-NLS-1$ - UIManager.put("ScrollPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("TabbedPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("Table.font", fontResource); //$NON-NLS-1$ - UIManager.put("TableHeader.font", fontResource); //$NON-NLS-1$ - UIManager.put("TextField.font", fontResource); //$NON-NLS-1$ - UIManager.put("TextPane.font", fontResource); //$NON-NLS-1$ - UIManager.put("TitledBorder.font", fontResource); //$NON-NLS-1$ - UIManager.put("ToggleButton.font", fontResource); //$NON-NLS-1$ - UIManager.put("TreeFont.font", fontResource); //$NON-NLS-1$ - UIManager.put("ViewportFont.font", fontResource); //$NON-NLS-1$ - } - - private void handleSettingsChange() { - Font newFont = getDisplay().getSystemFont(); - if (!newFont.equals(currentSystemFont)) { - currentSystemFont = newFont; - EventQueue.invokeLater(new Runnable() { - public void run() { - setComponentFont(); - } - }); - } - } - - private boolean isFocusable() { - if (awtContext == null) { - return false; - } - JComponent swingComponent = awtContext.getSwingComponent(); - return (swingComponent != null) && swingComponent.isFocusable(); - } - - /* (non-Javadoc) - * @see org.eclipse.swt.widgets.Control#setFocus() - */ - public boolean setFocus() { - checkWidget(); - - if (!isFocusable()) { - return false; - } - return super.setFocus(); - } - - /* (non-Javadoc) - * @see org.eclipse.swt.widgets.Control#forceFocus() - */ - public boolean forceFocus() { - checkWidget(); - - if (!isFocusable()) { - return false; - } - return super.forceFocus(); - } - - /* (non-Javadoc) - * @see org.eclipse.swt.widgets.Widget#dispose() - */ - public void dispose() { - if (!isDisposed()) { - getDisplay().removeListener(SWT.Settings, settingsListener); - getDisplay().removeFilter(SWT.Show, menuListener); - super.dispose(); - } - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/Platform.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/Platform.java deleted file mode 100644 index 0c511ca97..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/Platform.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import org.eclipse.swt.SWT; - -class Platform { - private static String platformString = SWT.getPlatform(); - - // prevent instantiation - private Platform() { - } - - public static boolean isWin32() { - return "win32".equals(platformString); //$NON-NLS-1$ - } - - public static boolean isGtk() { - return "gtk".equals(platformString); //$NON-NLS-1$ - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/RecursiveContainerListener.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/RecursiveContainerListener.java deleted file mode 100644 index cd9ddd12a..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/RecursiveContainerListener.java +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import java.awt.Component; -import java.awt.Container; -import java.awt.EventQueue; -import java.awt.event.ContainerEvent; -import java.awt.event.ContainerListener; - -class RecursiveContainerListener implements ContainerListener { - private final ContainerListener listener; - - RecursiveContainerListener(ContainerListener listener) { - assert listener != null; - - this.listener = listener; - } - - private void handleAdd(Container source, Component c) { - assert source != null; - assert c != null; - assert listener != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("Listening to: " + c); - listener.componentAdded(new ContainerEvent(source, ContainerEvent.COMPONENT_ADDED, c)); - if (c instanceof Container) { - ((Container)c).addContainerListener(this); - } - } - - private void handleRemove(Container source, Component c) { - assert source != null; - assert c != null; - assert listener != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - // System.out.println("Stopped Listening to: " + c); - listener.componentRemoved(new ContainerEvent(source, ContainerEvent.COMPONENT_REMOVED, c)); - if (c instanceof Container) { - ((Container)c).removeContainerListener(this); - } - } - - private void handleAllAdds(Container source, Component child) { - assert source != null; - assert child != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - if (child instanceof Container) { - Container container = (Container)child; - Component[] children = container.getComponents(); - for (int i = 0; i < children.length; i++) { - handleAllAdds(container, children[i]); - } - } - handleAdd(source, child); - } - - private void handleAllRemoves(Container source, Component child) { - assert source != null; - assert child != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - if (child instanceof Container) { - Container container = (Container)child; - Component[] children = container.getComponents(); - for (int i = 0; i < children.length; i++) { - handleAllRemoves(container, children[i]); - } - } - handleRemove(source, child); - - } - - public void componentAdded(ContainerEvent e) { - assert e != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - Container source = (Container)e.getSource(); - handleAllAdds(source, e.getChild()); - } - - public void componentRemoved(ContainerEvent e) { - assert e != null; - assert EventQueue.isDispatchThread(); // On AWT event thread - - Container source = (Container)e.getSource(); - handleAllRemoves(source, e.getChild()); - } -} - diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtFocusHandler.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtFocusHandler.java deleted file mode 100644 index 055386166..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtFocusHandler.java +++ /dev/null @@ -1,153 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import java.awt.EventQueue; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - -public class SwtFocusHandler implements FocusListener, KeyListener { - - private final Composite composite; - private final Display display; - private AwtFocusHandler awtHandler; - - public SwtFocusHandler(Composite composite) { - assert composite != null; - assert Display.getCurrent() != null; // On SWT event thread - - this.composite = composite; - display = composite.getDisplay(); - composite.addFocusListener(this); - composite.addKeyListener(this); - } - - void setAwtHandler(AwtFocusHandler handler) { - assert handler != null; - assert awtHandler == null; // this method is meant to be called once - assert composite != null; - assert Display.getCurrent() != null; // On SWT event thread - - awtHandler = handler; - - // Dismiss Swing popups when the main window is moved. (It would be - // better to dismiss popups whenever the titlebar is clicked, but - // there does not seem to be a way.) - final ControlAdapter controlAdapter = new ControlAdapter() { - public void controlMoved(ControlEvent e) { - assert awtHandler != null; - awtHandler.postHidePopups(); - } - }; - final Shell shell = composite.getShell(); - shell.addControlListener(controlAdapter); - - // Cleanup listeners on dispose - composite.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - shell.removeControlListener(controlAdapter); - } - }); - } - - void gainFocusNext() { - traverse(SWT.TRAVERSE_TAB_NEXT); - } - - void gainFocusPrevious() { - traverse(SWT.TRAVERSE_TAB_PREVIOUS); - } - - private void traverse(final int traversal) { - assert composite != null; - - // Tab from the containing SWT component while - // running on the SWT thread - Runnable r = new Runnable() { - public void run() { - composite.traverse(traversal); - } - }; - display.asyncExec(r); - } - -// boolean hasFocus() { -// assert composite != null; -// -// // This will return true if the composite has focus, or if any -// // foreign (e.g. AWT) child of the composite has focus. -// if (display.isDisposed()) { -// return false; -// } -// final boolean[] result = new boolean[1]; -// display.syncExec(new Runnable() { -// public void run() { -// result[0] = (!composite.isDisposed() && -// (display.getFocusControl() == composite)); -// } -// }); -// return result[0]; -// } - - // ..................... Listener implementations - - public void focusGained(FocusEvent e) { - assert awtHandler != null; - assert Display.getCurrent() != null; // On SWT event thread - - // System.out.println("Gained: " + e.toString() + " (" + e.widget.getClass().getName() + ")"); - EventQueue.invokeLater(new Runnable() { - public void run() { - awtHandler.gainFocus(); - } - }); - } - - public void focusLost(FocusEvent e) { - // System.out.println("Lost: " + e.toString() + " (" + e.widget.getClass().getName() + ")"); - } - - public void keyPressed(KeyEvent e) { - assert Display.getCurrent() != null; // On SWT event thread - - // If the embedded swing root pane has no components to receive focus, - // then there will be cases where the parent SWT composite will keep - // focus. (For example, when tabbing into the root pane container). - // By default, in these cases, the focus is swallowed by the Composite - // and never escapes. This code allows tab and back-tab to do the - // proper traversal to other SWT components from the composite. - // TODO: other keys? - if (e.keyCode == SWT.TAB) { - // TODO: In some cases, this gobbles up all the tabs, even from AWT children. Find a more selective way. - /*if (e.stateMask == SWT.NONE) { - traverse(SWT.TRAVERSE_TAB_NEXT); - } else if (e.stateMask == SWT.SHIFT) { - traverse(SWT.TRAVERSE_TAB_PREVIOUS); - }*/ - } - } - - public void keyReleased(KeyEvent e) { - } - - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtInputBlocker.java b/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtInputBlocker.java deleted file mode 100644 index 94de23801..000000000 --- a/com.eco.bio7.image/src/com/eco/bio7/image/swtawtutil/SwtInputBlocker.java +++ /dev/null @@ -1,111 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007 SAS Institute. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * SAS Institute - initial API and implementation - *******************************************************************************/ -package com.eco.bio7.image.swtawtutil; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.FocusAdapter; -import org.eclipse.swt.events.FocusEvent; -import org.eclipse.swt.widgets.Dialog; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; - - - -class SwtInputBlocker extends Dialog { - static private SwtInputBlocker instance = null; - static private int blockCount = 0; - private Shell shell; - - private SwtInputBlocker(Shell parent) { - super(parent, SWT.NONE); - } - - private Object open() { - assert Display.getCurrent() != null; // On SWT event thread - - final Shell parent = getParent(); - shell = new Shell(parent, SWT.APPLICATION_MODAL); - shell.setSize(0, 0); - shell.addFocusListener(new FocusAdapter() { - public void focusGained(FocusEvent e) { - // On some platforms (e.g. Linux/GTK), the 0x0 shell still appears as a dot - // on the screen, so make it invisible by moving it below other windows. This - // is unnecessary under Windows and causes a flash, so only make the call when necessary. - if (Platform.isGtk()) { - shell.moveBelow(null); - } - AwtEnvironment.getInstance(shell.getDisplay()).requestAwtDialogFocus(); - } - }); - shell.open(); - - Display display = parent.getDisplay(); - while (!shell.isDisposed()) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - return null; - } - - private void close() { - assert shell != null; - - shell.dispose(); - } - - static void unblock() { - assert blockCount >= 0; - assert Display.getCurrent() != null; // On SWT event thread - - - // System.out.println("Deleting SWT blocker"); - if (blockCount == 0) { - return; - } - if ((blockCount == 1) && (instance != null)) { - instance.close(); - instance = null; - } - blockCount--; - } - - static void block() { - assert blockCount >= 0; - - // System.out.println("Creating SWT blocker"); - final Display display = Display.getCurrent(); - assert display != null; // On SWT event thread - - blockCount++; - if (blockCount == 1) { - assert instance == null; // should be no existing blocker - - // get a shell to parent the blocking dialog - Shell shell = AwtEnvironment.getInstance(display).getShell(); - - // If there is a shell to block, block input now. If there are no shells, - // then there is no input to block. In the case of no shells, we are not - // protecting against a shell that might get created later. This is a rare - // enough case to skip, at least for now. In the future, a listener could be - // added to cover it. - // TODO: if (shell==null) add listener to block shells created later? - // - // Block is implemented with a hidden modal dialog. Using setEnabled(false) is another option, but - // on some platforms that will grey the disabled controls. - if (shell != null) { - instance = new SwtInputBlocker(shell); - instance.open(); - } - } - } - -} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/Thumbnail.java b/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/Thumbnail.java index a354c6094..93ac402e0 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/Thumbnail.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/Thumbnail.java @@ -31,7 +31,7 @@ public class Thumbnail extends Figure implements UpdateListener { // Bug on Mac - images are cached - private static final boolean useMacFix = Util.isMac() && com.eco.bio7.image.Util.compareOSVersion("10.14") >= 0;; + private static final boolean useMacFix = Util.isMac() && com.eco.bio7.image.ui.Util.compareOSVersion("10.14") >= 0;; // Hack for Mac Mojave drawing issue diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/ThumbnailsView.java b/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/ThumbnailsView.java index 504a55804..72aa19cba 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/ThumbnailsView.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/thumbs/ThumbnailsView.java @@ -27,7 +27,6 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import javax.swing.JPanel; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -72,8 +71,8 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.Util; +import com.eco.bio7.image.ui.CanvasView; +import com.eco.bio7.image.ui.Util; import ij.IJ; import ij.ImagePlus; import ij.ImageStack; @@ -421,11 +420,10 @@ public void run() { } else if (fileExtension.equals(".lut")) { ImagePlus plus = null; ImageData imageData = null; - Opener.setErrorMessage(false); setThumbSize(); String pathParent = Util.getImageJPath().replace("\\", "/"); /* Apply a LUT on the example image. Will be scaled afterwards! */ - plus = IJ.openImage(pathParent + "/src/images/lut200.tif"); + plus = openSilent(pathParent + "/src/images/lut200.tif"); if (plus != null) { LUT lut = Opener.openLut(files[i].getAbsolutePath()); @@ -460,7 +458,6 @@ public void run() { plus = null; imageData = null; - Opener.setErrorMessage(true); /* We handle *.zip files extra to also detect ROI Sets! */ } else if (fileExtension.equals(".zip")) { boolean zipRoi = false; @@ -485,8 +482,7 @@ public void run() { } } else { - Opener.setErrorMessage(false); - ImagePlus plus = IJ.openImage(files[i].getAbsolutePath()); + ImagePlus plus = openSilent(files[i].getAbsolutePath()); createFromImagePlus(plus, fileExtension, files[i]); } } @@ -495,16 +491,14 @@ public void run() { * stack! */ else if (fileExtension.equals(".tif") || fileExtension.equals(".TIF") || fileExtension.equals(".TIFF")) { - Opener.setErrorMessage(false); // ImagePlus plus = IJ.openImage(files[i].getAbsolutePath(), 1); not used since // the conversion results in a single images, no stack anymore and wrong color! - ImagePlus plus = IJ.openImage(files[i].getAbsolutePath()); + ImagePlus plus = openSilent(files[i].getAbsolutePath()); createFromImagePlus(plus, fileExtension, files[i]); } /* All other supported image types are handled here! */ else { - Opener.setErrorMessage(false); - ImagePlus plus = IJ.openImage(files[i].getAbsolutePath()); + ImagePlus plus = openSilent(files[i].getAbsolutePath()); createFromImagePlus(plus, fileExtension, files[i]); } @@ -516,7 +510,7 @@ else if (fileExtension.equals(".tif") || fileExtension.equals(".TIF") || fileExt * type! */ public void actionPerformed(ActionEvent arg0) { - if (com.eco.bio7.image.CanvasView.getCanvas_view() != null) { + if (com.eco.bio7.image.ui.CanvasView.getCanvas_view() != null) { Job job = new Job("Open...") { @Override protected IStatus run(IProgressMonitor monitor) { @@ -544,10 +538,6 @@ public void run() { } }); - JPanel current = CanvasView.getCurrent(); - if (current != null) { - current.doLayout(); - } } monitor.done(); @@ -617,8 +607,14 @@ public void run() { } + /* Opens an image without error dialogs (unsupported files are skipped)! */ + private static ImagePlus openSilent(String path) { + Opener opener = new Opener(); + opener.setSilentMode(true); + return opener.openImage(path); + } + public void createFromImagePlus(ImagePlus plus, String fileExtension, File file) { - Opener.setErrorMessage(true); ImageData imageData; Image im = null; if (plus != null) { diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/Activator.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Activator.java similarity index 94% rename from com.eco.bio7.image/src/com/eco/bio7/image/Activator.java rename to com.eco.bio7.image/src/com/eco/bio7/image/ui/Activator.java index 0553cdb43..a74e27e10 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/Activator.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Activator.java @@ -10,7 +10,7 @@ *******************************************************************************/ -package com.eco.bio7.image; +package com.eco.bio7.image.ui; import org.eclipse.ui.plugin.*; import org.eclipse.core.resources.IWorkspace; diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/Bio7ImageJ.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Bio7ImageJ.java new file mode 100644 index 000000000..b06e9155e --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Bio7ImageJ.java @@ -0,0 +1,332 @@ +/******************************************************************************* + * Copyright (c) 2007-2026 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ +package com.eco.bio7.image.ui; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.osgi.framework.Bundle; + +import ij.IJ; +import ij.ImageJ; +import ij.ImageListener; +import ij.ImagePlus; +import ij.Menus; +import ij.Prefs; +import ij.gui.ImageWindow; +import ij.swt.ImageJHost; + +/** + * Embeds SWTImageJ in Bio7. Image windows are created inside a holder composite + * which is displayed in a tab of the ImageJ-Canvas view ({@link CanvasView}) or + * in a detached view ({@link CustomDetachedImageJView}). The holder composite is + * the editor parent of the image (see {@link ImagePlus#getEditorParent()}) and + * is moved, not recreated, when an image is detached. + * + * @author M. Austenfeld + */ +public class Bio7ImageJ implements ImageJHost, ImageListener { + + private static Bio7ImageJ instance; + + /* See ij.plugin.Compiler! */ + private static final String COMPILER_TARGET_KEY = "javac.target"; + + private static final int COMPILER_TARGET = 25; + + private Bio7ImageJ() { + } + + /** + * Installs ImageJ in Bio7 (host callbacks, plugins path, ImageJ instance). Can + * be called several times. Must be called in the SWT UI thread. + */ + public static synchronized void install() { + if (instance != null) { + return; + } + instance = new Bio7ImageJ(); + setPluginsDirectory(); + addBundlesToCompilerClassPath(); + IJ.setHost(instance); + ImagePlus.addImageListener(instance); + /* F2 displays the current image in fullscreen mode (ESC closes it)! */ + Util.getDisplay().addFilter(SWT.KeyDown, Fullscreen.KEY_FILTER); + if (IJ.getInstance() == null) { + /* The ImageJ shell is never shown. Bio7 displays toolbar and menus! */ + new ImageJ(ImageJ.NO_SHOW); + } + setCompilerTarget(); + } + + /* + * SWTImageJ uses /plugins and /macros. The Bio7 + * preferences store the plugins folder itself. + */ + private static void setPluginsDirectory() { + if (System.getProperty("plugins.dir") != null) { + return; + } + IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + File plugins = new File(store.getString("PLUGINS_PATH")); + if (plugins.isDirectory() && plugins.getParentFile() != null) { + System.setProperty("plugins.dir", plugins.getParentFile().getAbsolutePath()); + } else { + System.setProperty("plugins.dir", Util.getImageJPath()); + } + } + + /* + * Plugins are compiled for Java 25 by default (SWTImageJ uses Java 8). The + * preference must be set after ImageJ has loaded the preferences and before + * the compiler class is loaded. A target selected in "Compile and Run" options + * (other than the old default 8) is kept! + */ + private static void setCompilerTarget() { + int target = (int) Prefs.get(COMPILER_TARGET_KEY, 0); + if (target == 0 || target == 8) { + Prefs.set(COMPILER_TARGET_KEY, COMPILER_TARGET); + } + } + + /* + * The ImageJ compiler (Compile and Run, Script Explorer) uses the + * "java.class.path" property which only contains the OSGi launcher. Add the + * ImageJ, SWT and Bio7 image bundles so that plugins can be compiled! + */ + private static void addBundlesToCompilerClassPath() { + Bundle self = Activator.getDefault().getBundle(); + for (Bundle bundle : self.getBundleContext().getBundles()) { + String name = bundle.getSymbolicName(); + if (name == null || !(name.startsWith("org.eclipse.swt") || bundle == self)) { + continue; + } + try { + File file = FileLocator.getBundleFile(bundle); + if (file.isDirectory()) { + /* A bundle in the workspace (development) or an unpacked bundle! */ + boolean classes = false; + for (String folder : new String[] { "bin", "target/classes" }) { + File dir = new File(file, folder); + if (dir.isDirectory()) { + Menus.addExtraClassPathDirectory(dir.getAbsolutePath()); + classes = true; + } + } + if (!classes) { + Menus.addExtraClassPathDirectory(file.getAbsolutePath()); + } + } else { + Menus.addExtraClassPathDirectory(file.getAbsolutePath()); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * Returns the holder composite of an image displayed in Bio7 or null. + */ + public static Composite getHolder(ImagePlus imp) { + if (imp == null) { + return null; + } + Composite holder = imp.getEditorParent(); + if (holder == null || holder.isDisposed()) { + return null; + } + return holder; + } + + /** + * Returns the tab of the ImageJ-Canvas view which displays the image or null + * (e.g., if the image is displayed in a detached view). Must be called in the + * SWT UI thread. + */ + public static CTabItem getTab(ImagePlus imp) { + Composite holder = getHolder(imp); + if (holder == null || CanvasView.tabFolder == null || CanvasView.tabFolder.isDisposed()) { + return null; + } + for (CTabItem item : CanvasView.tabFolder.getItems()) { + if (item.getControl() == holder) { + return item; + } + } + return null; + } + + /** + * Creates a new holder composite for an image in the given parent. + */ + static Composite createHolder(Composite parent, ImagePlus imp) { + Composite holder = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, true); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + holder.setLayout(layout); + /* Close the image if the holder is disposed (tab or view closed)! */ + holder.addDisposeListener(e -> { + ImageWindow win = imp.getWindow(); + if (win != null && !win.isClosed() && imp.getEditorParent() == holder) { + win.close(); + } + }); + return holder; + } + + @Override + public Composite getImageParent(ImagePlus imp) { + CanvasView view = CanvasView.getCanvas_view(); + if (view == null || CanvasView.tabFolder == null || CanvasView.tabFolder.isDisposed()) { + showView(CanvasView.ID); + view = CanvasView.getCanvas_view(); + } + if (view == null || CanvasView.tabFolder == null || CanvasView.tabFolder.isDisposed()) { + /* Fallback: ImageJ opens a separate shell! */ + return null; + } + return view.createImageTab(imp); + } + + @Override + public void titleChanged(ImageWindow win, String title) { + ImagePlus imp = win.getImagePlus(); + CTabItem item = getTab(imp); + if (item != null) { + item.setText(title); + return; + } + CustomDetachedImageJView detached = CustomDetachedImageJView.find(imp); + if (detached != null) { + detached.setPartName(title); + } + } + + @Override + public void toFront(ImageWindow win) { + ImagePlus imp = win.getImagePlus(); + CTabItem item = getTab(imp); + IWorkbenchPage page = getPage(); + if (item != null) { + CanvasView.tabFolder.setSelection(item); + CanvasView.getCanvas_view().tabSelected(item); + if (page != null) { + page.bringToTop(CanvasView.getCanvas_view()); + } + return; + } + CustomDetachedImageJView detached = CustomDetachedImageJView.find(imp); + if (detached != null && page != null) { + page.bringToTop(detached); + } + } + + @Override + public void showStatus(String message) { + Display display = Util.getDisplay(); + display.asyncExec(() -> { + CanvasView view = CanvasView.getCanvas_view(); + if (view != null) { + view.setstatusline(message); + } + }); + } + + @Override + public void imageOpened(ImagePlus imp) { + } + + @Override + public void imageClosed(ImagePlus imp) { + /* Remove the tab or detached view of a closed image! */ + Util.getDisplay().asyncExec(() -> { + Composite holder = getHolder(imp); + if (holder == null) { + return; + } + ImageWindow win = imp.getWindow(); + /* ImageJ also calls this if a window has been replaced (e.g., RGB to stack)! */ + if (win != null && !win.isClosed()) { + return; + } + if (Fullscreen.isFullscreen(holder)) { + Fullscreen.exit(); + } + CTabItem item = getTab(imp); + CustomDetachedImageJView detached = CustomDetachedImageJView.find(imp); + if (item != null) { + item.dispose(); + } + if (detached != null) { + IWorkbenchPage page = detached.getSite().getPage(); + page.hideView(detached); + } + if (!holder.isDisposed()) { + holder.dispose(); + } + }); + } + + @Override + public void imageUpdated(ImagePlus imp) { + /* Display the image information (size, type, etc.) in the status line! */ + Util.getDisplay().asyncExec(() -> { + CanvasView view = CanvasView.getCanvas_view(); + ImageWindow win = imp.getWindow(); + if (view != null && win != null && !win.isClosed() && ij.WindowManager.getCurrentImage() == imp) { + view.setstatusline(win.createSubtitle()); + } + }); + } + + static IWorkbenchPage getPage() { + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + if (window == null) { + IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); + if (windows.length == 0) { + return null; + } + window = windows[0]; + } + return window.getActivePage(); + } + + private static IViewPart showView(String id) { + IWorkbenchPage page = getPage(); + if (page == null) { + return null; + } + try { + return page.showView(id, null, IWorkbenchPage.VIEW_VISIBLE); + } catch (PartInitException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/CanvasView.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/CanvasView.java new file mode 100644 index 000000000..59e6d7f79 --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/CanvasView.java @@ -0,0 +1,423 @@ +/******************************************************************************* + * Copyright (c) 2004-2026 M. Austenfeld + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ + +package com.eco.bio7.image.ui; + +import java.io.File; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.StatusLineManager; +import org.eclipse.jface.action.SubContributionManager; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.custom.CTabFolder; +import org.eclipse.swt.custom.CTabFolder2Adapter; +import org.eclipse.swt.custom.CTabFolderEvent; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTarget; +import org.eclipse.swt.dnd.DropTargetAdapter; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.ViewPart; +import org.eclipse.ui.preferences.ScopedPreferenceStore; + +import com.eco.bio7.ImageJPluginActions.ImageJAnalyzeAction; +import com.eco.bio7.ImageJPluginActions.ImageJEditAction; +import com.eco.bio7.ImageJPluginActions.ImageJFileAction; +import com.eco.bio7.ImageJPluginActions.ImageJHelp; +import com.eco.bio7.ImageJPluginActions.ImageJImageAction; +import com.eco.bio7.ImageJPluginActions.ImageJPluginsAction; +import com.eco.bio7.ImageJPluginActions.ImageJProcessAction; +import com.eco.bio7.ImageJPluginActions.ImageJWindowAction; + +import ij.IJ; +import ij.ImagePlus; +import ij.WindowManager; +import ij.gui.ImageWindow; +import ij.plugin.CommandLister; +import ij.plugin.DragAndDrop; + +/** + * The ImageJ-Canvas view. Each image is displayed in a tab. The control of a + * tab is the holder composite of the image (see {@link Bio7ImageJ}) and the tab + * data is the {@link ImagePlus}. + */ +public class CanvasView extends ViewPart { + public static int insertMark = -1; + + public static final String ID = "com.eco.bio7.imagej"; + + public static Composite parent2; + + private ImageJFileAction file; + + private ImageJEditAction edit; + + private ImageJImageAction image; + + private ImageJProcessAction process; + + private ImageJAnalyzeAction analyze; + + private ImageJPluginsAction plugins; + + private ImageJWindowAction window; + + private ImageJHelp help; + + protected String[] fileList; + + protected ImagePlus plu; + + protected ImageWindow win; + + private static CanvasView canvas_view; + + public static CTabFolder tabFolder; + + public CanvasView() { + super(); + canvas_view = this; + } + + /** + * Lays out the view (kept for compatibility). + */ + public void updatePlotCanvas() { + recalculateLayout(); + } + + /** + * Lays out the view and the displayed image. + */ + public void recalculateLayout() { + Util.getDisplay().syncExec(() -> { + if (parent2 != null && !parent2.isDisposed()) { + parent2.layout(true, true); + } + }); + } + + public void layoutParent(Composite parent) { + Util.getDisplay().syncExec(() -> { + if (!parent.isDisposed()) { + parent.layout(true, true); + } + }); + } + + public void createPartControl(Composite parent) { + parent2 = parent; + /* Creates the ImageJ instance and registers Bio7 as the ImageJ host! */ + Bio7ImageJ.install(); + + parent.addDisposeListener(e -> { + /* Save the ImageJ preferences when the view is closed! */ + try { + ij.Prefs.savePreferences(); + } catch (RuntimeException ex) { + ex.printStackTrace(); + } + }); + + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "com.eco.bio7.imagej"); + + parent.addControlListener(new ControlAdapter() { + @Override + public void controlResized(final ControlEvent e) { + updatePlotDeviceSize(parent.getClientArea(), tabFolder != null && !tabFolder.isDisposed() ? tabFolder.getTabHeight() + 40 : 0); + } + }); + + file = new ImageJFileAction(); + edit = new ImageJEditAction(); + image = new ImageJImageAction(); + process = new ImageJProcessAction(); + analyze = new ImageJAnalyzeAction(); + plugins = new ImageJPluginsAction(); + window = new ImageJWindowAction(); + help = new ImageJHelp(); + + initializeToolBar(); + tabFolder = new CTabFolder(parent, SWT.TOP); + /* Get access to the ImageJ drag and drop methods! */ + DragAndDrop dragAndDrop = new DragAndDrop(); + DropTarget dt = new DropTarget(tabFolder, DND.DROP_DEFAULT | DND.DROP_MOVE | DND.DROP_COPY); + dt.setTransfer(new Transfer[] { FileTransfer.getInstance() }); + dt.addDropListener(new DropTargetAdapter() { + public void drop(DropTargetEvent event) { + FileTransfer ft = FileTransfer.getInstance(); + if (ft.isSupportedType(event.currentDataType)) { + fileList = (String[]) event.data; + Job job = new Job("Open...") { + @Override + protected IStatus run(IProgressMonitor monitor) { + monitor.beginTask("Opening...", fileList.length); + for (int i = 0; i < fileList.length; i++) { + dragAndDrop.openFile(new File(fileList[i])); + monitor.worked(1); + } + monitor.done(); + return Status.OK_STATUS; + } + }; + job.schedule(); + } + } + }); + + CommandLister hotkeys = new CommandLister(); + String[] shortcuts = hotkeys.getShortcuts(); + + tabFolder.addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + runShortcut(shortcuts, e); + } + }); + + tabFolder.setBorderVisible(true); + + tabFolder.addCTabFolder2Listener(new CTabFolder2Adapter() { + public void close(final CTabFolderEvent event) { + /* Disposing the holder closes the image (see Bio7ImageJ)! */ + Control holder = ((CTabItem) event.item).getControl(); + if (holder != null && !holder.isDisposed()) { + holder.dispose(); + } + } + }); + tabFolder.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + tabSelected((CTabItem) e.item); + } + }); + tabFolder.addMouseListener(new MouseAdapter() { + + public void mouseDown(MouseEvent mouseevent) { + CTabFolder ctab = (CTabFolder) mouseevent.widget; + if (mouseevent.count == 1) { + if (ctab.getItemCount() <= 0) { + tabFolder.setFocus(); + } else if (ctab.getSelection() != null) { + tabSelected(ctab.getSelection()); + } + } else if (mouseevent.button == 3 && mouseevent.count > 1) { + /* Detach the image of the selected tab in a view! */ + CTabItem item = ctab.getSelection(); + if (item != null && item.getData() instanceof ImagePlus) { + CustomDetachedImageJView.detach((ImagePlus) item.getData(), null); + } + } + } + }); + } + + /* + * Here we write the values in the com.eco.bio7 plugin preferences with the help + * of scoped preferences (R plots are created with the size of the view)! + */ + static void updatePlotDeviceSize(Rectangle rec, int correction) { + IPreferenceStore store = new ScopedPreferenceStore(InstanceScope.INSTANCE, "com.eco.bio7"); + String selection = store.getString("PLOT_DEVICE_SELECTION"); + String pathTo = store.getString("pathTempR"); + if (selection.equals("PLOT_IMAGEJ_DISPLAYSIZE_CAIRO")) { + store.setValue("DEVICE_DEFINITION", ".bio7Device <- function(filename = \"" + pathTo + "tempDevicePlot%05d.tiff" + "\") { tiff(filename,width = " + (rec.width - 20) + + ", height = " + (rec.height - correction) + ", type=\"cairo\")}; options(device=\".bio7Device\")"); + } else if (selection.equals("PLOT_IMAGEJ_DISPLAYSIZE")) { + store.setValue("DEVICE_DEFINITION", ".bio7Device <- function(filename = \"" + pathTo + "tempDevicePlot%05d.tiff" + "\") { tiff(filename,width = " + (rec.width - 20) + + ", height = " + (rec.height - correction) + ", units = \"px\")}; options(device=\".bio7Device\")"); + } + } + + private void runShortcut(String[] shortcuts, KeyEvent e) { + for (int i = 0; i < shortcuts.length; i++) { + String[] splitShortcut = shortcuts[i].split("\t"); + if (splitShortcut.length < 2) { + continue; + } + String key = splitShortcut[0].trim(); + if (key.equals("" + e.character)) { + IJ.doCommand(splitShortcut[1]); + } + /* Also allow the F keys for a shortcut! */ + for (int f = 1; f <= 20; f++) { + if (key.equals("F" + f) && e.keyCode == SWT.F1 + f - 1) { + IJ.doCommand(splitShortcut[1]); + } + } + } + } + + /** + * Creates a new tab for the given image and returns the holder composite in + * which the image window is created. + */ + Composite createImageTab(ImagePlus imp) { + CTabItem item = new CTabItem(tabFolder, SWT.CLOSE, Math.max(0, Math.min(insertMark + 1, tabFolder.getItemCount()))); + Composite holder = Bio7ImageJ.createHolder(tabFolder, imp); + item.setControl(holder); + item.setData(imp); + item.setText(imp.getTitle()); + tabFolder.showItem(item); + tabFolder.setSelection(item); + plu = imp; + return holder; + } + + /** + * Makes the image of the given tab the current ImageJ image. + */ + public void tabSelected(CTabItem item) { + if (item == null || !(item.getData() instanceof ImagePlus)) { + return; + } + plu = (ImagePlus) item.getData(); + win = plu.getWindow(); + if (win != null && !win.isClosed()) { + WindowManager.setTempCurrentImage(plu); + WindowManager.setCurrentWindow(win); + setstatusline(win.createSubtitle()); + } + } + + public void setstatusline(String message) { + IActionBars bars = getViewSite().getActionBars(); + bars.getStatusLineManager().setMessage(message); + } + + public void setStatusLineColor(String message, org.eclipse.swt.graphics.Color col) { + IActionBars bars = getViewSite().getActionBars(); + bars.getStatusLineManager().setMessage(message); + IStatusLineManager statusLineManager = bars.getStatusLineManager(); + if (statusLineManager instanceof SubContributionManager) { + SubContributionManager sub = (SubContributionManager) statusLineManager; + StatusLineManager parent = (StatusLineManager) sub.getParent(); + Composite composite = (Composite) parent.getControl(); + Control[] controls = composite.getChildren(); + for (Control control : controls) { + if (control instanceof CLabel) { + CLabel cLabel = (CLabel) control; + cLabel.setForeground(col); + break; + } + } + } + } + + private void initializeToolBar() { + IToolBarManager tbm = getViewSite().getActionBars().getToolBarManager(); + tbm.add(file); + tbm.add(edit); + tbm.add(image); + tbm.add(process); + tbm.add(analyze); + tbm.add(plugins); + tbm.add(window); + tbm.add(help); + /* If we have a plugin which installs a main menu item! */ + updateBio7ImageJMenu(); + } + + private static boolean isDefaultMenu(String name) { + return name.equals("File") || name.equals("Edit") || name.equals("Image") || name.equals("Process") || name.equals("Analyze") || name.equals("Plugins") || name.equals("Window") + || name.equals("Help"); + } + + /** + * Adds the additional ImageJ main menus (e.g., installed by a plugin) to the + * toolbar of the view. + */ + public static void updateBio7ImageJMenu() { + Util.getDisplay().asyncExec(() -> { + CanvasView canvasView = getCanvas_view(); + org.eclipse.swt.widgets.Menu menuBar = ij.Menus.getMenuBar(); + if (canvasView == null || menuBar == null || menuBar.isDisposed()) { + return; + } + IToolBarManager tbm = canvasView.getViewSite().getActionBars().getToolBarManager(); + for (org.eclipse.jface.action.IContributionItem item : tbm.getItems()) { + if (item.getId() != null && !isDefaultMenu(item.getId())) { + tbm.remove(item); + } + } + for (org.eclipse.swt.widgets.MenuItem item : menuBar.getItems()) { + String name = item.getText().replace("&", ""); + if (!name.isEmpty() && !isDefaultMenu(name)) { + tbm.add(new com.eco.bio7.ImageJPluginActions.ImageJExtensionAction(name)); + } + } + tbm.update(true); + }); + } + + public void setFocus() { + if (tabFolder != null && !tabFolder.isDisposed()) { + tabFolder.setFocus(); + } + } + + public void dispose() { + if (canvas_view == this) { + canvas_view = null; + } + super.dispose(); + } + + public static CanvasView getCanvas_view() { + return canvas_view; + } + + /** + * Returns the holder composite of the selected tab or null. + * + * @return the composite which embeds the selected image. + */ + public static Composite getCurrent() { + if (tabFolder == null || tabFolder.isDisposed()) { + return null; + } + Display display = tabFolder.getDisplay(); + Composite[] current = new Composite[1]; + display.syncExec(() -> { + if (!tabFolder.isDisposed() && tabFolder.getSelection() != null) { + current[0] = (Composite) tabFolder.getSelection().getControl(); + } + }); + return current[0]; + } + + public static Composite getParent2() { + return parent2; + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/CustomDetachedImageJView.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/CustomDetachedImageJView.java new file mode 100644 index 000000000..52db19be3 --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/CustomDetachedImageJView.java @@ -0,0 +1,198 @@ +/******************************************************************************* + * Copyright (c) 2007-2026 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ +package com.eco.bio7.image.ui; + +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; +import org.eclipse.e4.ui.workbench.modeling.EModelService; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.events.ControlAdapter; +import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.part.ViewPart; + +import ij.ImagePlus; +import ij.WindowManager; +import ij.gui.ImageWindow; + +/** + * A view which displays a single image detached from the ImageJ-Canvas view. + * The secondary id of the view is the ImageJ id of the image. Closing the view + * closes the image. + * + * @author Bio7 + * + */ +public class CustomDetachedImageJView extends ViewPart { + + public static final String ID = "com.eco.bio7.image.detachedImage"; + + public Composite customViewParent; + + public ImagePlus plus; + + public ImageWindow win; + + private boolean isDetached; + + public boolean isDetached() { + return isDetached; + } + + public CustomDetachedImageJView() { + } + + /* Implement to overwrite function to set name! */ + public void setPartName(String partName) { + super.setPartName(partName); + } + + public void createPartControl(Composite parent) { + PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, "com.eco.bio7.imagej"); + this.customViewParent = parent; + parent.setLayout(new FillLayout()); + parent.addControlListener(new ControlAdapter() { + @Override + public void controlResized(final ControlEvent e) { + updateDetached(); + CanvasView.updatePlotDeviceSize(parent.getClientArea(), 0); + } + }); + updateDetached(); + } + + private void updateDetached() { + isDetached = customViewParent.getShell().getText().length() == 0; + } + + public void setFocus() { + if (plus != null) { + win = plus.getWindow(); + if (win != null && !win.isClosed()) { + WindowManager.setTempCurrentImage(plus); + WindowManager.setCurrentWindow(win); + setstatusline(win.createSubtitle()); + } + } + customViewParent.setFocus(); + } + + /** + * Lays out the view and the image. + */ + public void layout() { + if (customViewParent != null && !customViewParent.isDisposed()) { + customViewParent.layout(true, true); + } + } + + /** + * Returns the detached view which displays the image or null. Must be called + * in the SWT UI thread. + */ + public static CustomDetachedImageJView find(ImagePlus imp) { + if (imp == null) { + return null; + } + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (page == null) { + return null; + } + IViewPart view = findBySecondaryId(page, Integer.toString(imp.getID())); + if (view instanceof CustomDetachedImageJView) { + return (CustomDetachedImageJView) view; + } + return null; + } + + private static IViewPart findBySecondaryId(IWorkbenchPage page, String secId) { + org.eclipse.ui.IViewReference ref = page.findViewReference(ID, secId); + return ref != null ? ref.getView(false) : null; + } + + /** + * Moves the image from its tab into a new view. + * + * @param imp the image displayed in a tab of the ImageJ-Canvas view. + * @param rec location and size of a floating (detached) view or null. + * @return the view or null. + */ + public static CustomDetachedImageJView detach(ImagePlus imp, Rectangle rec) { + CustomDetachedImageJView[] result = new CustomDetachedImageJView[1]; + Util.getDisplay().syncExec(() -> { + CTabItem item = Bio7ImageJ.getTab(imp); + Composite holder = Bio7ImageJ.getHolder(imp); + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (item == null || holder == null || page == null) { + return; + } + try { + IViewPart activated = page.showView(ID, Integer.toString(imp.getID()), IWorkbenchPage.VIEW_ACTIVATE); + if (!(activated instanceof CustomDetachedImageJView)) { + return; + } + CustomDetachedImageJView view = (CustomDetachedImageJView) activated; + if (rec != null) { + IWorkbenchPartSite site = activated.getSite(); + EModelService s = site.getService(EModelService.class); + MPartSashContainerElement p = site.getService(MPart.class); + if (p.getCurSharedRef() != null) + p = p.getCurSharedRef(); + s.detach(p, rec.x, rec.y, rec.width, rec.height); + } + view.setImage(imp, item, holder); + result[0] = view; + } catch (PartInitException e) { + e.printStackTrace(); + } + }); + return result[0]; + } + + /* Moves the holder (with the ImageJ window) from the tab into this view! */ + private void setImage(ImagePlus imp, CTabItem item, Composite holder) { + this.plus = imp; + this.win = imp.getWindow(); + setPartName(imp.getTitle()); + item.setControl(null); + holder.setParent(customViewParent); + item.dispose(); + holder.setVisible(true); + customViewParent.layout(true, true); + setFocus(); + } + + public void dispose() { + /* Disposing the holder closes the image (see Bio7ImageJ)! */ + if (customViewParent != null && !customViewParent.isDisposed()) { + for (Control child : customViewParent.getChildren()) { + child.dispose(); + } + } + super.dispose(); + } + + public void setstatusline(String message) { + IActionBars bars = getViewSite().getActionBars(); + bars.getStatusLineManager().setMessage(message); + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/Fullscreen.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Fullscreen.java new file mode 100644 index 000000000..5d9ba6b9f --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Fullscreen.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2007-2026 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ +package com.eco.bio7.image.ui; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; + +import ij.ImagePlus; +import ij.WindowManager; + +/** + * Displays the current image in a fullscreen shell (toggled with F2, closed + * with ESC). The holder composite of the image is moved into the shell and back + * to the tab or view when the fullscreen mode is closed. + */ +public class Fullscreen { + + private static Shell shell; + private static Composite holder; + private static Composite oldParent; + private static CTabItem oldItem; + + /* Installed once by Bio7ImageJ! */ + static final Listener KEY_FILTER = new Listener() { + public void handleEvent(Event e) { + if (e.keyCode == SWT.F2) { + if (isActive()) { + exit(); + e.doit = false; + } else if (e.widget instanceof Control && isImageControl((Control) e.widget)) { + ImagePlus imp = WindowManager.getCurrentImage(); + if (imp != null) { + enter(imp); + e.doit = false; + } + } + } else if (e.keyCode == SWT.ESC && isActive()) { + /* The ESC key is also forwarded to ImageJ (abort macro or plugin)! */ + Display.getCurrent().asyncExec(Fullscreen::exit); + } + } + }; + + /* Returns true if the control is part of an embedded image window! */ + private static boolean isImageControl(Control control) { + for (Control c = control; c != null; c = c.getParent()) { + if (c instanceof ij.gui.ImageCanvas) { + return true; + } + } + return false; + } + + public static boolean isActive() { + return shell != null && !shell.isDisposed(); + } + + /** Returns true if the given holder is displayed in fullscreen mode. */ + static boolean isFullscreen(Composite imageHolder) { + return isActive() && holder == imageHolder; + } + + /** + * Displays the image in fullscreen mode. Must be called in the SWT UI thread. + */ + public static void enter(ImagePlus imp) { + if (isActive()) { + return; + } + holder = Bio7ImageJ.getHolder(imp); + if (holder == null) { + return; + } + oldParent = holder.getParent(); + oldItem = Bio7ImageJ.getTab(imp); + shell = new Shell(holder.getDisplay(), SWT.NO_TRIM | SWT.ON_TOP); + shell.setLayout(new FillLayout()); + shell.setBackground(holder.getDisplay().getSystemColor(SWT.COLOR_BLACK)); + shell.addListener(SWT.Close, e -> restore()); + if (oldItem != null) { + oldItem.setControl(null); + } + holder.setParent(shell); + holder.setVisible(true); + shell.setBounds(holder.getMonitor().getBounds()); + shell.setFullScreen(true); + shell.open(); + shell.layout(true, true); + if (imp.getCanvas() != null) { + imp.getCanvas().setFocus(); + } + } + + /** + * Closes the fullscreen mode. + */ + public static void exit() { + if (isActive()) { + shell.close(); + } + } + + /* Moves the holder back to the tab or view! */ + private static void restore() { + if (holder != null && !holder.isDisposed()) { + if (oldParent != null && !oldParent.isDisposed()) { + holder.setParent(oldParent); + if (oldItem != null && !oldItem.isDisposed()) { + oldItem.setControl(holder); + oldItem.getParent().setSelection(oldItem); + } + oldParent.layout(true, true); + } else { + /* The tab or view has been closed. Disposing closes the image! */ + holder.dispose(); + } + } + holder = null; + oldParent = null; + oldItem = null; + shell = null; + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJTabs.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJTabs.java new file mode 100644 index 000000000..d0ff63d0e --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJTabs.java @@ -0,0 +1,362 @@ +/******************************************************************************* + * Copyright (c) 2007-2026 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ + +package com.eco.bio7.image.ui; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement; +import org.eclipse.e4.ui.workbench.modeling.EModelService; +import org.eclipse.swt.custom.CTabItem; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IViewReference; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.PartInitException; + +import ij.ImagePlus; +import ij.WindowManager; +import ij.gui.ImageWindow; + +/** + * A class for the control of the ImageJ tabs. + * + * @author Bio7 + * + */ +public class IJTabs { + + private static Display getDisplay() { + return Util.getDisplay(); + } + + private static CTabItem[] getItems() { + if (CanvasView.tabFolder == null || CanvasView.tabFolder.isDisposed()) { + return new CTabItem[0]; + } + return CanvasView.tabFolder.getItems(); + } + + /** + * Returns the image displayed in the given tab. + * + * @param item a tab of the ImageJ view. + * @return the image or null. + */ + public static ImagePlus getImagePlus(CTabItem item) { + if (item != null && !item.isDisposed() && item.getData() instanceof ImagePlus) { + return (ImagePlus) item.getData(); + } + return null; + } + + /** + * Returns the image window displayed in the given tab. + * + * @param item a tab of the ImageJ view. + * @return the image window or null. + */ + public static ImageWindow getImageWindow(CTabItem item) { + ImagePlus imp = getImagePlus(item); + return imp != null ? imp.getWindow() : null; + } + + /** + * Returns the image of the selected tab. + * + * @return the image or null. + */ + public static ImagePlus getSelectedImagePlus() { + AtomicReference imp = new AtomicReference(); + getDisplay().syncExec(() -> { + if (CanvasView.tabFolder != null && !CanvasView.tabFolder.isDisposed()) { + imp.set(getImagePlus(CanvasView.tabFolder.getSelection())); + } + }); + return imp.get(); + } + + /** + * Returns the images of all tabs. + * + * @return a list of images. + */ + public static List getImagePlusList() { + List list = new ArrayList(); + getDisplay().syncExec(() -> { + for (CTabItem item : getItems()) { + ImagePlus imp = getImagePlus(item); + if (imp != null) { + list.add(imp); + } + } + }); + return list; + } + + /** + * Activates the tab with the specified number. + * + * @param number the number of the tab. + */ + public static void setActive(final int number) { + getDisplay().syncExec(() -> { + CTabItem[] items = getItems(); + if (number >= 0 && number < items.length) { + selectTab(items[number]); + } + }); + } + + private static void selectTab(CTabItem item) { + CanvasView.tabFolder.showItem(item); + CanvasView.tabFolder.setSelection(item); + CanvasView view = CanvasView.getCanvas_view(); + if (view != null) { + view.tabSelected(item); + } + } + + /** + * Returns the amount of opened tabs in the ImageJ view. + * + * @return the amount of tabs as an integer value. + */ + public static int getAmountTabs() { + AtomicReference count = new AtomicReference(0); + getDisplay().syncExec(() -> count.set(getItems().length)); + return count.get(); + } + + /** + * Detaches the view with the given secondary id (the image id) at the given + * location and size. + */ + public static void setSecondaryViewShellLocAndSize(String sec, Rectangle rec) { + getDisplay().syncExec(() -> { + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (page == null) { + return; + } + IViewReference ref = page.findViewReference(CustomDetachedImageJView.ID, sec); + if (ref == null) { + return; + } + try { + IViewPart activated = page.showView(CustomDetachedImageJView.ID, sec, IWorkbenchPage.VIEW_ACTIVATE); + if (rec != null && activated != null) { + IWorkbenchPartSite site = activated.getSite(); + EModelService s = site.getService(EModelService.class); + MPartSashContainerElement p = site.getService(MPart.class); + if (p.getCurSharedRef() != null) + p = p.getCurSharedRef(); + s.detach(p, rec.x, rec.y, rec.width, rec.height); + } + } catch (PartInitException e) { + e.printStackTrace(); + } + }); + } + + /** + * Closes all tabs in the ImageJ view (and all detached image views). + */ + public static void deleteAllTabs() { + getDisplay().syncExec(() -> { + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (page != null) { + for (IViewReference ref : page.getViewReferences()) { + if (ref.getId().equals(CustomDetachedImageJView.ID)) { + page.hideView(ref); + } + } + } + for (CTabItem item : getItems()) { + closeTab(item); + } + }); + } + + /* Disposing the holder closes the image (see Bio7ImageJ)! */ + private static void closeTab(CTabItem item) { + Control holder = item.getControl(); + if (holder != null && !holder.isDisposed()) { + holder.dispose(); + } + if (!item.isDisposed()) { + item.dispose(); + } + } + + /** + * Closes the tab (and the image) with the specified number in the ImageJ view. + * + * @param number the number of the tab as an integer value. + */ + public static void deleteTab(int number) { + getDisplay().syncExec(() -> { + CTabItem[] items = getItems(); + if (number >= 0 && number < items.length) { + closeTab(items[number]); + } + }); + } + + /** + * Closes the active tab in the ImageJ view. + * + * @deprecated Since the SWT port tabs can't be hidden without closing the + * image. Same as {@link #deleteActiveTab()}. + */ + @Deprecated + public static void hideTab() { + deleteActiveTab(); + } + + /** + * Closes the tab with the specified number in the ImageJ view. + * + * @param number the tab number. + * @deprecated Since the SWT port tabs can't be hidden without closing the + * image. Same as {@link #deleteTab(int)}. + */ + @Deprecated + public static void hideTabNumber(int number) { + deleteTab(number); + } + + /** + * Closes the tab which displays the given image. + * + * @param imagePlus the image. + * @deprecated Since the SWT port tabs can't be hidden without closing the + * image. Use {@link ImagePlus#close()}. + */ + @Deprecated + public static void hideTab(ImagePlus imagePlus) { + getDisplay().syncExec(() -> { + CTabItem item = Bio7ImageJ.getTab(imagePlus); + if (item != null) { + closeTab(item); + } + }); + } + + /** + * Deletes the active tab in the ImageJ view. + */ + public static void deleteActiveTab() { + getDisplay().syncExec(() -> { + if (CanvasView.tabFolder != null && !CanvasView.tabFolder.isDisposed()) { + CTabItem item = CanvasView.tabFolder.getSelection(); + if (item != null) { + closeTab(item); + } + } + }); + } + + /** + * Selects the tab which displays the image with the given title. + */ + public static void setActiveTab(String title) { + getDisplay().syncExec(() -> { + for (CTabItem item : getItems()) { + ImagePlus imp = getImagePlus(item); + if (imp != null && imp.getTitle().equals(title)) { + selectTab(item); + return; + } + } + }); + } + + /** + * Selects the tab which displays the image with the given ImageJ id (or index + * if the value is positive). + */ + public static void setActiveTabID(int theId) { + int id = theId > 0 ? WindowManager.getNthImageID(theId) : theId; + ImagePlus plus = WindowManager.getImage(id); + if (plus != null) { + getDisplay().syncExec(() -> { + CTabItem item = Bio7ImageJ.getTab(plus); + if (item != null) { + selectTab(item); + } + }); + } + } + + /** + * Selects the tab which displays the given image window. + */ + public static void setActiveTabWindow(ImageWindow win) { + if (win == null || win.getImagePlus() == null) { + return; + } + getDisplay().syncExec(() -> { + CTabItem item = Bio7ImageJ.getTab(win.getImagePlus()); + if (item != null) { + selectTab(item); + } + }); + } + + /** + * Lays out the detached image views (e.g. for orthogonal stack views)! + */ + public static void doSecondaryViewLayout() { + getDisplay().syncExec(() -> { + IWorkbenchPage page = Bio7ImageJ.getPage(); + if (page == null) { + return; + } + for (IViewReference ref : page.getViewReferences()) { + if (ref.getId().equals(CustomDetachedImageJView.ID)) { + IViewPart view = ref.getView(false); + if (view instanceof CustomDetachedImageJView) { + ((CustomDetachedImageJView) view).layout(); + } + } + } + }); + } + + /** + * Closes the detached view which displays the given window. + * + * @return true if a detached view has been closed. + */ + public static boolean closeDetachedWindowView(ImageWindow refWin) { + AtomicBoolean result = new AtomicBoolean(false); + if (refWin == null) { + return false; + } + getDisplay().syncExec(() -> { + CustomDetachedImageJView view = CustomDetachedImageJView.find(refWin.getImagePlus()); + if (view != null) { + view.getSite().getPage().hideView(view); + result.set(true); + } + }); + return result.get(); + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJtoolbar.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJtoolbar.java new file mode 100644 index 000000000..99baf797d --- /dev/null +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/IJtoolbar.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2007-2025 M. Austenfeld + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * M. Austenfeld + *******************************************************************************/ + +package com.eco.bio7.image.ui; + +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.part.ViewPart; + +import ij.IJ; +import ij.ImageJ; + +/** + * The ImageJ-Toolbar view. Displays the SWT toolbar, status line and progress + * bar of the ImageJ instance. The composite is moved back to the (hidden) + * ImageJ shell when the view is closed. + */ +public class IJtoolbar extends ViewPart { + + public static IJtoolbar instance; + + private Composite ijComposite; + + public IJtoolbar() { + instance = this; + } + + public void createPartControl(Composite parent) { + Bio7ImageJ.install(); + parent.setLayout(new FillLayout()); + ImageJ ij = IJ.getInstance(); + if (ij == null || ij.getComposite() == null || ij.getComposite().isDisposed()) { + return; + } + ijComposite = ij.getComposite(); + ijComposite.setParent(parent); + parent.layout(true, true); + /* The CSS theme is applied to the view after creation! */ + parent.getDisplay().asyncExec(() -> applyThemeColors(parent)); + /* The dispose event is sent before the children are disposed! */ + parent.addDisposeListener(e -> { + if (ijComposite != null && !ijComposite.isDisposed() && ij.getShell() != null && !ij.getShell().isDisposed()) { + ijComposite.setParent(ij.getShell()); + } + }); + } + + public void setFocus() { + if (ijComposite != null && !ijComposite.isDisposed()) { + applyThemeColors(ijComposite.getParent()); + ijComposite.setFocus(); + } + } + + /* + * The ImageJ toolbar uses the colors of its control. Apply the colors of the + * (themed) view, e.g., for the Bio7 dark theme! + */ + private void applyThemeColors(Composite parent) { + if (parent.isDisposed() || ijComposite == null || ijComposite.isDisposed()) { + return; + } + Color background = parent.getBackground(); + Color foreground = parent.getForeground(); + RGB b = background.getRGB(); + boolean darkBackground = (0.299 * b.red + 0.587 * b.green + 0.114 * b.blue) < 128; + if (Util.isThemeBlack() && !darkBackground) { + /* The view is not styled (yet). Use dark default colors! */ + background = new Color(47, 47, 47); + foreground = new Color(220, 220, 220); + } + setColors(ijComposite, background, foreground); + ijComposite.redraw(); + ijComposite.update(); + } + + private static void setColors(Control control, Color background, Color foreground) { + control.setBackground(background); + control.setForeground(foreground); + control.redraw(); + if (control instanceof Composite) { + for (Control child : ((Composite) control).getChildren()) { + setColors(child, background, foreground); + } + } + } + + public void dispose() { + if (instance == this) { + instance = null; + } + super.dispose(); + } +} diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/ImageJBio7OpenEditor.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/ImageJBio7OpenEditor.java similarity index 94% rename from com.eco.bio7.image/src/com/eco/bio7/image/ImageJBio7OpenEditor.java rename to com.eco.bio7.image/src/com/eco/bio7/image/ui/ImageJBio7OpenEditor.java index 92ddb2acb..04963b422 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/ImageJBio7OpenEditor.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/ImageJBio7OpenEditor.java @@ -1,4 +1,4 @@ -package com.eco.bio7.image; +package com.eco.bio7.image.ui; import java.io.File; @@ -34,6 +34,7 @@ public class ImageJBio7OpenEditor extends EditorPart { public void createPartControl(Composite parent) { + Bio7ImageJ.install(); IFile file = ResourceUtil.getFile(input); fi = file.getRawLocation().toString(); diff --git a/com.eco.bio7.image/src/com/eco/bio7/image/Util.java b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Util.java similarity index 66% rename from com.eco.bio7.image/src/com/eco/bio7/image/Util.java rename to com.eco.bio7.image/src/com/eco/bio7/image/ui/Util.java index ac01c330c..44e38d340 100644 --- a/com.eco.bio7.image/src/com/eco/bio7/image/Util.java +++ b/com.eco.bio7.image/src/com/eco/bio7/image/ui/Util.java @@ -1,8 +1,5 @@ -package com.eco.bio7.image; +package com.eco.bio7.image.ui; -import java.awt.Color; -import java.awt.Font; -import java.awt.Toolkit; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -46,9 +43,6 @@ */ public class Util { - private static Font awtFont; - private static Color col = null; - /** * A method to get the ImageJ path. * @@ -70,112 +64,6 @@ public static String getImageJPath() { return path; } - /** - * A method to get the default OS font from SWT to AWT. - * - * @return the OS font as an AWT font. - */ - public static java.awt.Font getOSFontToAwt() { - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - int fontSizeCorrection = store.getInt("FONT_SIZE_CORRECTION"); - - Display dis = getDisplay(); - - dis.syncExec(new Runnable() { - - public void run() { - - FontData fontData = dis.getSystemFont().getFontData()[0]; - - // int resolution = Toolkit.getDefaultToolkit().getScreenResolution(); - int awtFontSize = (int) Math.round((double) fontData.getHeight() * dis.getDPI().y / 72.0); - - /* Font size correction! */ - - awtFont = new java.awt.Font(fontData.getName(), fontData.getStyle(), awtFontSize + fontSizeCorrection); - } - }); - - return awtFont; - } - - public static Color getSWTBackgroundToAWT() { - col = new Color(0, 0, 0); - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - - public void run() { - IViewSite viewSite = CanvasView.getCanvas_view().getViewSite(); - IWorkbenchWindow workbenchWindow = viewSite.getWorkbenchWindow(); - org.eclipse.swt.graphics.Color colswt = workbenchWindow.getShell().getBackground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - } - }); - return col; - - } - - public static Color getSWTForegroundToAWT() { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - public void run() { - IViewSite viewSite = CanvasView.getCanvas_view().getViewSite(); - IWorkbenchWindow workbenchWindow = viewSite.getWorkbenchWindow(); - org.eclipse.swt.graphics.Color colswt = workbenchWindow.getShell().getForeground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - } - }); - return col; - - } - - public static Color getSWTBackgroundToAWT(Composite parent) { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - - public void run() { - - org.eclipse.swt.graphics.Color colswt = parent.getParent().getBackground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - } - }); - return col; - - } - - public static Color getSWTForegroundToAWT(Composite parent) { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - - public void run() { - - org.eclipse.swt.graphics.Color colswt = parent.getParent().getForeground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - } - }); - return col; - - } - /** * A method to detect the current OS. * @@ -349,31 +237,7 @@ public static Display getDisplay() { * @return a boolean value. */ public static boolean isThemeBlack() { - boolean themeBlack = false; - IWorkbench workbench = PlatformUI.getWorkbench(); - MApplication application = workbench.getService(MApplication.class); - IEclipseContext context = application.getContext(); - IThemeEngine engine = context.get(IThemeEngine.class); - ITheme theme = engine.getActiveTheme(); - // System.out.println(theme.getLabel()); - - // IPreferenceStore workbenchStore = - // IDEWorkbenchPlugin.getDefault().getPreferenceStore(); - // System.out.print(ThemeHelper.getEngine().getActiveTheme().getId()); - if (theme != null) { - String activeTheme = theme.getId(); - /* - * We use a black style if the CSS is the dark theme or the darkest dark theme! - */ - if (activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_1) || activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_2) - || activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_3) || activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_4) - || activeTheme.startsWith(MessagesThemeIDsSettings.Theme_Black_5)) { - - themeBlack = true; - - } - } - return themeBlack; + return com.eco.bio7.util.Util.isThemeBlack(); } // The source for the following method from: diff --git a/com.eco.bio7.image/src/ij/CommandListener.java b/com.eco.bio7.image/src/ij/CommandListener.java deleted file mode 100644 index e1a88bce2..000000000 --- a/com.eco.bio7.image/src/ij/CommandListener.java +++ /dev/null @@ -1,16 +0,0 @@ -package ij; - - /** Plugins that implement this interface are notified when ImageJ - is about to run a menu command. There is an example plugin at - http://imagej.net/ij/plugins/download/misc/Command_Listener.java - */ - public interface CommandListener { - - /* The method is called when ImageJ is about to run a menu command, - where 'command' is the name of the command. Return this string - and ImageJ will run the command, return a different command name - and ImageJ will run that command, or return null to not run a command. - */ - public String commandExecuting(String command); - -} diff --git a/com.eco.bio7.image/src/ij/CompositeImage.java b/com.eco.bio7.image/src/ij/CompositeImage.java deleted file mode 100644 index 47b016fc2..000000000 --- a/com.eco.bio7.image/src/ij/CompositeImage.java +++ /dev/null @@ -1,779 +0,0 @@ -package ij; -import ij.process.*; -import ij.gui.*; -import ij.plugin.*; -import ij.plugin.frame.*; -import ij.io.FileInfo; -import java.awt.*; -import java.awt.image.*; - -public class CompositeImage extends ImagePlus { - - /** Display modes (note: TRANSPARENT mode has not yet been implemented) */ - public static final int COMPOSITE=1, COLOR=2, GRAYSCALE=3, TRANSPARENT=4; - public static final int MAX_CHANNELS = 8; - public static final Color[] colors = {Color.red, Color.green, Color.blue, Color.white, Color.cyan, Color.magenta, Color.yellow, Color.white}; - - int[] rgbPixels; - boolean newPixels; - MemoryImageSource imageSource; - Image awtImage; - WritableRaster rgbRaster; - SampleModel rgbSampleModel; - BufferedImage rgbImage; - ColorModel rgbCM; - ImageProcessor[] cip; - LUT[] lut; - int currentChannel = -1; - int previousChannel; - int currentSlice = 1; - int currentFrame = 1; - boolean singleChannel; - boolean[] active = new boolean[MAX_CHANNELS]; - int mode = COLOR; - int bitDepth; - double[] displayRanges; - byte[][] channelLuts; - boolean customLuts; - boolean syncChannels; - - public CompositeImage(ImagePlus imp) { - this(imp, COLOR); - } - - public CompositeImage(ImagePlus imp, int mode) { - if (modeGRAYSCALE) - mode = COLOR; - this.mode = mode; - int channels = imp.getNChannels(); - bitDepth = getBitDepth(); - if (IJ.debugMode) IJ.log("CompositeImage: "+imp+" "+mode+" "+channels); - ImageStack stack2; - boolean isRGB = imp.getBitDepth()==24; - if (isRGB) { - if (imp.getImageStackSize()>1) - throw new IllegalArgumentException("RGB stacks not supported"); - stack2 = getRGBStack(imp); - } else - stack2 = imp.getImageStack(); - int stackSize = stack2.getSize(); - if (channels==1 && isRGB) - channels = 3; - if (channels==1 && stackSize<=MAX_CHANNELS && !imp.dimensionsSet) - channels = stackSize; - if (channels<1 || (stackSize%channels)!=0) - throw new IllegalArgumentException("stacksize not multiple of channels"); - if (mode==COMPOSITE && channels>MAX_CHANNELS) - this.mode = COLOR; - compositeImage = true; - int z = imp.getNSlices(); - int t = imp.getNFrames(); - if (channels==stackSize || channels*z*t!=stackSize) - setDimensions(channels, stackSize/channels, 1); - else - setDimensions(channels, z, t); - setStack(imp.getTitle(), stack2); - setCalibration(imp.getCalibration()); - FileInfo fi = imp.getOriginalFileInfo(); - if (fi!=null) { - displayRanges = fi.displayRanges; - channelLuts = fi.channelLuts; - } - setFileInfo(fi); - Object info = imp.getProperty("Info"); - if (info!=null) - setProperty("Info", imp.getProperty("Info")); - setProperties(imp.getPropertiesAsArray()); - if (mode==COMPOSITE) { - for (int i=0; i0 && (stack2.getProcessor(1) instanceof ColorProcessor)) { // RGB? - cip = null; - lut = null; - return; - } - setupLuts(channels); - if (mode==COMPOSITE) { - cip = new ImageProcessor[channels]; - for (int i=0; iMAX_CHANNELS?createLutFromColor(Color.white):null; - for (int i=0; istack2.getSize() || channels>MAX_CHANNELS) - return; - for (int i=0; inChannels) ch = nChannels; - boolean newChannel = false; - if (ch-1!=currentChannel) { - previousChannel = currentChannel; - currentChannel = ch-1; - newChannel = true; - } - - ImageProcessor ip = getProcessor(); - if (mode!=COMPOSITE) { - if (newChannel) { - setupLuts(nChannels); - LUT cm = lut[currentChannel]; - if (ip!=null && !(ip instanceof ColorProcessor)) { - if (mode==COLOR) - ip.setLut(cm); - if (!(cm.min==0.0&&cm.max==0.0)) - ip.setMinAndMax(cm.min, cm.max); - } - if (!IJ.isMacro()) ContrastAdjuster.update(); - for (int i=0; i=nChannels) { - setSlice(1); - currentChannel = 0; - newChannel = true; - } - bitDepth = getBitDepth(); - } - - if (newChannel) { - getProcessor().setMinAndMax(cip[currentChannel].getMin(), cip[currentChannel].getMax()); - if (!IJ.isMacro()) ContrastAdjuster.update(); - } - //IJ.log(nChannels+" "+ch+" "+currentChannel+" "+newChannel); - - if (getSlice()!=currentSlice || getFrame()!=currentFrame) { - currentSlice = getSlice(); - currentFrame = getFrame(); - int position = getStackIndex(1, currentSlice, currentFrame); - if (cip==null) return; - for (int i=0; icip.length) - return; - for (int i=1; icip.length) - return null; - else - return cip[channel-1]; - } - - public boolean[] getActiveChannels() { - return active; - } - - public synchronized void setMode(int mode) { - if (modeGRAYSCALE) - return; - if (mode==COMPOSITE && getNChannels()>MAX_CHANNELS) - mode = COLOR; - if (!(mode==COMPOSITE && mode==this.mode)) { - for (int i=0; ilut.length) - throw new IllegalArgumentException("Channel out of range: "+channel); - return lut[channel-1]; - } - - /* Returns the LUT used by the current channel. */ - public LUT getChannelLut() { - int c = getChannelIndex(); - return lut[c]; - } - - /* Returns a copy of this image's channel LUTs as an array. */ - public LUT[] getLuts() { - int channels = getNChannels(); - if (lut==null) - setupLuts(channels); - LUT[] luts = new LUT[channels]; - for (int i=0; iMAX_CHANNELS && getMode()==COMPOSITE) - setMode(COLOR); - setup(nChannels, getImageStack()); - } - - public void completeReset() { - cip = null; - lut = null; - } - - /* Sets the LUT of the current channel. */ - public void setChannelLut(LUT table) { - int c = getChannelIndex(); - double min = lut[c].min; - double max = lut[c].max; - lut[c] = table; - lut[c].min = min; - lut[c].max = max; - if (mode==COMPOSITE && cip!=null && clut.length) - throw new IllegalArgumentException("Channel out of range"); - lut[channel-1] = (LUT)table.clone(); - if (getWindow()!=null && channel==getChannel()) - getProcessor().setLut(lut[channel-1]); - if (cip!=null && cip.length>=channel && cip[channel-1]!=null) - cip[channel-1].setLut(lut[channel-1]); - else - cip = null; - customLuts = true; - } - - /* Sets the IndexColorModel of the current channel. */ - public void setChannelColorModel(IndexColorModel cm) { - setChannelLut(new LUT(cm,0.0,0.0)); - } - - public void setDisplayRange(double min, double max) { - ip.setMinAndMax(min, max); - int c = getChannelIndex(); - lut[c].min = min; - lut[c].max = max; - if (getWindow()==null && cip!=null && c0) synchronized (listeners) { - for (int i=0; i0 && command.charAt(len-1)!=']') - IJ.setKeyUp(IJ.ALL_KEYS); // set keys up except for "<", ">", "+" and "-" shortcuts - } catch(Throwable e) { - IJ.showStatus(""); - IJ.showProgress(1, 1); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp!=null) imp.unlock(); - String msg = e.getMessage(); - if (e instanceof OutOfMemoryError) - IJ.outOfMemory(command); - else if (e instanceof RuntimeException && msg!=null && msg.equals(Macro.MACRO_CANCELED)) - ; //do nothing - else { - CharArrayWriter caw = new CharArrayWriter(); - PrintWriter pw = new PrintWriter(caw); - e.printStackTrace(pw); - String s = caw.toString(); - if (IJ.isMacintosh()) { - if (s.indexOf("ThreadDeath")>0) - return; - s = Tools.fixNewLines(s); - } - int w=500, h=340; - if (s.indexOf("UnsupportedClassVersionError")!=-1) { - if (s.indexOf("version 49.0")!=-1) { - s = e + "\n \nThis plugin requires Java 1.5 or later."; - w=700; h=150; - } - if (s.indexOf("version 50.0")!=-1) { - s = e + "\n \nThis plugin requires Java 1.6 or later."; - w=700; h=150; - } - if (s.indexOf("version 51.0")!=-1) { - s = e + "\n \nThis plugin requires Java 1.7 or later."; - w=700; h=150; - } - if (s.indexOf("version 52.0")!=-1) { - s = e + "\n \nThis plugin requires Java 1.8 or later."; - w=700; h=150; - } - } - if (IJ.getInstance()!=null) { - s = IJ.getInstance().getInfo()+"\n \n"+s; - new TextWindow("Exception", s, w, h); - } else - IJ.log(s); - } - } finally { - if (thread!=null) - WindowManager.setTempCurrentImage(null); - } - } - - void runCommand(String cmd) { - Hashtable table = Menus.getCommands(); - String className = (String)table.get(cmd); - if (className!=null) { - String arg = ""; - if (className.endsWith("\")")) { - // extract string argument (e.g. className("arg")) - int argStart = className.lastIndexOf("(\""); - if (argStart>0) { - arg = className.substring(argStart+2, className.length()-2); - className = className.substring(0, argStart); - } - } - if (Prefs.nonBlockingFilterDialogs) { - // we have the plugin class name, let us see whether it is allowed to run it - ImagePlus imp = WindowManager.getCurrentImage(); - boolean imageLocked = imp!=null && imp.isLockedByAnotherThread(); - if (imageLocked && !allowedWithLockedImage(className)) { - IJ.beep(); - IJ.showStatus("\""+cmd + "\" blocked because \"" + imp.getTitle() + "\" is locked"); - return; - } - } - // run the plugin - if (IJ.shiftKeyDown() && className.startsWith("ij.plugin.Macro_Runner") && !Menus.getShortcuts().contains("*"+cmd)) - IJ.open(IJ.getDirectory("plugins")+arg); - else - IJ.runPlugIn(cmd, className, arg); - } else { // command is not a plugin - // is command in the Plugins>Macros menu? - if (MacroInstaller.runMacroCommand(cmd)) - return; - // is it in the Image>Lookup Tables menu? - if (loadLut(cmd)) - return; - // is it in the File>Open Recent menu? - if (openRecent(cmd)) - return; - // is it an example in Help>Examples menu? - if (IJ.getInstance()!=null && !GraphicsEnvironment.isHeadless()) { - if (Editor.openExample(cmd)) - return; - } - if ("Auto Threshold".equals(cmd)&&(String)table.get("Auto Threshold...")!=null) - runCommand("Auto Threshold..."); - else if ("Enhance Local Contrast (CLAHE)".equals(cmd)&&(String)table.get("CLAHE ")!=null) - runCommand("CLAHE "); - else { - if ("Table...".equals(cmd)) - IJ.runPlugIn("ij.plugin.NewPlugin", "table"); - else { - if (repeatingCommand) - IJ.runMacro(previousCommand); - else { - if (!extraCommand(cmd)) - IJ.error("Unrecognized command: \"" + cmd+"\""); - } - } - } - } - } - - private boolean extraCommand(String cmd) { - if (cmd!=null && cmd.equals("Duplicate Image...")) { - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp!=null) { - Duplicator.ignoreNextSelection(); - IJ.run(imp, "Duplicate...", ""); - } else - IJ.noImage(); - return true; - } else - return false; - } - - /** If the foreground image is locked during a filter operation with NonBlockingGenericDialog, - * the following plugins are allowed */ - boolean allowedWithLockedImage(String className) { - return className.equals("ij.plugin.Zoom") || - className.equals("ij.plugin.frame.ContrastAdjuster") || - className.equals("ij.plugin.SimpleCommands") || //includes Plugins>Utiltites>Reset (needed to reset a locked image) - className.equals("ij.plugin.WindowOrganizer") || - className.equals("ij.plugin.URLOpener"); - } - - /** Opens a .lut file from the ImageJ/luts directory and returns 'true' if successful. */ - public static boolean loadLut(String name) { - String path = IJ.getDirectory("luts")+name.replace(" ","_")+".lut"; - File f = new File(path); - if (!f.exists()) { - path = IJ.getDirectory("luts")+name+".lut"; - f = new File(path); - } - if (!f.exists()) { - path = IJ.getDirectory("luts")+name.toLowerCase().replace(" ","_")+".lut"; - f = new File(path); - } - if (!f.exists() && Character.isLowerCase(name.charAt(0))) { - String name2 = name.substring(0,1).toUpperCase()+name.substring(1); - path = IJ.getDirectory("luts")+name2+".lut"; - f = new File(path); - } - if (!f.exists() && name.toLowerCase().equals("viridis")) { - path = IJ.getDirectory("luts")+"mpl-viridis.lut"; //Fiji version - f = new File(path); - } - if (f.exists()) { - String dir = OpenDialog.getLastDirectory(); - IJ.open(path); - OpenDialog.setLastDirectory(dir); - return true; - } - return false; - } - - /** Opens a file from the File/Open Recent menu - and returns 'true' if successful. */ - boolean openRecent(String cmd) { - Menu menu = Menus.getOpenRecentMenu(); - if (menu==null) return false; - for (int i=0; imacro on the current - * thread. Returns any string value returned by the macro, null if the macro - * does not return a value, or "[aborted]" if the macro was aborted due to an - * error. The equivalent macro function is eval(). - */ - public static String runMacro(String macro) { - return runMacro(macro, ""); - } - - /** - * Runs the macro contained in the string macro on the current - * thread. The optional string argument can be retrieved in the called macro - * using the getArgument() macro function. Returns any string value returned by - * the macro, null if the macro does not return a value, or "[aborted]" if the - * macro was aborted due to an error. - */ - public static String runMacro(String macro, String arg) { - Macro_Runner mr = new Macro_Runner(); - return mr.runMacro(macro, arg); - } - - /** - * Runs the specified macro or script file in the current thread. The file is - * assumed to be in the macros folder unless name is a full path. - * The optional string argument (arg) can be retrieved in the - * called macro or script using the getArgument() function. Returns any string - * value returned by the macro, or null. Scripts always return null. The - * equivalent macro function is runMacro(). - */ - public static String runMacroFile(String name, String arg) { - Macro_Runner mr = new Macro_Runner(); - return mr.runMacroFile(name, arg); - } - - /** Runs the specified macro file. */ - public static String runMacroFile(String name) { - return runMacroFile(name, null); - } - - /** Runs the specified plugin using the specified image. */ - public static Object runPlugIn(ImagePlus imp, String className, String arg) { - if (imp != null) { - ImagePlus temp = WindowManager.getTempCurrentImage(); - WindowManager.setTempCurrentImage(imp); - Object o = runPlugIn("", className, arg); - WindowManager.setTempCurrentImage(temp); - return o; - } else - return runPlugIn(className, arg); - } - - /** Runs the specified plugin and returns a reference to it. */ - public static Object runPlugIn(String className, String arg) { - return runPlugIn("", className, arg); - } - - /** Runs the specified plugin and returns a reference to it. */ - public static Object runPlugIn(String commandName, String className, String arg) { - if (arg == null) - arg = ""; - if (IJ.debugMode) - IJ.log("runPlugIn: " + className + argument(arg)); - // Load using custom classloader if this is a user - // plugin and we are not running as an applet - if (!className.startsWith("ij.") && applet == null) - return runUserPlugIn(commandName, className, arg, false); - Object thePlugIn = null; - try { - Class c = Class.forName(className); - thePlugIn = c.newInstance(); - if (thePlugIn instanceof PlugIn) - ((PlugIn) thePlugIn).run(arg); - else - new PlugInFilterRunner(thePlugIn, commandName, arg); - } catch (ClassNotFoundException e) { - if (!(className != null && className.startsWith("ij.plugin.MacAdapter"))) { - log("Plugin or class not found: \"" + className + "\"\n(" + e + ")"); - String path = Prefs.getCustomPropsPath(); - if (path != null) - ; - log("Error may be due to custom properties at " + path); - } - } catch (InstantiationException e) { - log("Unable to load plugin (ins)"); - } catch (IllegalAccessException e) { - log("Unable to load plugin, possibly \nbecause it is not public."); - } - redirectErrorMessages = false; - return thePlugIn; - } - - static Object runUserPlugIn(String commandName, String className, String arg, boolean createNewLoader) { - if (IJ.debugMode) - IJ.log("runUserPlugIn: " + className + ", arg=" + argument(arg)); - if (applet != null) - return null; - if (createNewLoader) - classLoader = null; - ClassLoader loader = getClassLoader(); - Object thePlugIn = null; - try { - thePlugIn = (loader.loadClass(className)).newInstance(); - if (thePlugIn instanceof PlugIn) - ((PlugIn) thePlugIn).run(arg); - else if (thePlugIn instanceof PlugInFilter) - new PlugInFilterRunner(thePlugIn, commandName, arg); - } catch (ClassNotFoundException e) { - if (className.startsWith("macro:")) - runMacro(className.substring(6)); - else if (className.contains("_") && !suppressPluginNotFoundError) - error("Plugin or class not found: \"" + className + "\"\n(" + e + ")"); - } catch (NoClassDefFoundError e) { - int dotIndex = className.indexOf('.'); - if (dotIndex >= 0 && className.contains("_")) { - // rerun plugin after removing folder name - if (debugMode) - IJ.log("runUserPlugIn: rerunning " + className); - return runUserPlugIn(commandName, className.substring(dotIndex + 1), arg, createNewLoader); - } - if (className.contains("_") && !suppressPluginNotFoundError) - error("Run User Plugin", "Class not found while attempting to run \"" + className + "\"\n \n " + e); - } catch (InstantiationException e) { - error("Unable to load plugin (ins)"); - } catch (IllegalAccessException e) { - error("Unable to load plugin, possibly \nbecause it is not public."); - } - if (thePlugIn != null && !"HandleExtraFileTypes".equals(className)) - redirectErrorMessages = false; - suppressPluginNotFoundError = false; - return thePlugIn; - } - - private static String argument(String arg) { - return arg != null && !arg.equals("") && !arg.contains("\n") ? "(\"" + arg + "\")" : ""; - } - - static void wrongType(int capabilities, String cmd) { - String s = "\"" + cmd + "\" requires an image of type:\n \n"; - if ((capabilities & PlugInFilter.DOES_8G) != 0) - s += " 8-bit grayscale\n"; - if ((capabilities & PlugInFilter.DOES_8C) != 0) - s += " 8-bit color\n"; - if ((capabilities & PlugInFilter.DOES_16) != 0) - s += " 16-bit grayscale\n"; - if ((capabilities & PlugInFilter.DOES_32) != 0) - s += " 32-bit (float) grayscale\n"; - if ((capabilities & PlugInFilter.DOES_RGB) != 0) - s += " RGB color\n"; - error(s); - } - - /** Runs a menu command on a separete thread and returns immediately. */ - public static void doCommand(String command) { - new Executer(command, null); - } - - /** Runs a menu command on a separete thread, using the specified image. */ - public static void doCommand(ImagePlus imp, String command) { - new Executer(command, imp); - } - - /** - * Runs an ImageJ command. Does not return until the command has finished - * executing. To avoid "image locked", errors, plugins that call this method - * should implement the PlugIn interface instead of PlugInFilter. - */ - public static void run(String command) { - run(command, null); - } - - /** - * Runs an ImageJ command, with options that are passed to the GenericDialog and - * OpenDialog classes. Does not return until the command has finished executing. - * To generate run() calls, start the recorder (Plugins/Macro/Record) and run - * commands from the ImageJ menu bar. - */ - public static void run(String command, String options) { - // IJ.log("run1: "+command+" "+Thread.currentThread().hashCode()+" - // "+options); - if (ij == null && Menus.getCommands() == null) - init(); - Macro.abort = false; - Macro.setOptions(options); - Thread thread = Thread.currentThread(); - if (previousThread == null || thread != previousThread) { - String name = thread.getName(); - if (!name.startsWith("Run$_")) - thread.setName("Run$_" + name); - } - command = convert(command); - previousThread = thread; - macroRunning = true; - Executer e = new Executer(command); - e.run(); - macroRunning = false; - Macro.setOptions(null); - testAbort(); - macroInterpreter = null; - // IJ.log("run2: "+command+" "+Thread.currentThread().hashCode()); - } - - /** The macro interpreter uses this method to run commands. */ - public static void run(Interpreter interpreter, String command, String options) { - macroInterpreter = interpreter; - run(command, options); - macroInterpreter = null; - } - - /** - * Converts commands that have been renamed so macros using the old names - * continue to work. - */ - private static String convert(String command) { - if (commandTable == null) { - commandTable = new Hashtable(30); - commandTable.put("New...", "Image..."); - commandTable.put("Threshold", "Make Binary"); - commandTable.put("Display...", "Appearance..."); - commandTable.put("Start Animation", "Start Animation [\\]"); - commandTable.put("Convert Images to Stack", "Images to Stack"); - commandTable.put("Convert Stack to Images", "Stack to Images"); - commandTable.put("Convert Stack to RGB", "Stack to RGB"); - commandTable.put("Convert to Composite", "Make Composite"); - commandTable.put("RGB Split", "Split Channels"); - commandTable.put("RGB Merge...", "Merge Channels..."); - commandTable.put("Channels...", "Channels Tool..."); - commandTable.put("New... ", "Table..."); - commandTable.put("Arbitrarily...", "Rotate... "); - commandTable.put("Measurements...", "Results... "); - commandTable.put("List Commands...", "Find Commands..."); - commandTable.put("Capture Screen ", "Capture Screen"); - commandTable.put("Add to Manager ", "Add to Manager"); - commandTable.put("In", "In [+]"); - commandTable.put("Out", "Out [-]"); - commandTable.put("Enhance Contrast", "Enhance Contrast..."); - commandTable.put("XY Coodinates... ", "XY Coordinates... "); - commandTable.put("Statistics...", "Statistics"); - commandTable.put("Channels Tool... ", "Channels Tool..."); - commandTable.put("Profile Plot Options...", "Plots..."); - commandTable.put("AuPbSn 40 (56K)", "AuPbSn 40"); - commandTable.put("Bat Cochlea Volume (19K)", "Bat Cochlea Volume"); - commandTable.put("Bat Cochlea Renderings (449K)", "Bat Cochlea Renderings"); - commandTable.put("Blobs (25K)", "Blobs"); - commandTable.put("Boats (356K)", "Boats"); - commandTable.put("Cardio (768K, RGB DICOM)", "Cardio (RGB DICOM)"); - commandTable.put("Cell Colony (31K)", "Cell Colony"); - commandTable.put("Clown (14K)", "Clown"); - commandTable.put("Confocal Series (2.2MB)", "Confocal Series"); - commandTable.put("CT (420K, 16-bit DICOM)", "CT (16-bit DICOM)"); - commandTable.put("Dot Blot (7K)", "Dot Blot"); - commandTable.put("Embryos (42K)", "Embryos"); - commandTable.put("Fluorescent Cells (400K)", "Fluorescent Cells"); - commandTable.put("Fly Brain (1MB)", "Fly Brain"); - commandTable.put("Gel (105K)", "Gel"); - commandTable.put("HeLa Cells (1.3M, 48-bit RGB)", "HeLa Cells (48-bit RGB)"); - commandTable.put("Leaf (36K)", "Leaf"); - commandTable.put("Line Graph (21K)", "Line Graph"); - commandTable.put("Mitosis (26MB, 5D stack)", "Mitosis (5D stack)"); - commandTable.put("MRI Stack (528K)", "MRI Stack"); - commandTable.put("M51 Galaxy (177K, 16-bits)", "M51 Galaxy (16-bits)"); - commandTable.put("Neuron (1.6M, 5 channels)", "Neuron (5 channels)"); - commandTable.put("Nile Bend (1.9M)", "Nile Bend"); - commandTable.put("Organ of Corti (2.8M, 4D stack)", "Organ of Corti (4D stack)"); - commandTable.put("Particles (75K)", "Particles"); - commandTable.put("T1 Head (2.4M, 16-bits)", "T1 Head (16-bits)"); - commandTable.put("T1 Head Renderings (736K)", "T1 Head Renderings"); - commandTable.put("TEM Filter (112K)", "TEM Filter"); - commandTable.put("Tree Rings (48K)", "Tree Rings"); - } - String command2 = (String) commandTable.get(command); - if (command2 != null) - return command2; - else - return command; - } - - /** - * Runs an ImageJ command using the specified image and options. To generate - * run() calls, start the recorder (Plugins/Macro/Record) and run commands from - * the ImageJ menu bar. - */ - public static void run(ImagePlus imp, String command, String options) { - if (ij == null && Menus.getCommands() == null) - init(); - if (imp != null) { - ImagePlus temp = WindowManager.getTempCurrentImage(); - WindowManager.setTempCurrentImage(imp); - run(command, options); - WindowManager.setTempCurrentImage(temp); - } else - run(command, options); - } - - static void init() { - Menus m = new Menus(null, null); - Prefs.load(m, null); - m.addMenuBar(); - } - - private static void testAbort() { - if (Macro.abort) - abort(); - } - - /** Returns true if the run(), open() or newImage() method is executing. */ - public static boolean macroRunning() { - return macroRunning; - } - - /** - * Returns true if a macro is running, or if the run(), open() or newImage() - * method is executing. - */ - public static boolean isMacro() { - return macroRunning || Interpreter.getInstance() != null; - } - - /** - * Returns the Applet that created this ImageJ or null if running as an - * application. - */ - public static java.applet.Applet getApplet() { - return applet; - } - - /** - * Displays a message in the ImageJ status bar. If 's' starts with '!', - * subsequent showStatus() calls in the current thread (without "!" in the - * message) are suppressed. - */ - public static void showStatus(String s) { - if ((Interpreter.getInstance() == null && statusBarThread == null) - || (statusBarThread != null && Thread.currentThread() != statusBarThread)) - protectStatusBar(false); - boolean doProtect = s.startsWith("!"); // suppress subsequent showStatus() calls - if (doProtect) { - protectStatusBar(true); - statusBarThread = Thread.currentThread(); - s = s.substring(1); - } - if (doProtect || !protectStatusBar) { - if (ij != null) - ij.showStatus(s); - ImagePlus imp = WindowManager.getCurrentImage(); - ImageCanvas ic = imp != null ? imp.getCanvas() : null; - if (ic != null) - ic.setShowCursorStatus(s.length() == 0 ? true : false); - } - } - - /** - * Displays a message in the status bar and flashes either the status bar or the - * active image. - * See: http://wsr.imagej.net/macros/FlashingStatusMessages.txt - */ - public static void showStatus(String message, String options) { - showStatus(message); - if (options == null) - return; - options = options.replace("flash", ""); - options = options.replace("ms", ""); - Color optionalColor = null; - int index1 = options.indexOf("#"); - if (index1 >= 0) { // hex color? - int index2 = options.indexOf(" ", index1); - if (index2 == -1) - index2 = options.length(); - String hexColor = options.substring(index1, index2); - optionalColor = Colors.decode(hexColor, null); - options = options.replace(hexColor, ""); - } - if (optionalColor == null) { // "red", "green", etc. - for (String c : Colors.colors) { - if (options.contains(c)) { - optionalColor = Colors.getColor(c, ImageJ.backgroundColor); - options = options.replace(c, ""); - break; - } - } - } - boolean flashImage = options.contains("image"); - Color defaultColor = new Color(255, 255, 245); - int defaultDelay = 500; - ImagePlus imp = WindowManager.getCurrentImage(); - if (flashImage) { - options = options.replace("image", ""); - if (imp != null && imp.getWindow() != null) { - defaultColor = Color.black; - defaultDelay = 100; - } else - flashImage = false; - } - Color color = optionalColor != null ? optionalColor : defaultColor; - int delay = (int) Tools.parseDouble(options, defaultDelay); - if (delay > 8000) - delay = 8000; - ImageJ ij = IJ.getInstance(); - if (flashImage) { - // Color previousColor = imp.getWindow().getBackground(); - /*Changed for Bio7!*/ - Color previousColor = Util.getSWTBackgroundToAWT(); - - Display display = Util.getDisplay(); - display.asyncExec(new Runnable() { - public void run() { - previousTabForegColor = CanvasView.tabFolder.getSelectionForeground(); - } - }); - imp.getWindow().setBackground(color); - // g.setColor(c); - setTabItemColor(color); - if (delay > 0) { - wait(delay); - imp.getWindow().setBackground(previousColor); - setTabItemColor(previousTabForegColor); - // current.setBackground(previousColor); - } - - } else if (ij != null) { - Color previousColor = ij.getStatusBar().getBackground(); - ij.getStatusBar().setBackground(color); - wait(delay); - ij.getStatusBar().setBackground(previousColor); - } - } - - public static void setTabItemColor(org.eclipse.swt.graphics.Color col) { - Display display = Util.getDisplay(); - display.asyncExec(new Runnable() { - public void run() { - CanvasView.tabFolder.setSelectionForeground(col); - CanvasView.tabFolder.setForeground(col); - - } - }); - } - - public static void setTabItemColor(Color col) { - int red = col.getRed(); - int green = col.getGreen(); - int blue = col.getBlue(); - Display display = Util.getDisplay(); - display.asyncExec(new Runnable() { - public void run() { - CanvasView.tabFolder - .setSelectionForeground(new org.eclipse.swt.graphics.Color(display, new RGB(red, green, blue))); - - } - }); - } - - /** - * @deprecated replaced by IJ.log(), ResultsTable.setResult() and - * TextWindow.append(). There are examples at - * http://imagej.net/ij/plugins/sine-cosine.html - */ - public static void write(String s) { - if (textPanel == null && ij != null) - showResults(); - if (textPanel != null) - textPanel.append(s); - else - System.out.println(s); - } - - private static void showResults() { - TextWindow resultsWindow = new TextWindow("Results", "", 400, 250); - textPanel = resultsWindow.getTextPanel(); - textPanel.setResultsTable(Analyzer.getResultsTable()); - } - - public static synchronized void log(String s) { - if (s == null) - return; - if (logPanel == null && ij != null) { - TextWindow logWindow = new TextWindow("Log", "", 400, 250); - logPanel = logWindow.getTextPanel(); - logPanel.setFont(new Font("SansSerif", Font.PLAIN, 16)); - } - if (logPanel != null) { - if (s.startsWith("\\")) - handleLogCommand(s); - else { - if (s.endsWith("\n")) { - if (s.equals("\n\n")) - s = "\n \n "; - else if (s.endsWith("\n\n")) - s = s.substring(0, s.length() - 2) + "\n \n "; - else - s = s + " "; - } - logPanel.append(s); - } - } else { - LogStream.redirectSystem(false); - System.out.println(s); - } - } - - static void handleLogCommand(String s) { - if (s.equals("\\Closed")) - logPanel = null; - else if (s.startsWith("\\Update:")) { - int n = logPanel.getLineCount(); - String s2 = s.substring(8, s.length()); - if (n == 0) - logPanel.append(s2); - else - logPanel.setLine(n - 1, s2); - } else if (s.startsWith("\\Update")) { - int cindex = s.indexOf(":"); - if (cindex == -1) { - logPanel.append(s); - return; - } - String nstr = s.substring(7, cindex); - int line = (int) Tools.parseDouble(nstr, -1); - if (line < 0 || line > 25) { - logPanel.append(s); - return; - } - int count = logPanel.getLineCount(); - while (line >= count) { - log(""); - count++; - } - String s2 = s.substring(cindex + 1, s.length()); - logPanel.setLine(line, s2); - } else if (s.equals("\\Clear")) { - logPanel.clear(); - } else if (s.startsWith("\\Heading:")) { - logPanel.updateColumnHeadings(s.substring(10)); - } else if (s.equals("\\Close")) { - Frame f = WindowManager.getFrame("Log"); - if (f != null && (f instanceof TextWindow)) - ((TextWindow) f).close(); - } else - logPanel.append(s); - } - - /** - * Returns the contents of the Log window or null if the Log window is not open. - */ - public static synchronized String getLog() { - if (logPanel == null || ij == null) - return null; - else - return logPanel.getText(); - } - - /** - * Clears the "Results" window and sets the column headings to those in the - * tab-delimited 'headings' String. Writes to System.out.println if the "ImageJ" - * frame is not present. - */ - public static void setColumnHeadings(String headings) { - if (textPanel == null && ij != null) - showResults(); - if (textPanel != null) - textPanel.setColumnHeadings(headings); - else - System.out.println(headings); - } - - /** Returns true if the "Results" window is open. */ - public static boolean isResultsWindow() { - return textPanel != null; - } - - /** Renames a results window. */ - public static void renameResults(String title) { - Frame frame = WindowManager.getFrontWindow(); - if (frame != null && (frame instanceof TextWindow)) { - TextWindow tw = (TextWindow) frame; - if (tw.getResultsTable() == null) { - IJ.error("Rename", "\"" + tw.getTitle() + "\" is not a results table"); - return; - } - tw.rename(title); - } else if (isResultsWindow()) { - TextPanel tp = getTextPanel(); - TextWindow tw = (TextWindow) tp.getParent(); - tw.rename(title); - } - } - - /** Changes the name of a table window from 'oldTitle' to 'newTitle'. */ - public static void renameResults(String oldTitle, String newTitle) { - Frame frame = WindowManager.getFrame(oldTitle); - if (frame == null) { - error("Rename", "\"" + oldTitle + "\" not found"); - return; - } else if (frame instanceof TextWindow) { - TextWindow tw = (TextWindow) frame; - if (tw.getResultsTable() == null) { - error("Rename", "\"" + oldTitle + "\" is not a table"); - return; - } - tw.rename(newTitle); - } else - error("Rename", "\"" + oldTitle + "\" is not a table"); - } - - /** - * Deletes 'row1' through 'row2' of the "Results" window, where 'row1' and - * 'row2' must be in the range 0-Analyzer.getCounter()-1. - */ - public static void deleteRows(int row1, int row2) { - - ResultsTable rt = Analyzer.getResultsTable(); - int tableSize = rt.size(); - rt.deleteRows(row1, row2); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp != null) - Overlay.updateTableOverlay(imp, row1, row2, tableSize); - rt.show("Results"); - } - - /** - * Returns a measurement result, where 'measurement' is "Area", "Mean", - * "StdDev", "Mode", "Min", "Max", "X", "Y", "XM", "YM", "Perim.", "BX", "BY", - * "Width", "Height", "Major", "Minor", "Angle", "Circ.", "Feret", "IntDen", - * "Median", "Skew", "Kurt", "%Area", "RawIntDen", "Ch", "Slice", "Frame", - * "FeretX", "FeretY", "FeretAngle", "MinFeret", "AR", "Round", "Solidity", - * "MinThr" or "MaxThr". Add " raw" to the argument to disable calibration, for - * example IJ.getValue("Mean raw"). Add " limit" to enable the "limit to - * threshold" option. - */ - public static double getValue(ImagePlus imp, String measurement) { - String options = ""; - int index = measurement.indexOf(" "); - if (index > 0) { - if (index < measurement.length() - 1) - options = measurement.substring(index + 1, measurement.length()); - measurement = measurement.substring(0, index); - } - int measurements = Measurements.ALL_STATS + Measurements.SLICE; - if (options.contains("limit")) - measurements += Measurements.LIMIT; - Calibration cal = null; - if (options.contains("raw")) { - cal = imp.getCalibration(); - imp.setCalibration(null); - } - ResultsTable rt = new ResultsTable(); - Analyzer analyzer = new Analyzer(imp, measurements, rt); - analyzer.measure(); - double value = Double.NaN; - try { - value = rt.getValue(measurement, 0); - } catch (Exception e) { - } - ; - if (cal != null) - imp.setCalibration(cal); - return value; - } - - /** - * Returns a reference to the "Results" window TextPanel. Opens the "Results" - * window if it is currently not open. Returns null if the "ImageJ" window is - * not open. - */ - public static TextPanel getTextPanel() { - if (textPanel == null && ij != null) - showResults(); - return textPanel; - } - - /** - * TextWindow calls this method with a null argument when the "Results" window - * is closed. - */ - public static void setTextPanel(TextPanel tp) { - textPanel = tp; - } - - /** Displays a "no images are open" dialog box. */ - public static void noImage() { - String msg = "There are no images open"; - if (macroInterpreter != null) { - macroInterpreter.abort(msg); - macroInterpreter = null; - } else - error("No Image", msg); - } - - /** Displays an "out of memory" message to the "Log" window. */ - public static void outOfMemory(String name) { - Undo.reset(); - System.gc(); - lastErrorMessage = "out of memory"; - String tot = Runtime.getRuntime().maxMemory() / 1048576L + "MB"; - if (!memMessageDisplayed) - log(">>>>>>>>>>>>>>>>>>>>>>>>>>>"); - log(""); - if (!memMessageDisplayed) { - log(""); - log(""); - log("Options>Memory & Threads command.>"); - log(">>>>>>>>>>>>>>>>>>>>>>>>>>>"); - memMessageDisplayed = true; - } - Macro.abort(); - } - - /** - * Updates the progress bar, where 0<=progress<=1.0. The progress bar is not - * shown in BatchMode and erased if progress>=1.0. The progress bar is updated - * only if more than 90 ms have passes since the last call. Does nothing if the - * ImageJ window is not present. - */ - public static void showProgress(double progress) { - if (progressBar != null) - progressBar.show(progress, false); - } - - /** - * Updates the progress bar, where the length of the bar is set to ( - * (currentValue+1)/finalValue of the maximum bar length. The bar - * is erased if currentValue>=finalValue. The bar is updated - * only if more than 90 ms have passed since the last call. Displays subordinate - * progress bars as dots if 'currentIndex' is negative (example: - * Plugins/Utilities/Benchmark). - */ - public static void showProgress(int currentIndex, int finalIndex) { - if (progressBar != null) { - progressBar.show(currentIndex, finalIndex); - if (currentIndex == finalIndex) - progressBar.setBatchMode(false); - } - } - - /** - * Displays a message in a dialog box titled "Message". Writes the Java console - * if ImageJ is not present. - */ - public static void showMessage(String msg) { - showMessage("Message", msg); - } - - /** - * Displays a message in a dialog box with the specified title. Displays HTML - * formatted text if 'msg' starts with "". There are examples at - * "http://imagej.net/ij/macros/HtmlDialogDemo.txt". Writes to the Java - * console if ImageJ is not present. - */ - public static void showMessage(String title, String msg) { - /* Changed for Bio7! */ - - if (ij != null) { - if (msg != null && (msg.startsWith("") || msg.startsWith(""))) { - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - - SwingUtilities.invokeLater(new Runnable() { - // !! - public void run() { - HTMLDialog hd = new HTMLDialog(title, msg); - - if (isMacro() && hd.escapePressed()) - throw new RuntimeException(Macro.MACRO_CANCELED); - } - }); - } - }); - } else { - /*Already wrapped in dis.syncExec!*/ - MessageDialog md = new MessageDialog(ij, title, msg); - if (isMacro() && md.escapePressed()) - throw new RuntimeException(Macro.MACRO_CANCELED); - } - IJ.wait(25); // fix GenericDialog non-editable text field - } else - System.out.println(msg); - - } - - /** - * Displays a message in a dialog box titled "ImageJ". If a macro or JavaScript - * is running, it is aborted. Writes to the Java console if the ImageJ window is - * not present. - */ - - public static void error(String msg) { - error(null, msg); - if (Thread.currentThread().getName().endsWith("JavaScript")) - throw new RuntimeException(Macro.MACRO_CANCELED); - else - Macro.abort(); - } - - /** - * Displays a message in a dialog box with the specified title. If a macro or - * JavaScript is running, it is aborted. Writes to the Java console if the - * ImageJ window is not present. - */ - public static void error(String title, String msg) { - if (macroInterpreter != null) { - macroInterpreter.abort(msg); - macroInterpreter = null; - return; - } - if (msg != null && msg.endsWith(Macro.MACRO_CANCELED)) - return; - String title2 = title != null ? title : "ImageJ"; - boolean abortMacro = title != null; - lastErrorMessage = msg; - if (redirectErrorMessages) { - IJ.log(title2 + ": " + msg); - if (abortMacro && (title.contains("Open") || title.contains("Reader"))) - abortMacro = false; - } else - showMessage(title2, msg); - redirectErrorMessages = false; - if (abortMacro) - Macro.abort(); - } - - /** - * Aborts any currently running JavaScript, or use IJ.error(string) to abort a - * JavaScript with a message. - */ - public static void exit() { - if (Thread.currentThread().getName().endsWith("JavaScript")) - throw new RuntimeException(Macro.MACRO_CANCELED); - } - - /** - * Returns the last error message written by IJ.error() or null if there was no - * error since the last time this method was called. - * - * @see #error(String) - */ - public static String getErrorMessage() { - String msg = lastErrorMessage; - lastErrorMessage = null; - return msg; - } - - /** - * Displays a message in a dialog box with the specified title. Returns false if - * the user pressed "Cancel". - */ - public static boolean showMessageWithCancel(String title, String msg) { - GenericDialog gd = new GenericDialog(title); - gd.addMessage(msg); - gd.showDialog(); - return !gd.wasCanceled(); - } - - public static final int CANCELED = Integer.MIN_VALUE; - - /** - * Allows the user to enter a number in a dialog box. Returns the value - * IJ.CANCELED (-2,147,483,648) if the user cancels the dialog box. Returns - * 'defaultValue' if the user enters an invalid number. - */ - public static double getNumber(String prompt, double defaultValue) { - GenericDialog gd = new GenericDialog(""); - int decimalPlaces = (int) defaultValue == defaultValue ? 0 : 2; - gd.addNumericField(prompt, defaultValue, decimalPlaces); - gd.showDialog(); - if (gd.wasCanceled()) - return CANCELED; - double v = gd.getNextNumber(); - if (gd.invalidNumber()) - return defaultValue; - else - return v; - } - - /** - * Allows the user to enter a string in a dialog box. Returns "" if the user - * cancels the dialog box. - */ - public static String getString(String prompt, String defaultString) { - GenericDialog gd = new GenericDialog(""); - gd.addStringField(prompt, defaultString, 20); - gd.showDialog(); - if (gd.wasCanceled()) - return ""; - return gd.getNextString(); - } - - /** Delays 'msecs' milliseconds. */ - public static void wait(int msecs) { - try { - Thread.sleep(msecs); - } catch (InterruptedException e) { - } - } - - /** Emits an audio beep. */ - public static void beep() { - java.awt.Toolkit.getDefaultToolkit().beep(); - } - - /** - * Returns a string something like "64K of 256MB (25%)" that shows how much of - * the available memory is in use. This is the string displayed when the user - * clicks in the status bar. - */ - public static String freeMemory() { - long inUse = currentMemory(); - String inUseStr = inUse < 10000 * 1024 ? inUse / 1024L + "K" : inUse / 1048576L + "MB"; - String maxStr = ""; - long max = maxMemory(); - if (max > 0L) { - double percent = inUse * 100 / max; - maxStr = " of " + max / 1048576L + "MB (" + (percent < 1.0 ? "<1" : d2s(percent, 0)) + "%)"; - } - return inUseStr + maxStr; - } - - /** Returns the amount of memory currently being used by ImageJ. */ - public static long currentMemory() { - long freeMem = Runtime.getRuntime().freeMemory(); - long totMem = Runtime.getRuntime().totalMemory(); - return totMem - freeMem; - } - - /** - * Returns the maximum amount of memory available to ImageJ or zero if ImageJ is - * unable to determine this limit. - */ - public static long maxMemory() { - if (maxMemory == 0L) { - Memory mem = new Memory(); - maxMemory = mem.getMemorySetting(); - if (maxMemory == 0L) - maxMemory = mem.maxMemory(); - } - return maxMemory; - } - - public static void showTime(ImagePlus imp, long start, String str) { - showTime(imp, start, str, 1); - } - - public static void showTime(ImagePlus imp, long start, String str, int nslices) { - if (Interpreter.isBatchMode()) - return; - double seconds = (System.currentTimeMillis() - start) / 1000.0; - if (seconds <= 0.5 && macroRunning()) - return; - double pixels = (double) imp.getWidth() * imp.getHeight(); - double rate = pixels * nslices / seconds; - String str2; - if (rate > 1000000000.0) - str2 = ""; - else if (rate < 1000000.0) - str2 = ", " + d2s(rate, 0) + " pixels/second"; - else - str2 = ", " + d2s(rate / 1000000.0, 1) + " million pixels/second"; - showStatus(str + seconds + " seconds" + str2); - } - - /** Experimental */ - public static String time(ImagePlus imp, long startNanoTime) { - double planes = imp.getStackSize(); - double seconds = (System.nanoTime() - startNanoTime) / 1000000000.0; - double mpixels = imp.getWidth() * imp.getHeight() * planes / 1000000.0; - String time = seconds < 1.0 ? d2s(seconds * 1000.0, 0) + " ms" : d2s(seconds, 1) + " seconds"; - return time + ", " + d2s(mpixels / seconds, 1) + " million pixels/second"; - } - - /** - * Converts a number to a formatted string using 2 digits to the right of the - * decimal point. - */ - public static String d2s(double n) { - return d2s(n, 2); - } - - /** - * Converts a number to a rounded formatted string. The 'decimalPlaces' argument - * specifies the number of digits to the right of the decimal point (0-9). Uses - * scientific notation if 'decimalPlaces is negative. - */ - public static String d2s(double n, int decimalPlaces) { - if (Double.isNaN(n) || Double.isInfinite(n)) - return "" + n; - if (n == Float.MAX_VALUE) // divide by 0 in FloatProcessor - return "3.4e38"; - double np = n; - if (n < 0.0) - np = -n; - if (decimalPlaces < 0) - synchronized (IJ.class) { - decimalPlaces = -decimalPlaces; - if (decimalPlaces > 9) - decimalPlaces = 9; - if (sf == null) { - if (dfs == null) - dfs = new DecimalFormatSymbols(Locale.US); - sf = new DecimalFormat[10]; - sf[1] = new DecimalFormat("0.0E0", dfs); - sf[2] = new DecimalFormat("0.00E0", dfs); - sf[3] = new DecimalFormat("0.000E0", dfs); - sf[4] = new DecimalFormat("0.0000E0", dfs); - sf[5] = new DecimalFormat("0.00000E0", dfs); - sf[6] = new DecimalFormat("0.000000E0", dfs); - sf[7] = new DecimalFormat("0.0000000E0", dfs); - sf[8] = new DecimalFormat("0.00000000E0", dfs); - sf[9] = new DecimalFormat("0.000000000E0", dfs); - } - return sf[decimalPlaces].format(n); // use scientific notation - } - if (decimalPlaces < 0) - decimalPlaces = 0; - if (decimalPlaces > 9) - decimalPlaces = 9; - - return df[decimalPlaces].format(n); - } - - /** - * Converts a number to a rounded formatted string. The 'significantDigits' - * argument specifies the minimum number of significant digits, which is also - * the preferred number of digits behind the decimal. Fewer decimals are shown - * if the number would have more than 'maxDigits'. Exponential notation is used - * if more than 'maxDigits' would be needed. - */ - public static String d2s(double x, int significantDigits, int maxDigits) { - double log10 = Math.log10(Math.abs(x)); - double roundErrorAtMax = 0.223 * Math.pow(10, -maxDigits); - int magnitude = (int) Math.ceil(log10 + roundErrorAtMax); - int decimals = x == 0 ? 0 : maxDigits - magnitude; - if (decimals < 0 || magnitude < significantDigits + 1 - maxDigits) - return IJ.d2s(x, -significantDigits); // exp notation for large and - // small numbers - else { - if (decimals > significantDigits) - decimals = Math.max(significantDigits, decimals - maxDigits + significantDigits); - return IJ.d2s(x, decimals); - } - } - - /** Pad 'n' with leading zeros to the specified number of digits. */ - public static String pad(int n, int digits) { - String str = "" + n; - while (str.length() < digits) - str = "0" + str; - return str; - } - - /** Pad 's' with leading zeros to the specified number of digits. */ - public static String pad(String s, int digits) { - String str = "" + s; - while (str.length() < digits) - str = "0" + str; - return str; - } - - /** Obsolete */ - public static void register(Class c) { - if (ij != null) - ij.register(c); - } - - /** Returns true if the space bar is down. */ - public static boolean spaceBarDown() { - return spaceDown; - } - - /** Returns true if the control key is down. */ - public static boolean controlKeyDown() { - return controlDown; - } - - /** Returns true if the alt key is down. */ - public static boolean altKeyDown() { - return altDown; - } - - /** Returns true if the shift key is down. */ - public static boolean shiftKeyDown() { - return shiftDown; - } - - /* Sets the specified key "down", where 'key' - * is KeyEvent.VK_CONTROL, KeyEvent.VK_META, - * KeyEvent.VK_ALT, KeyEvent.VK_SHIFT, - * KeyEvent.VK_SPACE or KeyEvent.VK_ESCAPE. - */ - public static void setKeyDown(int key) { - switch (key) { - case KeyEvent.VK_CONTROL: - controlDown = true; - break; - case KeyEvent.VK_META: - if (isMacintosh()) - controlDown = true; - break; - case KeyEvent.VK_ALT: - altDown = true; - updateStatus(); - break; - case KeyEvent.VK_SHIFT: - shiftDown = true; - if (debugMode) - beep(); - break; - case KeyEvent.VK_SPACE: { - spaceDown = true; - ImageWindow win = WindowManager.getCurrentWindow(); - // if (win != null) win.getCanvas().setCursor(-1, -1, -1, -1); - break; - } - case KeyEvent.VK_ESCAPE: { - escapePressed = true; - break; - } - } - } - - /* Sets the specified key "up", where 'key' - * is KeyEvent.VK_CONTROL, KeyEvent.VK_META, - * KeyEvent.VK_ALT, KeyEvent.VK_SHIFT, - * KeyEvent.VK_SPACE or IJ.ALL_KEYS (-1). - */ - public static void setKeyUp(int key) { - switch (key) { - case KeyEvent.VK_CONTROL: - controlDown = false; - break; - case KeyEvent.VK_META: - if (isMacintosh()) - controlDown = false; - break; - case KeyEvent.VK_ALT: - altDown = false; - updateStatus(); - break; - case KeyEvent.VK_SHIFT: - shiftDown = false; - if (debugMode) - beep(); - break; - - case KeyEvent.VK_SPACE: - spaceDown = false; - ImageWindow win = WindowManager.getCurrentWindow(); - // if (win != null) win.getCanvas().setCursor(-1, -1, -1, -1); - break; - case ALL_KEYS: - shiftDown = controlDown = altDown = spaceDown = false; - break; - } - } - - private static void updateStatus() { - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp != null) { - Roi roi = imp.getRoi(); - if (roi != null && imp.getCalibration().scaled()) { - roi.showStatus(); - } - } - } - - public static void setInputEvent(InputEvent e) { - altDown = e.isAltDown(); - shiftDown = e.isShiftDown(); - } - - /** Returns true if this machine is a Macintosh. */ - public static boolean isMacintosh() { - return isMac; - } - - /** Returns true if this machine is a Macintosh running OS X. */ - public static boolean isMacOSX() { - return isMacintosh(); - } - - /** Returns true if this machine is running Windows. */ - public static boolean isWindows() { - return isWin; - } - - /** Returns the Java version (6, 7, 8, 9, 10, etc.). */ - public static int javaVersion() { - return javaVersion; - } - - /** Always returns true. */ - public static boolean isJava2() { - return true; - } - - /** Always returns true. */ - public static boolean isJava14() { - return true; - } - - /** Always returns true. */ - public static boolean isJava15() { - return true; - } - - /** Returns true if ImageJ is running on a Java 1.6 or greater JVM. */ - public static boolean isJava16() { - return javaVersion >= 6; - } - - /** Returns true if ImageJ is running on a Java 1.7 or greater JVM. */ - public static boolean isJava17() { - return javaVersion >= 7; - } - - /** Returns true if ImageJ is running on a Java 1.8 or greater JVM. */ - public static boolean isJava18() { - return javaVersion >= 8; - } - - /** Returns true if ImageJ is running on a Java 1.9 or greater JVM. */ - public static boolean isJava19() { - return javaVersion >= 9; - } - - /** Returns true if ImageJ is running on Linux. */ - public static boolean isLinux() { - return isLinux; - } - - /** Obsolete; always returns false. */ - public static boolean isVista() { - return false; - } - - /** Returns true if ImageJ is running a 64-bit version of Java. */ - public static boolean is64Bit() { - if (osarch == null) - osarch = System.getProperty("os.arch"); - return osarch != null && osarch.indexOf("64") != -1; - } - - /** - * Displays an error message and returns true if the ImageJ version is less than - * the one specified. - */ - public static boolean versionLessThan(String version) { - boolean lessThan = ImageJ.VERSION.compareTo(version) < 0; - if (lessThan) - error("This plugin or macro requires ImageJ " + version - + " or later. Use\nHelp>Update ImageJ to upgrade to the latest version."); - return lessThan; - } - - /** - * Displays a "Process all images?" dialog. Returns - * 'flags'+PlugInFilter.DOES_STACKS if the user selects "Yes", 'flags' if the - * user selects "No" and PlugInFilter.DONE if the user selects "Cancel". - */ - public static int setupDialog(ImagePlus imp, int flags) { - if (imp == null || (ij != null && ij.hotkey)) { - if (ij != null) - ij.hotkey = false; - return flags; - } - int stackSize = imp.getStackSize(); - if (stackSize > 1) { - String macroOptions = Macro.getOptions(); - if (imp.isComposite() && ((CompositeImage) imp).getMode() == IJ.COMPOSITE) { - if (macroOptions == null || !macroOptions.contains("slice")) - return flags | PlugInFilter.DOES_STACKS; - } - if (macroOptions != null) { - if (macroOptions.indexOf("stack ") >= 0) - return flags | PlugInFilter.DOES_STACKS; - else - return flags; - } - if (hideProcessStackDialog) - return flags; - String note = ((flags & PlugInFilter.NO_CHANGES) == 0) ? " There is\nno Undo if you select \"Yes\"." : ""; - YesNoCancelDialog d = new YesNoCancelDialog(getInstance(), "Process Stack?", - "Process all " + stackSize + " images?" + note); - if (d.cancelPressed()) - return PlugInFilter.DONE; - else if (d.yesPressed()) { - if (imp.getStack().isVirtual() && ((flags & PlugInFilter.NO_CHANGES) == 0)) { - int size = (stackSize * imp.getWidth() * imp.getHeight() * imp.getBytesPerPixel() + 524288) - / 1048576; - String msg = "Use the Process>Batch>Virtual Stack command\n" - + "to process a virtual stack or convert it into a\n" - + "normal stack using Image>Duplicate, which\n" + "will require " + size - + "MB of additional memory."; - error(msg); - return PlugInFilter.DONE; - } - if (IJ.recording()) - Recorder.recordOption("stack"); - return flags | PlugInFilter.DOES_STACKS; - } - if (IJ.recording()) - Recorder.recordOption("slice"); - } - return flags; - } - - /** - * Creates a rectangular selection. Removes any existing selection if width or - * height are less than 1. - */ - public static void makeRectangle(int x, int y, int width, int height) { - if (width <= 0 || height < 0) - getImage().deleteRoi(); - else { - ImagePlus img = getImage(); - if (Interpreter.isBatchMode()) - img.setRoi(new Roi(x, y, width, height), false); - else - img.setRoi(x, y, width, height); - } - } - - /** Creates a subpixel resolution rectangular selection. */ - public static void makeRectangle(double x, double y, double width, double height) { - if (width <= 0 || height < 0) - getImage().deleteRoi(); - else - getImage().setRoi(new Roi(x, y, width, height), !Interpreter.isBatchMode()); - } - - /** - * Creates an oval selection. Removes any existing selection if width or height - * are less than 1. - */ - public static void makeOval(int x, int y, int width, int height) { - if (width <= 0 || height < 0) - getImage().deleteRoi(); - else { - ImagePlus img = getImage(); - img.setRoi(new OvalRoi(x, y, width, height)); - } - } - - /** Creates an subpixel resolution oval selection. */ - public static void makeOval(double x, double y, double width, double height) { - if (width <= 0 || height < 0) - getImage().deleteRoi(); - else - getImage().setRoi(new OvalRoi(x, y, width, height)); - } - - /** Creates a straight line selection. */ - public static void makeLine(int x1, int y1, int x2, int y2) { - getImage().setRoi(new Line(x1, y1, x2, y2)); - } - - /** Creates a straight line selection using floating point coordinates. */ - public static void makeLine(double x1, double y1, double x2, double y2) { - getImage().setRoi(new Line(x1, y1, x2, y2)); - } - - /** Creates a point selection using integer coordinates.. */ - public static void makePoint(int x, int y) { - ImagePlus img = getImage(); - Roi roi = img.getRoi(); - if (shiftKeyDown() && roi != null && roi.getType() == Roi.POINT) { - ((PointRoi)roi).addUserPoint(null, x, y); - IJ.setKeyUp(KeyEvent.VK_SHIFT); - } else if (altKeyDown() && roi != null && roi.getType() == Roi.POINT) { - ((PolygonRoi) roi).deleteHandle(x, y); - IJ.setKeyUp(KeyEvent.VK_ALT); - } else - img.setRoi(new PointRoi(x, y)); - } - - /** Creates a point selection using floating point coordinates. */ - public static void makePoint(double x, double y) { - ImagePlus img = getImage(); - Roi roi = img.getRoi(); - if (shiftKeyDown() && roi != null && roi.getType() == Roi.POINT) { - ((PointRoi)roi).addUserPoint(null, x, y); - IJ.setKeyUp(KeyEvent.VK_SHIFT); - } else if (altKeyDown() && roi != null && roi.getType() == Roi.POINT) { - ((PolygonRoi) roi).deleteHandle(x, y); - IJ.setKeyUp(KeyEvent.VK_ALT); - } else - img.setRoi(new PointRoi(x, y)); - } - - /** Creates an Roi. */ - public static Roi Roi(double x, double y, double width, double height) { - return new Roi(x, y, width, height); - } - - /** Creates an OvalRoi. */ - public static OvalRoi OvalRoi(double x, double y, double width, double height) { - return new OvalRoi(x, y, width, height); - } - - /** - * Sets the display range (minimum and maximum displayed pixel values) of the - * current image. - */ - public static void setMinAndMax(double min, double max) { - setMinAndMax(getImage(), min, max, 7); - } - - /** - * Sets the display range (minimum and maximum displayed pixel values) of the - * specified image. - */ - public static void setMinAndMax(ImagePlus img, double min, double max) { - setMinAndMax(img, min, max, 7); - } - - /** - * Sets the minimum and maximum displayed pixel values on the specified RGB - * channels, where 4=red, 2=green and 1=blue. - */ - public static void setMinAndMax(double min, double max, int channels) { - setMinAndMax(getImage(), min, max, channels); - } - - private static void setMinAndMax(ImagePlus img, double min, double max, int channels) { - Calibration cal = img.getCalibration(); - min = cal.getRawValue(min); - max = cal.getRawValue(max); - if (channels == 7) - img.setDisplayRange(min, max); - else - img.setDisplayRange(min, max, channels); - img.updateAndDraw(); - } - - /** - * Resets the minimum and maximum displayed pixel values of the current image to - * be the same as the min and max pixel values. - */ - public static void resetMinAndMax() { - resetMinAndMax(getImage()); - } - - /** - * Resets the minimum and maximum displayed pixel values of the specified image - * to be the same as the min and max pixel values. - */ - public static void resetMinAndMax(ImagePlus img) { - img.resetDisplayRange(); - img.updateAndDraw(); - } - - /** - * Sets the lower and upper threshold levels and displays the image using red to - * highlight thresholded pixels. May not work correctly on 16 and 32 bit images - * unless the display range has been reset using IJ.resetMinAndMax(). - */ - public static void setThreshold(double lowerThreshold, double upperThresold) { - setThreshold(lowerThreshold, upperThresold, null); - } - - /** - * Sets the lower and upper threshold levels and displays the image using the - * specified displayMode ("Red", "Black & White", "Over/Under" or - * "No Update"). - */ - public static void setThreshold(double lowerThreshold, double upperThreshold, String displayMode) { - setThreshold(getImage(), lowerThreshold, upperThreshold, displayMode); - } - - /** Sets the lower and upper threshold levels of the specified image. */ - public static void setThreshold(ImagePlus img, double lowerThreshold, double upperThreshold) { - setThreshold(img, lowerThreshold, upperThreshold, "Red"); - } - - /** - * Sets the lower and upper threshold levels of the specified image and updates - * the display using the specified displayMode ("Red", "Black & - * White", "Over/Under" or "No Update"). With calibrated images, - * 'lowerThreshold' and 'upperThreshold' must be density calibrated values. Use - * setRawThreshold() to set the threshold using raw (uncalibrated) values. - */ - public static void setThreshold(ImagePlus img, double lowerThreshold, double upperThreshold, String displayMode) { - Calibration cal = img.getCalibration(); - if (displayMode == null || !displayMode.contains("raw")) { - lowerThreshold = cal.getRawValue(lowerThreshold); - upperThreshold = cal.getRawValue(upperThreshold); - } - setRawThreshold(img, lowerThreshold, upperThreshold, displayMode); - } - - /** - * This is a version of setThreshold() that uses raw (uncalibrated) values in - * the range 0-255 for 8-bit images and 0-65535 for 16-bit images and the "Red" - * LUT display mode. - */ - public static void setRawThreshold(ImagePlus img, double lowerThreshold, double upperThreshold) { - setRawThreshold(img, lowerThreshold, upperThreshold, null); - } - - /** - * This is a version of setThreshold() that always uses raw (uncalibrated) - * values * in the range 0-255 for 8-bit images and 0-65535 for 16-bit images. - */ - - public static void setRawThreshold(ImagePlus img, double lowerThreshold, double upperThreshold, - String displayMode) { - int mode = ImageProcessor.RED_LUT; - if (displayMode != null) { - displayMode = displayMode.toLowerCase(Locale.US); - if (displayMode.contains("black")) - mode = ImageProcessor.BLACK_AND_WHITE_LUT; - else if (displayMode.contains("over")) - mode = ImageProcessor.OVER_UNDER_LUT; - else if (displayMode.contains("no")) - mode = ImageProcessor.NO_LUT_UPDATE; - } - img.getProcessor().setThreshold(lowerThreshold, upperThreshold, mode); - if (mode != ImageProcessor.NO_LUT_UPDATE && img.getWindow() != null) { - img.getProcessor().setLutAnimation(true); - img.updateAndDraw(); - ThresholdAdjuster.update(); - } - } - /** Replaced by ImagePlus.setAutoThreshold(). */ - public static void setAutoThreshold(ImagePlus imp, String method) { - ImageProcessor ip = imp.getProcessor(); - if (ip instanceof ColorProcessor) - throw new IllegalArgumentException("Non-RGB image required"); - ip.setRoi(imp.getRoi()); - if (method != null) { - try { - if (method.indexOf("stack") != -1) - setStackThreshold(imp, ip, method); - else - ip.setAutoThreshold(method); - } catch (Exception e) { - log(e.getMessage()); - } - } else - ip.setAutoThreshold(ImageProcessor.ISODATA2, ImageProcessor.RED_LUT); - ThresholdAdjuster.setMethod(method); - imp.updateAndDraw(); - } - - private static void setStackThreshold(ImagePlus imp, ImageProcessor ip, String method) { - boolean darkBackground = method.contains("dark"); - boolean histo16 = imp.getBitDepth()==16 && method.contains("16"); - //IJ.log("setStackThreshold: "+histo16+" "+method); - boolean addOne = !method.contains("16"); - int measurements = Analyzer.getMeasurements(); - Analyzer.setMeasurements(Measurements.AREA + Measurements.MIN_MAX); - ImageStatistics stats = new StackStatistics(imp); - Analyzer.setMeasurements(measurements); - AutoThresholder thresholder = new AutoThresholder(); - double min = 0.0, max = 255.0; - if (imp.getBitDepth() != 8) { - min = stats.min; - max = stats.max; - } - int[] histogram = stats.histogram; - if (histo16) - histogram = stats.histogram16; - int threshold = thresholder.getThreshold(method, histogram); - double lower, upper; - double tmax = 255.0; - if (histogram.length>256) - tmax = 65535.0; - if (darkBackground) { - if (ip.isInvertedLut()) { - lower = 0.0; - upper = threshold; - } else { - {lower=threshold+(addOne?1:0); upper=tmax;} - } - } else { - if (ip.isInvertedLut()) { - {lower=threshold+(addOne?1:0); upper=tmax;} - } else { - lower = 0.0; - upper = threshold; - } - } - if (!histo16) { - if (lower>255) lower = 255; - if (max>min) { - lower = min + (lower/255.0)*(max-min); - upper = min + (upper/255.0)*(max-min); - } else - lower = upper = min; - ip.setMinAndMax(min, max); - } - ip.setThreshold(lower, upper, ImageProcessor.RED_LUT); - imp.updateAndDraw(); - } - - /** Disables thresholding on the current image. */ - public static void resetThreshold() { - resetThreshold(getImage()); - } - - /** Disables thresholding on the specified image. */ - public static void resetThreshold(ImagePlus img) { - ImageProcessor ip = img.getProcessor(); - ip.resetThreshold(); - ip.setLutAnimation(true); - img.updateAndDraw(); - ThresholdAdjuster.update(); - } - - /** - * For IDs less than zero, activates the image with the specified ID. For IDs - * greater than zero, activates the Nth image. - */ - public static void selectWindow(int id) { - if (id > 0) - id = WindowManager.getNthImageID(id); - ImagePlus imp = WindowManager.getImage(id); - if (imp == null) - error("Macro Error", "Image " + id + " not found or no images are open."); - if (Interpreter.isBatchMode()) { - ImagePlus impT = WindowManager.getTempCurrentImage(); - ImagePlus impC = WindowManager.getCurrentImage(); - if (impC != null && impC != imp && impT != null) - impC.saveRoi(); - WindowManager.setTempCurrentImage(imp); - Interpreter.activateImage(imp); - WindowManager.setWindow(null); - } else { - if (imp == null) - return; - ImageWindow win = imp.getWindow(); - if (win != null) { - win.toFront(); - win.setState(Frame.NORMAL); - /*Changed for Bio7 to open the specified tab!*/ - IJTabs.setActiveTabWindow(win); - - WindowManager.setWindow(win); - } - long start = System.currentTimeMillis(); - // timeout after 1 second unless current thread is event dispatch thread - // thread - String thread = Thread.currentThread().getName(); - /*We run in an Eclipse job here so we don't have an "EventQueue"*/ - // int timeout = thread != null && thread.indexOf("EventQueue") != -1 ? 0 : - // 1000; - int timeout = thread != null ? 0 : 1000; - if (IJ.isMacOSX() && IJ.isJava18() && timeout > 0) - timeout = 250; // work around OS X/Java 8 window activation bug - while (true) { - wait(10); - imp = WindowManager.getCurrentImage(); - if (imp != null && imp.getID() == id) - return; // specified image is now active - if ((System.currentTimeMillis() - start) > timeout && win != null) { - WindowManager.setCurrentWindow(win); - return; - } - } - } - } - - /** Activates the window with the specified title. */ - public static void selectWindow(String title) { - if (title.equals("ImageJ") && ij != null) { - ij.toFront(); - return; - } - long start = System.currentTimeMillis(); - while (System.currentTimeMillis() - start < 3000) { // 3 sec timeout - Window win = WindowManager.getWindow(title); - if (win != null && !(win instanceof ImageWindow)) { - selectWindow(win); - return; - } - int[] wList = WindowManager.getIDList(); - int len = wList != null ? wList.length : 0; - for (int i = 0; i < len; i++) { - ImagePlus imp = WindowManager.getImage(wList[i]); - if (imp != null) { - if (imp.getTitle().equals(title)) { - selectWindow(imp.getID()); - return; - } - } - } - wait(10); - } - error("Macro Error", "No window with the title \"" + title + "\" found."); - } - - static void selectWindow(Window win) { - /*Changed for Bio7 to JFrame!*/ - if (win instanceof JFrame) { - ((JFrame) win).toFront(); - // IJTabs.setActiveTabWindow(win); - } else if (win instanceof Frame) { - ((Frame) win).toFront(); - ((Frame) win).setState(Frame.NORMAL); - } else - ((Dialog) win).toFront(); - long start = System.currentTimeMillis(); - while (true) { - wait(10); - if (WindowManager.getActiveWindow() == win) - return; // specified window is now in front - if ((System.currentTimeMillis() - start) > 100) { - WindowManager.setWindow(win); - return; // 1 second timeout - } - } - } - - /** Sets the foreground color. */ - public static void setForegroundColor(int red, int green, int blue) { - setColor(red, green, blue, true); - } - - /** Sets the background color. */ - public static void setBackgroundColor(int red, int green, int blue) { - setColor(red, green, blue, false); - } - - static void setColor(int red, int green, int blue, boolean foreground) { - Color c = Colors.toColor(red, green, blue); - if (foreground) { - Toolbar.setForegroundColor(c); - ImagePlus img = WindowManager.getCurrentImage(); - if (img != null) - img.getProcessor().setColor(c); - } else - Toolbar.setBackgroundColor(c); - } - - /** - * Switches to the specified tool, where id = Toolbar.RECTANGLE (0), - * Toolbar.OVAL (1), etc. - */ - public static void setTool(int id) { - Toolbar.getInstance().setTool(id); - } - - /** - * Switches to the specified tool, where 'name' is "rect", "elliptical", - * "brush", etc. Returns 'false' if the name is not recognized. - */ - public static boolean setTool(String name) { - return Toolbar.getInstance().setTool(name); - } - - /** Returns the name of the current tool. */ - public static String getToolName() { - return Toolbar.getToolName(); - } - - /** - * Equivalent to clicking on the current image at (x,y) with the wand tool. - * Returns the number of points in the resulting ROI. - */ - public static int doWand(int x, int y) { - return doWand(getImage(), x, y, 0, null); - } - - /** - * Traces the boundary of the area with pixel values within 'tolerance' of the - * value of the pixel at the starting location. 'tolerance' is in uncalibrated - * units. 'mode' can be "4-connected", "8-connected" or "Legacy". "Legacy" is - * for compatibility with previous versions of ImageJ; it is ignored if - * 'tolerance' > 0. - */ - public static int doWand(int x, int y, double tolerance, String mode) { - return doWand(getImage(), x, y, tolerance, mode); - } - - /** This version of doWand adds an ImagePlus argument. */ - public static int doWand(ImagePlus img, int x, int y, double tolerance, String mode) { - ImageProcessor ip = img.getProcessor(); - if ((img.getType() == ImagePlus.GRAY32) && Double.isNaN(ip.getPixelValue(x, y))) - return 0; - int imode = Wand.LEGACY_MODE; - boolean smooth = false; - if (mode != null) { - if (mode.startsWith("4")) - imode = Wand.FOUR_CONNECTED; - else if (mode.startsWith("8")) - imode = Wand.EIGHT_CONNECTED; - smooth = mode.contains("smooth"); - - } - Wand w = new Wand(ip); - if (!ip.isThreshold() || (ip.getLutUpdateMode()==ImageProcessor.NO_LUT_UPDATE&& tolerance>0.0)) { - w.autoOutline(x, y, tolerance, imode); - smooth = false; - } else { - w.autoOutline(x, y, ip.getMinThreshold(), ip.getMaxThreshold(), imode); - } - if (w.npoints > 0) { - Roi previousRoi = img.getRoi(); - Roi roi = new PolygonRoi(w.xpoints, w.ypoints, w.npoints, Roi.TRACED_ROI); - img.deleteRoi(); - img.setRoi(roi); - if (previousRoi != null) - roi.update(shiftKeyDown(), altKeyDown()); // add/subtract ROI to previous one if shift/alt key down - Roi roi2 = img.getRoi(); - if (smooth && roi2 != null && roi2.getType() == Roi.TRACED_ROI) { - Rectangle bounds = roi2.getBounds(); - if (bounds.width > 1 && bounds.height > 1) { - if (smoothMacro == null) - smoothMacro = BatchProcessor.openMacroFromJar("SmoothWandTool.txt"); - if (EventQueue.isDispatchThread()) - new MacroRunner(smoothMacro); // run on separate thread - else - Macro.eval(smoothMacro); - } - } - } - return w.npoints; - } - - /** - * Sets the transfer mode used by the Edit/Paste command, where mode is - * "Copy", "Blend", "Average", "Difference", "Transparent", "Transparent2", - * "AND", "OR", "XOR", "Add", "Subtract", "Multiply", or "Divide". - */ - public static void setPasteMode(String mode) { - Roi.setPasteMode(stringToPasteMode(mode)); - } - - public static int stringToPasteMode(String mode) { - if (mode == null) - return Blitter.COPY; - mode = mode.toLowerCase(Locale.US); - int m = Blitter.COPY; - if (mode.startsWith("ble") || mode.startsWith("ave")) - m = Blitter.AVERAGE; - else if (mode.startsWith("diff")) - m = Blitter.DIFFERENCE; - else if (mode.indexOf("zero") != -1) - m = Blitter.COPY_ZERO_TRANSPARENT; - else if (mode.startsWith("tran")) - m = Blitter.COPY_TRANSPARENT; - else if (mode.startsWith("and")) - m = Blitter.AND; - else if (mode.startsWith("or")) - m = Blitter.OR; - else if (mode.startsWith("xor")) - m = Blitter.XOR; - else if (mode.startsWith("sub")) - m = Blitter.SUBTRACT; - else if (mode.startsWith("add")) - m = Blitter.ADD; - else if (mode.startsWith("div")) - m = Blitter.DIVIDE; - else if (mode.startsWith("mul")) - m = Blitter.MULTIPLY; - else if (mode.startsWith("min")) - m = Blitter.MIN; - else if (mode.startsWith("max")) - m = Blitter.MAX; - return m; - } - - /** - * Returns a reference to the active image, or displays an error message and - * aborts the plugin or macro if no images are open. - */ - public static ImagePlus getImage() { - ImagePlus img = WindowManager.getCurrentImage(); - if (img == null) { - IJ.noImage(); - if (ij == null) - System.exit(0); - else - abort(); - } - return img; - } - - /** The macro interpreter uses this method to call getImage(). */ - public static ImagePlus getImage(Interpreter interpreter) { - macroInterpreter = interpreter; - ImagePlus imp = getImage(); - macroInterpreter = null; - return imp; - } - - /** - * Returns the active image or stack slice as an ImageProcessor, or displays an - * error message and aborts the plugin or macro if no images are open. - */ - public static ImageProcessor getProcessor() { - ImagePlus imp = IJ.getImage(); - return imp.getProcessor(); - } - - /** Switches to the specified stack slice, where 1<='slice'<=stack-size. */ - public static void setSlice(int slice) { - getImage().setSlice(slice); - } - - /** Returns the ImageJ version number as a string. */ - public static String getVersion() { - return ImageJ.VERSION; - } - - /** - * Returns the ImageJ version and build number as a String, for example - * "1.46n05", or 1.46n99 if there is no build number. - */ - public static String getFullVersion() { - String build = ImageJ.BUILD; - if (build.length() == 0) - build = "99"; - else if (build.length() == 1) - build = "0" + build; - return ImageJ.VERSION + build; - } - - /** - * Returns the path to the specified directory if title is "home" - * ("user.home"), "downloads", "startup", "imagej" (ImageJ directory), - * "plugins", "macros", "luts", "temp", "current", "default", "image" (directory - * active image was loaded from), "file" (directory most recently used to open - * or save a file), "cwd" (current working directory) or "preferences" (location - * of "IJ_Prefs.txt" file), otherwise displays a dialog and returns the path to - * the directory selected by the user. Returns null if the specified directory - * is not found or the user cancels the dialog box. Also aborts the macro if the - * user cancels the dialog box. - */ - public static String getDirectory(String title) { - String dir = null; - String title2 = title.toLowerCase(Locale.US); - if (title2.equals("plugins")) - dir = Menus.getPlugInsPath(); - else if (title2.equals("macros")) - dir = Menus.getMacrosPath(); - else if (title2.equals("luts")) { - String ijdir = Prefs.getImageJDir(); - if (ijdir != null) - dir = ijdir + "luts" + File.separator; - else - dir = null; - } else if (title2.equals("home")) - dir = System.getProperty("user.home"); - else if (title2.equals("downloads")) - dir = System.getProperty("user.home") + File.separator + "Downloads"; - else if (title2.equals("startup")) - dir = Prefs.getImageJDir(); - else if (title2.equals("imagej")) - dir = Prefs.getImageJDir(); - else if (title2.equals("current") || title2.equals("default")) - dir = OpenDialog.getDefaultDirectory(); - else if (title2.equals("preferences")) - dir = Prefs.getPrefsDir(); - else if (title2.equals("temp")) { - dir = System.getProperty("java.io.tmpdir"); - if (isMacintosh()) - dir = "/tmp/"; - } else if (title2.equals("image")) { - ImagePlus imp = WindowManager.getCurrentImage(); - FileInfo fi = imp != null ? imp.getOriginalFileInfo() : null; - if (fi != null && fi.directory != null) { - dir = fi.directory; - } else - dir = null; - } else if (title2.equals("file")) - dir = OpenDialog.getLastDirectory(); - else if (title2.equals("cwd")) - dir = System.getProperty("user.dir"); - else { - String defaultDir = OpenDialog.getDefaultDirectory(); - DirectoryChooser dc = new DirectoryChooser(title); - dir = dc.getDirectory(); - OpenDialog.setDefaultDirectory(defaultDir); - if (dir == null) - Macro.abort(); - - } - dir = addSeparator(dir); - return dir; - } - - public static String addSeparator(String path) { - if (path == null) - return null; - if (path.length() > 0 && !(path.endsWith(File.separator) || path.endsWith("/"))) { - if (IJ.isWindows() && path.contains(File.separator)) - path += File.separator; - else - path += "/"; - } - return path; - } - - /** Alias for getDirectory(). */ - public static String getDir(String title) { - return getDirectory(title); - } - - /** - * Displays an open file dialog and returns the path to the choosen file, or - * returns null if the dialog is canceled. - */ - public static String getFilePath(String dialogTitle) { - OpenDialog od = new OpenDialog(dialogTitle); - return od.getPath(); - } - - /** - * Displays a file open dialog box and then opens the tiff, dicom, fits, pgm, - * jpeg, bmp, gif, lut, roi, or text file selected by the user. Displays an - * error message if the selected file is not in one of the supported formats, or - * if it is not found. - */ - public static void open() { - open(null); - } - - /** - * Opens and displays a tiff, dicom, fits, pgm, jpeg, bmp, gif, lut, roi, or - * text file. Displays an error message if the specified file is not in one of - * the supported formats, or if it is not found. With 1.41k or later, opens - * images specified by a URL. - */ - public static void open(String path) { - if (ij == null && Menus.getCommands() == null) - init(); - Opener o = new Opener(); - macroRunning = true; - if (path == null || path.equals("")) - o.open(); - else - o.open(path); - macroRunning = false; - } - - /** Opens and displays the nth image in the specified tiff stack. */ - public static void open(String path, int n) { - if (ij == null && Menus.getCommands() == null) - init(); - ImagePlus imp = openImage(path, n); - if (imp != null) - imp.show(); - } - - /** - * Opens the specified file as a tiff, bmp, dicom, fits, pgm, gif, jpeg * or text image and returns an ImagePlus object if successful. - * Calls HandleExtraFileTypes plugin if the file type is not recognised. - * Displays a file open dialog if 'path' is null or an empty string. - * Note that 'path' can also be a URL. Some reader plugins, including - * the Bio-Formats plugin, display the image and return null. - * Use IJ.open() to display a file open dialog box. - * @see ij.io.Opener#openUsingBioFormats(String) - */ - public static ImagePlus openImage(String path) { - macroRunning = true; - ImagePlus imp = (new Opener()).openImage(path); - macroRunning = false; - return imp; - } - - /** Opens the nth image of the specified tiff stack. */ - public static ImagePlus openImage(String path, int n) { - Opener opener = new Opener(); - opener.doNotUseBioFormats(); - return opener.openImage(path, n); - } - - /** Opens the specified tiff file as a virtual stack. */ - public static ImagePlus openVirtual(String path) { - return FileInfoVirtualStack.openVirtual(path); - } - - /** - * Opens an image using a file open dialog and returns it as an ImagePlus - * object. - */ - public static ImagePlus openImage() { - return openImage(null); - } - - /** - * Opens a URL and returns the contents as a string. Returns "" - * if there an error, including host or file not found. - */ - public static String openUrlAsString(String url) { - // if (!trustManagerCreated && url.contains("nih.gov")) trustAllCerts(); - url = Opener.updateUrl(url); - if (debugMode) - log("OpenUrlAsString: " + url); - StringBuffer sb = null; - url = url.replaceAll(" ", "%20"); - try { - // if (url.contains("nih.gov")) addRootCA(); - URL u = new URL(url); - URLConnection uc = u.openConnection(); - long len = uc.getContentLength(); - if (len > 5242880L) - return ""; - InputStream in = u.openStream(); - BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF-8")); - sb = new StringBuffer(); - String line; - while ((line = br.readLine()) != null) - sb.append(line + "\n"); - in.close(); - } catch (Exception e) { - return (""); - } - if (sb != null) - return new String(sb); - else - return ""; - } - - /** - * Saves the current image, lookup table, selection or text window to the - * specified file path. The path must end in ".tif", ".jpg", ".gif", ".zip", - * ".raw", ".avi", ".bmp", ".fits", ".pgm", ".png", ".lut", ".roi" or ".txt". - */ - public static void save(String path) { - save(null, path); - } - - /** - * Saves the specified image, lookup table or selection to the specified file - * path. The file path should end with ".tif", ".jpg", ".gif", ".zip", ".raw", - * ".avi", ".bmp", ".fits", ".pgm", ".png", ".lut", ".roi" or ".txt". The - * specified image is saved in TIFF format if there is no extension. - */ - - public static void save(ImagePlus imp, String path) { - ImagePlus imp2 = imp; - if (imp2 == null) - imp2 = WindowManager.getCurrentImage(); - int dotLoc = path.lastIndexOf('.'); - if (dotLoc == -1 && imp2 != null) { - path = path + ".tif"; // save as TIFF if file name does not have an - // extension - dotLoc = path.lastIndexOf('.'); - } - - if (dotLoc != -1) { - - String title = imp2 != null ? imp2.getTitle() : null; - saveAs(imp, path.substring(dotLoc + 1), path); - if (title != null) - imp2.setTitle(title); - } else - error("The file path passed to IJ.save() method or save()\nmacro function is missing the required extension.\n \n\"" - + path + "\""); - } - - /* - * Saves the active image, lookup table, selection, measurement results, - * selection XY coordinates or text window to the specified file path. The - * format argument must be "tiff", "jpeg", "gif", "zip", "raw", "avi", "bmp", - * "fits", "pgm", "png", "text image", "lut", "selection", "measurements", - * "xy Coordinates" or "text". If path is null or an emply string, - * a file save dialog is displayed. - */ - public static void saveAs(String format, String path) { - saveAs(null, format, path); - } - - /* - * Saves the specified image. The format argument must be "tiff", "jpeg", "gif", - * "zip", "raw", "avi", "bmp", "fits", "pgm", "png", "text image", "lut", - * "selection" or "xy Coordinates". - */ - public static void saveAs(ImagePlus imp, String format, String path) { - if (format == null) - return; - if (path != null && path.length() == 0) - path = null; - format = format.toLowerCase(Locale.US); - Roi roi2 = imp != null ? imp.getRoi() : null; - if (roi2 != null) - roi2.endPaste(); - if (format.indexOf("tif") != -1) { - saveAsTiff(imp, path); - return; - } else if (format.indexOf("jpeg") != -1 || format.indexOf("jpg") != -1) { - path = updateExtension(path, ".jpg"); - JpegWriter.save(imp, path, FileSaver.getJpegQuality()); - return; - } else if (format.indexOf("gif") != -1) { - path = updateExtension(path, ".gif"); - GifWriter.save(imp, path); - return; - } else if (format.indexOf("text image") != -1) { - String extension = ".txt"; - if (path!=null && (path.endsWith(".csv")||path.endsWith(".CSV"))) - extension = ".csv"; - path = updateExtension(path, extension); - format = "Text Image..."; - } else if (format.indexOf("text") != -1 || format.indexOf("txt") != -1) { - if (path != null && !path.endsWith(".xls") && !path.endsWith(".csv") && !path.endsWith(".tsv")) - path = updateExtension(path, ".txt"); - format = "Text..."; - } else if (format.indexOf("zip") != -1) { - path = updateExtension(path, ".zip"); - format = "ZIP..."; - } else if (format.indexOf("raw") != -1) { - // path = updateExtension(path, ".raw"); - format = "Raw Data..."; - } else if (format.indexOf("avi") != -1) { - path = updateExtension(path, ".avi"); - format = "AVI... "; - } else if (format.indexOf("bmp") != -1) { - path = updateExtension(path, ".bmp"); - format = "BMP..."; - } else if (format.indexOf("fits") != -1) { - path = updateExtension(path, ".fits"); - format = "FITS..."; - } else if (format.indexOf("png") != -1) { - path = updateExtension(path, ".png"); - format = "PNG..."; - } else if (format.indexOf("pgm") != -1) { - path = updateExtension(path, ".pgm"); - format = "PGM..."; - } else if (format.indexOf("lut") != -1) { - path = updateExtension(path, ".lut"); - format = "LUT..."; - } else if (format.contains("results") || format.contains("measurements") || format.contains("table")) { - format = "Results..."; - } else if (format.contains("selection") || format.contains("roi")) { - path = updateExtension(path, ".roi"); - format = "Selection..."; - } else if (format.indexOf("xy") != -1 || format.indexOf("coordinates") != -1) { - path = updateExtension(path, ".txt"); - format = "XY Coordinates..."; - } else - error("Unsupported save() or saveAs() file format: \"" + format + "\"\n \n\"" + path + "\""); - if (path == null) - run(format); - else { - if (path.contains(" ")) - run(imp, format, "save=[" + path + "]"); - else - run(imp, format, "save=" + path); - } - } - - /** - * Saves the specified image in TIFF format. Displays a file save dialog if - * 'path' is null or an empty string. Returns 'false' if there is an error or if - * the user selects "Cancel" in the file save dialog. - */ - public static boolean saveAsTiff(ImagePlus imp, String path) { - if (imp == null) - imp = getImage(); - if (path == null || path.equals("")) - return (new FileSaver(imp)).saveAsTiff(); - if (!path.endsWith(".tiff")) - path = updateExtension(path, ".tif"); - FileSaver fs = new FileSaver(imp); - boolean ok; - if (imp.getStackSize() > 1) - ok = fs.saveAsTiffStack(path); - else - ok = fs.saveAsTiff(path); - if (ok) - fs.updateImagePlus(path, FileInfo.TIFF); - return ok; - } - - static String updateExtension(String path, String extension) { - if (path == null) - return null; - int dotIndex = path.lastIndexOf("."); - int separatorIndex = path.lastIndexOf(File.separator); - if (dotIndex >= 0 && dotIndex > separatorIndex && (path.length() - dotIndex) <= 5) { - if (dotIndex + 1 < path.length() && Character.isDigit(path.charAt(dotIndex + 1))) - path += extension; - else - path = path.substring(0, dotIndex) + extension; - } else - path += extension; - return path; - } - - /** - * Saves a string as a file. Displays a file save dialog if 'path' is null or - * blank. Returns an error message if there is an exception, otherwise returns - * null. - */ - public static String saveString(String string, String path) { - return write(string, path, false); - } - - /** - * Appends a string to the end of a file. A newline character ("\n") is added to - * the end of the string before it is written. Returns an error message if there - * is an exception, otherwise returns null. - */ - public static String append(String string, String path) { - return write(string + "\n", path, true); - } - - private static String write(String string, String path, boolean append) { - if (path == null || path.equals("")) { - String msg = append ? "Append String..." : "Save String..."; - SaveDialog sd = new SaveDialog(msg, "Untitled", ".txt"); - String name = sd.getFileName(); - if (name == null) - return null; - path = sd.getDirectory() + name; - } - try { - BufferedWriter out = new BufferedWriter(new FileWriter(path, append)); - out.write(string); - out.close(); - } catch (IOException e) { - return "" + e; - } - return null; - } - - /** - * Opens a text file as a string. Displays a file open dialog if path is null or - * blank. Returns null if the user cancels the file open dialog. If there is an - * error, returns a message in the form "Error: message". - */ - public static String openAsString(String path) { - if (path == null || path.equals("")) { - OpenDialog od = new OpenDialog("Open Text File", ""); - String directory = od.getDirectory(); - String name = od.getFileName(); - if (name == null) - return null; - path = directory + name; - } - String str = ""; - File file = new File(path); - if (!file.exists()) - return "Error: file not found"; - try { - StringBuffer sb = new StringBuffer(5000); - BufferedReader r = new BufferedReader(new FileReader(file)); - while (true) { - String s = r.readLine(); - if (s == null) - break; - else - sb.append(s + "\n"); - } - r.close(); - str = new String(sb); - } catch (Exception e) { - str = "Error: " + e.getMessage(); - } - return str; - } - - public static ByteBuffer openAsByteBuffer(String path) { - if (path == null || path.equals("")) { - OpenDialog od = new OpenDialog("Open as ByteBuffer", ""); - String directory = od.getDirectory(); - String name = od.getFileName(); - if (name == null) - return null; - path = directory + name; - } - File file = new File(path); - if (!file.exists()) { - error("OpenAsByteBuffer", "File not found"); - return null; - } - int len = (int) file.length(); - byte[] buffer = new byte[len]; - try { - InputStream in = new BufferedInputStream(new FileInputStream(path)); - DataInputStream dis = new DataInputStream(in); - dis.readFully(buffer); - dis.close(); - } catch (Exception e) { - error("OpenAsByteBuffer", e.getMessage()); - return null; - } - return ByteBuffer.wrap(buffer); - } - - /** - * Creates a new image. - * - * @param title image name - * @param width image width in pixels - * @param height image height in pixels - * @param depth number of stack images - * @param bitdepth 8, 16, 32 (float) or 24 (RGB) - */ - public static ImagePlus createImage(String title, int width, int height, int depth, int bitdepth) { - return NewImage.createImage(title, width, height, depth, bitdepth, NewImage.FILL_BLACK); - } - - /** - * Creates a new imagePlus. Type should contain "8-bit", "16-bit", - * "32-bit" or "RGB". In addition, it can contain "white", "black" or "ramp". - * Width and height specify the width and height of - * the image in pixels. Depth specifies the number of stack slices. - */ - public static ImagePlus createImage(String title, String type, int width, int height, int depth) { - type = type.toLowerCase(Locale.US); - int bitDepth = 8; - if (type.contains("16")) - bitDepth = 16; - boolean signedInt = type.contains("32-bit int"); - if (type.contains("32")) - bitDepth = 32; - if (type.contains("24") || type.contains("rgb") || signedInt) - bitDepth = 24; - int options = NewImage.FILL_WHITE; - if (bitDepth == 16 || bitDepth == 32) - options = NewImage.FILL_BLACK; - if (type.contains("white")) - options = NewImage.FILL_WHITE; - else if (type.contains("black")) - options = NewImage.FILL_BLACK; - else if (type.contains("ramp")) - options = NewImage.FILL_RAMP; - else if (type.contains("noise") || type.contains("random")) - options = NewImage.FILL_NOISE; - options += NewImage.CHECK_AVAILABLE_MEMORY; - if (signedInt) - options += NewImage.SIGNED_INT; - return NewImage.createImage(title, width, height, depth, bitDepth, options); - } - - /** - * Creates a new hyperstack. - * - * @param title image name - * @param type "8-bit", "16-bit", "32-bit" or "RGB". May also contain - * "white" , "black" (the default), "ramp", "composite-mode", - * "color-mode", "grayscale-mode or "label". - * @param width image width in pixels - * @param height image height in pixels - * @param channels number of channels - * @param slices number of slices - * @param frames number of frames - */ - public static ImagePlus createImage(String title, String type, int width, int height, int channels, int slices, - int frames) { - if (type.contains("label")) - type += "ramp"; - if (!(type.contains("white") || type.contains("ramp"))) - type += "black"; - ImagePlus imp = IJ.createImage(title, type, width, height, channels * slices * frames); - imp.setDimensions(channels, slices, frames); - int mode = IJ.COLOR; - if (type.contains("composite")) - mode = IJ.COMPOSITE; - if (type.contains("grayscale")) - mode = IJ.GRAYSCALE; - if (channels > 1 && imp.getBitDepth() != 24) - imp = new CompositeImage(imp, mode); - imp.setOpenAsHyperStack(true); - if (type.contains("label")) - HyperStackMaker.labelHyperstack(imp); - return imp; - } - - /** - * Creates a new hyperstack. - * - * @param title image name - * @param width image width in pixels - * @param height image height in pixels - * @param channels number of channels - * @param slices number of slices - * @param frames number of frames - * @param bitdepth 8, 16, 32 (float) or 24 (RGB) - */ - public static ImagePlus createHyperStack(String title, int width, int height, int channels, int slices, int frames, - int bitdepth) { - ImagePlus imp = createImage(title, width, height, channels * slices * frames, bitdepth); - imp.setDimensions(channels, slices, frames); - if (channels > 1 && bitdepth != 24) - imp = new CompositeImage(imp, IJ.COMPOSITE); - imp.setOpenAsHyperStack(true); - return imp; - } - - /** - * Opens a new image. Type should contain "8-bit", "16-bit", - * "32-bit" or "RGB". In addition, it can contain "white", "black" or "ramp". - * Width and height specify the width and height of - * the image in pixels. Depth specifies the number of stack slices. - */ - public static void newImage(String title, String type, int width, int height, int depth) { - ImagePlus imp = createImage(title, type, width, height, depth); - if (imp != null) { - macroRunning = true; - imp.show(); - macroRunning = false; - } - } - - /** - * Returns true if the Esc key was pressed since the last ImageJ - * command started to execute or since resetEscape() was called. - */ - public static boolean escapePressed() { - return escapePressed; - } - - /** - * This method sets the Esc key to the "up" position. The Executer - * class calls this method when it runs an ImageJ command in a separate thread. - */ - public static void resetEscape() { - escapePressed = false; - } - - /** - * Causes IJ.error() output to be temporarily redirected to the "Log" window. - */ - public static void redirectErrorMessages() { - redirectErrorMessages = true; - lastErrorMessage = null; - } - - /** - * Set 'true' and IJ.error() output will be temporarily redirected to the "Log" - * window. - */ - public static void redirectErrorMessages(boolean redirect) { - redirectErrorMessages = redirect; - lastErrorMessage = null; - } - - /** - * Returns the state of the 'redirectErrorMessages' flag, which is set by - * File/Import/Image Sequence. - */ - public static boolean redirectingErrorMessages() { - return redirectErrorMessages; - } - - /** Temporarily suppress "plugin not found" errors. */ - public static void suppressPluginNotFoundError() { - suppressPluginNotFoundError = true; - } - - /** - * Returns the class loader ImageJ uses to run plugins or the system class - * loader if Menus.getPlugInsPath() returns null. - */ - public static ClassLoader getClassLoader() { - if (classLoader == null) { - String pluginsDir = Menus.getPlugInsPath(); - if (pluginsDir == null) { - String home = System.getProperty("plugins.dir"); - if (home != null) { - if (!home.endsWith(Prefs.separator)) - home += Prefs.separator; - pluginsDir = home + "plugins" + Prefs.separator; - if (!(new File(pluginsDir)).isDirectory()) - pluginsDir = home; - } - } - if (pluginsDir == null) - return IJ.class.getClassLoader(); - else { - if (Menus.jnlp) - classLoader = new PluginClassLoader(pluginsDir, true); - else - classLoader = new PluginClassLoader(pluginsDir); - } - } - return classLoader; - } - - /** Returns the size, in pixels, of the primary display. */ - public static Dimension getScreenSize() { - Rectangle bounds = GUI.getScreenBounds(); - return new Dimension(bounds.width, bounds.height); - } - - /** - * Returns, as an array of strings, a list of the LUTs in the Image/Lookup - * Tables menu. - * - * @see ij.plugin.LutLoader#getLut See also: Help>Examples>JavaScript/Show all - * LUTs and Image/Color/Display LUTs - */ - public static String[] getLuts() { - ArrayList list = new ArrayList(); - Hashtable commands = Menus.getCommands(); - Menu lutsMenu = Menus.getImageJMenu("Image>Lookup Tables"); - if (commands == null || lutsMenu == null) - return new String[0]; - for (int i = 0; i < lutsMenu.getItemCount(); i++) { - MenuItem menuItem = lutsMenu.getItem(i); - String label = menuItem.getLabel(); - if (label.equals("-") || label.equals("Invert LUT") || label.equals("Apply LUT")) - continue; - String command = (String) commands.get(label); - if (command == null || command.startsWith("ij.plugin.LutLoader")) - list.add(label); - } - return (String[]) list.toArray(new String[list.size()]); - } - - static void abort() { - if ((ij != null || Interpreter.isBatchMode()) && macroInterpreter == null) - throw new RuntimeException(Macro.MACRO_CANCELED); - } - - static void setClassLoader(ClassLoader loader) { - classLoader = loader; - } - - public static void resetClassLoader() { - setClassLoader(null); - } - - /** - * Displays a stack trace. Use the setExceptionHandler method() to override with - * a custom exception handler. - */ - public static void handleException(Throwable e) { - if (exceptionHandler != null) { - exceptionHandler.handle(e); - return; - } - if (Macro.MACRO_CANCELED.equals(e.getMessage())) - return; - CharArrayWriter caw = new CharArrayWriter(); - PrintWriter pw = new PrintWriter(caw); - e.printStackTrace(pw); - String s = caw.toString(); - String lineNumber = ""; - if (s != null && s.contains("ThreadDeath")) - return; - Interpreter interpreter = Thread.currentThread().getName().endsWith("Macro$") ? Interpreter.getInstance() : null; - if (interpreter!=null) - lineNumber = "\nMacro line number: " + interpreter.getLineNumber(); - if (getInstance() != null) { - s = IJ.getInstance().getInfo()+lineNumber+"\n \n"+s; - new TextWindow("Exception", s, 500, 340); - } else - log(s); - } - - /** - * Installs a custom exception handler that overrides the handleException() - * method. - */ - public static void setExceptionHandler(ExceptionHandler handler) { - exceptionHandler = handler; - } - - public interface ExceptionHandler { - public void handle(Throwable e); - } - - static ExceptionHandler exceptionHandler; - - public static void addEventListener(IJEventListener listener) { - eventListeners.addElement(listener); - } - - public static void removeEventListener(IJEventListener listener) { - eventListeners.removeElement(listener); - } - - public static void notifyEventListeners(int eventID) { - synchronized (eventListeners) { - for (int i = 0; i < eventListeners.size(); i++) { - IJEventListener listener = (IJEventListener) eventListeners.elementAt(i); - listener.eventOccurred(eventID); - } - } - } - - /** - * Adds a key-value pair to IJ.properties. The key and value are removed if - * 'value' is null. - */ - public static void setProperty(String key, Object value) { - if (properties == null) - properties = new Properties(); - if (value == null) - properties.remove(key); - else - properties.put(key, value); - } - - /** - * Returns the object in IJ.properties associated with 'key', or null if 'key' - * is not found. - */ - public static Object getProperty(String key) { - if (properties == null) - return null; - else - return properties.get(key); - } - - public static boolean statusBarProtected() { - return protectStatusBar; - } - - public static void protectStatusBar(boolean protect) { - protectStatusBar = protect; - if (!protectStatusBar) - statusBarThread = null; - } - - /** Returns 'true' if the Recorder is running and ImageJ is not in headless mode. */ - public static boolean recording() { - return (!GraphicsEnvironment.isHeadless()&&Recorder.record); - } - - -} diff --git a/com.eco.bio7.image/src/ij/IJEventListener.java b/com.eco.bio7.image/src/ij/IJEventListener.java deleted file mode 100644 index f5af9b5ca..000000000 --- a/com.eco.bio7.image/src/ij/IJEventListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package ij; - - /** Plugins that implement this interface are notified when the user - changes the foreground color, changes the background color, - closes the color picker, closes the Log window or switches to - another tool. - */ - public interface IJEventListener { - public static final int FOREGROUND_COLOR_CHANGED = 0; - public static final int BACKGROUND_COLOR_CHANGED = 1; - public static final int COLOR_PICKER_CLOSED= 2; - public static final int LOG_WINDOW_CLOSED= 3; - public static final int TOOL_CHANGED= 4; - - public void eventOccurred(int eventID); - -} diff --git a/com.eco.bio7.image/src/ij/ImageJ.java b/com.eco.bio7.image/src/ij/ImageJ.java deleted file mode 100644 index e9563010b..000000000 --- a/com.eco.bio7.image/src/ij/ImageJ.java +++ /dev/null @@ -1,1205 +0,0 @@ -package ij; - -import ij.gui.*; -import ij.process.*; -import ij.io.*; -import ij.plugin.*; -import ij.plugin.filter.*; -import ij.plugin.frame.*; -import ij.text.*; -import ij.macro.Interpreter; -import ij.io.Opener; -import ij.util.*; -import java.awt.*; -import java.util.*; -import java.awt.event.*; -import java.io.*; -import java.net.*; -import java.awt.image.*; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JLabel; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.PlatformUI; -import com.eco.bio7.ImageJPluginActions.ImageJContextMenuAction; -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.CustomDetachedImageJView; -import com.eco.bio7.image.Fullscreen; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.Util; - -/** - * This frame is the main ImageJ class. - * - * ImageJ is a work of the United States Government. It is in the public domain - * and open source. There is no copyright. You are free to do anything you want - * with this source but I like to get credit for my work and I would like you to - * offer your changes to me so I can possibly add them to the "official" - * version. - * - * - * The following command line options are recognized by ImageJ: - * - * "file-name" - * Opens a file - * Example 1: blobs.tif - * Example 2: /Users/wayne/images/blobs.tif - * Example 3: e81*.tif - * - * -macro path [arg] - * Runs a macro or script (JavaScript, BeanShell or Python), passing an - * optional string argument, which the macro or script can be retrieve - * using the getArgument() function. The macro or script is assumed to - * be in the ImageJ/macros folder if 'path' is not a full directory path. - * Example 1: -macro analyze.ijm - * Example 2: -macro script.js /Users/wayne/images/stack1 - * Example 2: -macro script.py '1.2 2.4 3.8' - * - * -batch path [arg] - * Runs a macro or script (JavaScript, BeanShell or Python) in - * batch (no GUI) mode, passing it an optional argument. - * ImageJ exits when the macro finishes. - * - * -eval "macro code" - * Evaluates macro code - * Example 1: -eval "print('Hello, world');" - * Example 2: -eval "return getVersion();" - * - * -run command - * Runs an ImageJ menu command - * Example: -run "About ImageJ..." - * - * -ijpath path - * Specifies the path to the directory containing the plugins directory - * Example: -ijpath /Applications/ImageJ - * - * -port - * Specifies the port ImageJ uses to determine if another instance is running - * Example 1: -port1 (use default port address + 1) - * Example 2: -port2 (use default port address + 2) - * Example 3: -port0 (don't check for another instance) - * - * -debug - * Runs ImageJ in debug mode - * - * - * @author Wayne Rasband (rasband@gmail.com) - */ -public class ImageJ extends Frame implements ActionListener, MouseListener, KeyListener, WindowListener, ItemListener, Runnable { - - /** - * Plugins should call IJ.getVersion() or IJ.getFullVersion() to get the version - * string. - */ - - public static final String VERSION = "1.54u"; - public static final String BUILD = "8"; - public static Color backgroundColor; - /** SansSerif, 12-point, plain font. */ - public static final Font SansSerif12 = new Font("SansSerif", Font.PLAIN, 12); - /** SansSerif, 14-point, plain font. */ - public static final Font SansSerif14 = new Font("SansSerif", Font.PLAIN, 14); - /** Address of socket where Image accepts commands */ - public static final int DEFAULT_PORT = 57294; - - /** Run as normal application. */ - public static final int STANDALONE = 0; - - /** Run embedded in another application. */ - public static final int EMBEDDED = 1; - - /** Run embedded and invisible in another application. */ - public static final int NO_SHOW = 2; - - /** Run as the ImageJ application. */ - public static final int IMAGEJ_APP = 3; - - /** Run ImageJ in debug mode. */ - public static final int DEBUG = 256; - - private static final String IJ_X = "ij.x", IJ_Y = "ij.y"; - private static int port = DEFAULT_PORT; - private static String[] arguments; - - public Toolbar toolbar;// Changed for Bio7 to public! - public JPanel statusBar;// Changed for Bio7 to public! - private ProgressBar progressBar; - public JLabel statusLine; - private boolean firstTime = true; - private java.applet.Applet applet; // null if not running as an applet - private Vector classes = new Vector(); - private boolean exitWhenQuitting; - private boolean quitting; - private boolean quitMacro; - private long keyPressedTime, actionPerformedTime; - private String lastKeyCommand; - private boolean embedded; - private boolean windowClosed; - private static String commandName; - /* Changed for Bio7! -> Bio7 variables! */ - public static Fullscreen full; - private JPanel currentPanel; - private JPanel root; - private int index; - private int tabsBefore; - private int tabsAfter; - private org.eclipse.swt.graphics.Point p; - private static boolean batchMode; - boolean hotkey; - private ImageJContextMenuAction imageContextMenuAction; - - public ImageJContextMenuAction getImageContextMenuAction() { - return imageContextMenuAction; - } - - private static Color primaryColor; - - public static Color getPrimarySWTToAwtColor() { - return primaryColor; - } - - /** Creates a new ImageJ frame that runs as an application. */ - public ImageJ() { - this(null, STANDALONE); - } - - /** - * Creates a new ImageJ frame that runs as an application in the specified mode. - */ - public ImageJ(int mode) { - this(null, mode); - } - - /** Creates a new ImageJ frame that runs as an applet. */ - public ImageJ(java.applet.Applet applet) { - this(applet, STANDALONE); - } - - /** - * If 'applet' is not null, creates a new ImageJ frame that runs as an applet. - * If 'mode' is ImageJ.EMBEDDED and 'applet is null, creates an embedded - * (non-standalone) version of ImageJ. - */ - public ImageJ(java.applet.Applet applet, int mode) { - super("ImageJ"); - if ((mode & DEBUG) != 0) - IJ.setDebugMode(true); - mode = mode & 255; - boolean useExceptionHandler = false; - if (mode == IMAGEJ_APP) { - mode = STANDALONE; - useExceptionHandler = true; - } - if (IJ.debugMode) - IJ.log("ImageJ starting in debug mode: " + mode); - embedded = applet == null && (mode == EMBEDDED || mode == NO_SHOW); - this.applet = applet; - String err1 = Prefs.load(this, applet); - backgroundColor = Util.getSWTBackgroundToAWT(); - setBackground(backgroundColor); - Menus m = new Menus(this, applet); - String err2 = m.addMenuBar(); - m.installPopupMenu(this); - setLayout(new BorderLayout()); - - // Tool bar - toolbar = new Toolbar(); - toolbar.addKeyListener(this); - add("Center", toolbar); - primaryColor = getSystemColour(); - // Status bar - statusBar = new JPanel(); - statusBar.setLayout(new BorderLayout()); - statusBar.setForeground(Color.black); - statusBar.setBackground(getSystemColour());// Changed for Bio7! - statusLine = new JLabel(); - double scale = Prefs.getGuiScale(); - statusLine.setFont(new Font("SansSerif", Font.PLAIN, (int) (13 * scale))); - // Changed for Bio7! - if (Util.isThemeBlack()) { - statusLine.setForeground(Color.white); - } else { - statusLine.setForeground(Color.black); - } - statusLine.setFont(new Font("SansSerif", Font.PLAIN, 13)); - statusLine.addKeyListener(this); - statusLine.addMouseListener(this); - statusBar.add("Center", statusLine); - progressBar = new ProgressBar((int) (ProgressBar.WIDTH * scale), (int) (ProgressBar.HEIGHT * scale)); - progressBar.addKeyListener(this); - progressBar.addMouseListener(this); - statusBar.add("East", progressBar); - add("South", statusBar); - - IJ.init(this, applet); - addKeyListener(this); - addWindowListener(this); - setFocusTraversalKeysEnabled(false); - m.installStartupMacroSet(); // add custom tools - - Point loc = getPreferredLocation(); - Dimension tbSize = toolbar.getPreferredSize(); - setCursor(Cursor.getDefaultCursor()); // work-around for JDK 1.1.8 bug - if (mode != NO_SHOW) { - if (IJ.isWindows()) - try { - setIcon(); - } catch (Exception e) { - } - - setResizable(false); - setAlwaysOnTop(Prefs.alwaysOnTop); - pack(); - /* Changed for Bio7! */ - // setLocation(loc.x, loc.y); - // setVisible(true); - /* - * Dimension size = getSize(); if (size!=null) { if (IJ.debugMode) - * IJ.log("size: "+size); if (IJ.isWindows() && - * (size.height>108||IJ.javaVersion()>=10)) { { // workaround for IJ window - * layout and FileDialog freeze problems with Windows 10 Creators Update - * IJ.wait(10); pack(); if (IJ.debugMode) IJ.log("pack()"); if - * (!Prefs.jFileChooserSettingChanged) Prefs.useJFileChooser = true; } else if - * (IJ.isMacOSX()) { Rectangle maxBounds = GUI.getMaxWindowBounds(this); if - * (loc.x+size.width>maxBounds.x+maxBounds.width) setLocation(loc.x, loc.y); } - */ - } - if (err1 != null) - IJ.error(err1); - if (err2 != null) { - IJ.error(err2); - // IJ.runPlugIn("ij.plugin.ClassChecker", ""); - } - // Changed for Bio7. Adapter not needed anymore! - /* - * if (IJ.isMacintosh() && applet == null) { - * - * try { if (IJ.javaVersion()>8) // newer JREs use different drag-drop, about - * mechanism IJ.runPlugIn("ij.plugin.MacAdapter9", ""); else - * IJ.runPlugIn("ij.plugin.MacAdapter", ""); } catch (Throwable e) { - * - * } - * - * - * - * } - */ - if (applet == null) - IJ.runPlugIn("ij.plugin.DragAndDrop", ""); - if (!getTitle().contains("Fiji") && useExceptionHandler) { - Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler()); - System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName()); - } - String str = m.getMacroCount() == 1 ? " macro" : " macros"; - configureProxy(); - if (applet == null) - loadCursors(); - (new ij.macro.StartupRunner()).run(batchMode); // run RunAtStartup and AutoRun macros - IJ.showStatus(version() + m.getPluginCount() + " commands; " + m.getMacroCount() + str); - imageContextMenuAction = new ImageJContextMenuAction(); - } - - /* Changed for Bio7! */ - public static java.awt.Color getSystemColour() { - Color col = null; - org.eclipse.swt.graphics.Color colswt = CanvasView.getCanvas_view().getParent2().getBackground(); - int r = colswt.getRed(); - int g = colswt.getGreen(); - int b = colswt.getBlue(); - col = new Color(r, g, b); - - return col; - } - - private void loadCursors() { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - String path = Prefs.getImageJDir() + "images/crosshair-cursor.gif"; - File f = new File(path); - if (!f.exists()) - return; - // Image image = toolkit.getImage(path); - ImageIcon icon = new ImageIcon(path); - Image image = icon.getImage(); - if (image == null) - return; - int width = icon.getIconWidth(); - int height = icon.getIconHeight(); - Point hotSpot = new Point(width / 2, height / 2); - Cursor crosshairCursor = toolkit.createCustomCursor(image, hotSpot, "crosshair-cursor.gif"); - ImageCanvas.setCursor(crosshairCursor, 0); - } - - void configureProxy() { - if (Prefs.useSystemProxies) { - try { - System.setProperty("java.net.useSystemProxies", "true"); - } catch (Exception e) { - } - } else { - String server = Prefs.get("proxy.server", null); - if (server == null || server.equals("")) - return; - int port = (int) Prefs.get("proxy.port", 0); - if (port == 0) - return; - Properties props = System.getProperties(); - props.put("proxySet", "true"); - props.put("http.proxyHost", server); - props.put("http.proxyPort", "" + port); - props.put("https.proxyHost", server); - props.put("https.proxyPort", "" + port); - } - // new ProxySettings().logProperties(); - } - - void setIcon() throws Exception { - URL url = this.getClass().getResource("/microscope.gif"); - if (url == null) - return; - Image img = createImage((ImageProducer) url.getContent()); - if (img != null) - setIconImage(img); - } - - public Point getPreferredLocation() { - - int ijX = Prefs.getInt(IJ_X, -99); - int ijY = Prefs.getInt(IJ_Y, -99); - Rectangle maxBounds = GUI.getMaxWindowBounds(); - // System.out.println("getPreferredLoc1: "+ijX+" "+ijY+" "+maxBounds); - if (ijX >= maxBounds.x && ijY >= maxBounds.y && ijX < (maxBounds.x + maxBounds.width - 75) && ijY < (maxBounds.y + maxBounds.height - 75)) - return new Point(ijX, ijY); - Dimension tbsize = toolbar.getPreferredSize(); - int ijWidth = tbsize.width + 10; - double percent = maxBounds.width > 832 ? 0.8 : 0.9; - ijX = (int) (percent * (maxBounds.width - ijWidth)); - if (ijX < 10) - ijX = 10; - return new Point(ijX, maxBounds.y); - } - - /* Changed for Bio7! */ - void showStatus(final String s) { - statusLine.setText(s); - Display display = Util.getDisplay(); - /* - * MacOSX only seems to work with async method! Also on Windows async works best - * (avoids deadlocks when mouse moved in and out the canvas opening several - * images at once in the background!). - */ - - display.asyncExec(new Runnable() { - - public void run() { - if (CanvasView.getCanvas_view() != null) { - CanvasView.getCanvas_view().setstatusline(s); - } - - /* - * if (customImageJView != null) { customImageJView.setstatusline(s); } - */ - IViewReference[] viewRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences(); - for (int i = 0; i < viewRefs.length; i++) { - String id = viewRefs[i].getId(); - if (id.equals("com.eco.bio7.image.detachedImage")) { - IViewPart view = viewRefs[i].getView(false); - String secId = viewRefs[i].getSecondaryId(); - CustomDetachedImageJView cdview = (CustomDetachedImageJView) view; - /* Get the image from the detached secondary view id (same id)! */ - ImagePlus plu = WindowManager.getImage(Integer.valueOf(secId)); - if (plu != null) { - ImagePlus ip = WindowManager.getImage(Integer.valueOf(secId)); - ImageWindow currentWindow = WindowManager.getCurrentWindow(); - ImageWindow window = ip.getWindow(); - if (currentWindow != null && window != null) { - if (currentWindow.equals(window)) { - cdview.setstatusline(s); - } - } - } - - } - } - - } - }); - - } - - /* - * void showStatus(String s) { statusLine.setText(s); } - */ - - public ProgressBar getProgressBar() { - return progressBar; - } - - public JPanel getStatusBar() { - return statusBar; - } - - public static String getStatusBarText() { - ImageJ ij = IJ.getInstance(); - return ij != null ? ij.statusLine.getText() : ""; - } - - /** Starts executing a menu command in a separate thread. */ - /* Changed for Bio7 to public! */ - public void doCommand(String name) { - new Executer(name, null); - } - - public void runFilterPlugIn(Object theFilter, String cmd, String arg) { - new PlugInFilterRunner(theFilter, cmd, arg); - } - - public Object runUserPlugIn(String commandName, String className, String arg, boolean createNewLoader) { - return IJ.runUserPlugIn(commandName, className, arg, createNewLoader); - } - - /** Return the current list of modifier keys. */ - public static String modifiers(int flags) { // ?? needs to be moved - String s = " [ "; - if (flags == 0) - return ""; - if ((flags & Event.SHIFT_MASK) != 0) - s += "Shift "; - if ((flags & Event.CTRL_MASK) != 0) - s += "Control "; - if ((flags & Event.META_MASK) != 0) - s += "Meta "; - if ((flags & Event.ALT_MASK) != 0) - s += "Alt "; - s += "] "; - return s; - } - - /** Handle menu events. */ - public void actionPerformed(ActionEvent e) { - if ((e.getSource() instanceof MenuItem)) { - MenuItem item = (MenuItem) e.getSource(); - String cmd = e.getActionCommand(); - Frame frame = WindowManager.getFrontWindow(); - if (frame != null && (frame instanceof Fitter)) { - ((Fitter) frame).actionPerformed(e); - return; - } - commandName = cmd; - ImagePlus imp = null; - if (item.getParent() == Menus.getOpenRecentMenu()) { - new RecentOpener(cmd); // open image in separate thread - return; - } else if (item.getParent() == Menus.getPopupMenu()) { - Object parent = Menus.getPopupMenu().getParent(); - if (parent instanceof ImageCanvas) - imp = ((ImageCanvas) parent).getImage(); - } - int flags = e.getModifiers(); - hotkey = false; - actionPerformedTime = System.currentTimeMillis(); - long ellapsedTime = actionPerformedTime - keyPressedTime; - if (cmd != null && (ellapsedTime >= 200L || !cmd.equals(lastKeyCommand))) { - if ((flags & Event.ALT_MASK) != 0) - IJ.setKeyDown(KeyEvent.VK_ALT); - if ((flags & Event.SHIFT_MASK) != 0) - IJ.setKeyDown(KeyEvent.VK_SHIFT); - new Executer(cmd, imp); - } - lastKeyCommand = null; - if (IJ.debugMode) - IJ.log("actionPerformed: time=" + ellapsedTime + ", " + e); - } - } - - /** Handles CheckboxMenuItem state changes. */ - public void itemStateChanged(ItemEvent e) { - MenuItem item = (MenuItem) e.getSource(); - MenuComponent parent = (MenuComponent) item.getParent(); - String cmd = e.getItem().toString(); - if ("Autorun Examples".equals(cmd)) // Examples>Autorun Examples - Prefs.autoRunExamples = e.getStateChange() == 1; - else if ((Menu) parent == Menus.window) - WindowManager.activateWindow(cmd, item); - else - doCommand(cmd); - } - - public void mousePressed(MouseEvent e) { - Undo.reset(); - if (!Prefs.noClickToGC) - System.gc(); - IJ.showStatus(version() + IJ.freeMemory()); - if (IJ.debugMode) - IJ.log("Windows: " + WindowManager.getWindowCount()); - } - - public String getInfo() { - return version() + System.getProperty("os.name") + " " + System.getProperty("os.version") + "; " + IJ.freeMemory(); - } - - private String version() { - return "ImageJ " + VERSION + BUILD + "; " + "Java " + System.getProperty("java.version") + (IJ.is64Bit() ? " [64-bit]; " : " [32-bit]; "); - } - - public void mouseReleased(MouseEvent e) { - } - - public void mouseExited(MouseEvent e) { - } - - public void mouseClicked(MouseEvent e) { - } - - public void mouseEntered(MouseEvent e) { - } - - public void keyPressed(KeyEvent e) { - if (e.isConsumed()) - return; - int keyCode = e.getKeyCode(); - IJ.setKeyDown(keyCode); - hotkey = false; - if (keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_SHIFT) - return; - char keyChar = e.getKeyChar(); - int flags = e.getModifiers(); - if (IJ.debugMode) - IJ.log("keyPressed: code=" + keyCode + " (" + KeyEvent.getKeyText(keyCode) + "), char=\"" + keyChar + "\" (" + (int) keyChar + "), flags=" + KeyEvent.getKeyModifiersText(flags)); - boolean shift = (flags & KeyEvent.SHIFT_MASK) != 0; - boolean control = (flags & KeyEvent.CTRL_MASK) != 0; - boolean alt = (flags & KeyEvent.ALT_MASK) != 0; - boolean meta = (flags & KeyEvent.META_MASK) != 0; - if (keyCode == KeyEvent.VK_H && meta && IJ.isMacOSX()) - return; // Allow macOS to run ImageJ>Hide ImageJ command - String cmd = null; - ImagePlus imp = WindowManager.getCurrentImage(); - boolean isStack = (imp!=null) && (imp.getStackSize()>1); - if (imp != null && !meta && ((keyChar >= 32 && keyChar <= 255) || keyChar == '\b' || keyChar == '\n')) { - Roi roi = imp.getRoi(); - if (roi != null && roi instanceof TextRoi) { - if (imp.getOverlay() != null && (control || alt || meta) && (keyCode == KeyEvent.VK_BACK_SPACE || keyCode == KeyEvent.VK_DELETE)) { - if (deleteOverlayRoi(imp)) - return; - } - if ((flags & KeyEvent.META_MASK) != 0 && IJ.isMacOSX()) - return; - if (alt) { - switch (keyChar) { - case 'u': - case 'm': - keyChar = IJ.micronSymbol; - break; - case 'A': - keyChar = IJ.angstromSymbol; - break; - default: - } - } - ((TextRoi) roi).addChar(keyChar); - return; - } - } - - // Handle one character macro shortcuts - if (!control && !meta) { - Hashtable macroShortcuts = Menus.getMacroShortcuts(); - if (macroShortcuts.size() > 0) { - if (shift) - cmd = (String) macroShortcuts.get(Integer.valueOf(keyCode + 200)); - else - cmd = (String) macroShortcuts.get(Integer.valueOf(keyCode)); - if (cmd != null) { - - commandName = cmd; - MacroInstaller.runMacroShortcut(cmd); - return; - } - } - } - - if (keyCode == KeyEvent.VK_SEPARATOR) - keyCode = KeyEvent.VK_DECIMAL; - boolean functionKey = keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12; - boolean arrowKey = keyCode==37 || keyCode==38 || keyCode==39 || keyCode==40; - if (Interpreter.getInstance()==null) - arrowKey = false; - boolean numPad = keyCode == KeyEvent.VK_DIVIDE || keyCode == KeyEvent.VK_MULTIPLY || keyCode == KeyEvent.VK_DECIMAL || (keyCode >= KeyEvent.VK_NUMPAD0 && keyCode <= KeyEvent.VK_NUMPAD9); - if ((!Prefs.requireControlKey||control||meta||functionKey||numPad||arrowKey) && keyChar!='+') { - Hashtable shortcuts = Menus.getShortcuts(); - if (shift && !functionKey) - cmd = (String) shortcuts.get(Integer.valueOf(keyCode + 200)); - else - cmd = (String) shortcuts.get(Integer.valueOf(keyCode)); - } - - if (cmd == null) { - switch (keyChar) { - case '<': - case ',': - if (isStack) - cmd = "Previous Slice [<]"; - break; - case '>': - case '.': - case ';': - if (isStack) - cmd = "Next Slice [>]"; - break; - case '+': - case '=': - cmd = "In [+]"; - break; - case '-': - cmd = "Out [-]"; - break; - case '/': - cmd = "Reslice [/]..."; - break; - default: - } - } - - if (cmd == null) { - switch (keyCode) { - case KeyEvent.VK_TAB: - WindowManager.putBehind(); - return; - case KeyEvent.VK_BACK_SPACE: - case KeyEvent.VK_DELETE: - if (!(shift || control || alt || meta)) { - if (deleteOverlayRoi(imp)) - return; - if (imp != null && imp.getOverlay() != null && imp == GelAnalyzer.getGelImage()) - return; - cmd = "Clear"; - hotkey = true; - } - break; - // case KeyEvent.VK_BACK_SLASH: - // cmd=IJ.altKeyDown()?"Animation Options...":"Start Animation"; - // break; - case KeyEvent.VK_EQUALS: - cmd = "In [+]"; - break; - case KeyEvent.VK_MINUS: - cmd = "Out [-]"; - break; - case KeyEvent.VK_SLASH: - case 0xbf: - cmd = "Reslice [/]..."; - break; - case KeyEvent.VK_COMMA: - case 0xbc: - if (isStack) - cmd = "Previous Slice [<]"; - break; - case KeyEvent.VK_PERIOD: - case 0xbe: - if (isStack) - cmd = "Next Slice [>]"; - break; - case KeyEvent.VK_LEFT: - case KeyEvent.VK_RIGHT: - case KeyEvent.VK_UP: - case KeyEvent.VK_DOWN: // arrow keys - if (imp == null) - return; - Roi roi = imp.getRoi(); - if (shift && imp == Orthogonal_Views.getImage()) - return; - if (IJ.isMacOSX() && IJ.isJava18()) { - RoiManager rm = RoiManager.getInstance(); - boolean rmActive = rm != null && rm == WindowManager.getActiveWindow(); - if (rmActive && (keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_UP)) - rm.repaint(); - } - boolean stackKey = imp.getStackSize() > 1 && (roi == null || shift); - boolean zoomKey = roi == null || shift || control; - if (stackKey && keyCode == KeyEvent.VK_RIGHT) - cmd = "Next Slice [>]"; - else if (stackKey && keyCode == KeyEvent.VK_LEFT) - cmd = "Previous Slice [<]"; - //else if (zoomKey && keyCode==KeyEvent.VK_DOWN && !ignoreArrowKeys(imp,control) && Toolbar.getToolId() 1 && win != null && win.getClass().getName().startsWith("loci")) - return true; - if (Prefs.requireControlKey && !control) - return true; - return false; - } - - public void keyTyped(KeyEvent e) { - char keyChar = e.getKeyChar(); - int flags = e.getModifiers(); - // if (IJ.debugMode) IJ.log("keyTyped: char=\"" + keyChar + "\" (" + - // (int)keyChar - // + "), flags= "+Integer.toHexString(flags)+ " - // ("+KeyEvent.getKeyModifiersText(flags)+")"); - if (keyChar == '\\' || keyChar == 171 || keyChar == 223) { - if (((flags & Event.ALT_MASK) != 0)) - doCommand("Animation Options..."); - else - doCommand("Start Animation [\\]"); - } - } - - public void keyReleased(KeyEvent e) { - IJ.setKeyUp(e.getKeyCode()); - } - - /** called when escape pressed */ - void abortPluginOrMacro(ImagePlus imp) { - if (imp != null) { - ImageWindow win = imp.getWindow(); - if (win != null) { - win.running = false; - win.running2 = false; - Roi roi = imp.getRoi(); - if (roi != null && roi.getState() != Roi.NORMAL) { - roi.abortModification(imp); - return; - } else { - win.running = false; - win.running2 = false; - } - } - } - Macro.abort(); - Interpreter.abort(); - if (Interpreter.getInstance() != null) - IJ.beep(); - } - - public void windowClosing(WindowEvent e) { - if (Executer.getListenerCount() > 0) - doCommand("Quit"); - else { - quit(); - windowClosed = true; - } - } - - public void windowActivated(WindowEvent e) { - if (IJ.isMacintosh() && !quitting) { - IJ.wait(10); // may be needed for Java 1.4 on OS X - MenuBar mb = Menus.getMenuBar(); - if (mb != null && mb != getMenuBar() && !IJ.isMacro()) { - setMenuBar(mb); - Menus.setMenuBarCount++; - if (IJ.debugMode) - IJ.log("setMenuBar: " + Menus.setMenuBarCount); - } - } - } - - public void windowClosed(WindowEvent e) { - } - - public void windowDeactivated(WindowEvent e) { - } - - public void windowDeiconified(WindowEvent e) { - } - - public void windowIconified(WindowEvent e) { - } - - public void windowOpened(WindowEvent e) { - } - - /** - * Adds the specified class to a Vector to keep it from being garbage collected, - * causing static fields to be reset. - */ - public void register(Class c) { - if (!classes.contains(c)) - classes.addElement(c); - } - - /** Called by ImageJ when the user selects Quit. */ - public void quit() { - quitMacro = IJ.macroRunning(); - Thread thread = new Thread(this, "Quit"); - thread.setPriority(Thread.NORM_PRIORITY); - thread.start(); - IJ.wait(10); - } - - /** Returns true if ImageJ is exiting. */ - public boolean quitting() { - return quitting; - } - - /** - * Returns true if ImageJ is quitting as a result of a run("Quit") macro call. - */ - public boolean quittingViaMacro() { - return quitting && quitMacro; - } - - /** Called once when ImageJ quits. */ - public void savePreferences(Properties prefs) { - Point loc = getLocation(); - prefs.put(IJ_X, Integer.toString(loc.x)); - prefs.put(IJ_Y, Integer.toString(loc.y)); - - } - - public static void main(String args[]) { - boolean noGUI = false; - int mode = IMAGEJ_APP; - arguments = args; - int nArgs = args != null ? args.length : 0; - boolean commandLine = false; - for (int i = 0; i < nArgs; i++) { - String arg = args[i]; - if (arg == null) - continue; - if (arg.startsWith("-batch")) { - noGUI = true; - batchMode = true; - } else if (arg.startsWith("-macro") || arg.endsWith(".ijm") || arg.endsWith(".txt")) - batchMode = true; - else if (arg.startsWith("-debug")) - IJ.setDebugMode(true); - else if (arg.startsWith("-ijpath") && i + 1 < nArgs) { - if (IJ.debugMode) - IJ.log("-ijpath: " + args[i + 1]); - Prefs.setHomeDir(args[i + 1]); - commandLine = true; - args[i + 1] = null; - } else if (arg.startsWith("-port")) { - int delta = (int) Tools.parseDouble(arg.substring(5, arg.length()), 0.0); - commandLine = true; - if (delta == 0) - mode = EMBEDDED; - else if (delta > 0 && DEFAULT_PORT + delta < 65536) - port = DEFAULT_PORT + delta; - } - } - // If existing ImageJ instance, pass arguments to it and quit. - boolean passArgs = (mode == IMAGEJ_APP || mode == STANDALONE) && !noGUI; - if (IJ.isMacOSX() && !commandLine) - passArgs = false; - if (passArgs && isRunning(args)) - return; - ImageJ ij = IJ.getInstance(); - if (!noGUI && (ij == null || (ij != null && !ij.isShowing()))) { - ij = new ImageJ(null, mode); - ij.exitWhenQuitting = true; - } else if (batchMode && noGUI) - Prefs.load(null, null); - int macros = 0; - for (int i = 0; i < nArgs; i++) { - String arg = args[i]; - if (arg == null) - continue; - if (arg.startsWith("-")) { - if ((arg.startsWith("-macro") || arg.startsWith("-batch")) && i + 1 < nArgs) { - String arg2 = i + 2 < nArgs ? args[i + 2] : null; - Prefs.commandLineMacro = true; - if (noGUI && args[i + 1].endsWith(".js")) - Interpreter.batchMode = true; - IJ.runMacroFile(args[i + 1], arg2); - break; - } else if (arg.startsWith("-eval") && i + 1 < nArgs) { - String rtn = IJ.runMacro(args[i + 1]); - if (rtn != null) - System.out.print(rtn); - args[i + 1] = null; - } else if (arg.startsWith("-run") && i + 1 < nArgs) { - IJ.run(args[i + 1]); - args[i + 1] = null; - } - } else if (macros == 0 && (arg.endsWith(".ijm") || arg.endsWith(".txt"))) { - IJ.runMacroFile(arg); - macros++; - } else if (arg.length() > 0 && arg.indexOf("ij.ImageJ") == -1) { - File file = new File(arg); - IJ.open(file.getAbsolutePath()); - } - } - if (IJ.debugMode && IJ.getInstance() == null && !GraphicsEnvironment.isHeadless()) - new JavaProperties().run(""); - if (noGUI) - System.exit(0); - } - - // Is there another instance of ImageJ? If so, send it the arguments and - // quit. - static boolean isRunning(String args[]) { - return OtherInstance.sendArguments(args); - } - - /** - * Returns the port that ImageJ checks on startup to see if another instance is - * running. - * - * @see ij.OtherInstance - */ - public static int getPort() { - return port; - } - - /** Returns the command line arguments passed to ImageJ. */ - public static String[] getArgs() { - return arguments; - } - - /** - * ImageJ calls System.exit() when qutting when 'exitWhenQuitting' is true. - */ - public void exitWhenQuitting(boolean ewq) { - exitWhenQuitting = ewq; - } - - /** Quit using a separate thread, hopefully avoiding thread deadlocks. */ - public void run() { - quitting = true; - boolean changes = false; - int[] wList = WindowManager.getIDList(); - if (wList != null) { - for (int i = 0; i < wList.length; i++) { - ImagePlus imp = WindowManager.getImage(wList[i]); - if (imp != null && imp.changes == true) { - changes = true; - break; - } - } - } - Frame[] frames = WindowManager.getNonImageWindows(); - if (frames != null) { - for (int i = 0; i < frames.length; i++) { - if (frames[i] != null && (frames[i] instanceof Editor)) { - if (((Editor) frames[i]).fileChanged()) { - changes = true; - break; - } - } - } - } - if (windowClosed && !changes && Menus.window.getItemCount() > Menus.WINDOW_MENU_ITEMS && !(IJ.macroRunning() && WindowManager.getImageCount() == 0)) { - GenericDialog gd = new GenericDialog("ImageJ", this); - gd.addMessage("Are you sure you want to quit ImageJ?"); - gd.showDialog(); - quitting = !gd.wasCanceled(); - windowClosed = false; - } - if (!quitting) - return; - if (!WindowManager.closeAllWindows()) { - quitting = false; - return; - } - if (applet == null) { - saveWindowLocations(); - Prefs.set(ImageWindow.LOC_KEY, null); // don't save image window location - Prefs.savePreferences(); - } - IJ.cleanup(); - dispose(); - if (exitWhenQuitting) - System.exit(0); - } - - void saveWindowLocations() { - Window win = WindowManager.getWindow("B&C"); - if (win != null) - Prefs.saveLocation(ContrastAdjuster.LOC_KEY, win.getLocation()); - win = WindowManager.getWindow("Threshold"); - if (win != null) - Prefs.saveLocation(ThresholdAdjuster.LOC_KEY, win.getLocation()); - win = WindowManager.getWindow("Results"); - if (win != null) { - Prefs.saveLocation(TextWindow.LOC_KEY, win.getLocation()); - Dimension d = win.getSize(); - Prefs.set(TextWindow.WIDTH_KEY, d.width); - Prefs.set(TextWindow.HEIGHT_KEY, d.height); - } - win = WindowManager.getWindow("Log"); - if (win != null) { - Prefs.saveLocation(TextWindow.LOG_LOC_KEY, win.getLocation()); - Dimension d = win.getSize(); - Prefs.set(TextWindow.LOG_WIDTH_KEY, d.width); - Prefs.set(TextWindow.LOG_HEIGHT_KEY, d.height); - } - win = WindowManager.getWindow("ROI Manager"); - if (win != null) - Prefs.saveLocation(RoiManager.LOC_KEY, win.getLocation()); - } - - /* - * Changed for Bio7! Overrides the default Frame settings since Bio7 Gui uses - * swt for the primary frame! - */ - public Point getLocationOnScreen() { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - - public void run() { - p = CanvasView.getCanvas_view().tabFolder.getShell().getLocation(); - } - }); - - return new Point(p.x, p.y); - } - - public static String getCommandName() { - return commandName != null ? commandName : "null"; - } - - public static void setCommandName(String name) { - commandName = name; - } - - public void resize() { - double scale = Prefs.getGuiScale(); - toolbar.init(); - statusLine.setFont(new Font("SansSerif", Font.PLAIN, (int) (13 * scale))); - progressBar.init((int) (ProgressBar.WIDTH * scale), (int) (ProgressBar.HEIGHT * scale)); - pack(); - } - - /** Handles exceptions on the EDT. */ - public static class ExceptionHandler implements Thread.UncaughtExceptionHandler { - - // for EDT exceptions - public void handle(Throwable thrown) { - handleException(Thread.currentThread().getName(), thrown); - } - - // for other uncaught exceptions - public void uncaughtException(Thread thread, Throwable thrown) { - handleException(thread.getName(), thrown); - } - - protected void handleException(String tname, Throwable e) { - if (Macro.MACRO_CANCELED.equals(e.getMessage())) - return; - CharArrayWriter caw = new CharArrayWriter(); - PrintWriter pw = new PrintWriter(caw); - e.printStackTrace(pw); - String s = caw.toString(); - if (s != null && s.contains("ij.")) { - if (IJ.getInstance() != null) - s = IJ.getInstance().getInfo() + "\n" + s; - IJ.log(s); - } - } - - } // inner class ExceptionHandler - -} diff --git a/com.eco.bio7.image/src/ij/ImageJApplet.java b/com.eco.bio7.image/src/ij/ImageJApplet.java deleted file mode 100644 index db5cb6e4f..000000000 --- a/com.eco.bio7.image/src/ij/ImageJApplet.java +++ /dev/null @@ -1,44 +0,0 @@ -package ij; -import java.applet.Applet; - -/** - Runs ImageJ as an applet and optionally opens up to - nine images using URLs passed as a parameters. - - Here is an example applet tag that launches ImageJ as an applet - and passes it the URLs of two images: - - <applet archive="../ij.jar" code="ij.ImageJApplet.class" width=0 height=0> - <param name=url1 value="http://imagej.nih.gov/ij/images/FluorescentCells.jpg"> - <param name=url2 value="http://imagej.nih.gov/ij/images/blobs.gif"> - </applet> - - To use plugins, add them to ij.jar and add entries to IJ_Props.txt file (in ij.jar) that will - create commands for them in the Plugins menu, or a submenu. There are examples - of such entries in IJ.Props.txt, in the "Plugins installed in the Plugins menu" section. - - Macros contained in a file named "StartupMacros.txt", in the same directory as the HTML file - containing the applet tag, will be installed on startup. -*/ -public class ImageJApplet extends Applet { - - /** Starts ImageJ if it's not already running. */ - public void init() { - ImageJ ij = IJ.getInstance(); - if (ij==null || (ij!=null && !ij.isShowing())) - new ImageJ(this); - for (int i=1; i<=9; i++) { - String url = getParameter("url"+i); - if (url==null) break; - ImagePlus imp = new ImagePlus(url); - if (imp!=null) imp.show(); - } - } - - public void destroy() { - ImageJ ij = IJ.getInstance(); - if (ij!=null) ij.quit(); - } - -} - diff --git a/com.eco.bio7.image/src/ij/ImageListener.java b/com.eco.bio7.image/src/ij/ImageListener.java deleted file mode 100644 index ae8faacd6..000000000 --- a/com.eco.bio7.image/src/ij/ImageListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package ij; - - /** Plugins that implement this interface are notified when - an image is opened, closed or updated. The - Plugins/Utilities/Monitor Events command uses this interface. - */ - public interface ImageListener { - - public void imageOpened(ImagePlus imp); - - public void imageClosed(ImagePlus imp); - - public void imageUpdated(ImagePlus imp); - - //default void imageSaved(ImagePlus imp) { } - -} diff --git a/com.eco.bio7.image/src/ij/ImageListenerAdapter.java b/com.eco.bio7.image/src/ij/ImageListenerAdapter.java deleted file mode 100644 index 231b2ed51..000000000 --- a/com.eco.bio7.image/src/ij/ImageListenerAdapter.java +++ /dev/null @@ -1,34 +0,0 @@ -package ij; - -/** -* An Adapter class for the ImageListener interface. Note ImageListenerAdapter -* supports notification when an ImagePlus gets saved. -* -* With this adapter you need only override the methods that you require -* notification for. -* -* TODO When ImageJ has a minimum support of Java8 consider updating -* ImageListener to provide default methods for all these callbacks as this will -* allow ImageListener interface to be used as mix-in class whereas Java single -* inheritance precludes that for this ImageListenerAdapter class. -* -* @author Michael Ellis -*/ -public class ImageListenerAdapter implements ImageListener { - - @Override - public void imageOpened(ImagePlus imp) { - } - - @Override - public void imageClosed(ImagePlus imp) { - } - - @Override - public void imageUpdated(ImagePlus imp) { - } - - public void imageSaved(ImagePlus imp) { - } - -} diff --git a/com.eco.bio7.image/src/ij/ImagePlus.java b/com.eco.bio7.image/src/ij/ImagePlus.java deleted file mode 100644 index caa63874b..000000000 --- a/com.eco.bio7.image/src/ij/ImagePlus.java +++ /dev/null @@ -1,3547 +0,0 @@ -package ij; -import java.awt.*; -import java.awt.image.*; -import java.net.URL; -import java.util.*; -import ij.process.*; -import ij.io.*; -import ij.gui.*; - -import ij.measure.*; -import ij.plugin.filter.Analyzer; -import ij.util.*; -import ij.macro.Interpreter; -import ij.plugin.*; -import ij.plugin.frame.*; - - -/** -An ImagePlus contain an ImageProcessor (2D image) or an ImageStack (3D, 4D or 5D image). -It also includes metadata (spatial calibration and possibly the directory/file where -it was read from). The ImageProcessor contains the pixel data (8-bit, 16-bit, float or RGB) -of the 2D image and some basic methods to manipulate it. An ImageStack is essentually -a list ImageProcessors of same type and size. -@see ij.process.ImageProcessor -@see ij.ImageStack -@see ij.gui.ImageWindow -@see ij.gui.ImageCanvas -*/ - -public class ImagePlus implements ImageObserver, Measurements, Cloneable { - - /** 8-bit grayscale (unsigned)*/ - public static final int GRAY8 = 0; - - /** 16-bit grayscale (unsigned) */ - public static final int GRAY16 = 1; - - /** 32-bit floating-point grayscale */ - public static final int GRAY32 = 2; - - /** 8-bit indexed color */ - public static final int COLOR_256 = 3; - - /** 32-bit RGB color */ - public static final int COLOR_RGB = 4; - - /** Title of image used by Flatten command */ - public static final String flattenTitle = "flatten~canvas"; - - /** True if any changes have been made to this image. */ - public boolean changes; - - protected Image img; - protected ImageProcessor ip; - protected ImageWindow win; - protected Roi roi; - protected int currentSlice; // current stack index (one-based) - protected static final int OPENED=0, CLOSED=1, UPDATED=2, SAVED=3; - protected boolean compositeImage; - protected int width; - protected int height; - protected boolean locked; - private int lockedCount; - private Thread lockingThread; - protected int nChannels = 1; - protected int nSlices = 1; - protected int nFrames = 1; - protected boolean dimensionsSet; - - private ImageJ ij = IJ.getInstance(); - private String title; - private String url; - private FileInfo fileInfo; - private int imageType = GRAY8; - private boolean typeSet; - private ImageStack stack; - private static int currentID = -1; - private int ID; - private static Component comp; - private boolean imageLoaded; - private int imageUpdateY, imageUpdateW; - private Properties properties; - private long startTime; - private Calibration calibration; - private static Calibration globalCalibration; - private boolean activated; - private boolean ignoreFlush; - private boolean errorLoadingImage; - private static ImagePlus clipboard; - private static Vector listeners = new Vector(); - private boolean openAsHyperStack; - private int[] position = {1,1,1}; - private boolean noUpdateMode; - private ImageCanvas flatteningCanvas; - private Overlay overlay; - private boolean compositeChanges; - private boolean hideOverlay; - private static int default16bitDisplayRange; - private boolean antialiasRendering = true; - private boolean ignoreGlobalCalibration; - private boolean oneSliceStack; - public boolean setIJMenuBar = Prefs.setIJMenuBar; - private Plot plot; - private Properties imageProperties; - private Color borderColor; - private boolean temporary; - private double defaultMin, defaultMax; - - - /** Constructs an uninitialized ImagePlus. */ - public ImagePlus() { - title = (this instanceof CompositeImage)?"composite":"null"; - setID(); - } - - /** Constructs an ImagePlus from an Image or BufferedImage. The first - argument will be used as the title of the window that displays the image. - Throws an IllegalStateException if an error occurs while loading the image. */ - public ImagePlus(String title, Image image) { - this.title = title; - if (image!=null) - setImage(image); - setID(); - } - - /** Constructs an ImagePlus from an ImageProcessor. */ - public ImagePlus(String title, ImageProcessor ip) { - setProcessor(title, ip); - setID(); - } - - /** Constructs an ImagePlus from a TIFF, BMP, DICOM, FITS, - PGM, GIF or JPRG specified by a path or from a TIFF, DICOM, - GIF or JPEG specified by a URL. */ - public ImagePlus(String pathOrURL) { - Opener opener = new Opener(); - ImagePlus imp = null; - boolean isURL = pathOrURL.indexOf("://")>0; - if (isURL) - imp = opener.openURL(pathOrURL); - else - imp = opener.openImage(pathOrURL); - if (imp!=null) { - if (imp.getStackSize()>1) - setStack(imp.getTitle(), imp.getStack()); - else - setProcessor(imp.getTitle(), imp.getProcessor()); - setCalibration(imp.getCalibration()); - properties = imp.getProperties(); - setFileInfo(imp.getOriginalFileInfo()); - setDimensions(imp.getNChannels(), imp.getNSlices(), imp.getNFrames()); - setOverlay(imp.getOverlay()); - setRoi(imp.getRoi()); - if (isURL) - this.url = pathOrURL; - setID(); - } - } - - /** Constructs an ImagePlus from a stack. */ - public ImagePlus(String title, ImageStack stack) { - setStack(title, stack); - setID(); - } - - private void setID() { - ID = --currentID; - } - - public void setTemporary() { - if (!temporary) { - temporary = true; - currentID++; - ID = -Integer.MAX_VALUE; - } - } - - /** Locks the image so other threads can test to see if it is in use. - * One thread can lock an image multiple times, then it has to unlock - * it as many times until it is unlocked. This allows nested locking - * within a thread. - * Returns true if the image was successfully locked. - * Beeps, displays a message in the status bar, and returns - * false if the image is already locked by another thread. - */ - public synchronized boolean lock() { - return lock(true); - } - - /** Similar to lock, but doesn't beep and display an error - * message if the attempt to lock the image fails. - */ - public synchronized boolean lockSilently() { - return lock(false); - } - - private synchronized boolean lock(boolean loud) { - if (locked) { - if (Thread.currentThread()==lockingThread) { - lockedCount++; //allow locking multiple times by the same thread - return true; - } else { - if (loud) { - IJ.beep(); - IJ.showStatus("\"" + title + "\" is locked"); - if (IJ.debugMode) IJ.log(title + " is locked by " + lockingThread + "; refused locking by " + Thread.currentThread().getName()); - if (IJ.macroRunning()) - IJ.wait(500); - } - return false; - } - } else { - locked = true; //we could use 'lockedCount instead, but subclasses might use - lockedCount = 1; - lockingThread = Thread.currentThread(); - if (win instanceof StackWindow) - ((StackWindow)win).setSlidersEnabled(false); - if (IJ.debugMode) IJ.log(title + ": locked" + (loud ? "" : "silently") + " by " + Thread.currentThread().getName()); - return true; - } - } - - /** Unlocks the image. - * In case the image had been locked several times by the current thread, - * it gets unlocked only after as many unlock operations as there were - * previous lock operations. - */ - public synchronized void unlock() { - if (Thread.currentThread()==lockingThread && lockedCount>1) - lockedCount--; - else { - locked = false; - lockedCount = 0; - lockingThread = null; - if (win instanceof StackWindow) - ((StackWindow)win).setSlidersEnabled(true); - if (IJ.debugMode) IJ.log(title + ": unlocked"); - } - } - - /** Returns 'true' if the image is locked. */ - public boolean isLocked() { - return locked; - } - - /** Returns 'true' if the image was locked on another thread. */ - public boolean isLockedByAnotherThread() { - return locked && Thread.currentThread()!=lockingThread; - } - - private void waitForImage(Image image) { - if (comp==null) { - comp = IJ.getInstance(); - if (comp==null) - comp = new Canvas(); - } - imageLoaded = false; - if (!comp.prepareImage(image, this)) { - double progress; - waitStart = System.currentTimeMillis(); - while (!imageLoaded && !errorLoadingImage) { - IJ.wait(30); - if (imageUpdateW>1) { - progress = (double)imageUpdateY/imageUpdateW; - if (!(progress<1.0)) { - progress = 1.0 - (progress-1.0); - if (progress<0.0) progress = 0.9; - } - showProgress(progress); - } - } - showProgress(1.0); - } - } - - long waitStart; - private void showProgress(double percent) { - if ((System.currentTimeMillis()-waitStart)>500L) - IJ.showProgress(percent); - } - - /** Draws the image. If there is an ROI, its - outline is also displayed. Does nothing if there - is no window associated with this image (i.e. show() - has not been called).*/ - public void draw() { - if (win!=null) - win.getCanvas().repaint(); - } - - /** Draws image and roi outline using a clip rect. */ - public void draw(int x, int y, int width, int height){ - if (win!=null) { - ImageCanvas ic = win.getCanvas(); - double mag = ic.getMagnification(); - x = ic.screenX(x); - y = ic.screenY(y); - width = (int)(width*mag); - height = (int)(height*mag); - ic.repaint(x, y, width, height); - if (listeners.size()>0 && roi!=null && roi.getPasteMode()!=Roi.NOT_PASTING) - notifyListeners(UPDATED); - } - } - - /** Updates this image from the pixel data in its - associated ImageProcessor, then displays it. Does - nothing if there is no window associated with - this image (i.e. show() has not been called).*/ - public synchronized void updateAndDraw() { - if (win==null) { - img = null; - return; - } - if (stack!=null && !stack.isVirtual() && currentSlice>=1 && currentSlice<=stack.size()) { - if (stack.size()>1 && win!=null && !(win instanceof StackWindow)) { - setStack(stack); //adds scroll bar if stack size has changed to >1 - return; - } - Object pixels = stack.getPixels(currentSlice); - if (ip!=null && pixels!=null && pixels!=ip.getPixels()) { // was stack updated? - try { - ip.setPixels(pixels); - ip.setSnapshotPixels(null); - } catch(Exception e) {} - } - } - if (win!=null) { - win.getCanvas().setImageUpdated(); - if (listeners.size()>0) notifyListeners(UPDATED); - } - draw(); - } - - /** Use to update the image when the underlying virtual stack changes. */ - public void updateVirtualSlice() { - ImageStack vstack = getStack(); - if (vstack.isVirtual()) { - double min=getDisplayRangeMin(), max=getDisplayRangeMax(); - setProcessor(vstack.getProcessor(getCurrentSlice())); - setDisplayRange(min,max); - } else - throw new IllegalArgumentException("Virtual stack required"); - } - - /** Sets the display mode of composite color images, where 'mode' - should be IJ.COMPOSITE, IJ.COLOR or IJ.GRAYSCALE. */ - public void setDisplayMode(int mode) { - if (this instanceof CompositeImage) { - ((CompositeImage)this).setMode(mode); - updateAndDraw(); - } - } - - /** Returns the display mode (IJ.COMPOSITE, IJ.COLOR - or IJ.GRAYSCALE) if this is a composite color - image, or 0 if it not. */ - public int getDisplayMode() { - if (this instanceof CompositeImage) - return ((CompositeImage)this).getMode(); - else - return 0; - } - - /** Controls which channels in a composite color image are displayed, - where 'channels' is a list of ones and zeros that specify the channels to - display. For example, "101" causes channels 1 and 3 to be displayed. */ - public void setActiveChannels(String channels) { - if (!(this instanceof CompositeImage)) - return; - boolean[] active = ((CompositeImage)this).getActiveChannels(); - for (int i=0; ii && channels.charAt(i)=='1') - b = true; - active[i] = b; - } - updateAndDraw(); - Channels.updateChannels(); - } - - /** Updates this image from the pixel data in its - associated ImageProcessor, then displays it. - The CompositeImage class overrides this method - to only update the current channel. */ - public void updateChannelAndDraw() { - updateAndDraw(); - } - - /** Returns a reference to the current ImageProcessor. The - CompositeImage class overrides this method to return - the processor associated with the current channel. */ - public ImageProcessor getChannelProcessor() { - return getProcessor(); - } - - /** Returns an array containing the lookup tables used by this image, - * one per channel, or an empty array if this is an RGB image. - * @see #getNChannels - * @see #isComposite - * @see #getCompositeMode - * - * Javascript example: - * - * luts = imp.getLuts(); - * for (i=0; i - * IJ.log((i+1)+“: “+luts[i].min+”-”+luts[i].max); - * - */ - public LUT[] getLuts() { - ImageProcessor ip2 = getProcessor(); - if (ip2==null) - return new LUT[0]; - LUT lut = ip2.getLut(); - if (lut==null) - return new LUT[0]; - LUT[] luts = new LUT[1]; - luts[0] = lut; - return luts; - } - - /** Calls draw to draw the image and also repaints the - image window to force the information displayed above - the image (dimension, type, size) to be updated. */ - public void repaintWindow() { - if (win!=null) { - draw(); - win.repaint(); - } - } - - /** Calls updateAndDraw to update from the pixel data - and draw the image, and also repaints the image - window to force the information displayed above - the image (dimension, type, size) to be updated. */ - public void updateAndRepaintWindow() { - if (win!=null) { - updateAndDraw(); - win.repaint(); - } - } - - /** ImageCanvas.paint() calls this method when the - * ImageProcessor has generated a new image. - */ - public void updateImage() { - if (win==null) { - img = null; - return; - } - if (ip!=null) - img = ip.createImage(); - } - - /** Closes the window, if any, that is displaying this image. */ - public void hide() { - if (win==null) { - img = null; - Interpreter.removeBatchModeImage(this); - return; - } - boolean unlocked = lockSilently(); - Overlay overlay2 = getOverlay(); - changes = false; - win.close(); - win = null; - setOverlay(overlay2); - if (unlocked) unlock(); - } - - /** Closes this image and sets the ImageProcessor to null. To avoid the - "Save changes?" dialog, first set the public 'changes' variable to false. */ - public void close() { - ImageWindow win = getWindow(); - if (win!=null) - win.close(); - else { - if (WindowManager.getCurrentImage()==this) - WindowManager.setTempCurrentImage(null); - deleteRoi(); //save any ROI so it can be restored later - Interpreter.removeBatchModeImage(this); - } - } - - /** Opens a window to display this image and clears the status bar. */ - public void show() { - show(""); - } - - /** Opens a window to display this image and displays - 'statusMessage' in the status bar. */ - public void show(String statusMessage) { - if (isVisible() || temporary) - return; - win = null; - if ((IJ.isMacro() && ij==null) || Interpreter.isBatchMode()) { - if (isComposite()) ((CompositeImage)this).reset(); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp!=null) imp.saveRoi(); - WindowManager.setTempCurrentImage(this); - Interpreter.addBatchModeImage(this); - return; - } - if (Prefs.useInvertingLut && getBitDepth()==8 && ip!=null && !ip.isInvertedLut()&& !ip.isColorLut()) - invertLookupTable(); - img = getImage(); - if ((img!=null) && (width>=0) && (height>=0)) { - activated = false; - int stackSize = getStackSize(); - if (stackSize>1) - win = new StackWindow(this); // displays the window and (if macro) waits for window to be activated - else if (getProperty(Plot.PROPERTY_KEY) != null) - win = new PlotWindow(this, (Plot)(getProperty(Plot.PROPERTY_KEY))); - else - win = new ImageWindow(this); - if (roi!=null) roi.setImage(this); - if (overlay!=null && getCanvas()!=null) - getCanvas().setOverlay(overlay); - IJ.showStatus(statusMessage); - if (IJ.isMacro() && stackSize==1) // for non-stacks, wait for window to be activated - waitTillActivated(); - if (imageType==GRAY16 && default16bitDisplayRange!=0) { - resetDisplayRange(); - updateAndDraw(); - } - if (stackSize>1) { - int c = getChannel(); - int z = getSlice(); - int t = getFrame(); - if (c>1 || z>1 || t>1) - setPosition(c, z, t); - } - if (setIJMenuBar) - IJ.wait(25); - notifyListeners(OPENED); - } - } - - void invertLookupTable() { - int nImages = getStackSize(); - ip.invertLut(); - if (nImages==1) - ip.invert(); - else { - ImageStack stack2 = getStack(); - for (int i=1; i<=nImages; i++) - stack2.getProcessor(i).invert(); - stack2.setColorModel(ip.getColorModel()); - } - } - - /** Waits until the image window becomes activated. This is necessary in - * macros or other programs if an ImagePlus is shown on the screen, - * because displaying the window is asynchronous (happens later) - * and will make the image the active one. Without waiting, in the - * meanwhile another window could be already the active one and would - * become deactivated. - * If the ImagePlus may have been displayed previously, first call - * setDeactivated(). - * ImagePlus.show() and new StackWindow(ImagePlus) - * call this method if IJ.isMacro() is true, i.e., when running a macro or - * executing an IJ.run(...) call. - */ - public void waitTillActivated() { - if (win == null) return; - if (EventQueue.isDispatchThread()) { //'activated' is set in the EventQueue, we can't wait for it in the EventQueue - WindowManager.setTempCurrentImage(this); - return; - } - long start = System.currentTimeMillis(); - while (!activated) { - IJ.wait(5); - if (ij != null && ij.quitting()) return; - if ((System.currentTimeMillis()-start)>2000) { - WindowManager.setTempCurrentImage(this); - break; // 2 second timeout - } - } - } - - /** Called by ImageWindow.windowActivated(); to end waiting in waitTillActivated. */ - public void setActivated() { - activated = true; - if (borderColor!=null && win!=null) - win.setBackground(borderColor); - } - - /** Called by new StackWindow(ImagePlus) - * before showing the StackWindow, to prepare for - * waitTillActivated(). - */ - public void setDeactivated() { - activated = false; - } - - /** Returns this image as a AWT image. */ - public Image getImage() { - if (img==null && ip!=null) - img = ip.createImage(); - return img; - } - - /** Returns a copy of this image as an 8-bit or RGB BufferedImage. - * @see ij.process.ShortProcessor#get16BitBufferedImage - */ - public BufferedImage getBufferedImage() { - if (isComposite()) - return (new ColorProcessor(getImage())).getBufferedImage(); - else - return ip.getBufferedImage(); - } - - /** Returns this image's unique numeric ID. */ - public int getID() { - return ID; - } - - /** Replaces the image, if any, with the one specified. - * Throws an IllegalStateException if an error occurs - * while loading the image. - */ - public void setImage(Image image) { - if (image instanceof BufferedImage) { - BufferedImage bi = (BufferedImage)image; - int nBands = bi.getSampleModel().getNumBands(); - int type = bi.getType(); - boolean rgb = type==BufferedImage.TYPE_3BYTE_BGR||type==BufferedImage.TYPE_INT_RGB - ||type==BufferedImage.TYPE_4BYTE_ABGR||type==BufferedImage.TYPE_BYTE_INDEXED - ||type==BufferedImage.TYPE_INT_ARGB||type==BufferedImage.TYPE_INT_BGR; - int dataType = bi.getSampleModel().getDataType(); - if (IJ.debugMode) IJ.log("setImage: type="+type+", bands="+nBands+", rgb="+rgb+", datatype="+dataType); - if (nBands>1 && !rgb) { - ImageStack biStack = new ImageStack(bi.getWidth(), bi.getHeight()); - for (int b=0; b0?GRAY8:COLOR_RGB; - if (image!=null && type==COLOR_RGB) - ip = new ColorProcessor(image); - if (ip==null && image!=null) - ip = new ByteProcessor(image); - setType(type); - this.img = ip.createImage(); - if (win!=null) { - if (dimensionsChanged) - win = new ImageWindow(this); - else - repaintWindow(); - } - } - - /** - * Extract pixels as an ImageProcessor from a single band of a BufferedImage. - * @param img - * @param band - * @return - */ - public static ImageProcessor convertToImageProcessor(BufferedImage img, int band) { - int w = img.getWidth(); - int h = img.getHeight(); - int dataType = img.getSampleModel().getDataType(); - // Read data as float (no matter what it is - it's the most accuracy ImageJ can provide) - FloatProcessor fp = new FloatProcessor(w, h); - float[] pixels = (float[])fp.getPixels(); - img.getRaster().getSamples(0, 0, w, h, band, pixels); - // Convert to 8 or 16-bit, if appropriate - if (dataType == DataBuffer.TYPE_BYTE) { - ByteProcessor bp = new ByteProcessor(w, h); - bp.setPixels(0, fp); - return bp; - } else if (dataType == DataBuffer.TYPE_USHORT) { - ShortProcessor sp = new ShortProcessor(w, h); - sp.setPixels(0, fp); - return sp; - } else - return fp; - } - - /** Replaces this image with the specified ImagePlus. May - not work as expected if 'imp' is a CompositeImage - and this image is not. */ - public void setImage(ImagePlus imp) { - Properties newProperties = imp.getProperties(); - if (newProperties!=null) - newProperties = (Properties)(newProperties.clone()); - if (imp.getWindow()!=null) - imp = imp.duplicate(); - ImageStack stack2 = imp.getStack(); - if (imp.isHyperStack()) - setOpenAsHyperStack(true); - LUT[] luts = null; - if (imp.isComposite() && (this instanceof CompositeImage)) { - if (((CompositeImage)imp).getMode()!=((CompositeImage)this).getMode()) - ((CompositeImage)this).setMode(((CompositeImage)imp).getMode()); - luts = ((CompositeImage)imp).getLuts(); - } - LUT lut = !imp.isComposite()?imp.getProcessor().getLut():null; - setStack(stack2, imp.getNChannels(), imp.getNSlices(), imp.getNFrames()); - compositeImage = imp.isComposite(); - if (luts!=null) { - ((CompositeImage)this).setLuts(luts); - ((CompositeImage)this).setMode(((CompositeImage)imp).getMode()); - updateAndRepaintWindow(); - } else if (lut!=null) { - getProcessor().setLut(lut); - updateAndRepaintWindow(); - } - setTitle(imp.getTitle()); - setCalibration(imp.getCalibration()); - setOverlay(imp.getOverlay()); - properties = newProperties; - if (getProperty(Plot.PROPERTY_KEY)!=null && win instanceof PlotWindow) { - Plot plot = (Plot)(getProperty(Plot.PROPERTY_KEY)); - ((PlotWindow)win).setPlot(plot); - plot.setImagePlus(this); - } - setFileInfo(imp.getOriginalFileInfo()); - setProperty ("Info", imp.getProperty ("Info")); - setProperties(imp.getPropertiesAsArray()); - } - - /** Replaces the ImageProcessor with the one specified and updates the - display. With stacks, the ImageProcessor must be the same type as the - other images in the stack and it must be the same width and height. */ - public void setProcessor(ImageProcessor ip) { - setProcessor(null, ip); - } - - /** Replaces the ImageProcessor with the one specified and updates the display. With - stacks, the ImageProcessor must be the same type as other images in the stack and - it must be the same width and height. Set 'title' to null to leave the title unchanged. */ - public void setProcessor(String title, ImageProcessor ip) { - if (ip==null || ip.getPixels()==null) - throw new IllegalArgumentException("ip null or ip.getPixels() null"); - if (getStackSize()>1) { - if (ip.getWidth()!=width || ip.getHeight()!=height) - throw new IllegalArgumentException("Wrong dimensions for this stack"); - int ipBitDepth = ip.getBitDepth(); - int stackBitDepth = stack!=null?stack.getBitDepth():0; - if (ipBitDepth>0 && stackBitDepth>0 && ipBitDepth!=stackBitDepth) { - String info = " \nsize="+getStackSize()+", ipBitDepth="+ipBitDepth+", stackBitDepth="+stackBitDepth; - throw new IllegalArgumentException("Wrong type for this stack"+info); - } - } else { - setStackNull(); - setCurrentSlice(1); - } - setProcessor2(title, ip, null); - } - - void setProcessor2(String title, ImageProcessor ip, ImageStack newStack) { - if (title!=null) setTitle(title); - if (ip==null) - return; - this.ip = ip; - if (this.ip!=null && getWindow()!=null) - notifyListeners(UPDATED); - if (ij!=null) - ip.setProgressBar(ij.getProgressBar()); - int stackSize = 1; - boolean dimensionsChanged = width>0 && height>0 && (width!=ip.getWidth() || height!=ip.getHeight()); - if (stack!=null) { - stackSize = stack.size(); - if (currentSlice>stackSize) - setCurrentSlice(stackSize); - if (currentSlice>=1 && currentSlice<=stackSize && !dimensionsChanged) - stack.setPixels(ip.getPixels(),currentSlice); - } - img = null; - if (dimensionsChanged) roi = null; - int type; - if (ip instanceof ByteProcessor) - type = GRAY8; - else if (ip instanceof ColorProcessor) - type = COLOR_RGB; - else if (ip instanceof ShortProcessor) - type = GRAY16; - else - type = GRAY32; - if (width==0) - imageType = type; - else - setType(type); - width = ip.getWidth(); - height = ip.getHeight(); - if (win!=null) { - if (dimensionsChanged && stackSize==1) - win.updateImage(this); - else if (newStack==null) - repaintWindow(); - draw(); - } - } - - /** Replaces the image with the specified stack and updates the display. */ - public void setStack(ImageStack stack) { - setStack(null, stack); - } - - /** Replaces the image with the specified stack and updates - the display. Set 'title' to null to leave the title unchanged. */ - public void setStack(String title, ImageStack newStack) { - int bitDepth1 = getBitDepth(); - int previousStackSize = getStackSize(); - int newStackSize = newStack.getSize(); - if (newStackSize==0) - throw new IllegalArgumentException("Stack is empty"); - if (!newStack.isVirtual()) { - Object[] arrays = newStack.getImageArray(); - if (arrays==null || (arrays.length>0&&arrays[0]==null)) - throw new IllegalArgumentException("Stack pixel array null"); - } - boolean sliderChange = false; - if (win!=null && (win instanceof StackWindow)) { - int nScrollbars = ((StackWindow)win).getNScrollbars(); - if (nScrollbars>0 && newStackSize==1) - sliderChange = true; - else if (nScrollbars==0 && newStackSize>1) - sliderChange = true; - } - if (currentSlice<1) setCurrentSlice(1); - boolean resetCurrentSlice = currentSlice>newStackSize; - if (resetCurrentSlice) setCurrentSlice(newStackSize); - ImageProcessor newIP = newStack.getProcessor(currentSlice); - boolean dimensionsChanged = width>0 && height>0 && (width!=newIP.getWidth()||height!=newIP.getHeight()); - if (this.stack==null) - newStack.viewers(+1); - this.stack = newStack; - oneSliceStack = false; - setProcessor2(title, newIP, newStack); - if (bitDepth1!=0 && bitDepth1!=getBitDepth()) - compositeChanges = true; - if (compositeChanges && (this instanceof CompositeImage)) { - this.compositeImage = getStackSize()!=getNSlices(); - ((CompositeImage)this).completeReset(); - if (bitDepth1!=0 && bitDepth1!=getBitDepth()) - ((CompositeImage)this).resetDisplayRanges(); - } - compositeChanges = false; - if (win==null) { - if (resetCurrentSlice) setSlice(currentSlice); - return; - } - boolean invalidDimensions = (isDisplayedHyperStack()||(this instanceof CompositeImage)) && (win instanceof StackWindow) && !((StackWindow)win).validDimensions(); - if (newStackSize>1 && !(win instanceof StackWindow)) { - if (isDisplayedHyperStack()) - setOpenAsHyperStack(true); - activated = false; - win = new StackWindow(this, dimensionsChanged?null:getCanvas()); // replaces this window - if (IJ.isMacro()) waitTillActivated(); // wait for stack window to be activated - setPosition(1, 1, 1); - } else if (newStackSize>1 && invalidDimensions) { - if (isDisplayedHyperStack()) - setOpenAsHyperStack(true); - win = new StackWindow(this); // replaces this window - setPosition(1, 1, 1); - } else if (dimensionsChanged || sliderChange) { - win.updateImage(this); - } else { - if (win!=null && win instanceof StackWindow) - ((StackWindow)win).updateSliceSelector(); - if (isComposite()) { - ((CompositeImage)this).reset(); - updateAndDraw(); - } - repaintWindow(); - } - if (resetCurrentSlice) - setSlice(currentSlice); - } - - public void setStack(ImageStack newStack, int channels, int slices, int frames) { - if (newStack==null || channels*slices*frames!=newStack.getSize()) - throw new IllegalArgumentException("channels*slices*frames!=stackSize"); - if (IJ.debugMode) IJ.log("setStack: "+newStack.getSize()+" "+channels+" "+slices+" "+frames+" "+isComposite()); - compositeChanges = channels!=this.nChannels; - this.nChannels = channels; - this.nSlices = slices; - this.nFrames = frames; - setStack(null, newStack); - } - - private synchronized void setStackNull() { - if (oneSliceStack && stack!=null && stack.size()>0) { - String label = stack.getSliceLabel(1); - setProp("Slice_Label", label); - } - stack = null; - oneSliceStack = false; - } - - /** Saves this image's FileInfo so it can be later - retieved using getOriginalFileInfo(). */ - public void setFileInfo(FileInfo fi) { - if (fi!=null) { - fi.pixels = null; - if (fi.imageSaved) { - notifyListeners(SAVED); - fi.imageSaved = false; - } - } - fileInfo = fi; - } - - /** Returns the ImageWindow that is being used to display - this image. Returns null if show() has not be called - or the ImageWindow has been closed. */ - public ImageWindow getWindow() { - return win; - } - - /** Returns true if this image is currently being displayed in a window. */ - public boolean isVisible() { - return win!=null && win.isVisible(); - } - - /** This method should only be called from an ImageWindow. */ - public void setWindow(ImageWindow win) { - this.win = win; - if (roi!=null) - roi.setImage(this); // update roi's 'ic' field - } - - /** Returns the ImageCanvas being used to - display this image, or null. */ - public ImageCanvas getCanvas() { - return win!=null?win.getCanvas():flatteningCanvas; - } - - /** Sets current foreground color. */ - public void setColor(Color c) { - if (ip!=null) - ip.setColor(c); - } - - void setupProcessor() { - } - - public boolean isProcessor() { - return ip!=null; - } - - /** Returns a reference to the current ImageProcessor. If there - is no ImageProcessor, it creates one. Returns null if this - ImagePlus contains no ImageProcessor and no AWT Image. - Sets the line width to the current line width and sets the - calibration table if the image is density calibrated. */ - public ImageProcessor getProcessor() { - if (ip==null) - return null; - if (roi!=null && roi.isArea()) - ip.setRoi(roi.getBounds()); - else - ip.resetRoi(); - if (!compositeImage) - ip.setLineWidth(Line.getWidth()); - if (ij!=null) - ip.setProgressBar(ij.getProgressBar()); - Calibration cal = getCalibration(); - if (cal.calibrated()) - ip.setCalibrationTable(cal.getCTable()); - else - ip.setCalibrationTable(null); - if (IJ.recording()) { - Recorder recorder = Recorder.getInstance(); - if (recorder!=null) recorder.imageUpdated(this); - } - return ip; - } - - /** Frees RAM by setting the snapshot (undo) buffer in - the current ImageProcessor to null. */ - public void trimProcessor() { - ImageProcessor ip2 = ip; - if (!locked && ip2!=null) { - if (IJ.debugMode) IJ.log(title + ": trimProcessor"); - Roi roi2 = getRoi(); - if (roi2!=null && roi2.getPasteMode()!=Roi.NOT_PASTING) - roi2.endPaste(); - ip2.setSnapshotPixels(null); - } - } - - /** For images with irregular ROIs, returns a byte mask, otherwise, returns - * null. Mask pixels have a non-zero value.and the dimensions of the - * mask are equal to the width and height of the ROI. - * @see ij.ImagePlus#createRoiMask - * @see ij.ImagePlus#createThresholdMask - */ - public ImageProcessor getMask() { - if (roi==null) { - if (ip!=null) ip.resetRoi(); - return null; - } - ImageProcessor mask = roi.getMask(); - if (mask==null) - return null; - if (ip!=null && roi!=null) { - ip.setMask(mask); - ip.setRoi(roi.getBounds()); - } - return mask; - } - - /** Returns an 8-bit binary (foreground=255, background=0) - * ROI or overlay mask that has the same dimensions - * as this image. Creates an ROI mask If the image has both - * both an ROI and an overlay. Set the threshold of the mask to 255. - * @see #createThresholdMask - * @see ij.gui.Roi#getMask - */ - public ByteProcessor createRoiMask() { - Roi roi2 = getRoi(); - Overlay overlay2 = getOverlay(); - if (roi2==null && overlay2==null) - throw new IllegalArgumentException("ROI or overlay required"); - ByteProcessor mask = new ByteProcessor(getWidth(),getHeight()); - mask.setColor(255); - if (roi2!=null) - mask.fill(roi2); - else if (overlay2!=null) { - if (overlay2.size()==1 && (overlay2.get(0) instanceof ImageRoi)) { - ImageRoi iRoi = (ImageRoi)overlay2.get(0); - ImageProcessor ip = iRoi.getProcessor(); - if (ip.getWidth()!=mask.getWidth() || ip.getHeight()!=mask.getHeight()) - return mask; - for (int i=0; i - imp = IJ.getImage(); - stats = imp.getStatistics(); - IJ.log("Area: "+stats.area); - IJ.log("Mean: "+stats.mean); - IJ.log("Max: "+stats.max); - - @return an {@link ij.process.ImageStatistics} object - @see #getAllStatistics - @see #getRawStatistics - @see ij.process.ImageProcessor#getStats - */ - public ImageStatistics getStatistics() { - return getStatistics(AREA+MEAN+STD_DEV+MODE+MIN_MAX+RECT); - } - - /** This method returns complete calibrated statistics for this - * image or ROI (with "Limit to threshold"), but it is up to 70 times - * slower than getStatistics(). - * @return an {@link ij.process.ImageStatistics} object - * @see #getStatistics - * @see ij.process.ImageProcessor#getStatistics - */ - public ImageStatistics getAllStatistics() { - return getStatistics(ALL_STATS+LIMIT); - } - - /* Returns uncalibrated statistics for this image or ROI, including - 256 bin histogram, pixelCount, mean, mode, standard deviation, - min and max. - */ - public ImageStatistics getRawStatistics() { - if (roi!=null && roi.isArea()) - ip.setRoi(roi); - else - ip.resetRoi(); - return ImageStatistics.getStatistics(ip, AREA+MEAN+MODE+STD_DEV+MIN_MAX, null); - } - - /** Returns an ImageStatistics object generated using the - specified measurement options. - @see ij.measure.Measurements - */ - public ImageStatistics getStatistics(int mOptions) { - return getStatistics(mOptions, 256, 0.0, 0.0); - } - - /** Returns an ImageStatistics object generated using the - specified measurement options and histogram bin count. */ - public ImageStatistics getStatistics(int mOptions, int nBins) { - return getStatistics(mOptions, nBins, 0.0, 0.0); - } - - /** Returns an ImageStatistics object generated using the - specified measurement options, histogram bin count - and histogram range. */ - public ImageStatistics getStatistics(int mOptions, int nBins, double histMin, double histMax) { - ImageProcessor ip2 = ip; - int bitDepth = getBitDepth(); - if (nBins!=256 && (bitDepth==8||bitDepth==24)) - ip2 =ip.convertToShort(false); - Roi roi2 = roi; - if (roi2==null) - ip2.resetRoi(); - else if (roi2.isArea()) - ip2.setRoi(roi2); - else if ((roi2 instanceof PointRoi) && roi2.size()==1) { - // needed to be consistent with ImageProcessor.getStatistics() - FloatPolygon p = roi2.getFloatPolygon(); - ip2.setRoi((int)p.xpoints[0], (int)p.ypoints[0], 1, 1); - } - ip2.setHistogramSize(nBins); - Calibration cal = getCalibration(); - if (getType()==GRAY16&& !(histMin==0.0&&histMax==0.0)) { - histMin = cal.getRawValue(histMin); - histMax=cal.getRawValue(histMax); - } - ip2.setHistogramRange(histMin, histMax); - ImageStatistics stats = ImageStatistics.getStatistics(ip2, mOptions, cal); - ip2.setHistogramSize(256); - ip2.setHistogramRange(0.0, 0.0); - return stats; - } - - /** Returns the image name. */ - public String getTitle() { - if (title==null) - return ""; - else - return title; - } - - /** If the image title is a file name, returns the name - without the extension and with spaces removed, - otherwise returns the title shortened to the first space. - */ - public String getShortTitle() { - String title = getTitle().trim(); - int index = title.lastIndexOf('.'); - boolean fileName = index>0; - if (fileName) { - title = title.substring(0, index); - title = title.replaceAll(" ",""); - } else { - index = title.indexOf(' '); - if (index>-1 && !fileName) - title = title.substring(0, index); - } - return title; - } - - /** Sets the image name. */ - public void setTitle(String title) { - if (title==null) - return; - if (win!=null) { - if (ij!=null) - Menus.updateWindowMenuItem(this, this.title, title); - String virtual = stack!=null && stack.isVirtual()?" (V)":""; - String global = getGlobalCalibration()!=null?" (G)":""; - String scale = ""; - double magnification = win.getCanvas().getMagnification(); - if (magnification!=1.0) { - double percent = magnification*100.0; - int digits = percent>100.0||percent==(int)percent?0:1; - scale = " (" + IJ.d2s(percent,digits) + "%)"; - } - win.setTitle(title+virtual+global+scale); - } - boolean titleChanged = !title.equals(this.title); - this.title = title; - if (titleChanged && listeners.size()>0) - notifyListeners(UPDATED); - } - - /** Returns the width of this image in pixels. */ - public int getWidth() { - return width; - } - - /** Returns the height of this image in pixels. */ - public int getHeight() { - return height; - } - - /** Returns the size of this image in bytes. */ - public double getSizeInBytes() { - double size = ((double)getWidth()*getHeight()*getStackSize()); - int type = getType(); - switch (type) { - case ImagePlus.GRAY16: size *= 2.0; break; - case ImagePlus.GRAY32: size *= 4.0; break; - case ImagePlus.COLOR_RGB: size *= 4.0; break; - } - return size; - } - - /** Returns the number of stack images. */ - public int getStackSize() { - if (stack==null || oneSliceStack) - return 1; - else { - int slices = stack.size(); - if (slices<=0) slices = 1; - return slices; - } - } - - /** If this is a stack, returns the actual number of images in the stack, else returns 1. */ - public int getImageStackSize() { - if (stack==null) - return 1; - else { - int slices = stack.size(); - if (slices==0) slices = 1; - return slices; - } - } - - /** Sets the 3rd, 4th and 5th dimensions, where - nChannels*nSlices*nFrames - must be equal to the stack size. */ - public void setDimensions(int nChannels, int nSlices, int nFrames) { - //IJ.log("setDimensions: "+nChannels+" "+nSlices+" "+nFrames+" "+getImageStackSize()); - if (nChannels*nSlices*nFrames!=getImageStackSize() && ip!=null) { - //throw new IllegalArgumentException("channels*slices*frames!=stackSize"); - nChannels = 1; - nSlices = getImageStackSize(); - nFrames = 1; - if (isDisplayedHyperStack()) { - setOpenAsHyperStack(false); - new StackWindow(this); - setSlice(1); - } - } - boolean updateWin = isDisplayedHyperStack() && (this.nChannels!=nChannels||this.nSlices!=nSlices||this.nFrames!=nFrames); - boolean newSingleImage = win!=null && (win instanceof StackWindow) && nChannels==1&&nSlices==1&&nFrames==1; - if (newSingleImage) updateWin = true; - this.nChannels = nChannels; - this.nSlices = nSlices; - this.nFrames = nFrames; - if (updateWin) { - if (nSlices!=getImageStackSize()) - setOpenAsHyperStack(true); - ip = null; - img = null; - setPositionWithoutUpdate(getChannel(), getSlice(), getFrame()); - if (isComposite()) ((CompositeImage)this).reset(); - new StackWindow(this); - } - dimensionsSet = true; - } - - /** Returns 'true' if this image has more - * than three dimensions. - */ - public boolean isHyperStack() { - return getNDimensions()>3; - } - - /** Returns the number of dimensions (2, 3, 4 or 5). */ - public int getNDimensions() { - int dimensions = 2; - int[] dim = getDimensions(true); - if (dim[2]>1) dimensions++; - if (dim[3]>1) dimensions++; - if (dim[4]>1) dimensions++; - return dimensions; - } - - /** Returns 'true' if this is a hyperstack currently being displayed in a StackWindow. */ - public boolean isDisplayedHyperStack() { - return win!=null && win instanceof StackWindow && ((StackWindow)win).isHyperStack(); - } - - /** Returns the number of channels. */ - public int getNChannels() { - verifyDimensions(); - return nChannels; - } - - /** Returns the image depth (number of z-slices). */ - public int getNSlices() { - verifyDimensions(); - return nSlices; - } - - /** Returns the number of frames (time-points). */ - public int getNFrames() { - verifyDimensions(); - return nFrames; - } - - /** Returns the dimensions of this image (width, height, nChannels, - nSlices, nFrames) as a 5 element int array. */ - public int[] getDimensions() { - return getDimensions(true); - } - - public int[] getDimensions(boolean varify) { - if (varify) - verifyDimensions(); - int[] d = new int[5]; - d[0] = width; - d[1] = height; - d[2] = nChannels; - d[3] = nSlices; - d[4] = nFrames; - return d; - } - - void verifyDimensions() { - int stackSize = getImageStackSize(); - if (nSlices==1) { - if (nChannels>1 && nFrames==1) - nChannels = stackSize; - else if (nFrames>1 && nChannels==1) - nFrames = stackSize; - } - if (nChannels*nSlices*nFrames!=stackSize) { - nSlices = stackSize; - nChannels = 1; - nFrames = 1; - } - } - - /** Returns the current image type (ImagePlus.GRAY8, ImagePlus.GRAY16, - ImagePlus.GRAY32, ImagePlus.COLOR_256 or ImagePlus.COLOR_RGB). - @see #getBitDepth - */ - public int getType() { - return imageType; - } - - /** Returns the bit depth, 8, 16, 24 (RGB) or 32, or 0 if the bit depth - is unknown. RGB images actually use 32 bits per pixel. */ - public int getBitDepth() { - ImageProcessor ip2 = ip; - if (ip2==null) { - int bitDepth = 0; - switch (imageType) { - case GRAY8: bitDepth=typeSet?8:0; break; - case COLOR_256: bitDepth=8; break; - case GRAY16: bitDepth=16; break; - case GRAY32: bitDepth=32; break; - case COLOR_RGB: bitDepth=24; break; - } - return bitDepth; - } - if (ip2 instanceof ByteProcessor) - return 8; - else if (ip2 instanceof ShortProcessor) - return 16; - else if (ip2 instanceof ColorProcessor) - return 24; - else if (ip2 instanceof FloatProcessor) - return 32; - return 0; - } - - /** Returns the number of bytes per pixel. */ - public int getBytesPerPixel() { - switch (imageType) { - case GRAY16: return 2; - case GRAY32: case COLOR_RGB: return 4; - default: return 1; - } - } - - protected void setType(int type) { - if ((type<0) || (type>COLOR_RGB)) - return; - int previousType = imageType; - imageType = type; - if (imageType!=previousType) { - if (win!=null) - Menus.updateMenus(); - getLocalCalibration().setImage(this); - } - typeSet = true; - } - - public void setTypeToColor256() { - if (imageType==ImagePlus.GRAY8) { - ImageProcessor ip2 = getProcessor(); - if (ip2!=null && !ip2.isThreshold() && ip2.isColorLut() && !ip2.isPseudoColorLut()) { - imageType = COLOR_256; - typeSet = true; - } - } - } - - - /** Returns the string value from the "Info" property string - * associated with 'key', or null if the key is not found. - * Works with DICOM tags and Bio-Formats metadata. - * @see #getNumericProperty - * @see #getInfoProperty - * @see #getProp - * @see #setProp - */ - public String getStringProperty(String key) { - if (key==null) - return null; - if (isDicomTag(key)) - return DicomTools.getTag(this, key); - if (getStackSize()>1) { - ImageStack stack2 = getStack(); - String label = stack2.getSliceLabel(getCurrentSlice()); - if (label!=null && label.indexOf('\n')>0) { - String value = getStringProperty(key, label); - if (value!=null) - return value; - } - } - Object obj = getProperty("Info"); - if (obj==null || !(obj instanceof String)) - return null; - String info = (String)obj; - return getStringProperty(key, info); - } - - private boolean isDicomTag(String key) { - if (key.length()!=9 || key.charAt(4)!=',') - return false; - key = key.toLowerCase(); - for (int i=0; i<9; i++) { - char c = i!=4?key.charAt(i):'0'; - if (!(Character.isDigit(c)||(c=='a'||c=='b'||c=='c'||c=='d'||c=='e'||c=='f'))) - return false; - } - return true; - } - - /** Returns the numeric value from the "Info" property string - * associated with 'key', or NaN if the key is not found or the - * value associated with the key is not numeric. Works with - * DICOM tags and Bio-Formats metadata. - * @see #getStringProperty - * @see #getInfoProperty - */ - public double getNumericProperty(String key) { - return Tools.parseDouble(getStringProperty(key)); - } - - private String getStringProperty(String key, String info) { - int index1 = -1; - index1 = findKey(info, key+": "); // standard 'key: value' pair? - if (index1<0) // Bio-Formats metadata? - index1 = findKey(info, key+" = "); - if (index1<0) // '=' with no spaces - index1 = findKey(info, key+"="); - if (index1<0) // otherwise not found - return null; - if (index1==info.length()) - return ""; //empty value at the end - int index2 = info.indexOf("\n", index1); - if (index2==-1) - index2=info.length(); - String value = info.substring(index1, index2); - return value; - } - - /** Find a key in a String (words merely ending with 'key' don't qualify). - * @return index of first character after the key, or -1 if not found - */ - private int findKey(String s, String key) { - int i = s.indexOf(key); - if (i<0) - return -1; //key not found - while (i>0 && Character.isLetterOrDigit(s.charAt(i-1))) - i = s.indexOf(key, i+key.length()); - if (i>=0) - return i + key.length(); - else - return -1; - } - - /** Adds a key-value pair to this image's string properties. - * The key-value pair is removed if 'value' is null. The - * properties persist if the image is saved in TIFF format. - * Add a "HideInfo" property (e.g. set("HideInfo","true")) to - * prevent the properties from being displayed by the - * Image/Show Info command. - */ - public void setProp(String key, String value) { - if (key==null) - return; - if (imageProperties==null) - imageProperties = new Properties(); - if (value==null || value.length()==0) - imageProperties.remove(key); - else { - imageProperties.setProperty(key, value); - if (key.equals("CompositeProjection")) - Channels.updateChannels(); - } - } - - /** Saves a persistent numeric propery. The property is - * removed if 'value' is NaN. - * @see #getNumericProp - */ - public void setProp(String key, double value) { - String svalue = ""+value; - if (svalue.endsWith(".0")) - svalue = svalue.substring(0,svalue.length()-2); - setProp(key, Double.isNaN(value)?null:svalue); - } - - /** Returns as a string the image property associated with the - * specified key or null if the property is not found. - * @see #setProp - * @see #getNumericProp - * @see #getStringProperty - */ - public String getProp(String key) { - if (imageProperties==null) - return getStringProperty(key); - else { - String value = imageProperties.getProperty(key); - if (value==null) - value = getStringProperty(key); - return value; - } - } - - /** Returns the numeric property associated with the specified key - * or NaN if the property is not found. - * @see #setProp(String,double) - * @see #getProp - */ - public double getNumericProp(String key) { - if (imageProperties==null) - return Double.NaN; - else - return Tools.parseDouble(getProp(key), Double.NaN); - } - - /** Used for saving string properties in TIFF header. */ - public String[] getPropertiesAsArray() { - if (imageProperties==null || imageProperties.size()==0) - return null; - String props[] = new String[imageProperties.size()*2]; - int index = 0; - for (Enumeration en=imageProperties.keys(); en.hasMoreElements();) { - String key = (String)en.nextElement(); - String value = imageProperties.getProperty(key); - props[index++] = key; - props[index++] = value; - } - return props; - } - - /** Returns information displayed by Image/Show Info command. */ - public String getPropsInfo() { - if (imageProperties==null || imageProperties.size()==0) - return "0"; - String info2 = ""; - for (Enumeration en=imageProperties.keys(); en.hasMoreElements();) { - String key = (String)en.nextElement(); - if (info2.length()>50) { - info2 += "..."; - break; - } else - info2 += " " + key; - } - if (info2.length()>1) - info2 = " (" + info2.substring(1) + ")"; - return imageProperties.size() + info2; - } - - /** Creates a set of image properties from an array of strings. - * @see #getPropertiesAsArray - * @see #getProp(String) - * @see #setProp(String,String) - */ - public void setProperties(String[] props) { - imageProperties = null; - if (props==null) - return; - //IJ.log("setProperties: "+props.length+" "+getTitle()); - for (int i=0; i>16; - int g = (c&0xff00)>>8; - int b = c&0xff; - pvalue[0] = r; - pvalue[1] = g; - pvalue[2] = b; - break; - case GRAY16: case GRAY32: - if (ip!=null) pvalue[0] = ip.getPixel(x, y); - break; - } - return pvalue; - } - - /** Returns an empty image stack that has the same - width, height and color table as this image. */ - public ImageStack createEmptyStack() { - ColorModel cm; - if (ip!=null) - cm = ip.getColorModel(); - else - cm = createLut().getColorModel(); - return new ImageStack(width, height, cm); - } - - /** Returns the image stack. The stack may have only - one slice. After adding or removing slices, call - setStack() to update the image and - the window that is displaying it. - @see #setStack - */ - public ImageStack getStack() { - ImageStack s; - if (stack==null) { - s = createEmptyStack(); - ImageProcessor ip2 = getProcessor(); - if (ip2==null) - return s; - String label = getProp("Slice_Label"); - if (label==null) { - String info = (String)getProperty("Info"); - label = info!=null?getTitle()+"\n"+info:null; // DICOM metadata - } - s.addSlice(label, ip2); - s.update(ip2); - this.stack = s; - ip = ip2; - oneSliceStack = true; - setCurrentSlice(1); - } else { - s = stack; - if (ip!=null) { - Calibration cal = getCalibration(); - if (cal.calibrated()) - ip.setCalibrationTable(cal.getCTable()); - else - ip.setCalibrationTable(null); - } - s.update(ip); - } - if (roi!=null) - s.setRoi(roi.getBounds()); - else - s.setRoi(null); - return s; - } - - /** Returns the base image stack. */ - public ImageStack getImageStack() { - if (stack==null) - return getStack(); - else { - stack.update(ip); - return stack; - } - } - - /** Returns the current stack index (one-based) or 1 if this is a single image. */ - public int getCurrentSlice() { - if (currentSlice<1) setCurrentSlice(1); - if (currentSlice>getStackSize()) - setCurrentSlice(getStackSize()); - return currentSlice; - } - - final void setCurrentSlice(int slice) { - currentSlice = slice; - int stackSize = getStackSize(); - if (nChannels==stackSize) updatePosition(currentSlice, 1, 1); - if (nSlices==stackSize) updatePosition(1, currentSlice, 1); - if (nFrames==stackSize) updatePosition(1, 1, currentSlice); - } - - public int getChannel() { - return position[0]; - } - - public int getSlice() { - return position[1]; - } - - public int getFrame() { - return position[2]; - } - - public void killStack() { - setStackNull(); - trimProcessor(); - } - - /** Sets the current hyperstack position and updates the display, - where 'channel', 'slice' and 'frame' are one-based indexes. */ - public void setPosition(int channel, int slice, int frame) { - //IJ.log("setPosition: "+channel+" "+slice+" "+frame+" "+noUpdateMode); - verifyDimensions(); - if (channel<0) channel=0; - if (slice<0) slice=0; - if (frame<0) frame=0; - if (channel==0) channel=getC(); - if (slice==0) slice=getZ(); - if (frame==0) frame=getT(); - if (channel>nChannels) channel=nChannels; - if (slice>nSlices) slice=nSlices; - if (frame>nFrames) frame=nFrames; - if (isDisplayedHyperStack()) { - if (noUpdateMode) { - setSlice((frame-1)*nChannels*nSlices + (slice-1)*nChannels + channel); - updatePosition(channel, slice, frame); - } else - ((StackWindow)win).setPosition(channel, slice, frame); - } else { - boolean channelChanged = channel!=getChannel(); - setSlice((frame-1)*nChannels*nSlices + (slice-1)*nChannels + channel); - updatePosition(channel, slice, frame); - if (channelChanged && isComposite() && !noUpdateMode) - updateImage(); - } - } - - /** Sets the current hyperstack position without updating the display, - where 'channel', 'slice' and 'frame' are one-based indexes. */ - public void setPositionWithoutUpdate(int channel, int slice, int frame) { - noUpdateMode = true; - setPosition(channel, slice, frame); - noUpdateMode = false; - } - - /** Sets the hyperstack channel position (one based). */ - public void setC(int channel) { - setPosition(channel, getZ(), getT()); - } - - /** Sets the hyperstack slice position (one based). */ - public void setZ(int slice) { - setPosition(getC(), slice, getT()); - } - - /** Sets the hyperstack frame position (one based). */ - public void setT(int frame) { - setPosition(getC(), getZ(), frame); - } - - /** Returns the current hyperstack channel position. */ - public int getC() { - return position[0]; - } - - /** Returns the current hyperstack slice position. */ - public int getZ() { - return position[1]; - } - - /** Returns the current hyperstack frame position. */ - public int getT() { - return position[2]; - } - - /** Returns that stack index (one-based) corresponding to the specified position. */ - public int getStackIndex(int channel, int slice, int frame) { - if (channel<1) channel = 1; - if (channel>nChannels) channel = nChannels; - if (slice<1) slice = 1; - if (slice>nSlices) slice = nSlices; - if (frame<1) frame = 1; - if (frame>nFrames) frame = nFrames; - return (frame-1)*nChannels*nSlices + (slice-1)*nChannels + channel; - } - - /* Hack needed to make the HyperStackReducer work. */ - public void resetStack() { - if (currentSlice==1 && stack!=null && stack.size()>0) { - ColorModel cm = ip.getColorModel(); - double min = ip.getMin(); - double max = ip.getMax(); - ImageProcessor ip2 = stack.getProcessor(1); - if (ip2!=null) { - ip = ip2; - ip.setColorModel(cm); - ip.setMinAndMax(min, max); - } - } - } - - /** Set the current hyperstack position based on the stack index 'n' (one-based). */ - public void setPosition(int n) { - int[] pos = convertIndexToPosition(n); - setPosition(pos[0], pos[1], pos[2]); - } - - /** Converts the stack index 'n' (one-based) into a hyperstack position (channel, slice, frame). */ - public int[] convertIndexToPosition(int n) { - if (n<1 || n>getStackSize()) - throw new IllegalArgumentException("n out of range: "+n); - int[] position = new int[3]; - int[] dim = getDimensions(); - position[0] = ((n-1)%dim[2])+1; - position[1] = (((n-1)/dim[2])%dim[3])+1; - position[2] = (((n-1)/(dim[2]*dim[3]))%dim[4])+1; - return position; - } - - /** Displays the specified stack image, where {@literal 1<=n<=stackSize}. - * Does nothing if this image is not a stack. - * @see #setPosition - * @see #setC - * @see #setZ - * @see #setT - */ - public synchronized void setSlice(int n) { - if (stack==null || (n==currentSlice&&ip!=null)) { - if (!noUpdateMode) - updateAndRepaintWindow(); - return; - } - if (n>=1 && n<=stack.size()) { - Roi roi = getRoi(); - if (roi!=null) - roi.endPaste(); - if (isProcessor()) { - if (currentSlice==0) currentSlice=1; - stack.setPixels(ip.getPixels(),currentSlice); - } - setCurrentSlice(n); - Object pixels = null; - Overlay overlay2 = null; - if (stack.isVirtual() && !((stack instanceof FileInfoVirtualStack)||(stack instanceof AVI_Reader))) { - ImageProcessor ip2 = stack.getProcessor(currentSlice); - overlay2 = ip2!=null?ip2.getOverlay():null; - if (overlay2!=null) - setOverlay(overlay2); - if (stack instanceof VirtualStack) { - Properties props = ((VirtualStack)stack).getProperties(); - if (props!=null) - setProperty("FHT", props.get("FHT")); - } - if (ip2!=null) pixels=ip2.getPixels(); - } else - pixels = stack.getPixels(currentSlice); - if (ip!=null && pixels!=null) { - try { - ip.setPixels(pixels); - ip.setSnapshotPixels(null); - } catch(Exception e) {} - } else { - ImageProcessor ip2 = stack.getProcessor(n); - if (ip2!=null) ip = ip2; - } - if (compositeImage && getCompositeMode()==IJ.COMPOSITE && ip!=null) { - int channel = getC(); - if (channel>0 && channel<=getNChannels()) - ip.setLut(((CompositeImage)this).getChannelLut(channel)); - } - if (win!=null && win instanceof StackWindow) - ((StackWindow)win).updateSliceSelector(); - if (Prefs.autoContrast && nChannels==1 && imageType!=COLOR_RGB) { - (new ContrastEnhancer()).stretchHistogram(ip,0.35,ip.getStats()); - ContrastAdjuster.update(); - //IJ.showStatus(n+": min="+ip.getMin()+", max="+ip.getMax()); - } - if (imageType==COLOR_RGB) - ContrastAdjuster.update(); - if (!noUpdateMode) - updateAndRepaintWindow(); - else - img = null; - if (ip!=null) - ip.setSliceNumber(n); - } - } - - /** Displays the specified stack image ({@literal 1<=n<=stackSize}) - without updating the display. */ - public void setSliceWithoutUpdate(int n) { - noUpdateMode = true; - setSlice(n); - noUpdateMode = false; - } - - /** Returns the current selection, or null if there is no selection. */ - public Roi getRoi() { - return roi; - } - - /** Assigns the specified ROI to this image and displays it. Any existing - ROI is deleted if roi is null or its width or height is zero. */ - public void setRoi(Roi newRoi) { - setRoi(newRoi, true); - } - - /** Assigns 'newRoi' to this image and displays it if 'updateDisplay' is true. */ - public void setRoi(Roi newRoi, boolean updateDisplay) { - if (newRoi==null) { - deleteRoi(); - return; - } - if (IJ.recording()) { - Recorder recorder = Recorder.getInstance(); - if (recorder!=null) recorder.imageUpdated(this); - } - Rectangle bounds = newRoi.getBounds(); - if (newRoi.isVisible()) { - if ((newRoi instanceof Arrow) && newRoi.getState()==Roi.CONSTRUCTING && bounds.width==0 && bounds.height==0) { - deleteRoi(); - roi = newRoi; - return; - } - if (newRoi==null) { - deleteRoi(); - return; - } - ImagePlus imp = newRoi.getImage(); - if (imp!=null && imp.getID()!=getID()) - newRoi = (Roi)newRoi.clone(); - newRoi.setImage(null); - } - if (bounds.width==0 && bounds.height==0 && !(newRoi.getType()==Roi.POINT||newRoi.getType()==Roi.LINE)) { - deleteRoi(); - return; - } - roi = newRoi; - if (ip!=null) { - ip.setMask(null); - if (roi.isArea()) - ip.setRoi(bounds); - else - ip.resetRoi(); - } - roi.setImage(this); - if ((roi instanceof PointRoi) && ((PointRoi)roi).addToOverlay()) { - IJ.run(this, "Add Selection...", ""); - roi = null; - return; - } - if (updateDisplay) - draw(); - if (roi!=null) - roi.notifyListeners(RoiListener.CREATED); - } - - /** Creates a rectangular selection. */ - public void setRoi(int x, int y, int width, int height) { - setRoi(new Rectangle(x, y, width, height)); - } - - /** Creates a rectangular selection. */ - public void setRoi(Rectangle r) { - setRoi(new Roi(r.x, r.y, r.width, r.height)); - } - - /** Starts the process of creating a new selection, where sx and sy are the - starting screen coordinates. The selection type is determined by which tool in - the tool bar is active. The user interactively sets the selection size and shape. */ - public void createNewRoi(int sx, int sy) { - Roi previousRoi = roi; - deleteRoi(); //also saves the roi as Roi.previousRoi if non-null - Roi prevRoi = Roi.getPreviousRoi(); - if (prevRoi != null) - prevRoi.setImage(previousRoi==null ? null : this); //with 'this' it will be recalled in case of ESC - switch (Toolbar.getToolId()) { - case Toolbar.RECTANGLE: - if (Toolbar.getRectToolType()==Toolbar.ROTATED_RECT_ROI) - roi = new RotatedRectRoi(sx, sy, this); - else - roi = new Roi(sx, sy, this, Toolbar.getRoundRectArcSize()); - break; - case Toolbar.OVAL: - if (Toolbar.getOvalToolType()==Toolbar.ELLIPSE_ROI) - roi = new EllipseRoi(sx, sy, this); - else - roi = new OvalRoi(sx, sy, this); - break; - case Toolbar.POLYGON: - case Toolbar.POLYLINE: - case Toolbar.ANGLE: - roi = new PolygonRoi(sx, sy, this); - break; - case Toolbar.FREEROI: - case Toolbar.FREELINE: - roi = new FreehandRoi(sx, sy, this); - break; - case Toolbar.LINE: - if ("arrow".equals(Toolbar.getToolName())) - roi = new Arrow(sx, sy, this); - else - roi = new Line(sx, sy, this); - break; - case Toolbar.TEXT: - roi = new TextRoi(sx, sy, this); - ((TextRoi)roi).setPreviousTextRoi(previousRoi); - break; - case Toolbar.POINT: - roi = new PointRoi(sx, sy, this); - if (Prefs.pointAddToOverlay) { - int measurements = Analyzer.getMeasurements(); - if (!(Prefs.pointAutoMeasure && (measurements&Measurements.ADD_TO_OVERLAY)!=0)) - IJ.run(this, "Add Selection...", ""); - Overlay overlay2 = getOverlay(); - if (overlay2!=null) - overlay2.drawLabels(!Prefs.noPointLabels); - Prefs.pointAddToManager = false; - } - if (Prefs.pointAutoMeasure || (Prefs.pointAutoNextSlice&&!Prefs.pointAddToManager)) - IJ.run(this, "Measure", ""); - if (Prefs.pointAddToManager) { - IJ.run(this, "Add to Manager ", ""); - ImageCanvas ic = getCanvas(); - if (ic!=null) { - RoiManager rm = RoiManager.getInstance(); - if (rm!=null) { - if (Prefs.noPointLabels) - rm.runCommand("show all without labels"); - else - rm.runCommand("show all with labels"); - } - } - } - if (Prefs.pointAutoNextSlice && getStackSize()>1) { - boolean order = Prefs.reverseNextPreviousOrder; - Prefs.reverseNextPreviousOrder = true; - IJ.run(this, "Next Slice [>]", ""); - Prefs.reverseNextPreviousOrder = order; - deleteRoi(); - } - break; - } - if (roi!=null) - roi.notifyListeners(RoiListener.CREATED); - } - - /** Deletes the current region of interest. Makes a copy of the ROI - so it can be recovered by Edit/Selection/Restore Selection. */ - public void deleteRoi() { - if (roi==null) - return; - saveRoi(); - if (!(IJ.altKeyDown()||IJ.shiftKeyDown())) { - RoiManager rm = RoiManager.getRawInstance(); - if (rm!=null) - rm.deselect(roi); - } - if (roi!=null) - roi.notifyListeners(RoiListener.DELETED); - roi = null; - if (ip!=null) - ip.resetRoi(); - draw(); - } - - /** Removes the spatial scaling of this image. */ - public void removeScale() { - Calibration cal = getCalibration(); - cal.pixelWidth = 1.0; - cal.pixelHeight = 1.0; - cal.pixelDepth = 1.0; - cal.setUnit("pixel"); - ImageWindow win = getWindow(); - if (win!=null) - win.repaint(); - } - - public boolean okToDeleteRoi() { - if (roi!=null && (roi instanceof PointRoi) && getWindow()!=null && ((PointRoi)roi).promptBeforeDeleting()) { - int npoints = ((PolygonRoi)roi).getNCoordinates(); - int counters = ((PointRoi)roi).getNCounters(); - String msg = "Delete this multi-point selection ("+npoints+" points, "+counters+" counter"+(counters>1?"s":"")+")?"; - GenericDialog gd=new GenericDialog("Delete Points?"); - gd.addMessage(msg+"\nRestore using Edit>Selection>Restore Selection."); - gd.addHelp(PointToolOptions.help); - gd.setOKLabel("Keep"); - gd.setCancelLabel("Delete"); - gd.showDialog(); - if (gd.wasOKed()) - return false; - } - return true; - } - - /** Deletes the current region of interest. */ - public void killRoi() { - deleteRoi(); - } - - /** Deletes the current region of interest. */ - public void resetRoi() { - deleteRoi(); - } - - public void saveRoi() { - Roi roi2 = roi; - if (roi2!=null) { - roi2.endPaste(); - Rectangle r = roi2.getBounds(); - if ((r.width>0 || r.height>0)) { - Roi.setPreviousRoi(roi2); - if (IJ.debugMode) IJ.log("saveRoi: "+roi2); - } - if ((roi2 instanceof PointRoi) && ((PointRoi)roi2).promptBeforeDeleting()) { - PointRoi.savedPoints = (PointRoi)roi2.clone(); - if (IJ.debugMode) IJ.log("saveRoi: saving multi-point selection"); - } - } - } - - public void restoreRoi() { - if (Toolbar.getToolId()==Toolbar.POINT && PointRoi.savedPoints!=null) { - roi = (Roi)PointRoi.savedPoints.clone(); - draw(); - roi.notifyListeners(RoiListener.MODIFIED); - return; - } - Roi previousRoi = Roi.getPreviousRoi(); - if (previousRoi!=null) { - Roi pRoi = previousRoi; - Rectangle r = pRoi.getBounds(); - if (r.width<=width||r.height<=height||(r.x=width || r.y>=height || (r.x+r.width)<0 || (r.y+r.height)<0) // does it need to be moved? - roi.setLocation((width-r.width)/2, (height-r.height)/2); - else if (r.width==width && r.height==height) // is it the same size as the image - roi.setLocation(0, 0); - draw(); - roi.notifyListeners(RoiListener.MODIFIED); - } - } - } - - boolean isSmaller(Roi r) { - ImageProcessor mask = r.getMask(); - if (mask==null) return false; - mask.setThreshold(255, 255, ImageProcessor.NO_LUT_UPDATE); - ImageStatistics stats = ImageStatistics.getStatistics(mask, MEAN+LIMIT, null); - return stats.area<=width*height; - } - - /** Implements the File/Revert command. */ - public void revert() { - if (getStackSize()>1 && getStack().isVirtual()) { - int thisSlice = currentSlice; - currentSlice = 0; - setSlice(thisSlice); - return; - } - FileInfo fi = getOriginalFileInfo(); - boolean isFileInfo = fi!=null && fi.fileFormat!=FileInfo.UNKNOWN; - if (!isFileInfo && url==null) - return; - if (fi.directory==null && url==null) - return; - if (ij!=null && changes && isFileInfo && !Interpreter.isBatchMode() && !IJ.isMacro() && !IJ.altKeyDown()) { - if (!IJ.showMessageWithCancel("Revert?", "Revert to saved version of\n\""+getTitle()+"\"?")) - return; - } - Roi saveRoi = null; - if (roi!=null) { - roi.endPaste(); - saveRoi = (Roi)roi.clone(); - } - trimProcessor(); - new FileOpener(fi).revertToSaved(this); - if (Prefs.useInvertingLut && getBitDepth()==8 && ip!=null && !ip.isInvertedLut()&& !ip.isColorLut()) - invertLookupTable(); - if (getProperty("FHT")!=null) { - properties.remove("FHT"); - if (getTitle().startsWith("FFT of ")) - setTitle(getTitle().substring(7)); - } - ContrastAdjuster.update(); - if (saveRoi!=null) setRoi(saveRoi); - repaintWindow(); - IJ.showStatus(""); - changes = false; - notifyListeners(UPDATED); - } - - void revertStack(FileInfo fi) { - String path = null; - String url2 = null; - if (url!=null && !url.equals("")) { - path = url; - url2 = url; - } else if (fi!=null && !((fi.directory==null||fi.directory.equals("")))) { - path = fi.getFilePath(); - } else if (fi!=null && fi.url!=null && !fi.url.equals("")) { - path = fi.url; - url2 = fi.url; - } else - return; - IJ.showStatus("Loading: " + path); - ImagePlus imp = IJ.openImage(path); - if (imp!=null) { - int n = imp.getStackSize(); - int c = imp.getNChannels(); - int z = imp.getNSlices(); - int t = imp.getNFrames(); - if (z==n || t==n || (c==getNChannels()&&z==getNSlices()&&t==getNFrames())) { - setCalibration(imp.getCalibration()); - setStack(imp.getStack(), c, z, t); - } else { - ImageWindow win = getWindow(); - Point loc = null; - if (win!=null) loc = win.getLocation(); - changes = false; - close(); - FileInfo fi2 = imp.getOriginalFileInfo(); - if (fi2!=null && (fi2.url==null || fi2.url.length()==0)) { - fi2.url = url2; - imp.setFileInfo(fi2); - } - ImageWindow.setNextLocation(loc); - imp.show(); - } - } - } - - /** Returns a FileInfo object containing information, including the - pixel array, needed to save this image. Use getOriginalFileInfo() - to get a copy of the FileInfo object used to open the image. - @see ij.io.FileInfo - @see #getOriginalFileInfo - @see #setFileInfo - */ - public FileInfo getFileInfo() { - FileInfo fi = new FileInfo(); - fi.width = width; - fi.height = height; - fi.nImages = getStackSize(); - if (compositeImage) - fi.nImages = getImageStackSize(); - fi.whiteIsZero = isInvertedLut(); - fi.intelByteOrder = false; - if (fi.nImages==1 && ip!=null) - fi.pixels = ip.getPixels(); - else if (stack!=null) - fi.pixels = stack.getImageArray(); - Calibration cal = getCalibration(); - if (cal.scaled()) { - fi.pixelWidth = cal.pixelWidth; - fi.pixelHeight = cal.pixelHeight; - fi.unit = cal.getUnit(); - } - if (fi.nImages>1) - fi.pixelDepth = cal.pixelDepth; - fi.frameInterval = cal.frameInterval; - if (cal.calibrated()) { - fi.calibrationFunction = cal.getFunction(); - fi.coefficients = cal.getCoefficients(); - fi.valueUnit = cal.getValueUnit(); - } else if (!Calibration.DEFAULT_VALUE_UNIT.equals(cal.getValueUnit())) - fi.valueUnit = cal.getValueUnit(); - - switch (imageType) { - case GRAY8: case COLOR_256: - LookUpTable lut = createLut(); - boolean customLut = !lut.isGrayscale() || (ip!=null&&!ip.isDefaultLut()); - if (imageType==COLOR_256 || customLut) - fi.fileType = FileInfo.COLOR8; - else - fi.fileType = FileInfo.GRAY8; - addLut(lut, fi); - break; - case GRAY16: - if (compositeImage && fi.nImages==3) { - if ("Red".equals(getStack().getSliceLabel(1))) - fi.fileType = fi.RGB48; - else - fi.fileType = fi.GRAY16_UNSIGNED; - } else - fi.fileType = fi.GRAY16_UNSIGNED; - if (!compositeImage) { - lut = createLut(); - if (!lut.isGrayscale() || (ip!=null&&!ip.isDefaultLut())) - addLut(lut, fi); - } - break; - case GRAY32: - fi.fileType = fi.GRAY32_FLOAT; - if (!compositeImage) { - lut = createLut(); - if (!lut.isGrayscale() || (ip!=null&&!ip.isDefaultLut())) - addLut(lut, fi); - } - break; - case COLOR_RGB: - fi.fileType = fi.RGB; - break; - default: - } - return fi; - } - - private void addLut(LookUpTable lut, FileInfo fi) { - fi.lutSize = lut.getMapSize(); - fi.reds = lut.getReds(); - fi.greens = lut.getGreens(); - fi.blues = lut.getBlues(); - } - - /** Returns the FileInfo object that was used to open this image. - Returns null for images created using the File/New command. - @see ij.io.FileInfo - @see #getFileInfo - */ - public FileInfo getOriginalFileInfo() { - if (fileInfo==null & url!=null) { - fileInfo = new FileInfo(); - fileInfo.width = width; - fileInfo.height = height; - fileInfo.url = url; - fileInfo.directory = null; - } - return fileInfo; - } - - /** Used by ImagePlus to monitor loading of images. */ - public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) { - imageUpdateY = y; - imageUpdateW = w; - if ((flags & ERROR) != 0) { - errorLoadingImage = true; - return false; - } - imageLoaded = (flags & (ALLBITS|FRAMEBITS|ABORT)) != 0; - return !imageLoaded; - } - - /** Sets the ImageProcessor, Roi, AWT Image and stack image - arrays to null. Does nothing if the image is locked. */ - public synchronized void flush() { - notifyListeners(CLOSED); - if (locked || ignoreFlush) return; - ip = null; - if (roi!=null) roi.setImage(null); - roi = null; - if (stack!=null && stack.viewers(-1)<=0) { - Object[] arrays = stack.getImageArray(); - if (arrays!=null) { - for (int i=0; istackSize) s2 = stackSize; - if (s1>s2) {s1=1; s2=stackSize;} - return new Duplicator().run(this, (int)s1, (int)s2); - } - } - - /** Returns an array of cropped images based on the provided - * list of rois. 'options' applies with stacks and can be "stack", - * "slice" or a range (e.g., "20-30"). - * @see #crop(ij.gui.Roi[]) - */ - public ImagePlus[] crop(Roi[] rois, String options) { - int nRois = rois.length; - ImagePlus[] cropImps = new ImagePlus[nRois]; - for (int i=0; i1) { - int position = cropRoi.getPosition(); - this.setSlice(position); // no effect if roi position is undefined (=0), ok - } - this.setRoi(cropRoi); - ImagePlus cropped = this.crop(options); - if (cropRoi.getType()!=Roi.RECTANGLE) { - Roi cropRoi2 = (Roi)cropRoi.clone(); - cropRoi2.setLocation(0,0); - cropped.setRoi(cropRoi2); - } - String name2 = IJ.pad(i+1,3)+"_"+this.getTitle(); - cropped.setTitle(name!=null?name:name2); - cropped.setOverlay(null); - cropImps[i] = cropped; - } - return cropImps; - } - - /** Multi-roi cropping with default "slice" option. */ - public ImagePlus[] crop(Roi[] rois) { - return this.crop(rois, "slice"); - } - - /** Saves the contents of the ROIs in this overlay as separate images, - * where 'directory' is the directory path and 'format' is "tif", "png" or "jpg". - * Set 'format' to "show" and the images will be displayed in a stack - * and not saved. - */ - public void cropAndSave(Roi[] rois, String directory, String format) { - ImagePlus[] images = crop(rois); - if (format==null) format = ""; - if (format.contains("show")) { - ImageStack stack = ImageStack.create(images); - new ImagePlus("CROPPED_"+getTitle(),stack).show(); - return; - } - String fileFormat = "tif"; - if (format.contains("png")) fileFormat = "png"; - if (format.contains("jpg")) fileFormat = "jpg"; - for (int i=0; icut is true. */ - public void copy(boolean cut) { - Roi roi = getRoi(); - if (roi!=null && !roi.isArea()) - roi = null; - if (cut && roi==null && !IJ.isMacro()) { - IJ.error("Edit>Cut", "This command requires an area selection"); - return; - } - boolean batchMode = Interpreter.isBatchMode(); - String msg = (cut)?"Cut":"Copy"; - if (!batchMode) IJ.showStatus(msg+ "ing..."); - ImageProcessor ip = getProcessor(); - ImageProcessor ip2; - ip2 = ip.crop(); - clipboard = new ImagePlus("Clipboard", ip2); - if (roi!=null) - clipboard.setRoi((Roi)roi.clone()); - if (cut) { - ip.snapshot(); - ip.setColor(Toolbar.getBackgroundColor()); - ip.fill(); - if (roi!=null && roi.getType()!=Roi.RECTANGLE) { - getMask(); - ip.reset(ip.getMask()); - } setColor(Toolbar.getForegroundColor()); - Undo.setup(Undo.FILTER, this); - updateAndDraw(); - } - int bytesPerPixel = 1; - switch (clipboard.getType()) { - case ImagePlus.GRAY16: bytesPerPixel = 2; break; - case ImagePlus.GRAY32: case ImagePlus.COLOR_RGB: bytesPerPixel = 4; - } - if (!batchMode) { - msg = (cut)?"Cut":"Copy"; - IJ.showStatus(msg + ": " + (clipboard.getWidth()*clipboard.getHeight()*bytesPerPixel)/1024 + "k"); - } - } - - /** Inserts the contents of the internal clipboard into this image. If there - is a selection the same size as the image on the clipboard, the image is inserted - into that selection, otherwise the selection is inserted into the center of the image.*/ - public void paste() { - if (clipboard==null) - return; - int cType = clipboard.getType(); - int iType = getType(); - int w = clipboard.getWidth(); - int h = clipboard.getHeight(); - Roi cRoi = clipboard.getRoi(); - Rectangle r = null; - Rectangle cr = null; - Roi roi = getRoi(); - if (roi!=null) - r = roi.getBounds(); - if (cRoi!=null) - cr = cRoi.getBounds(); - if (cr==null) - cr = new Rectangle(0, 0, w, h); - if (r==null || (cr.width!=r.width || cr.height!=r.height)) { - // Create a new roi centered on visible part of image, or centered on image if clipboard is >= image - ImageCanvas ic = win!=null?ic = win.getCanvas():null; - Rectangle srcRect = ic!=null?ic.getSrcRect():new Rectangle(0,0,width,height); - int xCenter = w>=width ? width/2 : srcRect.x + srcRect.width/2; - int yCenter = h>=height ? height/2 : srcRect.y + srcRect.height/2; - if (cRoi!=null && cRoi.getType()!=Roi.RECTANGLE) { - cRoi.setImage(this); - cRoi.setLocation(xCenter-w/2, yCenter-h/2); - setRoi(cRoi); - } else - setRoi(xCenter-w/2, yCenter-h/2, w, h); - roi = getRoi(); - } - if (IJ.isMacro()) { - //non-interactive paste - int pasteMode = Roi.getCurrentPasteMode(); - boolean nonRect = roi.getType()!=Roi.RECTANGLE; - ImageProcessor ip = getProcessor(); - if (nonRect) ip.snapshot(); - r = roi.getBounds(); - int xoffset = cr.x<0?-cr.x:0; - int yoffset = cr.y<0?-cr.y:0; - ip.copyBits(clipboard.getProcessor(), r.x+xoffset, r.y+yoffset, pasteMode); - if (nonRect) { - ImageProcessor mask = roi.getMask(); - ip.setMask(mask); - ip.setRoi(roi.getBounds()); - ip.reset(ip.getMask()); - } - updateAndDraw(); - } else if (roi!=null) { - roi.startPaste(clipboard); - Undo.setup(Undo.PASTE, this); - } - changes = true; - } - - /** Inserts the contents of the internal clipboard at the - specified location, without updating the display. */ - public void paste(int x, int y) { - paste(x, y, null); - } - - /** Copies the contents of the internal clipboard to the - * specified location using the specified transfer mode - * ("Copy", "Blend", "Average", "Difference", "Transparent", - * "Transparent2", "AND", "OR", "XOR", "Add", "Subtract", - * "Multiply", or "Divide"). The display is not updating. - */ - public void paste(int x, int y, String mode) { - if (clipboard==null) - return; - Roi roi = clipboard.getRoi(); - boolean nonRect = roi!=null && roi.getType()!=Roi.RECTANGLE; - if (nonRect) - ip.snapshot(); - if (mode==null) - ip.insert(clipboard.getProcessor(), x, y); - else { - int pasteMode = IJ.stringToPasteMode(mode); - ip.copyBits(clipboard.getProcessor(), x, y, pasteMode); - } - if (nonRect) { - ImageProcessor mask = roi.getMask(); - ip.setRoi(x, y, mask.getWidth(), mask.getHeight()); - ip.setMask(mask); - ip.reset(ip.getMask()); - } - } - - /** Returns the internal clipboard or null if the internal clipboard is empty. */ - public static ImagePlus getClipboard() { - return clipboard; - } - - /** Clears the internal clipboard. */ - public static void resetClipboard() { - clipboard = null; - } - - /** Copies the contents of the current selection, or the entire - image if there is no selection, to the system clipboard. */ - public void copyToSystem() { - Clipboard.copyToSystem(this); - } - - protected void notifyListeners(final int id) { - if (temporary) - return; - final ImagePlus imp = this; - EventQueue.invokeLater(new Runnable() { - public void run() { - for (int i=0; i=1 && imageType!=COLOR_RGB && (this instanceof CompositeImage); - } - - /** Returns the display mode (IJ.COMPOSITE, IJ.COLOR - or IJ.GRAYSCALE) if this is a CompositeImage, otherwise returns -1. */ - public int getCompositeMode() { - if (isComposite()) - return ((CompositeImage)this).getMode(); - else - return -1; - } - - /** Sets the display range of the current channel. With non-composite - * images it is identical to ip.setMinAndMax(min, max). - * Call updateAndDraw() to update the display. - */ - public void setDisplayRange(double min, double max) { - if (ip!=null) - ip.setMinAndMax(min, max); - } - - /** Returns the display range minimum of the current channel. - * @see ij.process.ImageProcessor#getMin - * @see #getLuts - */ - public double getDisplayRangeMin() { - return ip.getMin(); - } - - /** Returns the display range maximum of the current channel. - * @see ij.process.ImageProcessor#getMax - * @see #getLuts - */ - public double getDisplayRangeMax() { - return ip.getMax(); - } - - /** Sets the display range of specified channels in an RGB image, where 4=red, - 2=green, 1=blue, 6=red+green, etc. With non-RGB images, this method is - identical to setDisplayRange(min, max). This method is used by the - Image/Adjust/Color Balance tool . - */ - public void setDisplayRange(double min, double max, int channels) { - if (ip instanceof ColorProcessor) - ((ColorProcessor)ip).setMinAndMax(min, max, channels); - else - ip.setMinAndMax(min, max); - } - - public void resetDisplayRange() { - if (defaultMin!=0.0 || defaultMax!=0.0) - setDisplayRange(defaultMin, defaultMax); - else if (imageType==GRAY16 && default16bitDisplayRange>=8 && default16bitDisplayRange<=16 && !(getCalibration().isSigned16Bit())) - ip.setMinAndMax(0, Math.pow(2,default16bitDisplayRange)-1); - else - ip.resetMinAndMax(); - } - - public void setDefaultDisplayRange(double min, double max) { - this.defaultMin = min; - this.defaultMax = max; - } - - /** Uses the specified method to set the threshold levels - * of this image. Use AutoThresholder.getMethods() - * to get a list of the available methods. Add " dark" - * to the method name if the image has a dark background. - * Add " 16-bit" to use the full 16-bit histogram - * when calculating the threshold of 16-bit images. - * Add " stack" to use the histogram of the entire - * stack when calculating the threshold. - */ - public void setAutoThreshold(String method) { - IJ.setAutoThreshold(this, method); - } - - /** Returns 'true' if this image is thresholded. - * @see ij.process.ImageProcessor#isThreshold - */ - public boolean isThreshold() { - return ip!=null && ip.getMinThreshold()!=ImageProcessor.NO_THRESHOLD; - } - - /** Set the default 16-bit display range, where 'bitDepth' must be 0 (auto-scaling), - 8 (0-255), 10 (0-1023), 12 (0-4095, 14 (0-16383), 15 (0-32767) or 16 (0-65535). */ - public static void setDefault16bitRange(int bitDepth) { - if (!(bitDepth==8 || bitDepth==10 || bitDepth==12 || bitDepth==14 || bitDepth==15 || bitDepth==16)) - bitDepth = 0; - default16bitDisplayRange = bitDepth; - } - - /** Returns the default 16-bit display range, 0 (auto-scaling), 8, 10, 12, 14, 15 or 16. */ - public static int getDefault16bitRange() { - return default16bitDisplayRange; - } - - public void updatePosition(int c, int z, int t) { - position[0] = c; - position[1] = z; - position[2] = t; - } - - /** Returns a "flattened" version of this image, or stack slice, in RGB format. */ - public ImagePlus flatten() { - if (IJ.debugMode) IJ.log("flatten"); - ImagePlus impCopy = this; - if (getStackSize()>1) - impCopy = crop("whole-slice"); - ImagePlus imp2 = impCopy.createImagePlus(); - imp2.setOverlay(impCopy.getOverlay()); - imp2.setTitle(flattenTitle); - ImageCanvas ic2 = new ImageCanvas(imp2); - imp2.flatteningCanvas = ic2; - imp2.setRoi(getRoi()); - Overlay overlay2 = getOverlay(); - if (overlay2!=null && imp2.getRoi()!=null && !(imp2.getRoi() instanceof PointRoi)) { - imp2.deleteRoi(); - if (getWindow()!=null) IJ.wait(100); - } - setPointScale(imp2.getRoi(), overlay2); - ImageCanvas ic = getCanvas(); - if (ic!=null) - ic2.setShowAllList(ic.getShowAllList()); - BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D)bi.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - antialiasRendering?RenderingHints.VALUE_ANTIALIAS_ON:RenderingHints.VALUE_ANTIALIAS_OFF); - g.drawImage(getImage(), 0, 0, null); - ic2.paint(g); - imp2.flatteningCanvas = null; - ImagePlus imp3 = new ImagePlus("Flat_"+getTitle(), new ColorProcessor(bi)); - imp3.copyScale(this); - imp3.setProperty("Info", getProperty("Info")); - imp3.setProperties(getPropertiesAsArray()); - return imp3; - } - - /** Flattens all slices of this stack or HyperStack. - * @throws UnsupportedOperationException if this image - * does not have an overlay and the RoiManager overlay is null. - * Non-RGB stacks are converted to RGB. - * Copied from OverlayCommands and modified by Marcel Boeglin - * on 2014.01.08 to work with HyperStacks. - */ - public void flattenStack() { - if (IJ.debugMode) IJ.log("flattenStack"); - boolean composite = isComposite(); - if (getBitDepth()!=24) - new ImageConverter(this).convertToRGB(); - Overlay overlay1 = getOverlay(); - Overlay roiManagerOverlay = null; - boolean roiManagerShowAllMode = !Prefs.showAllSliceOnly; - ImageCanvas ic = getCanvas(); - if (ic!=null) - roiManagerOverlay = ic.getShowAllList(); - setOverlay(null); - if (roiManagerOverlay!=null) { - RoiManager rm = RoiManager.getInstance(); - if (rm!=null) - rm.runCommand("show none"); - } - Overlay overlay2 = overlay1!=null?overlay1:roiManagerOverlay; - if (composite && overlay2==null) - return; - if (overlay2==null || overlay2.size()==0) - throw new UnsupportedOperationException("A non-empty overlay is required"); - ImageStack stack2 = getStack(); - boolean showAll = overlay1!=null?false:roiManagerShowAllMode; - if (isHyperStack()) { - int Z = getNSlices(); - for (int z=1; z<=Z; z++) { - for (int t=1; t<=getNFrames(); t++) { - int image = z + (t-1)*Z; - flattenImage(stack2, image, overlay2.duplicate(), showAll, z, t); - } - } - } else { - for (int s=1; s<=stack2.getSize(); s++) { - flattenImage(stack2, s, overlay2.duplicate(), showAll); - } - } - setStack(stack2); - } - - /** Flattens Overlay 'overlay' on slice 'slice' of ImageStack 'stack'. - * Copied from OverlayCommands by Marcel Boeglin 2014.01.08. - */ - private void flattenImage(ImageStack stack, int slice, Overlay overlay, boolean showAll) { - ImageProcessor ips = stack.getProcessor(slice); - ImagePlus imp1 = new ImagePlus("temp", ips); - int w = imp1.getWidth(); - int h = imp1.getHeight(); - for (int i=0; i1) { - if (!IJ.isMacro()) rm.toFront(); - rm.runCommand("show all with labels"); - } - } - } - return hideOverlay; - } - - /** Enable/disable use of antialiasing by the flatten() method. */ - public void setAntialiasRendering(boolean antialiasRendering) { - this.antialiasRendering = antialiasRendering; - } - - /** Returns a shallow copy of this ImagePlus. */ - public synchronized Object clone() { - try { - ImagePlus copy = (ImagePlus)super.clone(); - copy.win = null; - return copy; - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** Plots a 256 bin histogram of this image and returns the PlotWindow. */ - public PlotWindow plotHistogram() { - return plotHistogram(256); - } - - /** Plots a histogram of this image using the specified - number of bins and returns the PlotWindow. */ - public PlotWindow plotHistogram(int bins) { - ImageStatistics stats = getStatistics(AREA+MEAN+MODE+MIN_MAX, bins); - Plot plot = new Plot("Hist_"+getTitle(), "Value", "Frequency"); - plot.setColor("black", "#999999"); - plot.setFont(new Font("SansSerif",Font.PLAIN,14)); - double[] y = stats.histogram(); - int n = y.length; - double[] x = new double[n]; - int bits = getBitDepth(); - boolean eightBit = bits==8 || bits==24; - double min = !eightBit?stats.min:0; - for (int i=0; i=size) { - Object[] tmp1 = new Object[size*2]; - System.arraycopy(stack, 0, tmp1, 0, size); - stack = tmp1; - String[] tmp2 = new String[size*2]; - System.arraycopy(label, 0, tmp2, 0, size); - label = tmp2; - } - stack[nSlices-1] = pixels; - this.label[nSlices-1] = sliceLabel; - if (this.bitDepth==0) - setBitDepth(pixels); - } - - private void setBitDepth(Object pixels) { - if (pixels==null) - return; - if (pixels instanceof byte[]) - this.bitDepth = 8; - else if (pixels instanceof short[]) - this.bitDepth = 16; - else if (pixels instanceof float[]) - this.bitDepth = 32; - else if (pixels instanceof int[]) - this.bitDepth = 24; - } - - /** - * @deprecated - * Short images are always unsigned. - */ - public void addUnsignedShortSlice(String sliceLabel, Object pixels) { - addSlice(sliceLabel, pixels); - } - - /** Adds the image in 'ip' to the end of the stack. */ - public void addSlice(ImageProcessor ip) { - addSlice(null, ip); - } - - /** Adds the image in 'ip' to the end of the stack, setting - the string 'sliceLabel' as the slice metadata. */ - public void addSlice(String sliceLabel, ImageProcessor ip) { - ip = convertType(ip); - if (ip.getWidth()!=this.width || ip.getHeight()!=this.height) { - if (this.width==0 && this.height==0) - init(ip.getWidth(), ip.getHeight()); - else { - ImageProcessor ip2 = ip.createProcessor(this.width,this.height); - ip2.insert(ip, 0, 0); - ip = ip2; - } - } - if (nSlices==0) { - cm = ip.getColorModel(); - min = ip.getMin(); - max = ip.getMax(); - } - addSlice(sliceLabel, ip.getPixels()); - } - - private void init(int width, int height) { - this.width = width; - this.height = height; - stack = new Object[INITIAL_SIZE]; - label = new String[INITIAL_SIZE]; - } - - private ImageProcessor convertType(ImageProcessor ip) { - int newBitDepth = ip.getBitDepth(); - if (this.bitDepth==0) - this.bitDepth = newBitDepth; - if (this.bitDepth!=newBitDepth) { - switch (this.bitDepth) { - case 8: ip=ip.convertToByte(true); break; - case 16: ip=ip.convertToShort(true); break; - case 24: ip=ip.convertToRGB(); break; - case 32: ip=ip.convertToFloat(); break; - } - } - return ip; - } - - /** Adds the image in 'ip' to the stack following slice 'n'. Adds - the slice to the beginning of the stack if 'n' is zero. */ - public void addSlice(String sliceLabel, ImageProcessor ip, int n) { - if (n<0 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - addSlice(sliceLabel, ip); - Object tempSlice = stack[nSlices-1]; - String tempLabel = label[nSlices-1]; - int first = n>0?n:1; - for (int i=nSlices-1; i>=first; i--) { - stack[i] = stack[i-1]; - label[i] = label[i-1]; - } - stack[n] = tempSlice; - label[n] = tempLabel; - } - - /** Deletes the specified slice, where {@literal 1<=n<=nslices}. */ - public void deleteSlice(int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - if (nSlices<1) - return; - for (int i=n; i0) - deleteSlice(nSlices); - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public void setRoi(Rectangle roi) { - this.roi = roi; - } - - public Rectangle getRoi() { - if (roi==null) - return new Rectangle(0, 0, width, height); - else - return(roi); - } - - /** Updates this stack so its attributes, such as min, max, - calibration table and color model, are the same as 'ip'. */ - public void update(ImageProcessor ip) { - if (ip!=null) { - min = ip.getMin(); - max = ip.getMax(); - cTable = ip.getCalibrationTable(); - cm = ip.getColorModel(); - } - } - - /** Returns the pixel array for the specified slice, where {@literal 1<=n<=nslices}. */ - public Object getPixels(int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - return stack[n-1]; - } - - /** Assigns a pixel array to the specified slice, where {@literal 1<=n<=nslices}. */ - public void setPixels(Object pixels, int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - stack[n-1] = pixels; - if (this.bitDepth==0) - setBitDepth(pixels); - } - - /** Returns the stack as an array of 1D pixel arrays. Note - that the size of the returned array may be greater than - the number of slices currently in the stack, with - unused elements set to null. */ - public Object[] getImageArray() { - return stack; - } - - /** Returns the number of slices in this stack. */ - public int size() { - return getSize(); - } - - public int getSize() { - return nSlices; - } - - /** Returns the slice labels as an array of Strings. Note - that the size of the returned array may be greater than - the number of slices currently in the stack. Returns null - if the stack is empty or the label of the first slice is null. */ - public String[] getSliceLabels() { - if (nSlices==0) - return null; - else - return label; - } - - /** Returns the label of the specified slice, where {@literal 1<=n<=nslices}. - Returns null if the slice does not have a label or 'n'; - is out of range. For DICOM and FITS stacks, labels may - contain header information. - */ - public String getSliceLabel(int n) { - if (n<1 || n>nSlices) - return null; - else - return label[n-1]; - } - - /** Returns a shortened version (up to the first 60 characters - * or first newline), with the extension removed, of the specified - * slice label, or null if the slice does not have a label. - */ - public String getShortSliceLabel(int n) { - return getShortSliceLabel(n, 60); - } - - /** Returns a shortened version (up to the first 'max' characters - * or first newline), with the extension removed, of the specified - * slice label, or null if the slice does not have a label. - */ - public String getShortSliceLabel(int n, int max) { - String shortLabel = getSliceLabel(n); - if (shortLabel==null) return null; - int newline = shortLabel.indexOf('\n'); - if (newline==0) return null; - if (newline>0) - shortLabel = shortLabel.substring(0, newline); - int len = shortLabel.length(); - if (len>4 && shortLabel.charAt(len-4)=='.' && !Character.isDigit(shortLabel.charAt(len-1))) - shortLabel = shortLabel.substring(0,len-4); - if (shortLabel.length()>max) - shortLabel = shortLabel.substring(0, max); - return shortLabel; - } - - /** Sets the label of the specified slice, where {@literal 1<=n<=nslices}. */ - public void setSliceLabel(String label, int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - this.label[n-1] = label; - } - - /** Returns an ImageProcessor for the specified slice, - * where {@literal 1<=n<=nslices}. - * Returns null if the stack is empty. - */ - public ImageProcessor getProcessor(int n) { - ImageProcessor ip; - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - if (nSlices==0) - return null; - if (stack[n-1]==null) - throw new IllegalArgumentException("Pixel array is null"); - if (stack[n-1] instanceof byte[]) - ip = new ByteProcessor(width, height, null, cm); - else if (stack[n-1] instanceof short[]) - ip = new ShortProcessor(width, height, null, cm); - else if (stack[n-1] instanceof int[]) { - if (signedInt) - ip = new IntProcessor(width, height); - else - ip = new ColorProcessor(width, height, null); - } else if (stack[n-1] instanceof float[]) - ip = new FloatProcessor(width, height, null, cm); - else - throw new IllegalArgumentException("Unknown stack type"); - ip.setPixels(stack[n-1]); - if (min!=Double.MAX_VALUE && ip!=null && !(ip instanceof ColorProcessor)) - ip.setMinAndMax(min, max); - if (cTable!=null) - ip.setCalibrationTable(cTable); - ip.setSliceNumber(n); - return ip; - } - - /** Assigns the pixel array of an ImageProcessor to the specified slice, - * where {@literal 1<=n<=nslices}. - */ - public void setProcessor(ImageProcessor ip, int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - ip = convertType(ip); - if (ip.getWidth()!=width || ip.getHeight()!=height) - throw new IllegalArgumentException("Wrong dimensions for this stack"); - stack[n-1] = ip.getPixels(); - } - - /** Assigns a new color model to this stack. */ - public void setColorModel(ColorModel cm) { - this.cm = cm; - } - - /** Returns this stack's color model. May return null. */ - public ColorModel getColorModel() { - return cm; - } - - /** Returns true if this is a 3-slice, 8-bit RGB stack. */ - public boolean isRGB() { - return getSize()==3 && (stack[0] instanceof byte[]) && getSliceLabel(1)!=null && getSliceLabel(1).equals("Red"); - } - - /** Returns true if this is a 3-slice HSB stack. */ - public boolean isHSB() { - return getSize()==3 && bitDepth==8 && getSliceLabel(1)!=null && getSliceLabel(1).equals("Hue"); - } - - /** Returns true if this is a 3-slice 32-bit HSB stack. */ - public boolean isHSB32() { - return getSize()==3 && bitDepth==32 && getSliceLabel(1)!=null && getSliceLabel(1).equals("Hue"); - } - - /** Returns true if this is a Lab stack. */ - public boolean isLab() { - return getSize()==3 && getSliceLabel(1)!=null && getSliceLabel(1).equals("L*"); - } - - /** Returns true if this is a virtual (disk resident) stack. - This method is overridden by the VirtualStack subclass. */ - public boolean isVirtual() { - return false; - } - - /** Frees memory by deleting a few slices from the end of the stack. */ - public void trim() { - int n = (int)Math.round(Math.log(nSlices)+1.0); - for (int i=0; i=0 && x=0 && y=0 && z=0 && x=0 && y=0 && z255.0) - value = 255.0; - else if (value<0.0) - value = 0.0; - bytes[y*width+x] = (byte)(value+0.5); - break; - case 16: - short[] shorts = (short[])stack[z]; - if (value>65535.0) - value = 65535.0; - else if (value<0.0) - value = 0.0; - shorts[y*width+x] = (short)(value+0.5); - break; - case 32: - float[] floats = (float[])stack[z]; - floats[y*width+x] = (float)value; - break; - case 24: - int[] ints = (int[])stack[z]; - ints[y*width+x] = (int)value; - break; - } - } - } - - public float[] getVoxels(int x0, int y0, int z0, int w, int h, int d, float[] voxels) { - boolean inBounds = x0>=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - voxels = new float[w*h*d]; - int i = 0; - int offset; - for (int z=z0; z=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - voxels = new float[w*h*d]; - int i = 0; - for (int z=z0; z>16; break; - case 1: value=(value&0xff00)>>8; break; - case 2: value=value&0xff;; break; - } - voxels[i++] = (float)value; - } - } - } - return voxels; - } - - /** Experimental */ - public void setVoxels(int x0, int y0, int z0, int w, int h, int d, float[] voxels) { - boolean inBounds = x0>=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - ; - int i = 0; - float value; - for (int z=z0; z255f) - value = 255f; - else if (value<0f) - value = 0f; - bytes[y*width+x] = (byte)(value+0.5f); - } - break; - case 16: - short[] shorts = (short[])stack[z]; - for (int x=x0; x65535f) - value = 65535f; - else if (value<0f) - value = 0f; - shorts[y*width+x] = (short)(value+0.5f); - } - break; - case 32: - float[] floats = (float[])stack[z]; - for (int x=x0; x=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - ; - int i = 0; - for (int z=z0; z0) - setBitDepth(stack[0]); - return this.bitDepth; - } - - /** Sets the bit depth (8=byte, 16=short, 24=RGB, 32=float). */ - public void setBitDepth(int depth) { - if (size()==0 && (depth==8||depth==16||depth==24||depth==32)) - this.bitDepth = depth; - } - - /** Creates a new ImageStack. - * @param width width in pixels - * @param height height in pixels - * @param depth number of images - * @param bitdepth 8, 16, 32 (float) or 24 (RGB) - */ - public static ImageStack create(int width, int height, int depth, int bitdepth) { - ImageStack stack = IJ.createImage("", width, height, depth, bitdepth).getStack(); - if (bitdepth==16 || bitdepth==32) { - stack.min = Double.MAX_VALUE; - stack.max = 0.0; - } - return stack; - } - - /** Creates an ImageStack from an ImagePlus array. */ - public static ImageStack create(ImagePlus[] images) { - int w = 0; - int h = 0; - for (int i=0; iw) w=images[i].getWidth(); - if (images[i].getHeight()>h) h=images[i].getHeight(); - } - ImageStack stack = new ImageStack(w, h); - stack.init(w, h); - for (int i=0; ithis.width||y+height>this.height||z+depth>size()) - throw new IllegalArgumentException("Argument out of range"); - ImageStack stack2 = new ImageStack(width, height, getColorModel()); - for (int i=z; itrue if this is a 256 entry grayscale LUT. - @see ij.process.ImageProcessor#isColorLut - */ - public boolean isGrayscale() { - boolean isGray = true; - if (mapSize < 256) - return false; - for (int i=0; i 1) - return fs.saveAsTiffStack(path); - else - return fs.saveAsTiff(path); - } - - public static String getName(String path) { - int i = path.lastIndexOf('/'); - if (i == -1) - i = path.lastIndexOf('\\'); - if (i > 0) - return path.substring(i + 1); - else - return path; - } - - public static String getDir(String path) { - int i = path.lastIndexOf('/'); - if (i == -1) - i = path.lastIndexOf('\\'); - if (i > 0) - return path.substring(0, i + 1); - else - return ""; - } - - /** Aborts the currently running macro or any plugin using IJ.run(). */ - public static void abort() { - // IJ.log("Abort: "+Thread.currentThread().getName()); - abort = true; - if (Thread.currentThread().getName().endsWith("Macro$")) { - table.remove(Thread.currentThread()); - /* Changed for Bio7 to get a message instead of the stack trace! */ - try { - throw new RuntimeException(MACRO_CANCELED); - } catch (Exception e) { - System.out.println(MACRO_CANCELED); - } - - } - } - - /** - * If a command started using run(name, options) is running, and the current - * thread is the same thread, returns the options string, otherwise, returns - * null. - * - * @see ij.gui.GenericDialog - * @see ij.io.OpenDialog - */ - public static String getOptions() { - String threadName = Thread.currentThread().getName(); - - // IJ.log("getOptions: "+threadName+" "+Thread.currentThread().hashCode()); //ts - /*Changed for Bio7. Added Eclipse 'Worker' thread name!*/ - if (threadName.startsWith("Run$_") || threadName.contains("Worker")||threadName.startsWith("RMI TCP")) { - Object options = table.get(Thread.currentThread()); - return options == null ? null : options + " "; - } else - return null; - } - - /** Define a set of Macro options for the current Thread. */ - public static void setOptions(String options) { - // IJ.log("setOptions: "+Thread.currentThread().getName()+" - // "+Thread.currentThread().hashCode()+" "+options); //ts - if (options == null || options.equals("")) - table.remove(Thread.currentThread()); - else - table.put(Thread.currentThread(), options); - } - - /** Define a set of Macro options for a Thread. */ - public static void setOptions(Thread thread, String options) { - if (null == thread) - throw new RuntimeException("Need a non-null thread instance"); - if (null == options) - table.remove(thread); - else - table.put(thread, options); - } - - public static String getValue(String options, String key, String defaultValue) { - key = trimKey(key); - if (!options.endsWith(" ")) - options = options + " "; - key += '='; - int index = -1; - do { // Require that key not be preceded by a letter - index = options.indexOf(key, ++index); - if (index < 0) - return defaultValue; - } while (index != 0 && Character.isLetter(options.charAt(index - 1))); - options = options.substring(index + key.length(), options.length()); - if (options.charAt(0) == '\'') { - index = options.indexOf("'", 1); - if (index < 0) - return defaultValue; - else - return options.substring(1, index); - } else if (options.charAt(0) == '[') { - int count = 1; - index = -1; - for (int i = 1; i < options.length(); i++) { - char ch = options.charAt(i); - if (ch == '[') - count++; - else if (ch == ']') - count--; - if (count == 0) { - index = i; - break; - } - } - if (index < 0) - return defaultValue; - else - return options.substring(1, index); - } else { - index = options.indexOf(" "); - if (index < 0) - return defaultValue; - else - return options.substring(0, index); - } - } - - public static String trimKey(String key) { - if (key==null) - return key; - int index = key.indexOf(" "); - if (index > -1) - key = key.substring(0, index); - index = key.indexOf(":"); - if (index > -1) - key = key.substring(0, index); - key = key.toLowerCase(Locale.US); - return key; - } - - /** - * Evaluates 'code' and returns the output, or any error, as a String (e.g., - * Macro.eval("2+2") returns "4"). - */ - public static String eval(String code) { - return new Interpreter().eval(code); - } - -} diff --git a/com.eco.bio7.image/src/ij/Menus.java b/com.eco.bio7.image/src/ij/Menus.java deleted file mode 100644 index 6546f62fc..000000000 --- a/com.eco.bio7.image/src/ij/Menus.java +++ /dev/null @@ -1,1946 +0,0 @@ -package ij; - -import ij.process.*; -import ij.util.*; -import ij.gui.ImageWindow; -import ij.plugin.MacroInstaller; -import ij.gui.Toolbar; -import ij.macro.Interpreter; -import java.awt.*; -import java.awt.image.*; -import java.awt.event.*; -import java.util.*; -import java.io.*; -import java.net.URL; -import java.applet.Applet; -import java.awt.event.*; -import java.util.zip.*; - -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Platform; -import org.eclipse.jface.action.IContributionItem; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IViewSite; -import org.osgi.framework.Bundle; - -import com.eco.bio7.ImageJPluginActions.ImageJExtensionAction; -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.Util; - -/** - * This class installs and updates ImageJ's menus. Note that menu labels, even - * in submenus, must be unique. This is because ImageJ uses a single hash table - * for all menu labels. If you look closely, you will see that - * File->Import->Text Image... and File->Save As->Text Image... do not use the - * same label. One of the labels has an extra space. - * - * @see ImageJ - */ - -public class Menus { - - public static final char PLUGINS_MENU = 'p'; - public static final char IMPORT_MENU = 'i'; - public static final char SAVE_AS_MENU = 's'; - public static final char SHORTCUTS_MENU = 'h'; // 'h'=hotkey - public static final char ABOUT_MENU = 'a'; - public static final char FILTERS_MENU = 'f'; - public static final char TOOLS_MENU = 't'; - public static final char UTILITIES_MENU = 'u'; - - public static final int WINDOW_MENU_ITEMS = 6; // fixed items at top of - // Window menu - public static final int NORMAL_RETURN = 0; - public static final int COMMAND_IN_USE = -1; - public static final int INVALID_SHORTCUT = -2; - public static final int SHORTCUT_IN_USE = -3; - public static final int NOT_INSTALLED = -4; - public static final int COMMAND_NOT_FOUND = -5; - - public static final int MAX_OPEN_RECENT_ITEMS = 15; - - private static Menus instance; - private static MenuBar mbar; - private static CheckboxMenuItem gray8Item, gray16Item, gray32Item, color256Item, colorRGBItem, RGBStackItem, - HSBStackItem, LabStackItem, HSB32Item; - private static PopupMenu popup; - - private static ImageJ ij; - private static Applet applet; - private Hashtable demoImagesTable = new Hashtable(); - private static String ImageJPath, pluginsPath, macrosPath; - private static Properties menus; - private static Properties menuSeparators; - private static Menu pluginsMenu, saveAsMenu, shortcutsMenu, utilitiesMenu, macrosMenu; - static Menu window, openRecentMenu; - private static Hashtable pluginsTable; - - private static int nPlugins, nMacros; - private static Hashtable shortcuts; - private static Hashtable macroShortcuts; - private static Vector pluginsPrefs; // commands saved in IJ_Prefs - static int windowMenuItems2; // non-image windows listed in Window menu + - // separator - private String error; - private String jarError; - private String pluginError; - private boolean isJarErrorHeading; - private static boolean installingJars, duplicateCommand; - private static Vector jarFiles; // JAR files in plugins folder with "_" in - // their name - private Map menuEntry2jarFile = new HashMap(); - private static Vector macroFiles; // Macros and scripts in the plugins - // folder - private static int userPluginsIndex; // First user plugin or submenu in - // Plugins menu - private static boolean addSorted; - private static int defaultFontSize = IJ.isWindows() ? 15 : 0; - private static int fontSize; - private static double scale = 1.0; - private static Font cachedFont;//Not used since we are using SWT menus! - - static boolean jnlp; // true when using Java WebStart - public static int setMenuBarCount; - /* Changed for Bio7! */ - public static Vector bio7JarAllCommand; - - Menus(ImageJ ijInstance, Applet appletInstance) { - ij = ijInstance; - String title = ij != null ? ij.getTitle() : null; - applet = appletInstance; - instance = this; - fontSize = Prefs.getInt(Prefs.MENU_SIZE, defaultFontSize); - - } - - String addMenuBar() { - - scale = Prefs.getGuiScale(); - //if ((scale >= 1.5 && scale < 2.0) || (scale >= 2.5 && scale < 3.0)) - // scale = (int) Math.round(scale); - nPlugins = nMacros = userPluginsIndex = 0; - addSorted = installingJars = duplicateCommand = false; - error = null; - mbar = null; - menus = new Properties(); - pluginsTable = new Hashtable(); - - /* Changed for Bio7! */ - bio7JarAllCommand = new Vector(); - - shortcuts = new Hashtable(); - pluginsPrefs = new Vector(); - macroShortcuts = null; - setupPluginsAndMacrosPaths(); - Menu file = getMenu("File"); - Menu newMenu = getMenu("File>New", true); - addPlugInItem(file, "Open...", "ij.plugin.Commands(\"open\")", KeyEvent.VK_O, false); - addPlugInItem(file, "Open Next", "ij.plugin.NextImageOpener", KeyEvent.VK_O, true); - Menu openSamples = getMenu("File>Open Samples", true); - openSamples.addSeparator(); - addPlugInItem(openSamples, "Cache Sample Images ", "ij.plugin.URLOpener(\"cache\")", 0, false); - addOpenRecentSubMenu(file); - Menu importMenu = getMenu("File>Import", true); - Menu showFolderMenu = new Menu("Show Folder"); - file.add(showFolderMenu); - addPlugInItem(showFolderMenu, "Image", "ij.plugin.SimpleCommands(\"showdirImage\")", 0, false); - addPlugInItem(showFolderMenu, "Plugins", "ij.plugin.SimpleCommands(\"showdirPlugins\")", 0, false); - addPlugInItem(showFolderMenu, "Macros", "ij.plugin.SimpleCommands(\"showdirMacros\")", 0, false); - addPlugInItem(showFolderMenu, "LUTs", "ij.plugin.SimpleCommands(\"showdirLuts\")", 0, false); - addPlugInItem(showFolderMenu, "ImageJ", "ij.plugin.SimpleCommands(\"showdirImageJ\")", 0, false); - addPlugInItem(showFolderMenu, "temp", "ij.plugin.SimpleCommands(\"showdirTemp\")", 0, false); - addPlugInItem(showFolderMenu, "Home", "ij.plugin.SimpleCommands(\"showdirHome\")", 0, false); - file.addSeparator(); - addPlugInItem(file, "Close", "ij.plugin.Commands(\"close\")", KeyEvent.VK_W, false); - addPlugInItem(file, "Close All", "ij.plugin.Commands(\"close-all\")", KeyEvent.VK_W, true); - addPlugInItem(file, "Save", "ij.plugin.Commands(\"save\")", KeyEvent.VK_S, false); - saveAsMenu = getMenu("File>Save As", true); - addPlugInItem(file, "Revert", "ij.plugin.Commands(\"revert\")", KeyEvent.VK_R, true); - file.addSeparator(); - addPlugInItem(file, "Page Setup...", "ij.plugin.filter.Printer(\"setup\")", 0, false); - addPlugInItem(file, "Print...", "ij.plugin.filter.Printer(\"print\")", KeyEvent.VK_P, false); - - Menu edit = getMenu("Edit"); - addPlugInItem(edit, "Undo", "ij.plugin.Commands(\"undo\")", KeyEvent.VK_Z, false); - edit.addSeparator(); - addPlugInItem(edit, "Cut", "ij.plugin.Clipboard(\"cut\")", KeyEvent.VK_X, false); - addPlugInItem(edit, "Copy", "ij.plugin.Clipboard(\"copy\")", KeyEvent.VK_C, false); - addPlugInItem(edit, "Copy to System", "ij.plugin.Clipboard(\"scopy\")", 0, false); - addPlugInItem(edit, "Paste", "ij.plugin.Clipboard(\"paste\")", KeyEvent.VK_V, false); - addPlugInItem(edit, "Paste Control...", "ij.plugin.frame.PasteController", 0, false); - edit.addSeparator(); - addPlugInItem(edit, "Clear", "ij.plugin.filter.Filler(\"clear\")", 0, false); - addPlugInItem(edit, "Clear Outside", "ij.plugin.filter.Filler(\"outside\")", 0, false); - addPlugInItem(edit, "Fill", "ij.plugin.filter.Filler(\"fill\")", KeyEvent.VK_F, false); - addPlugInItem(edit, "Draw", "ij.plugin.filter.Filler(\"draw\")", KeyEvent.VK_D, false); - addPlugInItem(edit, "Invert", "ij.plugin.filter.Filters(\"invert\")", KeyEvent.VK_I, true); - edit.addSeparator(); - getMenu("Edit>Selection", true); - Menu optionsMenu = getMenu("Edit>Options", true); - - Menu image = getMenu("Image"); - Menu imageType = getMenu("Image>Type"); - gray8Item = addCheckboxItem(imageType, "8-bit", "ij.plugin.Converter(\"8-bit\")"); - gray16Item = addCheckboxItem(imageType, "16-bit", "ij.plugin.Converter(\"16-bit\")"); - gray32Item = addCheckboxItem(imageType, "32-bit", "ij.plugin.Converter(\"32-bit\")"); - color256Item = addCheckboxItem(imageType, "8-bit Color", "ij.plugin.Converter(\"8-bit Color\")"); - colorRGBItem = addCheckboxItem(imageType, "RGB Color", "ij.plugin.Converter(\"RGB Color\")"); - imageType.add(new MenuItem("-")); - RGBStackItem = addCheckboxItem(imageType, "RGB Stack", "ij.plugin.Converter(\"RGB Stack\")"); - HSBStackItem = addCheckboxItem(imageType, "HSB Stack", "ij.plugin.Converter(\"HSB Stack\")"); - HSB32Item = addCheckboxItem(imageType, "HSB (32-bit)", "ij.plugin.Converter(\"HSB (32-bit)\")"); - LabStackItem = addCheckboxItem(imageType, "Lab Stack", "ij.plugin.Converter(\"Lab Stack\")"); - image.add(imageType); - - image.addSeparator(); - getMenu("Image>Adjust", true); - addPlugInItem(image, "Show Info...", "ij.plugin.ImageInfo", KeyEvent.VK_I, false); - addPlugInItem(image, "Properties...", "ij.plugin.filter.ImageProperties", KeyEvent.VK_P, true); - getMenu("Image>Color", true); - getMenu("Image>Stacks", true); - getMenu("Image>Stacks>Animation_", true); - getMenu("Image>Stacks>Tools_", true); - Menu hyperstacksMenu = getMenu("Image>Hyperstacks", true); - image.addSeparator(); - addPlugInItem(image, "Crop", "ij.plugin.Resizer(\"crop\")", KeyEvent.VK_X, true); - addPlugInItem(image, "Duplicate...", "ij.plugin.Duplicator", KeyEvent.VK_D, true); - addPlugInItem(image, "Rename...", "ij.plugin.SimpleCommands(\"rename\")", 0, false); - addPlugInItem(image, "Scale...", "ij.plugin.Scaler", KeyEvent.VK_E, false); - getMenu("Image>Transform", true); - getMenu("Image>Zoom", true); - getMenu("Image>Overlay", true); - image.addSeparator(); - getMenu("Image>Lookup Tables", true); - - Menu process = getMenu("Process"); - addPlugInItem(process, "Smooth", "ij.plugin.filter.Filters(\"smooth\")", KeyEvent.VK_S, true); - addPlugInItem(process, "Sharpen", "ij.plugin.filter.Filters(\"sharpen\")", 0, false); - addPlugInItem(process, "Find Edges", "ij.plugin.filter.Filters(\"edge\")", 0, false); - addPlugInItem(process, "Find Maxima...", "ij.plugin.filter.MaximumFinder", 0, false); - addPlugInItem(process, "Enhance Contrast...", "ij.plugin.ContrastEnhancer", 0, false); - getMenu("Process>Noise", true); - getMenu("Process>Shadows", true); - getMenu("Process>Binary", true); - getMenu("Process>Math", true); - getMenu("Process>FFT", true); - Menu filtersMenu = getMenu("Process>Filters", true); - process.addSeparator(); - getMenu("Process>Batch", true); - addPlugInItem(process, "Image Calculator...", "ij.plugin.ImageCalculator", 0, false); - addPlugInItem(process, "Subtract Background...", "ij.plugin.filter.BackgroundSubtracter", 0, false); - addItem(process, "Repeat Command", KeyEvent.VK_R, false); - - Menu analyzeMenu = getMenu("Analyze"); - addPlugInItem(analyzeMenu, "Measure", "ij.plugin.filter.Analyzer", KeyEvent.VK_M, false); - addPlugInItem(analyzeMenu, "Analyze Particles...", "ij.plugin.filter.ParticleAnalyzer", 0, false); - addPlugInItem(analyzeMenu, "Summarize", "ij.plugin.filter.Analyzer(\"sum\")", 0, false); - addPlugInItem(analyzeMenu, "Distribution...", "ij.plugin.Distribution", 0, false); - addPlugInItem(analyzeMenu, "Label", "ij.plugin.filter.Filler(\"label\")", 0, false); - addPlugInItem(analyzeMenu, "Clear Results", "ij.plugin.filter.Analyzer(\"clear\")", 0, false); - addPlugInItem(analyzeMenu, "Set Measurements...", "ij.plugin.filter.Analyzer(\"set\")", 0, false); - analyzeMenu.addSeparator(); - addPlugInItem(analyzeMenu, "Set Scale...", "ij.plugin.filter.ScaleDialog", 0, false); - addPlugInItem(analyzeMenu, "Calibrate...", "ij.plugin.filter.Calibrator", 0, false); - if (IJ.isMacOSX()) { - addPlugInItem(analyzeMenu, "Histogram", "ij.plugin.Histogram", 0, false); - shortcuts.put(Integer.valueOf(KeyEvent.VK_H), "Histogram"); - } else - addPlugInItem(analyzeMenu, "Histogram", "ij.plugin.Histogram", KeyEvent.VK_H, false); - addPlugInItem(analyzeMenu, "Plot Profile", "ij.plugin.Profiler(\"plot\")", KeyEvent.VK_K, false); - addPlugInItem(analyzeMenu, "Surface Plot...", "ij.plugin.SurfacePlotter", 0, false); - getMenu("Analyze>Gels", true); - Menu toolsMenu = getMenu("Analyze>Tools", true); - - // the plugins will be added later, after a separator - addPluginsMenu(); - - Menu window = getMenu("Window"); - /*Changed for Bio7. We have a tabbed structure!*/ - addPlugInItem(window, "Show All", "ij.plugin.WindowOrganizer(\"show\")", KeyEvent.VK_CLOSE_BRACKET, false); - String key = IJ.isWindows() ? "enter" : "return"; - addPlugInItem(window, "Main Window [" + key + "]", "ij.plugin.WindowOrganizer(\"imagej\")", 0, false); - addPlugInItem(window, "Put Behind [tab]", "ij.plugin.Commands(\"tab\")", 0, false); - addPlugInItem(window, "Cascade", "ij.plugin.WindowOrganizer(\"cascade\")", 0, false); - addPlugInItem(window, "Tile", "ij.plugin.WindowOrganizer(\"tile\")", 0, false); - window.addSeparator(); - - Menu help = getMenu("Help"); - addPlugInItem(help, "ImageJ Website...", "ij.plugin.BrowserLauncher", 0, false); - help.addSeparator(); - addPlugInItem(help, "Dev. Resources...", "ij.plugin.BrowserLauncher(\"" + IJ.URL2 + "/developer/index.html\")", - 0, false); - addPlugInItem(help, "Macro Functions...", "ij.plugin.BrowserLauncher(\"https://wsr.imagej.net/developer/macro/functions.html\")", 0, false); - Menu examplesMenu = getExamplesMenu(ij); - addPlugInItem(examplesMenu, "Open as Panel", "ij.plugin.SimpleCommands(\"opencp\")", 0, false); - help.add(examplesMenu); - help.addSeparator(); - /* Changed for Bio7! Left out ImageJ update! */ - // addPlugInItem(help, "Update ImageJ...", "ij.plugin.ImageJ_Updater", - // 0, false); - addPlugInItem(help, "Release Notes...", "ij.plugin.BrowserLauncher(\"https://wsr.imagej.net/notes.html\")", 0, false); - addPlugInItem(help, "Refresh Menus", "ij.plugin.ImageJ_Updater(\"menus\")", 0, false); - help.addSeparator(); - Menu aboutMenu = getMenu("Help>About Plugins", true); - addPlugInItem(help, "About ImageJ...", "ij.plugin.AboutBox", 0, false); - - if (applet == null) { - menuSeparators = new Properties(); - installPlugins(); - } - - // make sure "Quit" is the last item in the File menu - file.addSeparator(); - addPlugInItem(file, "Quit", "ij.plugin.Commands(\"quit\")", 0, false); - - // System.out.println("MenuBar.setFont: "+fontSize+" "+scale+" "+getFont()); - if (fontSize != 0 || scale > 1.0) - mbar.setFont(getFont()); - if (ij != null) { - ij.setMenuBar(mbar); - Menus.setMenuBarCount++; - } - // Add deleted sample images to commands table - pluginsTable.put("Lena (68K)", "ij.plugin.URLOpener(\"lena-std.tif\")"); - pluginsTable.put("Bridge (174K)", "ij.plugin.URLOpener(\"bridge.gif\")"); - - if (pluginError != null) - error = error != null ? error += "\n" + pluginError : pluginError; - if (jarError != null) - error = error != null ? error += "\n" + jarError : jarError; - return error; - } - - public static Menu getExamplesMenu(ActionListener listener) { - Menu menu = new Menu("Examples"); - Menu submenu = new Menu("Plots"); - - addExample(submenu, "Example Plot", "Example_Plot_.ijm"); - addExample(submenu, "Semi-log Plot", "Semi-log_Plot_.ijm"); - addExample(submenu, "Arrow Plot", "Arrow_Plot_.ijm"); - addExample(submenu, "Damped Wave Plot", "Damped_Wave_Plot_.ijm"); - addExample(submenu, "Dynamic Plot", "Dynamic_Plot_.ijm"); - addExample(submenu, "Dynamic Plot 2D", "Dynamic_Plot_2D_.ijm"); - addExample(submenu, "Custom Plot Symbols", "Custom_Plot_Symbols_.ijm"); - addExample(submenu, "Histograms", "Histograms_.ijm"); - addExample(submenu, "Bar Charts", "Bar_Charts_.ijm"); - addExample(submenu, "Shapes", "Plot_Shapes_.ijm"); - addExample(submenu, "Plot Styles", "Plot_Styles_.ijm"); - addExample(submenu, "Random Data", "Random_Data_.ijm"); - addExample(submenu, "Plot Results", "Plot_Results_.ijm"); - addExample(submenu, "Plot With Spectrum", "Plot_With_Spectrum_.ijm"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Tools"); - addExample(submenu, "Annular Selection", "Annular_Selection_Tool.ijm"); - addExample(submenu, "Big Cursor", "Big_Cursor_Tool.ijm"); - addExample(submenu, "Circle Tool", "Circle_Tool.ijm"); - addExample(submenu, "Point Picker", "Point_Picker_Tool.ijm"); - addExample(submenu, "Star Tool", "Star_Tool.ijm"); - addExample(submenu, "Animated Icon Tool", "Animated_Icon_Tool.ijm"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Macro"); - addExample(submenu, "Sphere", "Sphere.ijm"); - addExample(submenu, "Dialog Box", "Dialog_Box.ijm"); - addExample(submenu, "Process Folder", "Batch_Process_Folder.ijm"); - addExample(submenu, "OpenDialog Demo", "OpenDialog_Demo.ijm"); - addExample(submenu, "Save All Images", "Save_All_Images.ijm"); - addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.ijm"); - addExample(submenu, "Non-numeric Table", "Non-numeric_Table.ijm"); - addExample(submenu, "Overlay", "Overlay.ijm"); - addExample(submenu, "Stack Overlay", "Stack_Overlay.ijm"); - addExample(submenu, "Array Functions", "Array_Functions.ijm"); - addExample(submenu, "Dual Progress Bars", "Dual_Progress_Bars.ijm"); - addExample(submenu, "Grab Viridis Colormap", "Grab_Viridis_Colormap.ijm"); - addExample(submenu, "Custom Measurement", "Custom_Measurement.ijm"); - addExample(submenu, "Synthetic Images", "Synthetic_Images.ijm"); - addExample(submenu, "Spiral Rotation", "Spiral_Rotation.ijm"); - addExample(submenu, "Curve Fitting", "Curve_Fitting.ijm"); - addExample(submenu, "Colors of 2021", "Colors_of_2021.ijm"); - addExample(submenu, "Turtle Graphics", "Turtle_Graphics.ijm"); - addExample(submenu, "Easter Eggs", "Easter_Eggs.ijm"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("JavaScript"); - addExample(submenu, "Sphere", "Sphere.js"); - addExample(submenu, "Plasma Cloud", "Plasma_Cloud.js"); - addExample(submenu, "Cloud Debugger", "Cloud_Debugger.js"); - addExample(submenu, "Synthetic Images", "Synthetic_Images.js"); - addExample(submenu, "Points", "Points.js"); - addExample(submenu, "Spiral Rotation", "Spiral_Rotation.js"); - addExample(submenu, "Example Plot", "Example_Plot.js"); - addExample(submenu, "Semi-log Plot", "Semi-log_Plot.js"); - addExample(submenu, "Arrow Plot", "Arrow_Plot.js"); - addExample(submenu, "Dynamic Plot", "Dynamic_Plot.js"); - addExample(submenu, "Plot Styles", "Plot_Styles.js"); - addExample(submenu, "Plot Random Data", "Plot_Random_Data.js"); - addExample(submenu, "Histogram Plots", "Histogram_Plots.js"); - addExample(submenu, "JPEG Quality Plot", "JPEG_Quality_Plot.js"); - addExample(submenu, "Process Folder", "Batch_Process_Folder.js"); - addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.js"); - addExample(submenu, "Non-numeric Table", "Non-numeric_Table.js"); - addExample(submenu, "Overlay", "Overlay.js"); - addExample(submenu, "Stack Overlay", "Stack_Overlay.js"); - addExample(submenu, "Dual Progress Bars", "Dual_Progress_Bars.js"); - addExample(submenu, "Gamma Adjuster", "Gamma_Adjuster.js"); - addExample(submenu, "Custom Measurement", "Custom_Measurement.js"); - addExample(submenu, "Terabyte VirtualStack", "Terabyte_VirtualStack.js"); - addExample(submenu, "Event Listener", "Event_Listener.js"); - addExample(submenu, "FFT Filter", "FFT_Filter.js"); - addExample(submenu, "Curve Fitting", "Curve_Fitting.js"); - addExample(submenu, "Overlay Text", "Overlay_Text.js"); - addExample(submenu, "Crop Multiple Rois", "Crop_Multiple_Rois.js"); - addExample(submenu, "Show all LUTs", "Show_all_LUTs.js"); - addExample(submenu, "Dialog Demo", "Dialog_Demo.js"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("BeanShell"); - addExample(submenu, "Sphere", "Sphere.bsh"); - addExample(submenu, "Example Plot", "Example_Plot.bsh"); - addExample(submenu, "Semi-log Plot", "Semi-log_Plot.bsh"); - addExample(submenu, "Arrow Plot", "Arrow_Plot.bsh"); - addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.bsh"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Python"); - addExample(submenu, "Sphere", "Sphere.py"); - addExample(submenu, "Animated Gaussian Blur", "Animated_Gaussian_Blur.py"); - addExample(submenu, "Spiral Rotation", "Spiral_Rotation.py"); - addExample(submenu, "Overlay", "Overlay.py"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Java"); - addExample(submenu, "Sphere", "Sphere_.java"); - addExample(submenu, "Plasma Cloud", "Plasma_Cloud.java"); - addExample(submenu, "Gamma Adjuster", "Gamma_Adjuster.java"); - addExample(submenu, "Plugin", "My_Plugin.java"); - addExample(submenu, "Plugin Filter", "Filter_Plugin.java"); - addExample(submenu, "Plugin Frame", "Plugin_Frame.java"); - addExample(submenu, "Plugin Tool", "Prototype_Tool.java"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Games"); - addExample(submenu, "2048", "2048.ijm"); - addExample(submenu, "Asteroids", "Asteroids.js"); - addExample(submenu, "Breakout", "Breakout.ijm"); - addExample(submenu, "Life", "GameOfLife.js"); - addExample(submenu, "Pong", "Pong.ijm"); - addExample(submenu, "Snake", "Snake.ijm"); - addExample(submenu, "Tetris", "Tetris.js"); - submenu.addActionListener(listener); - menu.add(submenu); - menu.addSeparator(); - CheckboxMenuItem item = new CheckboxMenuItem("Autorun Examples"); - menu.add(item); - item.addItemListener(ij); - item.setState(Prefs.autoRunExamples); - return menu; - } - - private static void addExample(Menu menu, String label, String command) { - MenuItem item = new MenuItem(label); - menu.add(item); - item.setActionCommand(command); - } - - void addOpenRecentSubMenu(Menu menu) { - openRecentMenu = getMenu("File>Open Recent"); - for (int i = 0; i < MAX_OPEN_RECENT_ITEMS; i++) { - String path = Prefs.getString("recent" + (i / 10) % 10 + i % 10); - if (path == null) - break; - MenuItem item = new MenuItem(path); - openRecentMenu.add(item); - item.addActionListener(ij); - } - menu.add(openRecentMenu); - } - - static void addItem(Menu menu, String label, int shortcut, boolean shift) { - if (menu == null) - return; - MenuItem item; - if (shortcut == 0) - item = new MenuItem(label); - else { - if (shift) { - item = new MenuItem(label, new MenuShortcut(shortcut, true)); - shortcuts.put(Integer.valueOf(shortcut + 200), label); - } else { - item = new MenuItem(label, new MenuShortcut(shortcut)); - shortcuts.put(Integer.valueOf(shortcut), label); - } - } - if (addSorted) { - if (menu == pluginsMenu) - addItemSorted(menu, item, userPluginsIndex); - else - addOrdered(menu, item); - } else - menu.add(item); - item.addActionListener(ij); - } - - void addPlugInItem(Menu menu, String label, String className, int shortcut, boolean shift) { - pluginsTable.put(label, className); - nPlugins++; - addItem(menu, label, shortcut, shift); - } - - CheckboxMenuItem addCheckboxItem(Menu menu, String label, String className) { - pluginsTable.put(label, className); - nPlugins++; - CheckboxMenuItem item = new CheckboxMenuItem(label); - menu.add(item); - item.addItemListener(ij); - item.setState(false); - return item; - } - - static Menu addSubMenu(Menu menu, String name) { - String value; - String key = name.toLowerCase(Locale.US); - int index; - Menu submenu = new Menu(name.replace('_', ' ')); - index = key.indexOf(' '); - if (index > 0) - key = key.substring(0, index); - for (int count = 1; count < 100; count++) { - value = Prefs.getString(key + (count / 10) % 10 + count % 10); - if (value == null) - break; - if (count == 1) - menu.add(submenu); - if (value.equals("-")) - submenu.addSeparator(); - else - addPluginItem(submenu, value); - } - if (name.equals("Lookup Tables") && applet == null) - addLuts(submenu); - return submenu; - } - - static void addLuts(Menu submenu) { - String path = IJ.getDirectory("luts"); - if (path == null) - return; - File f = new File(path); - String[] list = null; - if (applet == null && f.exists() && f.isDirectory()) - list = f.list(); - if (list == null) - return; - if (IJ.isLinux() || IJ.isMacOSX()) - Arrays.sort(list); - submenu.addSeparator(); - for (int i = 0; i < list.length; i++) { - String name = list[i]; - if (name.endsWith(".lut")) { - name = name.substring(0, name.length() - 4); - if (name.contains("_") && !name.contains(" ")) - name = name.replace("_", " "); - MenuItem item = new MenuItem(name); - submenu.add(item); - item.addActionListener(ij); - nPlugins++; - } - } - } - - static void addPluginItem(Menu submenu, String s) { - if (s.startsWith("\"-\"")) { - // add menu separator if command="-" - addSeparator(submenu); - return; - } - int lastComma = s.lastIndexOf(','); - if (lastComma <= 0) - return; - String command = s.substring(1, lastComma - 1); - int keyCode = 0; - boolean shift = false; - if (command.endsWith("]")) { - int openBracket = command.lastIndexOf('['); - if (openBracket > 0) { - String shortcut = command.substring(openBracket + 1, command.length() - 1); - keyCode = convertShortcutToCode(shortcut); - boolean functionKey = keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12; - if (keyCode > 0 && !functionKey) - command = command.substring(0, openBracket); - } - } - if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12) { - shortcuts.put(Integer.valueOf(keyCode), command); - keyCode = 0; - } else if (keyCode >= 265 && keyCode <= 290) { - keyCode -= 200; - shift = true; - } - addItem(submenu, command, keyCode, shift); - while (s.charAt(lastComma + 1) == ' ' && lastComma + 2 < s.length()) - lastComma++; // remove leading spaces - String className = s.substring(lastComma + 1, s.length()); - // IJ.log(command+" "+className); - if (installingJars) - duplicateCommand = pluginsTable.get(command) != null; - pluginsTable.put(command, className); - nPlugins++; - } - - void checkForDuplicate(String command) { - if (pluginsTable.get(command) != null) { - } - } - - void addPluginsMenu() { - String value, label, className; - int index; - // pluginsMenu = new Menu("Plugins"); - pluginsMenu = getMenu("Plugins"); - for (int count = 1; count < 100; count++) { - value = Prefs.getString("plug-in" + (count / 10) % 10 + count % 10); - if (value == null) - break; - char firstChar = value.charAt(0); - if (firstChar == '-') - pluginsMenu.addSeparator(); - else if (firstChar == '>') { - String submenu = value.substring(2, value.length() - 1); - // Menu menu = getMenu("Plugins>" + submenu, true); - Menu menu = addSubMenu(pluginsMenu, submenu); - if (submenu.equals("Shortcuts")) - shortcutsMenu = menu; - else if (submenu.equals("Utilities")) - utilitiesMenu = menu; - else if (submenu.equals("Macros")) - macrosMenu = menu; - } else - addPluginItem(pluginsMenu, value); - } - userPluginsIndex = pluginsMenu.getItemCount(); - if (userPluginsIndex < 0) - userPluginsIndex = 0; - } - - /** - * Install plugins using "pluginxx=" keys in IJ_Prefs.txt. Plugins not listed in - * IJ_Prefs are added to the end of the Plugins menu. - */ - void installPlugins() { - int nPlugins0 = nPlugins; - String value, className; - char menuCode; - Menu menu; - String[] pluginList = getPlugins(); - String[] pluginsList2 = null; - Hashtable skipList = new Hashtable(); - for (int index = 0; index < 100; index++) { - value = Prefs.getString("plugin" + (index / 10) % 10 + index % 10); - if (value == null) - break; - menuCode = value.charAt(0); - switch (menuCode) { - case PLUGINS_MENU: - default: - menu = pluginsMenu; - break; - case IMPORT_MENU: - menu = getMenu("File>Import"); - break; - case SAVE_AS_MENU: - menu = getMenu("File>Save As"); - break; - case SHORTCUTS_MENU: - menu = shortcutsMenu; - break; - case ABOUT_MENU: - menu = getMenu("Help>About Plugins"); - break; - case FILTERS_MENU: - menu = getMenu("Process>Filters"); - break; - case TOOLS_MENU: - menu = getMenu("Analyze>Tools"); - break; - case UTILITIES_MENU: - menu = utilitiesMenu; - break; - } - String prefsValue = value; - value = value.substring(2, value.length()); // remove menu code and - // coma - className = value.substring(value.lastIndexOf(',') + 1, value.length()); - boolean found = className.startsWith("ij."); - if (!found && pluginList != null) { // does this plugin exist? - if (pluginsList2 == null) - pluginsList2 = getStrippedPlugins(pluginList); - for (int i = 0; i < pluginsList2.length; i++) { - if (className.startsWith(pluginsList2[i])) { - found = true; - break; - } - } - } - if (found && menu != pluginsMenu) { - addPluginItem(menu, value); - pluginsPrefs.addElement(prefsValue); - if (className.endsWith("\")")) { // remove any argument - int argStart = className.lastIndexOf("(\""); - if (argStart > 0) - className = className.substring(0, argStart); - } - skipList.put(className, ""); - } - } - if (pluginList != null) { - for (int i = 0; i < pluginList.length; i++) { - if (!skipList.containsKey(pluginList[i])) - installUserPlugin(pluginList[i]); - } - } - if ((nPlugins - nPlugins0) <= 1 && IJ.getDir("imagej") != null && IJ.getDir("imagej").startsWith("/private")) { - pluginsMenu.addSeparator(); - addPlugInItem(pluginsMenu, "Why are Plugins Missing?", "ij.plugin.SimpleCommands(\"missing\")", 0, false); - } - installJarPlugins(); - installMacros(); - } - - /** Installs macros and scripts located in the plugins folder. */ - void installMacros() { - if (macroFiles == null) - return; - for (int i = 0; i < macroFiles.size(); i++) { - String name = (String) macroFiles.elementAt(i); - installMacro(name); - } - } - - /** - * Installs a macro or script in the Plugins menu, or submenu, with with - * underscores in the file name replaced by spaces. - */ - void installMacro(String name) { - Menu menu = pluginsMenu; - String dir = null; - int slashIndex = name.indexOf('/'); - if (slashIndex > 0) { - dir = name.substring(0, slashIndex); - name = name.substring(slashIndex + 1, name.length()); - menu = getPluginsSubmenu(dir); - slashIndex = name.indexOf('/'); - if (slashIndex > 0) { - String dir2 = name.substring(0, slashIndex); - name = name.substring(slashIndex + 1, name.length()); - String menuName = "Plugins>" + dir + ">" + dir2; - menu = getMenu(menuName); - dir += File.separator + dir2; - } - } - String command = name.replace('_', ' '); - if (command.endsWith(".js") || command.endsWith(".py")) - command = command.substring(0, command.length() - 3); // remove - // ".js" or - // ".py" - else - command = command.substring(0, command.length() - 4); // remove - // ".txt", - // ".ijm" or - // ".bsh" - command = command.trim(); - if (pluginsTable.get(command) != null) // duplicate command? - command = command + " Macro"; - MenuItem item = new MenuItem(command); - addOrdered(menu, item); - item.addActionListener(ij); - String path = (dir != null ? dir + File.separator : "") + name; - pluginsTable.put(command, "ij.plugin.Macro_Runner(\"" + path + "\")"); - nMacros++; - } - - static int addPluginSeparatorIfNeeded(Menu menu) { - if (menuSeparators == null) - return 0; - Integer i = (Integer) menuSeparators.get(menu); - if (i == null) { - if (menu.getItemCount() > 0) - addSeparator(menu); - i = Integer.valueOf(menu.getItemCount()); - menuSeparators.put(menu, i); - } - return i.intValue(); - } - - /** Inserts 'item' into 'menu' in alphanumeric order. */ - static void addOrdered(Menu menu, MenuItem item) { - String label = item.getLabel(); - int start = addPluginSeparatorIfNeeded(menu); - for (int i = start; i < menu.getItemCount(); i++) { - if (label.compareTo(menu.getItem(i).getLabel()) < 0) { - menu.insert(item, i); - return; - } - } - menu.add(item); - } - - public static String getJarFileForMenuEntry(String menuEntry) { - if (instance == null) - return null; - return (String) instance.menuEntry2jarFile.get(menuEntry); - } - - /** Install plugins located in JAR files. */ - void installJarPlugins() { - if (jarFiles == null) - return; - installingJars = true; - for (int i = 0; i < jarFiles.size(); i++) { - isJarErrorHeading = false; - String jar = (String) jarFiles.elementAt(i); - InputStream is = getConfigurationFile(jar); - if (is == null) - continue; - ArrayList entries = new ArrayList(20); - LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is)); - try { - while (true) { - String s = lnr.readLine(); - if (s == null) - break; - - if (s.length() >= 3 && !s.startsWith("#")) - entries.add(s); - } - } catch (IOException e) { - } finally { - try { - if (lnr != null) - lnr.close(); - } catch (IOException e) { - } - } - - for (int j = 0; j < entries.size(); j++) { - installJarPlugin(jar, (String) entries.get(j)); - /* Changed for Bio7! */ - bio7JarAllCommand.add((String) entries.get(j)); - - } - } - } - - /** Install a plugin located in a JAR file. */ - void installJarPlugin(String jar, String s) { - addSorted = false; - Menu menu; - s = s.trim(); - // System.out.println(s); - if (s.startsWith("Plugins>")) { - // extract name after Plugins> - int firstComma = s.indexOf(','); - // no comma or smaller than word plugins - if (firstComma == -1 || firstComma <= 8) - menu = null; - else { - // Extract name to first comma (before name of plugin) - String name = s.substring(8, firstComma); - menu = getPluginsSubmenu(name); - } - // Plugins>FeatureJ, "FeatureJ Derivatives", featurej.FJ_Derivatives - // give the name of the jar is description is empty or is 'plugins' - } else if (s.startsWith("\"") || s.startsWith("Plugins")) { - String name = getSubmenuName(jar); - if (name != null) - menu = getPluginsSubmenu(name); - else - menu = pluginsMenu; - addSorted = true; - } else { - // Creates a menu from the text! - int firstQuote = s.indexOf('"'); - String name = firstQuote < 0 ? s : s.substring(0, firstQuote).trim(); - int comma = name.indexOf(','); - if (comma >= 0) - name = name.substring(0, comma); - if (name.startsWith("Help>About")) // for backward compatibility - name = "Help>About Plugins"; - menu = getMenu(name); - } - int firstQuote = s.indexOf('"'); - if (firstQuote == -1) - return; - s = s.substring(firstQuote, s.length()); // remove menu - if (menu != null) { - addPluginSeparatorIfNeeded(menu); - // Adds the command to the hashtable and create a menuItem! - addPluginItem(menu, s); - addSorted = false; - } - String menuEntry = s; - if (s.startsWith("\"")) { - int quote = s.indexOf('"', 1); - menuEntry = quote < 0 ? s.substring(1) : s.substring(1, quote); - } else { - int comma = s.indexOf(','); - if (comma > 0) - menuEntry = s.substring(0, comma); - } - if (duplicateCommand) { - if (jarError == null) - jarError = ""; - addJarErrorHeading(jar); - String jar2 = (String) menuEntry2jarFile.get(menuEntry); - if (jar2 != null && jar2.startsWith(pluginsPath)) - jar2 = jar2.substring(pluginsPath.length()); - jarError += " Duplicate command: " + s + (jar2 != null ? " (already in " + jar2 + ")" : "") + "\n"; - } else - menuEntry2jarFile.put(menuEntry, jar); - duplicateCommand = false; - } - - void addJarErrorHeading(String jar) { - if (!isJarErrorHeading) { - if (!jarError.equals("")) - jarError += " \n"; - jarError += "Plugin configuration error: " + jar + "\n"; - isJarErrorHeading = true; - } - } - - /** - * Returns the specified ImageJ menu (e.g., "File>New") or null if it is not - * found. - */ - public static Menu getImageJMenu(String menuPath) { - if (menus==null && !GraphicsEnvironment.isHeadless()) - IJ.init(); - if (menus == null) - return null; - if (menus.get(menuPath) != null) - return getMenu(menuPath, false); - else - return null; - } - - private static Menu getMenu(String menuPath) { - if (GraphicsEnvironment.isHeadless()) - return null; - else - return getMenu(menuPath, false); - } - - /* Creates the menu and adds menus for the jar plugins! */ - private static Menu getMenu(String menuName, boolean readFromProps) { - if (menuName.endsWith(">")) - menuName = menuName.substring(0, menuName.length() - 1); - - Menu result = (Menu) menus.get(menuName); - if (result == null) { - int offset = menuName.lastIndexOf('>'); - if (offset < 0) { - result = new Menu(menuName); - if (mbar == null) - mbar = new MenuBar(); - if (menuName.equals("Help")) - mbar.setHelpMenu(result); - else - mbar.add(result); - if (menuName.equals("Window")) - window = result; - else if (menuName.equals("Plugins")) - pluginsMenu = result; - } else { - // B identifying the last index of > we can get the parent menu. - // Names are store as e.g. 'plugins>submenu' - String parentName = menuName.substring(0, offset); - String menuItemName = menuName.substring(offset + 1); - // Recursive call to get all parent menus! - Menu parentMenu = getMenu(parentName); - - result = new Menu(menuItemName); - addPluginSeparatorIfNeeded(parentMenu); - if (readFromProps) - result = addSubMenu(parentMenu, menuItemName); - else if (parentName.startsWith("Plugins") && menuSeparators != null) - addItemSorted(parentMenu, result, parentName.equals("Plugins") ? userPluginsIndex : 0); - else - parentMenu.add(result); - if (menuName.equals("File>Open Recent")) - openRecentMenu = result; - } - menus.put(menuName, result); - } - return result; - } - - Menu getPluginsSubmenu(String submenuName) { - return getMenu("Plugins>" + submenuName); - } - - String getSubmenuName(String jarPath) { - // IJ.log("getSubmenuName: \n"+jarPath+"\n"+pluginsPath); - if (pluginsPath == null) - return null; - if (jarPath.startsWith(pluginsPath)) - jarPath = jarPath.substring(pluginsPath.length() - 1); - int index = jarPath.lastIndexOf(File.separatorChar); - if (index < 0) - return null; - String name = jarPath.substring(0, index); - index = name.lastIndexOf(File.separatorChar); - if (index < 0) - return null; - name = name.substring(index + 1); - if (name.equals("plugins")) - return null; - return name; - } - - static void addItemSorted(Menu menu, MenuItem item, int startingIndex) { - String itemLabel = item.getLabel(); - int count = menu.getItemCount(); - boolean inserted = false; - for (int i = startingIndex; i < count; i++) { - MenuItem mi = menu.getItem(i); - String label = mi.getLabel(); - // IJ.log(i+ " "+itemLabel+" "+label + - // " "+(itemLabel.compareTo(label))); - if (itemLabel.compareTo(label) < 0) { - menu.insert(item, i); - inserted = true; - break; - } - } - if (!inserted) - menu.add(item); - } - - static void addSeparator(Menu menu) { - menu.addSeparator(); - } - - /** - * Opens the configuration file ("plugins.config") from a JAR file and returns - * it as an InputStream. - */ - InputStream getConfigurationFile(String jar) { - try { - ZipFile jarFile = new ZipFile(jar); - Enumeration entries = jarFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - if (entry.getName().endsWith("plugins.config")) - return jarFile.getInputStream(entry); - } - jarFile.close(); - } catch (Throwable e) { - IJ.log(jar + ": " + e); - } - return autoGenerateConfigFile(jar); - } - - /** Creates a configuration file for JAR/ZIP files that do not have one. */ - InputStream autoGenerateConfigFile(String jar) { - StringBuffer sb = null; - try { - ZipFile jarFile = new ZipFile(jar); - Enumeration entries = jarFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - String name = entry.getName(); - if (name.endsWith(".class") && name.indexOf("_") > 0 && name.indexOf("$") == -1 - && name.indexOf("/_") == -1 && !name.startsWith("_")) { - if (Character.isLowerCase(name.charAt(0)) && name.indexOf("/") != -1) - continue; - if (sb == null) - sb = new StringBuffer(); - String className = name.substring(0, name.length() - 6); - int slashIndex = className.lastIndexOf('/'); - String plugins = "Plugins"; - if (slashIndex >= 0) { - plugins += ">" + className.substring(0, slashIndex).replace('/', '>').replace('_', ' '); - name = className.substring(slashIndex + 1); - } else - name = className; - name = name.replace('_', ' '); - className = className.replace('/', '.'); - sb.append(plugins + ", \"" + name + "\", " + className + "\n"); - } - } - jarFile.close(); - } catch (Throwable e) { - IJ.log(jar + ": " + e); - } - if (sb == null) - return null; - else - return new ByteArrayInputStream(sb.toString().getBytes()); - } - - /** Returns a list of the plugins with directory names removed. */ - String[] getStrippedPlugins(String[] plugins) { - String[] plugins2 = new String[plugins.length]; - int slashPos; - for (int i = 0; i < plugins2.length; i++) { - plugins2[i] = plugins[i]; - slashPos = plugins2[i].lastIndexOf('/'); - if (slashPos >= 0) - plugins2[i] = plugins[i].substring(slashPos + 1, plugins2[i].length()); - } - return plugins2; - } - - void setupPluginsAndMacrosPaths() { - /* - * ImageJPath = pluginsPath = macrosPath = null; String currentDir = - * Prefs.getHomeDir(); // "user.dir" if (currentDir==null) return; if - * (currentDir.endsWith("plugins")) ImageJPath = pluginsPath = - * currentDir+File.separator; else { String pluginsDir = - * System.getProperty("plugins.dir"); if (pluginsDir!=null) { if - * (pluginsDir.endsWith("/")||pluginsDir.endsWith("\\")) pluginsDir = - * pluginsDir.substring(0, pluginsDir.length()-1); if - * (pluginsDir.endsWith("/plugins")||pluginsDir.endsWith("\\plugins")) - * pluginsDir = pluginsDir.substring(0, pluginsDir.length()-8); } if - * (pluginsDir==null) pluginsDir = currentDir; else if - * (pluginsDir.equals("user.home")) { pluginsDir = - * System.getProperty("user.home"); if (!(new - * File(pluginsDir+File.separator+"plugins")).isDirectory()) pluginsDir = - * pluginsDir + File.separator + "ImageJ"; // needed to run plugins when ImageJ - * launched using Java WebStart if (applet==null) - * System.setSecurityManager(null); jnlp = true; } pluginsPath = - * pluginsDir+File.separator+"plugins"+File.separator; macrosPath = - * pluginsDir+File.separator+"macros"+File.separator; ImageJPath = - * pluginsDir+File.separator; } - */ - - /* Changed for Bio7! */ - - pluginsPath = macrosPath = null; - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - /* We need an extra seperator here else the plugins are not found! */ - pluginsPath = store.getString("PLUGINS_PATH") + File.separator; - macrosPath = store.getString("MACROS_PATH") + File.separator; - /* Get the installation directory of the ImageJ plugin! */ - String currentDir = Util.getImageJPath(); - ImageJPath = Util.getImageJPath() + File.separator; - - File f = pluginsPath != null ? new File(pluginsPath) : null; - if (f == null || !f.isDirectory()) { - ImageJPath = currentDir + File.separator; - pluginsPath = ImageJPath + "plugins" + File.separator; - f = new File(pluginsPath); - if (!f.isDirectory()) { - String altPluginsPath = System.getProperty("plugins.dir"); - if (altPluginsPath != null) { - f = new File(altPluginsPath); - if (!f.isDirectory()) - altPluginsPath = null; - else { - ImageJPath = f.getParent() + File.separator; - pluginsPath = ImageJPath + f.getName() + File.separator; - macrosPath = ImageJPath + "macros" + File.separator; - } - } - if (altPluginsPath == null) - ImageJPath = pluginsPath = null; - } - } - f = macrosPath != null ? new File(macrosPath) : null; - if (f != null && !f.isDirectory()) { - macrosPath = currentDir + File.separator + "macros" + File.separator; - f = new File(macrosPath); - if (!f.isDirectory()) - macrosPath = null; - } - if (IJ.debugMode) { - IJ.log("Menus.setupPluginsAndMacrosPaths"); - IJ.log(" user.dir: " + currentDir); - IJ.log(" plugins.dir: " + System.getProperty("plugins.dir")); - IJ.log(" ImageJPath: " + ImageJPath); - IJ.log(" pluginsPath: " + pluginsPath); - } - } - - /** Returns a list of the plugins in the plugins menu. */ - public static synchronized String[] getPlugins() { - File f = pluginsPath != null ? new File(pluginsPath) : null; - if (f == null || (f != null && !f.isDirectory())) - return null; - String[] list = f.list(); - if (list == null) - return null; - Vector v = new Vector(); - jarFiles = null; - macroFiles = null; - for (int i = 0; i < list.length; i++) { - String name = list[i]; - boolean isClassFile = name.endsWith(".class"); - boolean hasUnderscore = name.indexOf('_') >= 0; - if (hasUnderscore && isClassFile && name.indexOf('$') < 0) { - name = name.substring(0, name.length() - 6); // remove ".class" - v.addElement(name); - } else if (hasUnderscore && (name.endsWith(".jar") || name.endsWith(".zip"))) { - if (jarFiles == null) - jarFiles = new Vector(); - jarFiles.addElement(pluginsPath + name); - } else if (validMacroName(name, hasUnderscore)) { - if (macroFiles == null) - macroFiles = new Vector(); - macroFiles.addElement(name); - } else { - if (!isClassFile) - checkSubdirectory(pluginsPath, name, v); - } - } - list = new String[v.size()]; - v.copyInto((String[]) list); - StringSorter.sort(list); - return list; - } - - /** - * Looks for plugins and jar files in a subdirectory of the plugins directory. - */ - private static void checkSubdirectory(String path, String dir, Vector v) { - if (dir.endsWith(".java")) - return; - File f = new File(path, dir); - if (!f.isDirectory()) - return; - String[] list = f.list(); - if (list == null) - return; - dir += "/"; - int classCount = 0, otherCount = 0; - String className = null; - for (int i = 0; i < list.length; i++) { - String name = list[i]; - boolean hasUnderscore = name.indexOf('_') >= 0; - if (hasUnderscore && name.endsWith(".class") && name.indexOf('$') < 0) { - name = name.substring(0, name.length() - 6); // remove ".class" - v.addElement(dir + name); - classCount++; - className = name; - } else if (hasUnderscore && (name.endsWith(".jar") || name.endsWith(".zip"))) { - if (jarFiles == null) - jarFiles = new Vector(); - jarFiles.addElement(f.getPath() + File.separator + name); - otherCount++; - } else if (validMacroName(name, hasUnderscore)) { - if (macroFiles == null) - macroFiles = new Vector(); - macroFiles.addElement(dir + name); - otherCount++; - } else { - File f2 = new File(f, name); - if (f2.isDirectory()) - installSubdirectorMacros(f2, dir + name); - } - } - if (Prefs.moveToMisc && classCount == 1 && otherCount == 0 && dir.indexOf("_") == -1) - v.setElementAt("Miscellaneous/" + className, v.size() - 1); - } - - /** Installs macros and scripts located in subdirectories. */ - private static void installSubdirectorMacros(File f2, String dir) { - if (dir.endsWith("Launchers")) - return; - String[] list = f2.list(); - if (list == null) - return; - for (int i = 0; i < list.length; i++) { - String name = list[i]; - boolean hasUnderscore = name.indexOf('_') >= 0; - if (validMacroName(name, hasUnderscore)) { - if (macroFiles == null) - macroFiles = new Vector(); - macroFiles.addElement(dir + "/" + name); - } - } - } - - private static boolean validMacroName(String name, boolean hasUnderscore) { - return (hasUnderscore && name.endsWith(".txt")) || name.endsWith(".ijm") || name.endsWith(".js") - || name.endsWith(".bsh") || name.endsWith(".py"); - } - - /** - * Installs a plugin in the Plugins menu using the class name, with underscores - * replaced by spaces, as the command. - */ - void installUserPlugin(String className) { - installUserPlugin(className, false); - } - - public void installUserPlugin(String className, boolean force) { - int slashIndex = className.indexOf('/'); - String menuName = slashIndex < 0 ? "Plugins" - : "Plugins>" + className.substring(0, slashIndex).replace('/', '>'); - Menu menu = getMenu(menuName); - String command = className; - if (slashIndex > 0) { - command = className.substring(slashIndex + 1); - } - command = command.replace('_', ' '); - //command = command.trim(); - boolean itemExists = (pluginsTable.get(command) != null); - if (force && itemExists) - return; - - if (!force && itemExists) // duplicate command? - command = command + " Plugin"; - MenuItem item = new MenuItem(command); - if (force) - addItemSorted(menu, item, 0); - else - addOrdered(menu, item); - item.addActionListener(ij); - pluginsTable.put(command, className.replace('/', '.')); - nPlugins++; - } - - void installPopupMenu(ImageJ ij) { - String s; - int count = 0; - MenuItem mi; - popup = new PopupMenu(""); - if (fontSize != 0 || scale > 1.0) - popup.setFont(getFont()); - - while (true) { - count++; - s = Prefs.getString("popup" + (count / 10) % 10 + count % 10); - if (s == null) - break; - if (s.equals("-")) - popup.addSeparator(); - else if (!s.equals("")) { - mi = new MenuItem(s); - mi.addActionListener(ij); - popup.add(mi); - } - } - } - - public static MenuBar getMenuBar() { - return mbar; - } - - public static Menu getMacrosMenu() { - return macrosMenu; - } - - public static Menu getOpenRecentMenu() { - return openRecentMenu; - } - - public int getMacroCount() { - return nMacros; - } - - public int getPluginCount() { - return nPlugins; - } - - static final int RGB_STACK = 10, HSB_STACK = 11, LAB_STACK = 12, HSB32_STACK = 13; - - /** Updates the Image/Type and Window menus. */ - public static void updateMenus() { - if (ij == null) - return; - gray8Item.setState(false); - gray16Item.setState(false); - gray32Item.setState(false); - color256Item.setState(false); - colorRGBItem.setState(false); - RGBStackItem.setState(false); - HSBStackItem.setState(false); - LabStackItem.setState(false); - HSB32Item.setState(false); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp == null) - return; - int type = imp.getType(); - if (imp.getStackSize() > 1) { - ImageStack stack = imp.getStack(); - if (stack.isRGB()) - type = RGB_STACK; - else if (stack.isHSB()) - type = HSB_STACK; - else if (stack.isLab()) - type = LAB_STACK; - else if (stack.isHSB32()) - type = HSB32_STACK; - } - - switch (type) { - case ImagePlus.GRAY8: - gray8Item.setState(true); - break; - case ImagePlus.GRAY16: - gray16Item.setState(true); - break; - case ImagePlus.GRAY32: - gray32Item.setState(true); - break; - case ImagePlus.COLOR_256: - color256Item.setState(true); - break; - case ImagePlus.COLOR_RGB: - colorRGBItem.setState(true); - break; - case RGB_STACK: - RGBStackItem.setState(true); - break; - case HSB_STACK: - HSBStackItem.setState(true); - break; - case LAB_STACK: - LabStackItem.setState(true); - break; - case HSB32_STACK: - HSB32Item.setState(true); - break; - - } - - // update Window menu - int nItems = window.getItemCount(); - int start = WINDOW_MENU_ITEMS + windowMenuItems2; - int index = start + WindowManager.getCurrentIndex(); - try { // workaround for Linux/Java 5.0/bug - for (int i = start; i < nItems; i++) { - CheckboxMenuItem item = (CheckboxMenuItem) window.getItem(i); - item.setState(i == index); - } - } catch (Exception e) { - } - } - - static boolean isColorLut(ImagePlus imp) { - ImageProcessor ip = imp.getProcessor(); - IndexColorModel cm = (IndexColorModel) ip.getColorModel(); - if (cm == null) - return false; - int mapSize = cm.getMapSize(); - byte[] reds = new byte[mapSize]; - byte[] greens = new byte[mapSize]; - byte[] blues = new byte[mapSize]; - cm.getReds(reds); - cm.getGreens(greens); - cm.getBlues(blues); - boolean isColor = false; - for (int i = 0; i < mapSize; i++) { - if ((reds[i] != greens[i]) || (greens[i] != blues[i])) { - isColor = true; - break; - } - } - return isColor; - } - - /** Use Prefs.getImageJDir() to get the path to the ImageJ directory. */ - static String getImageJPath() { - return ImageJPath; - } - - /** - * Returns the path to the user plugins directory or null if the plugins - * directory was not found. - */ - public static String getPlugInsPath() { - return pluginsPath; - } - - /** - * Returns the path to the macros directory or null if the macros directory was - * not found. - */ - public static String getMacrosPath() { - return macrosPath; - } - - /** Returns the hashtable that associates commands with plugins. */ - public static Hashtable getCommands() { - if (pluginsTable==null && !GraphicsEnvironment.isHeadless()) - IJ.init(); - return pluginsTable; - } - - /** - * Returns the hashtable that associates shortcuts with commands. The keys in - * the hashtable are Integer keycodes, or keycode+200 for uppercase. - */ - public static Hashtable getShortcuts() { - return shortcuts; - } - - /** - * Returns the hashtable that associates keyboard shortcuts with macros. The - * keys in the hashtable are Integer keycodes, or keycode+200 for uppercase. - */ - public static Hashtable getMacroShortcuts() { - if (macroShortcuts == null) - macroShortcuts = new Hashtable(); - return macroShortcuts; - } - - /** Inserts one item (a non-image window) into the Window menu. */ - static synchronized void insertWindowMenuItem(Window win) { - if (ij == null || win == null) - return; - String title = win instanceof Frame ? ((Frame) win).getTitle() : ((Dialog) win).getTitle(); - CheckboxMenuItem item = new CheckboxMenuItem(title); - item.addItemListener(ij); - int index = WINDOW_MENU_ITEMS + windowMenuItems2; - if (windowMenuItems2 >= 2) - index--; - window.insert(item, index); - windowMenuItems2++; - if (windowMenuItems2 == 1) { - window.insertSeparator(WINDOW_MENU_ITEMS + windowMenuItems2); - windowMenuItems2++; - } - } - - /** Adds one image to the end of the Window menu. */ - static synchronized void addWindowMenuItem(ImagePlus imp) { - if (ij==null) - return; - String name = imp.getTitle(); - String size = ImageWindow.getImageSize(imp); - CheckboxMenuItem item = new CheckboxMenuItem(name + " " + size); - item.setActionCommand("" + imp.getID()); - window.add(item); - item.addItemListener(ij); - } - - /** Removes the specified item from the Window menu. */ - static synchronized void removeWindowMenuItem(int index) { - // IJ.log("removeWindowMenuItem: "+index+" "+windowMenuItems2+" - // "+window.getItemCount()); - if (ij == null) - return; - try { - if (index >= 0 && index < window.getItemCount()) { - window.remove(WINDOW_MENU_ITEMS + index); - if (index < windowMenuItems2) { - windowMenuItems2--; - if (windowMenuItems2 == 1) { - window.remove(WINDOW_MENU_ITEMS); - windowMenuItems2 = 0; - } - } - } - } catch (Exception e) { - } - } - - /** Changes the name of an item in the Window menu. */ - public static synchronized void updateWindowMenuItem(String oldLabel, String newLabel) { - updateWindowMenuItem(null, oldLabel, newLabel); - } - - /** Changes the name of an item in the Window menu. */ - public static synchronized void updateWindowMenuItem(ImagePlus imp, String oldLabel, String newLabel) { - if (oldLabel == null || newLabel == null) - return; - int first = WINDOW_MENU_ITEMS; - int count = window.getItemCount(); - try { // workaround for Linux/Java 5.0/bug - for (int i = first; i < count; i++) { - MenuItem item = window.getItem(i); - String label = item.getLabel(); - String cmd = item.getActionCommand(); - if (imp != null) { // remove size (e.g. " 24MB") - int index = label.lastIndexOf(" "); - if (index > -1) - label = label.substring(0, index); - } - if (item!=null && label.equals(oldLabel) && (imp==null||(""+imp.getID()).equals(cmd))) { - String size = ""; - if (imp != null) - size = " " + ImageWindow.getImageSize(imp); - item.setLabel(newLabel + size); - return; - } - } - } catch (Exception e) { - } - } - - /** Adds a file path to the beginning of the File/Open Recent submenu. */ - public static synchronized void addOpenRecentItem(String path) { - if (ij == null) - return; - int count = openRecentMenu.getItemCount(); - for (int i = 0; i < count;) { - if (openRecentMenu.getItem(i).getLabel().equals(path)) { - openRecentMenu.remove(i); - count--; - } else - i++; - } - if (count == MAX_OPEN_RECENT_ITEMS) - openRecentMenu.remove(MAX_OPEN_RECENT_ITEMS - 1); - MenuItem item = new MenuItem(path); - openRecentMenu.insert(item, 0); - item.addActionListener(ij); - } - - public static PopupMenu getPopupMenu() { - return popup; - } - - public static Menu getSaveAsMenu() { - return saveAsMenu; - } - - /** - * Adds a plugin based command to the end of a specified menu. - * - * @param plugin the plugin (e.g. "Inverter_", "Inverter_("arg")") - * @param menuCode PLUGINS_MENU, IMPORT_MENU, SAVE_AS_MENU or HOT_KEYS - * @param command the menu item label (set to "" to uninstall) - * @param shortcut the keyboard shortcut (e.g. "y", "Y", "F1") - * @param ij ImageJ (the action listener) - * - * @return returns an error code(NORMAL_RETURN,COMMAND_IN_USE_ERROR, etc.) - */ - public static int installPlugin(String plugin, char menuCode, String command, String shortcut, ImageJ ij) { - if (command.equals("")) // uninstall - return NORMAL_RETURN; - - if (commandInUse(command)) - return COMMAND_IN_USE; - if (!validShortcut(shortcut)) - return INVALID_SHORTCUT; - if (shortcutInUse(shortcut)) - return SHORTCUT_IN_USE; - - Menu menu; - switch (menuCode) { - case PLUGINS_MENU: - menu = pluginsMenu; - break; - case IMPORT_MENU: - menu = getMenu("File>Import"); - break; - case SAVE_AS_MENU: - menu = getMenu("File>Save As"); - break; - case SHORTCUTS_MENU: - menu = shortcutsMenu; - break; - case ABOUT_MENU: - menu = getMenu("Help>About Plugins"); - break; - case FILTERS_MENU: - menu = getMenu("Process>Filters"); - break; - case TOOLS_MENU: - menu = getMenu("Analyze>Tools"); - break; - case UTILITIES_MENU: - menu = utilitiesMenu; - break; - default: - return 0; - } - int code = convertShortcutToCode(shortcut); - MenuItem item; - boolean functionKey = code >= KeyEvent.VK_F1 && code <= KeyEvent.VK_F12; - if (code == 0) - item = new MenuItem(command); - else if (functionKey) { - command += " [F" + (code - KeyEvent.VK_F1 + 1) + "]"; - shortcuts.put(Integer.valueOf(code), command); - item = new MenuItem(command); - } else { - shortcuts.put(Integer.valueOf(code), command); - int keyCode = code; - boolean shift = false; - if (keyCode >= 265 && keyCode <= 290) { - keyCode -= 200; - shift = true; - } - item = new MenuItem(command, new MenuShortcut(keyCode, shift)); - } - menu.add(item); - item.addActionListener(ij); - pluginsTable.put(command, plugin); - shortcut = code > 0 && !functionKey ? "[" + shortcut + "]" : ""; - pluginsPrefs.addElement(menuCode + ",\"" + command + shortcut + "\"," + plugin); - return NORMAL_RETURN; - } - - /** Deletes a command installed by Plugins/Shortcuts/Add Shortcut. */ - public static int uninstallPlugin(String command) { - boolean found = false; - for (Enumeration en = pluginsPrefs.elements(); en.hasMoreElements();) { - String cmd = (String) en.nextElement(); - if (cmd.contains(command)) { - boolean ok = pluginsPrefs.removeElement((Object) cmd); - found = true; - break; - } - } - if (found) - return NORMAL_RETURN; - else - return COMMAND_NOT_FOUND; - - } - - public static boolean commandInUse(String command) { - if (pluginsTable.get(command) != null) - return true; - else - return false; - } - - public static int convertShortcutToCode(String shortcut) { - int code = 0; - int len = shortcut.length(); - if (len==2 && shortcut.charAt(0)=='A') { //arrow key shortcuts - if (shortcut.charAt(1)=='L') code=37; - if (shortcut.charAt(1)=='U') code=38; - if (shortcut.charAt(1)=='R') code=39; - if (shortcut.charAt(1)=='D') code=40; - return code; - } - if (len == 2 && shortcut.charAt(0) == 'F') { - code = KeyEvent.VK_F1 + (int) shortcut.charAt(1) - 49; - if (code >= KeyEvent.VK_F1 && code <= KeyEvent.VK_F9) - return code; - else - return 0; - } - if (len == 3 && shortcut.charAt(0) == 'F') { - code = KeyEvent.VK_F10 + (int) shortcut.charAt(2) - 48; - if (code >= KeyEvent.VK_F10 && code <= KeyEvent.VK_F12) - return code; - else - return 0; - } - if (len == 2 && shortcut.charAt(0) == 'N') { // numeric keypad - code = KeyEvent.VK_NUMPAD0 + (int) shortcut.charAt(1) - 48; - if (code >= KeyEvent.VK_NUMPAD0 && code <= KeyEvent.VK_NUMPAD9) - return code; - switch (shortcut.charAt(1)) { - case '/': - return KeyEvent.VK_DIVIDE; - case '*': - return KeyEvent.VK_MULTIPLY; - case '-': - return KeyEvent.VK_SUBTRACT; - case '+': - return KeyEvent.VK_ADD; - case '.': - return KeyEvent.VK_DECIMAL; - default: - return 0; - } - } - if (len != 1) - return 0; - int c = (int) shortcut.charAt(0); - if (c >= 65 && c <= 90) // A-Z - code = KeyEvent.VK_A + c - 65 + 200; - else if (c >= 97 && c <= 122) // a-z - code = KeyEvent.VK_A + c - 97; - else if (c >= 48 && c <= 57) // 0-9 - code = KeyEvent.VK_0 + c - 48; - return code; - } - - void installStartupMacroSet() { - if (macrosPath == null) { - MacroInstaller.installFromJar("/macros/StartupMacros.txt"); - return; - } - String path = macrosPath + "StartupMacros.txt"; - File f = new File(path); - if (!f.exists()) { - path = macrosPath + "StartupMacros.ijm"; - f = new File(path); - if (!f.exists()) { - (new MacroInstaller()).installFromIJJar("/macros/StartupMacros.txt"); - return; - } - } else { - if ("StartupMacros.fiji.ijm".equals(f.getName())) - path = f.getPath(); - } - String libraryPath = macrosPath + "Library.txt"; - f = new File(libraryPath); - boolean isLibrary = f.exists(); - try { - MacroInstaller mi = new MacroInstaller(); - if (isLibrary) - mi.installLibrary(libraryPath); - mi.installStartupMacros(path); - nMacros += mi.getMacroCount(); - } catch (Exception e) { - } - } - - static boolean validShortcut(String shortcut) { - int len = shortcut.length(); - if (shortcut.equals("")) - return true; - else if (len == 1) - return true; - else if (shortcut.startsWith("F") && (len == 2 || len == 3)) - return true; - else - return false; - } - - /** Returns 'true' if this keyboard shortcut is in use. */ - public static boolean shortcutInUse(String shortcut) { - int code = convertShortcutToCode(shortcut); - if (shortcuts.get(Integer.valueOf(code)) != null) - return true; - else - return false; - } - - /** - * Set the size (in points) used for the fonts in ImageJ menus. Set the size to - * 0 to use the Java default size. - */ - public static void setFontSize(int size) { - if (size < 9 && size != 0) - size = 9; - if (size > 24) - size = 24; - fontSize = size; - } - - /** - * Returns the size (in points) used for the fonts in ImageJ menus. Returns 0 if - * the default font size is being used or if this is a Macintosh. - */ - public static int getFontSize() { - return fontSize; - } - - public static Font getFont() { - return getFont(true); - } - - public static Font getFont(boolean checkSize) { - int size = fontSize==0?13:fontSize; - size = (int)Math.round(size*scale); - int size0 = size; - if (checkSize && IJ.isWindows() && scale>1.0 && size>17) - size = 17; // Java resets size to 12 if you try to set it to 18 or greater - Font menuFont = new Font("SanSerif", Font.PLAIN, size); - //System.out.println("getFont: "+checkSize+" "+scale+" "+size0+" "+size+" "+menuFont); - return menuFont; - } - - /** Called once when ImageJ quits. */ - public static void savePreferences(Properties prefs) { - if (pluginsPrefs==null) - return; - int index = 0; - for (Enumeration en = pluginsPrefs.elements(); en.hasMoreElements();) { - String key = "plugin" + (index / 10) % 10 + index % 10; - String value = (String) en.nextElement(); - prefs.put(key, value); - index++; - } - int n = openRecentMenu.getItemCount(); - for (int i = 0; i < n; i++) { - String key = "" + i; - if (key.length() == 1) - key = "0" + key; - key = "recent" + key; - prefs.put(key, openRecentMenu.getItem(i).getLabel()); - } - prefs.put(Prefs.MENU_SIZE, Integer.toString(fontSize)); - } - - public static void updateImageJMenus() { - jarFiles = macroFiles = null; - Menus m = new Menus(IJ.getInstance(), IJ.getApplet()); - String err = m.addMenuBar(); - if (err != null) - IJ.error(err); - m.installStartupMacroSet(); - IJ.resetClassLoader(); - //IJ.runPlugIn("ij.plugin.ClassChecker", ""); - IJ.showStatus("Menus updated: " + m.nPlugins + " commands, " + m.nMacros + " macros"); - /*Changed for Bio7!*/ - updateBio7ImageJMenu(); - - } - - public static void updateBio7ImageJMenu() { - Display dis = Util.getDisplay(); - dis.asyncExec(new Runnable() { - public void run() { - CanvasView canvasView = CanvasView.getCanvas_view(); - IViewSite viewSite = canvasView.getViewSite(); - IActionBars actionBars = viewSite.getActionBars(); - IContributionItem[] it = actionBars.getToolBarManager().getItems(); - for (int j = 0; j < it.length; j++) { - //String name = Menus.getMenuBar().getMenu(j).getName(); - String name = it[j].getId(); - if (name.equals("File") == false && name.equals("Edit") == false && name.equals("Image") == false - && name.equals("Process") == false && name.equals("Analyze") == false - && name.equals("Plugins") == false && name.equals("Window") == false - && name.equals("Help") == false) { - - actionBars.getToolBarManager().remove(name); - actionBars.getToolBarManager().update(true); - } - } - int count = Menus.getMenuBar().getMenuCount(); - for (int i = 0; i < count; i++) { - String name = Menus.getMenuBar().getMenu(i).getLabel(); - if (name.equals("File") == false && name.equals("Edit") == false && name.equals("Image") == false - && name.equals("Process") == false && name.equals("Analyze") == false - && name.equals("Plugins") == false && name.equals("Window") == false - && name.equals("Help") == false) { - if (name.isEmpty() == false) { - actionBars.getToolBarManager().add(new ImageJExtensionAction(name)); - actionBars.getToolBarManager().update(true); - } - } - } - } - }); - } - - public static void updateFont() { - scale = (int) Math.round(Prefs.getGuiScale()); - Font font = getFont(); - mbar.setFont(font); - if (ij != null) - ij.setMenuBar(mbar); - popup.setFont(font); - } - - /** Adds a command to the ImageJ menu bar. */ - public static void add(String menuPath, String plugin) { - if (pluginsTable == null) - return; - int index = menuPath.lastIndexOf(">"); - if (index == -1 || index == menuPath.length() - 1) - return; - String label = menuPath.substring(index + 1, menuPath.length()); - menuPath = menuPath.substring(0, index); - pluginsTable.put(label, plugin); - addItem(getMenu(menuPath), label, 0, false); - } - -} diff --git a/com.eco.bio7.image/src/ij/OtherInstance.java b/com.eco.bio7.image/src/ij/OtherInstance.java deleted file mode 100644 index a440dab69..000000000 --- a/com.eco.bio7.image/src/ij/OtherInstance.java +++ /dev/null @@ -1,243 +0,0 @@ -package ij; - -import ij.IJ; -import ij.ImageJ; -import ij.Prefs; - -import ij.io.OpenDialog; -import ij.io.Opener; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import java.lang.reflect.Method; - -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.server.UnicastRemoteObject; - -import java.util.Properties; - -/* - * This class tries to contact another instance on the same machine, started - * by the current user. If such an instance is found, the arguments are - * sent to that instance. If no such an instance is found, listen for clients. - * - * No need for extra security, as the stub (and its serialization) contain - * a hard-to-guess hash code. - * - * @author Johannes Schindelin - */ -public class OtherInstance { - private static final String DELIMETER = "~!~"; // Separates macro name and argument - - interface ImageJInstance extends Remote { - void sendArgument(String arg) throws RemoteException; - } - - static class Implementation implements ImageJInstance { - int counter = 0; - - public void sendArgument(String cmd) { - if (IJ.debugMode) IJ.log("SocketServer.sendArgument: \""+ cmd+"\""); - if (cmd.startsWith("open ")) - (new Opener()).openAndAddToRecent(cmd.substring(5)); - else if (cmd.startsWith("macro ")) { - String name = cmd.substring(6); - String name2 = name; - String arg = null; - int index = name2.indexOf(DELIMETER); - if (index!=-1) { - name = name2.substring(0, index); - arg = name2.substring(index+DELIMETER.length(), name2.length()); - } - IJ.runMacroFile(name, arg); - } else if (cmd.startsWith("run ")) - IJ.run(cmd.substring(4)); - else if (cmd.startsWith("eval ")) { - String rtn = IJ.runMacro(cmd.substring(5)); - if (rtn!=null) - System.out.print(rtn); - } else if (cmd.startsWith("user.dir ")) { - OpenDialog.setDefaultDirectory(cmd.substring(9)); - System.setProperty("user.dir", cmd.substring(9)); - } - } - } - - public static String getStubPath() { - String display = System.getenv("DISPLAY"); - if (display!=null) { - display = display.replace(':', '_'); - display = display.replace('/', '_'); - } - String tmpDir = System.getProperty("java.io.tmpdir"); - tmpDir = IJ.addSeparator(tmpDir); - return tmpDir + "ImageJ-" - + System.getProperty("user.name") + "-" - + (display == null ? "" : display + "-") - + ImageJ.getPort() + ".stub"; - } - - public static void makeFilePrivate(String path) { - try { - File file = new File(path); - file.deleteOnExit(); - - // File.setReadable() is Java 6 - Class[] types = { boolean.class, boolean.class }; - Method m = File.class.getMethod("setReadable", types); - Object[] arguments = { Boolean.FALSE, Boolean.FALSE }; - m.invoke(file, arguments); - arguments = new Object[] { Boolean.TRUE, Boolean.TRUE }; - m.invoke(file, arguments); - types = new Class[] { boolean.class }; - m = File.class.getMethod("setWritable", types); - arguments = new Object[] { Boolean.FALSE }; - m.invoke(file, arguments); - return; - } catch (Exception e) { - if (IJ.debugMode) - System.err.println("Java < 6 detected," - + " trying chmod 0600 " + path); - } - if (!IJ.isWindows()) { - try { - String[] command = { - "chmod", "0600", path - }; - Runtime.getRuntime().exec(command); - } catch (Exception e) { - if (IJ.debugMode) - System.err.println("Even chmod failed."); - } - } - } - - public static boolean sendArguments(String[] args) { - if (!isRMIEnabled()) - return false; - String file = getStubPath(); - try { - FileInputStream in = new FileInputStream(file); - ImageJInstance instance = (ImageJInstance) new ObjectInputStream(in).readObject(); - in.close(); - if (instance==null) - return false; - instance.sendArgument("user.dir "+System.getProperty("user.dir")); - int macros = 0; - for (int i=0; itext in the preferences file using - * the keyword key. The string can be retrieved using the - * appropriate get() method. - * - * @see #get(String,String) - */ - public static void set(String key, String text) { - if (key.indexOf('.') < 1) - throw new IllegalArgumentException("Key must have a prefix"); - if (text == null) - ijPrefs.remove(KEY_PREFIX + key); - else - ijPrefs.put(KEY_PREFIX + key, text); - } - - /** - * Saves the value of the integer value in the preferences file - * using the keyword key. The value can be retrieved using the - * appropriate get() method. - * - * @see #get(String,double) - */ - public static void set(String key, int value) { - set(key, Integer.toString(value)); - } - - /** - * Saves the value of the double value in the preferences file - * using the keyword key. The value can be retrieved using the - * appropriate get() method. - * - * @see #get(String,double) - */ - public static void set(String key, double value) { - set(key, "" + value); - } - - /** - * Saves the value of the boolean value in the preferences file - * using the keyword key. The value can be retrieved using the - * appropriate get() method. - * - * @see #get(String,boolean) - */ - public static void set(String key, boolean value) { - set(key, "" + value); - } - - /** - * Uses the keyword key to retrieve a string from the preferences - * file. Returns defaultValue if the key is not found. - */ - public static String get(String key, String defaultValue) { - String value = ijPrefs.getProperty(KEY_PREFIX + key); - if (value == null) - return defaultValue; - else - return value; - } - - /** - * Uses the keyword key to retrieve a number from the preferences - * file. Returns defaultValue if the key is not found. - */ - public static double get(String key, double defaultValue) { - String s = ijPrefs.getProperty(KEY_PREFIX + key); - Double d = null; - if (s != null) { - try { - d = Double.valueOf(s); - } catch (NumberFormatException e) { - d = null; - } - if (d != null) - return (d.doubleValue()); - } - return defaultValue; - } - - /** - * Uses the keyword key to retrieve a boolean from the preferences - * file. Returns defaultValue if the key is not found. - */ - public static boolean get(String key, boolean defaultValue) { - String value = ijPrefs.getProperty(KEY_PREFIX + key); - if (value == null) - return defaultValue; - else - return value.equals("true"); - } - - /** - * Finds and loads the configuration file ("IJ_Props.txt") and the preferences - * file ("IJ_Prefs.txt"). - * - * @return an error message if "IJ_Props.txt" not found. - */ - public static String load(Object ij, Applet applet) { - /* Changed for Bio7! */ - - String path = Util.getImageJPath(); - - InputStream f = ij.getClass().getResourceAsStream(path + PROPS_NAME); - if (applet != null) - return loadAppletProps(f, applet); - if (ImageJDir == null) - /* /*Changed for Bio7! */ - ImageJDir = path;// System.getProperty("user.dir"); - /* - * String userHome = path;// System.getProperty("user.home"); if - * (IJ.isWindows()) { prefsDir = homeDir; // ImageJ folder on Windows if - * (prefsDir.endsWith("Desktop")) prefsDir = userHome; } else { prefsDir = - * homeDir; // prefsDir = userHome; // Mac Preferences folder or Unix home dir - * if (IJ.isMacOSX()) // prefsDir += "/Library/Preferences"; prefsDir = homeDir; - * // else // prefsDir += File.separator + ".imagej"; } - */ - if (f == null) { - try { - f = new FileInputStream(ImageJDir + "/" + PROPS_NAME); - propertiesPath = ImageJDir + "/" + PROPS_NAME; - } catch (FileNotFoundException e) { - f = null; - } - } - if (f == null) - return PROPS_NAME + " not found in ij.jar or in " + ImageJDir; - f = new BufferedInputStream(f); - try { - props.load(f); - f.close(); - } catch (IOException e) { - return ("Error loading " + PROPS_NAME); - } - imagesURL = props.getProperty(IJ.isJava18() ? "images.location" : "images.location2"); - loadPreferences(); - loadOptions(); - guiScale = get(GUI_SCALE, 1.0); - return null; - } - - /* - * static void dumpPrefs(String title) { IJ.log(""); IJ.log(title); static void - * dumpPrefs() { System.out.println(""); Enumeration e = ijPrefs.keys(); while - * (e.hasMoreElements()) { String key = (String) e.nextElement(); - * IJ.log(key+": "+ijPrefs.getProperty(key)); - * System.out.println(key+": "+ijPrefs.getProperty(key)); } } - */ - - static String loadAppletProps(InputStream f, Applet applet) { - if (f == null) - return PROPS_NAME + " not found in ij.jar"; - try { - props.load(f); - f.close(); - } catch (IOException e) { - return ("Error loading " + PROPS_NAME); - } - try { - URL url = new URL(applet.getDocumentBase(), "images/"); - imagesURL = url.toString(); - } catch (Exception e) { - } - return null; - } - - /** - * Returns the URL of the directory that contains the ImageJ sample images. - */ - public static String getImagesURL() { - return imagesURL; - } - - /** Sets the URL of the directory that contains the ImageJ sample images. */ - public static void setImagesURL(String url) { - imagesURL = url; - } - - /** - * Obsolete, replaced by getImageJDir(), which, unlike this method, returns a - * path that ends with File.separator. - */ - public static String getHomeDir() { - return ImageJDir; - } - - /** Returns the path, ending in File.separator, to the ImageJ directory. */ - public static String getImageJDir() { - /* Changed for Bio7! */ - String path = Util.getImageJPath(); - if (path == null) - return ImageJDir + File.separator; - else - return path + File.separator; - } - - public static String getPluginsDirProperty() { - if (pluginsDirProperty==null) { - String ijDir = System.getProperty("plugins.dir"); - if (ijDir!=null) { - if (ijDir.endsWith("/")||ijDir.endsWith("\\")) - ijDir = ijDir.substring(0, ijDir.length()-1); - if (ijDir.endsWith("/plugins")||ijDir.endsWith("\\plugins")) - ijDir = ijDir.substring(0, ijDir.length()-8); - pluginsDirProperty = ijDir; - } else - pluginsDirProperty = ""; - } - return pluginsDirProperty.length()>0?pluginsDirProperty:null; - } - - /** - * Returns the path to the directory where the preferences file (IJPrefs.txt) is - * saved. - */ - public static String getPrefsDir() { - /* Changed for Bio7! */ - String path = Util.getImageJPath(); - if (prefsDir == null) { - - /* - * if (IJ.isMacOSX()) dir += "/Library/Preferences"; else dir += - * File.separator+".imagej"; - */ - prefsDir = path; - preferencesPath = path + "/" + PREFS_NAME; - } - return prefsDir; - } - - /** Sets the path to the ImageJ directory. */ - static void setHomeDir(String path) { - if (path.endsWith(File.separator) || path.endsWith("/")) - path = path.substring(0, path.length() - 1); - ImageJDir = path; - } - - /** Returns the default directory, if any, or null. */ - public static String getDefaultDirectory() { - if (commandLineMacro) - return null; - else - return getString(DIR_IMAGE); - } - - /** Returns the file.separator system property. */ - public static String getFileSeparator() { - return separator; - } - - /** Opens the ImageJ preferences file ("IJ_Prefs.txt") file. */ - static void loadPreferences() { - String path = getPrefsDir() + separator + PREFS_NAME; - boolean ok = loadPrefs(path); - if (!ok) { // not found - if (IJ.isWindows()) - path = ImageJDir + separator + PREFS_NAME; - else - path = System.getProperty("user.home") + separator + PREFS_NAME; // User's - // home - // dir - ok = loadPrefs(path); - if (ok) - new File(path).delete(); - } - - } - - static boolean loadPrefs(String path) { - try { - InputStream is = new BufferedInputStream(new FileInputStream(path)); - ijPrefs.load(is); - is.close(); - return true; - } catch (Exception e) { - return false; - } - } - - /** Saves user preferences in the IJ_Prefs.txt properties file. */ - public static void savePreferences() { - String path = null; - commandLineMacro = false; - try { - Properties prefs = new Properties(); - String dir = OpenDialog.getDefaultDirectory(); - if (dir != null) - prefs.put(DIR_IMAGE, dir); - prefs.put(ROICOLOR, Tools.c2hex(Roi.getColor())); - prefs.put(SHOW_ALL_COLOR, Tools.c2hex(ImageCanvas.getShowAllColor())); - prefs.put(FCOLOR, Tools.c2hex(Toolbar.getForegroundColor())); - prefs.put(BCOLOR, Tools.c2hex(Toolbar.getBackgroundColor())); - prefs.put(JPEG, Integer.toString(FileSaver.getJpegQuality())); - prefs.put(FPS, Double.toString(Animator.getFrameRate())); - prefs.put(DIV_BY_ZERO_VALUE, Double.toString(FloatBlitter.divideByZeroValue)); - prefs.put(NOISE_SD, Double.toString(Filters.getSD())); - if (threads > 1) - prefs.put(THREADS, Integer.toString(threads)); - if (IJ.isMacOSX()) - useJFileChooser = false; - if (!IJ.isLinux()) - dialogCancelButtonOnRight = false; - saveOptions(prefs); - savePluginPrefs(prefs); - ImageJ ij = IJ.getInstance(); - if (ij!=null) - ij.savePreferences(prefs); - Menus.savePreferences(prefs); - ParticleAnalyzer.savePreferences(prefs); - Analyzer.savePreferences(prefs); - ImportDialog.savePreferences(prefs); - PlotWindow.savePreferences(prefs); - NewImage.savePreferences(prefs); - String prefsDir = getPrefsDir(); - path = prefsDir + separator + PREFS_NAME; - if (prefsDir.endsWith(".imagej")) { - File f = new File(prefsDir); - if (!f.exists()) - f.mkdir(); // create .imagej directory - } - if (resetPreferences) { - File f = new File(path); - if (!f.exists()) - IJ.error("Edit>Options>Reset", "Unable to reset preferences. File not found at\n" + path); - boolean rtn = f.delete(); - resetPreferences = false; - } else - savePrefs(prefs, path); - } catch (Throwable t) { - String msg = t.getMessage(); - if (msg == null) - msg = "" + t; - int delay = 4000; - try { - new TextWindow("Error Saving Preferences:\n" + path, msg, 500, 200); - IJ.wait(delay); - } catch (Throwable t2) { - } - } - } - - /** Delete the preferences file when ImageJ quits. */ - public static void resetPreferences() { - resetPreferences = true; - } - - static void loadOptions() { - // Changed for Bio7. On Win 10 we use the SWT file dialog by default. No need to - // switch to JFileChooser! - int defaultOptions = ANTIALIASING + AVOID_RESLICE_INTERPOLATION + ANTIALIASED_TOOLS + MULTI_POINT_MODE - + (!IJ.isMacOSX() ? RUN_SOCKET_LISTENER : 0) + BLACK_BACKGROUND; - int options = getInt(OPTIONS, defaultOptions); - usePointerCursor = (options & USE_POINTER) != 0; - // antialiasedText = (options&ANTIALIASING)!=0; - antialiasedText = false; - interpolateScaledImages = (options & INTERPOLATE) != 0; - open100Percent = (options & ONE_HUNDRED_PERCENT) != 0; - //blackBackground = (options&BLACK_BACKGROUND)!=0; - useJFileChooser = (options & JFILE_CHOOSER) != 0; - weightedColor = (options & WEIGHTED) != 0; - if (weightedColor) - ColorProcessor.setWeightingFactors(0.299, 0.587, 0.114); - blackCanvas = (options & BLACK_CANVAS) != 0; - requireControlKey = (options & REQUIRE_CONTROL) != 0; - useInvertingLut = (options & USE_INVERTING_LUT) != 0; - antialiasedTools = (options & ANTIALIASED_TOOLS) != 0; - intelByteOrder = (options & INTEL_BYTE_ORDER) != 0; - noBorder = (options & NO_BORDER) != 0; - //showAllSliceOnly = (options & SHOW_ALL_SLICE_ONLY) != 0; - copyColumnHeaders = (options & COPY_HEADERS) != 0; - noRowNumbers = (options & NO_ROW_NUMBERS) != 0; - moveToMisc = (options & MOVE_TO_MISC) != 0; - runSocketListener = (options & RUN_SOCKET_LISTENER) != 0; - multiPointMode = (options & MULTI_POINT_MODE) != 0; - rotateYZ = (options & ROTATE_YZ) != 0; - flipXZ = (options & FLIP_XZ) != 0; - // dontSaveHeaders = (options&DONT_SAVE_HEADERS)!=0; - // dontSaveRowNumbers = (options&DONT_SAVE_ROW_NUMBERS)!=0; - noClickToGC = (options & NO_CLICK_TO_GC) != 0; - avoidResliceInterpolation = (options & AVOID_RESLICE_INTERPOLATION) != 0; - keepUndoBuffers = (options & KEEP_UNDO_BUFFERS) != 0; - - defaultOptions = (!IJ.isMacOSX() ? USE_FILE_CHOOSER : 0); - int options2 = getInt(OPTIONS2, defaultOptions); - useSystemProxies = (options2 & USE_SYSTEM_PROXIES) != 0; - useFileChooser = (options2 & USE_FILE_CHOOSER) != 0; - subPixelResolution = (options2 & SUBPIXEL_RESOLUTION) != 0; - enhancedLineTool = (options2 & ENHANCED_LINE_TOOL) != 0; - skipRawDialog = (options2 & SKIP_RAW_DIALOG) != 0; - reverseNextPreviousOrder = (options2 & REVERSE_NEXT_PREVIOUS_ORDER) != 0; - autoRunExamples = (options2 & AUTO_RUN_EXAMPLES) != 0; - showAllPoints = (options2 & SHOW_ALL_POINTS) != 0; - doNotSaveWindowLocations = (options2 & DO_NOT_SAVE_WINDOW_LOCS) != 0; - jFileChooserSettingChanged = (options2 & JFILE_CHOOSER_CHANGED) != 0; - dialogCancelButtonOnRight = (options2 & CANCEL_BUTTON_ON_RIGHT) != 0; - ignoreRescaleSlope = (options2 & IGNORE_RESCALE_SLOPE) != 0; - nonBlockingFilterDialogs = (options2 & NON_BLOCKING_DIALOGS) != 0; - fixedDicomScaling = (options2&FIXED_DICOM_SCALING)!=0; - //calibrateConversions = (options2&CALIBRATE_CONVERSIONS)!=0; - } - - static void saveOptions(Properties prefs) { - int options = (usePointerCursor ? USE_POINTER : 0) + (antialiasedText ? ANTIALIASING : 0) - + (interpolateScaledImages ? INTERPOLATE : 0) + (open100Percent ? ONE_HUNDRED_PERCENT : 0) - + (blackBackground ? BLACK_BACKGROUND : 0) + (useJFileChooser ? JFILE_CHOOSER : 0) - + (blackCanvas ? BLACK_CANVAS : 0) + (weightedColor ? WEIGHTED : 0) - + (requireControlKey ? REQUIRE_CONTROL : 0) + (useInvertingLut ? USE_INVERTING_LUT : 0) - + (intelByteOrder ? INTEL_BYTE_ORDER : 0) + (doubleBuffer ? DOUBLE_BUFFER : 0) - + (noPointLabels ? NO_POINT_LABELS : 0) + (noBorder ? NO_BORDER : 0) - + (showAllSliceOnly ? SHOW_ALL_SLICE_ONLY : 0) + (copyColumnHeaders ? COPY_HEADERS : 0) - + (noRowNumbers ? NO_ROW_NUMBERS : 0) + (moveToMisc ? MOVE_TO_MISC : 0) - + (runSocketListener ? RUN_SOCKET_LISTENER : 0) + (multiPointMode ? MULTI_POINT_MODE : 0) - + (rotateYZ ? ROTATE_YZ : 0) + (flipXZ ? FLIP_XZ : 0) + (dontSaveHeaders ? DONT_SAVE_HEADERS : 0) - + (dontSaveRowNumbers ? DONT_SAVE_ROW_NUMBERS : 0) + (noClickToGC ? NO_CLICK_TO_GC : 0) - + (avoidResliceInterpolation ? AVOID_RESLICE_INTERPOLATION : 0) - + (keepUndoBuffers ? KEEP_UNDO_BUFFERS : 0); - prefs.put(OPTIONS, Integer.toString(options)); - - int options2 = (useSystemProxies ? USE_SYSTEM_PROXIES : 0) + (useFileChooser ? USE_FILE_CHOOSER : 0) - + (subPixelResolution ? SUBPIXEL_RESOLUTION : 0) + (enhancedLineTool ? ENHANCED_LINE_TOOL : 0) - + (skipRawDialog ? SKIP_RAW_DIALOG : 0) + (reverseNextPreviousOrder ? REVERSE_NEXT_PREVIOUS_ORDER : 0) - + (autoRunExamples ? AUTO_RUN_EXAMPLES : 0) + (showAllPoints ? SHOW_ALL_POINTS : 0) - + (doNotSaveWindowLocations ? DO_NOT_SAVE_WINDOW_LOCS : 0) - + (jFileChooserSettingChanged ? JFILE_CHOOSER_CHANGED : 0) - + (dialogCancelButtonOnRight ? CANCEL_BUTTON_ON_RIGHT : 0) - + (ignoreRescaleSlope ? IGNORE_RESCALE_SLOPE : 0) - + (nonBlockingFilterDialogs?NON_BLOCKING_DIALOGS:0) - + (fixedDicomScaling?FIXED_DICOM_SCALING:0); - //+ (calibrateConversions?CALIBRATE_CONVERSIONS:0); - prefs.put(OPTIONS2, Integer.toString(options2)); - } - - /** - * Saves the Point loc in the preferences file as a string using - * the keyword key. - */ - public static void saveLocation(String key, Point loc) { - if (!doNotSaveWindowLocations) - set(key, loc != null ? loc.x + "," + loc.y : null); - } - - /** - * Uses the keyword key to retrieve a location from the preferences - * file. Returns null if the key is not found or the location is not valid - * (e.g., offscreen). - */ - public static Point getLocation(String key) { - String value = ijPrefs.getProperty(KEY_PREFIX + key); - if (value == null) - return null; - int index = value.indexOf(","); - if (index == -1) - return null; - double xloc = Tools.parseDouble(value.substring(0, index)); - if (Double.isNaN(xloc) || index == value.length() - 1) - return null; - double yloc = Tools.parseDouble(value.substring(index + 1)); - if (Double.isNaN(yloc)) - return null; - Point p = new Point((int) xloc, (int) yloc); - Rectangle bounds = GUI.getScreenBounds(p); // get bounds of screen that contains p - if (bounds != null && p.x + 100 <= bounds.x + bounds.width && p.y + 40 <= bounds.y + bounds.height) { - if (locKeys.get(key) == null) { // first time for this key? - locKeys.setProperty(key, ""); - Rectangle primaryScreen = GUI.getMaxWindowBounds(); - ImageJ ij = IJ.getInstance(); - Point ijLoc = ij != null ? ij.getLocation() : null; - //System.out.println("getLoc: "+key+" "+(ijLoc!=null&&primaryScreen.contains(ijLoc)) + " "+!primaryScreen.contains(p)); - if ((ijLoc != null && primaryScreen.contains(ijLoc)) && !primaryScreen.contains(p)) - return null; // return null if "ImageJ" window on primary screen and this location is not - } - return p; - } else - return null; - } - - /** Save plugin preferences. */ - static void savePluginPrefs(Properties prefs) { - Enumeration e = ijPrefs.keys(); - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - if (key.indexOf(KEY_PREFIX) == 0) - prefs.put(key, ijPrefs.getProperty(key)); - } - } - - public static void savePrefs(Properties prefs, String path) throws IOException { - FileOutputStream fos = new FileOutputStream(path); - BufferedOutputStream bos = new BufferedOutputStream(fos); - prefs.store(bos, "ImageJ " + ImageJ.VERSION + " Preferences"); - bos.close(); - } - - /** - * Returns the number of threads used by PlugInFilters to process images and - * stacks. - */ - public static int getThreads() { - if (threads == 0) { - threads = getInt(THREADS, 0); - int processors = Runtime.getRuntime().availableProcessors(); - if (threads < 1 || threads > processors) - threads = processors; - } - return threads; - } - - /** - * Sets the number of threads (1-32) used by PlugInFilters to process stacks. - */ - public static void setThreads(int n) { - if (n < 1) - n = 1; - threads = n; - } - - /** - * Sets the transparent index (0-255), or set to -1 to disable transparency. - */ - public static void setTransparentIndex(int index) { - if (index < -1 || index > 255) - index = -1; - transparentIndex = index; - } - - /** - * Returns the transparent index (0-255), or -1 if transparency is disabled. - */ - public static int getTransparentIndex() { - return transparentIndex; - } - - public static Properties getControlPanelProperties() { - return ijPrefs; - } - - public static String defaultResultsExtension() { - return get("options.ext", ".csv"); - } - - /** Sets the GenericDialog and Command Finder text scale (0.5 to 3.0). */ - public static void setGuiScale(double scale) { - if (scale >= 0.5 && scale <= 3.0) { - guiScale = scale; - set(GUI_SCALE, guiScale); - Roi.resetDefaultHandleSize(); - } - } - - /** Returns the GenericDialog and Command Finder text scale. */ - public static double getGuiScale() { - return guiScale; - } - - /** Returns the custom properties (IJ_Props.txt) file path. */ - public static String getCustomPropsPath() { - return propertiesPath; - } - - /** Returns the custom preferences (IJ_Prefs.txt) file path. */ - public static String getCustomPrefsPath() { - return preferencesPath; - } - - /** - * Retrieves a string from IJ_Props or IJ_Prefs.txt. Does not retrieve strings - * set using Prefs.set(). - */ - public static String getString(String key, String defaultString) { - if (props == null) - return defaultString; - String s = props.getProperty(key); - if (s == null) - return defaultString; - else - return s; - } - - /** Retrieves a string from string in IJ_Props or IJ_Prefs.txt. */ - public static String getString(String key) { - return props.getProperty(key); - } - - /** - * Retrieves a number from IJ_Props or IJ_Prefs.txt. Does not retrieve numbers - * set using Prefs.set(). - */ - public static int getInt(String key, int defaultValue) { - if (props == null) //workaround for Netscape JIT bug - return defaultValue; - String s = props.getProperty(key); - if (s != null) { - try { - return Integer.decode(s).intValue(); - } catch (NumberFormatException e) { - IJ.log("" + e); - } - } - return defaultValue; - } - - /** - * Retrieves a number from IJ_Props or IJ_Prefs.txt. Does not retrieve numbers - * set using Prefs.set(). - */ - public static double getDouble(String key, double defaultValue) { - if (props == null) - return defaultValue; - String s = props.getProperty(key); - Double d = null; - if (s != null) { - try { - d = Double.valueOf(s); - } catch (NumberFormatException e) { - d = null; - } - if (d != null) - return (d.doubleValue()); - } - return defaultValue; - } - - /** - * Retrieves a boolean from IJ_Props or IJ_Prefs.txt. Does not retrieve boolean - * set using Prefs.set(). - */ - public static boolean getBoolean(String key, boolean defaultValue) { - if (props == null) - return defaultValue; - String s = props.getProperty(key); - if (s == null) - return defaultValue; - else - return s.equals("true"); - } - - /** Finds a color in IJ_Props or IJ_Prefs.txt. */ - public static Color getColor(String key, Color defaultColor) { - int i = getInt(key, 0xaaa); - if (i == 0xaaa) - return defaultColor; - return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF); - } - - public static boolean commandLineMacro() { - return commandLineMacro; - } - -} diff --git a/com.eco.bio7.image/src/ij/RecentOpener.java b/com.eco.bio7.image/src/ij/RecentOpener.java deleted file mode 100644 index 8f0416209..000000000 --- a/com.eco.bio7.image/src/ij/RecentOpener.java +++ /dev/null @@ -1,37 +0,0 @@ -package ij; -import ij.io.*; -import java.awt.*; -import java.io.*; - -/** Opens, in a separate thread, files selected from the File/Open Recent submenu.*/ -public class RecentOpener implements Runnable { - private String path; - - RecentOpener(String path) { - this.path = path; - Thread thread = new Thread(this, "RecentOpener"); - thread.start(); - } - - /** Open the file and move the path to top of the submenu. */ - public void run() { - Opener o = new Opener(); - o.open(path); - Menu menu = Menus.getOpenRecentMenu(); - int n = menu.getItemCount(); - int index = 0; - for (int i=0; i0) { - MenuItem item = menu.getItem(index); - menu.remove(index); - menu.insert(item, 0); - } - } - -} - diff --git a/com.eco.bio7.image/src/ij/Undo.java b/com.eco.bio7.image/src/ij/Undo.java deleted file mode 100644 index ebdfcc64b..000000000 --- a/com.eco.bio7.image/src/ij/Undo.java +++ /dev/null @@ -1,233 +0,0 @@ -/**Implements the Edit/Undo command.*/ - -package ij; -import ij.process.*; -import ij.gui.*; -import ij.measure.Calibration; -import java.awt.*; -import java.awt.image.*; - -/** This class consists of static methods and - fields that implement ImageJ's Undo command. */ -public class Undo { - - public static final int NOTHING = 0; - /** Undo using ImageProcessor.snapshot. */ - public static final int FILTER = 1; - /** Undo using an ImageProcessor copy. */ - public static final int TYPE_CONVERSION = 2; - public static final int PASTE = 3; - public static final int COMPOUND_FILTER = 4; - public static final int COMPOUND_FILTER_DONE = 5; - /** Undo using a single image, or composite color stack, copy (limited to 200MB). */ - public static final int TRANSFORM = 6; - public static final int OVERLAY_ADDITION = 7; - public static final int ROI = 8; - public static final int MACRO = 9; - /** Undo of overlay modification */ - public static final int OVERLAY = 10; - - private static int whatToUndo = NOTHING; - private static int imageID; - private static ImageProcessor ipCopy = null; - private static ImagePlus impCopy; - private static Calibration calCopy; - private static Roi roiCopy; - private static double displayRangeMin, displayRangeMax; - private static LUT lutCopy; - private static Overlay overlayCopy; - private static int overlayImageID; - - public static void setup(int what, ImagePlus imp) { - if (imp==null) { - whatToUndo = NOTHING; - reset(); - return; - } - if (IJ.debugMode) IJ.log("Undo.setup: "+what+" "+imp); - if (what==FILTER && whatToUndo==COMPOUND_FILTER) - return; - if (what==COMPOUND_FILTER_DONE) { - if (whatToUndo==COMPOUND_FILTER) - whatToUndo = what; - return; - } - whatToUndo = what; - imageID = imp.getID(); - if (what==TYPE_CONVERSION) { - ipCopy = imp.getProcessor(); - calCopy = (Calibration)imp.getCalibration().clone(); - } else if (what==TRANSFORM) { - if ((!IJ.macroRunning()||Prefs.supportMacroUndo) && (imp.getStackSize()==1||imp.getDisplayMode()==IJ.COMPOSITE) && imp.getSizeInBytes()<209715200) - impCopy = imp.duplicate(); - else - reset(); - } else if (what==MACRO) { - ipCopy = imp.getProcessor().duplicate(); - calCopy = (Calibration)imp.getCalibration().clone(); - impCopy = null; - } else if (what==COMPOUND_FILTER) { - ImageProcessor ip = imp.getProcessor(); - if (ip!=null) - ipCopy = ip.duplicate(); - else - ipCopy = null; - } else if (what==OVERLAY_ADDITION) { - impCopy = null; - ipCopy = null; - } else if (what==ROI) { - impCopy = null; - ipCopy = null; - Roi roi = imp.getRoi(); - if (roi!=null) { - roiCopy = (Roi)roi.clone(); - roiCopy.setImage(null); - } else - whatToUndo = NOTHING; - } else if (what==OVERLAY) { - saveOverlay(imp); - } else { - ipCopy = null; - //ImageProcessor ip = imp.getProcessor(); - //lutCopy = (LUT)ip.getLut().clone(); - } - } - - /** This function should be called from PlugInFilters that modify the overlay prior to the operation. - * For the type 'FILTER', undo of overlays requires that the modified image also has an overlay. */ - public static void saveOverlay(ImagePlus imp) { - Overlay overlay = imp!=null?imp.getOverlay():null; - if (overlay!=null) { - overlayCopy = overlay.duplicate(); - overlayImageID = imp.getID(); - } else - overlayCopy = null; - } - - public static void reset() { - //if (IJ.debugMode) IJ.log("Undo.reset: "+ whatToUndo+" "+impCopy); - if (whatToUndo==COMPOUND_FILTER || whatToUndo==OVERLAY_ADDITION) - return; - whatToUndo = NOTHING; - imageID = 0; - ipCopy = null; - impCopy = null; - calCopy = null; - roiCopy = null; - lutCopy = null; - overlayCopy = null; - } - - public static void undo() { - ImagePlus imp = WindowManager.getCurrentImage(); - if (IJ.debugMode) IJ.log("Undo.undo: "+ whatToUndo+" "+imp+" "+impCopy); - if (imp==null || imageID!=imp.getID()) { - if (imp!=null && !IJ.macroRunning()) { // does foreground image still have an undo buffer? - ImageProcessor ip2 = imp.getProcessor(); - ip2.swapPixelArrays(); - imp.updateAndDraw(); - } else - reset(); - return; - } - switch (whatToUndo) { - case FILTER: - undoOverlay(imp, true); - ImageProcessor ip = imp.getProcessor(); - if (ip!=null) { - if (!IJ.macroRunning()) { - ip.swapPixelArrays(); - imp.updateAndDraw(); - return; // don't reset - } else { - ip.reset(); - imp.updateAndDraw(); - } - } - break; - case TYPE_CONVERSION: - case COMPOUND_FILTER: - case COMPOUND_FILTER_DONE: - if (ipCopy!=null) { - if (whatToUndo==TYPE_CONVERSION && calCopy!=null) - imp.setCalibration(calCopy); - if (swapImages(new ImagePlus("",ipCopy), imp)) { - imp.updateAndDraw(); - return; - } else - imp.setProcessor(null, ipCopy); - if (whatToUndo==COMPOUND_FILTER_DONE || whatToUndo==TYPE_CONVERSION) - undoOverlay(imp, true); - } - break; - case TRANSFORM: - if (impCopy!=null) - imp.setStack(impCopy.getStack()); - break; - case PASTE: - Roi roi = imp.getRoi(); - if (roi!=null) - roi.abortPaste(); - break; - case ROI: - Roi roiCopy2 = roiCopy; - setup(ROI, imp); // setup redo - imp.setRoi(roiCopy2); - return; //don't reset - case MACRO: - if (ipCopy!=null) { - imp.setProcessor(ipCopy); - if (calCopy!=null) imp.setCalibration(calCopy); - } - break; - case OVERLAY_ADDITION: - Overlay overlay = imp.getOverlay(); - if (overlay==null) - {IJ.beep(); return;} - int size = overlay.size(); - if (size>0) { - overlay.remove(size-1); - imp.draw(); - } else { - IJ.beep(); - return; - } - return; //don't reset; successive undo removes further rois - case OVERLAY: - undoOverlay(imp, false); - imp.draw(); - break; - } - reset(); - } - - /** Reverts the overlay to the saved version. */ - private static void undoOverlay(ImagePlus imp, boolean onlyModifyOvly) { - if (overlayCopy!=null && imp.getID()==overlayImageID) { - Overlay overlay = imp.getOverlay(); - imp.setOverlay(overlayCopy); - if (overlay != null) - overlayCopy = overlay.duplicate(); //swap - } - } - - static boolean swapImages(ImagePlus imp1, ImagePlus imp2) { - if (imp1.getWidth()!=imp2.getWidth() || imp1.getHeight()!=imp2.getHeight() - || imp1.getBitDepth()!=imp2.getBitDepth() || IJ.macroRunning()) - return false; - ImageProcessor ip1 = imp1.getProcessor(); - ImageProcessor ip2 = imp2.getProcessor(); - double min1 = ip1.getMin(); - double max1 = ip1.getMax(); - double min2 = ip2.getMin(); - double max2 = ip2.getMax(); - ip2.setSnapshotPixels(ip1.getPixels()); - ip2.swapPixelArrays(); - ip1.setPixels(ip2.getSnapshotPixels()); - ip2.setSnapshotPixels(null); - ip1.setMinAndMax(min2, max2); - ip2.setMinAndMax(min1, max1); - return true; - } - -} diff --git a/com.eco.bio7.image/src/ij/VirtualStack.java b/com.eco.bio7.image/src/ij/VirtualStack.java deleted file mode 100644 index 72a5ebd64..000000000 --- a/com.eco.bio7.image/src/ij/VirtualStack.java +++ /dev/null @@ -1,433 +0,0 @@ -package ij; -import ij.process.*; -import ij.io.*; -import ij.gui.ImageCanvas; -import ij.util.Tools; -import ij.plugin.FolderOpener; -import java.io.*; -import java.awt.*; -import java.awt.image.ColorModel; -import java.util.Properties; - -/** This class represents an array of disk-resident images. */ -public class VirtualStack extends ImageStack { - private static final int INITIAL_SIZE = 100; - private String path; - private int nSlices; - private String[] names; - private String[] labels; - private int bitDepth; - private int delay; - private Properties properties; - private boolean generateData; - private int[] indexes; // used to translate non-CZT hyperstack slice numbers (0-based) - /** subclasses that support translation of slice indices (by calling translate) should set this to true */ - protected boolean canTranslate; - - - /** Default constructor. */ - public VirtualStack() { } - - public VirtualStack(int width, int height) { - super(width, height); - } - - /** Creates an empty virtual stack. - * @param width image width - * @param height image height - * @param cm ColorModel or null - * @param path file path of directory containing the images - * @see #addSlice(String) - * @see OpenAsVirtualStack.js - */ - public VirtualStack(int width, int height, ColorModel cm, String path) { - super(width, height, cm); - path = IJ.addSeparator(path); - this.path = path; - if (path != null) - canTranslate = true; - names = new String[INITIAL_SIZE]; - labels = new String[INITIAL_SIZE]; - } - - /** Creates a virtual stack with no backing storage. - * See: Help>Examples>JavaScript>Terabyte VirtualStack - */ - public VirtualStack(int width, int height, int slices) { - this(width, height, slices, "8-bit"); - } - - /** Creates a virtual stack with no backing storage. - * See: Help>Examples>JavaScript>Terabyte VirtualStack - */ - public VirtualStack(int width, int height, int slices, String options) { - super(width, height, null); - nSlices = slices; - int depth = 8; - if (options.contains("16-bit")) depth=16; - if (options.contains("RGB")) depth=24; - if (options.contains("32-bit")) depth=32; - if (options.contains("delay")) delay=250; - this.generateData = options.contains("fill"); - this.bitDepth = depth; - } - - /** Adds an image to the end of a virtual stack created using the - * VirtualStack(w,h,cm,path) constructor. The argument - * can be a full file path (e.g., "C:/Users/wayne/dir1/image.tif") - * if the 'path' argument in the constructor is "". File names - * that start with '.' are ignored. - */ - public void addSlice(String fileName) { - if (fileName==null) - throw new IllegalArgumentException("'fileName' is null!"); - if (fileName.startsWith(".")) - return; - if (names==null) - throw new IllegalArgumentException("This Virtual Stack cannot be modified [VirtualStack(w,h,cm,path) constructor not used]"); - if (isTranslatingIndices()) - throw new IllegalArgumentException("Virtual hyperstack with non-czt order cannot be modified"); - nSlices++; - expandArrays(nSlices); - names[nSlices-1] = fileName; - } - - /** Expands the 'names' and 'labels' arrays if existing and smaller than minSize. - * This should be called each time the stack is enlarged */ - protected void expandArrays(int minSize) { - if (indexes != null && minSize < indexes.length) - minSize = indexes.length; //min size if slices were deleted previously - if (names != null && names.length < minSize) { - String[] tmp = new String[minSize*2]; - System.arraycopy(names, 0, tmp, 0, names.length); - names = tmp; - } - if (labels != null && labels.length < minSize) { - String[] tmp = new String[minSize*2]; - System.arraycopy(labels, 0, tmp, 0, labels.length); - labels = tmp; - } - } - - /** Does nothing. */ - public void addSlice(String sliceLabel, Object pixels) { - } - - /** Does nothing.. */ - public void addSlice(String sliceLabel, ImageProcessor ip) { - } - - /** Does nothing. */ - public void addSlice(String sliceLabel, ImageProcessor ip, int n) { - } - - /** Deletes the specified slice, where {@literal 1<=n<=nslices}. */ - public void deleteSlice(int n) { - if (nSlices==0) - return; - if (n<1 || n>nSlices) - throw new IllegalArgumentException("Argument out of range: "+n); - if (names==null) - throw new IllegalArgumentException("This Virtual Stack cannot be modified [VirtualStack(w,h,cm,path) constructor not used]"); - if (isTranslatingIndices()) - throw new IllegalArgumentException("Virtual hyperstack with non-czt order cannot be modified"); - for (int i=n; i0) - deleteSlice(n); - } - - /** Returns the pixel array for the specified slice, where {@literal 1<=n<=nslices}. */ - public Object getPixels(int n) { - ImageProcessor ip = getProcessor(n); - if (ip!=null) - return ip.getPixels(); - else - return null; - } - - public void setPixels(Object pixels, int n) { - } - - /** Returns an ImageProcessor for the specified slice, - * where {@literal 1<=n<=nslices}. Returns null if - * the stack is empty. - * When overriding this function, note that the ImageProcessor - * may be modified at a later time. Its pixel array - * can get replaced by the pixel array of another slice. - * This is because the ImageProcessor may be re-used when a - * different slice is accessed via ImagePlus.setSlice. - * {@link Example} - */ - public ImageProcessor getProcessor(int n) { - if (path==null) { //Help>Examples>JavaScript>Terabyte VirtualStack - ImageProcessor ip = null; - int w=getWidth(), h=getHeight(); - switch (bitDepth) { - case 8: ip = new ByteProcessor(w,h); break; - case 16: ip = new ShortProcessor(w,h); break; - case 24: ip = new ColorProcessor(w,h); break; - case 32: ip = new FloatProcessor(w,h); break; - } - String hlabel = null; - if (generateData) { - int value = 0; - ImagePlus img = WindowManager.getCurrentImage(); - if (img!=null && img.getStackSize()==nSlices) - value = img.getCurrentSlice()-1; - if (bitDepth==16) - value *= 256; - if (bitDepth!=32) { - for (int i=0; i0) - IJ.wait(delay); - return ip; - } - n = translate(n); // update n for hyperstacks not in the default CZT order - Opener opener = new Opener(); - opener.setSilentMode(true); - IJ.redirectErrorMessages(true); - ImagePlus imp = opener.openTempImage(path, names[n-1]); - IJ.redirectErrorMessages(false); - ImageProcessor ip = null; - int depthThisImage = 0; - if (imp!=null) { - int w = imp.getWidth(); - int h = imp.getHeight(); - int type = imp.getType(); - ColorModel cm = imp.getProcessor().getColorModel(); - String info = (String)imp.getProperty("Info"); - if (info!=null) { - if (FolderOpener.useInfo(info)) - setSliceLabel(info, n); - } else { - String sliceLabel = imp.getStack().getSliceLabel(1); - if (FolderOpener.useInfo(sliceLabel)) - setSliceLabel("Label: "+sliceLabel, n); - } - depthThisImage = imp.getBitDepth(); - ip = imp.getProcessor(); - ip.setOverlay(imp.getOverlay()); - properties = imp.getProperty("FHT")!=null?imp.getProperties():null; - } else { - File f = new File(path, names[n-1]); - String msg = f.exists()?"Error opening ":"File not found: "; - ip = new ByteProcessor(getWidth(), getHeight()); - ip.invert(); - label(ip, msg+names[n-1], Color.black); - depthThisImage = 8; - } - if (depthThisImage!=bitDepth) { - switch (bitDepth) { - case 8: ip=ip.convertToByte(true); break; - case 16: ip=ip.convertToShort(true); break; - case 24: ip=ip.convertToRGB(); break; - case 32: ip=ip.convertToFloat(); break; - } - } - if (ip.getWidth()!=getWidth() || ip.getHeight()!=getHeight()) { - ImageProcessor ip2 = ip.createProcessor(getWidth(), getHeight()); - ip2.insert(ip, 0, 0); - ip = ip2; - } - if (cTable!=null) - ip.setCalibrationTable(cTable); - ip.setSliceNumber(n); - return ip; - } - - /** Draw label for Help>Examples>JavaScript>Terabyte VirtualStack */ - private void label(ImageProcessor ip, String msg, Color color) { - int size = getHeight()/20; - if (size<9) size=9; - Font font = new Font("Helvetica", Font.PLAIN, size); - ip.setFont(font); - ip.setAntialiasedText(true); - ip.setColor(color); - ip.drawString(msg, size, size*2); - } - - /** Currently not implemented */ - public int saveChanges(int n) { - return -1; - } - - /** Returns the number of slices in this stack. */ - public int size() { - return getSize(); - } - - /** Returns the number of slices in this stack. Subclasses shold override this function. */ - public int getSize() { - return nSlices; - } - - /** Returns the label of the Nth image. */ - public String getSliceLabel(int n) { - if (isTranslatingIndices()) - n = translate(n); - if (labels==null) - return null; - String label = (n<=labels.length) ? labels[n-1] : null; //subclass may have grown stack without adding labels - if (names == null) - return label; - if (label==null) - return names[n-1]; - else { - if (label.startsWith("Label: ")) // slice label - return label.substring(7,label.length()); - else - return names[n-1]+"\n"+label; - } - } - - /** Returns null. */ - public Object[] getImageArray() { - return null; - } - - /** Sets the label of the specified slice, where {@literal 1<=n<=nSlices}. */ - public void setSliceLabel(String label, int n) { - if (n <= 0 || n > getSize()) - throw new IllegalArgumentException(outOfRange+n); - if (isTranslatingIndices()) - n = translate(n); - if (labels == null) - labels = new String[getSize()]; - expandArrays(getSize()); - labels[n-1] = label; - } - - /** Sets the array of slice labels. The array size must be the stack size or larger */ - protected void setSliceLabels(String[] labels) { - if (labels != null && labels.length < getSize()) - throw new IllegalArgumentException("Labels array too short: "+labels.length); - this.labels = labels; - } - - /** Always returns true. */ - public boolean isVirtual() { - return true; - } - - /** Does nothing. */ - public void trim() { - } - - /** Returns the path to the directory containing the images. */ - public String getDirectory() { - return IJ.addSeparator(path); - } - - /** Returns the file name of the specified slice, where {@literal 1<=n<=nslices}. */ - public String getFileName(int n) { - return names[n-1]; - } - - /** Sets the bit depth (8, 16, 24 or 32). */ - public void setBitDepth(int bitDepth) { - this.bitDepth = bitDepth; - } - - /** Returns the bit depth (8, 16, 24 or 32), or 0 if the bit depth is not known. */ - public int getBitDepth() { - return bitDepth; - } - - public ImageStack sortDicom(String[] strings, String[] info, int maxDigits) { - int n = size(); - String[] names2 = new String[n]; - for (int i=0; ihyperstack>stack>hyperstack to reshuffle) - indexes = indexes.clone(); - for (int i=0; i 0) { - ImagePlus imp = getFocusManagerActiveImage(); - if (imp != null) - return imp; - ImageWindow win = (ImageWindow) imageList.get(imageList.size() - 1); - return win.getImagePlus(); - } else - return Interpreter.getLastBatchModeImage(); - } - - private static ImagePlus getFocusManagerActiveImage() { - if (IJ.isMacro()) - return null; - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Window win = kfm.getActiveWindow(); - ImagePlus imp = null; - if (win != null && (win instanceof ImageWindow)) - imp = ((ImageWindow) win).getImagePlus(); - return imp; - } - - /** Returns the number of open image windows. */ - public static int getWindowCount() { - int count = imageList.size(); - return count; - } - - /** Returns the number of open images. */ - public static int getImageCount() { - int count = imageList.size(); - count += Interpreter.getBatchModeImageCount(); - if (count == 0 && getCurrentImage() != null) - count = 1; - return count; - } - - /** Returns the front most window or null. */ - public static Window getActiveWindow() { - return frontWindow; - } - - /** Returns the Window containing the active table, or null. - * @see ij.measure.ResultsTable#getActiveTable - */ - public static Window getActiveTable() { - return frontTable; - } - - - - /** Obsolete; replaced by getActiveWindow. */ - public static Frame getFrontWindow() { - return frontFrame; - } - - /** - * Returns a list of the IDs of open images. Returns null if no image windows - * are open. - */ - public synchronized static int[] getIDList() { - int nWindows = imageList.size(); - int[] batchModeImages = Interpreter.getBatchModeImageIDs(); - int nBatchImages = batchModeImages.length; - if ((nWindows + nBatchImages) == 0) - return null; - int[] list = new int[nWindows + nBatchImages]; - for (int i=0; i 0) - imageID = getNthImageID(imageID); - if (imageID == 0 || getImageCount() == 0) - return null; - ImagePlus imp2 = Interpreter.getBatchModeImage(imageID); - if (imp2 != null) - return imp2; - ImagePlus imp = null; - for (int i = 0; i < imageList.size(); i++) { - ImageWindow win = (ImageWindow) imageList.get(i); - imp2 = win.getImagePlus(); - if (imageID == imp2.getID()) { - imp = imp2; - break; - } - } - imp2 = getCurrentImage(); - if (imp == null && imp2 != null && imp2.getID() == imageID) - return imp2; - return imp; - } - - /** - * Returns the ID of the Nth open image. Returns zero if n<=0 or n greater than - * the number of open image windows. - */ - public synchronized static int getNthImageID(int n) { - if (n <= 0) - return 0; - if (Interpreter.isBatchMode()) { - int[] list = getIDList(); - if (n > list.length) - return 0; - else - return list[n - 1]; - } else { - if (n > imageList.size()) - return 0; - ImageWindow win = (ImageWindow) imageList.get(n - 1); - if (win != null) - return win.getImagePlus().getID(); - else - return 0; - } - } - - /** - * Returns the first image that has the specified title or null if it is not - * found. - */ - public synchronized static ImagePlus getImage(String title) { - int[] wList = getIDList(); - if (wList == null) - return null; - for (int i = 0; i < wList.length; i++) { - ImagePlus imp = getImage(wList[i]); - if (imp != null && imp.getTitle().equals(title)) - return imp; - } - return null; - } - - /** Adds the specified window to the Window menu. */ - public synchronized static void addWindow(Window win) { - if (win == null) - return; - else if (win instanceof ImageWindow) - addImageWindow((ImageWindow) win); - else { - /* Changed for Bio7! */ - Menus.insertWindowMenuItem(win); - nonImageList.add(win); - } - } - - /** Adds the specified Frame to the Window menu. */ - public static void addWindow(Frame win) { - addWindow((Window) win); - } - - private static void addImageWindow(ImageWindow win) { - ImagePlus imp = win.getImagePlus(); - if (imp == null) - return; - checkForDuplicateName(imp); - imageList.add(win); - Menus.addWindowMenuItem(imp); - setCurrentWindow(win); - } - - static void checkForDuplicateName(ImagePlus imp) { - if (checkForDuplicateName) { - String name = imp.getTitle(); - if (isDuplicateName(name)) - imp.setTitle(getUniqueName(name)); - } - checkForDuplicateName = false; - } - - static boolean isDuplicateName(String name) { - if (name==null) - return false; - int n = imageList.size(); - for (int i = 0; i < n; i++) { - ImageWindow win = (ImageWindow) imageList.get(i); - String name2 = win.getImagePlus().getTitle(); - if (name.equals(name2)) - return true; - } - return false; - } - - /* - static boolean isDuplicateBatchModeName(String name) { - int[] list = getIDList(); - for (int i=0; i= 0) { - Menus.removeWindowMenuItem(index); - nonImageList.removeElement(win); - } - if (win!=null && win==frontTable) - frontTable = null; - } - setWindow(null); - } - - /** Removes the specified Frame from the Window menu. */ - public static void removeWindow(Frame win) { - removeWindow((Window) win); - } - - private static void removeImageWindow(ImageWindow win) { - int index = imageList.indexOf(win); - if (index == -1) - return; // not on the window list - try { - synchronized(WindowManager.class) { - imageList.remove(win); - } - activations.remove(win); - if (imageList.size() > 1 && !Prefs.closingAll) { - ImageWindow win2 = activations.size() > 0 ? (ImageWindow) activations.get(activations.size() - 1) : null; - setCurrentWindow(win2); - } else - currentWindow = null; - setTempCurrentImage(null); // ??? - int nonImageCount = nonImageList.size(); - if (nonImageCount > 0) - nonImageCount++; - Menus.removeWindowMenuItem(nonImageCount + index); - Menus.updateMenus(); - Undo.reset(); - } catch (Exception e) { - } - } - - /** The specified Window becomes the front window. */ - public static void setWindow(Window win) { - /* Changed for Bio7? - Probably not necessary! */ - // System.out.println("setWindow(W): "+win); - frontWindow = win; - if (win instanceof Frame) - frontFrame = (Frame) win; - - - } - - /** - * The specified frame becomes the front window, the one returnd by - * getFrontWindow(). - */ - public static void setWindow(Frame win) { - /* Changed for Bio7? - Probably not necessary! */ - - frontWindow = win; - frontFrame = win; - if (win!=null && win instanceof TextWindow && !(win instanceof Editor) && !"Log".equals(((TextWindow)win).getTitle())) - frontTable = win; - - // System.out.println("Set window(F): "+(win!=null?win.getTitle():"null")); - } - - /** - * Closes all windows. Stops and returns false if an image or Editor "save - * changes" dialog is canceled. - */ - public synchronized static boolean closeAllWindows() { - Prefs.closingAll = true; - while (imageList.size() > 0) { - /* Changed for Bio7! */ - if (!((ImageWindow) imageList.get(0)).bio7TabClose(true)) { - Prefs.closingAll = false; - return false; - } - if (!quittingViaMacro()) - IJ.wait(100); - } - Prefs.closingAll = false; - JFrame[] nonImages = getNonImageWindows(); - for (int i = 0; i < nonImages.length; i++) { - Frame frame = nonImages[i]; - if (frame != null && frame instanceof Commands) - ((Commands) frame).close(); - else if (frame != null && (frame instanceof Editor)) { - ((Editor) frame).close(); - if (((Editor) frame).fileChanged()) - return false; - if (!quittingViaMacro()) - IJ.wait(100); - } - } - ImageJ ij = IJ.getInstance(); - if (ij != null && ij.quitting() && IJ.getApplet() == null) - return true; - for (int i = 0; i < nonImages.length; i++) { - Frame frame = nonImages[i]; - if ((frame instanceof PlugInFrame) && !(frame instanceof Editor)) - ((PlugInFrame) frame).close(); - else if (frame instanceof TextWindow) - ((TextWindow) frame).close(); - else { - // frame.setVisible(false); - frame.dispose(); - } - } - return true; - } - - private static boolean quittingViaMacro() { - ImageJ ij = IJ.getInstance(); - return ij != null && ij.quittingViaMacro(); - } - - /** Activates the next image window on the window list. */ - public static void putBehind() { - if (IJ.debugMode) - IJ.log("putBehind"); - if (imageList.size() < 1 || currentWindow == null) - return; - int index = imageList.indexOf(currentWindow); - ImageWindow win = null; - int count = 0; - do { - index--; - if (index < 0) - index = imageList.size() - 1; - win = (ImageWindow) imageList.get(index); - if (++count == imageList.size()) - return; - } while (win instanceof HistogramWindow || win instanceof PlotWindow); - if (win == null) - return; - ImagePlus imp = win.getImagePlus(); - if (imp != null) - IJ.selectWindow(imp.getID()); - } - - /** Returns the temporary current image for this thread, or null. */ - public static ImagePlus getTempCurrentImage() { - return (ImagePlus) tempImageTable.get(Thread.currentThread()); - } - - /** - * Returns the window (a Frame or a Dialog) with the specified title, or null if - * a window with that title is not found. - */ - public static Window getWindow(String title) { - for (int i = 0; i < nonImageList.size(); i++) { - Object win = nonImageList.get(i); - String winTitle = win instanceof Frame ? ((Frame) win).getTitle() : ((Dialog) win).getTitle(); - if (title.equals(winTitle)) - return (Window) win; - } - return getImageWindow(title); - } - - /** Obsolete; replaced by getWindow(). */ - public static Frame getFrame(String title) { - for (int i = 0; i < nonImageList.size(); i++) { - Object win = nonImageList.get(i); - String winTitle = win instanceof Frame ? ((Frame) win).getTitle() : null; - if (title.equals(winTitle)) - return (Frame) win; - } - Frame frame = getImageWindow(title); - if (frame == null) { - Window win = getWindow(title); - if (win != null) - frame = new Frame("Proxy"); - } - return frame; - } - - private static Frame getImageWindow(String title) { - int[] wList = getIDList(); - int len = wList != null ? wList.length : 0; - for (int i = 0; i < len; i++) { - ImagePlus imp = getImage(wList[i]); - if (imp != null) { - if (imp.getTitle().equals(title)) - return imp.getWindow(); - } - } - return null; - } - - /** Activates a window selected from the Window menu. */ - public synchronized static void activateWindow(String menuItemLabel, MenuItem item) { - for (int i = 0; i < nonImageList.size(); i++) { - Object win = nonImageList.get(i); - String title = win instanceof Frame ? ((Frame) win).getTitle() : ((Dialog) win).getTitle(); - if (menuItemLabel.equals(title)) { - if (win instanceof Frame) { - toFront((Frame) win); - /* Changed for Bio7! */ - // IJTabs.setActiveTab(menuItemLabel); - } else - ((Dialog) win).toFront(); - ((CheckboxMenuItem) item).setState(false); - if (IJ.recording() && !IJ.isMacro()) - Recorder.record("selectWindow", title); - return; - } - } - int lastSpace = menuItemLabel.lastIndexOf(' '); - if (lastSpace > 0) // remove image size (e.g., " 90K") - menuItemLabel = menuItemLabel.substring(0, lastSpace); - String idString = item.getActionCommand(); - int id = (int) Tools.parseDouble(idString, 0); - ImagePlus imp = WindowManager.getImage(id); - if (imp == null) - return; - ImageWindow win1 = imp.getWindow(); - if (win1 == null) - return; - setCurrentWindow(win1); - toFront(win1); - /* Changed for Bio7! */ - // IJTabs.setActiveTabWindow(win1); - int index = imageList.indexOf(win1); - int n = Menus.window.getItemCount(); - int start = Menus.WINDOW_MENU_ITEMS + Menus.windowMenuItems2; - for (int j = start; j < n; j++) { - MenuItem mi = Menus.window.getItem(j); - if (mi instanceof CheckboxMenuItem) - ((CheckboxMenuItem) mi).setState((j - start) == index); - } - } - - /** Repaints all open image windows. */ - public synchronized static void repaintImageWindows() { - int[] list = getIDList(); - if (list == null) - return; - for (int i = 0; i < list.length; i++) { - ImagePlus imp2 = getImage(list[i]); - if (imp2 != null) { - imp2.setTitle(imp2.getTitle()); // update "(G)" flag (global - // calibration) - ImageWindow win = imp2.getWindow(); - if (win != null) - win.repaint(); - } - } - } - - public static void showList() { - for (int i = 0; i < imageList.size(); i++) { - ImageWindow win = (ImageWindow) imageList.get(i); - ImagePlus imp = win.getImagePlus(); - IJ.log(i + " " + imp.getTitle() + (win == currentWindow ? "*" : "") + " " + imp.getID()); - } - for (int i = 0; i < activations.size(); i++) { - ImageWindow win = (ImageWindow) activations.get(i); - ImagePlus imp = win.getImagePlus(); - IJ.log(i + " " + imp.getTitle() + " " + imp.getID()); - } - if (imageList.size() == 0) - IJ.log("imageList is empty"); - if (activations.size() == 0) - IJ.log("activations list is empty"); - IJ.log(" "); - } - - public static void toFront(Frame frame) { - if (frame == null) - return; - if (frame.getState() == Frame.ICONIFIED) - frame.setState(Frame.NORMAL); - frame.toFront(); - } - - public static void toFront(Window window) { - if (window == null) - return; - if (window instanceof Frame && ((Frame) window).getState() == Frame.ICONIFIED) - ((Frame) window).setState(Frame.NORMAL); - window.toFront(); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/Arrow.java b/com.eco.bio7.image/src/ij/gui/Arrow.java deleted file mode 100644 index 4427a0903..000000000 --- a/com.eco.bio7.image/src/ij/gui/Arrow.java +++ /dev/null @@ -1,421 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import java.awt.*; -import java.awt.geom.*; - - -/** This is an Roi subclass for creating and displaying arrows. */ -public class Arrow extends Line { - public static final String STYLE_KEY = "arrow.style"; - public static final String WIDTH_KEY = "arrow.width"; - public static final String SIZE_KEY = "arrow.size"; - public static final String DOUBLE_HEADED_KEY = "arrow.double"; - public static final String OUTLINE_KEY = "arrow.outline"; - public static final int FILLED=0, NOTCHED=1, OPEN=2, HEADLESS=3, BAR=4; - public static final String[] styles = {"Filled", "Notched", "Open", "Headless", "Bar"}; - private static int defaultStyle = (int)Prefs.get(STYLE_KEY, FILLED); - private static float defaultWidth = (float)Prefs.get(WIDTH_KEY, 2); - private static double defaultHeadSize = (int)Prefs.get(SIZE_KEY, 10); // 0-30; - private static boolean defaultDoubleHeaded = Prefs.get(DOUBLE_HEADED_KEY, false); - private static boolean defaultOutline = Prefs.get(OUTLINE_KEY, false); - private int style; - private double headSize = 10; // 0-30 - private boolean doubleHeaded; - private boolean outline; - private float[] points = new float[2*5]; - private GeneralPath path = new GeneralPath(); - private static Stroke defaultStroke = new BasicStroke(); - double headShaftRatio; - - static { - if (defaultStyleHEADLESS) - defaultStyle = FILLED; - } - - public Arrow(double ox1, double oy1, double ox2, double oy2) { - super(ox1, oy1, ox2, oy2); - setStrokeWidth(2); - } - - public Arrow(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - setStrokeWidth(defaultWidth); - style = defaultStyle; - headSize = defaultHeadSize; - doubleHeaded = defaultDoubleHeaded; - outline = defaultOutline; - setStrokeColor(Toolbar.getForegroundColor()); - } - - /** Draws this arrow on the image. */ - public void draw(Graphics g) { - Shape shape2 = null; - if (doubleHeaded) { - flipEnds(); - shape2 = getShape(); - flipEnds(); - } - Shape shape = getShape(); - if (shape==null) - return; - Color color = strokeColor!=null? strokeColor:ROIColor; - if (fillColor!=null) color = fillColor; - g.setColor(color); - Graphics2D g2 = (Graphics2D)g; - setRenderingHint(g2); - AffineTransform at = g2.getDeviceConfiguration().getDefaultTransform(); - double mag = getMagnification(); - int xbase=0, ybase=0; - if (ic!=null) { - Rectangle r = ic.getSrcRect(); - xbase = r.x; ybase = r.y; - } - at.setTransform(mag, 0.0, 0.0, mag, (-xbase+0.5)*mag, (-ybase+0.5)*mag); //0.5: int coordinate at pixel center - if (outline) { - float lineWidth = (float)(getOutlineWidth()*mag); - g2.setStroke(new BasicStroke(lineWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); - g2.draw(at.createTransformedShape(shape)); - if (doubleHeaded) g2.draw(at.createTransformedShape(shape2)); - g2.setStroke(defaultStroke); - } else { - g2.fill(at.createTransformedShape(shape)); - if (doubleHeaded) g2.fill(at.createTransformedShape(shape2)); - } - if (!overlay) { - handleColor=Color.white; - drawHandle(g, screenXD(x1d), screenYD(y1d)); - drawHandle(g, screenXD(x2d), screenYD(y2d)); - drawHandle(g, screenXD(x1d+(x2d-x1d)/2.0), screenYD(y1d+(y2d-y1d)/2.0)); - } - if (state!=NORMAL && imp!=null && imp.getRoi()!=null) - showStatus(); - if (updateFullWindow) - {updateFullWindow = false; imp.draw();} - } - - private void flipEnds() { - double tmp = x1R; - x1R=x2R; - x2R=tmp; - tmp=y1R; - y1R=y2R; - y2R=tmp; - } - - private Shape getPath() { - path.reset(); - path = new GeneralPath(); - calculatePoints(); - float tailx = points[0]; - float taily = points[1]; - float headbackx = points[2*1]; - float headbacky = points[2*1+1]; - float headtipx = points[2*3]; - float headtipy = points[2*3+1]; - if (outline) { - double dx = headtipx - tailx; - double dy = headtipy - taily; - double shaftLength = Math.sqrt(dx*dx+dy*dy); - dx = headtipx - headbackx; - dy = headtipy- headbacky; - double headLength = Math.sqrt(dx*dx+dy*dy); - headShaftRatio = headLength/shaftLength; - if (headShaftRatio>1.0) - headShaftRatio = 1.0; - //IJ.log(headShaftRatio+" "+(int)shaftLength+" "+(int)headLength+" "+(int)tailx+" "+(int)taily+" "+(int)headtipx+" "+(int)headtipy); - } - path.moveTo(tailx, taily); // tail - path.lineTo(headbackx, headbacky); // head back - path.moveTo(headbackx, headbacky); // head back - if (style==OPEN) - path.moveTo(points[2 * 2], points[2 * 2 + 1]); - else - path.lineTo(points[2 * 2], points[2 * 2 + 1]); // left point - path.lineTo(headtipx, headtipy); // head tip - path.lineTo(points[2 * 4], points[2 * 4 + 1]); // right point - path.lineTo(headbackx, headbacky); // back to the head back - return path; - } - - /** Based on the method with the same name in Fiji's Arrow plugin, - written by Jean-Yves Tinevez and Johannes Schindelin. */ - private void calculatePoints() { - double tip = 0.0; - double base; - double shaftWidth = getStrokeWidth(); - double length = 8+10*shaftWidth*0.5; - length = length*(headSize/10.0); - length -= shaftWidth*1.42; - if (style==NOTCHED) length*=0.74; - if (style==OPEN) length*=1.32; - if (length<0.0 || style==HEADLESS) length=0.0; - double x = getXBase(); - double y = getYBase(); - x1d=x+x1R; y1d=y+y1R; x2d=x+x2R; y2d=y+y2R; - x1=(int)x1d; y1=(int)y1d; x2=(int)x2d; y2=(int)y2d; - double dx=x2d-x1d, dy=y2d-y1d; - double arrowLength = Math.sqrt(dx*dx+dy*dy); - dx=dx/arrowLength; dy=dy/arrowLength; - if (doubleHeaded && style!=HEADLESS) { - points[0] = (float)(x1d+dx*shaftWidth*2.0); - points[1] = (float)(y1d+dy*shaftWidth*2.0); - } else { - points[0] = (float)x1d; - points[1] = (float)y1d; - } - if (length>0) { - double factor = style==OPEN?1.3:1.42; - points[2*3] = (float)(x2d-dx*shaftWidth*factor); - points[2*3+1] = (float)(y2d-dy*shaftWidth*factor); - if (style==BAR) { - points[2*3] = (float)(x2d-dx*shaftWidth*0.5); - points[2*3+1] = (float)(y2d-dy*shaftWidth*0.5); - } - } else { - points[2*3] = (float)x2d; - points[2*3+1] = (float)y2d; - } - final double alpha = Math.atan2(points[2*3+1]-points[1], points[2*3]-points[0]); - double SL = 0.0; - switch (style) { - case FILLED: case HEADLESS: - tip = Math.toRadians(20.0); - base = Math.toRadians(90.0); - points[1*2] = (float) (points[2*3] - length*Math.cos(alpha)); - points[1*2+1] = (float) (points[2*3+1] - length*Math.sin(alpha)); - SL = length*Math.sin(base)/Math.sin(base+tip);; - break; - case NOTCHED: - tip = Math.toRadians(20); - base = Math.toRadians(120); - points[1*2] = (float) (points[2*3] - length*Math.cos(alpha)); - points[1*2+1] = (float) (points[2*3+1] - length*Math.sin(alpha)); - SL = length*Math.sin(base)/Math.sin(base+tip);; - break; - case OPEN: - tip = Math.toRadians(25); //30 - points[1*2] = points[2*3]; - points[1*2+1] = points[2*3+1]; - SL = length; - break; - case BAR: - tip = Math.toRadians(90); //30 - points[1*2] = points[2*3]; - points[1*2+1] = points[2*3+1]; - SL = length; - updateFullWindow = true; - break; - } - // P2 = P3 - SL*alpha+tip - points[2*2] = (float) (points[2*3] - SL*Math.cos(alpha+tip)); - points[2*2+1] = (float) (points[2*3+1] - SL*Math.sin(alpha+tip)); - // P4 = P3 - SL*alpha-tip - points[2*4] = (float) (points[2*3] - SL*Math.cos(alpha-tip)); - points[2*4+1] = (float) (points[2*3+1] - SL*Math.sin(alpha-tip)); - } - - private Shape getShape() { - try { - Shape arrow = getPath(); - BasicStroke stroke = new BasicStroke((float)getStrokeWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); - Shape outlineShape = stroke.createStrokedShape(arrow); - Area a1 = new Area(arrow); - Area a2 = new Area(outlineShape); - a1.add(a2); - return a1; - } catch(Exception e) {}; - return null; - } - - private ShapeRoi getShapeRoi() { - try { - Shape arrow = getPath(); - BasicStroke stroke = new BasicStroke(getStrokeWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); - ShapeRoi sroi = new ShapeRoi(arrow); - Shape outlineShape = stroke.createStrokedShape(arrow); - sroi.or(new ShapeRoi(outlineShape)); - return sroi; - } catch(Exception e) {}; - return null; - } - - public ImageProcessor getMask() { - Roi roi = getShapeRoi(); - if ((width==0 && height==0) || roi==null) - return null; - else - return roi.getMask(); - } - - private double getOutlineWidth() { - double width = getStrokeWidth()/8.0; - double head = headSize/7.0; - double lineWidth = width + head + headShaftRatio; - if (lineWidth<1.0) lineWidth = 1.0; - //if (width<1) width=1; - //if (head<1) head=1; - //IJ.log(getStrokeWidth()+" "+IJ.d2s(width,2)+" "+IJ.d2s(head,2)+" "+IJ.d2s(headShaftRatio,2)+" "+IJ.d2s(lineWidth,2)+" "+IJ.d2s(width*head,2)); - return lineWidth; - } - - public void drawPixels(ImageProcessor ip) { - ShapeRoi shapeRoi = getShapeRoi(); - if (shapeRoi==null) - return; - ShapeRoi shapeRoi2 = null; - if (doubleHeaded) { - flipEnds(); - shapeRoi2 = getShapeRoi(); - flipEnds(); - } - if (outline) { - int lineWidth = ip.getLineWidth(); - ip.setLineWidth((int)Math.round(getOutlineWidth())); - shapeRoi.drawPixels(ip); - if (doubleHeaded) shapeRoi2.drawPixels(ip); - ip.setLineWidth(lineWidth); - } else { - ip.fill(shapeRoi); - if (doubleHeaded) ip.fill(shapeRoi2); - } - } - - public boolean contains(int x, int y) { - Roi roi = getShapeRoi(); - return roi!=null?roi.contains(x,y):false; - } - - /** Return the bounding rectangle of this arrow. */ - public Rectangle getBounds() { - Roi roi = getShapeRoi(); - if (roi!=null) - return roi.getBounds(); - else - return super.getBounds(); - } - - protected void handleMouseDown(int sx, int sy) { - super.handleMouseDown(sx, sy); - startxd = ic!=null?ic.offScreenXD(sx):sx; - startyd = ic!=null?ic.offScreenYD(sy):sy; - } - - protected int clipRectMargin() { - double mag = getMagnification(); - double arrowWidth = getStrokeWidth(); - double size = 8+10*arrowWidth*mag*0.5; - return (int)Math.max(size*2.0, headSize); - } - - public boolean isDrawingTool() { - return true; - } - - public static void setDefaultWidth(double width) { - defaultWidth = (float)width; - } - - public static double getDefaultWidth() { - return defaultWidth; - } - - public void setStyle(int style) { - this.style = style; - } - - /* Set the style, where 'style' is "filled", "notched", "open", "headless" or "bar", - plus optionial modifiers of "outline", "double", "small", "medium" and "large". */ - public void setStyle(String style) { - style = style.toLowerCase(); - int newStyle = Arrow.FILLED; - if (style.contains("notched")) - newStyle = Arrow.NOTCHED; - else if (style.contains("open")) - newStyle = Arrow.OPEN; - else if (style.contains("headless")) - newStyle = Arrow.HEADLESS; - else if (style.contains("bar")) - newStyle = Arrow.BAR; - setStyle(newStyle); - setOutline(style.contains("outline")); - setDoubleHeaded(style.contains("double")); - if (style.contains("small")) - setHeadSize(5); - else if (style.contains("large")) - setHeadSize(15); - } - - public int getStyle() { - return style; - } - - public static void setDefaultStyle(int style) { - defaultStyle = style; - } - - public static int getDefaultStyle() { - return defaultStyle; - } - - public void setHeadSize(double headSize) { - this.headSize = headSize; - } - - public double getHeadSize() { - return headSize; - } - - public static void setDefaultHeadSize(double size) { - defaultHeadSize = size; - } - - public static double getDefaultHeadSize() { - return defaultHeadSize; - } - - public void setDoubleHeaded(boolean b) { - doubleHeaded = b; - } - - public boolean getDoubleHeaded() { - return doubleHeaded; - } - - public static void setDefaultDoubleHeaded(boolean b) { - defaultDoubleHeaded = b; - } - - public static boolean getDefaultDoubleHeaded() { - return defaultDoubleHeaded; - } - - public void setOutline(boolean b) { - outline = b; - } - - public boolean getOutline() { - return outline; - } - - public static void setDefaultOutline(boolean b) { - defaultOutline = b; - } - - public static boolean getDefaultOutline() { - return defaultOutline; - } - - @Override - public void copyAttributes(Roi roi2) { - super.copyAttributes(roi2); - if (roi2 instanceof Arrow) { - Arrow a2 = (Arrow)roi2; - this.style = a2.getStyle(); - this.headSize = a2.getHeadSize(); - this.doubleHeaded = a2.getDoubleHeaded(); - this.outline = a2.getOutline(); - } - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ColorChooser.java b/com.eco.bio7.image/src/ij/gui/ColorChooser.java deleted file mode 100644 index eb2c3ad47..000000000 --- a/com.eco.bio7.image/src/ij/gui/ColorChooser.java +++ /dev/null @@ -1,121 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.util.*; -import ij.plugin.Colors; -import java.awt.*; -import java.util.Vector; -import java.awt.event.*; - - - /** Displays a dialog that allows the user to select a color using three sliders. */ -public class ColorChooser implements TextListener, AdjustmentListener { - Vector colors, sliders; - ColorPanel panel; - Color initialColor; - int red, green, blue; - boolean useHSB; - String title; - Frame frame; - double scale = Prefs.getGuiScale(); - - /** Constructs a ColorChooser using the specified title and initial color. */ - public ColorChooser(String title, Color initialColor, boolean useHSB) { - this(title, initialColor, useHSB, null); - } - - public ColorChooser(String title, Color initialColor, boolean useHSB, Frame frame) { - this.title = title; - if (initialColor==null) initialColor = Color.black; - this.initialColor = initialColor; - red = initialColor.getRed(); - green = initialColor.getGreen(); - blue = initialColor.getBlue(); - this.useHSB = useHSB; - this.frame = frame; - } - - /** Displays a color selection dialog and returns the color selected by the user. */ - public Color getColor() { - GenericDialog gd = frame!=null?new GenericDialog(title, frame):new GenericDialog(title); - gd.addSlider("Red:", 0, 255, red); - gd.addSlider("Green:", 0, 255, green); - gd.addSlider("Blue:", 0, 255, blue); - panel = new ColorPanel(initialColor, scale); - gd.addPanel(panel, GridBagConstraints.CENTER, new Insets(10, 0, 0, 0)); - colors = gd.getNumericFields(); - for (int i=0; i255) red=255; - if (green<0) green=0; if (green>255) green=255; - if (blue<0) blue=0; if (blue>255) blue=255; - panel.setColor(new Color(red, green, blue)); - panel.repaint(); - } - - public synchronized void adjustmentValueChanged(AdjustmentEvent e) { - Object source = e.getSource(); - for (int i=0; ie is null if the - * dialogItemChanged method is called after the user has pressed the - * OK button or if the GenericDialog has read its parameters from a - * macro. - * @param gd A reference to the GenericDialog. - * @return Should be true if the dialog input is valid. False disables the - * OK button and preview (if any). - */ - boolean dialogItemChanged(GenericDialog gd, AWTEvent e); -} diff --git a/com.eco.bio7.image/src/ij/gui/EllipseRoi.java b/com.eco.bio7.image/src/ij/gui/EllipseRoi.java deleted file mode 100644 index c7dc16823..000000000 --- a/com.eco.bio7.image/src/ij/gui/EllipseRoi.java +++ /dev/null @@ -1,270 +0,0 @@ -package ij.gui; -import java.awt.*; -import java.awt.image.*; -import java.awt.event.*; -import ij.*; -import ij.plugin.frame.Recorder; -import ij.process.FloatPolygon; -import ij.measure.Calibration; - -/** This class implements the ellipse selection tool. */ -public class EllipseRoi extends PolygonRoi { - private static final int vertices = 72; - private static double defaultRatio = 0.6; - private double xstart, ystart; - private double aspectRatio = defaultRatio; - private int[] handle = {0, vertices/4, vertices/2, vertices/2+vertices/4}; - - public EllipseRoi(double x1, double y1, double x2, double y2, double aspectRatio) { - super(new float[vertices], new float[vertices], vertices, FREEROI); - if (aspectRatio<0.0) aspectRatio = 0.0; - if (aspectRatio>1.0) aspectRatio = 1.0; - this.aspectRatio = aspectRatio; - makeEllipse(x1, y1, x2, y2); - state = NORMAL; - bounds = null; - } - - public EllipseRoi(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - type = FREEROI; - xstart = offScreenXD(sx); - ystart = offScreenYD(sy); - setDrawOffset(false); - bounds = null; - } - - public void draw(Graphics g) { - super.draw(g); - if (!overlay) { - for (int i=0; i1.0) aspectRatio = 1.0; - defaultRatio = aspectRatio; - } - - public int isHandle(int sx, int sy) { - int size = getHandleSize()+5; - int halfSize = size/2; - int index = -1; - for (int i=0; i=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) { - index = i; - break; - } - } - return index; - } - - /** Returns the perimeter of this ellipse. */ - public double getLength() { - double length = 0.0; - double dx, dy; - double w2=1.0, h2=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - w2 = cal.pixelWidth*cal.pixelWidth; - h2 = cal.pixelHeight*cal.pixelHeight; - } - for (int i=0; i<(nPoints-1); i++) { - dx = xpf[i+1]-xpf[i]; - dy = ypf[i+1]-ypf[i]; - length += Math.sqrt(dx*dx*w2+dy*dy*h2); - } - dx = xpf[0]-xpf[nPoints-1]; - dy = ypf[0]-ypf[nPoints-1]; - length += Math.sqrt(dx*dx*w2+dy*dy*h2); - return length; - } - - /** Returns x1, y1, x2, y2 and aspectRatio as a 5 element array. */ - public double[] getParams() { - double[] params = new double[5]; - params[0] = xpf[handle[2]]+x; - params[1] = ypf[handle[2]]+y; - params[2] = xpf[handle[0]]+x; - params[3] = ypf[handle[0]]+y; - params[4] = aspectRatio; - return params; - } - - public double[] getFeretValues() { - double a[] = super.getFeretValues(); - double pw=1.0, ph=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - pw = cal.pixelWidth; - ph = cal.pixelHeight; - } - if (pw != ph) //the following calculation holds only for pixel aspect ratio == 1 (otherwise different axes in distorted ellipse) - return a; - double[] p = getParams(); - double dx = p[2] - p[0]; //this is always major axis; aspect ratio p[4] is limited to <= 1 - double dy = p[3] - p[1]; - double major = Math.sqrt(dx*dx + dy*dy); - double minor = major*p[4]; - a[0] = major*pw; //Feret from convex hull should be accurate anyhow - a[2] = minor*pw; //here our own calculation is better - System.arraycopy(p, 0, a, 8, 4); //MaxFeret endpoints - double xCenter = 0.5*(p[2] + p[0]); - double yCenter = 0.5*(p[3] + p[1]); - double semiMinorX = dy * 0.5 * p[4]; - double semiMinorY = dx * (-0.5) * p[4]; - a[12] = xCenter + semiMinorX; a[14] = xCenter - semiMinorX; - a[13] = yCenter + semiMinorY; a[15] = yCenter - semiMinorY; - return a; - } - - /** Always returns true. */ - public boolean subPixelResolution() { - return true; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/FreehandRoi.java b/com.eco.bio7.image/src/ij/gui/FreehandRoi.java deleted file mode 100644 index 7cf4c463c..000000000 --- a/com.eco.bio7.image/src/ij/gui/FreehandRoi.java +++ /dev/null @@ -1,98 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.image.*; -import ij.*; - -/** Freehand region of interest or freehand line of interest*/ -public class FreehandRoi extends PolygonRoi { - - public FreehandRoi(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - if (Toolbar.getToolId()==Toolbar.FREEROI) - type = FREEROI; - else - type = FREELINE; - if (nPoints==2) nPoints--; - } - - protected void grow(int sx, int sy) { - if (subPixelResolution() && xpf!=null) { - growFloat(sx, sy); - return; - } - int ox = offScreenX(sx); - int oy = offScreenY(sy); - if (ox<0) ox = 0; - if (oy<0) oy = 0; - if (ox>xMax) ox = xMax; - if (oy>yMax) oy = yMax; - if (ox!=xp[nPoints-1]+x || oy!=yp[nPoints-1]+y) { - xp[nPoints] = ox-x; - yp[nPoints] = oy-y; - nPoints++; - if (IJ.altKeyDown()) - wipeBack(); - if (nPoints==xp.length) - enlargeArrays(); - drawLine(); - } - } - - private void growFloat(int sx, int sy) { - double ox = offScreenXD(sx); - double oy = offScreenYD(sy); - if (ox<0.0) ox = 0.0; - if (oy<0.0) oy = 0.0; - if (ox>xMax) ox = xMax; - if (oy>yMax) oy = yMax; - double xbase = getXBase(); - double ybase = getYBase(); - if (ox!=xpf[nPoints-1]+xbase || oy!=ypf[nPoints-1]+ybase) { - xpf[nPoints] = (float)(ox-xbase); - ypf[nPoints] = (float)(oy-ybase); - nPoints++; - if (nPoints==xpf.length) - enlargeArrays(); - drawLine(); - } - } - - void drawLine() { - int x1, y1, x2, y2; - if (xpf!=null) { - x1 = (int)Math.round(xpf[nPoints-2]+x); - y1 = (int)Math.round(ypf[nPoints-2]+y); - x2 = (int)Math.round(xpf[nPoints-1]+x); - y2 = (int)Math.round(ypf[nPoints-1]+y); - } else { - x1 = xp[nPoints-2]+x; - y1 = yp[nPoints-2]+y; - x2 = xp[nPoints-1]+x; - y2 = yp[nPoints-1]+y; - } - int xmin = Math.min(x1, x2); - int xmax = Math.max(x1, x2); - int ymin = Math.min(y1, y2); - int ymax = Math.max(y1, y2); - int margin = 4; - if (lineWidth>margin && isLine()) - margin = lineWidth; - if (ic!=null) { - double mag = ic.getMagnification(); - if (mag<1.0) margin = (int)(margin/mag); - } - if (IJ.altKeyDown()) - margin += 20; // for wipeBack - imp.draw(xmin-margin, ymin-margin, (xmax-xmin)+margin*2, (ymax-ymin)+margin*2); - } - - protected void handleMouseUp(int screenX, int screenY) { - if (state==CONSTRUCTING) { - addOffset(); - finishPolygon(); - } - state = NORMAL; - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/GUI.java b/com.eco.bio7.image/src/ij/gui/GUI.java deleted file mode 100644 index d687725ba..000000000 --- a/com.eco.bio7.image/src/ij/gui/GUI.java +++ /dev/null @@ -1,323 +0,0 @@ -package ij.gui; - -import ij.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JScrollBar; -import javax.swing.JTable; -import javax.swing.UIManager; - -/** This class consists of static GUI utility methods. */ -public class GUI { - private static final Font DEFAULT_FONT = ImageJ.SansSerif12; - private static Color lightGray = new Color(240, 240, 240); - private static boolean isWindows8; - private static Color scrollbarBackground = new Color(245, 245, 245); - - static { - if (IJ.isWindows()) { - String osname = System.getProperty("os.name"); - isWindows8 = osname.contains("unknown") || osname.contains("8"); - } - } - - /** - * Positions the specified window in the center of the screen that contains - * target. - */ - public static void center(Window win, Component target) { - if (win == null) - return; - Rectangle bounds = getMaxWindowBounds(target); - Dimension window = win.getSize(); - if (window.width == 0) - return; - int left = bounds.x + Math.max(0, (bounds.width - window.width) / 2); - int top = bounds.y + Math.max(0, (bounds.height - window.height) / 4); - win.setLocation(left, top); - } - - /** - * Positions the specified window in the center of the screen containing the - * "ImageJ" window. - */ - public static void centerOnImageJScreen(Window win) { - center(win, IJ.getInstance()); - } - - public static void center(Window win) { - center(win, win); - } - - private static java.util.List getScreenConfigs() { - java.util.ArrayList configs = new java.util.ArrayList(); - for (GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) { - configs.add(device.getDefaultConfiguration()); - } - return configs; - } - - /** - * Get maximum bounds for the screen that contains a given point. - * - * @param point Coordinates of point. - * @param accountForInsets Deduct the space taken up by menu and status bars, - * etc. (after point is found to be inside bonds) - * @return Rectangle of bounds or null if point not inside of any - * screen. - */ - public static Rectangle getScreenBounds(Point point, boolean accountForInsets) { - if (GraphicsEnvironment.isHeadless()) - return new Rectangle(0, 0, 0, 0); - for (GraphicsConfiguration config : getScreenConfigs()) { - Rectangle bounds = config.getBounds(); - if (bounds != null && bounds.contains(point)) { - Insets insets = accountForInsets ? Toolkit.getDefaultToolkit().getScreenInsets(config) : null; - return shrinkByInsets(bounds, insets); - } - } - return null; - } - - /** - * Get maximum bounds for the screen that contains a given component. - * - * @param component An AWT component located on the desired screen. If - * null is provided, the default screen is - * used. - * @param accountForInsets Deduct the space taken up by menu and status bars, - * etc. - * @return Rectangle of bounds. - */ - public static Rectangle getScreenBounds(Component component, boolean accountForInsets) { - if (GraphicsEnvironment.isHeadless()) - return new Rectangle(0, 0, 0, 0); - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsConfiguration gc = component == null ? ge.getDefaultScreenDevice().getDefaultConfiguration() - : component.getGraphicsConfiguration(); - Insets insets = accountForInsets ? Toolkit.getDefaultToolkit().getScreenInsets(gc) : null; - return shrinkByInsets(gc.getBounds(), insets); - } - - public static Rectangle getScreenBounds(Point point) { - return getScreenBounds(point, false); - } - - public static Rectangle getScreenBounds(Component component) { - return getScreenBounds(component, false); - } - - public static Rectangle getScreenBounds() { - return getScreenBounds((Component) null); - } - - public static Rectangle getMaxWindowBounds(Point point) { - return getScreenBounds(point, true); - } - - public static Rectangle getMaxWindowBounds(Component component) { - return getScreenBounds(component, true); - } - - public static Rectangle getMaxWindowBounds() { - return getMaxWindowBounds((Component) null); - } - - private static Rectangle shrinkByInsets(Rectangle bounds, Insets insets) { - Rectangle shrunk = new Rectangle(bounds); - if (insets == null) - return shrunk; - shrunk.x += insets.left; - shrunk.y += insets.top; - shrunk.width -= insets.left + insets.right; - shrunk.height -= insets.top + insets.bottom; - return shrunk; - } - - public static Rectangle getZeroBasedMaxBounds() { - for (GraphicsConfiguration config : getScreenConfigs()) { - Rectangle bounds = config.getBounds(); - if (bounds != null && bounds.x == 0 && bounds.y == 0) - return bounds; - } - return null; - } - - public static Rectangle getUnionOfBounds() { - Rectangle unionOfBounds = new Rectangle(); - for (GraphicsConfiguration config : getScreenConfigs()) { - unionOfBounds = unionOfBounds.union(config.getBounds()); - } - return unionOfBounds; - } - - static private Frame frame; - - /** Obsolete */ - public static Image createBlankImage(int width, int height) { - if (width == 0 || height == 0) - throw new IllegalArgumentException(""); - if (frame == null) { - frame = new Frame(); - frame.pack(); - frame.setBackground(Color.white); - } - Image img = frame.createImage(width, height); - return img; - } - - /** Lightens overly dark scrollbar background on Windows 8. */ - public static void fix(Scrollbar sb) { - } - - public static boolean showCompositeAdvisory(ImagePlus imp, String title) { - if (imp == null || imp.getCompositeMode() != IJ.COMPOSITE || imp.getNChannels() == 1 || IJ.macroRunning()) - return true; - String msg = "Channel " + imp.getC() + " of this color composite image will be processed."; - GenericDialog gd = new GenericDialog(title); - gd.addMessage(msg); - gd.showDialog(); - return !gd.wasCanceled(); - } - - /** - * Scales an AWT component according to {@link Prefs#getGuiScale()}. - * - * @param component the AWT component to be scaled. If a container, scaling is - * applied to all its child components - */ - public static void scale(final Component component) { - final float scale = (float) Prefs.getGuiScale(); - if (scale == 1f) - return; - if (component instanceof Container) - scaleComponents((Container) component, scale); - else - scaleComponent(component, scale); - } - - private static void scaleComponents(final Container container, final float scale) { - for (final Component child : container.getComponents()) { - if (child instanceof Container) - scaleComponents((Container) child, scale); - else - scaleComponent(child, scale); - } - } - - private static void scaleComponent(final Component component, final float scale) { - Font font = component.getFont(); - if (font == null) - font = DEFAULT_FONT; - font = font.deriveFont(scale * font.getSize()); - component.setFont(font); - } - - public static void scalePopupMenu(final PopupMenu popup) { - //System.out.println("scalePopupMenu1: "+popup); - if (Menus.getFontSize()!=0) { - popup.setFont(Menus.getFont(false)); - //System.out.println("scalePopupMenu2: "+popup.getFont()); - return; - } - final float scale = (float)Prefs.getGuiScale(); - if (scale == 1f) - return; - Font font=popup.getFont(); - if (font==null) - font = new Font("SansSerif", Font.PLAIN, (int)(scale*13)); - else - font = font.deriveFont(scale*font.getSize()); - popup.setFont(font); - //System.out.println("scalePopupMenu3: "+popup.getFont()); - } - - /** - * Tries to detect if a Swing component is unscaled and scales it it according - * to {@link #getGuiScale()}. - * - * This is mainly relevant to linux: Swing components scale automatically on - * most platforms, specially since Java 8. However there are still exceptions to - * this on linux: e.g., In Ubuntu, Swing components do scale, but only under the - * GTK L&F. (On the other hand AWT components do not scale at all on - * hiDPI screens on linux). - * - * - * This method tries to avoid exaggerated font sizes by detecting if a component - * has been already scaled by the UIManager, applying only - * {@link #getGuiScale()} to the component's font if not. - * - * - * @param component the component to be scaled - * @return true, if component's font was resized - */ - public static boolean scale(final JComponent component) { - final double guiScale = Prefs.getGuiScale(); - if (guiScale == 1d) - return false; - Font font = component.getFont(); - if (font == null && component instanceof JList) - font = UIManager.getFont("List.font"); - else if (font == null && component instanceof JTable) - font = UIManager.getFont("Table.font"); - else if (font == null) - font = UIManager.getFont("Label.font"); - if (font.getSize() > DEFAULT_FONT.getSize()) - return false; - if (component instanceof JTable) - ((JTable) component).setRowHeight((int) (((JTable) component).getRowHeight() * guiScale * 0.9)); - else if (component instanceof JList) - ((JList>) component) - .setFixedCellHeight((int) (((JList>) component).getFixedCellHeight() * guiScale * 0.9)); - component.setFont(font.deriveFont((float) guiScale * font.getSize())); - return true; - } - - /** - * Works around an OpenJDK bug on Windows that causes the scrollbar thumb color - * and background color to be almost identical. - */ - public static final void fixScrollbar(Scrollbar sb) { - if (IJ.isWindows()) - sb.setBackground(scrollbarBackground); - } - - /*Changed for Bio7!*/ - /** - * Works around an OpenJDK bug on Windows that causes the scrollbar thumb color - * and background color to be almost identical. - */ - public static final void fixScrollbar(JScrollBar sb) { - if (IJ.isWindows()) - sb.setBackground(scrollbarBackground); - } - - /** - * Returns a new NonBlockingGenericDialog with the given title, except when Java - * is running in headless mode, in which case a GenericDialog is be returned. - */ - public static GenericDialog newNonBlockingDialog(String title) { - if (GraphicsEnvironment.isHeadless()) - return new GenericDialog(title); - else - return new NonBlockingGenericDialog(title); - } - - /** Returns a new NonBlockingGenericDialog with the given title - * if Prefs.nonBlockingFilterDialogs is 'true' and 'imp' is - * displayed, otherwise returns a GenericDialog. - * - * @param title Dialog title - * @param imp The image associated with this dialog - */ - public static GenericDialog newNonBlockingDialog(String title, ImagePlus imp) { - if (Prefs.nonBlockingFilterDialogs && imp != null && imp.getWindow() != null) { - NonBlockingGenericDialog gd = new NonBlockingGenericDialog(title); - gd.imp = imp; - return gd; - } else - return new GenericDialog(title); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/GenericDialog.java b/com.eco.bio7.image/src/ij/gui/GenericDialog.java deleted file mode 100644 index 82fb76716..000000000 --- a/com.eco.bio7.image/src/ij/gui/GenericDialog.java +++ /dev/null @@ -1,2345 +0,0 @@ -package ij.gui; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JPanel; -import com.eco.bio7.image.Util; -import ij.*; -import ij.plugin.frame.Recorder; -import ij.plugin.ScreenGrabber; -import ij.plugin.filter.PlugInFilter; -import ij.plugin.filter.PlugInFilterRunner; -import ij.util.Tools; -import ij.macro.*; -import ij.io.OpenDialog; -import java.awt.*; -import java.io.*; -import java.awt.event.*; -import java.util.*; -import java.awt.datatransfer.*; -import java.awt.dnd.*; - -/** - * This class is a customizable modal dialog box. Here is an example - * GenericDialog with one string field and two numeric fields: - * - * - * public class Generic_Dialog_Example implements PlugIn { - * static String title = "Example"; - * static int width = 512, height = 512; - * - * public void run(String arg) { - * GenericDialog gd = new GenericDialog("New Image"); - * gd.addStringField("Title: ", title); - * gd.addNumericField("Width: ", width, 0); - * gd.addNumericField("Height: ", height, 0); - * gd.showDialog(); - * if (gd.wasCanceled()) - * return; - * title = gd.getNextString(); - * width = (int) gd.getNextNumber(); - * height = (int) gd.getNextNumber(); - * IJ.newImage(title, "8-bit", width, height, 1); - * } - * } - * - * - * To work with macros, the first word of each component label must be unique. - * If this is not the case, add underscores, which will be converted to spaces - * when the dialog is displayed. For example, change the checkbox labels "Show - * Quality" and "Show Residue" to "Show_Quality" and "Show_Residue". - */ -public class GenericDialog extends Dialog implements ActionListener, TextListener, FocusListener, ItemListener, KeyListener, AdjustmentListener, WindowListener, ComponentListener { - - protected Vector numberField, stringField, checkbox, choice, slider, radioButtonGroups; - protected TextArea textArea1, textArea2; - protected Vector defaultValues, defaultText, defaultStrings, defaultChoiceIndexes; - protected Component theLabel; - private Button okay; - private Button cancel; - private Button no, help; - private String helpLabel = "Help"; - private boolean wasCanceled, wasOKed; - private int nfIndex, sfIndex, cbIndex, choiceIndex, textAreaIndex, radioButtonIndex; - private GridBagConstraints c; - private boolean firstNumericField = true; - private boolean firstSlider = true; - private boolean invalidNumber; - private String errorMessage; - private Hashtable labels; - private boolean macro; - private String macroOptions; - private boolean addToSameRow; - private boolean addToSameRowCalled; - private int topInset, leftInset, bottomInset; - private boolean customInsets; - private Vector sliderIndexes, sliderScales, sliderDigits; - private Checkbox previewCheckbox; // the "Preview" Checkbox, if any - private Vector dialogListeners; // the Objects to notify on user input - private PlugInFilterRunner pfr; // the PlugInFilterRunner for automatic preview - private String previewLabel = " Preview"; - private final static String previewRunning = "wait..."; - private boolean recorderOn; // whether recording is allowed (after the dialog is closed) - private char echoChar; - private boolean hideCancelButton; - private boolean centerDialog = true; - private String helpURL; - private boolean smartRecording; - private Vector imagePanels; - protected static GenericDialog instance; - private boolean firstPaint = true; - private boolean fontSizeSet; - private boolean showDialogCalled; - private boolean optionsRecorded; // have dialogListeners been called to record options? - private Label lastLabelAdded; - private int[] windowIDs; - private String[] windowTitles; - - /** - * Creates a new GenericDialog with the specified title. Uses the current image - * image window as the parent frame or the ImageJ frame if no image windows are - * open. Dialog parameters are recorded by ImageJ's command recorder but this - * requires that the first word of each label be unique. - */ - public GenericDialog(String title) { - this(title, null); - } - - private static Frame getParentFrame() { - return null; - } - - /** Creates a new GenericDialog using the specified title and parent frame. */ - public GenericDialog(String title, Frame parent) { - super(parent, title, true); - ImageJ ij = IJ.getInstance(); - if (ij != null) - setFont(ij.getFont()); - okay = new Button(" OK "); - cancel = new Button("Cancel"); - if (Prefs.blackCanvas) { - setForeground(SystemColor.controlText); - setBackground(SystemColor.control); - } - // if (IJ.isMacOSX() && System.getProperty("java.vendor").contains("Azul")) - // setForeground(Color.black); // work around bug on Azul Java 8 on Apple - // Silicon - GridBagLayout grid = new GridBagLayout(); - c = new GridBagConstraints(); - setLayout(grid); - macroOptions = Macro.getOptions(); - macro = macroOptions != null; - addKeyListener(this); - addWindowListener(this); - // Added for Bio7! - addComponentListener(this); - /* Changed for Bio7! */ - Font font = Util.getOSFontToAwt(); - if (font != null) { - setFont(Util.getOSFontToAwt()); - } - /* - * Changed for Bio7! AWT must be colored per component. All JPanels will get the - * SWT background from the definition of the CanvasView (UIManager)! - */ - - if (Util.isThemeBlack()) { - if (Util.getOS().equals("Linux") || Util.getOS().equals("Mac")) { - setBackground(Util.getSWTBackgroundToAWT()); - setForeground(Util.getSWTForegroundToAWT()); - - } - } - } - - /** - * Adds a numeric field. The first word of the label must be unique or command - * recording will not work. - * - * @param label the label - * @param defaultValue value to be initially displayed - */ - public void addNumericField(String label, double defaultValue) { - int decimalPlaces = (int) defaultValue == defaultValue ? 0 : 3; - int columnWidth = decimalPlaces == 3 ? 8 : 6; - addNumericField(label, defaultValue, decimalPlaces, columnWidth, null); - } - - /** - * Adds a numeric field. The first word of the label must be unique or command - * recording will not work. - * - * @param label the label - * @param defaultValue value to be initially displayed - * @param digits number of digits to right of decimal point - */ - public void addNumericField(String label, double defaultValue, int digits) { - addNumericField(label, defaultValue, digits, 6, null); - } - - /** - * Adds a numeric field. The first word of the label must be unique or command - * recording will not work. - * - * @param label the label - * @param defaultValue value to be initially displayed - * @param digits number of digits to right of decimal point - * @param columns width of field in characters - * @param units a string displayed to the right of the field - */ - public void addNumericField(String label, double defaultValue, int digits, int columns, String units) { - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - c.insets.left = 10; - } else { - c.gridx = 0; - c.gridy++; - if (firstNumericField) - c.insets = getInsets(5, 0, 3, 0); // top, left, bottom, right - else - c.insets = getInsets(0, 0, 3, 0); - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - // IJ.log("x="+c.gridx+", y= "+c.gridy+", width="+c.gridwidth+", ancher= - // "+c.anchor+" "+c.insets); - add(fieldLabel, c); - if (addToSameRow) { - c.insets.left = 0; - addToSameRow = false; - } - if (numberField == null) { - numberField = new Vector(5); - defaultValues = new Vector(5); - defaultText = new Vector(5); - } - if (IJ.isWindows()) - columns -= 2; - if (columns < 1) - columns = 1; - boolean scientificNotationAsNeeded = false; - if (digits < 0) { - digits = -digits; - scientificNotationAsNeeded = true; - } - String defaultString = IJ.d2s(defaultValue, digits); - if (scientificNotationAsNeeded) - defaultString = ij.measure.ResultsTable.d2s(defaultValue, digits); - if (Double.isNaN(defaultValue)) - defaultString = ""; - TextField tf = newTextField(defaultString, columns); - if (IJ.isLinux()) - tf.setBackground(Color.white); - tf.addActionListener(this); - tf.addTextListener(this); - tf.addFocusListener(this); - tf.addKeyListener(this); - numberField.addElement(tf); - defaultValues.addElement(Double.valueOf(defaultValue)); - defaultText.addElement(tf.getText()); - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - tf.setEditable(true); - // if (firstNumericField) tf.selectAll(); - firstNumericField = false; - if (units == null || units.equals("")) { - add(tf, c); - } else { - JPanel panel = new JPanel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - panel.add(tf); - panel.add(new Label(" " + units)); - add(panel, c); - } - if (IJ.recording() || macro) - saveLabel(tf, label); - } - - private Label makeLabel(String label) { - if (IJ.isMacintosh()) - label += " "; - return new Label(label); - } - - /** - * Saves the label for given component, for macro recording and for accessing - * the component in macros. - */ - private void saveLabel(Object component, String label) { - if (labels == null) - labels = new Hashtable(); - if (label.length() > 0) - label = Macro.trimKey(label.trim()); - if (label.length() > 0 && hasLabel(label)) { // not a unique label? - label += "_0"; - for (int n = 1; hasLabel(label); n++) { // while still not a unique label - label = label.substring(0, label.lastIndexOf('_')); // remove counter - label += "_" + n; - } - } - labels.put(component, label); - } - - /** - * Returns whether the list of labels for macro recording or macro creation - * contains a given label. - */ - private boolean hasLabel(String label) { - for (Object o : labels.keySet()) - if (labels.get(o).equals(label)) - return true; - return false; - } - - /** - * Adds an 8 column text field. - * - * @param label the label - * @param defaultText the text initially displayed - */ - public void addStringField(String label, String defaultText) { - addStringField(label, defaultText, 8); - } - - /** - * Adds a text field. - * - * @param label the label - * @param defaultText text initially displayed - * @param columns width of the text field. If columns is 8 or more, - * additional items may be added to this line with - * addToSameRow() - */ - public void addStringField(String label, String defaultText, int columns) { - if (addToSameRow && label.equals("_")) - label = ""; - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - boolean custom = customInsets; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - if (stringField == null) - c.insets = getInsets(5, 0, 5, 0); // top, left, bottom, right - else - c.insets = getInsets(0, 0, 5, 0); - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - add(fieldLabel, c); - if (stringField == null) { - stringField = new Vector(4); - defaultStrings = new Vector(4); - } - - TextField tf = newTextField(defaultText, columns); - if (IJ.isLinux()) - tf.setBackground(Color.white); - - tf.setEchoChar(echoChar); - echoChar = 0; - tf.addActionListener(this); - tf.addTextListener(this); - tf.addFocusListener(this); - tf.addKeyListener(this); - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - c.gridwidth = columns <= 8 ? 1 : GridBagConstraints.REMAINDER; - c.insets.left = 0; - tf.setEditable(true); - add(tf, c); - stringField.addElement(tf); - defaultStrings.addElement(defaultText); - tf.setDropTarget(null); - new DropTarget(tf, new TextDropTarget(tf)); - if (IJ.recording() || macro) - saveLabel(tf, label); - } - - /** Sets the echo character for the next string field. */ - public void setEchoChar(char echoChar) { - this.echoChar = echoChar; - } - - /** - * Adds a directory text field and "Browse" button, where the field width is - * determined by the length of 'defaultPath', with a minimum of 25 columns. Use - * getNextString to retrieve the directory path. Call - * OpenDialog.setDefaultDirectory() to set the default directory used when the - * user clicks on "Browse". Based on the addDirectoryField() method in Fiji's - * GenericDialogPlus class. * @see ij.io.OpenDialog#setDefaultDirectory(String) - */ - public void addDirectoryField(String label, String defaultPath) { - int columns = defaultPath != null ? Math.max(defaultPath.length(), 25) : 25; - if (columns > 60) - columns = 60; - addDirectoryField(label, defaultPath, columns); - } - - public void addDirectoryField(String label, String defaultPath, int columns) { - defaultPath = IJ.addSeparator(defaultPath); - addStringField(label, defaultPath, columns); - if (GraphicsEnvironment.isHeadless()) - return; - TextField text = (TextField) stringField.lastElement(); - GridBagLayout layout = (GridBagLayout) getLayout(); - GridBagConstraints constraints = layout.getConstraints(text); - JButton button = new TrimmedButton("Browse", IJ.isMacOSX() ? 10 : 0); - BrowseButtonListener listener = new BrowseButtonListener(label, text, "dir"); - button.addActionListener(listener); - Panel panel = new Panel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - panel.add(text); - panel.add(button); - layout.setConstraints(panel, constraints); - add(panel); - if (IJ.recording() || macro) - saveLabel(panel, label); - } - - /** - * Adds a file text field and "Browse" button, where the field width is - * determined by the length of 'defaultPath', with a minimum of 25 columns. Use - * getNextString to retrieve the file path. Based on the addFileField() method - * in Fiji's GenericDialogPlus class. - */ - public void addFileField(String label, String defaultPath) { - int columns = defaultPath != null ? Math.max(defaultPath.length(), 25) : 25; - if (columns > 60) - columns = 60; - addFileField(label, defaultPath, columns); - } - - public void addFileField(String label, String defaultPath, int columns) { - addStringField(label, defaultPath, columns); - if (GraphicsEnvironment.isHeadless()) - return; - TextField text = (TextField) stringField.lastElement(); - GridBagLayout layout = (GridBagLayout) getLayout(); - GridBagConstraints constraints = layout.getConstraints(text); - JButton button = new TrimmedButton("Browse", IJ.isMacOSX() ? 10 : 0); - BrowseButtonListener listener = new BrowseButtonListener(label, text, "file"); - button.addActionListener(listener); - Panel panel = new Panel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - panel.add(text); - panel.add(button); - layout.setConstraints(panel, constraints); - add(panel); - if (IJ.recording() || macro) - saveLabel(panel, label); - } - - /** - * Add button to the dialog - * - * @param label button label - * @param listener listener to handle the action when pressing the button - */ - public void addButton(String label, ActionListener listener) { - if (GraphicsEnvironment.isHeadless()) - return; - Button button = new Button(label); - button.addActionListener(listener); - button.addKeyListener(this); - GridBagLayout layout = (GridBagLayout) getLayout(); - Panel panel = new Panel(); - addPanel(panel); - GridBagConstraints constraints = layout.getConstraints(panel); - remove(panel); - layout.setConstraints(button, constraints); - add(button); - } - - /** - * Adds a popup menu that lists the currently open images. Call getNextImage() - * to retrieve the selected image. Based on the addImageChoice() method in - * Fiji's GenericDialogPlus class. - * - * @param label the label - * @param defaultImage the image title initially selected in the menu or the - * first image if null - */ - public void addImageChoice(String label, String defaultImage) { - if (windowTitles == null) { - windowIDs = WindowManager.getIDList(); - if (windowIDs == null) - windowIDs = new int[0]; - windowTitles = new String[windowIDs.length]; - for (int i = 0; i < windowIDs.length; i++) { - ImagePlus image = WindowManager.getImage(windowIDs[i]); - windowTitles[i] = image == null ? "" : image.getTitle(); - } - } - addChoice(label, windowTitles, defaultImage); - } - - public ImagePlus getNextImage() { - int index = getNextChoiceIndex(); - return index < 0 ? null : WindowManager.getImage(windowIDs[index]); - } - - /** - * Adds a group of choices to the dialog with menu items taken from the - * enum class of the specified default item (enum constant). The - * default item is automatically set. Calls the original (string-based) - * {@link GenericDialog#addChoice(String, String[], String)} method. Usage - * example: - * - * - * import ij.process.AutoThresholder.Method; - * ... - * Method method = Method.Otsu; - * - * GenericDialog gd = new GenericDialog("Select AutoThresholder Method"); - * gd.addEnumChoice("All threshold methods", method); - * ... - * gd.showDialog(); - * ... - * method = gd.getNextEnumChoice(Method.class); - * - * - * @param the generic enum type containing the items to chose from - * @param label the label displayed for this choice group - * @param defaultItem the menu item initially selected - * - * @see #addEnumChoice(String, Enum[], Enum) - * @see #getNextEnumChoice(Class) - */ - public > void addEnumChoice(String label, E defaultItem) { - Class enumClass = defaultItem.getDeclaringClass(); - E[] enums = enumClass.getEnumConstants(); - String[] items = new String[enums.length]; - for (int i = 0; i < enums.length; i++) { - items[i] = enums[i].name(); - } - this.addChoice(label, items, defaultItem.name()); - } - - /** - * Adds a group of choices to the dialog with menu items taken from the supplied - * array of enum elements. This allows to present only a subset of - * enum choices in a specified order. A default item (enum constant) must be - * specified which, if {@code null} of not contained in the enum array, is - * replaced by the first element of the enum array. Calls the original - * (string-based) {@link GenericDialog#addChoice(String, String[], String)} - * method. Usage example: - * - * - * import ij.process.AutoThresholder.Method; - * ... - * Method[] selectMethods = {Method.Triangle, Method.Otsu, Method.Huang}; - * Method method = Method.Otsu; - * - * GenericDialog gd = new GenericDialog("Select AutoThresholder Method"); - * gd.addEnumChoice("Select threshold methods", selectMethods, method); - * ... - * gd.showDialog(); - * ... - * method = gd.getNextEnumChoice(Method.class); - * - * - * @param the generic enum type containing the items to choose from - * @param label the label displayed for this choice group - * @param enumArray an array of enum items (of type E) - * @param defaultItem the menu item initially selected (of type E, may be - * {@code null}) - * - * @see #addEnumChoice(String, Enum) - * @see #getNextEnumChoice(Class) - */ - public > void addEnumChoice(String label, E[] enumArray, E defaultItem) { - String[] items = new String[enumArray.length]; - boolean contained = false; // to check if defaultItem is contained in enumArray - for (int i = 0; i < enumArray.length; i++) { - if (enumArray[i] == defaultItem) { - contained = true; - } - items[i] = enumArray[i].name(); - } - if (!contained) { - defaultItem = enumArray[0]; - } - this.addChoice(label, items, defaultItem.name()); - } - - /** - * Returns the selected item in the next enum choice menu. Note that 'enumClass' - * is required to infer the proper enum type. Throws - * {@code IllegalArgumentException} if the selected item is not a defined - * constant in the specified enum class. - * - * @param the generic enum type - * @param enumClass the enum type - * @return the selected item - */ - public > E getNextEnumChoice(Class enumClass) { - String choiceString = this.getNextChoice(); - return Enum.valueOf(enumClass, choiceString); - } - - /** - * Adds a checkbox. - * - * @param label the label - * @param defaultValue the initial state - */ - public void addCheckbox(String label, boolean defaultValue) { - addCheckbox(label, defaultValue, false); - } - - /** - * Adds a checkbox; does not make it recordable if isPreview is true. With - * isPreview true, the checkbox can be referred to as previewCheckbox from - * hereon. - */ - private void addCheckbox(String label, boolean defaultValue, boolean isPreview) { - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - c.insets.left = 10; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - if (checkbox == null) - c.insets = getInsets(15, 20, 0, 0); // top, left, bottom, right - else - c.insets = getInsets(0, 20, 0, 0); - } - c.anchor = GridBagConstraints.WEST; - c.gridwidth = 2; - if (checkbox == null) - checkbox = new Vector(4); - Checkbox cb = new Checkbox(label2); - cb.setState(defaultValue); - cb.addItemListener(this); - cb.addKeyListener(this); - add(cb, c); - c.insets.left = 0; - checkbox.addElement(cb); - if (!isPreview && (Recorder.record || macro)) // preview checkbox is not recordable - saveLabel(cb, label); - if (isPreview) - previewCheckbox = cb; - } - - /** - * Adds a checkbox labelled "Preview" for "automatic" preview. The reference to - * this checkbox can be retrieved by getPreviewCheckbox() and it provides the - * additional method previewRunning for optical feedback while preview is - * prepared. PlugInFilters can have their "run" method automatically called for - * preview under the following conditions: - the PlugInFilter must pass a - * reference to itself (i.e., "this") as an argument to the AddPreviewCheckbox - - * it must implement the DialogListener interface and set the filter parameters - * in the dialogItemChanged method. - it must have DIALOG and PREVIEW set in its - * flags. A previewCheckbox is always off when the filter is started and does - * not get recorded by the Macro Recorder. - * - * @param pfr A reference to the PlugInFilterRunner calling the PlugInFilter if - * automatic preview is desired, null otherwise. - */ - public void addPreviewCheckbox(PlugInFilterRunner pfr) { - if (previewCheckbox != null) - return; - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp != null && imp.isComposite() && ((CompositeImage) imp).getMode() == IJ.COMPOSITE) - return; - this.pfr = pfr; - addCheckbox(previewLabel, false, true); - } - - /** - * Add the preview checkbox with user-defined label; for details see the - * addPreviewCheckbox method with standard "Preview" label. Adds the checkbox - * when the current image is a CompositeImage in "Composite" mode, unlike the - * one argument version. Note that a GenericDialog can have only one - * PreviewCheckbox. - */ - public void addPreviewCheckbox(PlugInFilterRunner pfr, String label) { - if (previewCheckbox != null) - return; - previewLabel = label; - this.pfr = pfr; - addCheckbox(previewLabel, false, true); - } - - /** - * Adds a group of checkboxs using a grid layout. - * - * @param rows the number of rows - * @param columns the number of columns - * @param labels the labels - * @param defaultValues the initial states - */ - public void addCheckboxGroup(int rows, int columns, String[] labels, boolean[] defaultValues) { - addCheckboxGroup(rows, columns, labels, defaultValues, null); - } - - /** - * Adds a group of checkboxs using a grid layout. - * - * @param rows the number of rows - * @param columns the number of columns - * @param labels the labels - * @param defaultValues the initial states - * @param headings the column headings Example: Example: - * http://imagej.net/ij/plugins/multi-column-dialog/index.html - */ - public void addCheckboxGroup(int rows, int columns, String[] labels, boolean[] defaultValues, String[] headings) { - JPanel panel = new JPanel(); - int nRows = headings != null ? rows + 1 : rows; - panel.setLayout(new GridLayout(nRows, columns, 6, 0)); - int startCBIndex = cbIndex; - if (checkbox == null) - checkbox = new Vector(12); - if (headings != null) { - Font font = new Font("SansSerif", Font.BOLD, 12); - for (int i = 0; i < columns; i++) { - if (i > headings.length - 1 || headings[i] == null) - panel.add(new Label("")); - else { - Label label = new Label(headings[i]); - label.setFont(font); - panel.add(label); - } - } - } - int i1 = 0; - int[] index = new int[labels.length]; - for (int row = 0; row < rows; row++) { - for (int col = 0; col < columns; col++) { - int i2 = col * rows + row; - if (i2 >= labels.length) - break; - index[i1] = i2; - String label = labels[i1]; - if (label == null || label.length() == 0) { - Label lbl = new Label(""); - panel.add(lbl); - i1++; - continue; - } - if (label.indexOf('_') != -1) - label = label.replace('_', ' '); - Checkbox cb = new Checkbox(label); - checkbox.addElement(cb); - cb.setState(defaultValues[i1]); - cb.addItemListener(this); - if (IJ.recording() || macro) - saveLabel(cb, labels[i1]); - if (IJ.isLinux()) { - JPanel panel2 = new JPanel(); - panel2.setLayout(new BorderLayout()); - panel2.add("West", cb); - panel.add(panel2); - } else - panel.add(cb); - i1++; - } - } - c.gridx = 0; - c.gridy++; - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.insets = getInsets(10, 0, 0, 0); - addToSameRow = false; - add(panel, c); - } - - /** - * Adds a radio button group. - * - * @param label group label (or null) - * @param items radio button labels - * @param rows number of rows - * @param columns number of columns - * @param defaultItem button initially selected - */ - public void addRadioButtonGroup(String label, String[] items, int rows, int columns, String defaultItem) { - addToSameRow = false; - JPanel panel = new JPanel(); - int n = items.length; - panel.setLayout(new GridLayout(rows, columns, 0, 0)); - CheckboxGroup cg = new CheckboxGroup(); - for (int i = 0; i < n; i++) { - Checkbox cb = new Checkbox(items[i], cg, items[i].equals(defaultItem)); - cb.addItemListener(this); - panel.add(cb); - } - if (radioButtonGroups == null) - radioButtonGroups = new Vector(); - radioButtonGroups.addElement(cg); - Insets insets = getInsets(5, 10, 0, 0); - if (label == null || label.equals("")) { - label = "rbg" + radioButtonGroups.size(); - insets.top += 5; - } else { - setInsets(10, insets.left, 0); - addMessage(label); - insets.top = 2; - insets.left += 10; - } - c.gridx = 0; - c.gridy++; - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.insets = new Insets(insets.top, insets.left, 0, 0); - add(panel, c); - if (IJ.recording() || macro) - saveLabel(cg, label); - } - - /** - * Adds a popup menu. - * - * @param label the label - * @param items the menu items - * @param defaultItem the menu item initially selected - */ - public void addChoice(String label, String[] items, String defaultItem) { - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - if (choice == null) - c.insets = getInsets(5, 0, 5, 0); - else - c.insets = getInsets(0, 0, 5, 0); - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - if (choice == null) { - choice = new Vector(4); - defaultChoiceIndexes = new Vector(4); - } - add(fieldLabel, c); - Choice thisChoice = new Choice(); - thisChoice.addKeyListener(this); - thisChoice.addItemListener(this); - for (int i = 0; i < items.length; i++) - thisChoice.addItem(items[i]); - if (defaultItem != null) - thisChoice.select(defaultItem); - else - thisChoice.select(0); - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - add(thisChoice, c); - choice.addElement(thisChoice); - int index = thisChoice.getSelectedIndex(); - defaultChoiceIndexes.addElement(Integer.valueOf(index)); - if (IJ.recording() || macro) - saveLabel(thisChoice, label); - } - - /** Adds a message consisting of one or more lines of text. */ - public void addMessage(String text) { - addMessage(text, null, null); - } - - /** - * Adds a message consisting of one or more lines of text, which will be - * displayed using the specified font. - */ - public void addMessage(String text, Font font) { - addMessage(text, font, null); - } - - /** - * Adds a message consisting of one or more lines of text, which will be - * displayed using the specified font and color. - */ - public void addMessage(String text, Font font, Color color) { - theLabel = null; - if (text.indexOf('\n') >= 0) - theLabel = new MultiLineLabel(text); - else - theLabel = new Label(text); - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - c.insets = getInsets("".equals(text) ? 0 : 10, 20, 0, 0); // top, left, bottom, right - } - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.HORIZONTAL; - if (font != null) { - if (Prefs.getGuiScale() > 1.0) - font = font.deriveFont((float) (font.getSize() * Prefs.getGuiScale())); - theLabel.setFont(font); - } - if (color != null) - theLabel.setForeground(color); - add(theLabel, c); - c.fill = GridBagConstraints.NONE; - } - - /** - * Adds one or two (side by side) text areas. Append "SCROLLBARS_VERTICAL_ONLY" - * to the text of the first text area to get vertical scrollbars and - * "SCROLLBARS_BOTH" to get both vertical and horizontal scrollbars. - * - * @param text1 initial contents of the first text area - * @param text2 initial contents of the second text area or null - * @param rows the number of rows - * @param columns the number of columns - */ - public void addTextAreas(String text1, String text2, int rows, int columns) { - if (textArea1 != null) - return; - Panel panel = new Panel(); - int scrollbars = TextArea.SCROLLBARS_NONE; - if (text1 != null && text1.endsWith("SCROLLBARS_BOTH")) { - scrollbars = TextArea.SCROLLBARS_BOTH; - text1 = text1.substring(0, text1.length() - 15); - } - if (text1 != null && text1.endsWith("SCROLLBARS_VERTICAL_ONLY")) { - scrollbars = TextArea.SCROLLBARS_VERTICAL_ONLY; - text1 = text1.substring(0, text1.length() - 24); - } - Font font = new Font("SansSerif", Font.PLAIN, (int) (14 * Prefs.getGuiScale())); - textArea1 = new TextArea(text1, rows, columns, scrollbars); - if (IJ.isLinux()) - textArea1.setBackground(Color.white); - /* Changed for Bio7! */ - if (Util.isThemeBlack()) { - textArea1.setBackground(Util.getSWTBackgroundToAWT()); - textArea1.setForeground(Util.getSWTForegroundToAWT()); - } - if (Util.isThemeBlack()) { - Util.getSWTBackgroundToAWT(); - } - textArea1.setFont(font); - textArea1.addTextListener(this); - panel.add(textArea1); - if (text2 != null) { - textArea2 = new TextArea(text2, rows, columns, scrollbars); - if (IJ.isLinux()) - textArea2.setBackground(Color.white); - - /* Changed for Bio7! */ - if (Util.isThemeBlack()) { - textArea2.setBackground(Util.getSWTBackgroundToAWT()); - textArea2.setForeground(Util.getSWTForegroundToAWT()); - - } - textArea2.setFont(font); - panel.add(textArea2); - } - - c.gridx = 0; - c.gridy++; - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.insets = getInsets(15, 20, 0, 0); - addToSameRow = false; - add(panel, c); - } - - /** - * Adds a slider (scroll bar) to the dialog box. Floating point values are used - * if (maxValue-minValue)<=5.0 and either defaultValue or minValue are - * non-integer. - * - * @param label the label - * @param minValue the minimum value of the slider - * @param maxValue the maximum value of the slider - * @param defaultValue the initial value of the slider - */ - public void addSlider(String label, double minValue, double maxValue, double defaultValue) { - if (defaultValue < minValue) - defaultValue = minValue; - if (defaultValue > maxValue) - defaultValue = maxValue; - int digits = 0; - double scale = 1.0; - if ((maxValue - minValue) <= 5.0 && (minValue != (int) minValue || maxValue != (int) maxValue || defaultValue != (int) defaultValue)) { - scale = 50.0; - minValue *= scale; - maxValue *= scale; - defaultValue *= scale; - digits = 2; - } - addSlider(label, minValue, maxValue, defaultValue, scale, digits); - } - - /** - * This vesion of addSlider() adds a 'stepSize' argument. - * Example: http://wsr.imagej.net/macros/SliderDemo.txt - */ - public void addSlider(String label, double minValue, double maxValue, double defaultValue, double stepSize) { - if (stepSize <= 0) - stepSize = 1; - int digits = digits(stepSize); - if (digits == 1 && "Angle:".equals(label)) - digits = 2; - double scale = 1.0 / Math.abs(stepSize); - if (scale <= 0) - scale = 1; - if (defaultValue < minValue) - defaultValue = minValue; - if (defaultValue > maxValue) - defaultValue = maxValue; - minValue *= scale; - maxValue *= scale; - defaultValue *= scale; - addSlider(label, minValue, maxValue, defaultValue, scale, digits); - } - - /** Author: Michael Kaul */ - private static int digits(double d) { - if (d == (int) d) - return 0; - String s = Double.toString(d); - int ePos = s.indexOf("E"); - if (ePos == -1) - ePos = s.indexOf("e"); - int dotPos = s.indexOf("."); - int digits = 0; - if (ePos == -1) - digits = s.substring(dotPos + 1).length(); - else { - String number = s.substring(dotPos + 1, ePos); - if (!number.equals("0")) - digits += number.length(); - digits = digits - Integer.valueOf(s.substring(ePos + 1)); - } - return digits; - } - - private void addSlider(String label, double minValue, double maxValue, double defaultValue, double scale, int digits) { - int columns = 4 + digits - 2; - if (columns < 4) - columns = 4; - if (minValue < 0.0) - columns++; - String mv = IJ.d2s(maxValue, 0); - if (mv.length() > 4 && digits == 0) - columns += mv.length() - 4; - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - c.insets.bottom += 3; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - c.insets = getInsets(0, 0, 3, 0); // top, left, bottom, right - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - add(fieldLabel, c); - - if (slider == null) { - slider = new Vector(5); - sliderIndexes = new Vector(5); - sliderScales = new Vector(5); - sliderDigits = new Vector(5); - } - Scrollbar s = new Scrollbar(Scrollbar.HORIZONTAL, (int) defaultValue, 1, (int) minValue, (int) maxValue + 1); - if (IJ.debugMode) - IJ.log("Scrollbar: " + scale + " " + defaultValue + " " + minValue + " " + maxValue); - GUI.fixScrollbar(s); - slider.addElement(s); - s.addAdjustmentListener(this); - s.setUnitIncrement(1); - if (IJ.isMacOSX()) - s.addKeyListener(this); - s.addMouseWheelListener(new MouseWheelListener() { - public void mouseWheelMoved(MouseWheelEvent e) { - Scrollbar sb = (Scrollbar) e.getSource(); - int value = sb.getValue() + e.getWheelRotation(); - sb.setValue(value); - for (int i = 0; i < slider.size(); i++) { - if (sb == slider.elementAt(i)) { - int index = ((Integer) sliderIndexes.get(i)).intValue(); - TextField tf = (TextField) numberField.elementAt(index); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - int digits = ((Integer) sliderDigits.get(i)).intValue(); - tf.setText("" + IJ.d2s(sb.getValue() / scale, digits)); - } - } - } - }); - - if (numberField == null) { - numberField = new Vector(5); - defaultValues = new Vector(5); - defaultText = new Vector(5); - } - if (IJ.isWindows()) - columns -= 2; - if (columns < 1) - columns = 1; - // IJ.log("scale=" + scale + ", columns=" + columns + ", digits=" + digits); - TextField tf = newTextField(IJ.d2s(defaultValue / scale, digits), columns); - // if (IJ.isLinux()) tf.setBackground(Color.white); - tf.setBackground(Color.white); - tf.addActionListener(this); - tf.addTextListener(this); - tf.addFocusListener(this); - tf.addKeyListener(this); - numberField.addElement(tf); - sliderIndexes.add(Integer.valueOf(numberField.size() - 1)); - sliderScales.add(Double.valueOf(scale)); - sliderDigits.add(Integer.valueOf(digits)); - defaultValues.addElement(Double.valueOf(defaultValue / scale)); - defaultText.addElement(tf.getText()); - tf.setEditable(true); - firstSlider = false; - - JPanel panel = new JPanel(); - GridBagLayout pgrid = new GridBagLayout(); - GridBagConstraints pc = new GridBagConstraints(); - panel.setLayout(pgrid); - pc.gridx = 0; - pc.gridy = 0; - pc.gridwidth = 1; - pc.ipadx = 85; - pc.anchor = GridBagConstraints.WEST; - panel.add(s, pc); - pc.ipadx = 0; // reset - // text field - pc.gridx = 1; - pc.insets = new Insets(5, 5, 0, 0); - pc.anchor = GridBagConstraints.EAST; - panel.add(tf, pc); - - c.gridx = GridBagConstraints.RELATIVE; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - c.insets.left = 0; - c.insets.bottom -= 3; - add(panel, c); - if (IJ.recording() || macro) - saveLabel(tf, label); - } - - private TextField newTextField(String txt, int columns) { - if (IJ.isLinux()) - return new TrimmedTextField(txt, columns); - else - return new TextField(txt, columns); - } - - /* Changed for Bio7! -> Added JPanel method! */ - public void addPanel(JPanel panel) { - addPanel(panel, GridBagConstraints.WEST, addToSameRow ? c.insets : getInsets(5, 0, 0, 0)); - } - - /** Adds a Panel to the dialog. */ - /** Adds a Panel to the dialog. */ - public void addPanel(Panel panel) { - addPanel(panel, GridBagConstraints.WEST, addToSameRow ? c.insets : getInsets(5, 0, 0, 0)); - } - - /* - * public void addPanel(Panel panel) { addPanel(panel , GridBagConstraints.WEST, - * new Insets(5, 0, 0, 0)); } - */ - // extra method to avoid plugin mistake - /* - * public void addPanel(Panel panel) { JPanel panel2 = new JPanel(); Component[] - * comp = panel.getComponents(); for (int i = 0; i < comp.length; i++) { - * panel2.add(comp[i]); } - * - * addPanel(panel, GridBagConstraints.WEST, addToSameRow ? c.insets : - * getInsets(5, 0, 0, 0)); } - */ - - /* Changed for Bio7! -> Extra method for plugins! */ - public void addPanel(Panel panel, int constraints, Insets insets) { - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - } - c.gridwidth = 2; - c.anchor = constraints; - c.insets = insets; - add(panel, c); - } - - /** - * Adds a Panel to the dialog with custom contraint and insets. The defaults are - * GridBagConstraints.WEST (left justified) and "new Insets(5, 0, 0, 0)" (5 - * pixels of padding at the top). - */ - public void addPanel(JPanel panel, int constraints, Insets insets) { - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - } - c.gridwidth = 2; - c.anchor = constraints; - c.insets = insets; - add(panel, c); - } - - /** Adds an image to the dialog. */ - public void addImage(ImagePlus image) { - if (image == null) - return; - ImagePanel imagePanel = new ImagePanel(image); - addPanel(imagePanel); - if (imagePanels == null) - imagePanels = new Vector(); - imagePanels.add(imagePanel); - } - - /** - * Set the insets (margins), in pixels, that will be used for the next component - * added to the dialog (except components added to the same row with - * addToSameRow) - * - * - Default insets: - addMessage: 0,20,0 (empty string) or 10,20,0 - addCheckbox: 15,20,0 (first checkbox) or 0,20,0 - addCheckboxGroup: 10,0,0 - addRadioButtonGroup: 5,10,0 - addNumericField: 5,0,3 (first field) or 0,0,3 - addStringField: 5,0,5 (first field) or 0,0,5 - addChoice: 5,0,5 (first field) or 0,0,5 - * - */ - public void setInsets(int top, int left, int bottom) { - topInset = top; - leftInset = left; - bottomInset = bottom; - customInsets = true; - } - - /** - * Makes the next item appear in the same row as the previous. May be used for - * addNumericField, addSlider, addChoice, addCheckbox, addStringField, - * addMessage, addPanel, and before the showDialog() method (in the latter case, - * the buttons appear to the right of the previous item). Note that addMessage - * (and addStringField, if its column width is more than 8) use the remaining - * width, so it must be the last item of a row. - */ - public void addToSameRow() { - addToSameRow = true; - addToSameRowCalled = true; - } - - /** Sets a replacement label for the "OK" button. */ - public void setOKLabel(String label) { - okay.setLabel(label); - } - - /** Sets a replacement label for the "Cancel" button. */ - public void setCancelLabel(String label) { - cancel.setLabel(label); - } - - /** Sets a replacement label for the "Help" button. */ - public void setHelpLabel(String label) { - helpLabel = label; - } - - /** Unchanged parameters are not recorder in 'smart recording' mode. */ - public void setSmartRecording(boolean smartRecording) { - this.smartRecording = smartRecording; - } - - /** Make this a "Yes No Cancel" dialog. */ - public void enableYesNoCancel() { - enableYesNoCancel(" Yes ", " No "); - } - - /** - * Make this a "Yes No Cancel" dialog with custom labels. Here is an example: - * - * - * GenericDialog gd = new GenericDialog("YesNoCancel Demo"); - * gd.addMessage("This is a custom YesNoCancel dialog"); - * gd.enableYesNoCancel("Do something", "Do something else"); - * gd.showDialog(); - * if (gd.wasCanceled()) - * IJ.log("User clicked 'Cancel'"); - * else if (gd.wasOKed()) - * IJ.log("User clicked 'Yes'"); - * else - * IJ.log("User clicked 'No'"); - * - */ - public void enableYesNoCancel(String yesLabel, String noLabel) { - okay.setLabel(yesLabel); - if (no != null) - no.setLabel(noLabel); - else if (noLabel != null) - no = new Button(noLabel); - } - - /** Do not display "Cancel" button. */ - public void hideCancelButton() { - hideCancelButton = true; - } - - Insets getInsets(int top, int left, int bottom, int right) { - if (customInsets) { - customInsets = false; - return new Insets(topInset, leftInset, bottomInset, 0); - } else - return new Insets(top, left, bottom, right); - } - - /** - * Add an Object implementing the DialogListener interface. This object will be - * notified by its dialogItemChanged method of input to the dialog. The first - * DialogListener will be also called after the user has typed 'OK' or if the - * dialog has been invoked by a macro; it should read all input fields of the - * dialog. For other listeners, the OK button will not cause a call to - * dialogItemChanged; the CANCEL button will never cause such a call. - * - * @param dl the Object that wants to listen. - */ - public void addDialogListener(DialogListener dl) { - if (dialogListeners == null) - dialogListeners = new Vector(); - dialogListeners.addElement(dl); - } - - /** Returns true if the user clicked on "Cancel". */ - public boolean wasCanceled() { - if (wasCanceled && !Thread.currentThread().getName().endsWith("Script_Macro$")) - Macro.abort(); - return wasCanceled; - } - - /** Returns true if the user has clicked on "OK" or a macro is running. */ - public boolean wasOKed() { - return wasOKed || macro; - } - - /** - * Returns the contents of the next numeric field, or NaN if the field does not - * contain a number. - */ - public double getNextNumber() { - if (numberField == null) - return -1.0; - TextField tf = (TextField) numberField.elementAt(nfIndex); - String theText = tf.getText(); - String label = null; - if (macro) { - label = (String) labels.get((Object) tf); - theText = Macro.getValue(macroOptions, label, theText); - } - String originalText = (String) defaultText.elementAt(nfIndex); - double defaultValue = ((Double) (defaultValues.elementAt(nfIndex))).doubleValue(); - double value; - boolean skipRecording = false; - if (theText.equals(originalText)) { - value = defaultValue; - if (smartRecording) - skipRecording = true; - } else if (theText.startsWith("0x")) { - value = parseHex(theText.substring(2)); - } else { - Double d = getValue(theText); - if (d != null) - value = d.doubleValue(); - else { - // Is the value a macro variable? - if (theText.startsWith("&")) - theText = theText.substring(1); - Interpreter interp = Interpreter.getInstance(); - value = interp != null ? interp.getVariable2(theText) : Double.NaN; - if (Double.isNaN(value)) { - invalidNumber = true; - errorMessage = "\"" + theText + "\" is an invalid number"; - value = Double.NaN; - if (macro) { - IJ.error("Macro Error", "Numeric value expected in run() function\n \n" + " Dialog box title: \"" + getTitle() + "\"\n" + " Key: \"" + label.toLowerCase(Locale.US) + "\"\n" - + " Value or variable name: \"" + theText + "\""); - } - } - } - } - if (recorderOn && !skipRecording) { - recordOption(tf, trim(theText)); - } - nfIndex++; - return value; - } - - int parseHex(String hexString) { - int n = 0; - ; - try { - n = Integer.parseInt(hexString, 16); - } catch (NumberFormatException e) { - } - return n; - } - - private String trim(String value) { - if (value.endsWith(".0")) - value = value.substring(0, value.length() - 2); - if (value.endsWith(".00")) - value = value.substring(0, value.length() - 3); - return value; - } - - private void recordOption(Object component, String value) { - if (labels == null) - return; - String label = (String) labels.get(component); - if (value.equals("")) - value = "[]"; - Recorder.recordOption(label, value); - } - - private void recordCheckboxOption(Checkbox cb) { - if (labels == null) - return; - String label = (String) labels.get((Object) cb); - if (label != null) { - if (cb.getState()) // checked - Recorder.recordOption(label); - else if (Recorder.getCommandOptions() == null) - Recorder.recordOption(" "); - } - } - - /* Bio7 extra method! */ - private void recordCheckboxOption(JCheckBox cb) { - if (labels == null) - return; - String label = (String) labels.get((Object) cb); - if (label != null) { - if (cb.isSelected()) // checked - Recorder.recordOption(label); - else if (Recorder.getCommandOptions() == null) - Recorder.recordOption(" "); - } - } - - protected Double getValue(String text) { - Double d; - try { - d = Double.valueOf(text); - } catch (NumberFormatException e) { - d = null; - } - return d; - } - - public double parseDouble(String s) { - if (s == null) - return Double.NaN; - double value = Tools.parseDouble(s); - if (Double.isNaN(value)) { - if (s.startsWith("&")) - s = s.substring(1); - Interpreter interp = Interpreter.getInstance(); - value = interp != null ? interp.getVariable2(s) : Double.NaN; - } - return value; - } - - /** - * Returns true if one or more of the numeric fields contained an invalid - * number. Must be called after one or more calls to getNextNumber(). - */ - public boolean invalidNumber() { - boolean wasInvalid = invalidNumber; - invalidNumber = false; - return wasInvalid; - } - - /** - * Returns an error message if getNextNumber was unable to convert a string into - * a number, otherwise, returns null. - */ - public String getErrorMessage() { - return errorMessage; - } - - /** Returns the contents of the next text field. */ - public String getNextString() { - String theText; - if (stringField == null) - return ""; - TextField tf = (TextField) (stringField.elementAt(sfIndex)); - theText = tf.getText(); - String label = labels != null ? (String) labels.get((Object) tf) : ""; - boolean numberExpected = theText != null && theText.length() > 0 && (Character.isDigit(theText.charAt(0)) || theText.startsWith("-")); - if (macro) { - theText = Macro.getValue(macroOptions, label, theText); - if (theText != null && (theText.startsWith("&") || numberExpected || label.toLowerCase(Locale.US).startsWith(theText))) { - // Is the value a macro variable? - if (theText.startsWith("&")) - theText = theText.substring(1); - Interpreter interp = Interpreter.getInstance(); - String s = interp != null ? interp.getVariableAsString(theText) : null; - if (s != null) - theText = s; - } - } - if (recorderOn && !label.equals("")) { - String s = theText; - if (s != null && s.length() >= 3 && Character.isLetter(s.charAt(0)) && s.charAt(1) == ':' && s.charAt(2) == '\\') - s = s.replaceAll("\\\\", "/"); // replace "\" with "/" in Windows file paths - s = Recorder.fixString(s); - if (!smartRecording || !s.equals((String) defaultStrings.elementAt(sfIndex))) - recordOption(tf, s); - else if (Recorder.getCommandOptions() == null) - Recorder.recordOption(" "); - } - sfIndex++; - return theText; - } - - /** Returns the state of the next checkbox. */ - public boolean getNextBoolean() { - if (checkbox == null) - return false; - /* Bio7 extra check for JCheckBox! */ - if (checkbox.elementAt(cbIndex) instanceof JCheckBox) { - JCheckBox cb = (JCheckBox) (checkbox.elementAt(cbIndex)); - if (recorderOn) - recordCheckboxOption(cb); - boolean state = cb.isSelected(); - if (macro) { - String label = (String) labels.get((Object) cb); - String key = Macro.trimKey(label); - state = isMatch(macroOptions, key + " "); - } - cbIndex++; - return state; - } else { - Checkbox cb = (Checkbox) (checkbox.elementAt(cbIndex)); - if (recorderOn) - recordCheckboxOption(cb); - boolean state = cb.getState(); - if (macro) { - String label = (String) labels.get((Object) cb); - String key = Macro.trimKey(label); - state = isMatch(macroOptions, key + " "); - } - cbIndex++; - return state; - - } - - } - - // Returns true if s2 is in s1 and not in a bracketed literal (e.g., - // "[literal]") - boolean isMatch(String s1, String s2) { - if (s1.startsWith(s2)) - return true; - s2 = " " + s2; - int len1 = s1.length(); - int len2 = s2.length(); - boolean match, inLiteral = false; - char c; - for (int i = 0; i < len1 - len2 + 1; i++) { - c = s1.charAt(i); - if (inLiteral && c == ']') - inLiteral = false; - else if (c == '[') - inLiteral = true; - if (c != s2.charAt(0) || inLiteral || (i > 1 && s1.charAt(i - 1) == '=')) - continue; - match = true; - for (int j = 0; j < len2; j++) { - if (s2.charAt(j) != s1.charAt(i + j)) { - match = false; - break; - } - } - if (match) - return true; - } - return false; - } - - /** Returns the selected item in the next popup menu. */ - public String getNextChoice() { - if (choice == null) - return ""; - Choice thisChoice = (Choice) (choice.elementAt(choiceIndex)); - String item = thisChoice.getSelectedItem(); - if (macro) { - String label = (String) labels.get((Object) thisChoice); - item = Macro.getValue(macroOptions, label, item); - if (item != null && item.startsWith("&")) // value is macro variable - item = getChoiceVariable(item); - } - if (recorderOn) - recordOption(thisChoice, item); - choiceIndex++; - return item; - } - - /** Returns the index of the selected item in the next popup menu. */ - public int getNextChoiceIndex() { - if (choice == null) - return -1; - Choice thisChoice = (Choice) (choice.elementAt(choiceIndex)); - int index = thisChoice.getSelectedIndex(); - if (macro) { - String label = (String) labels.get((Object) thisChoice); - String oldItem = thisChoice.getSelectedItem(); - int oldIndex = thisChoice.getSelectedIndex(); - String item = Macro.getValue(macroOptions, label, oldItem); - if (item != null && item.startsWith("&")) // value is macro variable - item = getChoiceVariable(item); - thisChoice.select(item); - index = thisChoice.getSelectedIndex(); - if (index == oldIndex && !item.equals(oldItem)) { - // is value a macro variable? - Interpreter interp = Interpreter.getInstance(); - String s = interp != null ? interp.getStringVariable(item) : null; - if (s == null) - IJ.error(getTitle(), "\"" + item + "\" is not a valid choice for \"" + label + "\""); - else - item = s; - } - } - if (recorderOn) { - int defaultIndex = ((Integer) (defaultChoiceIndexes.elementAt(choiceIndex))).intValue(); - if (!(smartRecording && index == defaultIndex)) { - String item = thisChoice.getSelectedItem(); - if (!(item.equals("*None*") && getTitle().equals("Merge Channels"))) - recordOption(thisChoice, thisChoice.getSelectedItem()); - } - } - choiceIndex++; - return index; - } - - /** Returns the selected item in the next radio button group. */ - public String getNextRadioButton() { - if (radioButtonGroups == null) - return null; - CheckboxGroup cg = (CheckboxGroup) (radioButtonGroups.elementAt(radioButtonIndex)); - radioButtonIndex++; - Checkbox checkbox = cg.getSelectedCheckbox(); - String item = "null"; - if (checkbox != null) - item = checkbox.getLabel(); - if (macro) { - String label = (String) labels.get((Object) cg); - item = Macro.getValue(macroOptions, label, item); - } - if (recorderOn) - recordOption(cg, item); - return item; - } - - private String getChoiceVariable(String item) { - item = item.substring(1); - Interpreter interp = Interpreter.getInstance(); - String s = interp != null ? interp.getStringVariable(item) : null; - if (s == null) { - double value = interp != null ? interp.getVariable2(item) : Double.NaN; - if (!Double.isNaN(value)) { - if ((int) value == value) - s = "" + (int) value; - else - s = "" + value; - } - } - if (s != null) - item = s; - return item; - } - - /** Returns the contents of the next text area. */ - public String getNextText() { - String text = null; - String key = "text1"; - if (textAreaIndex == 0 && textArea1 != null) { - text = textArea1.getText(); - if (macro) - text = Macro.getValue(macroOptions, "text1", text); - } else if (textAreaIndex == 1 && textArea2 != null) { - text = textArea2.getText(); - if (macro) - text = Macro.getValue(macroOptions, "text2", text); - key = "text2"; - } - textAreaIndex++; - if (recorderOn && text != null) { - String text2 = text; - String cmd = Recorder.getCommand(); - if (cmd != null && cmd.equals("Calibrate...")) - text2 = text2.replace('\n', ' '); - if (cmd != null && cmd.equals("Convolve...")) { - if (!text2.endsWith("\n")) - text2 += "\n"; - } - text2 = Recorder.fixString(text2); - Recorder.recordOption(key, text2); - } - return text; - } - - /** Displays this dialog box. */ - public void showDialog() { - showDialogCalled = true; - addToSameRow = false; - if (macro) { - dispose(); - recorderOn = Recorder.record && Recorder.recordInMacros; - } else { - if (pfr != null) // prepare preview (not in macro mode): tell the PlugInFilterRunner to listen - pfr.setDialog(this); - JPanel buttons = new JPanel(); - buttons.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 0)); - okay.addActionListener(this); - okay.addKeyListener(this); - if (!hideCancelButton) { - cancel.addActionListener(this); - cancel.addKeyListener(this); - } - if (no != null) { - no.addActionListener(this); - no.addKeyListener(this); - } - - boolean addHelp = helpURL != null; - if (addHelp) { - help.setLabel(helpLabel); - help.addActionListener(this); - help.addKeyListener(this); - } - if (IJ.isWindows() || Prefs.dialogCancelButtonOnRight) { - buttons.add(okay); - if (no != null) - buttons.add(no); - ; - if (!hideCancelButton) - buttons.add(cancel); - if (addHelp) - buttons.add(help); - } else { - if (addHelp) - buttons.add(help); - if (no != null) - buttons.add(no); - if (!hideCancelButton) - buttons.add(cancel); - buttons.add(okay); - } - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - } else { - c.gridx = 0; - c.gridy++; - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = addToSameRowCalled ? GridBagConstraints.REMAINDER : 2; - c.insets = new Insets(15, 0, 0, 0); - add(buttons, c); - instance = this; - Font font = getFont(); - if (!fontSizeSet && font != null && Prefs.getGuiScale() != 1.0) { - fontSizeSet = true; - setFont(font.deriveFont((float) (font.getSize() * Prefs.getGuiScale()))); - } - pack(); - if (okay != null && numberField == null && stringField == null && checkbox == null && choice == null && slider == null && radioButtonGroups == null && textArea1 == null) - okay.requestFocusInWindow(); - setup(); - if (centerDialog) - GUI.centerOnImageJScreen(this); - resetCounters(); - setVisible(true); // except for NonBlockingGenericDialog, returns after 'dispose' by OK or Cancel - } - } - - /** - * For plugins that read their input only via dialogItemChanged, call it at - * least once, then stop recording - */ - void finalizeRecording() { - if (optionsRecorded) - return; - optionsRecorded = true; - if (!wasCanceled && dialogListeners != null && dialogListeners.size() > 0) { - try { - resetCounters(); - ((DialogListener) dialogListeners.elementAt(0)).dialogItemChanged(this, null); - } catch (Exception err) { // for exceptions, don't cover the input by a window - IJ.beep(); // but show them at in the "Log" - IJ.log("ERROR: " + err + "\nin DialogListener of " + dialogListeners.elementAt(0) + "\nat " + (err.getStackTrace()[0]) + "\nfrom " + (err.getStackTrace()[1])); - } - recorderOn = false; - } - resetCounters(); - } - - @Override - public void setFont(Font font) { - super.setFont(!fontSizeSet && Prefs.getGuiScale() != 1.0 && font != null ? font.deriveFont((float) (font.getSize() * Prefs.getGuiScale())) : font); - fontSizeSet = true; - } - - /** Reset the counters before reading the dialog parameters */ - public void resetCounters() { - nfIndex = 0; // prepare for readout - sfIndex = 0; - cbIndex = 0; - choiceIndex = 0; - textAreaIndex = 0; - radioButtonIndex = 0; - invalidNumber = false; - } - - /** Returns the Vector containing the numeric TextFields. */ - public Vector getNumericFields() { - return numberField; - } - - /** Returns the Vector containing the string TextFields. */ - public Vector getStringFields() { - return stringField; - } - - /** Returns the Vector containing the Checkboxes. */ - public Vector getCheckboxes() { - return checkbox; - } - - /** Returns the Vector containing the Choices. */ - public Vector getChoices() { - return choice; - } - - /** Returns the Vector containing the sliders (Scrollbars). */ - public Vector getSliders() { - return slider; - } - - /** Returns the Vector that contains the RadioButtonGroups. */ - public Vector getRadioButtonGroups() { - return radioButtonGroups; - } - - /** Returns a reference to textArea1. */ - public TextArea getTextArea1() { - return textArea1; - } - - /** Returns a reference to textArea2. */ - public TextArea getTextArea2() { - return textArea2; - } - - /** - * Returns a reference to the Label or MultiLineLabel created by the last - * addMessage() call. Otherwise returns null. - */ - public Component getMessage() { - return theLabel; - } - - /** Returns a reference to the Preview checkbox. */ - public Checkbox getPreviewCheckbox() { - return previewCheckbox; - } - - /** Returns 'true' if this dialog has a "Preview" checkbox and it is enabled. */ - public boolean isPreviewActive() { - return previewCheckbox != null && previewCheckbox.getState(); - } - - /** - * Returns references to the "OK" ("Yes"), "Cancel", * "No", and "Help" buttons - * as an array of length 4. If a button is not present, the corresponding array - * element is null. - */ - public Button[] getButtons() { - return new Button[] { okay, cancel, no, help }; - } - - /** - * Used by PlugInFilterRunner to provide visable feedback whether preview is - * running or not by switching from "Preview" to "wait..." - */ - public void previewRunning(boolean isRunning) { - if (previewCheckbox != null) { - previewCheckbox.setLabel(isRunning ? previewRunning : previewLabel); - if (IJ.isMacOSX()) - repaint(); // workaround OSX 10.4 refresh bug - } - } - - /** Display dialog centered on the primary screen. */ - public void centerDialog(boolean b) { - centerDialog = b; - } - - /* Display the dialog at the specified location. */ - public void setLocation(int x, int y) { - super.setLocation(x, y); - centerDialog = false; - } - - public void setDefaultString(int index, String str) { - if (defaultStrings != null && index >= 0 && index < defaultStrings.size()) - defaultStrings.set(index, str); - } - - protected void setup() { - } - - public void actionPerformed(ActionEvent e) { - Object source = e.getSource(); - if (source == okay || source == cancel | source == no) { - wasCanceled = source == cancel; - wasOKed = source == okay; - dispose(); - } else if (source == help) { - if (hideCancelButton) { - if (helpURL != null && helpURL.equals("")) { - notifyListeners(e); - return; - } else { - wasOKed = true; - dispose(); - } - } - showHelp(); - } else - notifyListeners(e); - } - - public void textValueChanged(TextEvent e) { - notifyListeners(e); - if (slider == null) - return; - Object source = e.getSource(); - for (int i = 0; i < slider.size(); i++) { - int index = ((Integer) sliderIndexes.get(i)).intValue(); - if (source == numberField.elementAt(index)) { - TextField tf = (TextField) numberField.elementAt(index); - double value = Tools.parseDouble(tf.getText()); - if (!Double.isNaN(value)) { - Scrollbar sb = (Scrollbar) slider.elementAt(i); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - sb.setValue((int) Math.round(value * scale)); - } - } - } - } - - public void itemStateChanged(ItemEvent e) { - notifyListeners(e); - } - - public void focusGained(FocusEvent e) { - Component c = e.getComponent(); - // IJ.log("focusGained: "+c); - if (c instanceof TextField) - ((TextField) c).selectAll(); - } - - public void focusLost(FocusEvent e) { - Component c = e.getComponent(); - if (c instanceof TextField) - ((TextField) c).select(0, 0); - } - - public void keyPressed(KeyEvent e) { - Component component = e.getComponent(); - int keyCode = e.getKeyCode(); - IJ.setKeyDown(keyCode); - if ((component instanceof Scrollbar) && (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT)) { - Scrollbar sb = (Scrollbar) component; - int value = sb.getValue(); - if (keyCode == KeyEvent.VK_RIGHT) - sb.setValue(value + 1); - else - sb.setValue(value - 1); - for (int i = 0; i < slider.size(); i++) { - if (sb == slider.elementAt(i)) { - int index = ((Integer) sliderIndexes.get(i)).intValue(); - TextField tf = (TextField) numberField.elementAt(index); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - int digits = ((Integer) sliderDigits.get(i)).intValue(); - tf.setText("" + IJ.d2s(sb.getValue() / scale, digits)); - } - } - notifyListeners(e); - return; - } - if (keyCode == KeyEvent.VK_ENTER && textArea1 == null && okay != null && okay.isEnabled()) { - wasOKed = true; - if (IJ.isMacOSX()) - accessTextFields(); - dispose(); - } else if (keyCode == KeyEvent.VK_ESCAPE) { - wasCanceled = true; - dispose(); - IJ.resetEscape(); - } else if (keyCode == KeyEvent.VK_W && (e.getModifiers() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0) { - wasCanceled = true; - dispose(); - } - } - - void accessTextFields() { - if (stringField != null) { - for (int i = 0; i < stringField.size(); i++) - ((TextField) (stringField.elementAt(i))).getText(); - } - if (numberField != null) { - for (int i = 0; i < numberField.size(); i++) - ((TextField) (numberField.elementAt(i))).getText(); - } - } - - public void keyReleased(KeyEvent e) { - int keyCode = e.getKeyCode(); - IJ.setKeyUp(keyCode); - int flags = e.getModifiers(); - boolean control = (flags & KeyEvent.CTRL_MASK) != 0; - boolean meta = (flags & KeyEvent.META_MASK) != 0; - boolean shift = (flags & e.SHIFT_MASK) != 0; - if (keyCode == KeyEvent.VK_G && shift && (control || meta)) - new ScreenGrabber().run(""); - } - - public void keyTyped(KeyEvent e) { - } - - public Insets getInsets() { - Insets i = super.getInsets(); - return new Insets(i.top + 10, i.left + 10, i.bottom + 10, i.right + 10); - } - - /** Callback for sliders */ - public void adjustmentValueChanged(AdjustmentEvent e) { - Object source = e.getSource(); - for (int i = 0; i < slider.size(); i++) { - if (source == slider.elementAt(i)) { - Scrollbar sb = (Scrollbar) source; - int index = ((Integer) sliderIndexes.get(i)).intValue(); - TextField tf = (TextField) numberField.elementAt(index); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - int digits = ((Integer) sliderDigits.get(i)).intValue(); - tf.setText("" + IJ.d2s(sb.getValue() / scale, digits)); - } - } - } - - /** - * Notify any DialogListeners of changes having occurred If a listener returns - * false, do not call further listeners and disable the OK button and preview - * Checkbox (if it exists). For PlugInFilters, this ensures that the - * PlugInFilterRunner, which listens as the last one, is not called if the - * PlugInFilter has detected invalid parameters. Thus, unnecessary calling the - * run(ip) method of the PlugInFilter for preview is avoided in that case. - */ - private void notifyListeners(AWTEvent e) { - if (dialogListeners == null) - return; - boolean everythingOk = true; - for (int i = 0; everythingOk && i < dialogListeners.size(); i++) { - try { - resetCounters(); - if (this instanceof NonBlockingGenericDialog) - Recorder.resetCommandOptions(); - if (!((DialogListener) dialogListeners.elementAt(i)).dialogItemChanged(this, e)) - everythingOk = false; // disable further listeners if false (invalid parameters) returned - } catch (Exception err) { // for exceptions, don't cover the input by a window but - IJ.beep(); // show them at in the "Log" - IJ.log("ERROR: " + err + "\nin DialogListener of " + dialogListeners.elementAt(i) + "\nat " + (err.getStackTrace()[0]) + "\nfrom " + (err.getStackTrace()[1])); - } - } - resetCounters(); - boolean workaroundOSXbug = IJ.isMacOSX() && okay != null && !okay.isEnabled() && everythingOk; - if (everythingOk && recorderOn) - optionsRecorded = true; - if (previewCheckbox != null) - previewCheckbox.setEnabled(everythingOk); - if (okay != null) - okay.setEnabled(everythingOk); - if (workaroundOSXbug) - repaint(); // OSX 10.4 bug delays update of enabled until the next input - } - - public void repaint() { - super.repaint(); - if (imagePanels != null) { - for (int i = 0; i < imagePanels.size(); i++) - ((ImagePanel) imagePanels.get(i)).repaint(); - } - } - - public void paint(Graphics g) { - super.paint(g); - if (firstPaint && IJ.isMacOSX() && IJ.isJava18()) { // fix for incompletely drawn dialogs on Macs - EventQueue.invokeLater(new Runnable() { - public void run() { - IJ.wait(50); - Dimension size = getSize(); - if (size != null) - setSize(size.width + 2, size.height + 2); - firstPaint = false; - } - }); - } - } - - public void windowClosing(WindowEvent e) { - wasCanceled = true; - dispose(); - } - - /** - * Adds a "Help" button that opens the specified URL in the default browser. - * With v1.46b or later, displays an HTML formatted message if 'url' starts with - * "". There is an example at - * http://imagej.net/ij/macros/js/DialogWithHelp.js If url is an empty String, - * pressing the "Help" button does nothing except calling the DialogListeners - * (if any). See also: setHelpLabel. - */ - public void addHelp(String url) { - help = new Button(helpLabel); - helpURL = url; - } - - void showHelp() { - if (helpURL.startsWith("")) { - String title = getTitle() + " " + helpLabel; - if (this instanceof NonBlockingGenericDialog) - new HTMLDialog(title, helpURL, false); // non blocking - else - new HTMLDialog(this, title, helpURL); // modal - } else { - String macro = "call('ij.plugin.BrowserLauncher.open', '" + helpURL + "');"; - new MacroRunner(macro); // open on separate thread using BrowserLauncher - } - } - - protected boolean isMacro() { - return macro; - } - - public static GenericDialog getInstance() { - return instance; - } - - /** Closes the dialog; records the options */ - public void dispose() { - super.dispose(); - instance = null; - if (!macro) { - recorderOn = Recorder.record; - IJ.wait(25); - } - resetCounters(); - finalizeRecording(); - resetCounters(); - } - - /** - * Returns a reference to the label of the most recently added numeric field, - * string field, choice or slider. - */ - public Label getLabel() { - return lastLabelAdded; - } - - public void windowActivated(WindowEvent e) { - } - - public void windowOpened(WindowEvent e) { - } - - public void windowClosed(WindowEvent e) { - } - - public void windowIconified(WindowEvent e) { - } - - public void windowDeiconified(WindowEvent e) { - } - - public void windowDeactivated(WindowEvent e) { - } - - @SuppressWarnings("unchecked") - static String getString(DropTargetDropEvent event) throws IOException, UnsupportedFlavorException { - String text = null; - DataFlavor fileList = DataFlavor.javaFileListFlavor; - - if (event.isDataFlavorSupported(fileList)) { - event.acceptDrop(DnDConstants.ACTION_COPY); - java.util.List list = (java.util.List) event.getTransferable().getTransferData(fileList); - text = list.get(0).getAbsolutePath(); - } else if (event.isDataFlavorSupported(DataFlavor.stringFlavor)) { - event.acceptDrop(DnDConstants.ACTION_COPY); - text = (String) event.getTransferable().getTransferData(DataFlavor.stringFlavor); - if (text.startsWith("file://")) - text = text.substring(7); - text = stripSuffix(stripSuffix(text, "\n"), "\r").replaceAll("%20", " "); - } else { - event.rejectDrop(); - return null; - } - - event.dropComplete(text != null); - return text; - } - - static String stripSuffix(String s, String suffix) { - return !s.endsWith(suffix) ? s : s.substring(0, s.length() - suffix.length()); - } - - static class TextDropTarget extends DropTargetAdapter { - TextField text; - DataFlavor flavor = DataFlavor.stringFlavor; - - public TextDropTarget(TextField text) { - this.text = text; - } - - @Override - public void drop(DropTargetDropEvent event) { - try { - String path = getString(event); - path = Recorder.fixPath(path); - if (!path.endsWith("/") && (new File(path)).isDirectory()) - path = path + "/"; - text.setText(path); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - private class BrowseButtonListener implements ActionListener { - private String label; - private TextField textField; - private String mode; - - public BrowseButtonListener(String label, TextField textField, String mode) { - this.label = label; - this.textField = textField; - this.mode = mode; - } - - public void actionPerformed(ActionEvent e) { - String path = null; - String dialogTitle = label; - if (dialogTitle == null || dialogTitle.length() == 0) - dialogTitle = mode.equals("dir") ? "a Folder" : "a File"; - else if (dialogTitle.endsWith(":")) // remove trailing colon - dialogTitle = dialogTitle.substring(0, dialogTitle.length() - 1); - dialogTitle = "Select " + dialogTitle; - if (mode.equals("dir")) { - String saveDefaultDir = OpenDialog.getDefaultDirectory(); - String dir = this.textField.getText(); - boolean setDefaultDir = dir != null && !dir.equals(""); - if (setDefaultDir) - OpenDialog.setDefaultDirectory(dir); - path = IJ.getDir(dialogTitle); - if (setDefaultDir) - OpenDialog.setDefaultDirectory(saveDefaultDir); - } else { - OpenDialog od = new OpenDialog(dialogTitle, null); - String directory = od.getDirectory(); - String name = od.getFileName(); - if (name != null) - path = directory + name; - } - if (path != null) { - // if (IJ.isWindows()) - // path = path.replaceAll("\\\\", "/"); // replace "\" with "/" - this.textField.setText(path); - } - } - - } - - private class TrimmedTextField extends TextField { - - public TrimmedTextField(String text, int columns) { - super(text, columns); - } - - public Dimension getMinimumSize() { - Dimension d = super.getMinimumSize(); - if (d != null) { - d.width = d.width; - d.height = d.height * 3 / 4; - } - return d; - } - - public Dimension getPreferredSize() { - return getMinimumSize(); - } - - } - - /* Changed for Bio7! */ - - public void componentResized(ComponentEvent e) { - // TODO Auto-generated method stub - validate(); - repaint(); - - } - - @Override - public void componentMoved(ComponentEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void componentShown(ComponentEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void componentHidden(ComponentEvent e) { - // TODO Auto-generated method stub - - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/HTMLDialog.java b/com.eco.bio7.image/src/ij/gui/HTMLDialog.java deleted file mode 100644 index eb3e98866..000000000 --- a/com.eco.bio7.image/src/ij/gui/HTMLDialog.java +++ /dev/null @@ -1,154 +0,0 @@ -package ij.gui; -import ij.*; -import ij.plugin.URLOpener; -import ij.macro.MacroRunner; -import ij.util.Java2; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.text.*; -import javax.swing.text.html.*; -import javax.swing.event.HyperlinkListener; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkEvent.EventType; -import java.net.URL; - -/** This is modal or non-modal dialog box that displays HTML formated text. */ -public class HTMLDialog extends JDialog implements ActionListener, KeyListener, HyperlinkListener, WindowListener { - private boolean escapePressed; - private JEditorPane editorPane; - private boolean modal = true; - - public HTMLDialog(String title, String message) { - super(ij.IJ.getInstance(), title, true); - init(message); - } - - public HTMLDialog(Dialog parent, String title, String message) { - super(parent, title, true); - init(message); - } - - public HTMLDialog(String title, String message, boolean modal) { - super(ij.IJ.getInstance(), title, modal); - this.modal = modal; - init(message); - } - - private void init(String message) { - LookAndFeel saveLookAndFeel = Java2.getLookAndFeel(); - Java2.setSystemLookAndFeel(); - Container container = getContentPane(); - container.setLayout(new BorderLayout()); - if (message==null) message = ""; - editorPane = new JEditorPane("text/html",""); - editorPane.setEditable(false); - HTMLEditorKit kit = new HTMLEditorKit(); - editorPane.setEditorKit(kit); - StyleSheet styleSheet = kit.getStyleSheet(); - styleSheet.addRule("body{font-family:Verdana,sans-serif; font-size:11.5pt; margin:5px 10px 5px 10px;}"); //top right bottom left - styleSheet.addRule("h1{font-size:18pt;}"); - styleSheet.addRule("h2{font-size:15pt;}"); - styleSheet.addRule("dl dt{font-face:bold;}"); - editorPane.setText(message); //display the html text with the above style - editorPane.getActionMap().put("insert-break", new AbstractAction(){ - public void actionPerformed(ActionEvent e) {} - }); //suppress beep on key - JScrollPane scrollPane = new JScrollPane(editorPane); - container.add(scrollPane); - JButton button = new JButton("OK"); - button.addActionListener(this); - button.addKeyListener(this); - editorPane.addKeyListener(this); - editorPane.addHyperlinkListener(this); - JPanel panel = new JPanel(); - panel.add(button); - container.add(panel, "South"); - setForeground(Color.black); - addWindowListener(this); - pack(); - Dimension screenD = IJ.getScreenSize(); - Dimension dialogD = getSize(); - int maxWidth = (int)(Math.min(0.70*screenD.width, 800)); //max 70% of screen width, but not more than 800 pxl - if (maxWidth>400 && dialogD.width>maxWidth) - dialogD.width = maxWidth; - if ("Channels".equals(getTitle())) - dialogD.height = 1000; - if (dialogD.height>0.80*screenD.height && screenD.height>400) //max 80% of screen height - dialogD.height = (int)(0.80*screenD.height); - setSize(dialogD); - GUI.centerOnImageJScreen(this); - if (!modal) { - WindowManager.addWindow(this); - show(); - } - final JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar(); - if (verticalScrollBar!=null) { - EventQueue.invokeLater(new Runnable() { - public void run() { - verticalScrollBar.setValue(verticalScrollBar.getMinimum()); //start scrollbar at top - } - }); - } - if (modal) show(); - Java2.setLookAndFeel(saveLookAndFeel); - } - - public void actionPerformed(ActionEvent e) { - dispose(); - } - - public void keyPressed(KeyEvent e) { - int keyCode = e.getKeyCode(); - ij.IJ.setKeyDown(keyCode); - escapePressed = keyCode==KeyEvent.VK_ESCAPE; - if (keyCode==KeyEvent.VK_C) { - if (editorPane.getSelectedText()==null || editorPane.getSelectedText().length()==0) - editorPane.selectAll(); - editorPane.copy(); - editorPane.select(0,0); - } else if (keyCode==KeyEvent.VK_ENTER || keyCode==KeyEvent.VK_W || escapePressed) - dispose(); - } - - public void keyReleased(KeyEvent e) { - int keyCode = e.getKeyCode(); - ij.IJ.setKeyUp(keyCode); - } - - public void keyTyped(KeyEvent e) {} - - public boolean escapePressed() { - return escapePressed; - } - - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - String url = e.getDescription(); //getURL does not work for relative links within document such as "#top" - if (url==null) return; - if (url.startsWith("#")) - editorPane.scrollToReference(url.substring(1)); - else { - String macro = "run('URL...', 'url="+url+"');"; - new MacroRunner(macro); - } - } - } - - public void dispose() { - super.dispose(); - if (!modal) WindowManager.removeWindow(this); - } - - public void windowClosing(WindowEvent e) { - dispose(); - } - - public void windowActivated(WindowEvent e) {} - public void windowOpened(WindowEvent e) {} - public void windowClosed(WindowEvent e) {} - public void windowIconified(WindowEvent e) {} - public void windowDeiconified(WindowEvent e) {} - public void windowDeactivated(WindowEvent e) {} - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/HistogramPlot.java b/com.eco.bio7.image/src/ij/gui/HistogramPlot.java deleted file mode 100644 index 9271aef4c..000000000 --- a/com.eco.bio7.image/src/ij/gui/HistogramPlot.java +++ /dev/null @@ -1,409 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.plugin.filter.Analyzer; -import ij.measure.*; -import ij.macro.Interpreter; -import java.awt.*; -import java.awt.image.*; - -public class HistogramPlot extends ImagePlus { - static final double SCALE = Prefs.getGuiScale(); - static final int HIST_WIDTH = (int)(SCALE*256); - static final int HIST_HEIGHT = (int)(SCALE*128); - static final int XMARGIN = (int)(20*SCALE); - static final int YMARGIN = (int)(10*SCALE); - /* Changed for Bio7! Correction for the width else no plot is drawn! */ - static final int WIN_WIDTH = HIST_WIDTH + (int) (41 * SCALE); - static final int WIN_HEIGHT = HIST_HEIGHT + (int)(118*SCALE); - static final int BAR_HEIGHT = (int)(SCALE*12); - static final int INTENSITY1=0, INTENSITY2=1, RGB=2, RED=3, GREEN=4, BLUE=5; - static final Color frameColor = new Color(30,60,120); - - int rgbMode = -1; - ImageStatistics stats; - boolean stackHistogram; - Calibration cal; - long[] histogram; - LookUpTable lut; - int decimalPlaces; - int digits; - long newMaxCount; - boolean logScale; - int yMax; - int srcImageID; - Rectangle frame; - Font font = new Font("SansSerif",Font.PLAIN,(int)(12*SCALE)); - boolean showBins; - int col1, col2, row1, row2, row3, row4, row5; - - public HistogramPlot() { - setImage(NewImage.createRGBImage("Histogram", WIN_WIDTH, WIN_HEIGHT, 1, NewImage.FILL_WHITE)); - } - - /** Plots a histogram using the specified title and number of bins. - Currently, the number of bins must be 256 expect for 32 bit images. */ - public void draw(String title, ImagePlus imp, int bins) { - draw(imp, bins, 0.0, 0.0, 0); - } - - /** Plots a histogram using the specified title, number of bins and histogram range. - Currently, the number of bins must be 256 and the histogram range range must be - the same as the image range expect for 32 bit images. */ - public void draw(ImagePlus imp, int bins, double histMin, double histMax, int yMax) { - boolean limitToThreshold = (Analyzer.getMeasurements()&LIMIT)!=0; - ImageProcessor ip = imp.getProcessor(); - if (ip.isThreshold() && ip.getLutUpdateMode()==ImageProcessor.NO_LUT_UPDATE) - limitToThreshold = false; // ignore invisible thresholds - if (imp.isRGB() && rgbMode maxCount2) && (i != stats.mode)) { - maxCount2 = histogram[i]; - mode2 = i; - } - } - newMaxCount = histogram[stats.mode]; - if ((newMaxCount>(maxCount2 * 2)) && (maxCount2 != 0)) - newMaxCount = (int)(maxCount2 * 1.5); - if (logScale) - drawLogPlot(yMax>0?yMax:newMaxCount, ip); - drawPlot(yMax>0?yMax:newMaxCount, ip); - histogram[stats.mode] = saveModalCount; - x = XMARGIN + 1; - y = YMARGIN + HIST_HEIGHT + 2; - if (imp==null) - lut.drawUnscaledColorBar(ip, x-1, y, HIST_WIDTH, BAR_HEIGHT); - else - drawAlignedColorBar(imp, xMin, xMax, ip, x-1, y, HIST_WIDTH, BAR_HEIGHT); - y += BAR_HEIGHT+(int)(15*SCALE); - drawText(ip, x, y); - srcImageID = imp.getID(); - } - - void drawAlignedColorBar(ImagePlus imp, double xMin, double xMax, ImageProcessor ip, int x, int y, int width, int height) { - ImageProcessor ipSource = imp.getProcessor(); - float[] pixels = null; - ImageProcessor ipRamp = null; - if (rgbMode>=INTENSITY1) { - ipRamp = new FloatProcessor(width, height); - if (rgbMode==RED) - ipRamp.setColorModel(LUT.createLutFromColor(Color.red)); - else if (rgbMode==GREEN) - ipRamp.setColorModel(LUT.createLutFromColor(Color.green)); - else if (rgbMode==BLUE) - ipRamp.setColorModel(LUT.createLutFromColor(Color.blue)); - pixels = (float[])ipRamp.getPixels(); - } else - pixels = new float[width*height]; - for (int j=0; jipSource.getPixelCount()) { // stack histogram - cm = LUT.createLutFromColor(Color.white); - min = stats.min; - max = stats.max; - } else - cm = ((CompositeImage)imp).getChannelLut(); - } else if (!ipSource.isThreshold()) - cm = ipSource.getColorModel(); - else - cm = ipSource.getCurrentColorModel(); - ipRamp = new FloatProcessor(width, height, pixels, cm); - } - ipRamp.setMinAndMax(min,max); - ImageProcessor bar = null; - if (ip instanceof ColorProcessor) - bar = ipRamp.convertToRGB(); - else - bar = ipRamp.convertToByte(true); - ip.insert(bar, x,y); - ip.setColor(Color.black); - ip.drawRect(x-1, y, width+2, height); - } - - /** Scales a threshold level to the range 0-255. */ - int scaleDown(ImageProcessor ip, double threshold) { - double min = ip.getMin(); - double max = ip.getMax(); - if (max>min) - return (int)(((threshold-min)/(max-min))*255.0); - else - return 0; - } - - void drawPlot(long maxCount, ImageProcessor ip) { - if (frame == null) - frame = getDefaultFrame(); - drawPlot(histogram, maxCount, ip, frame, frameColor); - } - - /** Draws the histogram with linear scaling and the frame. - * Also used by HistogramWindow */ - static void drawPlot(long[] histogram, long maxCount, ImageProcessor ip, Rectangle frame, Color frameColor) { - if (maxCount==0) maxCount = 1; - if (histogram.length==256) { - double scale2 = HIST_WIDTH/256.0; - int barWidth = 1; - if (SCALE>1) barWidth=2; - if (SCALE>2) barWidth=3; - for (int i = 0; i < 256; i++) { - int x =(int)(i*scale2); - int y = (int)(((double)HIST_HEIGHT*(double)histogram[i])/maxCount); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - for (int j = 0; jHIST_HEIGHT) y = HIST_HEIGHT; - ip.drawLine(i+XMARGIN, YMARGIN+HIST_HEIGHT, i+XMARGIN, YMARGIN+HIST_HEIGHT-y); - } - } else { - double xscale = (double)HIST_WIDTH/histogram.length; - for (int i=0; i0L) { - int y = (int)(((double)HIST_HEIGHT*(double)value)/maxCount); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - int x = (int)(i*xscale)+XMARGIN; - ip.drawLine(x, YMARGIN+HIST_HEIGHT, x, YMARGIN+HIST_HEIGHT-y); - } - } - } - ip.setColor(frameColor); - ip.drawRect(frame.x-1, frame.y, frame.width+2, frame.height+1); - ip.setColor(Color.black); - } - - void drawLogPlot (long maxCount, ImageProcessor ip) { - if (frame == null) - frame = getDefaultFrame(); - drawLogPlot(histogram, maxCount, ip, frame); - } - - /** Draws the logarithm of histogram values in gray. To be called before the regular plot, - * which is then in the foreground. - * Also used by HistogramWindow */ - static void drawLogPlot(long[] histogram, long maxCount, ImageProcessor ip, Rectangle frame) { - ip.drawRect(frame.x-1, frame.y, frame.width+2, frame.height+1); - double max = Math.log(maxCount + 0.5); - ip.setColor(Color.gray); - if (histogram.length==256) { - double scale2 = HIST_WIDTH/256.0; - int barWidth = 1; - if (SCALE>1) barWidth=2; - if (SCALE>2) barWidth=3; - for (int i=0; i < 256; i++) { - int x =(int)(i*scale2); - int y = histogram[i]==0?0:(int)Math.max(HIST_HEIGHT*Math.log(histogram[i]+0.5)/max, 1); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - for (int j = 0; jHIST_HEIGHT) y = HIST_HEIGHT; - ip.drawLine(i+XMARGIN, YMARGIN+HIST_HEIGHT, i+XMARGIN, YMARGIN+HIST_HEIGHT-y); - } - } else { - double xscale = (double)HIST_WIDTH/histogram.length; - for (int i=0; i0L) { - int y = (int)Math.max(HIST_HEIGHT*Math.log(value+0.5)/max, 1); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - int x = (int)(i*xscale)+XMARGIN; - ip.drawLine(x, YMARGIN+HIST_HEIGHT, x, YMARGIN+HIST_HEIGHT-y); - } - } - } - ip.setColor(Color.black); - } - - void drawText(ImageProcessor ip, int x, int y) { - ip.setFont(font); - ip.setAntialiasedText(true); - double hmin = cal.getCValue(stats.histMin); - double hmax = cal.getCValue(stats.histMax); - ip.drawString(d2s(hmin), x - 4, y); - ip.drawString(d2s(hmax), x + HIST_WIDTH - getWidth(hmax, ip) + 10, y); - if (rgbMode>=INTENSITY1) { - x += HIST_WIDTH/2; - y += 1; - ip.setJustification(ImageProcessor.CENTER_JUSTIFY); - boolean weighted = ((ColorProcessor)ip).weightedHistogram(); - switch (rgbMode) { - case INTENSITY1: ip.drawString((weighted?"Intensity (weighted)":"Intensity (unweighted)"), x, y); break; - case INTENSITY2: ip.drawString((weighted?"Intensity (unweighted)":"Intensity (weighted)"), x, y); break; - case RGB: ip.drawString("R+G+B", x, y); break; - case RED: ip.drawString("Red", x, y); break; - case GREEN: ip.drawString("Green", x, y); break; - case BLUE: ip.drawString("Blue", x, y); break; - } - ip.setJustification(ImageProcessor.LEFT_JUSTIFY); - } - //double range = hmax-hmin; - //if (fixedRange&&!cal.calibrated()&&hmin==0&&hmax==255) - // range = 256; - double binWidth = stats.binSize; - binWidth = Math.abs(binWidth); - showBins = binWidth!=1.0; - col1 = XMARGIN + 5; - col2 = XMARGIN + HIST_WIDTH/2; - row1 = y+(int)(25*SCALE); - if (showBins) row1 -= (int)(8*SCALE); - row2 = row1 + (int)(15*SCALE); - row3 = row2 + (int)(15*SCALE); - row4 = row3 + (int)(15*SCALE); - row5 = row4 + (int)(15*SCALE); - long count = stats.longPixelCount>0?stats.longPixelCount:stats.pixelCount; - String modeCount = " (" + stats.maxCount + ")"; - if (histogram!=null) {// Add '*' if multi-modal histogram - int mcount = 0;; - for (int i=0; i1) break; - } - if (mcount>1) modeCount=modeCount+"*"; - } - if (modeCount.length()>12) modeCount = ""; - ip.drawString("N: " + count, col1, row1); - ip.drawString("Min: " + d2s(stats.min), col2, row1); - ip.drawString("Mean: " + d2s(stats.mean), col1, row2); - ip.drawString("Max: " + d2s(stats.max), col2, row2); - ip.drawString("StdDev: " + d2s(stats.stdDev), col1, row3); - ip.drawString("Mode: " + d2s(stats.dmode) + modeCount, col2, row3); - if (showBins) { - ip.drawString("Bins: " + d2s(stats.nBins), col1, row4); - ip.drawString("Bin Width: " + d2s(binWidth), col2, row4); - } - } - - /** Returns the default frame size. This is the size of the plot area excluding the - * line around. */ - static Rectangle getDefaultFrame() { - return new Rectangle(XMARGIN, YMARGIN, HIST_WIDTH, HIST_HEIGHT); - } - - private String d2s(double d) { - if ((int)d==d) - return IJ.d2s(d, 0); - else - return IJ.d2s(d, 3, 8); - } - - int getWidth(double d, ImageProcessor ip) { - return ip.getStringWidth(d2s(d)); - } - - public int[] getHistogram() { - int[] hist = new int[histogram.length]; - for (int i=0; i) ctab.getSelection().getData(); - JPanel current = (JPanel) ve.get(2); - current.add(buttons); - GUI.scale(buttons); - } - }); - CanvasView.getCanvas_view().getCurrent().validate(); - - } - - public void setup() { - setup(null); - } - - public void mouseMoved(int x, int y) { - ImageProcessor ip = this.imp != null ? this.imp.getProcessor() : null; - if (ip == null) - return; - if ((frame != null) && x >= frame.x && x <= (frame.x + frame.width)) { - /* Changed for Bio7! We have no frame margin! */ - x = x + 20 - frame.x; - x = (x - frame.x); - int index = (int) (x * (SCALE * histogram.length) / HIST_WIDTH / SCALE); - if (index < 0) - index = 0; - if (index >= histogram.length) - index = histogram.length - 1; - double value = cal.getCValue(stats.histMin + index * stats.binSize); - drawValueAndCount(ip, value, histogram[index]); - } else - drawValueAndCount(ip, Double.NaN, -1); - this.imp.updateAndDraw(); - } - - protected void drawHistogram(ImageProcessor ip, boolean fixedRange) { - drawHistogram(null, ip, fixedRange, 0.0, 0.0); - } - - void drawHistogram(ImagePlus imp, ImageProcessor ip, boolean fixedRange, double xMin, double xMax) { - if (frame == null) - frame = HistogramPlot.getDefaultFrame(); - int x, y; - long maxCount2 = 0; - int mode2 = 0; - long saveModalCount; - ip.setColor(Color.black); - ip.setLineWidth(1); - decimalPlaces = Analyzer.getPrecision(); - digits = cal.calibrated() || stats.binSize != 1.0 ? decimalPlaces : 0; - saveModalCount = histogram[stats.mode]; - for (int i = 0; i < histogram.length; i++) { - if ((histogram[i] > maxCount2) && (i != stats.mode)) { - maxCount2 = histogram[i]; - mode2 = i; - } - } - newMaxCount = histogram[stats.mode]; - if ((newMaxCount > (maxCount2 * 2)) && (maxCount2 != 0)) - newMaxCount = (int) (maxCount2 * 1.5); - if (logScale || IJ.shiftKeyDown() && !liveMode()) - HistogramPlot.drawLogPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame); - HistogramPlot.drawPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame, Color.BLACK); - histogram[stats.mode] = saveModalCount; - x = XMARGIN + 1; - y = YMARGIN + HIST_HEIGHT + 2; - if (imp == null) - lut.drawUnscaledColorBar(ip, x - 1, y, HIST_WIDTH, BAR_HEIGHT); - else - drawAlignedColorBar(imp, xMin, xMax, ip, x - 1, y, HIST_WIDTH, BAR_HEIGHT); - y += BAR_HEIGHT + (int) (15 * SCALE); - drawText(ip, x, y, fixedRange); - srcImageID = imp.getID(); - } - - void drawAlignedColorBar(ImagePlus imp, double xMin, double xMax, ImageProcessor ip, int x, int y, int width, int height) { - ImageProcessor ipSource = imp.getProcessor(); - float[] pixels = null; - ImageProcessor ipRamp = null; - if (rgbMode >= INTENSITY1) { - ipRamp = new FloatProcessor(width, height); - if (rgbMode == RED) - ipRamp.setColorModel(LUT.createLutFromColor(Color.red)); - else if (rgbMode == GREEN) - ipRamp.setColorModel(LUT.createLutFromColor(Color.green)); - else if (rgbMode == BLUE) - ipRamp.setColorModel(LUT.createLutFromColor(Color.blue)); - pixels = (float[]) ipRamp.getPixels(); - } else - pixels = new float[width * height]; - for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i++) - pixels[i + width * j] = (float) (xMin + i * (xMax - xMin) / (width - 1)); - } - double min = ipSource.getMin(); - double max = ipSource.getMax(); - if (ipSource.getNChannels() == 1) { - ColorModel cm = null; - if (imp.isComposite()) { - if (stats != null && stats.pixelCount > ipSource.getPixelCount()) { // stack histogram - cm = LUT.createLutFromColor(Color.white); - min = stats.min; - max = stats.max; - } else - cm = ((CompositeImage) imp).getChannelLut(); - } else if (!ipSource.isThreshold()) - cm = ipSource.getColorModel(); - else - cm = ipSource.getCurrentColorModel(); - ipRamp = new FloatProcessor(width, height, pixels, cm); - } - ipRamp.setMinAndMax(min, max); - ImageProcessor bar = null; - if (ip instanceof ColorProcessor) - bar = ipRamp.convertToRGB(); - else - bar = ipRamp.convertToByte(true); - ip.insert(bar, x, y); - ip.setColor(Color.black); - ip.drawRect(x - 1, y, width + 2, height); - } - - /** Scales a threshold level to the range 0-255. */ - int scaleDown(ImageProcessor ip, double threshold) { - double min = ip.getMin(); - double max = ip.getMax(); - if (max > min) - return (int) (((threshold - min) / (max - min)) * 255.0); - else - return 0; - } - - void drawText(ImageProcessor ip, int x, int y, boolean fixedRange) { - ip.setFont(font); - ip.setAntialiasedText(true); - double hmin = cal.getCValue(stats.histMin); - double hmax = cal.getCValue(stats.histMax); - ip.drawString(d2s(hmin), x - 4, y); - ip.drawString(d2s(hmax), x + HIST_WIDTH - getWidth(hmax, ip) + 10, y); - if (rgbMode >= INTENSITY1) { - x += HIST_WIDTH / 2; - y += 1; - ip.setJustification(ImageProcessor.CENTER_JUSTIFY); - boolean weighted = ((ColorProcessor) ip).weightedHistogram(); - switch (rgbMode) { - case INTENSITY1: - ip.drawString((weighted ? "Intensity (weighted)" : "Intensity (unweighted)"), x, y); - break; - case INTENSITY2: - ip.drawString((weighted ? "Intensity (unweighted)" : "Intensity (weighted)"), x, y); - break; - case RGB: - ip.drawString("R+G+B", x, y); - break; - case RED: - ip.drawString("Red", x, y); - break; - case GREEN: - ip.drawString("Green", x, y); - break; - case BLUE: - ip.drawString("Blue", x, y); - break; - } - ip.setJustification(ImageProcessor.LEFT_JUSTIFY); - } - double binWidth = stats.binSize; - binWidth = Math.abs(binWidth); - showBins = binWidth != 1.0 || !fixedRange; - col1 = XMARGIN + 5; - col2 = XMARGIN + HIST_WIDTH / 2; - row1 = y + (int) (25 * SCALE); - if (showBins) - row1 -= (int) (8 * SCALE); - row2 = row1 + (int) (15 * SCALE); - row3 = row2 + (int) (15 * SCALE); - row4 = row3 + (int) (15 * SCALE); - row5 = row4 + (int) (15 * SCALE); - long count = stats.longPixelCount > 0 ? stats.longPixelCount : stats.pixelCount; - String modeCount = " (" + stats.maxCount + ")"; - if (histogram != null) {// Add '*' if multi-modal histogram - int mcount = 0; - ; - for (int i = 0; i < histogram.length; i++) - if (histogram[i] == stats.maxCount) - mcount++; - if (mcount > 1) - modeCount = modeCount + "*"; - } - if (modeCount.length() > 12) - modeCount = ""; - - ip.drawString("N: " + count, col1, row1); - ip.drawString("Min: " + d2s(stats.min), col2, row1); - ip.drawString("Mean: " + d2s(stats.mean), col1, row2); - ip.drawString("Max: " + d2s(stats.max), col2, row2); - ip.drawString("StdDev: " + d2s(stats.stdDev), col1, row3); - ip.drawString("Mode: " + d2s(stats.dmode) + modeCount, col2, row3); - if (showBins) { - ip.drawString("Bins: " + d2s(stats.nBins), col1, row4); - ip.drawString("Bin Width: " + d2s(binWidth), col2, row4); - } - drawValueAndCount(ip, Double.NaN, -1); - } - - private void drawValueAndCount(ImageProcessor ip, double value, long count) { - int y = showBins ? row4 : row3; - ip.setRoi(0, y, WIN_WIDTH, WIN_HEIGHT - y); - ip.setColor(Color.white); - ip.fill(); - ip.setColor(Color.black); - String sValue = Double.isNaN(value) ? "---" : d2s(value); - String sCount = count == -1 ? "---" : "" + count; - int row = showBins ? row5 : row4; - ip.drawString("Value: " + sValue, col1, row); - ip.drawString("Count: " + sCount, col2, row); - } - - private String d2s(double d) { - if ((int) d == d) - return IJ.d2s(d, 0); - else - return IJ.d2s(d, 3, 8); - } - - int getWidth(double d, ImageProcessor ip) { - return ip.getStringWidth(d2s(d)); - } - - /** Returns the histogram values as a ResultsTable. */ - public ResultsTable getResultsTable() { - int decimalPlaces = Analyzer.getPrecision(); - if (digits == 0 && stats.binSize != 1.0) - digits = decimalPlaces; - ResultsTable rt = new ResultsTable(); - rt.setPrecision(digits); - String vheading = stats.binSize == 1.0 ? "value" : "bin start"; - if (cal.calibrated() && !cal.isSigned16Bit()) { - for (int i = 0; i < stats.nBins; i++) { - rt.setValue("level", i, i); - rt.setValue(vheading, i, cal.getCValue(stats.histMin + i * stats.binSize)); - rt.setValue("count", i, histogram[i]); - } - } else { - for (int i = 0; i < stats.nBins; i++) { - if (stats.binSize != 1.0) - rt.setValue("index", i, i); - rt.setValue(vheading, i, cal.getCValue(stats.histMin + i * stats.binSize)); - rt.setValue("count", i, histogram[i]); - } - } - return rt; - } - - public void showList() { - ResultsTable rt = getResultsTable(); - rt.show(getTitle()); - } - - protected void copyToClipboard() { - Clipboard systemClipboard = null; - try { - systemClipboard = getToolkit().getSystemClipboard(); - } catch (Exception e) { - systemClipboard = null; - } - if (systemClipboard == null) { - IJ.error("Unable to copy to Clipboard."); - return; - } - IJ.showStatus("Copying histogram values..."); - CharArrayWriter aw = new CharArrayWriter(stats.nBins * 4); - PrintWriter pw = new PrintWriter(aw); - for (int i = 0; i < stats.nBins; i++) - pw.print(ResultsTable.d2s(cal.getCValue(stats.histMin + i * stats.binSize), digits) + "\t" + histogram[i] + "\n"); - String text = aw.toString(); - pw.close(); - StringSelection contents = new StringSelection(text); - systemClipboard.setContents(contents, this); - IJ.showStatus(text.length() + " characters copied to Clipboard"); - } - - void replot() { - ImageProcessor ip = this.imp.getProcessor(); - frame = new Rectangle(XMARGIN, YMARGIN, HIST_WIDTH, HIST_HEIGHT); - ip.setColor(Color.white); - ip.setRoi(frame.x - 1, frame.y, frame.width + 2, frame.height); - ip.fill(); - ip.resetRoi(); - ip.setColor(Color.black); - ip.setLineWidth(1); - if (logScale) - HistogramPlot.drawLogPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame); - HistogramPlot.drawPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame, Color.BLACK); - this.imp.updateAndDraw(); - } - - public void actionPerformed(ActionEvent e) { - Object b = e.getSource(); - if (b == live) - toggleLiveMode(); - else if (b == rgb) - changeChannel(); - else if (b == list) { - showList(); - if (!Recorder.scriptMode()) - Recorder.record("Table.showHistogramTable"); - } else if (b == copy) - copyToClipboard(); - else if (b == log) { - logScale = !logScale; - replot(); - } - } - - public void lostOwnership(Clipboard clipboard, Transferable contents) { - } - - public int[] getHistogram() { - int[] hist = new int[histogram.length]; - for (int i = 0; i < histogram.length; i++) - hist[i] = (int) histogram[i]; - return hist; - } - - public double[] getXValues() { - double[] values = new double[stats.nBins]; - for (int i = 0; i < stats.nBins; i++) - values[i] = cal.getCValue(stats.histMin + i * stats.binSize); - return values; - } - - private void toggleLiveMode() { - if (liveMode()) - removeListeners(); - else - enableLiveMode(); - } - - private void changeChannel() { - ImagePlus imp = WindowManager.getImage(srcImageID); - if (imp == null || !imp.isRGB()) - return; - else { - rgbMode++; - if (rgbMode > BLUE) - rgbMode = INTENSITY1; - ColorProcessor cp = (ColorProcessor) imp.getProcessor(); - boolean weighted = cp.weightedHistogram(); - if (rgbMode == INTENSITY2) { - double[] weights = cp.getRGBWeights(); - if (weighted) - cp.setRGBWeights(1d / 3d, 1d / 3d, 1d / 3d); - else - cp.setRGBWeights(0.299, 0.587, 0.114); - showHistogram(imp, 256); - cp.setRGBWeights(weights); - } else - showHistogram(imp, 256); - } - } - - private boolean liveMode() { - return live != null && live.getForeground() == Color.red; - } - - private void enableLiveMode() { - if (bgThread == null) { - srcImp = WindowManager.getImage(srcImageID); - if (srcImp == null) - return; - bgThread = new Thread(this, "Live Histogram"); - bgThread.setPriority(Math.max(bgThread.getPriority() - 3, Thread.MIN_PRIORITY)); - bgThread.start(); - imageUpdated(srcImp); - } - createListeners(); - if (srcImp != null) - imageUpdated(srcImp); - } - - // Unused - public void imageOpened(ImagePlus imp) { - } - - // This listener is called if the source image content is changed - public synchronized void imageUpdated(ImagePlus imp) { - if (imp == srcImp) { - doUpdate = true; - notify(); - } - } - - public synchronized void roiModified(ImagePlus img, int id) { - if (img == srcImp) { - doUpdate = true; - notify(); - } - } - - // If either the source image or this image are closed, exit - public void imageClosed(ImagePlus imp) { - if (imp == srcImp || imp == this.imp) { - if (bgThread != null) - bgThread.interrupt(); - bgThread = null; - removeListeners(); - srcImp = null; - } - } - - // the background thread for live plotting. - public void run() { - while (true) { - if (doUpdate && srcImp != null) { - if (srcImp.getRoi() != null) - IJ.wait(50); // delay to make sure the roi has been updated - if (srcImp != null) { - if (srcImp.getBitDepth() == 16 && ImagePlus.getDefault16bitRange() != 0) - showHistogram(srcImp, 256, 0, Math.pow(2, ImagePlus.getDefault16bitRange()) - 1); - else - showHistogram(srcImp, 256); - } - } - synchronized (this) { - if (doUpdate) { - doUpdate = false; // and loop again - } else { - try { - wait(); - } // notify wakes up the thread - catch (InterruptedException e) { // interrupted tells the thread to exit - return; - } - } - } - } - } - - private void createListeners() { - if (srcImp == null) - return; - ImagePlus.addImageListener(this); - Roi.addRoiListener(this); - if (live != null) { - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); - live.setForeground(Color.red); - } - } - - private void removeListeners() { - if (srcImp == null) - return; - ImagePlus.removeImageListener(this); - Roi.removeRoiListener(this); - if (live != null) { - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.PLAIN, font.getSize())); - // live.setForeground(Color.black); - Color swtForegroundToAWT = Util.getSWTForegroundToAWT(); - live.setForeground(swtForegroundToAWT); - } - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImageCanvas.java b/com.eco.bio7.image/src/ij/gui/ImageCanvas.java deleted file mode 100644 index 70d1014fd..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageCanvas.java +++ /dev/null @@ -1,2236 +0,0 @@ -package ij.gui; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Event; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Frame; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Insets; -import java.awt.MenuItem; -import java.awt.Point; -import java.awt.PopupMenu; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.event.InputEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; -import java.awt.event.WindowEvent; -import java.awt.image.IndexColorModel; -import java.util.Timer; -import java.util.TimerTask; -import java.util.Vector; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.swing.JPanel; - -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; - -import com.eco.bio7.ImageJPluginActions.ImageJContextMenuAction; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.Util; - -import ij.IJ; -import ij.ImageJ; -import ij.ImagePlus; -import ij.Menus; -import ij.Prefs; -import ij.WindowManager; -import ij.macro.MacroRunner; -import ij.measure.ResultsTable; -import ij.plugin.PointToolOptions; -import ij.plugin.WandToolOptions; -import ij.plugin.frame.Recorder; -import ij.plugin.frame.RoiManager; -import ij.plugin.tool.PlugInTool; -import ij.process.FloatPolygon; -import ij.util.Tools; - -/** This is a Canvas used to display images in a Window. */ -public class ImageCanvas extends JPanel implements MouseListener, MouseWheelListener, MouseMotionListener, Cloneable { - - protected static Cursor defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR); - protected static Cursor handCursor = new Cursor(Cursor.HAND_CURSOR); - protected static Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR); - protected static Cursor crosshairCursor = new Cursor(Cursor.CROSSHAIR_CURSOR); - - public static boolean usePointer = Prefs.usePointerCursor; - - protected ImagePlus imp; - protected boolean imageUpdated; - protected Rectangle srcRect; - protected int imageWidth, imageHeight; - protected int xMouse; // current cursor offscreen x location - protected int yMouse; // current cursor offscreen y location - - private boolean showCursorStatus = true; - private int sx2, sy2; - private boolean disablePopupMenu; - private static Color zoomIndicatorColor; - private static Font smallFont, largeFont; - private Font font; - private Rectangle[] labelRects; - private boolean maxBoundsReset; - private Overlay showAllOverlay; - private static final int LIST_OFFSET = 100000; - private static Color showAllColor = Prefs.getColor(Prefs.SHOW_ALL_COLOR, new Color(0, 255, 255)); - private Color defaultColor = showAllColor; - private static Color labelColor, bgColor; - private int resetMaxBoundsCount; - private Roi currentRoi; - private int mousePressedX, mousePressedY; - private long mousePressedTime; - private boolean overOverlayLabel; - private Shell tempShell; - - /** - * If the mouse moves less than this in screen pixels, successive zoom - * operations are on the same image pixel - */ - protected final static int MAX_MOUSEMOVE_ZOOM = 10; - /** - * Screen coordinates where the last zoom operation was done (initialized to - * impossible value) - */ - protected int lastZoomSX = -9999999; - protected int lastZoomSY = -9999999; - /** - * Image (=offscreen) coordinates where the cursor was moved to for zooming - */ - protected int zoomTargetOX = -1; - protected int zoomTargetOY; - - protected ImageJ ij; - protected double magnification; - protected int dstWidth, dstHeight; - - protected int xMouseStart; - protected int yMouseStart; - protected int xSrcStart; - protected int ySrcStart; - protected int flags; - - private Image offScreenImage; - private int offScreenWidth = 0; - private int offScreenHeight = 0; - private boolean mouseExited = true; - private boolean customRoi; - private boolean drawNames; - private AtomicBoolean paintPending; - private boolean scaleToFit; - private boolean painted; - private boolean hideZoomIndicator; - private boolean flattening; - private Timer pressTimer; - private PopupMenu roiPopupMenu; - private static int longClickDelay = 1000; // ms - - public ImageCanvas(ImagePlus imp) { - this.imp = imp; - paintPending = new AtomicBoolean(false); - ij = IJ.getInstance(); - int width = imp.getWidth(); - int height = imp.getHeight(); - imageWidth = width; - imageHeight = height; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize(imageWidth, imageHeight); - magnification = 1.0; - addMouseListener(this); - addMouseMotionListener(this); - /* Changed for Bio7! */ - addMouseWheelListener(this); - addKeyListener(ij); // ImageJ handles keyboard shortcuts - setFocusTraversalKeysEnabled(false); - setFocusable(true); - } - - void updateImage(ImagePlus imp) { - this.imp = imp; - int width = imp.getWidth(); - int height = imp.getHeight(); - imageWidth = width; - imageHeight = height; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize(imageWidth, imageHeight); - magnification = 1.0; - } - - /** - * Update this ImageCanvas to have the same zoom and scale settings as the one - * specified. - */ - void update(ImageCanvas ic) { - if (ic == null || ic == this || ic.imp == null) - return; - if (ic.imp.getWidth() != imageWidth || ic.imp.getHeight() != imageHeight) - return; - srcRect = new Rectangle(ic.srcRect.x, ic.srcRect.y, ic.srcRect.width, ic.srcRect.height); - setMagnification(ic.magnification); - setSize(ic.dstWidth, ic.dstHeight); - } - - /** Sets the region of the image (in pixels) to be displayed. */ - public void setSourceRect(Rectangle r) { - if (r == null) - return; - r = new Rectangle(r.x, r.y, r.width, r.height); - imageWidth = imp.getWidth(); - imageHeight = imp.getHeight(); - if (r.x < 0) - r.x = 0; - if (r.y < 0) - r.y = 0; - if (r.width < 1) - r.width = 1; - if (r.height < 1) - r.height = 1; - if (r.width > imageWidth) - r.width = imageWidth; - if (r.height > imageHeight) - r.height = imageHeight; - if (r.x + r.width > imageWidth) - r.x = imageWidth - r.width; - if (r.y + r.height > imageHeight) - r.y = imageHeight - r.height; - if (srcRect == null) - srcRect = r; - else { - srcRect.x = r.x; - srcRect.y = r.y; - srcRect.width = r.width; - srcRect.height = r.height; - } - if (dstWidth == 0) { - Dimension size = getSize(); - dstWidth = size.width; - dstHeight = size.height; - } - magnification = (double) dstWidth / srcRect.width; - imp.setTitle(imp.getTitle()); - if (IJ.debugMode) - IJ.log("setSourceRect: " + magnification + " " + (int) (srcRect.height * magnification + 0.5) + " " + dstHeight + " " + srcRect); - } - - void setSrcRect(Rectangle srcRect) { - setSourceRect(srcRect); - } - - public Rectangle getSrcRect() { - return srcRect; - } - - /** Obsolete; replaced by setSize() */ - public void setDrawingSize(int width, int height) { - dstWidth = width; - dstHeight = height; - setSize(dstWidth, dstHeight); - } - - public void setSize(int width, int height) { - super.setSize(width, height); - dstWidth = width; - dstHeight = height; - } - - /** - * ImagePlus.updateAndDraw calls this method to force the paint() method to - * update the image from the ImageProcessor. - */ - public void setImageUpdated() { - imageUpdated = true; - } - - public void setPaintPending(boolean state) { - paintPending.set(state); - } - - public boolean getPaintPending() { - return paintPending.get(); - } - - /* Changed for Bio7! */ - /* - * public void update(Graphics g) { paint(g); } - */ - /* Changed for Bio7! */ - public void paintComponent(Graphics g) { - super.paintComponent(g); - painted = true; - Roi roi = imp.getRoi(); - - Overlay overlay = imp.getOverlay(); - if (roi != null || overlay != null || showAllOverlay != null || Prefs.paintDoubleBuffered || (IJ.isLinux() && magnification < 0.25)) { - if (roi != null) - roi.updatePaste(); - } - - /* Changed for Bio7! */ - // Already double buffered because we use a JPanel here! - - /* - * if (roi != null || overlay != null || showAllOverlay != null || - * Prefs.paintDoubleBuffered || (IJ.isLinux() && magnification < 0.25)) { // Use - * double buffering to avoid flickering of ROIs and to work around // a Linux - * problem with large images not showing at low magnification. if (roi != null) - * roi.updatePaste(); if (imageWidth != 0) { paintDoubleBuffered(g); - * setPaintPending(false); return; } } - */ - try { - if (imageUpdated) { - imageUpdated = false; - imp.updateImage(); - } - setInterpolation(g, Prefs.interpolateScaledImages); - Image img = imp.getImage(); - if (img != null) - g.drawImage(img, 0, 0, (int) (srcRect.width * magnification + 0.5), (int) (srcRect.height * magnification + 0.5), srcRect.x, srcRect.y, srcRect.x + srcRect.width, - srcRect.y + srcRect.height, null); - if (overlay != null) - drawOverlay(overlay, g); - if (showAllOverlay != null) - drawOverlay(showAllOverlay, g); - if (roi != null) - drawRoi(roi, g); - if (srcRect.width < imageWidth || srcRect.height < imageHeight) - drawZoomIndicator(g); - /* Changed for Bio7! */ - JPanel current = CanvasView.getCanvas_view().getCurrent(); - if (current != null) { - Rectangle maxWindow = current.getBounds(); - if (maxWindow.width / magnification < imageWidth || maxWindow.height / magnification < imageHeight) - drawZoomIndicator(g); - // if (IJ.debugMode) - // showFrameRate(g); - } - } catch (OutOfMemoryError e) { - IJ.outOfMemory("Paint"); - } - setPaintPending(false); - } - - private void setInterpolation(Graphics g, boolean interpolate) { - if (magnification == 1) - return; - else if (magnification < 1.0 || interpolate) { - Object value = RenderingHints.VALUE_RENDER_QUALITY; - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, value); - } else if (magnification > 1.0) { - Object value = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, value); - } - } - - private void drawRoi(Roi roi, Graphics g) { - if (roi == currentRoi) { - Color lineColor = roi.getStrokeColor(); - Color fillColor = roi.getFillColor(); - float lineWidth = roi.getStrokeWidth(); - roi.setStrokeColor(null); - roi.setFillColor(null); - boolean strokeSet = roi.getStroke() != null; - if (strokeSet) - roi.setStrokeWidth(1); - roi.draw(g); - roi.setStrokeColor(lineColor); - if (strokeSet) - roi.setStrokeWidth(lineWidth); - roi.setFillColor(fillColor); - currentRoi = null; - } else - roi.draw(g); - } - - public int getSliceNumber(String label) { - if (label == null) - return 0; - int slice = 0; - if (label.length() >= 14 && label.charAt(4) == '-' && label.charAt(9) == '-') - slice = (int) Tools.parseDouble(label.substring(0, 4), 0); - else if (label.length() >= 17 && label.charAt(5) == '-' && label.charAt(11) == '-') - slice = (int) Tools.parseDouble(label.substring(0, 5), 0); - else if (label.length() >= 20 && label.charAt(6) == '-' && label.charAt(13) == '-') - slice = (int) Tools.parseDouble(label.substring(0, 6), 0); - return slice; - } - - private void drawOverlay(Overlay overlay, Graphics g) { - if (imp != null && imp.getHideOverlay() && overlay != showAllOverlay) - return; - flattening = imp != null && ImagePlus.flattenTitle.equals(imp.getTitle()); - if (imp != null && showAllOverlay != null && overlay != showAllOverlay) - overlay.drawLabels(false); - Color labelColor = overlay.getLabelColor(); - if (labelColor == null) - labelColor = Color.white; - initGraphics(overlay, g, labelColor, Roi.getColor()); - int n = overlay.size(); - int currentImage = imp != null ? imp.getCurrentSlice() : -1; - int stackSize = imp.getStackSize(); - if (stackSize == 1) - currentImage = -1; - int channel = 0, slice = 0, frame = 0; - boolean hyperstack = imp.isHyperStack(); - if (imp.getNChannels() > 1) - hyperstack = true; - if (hyperstack) { - channel = imp.getChannel(); - slice = imp.getSlice(); - frame = imp.getFrame(); - } - drawNames = overlay.getDrawNames() && overlay.getDrawLabels(); - boolean drawLabels = drawNames || overlay.getDrawLabels(); - if (drawLabels) - labelRects = new Rectangle[n]; - else - labelRects = null; - font = overlay.getLabelFont(); - if (overlay.scalableLabels() && font != null) { - double mag = getMagnification(); - if (mag != 1.0) - font = font.deriveFont((float) (font.getSize() * mag)); - } - Roi activeRoi = imp.getRoi(); - boolean roiManagerShowAllMode = overlay == showAllOverlay && !Prefs.showAllSliceOnly; - for (int i = 0; i < n; i++) { - if (overlay == null) - break; - Roi roi = overlay.get(i); - if (roi == null) - break; - int c = roi.getCPosition(); - int z = roi.getZPosition(); - int t = roi.getTPosition(); - if (hyperstack) { - int position = roi.getPosition(); - if (position > 0) { - if (imp.getNChannels() == stackSize) { - c = position; - z = t = 0; - - } else if (imp.getNSlices() == stackSize) { - z = position; - c = t = 0; - } else if (imp.getNFrames() == stackSize) { - t = position; - c = z = 0; - - } - } - boolean match = (c == 0 || c == channel) && (z == 0 || z == slice) && (t == 0 || t == frame); - // IJ.log("drawOverlay1: i="+i+", pos="+roi.getPosition()+" "+c+" "+z+" "+t+" - // "+match+" "+roiManagerShowAllMode); - if (match || roiManagerShowAllMode || position == PointRoi.POINTWISE_POSITION) - drawRoi(g, roi, drawLabels ? i + LIST_OFFSET : -1); - } else { - int position = stackSize > 1 ? roi.getPosition() : 0; - if (stackSize > 1 && position == 0 && c == 1) { - if (z == 1) - position = t; - else if (t == 1) - position = z; - } - if (position == 0 && stackSize > 1) - position = getSliceNumber(roi.getName()); - if (position > 0 && imp.getCompositeMode() == IJ.COMPOSITE) - position = 0; - if (position == PointRoi.POINTWISE_POSITION) - position = 0; - if ((roi instanceof PointRoi) && Prefs.showAllPoints) - position = 0; - if (position == 0 || position == currentImage || roiManagerShowAllMode) - drawRoi(g, roi, drawLabels ? i + LIST_OFFSET : -1); - } - } - ((Graphics2D) g).setStroke(Roi.onePixelWide); - drawNames = false; - font = null; - } - - void drawOverlay(Graphics g) { - drawOverlay(imp.getOverlay(), g); - } - - private void initGraphics(Overlay overlay, Graphics g, Color textColor, Color defaultColor) { - if (smallFont == null) { - smallFont = new Font("SansSerif", Font.PLAIN, 9); - largeFont = IJ.font12; - } - if (textColor != null) { - labelColor = textColor; - if (overlay != null && overlay.getDrawBackgrounds()) { - double brightness = (labelColor.getRed() + labelColor.getGreen() + labelColor.getBlue()) / 3.0; - if (labelColor == Color.green) - brightness = 255; - bgColor = brightness <= 85 ? Color.white : Color.black; - } else - bgColor = null; - } else { - int red = defaultColor.getRed(); - int green = defaultColor.getGreen(); - int blue = defaultColor.getBlue(); - if ((red + green + blue) / 3 < 128) - labelColor = Color.white; - else - labelColor = Color.black; - bgColor = defaultColor; - } - this.defaultColor = defaultColor; - Font font = overlay != null ? overlay.getLabelFont() : null; - if (font != null && font.getSize() > 12) - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - g.setColor(defaultColor); - } - - void drawRoi(Graphics g, Roi roi, int index) { - ImagePlus imp2 = roi.getImage(); - roi.setImage(imp); - Color saveColor = roi.getStrokeColor(); - if (saveColor == null && roi.getFillColor() == null) - roi.setStrokeColor(defaultColor); - if (roi.getStroke() == null) - ((Graphics2D) g).setStroke(Roi.onePixelWide); - if (roi instanceof TextRoi) - ((TextRoi) roi).drawText(g); - else - roi.drawOverlay(g); - roi.setStrokeColor(saveColor); - if (index >= 0) { - if (roi == currentRoi) - g.setColor(Roi.getColor()); - else - g.setColor(defaultColor); - drawRoiLabel(g, index, roi); - } - if (imp2 != null) - roi.setImage(imp2); - else - roi.setImage(null); - } - - void drawRoiLabel(Graphics g, int index, Roi roi) { - if (roi.isCursor()) - return; - boolean pointRoi = roi instanceof PointRoi; - Rectangle r = roi.getBounds(); - int x = screenX(r.x); - int y = screenY(r.y); - double mag = getMagnification(); - int width = (int) (r.width * mag); - int height = (int) (r.height * mag); - int size = width > 40 || height > 40 ? 12 : 9; - int pointSize = 0; - int crossSize = 0; - if (pointRoi) { - pointSize = ((PointRoi) roi).getSize(); - switch (pointSize) { - case 0: - case 1: - size = 9; - break; - case 2: - case 3: - size = 10; - break; - case 4: - size = 12; - break; - } - crossSize = pointSize + 10 + 2 * pointSize; - } - if (font != null) { - g.setFont(font); - size = font.getSize(); - } else if (size == 12) - g.setFont(largeFont); - else - g.setFont(smallFont); - boolean drawingList = index >= LIST_OFFSET; - if (drawingList) - index -= LIST_OFFSET; - String label = "" + (index + 1); - if (drawNames) - label = roi.getName(); - if (label == null) - return; - FontMetrics metrics = g.getFontMetrics(); - int w = metrics.stringWidth(label); - x = x + width / 2 - w / 2; - y = y + height / 2 + Math.max(size / 2, 6); - int h = metrics.getAscent() + metrics.getDescent(); - int xoffset = 0, yoffset = 0; - if (pointRoi) { - xoffset = 6 + pointSize; - yoffset = h - 6 + pointSize; - } - if (bgColor != null) { - int h2 = h; - if (font != null && font.getSize() > 14) - h2 = (int) (h2 * 0.8); - g.setColor(bgColor); - g.fillRoundRect(x - 1 + xoffset, y - h2 + 2 + yoffset, w + 1, h2 - 2, 5, 5); - } - if (labelRects != null && index < labelRects.length) { - if (pointRoi) { - int x2 = screenX(r.x); - int y2 = screenY(r.y); - int crossSize2 = crossSize / 2; - labelRects[index] = new Rectangle(x2 - crossSize2, y2 - crossSize2, crossSize, crossSize); - } else - labelRects[index] = new Rectangle(x - 3, y - h + 1, w + 4, h); - } - g.setColor(labelColor); - g.drawString(label, x + xoffset, y - 2 + yoffset); - g.setColor(defaultColor); - } - - void drawZoomIndicator(Graphics g) { - if (hideZoomIndicator) - return; - int x1 = 10; - int y1 = 10; - double aspectRatio = (double) imageHeight / imageWidth; - int w1 = 64; - if (aspectRatio > 1.0) - w1 = (int) (w1 / aspectRatio); - int h1 = (int) (w1 * aspectRatio); - if (w1 < 4) - w1 = 4; - if (h1 < 4) - h1 = 4; - int w2 = (int) (w1 * ((double) srcRect.width / imageWidth)); - int h2 = (int) (h1 * ((double) srcRect.height / imageHeight)); - if (w2 < 1) - w2 = 1; - if (h2 < 1) - h2 = 1; - int x2 = (int) (w1 * ((double) srcRect.x / imageWidth)); - int y2 = (int) (h1 * ((double) srcRect.y / imageHeight)); - if (zoomIndicatorColor == null) - zoomIndicatorColor = new Color(128, 128, 255); - g.setColor(zoomIndicatorColor); - ((Graphics2D) g).setStroke(Roi.onePixelWide); - g.drawRect(x1, y1, w1, h1); - if (w2 * h2 <= 200 || w2 < 10 || h2 < 10) - g.fillRect(x1 + x2, y1 + y2, w2, h2); - else - g.drawRect(x1 + x2, y1 + y2, w2, h2); - } - - // Use double buffer to reduce flicker when drawing complex ROIs. - // Author: Erik Meijering - void paintDoubleBuffered(Graphics g) { - final int srcRectWidthMag = (int) (srcRect.width * magnification + 0.5); - final int srcRectHeightMag = (int) (srcRect.height * magnification + 0.5); - if (offScreenImage == null || offScreenWidth != srcRectWidthMag || offScreenHeight != srcRectHeightMag) { - offScreenImage = createImage(srcRectWidthMag, srcRectHeightMag); - offScreenWidth = srcRectWidthMag; - offScreenHeight = srcRectHeightMag; - } - Roi roi = imp.getRoi(); - try { - if (imageUpdated) { - imageUpdated = false; - imp.updateImage(); - } - Graphics offScreenGraphics = offScreenImage.getGraphics(); - setInterpolation(offScreenGraphics, Prefs.interpolateScaledImages); - Image img = imp.getImage(); - if (img != null) - offScreenGraphics.drawImage(img, 0, 0, srcRectWidthMag, srcRectHeightMag, srcRect.x, srcRect.y, srcRect.x + srcRect.width, srcRect.y + srcRect.height, null); - Overlay overlay = imp.getOverlay(); - if (overlay != null) - drawOverlay(overlay, offScreenGraphics); - if (showAllOverlay != null) - drawOverlay(showAllOverlay, offScreenGraphics); - if (roi != null) - drawRoi(roi, offScreenGraphics); - if (srcRect.width < imageWidth || srcRect.height < imageHeight) - drawZoomIndicator(offScreenGraphics); - // if (IJ.debugMode) - // showFrameRate(offScreenGraphics); - g.drawImage(offScreenImage, 0, 0, null); - } catch (OutOfMemoryError e) { - IJ.outOfMemory("Paint"); - } - } - - public void resetDoubleBuffer() { - offScreenImage = null; - } - - long firstFrame; - int frames, fps; - - void showFrameRate(Graphics g) { - frames++; - if (System.currentTimeMillis() > firstFrame + 1000) { - firstFrame = System.currentTimeMillis(); - fps = frames; - frames = 0; - } - g.setColor(Color.white); - g.fillRect(10, 12, 50, 15); - g.setColor(Color.black); - g.drawString((int) (fps + 0.5) + " fps", 10, 25); - } - - public Dimension getPreferredSize() { - return new Dimension(dstWidth, dstHeight); - } - - /** Returns the current cursor location in image coordinates. */ - public Point getCursorLoc() { - return new Point(xMouse, yMouse); - } - - /** Returns 'true' if the cursor is over this image. */ - public boolean cursorOverImage() { - return !mouseExited; - } - - /** Returns the mouse event modifiers. */ - public int getModifiers() { - return flags; - } - - /** - * Returns the ImagePlus object that is associated with this ImageCanvas. - */ - public ImagePlus getImage() { - return imp; - } - - /** Sets the cursor based on the current tool and cursor location. */ - public void setCursor(int sx, int sy, int ox, int oy) { - xMouse = ox; - yMouse = oy; - mouseExited = false; - Roi roi = imp.getRoi(); - ImageWindow win = imp.getWindow(); - overOverlayLabel = false; - if (win == null) - return; - if (IJ.spaceBarDown()) { - setCursor(handCursor); - return; - } - int id = Toolbar.getToolId(); - switch (id) { - case Toolbar.MAGNIFIER: - setCursor(moveCursor); - break; - case Toolbar.HAND: - setCursor(handCursor); - break; - default: // selection tool - PlugInTool tool = Toolbar.getPlugInTool(); - boolean arrowTool = roi != null && (roi instanceof Arrow) && tool != null && "Arrow Tool".equals(tool.getToolName()); - if ((id >= Toolbar.CUSTOM1) && !arrowTool) { - if (Prefs.usePointerCursor) - setCursor(defaultCursor); - else - setCursor(crosshairCursor); - } else if (roi != null && roi.getState() != roi.CONSTRUCTING && roi.isHandle(sx, sy) >= 0) { - setCursor(handCursor); - } else if ((imp.getOverlay() != null || showAllOverlay != null) && overOverlayLabel(sx, sy, ox, oy) && (roi == null || roi.getState() != roi.CONSTRUCTING)) { - overOverlayLabel = true; - setCursor(handCursor); - } else if (Prefs.usePointerCursor || (roi != null && roi.getState() != roi.CONSTRUCTING && roi.contains(ox, oy))) - setCursor(defaultCursor); - else - setCursor(crosshairCursor); - } - } - - private boolean overOverlayLabel(int sx, int sy, int ox, int oy) { - Overlay o = showAllOverlay; - if (o == null) - o = imp.getOverlay(); - if (o == null || !o.isSelectable() || !o.isDraggable() || !o.getDrawLabels() || labelRects == null) - return false; - for (int i = o.size() - 1; i >= 0; i--) { - if (labelRects != null && labelRects[i] != null && labelRects[i].contains(sx, sy)) { - Roi roi = imp.getRoi(); - if (roi == null || !roi.contains(ox, oy)) - return true; - else - return false; - } - } - return false; - } - - /** - * Converts a screen x-coordinate to an offscreen x-coordinate (nearest pixel - * center). - */ - public int offScreenX(int sx) { - return srcRect.x + (int) (sx / magnification); - } - - /** - * Converts a screen y-coordinate to an offscreen y-coordinate (nearest pixel - * center). - */ - public int offScreenY(int sy) { - return srcRect.y + (int) (sy / magnification); - } - - /** - * Converts a screen x-coordinate to an offscreen x-coordinate (Roi coordinate - * of nearest pixel border). - */ - public int offScreenX2(int sx) { - return srcRect.x + (int) Math.round(sx / magnification); - } - - /** - * Converts a screen y-coordinate to an offscreen y-coordinate (Roi coordinate - * of nearest pixel border). - */ - public int offScreenY2(int sy) { - return srcRect.y + (int) Math.round(sy / magnification); - } - - /** - * Converts a screen x-coordinate to a floating-point offscreen x-coordinate. - */ - public double offScreenXD(int sx) { - return srcRect.x + sx / magnification; - } - - /** - * Converts a screen y-coordinate to a floating-point offscreen y-coordinate. - */ - public double offScreenYD(int sy) { - return srcRect.y + sy / magnification; - - } - - /** Converts an offscreen x-coordinate to a screen x-coordinate. */ - public int screenX(int ox) { - return (int) ((ox - srcRect.x) * magnification); - } - - /** Converts an offscreen y-coordinate to a screen y-coordinate. */ - public int screenY(int oy) { - return (int) ((oy - srcRect.y) * magnification); - } - - /** - * Converts a floating-point offscreen x-coordinate to a screen x-coordinate. - */ - public int screenXD(double ox) { - return (int) ((ox - srcRect.x) * magnification); - } - - /** - * Converts a floating-point offscreen x-coordinate to a screen x-coordinate. - */ - public int screenYD(double oy) { - return (int) ((oy - srcRect.y) * magnification); - } - - public double getMagnification() { - return magnification; - } - - public void setMagnification(double magnification) { - setMagnification2(magnification); - } - - void setMagnification2(double magnification) { - if (magnification > 32.0) - magnification = 32.0; - if (magnification < zoomLevels[0]) - magnification = zoomLevels[0]; - this.magnification = magnification; - imp.setTitle(imp.getTitle()); - } - - /** Resizes the canvas when the user resizes the window. */ - void resizeCanvas(int width, int height) { - ImageWindow win = imp.getWindow(); - if (!maxBoundsReset && (width > dstWidth || height > dstHeight) && win != null && win.maxBounds != null && width != win.maxBounds.width - 10) { - if (resetMaxBoundsCount != 0) - resetMaxBounds(); // Works around problem that prevented window - // from being larger than maximized size - resetMaxBoundsCount++; - } - if (scaleToFit || IJ.altKeyDown()) { - fitToWindow(); - return; - } - if (width > imageWidth * magnification) - width = (int) (imageWidth * magnification); - if (height > imageHeight * magnification) - height = (int) (imageHeight * magnification); - Dimension size = getSize(); - if (srcRect.width < imageWidth || srcRect.height < imageHeight || (painted && (width != size.width || height != size.height))) { - setSize(width, height); - srcRect.width = (int) (dstWidth / magnification); - srcRect.height = (int) (dstHeight / magnification); - if ((srcRect.x + srcRect.width) > imageWidth) - srcRect.x = imageWidth - srcRect.width; - if ((srcRect.y + srcRect.height) > imageHeight) - srcRect.y = imageHeight - srcRect.height; - repaint(); - } - } - - public void fitToWindow() { - ImageWindow win = imp.getWindow(); - if (win == null) - return; - Rectangle bounds = win.getBounds(); - Insets insets = win.getInsets(); // do not include small window padding - int sliderHeight = win.getSliderHeight(); - double xmag = (double) (bounds.width - (insets.left + insets.right + ImageWindow.HGAP * 2)) / srcRect.width; - double ymag = (double) (bounds.height - (ImageWindow.VGAP * 2 + insets.top + insets.bottom + sliderHeight)) / srcRect.height; - setMagnification(Math.min(xmag, ymag)); - int width = (int) (imageWidth * magnification); - int height = (int) (imageHeight * magnification); - if (width == dstWidth && height == dstHeight) - return; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize(width, height); - // getParent().validate(); - /* Changed for Bio7 */ - CanvasView.getCurrent().validate(); - } - - void setMaxBounds() { - if (maxBoundsReset) { - maxBoundsReset = false; - ImageWindow win = imp.getWindow(); - if (win != null && !IJ.isLinux() && win.maxBounds != null) { - win.setMaximizedBounds(win.maxBounds); - win.setMaxBoundsTime = System.currentTimeMillis(); - } - } - } - - void resetMaxBounds() { - ImageWindow win = imp.getWindow(); - if (win != null && (System.currentTimeMillis() - win.setMaxBoundsTime) > 500L) { - win.setMaximizedBounds(win.maxWindowBounds); - maxBoundsReset = true; - } - } - - private static final double[] zoomLevels = { 1 / 72.0, 1 / 48.0, 1 / 32.0, 1 / 24.0, 1 / 16.0, 1 / 12.0, 1 / 8.0, 1 / 6.0, 1 / 4.0, 1 / 3.0, 1 / 2.0, 0.75, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, - 16.0, 24.0, 32.0 }; - - public static double getLowerZoomLevel(double currentMag) { - double newMag = zoomLevels[0]; - for (int i = 0; i < zoomLevels.length; i++) { - if (zoomLevels[i] < currentMag) - newMag = zoomLevels[i]; - else - break; - } - return newMag; - } - - public static double getHigherZoomLevel(double currentMag) { - double newMag = 32.0; - for (int i = zoomLevels.length - 1; i >= 0; i--) { - if (zoomLevels[i] > currentMag) - newMag = zoomLevels[i]; - else - break; - } - return newMag; - } - - /** - * Zooms in by making the window bigger. If it can't be made bigger, then makes - * the source rectangle (srcRect) smaller and centers it on the position in the - * image where the cursor was when zooming has started. Note that sx and sy are - * screen coordinates. - */ - public void zoomIn(int sx, int sy) { - - if (magnification >= 32) - return; - scaleToFit = false; - boolean mouseMoved = sqr(sx - lastZoomSX) + sqr(sy - lastZoomSY) > MAX_MOUSEMOVE_ZOOM * MAX_MOUSEMOVE_ZOOM; - lastZoomSX = sx; - lastZoomSY = sy; - if (mouseMoved || zoomTargetOX < 0) { - boolean cursorInside = sx >= 0 && sy >= 0 && sx < dstWidth && sy < dstHeight; - zoomTargetOX = offScreenX(cursorInside ? sx : dstWidth / 2); // where to zoom, offscreen (image) coordinates - zoomTargetOY = offScreenY(cursorInside ? sy : dstHeight / 2); - } - double newMag = getHigherZoomLevel(magnification); - int newWidth = (int) (imageWidth * newMag); - int newHeight = (int) (imageHeight * newMag); - Rectangle dim = CanvasView.getCurrent().getBounds(); - Dimension newSize = new Dimension(newWidth, newHeight); - // System.out.println(newWidth+" "+dim.width+" "+newHeight+" "+dim.height); - if (newWidth < dim.width && newHeight < dim.height) { - - setSize(newSize.width, newSize.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - - if (newSize.width != newWidth || newSize.height != newHeight) - adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); - else - setMagnification(newMag); - - } else if (newWidth > dim.width && newHeight < dim.height) { - setSize(newSize.width, newSize.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - setMagnification(newMag); - - } else if (newWidth < dim.width && newHeight > dim.height) { - setSize(newSize.width, newSize.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - setMagnification(newMag); - - } - - // Dimension newSize = canEnlarge(newWidth, newHeight); - else // can't enlarge window - setSize(dim.width, dim.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); - // CanvasView.getCurrent().validate(); - repaint(); - if (srcRect.width < imageWidth || srcRect.height < imageHeight) - resetMaxBounds(); - // fitToWindow(); - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the layout! */ - CanvasView.parent2.layout(); - - } - }); - CanvasView.getCurrent().validate(); - IJTabs.doSecondaryViewLayout(); - } - - /** Centers the viewable area on offscreen (image) coordinates x, y */ - void adjustSourceRect(double newMag, int x, int y) { - int w = (int) Math.round(dstWidth / newMag); - if (w * newMag < dstWidth) - w++; - int h = (int) Math.round(dstHeight / newMag); - if (h * newMag < dstHeight) - h++; - Rectangle r = new Rectangle(x - w / 2, y - h / 2, w, h); - if (r.x < 0) - r.x = 0; - if (r.y < 0) - r.y = 0; - if (r.x + w > imageWidth) - r.x = imageWidth - w; - if (r.y + h > imageHeight) - r.y = imageHeight - h; - srcRect = r; - setMagnification(newMag); - } - - /** - * Zooms in by making the window bigger. If it can't be made bigger, then makes - * the source rectangle (srcRect) smaller and centers it on the position in the - * image where the cursor was when zooming has started. Note that sx and sy are - * screen coordinates. - */ - /* - * public void zoomIn(int sx, int sy) { - * - * if (magnification >= 32) return; scaleToFit = false; boolean mouseMoved = - * sqr(sx - lastZoomSX) + sqr(sy - lastZoomSY) > MAX_MOUSEMOVE_ZOOM * - * MAX_MOUSEMOVE_ZOOM; lastZoomSX = sx; lastZoomSY = sy; if (mouseMoved || - * zoomTargetOX < 0) { boolean cursorInside = sx >= 0 && sy >= 0 && sx < - * dstWidth && sy < dstHeight; zoomTargetOX = offScreenX(cursorInside ? sx : - * dstWidth / 2); // where to zoom, offscreen (image) coordinates zoomTargetOY = - * offScreenY(cursorInside ? sy : dstHeight / 2); } double newMag = - * getHigherZoomLevel(magnification); // System.out.println(newMag); int - * newWidth = (int) (imageWidth * newMag); int newHeight = (int) (imageHeight * - * newMag); Dimension newSize = canEnlarge(newWidth, newHeight); Rectangle - * clientArea = CanvasView.getCurrent().getBounds(); if (newSize != null) { - * setSize(newSize.width, newSize.height); - * //imp.getWindow().scResizeEvent(newSize.width, newSize.height); - * - * if (newSize.width != newWidth || newSize.height != newHeight) { - * - * Changed for the SWT parent. If the next zoom level runs out of the max width - * we increase the size to the max of the parent! - * - * if (newSize.width != newWidth) { newSize = new Dimension(clientArea.width, - * newSize.height); setSize(newSize.width, newSize.height); // - * System.out.println("resize"); //imp.getWindow().scResizeEvent(newSize.width, - * newSize.height); } - * - * If the next zoom level runs out of the max height we increase the height to - * the max of the parent! - * - * else { Changed for the SWT parent. Resize to max parent! newSize = new - * Dimension(newSize.width, clientArea.height); setSize(newSize.width, - * newSize.height); // System.out.println("resize"); - * //imp.getWindow().scResizeEvent(newSize.width, newSize.height); - * - * } adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); } else { - * - * setMagnification(newMag); } imp.getWindow().pack(); - * //imp.getWindow().parentComposite.layout(); } else { // can't enlarge window. - * Maximize it! - * - * newSize = new Dimension(clientArea.width, clientArea.height); - * setSize(newSize.width, newSize.height); // System.out.println("resize"); - * //imp.getWindow().scResizeEvent(newSize.width, newSize.height); - * adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); // - * System.out.println("this is null"); } repaint(); - * - * - * - * } - */ - - /** - * Returns the size to which the window can be enlarged, or null if it can't be - * enlarged. newWidth, newHeight is the size needed for showing the - * full image at the magnification needed - */ - protected Dimension canEnlarge(int newWidth, int newHeight) { - if (IJ.altKeyDown()) - return null; - ImageWindow win = imp.getWindow(); - if (win == null) - return null; - Rectangle r1 = win.getBounds(); - Insets insets = win.getInsets(); - Point loc = getLocation(); - if (loc.x > insets.left + 5 || loc.y > insets.top + 5) { - r1.width = newWidth + insets.left + insets.right + ImageWindow.HGAP * 2; - r1.height = newHeight + insets.top + insets.bottom + ImageWindow.VGAP * 2 + win.getSliderHeight(); - } else { - r1.width = r1.width - dstWidth + newWidth; - r1.height = r1.height - dstHeight + newHeight; - } - Rectangle max = GUI.getMaxWindowBounds(win); - boolean fitsHorizontally = r1.x + r1.width < max.x + max.width; - boolean fitsVertically = r1.y + r1.height < max.y + max.height; - if (fitsHorizontally && fitsVertically) - return new Dimension(newWidth, newHeight); - else if (fitsVertically && newHeight < dstWidth) - return new Dimension(dstWidth, newHeight); - else if (fitsHorizontally && newWidth < dstHeight) - return new Dimension(newWidth, dstHeight); - /* - * else return null; - */ - /* Changed for Bio7! */ - else - return new Dimension(max.width, max.height); - } - - /** - * Zooms out by making the source rectangle (srcRect) larger and centering it on - * (x,y). If we can't make it larger, then make the window smaller. Note that sx - * and sy are screen coordinates. - */ - public void zoomOut(int sx, int sy) { - if (magnification <= zoomLevels[0]) - return; - boolean mouseMoved = sqr(sx - lastZoomSX) + sqr(sy - lastZoomSY) > MAX_MOUSEMOVE_ZOOM * MAX_MOUSEMOVE_ZOOM; - lastZoomSX = sx; - lastZoomSY = sy; - if (mouseMoved || zoomTargetOX < 0) { - boolean cursorInside = sx >= 0 && sy >= 0 && sx < dstWidth && sy < dstHeight; - zoomTargetOX = offScreenX(cursorInside ? sx : dstWidth / 2); // where - // to - // zoom, - // offscreen - // (image) - // coordinates - zoomTargetOY = offScreenY(cursorInside ? sy : dstHeight / 2); - } - double oldMag = magnification; - double newMag = getLowerZoomLevel(magnification); - double srcRatio = (double) srcRect.width / srcRect.height; - double imageRatio = (double) imageWidth / imageHeight; - double initialMag = imp.getWindow().getInitialMagnification(); - if (Math.abs(srcRatio - imageRatio) > 0.05) { - double scale = oldMag / newMag; - int newSrcWidth = (int) Math.round(srcRect.width * scale); - int newSrcHeight = (int) Math.round(srcRect.height * scale); - if (newSrcWidth > imageWidth) - newSrcWidth = imageWidth; - if (newSrcHeight > imageHeight) - newSrcHeight = imageHeight; - int newSrcX = srcRect.x - (newSrcWidth - srcRect.width) / 2; - int newSrcY = srcRect.y - (newSrcHeight - srcRect.height) / 2; - if (newSrcX + newSrcWidth > imageWidth) - newSrcX = imageWidth - newSrcWidth; - if (newSrcY + newSrcHeight > imageHeight) - newSrcY = imageHeight - newSrcHeight; - if (newSrcX < 0) - newSrcX = 0; - if (newSrcY < 0) - newSrcY = 0; - srcRect = new Rectangle(newSrcX, newSrcY, newSrcWidth, newSrcHeight); - int newDstWidth = (int) (srcRect.width * newMag); - int newDstHeight = (int) (srcRect.height * newMag); - setMagnification(newMag); - setMaxBounds(); - if (newDstWidth < dstWidth || newDstHeight < dstHeight) { - setSize(newDstWidth, newDstHeight); - imp.getWindow().pack(); - } else - repaint(); - /* Changes for Bio7! */ - // CanvasView.getCurrent().invalidate(); - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the layout! */ - CanvasView.parent2.layout(); - - } - }); - CanvasView.getCurrent().validate(); - // adjustSourceRect(newMag, sx, sy); - - return; - } - if (imageWidth * newMag > dstWidth) { - int w = (int) Math.round(dstWidth / newMag); - if (w * newMag < dstWidth) - w++; - int h = (int) Math.round(dstHeight / newMag); - if (h * newMag < dstHeight) - h++; - Rectangle r = new Rectangle(zoomTargetOX - w / 2, zoomTargetOY - h / 2, w, h); - if (r.x < 0) - r.x = 0; - if (r.y < 0) - r.y = 0; - if (r.x + w > imageWidth) - r.x = imageWidth - w; - if (r.y + h > imageHeight) - r.y = imageHeight - h; - srcRect = r; - setMagnification(newMag); - } else { - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize((int) (imageWidth * newMag), (int) (imageHeight * newMag)); - setMagnification(newMag); - imp.getWindow().pack(); - } - setMaxBounds(); - repaint(); - /* Changes for Bio7! */ - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the layout! */ - CanvasView.parent2.layout(); - - } - - }); - CanvasView.getCurrent().doLayout(); - IJTabs.doSecondaryViewLayout(); - // adjustSourceRect(newMag, sx, sy); - } - - int sqr(int x) { - return x * x; - } - - /** Implements the Image/Zoom/Original Scale command. */ - public void unzoom() { - double imag = imp.getWindow().getInitialMagnification(); - if (magnification == imag) - return; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - ImageWindow win = imp.getWindow(); - setSize((int) (imageWidth * imag), (int) (imageHeight * imag)); - setMagnification(imag); - setMaxBounds(); - win.pack(); - setMaxBounds(); - repaint(); - /* Changed for Bio7! */ - CanvasView.getCurrent().validate(); - } - - /** Implements the Image/Zoom/View 100% command. */ - public void zoom100Percent() { - if (magnification == 1.0) - return; - double imag = imp.getWindow().getInitialMagnification(); - if (magnification != imag) - unzoom(); - if (magnification == 1.0) - return; - if (magnification < 1.0) { - while (magnification < 1.0) - zoomIn(imageWidth / 2, imageHeight / 2); - } else if (magnification > 1.0) { - while (magnification > 1.0) - zoomOut(imageWidth / 2, imageHeight / 2); - } else - return; - int x = xMouse, y = yMouse; - if (mouseExited) { - x = imageWidth / 2; - y = imageHeight / 2; - } - int sx = screenX(x); - int sy = screenY(y); - adjustSourceRect(1.0, sx, sy); - repaint(); - /* Changed for Bio7! */ - CanvasView.getCurrent().validate(); - } - - protected void scroll(int sx, int sy) { - int ox = xSrcStart + (int) (sx / magnification); // convert to offscreen - // coordinates - int oy = ySrcStart + (int) (sy / magnification); - int newx = xSrcStart + (xMouseStart - ox); - int newy = ySrcStart + (yMouseStart - oy); - if (newx < 0) - newx = 0; - if (newy < 0) - newy = 0; - if ((newx + srcRect.width) > imageWidth) - newx = imageWidth - srcRect.width; - if ((newy + srcRect.height) > imageHeight) - newy = imageHeight - srcRect.height; - srcRect.x = newx; - srcRect.y = newy; - imp.draw(); - Thread.yield(); - } - - Color getColor(int index) { - IndexColorModel cm = (IndexColorModel) imp.getProcessor().getColorModel(); - // IJ.write(""+index+" "+(new Color(cm.getRGB(index)))); - return new Color(cm.getRGB(index)); - } - - /** - * Sets the foreground drawing color (or background color if 'setBackground' is - * true) to the color of the pixel at (ox,oy). - */ - public void setDrawingColor(int ox, int oy, boolean setBackground) { - int type = imp.getType(); - int[] v = imp.getPixel(ox, oy); - switch (type) { - case ImagePlus.GRAY8: { - if (setBackground) - setBackgroundColor(getColor(v[0])); - else - setForegroundColor(getColor(v[0])); - break; - } - case ImagePlus.GRAY16: - case ImagePlus.GRAY32: { - double min = imp.getProcessor().getMin(); - double max = imp.getProcessor().getMax(); - double value = (type == ImagePlus.GRAY32) ? Float.intBitsToFloat(v[0]) : v[0]; - int index = (int) (255.0 * ((value - min) / (max - min))); - if (index < 0) - index = 0; - if (index > 255) - index = 255; - if (setBackground) - setBackgroundColor(getColor(index)); - else - setForegroundColor(getColor(index)); - break; - } - case ImagePlus.COLOR_RGB: - case ImagePlus.COLOR_256: { - Color c = new Color(v[0], v[1], v[2]); - if (setBackground) - setBackgroundColor(c); - else - setForegroundColor(c); - break; - } - } - Color c; - if (setBackground) - c = Toolbar.getBackgroundColor(); - else { - c = Toolbar.getForegroundColor(); - imp.setColor(c); - } - IJ.showStatus("(" + c.getRed() + ", " + c.getGreen() + ", " + c.getBlue() + ")"); - } - - private void setForegroundColor(Color c) { - Toolbar.setForegroundColor(c); - if (IJ.recording()) - Recorder.record("setForegroundColor", c.getRed(), c.getGreen(), c.getBlue()); - } - - private void setBackgroundColor(Color c) { - Toolbar.setBackgroundColor(c); - if (IJ.recording()) - Recorder.record("setBackgroundColor", c.getRed(), c.getGreen(), c.getBlue()); - } - - public void mousePressed(final MouseEvent e) { - /* Changed for Bio7! */ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - ImageWindow wind = imp.getWindow(); - if (wind != null) { - Frame frameSwtAwt = wind.getSwtAwtMain().getFrame(); - if (frameSwtAwt != null) { - - if (frameSwtAwt != null) - frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, WindowEvent.WINDOW_ACTIVATED)); - // frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, - // WindowEvent.WINDOW_GAINED_FOCUS)); - - if (ImageCanvas.this.isFocusOwner() == false) { - ImageCanvas.this.requestFocus(); - - } - } - } - } - }); - /* Search for detached views and activate them on mouse pressed events! */ - Util.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - String secId = Integer.toString(ImageCanvas.this.getImage().getID()); - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - IViewReference ref2 = page.findViewReference("com.eco.bio7.image.detachedImage", secId); - if (ref2 != null) { - IViewPart activated = null; - try { - - activated = page.showView("com.eco.bio7.image.detachedImage", secId, IWorkbenchPage.VIEW_ACTIVATE); - } catch (PartInitException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - // CustomDetachedImageJView customView = (CustomDetachedImageJView) activated; - // ImageJ.setCustomView(customView); - } - } - }); - - showCursorStatus = true; - int toolID = Toolbar.getToolId(); - ImageWindow win = imp.getWindow(); - if (win != null && win.running2 && toolID != Toolbar.MAGNIFIER) { - if (win instanceof StackWindow) - ((StackWindow) win).setAnimate(false); - else - win.running2 = false; - return; - } - - int x = e.getX(); - int y = e.getY(); - flags = e.getModifiers(); - - if (toolID != Toolbar.MAGNIFIER && (e.isPopupTrigger() || (!IJ.isMacintosh() && (flags & Event.META_MASK) != 0))) { - handlePopupMenu(e); - return; - } - - int ox = offScreenX(x); - int oy = offScreenY(y); - xMouse = ox; - yMouse = oy; - if (IJ.spaceBarDown()) { - // temporarily switch to "hand" tool of space bar down - setupScroll(ox, oy); - return; - } - - if (overOverlayLabel && (imp.getOverlay() != null || showAllOverlay != null)) { - if (activateOverlayRoi(ox, oy)) - return; - } - - if ((System.currentTimeMillis() - mousePressedTime) < 300L && !drawingTool()) { - if (activateOverlayRoi(ox, oy)) - return; - } - - mousePressedX = ox; - mousePressedY = oy; - mousePressedTime = System.currentTimeMillis(); - - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mousePressed(imp, e); - if (e.isConsumed()) - return; - } - if (customRoi && imp.getOverlay() != null) - return; - - if (toolID >= Toolbar.CUSTOM1) { - if (tool != null && "Arrow Tool".equals(tool.getToolName())) - handleRoiMouseDown(e); - else - Toolbar.getInstance().runMacroTool(toolID); - return; - } - - final Roi roi1 = imp.getRoi(); - final int size1 = roi1 != null ? roi1.size() : 0; - final Rectangle r1 = roi1 != null ? roi1.getBounds() : null; - - switch (toolID) { - case Toolbar.MAGNIFIER: - if (IJ.shiftKeyDown()) - zoomToSelection(ox, oy); - else if ((flags & (Event.ALT_MASK | Event.META_MASK | Event.CTRL_MASK)) != 0) { - - zoomOut(x, y); - if (getMagnification() < 1.0) - imp.repaintWindow(); - } else { - - zoomIn(x, y); - if (getMagnification() <= 1.0) - imp.repaintWindow(); - } - break; - case Toolbar.HAND: - setupScroll(ox, oy); - break; - case Toolbar.DROPPER: - setDrawingColor(ox, oy, IJ.altKeyDown()); - break; - case Toolbar.WAND: - double tolerance = WandToolOptions.getTolerance(); - Roi roi = imp.getRoi(); - if (roi != null && (tolerance == 0.0 || imp.isThreshold()) && roi.contains(ox, oy)) { - Rectangle r = roi.getBounds(); - if (r.width == imageWidth && r.height == imageHeight) - imp.deleteRoi(); - else if (!e.isAltDown()) { - handleRoiMouseDown(e); - return; - } - } - if (roi != null) { - int handle = roi.isHandle(x, y); - if (handle >= 0) { - roi.mouseDownInHandle(handle, x, y); - return; - } - } - if (!imp.okToDeleteRoi()) - break; - setRoiModState(e, roi, -1); - String mode = WandToolOptions.getMode(); - if (Prefs.smoothWand) - mode = mode + " smooth"; - int npoints = IJ.doWand(imp, ox, oy, tolerance, mode); - if (IJ.recording() && npoints > 0) { - if (Recorder.scriptMode()) - Recorder.recordCall("IJ.doWand(imp, " + ox + ", " + oy + ", " + tolerance + ", \"" + mode + "\");"); - else { - if (tolerance == 0.0 && mode.equals("Legacy")) - Recorder.record("doWand", ox, oy); - else - Recorder.recordString("doWand(" + ox + ", " + oy + ", " + tolerance + ", \"" + mode + "\");\n"); - } - } - break; - case Toolbar.OVAL: - if (Toolbar.getBrushSize() > 0) - new RoiBrush(); - else - handleRoiMouseDown(e); - break; - default: // selection tool - handleRoiMouseDown(e); - } - if (longClickDelay > 0) { - if (pressTimer == null) - pressTimer = new java.util.Timer(); - final Point cursorLoc = getCursorLoc(); - pressTimer.schedule(new TimerTask() { - public void run() { - if (pressTimer != null) { - pressTimer.cancel(); - pressTimer = null; - } - Roi roi2 = imp.getRoi(); - int size2 = roi2 != null ? roi2.size() : 0; - Rectangle r2 = roi2 != null ? roi2.getBounds() : null; - boolean empty = r2 != null && r2.width == 0 && r2.height == 0; - int state = roi2 != null ? roi2.getState() : -1; - boolean unchanged = state != Roi.MOVING_HANDLE && r1 != null && r2 != null && r2.x == r1.x && r2.y == r1.y && r2.width == r1.width && r2.height == r1.height && size2 == size1 - && !(size2 > 1 && state == Roi.CONSTRUCTING); - boolean cursorMoved = !getCursorLoc().equals(cursorLoc); - if ((roi1 == null && (size2 <= 1 || empty)) || unchanged) { - if (roi1 == null) - imp.deleteRoi(); - if (!cursorMoved && Toolbar.getToolId() != Toolbar.HAND) - handlePopupMenu(e); - } - } - }, longClickDelay); - } - } - - private boolean drawingTool() { - int id = Toolbar.getToolId(); - return id == Toolbar.POLYLINE || id == Toolbar.FREELINE || id >= Toolbar.CUSTOM1; - } - - void zoomToSelection(int x, int y) { - IJ.setKeyUp(IJ.ALL_KEYS); - String macro = "args = split(getArgument);\n" + "x1=parseInt(args[0]); y1=parseInt(args[1]); flags=20;\n" + "while (flags&20!=0) {\n" + "getCursorLoc(x2, y2, z, flags);\n" - + "if (x2>=x1) x=x1; else x=x2;\n" + "if (y2>=y1) y=y1; else y=y2;\n" + "makeRectangle(x, y, abs(x2-x1), abs(y2-y1));\n" + "wait(10);\n" + "}\n" + "run('To Selection');\n"; - new MacroRunner(macro, x + " " + y); - } - - protected void setupScroll(int ox, int oy) { - xMouseStart = ox; - yMouseStart = oy; - xSrcStart = srcRect.x; - ySrcStart = srcRect.y; - } - - protected void handlePopupMenu(MouseEvent e) { - if (disablePopupMenu) - return; - if (IJ.debugMode) - IJ.log("show popup: " + (e.isPopupTrigger() ? "true" : "false")); - int sx = e.getX(); - int sy = e.getY(); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - Roi roi = imp.getRoi(); - if (roi != null && roi.getType() == Roi.COMPOSITE && Toolbar.getToolId() == Toolbar.OVAL && Toolbar.getBrushSize() > 0) - return; // selection brush tool - if (roi != null && (roi.getType() == Roi.POLYGON || roi.getType() == Roi.POLYLINE || roi.getType() == Roi.ANGLE) && roi.getState() == roi.CONSTRUCTING) { - roi.handleMouseUp(sx, sy); // simulate double-click to finalize - roi.handleMouseUp(sx, sy); // polygon or polyline selection - return; - } - if (roi != null && !(e.isAltDown() || e.isShiftDown())) { // show ROI popup? - if (roi.contains(ox, oy)) { - if (roiPopupMenu == null) - addRoiPopupMenu(); - if (IJ.isMacOSX()) - IJ.wait(10); - /* Changed for Bio7! */ - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction imageContextMenuAction = instance.getImageContextMenuAction(); - imageContextMenuAction.swtPopupMenu(e, roiPopupMenu, this); - // roiPopupMenu.show(this, sx, sy); - return; - } - } - PopupMenu popup = Menus.getPopupMenu(); - if (popup != null) { - add(popup); - if (IJ.isMacOSX()) - IJ.wait(10); - /* Changed for Bio7! SWT Popup Menu! */ - // popup.show(this, x, y); - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction imageContextMenuAction = instance.getImageContextMenuAction(); - imageContextMenuAction.swtPopupMenu(e, popup, this); - } - } - - public void mouseExited(MouseEvent e) { - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseExited(imp, e); - if (e.isConsumed()) - return; - } - ImageWindow win = imp.getWindow(); - if (win != null) - setCursor(defaultCursor); - IJ.showStatus(""); - mouseExited = true; - /* - * Change for Bio7! On Linux the editors don't receive key events when the - * ImageCanvas receives focus. We workaround this by open and close a SWT Shell - * to transfer back the focus to SWT. This could also solve the problem of a - * broken editor hoover in the Bio7 editors! - */ - /* - * if (Util.getOS().equals("Linux")) { Display dis = Util.getDisplay(); - * dis.syncExec(new Runnable() { - * - * public void run() { - * - * if (tempShell != null) { if (tempShell.isDisposed() == false) { - * tempShell.dispose(); } } tempShell = new Shell(); tempShell.setVisible(true); - * tempShell.setVisible(false); } }); } - */ - - } - - public void mouseDragged(MouseEvent e) { - int x = e.getX(); - int y = e.getY(); - xMouse = offScreenX(x); - yMouse = offScreenY(y); - flags = e.getModifiers(); - mousePressedX = mousePressedY = -1; - if (flags == 0) // workaround for Mac OS 9 bug - flags = InputEvent.BUTTON1_MASK; - if (Toolbar.getToolId() == Toolbar.HAND || IJ.spaceBarDown()) - scroll(x, y); - else { - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseDragged(imp, e); - if (e.isConsumed()) - return; - } - IJ.setInputEvent(e); - Roi roi = imp.getRoi(); - if (roi != null) - roi.handleMouseDrag(x, y, flags); - } - } - - protected void handleRoiMouseDown(MouseEvent e) { - int sx = e.getX(); - int sy = e.getY(); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - Roi roi = imp.getRoi(); - int tool = Toolbar.getToolId(); - int handle = roi != null ? roi.isHandle(sx, sy) : -1; - boolean multiPointMode = roi != null && (roi instanceof PointRoi) && handle == -1 && tool == Toolbar.POINT && Toolbar.getMultiPointMode(); - if (multiPointMode) { - double oxd = roi.offScreenXD(sx); - double oyd = roi.offScreenYD(sy); - if (e.isShiftDown() && !IJ.isMacro()) { - FloatPolygon points = roi.getFloatPolygon(); - if (points.npoints > 0) { - double x0 = points.xpoints[0]; - double y0 = points.ypoints[0]; - double slope = Math.abs((oxd - x0) / (oyd - y0)); - if (slope >= 1.0) - oyd = points.ypoints[0]; - else - oxd = points.xpoints[0]; - } - } - ((PointRoi) roi).addUserPoint(imp, oxd, oyd); - imp.setRoi(roi); - return; - } - - if (roi != null && (roi instanceof PointRoi)) { - int npoints = ((PolygonRoi) roi).getNCoordinates(); - if (npoints > 1 && handle == -1 && !IJ.altKeyDown() && !(tool == Toolbar.POINT && !Toolbar.getMultiPointMode() && IJ.shiftKeyDown())) { - String msg = "Type shift-a (Edit>Selection>Select None) to delete\npoints. Use multi-point tool to add points."; - GenericDialog gd = new GenericDialog("Point Selection"); - gd.addMessage(msg); - gd.addHelp(PointToolOptions.help); - gd.hideCancelButton(); - gd.showDialog(); - return; - } - } - - setRoiModState(e, roi, handle); - if (roi != null) { - if (handle >= 0) { - roi.mouseDownInHandle(handle, sx, sy); - return; - } - Rectangle r = roi.getBounds(); - int type = roi.getType(); - if (type == Roi.RECTANGLE && r.width == imp.getWidth() && r.height == imp.getHeight() && roi.getPasteMode() == Roi.NOT_PASTING && !(roi instanceof ImageRoi)) { - imp.deleteRoi(); - return; - } - if (roi.contains(ox, oy)) { - if (roi.modState == Roi.NO_MODS) - roi.handleMouseDown(sx, sy); - else { - imp.deleteRoi(); - imp.createNewRoi(sx, sy); - } - return; - } - boolean segmentedTool = tool == Toolbar.POLYGON || tool == Toolbar.POLYLINE || tool == Toolbar.ANGLE; - if (segmentedTool && (type == Roi.POLYGON || type == Roi.POLYLINE || type == Roi.ANGLE) && roi.getState() == roi.CONSTRUCTING) - return; - - if (segmentedTool && !(IJ.shiftKeyDown() || IJ.altKeyDown())) { - imp.deleteRoi(); - return; - } - } - imp.createNewRoi(sx, sy); - } - - void setRoiModState(MouseEvent e, Roi roi, int handle) { - if (roi == null || (handle >= 0 && roi.modState == Roi.NO_MODS)) - return; - if (roi.state == Roi.CONSTRUCTING) - return; - int tool = Toolbar.getToolId(); - if (tool > Toolbar.FREEROI && tool != Toolbar.WAND && tool != Toolbar.POINT) { - roi.modState = Roi.NO_MODS; - return; - } - if (e.isShiftDown()) - roi.modState = Roi.ADD_TO_ROI; - else if (e.isAltDown()) - roi.modState = Roi.SUBTRACT_FROM_ROI; - else - roi.modState = Roi.NO_MODS; - } - - /** Disable/enable popup menu. */ - public void disablePopupMenu(boolean status) { - disablePopupMenu = status; - } - - public void setShowAllList(Overlay showAllList) { - this.showAllOverlay = showAllList; - labelRects = null; - } - - public Overlay getShowAllList() { - return showAllOverlay; - } - - /** Obsolete */ - public void setShowAllROIs(boolean showAllROIs) { - RoiManager rm = RoiManager.getInstance(); - if (rm != null) - rm.runCommand(showAllROIs ? "show all" : "show none"); - } - - /** Obsolete */ - public boolean getShowAllROIs() { - return getShowAllList() != null; - } - - /** Obsolete */ - public static Color getShowAllColor() { - if (showAllColor != null && showAllColor.getRGB() == 0xff80ffff) - showAllColor = Color.cyan; - return showAllColor; - } - - /** Obsolete */ - public static void setShowAllColor(Color c) { - if (c == null) - return; - showAllColor = c; - labelColor = null; - } - - /** Experimental */ - public static void setCursor(Cursor cursor, int type) { - crosshairCursor = cursor; - } - - /** Use ImagePlus.setOverlay(ij.gui.Overlay). */ - public void setOverlay(Overlay overlay) { - imp.setOverlay(overlay); - } - - /** Use ImagePlus.getOverlay(). */ - public Overlay getOverlay() { - return imp.getOverlay(); - } - - /** - * @deprecated replaced by ImagePlus.setOverlay(ij.gui.Overlay) - */ - public void setDisplayList(Vector list) { - if (list != null) { - Overlay list2 = new Overlay(); - list2.setVector(list); - imp.setOverlay(list2); - } else - imp.setOverlay(null); - Overlay overlay = imp.getOverlay(); - if (overlay != null) - overlay.drawLabels(overlay.size() > 0 && overlay.get(0).getStrokeColor() == null); - else - customRoi = false; - repaint(); - } - - /** - * @deprecated replaced by ImagePlus.setOverlay(Shape, Color, BasicStroke) - */ - public void setDisplayList(Shape shape, Color color, BasicStroke stroke) { - imp.setOverlay(shape, color, stroke); - } - - /** - * @deprecated replaced by ImagePlus.setOverlay(Roi, Color, int, Color) - */ - public void setDisplayList(Roi roi, Color color) { - roi.setStrokeColor(color); - Overlay list = new Overlay(); - list.add(roi); - imp.setOverlay(list); - } - - /** - * @deprecated replaced by ImagePlus.getOverlay() - */ - public Vector getDisplayList() { - Overlay overlay = imp.getOverlay(); - if (overlay == null) - return null; - Vector displayList = new Vector(); - for (int i = 0; i < overlay.size(); i++) - displayList.add(overlay.get(i)); - return displayList; - } - - /** - * Allows plugins (e.g., Orthogonal_Views) to create a custom ROI using a - * display list. - */ - public void setCustomRoi(boolean customRoi) { - this.customRoi = customRoi; - } - - public boolean getCustomRoi() { - return customRoi; - } - - /** - * Called by IJ.showStatus() to prevent status bar text from being overwritten - * until the cursor moves at least 12 pixels. - */ - public void setShowCursorStatus(boolean status) { - showCursorStatus = status; - if (status == true) - sx2 = sy2 = -1000; - else { - sx2 = screenX(xMouse); - sy2 = screenY(yMouse); - } - } - - public void mouseReleased(MouseEvent e) { - - if (pressTimer != null) { - pressTimer.cancel(); - pressTimer = null; - } - - int ox = offScreenX(e.getX()); - int oy = offScreenY(e.getY()); - Overlay overlay = imp.getOverlay(); - if ((overlay != null || showAllOverlay != null) && ox == mousePressedX && oy == mousePressedY) { - boolean cmdDown = IJ.isMacOSX() && e.isMetaDown(); - Roi roi = imp.getRoi(); - if (roi != null && roi.getBounds().width == 0) - roi = null; - if ((e.isAltDown() || e.isControlDown() || cmdDown) && roi == null) { - if (activateOverlayRoi(ox, oy)) - return; - } else if ((System.currentTimeMillis() - mousePressedTime) > 250L && !drawingTool()) { // long press - if (activateOverlayRoi(ox, oy)) - return; - } - - } - - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseReleased(imp, e); - if (e.isConsumed()) - return; - } - flags = e.getModifiers(); - flags &= ~InputEvent.BUTTON1_MASK; // make sure button 1 bit is not set - flags &= ~InputEvent.BUTTON2_MASK; // make sure button 2 bit is not set - flags &= ~InputEvent.BUTTON3_MASK; // make sure button 3 bit is not set - Roi roi = imp.getRoi(); - if (roi != null) { - Rectangle r = roi.getBounds(); - int type = roi.getType(); - if ((r.width == 0 || r.height == 0) && !(type == Roi.POLYGON || type == Roi.POLYLINE || type == Roi.ANGLE || type == Roi.LINE) && !(roi instanceof TextRoi) - && roi.getState() == roi.CONSTRUCTING && type != roi.POINT) - imp.deleteRoi(); - else - roi.handleMouseUp(e.getX(), e.getY()); - } - } - - private boolean activateOverlayRoi(int ox, int oy) { - int currentImage = -1; - int stackSize = imp.getStackSize(); - if (stackSize > 1) - currentImage = imp.getCurrentSlice(); - int channel = 0, slice = 0, frame = 0; - boolean hyperstack = imp.isHyperStack(); - if (hyperstack) { - channel = imp.getChannel(); - slice = imp.getSlice(); - frame = imp.getFrame(); - } - Overlay o = showAllOverlay; - if (o == null) - o = imp.getOverlay(); - if (o == null || !o.isSelectable()) - return false; - boolean roiManagerShowAllMode = o == showAllOverlay && !Prefs.showAllSliceOnly; - boolean labels = o.getDrawLabels(); - int sx = screenX(ox); - int sy = screenY(oy); - for (int i = o.size() - 1; i >= 0; i--) { - Roi roi = o.get(i); - if (roi == null) - continue; - boolean containsMousePoint = false; - if (roi instanceof Line) { // grab line roi near its center - double grabLineWidth = 1.1 + 5. / magnification; - containsMousePoint = (((Line) roi).getFloatPolygon(grabLineWidth)).contains(ox, oy); - } else - containsMousePoint = roi.contains(ox, oy); - if (containsMousePoint || (labels && labelRects != null && labelRects[i] != null && labelRects[i].contains(sx, sy))) { - if (hyperstack && roi.getPosition() == 0) { - int c = roi.getCPosition(); - int z = roi.getZPosition(); - int t = roi.getTPosition(); - if (!((c == 0 || c == channel) && (z == 0 || z == slice) && (t == 0 || t == frame) || roiManagerShowAllMode)) - continue; - } else { - int position = stackSize > 1 ? roi.getPosition() : 0; - if (!(position == 0 || position == currentImage || roiManagerShowAllMode)) - continue; - } - if (!IJ.altKeyDown() && roi.getType() == Roi.COMPOSITE && roi.getBounds().width == imp.getWidth() && roi.getBounds().height == imp.getHeight()) - return false; - // if (Toolbar.getToolId()==Toolbar.OVAL && Toolbar.getBrushSize()>0) - // Toolbar.getInstance().setTool(Toolbar.RECTANGLE); - roi.setImage(null); - imp.setRoi(roi); - roi.handleMouseDown(sx, sy); - roiManagerSelect(roi, false); - ResultsTable.selectRow(roi); - return true; - } - } - return false; - } - - public boolean roiManagerSelect(Roi roi, boolean delete) { - RoiManager rm = RoiManager.getInstance(); - if (rm == null) - return false; - int index = rm.getRoiIndex(roi); - if (index < 0) - return false; - if (delete) { - rm.select(imp, index); - rm.runCommand("delete"); - } else - rm.selectAndMakeVisible(imp, index); - return true; - } - - public void mouseMoved(MouseEvent e) { - // if (ij==null) return; - int sx = e.getX(); - int sy = e.getY(); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - flags = e.getModifiers(); - setCursor(sx, sy, ox, oy); - mousePressedX = mousePressedY = -1; - IJ.setInputEvent(e); - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseMoved(imp, e); - if (e.isConsumed()) - return; - } - Roi roi = imp.getRoi(); - int type = roi != null ? roi.getType() : -1; - if (type > 0 && (type == Roi.POLYGON || type == Roi.POLYLINE || type == Roi.ANGLE || type == Roi.LINE) && roi.getState() == roi.CONSTRUCTING) - roi.mouseMoved(e); - else { - if (ox < imageWidth && oy < imageHeight) { - ImageWindow win = imp.getWindow(); - // Cursor must move at least 12 pixels before text - // displayed using IJ.showStatus() is overwritten. - if ((sx - sx2) * (sx - sx2) + (sy - sy2) * (sy - sy2) > 144) - showCursorStatus = true; - if (win != null && showCursorStatus) - win.mouseMoved(ox, oy); - } else - IJ.showStatus(""); - } - } - - public void mouseEntered(MouseEvent e) { - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) - tool.mouseEntered(imp, e); - } - - public void mouseClicked(MouseEvent e) { - Util.activateView("com.eco.bio7.imagej"); - /* Changed for Bio7! */ - if (this.isFocusOwner() == false) { - this.requestFocus(); - - } - WindowManager.setTempCurrentImage(imp); - WindowManager.setCurrentWindow(imp.getWindow()); - - /* import to set current Panel! */ - CanvasView.setCurrent((JPanel) this.getParent()); - - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) - tool.mouseClicked(imp, e); - } - - /* Changed for Bio7! */ - public void mouseWheelMoved(MouseWheelEvent e) { - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - if (IJ.debugMode) { - IJ.log("mouseWheelMoved: " + e); - IJ.log(" type: " + e.getScrollType()); - IJ.log(" ctrl: " + ctrl); - IJ.log(" rotation: " + rotation); - IJ.log(" amount: " + amount); - } - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - int width = imp.getWidth(); - int height = imp.getHeight(); - Rectangle srcRect = getSrcRect(); - int xstart = srcRect.x; - int ystart = srcRect.y; - if ((ctrl || IJ.shiftKeyDown()) && this != null) { - int ox = offScreenX(e.getX()); - int oy = offScreenY(e.getX()); - if (IJ.debugMode) - IJ.log(" x,y: " + ox + "," + oy); - if (rotation < 0) - zoomIn(ox, oy); - else - zoomOut(ox, oy); - return; - } else if (IJ.spaceBarDown() || srcRect.height == height) { - srcRect.x += rotation * amount * Math.max(width / 200, 1); - if (srcRect.x < 0) - srcRect.x = 0; - if (srcRect.x + srcRect.width > width) - srcRect.x = width - srcRect.width; - } else { - srcRect.y += rotation * amount * Math.max(height / 200, 1); - if (srcRect.y < 0) - srcRect.y = 0; - if (srcRect.y + srcRect.height > height) - srcRect.y = height - srcRect.height; - } - if (srcRect.x != xstart || srcRect.y != ystart) - repaint(); - - } - - public void setScaleToFit(boolean scaleToFit) { - this.scaleToFit = scaleToFit; - } - - public boolean getScaleToFit() { - return scaleToFit; - } - - public boolean hideZoomIndicator(boolean hide) { - boolean hidden = this.hideZoomIndicator; - if (!(srcRect.width < imageWidth || srcRect.height < imageHeight)) - return hidden; - this.hideZoomIndicator = hide; - setPaintPending(true); - repaint(); - long t0 = System.currentTimeMillis(); - while (getPaintPending() && (System.currentTimeMillis() - t0) < 500L) - IJ.wait(10); - return hidden; - } - - public void repaintOverlay() { - labelRects = null; - repaint(); - } - - /** - * Sets the context menu long click delay in milliseconds (default is 1000). Set - * to 0 to disable long click triggering. - */ - public static void setLongClickDelay(int delay) { - longClickDelay = delay; - } - - void addRoiPopupMenu() { - ImageJ ij = IJ.getInstance(); - if (ij == null) - return; - roiPopupMenu = new PopupMenu(); - GUI.scalePopupMenu(roiPopupMenu); - addPopupItem("ROI Properties... ", "Properties... ", roiPopupMenu, ij); - addPopupItem("Roi Defaults...", null, roiPopupMenu, ij); - addPopupItem("Add to Overlay", "Add Selection...", roiPopupMenu, ij); - addPopupItem("Add to ROI Manager", "Add to Manager", roiPopupMenu, ij); - addPopupItem("Duplicate...", null, roiPopupMenu, ij); - addPopupItem("Fit Spline", null, roiPopupMenu, ij); - addPopupItem("Create Mask", null, roiPopupMenu, ij); - addPopupItem("Measure", null, roiPopupMenu, ij); - add(roiPopupMenu); - } - - private void addPopupItem(String label, String command, PopupMenu pm, ImageJ ij) { - MenuItem mi = new MenuItem(label); - if (command != null) - mi.setActionCommand(command); - mi.addActionListener(ij); - pm.add(mi); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImageLayout.java b/com.eco.bio7.image/src/ij/gui/ImageLayout.java deleted file mode 100644 index 7888616c7..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageLayout.java +++ /dev/null @@ -1,113 +0,0 @@ -package ij.gui; -import java.awt.*; -import ij.*; - -/** This is a custom layout manager that supports resizing of zoomed -images. It's based on FlowLayout, but with vertical and centered flow. */ -public class ImageLayout implements LayoutManager { - - int hgap = ImageWindow.HGAP; - int vgap = ImageWindow.VGAP; - ImageCanvas ic; - boolean ignoreNonImageWidths; - - /** Creates a new ImageLayout with center alignment. */ - public ImageLayout(ImageCanvas ic) { - this.ic = ic; - } - - /** Not used by this class. */ - public void addLayoutComponent(String name, Component comp) { - } - - /** Not used by this class. */ - public void removeLayoutComponent(Component comp) { - } - - /** Returns the preferred dimensions for this layout. */ - public Dimension preferredLayoutSize(Container target) { - Dimension dim = new Dimension(0,0); - int nmembers = target.getComponentCount(); - for (int i=0; i0) dim.height += vgap; - dim.height += d.height; - } - Insets insets = target.getInsets(); - dim.width += insets.left + insets.right + hgap*2; - dim.height += insets.top + insets.bottom + vgap*2; - return dim; - } - - /** Returns the minimum dimensions for this layout. */ - public Dimension minimumLayoutSize(Container target) { - return preferredLayoutSize(target); - } - - /** Determines whether to ignore the width of non-image components when calculating - * the preferred width (default false, i.e. the maximum of the widths of all components is used). - * When true, components that do not fit the window will be truncated at the right. - * The width of the 0th component (the ImageCanvas) is always taken into account. */ - public void ignoreNonImageWidths(boolean ignoreNonImageWidths) { - this.ignoreNonImageWidths = ignoreNonImageWidths; - } - - /** Centers the elements in the specified column, if there is any slack.*/ - private void moveComponents(Container target, int x, int y, int width, int height, int nmembers) { - int x2 = 0; - y += height / 2; - for (int i=0; i60) - x2 = x + (width - d.width)/2; - m.setLocation(x2, y); - y += vgap + d.height; - } - } - - /** Lays out the container and calls ImageCanvas.resizeCanvas() - to adjust the image canvas size as needed. */ - public void layoutContainer(Container target) { - Insets insets = target.getInsets(); - int nmembers = target.getComponentCount(); - Dimension d; - int extraHeight = 0; - for (int i=1; i 0) y += vgap; - y += d.height; - if (i==0 || !ignoreNonImageWidths) - colw = Math.max(colw, d.width); - } - moveComponents(target, x, insets.top + vgap, colw, maxheight - y, nmembers); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImagePanel.java b/com.eco.bio7.image/src/ij/gui/ImagePanel.java deleted file mode 100644 index 13481eedb..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImagePanel.java +++ /dev/null @@ -1,25 +0,0 @@ -package ij.gui; -import java.awt.*; -import ij.*; - -/** This class is used by GenericDialog to add images to dialogs. */ -public class ImagePanel extends Panel { - private ImagePlus img; - - public ImagePanel(ImagePlus img) { - this.img = img; - } - - public Dimension getPreferredSize() { - return new Dimension(img.getWidth(), img.getHeight()); - } - - public Dimension getMinimumSize() { - return new Dimension(img.getWidth(), img.getHeight()); - } - - public void paint(Graphics g) { - g.drawImage(img.getProcessor().createImage(), 0, 0, null); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImageRoi.java b/com.eco.bio7.image/src/ij/gui/ImageRoi.java deleted file mode 100644 index 1f2bd6e2f..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageRoi.java +++ /dev/null @@ -1,152 +0,0 @@ -package ij.gui; -import ij.ImagePlus; -import ij.process.*; -import ij.io.FileSaver; -import java.awt.*; -import java.awt.image.*; - -/** An ImageRoi is an Roi that overlays an image. -* @see ij.ImagePlus#setOverlay(ij.gui.Overlay) -*/ -public class ImageRoi extends Roi { - private Image img; - private Composite composite; - private double opacity = 1.0; - private double angle = 0.0; - private boolean zeroTransparent; - private ImageProcessor ip; - - /** Creates a new ImageRoi from a BufferedImage.*/ - public ImageRoi(int x, int y, BufferedImage bi) { - super(x, y, bi.getWidth(), bi.getHeight()); - img = bi; - setStrokeColor(Color.black); - } - - /** Creates a new ImageRoi from a ImageProcessor.*/ - public ImageRoi(int x, int y, ImageProcessor ip) { - super(x, y, ip.getWidth(), ip.getHeight()); - img = ip.createImage(); - this.ip = ip; - setStrokeColor(Color.black); - } - - public void draw(Graphics g) { - Graphics2D g2d = (Graphics2D)g; - double mag = getMagnification(); - int sx2 = screenX(x+width); - int sy2 = screenY(y+height); - Composite saveComposite = null; - if (composite!=null) { - saveComposite = g2d.getComposite(); - g2d.setComposite(composite); - } - Image img2 = img; - if (angle!=0.0) { - ImageProcessor ip = new ColorProcessor(img); - ip.setInterpolate(true); - ip.setBackgroundValue(0.0); - ip.rotate(angle); - if (zeroTransparent) - ip = makeZeroTransparent(ip, true); - img2 = ip.createImage(); - } - g.drawImage(img2, screenX(x), screenY(y), sx2, sy2, 0, 0, img.getWidth(null), img.getHeight(null), null); - if (composite!=null) g2d.setComposite(saveComposite); - if (isActiveOverlayRoi() && !overlay) - super.draw(g); - } - - /** Sets the composite mode. */ - public void setComposite(Composite composite) { - this.composite = composite; - } - - /** Sets the composite mode using the specified opacity (alpha), in the - range 0.0-1.0, where 0.0 is fully transparent and 1.0 is fully opaque. */ - public void setOpacity(double opacity) { - if (opacity<0.0) opacity = 0.0; - if (opacity>1.0) opacity = 1.0; - this.opacity = opacity; - if (opacity!=1.0) - composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)opacity); - else - composite = null; - } - - /** Returns a serialized version of the image. */ - public byte[] getSerializedImage() { - ImagePlus imp = new ImagePlus("",img); - return new FileSaver(imp).serialize(); - } - - /** Returns the current opacity. */ - public double getOpacity() { - return opacity; - } - - public void rotate(double angle) { - this.angle += angle; - } - - public void setAngle(double angle) { - this.angle = angle; - } - - public void setZeroTransparent(boolean zeroTransparent) { - if (this.zeroTransparent!=zeroTransparent) { - ip = makeZeroTransparent(new ColorProcessor(img), zeroTransparent); - img = ip.createImage(); - } - this.zeroTransparent = zeroTransparent; - } - - public boolean getZeroTransparent() { - return zeroTransparent; - } - - private ImageProcessor makeZeroTransparent(ImageProcessor ip, boolean transparent) { - if (transparent) { - ip.setColorModel(new DirectColorModel(32,0x00ff0000,0x0000ff00,0x000000ff,0xff000000)); - for (int x=0; x1) - ip.set(x, y, ip.get(x,y)|0xff000000); // set alpha bits - else - ip.set(x, y, ip.get(x,y)&0xffffff); // clear alpha bits - } - } - } - return ip; - } - - public synchronized Object clone() { - ImageRoi roi2 = (ImageRoi)super.clone(); - ImagePlus imp = new ImagePlus("", img); - roi2.setProcessor(imp.getProcessor()); - roi2.setOpacity(getOpacity()); - return roi2; - } - - public ImageProcessor getProcessor() { - if (ip!=null) - return ip; - else { - ip = new ColorProcessor(img); - return ip; - } - } - - public void setProcessor(ImageProcessor ip) { - img = ip.createImage(); - this.ip = ip; - if (zeroTransparent) { - setZeroTransparent(false); - setZeroTransparent(true); - } - width = ip.getWidth(); - height = ip.getHeight(); - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/ImageWindow.java b/com.eco.bio7.image/src/ij/gui/ImageWindow.java deleted file mode 100644 index a7fbf16bd..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageWindow.java +++ /dev/null @@ -1,1120 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.image.*; -import java.util.Properties; -import java.util.Vector; - -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - -import java.awt.event.*; - -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.custom.CTabItem; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.PlatformUI; - -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.CustomDetachedImageJView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.SwtAwtImageJ; -import com.eco.bio7.image.Util; - -import ij.*; -import ij.process.*; -import ij.io.*; -import ij.measure.*; -import ij.plugin.frame.*; -import ij.plugin.PointToolOptions; -import ij.macro.Interpreter; -import ij.util.*; - -/** A frame for displaying images. */ -public class ImageWindow extends JFrame - implements FocusListener, WindowListener, WindowStateListener, MouseWheelListener { - - public static final int MIN_WIDTH = 128; - public static final int MIN_HEIGHT = 32; - public static final int HGAP = 5; - public static final int VGAP = 5; - public static final String LOC_KEY = "image.loc"; - - protected ImagePlus imp; - protected ImageJ ij; - protected ImageCanvas ic; - private double initialMagnification = 1; - private int newWidth, newHeight; - protected boolean closed; - private boolean newCanvas; - private boolean unzoomWhenMinimizing = true; - Rectangle maxWindowBounds; // largest possible window on this screen - Rectangle maxBounds; // Size of this window after it is maximized - long setMaxBoundsTime; - private int sliderHeight; - private static final int XINC = 12; - private static final int YINC = 16; - private final double SCALE = Prefs.getGuiScale(); - private int TEXT_GAP = 11; - private static int xbase = -1; - private static int ybase; - private static int xloc; - private static int yloc; - private static int count; - private static boolean centerOnScreen; - private static Point nextLocation; - public static long setMenuBarTime; - private int textGap = centerOnScreen ? 0 : TEXT_GAP; - private int screenHeight, screenWidth; - public SwtAwtImageJ swtAwtMain;// Changed for Bio7! - public boolean running2; - protected boolean imageInTab; - protected ImageWindow win2; - /** - * This variable is set false if the user presses the escape key or closes the - * window. - */ - public boolean running; - - /** - * This variable is set false if the user clicks in this window, presses the - * escape key, or closes the window. - */ - - // private ImageWindow windowInstance;// Changed for Bio7! - public SwtAwtImageJ getSwtAwtMain() { - return swtAwtMain; - } - - public void setSwtAwtMain(SwtAwtImageJ swtAwtMainFrame) { - this.swtAwtMain = swtAwtMainFrame; - } - - public ImageWindow(String title) { - super(title); - } - - public ImageWindow(ImagePlus imp) { - this(imp, null); - /// * Changed for Bio7! */ - // windowInstance = this; - } - - /* Changed for Bio7 setting the tab title and not the JFrame title! */ - public void setTitle(String title) { - - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - for (int i = 0; i < items.length; i++) { - - Vector ve = (Vector) items[i].getData(); - - final ImageWindow win2 = (ImageWindow) ve.get(1); - - /* Search for the tab which embeds this instance! */ - if (ImageWindow.this.equals(win2)) { - // Rename the tab! - CanvasView.tabFolder.getItem(i).setText(title); - - return; - - } - - } - - /* - * CustomDetachedImageJView customImageJView = ImageJ.customImageJView; if - * (customImageJView != null) { customImageJView.setPartName(title); } - */ - - IViewReference[] viewRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() - .getViewReferences(); - for (int i = 0; i < viewRefs.length; i++) { - String id = viewRefs[i].getId(); - if (id.equals("com.eco.bio7.image.detachedImage")) { - IViewPart view = viewRefs[i].getView(false); - String secId = viewRefs[i].getSecondaryId(); - CustomDetachedImageJView cdview = (CustomDetachedImageJView) view; - /* Get the image from the detached secondary view id (same id)! */ - ImagePlus ip = WindowManager.getImage(Integer.valueOf(secId)); - if (ip != null) { - if (ImageWindow.this.equals(ip.getWindow())) { - cdview.setPartName(title); - } - } - - } - } - - } - }); - - } - - public ImageWindow(ImagePlus imp, ImageCanvas ic) { - super(imp.getTitle()); - if (SCALE > 1.0) { - TEXT_GAP = (int) (TEXT_GAP * SCALE); - textGap = centerOnScreen ? 0 : TEXT_GAP; - } - boolean openAsHyperStack = imp.getOpenAsHyperStack(); - ij = IJ.getInstance(); - this.imp = imp; - if (ic == null) { - ic = (this instanceof PlotWindow) ? new PlotCanvas(imp) : new ImageCanvas(imp); - newCanvas = true; - } - this.ic = ic; - ImageWindow previousWindow = imp.getWindow(); - - setLayout(new ImageLayout(ic)); - add(ic); - addFocusListener(this); - addWindowListener(this); - addWindowStateListener(this); - addKeyListener(ij); - - setFocusTraversalKeysEnabled(false); - if (!(this instanceof StackWindow)) - addMouseWheelListener(this); - - setResizable(true); - if (!(this instanceof HistogramWindow && IJ.isMacro() && Interpreter.isBatchMode())) { - WindowManager.addWindow(this); - imp.setWindow(this); - } - if (previousWindow != null) { - /* Hide the tab without to close the image! */ - IJTabs.hideTab(); - if (newCanvas) - setLocationAndSize(false); - else - ic.update(previousWindow.getCanvas()); - - if (!(this instanceof StackWindow || this instanceof PlotWindow)) { // layout now unless components will be - // added later - swtAwtMain = new SwtAwtImageJ(null, null, null, ic, imp, this); - /* Add the panel to the tab folder with the image */ - swtAwtMain.addTab(imp.getTitle()); - imp.setWindow(this); - - /* - * The next seems to be important for Mac. Else at the first zoom level the - * image disapears! - */ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - pack(); - } - }); - /* Necessary for highDPI layout SWT_AWT! */ - CanvasView canvasView = CanvasView.getCanvas_view(); - canvasView.recalculateLayout(); - /* - * The next seems to be important for Mac. Else at the first zoom level the - * image disapears! - */ - if (IJ.isMacro()) - imp.setDeactivated(); // prepare for waitTillActivated (imp may have been activated before if it - // gets a new Window now) - // show(); - } - if (ic.getMagnification() != 0.0) - imp.setTitle(imp.getTitle()); - boolean unlocked = imp.lockSilently(); - boolean changes = imp.changes; - imp.changes = false; - /* - * Changed for Bio7. We have to call the default ImageJ close function which is - * renamed to bio7TabClose because we have hidden the tab already (close - * searches for the tab and closes it)! - */ - previousWindow.bio7TabClose(true); - imp.changes = changes; - if (unlocked) - imp.unlock(); - if (this.imp != null) - this.imp.setOpenAsHyperStack(openAsHyperStack); - WindowManager.setCurrentWindow(this); - } else { - // setLocationAndSize(false); - /* - * if (ij != null && !IJ.isMacintosh()) { Image img = ij.getIconImage(); if (img!=null) try { - setIconImage(img); - } catch (Exception e) {} - */ - - if (Interpreter.isBatchMode() || (IJ.getInstance() == null && this instanceof HistogramWindow)) { - WindowManager.setTempCurrentImage(imp); - Interpreter.addBatchModeImage(imp); - } - - else { - if (IJ.isMacro()) - imp.setDeactivated(); // prepare for waitTillActivated (imp may have been activated previously and - // gets a new Window now) - - if (!(this instanceof StackWindow)) { - swtAwtMain = new SwtAwtImageJ(null, null, null, ic, imp, this); - /* Add the panel to the tab folder with the image */ - swtAwtMain.addTab(imp.getTitle()); - imp.setWindow(this); - /* - * The next seems to be important for Mac. Else at the first zoom level the - * image disapears! - */ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - pack(); - } - }); - /* Necessary for highDPI layout SWT_AWT! */ - CanvasView canvasView = CanvasView.getCanvas_view(); - canvasView.recalculateLayout(); - - } - - } - - } - - } - - private void setLocationAndSize(boolean updating) { - if (imp == null) - return; - int width = imp.getWidth(); - int height = imp.getHeight(); - - // load preferences file location - Point loc = Prefs.getLocation(LOC_KEY); - Rectangle bounds = null; - if (loc != null) { - bounds = GUI.getMaxWindowBounds(loc); - if (bounds != null && (loc.x > bounds.x + bounds.width / 3 || loc.y > bounds.y + bounds.height / 3) - && (loc.x + width > bounds.x + bounds.width || loc.y + height > bounds.y + bounds.height)) { - loc = null; - bounds = null; - } - } - // if loc not valid, use screen bounds of visible window (this) or of main - // window (ij) if not visible yet (updating == false) - Rectangle maxWindow = bounds != null ? bounds : GUI.getMaxWindowBounds(updating ? this : ij); - - if (WindowManager.getWindowCount() <= 1) - xbase = -1; - if (width > maxWindow.width / 2 && xbase > maxWindow.x + 5 + XINC * 6) - xbase = -1; - if (xbase == -1) { - count = 0; - if (loc != null) { - xbase = loc.x; - ybase = loc.y; - } else if (ij != null) { - Rectangle ijBounds = ij.getBounds(); - if (ijBounds.y - maxWindow.x < maxWindow.height / 8) { - xbase = ijBounds.x; - if (xbase + width > maxWindow.x + maxWindow.width) { - xbase = maxWindow.x + maxWindow.width - width - 10; - if (xbase < maxWindow.x) - xbase = maxWindow.x + 5; - ; - } - ybase = ijBounds.y + ijBounds.height + 5; - } else { - xbase = maxWindow.x + (maxWindow.width - width) / 2; - ybase = maxWindow.y + (maxWindow.height - height) / 4; - } - } else { - xbase = maxWindow.x + (maxWindow.width - width) / 2; - ybase = maxWindow.y + (maxWindow.height - height) / 4; - } - xbase = Math.max(xbase, maxWindow.x); - ybase = Math.max(ybase, maxWindow.y); - //if (IJ.debugMode) - //IJ.log("ImageWindow.xbase: " + xbase); - xloc = xbase; - yloc = ybase; - } - int x = xloc; - int y = yloc; - xloc += XINC; - yloc += YINC; - count++; - if (count % 6 == 0) { - xloc = xbase; - yloc = ybase; - } - - screenHeight = maxWindow.y + maxWindow.height - sliderHeight; - screenWidth = maxWindow.x + maxWindow.width; - double mag = 1; - if (!(this instanceof PlotWindow)) { // unless a plot (always at 100%), zoom out to show all of image - while (xbase + width * mag > screenWidth || ybase + height * mag >= screenHeight) { - double mag2 = ImageCanvas.getLowerZoomLevel(mag); - if (mag2 == mag) - break; - mag = mag2; - } - } - - if (mag < 1.0) { - initialMagnification = mag; - ic.setSize((int) (width * mag), (int) (height * mag)); - } - ic.setMagnification(mag); - if (y + height * mag > screenHeight) - y = ybase; - if (Prefs.open100Percent && ic.getMagnification() < 1.0) { - while (ic.getMagnification() < 1.0) - ic.zoomIn(0, 0); - setSize(Math.min(width, screenWidth - x), Math.min(height, screenHeight - y)); - validate(); - } else - pack(); - if (!updating) - setLocation(x, y); - } - - Rectangle getMaxWindow(int xloc, int yloc) { - - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - /* Changed for Bio7! */ - Rectangle bounds = CanvasView.getCanvas_view().getCurrent().getBounds(); - - // return GUI.getMaxWindowBounds(new Point(xloc, yloc)); - - return bounds; - } - - /* - * public Rectangle getBounds() { - * - * Changed for Bio7! Rectangle bounds = - * CanvasView.getCanvas_view().getCurrent().getBounds(); - * - * return bounds; } - */ - - public double getInitialMagnification() { - return initialMagnification; - } - - /** - * Override Container getInsets() to make room for some text above the image. - */ - /* - * public Insets getInsets() { Insets insets = super.getInsets(); if (imp == - * null) return insets; double mag = ic.getMagnification(); int extraWidth = - * (int) ((MIN_WIDTH - imp.getWidth() * mag) / 2.0); if (extraWidth < 0) - * extraWidth = 0; int extraHeight = (int) ((MIN_HEIGHT - imp.getHeight() * mag) - * / 2.0); if (extraHeight < 0) extraHeight = 0; insets = new Insets(insets.top - * + textGap + extraHeight, insets.left + extraWidth, insets.bottom + - * extraHeight, insets.right + extraWidth); return insets; } - */ - - /** Draws the subtitle. */ - public void drawInfo(Graphics g) { - if (imp == null) - return; - if (textGap != 0) { - Insets insets = super.getInsets(); - Color savec = null; - if (imp.isComposite()) { - CompositeImage ci = (CompositeImage) imp; - if (ci.getMode() == IJ.COMPOSITE) { - savec = g.getColor(); - Color c = ci.getChannelColor(); - if (Color.green.equals(c)) - c = new Color(0, 180, 0); - g.setColor(c); - } - } - Java2.setAntialiasedText(g, true); - if (SCALE > 1.0) { - Font font = new Font("SansSerif", Font.PLAIN, (int) (12 * SCALE)); - g.setFont(font); - } - g.drawString(createSubtitle(), insets.left + 5, insets.top + TEXT_GAP); - if (savec != null) - g.setColor(savec); - } - } - - /** Creates the subtitle. */ - public String createSubtitle() { - String s = ""; - if (imp == null) - return s; - int stackSize = imp.getStackSize(); - if (stackSize > 1) { - ImageStack stack = imp.getStack(); - int currentSlice = imp.getCurrentSlice(); - s += currentSlice + "/" + stackSize; - String label = stack.getShortSliceLabel(currentSlice); - if (label != null && label.length() > 0) { - if (imp.isHyperStack()) - label = label.replace(';', ' '); - s += " (" + label + ")"; - } - if ((this instanceof StackWindow) && running2) { - return s; - } - s += "; "; - } else { - String label = imp.getProp("Slice_Label"); - if (label==null && imp.hasImageStack()) - label = imp.getStack().getSliceLabel(1); - if (label != null && label.length() > 0) { - int newline = label.indexOf('\n'); - if (newline > 0) - label = label.substring(0, newline); - int len = label.length(); - if (len > 4 && label.charAt(len - 4) == '.' && !Character.isDigit(label.charAt(len - 1))) - label = label.substring(0, len - 4); - if (label.length() > 60) - label = label.substring(0, 60) + "..."; - s = "\"" + label + "\"; "; - } - } - int type = imp.getType(); - Calibration cal = imp.getCalibration(); - if (cal.scaled()) { - boolean unitsMatch = cal.getXUnit().equals(cal.getYUnit()); - double cwidth = imp.getWidth() * cal.pixelWidth; - double cheight = imp.getHeight() * cal.pixelHeight; - int digits = Tools.getDecimalPlaces(cwidth, cheight); - if (digits > 2) - digits = 2; - if (unitsMatch) { - s += IJ.d2s(cwidth, digits) + "x" + IJ.d2s(cheight, digits) + " " + cal.getUnits() + " (" - + imp.getWidth() + "x" + imp.getHeight() + "); "; - } else { - s += d2s(cwidth) + " " + cal.getXUnit() + " x " + d2s(cheight) + " " + cal.getYUnit() + " (" - + imp.getWidth() + "x" + imp.getHeight() + "); "; - } - } else - s += imp.getWidth() + "x" + imp.getHeight() + " pixels; "; - switch (type) { - case ImagePlus.GRAY8: - case ImagePlus.COLOR_256: - s += "8-bit"; - break; - case ImagePlus.GRAY16: - s += "16-bit"; - break; - case ImagePlus.GRAY32: - s += "32-bit"; - break; - case ImagePlus.COLOR_RGB: - s += imp.isRGB() ? "RGB" : "32-bit (int)"; - break; - } - if (imp.isInvertedLut()) - s += " (inverting LUT)"; - return s + "; " + getImageSize(imp); - } - - public static String getImageSize(ImagePlus imp) { - if (imp == null) - return null; - double size = imp.getSizeInBytes() / 1024.0; - String s2 = null, s3 = null; - if (size < 1024.0) { - s2 = IJ.d2s(size, 0); - s3 = "K"; - } else if (size < 10000.0) { - s2 = IJ.d2s(size / 1024.0, 1); - s3 = "MB"; - } else if (size < 1048576.0) { - s2 = IJ.d2s(Math.round(size / 1024.0), 0); - s3 = "MB"; - } else { - s2 = IJ.d2s(size / 1048576.0, 1); - s3 = "GB"; - } - if (s2.endsWith(".0")) - s2 = s2.substring(0, s2.length() - 2); - return s2 + s3; - } - - private String d2s(double n) { - int digits = Tools.getDecimalPlaces(n); - if (digits > 2) - digits = 2; - return IJ.d2s(n, digits); - } - - /* Changed for Bio7! */ - /* - * public Rectangle getBounds(){ GraphicsEnvironment ge = - * GraphicsEnvironment.getLocalGraphicsEnvironment(); Changed for Bio7! - * Rectangle bounds = CanvasView.getCanvas_view().getCurrent().getBounds(); - * return bounds; } - */ - - public void paintComponents(Graphics g) { - super.paintComponents(g); - drawInfo(g); - Rectangle r = ic.getBounds(); - int extraWidth = MIN_WIDTH - r.width; - int extraHeight = MIN_HEIGHT - r.height; - if (extraWidth <= 0 && extraHeight <= 0 && !Prefs.noBorder && !IJ.isLinux()) - g.drawRect(r.x - 1, r.y - 1, r.width + 1, r.height + 1); - } - - /** - * Removes this window from the window list and disposes of it. Returns false if - * the user cancels the "save changes" dialog. - */ - public boolean close() { - /* - * boolean isRunning = running || running2; running = running2 = false; if - * (imp==null) return true; boolean virtual = imp.getStackSize()>1 && - * imp.getStack().isVirtual(); if (isRunning) IJ.wait(500); if (ij==null || - * IJ.getApplet()!=null || Interpreter.isBatchMode() || IJ.macroRunning() || - * virtual) imp.changes = false; if (imp.changes) { String msg; String name = - * imp.getTitle(); if (name.length()>22) msg = "Save changes to\n" + "\"" + name - * + "\"?"; else msg = "Save changes to \"" + name + "\"?"; YesNoCancelDialog d - * = new YesNoCancelDialog(this, "ImageJ", msg); if (d.cancelPressed()) return - * false; else if (d.yesPressed()) { FileSaver fs = new FileSaver(imp); if - * (!fs.save()) return false; } } closed = true; if - * (WindowManager.getWindowCount()==0) {xloc = 0; yloc = 0;} if - * (firstSmallWindow) Prefs.saveLocation(LOC_KEY, getLocation()); - * WindowManager.removeWindow(this); - if (ij!=null && ij.quitting()) // this may help avoid thread deadlocks - return true; - Rectangle bounds = getBounds(); - if (initialLoc!=null && !bounds.equals(initialLoc) && !IJ.isMacro() - && bounds.y 1 && imp.getStack().isVirtual(); - if (isRunning) - IJ.wait(500); - if (ij == null || ij.quittingViaMacro() || IJ.getApplet() != null || Interpreter.isBatchMode() - || IJ.macroRunning() || virtual) - imp.changes = false; - /* Changed for Bio7! */ - /* - * if (imp.changes) { String msg; String name = imp.getTitle(); if - * (name.length()>22) msg = "Save changes to\n" + "\"" + name + "\"?"; else msg - * = "Save changes to \"" + name + "\"?"; YesNoCancelDialog d = new - * YesNoCancelDialog(this, "ImageJ", msg); if (d.cancelPressed()) return false; - * else if (d.yesPressed()) { FileSaver fs = new FileSaver(imp); if (!fs.save()) - * return false; } } - */ - closed = true; - if (WindowManager.getWindowCount() == 0) { - xloc = 0; - yloc = 0; - } - Point currentLoc = getLocation(); - if (!IJ.isMacro()) { - Prefs.saveLocation(LOC_KEY, currentLoc); - xbase = -1; - } - WindowManager.removeWindow(this); - setVisible(false); - if (ij != null && ij.quitting()) // this may help avoid thread deadlocks - return true; - /*Changed for Bio7! - Avoid deadlock situation by disposing the JFrame!*/ - if (disposeFrame) { - dispose(); - } - if (imp != null) - imp.flush(); - imp = null; - return true; - } - - public ImagePlus getImagePlus() { - return imp; - } - - public void setImage(ImagePlus imp2) { - ImageCanvas ic = getCanvas(); - if (ic == null || imp2 == null) - return; - imp = imp2; - imp.setWindow(this); - ic.updateImage(imp); - ic.setImageUpdated(); - ic.repaint(); - repaint(); - } - - /*Changed for Bio7. Overwrite repaint to send a message to the swt statusline!*/ - public void repaint() { - Display display = Util.getDisplay(); - /* - * MacOSX only seems to work with async method! Also on Windows async works best - * (avoids deadlocks when mouse moved in and out the canvas opening several - * images at once in the background!). - */ - - display.asyncExec(new Runnable() { - public void run() { - if (imp != null) { - - if (imp.isComposite()) { - CompositeImage ci = (CompositeImage) imp; - if (ci.getMode() == IJ.COMPOSITE) { - Color c = ci.getChannelColor(); - if (Color.green.equals(c)) - c = new Color(0, 180, 0); - // g.setColor(c); - int red = c.getRed(); - int green = c.getGreen(); - int blue = c.getBlue(); - org.eclipse.swt.graphics.Color color = new org.eclipse.swt.graphics.Color(display, - new RGB(red, green, blue)); - // CanvasView.tabFolder.setSelectionForeground(color); - /*On MacOSX we get NullPointerException when we call the status line first. - * So we place the call to the status line here!*/ - CanvasView canvasView = CanvasView.getCanvas_view(); - if (canvasView != null) { - canvasView.setStatusLineColor(createSubtitle(), color); - } - - } - - } else { - CanvasView canvasView = CanvasView.getCanvas_view(); - if (canvasView != null) { - canvasView.setstatusline(createSubtitle()); - } - } - - } - } - }); - super.repaint(); - } - - public void show() { - /*Changed for Bio7! - * Empty function. - * The overwrite implementation avoids the opening - * of a JFrame ImageWindow and a reference to the image from the - * Functions class method: displayBatchModeImage in a macro when calling - * setBatchMode(false) - * */ - // System.out.println("Show"); - } - - public void updateImage(ImagePlus imp) { - if (imp != this.imp) - throw new IllegalArgumentException("imp!=this.imp"); - this.imp = imp; - ic.updateImage(imp); - setLocationAndSize(true); - if (this instanceof StackWindow) { - StackWindow sw = (StackWindow) this; - int stackSize = imp.getStackSize(); - int nScrollbars = sw.getNScrollbars(); - if (stackSize == 1 && nScrollbars > 0) - sw.removeScrollbars(); - else if (stackSize > 1 && nScrollbars == 0) - sw.addScrollbars(imp); - } - pack(); - repaint(); - maxBounds = getMaximumBounds(); - setMaximizedBounds(maxBounds); - setMaxBoundsTime = System.currentTimeMillis(); - } - - public ImageCanvas getCanvas() { - return ic; - } - - static ImagePlus getClipboard() { - return ImagePlus.getClipboard(); - } - - public Rectangle getBounds() { - Rectangle rec; - JPanel current = CanvasView.getCanvas_view().getCurrent(); - JPanel pan = current; - if (pan != null) { - rec = current.getBounds(); - } else { - rec = new Rectangle(400, 400); - } - - return rec; - - } - - public Rectangle getMaximumBounds() { - Rectangle rec; - JPanel pan = CanvasView.getCanvas_view().getCurrent(); - if (pan != null) { - rec = CanvasView.getCanvas_view().getCurrent().getBounds(); - } else { - rec = new Rectangle(400, 400); - } - - /* - * Rectangle maxWindow = GUI.getMaxWindowBounds(); if (imp == null) return - * maxWindow; double width = imp.getWidth(); double height = imp.getHeight(); - * double iAspectRatio = width / height; - * - * maxWindowBounds = maxWindow; if (iAspectRatio / ((double) maxWindow.width / - * maxWindow.height) > 0.75) { maxWindow.y += 22; // uncover ImageJ menu bar - * maxWindow.height -= 22; } Dimension extraSize = getExtraSize(); double - * maxWidth = maxWindow.width - extraSize.width; double maxHeight = - * maxWindow.height - extraSize.height; double mAspectRatio = maxWidth / - * maxHeight; int wWidth, wHeight; double mag; if (iAspectRatio >= mAspectRatio) - * { mag = maxWidth / width; wWidth = maxWindow.width; wHeight = (int) (height * - * mag + extraSize.height); } else { mag = maxHeight / height; wHeight = - * maxWindow.height; wWidth = (int) (width * mag + extraSize.width); } int xloc - * = (int) (maxWidth - wWidth) / 2; if (xloc < 0) xloc = 0; - */ - return rec; - } - - Dimension getExtraSize() { - Insets insets = getInsets(); - int extraWidth = insets.left + insets.right + 10; - int extraHeight = insets.top + insets.bottom + 10; - if (extraHeight == 20) - extraHeight = 42; - int members = getComponentCount(); - for (int i = 1; i < members; i++) { - Component m = getComponent(i); - Dimension d = m.getPreferredSize(); - extraHeight += d.height + 5; - if (IJ.debugMode) - IJ.log(i + " " + d.height + " " + extraHeight); - } - return new Dimension(extraWidth, extraHeight); - } - - public Component add(Component comp) { - comp = super.add(comp); - maxBounds = getMaximumBounds(); - setMaximizedBounds(maxBounds); - setMaxBoundsTime = System.currentTimeMillis(); - return comp; - } - - public void maximize() { - if (GenericDialog.getInstance() != null && IJ.isMacOSX() && IJ.isJava18()) - return; // workaround for OSX/Java 8 maximize bug - Rectangle rect = getMaximumBounds(); - if (IJ.debugMode) - IJ.log("maximize: " + rect); - setLocationAndSize(rect.x, rect.y, rect.width, rect.height); - } - - public void minimize() { - if (IJ.debugMode) - IJ.log("minimize: " + unzoomWhenMinimizing); - if (unzoomWhenMinimizing) - ic.unzoom(); - unzoomWhenMinimizing = true; - } - - /** Has this window been closed? */ - public boolean isClosed() { - return closed; - } - - public void focusGained(FocusEvent e) { - if (!Interpreter.isBatchMode() && ij != null && !ij.quitting() && imp != null) { - //if (IJ.debugMode) - //IJ.log("focusGained: " + imp); - WindowManager.setCurrentWindow(this); - } - } - - public void windowActivated(WindowEvent e) { - if (IJ.debugMode) - IJ.log("windowActivated: " + imp.getTitle()); - if (IJ.isMacOSX() && Prefs.setIJMenuBar && !IJ.isMacro()) - setImageJMenuBar(this); - if (imp == null) - return; - ImageJ ij = IJ.getInstance(); - if (ij != null && !closed && !ij.quitting() && !Interpreter.isBatchMode()) - WindowManager.setCurrentWindow(this); - Roi roi = imp.getRoi(); - if (roi != null && (roi instanceof PointRoi)) - PointToolOptions.update(); - if (imp.isComposite()) - Channels.updateChannels(); - imp.setActivated(); // notify ImagePlus that image has been activated - } - - public void windowClosing(WindowEvent e) { - if (closed) - return; - if (ij != null) { - WindowManager.setCurrentWindow(this); - IJ.doCommand("Close"); - } else { - dispose(); - WindowManager.removeWindow(this); - } - } - - public void windowStateChanged(WindowEvent e) { - int oldState = e.getOldState(); - int newState = e.getNewState(); - if (IJ.debugMode) - IJ.log("windowStateChanged: " + oldState + " " + newState); - if ((oldState & Frame.MAXIMIZED_BOTH) == 0 && (newState & Frame.MAXIMIZED_BOTH) != 0) - maximize(); - - } - - public void windowClosed(WindowEvent e) { - } - - public void windowDeactivated(WindowEvent e) { - } - - public void focusLost(FocusEvent e) { - } - - public void windowDeiconified(WindowEvent e) { - } - - public void windowIconified(WindowEvent e) { - } - - public void windowOpened(WindowEvent e) { - } - - public synchronized void mouseWheelMoved(MouseWheelEvent e) { - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - //if (IJ.debugMode) { - // IJ.log("mouseWheelMoved: "+e); - // IJ.log(" type: "+e.getScrollType()); - // IJ.log(" ctrl: "+ctrl); - // IJ.log(" rotation: "+rotation); - // IJ.log(" amount: "+amount); - //} - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - int width = imp.getWidth(); - int height = imp.getHeight(); - Rectangle srcRect = ic.getSrcRect(); - int xstart = srcRect.x; - int ystart = srcRect.y; - if ((ctrl || IJ.shiftKeyDown()) && ic != null) { - int ox = ic.offScreenX(e.getX()); - int oy = ic.offScreenY(e.getX()); - if (IJ.debugMode) - IJ.log(" x,y: " + ox + "," + oy); - if (rotation < 0) - ic.zoomIn(ox, oy); - else - ic.zoomOut(ox, oy); - return; - } else if (IJ.spaceBarDown() || srcRect.height == height) { - srcRect.x += rotation * amount * Math.max(width / 200, 1); - if (srcRect.x < 0) - srcRect.x = 0; - if (srcRect.x + srcRect.width > width) - srcRect.x = width - srcRect.width; - } else { - srcRect.y += rotation * amount * Math.max(height / 200, 1); - if (srcRect.y < 0) - srcRect.y = 0; - if (srcRect.y + srcRect.height > height) - srcRect.y = height - srcRect.height; - } - if (srcRect.x != xstart || srcRect.y != ystart) - ic.repaint(); - } - - /** - * Copies the current ROI to the clipboard. The entire image is copied if there - * is no ROI. - */ - public void copy(boolean cut) { - imp.copy(cut); - } - - public void paste() { - imp.paste(); - } - - /** - * This method is called by ImageCanvas.mouseMoved(MouseEvent). - * - * @see ij.gui.ImageCanvas#mouseMoved - */ - public void mouseMoved(int x, int y) { - imp.mouseMoved(x, y); - } - - public String toString() { - return imp != null ? imp.getTitle() : ""; - } - - /** - * Causes the next image to be opened to be centered on the screen and displayed - * without informational text above the image. - */ - public static void centerNextImage() { - centerOnScreen = true; - } - - /** Causes the next image to be displayed at the specified location. */ - public static void setNextLocation(Point loc) { - nextLocation = loc; - } - - /** Causes the next image to be displayed at the specified location. */ - public static void setNextLocation(int x, int y) { - nextLocation = new Point(x, y); - } - - /** - * Moves and resizes this window. Changes the magnification so the image fills - * the window. - */ - public void setLocationAndSize(int x, int y, int width, int height) { - /*Changed for Bio7 for detached views only!*/ - String idValue = Integer.toString(getImagePlus().getID()); - IJTabs.setSecondaryViewShellLocAndSize(idValue, new org.eclipse.swt.graphics.Rectangle(x, y, width, height)); - } - - @Override - public void setLocation(int x, int y) { - super.setLocation(x, y); - } - - public void setSliderHeight(int height) { - sliderHeight = height; - } - - public int getSliderHeight() { - return sliderHeight; - } - - public static void setImageJMenuBar(ImageWindow win) { - ImageJ ij = IJ.getInstance(); - boolean setMenuBar = true; - ImagePlus imp = win.getImagePlus(); - if (imp != null) - setMenuBar = imp.setIJMenuBar(); - MenuBar mb = Menus.getMenuBar(); - if (mb != null && mb == win.getMenuBar()) - setMenuBar = false; - setMenuBarTime = 0L; - if (setMenuBar && ij!=null && !ij.quitting()) { - IJ.wait(10); // may be needed for Java 1.4 on OS X - long t0 = System.currentTimeMillis(); - win.setMenuBar(mb); - long time = System.currentTimeMillis() - t0; - setMenuBarTime = time; - Menus.setMenuBarCount++; - if (time > 2000L) - Prefs.setIJMenuBar = false; - - } - if (imp != null) - imp.setIJMenuBar(true); - } - -} // class ImageWindow diff --git a/com.eco.bio7.image/src/ij/gui/Line.java b/com.eco.bio7.image/src/ij/gui/Line.java deleted file mode 100644 index 3149cffd0..000000000 --- a/com.eco.bio7.image/src/ij/gui/Line.java +++ /dev/null @@ -1,841 +0,0 @@ -package ij.gui; - -import ij.*; -import ij.process.*; -import ij.measure.*; -import ij.plugin.Straightener; -import ij.plugin.frame.Recorder; -import ij.plugin.CalibrationBar; -import java.awt.*; -import java.awt.image.*; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.awt.event.*; -import java.awt.geom.*; - -/** This class represents a straight line selection. */ -public class Line extends Roi { - public int x1, y1, x2, y2; // the line end points as integer coordinates, for compatibility only - public double x1d, y1d, x2d, y2d; // the line using sub-pixel coordinates - protected double x1R, y1R, x2R, y2R; // the line, relative to base of subpixel bounding rect 'bounds' - protected double startxd, startyd; - static boolean widthChanged; - private boolean dragged; - private int mouseUpCount; - - /** - * Creates a new straight line selection using the specified starting and ending - * offscreen integer coordinates. - */ - public Line(int ox1, int oy1, int ox2, int oy2) { - this((double) ox1, (double) oy1, (double) ox2, (double) oy2); - } - - /** - * Creates a new straight line selection using the specified starting and ending - * offscreen double coordinates. - */ - public Line(double ox1, double oy1, double ox2, double oy2) { - super((int) (ox1 + 0.5), (int) (oy1 + 0.5), 0, 0); - type = LINE; - updateCoordinates(ox1, oy1, ox2, oy2); - if (!(this instanceof Arrow) && lineWidth > 1) - updateWideLine(lineWidth); - updateClipRect(); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - state = NORMAL; - } - - /** - * Creates a new straight line selection using the specified starting and ending - * offscreen coordinates. - */ - public static Line create(double x1, double y1, double x2, double y2) { - return new Line(x1, y1, x2, y2); - } - - /** - * Starts the process of creating a new user-generated straight line selection. - * 'sx' and 'sy' are screen coordinates that specify the start of the line. The - * user will determine the end of the line interactively using rubber banding. - */ - public Line(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - type = LINE; - startxd = offScreenXD(sx); - startyd = offScreenYD(sy); - if (!magnificationForSubPixel()) { - startxd = Math.round(startxd); - startyd = Math.round(startyd); - } - updateCoordinates(startxd, startyd, startxd, startyd); - if (!(this instanceof Arrow) && lineWidth > 1) - updateWideLine(lineWidth); - } - - /** - * @deprecated replaced by Line(int, int, int, int) - */ - public Line(int ox1, int oy1, int ox2, int oy2, ImagePlus imp) { - this(ox1, oy1, ox2, oy2); - setImage(imp); - } - - protected void grow(int sx, int sy) { // mouseDragged - drawLine(sx, sy); - dragged = true; - } - - public void mouseMoved(MouseEvent e) { - drawLine(e.getX(), e.getY()); - } - - protected void handleMouseUp(int screenX, int screenY) { - mouseUpCount++; - if (Prefs.enhancedLineTool && mouseUpCount == 1 && !dragged) - return; - state = NORMAL; - if (imp == null) - return; - imp.draw(clipX - 5, clipY - 5, clipWidth + 10, clipHeight + 10); - if (IJ.recording()) { - String method = (this instanceof Arrow) ? "makeArrow" : "makeLine"; - Recorder.record(method, x1, y1, x2, y2); - } - if (getLength() == 0.0) - imp.deleteRoi(); - } - - protected void drawLine(int sx, int sy) { - double xend = offScreenXD(sx); - double yend = offScreenYD(sy); - if (xend < 0.0) - xend = 0.0; - if (yend < 0.0) - yend = 0.0; - if (xend > xMax - 1) - xend = xMax - 1; - if (yend > yMax - 1) - yend = yMax - 1; - double xstart = getXBase() + x1R, ystart = getYBase() + y1R; - if (constrain) { - int i = 0; - double dy = Math.abs(yend - ystart); - double dx = Math.abs(xend - xstart); - double comp = dy / dx; - for (; i < PI_SEARCH.length; i++) { - if (comp < PI_SEARCH[i]) { - break; - } - } - if (i < PI_SEARCH.length) { - if (yend > ystart) { - yend = ystart + dx * PI_MULT[i]; - } else { - yend = ystart - dx * PI_MULT[i]; - } - } else { - xend = xstart; - } - } - if (!magnificationForSubPixel() || IJ.controlKeyDown()) { // during creation, CTRL enforces integer coordinates - xstart = Math.round(xstart); - ystart = Math.round(ystart); - xend = Math.round(xend); - yend = Math.round(yend); - } - updateCoordinates(xstart, ystart, xend, yend); - updateClipRect(); - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - } - - /** - * Used for angle searches in line ROI creation: tan = y/x for angle limits - * 1/2*45 degrees, and 3/2*45 deg - */ - private static final double[] PI_SEARCH = { Math.tan(Math.PI / 8), Math.tan((3 * Math.PI) / 8) }; - private static final double[] PI_MULT = { 0, 1 }; // y/x for horizontal (0 degrees) and 45 deg - - void move(int sx, int sy) { - int xNew = offScreenX(sx); - int yNew = offScreenY(sy); - x += xNew - startxd; - y += yNew - startyd; - clipboard = null; - startxd = xNew; - startyd = yNew; - updateClipRect(); - if (ignoreClipRect) - imp.draw(); - else - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - } - - protected void moveHandle(int sx, int sy) { - if (constrain && activeHandle == 2) { // constrain translation in 90deg steps - int dx = sx - previousSX; - int dy = sy - previousSY; - if (Math.abs(dx) > Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - double ox = offScreenXD(sx); - double oy = offScreenYD(sy); - double x1d = getXBase() + x1R, y1d = getYBase() + y1R; - double x2d = getXBase() + x2R, y2d = getYBase() + y2R; - double length = Math.sqrt(sqr(x2d - x1d) + sqr(y2d - y1d)); - switch (activeHandle) { - case 0: - double dx = ox - x1d; - double dy = oy - y1d; - x1d = ox; - y1d = oy; - if (center) { - x2d -= dx; - y2d -= dy; - } - if (aspect) { - double ratio = length / (Math.sqrt(sqr(x2d - x1d) + sqr(y2d - y1d))); - double xcd = x1d + (x2d - x1d) / 2; - double ycd = y1d + (y2d - y1d) / 2; - - if (center) { - x1d = xcd - ratio * (xcd - x1d); - x2d = xcd + ratio * (x2d - xcd); - y1d = ycd - ratio * (ycd - y1d); - y2d = ycd + ratio * (y2d - ycd); - } else { - x1d = x2d - ratio * (x2d - x1d); - y1d = y2d - ratio * (y2d - y1d); - } - - } - break; - case 1: - dx = ox - x2d; - dy = oy - y2d; - x2d = ox; - y2d = oy; - if (center) { - x1d -= dx; - y1d -= dy; - } - if (aspect) { - double ratio = length / (Math.sqrt((x2d - x1d) * (x2d - x1d) + (y2d - y1d) * (y2d - y1d))); - double xcd = x1d + (x2d - x1d) / 2; - double ycd = y1d + (y2d - y1d) / 2; - - if (center) { - x1d = xcd - ratio * (xcd - x1d); - x2d = xcd + ratio * (x2d - xcd); - y1d = ycd - ratio * (ycd - y1d); - y2d = ycd + ratio * (y2d - ycd); - } else { - x2d = x1d + ratio * (x2d - x1d); - y2d = y1d + ratio * (y2d - y1d); - } - - } - break; - case 2: - dx = ox - (x1d + (x2d - x1d) / 2); - dy = oy - (y1d + (y2d - y1d) / 2); - x1d += dx; - y1d += dy; - x2d += dx; - y2d += dy; - break; - } - if (constrain) { - double dx = Math.abs(x1d - x2d); - double dy = Math.abs(y1d - y2d); - double xcd = Math.min(x1d, x2d) + dx / 2; - double ycd = Math.min(y1d, y2d) + dy / 2; - - // double ratio = length/(Math.sqrt((x2d-x1d)*(x2d-x1d) + (y2d-y1d)*(y2d-y1d))); - if (activeHandle == 0) { - if (dx >= dy) { - if (aspect) { - if (x2d > x1d) - x1d = x2d - length; - else - x1d = x2d + length; - } - y1d = y2d; - if (center) { - y1d = y2d = ycd; - if (aspect) { - if (xcd > x1d) { - x1d = xcd - length / 2; - x2d = xcd + length / 2; - } else { - x1d = xcd + length / 2; - x2d = xcd - length / 2; - } - } - } - } else { - if (aspect) { - if (y2d > y1d) - y1d = y2d - length; - else - y1d = y2d + length; - } - x1d = x2d; - if (center) { - x1d = x2d = xcd; - if (aspect) { - if (ycd > y1d) { - y1d = ycd - length / 2; - y2d = ycd + length / 2; - } else { - y1d = ycd + length / 2; - y2d = ycd - length / 2; - } - } - } - } - } else if (activeHandle == 1) { - if (dx >= dy) { - if (aspect) { - if (x1d > x2d) - x2d = x1d - length; - else - x2d = x1d + length; - } - y2d = y1d; - if (center) { - y1d = y2d = ycd; - if (aspect) { - if (xcd > x1d) { - x1d = xcd - length / 2; - x2d = xcd + length / 2; - } else { - x1d = xcd + length / 2; - x2d = xcd - length / 2; - } - } - } - } else { - if (aspect) { - if (y1d > y2d) - y2d = y1d - length; - else - y2d = y1d + length; - } - x2d = x1d; - if (center) { - x1d = x2d = xcd; - if (aspect) { - if (ycd > y1d) { - y1d = ycd - length / 2; - y2d = ycd + length / 2; - } else { - y1d = ycd + length / 2; - y2d = ycd - length / 2; - } - } - } - } - } - } - if (!magnificationForSubPixel()) { - x1d = Math.round(x1d); - y1d = Math.round(y1d); - x2d = Math.round(x2d); - y2d = Math.round(y2d); - } - updateCoordinates(x1d, y1d, x2d, y2d); - updateClipRect(); - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - } - - protected void mouseDownInHandle(int handle, int sx, int sy) { - super.mouseDownInHandle(handle, sx, sy); // sets state, activeHandle, previousSX&Y - if (getStrokeWidth() <= 3) - ic.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); - } - - /** - * Sets the x1d, y1d, x2d, y2d line end points, the (legacy) integer coordinates - * of the end points x1, y1, x2, y2 the 'bounds' subpixel rectangle of the Roi - * superclass (spanned by the end points), the int x, y, width, height integer - * bounds of the superclass (these enclose the 'draw' area for 1 pixel width), - * and the coordinates x1R, y1R, x2R, y2R relative to the base x, y of the - * 'bounds' - */ - void updateCoordinates(double x1d, double y1d, double x2d, double y2d) { - this.x1d = x1d; - this.y1d = y1d; - this.x2d = x2d; - this.y2d = y2d; - Rectangle2D.Double bounds = this.bounds; // local variable (this.bounds may become null asynchronously upon nudge) - if (bounds == null) - bounds = new Rectangle2D.Double(); - bounds.x = Math.min(x1d, x2d); - bounds.y = Math.min(y1d, y2d); - bounds.width = Math.abs(x2d - x1d); - bounds.height = Math.abs(y2d - y1d); - setIntBounds(bounds); // sets x, y, width, height - x1R = x1d - bounds.x; - y1R = y1d - bounds.y; - x2R = x2d - bounds.x; - y2R = y2d - bounds.y; - x1 = (int) x1d; - y1 = (int) y1d; - x2 = (int) x2d; - y2 = (int) y2d; - this.bounds = bounds; - } - - /** Draws this line on the image. */ - public void draw(Graphics g) { - Color color = strokeColor != null ? strokeColor : ROIColor; - boolean isActiveOverlayRoi = !overlay && isActiveOverlayRoi(); - mag = getMagnification(); - if (isActiveOverlayRoi) { - if (color == Color.cyan) - color = Color.magenta; - else - color = Color.cyan; - } - g.setColor(color); - x1d = getXBase() + x1R; - y1d = getYBase() + y1R; - x2d = getXBase() + x2R; - y2d = getYBase() + y2R; - x1 = (int) x1d; - y1 = (int) y1d; - x2 = (int) x2d; - y2 = (int) y2d; - int sx1 = screenXD(x1d); - int sy1 = screenYD(y1d); - int sx2 = screenXD(x2d); - int sy2 = screenYD(y2d); - int sx3 = sx1 + (sx2 - sx1) / 2; - int sy3 = sy1 + (sy2 - sy1) / 2; - Graphics2D g2d = (Graphics2D) g; - setRenderingHint(g2d); - boolean cbar = overlay && mag < 1.0 && Math.abs(getStrokeWidth() - CalibrationBar.STROKE_WIDTH) < 0.0001; - if (stroke != null && !isActiveOverlayRoi && !cbar) - g2d.setStroke(getScaledStroke()); - else if (cbar) - g2d.setStroke(onePixelWide); - if (wideLine && !isActiveOverlayRoi && !cbar) { - double dx = sx2 - sx1; - double dy = sy2 - sy1; - double len = length(dx, dy); - dx *= 0.5 * mag / len; // half-pixel extension, corresponding to getFloatPolygon or convertLineToArea - dy *= 0.5 * mag / len; - g2d.draw(new Line2D.Double(sx1 - dx, sy1 - dy, sx2 + dx, sy2 + dy)); - } else - g.drawLine(sx1, sy1, sx2, sy2); - if (wideLine && !overlay) { - g2d.setStroke(onePixelWide); - g.setColor(getColor()); - g.drawLine(sx1, sy1, sx2, sy2); - } - if (!overlay) { - handleColor = strokeColor != null ? strokeColor : ROIColor; - drawHandle(g, sx1, sy1); - handleColor = Color.white; - drawHandle(g, sx2, sy2); - drawHandle(g, sx3, sy3); - } - if (state != NORMAL) - showStatus(); - if (updateFullWindow) { - updateFullWindow = false; - imp.draw(); - } - } - - public void showStatus() { - IJ.showStatus(imp.getLocationAsString((int) Math.round(x2d), (int) Math.round(y2d)) + ", angle=" + IJ.d2s(getAngle()) + ", length=" + IJ.d2s(getLength())); - } - - public double getAngle() { - return getFloatAngle(x1d, y1d, x2d, y2d); - } - - /** Returns the length of this line. */ - public double getLength() { - if (imp == null || IJ.altKeyDown()) - return getRawLength(); - else { - Calibration cal = imp.getCalibration(); - return Math.sqrt(sqr((x2d - x1d) * cal.pixelWidth) + sqr((y2d - y1d) * cal.pixelHeight)); - } - } - - /** Returns the length of this line in pixels. */ - public double getRawLength() { - return Math.sqrt(sqr(x2d - x1d) + sqr(y2d - y1d)); - } - - /** - * Returns the pixel values along this line. The line roi must have an - * associated ImagePlus. - */ - public double[] getPixels() { - double[] profile; - if (getStrokeWidth() <= 1) { - ImageProcessor ip = imp.getProcessor(); - profile = ip.getLine(x1d, y1d, x2d, y2d); - } else { - Straightener s = new Straightener(); - ImageProcessor ip2 = s.straightenLine(imp, this, 0); - if (ip2 == null) - return new double[0]; - int width = ip2.getWidth(); - int height = ip2.getHeight(); - if (ip2 instanceof FloatProcessor) - return ProfilePlot.getColumnAverageProfile(new Rectangle(0, 0, width, height), ip2); - profile = new double[width]; - double[] aLine; - ip2.setInterpolate(false); - for (int y = 0; y < height; y++) { - aLine = ip2.getLine(0, y, width - 1, y); - for (int i = 0; i < width; i++) - profile[i] += aLine[i]; - } - for (int i = 0; i < width; i++) - profile[i] /= height; - } - return profile; - } - - /** Returns, as a Polygon, the two points that define this line. */ - public Polygon getPoints() { - Polygon p = new Polygon(); - p.addPoint((int) Math.round(x1d), (int) Math.round(y1d)); - p.addPoint((int) Math.round(x2d), (int) Math.round(y2d)); - return p; - } - - /** Returns, as a FloatPolygon, the two points that define this line. */ - public FloatPolygon getFloatPoints() { - FloatPolygon p = new FloatPolygon(); - p.addPoint((float) x1d, (float) y1d); - p.addPoint((float) x2d, (float) y2d); - return p; - } - - /** - * If the width of this line is less than or equal to one, returns the starting - * and ending coordinates as a 2-point Polygon, or, if the width is greater than - * one, returns an outline of the line as a 4-point Polygon. - * - * @see #getFloatPolygon - * @see #getPoints - */ - public Polygon getPolygon() { - FloatPolygon p = getFloatPolygon(); - return new Polygon(toIntR(p.xpoints), toIntR(p.ypoints), p.npoints); - } - - /** - * If the width of this line is less than or equal to one, returns the starting - * and ending coordinates as a 2-point FloatPolygon, or, if the width is greater - * than one, returns an outline of the line as a 4-point FloatPolygon. - * - * @see #getFloatPoints - */ - public FloatPolygon getFloatPolygon() { - return getFloatPolygon(getStrokeWidth()); - } - - /** Obsolete */ - public FloatPolygon getFloatPolygon(double strokeWidth) { - FloatPolygon p = new FloatPolygon(); - if (strokeWidth <= 1) { - p.addPoint((float) x1d, (float) y1d); - p.addPoint((float) x2d, (float) y2d); - } else { - double dx = x2d - x1d; - double dy = y2d - y1d; - double len = length(dx, dy); - dx *= 0.5 / len; // half unit vector in the direction of the line - dy *= 0.5 / len; // when rotated 90 deg cw, this yields the vector (-dx, dy) - double p1x = x1d + 0.5 - dx + dy * strokeWidth; // 0.5 pxl shift: area vs. line coordinate convention - double p1y = y1d + 0.5 - dy - dx * strokeWidth; - double p2x = x1d + 0.5 - dx - dy * strokeWidth; - double p2y = y1d + 0.5 - dy + dx * strokeWidth; - double p3x = x2d + 0.5 + dx - dy * strokeWidth; - double p3y = y2d + 0.5 + dy + dx * strokeWidth; - double p4x = x2d + 0.5 + dx + dy * strokeWidth; - double p4y = y2d + 0.5 + dy - dx * strokeWidth; - p.addPoint((float) p1x, (float) p1y); - p.addPoint((float) p2x, (float) p2y); - p.addPoint((float) p3x, (float) p3y); - p.addPoint((float) p4x, (float) p4y); - } - return p; - } - - /** - * Returns the number of points in this selection; equivalent to - * getPolygon().npoints. - */ - public int size() { - return getStrokeWidth() <= 1 ? 2 : 4; - } - - /** - * If the width of this line is less than or equal to one, draws the line. - * Otherwise draws the outline of the area of this line. - */ - public void drawPixels(ImageProcessor ip) { - boolean fillLine = getStrokeWidth() > 1 && getWidth() <= 1; - if (fillLine) - ip.setLineWidth((int) Math.round(getStrokeWidth())); - else - ip.setLineWidth(1); - double x = getXBase(); - double y = getYBase(); - x1d = getXBase() + x1R; - y1d = getYBase() + y1R; - x2d = getXBase() + x2R; - y2d = getYBase() + y2R; - if (getStrokeWidth() <= 1 || fillLine) { - ip.moveTo((int) Math.round(x1d), (int) Math.round(y1d)); - ip.lineTo((int) Math.round(x2d), (int) Math.round(y2d)); - } else { - Polygon p = getPolygon(); - ip.drawPolygon(p); - updateFullWindow = true; - } - } - - public boolean contains(int x, int y) { - if (getStrokeWidth() > 1) { - if ((x == x1 && y == y1) || (x == x2 && y == y2)) - return true; - else - return getPolygon().contains(x, y); - } else - return false; - } - - protected void handleMouseDown(int sx, int sy) { - super.handleMouseDown(sx, sy); - startxd = ic.offScreenXD(sx); - startyd = ic.offScreenYD(sy); - } - - /** - * Returns a handle number if the specified screen coordinates are inside or - * near a handle, otherwise returns -1. - */ - public int isHandle(int sx, int sy) { - int size = HANDLE_SIZE + 5; - if (getStrokeWidth() > 1) - size += (int) Math.log(getStrokeWidth()); - int halfSize = size / 2; - int sx1 = screenXD(getXBase() + x1R) - halfSize; - int sy1 = screenYD(getYBase() + y1R) - halfSize; - int sx2 = screenXD(getXBase() + x2R) - halfSize; - int sy2 = screenYD(getYBase() + y2R) - halfSize; - int sx3 = sx1 + (sx2 - sx1) / 2 - 1; - int sy3 = sy1 + (sy2 - sy1) / 2 - 1; - if (sx >= sx1 && sx <= sx1 + size && sy >= sy1 && sy <= sy1 + size) - return 0; - if (sx >= sx2 && sx <= sx2 + size && sy >= sy2 && sy <= sy2 + size) - return 1; - if (sx >= sx3 && sx <= sx3 + size + 2 && sy >= sy3 && sy <= sy3 + size + 2) - return 2; - return -1; - } - - /** - * Returns the default line width. Use getStrokeWidth()to get the width of a - * Line instance. - * - * @see #getStrokeWidth - */ - public static int getWidth() { - return lineWidth; - } - - /** - * Sets the default line width. Use setStrokeWidth() to set the width of a Line - * instance. - * - * @see #setStrokeWidth - */ - public static void setWidth(int w) { - if (w < 1) - w = 1; - int max = 500; - if (w > max) { - ImagePlus imp2 = WindowManager.getCurrentImage(); - if (imp2 != null) { - max = Math.max(max, imp2.getWidth()); - max = Math.max(max, imp2.getHeight()); - } - if (w > max) - w = max; - } - lineWidth = w; - widthChanged = true; - } - - /* Sets the width of this line. */ - public void setStrokeWidth(float width) { - super.setStrokeWidth(width); - if (getStrokeColor() == Roi.getColor()) - wideLine = true; - } - - protected int clipRectMargin() { - return 4; - } - - /** Nudge end point of line by one pixel. */ - public void nudgeCorner(int key) { - if (ic == null) - return; - double inc = 1.0 / ic.getMagnification(); - switch (key) { - case KeyEvent.VK_UP: - y2R -= inc; - break; - case KeyEvent.VK_DOWN: - y2R += inc; - break; - case KeyEvent.VK_LEFT: - x2R -= inc; - break; - case KeyEvent.VK_RIGHT: - x2R += inc; - break; - } - grow(screenXD(x + x2R), screenYD(y + y2R)); - notifyListeners(RoiListener.MOVED); - showStatus(); - } - - /** Always returns true. */ - public boolean subPixelResolution() { - return true; - } - - public void setLocation(int x, int y) { - setLocation((double) x, (double) y); - } - - /** - * Sets the x coordinate of the leftmost and y coordinate of the topmost end - * point - */ - public void setLocation(double x, double y) { - updateCoordinates(x + x1R, y + y1R, x + x2R, y + y2R); - } - - public FloatPolygon getRotationCenter() { - double xcenter = x1d + (x2d - x1d) / 2.0; - double ycenter = y1d + (y2d - y1d) / 2.0; - FloatPolygon p = new FloatPolygon(); - p.addPoint(xcenter, ycenter); - return p; - } - - /** - * Dedicated point iterator for thin lines. The iterator is based on (an - * improved version of) the algorithm used by the original method - * {@code ImageProcessor.getLine(double, double, double, double)}. Improvements - * are (a) that the endpoint is drawn too and (b) every line point is visited - * only once, duplicates are skipped. - * - * Author: Wilhelm Burger (04/2017) - */ - public static class PointIterator implements Iterator { - private double x1, y1; - private final int n; - private final double xinc, yinc; - private double x, y; - private int u, v; - private int u_prev, v_prev; - private int i; - - public PointIterator(Line line) { - this(line.x1d, line.y1d, line.x2d, line.y2d); - } - - public PointIterator(double x1, double y1, double x2, double y2) { - this.x1 = x1; - this.y1 = y1; - double dx = x2 - x1; - double dy = y2 - y1; - this.n = (int) Math.ceil(Math.sqrt(dx * dx + dy * dy)); - this.xinc = dx / n; - this.yinc = dy / n; - x = x1; - y = y1; - u = (int) Math.round(x - 0.5); - v = (int) Math.round(y - 0.5); - u_prev = Integer.MIN_VALUE; - v_prev = Integer.MIN_VALUE; - i = 0; - } - - @Override - public boolean hasNext() { - return i <= n; // needs to be '<=' to include last segment (point)! - } - - @Override - public Point next() { - if (i > n) - throw new NoSuchElementException(); - Point p = new Point(u, v); // the current (next) point - moveToNext(); - return p; - } - - // move to next point by skipping duplicate points - private void moveToNext() { - do { - i = i + 1; - x = x1 + i * xinc; - y = y1 + i * yinc; - u_prev = u; - v_prev = v; - u = (int) Math.round(x - 0.5); - v = (int) Math.round(y - 0.5); - } while (i <= n && u == u_prev && v == v_prev); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - @Override - public Iterator iterator() { - if (getStrokeWidth() <= 1.0) - return new PointIterator(this); // use the specific thin-line iterator - else - return super.iterator(); // fall back on Roi's iterator - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/MessageDialog.java b/com.eco.bio7.image/src/ij/gui/MessageDialog.java deleted file mode 100644 index 3f02e1b55..000000000 --- a/com.eco.bio7.image/src/ij/gui/MessageDialog.java +++ /dev/null @@ -1,62 +0,0 @@ -/*Message Dialog copied from the Bio7 project. - * Author: Marcel Austenfeld*/ -package ij.gui; - -import java.awt.Frame; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.MessageBox; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; - -/* Changed for Bio7! A modal dialog base on SWT as a replacement for the ImageJ message dialog! */ - -public class MessageDialog { - protected MultiLineLabel label; - private boolean escapePressed; - protected int result; - - public MessageDialog(Frame parent, String title, String message) { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - public void run() { - MessageBox messageBox = new MessageBox(getShell(), - - SWT.ICON_WARNING); - - messageBox.setText(title); - messageBox.setMessage(message); - result = messageBox.open(); - if (result == SWT.OK) { - escapePressed = true; - } - } - }); - - } - - /** - * Returns a platform shell for dialogs, etc. - * - * @return a shell - */ - public static Shell getShell() { - IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (window == null) { - IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); - if (windows.length > 0) { - return windows[0].getShell(); - } - } else { - return window.getShell(); - } - return null; - } - - public boolean escapePressed() { - return escapePressed; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/MultiLineLabel.java b/com.eco.bio7.image/src/ij/gui/MultiLineLabel.java deleted file mode 100644 index 4aed7d6e9..000000000 --- a/com.eco.bio7.image/src/ij/gui/MultiLineLabel.java +++ /dev/null @@ -1,111 +0,0 @@ -package ij.gui; -import java.awt.*; -import java.util.*; - -import javax.swing.JPanel; - -/**Custom component for displaying multiple lines. Based on - MultiLineLabel class from "Java in a Nutshell" by David Flanagan.*/ -public class MultiLineLabel extends JPanel { - String[] lines; - int num_lines; - int margin_width = 6; - int margin_height = 6; - int line_height; - int line_ascent; - int[] line_widths; - int min_width, max_width; - - // Breaks the specified label up into an array of lines. - public MultiLineLabel(String label) { - init(label); - } - - public MultiLineLabel(String label, int minimumWidth) { - init(label); - min_width = minimumWidth; - } - - private void init(String text) { - StringTokenizer t = new StringTokenizer(text, "\n"); - num_lines = t.countTokens(); - lines = new String[num_lines]; - line_widths = new int[num_lines]; - for (int i=0; i max_width) max_width = line_widths[i]; - } - } - - - public void setText(String text) { - init(text); - measure(); - repaint(); - } - - public void setFont(Font f) { - super.setFont(f); - measure(); - repaint(); - } - - - // This method is invoked after our Canvas is first created - // but before it can actually be displayed. After we've - // invoked our superclass's addNotify() method, we have font - // metrics and can successfully call measure() to figure out - // how big the label is. - public void addNotify() { - super.addNotify(); - measure(); - } - - - // Called by a layout manager when it wants to - // know how big we'd like to be. - public Dimension getPreferredSize() { - return new Dimension(Math.max(min_width, max_width + 2*margin_width), - num_lines * line_height + 2*margin_height); - } - - - // Called when the layout manager wants to know - // the bare minimum amount of space we need to get by. - public Dimension getMinimumSize() { - return new Dimension(Math.max(min_width, max_width), num_lines * line_height); - } - - // Draws the label - public void paintComponent(Graphics g) { - super.paintComponent(g); - int x, y; - Dimension d = this.getSize(); - if (!ij.IJ.isLinux()) setAntialiasedText(g); - y = line_ascent + (d.height - num_lines * line_height)/2; - for(int i = 0; i < num_lines; i++, y += line_height) { - x = margin_width; - g.drawString(lines[i], x, y); - } - } - - void setAntialiasedText(Graphics g) { - Graphics2D g2d = (Graphics2D)g; - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/NewImage.java b/com.eco.bio7.image/src/ij/gui/NewImage.java deleted file mode 100644 index 2075ac427..000000000 --- a/com.eco.bio7.image/src/ij/gui/NewImage.java +++ /dev/null @@ -1,466 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.image.*; -import java.io.*; -import java.awt.event.*; -import java.util.*; -import ij.*; -import ij.process.*; - -/** New image dialog box plus several static utility methods for creating images.*/ -public class NewImage { - - public static final int GRAY8=0, GRAY16=1, GRAY32=2, RGB=3; - public static final int FILL_BLACK=1, FILL_RAMP=2, FILL_NOISE=3, FILL_RANDOM=3, - FILL_WHITE=4, CHECK_AVAILABLE_MEMORY=8, SIGNED_INT=16; - private static final int OLD_FILL_WHITE=0; - - static final String TYPE = "new.type"; - static final String FILL = "new.fill"; - static final String WIDTH = "new.width"; - static final String HEIGHT = "new.height"; - static final String SLICES = "new.slices"; - - private static String name = "Untitled"; - private static int staticWidth = Prefs.getInt(WIDTH, 512); - private static int staticHeight = Prefs.getInt(HEIGHT, 512); - private static int staticSlices = Prefs.getInt(SLICES, 1); - private static int staticType = Prefs.getInt(TYPE, GRAY8); - private static int staticFillWith = Prefs.getInt(FILL, FILL_BLACK); - private static String[] types = {"8-bit", "16-bit", "32-bit", "RGB"}; - private static String[] fill = {"White", "Black", "Ramp", "Noise"}; - private int gwidth, gheight, gslices, gtype, gfill; - - public NewImage() { - openImage(); - } - - static boolean createStack(ImagePlus imp, ImageProcessor ip, int nSlices, int type, int options) { - int fill = getFill(options); - int width = imp.getWidth(); - int height = imp.getHeight(); - long bytesPerPixel = 1; - if (type==GRAY16) bytesPerPixel = 2; - else if (type==GRAY32||type==RGB) bytesPerPixel = 4; - long size = (long)width*height*nSlices*bytesPerPixel; - int sizeThreshold = fill==FILL_NOISE?10:250; - boolean bigStack = size/(1024*1024)>=sizeThreshold; - String size2 = size/(1024*1024)+"MB ("+width+"x"+height+"x"+nSlices+")"; - if ((options&CHECK_AVAILABLE_MEMORY)!=0) { - long max = IJ.maxMemory(); // - 100*1024*1024; - if (max>0) { - long inUse = IJ.currentMemory(); - long available = max - inUse; - if (size>available) - System.gc(); - inUse = IJ.currentMemory(); - available = max-inUse; - if (size>available) { - IJ.error("Insufficient Memory", "There is not enough free memory to allocate a \n" - + size2+" stack.\n \n" - + "Memory available: "+available/(1024*1024)+"MB\n" - + "Memory in use: "+IJ.freeMemory()+"\n \n" - + "More information can be found in the \"Memory\"\n" - + "sections of the ImageJ installation notes at\n" - + "\""+IJ.URL2+"/docs/install/\"."); - return false; - } - } - } - ImageStack stack = imp.createEmptyStack(); - boolean signedInt = (options&SIGNED_INT)!=0; - if (type==RGB && signedInt) - stack.setOptions("32-bit int"); - int inc = nSlices/40; - if (inc<1) inc = 1; - if (bigStack) - IJ.showStatus("Allocating "+size2+". Press 'Esc' to abort."); - IJ.resetEscape(); - try { - stack.addSlice(null, ip); - for (int i=2; i<=nSlices; i++) { - if ((i%inc)==0 && bigStack) - IJ.showProgress(i, nSlices); - Object pixels2 = null; - switch (type) { - case GRAY8: pixels2 = new byte[width*height]; - if (fill==FILL_NOISE) - fillNoiseByte(new ByteProcessor(width,height,(byte[])pixels2)); - break; - case GRAY16: pixels2 = new short[width*height]; - if (fill==FILL_NOISE) - fillNoiseShort(new ShortProcessor(width,height,(short[])pixels2,null)); - break; - case GRAY32: pixels2 = new float[width*height]; - if (fill==FILL_NOISE) - fillNoiseFloat(new FloatProcessor(width,height,(float[])pixels2,null)); - break; - case RGB: pixels2 = new int[width*height]; - if (fill==FILL_NOISE) { - if (signedInt) - fillNoiseInt(new IntProcessor(width,height,(int[])pixels2)); - else - fillNoiseRGB(new ColorProcessor(width,height,(int[])pixels2), false); - } - break; - } - if (fill==FILL_WHITE||fill==FILL_RAMP) - System.arraycopy(ip.getPixels(), 0, pixels2, 0, width*height); - stack.addSlice(null, pixels2); - if (IJ.escapePressed()) {IJ.beep(); break;}; - } - } - catch(OutOfMemoryError e) { - IJ.outOfMemory(imp.getTitle()); - stack.trim(); - } - IJ.showStatus(""); - if (bigStack) - IJ.showProgress(nSlices, nSlices); - if (stack.size()>1) - imp.setStack(null, stack); - return true; - } - - static int getFill(int options) { - int fill = options&7; - if (fill==OLD_FILL_WHITE) - fill = FILL_WHITE; - if (fill==7||fill==6||fill==5) - fill = FILL_BLACK; - return fill; - } - - public static ImagePlus createByteImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - byte[] pixels = new byte[size]; - ImageProcessor ip = new ByteProcessor(width, height, pixels, null); - switch (fill) { - case FILL_WHITE: - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, GRAY8, options); - if (!ok) imp = null; - } - return imp; - } - - private static void fillNoiseByte(ImageProcessor ip) { - ip.add(127); - ip.noise(31); - } - - public static ImagePlus createRGBImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - int[] pixels = new int[size]; - ColorProcessor ip = new ColorProcessor(width, height, pixels); - switch (fill) { - case FILL_WHITE: - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, RGB, options); - if (!ok) imp = null; - } - return imp; - } - - public static ImagePlus createIntImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - int[] pixels = new int[size]; - IntProcessor ip = new IntProcessor(width, height, pixels); - switch (fill) { - case FILL_RAMP: - int[] ramp = new int[width]; - double inc = ((double)Integer.MAX_VALUE - (double)Integer.MIN_VALUE)/width; - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, RGB, options); - if (!ok) imp = null; - } - return imp; - } - - private static void fillNoiseRGB(ColorProcessor ip, boolean sp) { - int width = ip.getWidth(); - int height = ip.getHeight(); - ByteProcessor rr = new ByteProcessor(width, height); - ByteProcessor gg = new ByteProcessor(width, height); - ByteProcessor bb = new ByteProcessor(width, height); - if (sp) IJ.showProgress(0.0); - rr.add(127); if (sp) IJ.showProgress(0.05); - gg.add(127); if (sp) IJ.showProgress(0.10); - bb.add(127); if (sp) IJ.showProgress(0.15); - rr.noise(31); if (sp) IJ.showProgress(0.40); - gg.noise(31); if (sp) IJ.showProgress(0.65); - bb.noise(31); if (sp) IJ.showProgress(0.90); - if (sp) IJ.showProgress(1.0); - ip.setChannel(1,rr); ip.setChannel(2,gg); ip.setChannel(3,bb); - } - - private static void fillNoiseInt(ImageProcessor ip) { - Random rnd = new Random(); - int n = ip.getPixelCount(); - double std =((double)Integer.MAX_VALUE - (double)Integer.MIN_VALUE)*0.12; - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, GRAY16, options); - if (!ok) imp = null; - } - imp.getProcessor().setMinAndMax(0, 65535); // default display range - return imp; - } - - private static void fillNoiseShort(ImageProcessor ip) { - ip.add(32767); - ip.noise(7940); - } - - /** - * @deprecated - * Short images are always unsigned. - */ - public static ImagePlus createUnsignedShortImage(String title, int width, int height, int slices, int options) { - return createShortImage(title, width, height, slices, options); - } - - public static ImagePlus createFloatImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - float[] pixels = new float[size]; - ImageProcessor ip = new FloatProcessor(width, height, pixels, null); - switch (fill) { - case FILL_WHITE: case FILL_BLACK: - break; - case FILL_RAMP: - float[] ramp = new float[width]; - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, GRAY32, options); - if (!ok) imp = null; - } - if (fill!=FILL_NOISE) - imp.getProcessor().setMinAndMax(0.0, 1.0); // default display range - return imp; - } - - private static void fillNoiseFloat(ImageProcessor ip) { - ip.noise(1); - } - - private static int getSize(int width, int height) { - long size = (long)width*height; - if (size>Integer.MAX_VALUE) { - IJ.error("Image is too large. ImageJ does not support\nsingle images larger than 2 gigapixels."); - return -1; - } else - return (int)size; - } - - public static void open(String title, int width, int height, int nSlices, int type, int options) { - int bitDepth = 8; - if (type==GRAY16) bitDepth = 16; - else if (type==GRAY32) bitDepth = 32; - else if (type==RGB) bitDepth = 24; - long startTime = System.currentTimeMillis(); - ImagePlus imp = createImage(title, width, height, nSlices, bitDepth, options); - if (imp!=null) { - WindowManager.checkForDuplicateName = true; - imp.show(); - IJ.showStatus(IJ.d2s(((System.currentTimeMillis()-startTime)/1000.0),2)+" seconds"); - } - } - - public static ImagePlus createImage(String title, int width, int height, int nSlices, int bitDepth, int options) { - ImagePlus imp = null; - switch (bitDepth) { - case 8: imp = createByteImage(title, width, height, nSlices, options); break; - case 16: imp = createShortImage(title, width, height, nSlices, options); break; - case 32: imp = createFloatImage(title, width, height, nSlices, options); break; - case 24: - if ((options&SIGNED_INT)!=0) - imp = createIntImage(title, width, height, nSlices, options); - else - imp = createRGBImage(title, width, height, nSlices, options); - break; - default: throw new IllegalArgumentException("Invalid bitDepth: "+bitDepth); - } - return imp; - } - - boolean showDialog() { - if (staticTypeRGB) - staticType = GRAY8; - if (staticFillWithFILL_NOISE) - staticFillWith = FILL_WHITE; - GenericDialog gd = new GenericDialog("New Image..."); - gd.addStringField("Name:", name, 12); - gd.addChoice("Type:", types, types[staticType]); - gd.addChoice("Fill with:", fill, fill[staticFillWith]); - gd.addNumericField("Width:", staticWidth, 0, 5, "pixels"); - gd.addNumericField("Height:", staticHeight, 0, 5, "pixels"); - gd.addNumericField("Slices:", staticSlices, 0, 5, ""); - gd.showDialog(); - if (gd.wasCanceled()) - return false; - name = gd.getNextString(); - String s = gd.getNextChoice(); - if (s.startsWith("8")) - gtype = GRAY8; - else if (s.startsWith("16")) - gtype = GRAY16; - else if (s.endsWith("RGB") || s.endsWith("rgb")) - gtype = RGB; - else - gtype = GRAY32; - gfill = gd.getNextChoiceIndex(); - gwidth = (int)gd.getNextNumber(); - gheight = (int)gd.getNextNumber(); - gslices = (int)gd.getNextNumber(); - if (gslices<1) gslices = 1; - if (gwidth<1 || gheight<1) { - IJ.error("New Image", "Width and height must be >0"); - return false; - } else { - if (!IJ.isMacro()) { - staticWidth = gwidth; - staticHeight = gheight; - staticSlices = gslices; - staticType = gtype; - staticFillWith = gfill; - } - return true; - } - } - - void openImage() { - if (!showDialog()) - return; - try { - open(name, gwidth, gheight, gslices, gtype, gfill); - } catch(OutOfMemoryError e) { - IJ.outOfMemory("New Image..."); - } - } - - /** Called when ImageJ quits. */ - public static void savePreferences(Properties prefs) { - prefs.put(TYPE, Integer.toString(staticType)); - prefs.put(FILL, Integer.toString(staticFillWith)); - prefs.put(WIDTH, Integer.toString(staticWidth)); - prefs.put(HEIGHT, Integer.toString(staticHeight)); - prefs.put(SLICES, Integer.toString(staticSlices)); - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/NonBlockingGenericDialog.java b/com.eco.bio7.image/src/ij/gui/NonBlockingGenericDialog.java deleted file mode 100644 index 44381da6d..000000000 --- a/com.eco.bio7.image/src/ij/gui/NonBlockingGenericDialog.java +++ /dev/null @@ -1,104 +0,0 @@ -package ij.gui; -import ij.*; -import java.awt.event.*; -import java.awt.EventQueue; -import java.awt.GraphicsEnvironment; -import java.awt.Frame; - -/** This is an extension of GenericDialog that is non-modal. - * @author Johannes Schindelin - */ -public class NonBlockingGenericDialog extends GenericDialog { - ImagePlus imp; //when non-null, this dialog gets closed when the image is closed - WindowListener windowListener; //checking for whether the associated window gets closed - - public NonBlockingGenericDialog(String title) { - super(title, null); - setModal(false); - IJ.protectStatusBar(false); - instance = this; - } - - public synchronized void showDialog() { - super.showDialog(); - if (isMacro()) - return; - if (EventQueue.isDispatchThread()) - throw new RuntimeException("To avoid a deadlock, NonBlockingGenericDialog must not be called from the Event Queue"); - if (!IJ.macroRunning()) { // add to Window menu on event dispatch thread - final NonBlockingGenericDialog thisDialog = this; - EventQueue.invokeLater(new Runnable() { - public void run() { - WindowManager.addWindow(thisDialog); - } - }); - } - if (imp != null) { - ImageWindow win = imp.getWindow(); - if (win != null) { //when the associated image closes, also close the dialog - final NonBlockingGenericDialog gd = this; - windowListener = new WindowAdapter() { - public void windowClosed(WindowEvent e) { - cancelDialogAndClose(); - } - }; - win.addWindowListener(windowListener); - } - } - try { - wait(); - } catch (InterruptedException e) { } - } - - /** Gets called if the associated image window is closed */ - private void cancelDialogAndClose() { - super.windowClosing(null); // sets wasCanceled=true and does dispose() - } - - public synchronized void actionPerformed(ActionEvent e) { - super.actionPerformed(e); - if (!isVisible()) - notify(); - } - - public synchronized void keyPressed(KeyEvent e) { - super.keyPressed(e); - if (wasOKed() || wasCanceled()) - notify(); - } - - public synchronized void windowClosing(WindowEvent e) { - super.windowClosing(e); - if (wasOKed() || wasCanceled()) - notify(); - } - - public void dispose() { - super.dispose(); - WindowManager.removeWindow(this); - if (imp != null) { - ImageWindow win = imp.getWindow(); - if (win != null && windowListener != null) - win.removeWindowListener(windowListener); - } - } - - /** Obsolete, replaced by GUI.newNonBlockingDialog(String,ImagePlus). */ - public static GenericDialog newDialog(String title, ImagePlus imp) { - return GUI.newNonBlockingDialog(title, imp); - } - - /** Obsolete, replaced by GUI.newNonBlockingDialog(String). */ - public static GenericDialog newDialog(String title) { - return GUI.newNonBlockingDialog(title); - } - - /** Put the dialog into the foreground when the image we work on gets into the foreground */ - @Override - public void windowActivated(WindowEvent e) { - if ((e.getWindow() instanceof ImageWindow) && e.getOppositeWindow()!=this) - toFront(); - WindowManager.setWindow(this); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/OvalRoi.java b/com.eco.bio7.image/src/ij/gui/OvalRoi.java deleted file mode 100644 index fc1770808..000000000 --- a/com.eco.bio7.image/src/ij/gui/OvalRoi.java +++ /dev/null @@ -1,440 +0,0 @@ -package ij.gui; -import java.awt.*; -import java.awt.image.*; -import java.awt.geom.*; -import ij.*; -import ij.process.*; -import ij.measure.Calibration; - -/** Oval region of interest */ -public class OvalRoi extends Roi { - - /** Creates an OvalRoi.*/ - public OvalRoi(int x, int y, int width, int height) { - super(x, y, width, height); - type = OVAL; - } - - /** Creates an OvalRoi using double arguments.*/ - public OvalRoi(double x, double y, double width, double height) { - super(x, y, width, height); - type = OVAL; - } - - /** Creates an OvalRoi. */ - public static OvalRoi create(double x, double y, double width, double height) { - return new OvalRoi(x, y, width, height); - } - - /** Starts the process of creating a user-defined OvalRoi. */ - public OvalRoi(int x, int y, ImagePlus imp) { - super(x, y, imp); - type = OVAL; - } - - /** @deprecated */ - public OvalRoi(int x, int y, int width, int height, ImagePlus imp) { - this(x, y, width, height); - setImage(imp); - } - - /** Feret (caliper width) values, see ij.gui.Roi.getFeretValues(). - * The superclass method of calculating this via the convex hull is less accurate for the MinFeret - * because it does not get the exact minor axis. */ - public double[] getFeretValues() { - double[] a = new double[FERET_ARRAYSIZE]; - double pw=1.0, ph=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - pw = cal.pixelWidth; - ph = cal.pixelHeight; - } - boolean highAspect = ph*height > pw*width; - a[0] = highAspect ? height*ph : width*pw; // (max)Feret - a[1] = highAspect ? 90.0 : 0.0; // (max)Feret angle - a[2] = highAspect ? width*pw : height*ph; // MinFeret - a[3] = (x + (highAspect ? 0.5*width : 0)) * pw; //FeretX scaled - a[4] = (y + (highAspect ? height : 0.5*height)) * ph;//FeretY scaled - int i = FERET_ARRAY_POINTOFFSET; - a[i++] = x + (highAspect ? 0.5*width : 0); //MaxFeret start - a[i++] = y + (highAspect ? height : 0.5*height); - a[i++] = x + (highAspect ? 0.5*width : width); //MaxFeret end - a[i++] = y + (highAspect ? 0 : 0.5*height); - a[i++] = x + (highAspect ? 0 : 0.5*width); //MinFeret start - a[i++] = y + (highAspect ? 0.5*height : height); - a[i++] = x + (highAspect ? width : 0.5*width); //MinFeret end - a[i++] = y + (highAspect ? 0.5*height : 0); - return a; - } - - protected void moveHandle(int sx, int sy) { - double asp; - if (clipboard!=null) return; - int ox = offScreenX(sx); - int oy = offScreenY(sy); - //IJ.log("moveHandle: "+activeHandle+" "+ox+" "+oy); - int x1=x, y1=y, x2=x+width, y2=y+height, xc=x+width/2, yc=y+height/2; - int w2 = (int)(0.14645*width); - int h2 = (int)(0.14645*height); - if (width > 7 && height > 7) { - asp = (double)width/(double)height; - asp_bk = asp; - } else - asp = asp_bk; - switch (activeHandle) { - case 0: x=ox-w2; y=oy-h2; break; - case 1: y=oy; break; - case 2: x2=ox+w2; y=oy-h2; break; - case 3: x2=ox; break; - case 4: x2=ox+w2; y2=oy+h2; break; - case 5: y2=oy; break; - case 6: x=ox-w2; y2=oy+h2; break; - case 7: x=ox; break; - } - //if (x<0) x=0; if (y<0) y=0; - if (x=x2) { - width=1; - x=x2=xc; - } - if (y>=y2) { - height=1; - y=y2=yc; - } - - } - - if (constrain) { - if (activeHandle==1 || activeHandle==5) width=height; - else height=width; - - if (x>=x2) { - width=1; - x=x2=xc; - } - if (y>=y2) { - height=1; - y=y2=yc; - } - switch(activeHandle){ - case 0: - x=x2-width; - y=y2-height; - break; - case 1: - x=xc-width/2; - y=y2-height; - break; - case 2: - y=y2-height; - break; - case 3: - y=yc-height/2; - break; - case 5: - x=xc-width/2; - break; - case 6: - x=x2-width; - break; - case 7: - y=yc-height/2; - x=x2-width; - break; - } - if (center){ - x=xc-width/2; - y=yc-height/2; - } - } - - if (aspect && !constrain) { - if (activeHandle==1 || activeHandle==5) width=(int)Math.rint((double)height*asp); - else height=(int)Math.rint((double)width/asp); - - switch (activeHandle) { - case 0: - x=x2-width; - y=y2-height; - break; - case 1: - x=xc-width/2; - y=y2-height; - break; - case 2: - y=y2-height; - break; - case 3: - y=yc-height/2; - break; - case 5: - x=xc-width/2; - break; - case 6: - x=x2-width; - break; - case 7: - y=yc-height/2; - x=x2-width; - break; - } - if (center) { - x=xc-width/2; - y=yc-height/2; - } - // Attempt to preserve aspect ratio when roi very small: - if (width<8) { - if (width<1) width = 1; - height=(int)Math.rint((double)width/asp_bk); - } - if (height<8) { - if (height<1) height =1; - width=(int)Math.rint((double)height*asp_bk); - } - } - - updateClipRect(); - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX=x; oldY=y; - oldWidth=width; oldHeight=height; - cachedMask = null; - bounds = null; - } - - public void draw(Graphics g) { - Color color = strokeColor!=null? strokeColor:ROIColor; - if (fillColor!=null) color = fillColor; - g.setColor(color); - mag = getMagnification(); - int sw = (int)(width*mag); - int sh = (int)(height*mag); - int sx1 = screenX(x); - int sy1 = screenY(y); - if (subPixelResolution() && bounds!=null) { - sw = (int)(bounds.width*mag); - sh = (int)(bounds.height*mag); - sx1 = screenXD(bounds.x); - sy1 = screenYD(bounds.y); - } - int sw2 = (int)(0.14645*width*mag); - int sh2 = (int)(0.14645*height*mag); - int sx2 = sx1+sw/2; - int sy2 = sy1+sh/2; - int sx3 = sx1+sw; - int sy3 = sy1+sh; - Graphics2D g2d = (Graphics2D)g; - if (stroke!=null) - g2d.setStroke(getScaledStroke()); - setRenderingHint(g2d); - if (fillColor!=null) { - if (!overlay && isActiveOverlayRoi()) { - g.setColor(Color.cyan); - g.drawOval(sx1, sy1, sw, sh); - } else { - g.fillOval(sx1, sy1, sw, sh); - if (strokeColor!=null) { - g.setColor(strokeColor); - g.drawOval(sx1, sy1, sw, sh); - } - } - } else - g.drawOval(sx1, sy1, sw, sh); - if (clipboard==null && !overlay) { - drawHandle(g, sx1+sw2, sy1+sh2); - drawHandle(g, sx3-sw2, sy1+sh2); - drawHandle(g, sx3-sw2, sy3-sh2); - drawHandle(g, sx1+sw2, sy3-sh2); - drawHandle(g, sx2, sy1); - drawHandle(g, sx3, sy2); - drawHandle(g, sx2, sy3); - drawHandle(g, sx1, sy2); - } - drawPreviousRoi(g); - if (updateFullWindow) - {updateFullWindow = false; imp.draw();} - if (state!=NORMAL) showStatus(); - } - - /** Draws an outline of this OvalRoi on the image. */ - public void drawPixels(ImageProcessor ip) { - Polygon p = getPolygon(); - if (p.npoints>0) { - int saveWidth = ip.getLineWidth(); - if (getStrokeWidth()>1f) - ip.setLineWidth((int)Math.round(getStrokeWidth())); - ip.drawPolygon(p); - ip.setLineWidth(saveWidth); - } - if (Line.getWidth()>1 || getStrokeWidth()>1) - updateFullWindow = true; - } - - /** Returns this OvalRoi as a Polygon that outlines the mask, in image pixel coordinates. */ - public Polygon getPolygon() { - return getPolygon(true); - } - - /** Returns this OvalRoi as a Polygon that outlines the mask. - * @param absoluteCoordinates determines whether to use image pixel coordinates - * instead of coordinates relative to roi origin. */ - Polygon getPolygon(boolean absoluteCoordinates) { - ImageProcessor mask = getMask(); - Wand wand = new Wand(mask); - wand.autoOutline(width/2,height/2, 255, 255); - if (absoluteCoordinates) - for (int i=0; i=sx1+sw2&&sx<=sx1+sw2+size&&sy>=sy1+sh2&&sy<=sy1+sh2+size) return 0; - if (sx>=sx2&&sx<=sx2+size&&sy>=sy1&&sy<=sy1+size) return 1; - if (sx>=sx3-sw2&&sx<=sx3-sw2+size&&sy>=sy1+sh2&&sy<=sy1+sh2+size) return 2; - if (sx>=sx3&&sx<=sx3+size&&sy>=sy2&&sy<=sy2+size) return 3; - if (sx>=sx3-sw2&&sx<=sx3-sw2+size&&sy>=sy3-sh2&&sy<=sy3-sh2+size) return 4; - if (sx>=sx2&&sx<=sx2+size&&sy>=sy3&&sy<=sy3+size) return 5; - if (sx>=sx1+sw2&&sx<=sx1+sw2+size&&sy>=sy3-sh2&&sy<=sy3-sh2+size) return 6; - if (sx>=sx1&&sx<=sx1+size&&sy>=sy2&&sy<=sy2+size) return 7; - return -1; - } - - public ImageProcessor getMask() { - ImageProcessor mask = cachedMask; - if (mask!=null && mask.getPixels()!=null && mask.getWidth()==width && mask.getHeight()==height) - return mask; - mask = new ByteProcessor(width, height); - double a=width/2.0, b=height/2.0; - double a2=a*a, b2=b*b; - a -= 0.5; b -= 0.5; - double xx, yy; - int offset; - byte[] pixels = (byte[])mask.getPixels(); - for (int y=0; y { - private Vector list; - private boolean label; - private boolean drawNames; - private boolean drawBackgrounds; - private Color labelColor; - private Font labelFont; - private boolean scalableLabels; - private boolean isCalibrationBar; - private boolean selectable = true; - private boolean draggable = true; - - /** Constructs an empty Overlay. */ - public Overlay() { - list = new Vector(); - } - - /** Constructs an Overlay and adds the specified ROI. */ - public Overlay(Roi roi) { - list = new Vector(); - if (roi!=null) - list.add(roi); - } - - /** Adds an ROI to this Overlay. */ - public void add(Roi roi) { - if (roi!=null) - list.add(roi); - } - - /** Adds an ROI to this Overlay using the specified name. */ - public void add(Roi roi, String name) { - roi.setName(name); - add(roi); - } - - /** Adds the ROIs in 'overlay2' to this overlay. */ - public Overlay add(Overlay overlay2) { - for (int i=0; i=list.size()) - throw new IllegalArgumentException("set: index out of range"); - if (roi!=null) - list.set(index, roi); - } - - /** Removes the ROI with the specified index from this Overlay. */ - public void remove(int index) { - if (index>=0) - list.remove(index); - } - - /** Removes the specified ROI from this Overlay. */ - public void remove(Roi roi) { - list.remove(roi); - } - - /** Removes all ROIs that have the specified name. */ - public void remove(String name) { - if (name==null) return; - for (int i=size()-1; i>=0; i--) { - if (name.equals(get(i).getName())) - remove(i); - } - } - - /** Removes all the ROIs in this Overlay. */ - public void clear() { - list.clear(); - } - - /** Returns the ROI with the specified index or null if the index is invalid. */ - public Roi get(int index) { - try { - return (Roi)list.get(index); - } catch(Exception e) { - return null; - } - } - - /** Returns the ROI with the specified name or null if not found. */ - public Roi get(String name) { - int index = getIndex(name); - if (index==-1) - return null; - else - return get(index); - } - - /** Returns the index of the ROI with the specified name, or -1 if not found. */ - public int getIndex(String name) { - if (name==null) return -1; - Roi[] rois = toArray(); - for (int i=rois.length-1; i>=0; i--) { - if (name.equals(rois[i].getName())) - return i; - } - return -1; - } - - /** Returns the index of the last ROI that contains the point (x,y) - or null if no ROI contains the point. */ - public int indexAt(int x, int y) { - Roi[] rois = toArray(); - for (int i=rois.length-1; i>=0; i--) { - if (contains(rois[i],x,y)) - return i; - } - return -1; - } - - private boolean contains(Roi roi, int x, int y) { - if (roi==null) return false; - if (roi instanceof Line) - return (((Line)roi).getFloatPolygon(10)).contains(x,y); - else - return roi.contains(x,y); - } - - /** Returns 'true' if this Overlay contains the specified ROI. */ - public boolean contains(Roi roi) { - return list.contains(roi); - } - - /** Returns the number of ROIs in this Overlay. */ - public int size() { - return list.size(); - } - - /** Returns on array containing the ROIs in this Overlay. */ - public Roi[] toArray() { - Roi[] array = new Roi[list.size()]; - return (Roi[])list.toArray(array); - } - - /** Returns on array containing the ROIs with the specified indexes. */ - public Roi[] toArray(int[] indexes) { - ArrayList rois = new ArrayList(); - for (int i=0; i=0 && indexes[i]0?bounds.x:0; - int dy = bounds.y>0?bounds.y:0; - if (dx>0 || dy>0) - overlay2.translate(-dx, -dy); - return overlay2; - } - - /** Removes ROIs having positions outside of the - * interval defined by firstSlice and lastSlice. - * Marcel Boeglin, September 2013 - */ - public void crop(int firstSlice, int lastSlice) { - for (int i=size()-1; i>=0; i--) { - Roi roi = get(i); - int position = roi.getPosition(); - if (position>0) { - if (positionlastSlice) - remove(i); - else - roi.setPosition(position-firstSlice+1); - } - } - } - - /** Removes ROIs having a C, Z or T coordinate outside the volume - * defined by firstC, lastC, firstZ, lastZ, firstT and lastT. - * Marcel Boeglin, September 2013 - */ - public void crop(int firstC, int lastC, int firstZ, int lastZ, int firstT, int lastT) { - int nc = lastC-firstC+1, nz = lastZ-firstZ+1, nt = lastT-firstT+1; - boolean toCStack = nz==1 && nt==1; - boolean toZStack = nt==1 && nc==1; - boolean toTStack = nc==1 && nz==1; - Roi roi; - int c, z, t, c2, z2, t2; - for (int i=size()-1; i>=0; i--) { - roi = get(i); - c = roi.getCPosition(); - z = roi.getZPosition(); - t = roi.getTPosition(); - c2 = c-firstC+1; - z2 = z-firstZ+1; - t2 = t-firstT+1; - if (toCStack) - roi.setPosition(c2); - else if (toZStack) - roi.setPosition(z2); - else if (toTStack) - roi.setPosition(t2); - else - roi.setPosition(c2, z2, t2); - if ((c2<1||c2>nc) && c>0 || (z2<1||z2>nz) && z>0 || (t2<1||t2>nt) && t>0) - remove(i); - } - } - - /** Returns the bounds of this overlay. */ - /* - public Rectangle getBounds() { - if (size()==0) - return new Rectangle(0,0,0,0); - int xmin = Integer.MAX_VALUE; - int xmax = -Integer.MAX_VALUE; - int ymin = Integer.MAX_VALUE; - int ymax = -Integer.MAX_VALUE; - Roi[] rois = toArray(); - for (int i=0; ixmax) xmax = r.x+r.width; - if (r.y+r.height>ymax) ymax = r.y+r.height; - } - return new Rectangle(xmin, ymin, xmax-xmin, ymax-ymin); - } - */ - - /* Returns the Roi that results from XORing all the ROIs - * in this overlay that have an index in the array ‘indexes’. - */ - public Roi xor(int[] indexes) { - return Roi.xor(toArray(indexes)); - } - - /** Returns a new Overlay that has the same properties as this one. */ - public Overlay create() { - Overlay overlay2 = new Overlay(); - overlay2.drawLabels(label); - overlay2.drawNames(drawNames); - overlay2.drawBackgrounds(drawBackgrounds); - overlay2.setLabelColor(labelColor); - overlay2.setLabelFont(labelFont, scalableLabels); - overlay2.setIsCalibrationBar(isCalibrationBar); - overlay2.selectable(selectable); - overlay2.setDraggable(draggable); - return overlay2; - } - - /** Returns a clone of this Overlay. */ - public Overlay duplicate() { - Roi[] rois = toArray(); - Overlay overlay2 = create(); - for (int i=0; i v) {list = v;} - - Vector getVector() {return list;} - - /** Set 'false' to prevent ROIs in this overlay from being activated - by clicking on their labels or by a long clicking. */ - public void selectable(boolean selectable) { - this.selectable = selectable; - } - - /** Returns 'true' if ROIs in this overlay can be activated - by clicking on their labels or by a long press. */ - public boolean isSelectable() { - return selectable; - } - - /** Set 'false' to prevent ROIs in this overlay from being dragged by their labels. */ - public void setDraggable(boolean draggable) { - this.draggable = draggable; - } - - /** Returns 'true' if ROIs in this overlay can be dragged by their labels. */ - public boolean isDraggable() { - return draggable; - } - - public boolean scalableLabels() { - return scalableLabels; - } - - public String toString() { - return "Overlay[size="+size()+" "+(scalableLabels?"scale":"")+" "+Colors.colorToString(getLabelColor())+"]"; - } - - /** Updates overlays created by the particle analyzer - after rows are deleted from the Results table. */ - public static void updateTableOverlay(ImagePlus imp, int first, int last, int tableSize) { - if (imp==null) - return; - Overlay overlay = imp.getOverlay(); - if (overlay==null) - return; - if (overlay.size()!=tableSize) - return; - if (first<0) - first = 0; - if (last>tableSize-1) - last = tableSize-1; - if (first>last) - return; - String name1 = overlay.get(0).getName(); - String name2 = overlay.get(overlay.size()-1).getName(); - if (!"1".equals(name1) || !(""+tableSize).equals(name2)) - return; - int count = last-first+1; - if (overlay.size()==count && !IJ.isMacro()) { - if (count==1 || IJ.showMessageWithCancel("ImageJ", "Delete "+overlay.size()+" element overlay? ")) - imp.setOverlay(null); - return; - } - for (int i=0; i iterator() { - final Overlay overlay = this; - - Iterator it = new Iterator() { - private int index = -1; - - /** Returns 'true' if next element exists. */ - @Override - public boolean hasNext() { - if (index+12 - private static final int LEGEND_PADDING = 4; //pixels around legend text etc - private static final int LEGEND_LINELENGTH = 20; //length of lines in legend - private static final int USUALLY_ENLARGE = 1, ALWAYS_ENLARGE = 2; //enlargeRange settings - private static final double RELATIVE_ARROWHEAD_SIZE = 0.2; //arrow heads have 1/5 of vector length - private static final int MIN_ARROWHEAD_LENGTH = 3; - private static final int MAX_ARROWHEAD_LENGTH = 20; - private static final String MULTIPLY_SYMBOL = "\u00B7"; //middot, default multiplication symbol for scientific notation. Use setOptions("msymbol=\\u00d7") for '×' - - PlotProperties pp = new PlotProperties(); //size, range, formatting etc, for easy serialization - PlotProperties ppSnapshot; //copy for reverting - Vector allPlotObjects = new Vector(); //all curves, labels etc., also serialized for saving/reading - Vector allPlotObjectsSnapshot; //copy for reverting - private PlotVirtualStack stack; - /** For high-resolution plots, everything will be scaled with this number. Otherwise, must be 1.0. - * (creating margins, saving PlotProperties etc only supports scale=1.0) */ - float scale = 1.0f; - Rectangle frame = null; //the clip frame, do not use for image scale - //The following are the margin sizes actually used. They are modified for font size and also scaled for high-resolution plots - public int leftMargin = LEFT_MARGIN; - public int rightMargin = RIGHT_MARGIN; - public int topMargin = TOP_MARGIN; - public int bottomMargin = BOTTOM_MARGIN; - int frameWidth; //width corresponding to plot range; frame.width is larger by 1 - int frameHeight; //height corresponding to plot range; frame.height is larger by 1 - int preferredPlotWidth = PlotWindow.plotWidth; //default size of plot frame (not taking 'High-Resolution' scale factor into account) - int preferredPlotHeight = PlotWindow.plotHeight; - - double xMin = Double.NaN, xMax, yMin, yMax; //current plot range, logarithm if log axis - double[] currentMinMax = new double[]{Double.NaN, 0, Double.NaN, 0}; //current plot range, xMin, xMax, yMin, yMax (values, not logarithm if log axis) - double[] defaultMinMax = new double[]{Double.NaN, 0, Double.NaN, 0}; //default plot range - double[] savedMinMax = new double[]{Double.NaN, 0, Double.NaN, 0}; //keeps previous range for revert - int[] enlargeRange; // whether to enlarge the range slightly to avoid values at the border (0=off, USUALLY_ENLARGE, ALWAYS_ENLARGE) - boolean logXAxis, logYAxis; // whether to really use log axis (never for small relative range) - //for passing on what should be kept when 'live' plotting (PlotMaker), but note that 'COPY_EXTRA_OBJECTS' is also on for live plotting: - int templateFlags = COPY_SIZE | COPY_LABELS | COPY_AXIS_STYLE | COPY_CONTENTS_STYLE | COPY_LEGEND; - private int dsize = PlotWindow.getDefaultFontSize(); - Font defaultFont = FontUtil.getFont("Arial",Font.PLAIN,dsize); //default font for labels, axis, etc. - Font currentFont = defaultFont; // font as changed by setFont or setFontSize, must never be null - private double xScale, yScale; // pixels per data unit - private int xBasePxl, yBasePxl; // pixel coordinates corresponding to 0 - private int maxIntervals = 12; // maximum number of intervals between ticks or grid lines - private int tickLength = 7; // length of major ticks - private int minorTickLength = 3; // length of minor ticks - private Color gridColor = new Color(0xc0c0c0); // light gray - private ImageProcessor ip; - private ImagePlus imp; // if we have an ImagePlus, updateAndDraw on changes - private String title; - private boolean invertedLut; // grayscale plots only, set in Edit>Options>Appearance - private boolean plotDrawn; - PlotMaker plotMaker; // for PlotMaker interface, handled by PlotWindow - private Color currentColor; // for next objects added - private Color currentColor2; // 2nd color for next object added (e.g. line for CONNECTED_CIRCLES) - float currentLineWidth; - private int currentJustification = LEFT; - private boolean ignoreForce2Grid; // after explicit setting of range (limits), ignore 'FORCE2GRID' flags - //private boolean snapToMinorGrid; // snap to grid when zooming to selection - private static double SEPARATED_BAR_WIDTH=0.5; // for plots with separate bars (e.g. categories), fraction of space, 0.1-1.0 - double[] steps; // x & y interval between numbers, major ticks & grid lines, remembered for redrawing the grid - private int objectToReplace = -1; // index in allPlotObjects, for replace - //private Point2D.Double textLoc; // remembers position of previous addLabel call (replaces text if at the same position) - //private int textIndex; // remembers index of previous addLabel call (for replacing if at the same position) - - /** Constructs a new Plot with the default options. - * Use add(shape,xvalues,yvalues) to add curves. - * @param title the window title - * @param xLabel the x-axis label; see setXYLabels for seting categories on an axis via the label - * @param yLabel the y-axis label; see setXYLabels for seting categories on an axis via the label - * @see #add(String,double[],double[]) - * @see #add(String,double[]) - */ - public Plot(String title, String xLabel, String yLabel) { - this(title, xLabel, yLabel, (float[])null, (float[])null, getDefaultFlags()); - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, float[] x, float[] y) { - this(title, xLabel, yLabel, x, y, getDefaultFlags()); - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, double[] x, double[] y) { - this(title, xLabel, yLabel, x!=null?Tools.toFloat(x):null, y!=null?Tools.toFloat(y):null, getDefaultFlags()); - } - - /** This version of the constructor has a 'flags' argument for - controlling whether ticks, grid, etc. are present and whether - the axes are logarithmic */ - public Plot(String title, String xLabel, String yLabel, int flags) { - this(title, xLabel, yLabel, (float[])null, (float[])null, flags); - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel,flags); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, float[] xValues, float[] yValues, int flags) { - this.title = title; - pp.axisFlags = flags; - setXYLabels(xLabel, yLabel); - if (yValues != null && yValues.length>0) { - addPoints(xValues, yValues, /*yErrorBars=*/null, LINE, /*label=*/null); - allPlotObjects.get(0).flags = PlotObject.CONSTRUCTOR_DATA; - } - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel,flags); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, double[] x, double[] y, int flags) { - this(title, xLabel, yLabel, x!=null?Tools.toFloat(x):null, y!=null?Tools.toFloat(y):null, flags); - } - - /** Constructs a new plot from an InputStream and closes the stream. If the ImagePlus is - * non-null, its title and ImageProcessor are used, but the image displayed is not modified. - */ - public Plot(ImagePlus imp, InputStream is) throws IOException, ClassNotFoundException { - ObjectInputStream in = new ObjectInputStream(is); - pp = (PlotProperties)in.readObject(); - allPlotObjects = (Vector)in.readObject(); - in.close(); - if (pp.xLabel.type==8) { - pp.xLabel.updateType(); //convert old (pre-1.52i) type codes for the PlotObjects - pp.yLabel.updateType(); - pp.frame.updateType(); - if (pp.legend != null) pp.legend.updateType(); - for (PlotObject plotObject : allPlotObjects) - plotObject.updateType(); - } - - defaultMinMax = pp.rangeMinMax; - currentFont = nonNullFont(pp.frame.getFont(), currentFont); // best guess in case we want to add a legend - getProcessor(); //prepares scale, calibration etc, but does not plot it yet - this.title = imp != null ? imp.getTitle() : "Untitled Plot"; - if (imp != null) { - this.imp = imp; - ip = imp.getProcessor(); - imp.setIgnoreGlobalCalibration(true); - adjustCalibration(imp.getCalibration()); - imp.setProperty(PROPERTY_KEY, this); - } - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel); add(shape,x,y);". - * @deprecated - */ - public Plot(String dummy, String title, String xLabel, String yLabel, float[] x, float[] y) { - this(title, xLabel, yLabel, x, y, getDefaultFlags()); - } - - /** Writes this plot into an OutputStream containing (1) the serialized PlotProperties and - * (2) the serialized Vector of all 'added' PlotObjects. The stream is NOT closed. - * The plot should have been drawn already. - */ - // Conversion to Streams can be also used to clone plots (not a shallow clone), but this is rather slow. - // Sample code: - // try { - // final PipedOutputStream pos = new PipedOutputStream(); - // final PipedInputStream pis = new PipedInputStream(pos); - // new Thread(new Runnable() { - // final public void run() { - // try { - // Plot p = new Plot(null, pis); - // pis.close(); - // pos.close(); - // p.show(); - // } catch(Exception e) {IJ.handleException(e);}; - // } - // }, "threadMakingPlotFromStream").start(); - // toStream(pos); - // } catch(Exception e) {IJ.handleException(e);} - void toStream(OutputStream os) throws IOException { - //prepare - for (PlotObject plotObject : pp.getAllPlotObjects()) //make sure all fonts are set properly - if (plotObject != null) - plotObject.setFont(nonNullFont(plotObject.getFont(), currentFont)); - pp.rangeMinMax = currentMinMax; - //write - ObjectOutputStream out = new ObjectOutputStream(os); - out.writeObject(pp); - out.writeObject(allPlotObjects); - } - - /** Writes this plot into a byte array containing (1) the serialized PlotProperties and - * (2) the serialized Vector of all 'added' PlotObjects. - * The plot should have been drawn already. Returns null on error (which should never happen). */ - public byte[] toByteArray() { - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - toStream(bos); - bos.close(); - return bos.toByteArray(); - } catch (Exception e) { - IJ.handleException(e); - return null; - } - } - - /** Returns the title of the image showing the plot (if any) or title of the plot */ - public String getTitle() { - return imp == null ? title : imp.getTitle(); - } - - /** Sets the x-axis and y-axis range. Saves the new limits as default (so the 'R' field sets the limits to these). - * Updates the image if existing. - * Accepts NaN values to indicate auto-range. */ - public void setLimits(double xMin, double xMax, double yMin, double yMax) { - setLimitsNoUpdate(xMin, xMax, yMin, yMax); - makeLimitsDefault(); - ignoreForce2Grid = true; - if (plotDrawn) - setLimitsToDefaults(true); - } - - /** Sets the x-axis and y-axis range. Accepts NaN values to indicate auto range. - * Does not update the image and leaves the default limits (for reset via the 'R' field) untouched. */ - void setLimitsNoUpdate(double xMin, double xMax, double yMin, double yMax) { - boolean containsNaN = (Double.isNaN(xMin + xMax + yMin + yMax)); - if (containsNaN && getNumPlotObjects(PlotObject.XY_DATA|PlotObject.ARROWS, false)==0)//can't apply auto-range without data - return; - double[] range = {xMin, xMax, yMin, yMax}; - if (containsNaN) { //auto range for at least one limit - double[] extrema = getMinAndMax(true, ALL_AXES_RANGE); - boolean[] auto = new boolean[range.length]; - for (int i = 0; i < range.length; i++) - if (Double.isNaN(range[i])) { - auto[i] = true; - range[i] = extrema[i]; - } - for (int a = 0; aOptions>Plots. - * @see #setFrameSize(int,int) - * @see #setWindowSize(int,int) - */ - public void setSize(int width, int height) { - if (ip != null && width == ip.getWidth() && height == ip.getHeight()) - return; - Dimension minSize = getMinimumSize(); - pp.width = Math.max(width, minSize.width); - pp.height = Math.max(height, minSize.height); - scale = 1.0f; - ip = null; - if (plotDrawn) updateImage(); - } - - /** The size of the plot including borders with axis labels etc., in pixels */ - public Dimension getSize() { - if (ip == null) - getBlankProcessor(); - return new Dimension(ip.getWidth(), ip.getHeight()); - } - - /** Sets the plot frame size in (unscaled) pixels. This size does not include the - * borders with the axis labels. Also sets the scale to 1.0. - * This frame size in pixels divided by the data range defines the image scale. - * This method does not check for the minimum size MIN_FRAMEWIDTH, MIN_FRAMEHEIGHT. - * Note that the black frame will have an outer size that is one pixel larger - * (when plotted with a linewidth of one pixel). - * @see #setWindowSize(int,int) - */ - public void setFrameSize(int width, int height) { - if (pp.width <= 0) { //plot not drawn yet? Just remember as preferred size - preferredPlotWidth = width; - preferredPlotHeight = height; - scale = 1.0f; - } else { - makeMarginValues(); - width += leftMargin+rightMargin; - height += topMargin+bottomMargin; - setSize(width, height); - } - } - - /** Sets the plot window size in pixels. - * @see #setFrameSize(int,int) - */ - public void setWindowSize(int width, int height) { - scale = 1.0f; - makeMarginValues(); - int titleBarHeight = 22; - int infoHeight = 11; - double scale = Prefs.getGuiScale(); - if (scale>1.0) - infoHeight = (int)(infoHeight*scale); - int buttonPanelHeight = 45; - if (pp.width <= 0) { //plot not drawn yet? - int extraWidth = leftMargin+rightMargin+ImageWindow.HGAP*2; - int extraHeight = topMargin+bottomMargin+titleBarHeight+infoHeight+buttonPanelHeight; - if (extraWidthplot may be null; then the call has no effect. */ - public void useTemplate(Plot plot) { - useTemplate(plot, templateFlags); - } - - /** Adjusts the format (style) with another plot as a template. Flags determine what to - * copy from the template; these can be X_RANGE, Y_RANGE, COPY_SIZE, COPY_LABELS, COPY_AXIS_STYLE, - * COPY_CONTENTS_STYLE (hidden items are ignored), and COPY_LEGEND. - * plot may be null; then the call has no effect. */ - public void useTemplate(Plot plot, int templateFlags) { - if (plot == null) return; - this.defaultFont = plot.defaultFont; - this.currentFont = plot.currentFont; - this.currentLineWidth = plot.currentLineWidth; - this.currentColor = plot.currentColor; - if ((templateFlags & COPY_AXIS_STYLE) != 0) { - this.pp.axisFlags = plot.pp.axisFlags; - this.pp.frame = plot.pp.frame.deepClone(); - } - if ((templateFlags & COPY_LABELS) != 0) { - this.pp.xLabel.label = plot.pp.xLabel.label; - this.pp.yLabel.label = plot.pp.yLabel.label; - this.pp.xLabel.setFont(plot.pp.xLabel.getFont()); - this.pp.yLabel.setFont(plot.pp.yLabel.getFont()); - } - for (int i=0; i>(i/2)&0x1) != 0) { - currentMinMax[i] = plot.currentMinMax[i]; - if (!plotDrawn) defaultMinMax[i] = plot.currentMinMax[i]; - } - if ((templateFlags & COPY_LEGEND) != 0 && plot.pp.legend != null) - this.pp.legend = plot.pp.legend.deepClone(); - if ((templateFlags & (COPY_LEGEND | COPY_CONTENTS_STYLE)) != 0) { - int plotPObjectIndex = 0; //points to PlotObjects of the templatePlot - int plotPObjectsSize = plot.allPlotObjects.size(); - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN)) { - while(plotPObjectIndex=plotPObjectsSize) break; - if ((templateFlags & COPY_LEGEND) != 0) - plotObject.label = plot.allPlotObjects.get(plotPObjectIndex).label; - if ((templateFlags & COPY_CONTENTS_STYLE) != 0) - setPlotObjectStyle(plotObject, getPlotObjectStyle(plot.allPlotObjects.get(plotPObjectIndex))); - plotPObjectIndex++; - } - } - } - if ((templateFlags & COPY_SIZE) != 0) - setSize(plot.pp.width, plot.pp.height); - - if ((templateFlags & COPY_EXTRA_OBJECTS) != 0) - for (int p = allPlotObjects.size(); p < plot.allPlotObjects.size(); p++) - allPlotObjects.add(plot.allPlotObjects.get(p)); - this.templateFlags = templateFlags; - } - - /** Sets the scale. Everything, including labels, line thicknesses, etc will be scaled by this factor. - * Also multiplies the plot size by this value. Used for 'Create high-resolution plot'. - * Should be called before creating the plot. - * Note that plots with a scale different from 1.0 must not be shown in a PlotWindow, but only as - * simple image in a normal ImageWindow. */ - public void setScale(float scale) { - this.scale = scale; - if (scale > 20f) scale = 20f; - if (scale < 0.7f) scale = 0.7f; - pp.width = sc(pp.width); - pp.height = sc(pp.height); - plotDrawn = false; - } - - /** Sets the labels of the x and y axes. 'xLabel', 'yLabel' may be null. - * If a label has the form {txt1,txt2,txt3}, the corresponding axis will be labeled - * not by numbers but rather with the texts "txt1", "txt2" ... instead of 0, 1, ... - * In this special case, there will be no label for the axis on the plot. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setXYLabels(String xLabel, String yLabel) { - pp.xLabel.label = xLabel!=null ? xLabel : ""; - pp.yLabel.label = yLabel!=null ? yLabel : ""; - } - - /** Sets the maximum number of intervals in a plot. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setMaxIntervals(int intervals) { - maxIntervals = intervals; - } - - /** Sets the length of the major tick in pixels. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setTickLength(int tickLength) { - this.tickLength = tickLength; - } - - /** Sets the length of the minor tick in pixels. */ - public void setMinorTickLength(int minorTickLength) { - this.minorTickLength = minorTickLength; - } - - /** Sets the flags that control the axes format. - * Does not modify the flags for logarithmic axes on/off and the FORCE2GRID flags. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setFormatFlags(int flags) { - int unchangedFlags = X_LOG_NUMBERS | Y_LOG_NUMBERS | X_FORCE2GRID | Y_FORCE2GRID; - flags = flags & (~unchangedFlags); //remove flags that should not be affected - pp.axisFlags = (pp.axisFlags & unchangedFlags) | flags; - } - - /** Returns the flags that control the axes */ - public int getFlags() { - return pp.axisFlags; - } - - /** Sets the X Axis format to Log or Linear. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setAxisXLog(boolean axisXLog) { - pp.axisFlags = axisXLog ? pp.axisFlags | X_LOG_NUMBERS : pp.axisFlags & (~X_LOG_NUMBERS); - } - - /** Sets the Y Axis format to Log or Linear. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setAxisYLog(boolean axisYLog) { - pp.axisFlags = axisYLog ? pp.axisFlags | Y_LOG_NUMBERS : pp.axisFlags & (~Y_LOG_NUMBERS); - } - - /** Sets whether to show major ticks at the x axis. - * Call update() thereafter to make the change visible (if the image is shown already). */ - - public void setXTicks(boolean xTicks) { - pp.axisFlags = xTicks ? pp.axisFlags | X_TICKS : pp.axisFlags & (~X_TICKS); - } - - /** Sets whether to show major ticks at the y axis. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setYTicks(boolean yTicks) { - pp.axisFlags = yTicks ? pp.axisFlags | Y_TICKS : pp.axisFlags & (~Y_TICKS); - } - - /** Sets whether to show minor ticks on the x axis (if linear). Also sets major ticks if true and no grid is set. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setXMinorTicks(boolean xMinorTicks) { - pp.axisFlags = xMinorTicks ? pp.axisFlags | X_MINOR_TICKS : pp.axisFlags & (~X_MINOR_TICKS); - if (xMinorTicks && !hasFlag(X_GRID)) - pp.axisFlags |= X_TICKS; - } - - /** Sets whether to show minor ticks on the y axis (if linear). Also sets major ticks if true and no grid is set. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setYMinorTicks(boolean yMinorTicks) { - pp.axisFlags = yMinorTicks ? pp.axisFlags | Y_MINOR_TICKS : pp.axisFlags & (~Y_MINOR_TICKS); - if (yMinorTicks && !hasFlag(Y_GRID)) - pp.axisFlags |= Y_TICKS; - } - - /** Sets the properties of the axes. Call update() thereafter to make the change visible - * (if the image is shown already). */ - public void setAxes(boolean xLog, boolean yLog, boolean xTicks, boolean yTicks, boolean xMinorTicks, boolean yMinorTicks, - int tickLenght, int minorTickLenght) { - setAxisXLog (xLog); - setAxisYLog (yLog); - setXMinorTicks (xMinorTicks); - setYMinorTicks (yMinorTicks); - setXTicks (xTicks); - setYTicks (yTicks); - setTickLength (tickLenght); - setMinorTickLength(minorTickLenght); - } - - /** Sets log scale in x. Call update() thereafter to make the change visible - * (if the image is shown already). */ - - public void setLogScaleX() { - setAxisXLog(true); - } - - public void setLogScaleY() { - setAxisYLog(true); - } - - /** The default flags, taking PlotWindow.noGridLines, PlotWindow.noTicks into account */ - public static int getDefaultFlags() { - int defaultFlags = 0; - if (!PlotWindow.noGridLines) //note that log ticks are also needed because the range may span less than a decade, then no grid is visible - defaultFlags |= X_GRID | Y_GRID | X_NUMBERS | Y_NUMBERS | X_LOG_TICKS | Y_LOG_TICKS; - if (!PlotWindow.noTicks) - defaultFlags |= X_TICKS | Y_TICKS | X_MINOR_TICKS | Y_MINOR_TICKS | X_NUMBERS | Y_NUMBERS | X_LOG_TICKS | Y_LOG_TICKS; - return defaultFlags; - } - - /** Adds a curve or set of points to this plot, where 'type' is - * "line", "connected circle", "filled", "bar", "separated bar", "circle", "box", "triangle", "diamond", "cross", - * "x" or "dot". Run Help>Examples>JavaScript>Graph Types to see examples. - * If 'type' is in the form "code: ", the macro given is executed to draw the symbol; - * macro variables 'x' and 'y' are the pixel coordinates of the point, 'xval' and 'yval' are the plot data - * and 'i' is the index of the data point (starting with 0 for the first point in the array). - * The drawing including line thickness, font size, etc. be scaled by scale factor 's' (to make high-resolution plots work). - * Example: "code: setFont('sanserif',12*s,'bold anti');drawString(d2s(yval,1),x-14*s,y-4*s);" - * writes the y value for each point above the point. - */ - public void add(String type, double[] xvalues, double[] yvalues) { - int iShape = toShape(type); - addPoints(Tools.toFloat(xvalues), Tools.toFloat(yvalues), null, iShape, iShape==CUSTOM?type.substring(5, type.length()):null); - } - - /** Replaces the specified plot object (curve or set of points). - * Equivalent to add() if there are no plot objects. */ - public void replace(int index, String type, double[] xvalues, double[] yvalues) { - if (index>=0 && index0?index:-1; - add(type, xvalues, yvalues); - } - } - - /** Adds a curve, set of points or error bars to this plot, where 'type' is - * "line", "connected circle", "filled", "bar", "separated bar", "circle", "box", - * "triangle", "diamond", "cross", "x", "dot", "error bars" or "xerror bars". - */ - public void add(String type, double[] yvalues) { - int iShape = toShape(type); - if (iShape==-1) - addErrorBars(yvalues); - else if (iShape==-2) - addHorizontalErrorBars(yvalues); - else - addPoints(null, Tools.toFloat(yvalues), null, iShape, iShape==CUSTOM?type.substring(5, type.length()):null); - } - - /** Adds a set of points to the plot or adds a curve if shape is set to LINE. - * @param xValues the x coordinates, or null. If null, integers starting at 0 will be used for x. - * @param yValues the y coordinates (must not be null) - * @param yErrorBars error bars in y, may be null - * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS, DIAMOND, DOT, LINE, CONNECTED_CIRCLES - * @param label Label for this curve or set of points, used for a legend and for listing the plots. - * For shape type CUSTOM, the 'label' String should contain the macro code as in "Custom Plot Symbols" - * example macro and in add(String, double[], double[]) (without the 'code:') - */ - public void addPoints(float[] xValues, float[] yValues, float[] yErrorBars, int shape, String label) { - if (xValues==null || xValues.length==0) { - xValues = new float[yValues.length]; - for (int i=0; i=0) - allPlotObjects.set(objectToReplace, new PlotObject(xValues, yValues, yErrorBars, shape, currentLineWidth, currentColor, currentColor2, label)); - else - allPlotObjects.add(new PlotObject(xValues, yValues, yErrorBars, shape, currentLineWidth, currentColor, currentColor2, label)); - objectToReplace = -1; - if (plotDrawn) updateImage(); - } - - /** Adds a set of points to the plot or adds a curve if shape is set to LINE. - * @param x the x coordinates - * @param y the y coordinates - * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS, DIAMOND, DOT, LINE, CONNECTED_CIRCLES - */ - public void addPoints(float[] x, float[] y, int shape) { - addPoints(x, y, null, shape, null); - } - - /** Adds a set of points to the plot using double arrays. */ - public void addPoints(double[] x, double[] y, int shape) { - addPoints(Tools.toFloat(x), Tools.toFloat(y), shape); - } - - /** Returns the number for a given plot symbol shape, -1 for xError and -2 for yError (all case-insensitive) */ - public static int toShape(String str) { - str = str.toLowerCase(Locale.US); - int shape = Plot.CIRCLE; - if (str.contains("curve") || str.contains("line")) - shape = Plot.LINE; - else if (str.contains("connected")) - shape = Plot.CONNECTED_CIRCLES; - else if (str.contains("filled")) - shape = Plot.FILLED; - else if (str.contains("circle")) - shape = Plot.CIRCLE; - else if (str.contains("box")) - shape = Plot.BOX; - else if (str.contains("triangle")) - shape = Plot.TRIANGLE; - else if (str.contains("cross") || str.contains("+")) - shape = Plot.CROSS; - else if (str.contains("diamond")) - shape = Plot.DIAMOND; - else if (str.contains("dot")) - shape = Plot.DOT; - else if (str.contains("xerror")) - shape = -2; - else if (str.contains("error")) - shape = -1; - else if (str.contains("x")) - shape = Plot.X; - else if (str.contains("separate")) - shape = Plot.SEPARATED_BAR; - else if (str.contains("bar")) - shape = Plot.BAR; - if (str.startsWith("code:")) - shape = CUSTOM; - return shape; - } - - /** Adds a set of points to the plot using double ArrayLists. - * Must be called before the plot is displayed. */ - public void addPoints(ArrayList x, ArrayList y, int shape) { - addPoints(getDoubleFromArrayList(x), getDoubleFromArrayList(y), shape); - } - - /** Adds a set of points to the plot or adds a curve if shape is set to LINE. - * @param x the x-coodinates - * @param y the y-coodinates - * @param errorBars half-lengths of the vertical error bars, may be null - * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS, DIAMOND, DOT or LINE - */ - public void addPoints(double[] x, double[] y, double[] errorBars, int shape) { - addPoints(Tools.toFloat(x), Tools.toFloat(y), Tools.toFloat(errorBars), shape, null); - } - - /** Adds a set of points to the plot using double ArrayLists. - * Must be called before the plot is displayed. */ - public void addPoints(ArrayList x, ArrayList y, ArrayList errorBars, int shape) { - addPoints(getDoubleFromArrayList(x), getDoubleFromArrayList(y), getDoubleFromArrayList(errorBars), shape); - } - - public double[] getDoubleFromArrayList(ArrayList list) { - if (list == null) return null; - double[] targ = new double[list.size()]; - for (int i = 0; i < list.size(); i++) - targ[i] = ((Double) list.get(i)).doubleValue(); - return targ; - } - - /** Adds a set of points that will be drawn as ARROWs. - * @param x1 the x-coodinates of the beginning of the arrow - * @param y1 the y-coodinates of the beginning of the arrow - * @param x2 the x-coodinates of the end of the arrow - * @param y2 the y-coodinates of the end of the arrow - */ - public void drawVectors(double[] x1, double[] y1, double[] x2, double[] y2) { - allPlotObjects.add(new PlotObject(Tools.toFloat(x1), Tools.toFloat(y1), - Tools.toFloat(x2), Tools.toFloat(y2), currentLineWidth, currentColor)); - } - - /** - * Adds a set of 'shapes' such as boxes and whiskers - * - * @param shapeType e.g. "boxes width=20" - * @param floatCoords eg[6][3] holding 1 Xval + 5 Yvals for 3 boxes - */ - public void drawShapes(String shapeType, ArrayList floatCoords) { - allPlotObjects.add(new PlotObject(shapeType, floatCoords, currentLineWidth, currentColor, currentColor2)); - } - - public static double calculateDistance(int x1, int y1, int x2, int y2) { - return java.lang.Math.sqrt((x2 - x1)*(double)(x2 - x1) + (y2 - y1)*(double)(y2 - y1)); - } - - /** Adds a set of vectors to the plot using double ArrayLists. - * Does not support logarithmic axes. - * Must be called before the plot is displayed. */ - public void drawVectors(ArrayList x1, ArrayList y1, ArrayList x2, ArrayList y2) { - drawVectors(getDoubleFromArrayList(x1), getDoubleFromArrayList(y1), getDoubleFromArrayList(x2), getDoubleFromArrayList(y2)); - } - - /** Adds vertical error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addErrorBars(float[] errorBars) { - PlotObject mainObject = getLastCurveObject(); - if (mainObject != null) - mainObject.yEValues = errorBars; - else throw new RuntimeException("Plot can't add y error bars without data"); - } - - /** Adds vertical error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addErrorBars(double[] errorBars) { - addErrorBars(Tools.toFloat(errorBars)); - } - - /** Adds horizontal error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addHorizontalErrorBars(float[] xErrorBars) { - PlotObject mainObject = getLastCurveObject(); - if (mainObject != null) - mainObject.xEValues = xErrorBars; - else throw new RuntimeException("Plot can't add x error bars without data"); - } - - /** Adds horizontal error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addHorizontalErrorBars(double[] xErrorBars) { - addHorizontalErrorBars(Tools.toFloat(xErrorBars)); - } - - /** Draws text at the specified location, where (0,0) - * is the upper left corner of the the plot frame and (1,1) is - * the lower right corner. Uses the justification specified by setJustification(). - * When called with the same position as the previous addLabel call, the text of that previous call is replaced */ - public void addLabel(double x, double y, String label) { - for (int i=allPlotObjects.size()-1; i>=0; i--) { - PlotObject plotObject = allPlotObjects.get(i); - if (plotObject.type == PlotObject.NORMALIZED_LABEL) { //result of previous addLabel - if (plotObject.x == x && plotObject.y == y) { - allPlotObjects.set(i, new PlotObject(label, x, y, currentJustification, - currentFont, currentColor, PlotObject.NORMALIZED_LABEL)); - return; - } - break; - } - } - allPlotObjects.add(new PlotObject(label, x, y, currentJustification, currentFont, currentColor, PlotObject.NORMALIZED_LABEL)); - } - - /* Draws text at the specified location, using the coordinate system defined - * by setLimits() and the justification specified by setJustification(). */ - public void addText(String label, double x, double y) { - allPlotObjects.add(new PlotObject(label, x, y, currentJustification, currentFont, currentColor, PlotObject.LABEL)); - } - - /** Adds an automatically positioned legend, where 'labels' can be a tab-delimited or - newline-delimited list of curve or point labels in the sequence these data were added. - Hidden data sets are ignored. - If 'labels' is null or empty, the labels of the data set previously (if any) are used. - To modify the legend's style, call 'setFont' and 'setLineWidth' before 'addLegend'. */ - public void addLegend(String labels) { - addLegend(labels, "auto"); - } - - /** Adds a legend at the position given in 'options', where 'labels' can be tab-delimited or - * newline-delimited list of curve or point labels in the sequence these data were added. - * Hidden data sets are ignored; no labels (and no delimiters) should be provided for these. - * Apart from top to bottom and bottom to top (controlled by "bottom-to-top" in the options), - * the sequence may be altered by preceding numbers followed by double underscores, such as - * "1__Other Data Set\t0__First Data Set" (the number and double underscore won't be displayed). - * When this possibility is used, only items with double underscores will be shown in the legend - * (preceding double underscores without a number make the item appear in the legend without altering the sequence). - * If 'labels' is null or empty, the labels of the data set previously (if any) are used. - To modify the legend's style, call 'setFont' and 'setLineWidth' before 'addLegend'. */ - public void addLegend(String labels, String options) { - int flags = 0; - if (options!=null) { - options = options.toLowerCase(); - if (options.contains("top-left")) - flags |= Plot.TOP_LEFT; - else if (options.contains("top-right")) - flags |= Plot.TOP_RIGHT; - else if (options.contains("bottom-left")) - flags |= Plot.BOTTOM_LEFT; - else if (options.contains("bottom-right")) - flags |= Plot.BOTTOM_RIGHT; - else if (!options.contains("off") && !options.contains("no")) - flags |= Plot.AUTO_POSITION; - if (options.contains("bottom-to-top")) - flags |= Plot.LEGEND_BOTTOM_UP; - if (options.contains("transparent")) - flags |= Plot.LEGEND_TRANSPARENT; - } - setLegend(labels, flags); - } - - /** Adds a legend. The legend will be always drawn last (on top of everything). - * To modify the legend's style, call 'setFont' and 'setLineWidth' before 'addLegend' - * @param labels labels of the points or curves in the sequence of the data were added, tab-delimited or linefeed-delimited. - * The labels of the datasets will be set to these values. If null or not given, the labels set - * previously (if any) will be used. - * Hidden data sets are ignored; no labels (and no delimiters) should be provided for these. - * Apart from top to bottom and bottom to top (controlled by the LEGEND_BOTTOM_UP flag), - * the sequence may be altered by preceding numbers followed by double underscores, such as - * "1__Other Data Set\t0__First Data Set" (the number and double underscore won't be displayed). - * When this possibility is used, only items with double underscores will be shown in the legend - * (preceding double underscores without a number make the item appear in the legend without altering the sequence). - * @param flags Bitwise or of position (AUTO_POSITION, TOP_LEFT etc.), LEGEND_TRANSPARENT, and LEGEND_BOTTOM_UP if desired. - * Updates the image (if it is shown already). */ - public void setLegend(String labels, int flags) { - if (labels != null && labels.length()>0) { - String[] allLabels = labels.split("[\n\t]"); - int iPart = 0; - for (PlotObject plotObject : allPlotObjects) - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN)) - if (iPart < allLabels.length) { - String label = allLabels[iPart++]; - if (label!=null && label.length()>0) - plotObject.label = label; - } - } - pp.legend = new PlotObject(currentLineWidth == 0 ? 1 : currentLineWidth, - currentFont, currentColor == null ? Color.black : currentColor, flags); - if (plotDrawn) updateImage(); - } - - /** Sets the label for the plot object number 'index' in the sequence they were added. - * With index=-1, sets the label for the last object added. - * For x/y data, the label is used for the legend and as header in getResultsTableWithLabels. - * For Text/Label objects, it affects the label shown (but the plot is not redisplayed). - */ - public void setLabel(int index, String label) { - if (index < 0) index = allPlotObjects.size() + index; - allPlotObjects.get(index).label = label; - } - - /** Removes NaNs from the xValues and yValues arrays of all plot objects. */ - public void removeNaNs() { - for (PlotObject plotObj : allPlotObjects){ - if(plotObj != null && plotObj.xValues!= null && plotObj.yValues != null ){ - int oldSize = plotObj.xValues.length; - float[] xVals = new float[oldSize]; - float[] yVals = new float[oldSize]; - int newSize = 0; - for (int kk = 0; kk < oldSize; kk++) { - if (!Float.isNaN(plotObj.xValues[kk] + plotObj.yValues[kk])) { - xVals[newSize] = plotObj.xValues[kk]; - yVals[newSize] = plotObj.yValues[kk]; - newSize++; - } - } - if (newSize < oldSize) { - plotObj.xValues = new float[newSize]; - plotObj.yValues = new float[newSize]; - System.arraycopy(xVals, 0, plotObj.xValues, 0, newSize); - System.arraycopy(yVals, 0, plotObj.yValues, 0, newSize); - } - } - } - } - - /** Returns an array of the available curve types ("Line", "Bar", "Circle", etc). */ - public String[] getTypes() { - return SORTED_SHAPES; - } - - /** Sets the justification used by addLabel(), where justification - * is Plot.LEFT, Plot.CENTER or Plot.RIGHT. Default is LEFT. */ - public void setJustification(int justification) { - currentJustification = justification; - } - - /** Changes the drawing color for the next objects that will be added to the plot. - * For selecting the color of the curve passed with the constructor, - * use setColor before draw. - * The frame and labels are always drawn in black. */ - public void setColor(Color c) { - currentColor = c; - currentColor2 = null; - } - - public void setColor(String color) { - setColor(Colors.decode(color, Color.black)); - } - - /** Changes the drawing color for the next objects that will be added to the plot. - * It also sets secondary color: This is the color of the line for CONNECTED_CIRCLES, - * and the color for filling open symbols (CIRCLE, BOX, TRIANGLE). - * Set it to null or use the one-argument call setColor(color) to disable filling. - * For selecting the color of the curve passed with the constructor, - * use setColor before draw. - * The frame and labels are always drawn in black. */ - public void setColor(Color c, Color c2) { - currentColor = c; - currentColor2 = c2; - } - - /** Sets the drawing colors for the next objects that will be added to the plot. */ - public void setColor(String c1, String c2) { - setColor(Colors.decode(c1, Color.black), Colors.decode(c2, null)); - } - - /** Set the plot frame background color. */ - public void setBackgroundColor(Color c) { - pp.frame.color2 = c; - } - - /** Set the plot frame background color. */ - public void setBackgroundColor(String c) { - setBackgroundColor(Colors.decode(c,Color.white)); - } - - /** Changes the line width for the next objects that will be added to the plot. */ - public void setLineWidth(int lineWidth) { - currentLineWidth = lineWidth > 0 ? lineWidth : 0.01f; - } - - /** Changes the line width for the next objects that will be added to the plot. - * After all objects have been added, set the line width to the width desired - * for the frame around the plot (max. 3) */ - public void setLineWidth(float lineWidth) { - currentLineWidth = lineWidth > 0.01 ? lineWidth : 0.01f; - } - - /** Draws a line using the coordinate system defined by setLimits(). */ - public void drawLine(double x1, double y1, double x2, double y2) { - allPlotObjects.add(new PlotObject(x1, y1, x2, y2, currentLineWidth, 0, currentColor, PlotObject.LINE)); - } - - /** Draws a line using a normalized 0-1, 0-1 coordinate system, - * with (0,0) at the top left and (1,1) at the lower right corner. - * This is the same coordinate system used by addLabel(x,y,label). - */ - public void drawNormalizedLine(double x1, double y1, double x2, double y2) { - allPlotObjects.add(new PlotObject(x1, y1, x2, y2, currentLineWidth, 0, currentColor, PlotObject.NORMALIZED_LINE)); - } - - /** Draws a line using the coordinate system defined by setLimits(). */ - public void drawDottedLine(double x1, double y1, double x2, double y2, int step) { - allPlotObjects.add(new PlotObject(x1, y1, x2, y2, currentLineWidth, step, currentColor, PlotObject.DOTTED_LINE)); - } - - /** Sets the font size for all following addLabel() etc. operations. The currently set font when - * displaying the plot determines the font of all labels & numbers. - * After the plot has been shown, sets the font for the numbers and the legend (if present). - * If the plot is hown already, call update() thereafter to make the change visible. */ - public void setFontSize(int size) { - setFont(-1, (float)size); - } - - /** Sets the font for all following addLabel() etc. operations. The currently set font when - * displaying the plot determines the font of all labels & numbers. - * After the plot has been shown, sets the font for the numbers and the legend (if present); - * use setFont(char, Font) to set these fonts individually. - * If the plot is hown already, call update() thereafter to make the change visible. */ - public void setFont(Font font) { - if (font == null) font = defaultFont; - currentFont = font; - if (plotDrawn) { - pp.frame.setFont(font); - if (pp.legend != null) - pp.legend.setFont(font); - } - } - - /** Sets the font size and style for all following addLabel() etc. operations. This leaves - * the font name and style of the previously used fonts unchanged. The currently set font - * when displaying the plot determines the font of the numbers at the axes. - * That font also sets the default label font size, which may be overridden by - * setAxisLabelFontSize or setXLabelFont, setYLabelFont. - * After the plot has been shown, sets the font for the numbers and the legend (if present); - * use setFont(char, Font) to set these fonts individually. - * Styles are defined in the Font class, e.g. Font.PLAIN, Font.BOLD. - * Set style to -1 to leave the style unchanged. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setFont(int style, float size) { - if (size < 9) size = 9f; - if (size > 36) size = 36f; - Font previousFont = nonNullFont(pp.frame.getFont(), currentFont); - if (style < 0) style = previousFont.getStyle(); - setFont(previousFont.deriveFont(style, size)); - } - - /** Sets the x and y label font size and style. Styles are defined - * in the Font class, e.g. Font.PLAIN, Font.BOLD. - * Set style to -1 to leave the style unchanged. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setAxisLabelFont(int style, float size) { - if (size < 9) size = 9f; - if (size > 33) size = 33f; - pp.xLabel.setFont(nonNullFont(pp.xLabel.getFont(), currentFont)); - pp.yLabel.setFont(nonNullFont(pp.yLabel.getFont(), currentFont)); - setXLabelFont(pp.xLabel.getFont().deriveFont(style < 0 ? pp.xLabel.getFont().getStyle() : style, size)); - setYLabelFont(pp.xLabel.getFont().deriveFont(style < 0 ? pp.yLabel.getFont().getStyle() : style, size)); - } - - /** Sets the xLabelFont; must not be null. If this method is not used, the last setFont - * of setFontSize call before displaying the plot determines the font, or if neither - * was called, the font size of the Plot Options is used. */ - public void setXLabelFont(Font font) { - pp.xLabel.setFont(font); - } - - /** Sets the yLabelFont; must not be null. */ - public void setYLabelFont(Font font) { - pp.yLabel.setFont(font); - } - - /** Determines whether to use antialiased text (default true) */ - public void setAntialiasedText(boolean antialiasedText) { - pp.antialiasedText = antialiasedText; - } - - /** Returns the font currently used (e.g. for the next 'addLabel') */ - public Font getCurrentFont() { - return currentFont != null ? currentFont : defaultFont; - } - - /** Returns the default font for the plot */ - public Font getDefaultFont() { - return defaultFont; - } - - /** Gets the font for xLabel ('x'), yLabel('y'), numbers ('f' for 'frame') or the legend ('l'). - * Returns null if the given PlotObject does not exist or its font is null */ - public Font getFont(char c) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - return plotObject.getFont(); - else - return null; - } - - /** Sets the font for xLabel ('x'), yLabel('y'), numbers ('f' for 'frame') or the legend ('l') */ - public void setFont(char c, Font font) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - plotObject.setFont(font); - } - - /** Gets the label String of the xLabel ('x'), yLabel('y') or the legend ('l'). - * Returns null if the given PlotObject does not exist or its label is null */ - public String getLabel(char c) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - return plotObject.label; - else - return null; - } - - /** Gets the flags of the xLabel ('x'), yLabel('y') or the legend ('l'). - * Returns -1 if the given PlotObject does not exist */ - public int getObjectFlags(char c) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - return plotObject.flags; - else - return -1; - } - - /** Get the x coordinates of the data set passed with the constructor (if not null) - * or otherwise of the data set of the first 'addPoints'. Returns null if neither exists */ - public float[] getXValues() { - PlotObject p = getMainCurveObject(); - return p==null ? null : p.xValues; - } - - /** Get the y coordinates of the data set passed with the constructor (if not null) - * or otherwise of the data set of the first 'addPoints'. Returns null if neither exists */ - public float[] getYValues() { - PlotObject p = getMainCurveObject(); - return p==null ? null : p.yValues; - } - - /** Get the data of the n-th Plot Object containing xy data in the sequence they were added - * (Other Plot Objects such as labels, arrows, lines, shapes and hidden PlotObjects are not counted). - * The array returned has elements [0] x data, [1] y data, [2] x error bars, [3] y error bars. - * If no error bars are given, the corresponding arrays are null. - * Returns null if there is no Plot Object with xy data with this index. - * @see #getDataObjectDesignations() - **/ - public float[][] getDataObjectArrays(int index) { - int i = 0; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type != PlotObject.XY_DATA || plotObject.hasFlag(PlotObject.HIDDEN)) continue; - if (index == i) - return new float[][] {plotObject.xValues, plotObject.yValues, plotObject.xEValues, plotObject.yEValues}; - i++; - } - return null; - } - - /** Gets an array with human-readable designations of the PlotObjects (curves, labels, ...) - * in the sequence they were added (the object passed with the constructor is first, - * even though it is plotted last). Hidden PlotObjects are included. **/ - public String[] getPlotObjectDesignations() { - return getPlotObjectDesignations(-1, true); - } - - /** Gets an array with human-readable designations of the PlotObjects containing xy data - * in the sequence they were added. Other Plot Objects such as labels, arrows, lines, - * shapes and hidden PlotObjects are not counted. - * (the object passed with the constructor is first, even though it is plotted last). */ - public String[] getDataObjectDesignations() { - return getPlotObjectDesignations(PlotObject.XY_DATA, false); - } - - /** Returns the number of PlotObjects (curves, labels, ...) passed with the constructor or added by 'add' or 'draw' methods. - * Legend, frame and axes (though internally PlotObjects) are not included */ - public int getNumPlotObjects() { - return allPlotObjects.size(); - } - - /** Returns the number of PlotObjects fitting the mask. - * Legend, frame and axes (though internally PlotObjects) are not included */ - int getNumPlotObjects(int mask, boolean includeHidden) { - int nObjects = 0; - for (PlotObject plotObject : allPlotObjects) - if ((plotObject.type & mask) != 0 && (includeHidden || !plotObject.hasFlag(PlotObject.HIDDEN))) - nObjects++; - return nObjects; - } - - /** Gets an array with human-readable designations of the PlotObjects with types fitting the mask - * (i.e., 'mask' should be a bitwise or of the types desired: XY_DATA = 1, ARROWS = 2, LINE = 4, - * NORMALIZED_LINE = 8, DOTTED_LINE = 16, LABEL = 32, NORMALIZED_LABEL = 64, LEGEND = 128) */ - String[] getPlotObjectDesignations(int mask, boolean includeHidden) { - int nObjects = getNumPlotObjects(mask, includeHidden); - String[] names = new String[nObjects]; - if (names.length == 0) return names; - int iData = 1, iArrow = 1, iLine = 1, iText = 1, iBox = 1, iShape = 1; //Human readable counters of each object type - int i = 0; - for (PlotObject plotObject : allPlotObjects) { - int type = plotObject.type; - if ((type & mask) == 0 || (!includeHidden && plotObject.hasFlag(PlotObject.HIDDEN))) continue; - String label = plotObject.label; - switch (type) { - case PlotObject.XY_DATA: - names[i] = "Data Set "+iData+": "+(plotObject.label != null ? - plotObject.label : "(" + plotObject.yValues.length + " data points)"); - iData++; - break; - case PlotObject.ARROWS: - names[i] = "Arrow Set "+iArrow+" ("+ plotObject.xValues.length + ")"; - iArrow++; - break; - case PlotObject.LINE: case PlotObject.NORMALIZED_LINE: case PlotObject.DOTTED_LINE: - String detail = ""; - if (type == PlotObject.DOTTED_LINE) detail = "dotted "; - if (plotObject.x ==plotObject.xEnd) detail += "vertical"; - else if (plotObject.y ==plotObject.yEnd) detail += "horizontal"; - if (detail.length()>0) detail = " ("+detail.trim()+")"; - names[i] = "Straight Line "+iLine+detail; - iLine++; - break; - case PlotObject.LABEL: case PlotObject.NORMALIZED_LABEL: - String text = plotObject.label.replaceAll("\n"," "); - if (text.length()>45) text = text.substring(0, 40)+"..."; - names[i] = "Text "+iText+": \""+text+'"'; - iText++; - break; - case PlotObject.SHAPES: - String s = plotObject.shapeType; - String[] words = s.split(" "); - names[i] = "Shapes (" + words[0] +") " + iShape; - iShape++; - break; - } - i++; - } - return names; - } - - /** Add the i-th PlotObject (in the sequence how they were added, including hidden ones) - * from another plot to this one. PlotObjects here refers to curves, arrows, labels etc. - * (not legend, axes and frame, though implemented as PlotObjects) - * Use 'update' to update the plot thereafter. - * @return Index of the plotObject added in the sequence they were added */ - public int addObjectFromPlot(Plot plot, int i) { - PlotObject plotObject = plot.getPlotObjectDeepClone(i); - plotObject.unsetFlag(PlotObject.CONSTRUCTOR_DATA); - allPlotObjects.add(plotObject); - int index = allPlotObjects.size() - 1; - return index; - } - - /** Get the style of the i-th PlotObject (curve, label, ...) in the sequence - * they were added (including hidden ones), as String with comma delimiters: - * Main Color, Secondary Color (or "none"), Line Width [, Symbol shape for XY_DATA] [,hidden] - * PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public String getPlotObjectStyle(int i) { - return getPlotObjectStyle(allPlotObjects.get(i)); - } - - String getPlotObjectStyle(PlotObject plotObject) { - String styleString = Colors.colorToString(plotObject.color) + "," + - Colors.colorToString(plotObject.color2) + "," + - plotObject.lineWidth; - if (plotObject.type == PlotObject.XY_DATA) - styleString += ","+SHAPE_NAMES[plotObject.shape]; - if (plotObject.hasFlag(PlotObject.HIDDEN)) - styleString += ",hidden"; - return styleString; - } - - /** Get the label the i-th PlotObject (in the sequence how they were added, including hidden ones). - * Returns null if no label. PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public String getPlotObjectLabel(int i) { - return allPlotObjects.get(i).label; - } - - /** Set the label the i-th PlotObject (in the sequence how they were added, including hidden ones) - * PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public void setPlotObjectLabel(int i, String label) { - allPlotObjects.get(i).label = label; - } - - /** Sets the style of the specified PlotObject (curve, label, etc.) from a - * comma-delimited string ("color1,color2,lineWidth[,symbol][,hidden]"), - * where "color2" can be "none" and "symbol" and "hidden" are optional. - * PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public void setStyle(int index, String style) { - if (index<0 || index>=allPlotObjects.size()) - throw new IllegalArgumentException("Index out of range"); - setPlotObjectStyle(allPlotObjects.get(index), style); - } - - public void setPlotObjectStyle(int i, String styleString) { - setStyle(i, styleString); - } - - void setPlotObjectStyle(PlotObject plotObject, String styleString) { - String[] items = styleString.split(","); - int nItems = items.length; - if (items[nItems-1].indexOf("hidden") >= 0) { - plotObject.setFlag(PlotObject.HIDDEN); - nItems = items.length - 1; - } else - plotObject.unsetFlag(PlotObject.HIDDEN); - plotObject.color = Colors.decode(items[0].trim(), plotObject.color); - plotObject.color2 = Colors.decode(items[1].trim(), null); - float lineWidth = plotObject.lineWidth; - if (items.length >= 3) try { - plotObject.lineWidth = Float.parseFloat(items[2].trim()); - } catch (NumberFormatException e) {}; - if (items.length >= 4 && plotObject.shape!=CUSTOM) - plotObject.shape = toShape(items[3].trim()); - updateImage(); - return; - } - - /** Returns the index of the first plot object with x,y data (points, line) or arrows - * with all data equal to those given. Returns or -1 is no such plot object exists. - * The array 'values' should contain the x, y, x error bar, yerror bar data. The 'values' array may have any size; - * only the data given are compared (e.g. for an array with length 2, there is no check for erro bars). - * Used when adding data from a table not to suggest the same data twice. */ - public int getPlotObjectIndex(float[][] values) { - return getPlotObjectIndex(PlotObject.XY_DATA|PlotObject.ARROWS, values); - } - - /** Returns the index of the first plot object fitting the type mask and with all data equal to those given. - * ('mask' should be a bitwise or of the types desired) - * Returns or -1 is no such plot object exists. - * The array 'values' should contain the x, y, x error bar, yerror bar data. The 'values' array may have any size; - * only the data given are compared (e.g. for an array with length 2, there is no check for erro bars). - * Used when adding data from a table not to suggest the same data twice. */ - int getPlotObjectIndex(int typeMask, float[][] values) { - for (int i=0; i(allPlotObjects.size()); - copyPlotObjectsVector(allPlotObjects, allPlotObjectsSnapshot); - } - - /** Restores the plot contents (not including axis formats etc) from the snapshot - * previously created by savePlotObjects(). See also killPlotObjectsSnapshot - * Use 'update' to update the plot thereafter. */ - public void restorePlotObjects() { - if (allPlotObjectsSnapshot != null) - copyPlotObjectsVector(allPlotObjectsSnapshot, allPlotObjects); - } - - /** Deletes the snapshot of the plot contents to make space */ - public void killPlotObjectsSnapshot() { - allPlotObjectsSnapshot = null; - } - - /** Creates a snapshot of the plot properties (formatting, range etc., not PlotObjects such as data and corresponding curves etc.), - * for later undo by restorePlotProperties. See also killPlotPropertiesSnapshot */ - public void savePlotPlotProperties() { - pp.rangeMinMax = currentMinMax; - ppSnapshot = pp.deepClone(); - } - - /** Restores the plot properties (formatting, range etc., not PlotObjects such as data and corresponding curves etc.) - * from a snapshot previously created by savePlotPlotProperties. See also killPlotPropertiesSnapshot. - * Use 'update' to update the plot thereafter. */ - public void restorePlotProperties() { - pp = ppSnapshot.deepClone(); - System.arraycopy(pp.rangeMinMax, 0, currentMinMax, 0, Math.min(pp.rangeMinMax.length, currentMinMax.length)); - } - - /** Deletes the snapshot of the plot properties to make space */ - public void killPlotPropertiesSnapshot() { - ppSnapshot = null; - } - - private void copyPlotObjectsVector(Vector src, Vectordest) { - if (dest.size() > 0) dest.removeAllElements(); - for (PlotObject plotObject : src) - dest.add(plotObject.deepClone()); - } - - PlotObject getPlotObjectDeepClone(int i) { - return allPlotObjects.get(i).deepClone(); - } - - /** Sets the plot range to the initial value determined from minima&maxima or given by setLimits. - * Updates the image if existing and updateImg is true */ - public void setLimitsToDefaults(boolean updateImg) { - saveMinMax(); - System.arraycopy(defaultMinMax, 0, currentMinMax, 0, defaultMinMax.length); - if (plotDrawn && updateImg) updateImage(); - } - - /** Sets the plot range to encompass all data. Updates the image if existing and updateImg is true. */ - public void setLimitsToFit(boolean updateImg) { - saveMinMax(); - currentMinMax = getMinAndMax(true, ALL_AXES_RANGE); - if (Double.isNaN(defaultMinMax[0]) && Double.isNaN(defaultMinMax[2])) //no range at all so far - System.arraycopy(currentMinMax, 0, defaultMinMax, 0, Math.min(currentMinMax.length, defaultMinMax.length)); - - enlargeRange(currentMinMax); //avoid points exactly at the border - //System.arraycopy(currentMinMax, 0, defaultMinMax, 0, currentMinMax.length); - if (plotDrawn && updateImg) updateImage(); - } - - /** reverts plot range to previous values and updates the image */ - public void setPreviousMinMax() { - if (Double.isNaN(savedMinMax[0])) return; //no saved values yet - double[] swap = new double[currentMinMax.length]; - System.arraycopy(currentMinMax, 0, swap, 0, currentMinMax.length); - System.arraycopy(savedMinMax, 0, currentMinMax, 0, currentMinMax.length); - System.arraycopy(swap, 0, savedMinMax, 0, currentMinMax.length); - updateImage(); - } - - /** Draws the plot (if not done before) in an ImageProcessor and returns the ImageProcessor with the plot. */ - public ImageProcessor getProcessor() { - draw(); - return ip; - } - - /** Returns the plot as an ImagePlus. - * If an ImagePlus for this plot already exists, displays the plot in that ImagePlus and returns it. */ - public ImagePlus getImagePlus() { - if (stack != null) { - if (imp != null) - return imp; - else { - imp = new ImagePlus(title, stack); - adjustCalibration(imp.getCalibration()); - return imp; - } - } - if (plotDrawn) - updateImage(); - else - draw(); - if (imp != null) { - if (imp.getProcessor() != ip) - imp.setProcessor(ip); - return imp; - } else { - ImagePlus imp = new ImagePlus(title, ip); - setImagePlus(imp); - return imp; - } - } - - /** Sets the ImagePlus where the plot will be displayed. If the ImagePlus is not - * known otherwise (e.g. from getImagePlus), this is needed for changes such as - * zooming in to work correctly. It also sets the calibration of the ImagePlus. - * The ImagePlus is not displayed or updated unless its ImageProcessor is - * no that of the current Plot (then it gets this ImageProcessor). - * Does nothing if imp is unchanged and has the ImageProcessor of this plot. - * 'imp' may be null to disconnect the plot from its ImagePlus. - * Does nothing for Plot Stacks. */ - public void setImagePlus(ImagePlus imp) { - if (imp != null && imp == this.imp && imp.getProcessor() == ip) - return; - if (stack != null) - return; - if (this.imp != null) - this.imp.setProperty(PROPERTY_KEY, null); - this.imp = imp; - if (imp != null) { - imp.setIgnoreGlobalCalibration(true); - adjustCalibration(imp.getCalibration()); - imp.setProperty(PROPERTY_KEY, this); - if (ip != null && imp.getProcessor() != ip) - imp.setProcessor(ip); - } - } - - /** Adjusts a Calibration object to fit the current axes. - * For log axes, the calibration refers to the base-10 logarithm of the value */ - public void adjustCalibration(Calibration cal) { - if (xMin == xMax) //tiff images can't handle infinity in scale, see TiffEncoder.writeScale - xScale = 1e6; - if (yMin == yMax) - yScale = 1e6; - cal.xOrigin = xBasePxl-xMin*xScale; - cal.pixelWidth = 1.0/Math.abs(xScale); //Calibration must not have negative pixel size - cal.yOrigin = yBasePxl+yMin*yScale; - cal.pixelHeight = 1.0/Math.abs(yScale); - cal.setInvertY(yScale >= 0); - cal.setXUnit(" "); // avoid 'pixels' for scaled units - if (xMin == xMax) - xScale = Double.POSITIVE_INFINITY; - if (yMin == yMax) - yScale = Double.POSITIVE_INFINITY; - } - - /** Displays the plot in a PlotWindow. - * Plot stacks are shown in a StackWindow, not in a PlotWindow; - * in this case the return value is null (use getImagePlus().getWindow() instead). - * Also returns null in BatchMode. Note that the PlotWindow might get closed - * immediately if its 'listValues' and 'autoClose' flags are set. - * @see #update() - */ - public PlotWindow show() { - PlotVirtualStack stack = getStack(); - if (stack!=null) { - getImagePlus().show(); - return null; - } - if ((IJ.macroRunning() && IJ.getInstance()==null) || Interpreter.isBatchMode()) { - imp = getImagePlus(); - imp.setPlot(this); - WindowManager.setTempCurrentImage(imp); - if (getMainCurveObject() != null) { - imp.setProperty("XValues", getXValues()); // Allows values to be retrieved by - imp.setProperty("YValues", getYValues()); // by Plot.getValues() macro function - } - Interpreter.addBatchModeImage(imp); - return null; - } - if (imp != null) { - Window win = imp.getWindow(); - if (win instanceof PlotWindow && win.isVisible()) { - updateImage(); // show in existing window - return (PlotWindow)win; - } else - setImagePlus(null); - } - PlotWindow pw = new PlotWindow(this); //note: this may set imp to null if pw has listValues and autoClose are set - if (IJ.isMacro() && imp!=null) // wait for plot to be displayed - IJ.selectWindow(imp.getID()); - return pw; - } - - /** - * Appends the current plot to a virtual stack and resets allPlotObjects - * for next slice - * N. Vischer - */ - public void addToStack() { - if (stack==null) - stack = new PlotVirtualStack(getSize().width,getSize().height); - draw(); - stack.addPlot(this); - IJ.showStatus("addToPlotStack: "+stack.size()); - allPlotObjects.clear(); - } - - /** Alias for addToStack(). */ - public void appendToStack() { - addToStack(); - } - - /** Returns the virtual stack created by addToStack(). */ - public PlotVirtualStack getStack() { - IJ.showStatus(""); - return stack; - } - - /** Draws the plot specified for the first time. Does nothing if the plot has been drawn already. - * Call getProcessor to retrieve the ImageProcessor with it. - * Does no action with respect to the ImagePlus (if any) */ - public void draw() { - //IJ.log("draw(); plotDrawn="+plotDrawn); - if (plotDrawn) return; - getInitialMinAndMax(); - pp.frame.setFont(nonNullFont(pp.frame.getFont(), currentFont)); //make sure we have a number font for calculating the margins - getBlankProcessor(); - drawContents(ip); - } - - /** Freezes or unfreezes the plot. In the frozen state, the plot cannot be resized or updated, - * and the Plot class does no modifications to the ImageProcessor. - * Changes are recorded nevertheless and become effective with setFrozen(false). */ - public void setFrozen(boolean frozen) { - pp.isFrozen = frozen; - if (!pp.isFrozen) { // unfreeze operations ... - if (imp != null && ip != null) { - ImageCanvas ic = imp.getCanvas(); - if (ic instanceof PlotCanvas) { - ((PlotCanvas)ic).resetMagnification(); - imp.setTitle(imp.getTitle()); //update magnification in title - } - Undo.setup(Undo.TRANSFORM, imp); - } - updateImage(); - ImageWindow win = imp == null ? null : imp.getWindow(); - if (win != null) win.updateImage(imp); //show any changes made during the frozen state - } - } - - public boolean isFrozen() { - return pp.isFrozen; - } - - /** Draws the plot again, ignored if the plot has not been drawn before or the plot is frozen. */ - public void update() { - updateImage(); - } - - /** Draws the plot again, ignored if the plot has not been drawn before or the plot is frozen. - * If the ImagePlus exist, updates it and its calibration. */ - public void updateImage() { - if (!plotDrawn || pp.isFrozen) return; - getBlankProcessor(); - drawContents(ip); - if (imp == null || stack != null) return; - adjustCalibration(imp.getCalibration()); - imp.updateAndDraw(); - if (ip != imp.getProcessor()) - imp.setProcessor(ip); - } - - /** Returns the rectangle where the data are plotted. - * This rectangle includes the black outline frame at the top and left, but not at the bottom - * and right (when the frame is plotted with 1 pxl width). - * The image scale is its width or height in pixels divided by the data range in x or y. */ - public Rectangle getDrawingFrame() { - if (frame == null) - getBlankProcessor(); //setup frame if not done yet - return new Rectangle(frame.x, frame.y, frameWidth, frameHeight); - } - - /** Creates a new high-resolution plot by scaling it and displays that plot if showIt is true. - * title may be null, then a default title is used. */ - public ImagePlus makeHighResolution(String title, float scale, boolean antialiasedText, boolean showIt) { - Plot hiresPlot = null; - try { - hiresPlot = (Plot)clone(); //shallow clone, thus arrays&objects are not cloned, but they will be used only now - } catch (Exception e) {return null;} - hiresPlot.ip = null; - hiresPlot.imp = null; - hiresPlot.pp = pp.clone(); - if (!plotDrawn) hiresPlot.getInitialMinAndMax(); - hiresPlot.setScale(scale); - hiresPlot.setAntialiasedText(antialiasedText); - hiresPlot.defaultMinMax = currentMinMax.clone(); - ImageProcessor hiresIp = hiresPlot.getProcessor(); - if (title == null || title.length() == 0) - title = getTitle()+"_HiRes"; - title = WindowManager.makeUniqueName(title); - ImagePlus hiresImp = new ImagePlus(title, hiresIp); - Calibration cal = hiresImp.getCalibration(); - hiresPlot.adjustCalibration(cal); - if (showIt) { - hiresImp.setIgnoreGlobalCalibration(true); - hiresImp.show(); - } - hiresPlot.dispose(); //after drawing, we don't need the plot of the high-resolution image any more - return hiresImp; - } - - /** Releases the ImageProcessor and ImagePlus associated with the plot. - * May help garbage collection because some garbage collectors - * are said to be inefficient with circular references. */ - public void dispose() { - if (imp != null) - imp.setProperty(PROPERTY_KEY, null); - imp = null; - ip = null; - } - - /** Converts pixels to calibrated coordinates. In contrast to the image calibration, also - * works with log axes and inverted x axes */ - public double descaleX(int x) { - if (xMin == xMax) return xMin; - double xv = (x-xBasePxl)/xScale + xMin; - if (logXAxis) xv = Math.pow(10, xv); - return xv; - } - - /** Converts pixels to calibrated coordinates. In contrast to the image calibration, also - * works with log axes */ - public double descaleY(int y) { - if (yMin == yMax) return yMin; - double yv = (yBasePxl-y)/yScale +yMin; - if (logYAxis) yv = Math.pow(10, yv); - return yv; - } - - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log x axis and inverted x axis */ - public double scaleXtoPxl(double x) { - if (xMin == xMax) { - if (x==xMin) return xBasePxl; - else return x>xMin ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; - } - if (logXAxis) - return xBasePxl+(Math.log10(x)-xMin)*xScale; - else - return xBasePxl+(x-xMin)*xScale; - } - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log y axis */ - public double scaleYtoPxl(double y) { - if (yMin == yMax) { - if (y==xMin) return yBasePxl; - else return y>yMin ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; - } - if (logYAxis) - return yBasePxl-(Math.log10(y)-yMin)*yScale; - else - return yBasePxl-(y-yMin)*yScale; - } - - /** Converts calibrated coordinates to integer pixel coordinates. */ - private int scaleX(double x) { - double xPxl = scaleXtoPxl(x); - return pxlToInt(xPxl); - } - - /** Converts calibrated coordinates to integer pixel coordinates. */ - private int scaleY(double y) { - double yPxl = scaleYtoPxl(y); - return pxlToInt(yPxl); - } - - /** Converts a double-precision pixel coordinate value 'v' to integer, - * with overflow handling: Limits are +/-Integer.MAX_VALUE/2. - * This ensures that the difference between two points is in the range - * that can be handled by ImageProcessor.moveTo. - * NaN values are converted to -Integer.MAX_VALUE (negative). - **/ - private int pxlToInt(double v) { - if (Double.isNaN(v)) - return -Integer.MAX_VALUE; - else if (v > -Integer.MAX_VALUE/2 && v < Integer.MAX_VALUE/2) - return (int)Math.round(v); - else - return v > 0 ? Integer.MAX_VALUE/2 : -Integer.MAX_VALUE/2; - } - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log axes and inverted x axes. Returns a large number instead NaN for log x axis and zero or negative x */ - private int scaleXWithOverflow(double x) { - if (!logXAxis || x>0) - return scaleX(x); - else - return xScale > 0 ? -1000000 : 1000000; - } - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log axes and inverted x axes. Returns a large number instead NaN for log y axis and zero or negative y */ - private int scaleYWithOverflow(double y) { - if (!logYAxis || y>0) - return scaleY(y); - else - return yScale > 0 ? 1000000 : -1000000; - } - - /** Scales a value of the original plot for a high-resolution plot. Returns an integer number of pixels >=1 */ - int sc(float length) { - int pixels = (int)(length*scale + 0.5); - if (pixels < 1) pixels = 1; - return pixels; - } - - /** Scales a font of the original plot for a high-resolution plot. */ - Font scFont(Font font) { - float size = font.getSize2D(); - return scale==1 ? font : font.deriveFont(size*scale); - } - - /** Returns whether the plot requires color (not grayscale) */ - boolean isColored() { - for (PlotObject plotObject : allPlotObjects) - if (isColored(plotObject.color) || isColored(plotObject.color2)) - return true; - for (PlotObject plotObject : pp.getAllPlotObjects()) - if (plotObject != null && (isColored(plotObject.color) || isColored(plotObject.color2))) - return true; - return false; - } - - /** Whether a color is non-grayscale, which requires color (not grayscale) for the plot */ - boolean isColored(Color c) { - if (c == null) return false; - return c.getRed() != c.getGreen() || c.getGreen() != c.getBlue(); - } - - /** Draws the plot contents (all PlotObjects and the frame and legend), without axes etc. */ - void drawContents(ImageProcessor ip) { - makeRangeGetSteps(); - ip.setColor(Color.black); - ip.setLineWidth(sc(1)); - float lineWidth = 1; - Color color = Color.black; - Font font = defaultFont; - - // draw all the plot objects in the sequence they were added, except for the one of the constructor - for (PlotObject plotObject : allPlotObjects) - if (!plotObject.hasFlag(PlotObject.CONSTRUCTOR_DATA)) { - //properties lineWidth, Font, Color set for one object remain for the next object unless changed - if (plotObject.lineWidth > 0) - lineWidth = plotObject.lineWidth; - else - plotObject.lineWidth = lineWidth; - if (plotObject.color != null) - color = plotObject.color; - else - plotObject.color = color; - if (plotObject.getFont() != null) - font = plotObject.getFont(); - else - plotObject.setFont(font); - //IJ.log("type="+plotObject.type+" color="+plotObject.color); - drawPlotObject(plotObject, ip); - } - - // draw the line passed with the constructor last, using the settings present when calling 'draw' - if (allPlotObjects.size()>0 && allPlotObjects.get(0).hasFlag(PlotObject.CONSTRUCTOR_DATA)) { - PlotObject mainPlotObject = allPlotObjects.get(0); - if (mainPlotObject.lineWidth == 0) - mainPlotObject.lineWidth = currentLineWidth == 0 ? 1 : currentLineWidth; - lineWidth = mainPlotObject.lineWidth; - if (mainPlotObject.color == null) - mainPlotObject.color = currentColor == null ? Color.black : currentColor; - drawPlotObject(mainPlotObject, ip); - } else { - if (currentLineWidth > 0) lineWidth = currentLineWidth; //linewidth when drawing determines frame linewidth - } - - // finally draw the frame & legend - if (!plotDrawn && pp.frame.lineWidth==DEFAULT_FRAME_LINE_WIDTH) { //when modifying PlotObjects styles later, don't change the frame line width any more - pp.frame.lineWidth = lineWidth; - if (pp.frame.lineWidth == 0) pp.frame.lineWidth = 1; - if (pp.frame.lineWidth > 3) pp.frame.lineWidth = 3; - } - ip.setLineWidth(sc(pp.frame.lineWidth)); - ip.setColor(pp.frame.color); - int x2 = frame.x + frame.width - 1; - int y2 = frame.y + frame.height - 1; - ip.moveTo(frame.x, frame.y); // draw the frame. Can't use ip.drawRect because it is inconsistent for different lineWidths - ip.lineTo(x2, frame.y); - ip.lineTo(x2, y2); - ip.lineTo(frame.x, y2); - ip.lineTo(frame.x, frame.y); - if (pp.legend != null && (pp.legend.flags & LEGEND_POSITION_MASK) != 0) - drawPlotObject(pp.legend, ip); - - plotDrawn = true; - } - - /** Creates the processor if not existing, clears the background and prepares - * it for plotting. Also called by the PlotWindow class to prepare the window. */ - ImageProcessor getBlankProcessor() { - makeMarginValues(); - //IJ.log("Plot.getBlankPr preferredH="+preferredPlotHeight+" pp.h="+pp.height); - if (pp.width <= 0 || pp.height <= 0) { - pp.width = sc(preferredPlotWidth) + leftMargin + rightMargin; - pp.height = sc(preferredPlotHeight) + topMargin + bottomMargin; - } - frameWidth = pp.width - (leftMargin + rightMargin); - frameHeight = pp.height - (topMargin + bottomMargin); - boolean isColored = isColored(); //color, not grayscale required? - if (ip == null || pp.width != ip.getWidth() || pp.height != ip.getHeight() || (isColored != (ip instanceof ColorProcessor))) { - if (isColored) { - ip = new ColorProcessor(pp.width, pp.height); - } else { - ip = new ByteProcessor(pp.width, pp.height); - invertedLut = Prefs.useInvertingLut && !Interpreter.isBatchMode() && IJ.getInstance()!=null; - if (invertedLut) ip.invertLut(); - } - if (imp != null && stack == null) - imp.setProcessor(ip); - } - if (ip instanceof ColorProcessor) - Arrays.fill((int[])(ip.getPixels()), 0xffffff); - else - Arrays.fill((byte[])(ip.getPixels()), invertedLut ? (byte)0 : (byte)0xff); - - ip.setFont(scFont(defaultFont)); - ip.setLineWidth(sc(1)); - ip.setAntialiasedText(pp.antialiasedText); - frame = new Rectangle(leftMargin, topMargin, frameWidth+1, frameHeight+1); - if (pp.frame.color2 != null) { //background color - ip.setColor(pp.frame.color2); - ip.setRoi(frame); - ip.fill(); - ip.resetRoi(); - } - ip.setColor(Color.black); - return ip; - } - - /** Calculates the margin sizes and sets the class variables accordingly */ - void makeMarginValues() { - Font font = nonNullFont(pp.frame.getFont(), currentFont); - float marginScale = 0.1f + 0.9f*font.getSize2D()/12f; - if (marginScale < 0.7f) marginScale = 0.7f; - if (marginScale > 2f) marginScale = 2f; - int addHspace = (int)Tools.getNumberFromList(pp.frame.options, "addhspace="); //user-defined extra space - int addVspace = (int)Tools.getNumberFromList(pp.frame.options, "addvspace="); - leftMargin = sc(LEFT_MARGIN*marginScale + addHspace); - rightMargin = sc(RIGHT_MARGIN*marginScale + addHspace); - topMargin = sc(TOP_MARGIN*marginScale + addVspace); - bottomMargin = sc(BOTTOM_MARGIN*marginScale + 2 + addVspace); - if(pp != null && pp.xLabel != null && pp.xLabel.getFont() != null){ - float numberSize = font.getSize2D(); - float labelSize = pp.xLabel.getFont().getSize2D(); - float extraHeight = 1.5f *(labelSize - numberSize); - if(extraHeight > 0){ - bottomMargin += sc(extraHeight); - leftMargin += sc(extraHeight); - } - } - } - - /** Calculate the actual range, major step interval and set variables for data <-> pixels scaling */ - double[] makeRangeGetSteps() { - steps = new double[2]; - logXAxis = hasFlag(X_LOG_NUMBERS); - logYAxis = hasFlag(Y_LOG_NUMBERS); - - for (int i=0; i MIN_LOG_RATIO || 1./rangeRatio > MIN_LOG_RATIO) || - !(currentMinMax[i] > 10*Float.MIN_VALUE) || !(currentMinMax[i+1] > 10*Float.MIN_VALUE)) - logAxis = false; - } - //for log axes, temporarily work on the logarithm - if (logAxis) { - currentMinMax[i] = Math.log10(currentMinMax[i]); - currentMinMax[i+1] = Math.log10(currentMinMax[i+1]); - } - // calculate grid or major tick interval - if ((i==0 && !simpleXAxis()) || (i==2 && !simpleYAxis())) { - int minGridspacing = i==0 ? MIN_X_GRIDSPACING : MIN_Y_GRIDSPACING; - int frameSize = i==0 ? frameWidth : frameHeight; - double step = Tools.getNumberFromList(pp.frame.options, i==0 ? "xinterval=" : "yinterval="); //user-defined interval - if (!Double.isNaN(step)) { - int nSteps = (int)(Math.floor(currentMinMax[i+1]/step+1e-10) - Math.ceil(currentMinMax[i]/step-1e-10)); - if (nSteps < 1) step = Double.NaN; //user-suppied interval too large, less than two numbers would be shown - if ((i==0 && nSteps*sc(minGridspacing)*0.5 > frameSize) || i!=0 && nSteps*sc(pp.frame.getFont().getSize()) > frameSize) - step = Double.NaN; //user-suppied interval too small, too many numbers would be shown - } - if (Double.isNaN(step)) { //automatic interval - step = Math.abs((currentMinMax[i+1] - currentMinMax[i]) * - Math.max(1.0/maxIntervals, (float)sc(minGridspacing)/frameSize+(maxIntervals>12 ? 0.02 : 0.06))); //the smallest allowable step - step = niceNumber(step); - } - if (logAxis && step < 1) - step = 1; - steps[i/2] = step; - //modify limits to grid or minor ticks if desired - boolean force2grid = hasFlag(i==0 ? X_FORCE2GRID : Y_FORCE2GRID) && !ignoreForce2Grid; - if (force2grid) { - int i1 = (int)Math.floor(Math.min(currentMinMax[i],currentMinMax[i+1])/step+1.e-10); - int i2 = (int)Math.ceil (Math.max(currentMinMax[i],currentMinMax[i+1])/step-1.e-10); - if (currentMinMax[i+1] > currentMinMax[i]) { // care about inverted axes with max= 0.999) { //don't snap on log axis if minor ticks are not full decades - // currentMinMax[i] = stepForSnap * Math.round(currentMinMax[i]/stepForSnap); - // currentMinMax[i+1] = stepForSnap * Math.round(currentMinMax[i+1]/stepForSnap); - // } - } - } - if (i==0) { - xMin = currentMinMax[i]; - xMax = currentMinMax[i+1]; - logXAxis = logAxis; - } else { - yMin = currentMinMax[i]; - yMax = currentMinMax[i+1]; - logYAxis = logAxis; - } - if (logAxis) { - currentMinMax[i] = Math.pow(10, currentMinMax[i]); - currentMinMax[i+1] = Math.pow(10, currentMinMax[i+1]); - } - } - //snapToMinorGrid = false; - ignoreForce2Grid = false; - - // calculate what we need to convert the data to screen pixels - xBasePxl = leftMargin; - yBasePxl = topMargin + frameHeight; - xScale = frameWidth/(xMax-xMin); - if (!(xMax-xMin!=0.0)) //if range==0 (all data the same), or NaN shift zero level so one can see the curve - xBasePxl += sc(10); - yScale = frameHeight/(yMax-yMin); - if (!(yMax-yMin!=0.0)) - yBasePxl -= sc(10); - //IJ.log("x,yScale="+(float)xScale+","+(float)yScale+" xMin,max="+(float)xMin+","+(float)xMax+" yMin.max="+(float)yMin+","+(float)yMax); - - drawAxesTicksGridNumbers(steps); - return steps; - } - - public void redrawGrid(){ - if (ip != null) { - ip.setColor(Color.black); - drawAxesTicksGridNumbers(steps); - ip.setColor(Color.black); - } - } - - /** Gets the initial plot limits (i.e., x&y ranges). For compatibility with previous versions of ImageJ, - * only the first PlotObject (with numeric data) is used to determine the limits. */ - void getInitialMinAndMax() { - int axisRangeFlags = 0; - if (Double.isNaN(defaultMinMax[0])) axisRangeFlags |= X_RANGE; - if (Double.isNaN(defaultMinMax[2])) axisRangeFlags |= Y_RANGE; - if (axisRangeFlags != 0) { - defaultMinMax = getMinAndMax(false, axisRangeFlags); - enlargeRange(defaultMinMax); - } - setLimitsToDefaults(false); //use the range values to start with, but don't draw yet - } - - /** Gets the minimum and maximum values from the first XY_DATA or ARROWS plotObject or all such plotObjects; - * axisRangeFlags determine for which axis to calculate the min&max (X_RANGE for x axis, Y_RANGE for y axis); - * for the other axes the limit is taken from defaultMinMax - * Array elements returned are xMin, xMax, yMin, yMax. Also sets enlargeRange to tell which limits should be enlarged - * beyond the minimum or maximum of the data */ - double[] getMinAndMax(boolean allObjects, int axisRangeFlags) { - boolean invertedXAxis = currentMinMax[1] < currentMinMax[0]; - boolean invertedYAxis = currentMinMax[3] < currentMinMax[2]; - double xSign = invertedXAxis ? -1 : 1; - double ySign = invertedYAxis ? -1 : 1; - double[] allMinMax = new double[]{xSign*Double.MAX_VALUE, -xSign*Double.MAX_VALUE, ySign*Double.MAX_VALUE, -ySign*Double.MAX_VALUE}; - for (int i=0; i>i/2) & 1)==0) //keep default min & max for this axis - allMinMax[i] = defaultMinMax[i]; - enlargeRange = new int[allMinMax.length]; - for (PlotObject plotObject : allPlotObjects) { - if ((plotObject.type == PlotObject.XY_DATA || plotObject.type == PlotObject.ARROWS) && !plotObject.hasFlag(PlotObject.HIDDEN)) { - getMinAndMax(allMinMax, enlargeRange, plotObject, axisRangeFlags); - if (!allObjects) break; - } - } - if ((axisRangeFlags & X_RANGE) != 0) { - String[] xCats = labelsInBraces('x'); // if we have categories at the axis, make some space for this text - if (xCats != null) { - allMinMax[0] = Math.min(allMinMax[0], -0.5); - allMinMax[1] = Math.min(allMinMax[1], xCats.length+0.5); - } - } - if ((axisRangeFlags & Y_RANGE) != 0) { - String[] yCats = labelsInBraces('y'); - if (yCats != null) { - allMinMax[2] = Math.min(allMinMax[2], -0.5); - allMinMax[3] = Math.min(allMinMax[3], yCats.length+0.5); - } - } - if (allMinMax[0]==Double.MAX_VALUE && allMinMax[1]==-Double.MAX_VALUE) { // no x values at all? keep previous - allMinMax[0] = defaultMinMax[0]; - allMinMax[1] = defaultMinMax[1]; - } - if (allMinMax[2]==Double.MAX_VALUE && allMinMax[3]==-Double.MAX_VALUE) { // no y values at all? keep previous - allMinMax[2] = defaultMinMax[2]; - allMinMax[3] = defaultMinMax[3]; - } - return allMinMax; - } - - /** Enlarges the current minimum and maximum ranges to include the data range of the last plotObject added, - * if it is an XY_DATA or ARROWS plotObject. - * Does not set the new limits as default, does not redraw the plot. */ - void fitRangeToLastPlotObject() { - if (allPlotObjects.size() < 1) return; - PlotObject plotObject = allPlotObjects.lastElement(); - if (Double.isNaN(currentMinMax[0]) || Double.isNaN(currentMinMax[2])) { // no range determined yet? - setLimitsToFit(false); - } else { //we have min&max already, just extend the range if necessary - enlargeRange = new int[currentMinMax.length]; - getMinAndMax(currentMinMax, enlargeRange, plotObject, ALL_AXES_RANGE); - enlargeRange(currentMinMax); - } - } - - /** Gets the minimum and maximum values from an XY_DATA or ARROWS plotObject; - * axisRangeFlags determine for which axis (X_RANGE for x axis, Y_RANGE for y axis) - * The minimum modifies allMinAndMax[0] (x), allMinAndMax[2] (y); the maximum modifies [1], [3]. - * If allMinAndMax values are modified, the corresponding enlargeRange array elements are also set */ - void getMinAndMax(double[] allMinAndMax, int[] enlargeRange, PlotObject plotObject, int axisRangeFlags) { - boolean invertedXAxis = currentMinMax[1] < currentMinMax[0]; - boolean invertedYAxis = currentMinMax[3] < currentMinMax[2]; - if (plotObject.type == PlotObject.XY_DATA) { - if ((axisRangeFlags & X_RANGE) != 0) { - int suggestedEnlarge = 0; - if (!(plotObject.shape == LINE || plotObject.shape == FILLED) || plotObject.yEValues != null) - suggestedEnlarge = ALWAYS_ENLARGE; //enlarge to make space at the obrders (we don't try to keep x=0 at the frame border) - getMinAndMax(allMinAndMax, enlargeRange, suggestedEnlarge, 0, plotObject.xValues, plotObject.xEValues, invertedXAxis); - if ((plotObject.shape == BAR || plotObject.shape == SEPARATED_BAR)&& plotObject.xValues.length > 1) { - int n = plotObject.xValues.length; - allMinAndMax[0] -= 0.5 * Math.abs(plotObject.xValues[1] - plotObject.xValues[0]); - allMinAndMax[1] += 0.5 * Math.abs(plotObject.xValues[n - 1] - plotObject.xValues[n - 2]); - } - } - if ((axisRangeFlags & Y_RANGE) != 0) { - int suggestedEnlarge = 0; - if (plotObject.shape==DOT || plotObject.xEValues != null) //these can't be seen if merging with the frame - suggestedEnlarge = ALWAYS_ENLARGE; - else if (!(plotObject.shape == LINE || plotObject.shape == FILLED)) - suggestedEnlarge = USUALLY_ENLARGE; - getMinAndMax(allMinAndMax, enlargeRange, suggestedEnlarge, 2, plotObject.yValues, plotObject.yEValues, invertedYAxis); - if ((plotObject.shape == BAR || plotObject.shape == SEPARATED_BAR) && - (allMinAndMax[2] > 0 && allMinAndMax[3]/allMinAndMax[2] >= 2) && !logYAxis) - allMinAndMax[2] = 0; // for bar plots, y min = 0 unless values differ less than a factor of 2 - } - } else if (plotObject.type == PlotObject.ARROWS) { - if ((axisRangeFlags & X_RANGE) != 0) { - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 0, plotObject.xValues, null, invertedXAxis); - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 0, plotObject.xEValues, null, invertedXAxis); - } - if ((axisRangeFlags & Y_RANGE) != 0) { - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 2, plotObject.yValues, null, invertedYAxis); - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 2, plotObject.yEValues, null, invertedYAxis); - } - } - } - - /** Gets the minimum and maximum values for a dataset (one direction, x or y), - * taking error bars (if not null) into account. - * The minimum modifies allMinAndMax[axisIndex] the maximum modifies allMinAndMax[axisIndex+1]. - * Also cares about whether the range should be enlarged to avoid hiding markers at the borders: - * suggestedEnlarge is 0 for lines or a suggestion for the data type; if the allMinAndMax is - * range is extended, the corresponding enlargeRange item is set accordingly */ - void getMinAndMax(double[] allMinAndMax, int[] enlargeRange, int suggestedEnlarge, - int axisIndex, float[] data, float[] errorBars, boolean invertedAxis) { - int nMinEqual = 0, nMaxEqual = 0; - int minIndex = invertedAxis ? axisIndex+1 : axisIndex; // index of 'min' value in allMinAndMax, enlargeRange - int maxIndex = invertedAxis ? axisIndex : axisIndex+1; - for (int i=0; i0 && i allMinAndMax[maxIndex] && !Double.isInfinite(v1)) { - allMinAndMax[maxIndex] = v2; - nMaxEqual = 1; - enlargeRange[maxIndex] = suggestedEnlarge; - if (suggestedEnlarge == 0 && ((i>0 && i10%) at min or max? Add extra space at borders ('usually', i.e. unless limit is zero) - if (enlargeRange[minIndex] == 0 && nMinEqual > 2 && nMinEqual*10 > data.length) - enlargeRange[minIndex] = USUALLY_ENLARGE; - if (enlargeRange[maxIndex] == 0 && nMaxEqual > 2 && nMaxEqual*10 > data.length) - enlargeRange[maxIndex] = USUALLY_ENLARGE; - //all data at min or max? Always add space to avoid hiding the line behind the frame - if (nMinEqual == data.length) - enlargeRange[minIndex] = ALWAYS_ENLARGE; - if (nMaxEqual == data.length) - enlargeRange[maxIndex] = ALWAYS_ENLARGE; - //same min or max as for current data set found already previously, but not asking yet for added space at borders? - if (nMinEqual>0 && enlargeRange[minIndex]0 && enlargeRange[maxIndex] frame.x && x < frame.x + frame.width; - boolean insideY = y > frame.y && y < frame.y + frame.height; - if (!insideX && !insideY) { - insideX = true; - insideY = true; - x = frame.x + frame.width / 2; - y = frame.y + frame.height / 2; - } - int leftPart = x - frame.x; - int rightPart = frame.x + frame.width - x; - int highPart = y - frame.y; - int lowPart = frame.y + frame.height - y; - - if (insideX) { - currentMinMax[0] = descaleX((int) (x - leftPart / zoomFactor)); - currentMinMax[1] = descaleX((int) (x + rightPart / zoomFactor)); - } - if (insideY) { - currentMinMax[2] = descaleY((int) (y + lowPart / zoomFactor)); - currentMinMax[3] = descaleY((int) (y - highPart / zoomFactor)); - } - updateImage(); - if (wasLogX != logXAxis ){//log-lin was automatically changed - int changedX = (int) scaleXtoPxl(plotX); - int left = changedX - leftPart; - int right = changedX + rightPart; - currentMinMax[0] = descaleX(left); - currentMinMax[1] = descaleX(right); - updateImage(); - } - if (wasLogY != logYAxis){//log-lin was automatically changed - int changedY = (int) scaleYtoPxl(plotY); - int bottom = changedY + lowPart; - int top = changedY + highPart; - currentMinMax[2] = descaleY(bottom); - currentMinMax[3] = descaleY(top); - updateImage(); - } - } - - /** Moves the plot range by a given number of pixels and updates the image */ - void scroll(int dx, int dy) { - if (logXAxis) { - currentMinMax[0] /= Math.pow(10, dx/xScale); - currentMinMax[1] /= Math.pow(10, dx/xScale); - } else { - currentMinMax[0] -= dx/xScale; - currentMinMax[1] -= dx/xScale; - } - if (logYAxis) { - currentMinMax[2] *= Math.pow(10, dy/yScale); - currentMinMax[3] *= Math.pow(10, dy/yScale); - } else { - currentMinMax[2] += dy/yScale; - currentMinMax[3] += dy/yScale; - } - updateImage(); - } - - /** Whether to draw simple axes without ticks, grid and numbers only for min, max*/ - private boolean simpleXAxis() { - return !hasFlag(X_TICKS | X_MINOR_TICKS | X_LOG_TICKS | X_GRID | X_NUMBERS); - } - - private boolean simpleYAxis() { - return !hasFlag(Y_TICKS | Y_MINOR_TICKS | Y_LOG_TICKS | Y_GRID | Y_NUMBERS); - } - - /** Draws ticks, grid and axis label for each tick/grid line. - * The grid or major tick spacing in each direction is given by steps */ - void drawAxesTicksGridNumbers(double[] steps) { - - if (ip==null) - return; - String[] xCats = labelsInBraces('x'); // create categories for the axes (if any) - String[] yCats = labelsInBraces('y'); - String multiplySymbol = getMultiplySymbol(); // for scientific notation - Font scFont = scFont(pp.frame.getFont()); - Font scFontMedium = scFont.deriveFont(scFont.getSize2D()*10f/12f); //for axis numbers if full size does not fit - Font scFontSmall = scFont.deriveFont(scFont.getSize2D()*9f/12f); //for subscripts - ip.setFont(scFont); - FontMetrics fm = ip.getFontMetrics(); - int fontAscent = fm.getAscent(); - ip.setJustification(LEFT); - // --- A l o n g X A x i s - int yOfXAxisNumbers = topMargin + frameHeight + fm.getHeight()*5/4 + sc(2); - if (hasFlag(X_NUMBERS | (logXAxis ? (X_TICKS | X_MINOR_TICKS) : X_LOG_TICKS) + X_GRID)) { - Font baseFont = scFont; - boolean majorTicks = logXAxis ? hasFlag(X_LOG_TICKS) : hasFlag(X_TICKS); - boolean minorTicks = hasFlag(X_MINOR_TICKS); - minorTicks = minorTicks && (xCats == null); - double step = steps[0]; - int i1 = (int)Math.ceil (Math.min(xMin, xMax)/step-1.e-10); - int i2 = (int)Math.floor(Math.max(xMin, xMax)/step+1.e-10); - int suggestedDigits = (int)Tools.getNumberFromList(pp.frame.options, "xdecimals="); //is not given, NaN cast to 0 - int digits = getDigits(xMin, xMax, step, 7, suggestedDigits); - int y1 = topMargin; - int y2 = topMargin + frameHeight; - if (xMin==xMax) { - if (hasFlag(X_NUMBERS)) { - String s = IJ.d2s(xMin,getDigits(xMin, 0.001*xMin, 5, suggestedDigits)); - int y = yBasePxl; - ip.drawString(s, xBasePxl-ip.getStringWidth(s)/2, yOfXAxisNumbers); - } - } else { - if (hasFlag(X_NUMBERS)) { - int w1 = ip.getStringWidth(IJ.d2s(currentMinMax[0], logXAxis ? -1 : digits)); - int w2 = ip.getStringWidth(IJ.d2s(currentMinMax[1], logXAxis ? -1 : digits)); - int wMax = Math.max(w1,w2); - if (wMax > Math.abs(step*xScale)-sc(8)) { - baseFont = scFontMedium; //small font if there is not enough space for the numbers - ip.setFont(baseFont); - } - } - - for (int i=0; i<=(i2-i1); i++) { - double v = (i+i1)*step; - int x = (int)Math.round((v - xMin)*xScale) + leftMargin; - - if (xCats!= null) { - int index = (int) v; - double remainder = Math.abs(v - Math.round(v)); - if(index >= 0 && index < xCats.length && remainder < 1e-9){ - String s = xCats[index]; - String[] parts = s.split("\n"); - int w = 0; - for(int jj = 0; jj < parts.length; jj++) - w = Math.max(w, ip.getStringWidth(parts[jj])); - - ip.drawString(s, x-w/2, yOfXAxisNumbers); - //ip.drawString(s, x-ip.getStringWidth(s)/2, yOfXAxisNumbers); - } - continue; - } - - if (hasFlag(X_GRID)) { - ip.setColor(gridColor); - ip.drawLine(x, y1, x, y2); - ip.setColor(Color.black); - } - if (majorTicks) { - ip.drawLine(x, y1, x, y1+sc(tickLength)); - ip.drawLine(x, y2, x, y2-sc(tickLength)); - } - if (hasFlag(X_NUMBERS)) { - if (logXAxis || digits<0) { - drawExpString(logXAxis ? Math.pow(10,v) : v, logXAxis ? -1 : -digits, - x, yOfXAxisNumbers-fontAscent/2, CENTER, fontAscent, baseFont, scFontSmall, multiplySymbol); - } else { - String s = IJ.d2s(v,digits); - ip.drawString(s, x-ip.getStringWidth(s)/2, yOfXAxisNumbers); - } - } - } - boolean haveMinorLogNumbers = i2-i1 < 2; //nunbers on log minor ticks only if < 2 decades - if (minorTicks && (!logXAxis || step > 1.1)) { //'standard' log minor ticks only for full decades - double mstep = niceNumber(step*0.19); //non-log: 4 or 5 minor ticks per major tick - double minorPerMajor = step/mstep; - if (Math.abs(minorPerMajor-Math.round(minorPerMajor)) > 1e-10) //major steps are not an integer multiple of minor steps? (e.g. user step 90 deg) - mstep = step/4; - if (logXAxis && mstep < 1) mstep = 1; - i1 = (int)Math.ceil (Math.min(xMin,xMax)/mstep-1.e-10); - i2 = (int)Math.floor(Math.max(xMin,xMax)/mstep+1.e-10); - for (int i=i1; i<=i2; i++) { - double v = i*mstep; - int x = (int)Math.round((v - xMin)*xScale) + leftMargin; - ip.drawLine(x, y1, x, y1+sc(minorTickLength)); - ip.drawLine(x, y2, x, y2-sc(minorTickLength)); - } - } else if (logXAxis && majorTicks && Math.abs(xScale)>sc(MIN_X_GRIDSPACING)) { //minor ticks for log - int minorNumberLimit = haveMinorLogNumbers ? (int)(0.12*Math.abs(xScale)/(fm.charWidth('0')+sc(2))) : 0; //more numbers on minor ticks when zoomed in - i1 = (int)Math.floor(Math.min(xMin,xMax)-1.e-10); - i2 = (int)Math.ceil (Math.max(xMin,xMax)+1.e-10); - for (int i=i1; i<=i2; i++) { - for (int m=2; m<10; m++) { - double v = i+Math.log10(m); - if (v > Math.min(xMin,xMax) && v < Math.max(xMin,xMax)) { - int x = (int)Math.round((v - xMin)*xScale) + leftMargin; - ip.drawLine(x, y1, x, y1+sc(minorTickLength)); - ip.drawLine(x, y2, x, y2-sc(minorTickLength)); - if (m<=minorNumberLimit) - drawExpString(Math.pow(10,v), 0, x, yOfXAxisNumbers-fontAscent/2, CENTER, - fontAscent, baseFont, scFontSmall, multiplySymbol); - } - } - } - } - } - } - // --- A l o n g Y A x i s - ip.setFont(scFont); - int maxNumWidth = 0; - int xNumberRight = leftMargin-sc(2)-ip.getStringWidth("0")/2; - Rectangle rect = ip.getStringBounds("0169"); - int yNumberOffset = -rect.y-rect.height/2; - if (hasFlag(Y_NUMBERS | (logYAxis ? (Y_TICKS | Y_MINOR_TICKS) : Y_LOG_TICKS) + Y_GRID)) { - ip.setJustification(RIGHT); - Font baseFont = scFont; - boolean majorTicks = logYAxis ? hasFlag(Y_LOG_TICKS) : hasFlag(Y_TICKS); - boolean minorTicks = logYAxis ? hasFlag(Y_LOG_TICKS) : hasFlag(Y_MINOR_TICKS); - minorTicks = minorTicks && (yCats == null); - double step = steps[1]; - int i1 = (int)Math.ceil (Math.min(yMin, yMax)/step-1.e-10); - int i2 = (int)Math.floor(Math.max(yMin, yMax)/step+1.e-10); - int suggestedDigits = (int)Tools.getNumberFromList(pp.frame.options, "ydecimals="); //is not given, NaN cast to 0 - int digits = getDigits(yMin, yMax, step, 5, suggestedDigits); - int x1 = leftMargin; - int x2 = leftMargin + frameWidth; - if (yMin==yMax) { - if (hasFlag(Y_NUMBERS)) { - String s = IJ.d2s(yMin,getDigits(yMin, 0.001*yMin, 5, suggestedDigits)); - maxNumWidth = ip.getStringWidth(s); - int y = yBasePxl; - ip.drawString(s, xNumberRight, y+fontAscent/2+sc(1)); - } - } else { - int digitsForWidth = logYAxis ? -1 : digits; - if (digitsForWidth < 0) { - digitsForWidth--; //"1.0*10^5" etc. needs more space than 1.0*5, simulate by adding one decimal - xNumberRight += sc(1)+ip.getStringWidth("0")/4; - } - String str1 = IJ.d2s(currentMinMax[2], digitsForWidth); - String str2 = IJ.d2s(currentMinMax[3], digitsForWidth); - if (digitsForWidth < 0) { - str1 = str1.replaceFirst("E",multiplySymbol); - str2 = str2.replaceFirst("E",multiplySymbol); - } - int w1 = ip.getStringWidth(str1); - int w2 = ip.getStringWidth(str2); - int wMax = Math.max(w1,w2); - if (hasFlag(Y_NUMBERS)) { - if (wMax > xNumberRight - sc(4) - (pp.yLabel.label.length()>0 ? fm.getHeight() : 0)) { - baseFont = scFontMedium; //small font if there is not enough space for the numbers - ip.setFont(baseFont); - } - } - //IJ.log(IJ.d2s(currentMinMax[2],digits)+": w="+w1+"; "+IJ.d2s(currentMinMax[3],digits)+": w="+w2+baseFont+" Space="+(leftMargin-sc(4+5)-fm.getHeight())); - for (int i=i1; i<=i2; i++) { - double v = step==0 ? yMin : i*step; - int y = topMargin + frameHeight - (int)Math.round((v - yMin)*yScale); - - if (yCats != null){ - int index = (int) v; - double remainder = Math.abs(v - Math.round(v)); - if(index >= 0 && index < yCats.length && remainder < 1e-9){ - String s = yCats[index]; - int multiLineOffset = 0; // multi-line cat labels - for(int jj = 0; jj < s.length(); jj++) - if(s.charAt(jj) == '\n') - multiLineOffset -= rect.height/2; - - ip.drawString(s, xNumberRight, y+yNumberOffset+ multiLineOffset); - } - continue; - } - - if (hasFlag(Y_GRID)) { - ip.setColor(gridColor); - ip.drawLine(x1, y, x2, y); - ip.setColor(Color.black); - } - if (majorTicks) { - ip.drawLine(x1, y, x1+sc(tickLength), y); - ip.drawLine(x2, y, x2-sc(tickLength), y); - } - if (hasFlag(Y_NUMBERS)) { - int w = 0; - if (logYAxis || digits<0) { - w = drawExpString(logYAxis ? Math.pow(10,v) : v, logYAxis ? -1 : -digits, - xNumberRight, y, RIGHT, fontAscent, baseFont, scFontSmall, multiplySymbol); - } else { - String s = IJ.d2s(v,digits); - w = ip.getStringWidth(s); - ip.drawString(s, xNumberRight, y+yNumberOffset); - } - if (w > maxNumWidth) maxNumWidth = w; - } - } - boolean haveMinorLogNumbers = i2-i1 < 2; //numbers on log minor ticks only if < 2 decades - if (minorTicks && (!logYAxis || step > 1.1)) { //'standard' log minor ticks only for full decades - double mstep = niceNumber(step*0.19); //non-log: 4 or 5 minor ticks per major tick - double minorPerMajor = step/mstep; - if (Math.abs(minorPerMajor-Math.round(minorPerMajor)) > 1e-10) //major steps are not an integer multiple of minor steps? (e.g. user step 90 deg) - mstep = step/4; - if (logYAxis && step < 1) mstep = 1; - i1 = (int)Math.ceil (Math.min(yMin,yMax)/mstep-1.e-10); - i2 = (int)Math.floor(Math.max(yMin,yMax)/mstep+1.e-10); - for (int i=i1; i<=i2; i++) { - double v = i*mstep; - int y = topMargin + frameHeight - (int)Math.round((v - yMin)*yScale); - ip.drawLine(x1, y, x1+sc(minorTickLength), y); - ip.drawLine(x2, y, x2-sc(minorTickLength), y); - } - } - if (logYAxis && majorTicks && Math.abs(yScale)>sc(MIN_X_GRIDSPACING)) { //minor ticks for log within the decade - int minorNumberLimit = haveMinorLogNumbers ? (int)(0.4*Math.abs(yScale)/fm.getHeight()) : 0; //more numbers on minor ticks when zoomed in - i1 = (int)Math.floor(Math.min(yMin,yMax)-1.e-10); - i2 = (int)Math.ceil(Math.max(yMin,yMax)+1.e-10); - for (int i=i1; i<=i2; i++) { - for (int m=2; m<10; m++) { - double v = i+Math.log10(m); - if (v > Math.min(yMin,yMax) && v < Math.max(yMin,yMax)) { - int y = topMargin + frameHeight - (int)Math.round((v - yMin)*yScale); - ip.drawLine(x1, y, x1+sc(minorTickLength), y); - ip.drawLine(x2, y, x2-sc(minorTickLength), y); - if (m<=minorNumberLimit) { - int w = drawExpString(Math.pow(10,v), 0, xNumberRight, y, RIGHT, - fontAscent, baseFont, scFontSmall, multiplySymbol); - if (w > maxNumWidth) maxNumWidth = w; - } - } - } - } - } - } - } - // --- Write min&max of range if simple style without any axis format flags - ip.setFont(scFont); - ip.setJustification(LEFT); - String xLabelToDraw = pp.xLabel.label; - String yLabelToDraw = pp.yLabel.label; - if (simpleYAxis()) { // y-axis min&max - int digits = getDigits(yMin, yMax, 0.001*(yMax-yMin), 6, 0); - String s = IJ.d2s(yMax, digits); - int sw = ip.getStringWidth(s); - if ((sw+sc(4)) > leftMargin) - ip.drawString(s, sc(4), topMargin-sc(4)); - else - ip.drawString(s, leftMargin-ip.getStringWidth(s)-sc(4), topMargin+10); - s = IJ.d2s(yMin, digits); - sw = ip.getStringWidth(s); - if ((sw+4)>leftMargin) - ip.drawString(s, sc(4), topMargin+frame.height); - else - ip.drawString(s, leftMargin-ip.getStringWidth(s)-sc(4), topMargin+frame.height); - if (logYAxis) yLabelToDraw += " (LOG)"; - } - int y = yOfXAxisNumbers; - if (simpleXAxis()) { // x-axis min&max - int digits = getDigits(xMin, xMax, 0.001*(xMax-xMin), 7, 0); - ip.drawString(IJ.d2s(xMin,digits), leftMargin, y); - String s = IJ.d2s(xMax,digits); - ip.drawString(s, leftMargin + frame.width-ip.getStringWidth(s)+6, y); - y -= fm.getHeight(); - if (logXAxis) xLabelToDraw += " (LOG)"; - } else - y += sc(1); - // --- Write x and y axis text labels - if (xCats == null) { - ip.setFont(pp.xLabel.getFont() == null ? scFont : scFont(pp.xLabel.getFont())); - ImageProcessor xLabel = stringToPixels(xLabelToDraw); - if(xLabel != null){ - int xpos = leftMargin+(frame.width-xLabel.getWidth())/2; - int ypos = y + scFont.getSize()/3;//topMargin + frame.height + bottomMargin-xLabel.getHeight(); - ip.insert(xLabel, xpos, ypos); - } - } - if (yCats == null) { - ip.setFont(pp.yLabel.getFont() == null ? scFont : scFont(pp.yLabel.getFont())); - ImageProcessor yLabel = stringToPixels(yLabelToDraw); - if(yLabel != null){ - yLabel = yLabel.rotateLeft(); - int xRightOfYLabel = xNumberRight - maxNumWidth - sc(2); - int xpos = xRightOfYLabel - yLabel.getWidth() - sc(2); - int ypos = topMargin + (frame.height -yLabel.getHeight())/2; - ip.insert(yLabel, xpos, ypos); - } - } - } - - /** Returns the array of categories from an axis label in the form {cat1,cat2,cat3}, or null if not this form - * @param labelCode can be 'x' or 'y', for the x or y axis label*/ - String[] labelsInBraces(char labelCode) { - String s = getLabel(labelCode); - if (s.startsWith("{") && s.endsWith("}")) { - String inBraces = s.substring(1, s.length() - 1); - String[] catLabels = inBraces.split(","); - return catLabels; - } else { - return null; - } - } - - /** Returns the smallest "nice" number >= v. "Nice" numbers are .. 0.5, 1, 2, 5, 10, 20 ... */ - double niceNumber(double v) { - double base = Math.pow(10,Math.floor(Math.log10(v)-1.e-6)); - if (v > 5.0000001*base) return 10*base; - else if (v > 2.0000001*base) return 5*base; - else return 2*base; - } - - /** draw something like 1.2 10^-9; returns the width of the string drawn. - * 'Digits' should be >=0 for drawing the mantissa (=1.38 in this example), negative to draw only 10^exponent - * Currently only supports center justification and right justification (y of center line) - * Fonts baseFont, smallFont should be scaled already - * Returns the width of the String */ - int drawExpString(double value, int digits, int x, int y, int justification, - int fontAscent, Font baseFont, Font smallFont, String multiplySymbol) { - String base = "10"; - String exponent = null; - String s = IJ.d2s(value, digits<=0 ? -1 : -digits); - if (Tools.parseDouble(s) == 0) s = "0"; //don't write 0 as 0*10^0 - int ePos = s.indexOf('E'); - if (ePos < 0) - base = s; //can't have exponential format, e.g. NaN - else { - if (digits>=0) { - base = s.substring(0,ePos); - if (digits == 0) - base = Integer.toString((int)Math.round(Tools.parseDouble(base))); - base += multiplySymbol+"10"; - } - exponent = s.substring(ePos+1); - } - //IJ.log(s+" -> "+base+"^"+exponent+" maxAsc="+fontAscent+" font="+baseFont); - ip.setJustification(RIGHT); - int width = ip.getStringWidth(base); - if (exponent != null) { - ip.setFont(smallFont); - int wExponent = ip.getStringWidth(exponent); - width += wExponent; - if (justification == CENTER) x += width/2; - ip.drawString(exponent, x, y+fontAscent*3/10); - x -= wExponent; - ip.setFont(baseFont); - } - ip.drawString(base, x, y+fontAscent*7/10); - return width; - } - - /** Returns the user-supplied (via setOptions) or default multiplication symbol (middot) */ - String getMultiplySymbol() { - String multiplySymbol = Tools.getStringFromList(pp.frame.options, "msymbol="); - if (multiplySymbol==null) - multiplySymbol = Tools.getStringFromList(pp.frame.options, "multiplysymbol="); - return multiplySymbol != null ? multiplySymbol : MULTIPLY_SYMBOL; - } - - //Returns a pixelMap containting labelStr. - //Uses font of current ImageProcessor. - //Returns null for empty or blank-only strings - //Supports !!subscript!! and ^^superscript^^ - ByteProcessor stringToPixels(String labelStr) { - Font bigFont = ip.getFont(); - Rectangle rect = ip.getStringBounds(labelStr); - int ww = rect.width * 2; - int hh = rect.height * 3;//enough space, will be cropped later - int y0 = rect.height * 2;//base line - if (ww <= 0 || hh <= 0) { - return null; - } - ByteProcessor box = new ByteProcessor(ww, hh); - box.setColor(Color.WHITE); - //box.setColor(Color.LIGHT_GRAY); //make box visible for test - box.fill(); - box.setColor(Color.black); - box.setAntialiasedText(pp.antialiasedText); - if (invertedLut) { - box.invertLut(); - } - box.setFont(bigFont); - - FontMetrics fm = box.getFontMetrics(); - int ascent = fm.getAscent(); - int offSub = ascent / 6; - int offSuper = -ascent / 2; - Font smallFont = bigFont.deriveFont((float) (bigFont.getSize() * 0.7)); - - Rectangle bigBounds = box.getStringBounds(labelStr); - boolean doParse = (labelStr.indexOf("^^") >= 0 || labelStr.indexOf("!!") >= 0); - doParse = doParse && (labelStr.indexOf("^^^") < 0 && labelStr.indexOf("!!!") < 0); - if (!doParse) { - box.drawString(labelStr, 0, y0); - Rectangle cropRect = new Rectangle(bigBounds); - cropRect.y += y0; - box.setRoi(cropRect); - ImageProcessor boxI = box.crop(); - box = boxI.convertToByteProcessor(); - return box; - } - - if (labelStr.endsWith("^^") || labelStr.endsWith("!!")) { - labelStr = labelStr.substring(0, labelStr.length() - 2); - } - if (labelStr.startsWith("^^") || labelStr.startsWith("!!")) { - labelStr = " " + labelStr; - } - - box.setFont(smallFont); - Rectangle smallBounds = box.getStringBounds(labelStr); - box.setFont(bigFont); - int upperBound = y0 + smallBounds.y + offSuper; - int lowerBound = y0 + smallBounds.y + smallBounds.height + offSub; - - int h = fm.getHeight(); - int len = labelStr.length(); - int[] tags = new int[len]; - int nTags = 0; - - for (int jj = 0; jj < len - 2; jj++) {//get positions where font size changes - if (labelStr.substring(jj, jj + 2).equals("^^")) { - tags[nTags++] = jj; - } - if (labelStr.substring(jj, jj + 2).equals("!!")) { - tags[nTags++] = -jj; - } - } - tags[nTags++] = len; - tags = Arrays.copyOf(tags, nTags); - - int leftIndex = 0; - int xRight = 0; - int y2 = y0; - - boolean subscript = labelStr.startsWith("!!"); - for (int pp = 0; pp < tags.length; pp++) {//draw all text fragments - int rightIndex = tags[pp]; - rightIndex = Math.abs(rightIndex); - String part = labelStr.substring(leftIndex, rightIndex); - boolean small = pp % 2 == 1;//toggle odd/even - if (small) { - box.setFont(smallFont); - if (subscript) { - y2 = y0 + offSub; - } else {//superscript: - y2 = y0 + offSuper; - } - } else { - box.setFont(bigFont); - y2 = y0; - } - xRight++; - int partWidth = box.getStringWidth(part); - box.drawString(part, xRight, y2); - leftIndex = rightIndex + 2; - subscript = tags[pp] < 0;//negative positions = subscript - xRight += partWidth; - } - xRight += h / 4; - Rectangle cropRect = new Rectangle(0, upperBound, xRight, lowerBound - upperBound); - box.setRoi(cropRect); - ImageProcessor boxI = box.crop(); - box = boxI.convertToByteProcessor(); - return box; - } - - /** Returns the number of digits to display the number n with resolution 'resolution'; - * (if n is integer and small enough to display without scientific notation, - * no decimals are needed, irrespective of 'resolution') - * Scientific notation is used for more than 'maxDigits' (must be >=3), and indicated - * by a negative return value, or if suggestedDigits is negative - * Returns 'suggestedDigits' if not 0 and compatible with the resolution; negative values of - * 'suggestedDigits' switch to scientific notation. */ - static int getDigits(double n, double resolution, int maxDigits, int suggestedDigits) { - if (n==Math.round(n) && Math.abs(n) < Math.pow(10,maxDigits-1)-1) //integers and not too big - return suggestedDigits; - else - return getDigits2(n, resolution, maxDigits, suggestedDigits); - } - - /** Number of digits to display the range between n1 and n2 with resolution 'resolution'; - * Scientific notation is used for more than 'maxDigits' (must be >=3), and indicated - * by a negative return value - * Returns 'suggestedDigits' if not 0 and compatible with the resolution; negative values of - * 'suggestedDigits' switch to sceintific notation. */ - static int getDigits(double n1, double n2, double resolution, int maxDigits, int suggestedDigits) { - if (n1==0 && n2==0) return suggestedDigits; - return getDigits2(Math.max(Math.abs(n1),Math.abs(n2)), resolution, maxDigits, suggestedDigits); - } - - static int getDigits2(double n, double resolution, int maxDigits, int suggestedDigits) { - if (Double.isNaN(n) || Double.isInfinite(n)) - return 0; //no scientific notation - int log10ofN = (int)Math.floor(Math.log10(Math.abs(n))+1e-7); - int digits = resolution != 0 ? - -(int)Math.floor(Math.log10(Math.abs(resolution))+1e-7) : - Math.max(0, -log10ofN+maxDigits-2); - int sciDigits = -Math.max((log10ofN+digits),1); - //IJ.log("n="+(float)n+"digitsRaw="+digits+" log10ofN="+log10ofN+" sciDigits="+sciDigits); - if ((digits < -2 && log10ofN >= maxDigits) || suggestedDigits < 0) - digits = sciDigits; //scientific notation for large numbers or if desired via suggestedDigits (plot.setOptions) - else if (digits < 0) - digits = 0; - else if (digits > maxDigits-1 && log10ofN < -2) - digits = sciDigits; // scientific notation for small numbers - return digits < 0 ? Math.min(sciDigits, suggestedDigits) : Math.max(digits, suggestedDigits); - } - - static boolean isInteger(double n) { - return n==Math.round(n); - } - - private void drawPlotObject(PlotObject plotObject, ImageProcessor ip) { - //IJ.log("DRAWING type="+plotObject.type+" lineWidth="+plotObject.lineWidth+" shape="+plotObject.shape); - if (plotObject.hasFlag(PlotObject.HIDDEN)) return; - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - int type = plotObject.type; - switch (type) { - case PlotObject.XY_DATA: - ip.setClipRect(frame); - int nPoints = Math.min(plotObject.xValues.length, plotObject.yValues.length); - - if (plotObject.shape==BAR || plotObject.shape==SEPARATED_BAR) - drawBarChart(plotObject); // (separated) bars - - if (plotObject.shape == FILLED) { // filling below line - ip.setColor(plotObject.color2 != null ? plotObject.color2 : plotObject.color); - drawFloatPolyLineFilled(ip, plotObject.xValues, plotObject.yValues, nPoints); - } - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - - if (plotObject.yEValues != null) // error bars in front of bars and fill area below the line, but behind lines and marker symbols - drawVerticalErrorBars(plotObject.xValues, plotObject.yValues, plotObject.yEValues); - if (plotObject.xEValues != null) - drawHorizontalErrorBars(plotObject.xValues, plotObject.yValues, plotObject.xEValues); - - if (plotObject.hasFilledMarker()) { // fill markers with secondary color - int markSize = plotObject.getMarkerSize(); - ip.setColor(plotObject.color2); - ip.setLineWidth(1); - for (int i=0; i0) && (!logYAxis || plotObject.yValues[i]>0) - && !Double.isNaN(plotObject.xValues[i]) && !Double.isNaN(plotObject.yValues[i])) - fillShape(plotObject.shape, scaleX(plotObject.xValues[i]), scaleY(plotObject.yValues[i]), markSize); - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - } - if (plotObject.hasCurve()) { // draw the lines between the points - if (plotObject.shape == CONNECTED_CIRCLES) - ip.setColor(plotObject.color2 == null ? Color.black : plotObject.color2); - drawFloatPolyline(ip, plotObject.xValues, plotObject.yValues, nPoints); - ip.setColor(plotObject.color); - } - if (plotObject.hasMarker()) { // draw the marker symbols - int markSize = plotObject.getMarkerSize(); - ip.setColor(plotObject.color); - Font saveFont = ip.getFont(); - for (int i=0; i0) && (!logYAxis || plotObject.yValues[i]>0) - && !Double.isNaN(plotObject.xValues[i]) && !Double.isNaN(plotObject.yValues[i])) - drawShape(plotObject, scaleX(plotObject.xValues[i]), scaleY(plotObject.yValues[i]), plotObject.shape, markSize, i); - } - if (plotObject.shape==CUSTOM) - ip.setFont(saveFont); - } - ip.setClipRect(null); - break; - case PlotObject.ARROWS: - ip.setClipRect(frame); - for (int i=0; i sc(MAX_ARROWHEAD_LENGTH)) arrowHeadLength = sc(MAX_ARROWHEAD_LENGTH); - if (arrowHeadLength < sc(MIN_ARROWHEAD_LENGTH)) arrowHeadLength = sc(MIN_ARROWHEAD_LENGTH); - drawArrow(xt1, yt1, xt2, yt2, arrowHeadLength); - } - } - ip.setClipRect(null); - break; - - case PlotObject.SHAPES: - int iBoxWidth = 20; - ip.setClipRect(frame); - String shType = plotObject.shapeType.toLowerCase(); - if (shType.contains("rectangles")) { - int nShapes = plotObject.shapeData.size(); - - for (int i = 0; i < nShapes; i++) { - float[] corners = (float[])(plotObject.shapeData.get(i)); - int x1 = scaleX(corners[0]); - int y1 = scaleY(corners[1]); - int x2 = scaleX(corners[2]); - int y2 = scaleY(corners[3]); - - ip.setLineWidth(sc(plotObject.lineWidth)); - int left = Math.min(x1, x2); - int right = Math.max(x1, x2); - int top = Math.min(y1, y2); - int bottom = Math.max(y1, y2); - - Rectangle r1 = new Rectangle(left, top, right-left, bottom - top); - Rectangle cBox = frame.intersection(r1); - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - ip.fillRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setColor(plotObject.color); - ip.drawRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setClipRect(null); - break; - } - if (shType.equals("redraw_grid")) { - ip.setLineWidth(sc(1)); - redrawGrid(); - ip.setClipRect(null); - break; - } - if (shType.contains("boxes")) { - - String[] parts = Tools.split(shType); - for (int jj = 0; jj < parts.length; jj++) { - String[] pairs = parts[jj].split("="); - if ((pairs.length == 2) && pairs[0].equals("width")) { - iBoxWidth = Integer.parseInt(pairs[1]); - } - } - boolean horizontal = shType.contains("boxesx"); - int nShapes = plotObject.shapeData.size(); - int halfWidth = Math.round(sc(iBoxWidth / 2)); - for (int i = 0; i < nShapes; i++) { - - float[] coords = (float[])(plotObject.shapeData.get(i)); - - if (!horizontal) { - - int x = scaleX(coords[0]); - int y1 = scaleY(coords[1]); - int y2 = scaleY(coords[2]); - int y3 = scaleY(coords[3]); - int y4 = scaleY(coords[4]); - int y5 = scaleY(coords[5]); - ip.setLineWidth(sc(plotObject.lineWidth)); - - Rectangle r1 = new Rectangle(x - halfWidth, y4, halfWidth * 2, y2 - y4); - Rectangle cBox = frame.intersection(r1); - if (y1 != y2 || y4 != y5)//otherwise omit whiskers - { - ip.drawLine(x, y1, x, y5);//whiskers - } - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - ip.fillRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setColor(plotObject.color); - ip.drawRect(cBox.x, cBox.y, cBox.width, cBox.height); - ip.setClipRect(frame); - ip.drawLine(x - halfWidth, y3, x + halfWidth - 1, y3); - } - - if (horizontal) { - - int y = scaleY(coords[0]); - int x1 = scaleX(coords[1]); - int x2 = scaleX(coords[2]); - int x3 = scaleX(coords[3]); - int x4 = scaleX(coords[4]); - int x5 = scaleX(coords[5]); - ip.setLineWidth(sc(plotObject.lineWidth)); - if(x1 !=x2 || x4 != x5)//otherwise omit whiskers - ip.drawLine(x1, y, x5, y);//whiskers - Rectangle r1 = new Rectangle(x2, y - halfWidth, x4 - x2, halfWidth * 2); - Rectangle cBox = frame.intersection(r1); - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - ip.fillRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setColor(plotObject.color); - ip.drawRect(cBox.x, cBox.y, cBox.width, cBox.height); - ip.setClipRect(frame); - ip.drawLine(x3, y - halfWidth, x3, y + halfWidth - 1); - } - } - ip.setClipRect(null); - break; - } - case PlotObject.LINE: - if (Double.isNaN(plotObject.x) || Double.isNaN(plotObject.y)) break; - ip.setClipRect(frame); - ip.drawLine(scaleX(plotObject.x), scaleY(plotObject.y), scaleX(plotObject.xEnd), scaleY(plotObject.yEnd)); - ip.setClipRect(null); - break; - case PlotObject.NORMALIZED_LINE: - ip.setClipRect(frame); - int ix1 = leftMargin + (int)(plotObject.x*frameWidth); - int iy1 = topMargin + (int)(plotObject.y*frameHeight); - int ix2 = leftMargin + (int)(plotObject.xEnd*frameWidth); - int iy2 = topMargin + (int)(plotObject.yEnd*frameHeight); - ip.drawLine(ix1, iy1, ix2, iy2); - ip.setClipRect(null); - break; - case PlotObject.DOTTED_LINE: - ip.setClipRect(frame); - ix1 = scaleX(plotObject.x); - iy1 = scaleY(plotObject.y); - ix2 = scaleX(plotObject.xEnd); - iy2 = scaleY(plotObject.yEnd); - double length = calculateDistance(ix1, ix2, iy1, iy2) + 0.1; - int n = (int)(length/plotObject.step); - for (int i = 0; i<=n; i++) - ip.drawDot(ix1 + (int)Math.round((ix2-ix1)*(double)i/n), iy1 + (int)Math.round((iy2-iy1)*(double)i/n)); - ip.setClipRect(null); - break; - case PlotObject.LABEL: - case PlotObject.NORMALIZED_LABEL: - ip.setJustification(plotObject.justification); - if (plotObject.getFont() != null) - ip.setFont(scFont(plotObject.getFont())); - int xt = type==PlotObject.LABEL ? scaleX(plotObject.x) : leftMargin + (int)(plotObject.x*frameWidth); - int yt = type==PlotObject.LABEL ? scaleY(plotObject.y) : topMargin + (int)(plotObject.y*frameHeight); - ip.drawString(plotObject.label, xt, yt); - break; - case PlotObject.LEGEND: - drawLegend(plotObject, ip); - break; - } - } - - /** Draw a bar at each point */ - void drawBarChart(PlotObject plotObject) { - int n = Math.min(plotObject.xValues.length, plotObject.yValues.length); - String[] xCats = labelsInBraces('x'); // do we have categories at the x axis instead of numbers? - boolean separatedBars = plotObject.shape == SEPARATED_BAR || xCats != null; - int halfBarWidthInPixels = n <= 1 ? Math.max(1, frameWidth/2-2) : 0; - if (separatedBars && n > 1) - halfBarWidthInPixels = Math.max(1, (int)Math.round(Math.abs - (0.5*(plotObject.xValues[n-1] - plotObject.xValues[0])/(n-1) * xScale * SEPARATED_BAR_WIDTH))); - int y0 = scaleYWithOverflow(0); - boolean yZeroInFrame = !logYAxis && yBasePxl>frame.y && yBasePxl 0 ? 0.5f*(plotObject.xValues[i-1]+plotObject.xValues[i]) : - 1.5f*plotObject.xValues[i] - 0.5f*plotObject.xValues[i+1]); - right = scaleX(i < n-1 ? 0.5f*(plotObject.xValues[i]+plotObject.xValues[i+1]) : - 1.5f*plotObject.xValues[i] - 0.5f*plotObject.xValues[i-1]); - } else { - int x = scaleX(plotObject.xValues[i]); - left = x - halfBarWidthInPixels; //separated bars or n<=1 : fixed bar width - right = x + halfBarWidthInPixels; - } - if (left < frame.x) left = frame.x; - if (left > frame.x+frame.width) left = frame.x+frame.width; - if (right < frame.x) right = frame.x; - if (right > frame.x+frame.width) right = frame.x+frame.width; - int y = scaleYWithOverflow(plotObject.yValues[i]); - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - for (int x2 = Math.min(left,right); x2 <= Math.max(left,right); x2++) - ip.drawLine(x2, y0, x2, y); //cant use ip.fillRect (ignores the clipRect), so we it fill line by line - } - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - if (separatedBars) { - ip.drawLine(left, y0, left, y); //up - ip.drawLine(left, y, right, y); //right - ip.drawLine(right, y, right, y0); //down - if (yZeroInFrame) - ip.drawLine(left, y0, right, y0);//baseline - } else { - ip.drawLine(left, prevY, left, y); //up or down - ip.drawLine(left, y, right, y); //right - if (i == n - 1) - ip.drawLine(right, y, right, y0);//last down - prevY = y; - } - } - } - - /** Draw the symbol for the data point number 'pointIndex' (pointIndex < 0 when drawing the legend) */ - void drawShape(PlotObject plotObject, int x, int y, int shape, int size, int pointIndex) { - if (ip==null) - return; - int lineWidth = ip.getLineWidth(); - if (shape == DIAMOND) - size = (int)(size*1.21); - int xbase = x-sc(size/2); - int ybase = y-sc(size/2); - int xend = x+sc(size/2); - int yend = y+sc(size/2); - if (lineWidth>3) { - int newLineWidth = 3; - ip.setLineWidth(newLineWidth); - } - //IJ.log("drawShape: "+size+" "+size); - switch(shape) { - case X: - ip.drawLine(xbase,ybase,xend,yend); - ip.drawLine(xend,ybase,xbase,yend); - break; - case BOX: - ip.drawLine(xbase,ybase,xend,ybase); - ip.drawLine(xend,ybase,xend,yend); - ip.drawLine(xend,yend,xbase,yend); - ip.drawLine(xbase,yend,xbase,ybase); - break; - case TRIANGLE: - ip.drawLine(x,ybase-sc(1),xend+sc(1),yend); //height must be odd, otherwise rounding leads to asymmetric shape - ip.drawLine(x,ybase-sc(1),xbase-sc(1),yend); - ip.drawLine(xend+sc(1),yend,xbase-sc(1),yend); - break; - case CROSS: - ip.drawLine(xbase,y,xend,y); - ip.drawLine(x,ybase,x,yend); - break; - case DIAMOND: - ip.drawLine(xbase,y,x,ybase); - ip.drawLine(x,ybase,xend,y); - ip.drawLine(xend,y,x,yend); - ip.drawLine(x,yend,xbase,y); - break; - case DOT: - ip.drawDot(x, y); //uses current line width - break; - case CUSTOM: - if (plotObject.macroCode==null || frame==null) - break; - if (x=frame.x+frame.width || y>=frame.y+frame.height) - break; - ImagePlus imp = new ImagePlus("", ip); - WindowManager.setTempCurrentImage(imp); - StringBuilder sb = new StringBuilder(140+plotObject.macroCode.length()); - sb.append("x="); sb.append(x); - sb.append(";y="); sb.append(y); - sb.append(";setColor('"); - sb.append(Tools.c2hex(plotObject.color)); - sb.append("');s="); sb.append(sc(1)); - boolean drawingLegend = pointIndex < 0; - double xVal = 0; - double yVal = 0; - if (!drawingLegend) { - xVal = plotObject.xValues[pointIndex]; - yVal = plotObject.yValues[pointIndex]; - } - sb.append(";i="); sb.append(drawingLegend ? 0 : pointIndex); - sb.append(";xval=" + xVal); - sb.append(";yval=" + yVal); - sb.append(";"); - sb.append(plotObject.macroCode); - if (!drawingLegend ||!sb.toString().contains("d2s") ) {// a graphical symbol won't contain "d2s" .. - String rtn = IJ.runMacro(sb.toString());//.. so it can go to the legend - if ("[aborted]".equals(rtn)) - plotObject.macroCode = null; - } - WindowManager.setTempCurrentImage(null); - break; - default: // CIRCLE, CONNECTED_CIRCLES: 5x5 oval approximated by 5x5 square without corners - if (sc(size) < 5.01) { - ip.drawLine(x-1, y-2, x+1, y-2); - ip.drawLine(x-1, y+2, x+1, y+2); - ip.drawLine(x+2, y+1, x+2, y-1); - ip.drawLine(x-2, y+1, x-2, y-1); - } else { - int r = sc(0.5f*size-0.5f); - ip.drawOval(x-r, y-r, 2*r, 2*r); - } - break; - } - ip.setLineWidth(lineWidth); - } - - /** Fill the area of the symbols for data points (except for shape=DOT) - * Note that ip.fill, ip.fillOval etc. can't be used here: they do not care about the clip rectangle */ - void fillShape(int shape, int x0, int y0, int size) { - if (shape == DIAMOND) size = (int)(size*1.21); - int r = sc(size/2)-1; - switch(shape) { - case BOX: - for (int dy=-r; dy<=r; dy++) - for (int dx=-r; dx<=r; dx++) - ip.drawDot(x0+dx, y0+dy); - break; - case TRIANGLE: - int ybase = y0 - r - sc(1); - int yend = y0 + r; - double halfWidth = sc(size/2)+sc(1)-1; - double hwStep = halfWidth/(yend-ybase+1); - for (int y=yend; y>=ybase; y--, halfWidth -= hwStep) { - int dx = (int)(Math.round(halfWidth)); - for (int x=x0-dx; x<=x0+dx; x++) - ip.drawDot(x,y); - } - break; - case DIAMOND: - ybase = y0 - r - sc(1); - yend = y0 + r; - halfWidth = sc(size/2)+sc(1)-1; - hwStep = halfWidth/(yend-ybase+1); - for (int y=yend; y>=ybase; y--) { - int dx = (int)(Math.round(halfWidth-(hwStep+1)*Math.abs(y-y0))); - for (int x=x0-dx; x<=x0+dx; x++) - ip.drawDot(x,y); - } - break; - case CIRCLE: case CONNECTED_CIRCLES: - int rsquare = (r+1)*(r+1); - for (int dy=-r; dy<=r; dy++) - for (int dx=-r; dx<=r; dx++) - if (dx*dx + dy*dy <= rsquare) - ip.drawDot(x0+dx, y0+dy); - break; - } - } - - /** Adds an arrow from position 1 to 2 given in pixels; 'size' is the length of the arrowhead - * @deprecated Use as a public method is not supported any more because it is incompatible with rescaling */ - @Deprecated - public void drawArrow(int x1, int y1, int x2, int y2, double size) { - double dx = x2 - x1; - double dy = y2 - y1; - double ra = Math.sqrt(dx * dx + dy * dy); - dx /= ra; - dy /= ra; - int x3 = (int) Math.round(x2 - dx * size); //arrow base - int y3 = (int) Math.round(y2 - dy * size); - double r = 0.3 * size; - int x4 = (int) Math.round(x3 + dy * r); - int y4 = (int) Math.round(y3 - dx * r); - int x5 = (int) Math.round(x3 - dy * r); - int y5 = (int) Math.round(y3 + dx * r); - ip.moveTo(x1, y1); ip.lineTo(x2, y2); - ip.moveTo(x4, y4); ip.lineTo(x2, y2); ip.lineTo(x5, y5); - } - - private void drawVerticalErrorBars(float[] x, float[] y, float[] e) { - int nPoints = Math.min(Math.min(x.length, y.length), e.length); - for (int i=0; i0))) continue; - int x0 = scaleX(x[i]); - int yPlus = scaleYWithOverflow(y[i] + e[i]); - int yMinus = scaleYWithOverflow(y[i] - e[i]); - ip.moveTo(x0,yMinus); - ip.lineTo(x0, yPlus); - } - } - - private void drawHorizontalErrorBars(float[] x, float[] y, float[] e) { - int nPoints = Math.min(Math.min(x.length, y.length), e.length); - float[] xpoints = new float[2]; - float[] ypoints = new float[2]; - for (int i=0; i0))) continue; - int y0 = scaleY(y[i]); - int xPlus = scaleXWithOverflow(x[i] + e[i]); - int xMinus = scaleXWithOverflow(x[i] - e[i]); - ip.moveTo(xMinus,y0); - ip.lineTo(xPlus, y0); - } - } - - /** Draw a polygon line; NaN values interrupt it. */ - void drawFloatPolyline(ImageProcessor ip, float[] x, float[] y, int n) { - if (x==null || x.length==0) return; - int x1, y1; - boolean isNaN0; - boolean isNaN1 = true; //no previous point - int x2 = scaleX(x[0]); - int y2 = scaleY(y[0]); - boolean isNaN2 = Float.isNaN(x[0]) || Float.isNaN(y[0]) || (logXAxis && x[0]<=0) || (logYAxis && y[0]<=0); - for (int i=1; i= frame.x+frame.width && right >= frame.x+frame.width) continue; - if (left < frame.x) left = frame.x; - if (left >= frame.x+frame.width) left = frame.x+frame.width-1; - if (right < frame.x) right = frame.x; - if (right >= frame.x+frame.width) right = frame.x+frame.width-1; - if (left != right) { - for (int xi = Math.min(left,right); xi <= Math.max(left,right); xi++) { - int yi = (int)Math.round(y1 + (double)(y2 - y1)*(double)(xi - x1)/(double)(x2 - x1)); - /* double yMin = Math.min(yF[i-1], yF[i]); - double yMax = Math.max(yF[i-1], yF[i]); - if (y < yMin) y = yMin; // dont extrapolate (in case rounding to pixels falls outside [xi, xi+1] interval) - if (y > yMax) y = yMax;*/ - ip.drawLine(xi, y0, xi, yi); - } - } else { - ip.drawLine(left, y0, left, y2); - } - } - } - - /** Returns only indexed and sorted plot objects, if at least one label is indexed like "1__MyLabel" */ - Vector getIndexedPlotObjects(){ - boolean withIndex = false; - int len = allPlotObjects.size(); - String[] labels = new String[len]; - Vector indexedObjects = new Vector(); - for(int jj = 0; jj < len; jj++){ - PlotObject plotObject = allPlotObjects.get(jj); - labels[jj] = ""; - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN) && plotObject.label != null) { - String label = plotObject.label; - if(label.indexOf("__") >=0 && label.indexOf("__") <= 2){ - labels[jj]= plotObject.label; - withIndex = true; - } - } - } - int[] ranks = Tools.rank(labels); - for(int jj = 0; jj < len; jj++){ - if(labels[ranks[jj]] != ""){ - int index = ranks[jj]; - indexedObjects.add(allPlotObjects.get(index)); - } - } - if(!withIndex) - return null; - return indexedObjects; - } - - /** Draw the legend */ - void drawLegend(PlotObject legendObject, ImageProcessor ip) { - ip.setFont(scFont(legendObject.getFont())); - int nLabels = 0; - int maxStringWidth = 0; - float maxLineThickness = 0; - Vector usedPlotObjects = allPlotObjects; - Vector indexedObjects = getIndexedPlotObjects(); - if(indexedObjects != null) - usedPlotObjects= indexedObjects; - - for (PlotObject plotObject : usedPlotObjects) - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN) && plotObject.label != null) { //label exists: was set now or previously - nLabels++; - String label = plotObject.label; - if (indexedObjects != null) - label = label.substring(label.indexOf("__") + 2); - int w = ip.getStringWidth(label); - if (w > maxStringWidth) maxStringWidth = w; - if (plotObject.lineWidth > maxLineThickness) maxLineThickness = plotObject.lineWidth; - } - if (nLabels == 0) return; - if (pp.antialiasedText && scale > 1) //fix incorrect width of large fonts - maxStringWidth = (int)((1 + 0.004*scale) * maxStringWidth); - int frameThickness = sc(legendObject.lineWidth > 0 ? legendObject.lineWidth : 1); - FontMetrics fm = ip.getFontMetrics(); - ip.setJustification(LEFT); - int lineHeight = fm.getHeight(); - int height = nLabels*lineHeight + 2*sc(LEGEND_PADDING); - int width = maxStringWidth + sc(3*LEGEND_PADDING + LEGEND_LINELENGTH + maxLineThickness); - int positionCode = legendObject.flags & LEGEND_POSITION_MASK; - if (positionCode == AUTO_POSITION) - positionCode = autoLegendPosition(width, height, frameThickness); - Rectangle rect = legendRect(positionCode, width, height, frameThickness); - int x0 = rect.x; - int y0 = rect.y; - - ip.setColor(Color.white); - ip.setLineWidth(1); - if (!legendObject.hasFlag(LEGEND_TRANSPARENT)) { - ip.setRoi(x0, y0, width, height); - ip.fill(); - } else if (hasFlag(X_GRID | Y_GRID)) { //erase grid - int grid = ip instanceof ColorProcessor ? (gridColor.getRGB() & 0xffffff) : ip.getBestIndex(gridColor); - for (int y=y0; y=0) - label = label.substring(start+2); - } - ip.drawString(label, xText, y+ lineHeight/2); - y += bottomUp ? -lineHeight : lineHeight; - } - } - - /** The legend area; positionCode should be TOP_LEFT, TOP_RIGHT, etc. */ - Rectangle legendRect(int positionCode, int width, int height, int frameThickness) { - boolean leftPosition = positionCode == TOP_LEFT || positionCode == BOTTOM_LEFT; - boolean topPosition = positionCode == TOP_LEFT || positionCode == TOP_RIGHT; - int x0 = (leftPosition) ? - leftMargin + sc(2*LEGEND_PADDING) + frameThickness/2 : - leftMargin + frameWidth - width - sc(2*LEGEND_PADDING) - frameThickness/2; - int y0 = (topPosition) ? - topMargin + sc(LEGEND_PADDING) + frameThickness/2 : - topMargin + frameHeight - height - sc(LEGEND_PADDING) + frameThickness/2; - if (hasFlag(Y_TICKS)) - x0 += (leftPosition ? 1 : -1) * sc(tickLength - LEGEND_PADDING); - if (hasFlag(X_TICKS)) - y0 += (topPosition ? 1 : -1) * sc(tickLength - LEGEND_PADDING/2); - return new Rectangle(x0, y0, width, height); - } - - /** The position code of the legend position where the smallest amount of foreground pixels is covered */ - int autoLegendPosition(int width, int height, int frameThickness) { - int background = ip instanceof ColorProcessor ? (0xffffff) : (ip.isInvertedLut() ? 0 : 0xff); - int grid = ip instanceof ColorProcessor ? (gridColor.getRGB() & 0xffffff) : ip.getBestIndex(gridColor); - int bestPosition = 0; - int minCoveredPixels = Integer.MAX_VALUE; - for (int positionCode : new int[]{TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT}) { - Rectangle rect = legendRect(positionCode, width, height, frameThickness); - int coveredPixels = 0; - for (int y = rect.y - frameThickness/2; y <= rect.y + rect.height + frameThickness/2; y++) - for (int x = rect.x - frameThickness/2; x <= rect.x + rect.width + frameThickness/2; x++) { - int pixel = ip.getPixel(x, y) & 0xffffff; - if (pixel != background && pixel != grid) - coveredPixels ++; - } - if (coveredPixels < minCoveredPixels) { - minCoveredPixels = coveredPixels; - bestPosition = positionCode; - } - } - return bestPosition; - } - - /** Returns the x, y coordinates at the cursor position or the nearest point as a String */ - String getCoordinates(int x, int y) { - if (frame==null) return ""; - String text = ""; - if (!frame.contains(x, y)) - return text; - double xv = descaleX(x); // cursor location - double yv = descaleY(y); - boolean yIsValue = false; - if (!hasMultiplePlots()) { - PlotObject p = getMainCurveObject(); // display x and f(x) instead of cursor y - if (p != null) { - double bestDx = Double.MAX_VALUE; - double xBest = 0, yBest = 0; - for (int i=0; i=0; i--) { - if (allPlotObjects.get(i).type == PlotObject.XY_DATA) - return allPlotObjects.get(i); - } - return null; - } - - /** returns whether there are several plots so that one cannot give a single y value for a given x value */ - private boolean hasMultiplePlots() { - int nPlots = 0; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type == PlotObject.ARROWS) - return true; - else if (plotObject.type == PlotObject.XY_DATA) { - nPlots ++; - if (nPlots > 1) return true; - } - } - return nPlots > 1; - } - - public void setPlotMaker(PlotMaker plotMaker) { - this.plotMaker = plotMaker; - } - - PlotMaker getPlotMaker() { - return plotMaker; - } - - /** Returns the labels of the (non-hidden) datasets as linefeed-delimited String. - * If the label is not set, a blank line is added. */ - String getDataLabels() { - String labels = ""; - boolean first = true; - for (PlotObject plotObject : allPlotObjects) - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN)) { - if (first) - first = false; - else - labels += '\n'; - if (plotObject.label != null) labels += plotObject.label; - } - return labels; - } - - /** Creates a ResultsTable with the plot data. Returns an empty table if no data. */ - public ResultsTable getResultsTable() { - return getResultsTable(true); - } - - /** Creates a ResultsTable with the data of the plot. Returns null if no data. - * Does not write the first x column if writeFirstXColumn is false. - * When all columns are the same length, x columns equal to the first x column are - * not written, independent of writeFirstXColumn. - * Column headings are "X", "Y", "X1", "Y1", etc, irrespective of any labels of the data sets - */ - public ResultsTable getResultsTable(boolean writeFirstXColumn) { - return getResultsTable(writeFirstXColumn, false); - } - - /** Creates a ResultsTable with the data of the plot. Returns null if no data. - * When all columns are the same length, x columns equal to the first x column are - * not written, independent of writeFirstXColumn. - * When the data sets have labels, they are used for column headings - */ - public ResultsTable getResultsTableWithLabels() { - return getResultsTable(true, true); - } - - /** Creates a ResultsTable with the data of the plot. Returns null if no data. - * Does not write the first x column if writeFirstXColumn is false. - * When all columns are the same length, x columns equal to the first x column are - * not written, independent of writeFirstXColumn. - * When the data sets have labels and useLabels is true, they are used for column headings, - * otherwise columns are named X, Y, X1, Y1, ... */ - ResultsTable getResultsTable(boolean writeFirstXColumn, boolean useLabels) { - ResultsTable rt = new ResultsTable(); - // find the longest x-value data set and count the data sets - int nDataSets = 0; - int tableLength = 0; - for (PlotObject plotObject : allPlotObjects) - if (plotObject.xValues != null) { - nDataSets++; - tableLength = Math.max(tableLength, plotObject.xValues.length); - } - if (nDataSets == 0) - return null; - // enter columns one by one to lists of data and headings - ArrayList headings = new ArrayList(2*nDataSets); - ArrayList data = new ArrayList(2*nDataSets); - int dataSetNumber = 0; - int arrowsNumber = 0; - PlotObject firstXYobject = null; - boolean allSameLength = true; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type==PlotObject.XY_DATA) { - if (firstXYobject != null && firstXYobject.xValues.length!=plotObject.xValues.length) { - allSameLength = false; - break; - } - if (firstXYobject==null) - firstXYobject = plotObject; - } - } - firstXYobject = null; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type==PlotObject.XY_DATA) { - boolean sameX = firstXYobject!=null && Arrays.equals(firstXYobject.xValues, plotObject.xValues) && allSameLength; - boolean sameXY = sameX && Arrays.equals(firstXYobject.yValues, plotObject.yValues); //ignore duplicates (e.g. Markers plus Curve) - boolean writeX = firstXYobject==null ? writeFirstXColumn : !sameX; - addToLists(headings, data, plotObject, dataSetNumber, writeX, /*writeY=*/!sameXY, /*multipleSets=*/nDataSets>1, useLabels); - if (firstXYobject == null) - firstXYobject = plotObject; - dataSetNumber++; - } else if (plotObject.type==PlotObject.ARROWS) { - addToLists(headings, data, plotObject, arrowsNumber, /*writeX=*/true, /*writeY=*/true, /*multipleSets=*/nDataSets>1, /*useLabels=*/false); - arrowsNumber++; - } - } - // populate the ResultsTable - int nColumns = headings.size(); - for (int line=0; line headings, ArrayListdata, PlotObject plotObject, - int dataSetNumber, boolean writeX, boolean writeY, boolean multipleSets, boolean useLabels) { - String plotObjectLabel = useLabels ? replaceSpacesEtc(plotObject.label) : null; - if (writeX) { - String label = null; // column header for x column - if (plotObject.type!=PlotObject.ARROWS) { - String plotXLabel = getLabel('x'); - if (dataSetNumber==0 && plotXLabel!=null) { // use x axis label for 1st dataset if permitted - if (useLabels) - label = replaceSpacesEtc(plotXLabel); - else if (plotXLabel.startsWith(" ") && plotXLabel.endsWith(" ")) // legacy: always use axis label for 1st data if spaces at start&end - label = plotXLabel.substring(1,plotXLabel.length()-1); - } else if (plotObjectLabel != null && dataSetNumber>0) - label = "X_"+plotObjectLabel; // use "X_" + dataset label - if (label != null && headings.contains(label)) - label = null; // avoid duplicate labels (not possible in ResultsTable) - } - if (label == null) { // create default label if no specific label yet - label = plotObject.type == PlotObject.ARROWS ? "XStart" : "X"; - if (multipleSets) label += dataSetNumber; - } - headings.add(label); - data.add(plotObject.xValues); - } - if (writeY) { - String label = null;; // column header for y column - if (plotObject.type!=PlotObject.ARROWS) { - String plotYLabel = getLabel('y'); - if (dataSetNumber==0 && plotYLabel!=null) { - if (useLabels && plotObjectLabel == null) // use y axis label for 1st dataset if no data set label - label = replaceSpacesEtc(plotYLabel); - else if (plotYLabel.startsWith(" ") && plotYLabel.endsWith(" ")) // legacy: always use axis label for 1st data if spaces at start&end - label = plotYLabel.substring(1,plotYLabel.length()-1); - } - if (plotObjectLabel != null) - label = plotObjectLabel; - if (label != null && headings.contains(label)) - label = null; // avoid duplicate labels (not possible in ResultsTable) - } - if (label == null) { // create default label if no specific label yet - label = plotObject.type == PlotObject.ARROWS ? "YStart" : "Y"; - if (multipleSets) label += dataSetNumber; - } - headings.add(label); - data.add(plotObject.yValues); - } - if (plotObject.xEValues != null) { - String label = plotObject.type == PlotObject.ARROWS ? "XEnd" : "XERR"; - if (multipleSets) label += dataSetNumber; - headings.add(label); - data.add(plotObject.xEValues); - } - if (plotObject.yEValues != null) { - String label = plotObject.type == PlotObject.ARROWS ? "YEnd" : "ERR"; - if (multipleSets) label += dataSetNumber; - headings.add(label); - data.add(plotObject.yEValues); - } - } - - /** Convert a string to a label suitable for a ResultsTable without whitespace, quotes or commas, - * to avoid problems when saving and reading the table. Returns null if an empty string or null. */ - static String replaceSpacesEtc(String s) { - if (s == null) return null; - s = s.trim().replaceAll("[\\s,]", "_").replace("\"","''"); - if (s.length() == 0) return null; - return s; - } - - /** get the number of digits for writing a column to the results table or the clipboard */ - static int getPrecision(float[] values) { - int setDigits = Analyzer.getPrecision(); - int measurements = Analyzer.getMeasurements(); - boolean scientificNotation = (measurements&Measurements.SCIENTIFIC_NOTATION)!=0; - if (scientificNotation) { - if (setDigits max) max = values[i]; - } - } - if (allInteger) - return 0; - int digits = (max - min) > 0 ? getDigits(min, max, MIN_FLOAT_PRECISION*(max-min), 15, 0) : - getDigits(max, MIN_FLOAT_PRECISION*Math.abs(max), 15, 0); - if (setDigits>Math.abs(digits)) - digits = setDigits * (digits < 0 ? -1 : 1); //use scientific notation if needed - return digits; - } - - /** Whether a given flag 'what' is set */ - boolean hasFlag(int what) { - return (pp.axisFlags&what) != 0; - } - - /* Obsolete, replaced by add(shape,x,y). */ - public void addPoints(String dummy, float[] x, float[] y, int shape) { - addPoints(x, y, shape); - } - - /** Plots a histogram from an array using auto-binning. - * @param values array containing the population - * N.Vischer - */ - public void addHistogram(double[] values) { - addHistogram(values, 0, 0); - } - - /** Plots a histogram from an array using the specified bin width. - * @param values array containing the population - * @param binWidth set zero for auto-binning - * N.Vischer - */ - public void addHistogram(double[] values, double binWidth) { - addHistogram(values, binWidth, 0); - } - - /** Plots a histogram of the value distribution (bin counts) from an array - * @param values array containing the values for the population - * @param binWidth set zero for auto-binning - * @param binCenter any x value can be the center of a bin - * N.Vischer - */ - public void addHistogram(double[] values, double binWidth, double binCenter) { - int len = values.length; - double min = Double.POSITIVE_INFINITY; - double max = Double.NEGATIVE_INFINITY; - double[] cleanVals = new double[len]; - int count = 0; - double sum = 0, sum2 = 0; - for (int i = 0; i < len; i++) { - double val = values[i]; - if (!Double.isNaN(val)) { - cleanVals[count++] = val; - sum += val; - sum2 += val * val; - if (val < min) - min = val; - if (val > max) - max = val; - } - } - if (binWidth <= 0) {//autobinning - double stdDev = Math.sqrt(((count * sum2 - sum * sum) / count) / count);//not count - 1 - // use Scott's method (1979 Biometrika, 66:605-610) for optimal binning: 3.49*sd*N^-1/3 - binWidth = 3.49 * stdDev * (Math.pow(count, -1.0 / 3)); - - } - double modCenter = binCenter % binWidth; - double modMin = min % binWidth; - double diff = modMin - modCenter; - double firstBin = min-diff; - while(firstBin - binWidth * 0.499 > min) - firstBin -= binWidth; - int nBins = (int) ((max - firstBin)/binWidth); - double lastBin = firstBin + nBins * binWidth; - while(lastBin + binWidth * 0.499 < max) - lastBin += binWidth; - nBins = (int) Math.round((lastBin - firstBin)/binWidth) + 1; - if (nBins == 1) - nBins = 2; - if (nBins > 9999) { - IJ.error("max bins > 9999"); - return; - } - double[] histo = new double[nBins]; - double[] xValues = new double[nBins]; - for (int i = 0; i < nBins; i++) - xValues[i] = firstBin + i * binWidth; - for (int i = 0; i < count; i++) { - double val = cleanVals[i]; - double indexD = (val - firstBin) / binWidth; - int index = (int) Math.round(indexD); - if (index < 0 || index >= nBins) { - IJ.error("index out of range"); - return; - } else - histo[index]++; - } - add("bar", xValues, histo); - } - - /* Obsolete, replaced by add("error bars",errorBars). */ - public void addErrorBars(String dummy, float[] errorBars) { - addErrorBars(errorBars); - } - - /* Obsolete; replaced by setFont(). */ - public void changeFont(Font font) { - setFont(font); - } - -} - -/** This class contains the properties of the plot, such as size, format, range, etc, except for the data+format (plot contents). - * To enable reading serialized PlotObjects of plots created with previous versions of ImageJ, - * the variable names MUST NEVER be changed! Also any additions should be made after careful thought, - * since they have to be kept for all future versions. */ -class PlotProperties implements Cloneable, Serializable { - /** The serialVersionUID should not be modified, otherwise saved plots won't be readable any more */ - static final long serialVersionUID = 1L; - // - PlotObject frame = new PlotObject(Plot.DEFAULT_FRAME_LINE_WIDTH); //the frame, including background color and axis numbering - PlotObject xLabel = new PlotObject(PlotObject.AXIS_LABEL); //the x axis label (string & font) - PlotObject yLabel = new PlotObject(PlotObject.AXIS_LABEL); //the x axis label (string & font) - PlotObject legend; //the legend (if any) - int width = 0; //canvas width (note: when stored, this must fit the image) - int height = 0; - int axisFlags; //these define axis layout - double[] rangeMinMax; //currentMinMax when writing, sets defaultMinMax when reading - boolean antialiasedText = true; - boolean isFrozen; //modifications (size, range, contents) don't update the ImageProcessor - - /** Returns an array of all PlotObjects defined as PlotProperties. Note that some may be null */ - PlotObject[] getAllPlotObjects() { - return new PlotObject[]{frame, xLabel, xLabel, legend}; - } - - /** Returns the PlotObject for xLabel ('x'), yLabel('y'), frame ('f'; includes number font) or the legend ('l'). */ - PlotObject getPlotObject(char c) { - switch(c) { - case 'x': return xLabel; - case 'y': return yLabel; - case 'f': return frame; - case 'l': return legend; - default: return null; - } - } - - /** A shallow clone that does not duplicate arrays or objects */ - public PlotProperties clone() { - try { - return (PlotProperties)(super.clone()); - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** A deep clone; it also duplicates arrays and pPlotObjects */ - public PlotProperties deepClone() { - PlotProperties pp2 = clone(); //shallow clone - if (frame != null) pp2.frame = frame.deepClone(); - if (xLabel != null) pp2.xLabel = xLabel.deepClone(); - if (yLabel != null) pp2.yLabel = yLabel.deepClone(); - if (legend != null) pp2.legend = legend.deepClone(); - if (rangeMinMax != null) pp2.rangeMinMax = rangeMinMax.clone(); - return pp2; - } - -} // class PlotProperties - -/** This class contains the data and properties for displaying a curve, a set of arrows, a line or a label in a plot, - * as well as the legend, axis labels, and frame (including background and fonts of axis numbering). - * Note that all properties such as lineWidths and Fonts have to be scaled up for high-resolution plots. - * This class allows serialization for writing into tiff files. - * To enable reading serialized PlotObjects of plots created with previous versions of ImageJ, - * the variable names MUST NEVER be changed! Also any additions should be made after careful thought, - * since they have to be kept for all future versions. */ -class PlotObject implements Cloneable, Serializable { - /** The serialVersionUID should not be modified, otherwise saved plots won't be readable any more */ - static final long serialVersionUID = 1L; - /** Constants for the type of objects. These are powers of two so one can use them as masks */ - public final static int XY_DATA = 1, ARROWS = 2, LINE = 4, NORMALIZED_LINE = 8, DOTTED_LINE = 16, - LABEL = 32, NORMALIZED_LABEL = 64, LEGEND = 128, AXIS_LABEL = 256, FRAME = 512, SHAPES = 1024; - /** mask for recovering font style from the flags */ - final static int FONT_STYLE_MASK = 0x0f; - /** flag for the data set passed with the constructor. Note that 0 to 0x0f are reserved for fonts modifiers, 0x010-0x800 are reserved for legend modifiers */ - public final static int CONSTRUCTOR_DATA = 0x1000; - /** flag for hiding a PlotObject */ - public final static int HIDDEN = 0x2000; - /** Type of the object; XY_DATA stands for curve or markers, can be also ARROWS ... SHAPES */ - public int type = XY_DATA; - /** bitwise combination of flags, or the position of a legend */ - public int flags; - /** Options, currently only for FRAME, see Plot.setOptions */ - public String options; - /** The x and y data arrays and the error bars (if non-null). These arrays also serve as x0, y0, x1, y1 - * arrays for plotting arrays of arrows */ - public float[] xValues, yValues, xEValues, yEValues; - /** For SHAPES: For boxplots with whiskers ('boxes'), elements of the ArrayList are float[6] with x and all 5 y values - * (for 'boxesx', y and all 5 x values), for 'rectangles', float[4] with x1, y1, x2, y2. */ - public ArrayList shapeData; - /** For SHAPES only, shape type & options. Currently implemented: 'boxes', 'boxesx' (box plots with whiskers), 'rectangles', 'redraw_grid' */ - public String shapeType; //e.g. "boxes width=20" - /** Type of the points, such as Plot.LINE, Plot.CROSS etc. (for type = XY_DATA) */ - public int shape; - /** The line width in pixels for 'normal' plots (for high-resolution plots, to be multiplied by a scale factor) */ - public float lineWidth; - /** The color of the object, must not be null */ - public Color color; - /** The secondary color (for filling closed symbols and for the line of CIRCLES_AND_LINE, may be null for unfilled/default */ - public Color color2; - /** Labels and lines: Position (NORMALIZED objects: relative units 0...1). */ - public double x, y; - /** Lines only: End position */ - public double xEnd, yEnd; - /** Dotted lines only: step */ - public int step; - /** A label for the y data of the curve, a text to draw, or the text of a legend (tab-delimited lines) */ - public String label; - /** Labels only: Justification can be Plot.LEFT, Plot.CENTER or Plot.RIGHT */ - public int justification; - /** Macro code for drawing symbols */ - public String macroCode; - /** Text objects (labels, legend, axis labels) only: the font; maybe null for default. This is not serialized (transient) */ - private transient Font font; - /** String for representation of the font family (for Serialization); may be null for default. Font style is in flags, font size in fontSize. */ - private String fontFamily; - /** Font size (for Serialization), for 'normal' plots (for high-resolution plots, to be multiplied by a scale factor) */ - private float fontSize; - - - /** Generic constructor */ - PlotObject(int type) { - this.type = type; - } - - /** Constructor for XY_DATA, i.e., a curve or set of points */ - PlotObject(float[] xValues, float[] yValues, float[] yErrorBars, int shape, float lineWidth, Color color, Color color2, String yLabel) { - this.type = XY_DATA; - this.xValues = xValues; - this.yValues = yValues; - this.yEValues = yErrorBars; - this.shape = shape; - this.lineWidth = lineWidth; - this.color = color; - this.color2 = color2; - this.label = yLabel; - if (shape==Plot.CUSTOM) - this.macroCode = yLabel; - } - - /** Constructor for a set of arrows */ - PlotObject(float[] x1, float[] y1, float[] x2, float[] y2, float lineWidth, Color color) { - this.type = ARROWS; - this.xValues = x1; - this.yValues = y1; - this.xEValues = x2; - this.yEValues = y2; - this.lineWidth = lineWidth; - this.color = color; - } - - /** Constructor for a set of shapes */ - PlotObject(String shapeType, ArrayList shapeData, float lineWidth, Color color, Color color2) { - this.type = SHAPES; - this.shapeData = shapeData; - this.shapeType = shapeType; - this.lineWidth = lineWidth; - this.color = color; - this.color2 = color2; - } - - /** Constructor for a line */ - PlotObject(double x, double y, double xEnd, double yEnd, float lineWidth, int step, Color color, int type) { - this.type = type; - this.x = x; - this.y = y; - this.xEnd = xEnd; - this.yEnd = yEnd; - this.lineWidth = lineWidth; - this.step = step; - this.color = color; - } - - /** Constructor for a label or NORMALIZED_LABEL */ - PlotObject(String label, double x, double y, int justification, Font font, Color color, int type) { - this.type = type; - this.label = label; - this.x = x; - this.y = y; - this.justification = justification; - setFont(font); - this.color = color; - } - - /** Constructor for the legend. flags is bitwise or of TOP_LEFT etc. and LEGEND_TRANSPARENT if desired. - * Note that the labels in the legend are those of the data plotObjects */ - PlotObject(float lineWidth, Font font, Color color, int flags) { - this.type = LEGEND; - this.lineWidth = lineWidth; - setFont(font); - this.color = color; - this.flags = flags; - } - - /** Constructor for the frame, including axis numbers. In the current version, the primary color (line color) is always black */ - PlotObject(float lineWidth) { - this.type = FRAME; - this.color = Color.black; - this.lineWidth = lineWidth; - } - - /** Whether a given flag 'what' is set */ - boolean hasFlag(int what) { - return (flags&what) != 0; - } - - /** Sets a given flag */ - void setFlag(int what) { - flags |= what; - } - - /** Unsets a given flag */ - void unsetFlag(int what) { - flags = flags & (~what); - } - - /** Whether an XY_DATA object has a curve to draw */ - boolean hasCurve() { - return type == XY_DATA && (shape == Plot.LINE || shape == Plot.CONNECTED_CIRCLES || shape == Plot.FILLED); - } - - /** Whether an XY_DATA object has markers to draw */ - boolean hasMarker() { - return type == XY_DATA && (shape == Plot.CIRCLE || shape == Plot.X || shape == Plot.BOX || shape == Plot.TRIANGLE - || shape == Plot.CROSS || shape == Plot.DIAMOND || shape == Plot.DOT || shape == Plot.CONNECTED_CIRCLES - || shape == Plot.CUSTOM); - } - - /** Whether an XY_DATA object has markers that can be filled */ - boolean hasFilledMarker() { - return type == XY_DATA && color2 != null && (shape == Plot.CIRCLE || shape == Plot.BOX || shape == Plot.TRIANGLE || - shape == Plot.DIAMOND || shape == Plot.CONNECTED_CIRCLES); - } - - /** Size of the markers for an XY_DATA object with markers */ - int getMarkerSize() { - if (lineWidth<=1) - return 5; - else if (lineWidth<=3) - return 7; - else - return (int)(lineWidth+4); - } - - /** Sets the font. Also writes font properties for serialization. */ - void setFont(Font font) { - if (font == this.font) return; - this.font = font; - if (font == null) { - fontFamily = null; - } else { - fontFamily = font.getFamily(); - flags = (flags & ~FONT_STYLE_MASK) | font.getStyle(); - fontSize = font.getSize2D(); - } - } - - /** Returns the font, or null if none specified */ - Font getFont() { - if (font == null && fontFamily != null) //after recovery from serialization, create the font from its description - font = FontUtil.getFont(fontFamily, flags&FONT_STYLE_MASK, fontSize); - return font; - } - - /** Returns the font size */ - float getFontSize() { - return fontSize; - } - - /** Returns all data xValues, yValues, xEValues, yEValues as a float[][] array. Note that future versions may have more data. */ - float[][] getAllDataValues() { - return new float[][] {xValues, yValues, xEValues, yEValues}; - } - - /** A shallow clone that does not duplicate arrays or objects */ - public PlotObject clone() { - try { - return (PlotObject)(super.clone()); - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** A deep clone, which duplicates arrays etc. - * Note that colors & font are not cloned; it is assumed that these wil not be modified but replaced, - * so the clone remains unaffected */ - public PlotObject deepClone() { - PlotObject po2 = clone(); - if (xValues != null) po2.xValues = xValues.clone(); - if (yValues != null) po2.yValues = yValues.clone(); - if (xEValues != null) po2.xEValues = xEValues.clone(); - if (yEValues != null) po2.yEValues = yEValues.clone(); - if (shapeData != null) po2.shapeData = cloneArrayList(shapeData); - return po2; - } - - /** A clone of an array list one level deeper than a shallow clone. - * The clone() method of the objects in the list must be accessible */ - private ArrayList cloneArrayList(ArrayList src) { - ArrayList dest = (ArrayList)(src.clone()); //shallow clone - Class[] noClasses = new Class[0]; - Object[] noObjects = new Object[0]; - for (int i=0; i 1) - super.zoomIn(sx, sy); - else - super.zoomOut(sx, sy); - return; - } - plot.zoom(sx, sy, zoomFactor); - } - - /** - * Implements the Image/Zoom/Original Scale command. Sets the original range of - * the x, y axes (unless the plot is frozen) - */ - public void unzoom() { - if (plot == null || plot.isFrozen()) { - super.unzoom(); - return; - } - resetMagnification(); - plot.setLimitsToDefaults(true); - } - - /** - * Implements the Image/Zoom/View 100% command: Sets the original frame size as - * specified in Edit/Options/Plots (unless the plot is frozen) - */ - public void zoom100Percent() { - if (plot == null || plot.isFrozen()) { - super.zoom100Percent(); - return; - } - resetMagnification(); - plot.setFrameSize(PlotWindow.plotWidth, PlotWindow.plotHeight); - } - - /** Resizes the plot (unless frozen) to fit the window */ - public void fitToWindow() { - if (plot == null || plot.isFrozen()) { - super.fitToWindow(); - return; - } - ImageWindow win = imp.getWindow(); - if (win == null) - return; - Rectangle bounds = win.getBounds(); - Dimension extraSize = win.getExtraSize(); - int width = bounds.width - extraSize.width;// (insets.left+insets.right+ImageWindow.HGAP*2); - int height = bounds.height - extraSize.height;// (insets.top+insets.bottom+ImageWindow.VGAP*2); - // IJ.log("fitToWindow "+bounds+"-> w*h="+width+"*"+height); - resizeCanvas(width, height); - getParent().doLayout(); - } - - /** - * Resizes the canvas when the user resizes the window. To avoid a race - * condition while creating a new window, this is ignored if no window exists or - * the window has not been activated yet. - */ - void resizeCanvas(int width, int height) { - if (plot == null || plot.isFrozen()) { - super.resizeCanvas(width, height); - return; - } - resetMagnification(); - if (width == oldWidth && height == oldHeight) - return; - if (plot == null) - return; - ImageWindow win = imp.getWindow(); - if (win == null || !(win instanceof PlotWindow)) - return; - if (!win.isVisible()) - return; - if (!((PlotWindow) win).wasActivated) - return; // window layout not finished yet? - Dimension minSize = plot.getMinimumSize(); - int plotWidth = width < minSize.width ? minSize.width : width; - int plotHeight = height < minSize.height ? minSize.height : height; - plot.setSize(plotWidth, plotHeight); - setSize(width, height); - oldWidth = width; - oldHeight = height; - ((PlotWindow)win).canvasResized(); - } - - /** - * The image of a PlotCanvas is always shown at 100% magnification unless the - * plot is frozen - */ - public void setMagnification(double magnification) { - if (plot == null || plot.isFrozen()) - super.setMagnification(magnification); - else - resetMagnification(); - } - - /** - * Scrolling a PlotCanvas is updating the plot, not viewing part of the plot, - * unless the plot is frozen - */ - public void setSourceRect(Rectangle r) { - if (plot.isFrozen()) - super.setSourceRect(r); - else - resetMagnification(); - } - - void resetMagnification() { - magnification = 1.0; - srcRect.x = 0; - srcRect.y = 0; - } - - /** - * overrides ImageCanvas.setupScroll; if plot is not frozen, scrolling modifies - * the plot data range - */ - protected void setupScroll(int ox, int oy) { - if (plot.isFrozen()) { - super.setupScroll(ox, oy); - return; - } - xMouseStart = ox; - yMouseStart = oy; - xScrolled = 0; - yScrolled = 0; - } - - /** - * overrides ImageCanvas.scroll; if plot is not frozen, scrolling modifies the - * plot data range - */ - protected void scroll(int sx, int sy) { - if (plot.isFrozen()) { - super.scroll(sx, sy); - return; - } - if (sx == 0 && sy == 0) - return; - if (xScrolled == 0 && yScrolled == 0) - plot.saveMinMax(); - int dx = sx - xMouseStart; - int dy = sy - yMouseStart; - plot.scroll(dx - xScrolled, dy - yScrolled); - xScrolled = dx; - yScrolled = dy; - Thread.yield(); - } - - /** overrides ImageCanvas.mouseExited; removes 'range' arrows */ - public void mouseExited(MouseEvent e) { - ImageWindow win = imp.getWindow(); - if (win instanceof PlotWindow) - ((PlotWindow) win).mouseExited(e); - super.mouseExited(e); - } - - /** - * overrides ImageCanvas.mousePressed: no further processing of clicks on - * 'range' arrows - */ - public void mousePressed(MouseEvent e) { - /* Changed for Bio7! */ - - WindowManager.setTempCurrentImage(imp); - WindowManager.setCurrentWindow(imp.getWindow()); - - /* import to set current Panel! */ - CanvasView.setCurrent((JPanel) this.getParent()); - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - ImageWindow wind = imp.getWindow(); - if (wind != null) { - Frame frameSwtAwt = wind.getSwtAwtMain().getFrame(); - if (frameSwtAwt != null) { - - if (frameSwtAwt != null) - frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, WindowEvent.WINDOW_ACTIVATED)); - // frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, - // WindowEvent.WINDOW_GAINED_FOCUS)); - - if (PlotCanvas.this.isFocusOwner() == false) { - PlotCanvas.this.requestFocus(); - - } - } - } - } - }); - - rangeArrowIndexWhenPressed = getRangeArrowIndex(e); - if (rangeArrowIndexWhenPressed < 0) - super.mousePressed(e); - } - - /** Overrides ImageCanvas.mouseReleased, handles clicks on 'range' arrows */ - public void mouseReleased(MouseEvent e) { - if (rangeArrowIndexWhenPressed >= 0 && rangeArrowIndexWhenPressed == getRangeArrowIndex(e)) - plot.zoomOnRangeArrow(rangeArrowIndexWhenPressed); - else - super.mouseReleased(e); - } - - /* - * Changed for Bio7! We have no visible PlotWindow so we implement the mouse - * listener here! - */ - - public void mouseWheelMoved(MouseWheelEvent e) { - ImageCanvas ic = imp.getCanvas(); - if (plot.isFrozen() || !(ic instanceof PlotCanvas)) { // frozen plots are like normal images - super.mouseWheelMoved(e); - return; - } - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - if (e.getX() < plot.leftMargin || e.getX() > plot.leftMargin + plot.frameWidth)// n__ - return; - if (e.getY() < plot.topMargin || e.getY() > plot.topMargin + plot.frameHeight) - return; - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - if (ctrl || IJ.shiftKeyDown()) { - double zoomFactor = rotation < 0 ? Math.pow(2, 0.2) : Math.pow(0.5, 0.2); - Point loc = ic.getCursorLoc(); - int x = ic.screenX(loc.x); - int y = ic.screenY(loc.y); - ((PlotCanvas) ic).zoom(x, y, zoomFactor); - } else if (IJ.spaceBarDown()) - plot.scroll(rotation * amount * Math.max(ic.imageWidth / 50, 1), 0); - else - plot.scroll(0, rotation * amount * Math.max(ic.imageHeight / 50, 1)); - } - - /** - * Returns the index of the arrow for modifying the range when the mouse click - * was at such an arrow, otherwise -1 - */ - int getRangeArrowIndex(MouseEvent e) { - ImageWindow win = imp.getWindow(); - int rangeArrowIndex = -1; - if (win instanceof PlotWindow) { - int x = e.getX(); - int y = e.getY(); - rangeArrowIndex = ((PlotWindow) win).getRangeArrowIndex(x, y); - } - return rangeArrowIndex; - } -} diff --git a/com.eco.bio7.image/src/ij/gui/PlotContentsDialog.java b/com.eco.bio7.image/src/ij/gui/PlotContentsDialog.java deleted file mode 100644 index 5fe72bfed..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotContentsDialog.java +++ /dev/null @@ -1,670 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.measure.CurveFitter; -import ij.measure.Minimizer; -import ij.text.TextWindow; -import ij.measure.ResultsTable; -import ij.plugin.Colors; -import ij.plugin.frame.Recorder; -import ij.util.Tools; -import java.awt.*; -import java.awt.event.*; -import java.util.Arrays; -import java.util.Vector; -import java.util.ArrayList; - -/** This class implements the Plot Window's Data>"Add from Plot", "Add form Table", "Add Fit" and - * "More>Contents Style" dialogs - */ -public class PlotContentsDialog implements DialogListener { - /** Types of dialog (ERROR suppresses the dialog after an invalid call of a constructor) */ - public final static int ERROR=-1, STYLE=0, ADD_FROM_PLOT=1, ADD_FROM_TABLE=2, ADD_FROM_ARRAYS=3, ADD_FIT=4; - /** Dialog headings for each dialogType >= 0 */ - private static final String[] HEADINGS = new String[] {"Plot Contents Style", "Add From Plot", "Plot From Table", "Add Plot Data", "Add Fit"}; - private Plot plot; // the plot we work on - private int dialogType; // determines what to do: ADD_FORM_PLOT, etc. - private double[] savedLimits; // previous plot range, for undo upon cancel - GenericDialog gd; - private int currentObjectIndex = -1; - private Choice objectChoice; - private Choice symbolChoice; - private TextField colorField, color2Field, labelField, widthField; - private Checkbox visibleCheckbox; - private boolean creatingPlot; // for creating plots; dialogType determines source - private Choice plotChoice; // for "Add from Plot" - private Plot[] allPlots; - private String[] allPlotNames; - private static Plot previousPlot; - private static int previousPlotObjectIndex; - private int defaultPlotIndex, defaultObjectIndex; - private int currentPlotNumObjects; - private Choice tableChoice; // for "Add from Table" - final static int N_COLUMNS = 4; // number of data columns that we can have; x, y, xE, yE - private int nColumnsToUse = N_COLUMNS; // user may restrict to 2, for not having error bars - private Choice[] columnChoice = new Choice[N_COLUMNS]; - private final static String[] COLUMN_NAMES = new String[] {"X:", "Y:", "X Error:", "Y Error:"}; - private final static boolean[] COLUMN_ALLOW_NONE = new boolean[] {true, false, true, true}; //y data cannot be null - private ResultsTable[] allTables; - private String[] allTableNames; - private static String previousTableName; - private static int[] previousColumns = new int[]{1, 1, 0, 0}; //must be N_COLUMNS elements - private static int defaultTableIndex; - private static int[] defaultColumnIndex = new int[N_COLUMNS]; - private String[] arrayHeadings; // for "Add from Arrays" - private ArrayList arrayData; - private Choice fitDataChoice; // for "Add Fit" - private Choice fitFunctionChoice; - private Thread fittingThread; - private static String lastFitFunction = CurveFitter.fitList[0]; - private String curveFitterStatusString; - private static String previousColor="blue", previousColor2="#a0a0ff", previousSymbol="Circle"; - private static double previousLineWidth = 1; - private static final String[] PLOT_COLORS = new String[] {"blue", "red", "black", "#00c0ff", "#00e000", "gray", "#c08060", "magenta"}; - - - /** Prepares a new PlotContentsDialog for an existing plot. Use showDialog thereafter. - * @param dialogType may be STYLE (contents style), ADD_FROM_PLOT (add object from other plot), ADD_FROM_TABLE, and ADD_FIT */ - public PlotContentsDialog(Plot plot, int dialogType) { - this.plot = plot; - this.dialogType = plot == null ? ERROR : dialogType; - if (plot != null) currentPlotNumObjects = plot.getNumPlotObjects(); - } - - /** Prepares a new PlotContentsDialog for creating a new plot using data from a ResultsTable. - * Use showDialog thereafter. */ - public PlotContentsDialog(String title, ResultsTable rt) { - creatingPlot = true; - dialogType = ADD_FROM_TABLE; - if (rt == null || !isValid(rt)) { - IJ.error("Cant Create Plot","No (results) table or no data in "+title); - dialogType = ERROR; - } - plot = new Plot("Plot of "+title, "x", "y"); - allTables = new ResultsTable[] {rt}; - allTableNames = new String[] {title}; - } - - /** Prepares a new PlotContentsDialog for creating a new plot using float[] arrays as data. - * Each 'data' array in the ArrayList must have a corresponding element in the 'headings' array. - * 'defaultHeadings' may contain the headings of the items selected initially for x, y, x error and y error, respectively. - * 'defaultHeadings' and each of its entries may be null, and the array may have any length. */ - public PlotContentsDialog(String title, String[] headings, String[] defaultHeadings, ArrayList data) { - creatingPlot = true; - dialogType = ADD_FROM_ARRAYS; - this.arrayHeadings = headings; - this.arrayData = data; - plot = new Plot(title, "x", "y"); - setDefaultColumns(defaultHeadings); - } - - /** Prepares a new PlotContentsDialog for adding data from float[] arrays to a plot. - * Each 'data' array in the ArrayList must have a corresponding element in the 'headings' array. - * 'defaultHeadings' may contain the headings of the items selected initially for x, y, x error and y error, respectively. - * 'defaultHeadings' and each of its entries may be null, and the array may have any length. */ - public PlotContentsDialog(Plot plot, String[] headings, String[] defaultHeadings, ArrayList data) { - dialogType = ADD_FROM_ARRAYS; - this.plot = plot; - this.arrayHeadings = headings; - this.arrayData = data; - setDefaultColumns(defaultHeadings); - } - - /** Avoids showing a selection for the error bars; must be called before showDialog. */ - public void noErrorBars() { - nColumnsToUse = 2; // only x, y columns can be selected - } - - /** Shows the dialog, with a given parent Frame (may be null) */ - public void showDialog(Frame parent) { - if (dialogType == ERROR) return; - if (!creatingPlot) savedLimits = plot.getLimits(); - plot.savePlotObjects(); - String[] designations = plot.getPlotObjectDesignations(); - if (dialogType == STYLE && designations.length==0) { - IJ.error("Empty Plot"); - return; - } else if (dialogType == ADD_FROM_PLOT) { - prepareAddFromPlot(); - if (allPlots.length == 0) return; //should never happen; we have at least the current plot - } else if (dialogType == ADD_FROM_TABLE && !creatingPlot) { - prepareAddFromTable(); - if (allTables.length == 0) return; //should never happen; PlotWindow should not enable if no table - } - if ((dialogType == ADD_FROM_TABLE || dialogType == ADD_FROM_ARRAYS) && !creatingPlot) - suggestColor(); - if (parent == null && plot.getImagePlus() != null) - parent = plot.getImagePlus().getWindow(); - gd = parent == null ? new GenericDialog(HEADINGS[dialogType]) : - new GenericDialog(HEADINGS[dialogType], parent); - IJ.wait(100); //sometimes needed to avoid hanging? - if (dialogType == STYLE) { - gd.addChoice("Item:", designations, designations[0]); - objectChoice = (Choice)(gd.getChoices().get(0)); - currentObjectIndex = objectChoice.getSelectedIndex(); - } else if (dialogType == ADD_FROM_PLOT) { - gd.addChoice("Select Plot:", allPlotNames, allPlotNames[defaultPlotIndex]); - gd.addChoice("Item to Add:", new String[]{""}, ""); // will be set up by makeSourcePlotObjects - Vector choices = gd.getChoices(); - plotChoice = (Choice)(choices.get(0)); - objectChoice = (Choice)(choices.get(1)); - makeSourcePlotObjects(); - } else if (dialogType == ADD_FROM_TABLE) { - gd.addChoice("Select Table:", allTableNames, allTableNames[defaultTableIndex]); - tableChoice = (Choice)(gd.getChoices().get(0)); - if (creatingPlot) tableChoice.setEnabled(false); // we can't select the table, we have only one - } else if (dialogType == ADD_FIT) { - String[] dataSources = plot.getDataObjectDesignations(); - if (dataSources.length == 0) { - IJ.error("No Data For Fitting"); - return; - } - gd.addChoice("Fit Data Set:", dataSources, dataSources[0]); - gd.addChoice("Fit Function:", new String[0], ""); - Vector choices = gd.getChoices(); - fitDataChoice = (Choice)(choices.get(0)); - fitFunctionChoice = (Choice)(choices.get(1)); - if (dataSources.length == 1) - fitDataChoice.setEnabled(false); - for (int i=0; i 0) - Recorder.recordString("Plot.add(\"xerror\", Table.getColumn(\""+ - columnChoice[2].getSelectedItem()+"\", \""+tableChoice.getSelectedItem()+"\"));\n"); - if (columnChoice[3].getSelectedIndex() > 0) - Recorder.recordString("Plot.add(\"error\", Table.getColumn(\""+ - columnChoice[3].getSelectedItem()+"\", \""+tableChoice.getSelectedItem()+"\"));\n"); - } - Recorder.recordString("Plot.setStyle("+currentObjectIndex+", \""+getStyleString()+"\");\n"); - } - } - - public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { - if (e==null) - return true; //gets called with e=null upon OK - boolean setStyle = false; - if (dialogType == STYLE) { - int objectIndex = objectChoice.getSelectedIndex(); // no getNextChoice since Choices depend on dialog type - setStyle = (e.getSource() != objectChoice); - if (e.getSource() == objectChoice) { - setDialogStyleFields(objectIndex); - currentObjectIndex = objectIndex; - } else - setStyle = true; - } else if (dialogType == ADD_FROM_PLOT) { - if (e.getSource() == plotChoice) { - makeSourcePlotObjects(); - addObjectFromPlot(); - } else if (e.getSource() == objectChoice) { - addObjectFromPlot(); - } else - setStyle = true; - } else if (dialogType == ADD_FROM_TABLE || dialogType == ADD_FROM_ARRAYS) { - if (e.getSource() == tableChoice) { - makeSourceColumns(); - addObjectFromTable(); - } else { - boolean columnChanged = false; - for (int c=0; c 0 ? label : null); - } - } - - /** Returns the style String for Plot.setPlotObjectStyle from the dialog fields */ - private String getStyleString() { - String color = colorField.getText(); - String color2 = color2Field.getText(); - double width = Tools.parseDouble(widthField.getText()); - String symbol = symbolChoice.getSelectedItem(); - Boolean visible = visibleCheckbox.getState(); - String style = color.trim()+","+color2.trim()+","+(float)width+","+ symbol+(visible?"":"hidden"); - return style; - } - - /** Sets the style fields of the dialog according to the style of the PlotObject having the - * index given. Does nothing with index < 0 */ - private void setDialogStyleFields(int index) { - if (index < 0) return; - Checkbox visibleC = (Checkbox)gd.getCheckboxes().get(0); - String styleString = plot.getPlotObjectStyle(index); - String designation = plot.getPlotObjectDesignations()[index].toLowerCase(); - boolean isData = designation.startsWith("data"); - boolean isText = designation.startsWith("text"); - boolean isBox = designation.startsWith("shapes") && - (designation.contains("boxes") || designation.contains("rectangles")); - boolean isGrid = designation.startsWith("shapes") && designation.contains("redraw_grid"); - - String[] items = styleString.split(","); - colorField.setText(items[0]); - color2Field.setText(items[1]); - widthField.setText(items[2]); - if (items.length >= 4) - symbolChoice.select(items[3]); - labelField.setText(isData ? plot.getPlotObjectLabel(index) : ""); - visibleC.setState(!styleString.contains("hidden")); - - colorField.setEnabled(!isGrid); //grid color is fixed - color2Field.setEnabled(isData || isBox);//only (some) data symbols and boxes have secondary (fill) color - widthField.setEnabled(!isText && !isGrid); //all non-Text types have line width - // visibleC.setEnabled(!isGrid); //allow to hide everything - symbolChoice.setEnabled(isData); //only data have a symbol to choose - labelField.setEnabled(isData); //only data have a label in the legend - } - - - /** Prepare the lists 'allPlots', 'allPlotNames' for the "Add from Plot" dialog. - * Also sets 'defaultPlotIndex', 'defaultObjectIndex' */ - private void prepareAddFromPlot() { - int[] windowIDlist = WindowManager.getIDList(); - ArrayList plotImps = new ArrayList(); - ImagePlus currentPlotImp = null; - for (int windowID : windowIDlist) { - ImagePlus imp = WindowManager.getImage(windowID); - if (imp == null || imp.getWindow() == null) continue; - Plot thePlot = (Plot)(imp.getProperty(Plot.PROPERTY_KEY)); - if (thePlot != null) { - if (thePlot == plot) - currentPlotImp = imp; - else - plotImps.add(imp); - } - } - if (currentPlotImp != null) - plotImps.add(currentPlotImp); // add current plot as the last one (usually not used) - if (plotImps.size() == 0) return; // should never happen; we have at least the current plot - - allPlots = new Plot[plotImps.size()]; - allPlotNames = new String[plotImps.size()]; - defaultPlotIndex = 0; - for (int i=0; i tableWindows = new ArrayList(); - Frame[] windows = WindowManager.getNonImageWindows(); - for (Frame win : windows) { - if (!(win instanceof TextWindow)) continue; - ResultsTable rt = ((TextWindow)win).getResultsTable(); - if (isValid(rt)) - tableWindows.add((TextWindow)win); - } - allTables = new ResultsTable[tableWindows.size()]; - allTableNames = new String[tableWindows.size()]; - defaultTableIndex = 0; - for (int i=0; i 0) { - String[] newHeadings = new String[columnHeadings.length - nBadColumns]; - int i=0; - for (String heading : columnHeadings) //copy 'good' headings - if (heading != null) - newHeadings[i++] = heading; - columnHeadings = newHeadings; - } - } else { // if (dialogType == ADD_FROM_ARRAYS) - columnHeadings = new String[arrayHeadings.length+1]; - System.arraycopy(arrayHeadings, 0, columnHeadings, 1, arrayHeadings.length); - } - columnHeadings[0] = "---"; - for (int c=0; c 0 && previousColumns[c] >= 0) - columnChoice[c].select(Math.min(columnChoice[c].getItemCount()-1, previousColumns[c])); - } - } - - /** For "Add from Table" and "Add from Arrays" adds item to the plot according to the current Choice settings - * and sets the Style fields for it. */ - private void addObjectFromTable() { - float[][] data = getDataArrays(); - if (data[1] == null) return; //no y data? then can't plot - String label = columnChoice[1].getSelectedItem(); //take label from y - int shape = Plot.toShape(symbolChoice.getSelectedItem()); - float lineWidth = (float)(Tools.parseDouble(widthField.getText())); - if (lineWidth > 0) - plot.setLineWidth(lineWidth); - plot.restorePlotObjects(); - if (savedLimits != null) - plot.setLimits(savedLimits); - plot.setColor(colorField.getText(), color2Field.getText()); - plot.addPoints(data[0], data[1], data[3], shape, label); - if (data[2] != null) - plot.addHorizontalErrorBars(data[2]); - if (creatingPlot) { - plot.setXYLabels(data[0]==null ? "x" : columnChoice[0].getSelectedItem(), columnChoice[1].getSelectedItem()); - plot.setLimitsToFit(false); - } else - plot.fitRangeToLastPlotObject(); - currentObjectIndex = plot.getNumPlotObjects()-1; - setDialogStyleFields(currentObjectIndex); - if (dialogType == ADD_FROM_TABLE) - previousTableName = allTableNames[tableChoice.getSelectedIndex()]; - } - - /** For "Add from Table" and "Add from Arrays", tries to set a 'y' data column that has not been plotted yet. */ - private void suggestNewYColumn() { - int nYcolumns = columnChoice[1].getItemCount(); - int currentIndex = columnChoice[1].getSelectedIndex(); - for (int i=0; i= 0) - data[c] = rt.getColumn(index); - previousColumns[c] = columnChoice[c].getSelectedIndex(); - } - } else { //if (dialogType == ADD_FROM_ARRAYS) - for (int c=0; c= 0) - data[c] = arrayData.get(index); - previousColumns[c] = columnChoice[c].getSelectedIndex(); - } - } - return data; - } - - /** Does the curve fit and adds the fit curve to the plot */ - private void addFitCurve() { - plot.restorePlotObjects(); - if (savedLimits != null) - plot.setLimits(savedLimits); - int dataIndex = fitDataChoice.getSelectedIndex(); - float[][] data = plot.getDataObjectArrays(dataIndex); - String fitName = fitFunctionChoice.getSelectedItem(); - int fitType = getIndex(CurveFitter.fitList, fitName); - CurveFitter cf = new CurveFitter(Tools.toDouble(data[0]), Tools.toDouble(data[1])); - cf.doFit(fitType); - String statusString = "Fit: "+Minimizer.STATUS_STRING[cf.getStatus()]; - if (cf.getStatus() == Minimizer.SUCCESS) - statusString += ", sum residuals ^2 = "+(float)(cf.getSumResidualsSqr()); - IJ.showStatus(statusString); - curveFitterStatusString = "Fit for "+plot.getTitle()+": "+fitDataChoice.getSelectedItem()+cf.getResultString(); //will be shown in Log when done - - double[] plotMinMax = plot.getLimits(); - double[] dataMinMax = Tools.getMinMax(data[0]); - double min = Math.min(plotMinMax[0], dataMinMax[0]); - double max = Math.max(plotMinMax[1], dataMinMax[1]); - double plotSpan = Math.abs(plotMinMax[1] - plotMinMax[0]); - double dataSpan = Math.abs(dataMinMax[1] - dataMinMax[0]); - double rangeFactor = Math.max(plotSpan/dataSpan, dataSpan/plotSpan); - if (rangeFactor > 20) rangeFactor = 20; - int nPoints = (int)(1000*rangeFactor); //finer data point spacing if we will want to zoom out or in - float[] xFit = new float[nPoints]; - float[] yFit = new float[nPoints]; - for (int i=0; i=3; - else - return columnHeadingStr.length() >= 1; - - } - - /** For "Add from Arrays", sets default columns from the colums titles */ - private void setDefaultColumns(String[] defaultHeadings) { - if (defaultHeadings == null) return; - for (int i=0; i 190 ? 255 : 255 - (int)(0.4*(255-v)); - } -} diff --git a/com.eco.bio7.image/src/ij/gui/PlotDialog.java b/com.eco.bio7.image/src/ij/gui/PlotDialog.java deleted file mode 100644 index bad6e4e9e..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotDialog.java +++ /dev/null @@ -1,606 +0,0 @@ -package ij.gui; - -import ij.*; -import ij.process.*; -import ij.plugin.frame.Recorder; -import java.awt.*; -import java.util.Vector; - -import org.eclipse.swt.widgets.Display; - -import com.eco.bio7.image.Util; - -/* - * This class contains dialogs for formatting of plots (range, axes, labels, legend, creating a high-resolution plot) - * Adding and formatting of contents (curves, symbols, ...) is in PlotContentsStyleDialog - */ - -public class PlotDialog implements DialogListener { - - /** - * Types of dialog. Note that 10-14 must be the same as the corresponding - * PlotWindow.rangeArrow numbers - */ - public static final int SET_RANGE = 0, AXIS_OPTIONS = 1, LEGEND = 2, HI_RESOLUTION = 3, TEMPLATE = 4, //5-9 spare - X_LEFT = 10, X_RIGHT = 11, Y_BOTTOM = 12, Y_TOP = 13, X_AXIS = 14, Y_AXIS = 15; - /** Dialog headings for the dialogTypes */ - private static final String[] HEADINGS = new String[] { "Plot Range", "Axis Options", "Add Legend", "High-Resolution Plot", "Use Template", null, null, null, null, null, // 5-9 spare - "X Left", "X Right", "Y Bottom", "Y Top", "X Axis", "Y Axis" }; - /** Positions and corresponding codes for legend position */ - 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 }; - /** - * Template "copy what" flag: dialog texts and corresponding bit masks, in the - * sequence as they appear in the dialog - */ - private static final String[] TEMPLATE_FLAG_NAMES = new String[] { "X Range", "Y Range", "Axis Style", "Labels", "Legend", "Contents Style", "Extra Objects (Curves...)", "Window Size" }; - private static final int[] TEMPLATE_FLAGS = new int[] { Plot.X_RANGE, Plot.Y_RANGE, Plot.COPY_AXIS_STYLE, Plot.COPY_LABELS, Plot.COPY_LEGEND, Plot.COPY_CONTENTS_STYLE, Plot.COPY_EXTRA_OBJECTS, - Plot.COPY_SIZE }; - - private Plot plot; - private int dialogType; - private boolean minMaxSaved; //whether plot min&max has been saved for "previous range" - private boolean dialogShowing; //when the dialog is showing, ignore the last call with event null - private Plot[] templatePlots; - - private Checkbox xLogCheckbox, yLogCheckbox; - - //saved dialog options: legend - private static int legendPosNumber = 0; - private static boolean bottomUp; - private static boolean transparentBackground; - //saved dialog options: Axis labels - private static String lastXLabel, lastYLabel; - private static float plotFontSize; - //saved dialog options: High-resolution plot - private static float hiResFactor = 4.0f; - private static boolean hiResAntiAliased = true; - //saved dialog options: Use Template - private static int templateID; - private static int lastTemplateFlags = Plot.COPY_AXIS_STYLE | Plot.COPY_CONTENTS_STYLE; - - /** Constructs a new PlotDialog for a given plot and sets the type of dialog */ - public PlotDialog(Plot plot, int dialogType) { - this.plot = plot; - this.dialogType = dialogType; - } - - /** - * Asks the user for axis scaling; then replot with new scale on the same - * ImageProcessor. The 'parent' frame may be null - */ - public void showDialog(Frame parent) { - if (dialogType == HI_RESOLUTION) { //'make high-resolution plot' dialog has no preview, handled separately - doHighResolutionDialog(parent); - return; - } - plot.savePlotPlotProperties(); - if (dialogType == TEMPLATE) - plot.savePlotObjects(); - - String dialogTitle = dialogType >= X_LEFT && dialogType <= Y_TOP ? "Set Axis Limit..." : (HEADINGS[dialogType] + "..."); - GenericDialog gd = parent == null ? new GenericDialog(dialogTitle) : new GenericDialog(dialogTitle, parent); - if (!setupDialog(gd)) - return; - gd.addDialogListener(this); - dialogItemChanged(gd, null); //preview immediately - dialogShowing = true; - gd.showDialog(); - if (gd.wasCanceled()) { - plot.restorePlotProperties(); - if (dialogType == TEMPLATE) - plot.restorePlotObjects(); - plot.update(); - } else { - if (IJ.recording()) - record(); - String xAxisLabel = plot.getLabel('x'); - if ((dialogType == AXIS_OPTIONS || dialogType == X_AXIS) && xAxisLabel != null && xAxisLabel.length() > 0) - lastXLabel = xAxisLabel; //remember for next time, in case we have none - String yAxisLabel = plot.getLabel('y'); - if ((dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) && yAxisLabel != null && yAxisLabel.length() > 0) - lastYLabel = yAxisLabel; - if (dialogType == SET_RANGE || dialogType == X_AXIS || dialogType == Y_AXIS) - plot.makeLimitsDefault(); - if (dialogType == TEMPLATE) - lastTemplateFlags = plot.templateFlags; - - } - plot.killPlotPropertiesSnapshot(); - if (dialogType == TEMPLATE) - plot.killPlotObjectsSnapshot(); - - ImagePlus imp = plot.getImagePlus(); - ImageWindow win = imp == null ? null : imp.getWindow(); - if (win instanceof PlotWindow) - ((PlotWindow) win).hideRangeArrows(); // arrows etc might be still visible, but the mouse maybe elsewhere - - if (!gd.wasCanceled() && !gd.wasOKed()) { // user has pressed "Set all limits" or "Set Axis Options" button - int newDialogType = (dialogType == SET_RANGE) ? AXIS_OPTIONS : SET_RANGE; - new PlotDialog(plot, newDialogType).showDialog(parent); - } - } - - /** - * Setting up the dialog fields and initial parameters. The input is read in the - * dialogItemChanged method, which must have exactly the same structure of 'if' - * blocks and matching 'get' methods for each input field. - * - * @return false on error - */ - private boolean setupDialog(GenericDialog gd) { - double[] currentMinMax = plot.getLimits(); - 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, 0); - if (dialogType == SET_RANGE || dialogType == X_AXIS) { - gd.addNumericField("X_From", currentMinMax[0], xDigits, 6, "*"); - gd.addToSameRow(); - gd.addNumericField("To", currentMinMax[1], xDigits, 6, "*"); - gd.setInsets(0, 20, 0); //top, left, bottom - 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))); - xLogCheckbox = lastCheckboxAdded(gd); - enableDisableLogCheckbox(xLogCheckbox, currentMinMax[0], currentMinMax[1]); - } - int yDigits = plot.logYAxis ? -2 : Plot.getDigits(currentMinMax[2], currentMinMax[3], 0.005 * Math.abs(currentMinMax[3] - currentMinMax[2]), 6, 0); - if (dialogType == SET_RANGE || dialogType == Y_AXIS) { - gd.setInsets(20, 0, 3); //top, left, bottom - gd.addNumericField("Y_From", currentMinMax[2], yDigits, 6, "*"); - gd.addToSameRow(); - gd.addNumericField("To", currentMinMax[3], yDigits, 6, "*"); - 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))); - yLogCheckbox = lastCheckboxAdded(gd); - enableDisableLogCheckbox(yLogCheckbox, currentMinMax[2], currentMinMax[3]); - } - if (dialogType >= X_LEFT && dialogType <= Y_TOP) { - int digits = dialogType < Y_BOTTOM ? xDigits : yDigits; - gd.addNumericField(HEADINGS[dialogType], currentMinMax[dialogType - X_LEFT], digits, 6, "*"); - } - - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS || dialogType == Y_AXIS) { - int flags = plot.getFlags(); - 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 }; - int rows = xFlags.length; - int columns = dialogType == AXIS_OPTIONS ? 2 : 1; - String[] allLabels = new String[rows * columns]; - boolean[] defaultValues = new boolean[rows * columns]; - String[] headings = dialogType == AXIS_OPTIONS ? new String[] { "X Axis", "Y Axis" } : null; - int i = 0; - for (int l = 0; l < xFlags.length; l++) { - String label = labels[l]; - boolean xFlag = getFlag(flags, xFlags[l]); - boolean yFlag = getFlag(flags, xFlags[l] << 1); //y flags are shifted up one bit - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) { - allLabels[i] = labels[l]; - defaultValues[i++] = xFlag; - } - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) { - allLabels[i] = labels[l]; - defaultValues[i++] = yFlag; - } - } - if (dialogType == X_AXIS || dialogType == Y_AXIS) - gd.setInsets(15, 20, 0); //top, left, bottom - gd.addCheckboxGroup(rows, columns, allLabels, defaultValues, headings); - if (dialogType == AXIS_OPTIONS) - gd.setInsets(15, 0, 5); //top, left, bottom - - String plotXLabel = plot.getLabel('x'); - String plotYLabel = plot.getLabel('y'); - if ((plotXLabel == null || plotXLabel.equals("Distance (pixels)") || plotXLabel.equals("Distance ( )")) && lastXLabel != null) - plotXLabel = lastXLabel; // suggest last dialog entry if default profile label - if ((plotYLabel == null || plotYLabel.equals("Gray Value")) && lastYLabel != null) - plotYLabel = lastYLabel; - int nChars = 20; - if ((plotXLabel != null && plotXLabel.startsWith("{")) || (plotYLabel != null && plotYLabel.startsWith("{"))) { - nChars = Math.max(nChars, plotXLabel.length()); - nChars = Math.max(nChars, plotYLabel.length()); - } - if (nChars > 80) - nChars = 80; - //plotXLabel = plotXLabel.replace("\n", "|"); //multiline label currently no supported by Plot class - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) - gd.addStringField("X Axis Label", plotXLabel, nChars); - //plotYLabel = plotYLabel.replace("\n", "|"); - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) - gd.addStringField("Y Axis Label", plotYLabel, nChars); - } - if (dialogType == SET_RANGE || dialogType == X_AXIS || dialogType == Y_AXIS) { - Font smallFont = IJ.font10; - gd.setInsets(10, 0, 0); //top, left, bottom - gd.addMessage("* Leave empty for automatic range", smallFont, Color.gray); - gd.setInsets(0, 0, 0); - gd.addMessage("** Requires limits > 0 and max/min > 3", smallFont, Color.gray); - if (dialogType == X_AXIS || dialogType == Y_AXIS) { - gd.setInsets(0, 0, 0); - gd.addMessage(" Label supports !!sub-!! and ^^superscript^^", smallFont, Color.gray); - } - } - - if (dialogType == AXIS_OPTIONS) { - Font plotFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - Font labelFont = plot.getFont('x'); - if (labelFont == null) - labelFont = plotFont; - Font numberFont = plot.getFont('f'); - if (numberFont == null) - numberFont = plotFont; - gd.addNumericField("Number Font Size", numberFont.getSize2D(), 1); - gd.addNumericField("Label Font Size", labelFont.getSize2D(), 1); - //gd.setInsets(0, 20, 0); // no extra space - gd.addToSameRow(); - gd.addCheckbox("Bold", labelFont.isBold()); - } - if (dialogType == LEGEND) { - String labels = plot.getDataLabels(); - int nLines = labels.split("\n", -1).length; - Font legendFont = plot.getFont('l'); - if (legendFont == null) - legendFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - int lFlags = plot.getObjectFlags('l'); - if (lFlags != -1) { //if we have a legend already - for (int i = 0; i < LEGEND_POSITION_N.length; i++) //determine the position option from the flags - if ((lFlags & Plot.LEGEND_POSITION_MASK) == LEGEND_POSITION_N[i]) { - legendPosNumber = i; - break; - } - transparentBackground = getFlag(lFlags, Plot.LEGEND_TRANSPARENT); - bottomUp = getFlag(lFlags, Plot.LEGEND_BOTTOM_UP); - } - gd.addMessage("Enter Labels for the datasets, one per line.\n"); - - Font smallFont = IJ.font10; - gd.setInsets(0, 20, 0); //top, left, bottom - String msg = "Prepend index plus dual underscore (e.g. '1__MyLabel' )\nto control legend order and to hide non-indexed labels"; - gd.addMessage(msg, smallFont, Color.darkGray); - gd.setInsets(0, 0, 0); - - gd.addTextAreas(labels, null, Math.min(nLines + 1, 20), 40); - gd.addChoice("Legend position", LEGEND_POSITIONS, LEGEND_POSITIONS[legendPosNumber]); - gd.addNumericField("Font Size", legendFont.getSize2D(), 1); - - gd.addCheckbox("Transparent background", transparentBackground); - gd.addCheckbox("Bottom-to-top", bottomUp); - } - if (dialogType == TEMPLATE) { - int[] idList = WindowManager.getIDList(); //create list of plots to use as template - int[] plotIdList = new int[idList.length]; - templatePlots = new Plot[idList.length]; - int nPlots = 0; - for (int id : idList) { - ImagePlus imp = WindowManager.getImage(id); - if (imp == null) - continue; - Plot impPlot = (Plot) (imp.getProperty(Plot.PROPERTY_KEY)); - if (impPlot != null && impPlot != this.plot) { - templatePlots[nPlots] = impPlot; - plotIdList[nPlots++] = id; - } - } - if (nPlots == 0) { - IJ.error("No plot to use as template"); - return false; - } - String[] plotImpTitles = new String[nPlots]; - int defaultTemplateIndex = 0; - for (int i = 0; i < nPlots; i++) { - ImagePlus imp = WindowManager.getImage(plotIdList[i]); - plotImpTitles[i] = imp == null ? "" : imp.getTitle(); - if (imp.getID() == templateID) - defaultTemplateIndex = i; - } - gd.addChoice("Template Plot", plotImpTitles, plotImpTitles[defaultTemplateIndex]); - gd.setInsets(10, 0, 0); //top, left, bottom - gd.addMessage("Copy From Template:"); - gd.setInsets(5, 20, 0); //top, left, bottom - if (lastTemplateFlags == 0) - lastTemplateFlags = Plot.COPY_AXIS_STYLE | Plot.COPY_CONTENTS_STYLE; - for (int i = 0; i < TEMPLATE_FLAGS.length; i++) { - boolean flag = getFlag(lastTemplateFlags, TEMPLATE_FLAGS[i]); - gd.addCheckbox(TEMPLATE_FLAG_NAMES[i], flag); - } - } - // Add a button to access another dialog that might be also desired - if (dialogType >= X_LEFT && dialogType <= Y_TOP) - gd.enableYesNoCancel("OK", "Set All Limits..."); - else if (dialogType == AXIS_OPTIONS) - gd.enableYesNoCancel("OK", "Set Range..."); - else if (dialogType == SET_RANGE) - gd.enableYesNoCancel("OK", "Set Axis Options..."); - return true; - } //setupDialog - - /** - * This method is called when the user changes something in the dialog. Note - * that the 'if's for reading the fields must be exactly the same as those for - * setting up the fields in 'setupDialog' (fields must be also read in the same - * sequence). - */ - public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { - if (dialogShowing && e==null) - return true; //gets called with e=null upon OK; ignore this - boolean livePlot = plot.plotMaker != null; - - if (dialogType == SET_RANGE || dialogType == X_AXIS) { - double[] currentMinMax = plot.getLimits(); - double linXMin = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linXMin = Double.NaN; - double linXMax = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linXMax = Double.NaN; - if (linXMin == linXMax) - return false; - if (!minMaxSaved) { - plot.saveMinMax(); //save for 'Previous Range' in plot menu - minMaxSaved = true; - } - if (livePlot) - plot.templateFlags = setFlag(plot.templateFlags, Plot.X_RANGE, gd.getNextBoolean()); - boolean xLog = gd.getNextBoolean(); - plot.setAxisXLog(xLog); - plot.setLimitsNoUpdate(linXMin, linXMax, currentMinMax[2], currentMinMax[3]); - currentMinMax = plot.getLimits(); - enableDisableLogCheckbox(xLogCheckbox, currentMinMax[0], currentMinMax[1]); - } - if (dialogType == SET_RANGE || dialogType == Y_AXIS) { - double[] currentMinMax = plot.getLimits(); - double linYMin = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linYMin = Double.NaN; - double linYMax = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linYMax = Double.NaN; - if (linYMin == linYMax) - return false; - if (!minMaxSaved) { - plot.saveMinMax(); //save for 'Previous Range' in plot menu - minMaxSaved = true; - } - - if (livePlot) - plot.templateFlags = setFlag(plot.templateFlags, Plot.Y_RANGE, gd.getNextBoolean()); - boolean yLog = gd.getNextBoolean(); - plot.setAxisYLog(yLog); - plot.setLimitsNoUpdate(currentMinMax[0], currentMinMax[1], linYMin, linYMax); - currentMinMax = plot.getLimits(); - enableDisableLogCheckbox(yLogCheckbox, currentMinMax[2], currentMinMax[3]); - } - if (dialogType >= X_LEFT && dialogType <= Y_TOP) { - double newLimit = gd.getNextNumber(); - double[] minMaxCopy = (double[]) (plot.getLimits().clone()); - minMaxCopy[dialogType - X_LEFT] = newLimit; - plot.setLimitsNoUpdate(minMaxCopy[0], minMaxCopy[1], minMaxCopy[2], minMaxCopy[3]); - } - - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS || dialogType == Y_AXIS) { - final int[] xFlags = new int[] { Plot.X_GRID, Plot.X_TICKS, Plot.X_MINOR_TICKS, Plot.X_LOG_TICKS, Plot.X_NUMBERS }; - int rows = xFlags.length; - int columns = dialogType == AXIS_OPTIONS ? 2 : 1; - int flags = 0; - if (dialogType == X_AXIS) - flags = plot.getFlags() & 0xaaaaaaaa; //keep y flags, i.e., odd bits - if (dialogType == Y_AXIS) - flags = plot.getFlags() & 0x55555555; //keep x flags, i.e., even bits - for (int l = 0; l < xFlags.length; l++) { - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) - if (gd.getNextBoolean()) - flags |= xFlags[l]; - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) - if (gd.getNextBoolean()) - flags |= xFlags[l] << 1; //y flags are shifted up one bit; - } - plot.setFormatFlags(flags); - - String xAxisLabel = plot.getLabel('x'); - String yAxisLabel = plot.getLabel('y'); - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) { - xAxisLabel = gd.getNextString(); - //xAxisLabel = xAxisLabel.replace("|", "\n"); //multiline label currently not supported by Plot class - } - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) { - yAxisLabel = gd.getNextString(); - //yAxisLabel = yAxisLabel.replace("|", "\n"); - } - plot.setXYLabels(xAxisLabel, yAxisLabel); - } - if (dialogType == AXIS_OPTIONS) { - Font plotFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - Font labelFont = plot.getFont('x'); - if (labelFont == null) - labelFont = plotFont; - Font numberFont = plot.getFont('f'); - if (numberFont == null) - numberFont = plotFont; - - float numberFontSize = (float) gd.getNextNumber(); - if (gd.invalidNumber()) - numberFontSize = numberFont.getSize2D(); - if (numberFontSize < 9) - numberFontSize = 9f; - if (numberFontSize > 24) - numberFontSize = 24f; - float labelFontSize = (float) gd.getNextNumber(); - if (gd.invalidNumber()) - labelFontSize = labelFont.getSize2D(); - boolean axisLabelBold = gd.getNextBoolean(); - plot.setFont('f', numberFont.deriveFont(numberFont.getStyle(), numberFontSize)); - plot.setAxisLabelFont(axisLabelBold ? Font.BOLD : Font.PLAIN, labelFontSize); - Font smallFont = new Font("SansSerif", Font.PLAIN, (int) (10 * Prefs.getGuiScale())); - gd.addMessage("Labels support !!sub-!! and ^^superscript^^", smallFont, Color.gray); - } - if (dialogType == LEGEND) { - Font legendFont = plot.getFont('l'); - if (legendFont == null) - legendFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - - String labels = gd.getNextText(); - legendPosNumber = gd.getNextChoiceIndex(); - int lFlags = LEGEND_POSITION_N[legendPosNumber]; - float legendFontSize = (float) gd.getNextNumber(); - transparentBackground = gd.getNextBoolean(); - bottomUp = gd.getNextBoolean(); - if (bottomUp) - lFlags |= Plot.LEGEND_BOTTOM_UP; - if (transparentBackground) - lFlags |= Plot.LEGEND_TRANSPARENT; - plot.setColor(Color.black); - plot.setLineWidth(1); - plot.setLegend(labels, lFlags); - plot.setFont('l', legendFont.deriveFont(legendFont.getStyle(), legendFontSize)); - } - if (dialogType == TEMPLATE) { - Plot templatePlot = templatePlots[gd.getNextChoiceIndex()]; - ImagePlus imp = templatePlot.getImagePlus(); - if (imp != null) - templateID = imp.getID(); //remember for next time - int templateFlags = 0; - for (int i = 0; i < TEMPLATE_FLAGS.length; i++) - if (gd.getNextBoolean()) - templateFlags |= TEMPLATE_FLAGS[i]; - plot.restorePlotProperties(); - plot.restorePlotObjects(); - plot.useTemplate(templatePlot, templateFlags); - } - - plot.updateImage(); - return true; - } //dialogItemChanged - - /** Macro recording */ - private void record() { - if (Recorder.scriptMode()) - Recorder.recordCall("//plot = IJ.getImage().getProperty(Plot.PROPERTY_KEY);"); - String plotDot = Recorder.scriptMode() ? "plot." : "Plot."; - - if (dialogType == SET_RANGE || dialogType == X_AXIS) - Recorder.recordString(plotDot + (Recorder.scriptMode() ? "setAxisXLog(" : "setLogScaleX(") + plot.hasFlag(Plot.X_LOG_NUMBERS) + ");\n"); - if (dialogType == SET_RANGE || dialogType == Y_AXIS) - Recorder.recordString(plotDot + (Recorder.scriptMode() ? "setAxisYLog(" : "setLogScaleY(") + plot.hasFlag(Plot.Y_LOG_NUMBERS) + ");\n"); - if (dialogType == SET_RANGE || dialogType == X_AXIS || dialogType == Y_AXIS) { - double[] currentMinMax = plot.getLimits(); - int xDigits = plot.logXAxis ? -2 : Plot.getDigits(currentMinMax[0], currentMinMax[1], 0.005 * Math.abs(currentMinMax[1] - currentMinMax[0]), 6, 0); - int yDigits = plot.logYAxis ? -2 : Plot.getDigits(currentMinMax[2], currentMinMax[3], 0.005 * Math.abs(currentMinMax[3] - currentMinMax[2]), 6, 0); - Recorder.recordString(plotDot + "setLimits(" + IJ.d2s(currentMinMax[0], xDigits) + "," + IJ.d2s(currentMinMax[1], xDigits) + "," + IJ.d2s(currentMinMax[2], yDigits) + "," - + IJ.d2s(currentMinMax[3], yDigits) + ");\n"); - } - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS || dialogType == Y_AXIS) { - int flags = plot.getFlags(); - String xAxisLabel = Recorder.fixString(plot.getLabel('x')); - String yAxisLabel = Recorder.fixString(plot.getLabel('y')); - Font labelFont = plot.getFont('x'); - Font numberFont = plot.getFont('f'); - if (labelFont != null) { - if (Recorder.scriptMode()) - Recorder.recordString("plot.setAxisLabelFont(" + (labelFont.isBold() ? "Font.BOLD," : "Font.PLAIN,") + IJ.d2s(labelFont.getSize2D(), 1) + ");\n"); - else - Recorder.recordString("Plot.setAxisLabelSize(" + IJ.d2s(labelFont.getSize2D(), 1) + ", \"" + (labelFont.isBold() ? "bold" : "plain") + "\");\n"); - } - if (numberFont != null) - Recorder.recordString(plotDot + (Recorder.scriptMode() ? "setFont(-1, " : "setFontSize(") + IJ.d2s(numberFont.getSize2D(), 1) + ");\n"); - Recorder.recordString(plotDot + "setXYLabels(\"" + xAxisLabel + "\", \"" + yAxisLabel + "\");\n"); - Recorder.recordString(plotDot + "setFormatFlags(" + (Recorder.scriptMode() ? "0x" + Integer.toHexString(flags) : '\"' + Integer.toString(flags, 2) + '\"') + ");\n"); - } - if (dialogType == LEGEND) { - String labels = Recorder.fixString(plot.getDataLabels()); - int lFlags = plot.getObjectFlags('l'); - if (Recorder.scriptMode()) { - Recorder.recordCall("plot.setColor(Color.black);"); - Recorder.recordCall("plot.setLineWidth(1);"); - Recorder.recordCall("plot.addLegend(\"" + labels + "\", 0x" + Integer.toHexString(lFlags) + ");"); - } else { - String options = LEGEND_POSITIONS[legendPosNumber]; - if (getFlag(lFlags, Plot.LEGEND_BOTTOM_UP)) - options += " Bottom-To-Top"; - if (getFlag(lFlags, Plot.LEGEND_TRANSPARENT)) - options += " Transparent"; - Recorder.recordString("Plot.addLegend(\"" + labels + "\", \"" + options + "\");\n"); - } - } - - if (Recorder.scriptMode()) - Recorder.recordCall("plot.update();"); - } - - /** The dialog for "Make High Resolution Plot"; it has no preview */ - private void doHighResolutionDialog(Frame parent) { - GenericDialog gd = parent == null ? new GenericDialog(HEADINGS[dialogType]) : new GenericDialog(HEADINGS[dialogType], parent); - String title = plot.getTitle(); - if (title.toLowerCase().endsWith(".tif") || title.toLowerCase().endsWith(".zip")) - title = title.substring(0, title.length()-4); - title += "_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) //more range checking is done in Plot.setScale - hiResFactor = (float) scale; - hiResAntiAliased = !gd.getNextBoolean(); - /*final ImagePlus hiresImp = plot.makeHighResolution(title, hiResFactor, hiResAntiAliased, showIt=true); - *//** - * The following command is needed to have the high-resolution plot as front - * window. Otherwise, as the dialog is owned by the original PlotWindow, the - * WindowManager will see the original plot as active, but the user interface - * will show the high-res plot as foreground window - *//* - EventQueue.invokeLater(new Runnable() {public void run() {IJ.selectWindow(hiresImp.getID());}});*/ - /* Changed for Bio7. Deadlock with activate tab function! */ - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - String title = plot.getTitle() + "_HiRes"; - - final ImagePlus hiresImp = plot.makeHighResolution(title, hiResFactor, hiResAntiAliased, /* showIt= */true); - IJ.selectWindow(hiresImp.getID()); - } - }); - - if (IJ.recording()) { - if (Recorder.scriptMode()) { - Recorder.recordCall("plot.makeHighResolution(\"" + title + "\"," + hiResFactor + "," + hiResAntiAliased + ",true);"); - } else { - String options = !hiResAntiAliased ? "disable" : ""; - if (options.length() > 0) - options = ",\"" + options + "\""; - Recorder.recordString("Plot.makeHighResolution(\"" + title + "\"," + hiResFactor + options + ");\n"); - } - } - } - - /** - * Disables switching on a checkbox for log range if the axis limits do not - * allow it. The checkbox can be always switched off. - */ - void enableDisableLogCheckbox(Checkbox checkbox, double limit1, double limit2) { - boolean logPossible = limit1 > 0 && limit2 > 0 && (limit1 > 3 * limit2 || limit2 > 3 * limit1); - checkbox.setEnabled(logPossible); - } - - 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; - } - - Checkbox lastCheckboxAdded(GenericDialog gd) { - Vector checkboxes = gd.getCheckboxes(); - return (Checkbox) (checkboxes.get(checkboxes.size() - 1)); - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/PlotMaker.java b/com.eco.bio7.image/src/ij/gui/PlotMaker.java deleted file mode 100644 index ddaef8a3b..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotMaker.java +++ /dev/null @@ -1,15 +0,0 @@ -package ij.gui; -import ij.ImagePlus; - -/** Plugins that generate "Live" profile plots (Profiler and ZAxisProfiler) - displayed in PlotWindows implement this interface. */ -public interface PlotMaker { - - /** Returns a profile plot. */ - public Plot getPlot(); - - /** Returns the ImagePlus used to generate the profile plots. */ - public ImagePlus getSourceImage(); - -} - diff --git a/com.eco.bio7.image/src/ij/gui/PlotVirtualStack.java b/com.eco.bio7.image/src/ij/gui/PlotVirtualStack.java deleted file mode 100644 index 7bac94ed2..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotVirtualStack.java +++ /dev/null @@ -1,84 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import java.util.*; -import java.io.*; - -/** This is a virtual stack of frozen plots. */ -public class PlotVirtualStack extends VirtualStack { - private Vector plots = new Vector(50); - private int bitDepth = 8; - - public PlotVirtualStack(int width, int height) { - super(width, height); - } - - /** Adds a plot to the end of the stack. */ - public void addPlot(Plot plot) { - plots.add(plot.toByteArray()); - if (plot.isColored()) - bitDepth = 24; - } - - /** Returns the pixel array for the specified slice, where {@literal 1<=n<=nslices}. */ - public Object getPixels(int n) { - ImageProcessor ip = getProcessor(n); - if (ip!=null) - return ip.getPixels(); - else - return null; - } - - /** Returns an ImageProcessor for the specified slice, - where {@literal 1<=n<=nslices}. Returns null if the stack is empty. */ - public ImageProcessor getProcessor(int n) { - byte[] bytes = (byte[])plots.get(n-1); - if (bytes!=null) { - try { - Plot plot = new Plot(null, new ByteArrayInputStream(bytes)); - ImageProcessor ip = plot.getProcessor(); - if (bitDepth==24) - ip = ip.convertToRGB(); - else if (bitDepth==8) - ip = ip.convertToByte(false); - ip.setSliceNumber(n); - return ip; - } catch (Exception e) { - IJ.handleException(e); - } - } - return null; - } - - /** Returns the number of slices in this stack. */ - public int getSize() { - return plots.size(); - } - - /** Returns either 24 (RGB) or 8 (grayscale). */ - public int getBitDepth() { - return bitDepth; - } - - public void setBitDepth(int bitDepth) { - this.bitDepth = bitDepth; - } - - public String getSliceLabel(int n) { - return null; - } - - public void setPixels(Object pixels, int n) { - } - - /** Deletes the specified slice, where {@literal 1<=n<=nslices}. */ - public void deleteSlice(int n) { - if (n<1 || n>plots.size()) - throw new IllegalArgumentException("Argument out of range: "+n); - if (plots.size()<1) - return; - plots.remove(n-1); - } - - -} // PlotVirtualStack \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/PlotWindow.java b/com.eco.bio7.image/src/ij/gui/PlotWindow.java deleted file mode 100644 index 7236b2045..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotWindow.java +++ /dev/null @@ -1,1156 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import java.awt.datatransfer.*; -import java.util.*; - -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import ij.*; -import ij.process.*; -import ij.util.*; -import ij.text.TextWindow; -import ij.plugin.filter.Analyzer; -import ij.plugin.filter.PlugInFilterRunner; -import ij.measure.*; -import ij.io.SaveDialog; -import org.eclipse.swt.custom.CTabFolder; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.PlatformUI; - -import com.eco.bio7.ImageJPluginActions.ImageJContextMenuAction; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.CustomDetachedImageJView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.Util; - -/** - * This class implements the Analyze/Plot Profile command. - * - * @author Michael Schmid - * @author Wayne Rasband - */ -public class PlotWindow extends ImageWindow - implements ActionListener, ItemListener, ClipboardOwner, ImageListener, RoiListener, Runnable { - - private static final int WIDTH = 600; - private static final int HEIGHT = 340; - private static final int FONT_SIZE = 14; - private static final String PREFS_WIDTH = "pp.width"; - private static final String PREFS_HEIGHT = "pp.height"; - private static final String PREFS_FONT_SIZE = "pp.fontsize"; - - /** @deprecated */ - public static final int CIRCLE = Plot.CIRCLE; - /** @deprecated */ - public static final int X = Plot.X; - /** @deprecated */ - public static final int BOX = Plot.BOX; - /** @deprecated */ - public static final int TRIANGLE = Plot.TRIANGLE; - /** @deprecated */ - public static final int CROSS = Plot.CROSS; - /** @deprecated */ - public static final int LINE = Plot.LINE; - /** Write first X column when listing or saving. */ - public static boolean saveXValues = true; - /** - * Automatically close window after saving values. To set, use - * Edit/Options/Plots. - */ - public static boolean autoClose; - /** - * Display the XY coordinates in a separate window. To set, use - * Edit/Options/Plots. - */ - public static boolean listValues; - /** - * Interpolate line profiles. To set, use Edit/Options/Plots or - * setOption("InterpolateLines",boolean). - */ - public static boolean interpolate = true; - // default values for new installations; values will be then saved in prefs - private static int defaultFontSize = Prefs.getInt(PREFS_FONT_SIZE, FONT_SIZE); - /** The width of the plot (without frame) in pixels. */ - public static int plotWidth = WIDTH; - /** The height of the plot in pixels. */ - public static int plotHeight = HEIGHT; - /** - * The plot text size, can be overridden by Plot.setFont, Plot.setFontSize, - * Plot.setXLabelFont etc. - */ - public static int fontSize = defaultFontSize; - /** - * Have axes with no grid lines. If both noGridLines and noTicks are true, only - * min&max value of the axes are given - */ - public static boolean noGridLines; - /** - * Have axes with no ticks. If both noGridLines and noTicks are true, only - * min&max value of the axes are given - */ - public static boolean noTicks; - private static final String OPTIONS = "pp.options"; - private static final int SAVE_X_VALUES = 1; - private static final int AUTO_CLOSE = 2; - private static final int LIST_VALUES = 4; - private static final int INTERPOLATE = 8; - private static final int NO_GRID_LINES = 16; - private static final int NO_TICKS = 32; - private static String moreButtonLabel = "More " + '\u00bb'; - private static String dataButtonLabel = "Data " + '\u00bb'; - - boolean wasActivated; // true after window has been activated once, needed by PlotCanvas - - JButton list; - private JButton data, more, live; - private PopupMenu dataPopupMenu, morePopupMenu; - private static final int NUM_MENU_ITEMS = 20; // how many menu items we have in total - private MenuItem[] menuItems = new MenuItem[NUM_MENU_ITEMS]; - private JLabel statusLabel; - private String userStatusText; - private static String defaultDirectory = null; - private static int options; - private int defaultDigits = -1; - private int markSize = 5; - private static Plot staticPlot; - private Plot plot; - - private PlotMaker plotMaker; - private ImagePlus srcImp; // the source image for live plotting - private Thread bgThread; // thread for plotting (in the background) - private boolean doUpdate; // tells the background thread to update - - private Roi[] rangeArrowRois; // the overlays (arrows etc) for changing the range. Note: #10-15 must - // correspond to PlotDialog.dialogType! - private boolean rangeArrowsVisible; - private int activeRangeArrow = -1; - private static Color inactiveRangeArrowColor = Color.GRAY; - private static Color inactiveRangeRectColor = new Color(0x20404040, true); // transparent gray - private static Color activeRangeArrowColor = Color.RED; - private static Color activeRangeRectColor = new Color(0x18ff0000, true); // transparent red - protected Vector ve; - - // static initializer - static { - options = Prefs.getInt(OPTIONS, SAVE_X_VALUES); - autoClose = (options & AUTO_CLOSE) != 0; - plotWidth = Prefs.getInt(PREFS_WIDTH, WIDTH); - plotHeight = Prefs.getInt(PREFS_HEIGHT, HEIGHT); - Dimension screen = IJ.getScreenSize(); - if (plotWidth > screen.width && plotHeight > screen.height) { - plotWidth = WIDTH; - plotHeight = HEIGHT; - } - } - - /** - * @deprecated replaced by the Plot class. - */ - public PlotWindow(String title, String xLabel, String yLabel, float[] xValues, float[] yValues) { - super(createImage(title, xLabel, yLabel, xValues, yValues)); - plot = staticPlot; - // Changed for Bio7! - ((PlotCanvas) getCanvas()).setPlot(plot); - } - - /** - * @deprecated replaced by the Plot class. - */ - public PlotWindow(String title, String xLabel, String yLabel, double[] xValues, double[] yValues) { - this(title, xLabel, yLabel, Tools.toFloat(xValues), Tools.toFloat(yValues)); - } - - /** - * Creates a PlotWindow from a given ImagePlus with a Plot object. (called when - * reading an ImagePlus with an associated plot from a file) - */ - public PlotWindow(ImagePlus imp, Plot plot) { - super(imp); - // Changed for Bio7! - ((PlotCanvas) getCanvas()).setPlot(plot); - this.plot = plot; - draw(); - } - - /** Creates a PlotWindow from a Plot object. */ - PlotWindow(Plot plot) { - super(plot.getImagePlus()); - // Changed for Bio7! - ((PlotCanvas) getCanvas()).setPlot(plot); - this.plot = plot; - draw(); - } - - /** - * Called by the constructor to generate the image the plot will be drawn on. - * This is a static method because constructors cannot call instance methods. - */ - static ImagePlus createImage(String title, String xLabel, String yLabel, float[] xValues, float[] yValues) { - staticPlot = new Plot(title, xLabel, yLabel, xValues, yValues); - return new ImagePlus(title, staticPlot.getBlankProcessor()); - } - - /** - * Sets the x-axis and y-axis range. - * - * @deprecated use the corresponding method of the Plot class - */ - public void setLimits(double xMin, double xMax, double yMin, double yMax) { - plot.setLimits(xMin, xMax, yMin, yMax); - } - - /** - * Adds a set of points to the plot or adds a curve if shape is set to LINE. - * Note that there are more options available by using the methods of the Plot - * class instead. - * - * @param x the x-coodinates - * @param y the y-coodinates - * @param shape Plot.CIRCLE, X, BOX, TRIANGLE, CROSS, LINE etc. - * @deprecated use the corresponding method of the Plot class - */ - public void addPoints(float[] x, float[] y, int shape) { - plot.addPoints(x, y, shape); - } - - /** - * Adds a set of points to the plot using double arrays. Must be called before - * the plot is displayed. Note that there are more options available by using - * the methods of the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void addPoints(double[] x, double[] y, int shape) { - addPoints(Tools.toFloat(x), Tools.toFloat(y), shape); - } - - /** - * Adds vertical error bars to the plot. Must be called before the plot is - * displayed. Note that there are more options available by using the methods of - * the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void addErrorBars(float[] errorBars) { - plot.addErrorBars(errorBars); - } - - /** - * Draws a label. Note that there are more options available by using the - * methods of the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void addLabel(double x, double y, String label) { - plot.addLabel(x, y, label); - } - - /** - * Changes the drawing color. The frame and labels are always drawn in black. - * Must be called before the plot is displayed. Note that there are more options - * available by using the methods of the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void setColor(Color c) { - plot.setColor(c); - } - - /** - * Changes the line width. Must be called before the plot is displayed. Note - * that there are more options available by using the methods of the Plot class - * instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void setLineWidth(int lineWidth) { - plot.setLineWidth(lineWidth); - } - - /** - * Changes the font. Must be called before the plot is displayed. Note that - * there are more options available by using the methods of the Plot class - * instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void changeFont(Font font) { - plot.changeFont(font); - } - - /** Displays the plot. */ - public void draw() { - JPanel bottomPanel = new JPanel(); - Color primarySWTToAwtColor = ImageJ.getPrimarySWTToAwtColor(); - /* - * Changed for Bio7! AWT must be colored per component. All JPanels will get the - * SWT background from the definition of the CanvasView (UIManager)! - */ - Color swtBackgroundToAWT = Util.getSWTBackgroundToAWT(); - Color swtForegroundToAWT = Util.getSWTForegroundToAWT(); - //if (Util.getOS().equals("Linux")) { - bottomPanel.setBackground(swtBackgroundToAWT); - bottomPanel.setForeground(swtForegroundToAWT); - //} - //bottomPanel.setBackground(primarySWTToAwtColor); - int hgap = IJ.isMacOSX() ? 1 : 5; - - list = new JButton(" List "); - list.setBackground(swtBackgroundToAWT); - list.setForeground(swtForegroundToAWT); - list.setBorderPainted(false); - list.addActionListener(this); - bottomPanel.add(list); - bottomPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, hgap, 0)); - data = new JButton(dataButtonLabel); - data.setBackground(swtBackgroundToAWT); - data.setForeground(swtForegroundToAWT); - data.setBorderPainted(false); - data.addActionListener(this); - bottomPanel.add(data); - more = new JButton(moreButtonLabel); - more.setBackground(swtBackgroundToAWT); - more.setForeground(swtForegroundToAWT); - more.setBorderPainted(false); - more.addActionListener(this); - bottomPanel.add(more); - if (plot != null && plot.getPlotMaker() != null) { - live = new JButton("Live"); - live.setBorderPainted(false); - live.setBackground(swtBackgroundToAWT); - live.setForeground(swtForegroundToAWT); - live.addActionListener(this); - bottomPanel.add(live); - } - statusLabel = new JLabel(); - statusLabel.setFont(new Font("Monospaced", Font.PLAIN, 12)); - statusLabel.setBackground(new Color(220, 220, 220)); - // bottomPanel.add(statusLabel); - - // Changed for Bio7! - //statusLabel.setBackground(primarySWTToAwtColor); - /* - * Changed for Bio7! AWT must be colored per component. All JPanels will get the - * SWT background from the definition of the CanvasView (UIManager)! - */ - //if (Util.getOS().equals("Linux")) { - statusLabel.setBackground(swtBackgroundToAWT); - statusLabel.setForeground(swtForegroundToAWT); - //} - - bottomPanel.add(statusLabel); - add(bottomPanel); - data.add(getDataPopupMenu()); - more.add(getMorePopupMenu()); - plot.draw(); - LayoutManager lm = getLayout(); - if (lm instanceof ImageLayout) - ((ImageLayout) lm).ignoreNonImageWidths(true); // don't expand size to make the panel fit - GUI.scale(bottomPanel); - maximizeCoordinatesLabelWidth(); - /* Changed for Bio7. Pack causes deadlock on MacOSX with detached view! */ - // pack(); - /* Changed for Bio7. Introduced a pause for the plot display!*/ - IJ.wait(200); - ImageProcessor ip = plot.getProcessor(); - boolean ipIsColor = ip instanceof ColorProcessor; - boolean impIsColor = imp.getProcessor() instanceof ColorProcessor; - if (ipIsColor != impIsColor) - imp.setProcessor(null, ip); - else - imp.updateAndDraw(); - if (listValues) - showList(/*useLabels=*/false); - else - ic.requestFocus(); // have focus on the canvas, not the button, so that pressing the space bar - // allows panning - if (Prefs.autoLivePlots && bgThread==null) - enableLivePlot(); - /* - * Changed for Bio7! - */ - - Display display = Util.getDisplay(); - display.syncExec(new Runnable() { - public void run() { - CanvasView.parent2.layout(); - CTabFolder ctab = CanvasView.getCanvas_view().tabFolder; - ve = (Vector>) ctab.getSelection().getData(); - JPanel current = (JPanel) ve.get(2); - current.add(bottomPanel); - } - }); - CanvasView.getCanvas_view().getCurrent().validate(); - } - - /** - * Sets the Plot object shown in this PlotWindow. Does not update the window. - */ - public void setPlot(Plot plot) { - this.plot = plot; - ((PlotCanvas) getCanvas()).setPlot(plot); - } - - /** Releases the resources used by this PlotWindow */ - public void dispose() { - if (plot != null) - plot.dispose(); - disableLivePlot(); - plot = null; - plotMaker = null; - srcImp = null; - super.dispose(); - } - - /** - * Called when the window is activated (WindowListener) Window layout is - * finished at latest a few millisec after windowActivated, then the - * 'wasActivated' boolean is set to tell the ImageCanvas that resize events - * should lead to resizing the canvas (before, creating the layout can lead to - * resize events) - */ - public void windowActivated(WindowEvent e) { - super.windowActivated(e); - if (!wasActivated) { - new Thread(new Runnable() { - public void run() { - IJ.wait(50); // sometimes, window layout is done only a few millisec after windowActivated - wasActivated = true; - } - }).start(); - } - } - - /** Called when the canvas is resized */ - void canvasResized() { - if (plot == null) - return; - /*Dimension d1 = getExtraSize(); - Dimension d2 = plot.getMinimumSize(); - setMinimumSize(new Dimension(d1.width + d2.width, d1.height + d2.height));*/ - maximizeCoordinatesLabelWidth(); - } - - /** - * Maximizes the width for the coordinate&status readout field and its parent - * bottomPanel - */ - void maximizeCoordinatesLabelWidth() { - Insets insets = getInsets(); // by default, left & right insets are 0 anyhow - Component parent = statusLabel.getParent(); // the bottomPanel, has insets of 0 - if (!parent.isValid()) - parent.validate(); - int cWidth = getWidth() - 2 * HGAP - statusLabel.getX() - insets.left - insets.right; - int cHeight = statusLabel.getPreferredSize().height; - statusLabel.setPreferredSize(new Dimension(cWidth, cHeight)); - parent.setSize(getWidth() - 2 * HGAP, parent.getHeight()); - } - - /** - * Shows the text in the coordinate&status readout field at the bottom. This - * text may get temporarily replaced for 'tooltips' (mouse over range arrows - * etc.). Call with a null argument to enable coordinate readout again. - */ - public void showStatus(String text) { - userStatusText = text; - if (statusLabel != null) - statusLabel.setText(text == null ? "" : text); - } - - /** - * Names for popupMenu items. Update NUM_MENU_ITEMS at the top when adding new - * ones! - */ - private static int SAVE = 0, COPY = 1, COPY_ALL = 2, LIST_SIMPLE = 3, ADD_FROM_TABLE = 4, ADD_FROM_PLOT = 5, - ADD_FIT = 6, // data menu - SET_RANGE = 7, PREV_RANGE = 8, RESET_RANGE = 9, FIT_RANGE = 10, // the rest is in the more menu - ZOOM_SELECTION = 11, AXIS_OPTIONS = 12, LEGEND = 13, STYLE = 14, TEMPLATE = 15, RESET_PLOT = 16, - FREEZE = 17, HI_RESOLUTION = 18, PROFILE_PLOT_OPTIONS = 19; - // the following commands are disabled when the plot is frozen - private static int[] DISABLED_WHEN_FROZEN = new int[] { ADD_FROM_TABLE, ADD_FROM_PLOT, ADD_FIT, SET_RANGE, - PREV_RANGE, RESET_RANGE, FIT_RANGE, ZOOM_SELECTION, AXIS_OPTIONS, LEGEND, STYLE, RESET_PLOT }; - - /** Prepares and returns the popupMenu of the Data>> button */ - PopupMenu getDataPopupMenu() { - dataPopupMenu = new PopupMenu(); - GUI.scalePopupMenu(dataPopupMenu); - menuItems[SAVE] = addPopupItem(dataPopupMenu, "Save Data..."); - menuItems[COPY] = addPopupItem(dataPopupMenu, "Copy 1st Data Set"); - menuItems[COPY_ALL] = addPopupItem(dataPopupMenu, "Copy All Data"); - menuItems[LIST_SIMPLE] = addPopupItem(dataPopupMenu, "List (Simple Headings)"); - dataPopupMenu.addSeparator(); - menuItems[ADD_FROM_TABLE] = addPopupItem(dataPopupMenu, "Add from Table..."); - menuItems[ADD_FROM_PLOT] = addPopupItem(dataPopupMenu, "Add from Plot..."); - menuItems[ADD_FIT] = addPopupItem(dataPopupMenu, "Add Fit..."); - return dataPopupMenu; - } - - /** Prepares and returns the popupMenu of the More>> button */ - PopupMenu getMorePopupMenu() { - morePopupMenu = new PopupMenu(); - GUI.scalePopupMenu(morePopupMenu); - menuItems[SET_RANGE] = addPopupItem(morePopupMenu, "Set Range..."); - menuItems[PREV_RANGE] = addPopupItem(morePopupMenu, "Previous Range"); - menuItems[RESET_RANGE] = addPopupItem(morePopupMenu, "Reset Range"); - menuItems[FIT_RANGE] = addPopupItem(morePopupMenu, "Set Range to Fit All"); - menuItems[ZOOM_SELECTION] = addPopupItem(morePopupMenu, "Zoom to Selection"); - morePopupMenu.addSeparator(); - menuItems[AXIS_OPTIONS] = addPopupItem(morePopupMenu, "Axis Options..."); - menuItems[LEGEND] = addPopupItem(morePopupMenu, "Legend..."); - menuItems[STYLE] = addPopupItem(morePopupMenu, "Contents Style..."); - menuItems[TEMPLATE] = addPopupItem(morePopupMenu, "Use Template..."); - menuItems[RESET_PLOT] = addPopupItem(morePopupMenu, "Reset Format"); - menuItems[FREEZE] = addPopupItem(morePopupMenu, "Freeze Plot", true); - menuItems[HI_RESOLUTION] = addPopupItem(morePopupMenu, "High-Resolution Plot..."); - morePopupMenu.addSeparator(); - menuItems[PROFILE_PLOT_OPTIONS] = addPopupItem(morePopupMenu, "Plot Defaults..."); - return morePopupMenu; - } - - MenuItem addPopupItem(PopupMenu popupMenu, String s) { - return addPopupItem(popupMenu, s, false); - } - - MenuItem addPopupItem(PopupMenu popupMenu, String s, boolean isCheckboxItem) { - MenuItem mi = null; - if (isCheckboxItem) { - mi = new CheckboxMenuItem(s); - ((CheckboxMenuItem) mi).addItemListener(this); - } else { - mi = new MenuItem(s); - mi.addActionListener(this); - } - popupMenu.add(mi); - return mi; - } - - /*Changed for Bio7*/ - public void actionPerformed(ActionEvent e) { - // String label = e.getActionCommand(); - Object b = e.getSource(); - if (b == live) { - toggleLivePlot(); - } else if (b == data) { - enableDisableMenuItems(); - Component c = (Component) b; - Point loc = c.getLocationOnScreen(); - // dataPopupMenu.show((Component) b, 1, 1); - /*Changed for Bio7*/ - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction icma = instance.getImageContextMenuAction(); - icma.swtPopupMenu(e, dataPopupMenu, new Point(loc.x, loc.y), this); - } else if (b == more) { - enableDisableMenuItems(); - Component c = (Component) b; - Point loc = c.getLocationOnScreen(); - // morePopupMenu.show((Component) b, 1, 1); - /*Changed for Bio7*/ - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction imageContextMenuAction = instance.getImageContextMenuAction(); - imageContextMenuAction.swtPopupMenu(e, morePopupMenu, new Point(loc.x, loc.y), this); - } - - actionPerformed(b); - } - - /*Changed for Bio7 - see above!*/ - /** Called if user has activated a button or popup menu item */ - public void actionPerformed(Object b) { - try { - //System.out.println(b.toString()); - // Object b = e.getSource(); - // if (b == live) - // toggleLiveProfiling(); - if (b == list) - showList(/*useLabels=*/true); - else if (b == data) { - // enableDisableMenuItems(); - // dataPopupMenu.show((Component) b, 1, 1); - } else if (b == more) { - // enableDisableMenuItems(); - // morePopupMenu.show((Component) b, 1, 1); - } else if (b == menuItems[SAVE]) - saveAsText(); - else if (b == menuItems[COPY]) - copyToClipboard(false); - else if (b == menuItems[COPY_ALL]) - copyToClipboard(true); - else if (b == menuItems[LIST_SIMPLE]) - showList(/*useLabels=*/false); - else if (b == menuItems[ADD_FROM_TABLE]) - new PlotContentsDialog(plot, PlotContentsDialog.ADD_FROM_TABLE).showDialog(this); - else if (b == menuItems[ADD_FROM_PLOT]) - new PlotContentsDialog(plot, PlotContentsDialog.ADD_FROM_PLOT).showDialog(this); - else if (b == menuItems[ADD_FIT]) - new PlotContentsDialog(plot, PlotContentsDialog.ADD_FIT).showDialog(this); - else if (b == menuItems[ZOOM_SELECTION]) { - if (imp != null && imp.getRoi() != null && imp.getRoi().isArea()) - plot.zoomToRect(imp.getRoi().getBounds()); - } else if (b == menuItems[SET_RANGE]) - new PlotDialog(plot, PlotDialog.SET_RANGE).showDialog(this); - else if (b == menuItems[PREV_RANGE]) - plot.setPreviousMinMax(); - else if (b == menuItems[RESET_RANGE]) - plot.setLimitsToDefaults(true); - else if (b == menuItems[FIT_RANGE]) - plot.setLimitsToFit(true); - else if (b == menuItems[AXIS_OPTIONS]) - new PlotDialog(plot, PlotDialog.AXIS_OPTIONS).showDialog(this); - else if (b == menuItems[LEGEND]) - new PlotDialog(plot, PlotDialog.LEGEND).showDialog(this); - else if (b == menuItems[STYLE]) - new PlotContentsDialog(plot, PlotContentsDialog.STYLE).showDialog(this); - else if (b == menuItems[TEMPLATE]) - new PlotDialog(plot, PlotDialog.TEMPLATE).showDialog(this); - else if (b == menuItems[RESET_PLOT]) { - plot.setFont(Font.PLAIN, fontSize); - plot.setAxisLabelFont(Font.PLAIN, fontSize); - plot.setFormatFlags(Plot.getDefaultFlags()); - plot.setFrameSize(plotWidth, plotHeight); // updates the image only when size changed - int correctionX = plot.leftMargin + plot.rightMargin; - int correctionY = plot.topMargin + plot.bottomMargin; - /* Changed for Bio7. We have no window and have to resize the canvas! */ - plot.getImagePlus().getCanvas().setSize(plotWidth + correctionX, plotHeight + correctionY); - plot.updateImage(); - /* Changed for Bio7 */ - CanvasView view = CanvasView.getCanvas_view(); - if (view != null) { - view.updatePlotCanvas(); - } - } else if (b == menuItems[HI_RESOLUTION]) - new PlotDialog(plot, PlotDialog.HI_RESOLUTION).showDialog(this); - else if (b == menuItems[PROFILE_PLOT_OPTIONS]) - IJ.doCommand("Plots..."); - ic.requestFocus(); // have focus on the canvas, not the button, so that pressing the space bar - // allows panning - } catch (Exception ex) { - IJ.handleException(ex); - } - } - - private void enableDisableMenuItems() { - boolean frozen = plot.isFrozen(); // prepare menu according to 'frozen' state of plot - ((CheckboxMenuItem) menuItems[FREEZE]).setState(frozen); - for (int i : DISABLED_WHEN_FROZEN) - menuItems[i].setEnabled(!frozen); - if (!PlotContentsDialog.tableWindowExists()) - menuItems[ADD_FROM_TABLE].setEnabled(false); - if (plot.getDataObjectDesignations().length == 0) - menuItems[ADD_FIT].setEnabled(false); - } - - /** Called if the user activates/deactivates a CheckboxMenuItem */ - public void itemStateChanged(ItemEvent e) { - if (e.getSource() == menuItems[FREEZE]) { - boolean frozen = ((CheckboxMenuItem) menuItems[FREEZE]).getState(); - plot.setFrozen(frozen); - } - } - - /** - * Updates the X and Y values when the mouse is moved and, if appropriate, - * shows/hides the overlay with the triangular buttons for changing the axis - * range limits. Overrides mouseMoved() in ImageWindow. - * - * @see ij.gui.ImageWindow#mouseMoved - */ - public void mouseMoved(int x, int y) { - super.mouseMoved(x, y); - if (plot == null) - return; - String statusText = null; // coordinate readout, status or tooltip, will be shown in coordinate&status - // line - - // arrows and other symbols for modifying the plot range - if (x < plot.leftMargin || y > plot.topMargin + plot.frameHeight) { - if (!rangeArrowsVisible && !plot.isFrozen()) - showRangeArrows(); - if (activeRangeArrow < 0) // mouse is not on one of the symbols, ignore (nothing to display) - { - } else if (activeRangeArrow < 8) // mouse over an arrow: 0,3,4,7 for increase, 1,2,5,6 for decrease - statusText = ((activeRangeArrow + 1) & 0x02) != 0 ? "Decrease Range" : "Increase Range"; - else if (activeRangeArrow == 8) // it's the 'R' icon - statusText = "Reset Range"; - else if (activeRangeArrow == 9) // it's the 'F' icon - statusText = "Full Range (Fit All)"; - else if (activeRangeArrow >= 10 && activeRangeArrow < 14) // space between arrow-pairs for single number - statusText = "Set limit..."; - else if (activeRangeArrow >= 14) - statusText = "Axis Range & Options..."; - boolean repaint = false; - if (activeRangeArrow >= 0 && !rangeArrowRois[activeRangeArrow].contains(x, y)) { - rangeArrowRois[activeRangeArrow] - .setFillColor(activeRangeArrow < 10 ? inactiveRangeArrowColor : inactiveRangeRectColor); - repaint = true; // de-highlight arrow where cursor has moved out - activeRangeArrow = -1; - } - if (activeRangeArrow < 0) { // no currently highlighted arrow, do we have a new one? - int i = getRangeArrowIndex(x, y); - if (i >= 0) { // we have an arrow or symbol at cursor position - rangeArrowRois[i].setFillColor(i < 14 ? activeRangeArrowColor : activeRangeRectColor); - activeRangeArrow = i; - repaint = true; - } - } - if (repaint) - ic.repaint(); - } else if (rangeArrowsVisible) - hideRangeArrows(); - if (statusText == null) - statusText = userStatusText != null ? userStatusText : plot.getCoordinates(x, y); - if (statusLabel != null) - statusLabel.setText(statusText); - } - - /** Called by PlotCanvas */ - void mouseExited(MouseEvent e) { - if (rangeArrowsVisible) - hideRangeArrows(); - } - - /** - * Mouse wheel: zooms when shift or ctrl is pressed, scrolls in x if space bar - * down, in y otherwise. - */ - public synchronized void mouseWheelMoved(MouseWheelEvent e) { - if (plot.isFrozen() || !(ic instanceof PlotCanvas)) { // frozen plots are like normal images - super.mouseWheelMoved(e); - return; - } - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - if (e.getX() < plot.leftMargin || e.getX() > plot.leftMargin + plot.frameWidth)// n__ - return; - if (e.getY() < plot.topMargin || e.getY() > plot.topMargin + plot.frameHeight) - return; - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - if (ctrl || IJ.shiftKeyDown()) { - double zoomFactor = rotation < 0 ? Math.pow(2, 0.2) : Math.pow(0.5, 0.2); - Point loc = ic.getCursorLoc(); - int x = ic.screenX(loc.x); - int y = ic.screenY(loc.y); - ((PlotCanvas) ic).zoom(x, y, zoomFactor); - } else if (IJ.spaceBarDown()) - plot.scroll(rotation * amount * Math.max(ic.imageWidth / 50, 1), 0); - else - plot.scroll(0, rotation * amount * Math.max(ic.imageHeight / 50, 1)); - } - - /** - * Creates an overlay with triangular buttons and other symbols for changing the - * axis range limits and shows it - */ - void showRangeArrows() { - if (imp == null) - return; - hideRangeArrows(); // in case we have old arrows from a different plot size or so - rangeArrowRois = new Roi[4 * 2 + 2 + 4 + 2]; // 4 arrows per axis, + 'Reset' and 'Fit All' icons, + 4 numerical - // input boxes + 2 axes - int i = 0; - int height = imp.getHeight(); - int arrowH = plot.topMargin < 14 ? 6 : 8; // height of arrows and distance between them; base is twice that - // value - float[] yP = new float[] { height - arrowH / 2, height - 3 * arrowH / 2, height - 5 * arrowH / 2 - 0.1f }; - - for (float x : new float[] { plot.leftMargin, plot.leftMargin + plot.frameWidth }) { // create arrows for x axis - float[] x0 = new float[] { x - arrowH / 2, x - 3 * arrowH / 2 - 0.1f, x - arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(x0, yP, 3, Roi.POLYGON); - float[] x1 = new float[] { x + arrowH / 2, x + 3 * arrowH / 2 + 0.1f, x + arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(x1, yP, 3, Roi.POLYGON); - } - float[] xP = new float[] { arrowH / 2 - 0.1f, 3 * arrowH / 2, 5 * arrowH / 2 + 0.1f }; - for (float y : new float[] { plot.topMargin + plot.frameHeight, plot.topMargin }) { // create arrows for y axis - float[] y0 = new float[] { y + arrowH / 2, y + 3 * arrowH / 2 + 0.1f, y + arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(xP, y0, 3, Roi.POLYGON); - float[] y1 = new float[] { y - arrowH / 2, y - 3 * arrowH / 2 - 0.1f, y - arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(xP, y1, 3, Roi.POLYGON); - } - Font theFont = new Font("SansSerif", Font.BOLD, 13); - - TextRoi txtRoi = new TextRoi(1, height - 19, "\u2009R\u2009", theFont); // thin spaces to make roi slightly - // wider - rangeArrowRois[8] = txtRoi; - TextRoi txtRoi2 = new TextRoi(20, height - 19, "\u2009F\u2009", theFont); - rangeArrowRois[9] = txtRoi2; - - rangeArrowRois[10] = new Roi(plot.leftMargin - arrowH / 2 + 1, height - 5 * arrowH / 2, arrowH - 2, arrowH * 2);// numerical - // box - // left - rangeArrowRois[11] = new Roi(plot.leftMargin + plot.frameWidth - arrowH / 2 + 1, height - 5 * arrowH / 2, - arrowH - 2, arrowH * 2);// numerical box right - rangeArrowRois[12] = new Roi(arrowH / 2, plot.topMargin + plot.frameHeight - arrowH / 2 + 1, arrowH * 2, - arrowH - 2);// numerical box bottom - rangeArrowRois[13] = new Roi(arrowH / 2, plot.topMargin - arrowH / 2 + 1, arrowH * 2, arrowH - 2);// numerical - // box top - - int topMargin = plot.topMargin; - int bottomMargin = topMargin + plot.frameHeight; - int leftMargin = plot.leftMargin; - int rightMargin = plot.leftMargin + plot.frameWidth; - rangeArrowRois[14] = new Roi(leftMargin, bottomMargin + 2, // area to click for x axis options - rightMargin - leftMargin + 1, 2 * arrowH); - rangeArrowRois[15] = new Roi(leftMargin - 2 * arrowH - 2, topMargin, // area to click for y axis options - 2 * arrowH, bottomMargin - topMargin + 1); - - Overlay ovly = imp.getOverlay(); - if (ovly == null) - ovly = new Overlay(); - for (Roi roi : rangeArrowRois) { - if (roi instanceof PolygonRoi) - roi.setFillColor(inactiveRangeArrowColor); - else if (roi instanceof TextRoi) { - roi.setStrokeColor(Color.WHITE); - roi.setFillColor(inactiveRangeArrowColor); - } else - roi.setFillColor(inactiveRangeRectColor); // transparent gray for single number boxes and axis range - ovly.add(roi); - } - imp.setOverlay(ovly); - ic.repaint(); - rangeArrowsVisible = true; - } - - public void hideRangeArrows() { - if (imp == null || rangeArrowRois == null) - return; - Overlay ovly = imp.getOverlay(); - if (ovly == null) - return; - for (Roi roi : rangeArrowRois) - ovly.remove(roi); - ic.repaint(); - rangeArrowsVisible = false; - activeRangeArrow = -1; - } - - /** - * Returns the index of the range-modifying symbol or axis at the cursor - * position x,y, or -1 of none. Index numbers for arrows start with 0 at the - * 'down' arrow of the lower side of the x axis and end with 7 the up arrow at - * the upper side of the y axis. Numbers 8 & 9 are for "Reset Range" and "Fit - * All"; numbers 10-13 for a dialog to set a single limit, and 14-15 for the - * axis options. - */ - - int getRangeArrowIndex(int x, int y) { - if (!rangeArrowsVisible) - return -1; - for (int i = 0; i < rangeArrowRois.length; i++) - if (rangeArrowRois[i].getBounds().contains(x, y)) - return i; - return -1; - } - - /** Shows the data of the backing plot in a Textwindow with columns */ - void showList(boolean useLabels) { - ResultsTable rt = plot.getResultsTable(saveXValues, useLabels); - if (rt == null) - return; - rt.show("Plot Values"); - if (autoClose) { - imp.changes = false; - close(); - } - } - - /** - * Returns the plot values with simple headings (X, Y, Y1 etc, not the labels) - * as a ResultsTable. Use plot.getResultsTableWithLabels for a table with data - * set labels as column headings - */ - public ResultsTable getResultsTable() { - return plot.getResultsTable(saveXValues); - } - - /** creates the data that fills the showList() function values */ - private String getValuesAsString() { - ResultsTable rt = getResultsTable(); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < rt.size(); i++) { - sb.append(rt.getRowAsString(i)); - sb.append("\n"); - } - return sb.toString(); - } - - /** Saves the data of the plot in a text file */ - void saveAsText() { - if (plot.getXValues() == null) { - IJ.error("Plot has no data"); - return; - } - SaveDialog sd = new SaveDialog("Save as Text", "Values", Prefs.defaultResultsExtension()); - String name = sd.getFileName(); - if (name == null) - return; - String directory = sd.getDirectory(); - IJ.wait(250); // give system time to redraw ImageJ window - IJ.showStatus("Saving plot values..."); - ResultsTable rt = plot.getResultsTable(/*writeFirstXColumn=*/saveXValues, /*useLabels=*/true); - try { - rt.saveAs(directory + name); - } catch (IOException e) { - IJ.error("" + e); - return; - } - if (autoClose) { - imp.changes = false; - close(); - } - } - - /** Copy the first dataset or all values to the clipboard */ - void copyToClipboard(boolean writeAllColumns) { - float[] xValues = plot.getXValues(); - float[] yValues = plot.getYValues(); - if (xValues == null) - return; - Clipboard systemClipboard = null; - try { - systemClipboard = getToolkit().getSystemClipboard(); - } catch (Exception e) { - systemClipboard = null; - } - if (systemClipboard == null) { - IJ.error("Unable to copy to Clipboard."); - return; - } - IJ.showStatus("Copying plot values..."); - CharArrayWriter aw = new CharArrayWriter(10 * xValues.length); - PrintWriter pw = new PrintWriter(aw); // uses platform's line termination characters - - if (writeAllColumns) { - ResultsTable rt = plot.getResultsTableWithLabels(); - if (!Prefs.dontSaveHeaders) { - String headings = rt.getColumnHeadings(); - pw.println(headings); - } - for (int i = 0; i < rt.size(); i++) - pw.println(rt.getRowAsString(i)); - } else { - int xdigits = 0; - if (saveXValues) - xdigits = plot.getPrecision(xValues); - int ydigits = plot.getPrecision(yValues); - for (int i = 0; i < Math.min(xValues.length, yValues.length); i++) { - if (saveXValues) - pw.println(IJ.d2s(xValues[i], xdigits) + "\t" + IJ.d2s(yValues[i], ydigits)); - else - pw.println(IJ.d2s(yValues[i], ydigits)); - } - } - String text = aw.toString(); - pw.close(); - StringSelection contents = new StringSelection(text); - systemClipboard.setContents(contents, this); - IJ.showStatus(text.length() + " characters copied to Clipboard"); - if (autoClose) { - imp.changes = false; - close(); - } - } - - public void lostOwnership(Clipboard clipboard, Transferable contents) { - } - - public float[] getXValues() { - return plot.getXValues(); - } - - public float[] getYValues() { - return plot.getYValues(); - } - - /** Draws a new plot in this window. */ - public void drawPlot(Plot plot) { - this.plot = plot; - if (imp != null) { - if (ic instanceof PlotCanvas) - ((PlotCanvas) ic).setPlot(plot); - imp.setProcessor(null, plot.getProcessor()); - plot.setImagePlus(imp); // also adjusts the calibration of imp - } - } - - /** Called once when ImageJ quits. */ - public static void savePreferences(Properties prefs) { - double min = ProfilePlot.getFixedMin(); - double max = ProfilePlot.getFixedMax(); - prefs.put(PREFS_WIDTH, Integer.toString(plotWidth)); - prefs.put(PREFS_HEIGHT, Integer.toString(plotHeight)); - prefs.put(PREFS_FONT_SIZE, Integer.toString(defaultFontSize)); - int options = 0; - if (!interpolate) - options |= INTERPOLATE; // true=0, false=1 - prefs.put(OPTIONS, Integer.toString(options)); - } - - /** Enables or disables live plotting. - * Does nothing if the plot has no PlotMaker (then there is no 'live' button). */ - public void enableLivePlot(boolean b) { - if (plot==null || plot.getPlotMaker()==null || live == null) - return; - if (b && bgThread == null) - enableLivePlot(); - else if (!b && bgThread != null) - disableLivePlot(); - } - - private void toggleLivePlot() { - boolean liveMode = bgThread != null; - enableLivePlot(!liveMode); - } - - /** Enables live plotting. - * This requires that the PlotWindow has been initialized with a Plot having a PlotMaker. - * Live plotting runs in a background thread. */ - private void enableLivePlot() { - if (plotMaker == null) - plotMaker = plot != null ? plot.getPlotMaker() : null; - if (plotMaker == null) - return; - srcImp = plotMaker.getSourceImage(); - if (srcImp == null) - return; - if (bgThread == null) { - bgThread = new Thread(this, "Live Plot"); - bgThread.setPriority(Math.max(bgThread.getPriority() - 3, Thread.MIN_PRIORITY)); - doUpdate = true; - bgThread.start(); - } - if (IJ.debugMode) - IJ.log("PlotWindow.createListeners"); - ImagePlus.addImageListener(this); - Roi.addRoiListener(this); - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); - live.setForeground(Color.red); - } - - /** Disables live plotting (when currently active) */ - private void disableLivePlot() { - if (IJ.debugMode) - IJ.log("PlotWindow.disableLivePlot: " + srcImp); - if (srcImp == null) - return; - if (bgThread != null) - bgThread.interrupt(); - bgThread = null; - ImagePlus.removeImageListener(this); - Roi.removeRoiListener(this); - if (live != null) { - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.PLAIN, font.getSize())); - //live.setForeground(Color.black); - /*Changed for Bio7!*/ - //Color swtBackgroundToAWT = Util.getSWTBackgroundToAWT(); - Color swtForegroundToAWT = Util.getSWTForegroundToAWT(); - //live.setBackground(swtBackgroundToAWT); - live.setForeground(swtForegroundToAWT); - } - } - - /** For live plots, update the plot if the ROI of the source image changes */ - public synchronized void roiModified(ImagePlus img, int id) { - if (IJ.debugMode) - IJ.log("PlotWindow.roiModified: " + img + " " + id); - if (img == srcImp) { - doUpdate = true; - notify(); - } - } - - // Unused - public void imageOpened(ImagePlus imp) { - } - - /** - * For live plots, this method is called if the source image content is changed. - */ - public synchronized void imageUpdated(ImagePlus imp) { - if (imp == srcImp) { - doUpdate = true; - notify(); - } - } - - /** - * For live plots, if either the source image or this image are closed, exit - * live mode - */ - public void imageClosed(ImagePlus imp) { - if (imp == srcImp || imp == this.imp) { - disableLivePlot(); - srcImp = null; - plotMaker = null; - } - } - - // the background thread for live plotting. - public void run() { - while (true) { - IJ.wait(50); // delay to make sure the roi has been updated - Plot plot = plotMaker != null ? plotMaker.getPlot() : null; - if (doUpdate && plot != null && plot.getNumPlotObjects() > 0) { - plot.useTemplate(this.plot, this.plot.templateFlags | Plot.COPY_SIZE | Plot.COPY_LABELS - | Plot.COPY_AXIS_STYLE | Plot.COPY_CONTENTS_STYLE | Plot.COPY_LEGEND | Plot.COPY_EXTRA_OBJECTS); - plot.setPlotMaker(plotMaker); - this.plot = plot; - /* Changed for Bio7! */ - // ((PlotCanvas)ic).setPlot(plot); - ImageProcessor ip = plot.getProcessor(); - if (ip != null && imp != null) { - imp.setProcessor(null, ip); - plot.setImagePlus(imp); - } - } - synchronized (this) { - if (doUpdate) { - doUpdate = false; // and loop again - } else { - try { - wait(); - } // notify wakes up the thread - catch (InterruptedException e) { // interrupted tells the thread to exit - return; - } - } - } - } - } - - /** Returns the Plot associated with this PlotWindow. */ - public Plot getPlot() { - return plot; - } - - /** - * Freezes the active plot window, so the image does not get redrawn for - * zooming, setting the range, etc. - */ - public static void freeze() { - Window win = WindowManager.getActiveWindow(); - if (win != null && (win instanceof PlotWindow)) - ((PlotWindow) win).getPlot().setFrozen(true); - } - - public static void setDefaultFontSize(int size) { - if (size < 9) - size = 9; - defaultFontSize = size; - } - - public static int getDefaultFontSize() { - return defaultFontSize; - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/PointRoi.java b/com.eco.bio7.image/src/ij/gui/PointRoi.java deleted file mode 100644 index d349965b3..000000000 --- a/com.eco.bio7.image/src/ij/gui/PointRoi.java +++ /dev/null @@ -1,1064 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.measure.*; -import ij.plugin.Colors; -import ij.plugin.PointToolOptions; -import ij.plugin.filter.Analyzer; -import ij.plugin.frame.Recorder; -import ij.util.Tools; -import ij.util.Java2; -import java.awt.*; -import java.awt.image.*; -import java.awt.event.KeyEvent; -import java.util.*; -import java.awt.geom.*; - -/** This class represents a collection of points that can be associated - * with counters. Use the getPolygon() or getFloatPolygon() methods - * to retrieve the coordinates of the points. - * @see PointProperties.js -*/ -public class PointRoi extends PolygonRoi { - public static final String[] sizes = {"Tiny", "Small", "Medium", "Large", "Extra Large", "XXL", "XXXL"}; - public static final String[] types = {"Hybrid", "Cross", "Dot", "Circle"}; - public static final int HYBRID=0, CROSS=1, CROSSHAIR=1, DOT=2, CIRCLE=3; - /** Returned by getPosition if point stack positions are different */ - public static final int POINTWISE_POSITION = -2; - private static final String TYPE_KEY = "point.type"; - private static final String SIZE_KEY = "point.size"; - private static final String CROSS_COLOR_KEY = "point.cross.color"; - private static final int TINY=1, SMALL=3, MEDIUM=5, LARGE=7, EXTRA_LARGE=11, XXL=17, XXXL=25; - private static final BasicStroke twoPixelsWide = new BasicStroke(2); - private static final BasicStroke threePixelsWide = new BasicStroke(3); - private static final BasicStroke fivePixelsWide = new BasicStroke(5); - private static int defaultType = HYBRID; - private static int defaultSize = SMALL; - private static Font font; - private static Color defaultCrossColor = Color.white; - private static int fontSize = 9; - public static final int MAX_COUNTERS = 100; - private static String[] counterChoices; - private static Color[] colors; - private boolean showLabels; - private int type = HYBRID; - private int size = SMALL; - private static int defaultCounter; - private int counter; - private int nCounters = 1; - private short[] counters; //for each point, 0-100 for counter (=category that can be defined by the user) - private int[] positions; //for each point, the stack slice, or 0 for 'show on all' - private int[] counts = new int[MAX_COUNTERS]; - private ResultsTable rt; - private long lastPointTime; - private int[] counterInfo; - private boolean promptBeforeDeleting; - private boolean promptBeforeDeletingCalled; - private int nMarkers; - private boolean addToOverlay; - public static PointRoi savedPoints; - - static { - setDefaultType((int)Prefs.get(TYPE_KEY, HYBRID)); - setDefaultSize((int)Prefs.get(SIZE_KEY, 1)); - } - - public PointRoi() { - this(0.0, 0.0); - deletePoint(0); - } - - /** Creates a new PointRoi using the specified int arrays of offscreen coordinates. */ - public PointRoi(int[] ox, int[] oy, int points) { - super(itof(ox), itof(oy), points, POINT); - updateCounts(); - } - - /** Creates a new PointRoi using the specified float arrays of offscreen coordinates. */ - public PointRoi(float[] ox, float[] oy, int points) { - super(ox, oy, points, POINT); - updateCounts(); - } - - /** Creates a new PointRoi using the specified float arrays of offscreen coordinates. */ - public PointRoi(float[] ox, float[] oy) { - this(ox, oy, ox.length); - } - - /** Creates a new PointRoi using the specified coordinate arrays and options. */ - public PointRoi(float[] ox, float[] oy, String options) { - this(ox, oy, ox.length); - setOptions(options); - } - - /** Creates a new PointRoi from a FloatPolygon. */ - public PointRoi(FloatPolygon poly) { - this(poly.xpoints, poly.ypoints, poly.npoints); - } - - /** Creates a new PointRoi from a Polygon. */ - public PointRoi(Polygon poly) { - this(itof(poly.xpoints), itof(poly.ypoints), poly.npoints); - } - - /** Creates a new PointRoi using the specified coordinates and options. */ - public PointRoi(double ox, double oy, String options) { - super(makeXorYArray(ox, null, false), makeXorYArray(oy, null, true), 1, POINT); - width=1; height=1; - incrementCounter(null); - setOptions(options); - } - - /** Creates a new PointRoi using the specified offscreen int coordinates. */ - public PointRoi(int ox, int oy) { - super(makeXorYArray(ox, null, false), makeXorYArray(oy, null, true), 1, POINT); - width=1; height=1; - incrementCounter(null); - } - - /** Creates a new PointRoi using the specified offscreen double coordinates. */ - public PointRoi(double ox, double oy) { - super(makeXorYArray(ox, null, false), makeXorYArray(oy, null, true), 1, POINT); - width=1; height=1; - incrementCounter(null); - } - - /** Creates a new PointRoi using the specified screen coordinates. */ - public PointRoi(int sx, int sy, ImagePlus imp) { - super(makeXorYArray(sx, imp, false), makeXorYArray(sy, imp, true), 1, POINT); - //defaultCounter = 0; - setImage(imp); - width=1; height=1; - type = defaultType; - size = defaultSize; - showLabels = !Prefs.noPointLabels; - if (imp!=null) { - int r = 10 + size; - double mag = ic!=null?ic.getMagnification():1; - if (mag<1) - r = (int)(r/mag); - imp.draw(x-r, y-r, 2*r, 2*r); - } - setCounter(Toolbar.getMultiPointMode()?defaultCounter:0); - incrementCounter(imp); - enlargeArrays(50); - record(x, y, false); - } - - private void record(int xx, int yy, boolean addingPoint) { - if (!IJ.recording()) - return; - String add = Prefs.pointAddToOverlay?" add":""; - String options = sizes[convertSizeToIndex(size)]+" "+Colors.colorToString(getColor())+" "+types[type]+add; - options = options.toLowerCase(); - if (addingPoint) - options = "add"; - if (Recorder.scriptMode()) - Recorder.recordCall("imp.setRoi(new PointRoi("+xx+","+yy+",\""+options+"\"));"); - else - Recorder.record("makePoint", xx, yy, options); - } - - public void setOptions(String options) { - if (options==null) - return; - if (options.contains("tiny")) size=TINY; - else if (options.contains("medium")) size=MEDIUM; - else if (options.contains("extra")) size=EXTRA_LARGE; - else if (options.contains("large")) size=LARGE; - else if (options.contains("xxxl")) size=XXXL; - else if (options.contains("xxl")) size=XXL; - if (options.contains("cross")) type=CROSS; - else if (options.contains("dot")) type=DOT; - else if (options.contains("circle")) type=CIRCLE; - if (options.contains("nolabel")) setShowLabels(false); - else if (options.contains("label")) setShowLabels(true); - setStrokeColor(Colors.getColor(options,Roi.getColor())); - addToOverlay = options.contains("add"); - } - - static float[] itof(int[] arr) { - if (arr==null) - return null; - int n = arr.length; - float[] temp = new float[n]; - for (int i=0; i1) { - fontSize = 8; - double scale = size>=XXL?2:1.5; - fontSize += scale*convertSizeToIndex(size); - fontSize = (int)Math.round(fontSize); - font = new Font("SansSerif", Font.PLAIN, fontSize); - g.setFont(font); - if (fontSize>9) - Java2.setAntialiasedText(g, true); - } - int[] positions = this.positions; //use a copy to avoid NullPointerException on asynchronous change to null - int slice = imp!=null && positions!=null && imp.getStackSize()>1?imp.getCurrentSlice():0; - ImageCanvas ic = imp!=null?imp.getCanvas():null; - if (ic!=null && overlay && ic.getShowAllList()!=null && ic.getShowAllList().contains(this) && !Prefs.showAllSliceOnly) - slice = 0; // In RoiManager's "show all" mode and not "associate with slice", draw point irrespective of currently selected slice - if (Prefs.showAllPoints) - slice = 0; // "Show on all slices" in Point tool options - for (int i=0; i1.0) { - saveXform = g2d.getTransform(); - g2d.translate(x, y); - g2d.scale(flattenScale, flattenScale); - x = y = 0; - } - Color color = strokeColor!=null?strokeColor:ROIColor; - if (!overlay && isActiveOverlayRoi()) { - if (color==Color.cyan) - color = Color.magenta; - else - color = Color.cyan; - } - if (nCounters>1 && counters!=null && n<=counters.length) - color = getColor(counters[n-1]); - if (type==HYBRID || type==CROSS) { - if (type==HYBRID) - g.setColor(Color.white); - else { - g.setColor(color); - colorSet = true; - } - if (size>XXL) - g2d.setStroke(fivePixelsWide); - else if (size>LARGE) - g2d.setStroke(threePixelsWide); - g.drawLine(x-(size+2), y, x+size+2, y); - g.drawLine(x, y-(size+2), x, y+size+2); - } - if (type!=CROSS && size>SMALL) - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - if (type==HYBRID || type==DOT) { - if (!colorSet) { - g.setColor(color); - colorSet = true; - } - if (size>LARGE) - g2d.setStroke(onePixelWide); - if (size>LARGE && type==DOT) - g.fillOval(x-size2, y-size2, size, size); - else if (size>LARGE && type==HYBRID) - g.fillRect(x-(size2-2), y-(size2-2), size-4, size-4); - else if (size>SMALL && type==HYBRID) - g.fillRect(x-(size2-1), y-(size2-1), size-2, size-2); - else - g.fillRect(x-size2, y-size2, size, size); - } - if (showLabels && nPoints>1) { - int xoffset = 2; - if (size==LARGE) xoffset=3; - if (size==EXTRA_LARGE) xoffset=4; - if (size==XXL) xoffset=5; - if (size==XXXL) xoffset=7; - int yoffset = xoffset; - if (size>=LARGE) yoffset=yoffset-1; - if (nCounters==1) { - if (!colorSet) - g.setColor(color); - g.drawString(""+n, x+xoffset, y+yoffset+fontSize); - } else if (counters!=null) { - g.setColor(getColor(counters[n-1])); - g.drawString(""+counters[n-1], x+xoffset, y+yoffset+fontSize); - } - } - if ((size>TINY||type==DOT) && (type==HYBRID||type==DOT)) { - g.setColor(Color.black); - if (size>LARGE && type==HYBRID) - g.drawOval(x-(size2-1), y-(size2-1), size-3, size-3); - else if (size>SMALL && type==HYBRID) - g.drawOval(x-size2, y-size2, size-1, size-1); - else - g.drawOval(x-(size2+1), y-(size2+1), size+1, size+1); - } - if (type==CIRCLE) { - int scaledSize = (int)Math.round(size+1); - g.setColor(color); - if (size>LARGE) - g2d.setStroke(twoPixelsWide); - g.drawOval(x-scaledSize/2, y-scaledSize/2, scaledSize, scaledSize); - } - if (saveXform!=null) - g2d.setTransform(saveXform); - } - - public void drawPixels(ImageProcessor ip) { - ip.setLineWidth(Analyzer.markWidth); - double x0 = bounds == null ? x : bounds.x; - double y0 = bounds == null ? y : bounds.y; - for (int i=0; i=0 && index<=nPoints && counters!=null) { - counts[counters[index]]--; - for (int i=index; i1; - if (counter!=0 || isStack || counters!=null) { - if (counters==null) { - int size = nPoints*2; - if (size<100) size=100; - counters = new short[size]; - positions = new int[size]; - } - if (nPoints>=counters.length) { - short[] temp = new short[counters.length*2]; - System.arraycopy(counters, 0, temp, 0, counters.length); - counters = temp; - int[] temp1 = new int[counters.length*2]; - System.arraycopy(positions, 0, temp1, 0, positions.length); - positions = temp1; - } - counters[nPoints-1] = (short)counter; - if (imp!=null) - positions[nPoints-1] = imp.getStackSize()>1 ? imp.getCurrentSlice() : 0; - } - if (rt!=null && WindowManager.getFrame(getCountsTitle())!=null) - displayCounts(); - } - - /** Returns the index of the current counter. */ - public int getCounter() { - return counter; - } - - /** Returns the count associated with the specified counter index. - * @see #getLastCounter - * @see PointProperties.js - */ - public int getCount(int counter) { - if (counter==0 && counters==null) - return nPoints; - else - return counts[counter]; - } - - /** Returns the index of the last counter. */ - public int getLastCounter() { - return nCounters - 1; - } - - /** Returns the number of counters. */ - public int getNCounters() { - int n = 0; - for (int counter=0; counter0) n++; - } - return n; - } - - /** Returns the counter assocated with the specified point. */ - public int getCounter(int index) { - if (counters==null || index>=counters.length) - return 0; - else - return counters[index]; - } - - /** Deletes all counters and stack position associations */ - public void resetCounters() { - for (int i=0; iroi if keepContained is true (false). */ - PointRoi checkContained(Roi roi, boolean keepContained) { - if (!roi.isArea()) return null; - FloatPolygon points = getFloatPolygon(); - FloatPolygon points2 = new FloatPolygon(); - for (int i=0; i=0 && type=0 && type=0 && index=0 && sizenCounters-1 && nCounters8||getNCounters()>1) && imp!=null && imp.getWindow()!=null; - } - - public void promptBeforeDeleting(Boolean prompt) { - promptBeforeDeleting = prompt; - promptBeforeDeletingCalled = true; - } - - public static void setDefaultCounter(int counter) { - defaultCounter = counter; - } - - /** Returns an array containing for each point: - * The counter number (0-100) in the lower 8 bits, and the slice number - * (or 0, if the point appears on all slices) in the higher 24 bits. - * Used when writing a Roi to file (RoiEncoder) */ - public int[] getCounters() { - if (nPoints>65535) - return null; - int[] temp = new int[nPoints]; - if (counters!=null) { - for (int i=0; i>8; - this.counters[i] = (short)counter; - this.positions[i] = position; - if (counternCounters-1) - nCounters = counter + 1; - } - updateCounts(); - } - } - - /** Updates the counts for each category in 'counters' */ - public void updateCounts() { - Arrays.fill(counts, 0); - for (int i=0; i=counts.length) ? 0 : counters[i]] ++; - } - - /** Sets the stack position (image number) of all points in this Roi. - * The points are only displayed when the stack is at the specified position. - * Set to zero to have the points displayed on all images in the stack. - * The stack position, when set, determines the visibility of this Roi - * (i) if it is part of an overlay (normal overlay or the RoiManager's - * 'Show All' overlay), or - * (ii) if it is the currently active Roi and Prefs.showAllPoints - * ('Show an all slices' in the Point Tool Options dialog) is off. - * Clears any association of this Roi to a hyperstack position. - * Stack positions of individual points are overwritten. - * - * Note that the behavior differs from that of the other Roi types: - * For the other Roi types, setPosition does not restrict the visibility - * to stack slice 'n' if that roi is the currently active Roi; it only - * affects the visibility if that Roi is part of an overlay. - */ - public void setPosition(int n) { - if (n<0 && n!=POINTWISE_POSITION) - n = 0; - if (n == 0) { - positions = null; - } else { - if (positions == null) { - if (counters == null) - counters = new short[nPoints*2]; - positions = new int[counters.length]; - } - if (n != POINTWISE_POSITION) - Arrays.fill(positions, n); - } - super.setPosition(nPoints>1?0:n); - } - - /** Returns the stack position (image number) of the points in this Roi, if - * all points have the same position. Returns 0 if none of the points is - * associated with a particular stack image, and PointRoi.POINTWISE_POSITION = -2 - * if there are different stack positions for different points. - */ - public int getPosition() { - int position = 0; - if (positions==null || nPoints<1) - position = 0; - else if (nPoints==1) - return super.getPosition(); - else { - position = positions[0]; - for (int i=1; i= 0; - } - - public void displayCounts() { - ImagePlus imp = getImage(); - String firstColumnHdr = "Slice"; - rt = new ResultsTable(); - int row = 0; - if (imp!=null && imp.getStackSize()>1 && positions!=null) { - int nChannels = 1; - int nSlices = 1; - int nFrames = 1; - boolean isHyperstack = true; - if (imp.isComposite() || imp.isHyperStack()) { - nChannels = imp.getNChannels(); - nSlices = imp.getNSlices(); - nFrames = imp.getNFrames(); - int nDimensions = 2; - if (nChannels>1) nDimensions++; - if (nSlices>1) nDimensions++; - if (nFrames>1) nDimensions++; - if (nDimensions==3) { - isHyperstack = false; - if (nChannels>1) - firstColumnHdr = "Channel"; - } else - firstColumnHdr = "Image"; - } - int firstSlice = Integer.MAX_VALUE; - for (int i=0; i0 && positions[i]0) { - for (int i=0; ilastSlice) - lastSlice = positions[i]; - } - } - if (firstSlice>0) { - for (int slice=firstSlice; slice<=lastSlice; slice++) { - rt.setValue(firstColumnHdr, row, slice); - if (isHyperstack) { - int[] position = imp.convertIndexToPosition(slice); - if (nChannels>1) - rt.setValue("Channel", row, position[0]); - if (nSlices>1) - rt.setValue("Slice", row, position[1]); - if (nFrames>1) - rt.setValue("Frame", row, position[2]); - } - for (int counter=0; counter1?imp.getCurrentSlice():0; - for (int i=0; i=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) { - handle = i; - break; - } - } - return handle; - } - - /** Returns the points as an array of Points. - * Wilhelm Burger: modified to use FloatPolygon for correct point positions. - */ - public Point[] getContainedPoints() { - FloatPolygon p = getFloatPolygon(); - Point[] points = new Point[p.npoints]; - for (int i=0; i iterator() { - return new Iterator() { - final Point[] pnts = getContainedPoints(); - final int n = pnts.length; - int next = (n == 0) ? 1 : 0; - @Override - public boolean hasNext() { - return next < n; - } - @Override - public Point next() { - if (next >= n) { - throw new NoSuchElementException(); - } - Point pnt = pnts[next]; - next = next + 1; - return pnt; - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - protected int getClosestPoint(double x, double y, FloatPolygon points) { - int index = -1; - double distance = Double.MAX_VALUE; - int slice = imp!=null&&positions!=null&&imp.getStackSize()>1?imp.getCurrentSlice():0; - if (Prefs.showAllPoints) - slice = 0; - for (int i=0; i=0; i--) { - if (!roi.contains(p.xpoints[i],p.ypoints[i])) { - points.deletePoint(i); - } - } - return points; - } - - @Override - public void copyAttributes(Roi roi2) { - super.copyAttributes(roi2); - if (roi2 instanceof PointRoi) { - PointRoi p2 = (PointRoi)roi2; - this.type = p2.type; - this.size = p2.size; - this.showLabels = p2.showLabels; - this.fontSize = p2.fontSize; - } - } - - public void setCounterInfo(int[] info) { - counterInfo = info; - } - - public int[] getCounterInfo() { - return counterInfo; - } - - public boolean addToOverlay() { - return addToOverlay; - } - - public String toString() { - if (nPoints>1) - return ("Roi[Points, count="+nPoints+", pos="+getPositionAsString()+", psize="+size+"]"); - else - return ("Roi[Point, x="+x+", y="+y+", pos="+getPositionAsString()+", psize="+size+"]"); - } - - /** @deprecated */ - public void setHideLabels(boolean hideLabels) { - this.showLabels = !hideLabels; - } - - /** @deprecated */ - public static void setDefaultMarkerSize(String size) { - } - - /** @deprecated */ - public static String getDefaultMarkerSize() { - return sizes[defaultSize]; - } - - /** Deprecated */ - public static void setDefaultCrossColor(Color color) { - } - - /** Deprecated */ - public static Color getDefaultCrossColor() { - return null; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/PolygonRoi.java b/com.eco.bio7.image/src/ij/gui/PolygonRoi.java deleted file mode 100644 index 2b58adde9..000000000 --- a/com.eco.bio7.image/src/ij/gui/PolygonRoi.java +++ /dev/null @@ -1,1705 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.measure.*; -import ij.plugin.frame.*; -import ij.util.Tools; -import ij.util.FloatArray; -import java.awt.*; -import java.awt.image.*; -import java.awt.geom.*; -import java.awt.event.*; - -/** This class represents a polygon region of interest or polyline of interest. */ -public class PolygonRoi extends Roi { - - protected int maxPoints = 1000; // will be increased if necessary - protected int[] xp, yp; // image coordinates relative to origin of roi bounding box - protected float[] xpf, ypf; // or alternative sub-pixel coordinates - protected int[] xp2, yp2; // absolute screen coordinates - protected int nPoints; - protected float[] xSpline,ySpline; // relative image coordinates - protected int splinePoints = 200; - Rectangle clip; - - private double angle1, degrees=Double.NaN; - private int xClipMin, yClipMin, xClipMax, yClipMax; - private boolean userCreated; - private int boxSize = 8; - - long mouseUpTime = 0; - - /** Creates a new polygon or polyline ROI from x and y coordinate arrays. - Type must be Roi.POLYGON, Roi.FREEROI, Roi.TRACED_ROI, Roi.POLYLINE, Roi.FREELINE or Roi.ANGLE.*/ - public PolygonRoi(int[] xPoints, int[] yPoints, int nPoints, int type) { - super(0, 0, null); - init1(nPoints, type); - xp = xPoints; - yp = yPoints; - if (type!=TRACED_ROI) { - xp = new int[nPoints]; - yp = new int[nPoints]; - for (int i=0; i1 && isLine()) - updateWideLine(lineWidth); - finishPolygon(); - } - - /** Creates a new polygon or polyline ROI from a Polygon. Type must be Roi.POLYGON, - Roi.FREEROI, Roi.TRACED_ROI, Roi.POLYLINE, Roi.FREELINE or Roi.ANGLE.*/ - public PolygonRoi(Polygon p, int type) { - this(p.xpoints, p.ypoints, p.npoints, type); - } - - /** Creates a new polygon or polyline ROI from a FloatPolygon. Type must be Roi.POLYGON, - Roi.FREEROI, Roi.TRACED_ROI, Roi.POLYLINE, Roi.FREELINE or Roi.ANGLE.*/ - public PolygonRoi(FloatPolygon p, int type) { - this(p.xpoints, p.ypoints, p.npoints, type); - } - - /** @deprecated */ - public PolygonRoi(int[] xPoints, int[] yPoints, int nPoints, ImagePlus imp, int type) { - this(xPoints, yPoints, nPoints, type); - setImage(imp); - } - - /** Starts the process of creating a new user-generated polygon or polyline ROI. */ - public PolygonRoi(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - int tool = Toolbar.getToolId(); - switch (tool) { - case Toolbar.POLYGON: - type = POLYGON; - break; - case Toolbar.FREEROI: - type = FREEROI; - break; - case Toolbar.FREELINE: - type = FREELINE; - break; - case Toolbar.ANGLE: - type = ANGLE; - break; - default: - type = POLYLINE; - break; - } - if (magnificationForSubPixel()) - enableSubPixelResolution(); - previousSX = sx; - previousSY = sy; - x = offScreenX(sx); - y = offScreenY(sy); - startXD = offScreenXD(sx); - startYD = offScreenYD(sy); - if (subPixelResolution()) { - setLocation(startXD, startYD); - xpf = new float[maxPoints]; - ypf = new float[maxPoints]; - double xbase = getXBase(); - double ybase = getYBase(); - xpf[0] = (float)(startXD-xbase); - ypf[0] = (float)(startYD-ybase); - xpf[1] = xpf[0]; - ypf[1] = ypf[0]; - } else { - xp = new int[maxPoints]; - yp = new int[maxPoints]; - } - xp2 = new int[maxPoints]; - yp2 = new int[maxPoints]; - nPoints = 2; - width=1; - height=1; - clipX = x; - clipY = y; - clipWidth = 1; - clipHeight = 1; - state = CONSTRUCTING; - userCreated = true; - if (lineWidth>1 && isLine()) - updateWideLine(lineWidth); - boxSize = (int)(boxSize*Prefs.getGuiScale()); - } - - private void drawStartBox(Graphics g) { - if (type!=ANGLE) - g.drawRect(screenXD(startXD)-4, screenYD(startYD)-4, 8, 8); - } - - public void draw(Graphics g) { - updatePolygon(); - Color color = strokeColor!=null?strokeColor:ROIColor; - boolean hasHandles = xSpline!=null||type==POLYGON||type==POLYLINE||type==ANGLE; - boolean isActiveOverlayRoi = !overlay && isActiveOverlayRoi(); - if (isActiveOverlayRoi) { - if (color==Color.cyan) - color = Color.magenta; - else - color = Color.cyan; - } - boolean fill = false; - mag = getMagnification(); - if (fillColor!=null && !isLine() && state!=CONSTRUCTING) { - color = fillColor; - fill = true; - } - g.setColor(color); - Graphics2D g2d = (Graphics2D)g; - setRenderingHint(g2d); - if (stroke!=null && !isActiveOverlayRoi) - g2d.setStroke(getScaledStroke()); - if (xSpline!=null) { - if (type==POLYLINE || type==FREELINE) { - drawSpline(g, xSpline, ySpline, splinePoints, false, fill, isActiveOverlayRoi); - if (wideLine && !overlay) { - g2d.setStroke(onePixelWide); - g.setColor(getColor()); - drawSpline(g, xSpline, ySpline, splinePoints, false, fill, isActiveOverlayRoi); - } - } else - drawSpline(g, xSpline, ySpline, splinePoints, true, fill, isActiveOverlayRoi); - } else { - if (type==POLYLINE || type==FREELINE || type==ANGLE || (state==CONSTRUCTING && !(this instanceof RotatedRectRoi))) { g.drawPolyline(xp2, yp2, nPoints); - if (wideLine && !overlay) { - g2d.setStroke(onePixelWide); - g.setColor(getColor()); - g.drawPolyline(xp2, yp2, nPoints); - } - } else { - if (fill) { - if (isActiveOverlayRoi) { - g.setColor(Color.cyan); - g.drawPolygon(xp2, yp2, nPoints); - } else - g.fillPolygon(xp2, yp2, nPoints); - if (strokeColor!=null) { - g.setColor(strokeColor); - g.drawPolygon(xp2, yp2, nPoints); - } - } else - g.drawPolygon(xp2, yp2, nPoints); - } - if (state==CONSTRUCTING && type!=FREEROI && type!=FREELINE) - drawStartBox(g); - } - if (hasHandles && clipboard==null && !overlay) { - if (activeHandle>0) - drawHandle(g, xp2[activeHandle-1], yp2[activeHandle-1]); - if (activeHandle1f) - ip.setLineWidth((int)Math.round(getStrokeWidth())); - double xbase = getXBase(); - double ybase = getYBase(); - if (xSpline!=null) { - ip.moveTo((int)Math.round(xbase+xSpline[0]), (int)Math.round(ybase+ySpline[0])); - for (int i=1; i Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - - // Do rubber banding - int tool = Toolbar.getToolId(); - if (!(tool==Toolbar.POLYGON || tool==Toolbar.POLYLINE || tool==Toolbar.ANGLE)) { - imp.deleteRoi(); - imp.draw(); - return; - } - if (IJ.altKeyDown()) - wipeBack(); - - drawRubberBand(sx, sy); - - // show status: length & angle - degrees = Double.NaN; - double len = -1; - if (nPoints>1) { - double x1, y1, x2, y2; - if (xpf!=null) { - x1 = xpf[nPoints-2]; - y1 = ypf[nPoints-2]; - x2 = xpf[nPoints-1]; - y2 = ypf[nPoints-1]; - } else { - x1 = xp[nPoints-2]; - y1 = yp[nPoints-2]; - x2 = xp[nPoints-1]; - y2 = yp[nPoints-1]; - } - degrees = getFloatAngle(x1, y1, x2, y2); - if (tool!=Toolbar.ANGLE) { - Calibration cal = imp.getCalibration(); - double pw=cal.pixelWidth, ph=cal.pixelHeight; - if (IJ.altKeyDown()) {pw=1.0; ph=1.0;} - len = Math.sqrt((x2-x1)*pw*(x2-x1)*pw + (y2-y1)*ph*(y2-y1)*ph); - } - } - if (tool==Toolbar.ANGLE) { - if (nPoints==2) - angle1 = degrees; - else if (nPoints==3) { - double angle2 = xpf != null ? getFloatAngle(xpf[1], ypf[1], xpf[2], ypf[2]) : - getAngle(xp[1], yp[1], xp[2], yp[2]); - degrees = Math.abs(180-Math.abs(angle1-angle2)); - if (degrees>180.0) - degrees = 360.0-degrees; - } - } - String length = len!=-1?", length=" + IJ.d2s(len):""; - double degrees2 = tool==Toolbar.ANGLE&&nPoints==3&&Prefs.reflexAngle?360.0-degrees:degrees; - String angle = !Double.isNaN(degrees)?", angle=" + IJ.d2s(degrees2):""; - int ox = ic.offScreenX(sx); - int oy = ic.offScreenY(sy); - IJ.showStatus(imp.getLocationAsString(ox,oy) + length + angle); - } - - //Mouse behaves like an eraser when moved backwards with alt key down. - //Within correction circle, all vertices with sharp angles are removed. - //Norbert Vischer - protected void wipeBack() { - Roi prevRoi = Roi.getPreviousRoi(); - if (prevRoi!=null && prevRoi.modState==SUBTRACT_FROM_ROI) - return; - double correctionRadius = 20; - if (ic!=null) - correctionRadius /= ic.getMagnification(); - boolean found = false; - int p3 = nPoints - 1; - int p1 = p3; - while (p1 > 0 && !found) { - p1--; - double dx = xpf != null ? xpf[p3] - xpf[p1] : xp[p3] - xp[p1]; - double dy = xpf != null ? ypf[p3] - ypf[p1] : yp[p3] - yp[p1]; - double dist = Math.sqrt(dx * dx + dy * dy); - if (dist > correctionRadius) - found = true; - } - //examine all angles p1-p2-p3 - boolean killed = false; - int safety = 10; //don't delete more than this number of points at once - do { - killed = false; - safety--; - for (int p2 = p1 + 1; p2 < p3; p2++) { - double dx1 = xpf != null ? xpf[p2] - xpf[p1] : xp[p2] - xp[p1]; - double dy1 = xpf != null ? ypf[p2] - ypf[p1] : yp[p2] - yp[p1]; - double dx2 = xpf != null ? xpf[p3] - xpf[p1] : xp[p3] - xp[p1]; - double dy2 = xpf != null ? ypf[p3] - ypf[p1] : yp[p3] - yp[p1]; - double kk = 1;//allowed sharpness - if (this instanceof FreehandRoi) - kk = 0.8; - if ((dx1 * dx1 + dy1 * dy1) > kk * (dx2 * dx2 + dy2 * dy2)) { - if (xpf != null) { - xpf[p2] = xpf[p3]; ypf[p2] = ypf[p3]; //replace sharp vertex with end point - } else { - xp[p2] = xp[p3]; yp[p2] = yp[p3]; - } - p3 = p2; - nPoints = p2 + 1; //shorten array - killed = true; - } - } - } while (killed && safety > 0); - } - - void drawRubberBand(int sx, int sy) { - double oxd = offScreenXD(sx); - double oyd = offScreenYD(sy); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - int x1, y1, x2, y2; - if (xpf!=null) { - x1 = (int)xpf[nPoints-2]+x; - y1 = (int)ypf[nPoints-2]+y; - x2 = (int)xpf[nPoints-1]+x; - y2 = (int)ypf[nPoints-1]+y; - } else { - x1 = xp[nPoints-2]+x; - y1 = yp[nPoints-2]+y; - x2 = xp[nPoints-1]+x; - y2 = yp[nPoints-1]+y; - } - int xmin=Integer.MAX_VALUE, ymin=Integer.MAX_VALUE, xmax=0, ymax=0; - if (x1xmax) xmax=x1; - if (x2>xmax) xmax=x2; - if (ox>xmax) xmax=ox; - if (y1ymax) ymax=y1; - if (y2>ymax) ymax=y2; - if (oy>ymax) ymax=oy; - int margin = boxSize; - if (ic!=null) { - double mag = ic.getMagnification(); - if (mag<1.0) margin = (int)(margin/mag); - } - margin = (int)(margin+getStrokeWidth()); - if (IJ.altKeyDown()) - margin+=20; - if (xpf!=null) { - xpf[nPoints-1] = (float)(oxd-getXBase()); - ypf[nPoints-1] = (float)(oyd-getYBase()); - } else { - xp[nPoints-1] = ox-x; - yp[nPoints-1] = oy-y; - } - if (type==POLYLINE && Prefs.splineFitLines) { - fitSpline(); - imp.draw(); - } else - imp.draw(xmin-margin, ymin-margin, (xmax-xmin)+margin*2, (ymax-ymin)+margin*2); - } - - void finishPolygon() { - if (xpf!=null) { - double xbase0 = getXBase(); - double ybase0 = getYBase(); - FloatPolygon poly = new FloatPolygon(xpf, ypf, nPoints); - bounds = poly.getFloatBounds(); - for (int i=0; i Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - - if (clipboard!=null) return; - - int ox = offScreenX(sx); - int oy = offScreenY(sy); - if (xpf!=null) { - xpf[activeHandle] = (float)(offScreenXD(sx)-getXBase()); - ypf[activeHandle] = (float)(offScreenYD(sy)-getYBase()); - } else { - xp[activeHandle] = ox-x; - yp[activeHandle] = oy-y; - } - if (xSpline!=null) { - fitSpline(splinePoints); - imp.draw(); - } else { - if (!subPixelResolution() || (type==POINT&&nPoints==1)) - resetBoundingRect(); - if (type==POINT && width==0 && height==0) - {width=1; height=1;} - updateClipRectAndDraw(); - } - String angle = type==ANGLE?getAngleAsString():""; - IJ.showStatus(imp.getLocationAsString(ox,oy) + angle); - } - - /** After handle is moved, find clip rect and repaint. */ - void updateClipRectAndDraw() { - if (xpf!=null) { - xp = toInt(xpf, xp, nPoints); - yp = toInt(ypf, yp, nPoints); - } - int xmin=Integer.MAX_VALUE, ymin=Integer.MAX_VALUE, xmax=0, ymax=0; - int x2, y2; - if (activeHandle>0) - {x2=x+xp[activeHandle-1]; y2=y+yp[activeHandle-1];} - else - {x2=x+xp[nPoints-1]; y2=y+yp[nPoints-1];} - if (x2xmax) xmax = x2; - if (y2>ymax) ymax = y2; - x2=x+xp[activeHandle]; y2=y+yp[activeHandle]; - if (x2xmax) xmax = x2; - if (y2>ymax) ymax = y2; - if (activeHandlexmax) xmax = x2; - if (y2>ymax) ymax = y2; - int xmin2=xmin, ymin2=ymin, xmax2=xmax, ymax2=ymax; - if (xClipMinxmax2) xmax2 = xClipMax; - if (yClipMax>ymax2) ymax2 = yClipMax; - xClipMin=xmin; yClipMin=ymin; xClipMax=xmax; yClipMax=ymax; - double mag = ic.getMagnification(); - int handleSize = type==POINT?getHandleSize()+25:getHandleSize(); - double strokeWidth = getStrokeWidth(); - if (strokeWidth<1.0) strokeWidth=1.0; - if (handleSizexmax) xmax=xx; - yy = yp[i]; - if (yyymax) ymax=yy; - } - if (xmin!=0) { - for (int i=0; i180.0) - degrees = 360.0-degrees; - double degrees2 = Prefs.reflexAngle&&type==ANGLE?360.0-degrees:degrees; - return ", angle=" + IJ.d2s(degrees2); - } - - protected void mouseDownInHandle(int handle, int sx, int sy) { - if (state==CONSTRUCTING) - return; - int ox = offScreenX(sx); - int oy = offScreenY(sy); - double oxd = offScreenXD(sx); - double oyd = offScreenYD(sy); - if ((IJ.altKeyDown()||IJ.controlKeyDown()) && !(nPoints<=3 && type!=POINT) && !(this instanceof RotatedRectRoi)) { - deleteHandle(oxd, oyd); - return; - } else if (IJ.shiftKeyDown() && type!=POINT && !(this instanceof RotatedRectRoi)) { - addHandle(oxd, oyd); - return; - } - super.mouseDownInHandle(handle, sx, sy); //sets state, activeHandle, previousSX&Y - int m = ic!=null?(int)(10.0/ic.getMagnification()):1; - xClipMin=ox-m; yClipMin=oy-m; xClipMax=ox+m; yClipMax=oy+m; - } - - public void deleteHandle(double ox, double oy) { - if (imp==null) - return; - if (nPoints<=1) { - imp.deleteRoi(); - return; - } - boolean splineFit = xSpline!=null; - if (splineFit) - removeSplineFit(); - FloatPolygon points = getFloatPolygon(); - int pointToDelete = getClosestPoint(ox, oy, points); - if (pointToDelete>=0) { - deletePoint(pointToDelete); - if (splineFit) - fitSpline(splinePoints); - imp.draw(); - } - } - - protected void deletePoint(int index) { - if (index<0 || index>=nPoints) - return; - for (int i=index; i=maxPoints) - enlargeArrays(); - float xbase = (float)getXBase(); - float ybase = (float)getYBase(); - if (xp==null) { - xp = new int[maxPoints]; - yp = new int[maxPoints]; - } - for (int i=0; i= 0.0 || i==npoints-1) && pointsWritten < npOut) { // we have to write a new point - double fractionOverNextWrite = distanceOverNextWrite/distance; - if (distance==0) fractionOverNextWrite = 0; - xpOut[pointsWritten] = (float)(x2 - fractionOverNextWrite*dx); - ypOut[pointsWritten] = (float)(y2 - fractionOverNextWrite*dy); - distanceOverNextWrite -= step; - pointsWritten++; - } - } - return new float[][] {xpOut, ypOut, new float[] {(float)step}}; - } - - /** With segmented selections, ignore first mouse up and finalize - when user double-clicks, control-clicks or clicks in start box. */ - protected void handleMouseUp(int sx, int sy) { - if (state==MOVING) { - state = NORMAL; - return; - } - if (state==MOVING_HANDLE) { - cachedMask = null; //mask is no longer valid - state = NORMAL; - updateClipRect(); - oldX=x; oldY=y; - oldWidth=width; oldHeight=height; - if (subPixelResolution()) - resetBoundingRect(); - return; - } - if (state!=CONSTRUCTING) - return; - if (IJ.spaceBarDown()) // is user scrolling image? - return; - boolean samePoint = false; - if (xpf!=null) - samePoint = (xpf[nPoints-2]==xpf[nPoints-1] && ypf[nPoints-2]==ypf[nPoints-1]); - else - samePoint = (xp[nPoints-2]==xp[nPoints-1] && yp[nPoints-2]==yp[nPoints-1]); - boolean doubleClick = (System.currentTimeMillis()-mouseUpTime)<=300; - int size = boxSize+2; - int size2 = boxSize/2 +1; - Rectangle biggerStartBox = new Rectangle(screenXD(startXD)-5, screenYD(startYD)-5, 10, 10); - if (nPoints>2 && (biggerStartBox.contains(sx, sy) - || (offScreenXD(sx)==startXD && offScreenYD(sy)==startYD) - || (samePoint && doubleClick))) { - boolean okayToFinish = true; - if (type==POLYGON && samePoint && doubleClick && nPoints>25) { - okayToFinish = IJ.showMessageWithCancel("Polygon Tool", "Complete the selection?"); - } - if (okayToFinish) { - nPoints--; - addOffset(); - finishPolygon(); - return; - } - } else if (!samePoint) { - mouseUpTime = System.currentTimeMillis(); - if (type==ANGLE && nPoints==3) { - addOffset(); - finishPolygon(); - return; - } - //add point to polygon - if (xpf!=null) { - xpf[nPoints] = xpf[nPoints-1]; - ypf[nPoints] = ypf[nPoints-1]; - nPoints++; - if (nPoints==xpf.length) - enlargeArrays(); - } else { - xp[nPoints] = xp[nPoints-1]; - yp[nPoints] = yp[nPoints-1]; - nPoints++; - if (nPoints==xp.length) - enlargeArrays(); - } - if (constrain) { // this point was constrained in 90deg steps; correct coordinates - int dx = sx - previousSX; - int dy = sy - previousSY; - if (Math.abs(dx) > Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - previousSX = sx; //save for constraining next line if desired - previousSY = sy; - notifyListeners(RoiListener.EXTENDED); - } - } - - protected void addOffset() { - if (xpf!=null) { - float xbase = (float)getXBase(); - float ybase = (float)getYBase(); - for (int i=0; i=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) { - handle = i; - break; - } - } - return handle; - } - - public ImageProcessor getMask() { - ImageProcessor mask = cachedMask; - if (mask!=null && mask.getPixels()!=null - && mask.getWidth()==width && mask.getHeight()==height) - return mask; - PolygonFiller pf = new PolygonFiller(); - if (xSpline!=null) - pf.setPolygon(xSpline, ySpline, splinePoints, getXBase()-x, getYBase()-y); - else if (xpf!=null) - pf.setPolygon(xpf, ypf, nPoints, getXBase()-x, getYBase()-y); - else - pf.setPolygon(xp, yp, nPoints); - mask = pf.getMask(width, height); - cachedMask = mask; - return mask; - } - - /** Returns the length of this line selection after - smoothing using a 3-point running average.*/ - double getSmoothedLineLength(ImagePlus imp) { - if (subPixelResolution() && xpf!=null) - return getFloatSmoothedLineLength(imp); - double length = 0.0; - double w2 = 1.0; - double h2 = 1.0; - double dx, dy; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - w2 = cal.pixelWidth*cal.pixelWidth; - h2 = cal.pixelHeight*cal.pixelHeight; - } - dx = (xp[0]+xp[1]+xp[2])/3.0-xp[0]; - dy = (yp[0]+yp[1]+yp[2])/3.0-yp[0]; - length += Math.sqrt(dx*dx*w2+dy*dy*h2); - for (int i=1; i1 || !corner) { - corner = true; - nCorners++; - } else - corner = false; - dx1 = dx2; - dy1 = dy2; - side1 = side2; - } - double w=1.0,h=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - w = cal.pixelWidth; - h = cal.pixelHeight; - } - return sumdx*w+sumdy*h-(nCorners*((w+h)-Math.sqrt(w*w+h*h))); - } - - /** Returns the perimeter (for ROIs) or length (for lines).*/ - public double getLength() { - return getLength(imp); - } - - public double getUncalibratedLength() { - return getLength(null); - } - - /** Returns the perimeter (for ROIs) or length (for lines), using calibration if imp is not null */ - double getLength(ImagePlus imp) { - if (isTraced()) - return getTracedPerimeter(imp); - - if (nPoints>2) { - if (type==FREEROI) - return getSmoothedPerimeter(imp); - else if (type==FREELINE && !(width==0 || height==0)) - return getSmoothedLineLength(imp); - } - - boolean closeShape = isArea(); - if (xSpline!=null) - return getLength(xSpline, ySpline, splinePoints, closeShape, imp); - else if (xpf!=null) - return getLength(xpf, ypf, nPoints, closeShape, imp); - else - return getLength(xp, yp, nPoints, closeShape, imp); - } - - /** Returns 'true' if this ROI was created using - * the wand tool or the particle analyzer. - */ - private boolean isTraced() { - if (type==TRACED_ROI) - return true; - else if (type!=POLYGON || (this instanceof RotatedRectRoi)) - return false; - else if (xp==null) { - if (xpf==null) - return false; - for (int i=0; i "+newSize); - maxPoints = newSize; - } - - public void setLocation(double x, double y) { - super.setLocation(x, y); - if ((int)x!=x || (int)y!=y) - enableSubPixelResolution(); - } - - public void enableSubPixelResolution() { - super.enableSubPixelResolution(); - if (xpf==null && xp!=null) { - xpf = toFloat(xp); - ypf = toFloat(yp); - } - } - - public String getDebugInfo() { - String s = "ROI Debug Properties\n"; - s += " bounds: "+bounds+"\n"; - s += " x,y,w,h: "+x+","+y+","+width+","+height+"\n"; - if (xpf!=null && xpf.length>0) - s += " xpf[0],ypf[0]: "+xpf[0]+","+ypf[0]+"\n"; - return s; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ProfilePlot.java b/com.eco.bio7.image/src/ij/gui/ProfilePlot.java deleted file mode 100644 index 1bc063da9..000000000 --- a/com.eco.bio7.image/src/ij/gui/ProfilePlot.java +++ /dev/null @@ -1,340 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.util.ArrayList; -import ij.*; -import ij.process.*; -import ij.util.*; -import ij.measure.*; -import ij.plugin.Straightener; - -/** Creates a density profile plot of a line or rectangular selection. */ -public class ProfilePlot { - - static final int MIN_WIDTH = 350; - static final double ASPECT_RATIO = 0.5; - private double min, max; - private boolean minAndMaxCalculated; - private static double fixedMin; - private static double fixedMax; - - protected ImagePlus imp; - protected double[] profile; - protected double magnification; - protected double xInc; - protected String units; - protected String yLabel; - protected float[] xValues; - - - public ProfilePlot() { - } - - /** Based on the current line or rectangular selection, - * creates a profile plot that can be retrieved using - * the getPlot() method. - */ - public ProfilePlot(ImagePlus imp) { - this(imp, false); - } - - /** Based on the current rectangular selection, - * creates profile plot, which is a vertical if - * verticalPlot is 'true'. Use the getPlot() method - * to retrieve the plot. - */ - public ProfilePlot(ImagePlus imp, boolean verticalPlot) { - this.imp = imp; - boolean averageHorizontally = verticalPlot; - Roi roi = imp.getRoi(); - if (roi==null) { - IJ.error("Profile Plot", "Selection required."); - return; - } - int roiType = roi.getType(); - boolean rotatedRect = roi!=null && (roi instanceof RotatedRectRoi); - if (!(roi.isLine()||roiType==Roi.RECTANGLE||rotatedRect)) { - IJ.error("Line or rectangular selection required."); - return; - } - if (rotatedRect) { - double[] p = ((RotatedRectRoi)roi).getParams(); - roi = new Line(p[0], p[1], p[2], p[3]); - roi.setStrokeWidth(p[4]); - roi.setImage(imp); - roiType = Roi.LINE; - } - Calibration cal = imp.getCalibration(); - xInc = cal.pixelWidth; - units = cal.getUnits(); - yLabel = cal.getValueUnit(); - ImageProcessor ip = imp.getProcessor(); - if (roiType==Roi.LINE) - profile = getStraightLineProfile(roi, cal, ip); - else if (roiType==Roi.POLYLINE || roiType==Roi.FREELINE) { - int lineWidth = (int)Math.round(roi.getStrokeWidth()); - if (lineWidth<=1) - profile = getIrregularProfile(roi, ip, cal); - else - profile = getWideLineProfile(imp, lineWidth); - } else if (averageHorizontally) - profile = getRowAverageProfile(roi.getBounds(), cal, ip); - else - profile = getColumnAverageProfile(roi.getBounds(), ip); - ip.setCalibrationTable(null); - ImageCanvas ic = imp.getCanvas(); - if (ic!=null) - magnification = ic.getMagnification(); - else - magnification = 1.0; - } - - /** Returns the size of the plot that createWindow() creates. */ - public Dimension getPlotSize() { - if (profile==null) return null; - int width = (int)(profile.length*magnification); - int height = (int)(width*ASPECT_RATIO); - if (widthmaxWidth) { - width = maxWidth; - height = (int)(width*ASPECT_RATIO); - } - return new Dimension(width, height); - } - - /** Displays this profile plot in a window. */ - public void createWindow() { - Plot plot = getPlot(); - if (plot!=null) - plot.show(); - } - - /** Returns the profile plot as a Plot object. */ - public Plot getPlot() { - if (profile==null) - return null; - String xLabel = "Distance ("+units+")"; - int n = profile.length; - if (xValues==null) { - xValues = new float[n]; - for (int i=0; i0 && (title.length()-index)<=5) - title = title.substring(0, index); - return title; - } - - /** Returns the profile plot data. */ - public double[] getProfile() { - return profile; - } - - /** Returns the calculated minimum value. */ - public double getMin() { - if (!minAndMaxCalculated) - findMinAndMax(); - return min; - } - - /** Returns the calculated maximum value. */ - public double getMax() { - if (!minAndMaxCalculated) - findMinAndMax(); - return max; - } - - /** Sets the y-axis min and max. Specify (0,0) to autoscale. */ - public static void setMinAndMax(double min, double max) { - fixedMin = min; - fixedMax = max; - IJ.register(ProfilePlot.class); - } - - /** Returns the profile plot y-axis min. Auto-scaling is used if min=max=0. */ - public static double getFixedMin() { - return fixedMin; - } - - /** Returns the profile plot y-axis max. Auto-scaling is used if min=max=0. */ - public static double getFixedMax() { - return fixedMax; - } - - double[] getStraightLineProfile(Roi roi, Calibration cal, ImageProcessor ip) { - ip.setInterpolate(PlotWindow.interpolate); - Line line = (Line)roi; - double[] values = line.getPixels(); - if (values==null) return null; - if (cal!=null && cal.pixelWidth!=cal.pixelHeight) { - FloatPolygon p = line.getFloatPoints(); - double dx = p.xpoints[1] - p.xpoints[0]; - double dy = p.ypoints[1] - p.ypoints[0]; - double pixelLength = Math.sqrt(dx*dx + dy*dy); - dx = cal.pixelWidth*dx; - dy = cal.pixelHeight*dy; - double calibratedLength = Math.sqrt(dx*dx + dy*dy); - xInc = calibratedLength * 1.0/pixelLength; - } - return values; - } - - double[] getRowAverageProfile(Rectangle rect, Calibration cal, ImageProcessor ip) { - double[] profile = new double[rect.height]; - int[] counts = new int[rect.height]; - double[] aLine; - ip.setInterpolate(false); - for (int x=rect.x; xsubpixel resolution), - * the line coordinates are interpreted as the roi line shown at high zoom level, - * i.e., integer (x,y) is at the top left corner of pixel (x,y). - * Thus, the coordinates of the pixel center are taken as (x+0.5, y+0.5). - * If subpixel resolution if off, the coordinates of the pixel centers are taken - * as integer (x,y). */ - double[] getIrregularProfile(Roi roi, ImageProcessor ip, Calibration cal) { - boolean interpolate = PlotWindow.interpolate; - boolean calcXValues = cal!=null && cal.pixelWidth!=cal.pixelHeight; - FloatPolygon p = roi.getFloatPolygon(); - int n = p.npoints; - float[] xpoints = p.xpoints; - float[] ypoints = p.ypoints; - ArrayList values = new ArrayList(); - int n2; - double inc = 0.01; - double distance=0.0, distance2=0.0, dx=0.0, dy=0.0, xinc, yinc; - double x, y, lastx=0.0, lasty=0.0, x1, y1, x2=xpoints[0], y2=ypoints[0]; - double value; - for (int i=1; i=1.0-inc/2.0) { - if (interpolate) - value = ip.getInterpolatedValue(x, y); - else - value = ip.getPixelValue((int)Math.round(x), (int)Math.round(y)); - values.add(Double.valueOf(value)); - lastx=x; lasty=y; - } - x += xinc; - y += yinc; - } while (--n2>0); - } - double[] values2 = new double[values.size()]; - for (int i=0; imax) - max = value; - } - this.min = min; - this.max = max; - } - - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/ProgressBar.java b/com.eco.bio7.image/src/ij/gui/ProgressBar.java deleted file mode 100644 index 87e7cfd9f..000000000 --- a/com.eco.bio7.image/src/ij/gui/ProgressBar.java +++ /dev/null @@ -1,174 +0,0 @@ -package ij.gui; - -import ij.IJ; -import ij.ImageJ; -import ij.macro.Interpreter; - -import java.awt.*; -import java.awt.image.*; - -import javax.swing.JPanel; - -/** - * This is the progress bar that is displayed in the lower right hand corner of - * the ImageJ window. Use one of the static IJ.showProgress() methods to display - * and update the progress bar. - */ -public class ProgressBar extends JPanel { - public static final int WIDTH = 120; - public static final int HEIGHT = 20; - private int canvasWidth, canvasHeight; - private int x, y, width, height; - private long lastTime = 0; - private boolean showBar; - private boolean batchMode; - - private Color barColor = Color.gray; - private Color fillColor = new Color(204, 204, 255); - private Color backgroundColor = ImageJ.getSystemColour();// Changed for Bio7! - private Color frameBrighter = backgroundColor.brighter(); - private Color frameDarker = backgroundColor.darker(); - private boolean dualDisplay = false; - private double slowX = 0.0;// box - private double fastX = 0.0;// dot - - /** - * This constructor is called once by ImageJ at startup. - */ - public ProgressBar(int canvasWidth, int canvasHeight) { - init(canvasWidth, canvasHeight); - } - - public void init(int canvasWidth, int canvasHeight) { - this.canvasWidth = canvasWidth; - this.canvasHeight = canvasHeight; - x = 3; - y = 5; - width = canvasWidth - 8; - height = canvasHeight - 7; - /* Changed for Bio7! */ - this.setBackground(ImageJ.getSystemColour()); - } - - void fill3DRect(Graphics g, int x, int y, int width, int height) { - g.setColor(fillColor); - g.fillRect(x + 1, y + 1, width - 2, height - 2); - g.setColor(frameDarker); - g.drawLine(x, y, x, y + height); - g.drawLine(x + 1, y, x + width - 1, y); - g.setColor(frameBrighter); - g.drawLine(x + 1, y + height, x + width, y + height); - g.drawLine(x + width, y, x + width, y + height - 1); - } - - /** - * Updates the progress bar, where abs(progress) should run from 0 to 1. If - * abs(
macro
name
arg
currentValue+1)/finalValue
currentValue>=finalValue
displayMode
title
path
Type
Width
height
Depth
Esc
- * ImageJ is a work of the United States Government. It is in the public domain - * and open source. There is no copyright. You are free to do anything you want - * with this source but I like to get credit for my work and I would like you to - * offer your changes to me so I can possibly add them to the "official" - * version. - * - *
- * The following command line options are recognized by ImageJ: - * - * "file-name" - * Opens a file - * Example 1: blobs.tif - * Example 2: /Users/wayne/images/blobs.tif - * Example 3: e81*.tif - * - * -macro path [arg] - * Runs a macro or script (JavaScript, BeanShell or Python), passing an - * optional string argument, which the macro or script can be retrieve - * using the getArgument() function. The macro or script is assumed to - * be in the ImageJ/macros folder if 'path' is not a full directory path. - * Example 1: -macro analyze.ijm - * Example 2: -macro script.js /Users/wayne/images/stack1 - * Example 2: -macro script.py '1.2 2.4 3.8' - * - * -batch path [arg] - * Runs a macro or script (JavaScript, BeanShell or Python) in - * batch (no GUI) mode, passing it an optional argument. - * ImageJ exits when the macro finishes. - * - * -eval "macro code" - * Evaluates macro code - * Example 1: -eval "print('Hello, world');" - * Example 2: -eval "return getVersion();" - * - * -run command - * Runs an ImageJ menu command - * Example: -run "About ImageJ..." - * - * -ijpath path - * Specifies the path to the directory containing the plugins directory - * Example: -ijpath /Applications/ImageJ - * - * -port - * Specifies the port ImageJ uses to determine if another instance is running - * Example 1: -port1 (use default port address + 1) - * Example 2: -port2 (use default port address + 2) - * Example 3: -port0 (don't check for another instance) - * - * -debug - * Runs ImageJ in debug mode - *
- Here is an example applet tag that launches ImageJ as an applet - and passes it the URLs of two images: -
- <applet archive="../ij.jar" code="ij.ImageJApplet.class" width=0 height=0> - <param name=url1 value="http://imagej.nih.gov/ij/images/FluorescentCells.jpg"> - <param name=url2 value="http://imagej.nih.gov/ij/images/blobs.gif"> - </applet> -
- Macros contained in a file named "StartupMacros.txt", in the same directory as the HTML file - containing the applet tag, will be installed on startup. -*/ -public class ImageJApplet extends Applet { - - /** Starts ImageJ if it's not already running. */ - public void init() { - ImageJ ij = IJ.getInstance(); - if (ij==null || (ij!=null && !ij.isShowing())) - new ImageJ(this); - for (int i=1; i<=9; i++) { - String url = getParameter("url"+i); - if (url==null) break; - ImagePlus imp = new ImagePlus(url); - if (imp!=null) imp.show(); - } - } - - public void destroy() { - ImageJ ij = IJ.getInstance(); - if (ij!=null) ij.quit(); - } - -} - diff --git a/com.eco.bio7.image/src/ij/ImageListener.java b/com.eco.bio7.image/src/ij/ImageListener.java deleted file mode 100644 index ae8faacd6..000000000 --- a/com.eco.bio7.image/src/ij/ImageListener.java +++ /dev/null @@ -1,17 +0,0 @@ -package ij; - - /** Plugins that implement this interface are notified when - an image is opened, closed or updated. The - Plugins/Utilities/Monitor Events command uses this interface. - */ - public interface ImageListener { - - public void imageOpened(ImagePlus imp); - - public void imageClosed(ImagePlus imp); - - public void imageUpdated(ImagePlus imp); - - //default void imageSaved(ImagePlus imp) { } - -} diff --git a/com.eco.bio7.image/src/ij/ImageListenerAdapter.java b/com.eco.bio7.image/src/ij/ImageListenerAdapter.java deleted file mode 100644 index 231b2ed51..000000000 --- a/com.eco.bio7.image/src/ij/ImageListenerAdapter.java +++ /dev/null @@ -1,34 +0,0 @@ -package ij; - -/** -* An Adapter class for the ImageListener interface. Note ImageListenerAdapter -* supports notification when an ImagePlus gets saved. -*
-* With this adapter you need only override the methods that you require -* notification for. -*
-* TODO When ImageJ has a minimum support of Java8 consider updating -* ImageListener to provide default methods for all these callbacks as this will -* allow ImageListener interface to be used as mix-in class whereas Java single -* inheritance precludes that for this ImageListenerAdapter class. -* -* @author Michael Ellis -*/ -public class ImageListenerAdapter implements ImageListener { - - @Override - public void imageOpened(ImagePlus imp) { - } - - @Override - public void imageClosed(ImagePlus imp) { - } - - @Override - public void imageUpdated(ImagePlus imp) { - } - - public void imageSaved(ImagePlus imp) { - } - -} diff --git a/com.eco.bio7.image/src/ij/ImagePlus.java b/com.eco.bio7.image/src/ij/ImagePlus.java deleted file mode 100644 index caa63874b..000000000 --- a/com.eco.bio7.image/src/ij/ImagePlus.java +++ /dev/null @@ -1,3547 +0,0 @@ -package ij; -import java.awt.*; -import java.awt.image.*; -import java.net.URL; -import java.util.*; -import ij.process.*; -import ij.io.*; -import ij.gui.*; - -import ij.measure.*; -import ij.plugin.filter.Analyzer; -import ij.util.*; -import ij.macro.Interpreter; -import ij.plugin.*; -import ij.plugin.frame.*; - - -/** -An ImagePlus contain an ImageProcessor (2D image) or an ImageStack (3D, 4D or 5D image). -It also includes metadata (spatial calibration and possibly the directory/file where -it was read from). The ImageProcessor contains the pixel data (8-bit, 16-bit, float or RGB) -of the 2D image and some basic methods to manipulate it. An ImageStack is essentually -a list ImageProcessors of same type and size. -@see ij.process.ImageProcessor -@see ij.ImageStack -@see ij.gui.ImageWindow -@see ij.gui.ImageCanvas -*/ - -public class ImagePlus implements ImageObserver, Measurements, Cloneable { - - /** 8-bit grayscale (unsigned)*/ - public static final int GRAY8 = 0; - - /** 16-bit grayscale (unsigned) */ - public static final int GRAY16 = 1; - - /** 32-bit floating-point grayscale */ - public static final int GRAY32 = 2; - - /** 8-bit indexed color */ - public static final int COLOR_256 = 3; - - /** 32-bit RGB color */ - public static final int COLOR_RGB = 4; - - /** Title of image used by Flatten command */ - public static final String flattenTitle = "flatten~canvas"; - - /** True if any changes have been made to this image. */ - public boolean changes; - - protected Image img; - protected ImageProcessor ip; - protected ImageWindow win; - protected Roi roi; - protected int currentSlice; // current stack index (one-based) - protected static final int OPENED=0, CLOSED=1, UPDATED=2, SAVED=3; - protected boolean compositeImage; - protected int width; - protected int height; - protected boolean locked; - private int lockedCount; - private Thread lockingThread; - protected int nChannels = 1; - protected int nSlices = 1; - protected int nFrames = 1; - protected boolean dimensionsSet; - - private ImageJ ij = IJ.getInstance(); - private String title; - private String url; - private FileInfo fileInfo; - private int imageType = GRAY8; - private boolean typeSet; - private ImageStack stack; - private static int currentID = -1; - private int ID; - private static Component comp; - private boolean imageLoaded; - private int imageUpdateY, imageUpdateW; - private Properties properties; - private long startTime; - private Calibration calibration; - private static Calibration globalCalibration; - private boolean activated; - private boolean ignoreFlush; - private boolean errorLoadingImage; - private static ImagePlus clipboard; - private static Vector listeners = new Vector(); - private boolean openAsHyperStack; - private int[] position = {1,1,1}; - private boolean noUpdateMode; - private ImageCanvas flatteningCanvas; - private Overlay overlay; - private boolean compositeChanges; - private boolean hideOverlay; - private static int default16bitDisplayRange; - private boolean antialiasRendering = true; - private boolean ignoreGlobalCalibration; - private boolean oneSliceStack; - public boolean setIJMenuBar = Prefs.setIJMenuBar; - private Plot plot; - private Properties imageProperties; - private Color borderColor; - private boolean temporary; - private double defaultMin, defaultMax; - - - /** Constructs an uninitialized ImagePlus. */ - public ImagePlus() { - title = (this instanceof CompositeImage)?"composite":"null"; - setID(); - } - - /** Constructs an ImagePlus from an Image or BufferedImage. The first - argument will be used as the title of the window that displays the image. - Throws an IllegalStateException if an error occurs while loading the image. */ - public ImagePlus(String title, Image image) { - this.title = title; - if (image!=null) - setImage(image); - setID(); - } - - /** Constructs an ImagePlus from an ImageProcessor. */ - public ImagePlus(String title, ImageProcessor ip) { - setProcessor(title, ip); - setID(); - } - - /** Constructs an ImagePlus from a TIFF, BMP, DICOM, FITS, - PGM, GIF or JPRG specified by a path or from a TIFF, DICOM, - GIF or JPEG specified by a URL. */ - public ImagePlus(String pathOrURL) { - Opener opener = new Opener(); - ImagePlus imp = null; - boolean isURL = pathOrURL.indexOf("://")>0; - if (isURL) - imp = opener.openURL(pathOrURL); - else - imp = opener.openImage(pathOrURL); - if (imp!=null) { - if (imp.getStackSize()>1) - setStack(imp.getTitle(), imp.getStack()); - else - setProcessor(imp.getTitle(), imp.getProcessor()); - setCalibration(imp.getCalibration()); - properties = imp.getProperties(); - setFileInfo(imp.getOriginalFileInfo()); - setDimensions(imp.getNChannels(), imp.getNSlices(), imp.getNFrames()); - setOverlay(imp.getOverlay()); - setRoi(imp.getRoi()); - if (isURL) - this.url = pathOrURL; - setID(); - } - } - - /** Constructs an ImagePlus from a stack. */ - public ImagePlus(String title, ImageStack stack) { - setStack(title, stack); - setID(); - } - - private void setID() { - ID = --currentID; - } - - public void setTemporary() { - if (!temporary) { - temporary = true; - currentID++; - ID = -Integer.MAX_VALUE; - } - } - - /** Locks the image so other threads can test to see if it is in use. - * One thread can lock an image multiple times, then it has to unlock - * it as many times until it is unlocked. This allows nested locking - * within a thread. - * Returns true if the image was successfully locked. - * Beeps, displays a message in the status bar, and returns - * false if the image is already locked by another thread. - */ - public synchronized boolean lock() { - return lock(true); - } - - /** Similar to lock, but doesn't beep and display an error - * message if the attempt to lock the image fails. - */ - public synchronized boolean lockSilently() { - return lock(false); - } - - private synchronized boolean lock(boolean loud) { - if (locked) { - if (Thread.currentThread()==lockingThread) { - lockedCount++; //allow locking multiple times by the same thread - return true; - } else { - if (loud) { - IJ.beep(); - IJ.showStatus("\"" + title + "\" is locked"); - if (IJ.debugMode) IJ.log(title + " is locked by " + lockingThread + "; refused locking by " + Thread.currentThread().getName()); - if (IJ.macroRunning()) - IJ.wait(500); - } - return false; - } - } else { - locked = true; //we could use 'lockedCount instead, but subclasses might use - lockedCount = 1; - lockingThread = Thread.currentThread(); - if (win instanceof StackWindow) - ((StackWindow)win).setSlidersEnabled(false); - if (IJ.debugMode) IJ.log(title + ": locked" + (loud ? "" : "silently") + " by " + Thread.currentThread().getName()); - return true; - } - } - - /** Unlocks the image. - * In case the image had been locked several times by the current thread, - * it gets unlocked only after as many unlock operations as there were - * previous lock operations. - */ - public synchronized void unlock() { - if (Thread.currentThread()==lockingThread && lockedCount>1) - lockedCount--; - else { - locked = false; - lockedCount = 0; - lockingThread = null; - if (win instanceof StackWindow) - ((StackWindow)win).setSlidersEnabled(true); - if (IJ.debugMode) IJ.log(title + ": unlocked"); - } - } - - /** Returns 'true' if the image is locked. */ - public boolean isLocked() { - return locked; - } - - /** Returns 'true' if the image was locked on another thread. */ - public boolean isLockedByAnotherThread() { - return locked && Thread.currentThread()!=lockingThread; - } - - private void waitForImage(Image image) { - if (comp==null) { - comp = IJ.getInstance(); - if (comp==null) - comp = new Canvas(); - } - imageLoaded = false; - if (!comp.prepareImage(image, this)) { - double progress; - waitStart = System.currentTimeMillis(); - while (!imageLoaded && !errorLoadingImage) { - IJ.wait(30); - if (imageUpdateW>1) { - progress = (double)imageUpdateY/imageUpdateW; - if (!(progress<1.0)) { - progress = 1.0 - (progress-1.0); - if (progress<0.0) progress = 0.9; - } - showProgress(progress); - } - } - showProgress(1.0); - } - } - - long waitStart; - private void showProgress(double percent) { - if ((System.currentTimeMillis()-waitStart)>500L) - IJ.showProgress(percent); - } - - /** Draws the image. If there is an ROI, its - outline is also displayed. Does nothing if there - is no window associated with this image (i.e. show() - has not been called).*/ - public void draw() { - if (win!=null) - win.getCanvas().repaint(); - } - - /** Draws image and roi outline using a clip rect. */ - public void draw(int x, int y, int width, int height){ - if (win!=null) { - ImageCanvas ic = win.getCanvas(); - double mag = ic.getMagnification(); - x = ic.screenX(x); - y = ic.screenY(y); - width = (int)(width*mag); - height = (int)(height*mag); - ic.repaint(x, y, width, height); - if (listeners.size()>0 && roi!=null && roi.getPasteMode()!=Roi.NOT_PASTING) - notifyListeners(UPDATED); - } - } - - /** Updates this image from the pixel data in its - associated ImageProcessor, then displays it. Does - nothing if there is no window associated with - this image (i.e. show() has not been called).*/ - public synchronized void updateAndDraw() { - if (win==null) { - img = null; - return; - } - if (stack!=null && !stack.isVirtual() && currentSlice>=1 && currentSlice<=stack.size()) { - if (stack.size()>1 && win!=null && !(win instanceof StackWindow)) { - setStack(stack); //adds scroll bar if stack size has changed to >1 - return; - } - Object pixels = stack.getPixels(currentSlice); - if (ip!=null && pixels!=null && pixels!=ip.getPixels()) { // was stack updated? - try { - ip.setPixels(pixels); - ip.setSnapshotPixels(null); - } catch(Exception e) {} - } - } - if (win!=null) { - win.getCanvas().setImageUpdated(); - if (listeners.size()>0) notifyListeners(UPDATED); - } - draw(); - } - - /** Use to update the image when the underlying virtual stack changes. */ - public void updateVirtualSlice() { - ImageStack vstack = getStack(); - if (vstack.isVirtual()) { - double min=getDisplayRangeMin(), max=getDisplayRangeMax(); - setProcessor(vstack.getProcessor(getCurrentSlice())); - setDisplayRange(min,max); - } else - throw new IllegalArgumentException("Virtual stack required"); - } - - /** Sets the display mode of composite color images, where 'mode' - should be IJ.COMPOSITE, IJ.COLOR or IJ.GRAYSCALE. */ - public void setDisplayMode(int mode) { - if (this instanceof CompositeImage) { - ((CompositeImage)this).setMode(mode); - updateAndDraw(); - } - } - - /** Returns the display mode (IJ.COMPOSITE, IJ.COLOR - or IJ.GRAYSCALE) if this is a composite color - image, or 0 if it not. */ - public int getDisplayMode() { - if (this instanceof CompositeImage) - return ((CompositeImage)this).getMode(); - else - return 0; - } - - /** Controls which channels in a composite color image are displayed, - where 'channels' is a list of ones and zeros that specify the channels to - display. For example, "101" causes channels 1 and 3 to be displayed. */ - public void setActiveChannels(String channels) { - if (!(this instanceof CompositeImage)) - return; - boolean[] active = ((CompositeImage)this).getActiveChannels(); - for (int i=0; ii && channels.charAt(i)=='1') - b = true; - active[i] = b; - } - updateAndDraw(); - Channels.updateChannels(); - } - - /** Updates this image from the pixel data in its - associated ImageProcessor, then displays it. - The CompositeImage class overrides this method - to only update the current channel. */ - public void updateChannelAndDraw() { - updateAndDraw(); - } - - /** Returns a reference to the current ImageProcessor. The - CompositeImage class overrides this method to return - the processor associated with the current channel. */ - public ImageProcessor getChannelProcessor() { - return getProcessor(); - } - - /** Returns an array containing the lookup tables used by this image, - * one per channel, or an empty array if this is an RGB image. - * @see #getNChannels - * @see #isComposite - * @see #getCompositeMode - * - * Javascript example: - * - * luts = imp.getLuts(); - * for (i=0; i - * IJ.log((i+1)+“: “+luts[i].min+”-”+luts[i].max); - * - */ - public LUT[] getLuts() { - ImageProcessor ip2 = getProcessor(); - if (ip2==null) - return new LUT[0]; - LUT lut = ip2.getLut(); - if (lut==null) - return new LUT[0]; - LUT[] luts = new LUT[1]; - luts[0] = lut; - return luts; - } - - /** Calls draw to draw the image and also repaints the - image window to force the information displayed above - the image (dimension, type, size) to be updated. */ - public void repaintWindow() { - if (win!=null) { - draw(); - win.repaint(); - } - } - - /** Calls updateAndDraw to update from the pixel data - and draw the image, and also repaints the image - window to force the information displayed above - the image (dimension, type, size) to be updated. */ - public void updateAndRepaintWindow() { - if (win!=null) { - updateAndDraw(); - win.repaint(); - } - } - - /** ImageCanvas.paint() calls this method when the - * ImageProcessor has generated a new image. - */ - public void updateImage() { - if (win==null) { - img = null; - return; - } - if (ip!=null) - img = ip.createImage(); - } - - /** Closes the window, if any, that is displaying this image. */ - public void hide() { - if (win==null) { - img = null; - Interpreter.removeBatchModeImage(this); - return; - } - boolean unlocked = lockSilently(); - Overlay overlay2 = getOverlay(); - changes = false; - win.close(); - win = null; - setOverlay(overlay2); - if (unlocked) unlock(); - } - - /** Closes this image and sets the ImageProcessor to null. To avoid the - "Save changes?" dialog, first set the public 'changes' variable to false. */ - public void close() { - ImageWindow win = getWindow(); - if (win!=null) - win.close(); - else { - if (WindowManager.getCurrentImage()==this) - WindowManager.setTempCurrentImage(null); - deleteRoi(); //save any ROI so it can be restored later - Interpreter.removeBatchModeImage(this); - } - } - - /** Opens a window to display this image and clears the status bar. */ - public void show() { - show(""); - } - - /** Opens a window to display this image and displays - 'statusMessage' in the status bar. */ - public void show(String statusMessage) { - if (isVisible() || temporary) - return; - win = null; - if ((IJ.isMacro() && ij==null) || Interpreter.isBatchMode()) { - if (isComposite()) ((CompositeImage)this).reset(); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp!=null) imp.saveRoi(); - WindowManager.setTempCurrentImage(this); - Interpreter.addBatchModeImage(this); - return; - } - if (Prefs.useInvertingLut && getBitDepth()==8 && ip!=null && !ip.isInvertedLut()&& !ip.isColorLut()) - invertLookupTable(); - img = getImage(); - if ((img!=null) && (width>=0) && (height>=0)) { - activated = false; - int stackSize = getStackSize(); - if (stackSize>1) - win = new StackWindow(this); // displays the window and (if macro) waits for window to be activated - else if (getProperty(Plot.PROPERTY_KEY) != null) - win = new PlotWindow(this, (Plot)(getProperty(Plot.PROPERTY_KEY))); - else - win = new ImageWindow(this); - if (roi!=null) roi.setImage(this); - if (overlay!=null && getCanvas()!=null) - getCanvas().setOverlay(overlay); - IJ.showStatus(statusMessage); - if (IJ.isMacro() && stackSize==1) // for non-stacks, wait for window to be activated - waitTillActivated(); - if (imageType==GRAY16 && default16bitDisplayRange!=0) { - resetDisplayRange(); - updateAndDraw(); - } - if (stackSize>1) { - int c = getChannel(); - int z = getSlice(); - int t = getFrame(); - if (c>1 || z>1 || t>1) - setPosition(c, z, t); - } - if (setIJMenuBar) - IJ.wait(25); - notifyListeners(OPENED); - } - } - - void invertLookupTable() { - int nImages = getStackSize(); - ip.invertLut(); - if (nImages==1) - ip.invert(); - else { - ImageStack stack2 = getStack(); - for (int i=1; i<=nImages; i++) - stack2.getProcessor(i).invert(); - stack2.setColorModel(ip.getColorModel()); - } - } - - /** Waits until the image window becomes activated. This is necessary in - * macros or other programs if an ImagePlus is shown on the screen, - * because displaying the window is asynchronous (happens later) - * and will make the image the active one. Without waiting, in the - * meanwhile another window could be already the active one and would - * become deactivated. - * If the ImagePlus may have been displayed previously, first call - * setDeactivated(). - * ImagePlus.show() and new StackWindow(ImagePlus) - * call this method if IJ.isMacro() is true, i.e., when running a macro or - * executing an IJ.run(...) call. - */ - public void waitTillActivated() { - if (win == null) return; - if (EventQueue.isDispatchThread()) { //'activated' is set in the EventQueue, we can't wait for it in the EventQueue - WindowManager.setTempCurrentImage(this); - return; - } - long start = System.currentTimeMillis(); - while (!activated) { - IJ.wait(5); - if (ij != null && ij.quitting()) return; - if ((System.currentTimeMillis()-start)>2000) { - WindowManager.setTempCurrentImage(this); - break; // 2 second timeout - } - } - } - - /** Called by ImageWindow.windowActivated(); to end waiting in waitTillActivated. */ - public void setActivated() { - activated = true; - if (borderColor!=null && win!=null) - win.setBackground(borderColor); - } - - /** Called by new StackWindow(ImagePlus) - * before showing the StackWindow, to prepare for - * waitTillActivated(). - */ - public void setDeactivated() { - activated = false; - } - - /** Returns this image as a AWT image. */ - public Image getImage() { - if (img==null && ip!=null) - img = ip.createImage(); - return img; - } - - /** Returns a copy of this image as an 8-bit or RGB BufferedImage. - * @see ij.process.ShortProcessor#get16BitBufferedImage - */ - public BufferedImage getBufferedImage() { - if (isComposite()) - return (new ColorProcessor(getImage())).getBufferedImage(); - else - return ip.getBufferedImage(); - } - - /** Returns this image's unique numeric ID. */ - public int getID() { - return ID; - } - - /** Replaces the image, if any, with the one specified. - * Throws an IllegalStateException if an error occurs - * while loading the image. - */ - public void setImage(Image image) { - if (image instanceof BufferedImage) { - BufferedImage bi = (BufferedImage)image; - int nBands = bi.getSampleModel().getNumBands(); - int type = bi.getType(); - boolean rgb = type==BufferedImage.TYPE_3BYTE_BGR||type==BufferedImage.TYPE_INT_RGB - ||type==BufferedImage.TYPE_4BYTE_ABGR||type==BufferedImage.TYPE_BYTE_INDEXED - ||type==BufferedImage.TYPE_INT_ARGB||type==BufferedImage.TYPE_INT_BGR; - int dataType = bi.getSampleModel().getDataType(); - if (IJ.debugMode) IJ.log("setImage: type="+type+", bands="+nBands+", rgb="+rgb+", datatype="+dataType); - if (nBands>1 && !rgb) { - ImageStack biStack = new ImageStack(bi.getWidth(), bi.getHeight()); - for (int b=0; b0?GRAY8:COLOR_RGB; - if (image!=null && type==COLOR_RGB) - ip = new ColorProcessor(image); - if (ip==null && image!=null) - ip = new ByteProcessor(image); - setType(type); - this.img = ip.createImage(); - if (win!=null) { - if (dimensionsChanged) - win = new ImageWindow(this); - else - repaintWindow(); - } - } - - /** - * Extract pixels as an ImageProcessor from a single band of a BufferedImage. - * @param img - * @param band - * @return - */ - public static ImageProcessor convertToImageProcessor(BufferedImage img, int band) { - int w = img.getWidth(); - int h = img.getHeight(); - int dataType = img.getSampleModel().getDataType(); - // Read data as float (no matter what it is - it's the most accuracy ImageJ can provide) - FloatProcessor fp = new FloatProcessor(w, h); - float[] pixels = (float[])fp.getPixels(); - img.getRaster().getSamples(0, 0, w, h, band, pixels); - // Convert to 8 or 16-bit, if appropriate - if (dataType == DataBuffer.TYPE_BYTE) { - ByteProcessor bp = new ByteProcessor(w, h); - bp.setPixels(0, fp); - return bp; - } else if (dataType == DataBuffer.TYPE_USHORT) { - ShortProcessor sp = new ShortProcessor(w, h); - sp.setPixels(0, fp); - return sp; - } else - return fp; - } - - /** Replaces this image with the specified ImagePlus. May - not work as expected if 'imp' is a CompositeImage - and this image is not. */ - public void setImage(ImagePlus imp) { - Properties newProperties = imp.getProperties(); - if (newProperties!=null) - newProperties = (Properties)(newProperties.clone()); - if (imp.getWindow()!=null) - imp = imp.duplicate(); - ImageStack stack2 = imp.getStack(); - if (imp.isHyperStack()) - setOpenAsHyperStack(true); - LUT[] luts = null; - if (imp.isComposite() && (this instanceof CompositeImage)) { - if (((CompositeImage)imp).getMode()!=((CompositeImage)this).getMode()) - ((CompositeImage)this).setMode(((CompositeImage)imp).getMode()); - luts = ((CompositeImage)imp).getLuts(); - } - LUT lut = !imp.isComposite()?imp.getProcessor().getLut():null; - setStack(stack2, imp.getNChannels(), imp.getNSlices(), imp.getNFrames()); - compositeImage = imp.isComposite(); - if (luts!=null) { - ((CompositeImage)this).setLuts(luts); - ((CompositeImage)this).setMode(((CompositeImage)imp).getMode()); - updateAndRepaintWindow(); - } else if (lut!=null) { - getProcessor().setLut(lut); - updateAndRepaintWindow(); - } - setTitle(imp.getTitle()); - setCalibration(imp.getCalibration()); - setOverlay(imp.getOverlay()); - properties = newProperties; - if (getProperty(Plot.PROPERTY_KEY)!=null && win instanceof PlotWindow) { - Plot plot = (Plot)(getProperty(Plot.PROPERTY_KEY)); - ((PlotWindow)win).setPlot(plot); - plot.setImagePlus(this); - } - setFileInfo(imp.getOriginalFileInfo()); - setProperty ("Info", imp.getProperty ("Info")); - setProperties(imp.getPropertiesAsArray()); - } - - /** Replaces the ImageProcessor with the one specified and updates the - display. With stacks, the ImageProcessor must be the same type as the - other images in the stack and it must be the same width and height. */ - public void setProcessor(ImageProcessor ip) { - setProcessor(null, ip); - } - - /** Replaces the ImageProcessor with the one specified and updates the display. With - stacks, the ImageProcessor must be the same type as other images in the stack and - it must be the same width and height. Set 'title' to null to leave the title unchanged. */ - public void setProcessor(String title, ImageProcessor ip) { - if (ip==null || ip.getPixels()==null) - throw new IllegalArgumentException("ip null or ip.getPixels() null"); - if (getStackSize()>1) { - if (ip.getWidth()!=width || ip.getHeight()!=height) - throw new IllegalArgumentException("Wrong dimensions for this stack"); - int ipBitDepth = ip.getBitDepth(); - int stackBitDepth = stack!=null?stack.getBitDepth():0; - if (ipBitDepth>0 && stackBitDepth>0 && ipBitDepth!=stackBitDepth) { - String info = " \nsize="+getStackSize()+", ipBitDepth="+ipBitDepth+", stackBitDepth="+stackBitDepth; - throw new IllegalArgumentException("Wrong type for this stack"+info); - } - } else { - setStackNull(); - setCurrentSlice(1); - } - setProcessor2(title, ip, null); - } - - void setProcessor2(String title, ImageProcessor ip, ImageStack newStack) { - if (title!=null) setTitle(title); - if (ip==null) - return; - this.ip = ip; - if (this.ip!=null && getWindow()!=null) - notifyListeners(UPDATED); - if (ij!=null) - ip.setProgressBar(ij.getProgressBar()); - int stackSize = 1; - boolean dimensionsChanged = width>0 && height>0 && (width!=ip.getWidth() || height!=ip.getHeight()); - if (stack!=null) { - stackSize = stack.size(); - if (currentSlice>stackSize) - setCurrentSlice(stackSize); - if (currentSlice>=1 && currentSlice<=stackSize && !dimensionsChanged) - stack.setPixels(ip.getPixels(),currentSlice); - } - img = null; - if (dimensionsChanged) roi = null; - int type; - if (ip instanceof ByteProcessor) - type = GRAY8; - else if (ip instanceof ColorProcessor) - type = COLOR_RGB; - else if (ip instanceof ShortProcessor) - type = GRAY16; - else - type = GRAY32; - if (width==0) - imageType = type; - else - setType(type); - width = ip.getWidth(); - height = ip.getHeight(); - if (win!=null) { - if (dimensionsChanged && stackSize==1) - win.updateImage(this); - else if (newStack==null) - repaintWindow(); - draw(); - } - } - - /** Replaces the image with the specified stack and updates the display. */ - public void setStack(ImageStack stack) { - setStack(null, stack); - } - - /** Replaces the image with the specified stack and updates - the display. Set 'title' to null to leave the title unchanged. */ - public void setStack(String title, ImageStack newStack) { - int bitDepth1 = getBitDepth(); - int previousStackSize = getStackSize(); - int newStackSize = newStack.getSize(); - if (newStackSize==0) - throw new IllegalArgumentException("Stack is empty"); - if (!newStack.isVirtual()) { - Object[] arrays = newStack.getImageArray(); - if (arrays==null || (arrays.length>0&&arrays[0]==null)) - throw new IllegalArgumentException("Stack pixel array null"); - } - boolean sliderChange = false; - if (win!=null && (win instanceof StackWindow)) { - int nScrollbars = ((StackWindow)win).getNScrollbars(); - if (nScrollbars>0 && newStackSize==1) - sliderChange = true; - else if (nScrollbars==0 && newStackSize>1) - sliderChange = true; - } - if (currentSlice<1) setCurrentSlice(1); - boolean resetCurrentSlice = currentSlice>newStackSize; - if (resetCurrentSlice) setCurrentSlice(newStackSize); - ImageProcessor newIP = newStack.getProcessor(currentSlice); - boolean dimensionsChanged = width>0 && height>0 && (width!=newIP.getWidth()||height!=newIP.getHeight()); - if (this.stack==null) - newStack.viewers(+1); - this.stack = newStack; - oneSliceStack = false; - setProcessor2(title, newIP, newStack); - if (bitDepth1!=0 && bitDepth1!=getBitDepth()) - compositeChanges = true; - if (compositeChanges && (this instanceof CompositeImage)) { - this.compositeImage = getStackSize()!=getNSlices(); - ((CompositeImage)this).completeReset(); - if (bitDepth1!=0 && bitDepth1!=getBitDepth()) - ((CompositeImage)this).resetDisplayRanges(); - } - compositeChanges = false; - if (win==null) { - if (resetCurrentSlice) setSlice(currentSlice); - return; - } - boolean invalidDimensions = (isDisplayedHyperStack()||(this instanceof CompositeImage)) && (win instanceof StackWindow) && !((StackWindow)win).validDimensions(); - if (newStackSize>1 && !(win instanceof StackWindow)) { - if (isDisplayedHyperStack()) - setOpenAsHyperStack(true); - activated = false; - win = new StackWindow(this, dimensionsChanged?null:getCanvas()); // replaces this window - if (IJ.isMacro()) waitTillActivated(); // wait for stack window to be activated - setPosition(1, 1, 1); - } else if (newStackSize>1 && invalidDimensions) { - if (isDisplayedHyperStack()) - setOpenAsHyperStack(true); - win = new StackWindow(this); // replaces this window - setPosition(1, 1, 1); - } else if (dimensionsChanged || sliderChange) { - win.updateImage(this); - } else { - if (win!=null && win instanceof StackWindow) - ((StackWindow)win).updateSliceSelector(); - if (isComposite()) { - ((CompositeImage)this).reset(); - updateAndDraw(); - } - repaintWindow(); - } - if (resetCurrentSlice) - setSlice(currentSlice); - } - - public void setStack(ImageStack newStack, int channels, int slices, int frames) { - if (newStack==null || channels*slices*frames!=newStack.getSize()) - throw new IllegalArgumentException("channels*slices*frames!=stackSize"); - if (IJ.debugMode) IJ.log("setStack: "+newStack.getSize()+" "+channels+" "+slices+" "+frames+" "+isComposite()); - compositeChanges = channels!=this.nChannels; - this.nChannels = channels; - this.nSlices = slices; - this.nFrames = frames; - setStack(null, newStack); - } - - private synchronized void setStackNull() { - if (oneSliceStack && stack!=null && stack.size()>0) { - String label = stack.getSliceLabel(1); - setProp("Slice_Label", label); - } - stack = null; - oneSliceStack = false; - } - - /** Saves this image's FileInfo so it can be later - retieved using getOriginalFileInfo(). */ - public void setFileInfo(FileInfo fi) { - if (fi!=null) { - fi.pixels = null; - if (fi.imageSaved) { - notifyListeners(SAVED); - fi.imageSaved = false; - } - } - fileInfo = fi; - } - - /** Returns the ImageWindow that is being used to display - this image. Returns null if show() has not be called - or the ImageWindow has been closed. */ - public ImageWindow getWindow() { - return win; - } - - /** Returns true if this image is currently being displayed in a window. */ - public boolean isVisible() { - return win!=null && win.isVisible(); - } - - /** This method should only be called from an ImageWindow. */ - public void setWindow(ImageWindow win) { - this.win = win; - if (roi!=null) - roi.setImage(this); // update roi's 'ic' field - } - - /** Returns the ImageCanvas being used to - display this image, or null. */ - public ImageCanvas getCanvas() { - return win!=null?win.getCanvas():flatteningCanvas; - } - - /** Sets current foreground color. */ - public void setColor(Color c) { - if (ip!=null) - ip.setColor(c); - } - - void setupProcessor() { - } - - public boolean isProcessor() { - return ip!=null; - } - - /** Returns a reference to the current ImageProcessor. If there - is no ImageProcessor, it creates one. Returns null if this - ImagePlus contains no ImageProcessor and no AWT Image. - Sets the line width to the current line width and sets the - calibration table if the image is density calibrated. */ - public ImageProcessor getProcessor() { - if (ip==null) - return null; - if (roi!=null && roi.isArea()) - ip.setRoi(roi.getBounds()); - else - ip.resetRoi(); - if (!compositeImage) - ip.setLineWidth(Line.getWidth()); - if (ij!=null) - ip.setProgressBar(ij.getProgressBar()); - Calibration cal = getCalibration(); - if (cal.calibrated()) - ip.setCalibrationTable(cal.getCTable()); - else - ip.setCalibrationTable(null); - if (IJ.recording()) { - Recorder recorder = Recorder.getInstance(); - if (recorder!=null) recorder.imageUpdated(this); - } - return ip; - } - - /** Frees RAM by setting the snapshot (undo) buffer in - the current ImageProcessor to null. */ - public void trimProcessor() { - ImageProcessor ip2 = ip; - if (!locked && ip2!=null) { - if (IJ.debugMode) IJ.log(title + ": trimProcessor"); - Roi roi2 = getRoi(); - if (roi2!=null && roi2.getPasteMode()!=Roi.NOT_PASTING) - roi2.endPaste(); - ip2.setSnapshotPixels(null); - } - } - - /** For images with irregular ROIs, returns a byte mask, otherwise, returns - * null. Mask pixels have a non-zero value.and the dimensions of the - * mask are equal to the width and height of the ROI. - * @see ij.ImagePlus#createRoiMask - * @see ij.ImagePlus#createThresholdMask - */ - public ImageProcessor getMask() { - if (roi==null) { - if (ip!=null) ip.resetRoi(); - return null; - } - ImageProcessor mask = roi.getMask(); - if (mask==null) - return null; - if (ip!=null && roi!=null) { - ip.setMask(mask); - ip.setRoi(roi.getBounds()); - } - return mask; - } - - /** Returns an 8-bit binary (foreground=255, background=0) - * ROI or overlay mask that has the same dimensions - * as this image. Creates an ROI mask If the image has both - * both an ROI and an overlay. Set the threshold of the mask to 255. - * @see #createThresholdMask - * @see ij.gui.Roi#getMask - */ - public ByteProcessor createRoiMask() { - Roi roi2 = getRoi(); - Overlay overlay2 = getOverlay(); - if (roi2==null && overlay2==null) - throw new IllegalArgumentException("ROI or overlay required"); - ByteProcessor mask = new ByteProcessor(getWidth(),getHeight()); - mask.setColor(255); - if (roi2!=null) - mask.fill(roi2); - else if (overlay2!=null) { - if (overlay2.size()==1 && (overlay2.get(0) instanceof ImageRoi)) { - ImageRoi iRoi = (ImageRoi)overlay2.get(0); - ImageProcessor ip = iRoi.getProcessor(); - if (ip.getWidth()!=mask.getWidth() || ip.getHeight()!=mask.getHeight()) - return mask; - for (int i=0; i - imp = IJ.getImage(); - stats = imp.getStatistics(); - IJ.log("Area: "+stats.area); - IJ.log("Mean: "+stats.mean); - IJ.log("Max: "+stats.max); - - @return an {@link ij.process.ImageStatistics} object - @see #getAllStatistics - @see #getRawStatistics - @see ij.process.ImageProcessor#getStats - */ - public ImageStatistics getStatistics() { - return getStatistics(AREA+MEAN+STD_DEV+MODE+MIN_MAX+RECT); - } - - /** This method returns complete calibrated statistics for this - * image or ROI (with "Limit to threshold"), but it is up to 70 times - * slower than getStatistics(). - * @return an {@link ij.process.ImageStatistics} object - * @see #getStatistics - * @see ij.process.ImageProcessor#getStatistics - */ - public ImageStatistics getAllStatistics() { - return getStatistics(ALL_STATS+LIMIT); - } - - /* Returns uncalibrated statistics for this image or ROI, including - 256 bin histogram, pixelCount, mean, mode, standard deviation, - min and max. - */ - public ImageStatistics getRawStatistics() { - if (roi!=null && roi.isArea()) - ip.setRoi(roi); - else - ip.resetRoi(); - return ImageStatistics.getStatistics(ip, AREA+MEAN+MODE+STD_DEV+MIN_MAX, null); - } - - /** Returns an ImageStatistics object generated using the - specified measurement options. - @see ij.measure.Measurements - */ - public ImageStatistics getStatistics(int mOptions) { - return getStatistics(mOptions, 256, 0.0, 0.0); - } - - /** Returns an ImageStatistics object generated using the - specified measurement options and histogram bin count. */ - public ImageStatistics getStatistics(int mOptions, int nBins) { - return getStatistics(mOptions, nBins, 0.0, 0.0); - } - - /** Returns an ImageStatistics object generated using the - specified measurement options, histogram bin count - and histogram range. */ - public ImageStatistics getStatistics(int mOptions, int nBins, double histMin, double histMax) { - ImageProcessor ip2 = ip; - int bitDepth = getBitDepth(); - if (nBins!=256 && (bitDepth==8||bitDepth==24)) - ip2 =ip.convertToShort(false); - Roi roi2 = roi; - if (roi2==null) - ip2.resetRoi(); - else if (roi2.isArea()) - ip2.setRoi(roi2); - else if ((roi2 instanceof PointRoi) && roi2.size()==1) { - // needed to be consistent with ImageProcessor.getStatistics() - FloatPolygon p = roi2.getFloatPolygon(); - ip2.setRoi((int)p.xpoints[0], (int)p.ypoints[0], 1, 1); - } - ip2.setHistogramSize(nBins); - Calibration cal = getCalibration(); - if (getType()==GRAY16&& !(histMin==0.0&&histMax==0.0)) { - histMin = cal.getRawValue(histMin); - histMax=cal.getRawValue(histMax); - } - ip2.setHistogramRange(histMin, histMax); - ImageStatistics stats = ImageStatistics.getStatistics(ip2, mOptions, cal); - ip2.setHistogramSize(256); - ip2.setHistogramRange(0.0, 0.0); - return stats; - } - - /** Returns the image name. */ - public String getTitle() { - if (title==null) - return ""; - else - return title; - } - - /** If the image title is a file name, returns the name - without the extension and with spaces removed, - otherwise returns the title shortened to the first space. - */ - public String getShortTitle() { - String title = getTitle().trim(); - int index = title.lastIndexOf('.'); - boolean fileName = index>0; - if (fileName) { - title = title.substring(0, index); - title = title.replaceAll(" ",""); - } else { - index = title.indexOf(' '); - if (index>-1 && !fileName) - title = title.substring(0, index); - } - return title; - } - - /** Sets the image name. */ - public void setTitle(String title) { - if (title==null) - return; - if (win!=null) { - if (ij!=null) - Menus.updateWindowMenuItem(this, this.title, title); - String virtual = stack!=null && stack.isVirtual()?" (V)":""; - String global = getGlobalCalibration()!=null?" (G)":""; - String scale = ""; - double magnification = win.getCanvas().getMagnification(); - if (magnification!=1.0) { - double percent = magnification*100.0; - int digits = percent>100.0||percent==(int)percent?0:1; - scale = " (" + IJ.d2s(percent,digits) + "%)"; - } - win.setTitle(title+virtual+global+scale); - } - boolean titleChanged = !title.equals(this.title); - this.title = title; - if (titleChanged && listeners.size()>0) - notifyListeners(UPDATED); - } - - /** Returns the width of this image in pixels. */ - public int getWidth() { - return width; - } - - /** Returns the height of this image in pixels. */ - public int getHeight() { - return height; - } - - /** Returns the size of this image in bytes. */ - public double getSizeInBytes() { - double size = ((double)getWidth()*getHeight()*getStackSize()); - int type = getType(); - switch (type) { - case ImagePlus.GRAY16: size *= 2.0; break; - case ImagePlus.GRAY32: size *= 4.0; break; - case ImagePlus.COLOR_RGB: size *= 4.0; break; - } - return size; - } - - /** Returns the number of stack images. */ - public int getStackSize() { - if (stack==null || oneSliceStack) - return 1; - else { - int slices = stack.size(); - if (slices<=0) slices = 1; - return slices; - } - } - - /** If this is a stack, returns the actual number of images in the stack, else returns 1. */ - public int getImageStackSize() { - if (stack==null) - return 1; - else { - int slices = stack.size(); - if (slices==0) slices = 1; - return slices; - } - } - - /** Sets the 3rd, 4th and 5th dimensions, where - nChannels*nSlices*nFrames - must be equal to the stack size. */ - public void setDimensions(int nChannels, int nSlices, int nFrames) { - //IJ.log("setDimensions: "+nChannels+" "+nSlices+" "+nFrames+" "+getImageStackSize()); - if (nChannels*nSlices*nFrames!=getImageStackSize() && ip!=null) { - //throw new IllegalArgumentException("channels*slices*frames!=stackSize"); - nChannels = 1; - nSlices = getImageStackSize(); - nFrames = 1; - if (isDisplayedHyperStack()) { - setOpenAsHyperStack(false); - new StackWindow(this); - setSlice(1); - } - } - boolean updateWin = isDisplayedHyperStack() && (this.nChannels!=nChannels||this.nSlices!=nSlices||this.nFrames!=nFrames); - boolean newSingleImage = win!=null && (win instanceof StackWindow) && nChannels==1&&nSlices==1&&nFrames==1; - if (newSingleImage) updateWin = true; - this.nChannels = nChannels; - this.nSlices = nSlices; - this.nFrames = nFrames; - if (updateWin) { - if (nSlices!=getImageStackSize()) - setOpenAsHyperStack(true); - ip = null; - img = null; - setPositionWithoutUpdate(getChannel(), getSlice(), getFrame()); - if (isComposite()) ((CompositeImage)this).reset(); - new StackWindow(this); - } - dimensionsSet = true; - } - - /** Returns 'true' if this image has more - * than three dimensions. - */ - public boolean isHyperStack() { - return getNDimensions()>3; - } - - /** Returns the number of dimensions (2, 3, 4 or 5). */ - public int getNDimensions() { - int dimensions = 2; - int[] dim = getDimensions(true); - if (dim[2]>1) dimensions++; - if (dim[3]>1) dimensions++; - if (dim[4]>1) dimensions++; - return dimensions; - } - - /** Returns 'true' if this is a hyperstack currently being displayed in a StackWindow. */ - public boolean isDisplayedHyperStack() { - return win!=null && win instanceof StackWindow && ((StackWindow)win).isHyperStack(); - } - - /** Returns the number of channels. */ - public int getNChannels() { - verifyDimensions(); - return nChannels; - } - - /** Returns the image depth (number of z-slices). */ - public int getNSlices() { - verifyDimensions(); - return nSlices; - } - - /** Returns the number of frames (time-points). */ - public int getNFrames() { - verifyDimensions(); - return nFrames; - } - - /** Returns the dimensions of this image (width, height, nChannels, - nSlices, nFrames) as a 5 element int array. */ - public int[] getDimensions() { - return getDimensions(true); - } - - public int[] getDimensions(boolean varify) { - if (varify) - verifyDimensions(); - int[] d = new int[5]; - d[0] = width; - d[1] = height; - d[2] = nChannels; - d[3] = nSlices; - d[4] = nFrames; - return d; - } - - void verifyDimensions() { - int stackSize = getImageStackSize(); - if (nSlices==1) { - if (nChannels>1 && nFrames==1) - nChannels = stackSize; - else if (nFrames>1 && nChannels==1) - nFrames = stackSize; - } - if (nChannels*nSlices*nFrames!=stackSize) { - nSlices = stackSize; - nChannels = 1; - nFrames = 1; - } - } - - /** Returns the current image type (ImagePlus.GRAY8, ImagePlus.GRAY16, - ImagePlus.GRAY32, ImagePlus.COLOR_256 or ImagePlus.COLOR_RGB). - @see #getBitDepth - */ - public int getType() { - return imageType; - } - - /** Returns the bit depth, 8, 16, 24 (RGB) or 32, or 0 if the bit depth - is unknown. RGB images actually use 32 bits per pixel. */ - public int getBitDepth() { - ImageProcessor ip2 = ip; - if (ip2==null) { - int bitDepth = 0; - switch (imageType) { - case GRAY8: bitDepth=typeSet?8:0; break; - case COLOR_256: bitDepth=8; break; - case GRAY16: bitDepth=16; break; - case GRAY32: bitDepth=32; break; - case COLOR_RGB: bitDepth=24; break; - } - return bitDepth; - } - if (ip2 instanceof ByteProcessor) - return 8; - else if (ip2 instanceof ShortProcessor) - return 16; - else if (ip2 instanceof ColorProcessor) - return 24; - else if (ip2 instanceof FloatProcessor) - return 32; - return 0; - } - - /** Returns the number of bytes per pixel. */ - public int getBytesPerPixel() { - switch (imageType) { - case GRAY16: return 2; - case GRAY32: case COLOR_RGB: return 4; - default: return 1; - } - } - - protected void setType(int type) { - if ((type<0) || (type>COLOR_RGB)) - return; - int previousType = imageType; - imageType = type; - if (imageType!=previousType) { - if (win!=null) - Menus.updateMenus(); - getLocalCalibration().setImage(this); - } - typeSet = true; - } - - public void setTypeToColor256() { - if (imageType==ImagePlus.GRAY8) { - ImageProcessor ip2 = getProcessor(); - if (ip2!=null && !ip2.isThreshold() && ip2.isColorLut() && !ip2.isPseudoColorLut()) { - imageType = COLOR_256; - typeSet = true; - } - } - } - - - /** Returns the string value from the "Info" property string - * associated with 'key', or null if the key is not found. - * Works with DICOM tags and Bio-Formats metadata. - * @see #getNumericProperty - * @see #getInfoProperty - * @see #getProp - * @see #setProp - */ - public String getStringProperty(String key) { - if (key==null) - return null; - if (isDicomTag(key)) - return DicomTools.getTag(this, key); - if (getStackSize()>1) { - ImageStack stack2 = getStack(); - String label = stack2.getSliceLabel(getCurrentSlice()); - if (label!=null && label.indexOf('\n')>0) { - String value = getStringProperty(key, label); - if (value!=null) - return value; - } - } - Object obj = getProperty("Info"); - if (obj==null || !(obj instanceof String)) - return null; - String info = (String)obj; - return getStringProperty(key, info); - } - - private boolean isDicomTag(String key) { - if (key.length()!=9 || key.charAt(4)!=',') - return false; - key = key.toLowerCase(); - for (int i=0; i<9; i++) { - char c = i!=4?key.charAt(i):'0'; - if (!(Character.isDigit(c)||(c=='a'||c=='b'||c=='c'||c=='d'||c=='e'||c=='f'))) - return false; - } - return true; - } - - /** Returns the numeric value from the "Info" property string - * associated with 'key', or NaN if the key is not found or the - * value associated with the key is not numeric. Works with - * DICOM tags and Bio-Formats metadata. - * @see #getStringProperty - * @see #getInfoProperty - */ - public double getNumericProperty(String key) { - return Tools.parseDouble(getStringProperty(key)); - } - - private String getStringProperty(String key, String info) { - int index1 = -1; - index1 = findKey(info, key+": "); // standard 'key: value' pair? - if (index1<0) // Bio-Formats metadata? - index1 = findKey(info, key+" = "); - if (index1<0) // '=' with no spaces - index1 = findKey(info, key+"="); - if (index1<0) // otherwise not found - return null; - if (index1==info.length()) - return ""; //empty value at the end - int index2 = info.indexOf("\n", index1); - if (index2==-1) - index2=info.length(); - String value = info.substring(index1, index2); - return value; - } - - /** Find a key in a String (words merely ending with 'key' don't qualify). - * @return index of first character after the key, or -1 if not found - */ - private int findKey(String s, String key) { - int i = s.indexOf(key); - if (i<0) - return -1; //key not found - while (i>0 && Character.isLetterOrDigit(s.charAt(i-1))) - i = s.indexOf(key, i+key.length()); - if (i>=0) - return i + key.length(); - else - return -1; - } - - /** Adds a key-value pair to this image's string properties. - * The key-value pair is removed if 'value' is null. The - * properties persist if the image is saved in TIFF format. - * Add a "HideInfo" property (e.g. set("HideInfo","true")) to - * prevent the properties from being displayed by the - * Image/Show Info command. - */ - public void setProp(String key, String value) { - if (key==null) - return; - if (imageProperties==null) - imageProperties = new Properties(); - if (value==null || value.length()==0) - imageProperties.remove(key); - else { - imageProperties.setProperty(key, value); - if (key.equals("CompositeProjection")) - Channels.updateChannels(); - } - } - - /** Saves a persistent numeric propery. The property is - * removed if 'value' is NaN. - * @see #getNumericProp - */ - public void setProp(String key, double value) { - String svalue = ""+value; - if (svalue.endsWith(".0")) - svalue = svalue.substring(0,svalue.length()-2); - setProp(key, Double.isNaN(value)?null:svalue); - } - - /** Returns as a string the image property associated with the - * specified key or null if the property is not found. - * @see #setProp - * @see #getNumericProp - * @see #getStringProperty - */ - public String getProp(String key) { - if (imageProperties==null) - return getStringProperty(key); - else { - String value = imageProperties.getProperty(key); - if (value==null) - value = getStringProperty(key); - return value; - } - } - - /** Returns the numeric property associated with the specified key - * or NaN if the property is not found. - * @see #setProp(String,double) - * @see #getProp - */ - public double getNumericProp(String key) { - if (imageProperties==null) - return Double.NaN; - else - return Tools.parseDouble(getProp(key), Double.NaN); - } - - /** Used for saving string properties in TIFF header. */ - public String[] getPropertiesAsArray() { - if (imageProperties==null || imageProperties.size()==0) - return null; - String props[] = new String[imageProperties.size()*2]; - int index = 0; - for (Enumeration en=imageProperties.keys(); en.hasMoreElements();) { - String key = (String)en.nextElement(); - String value = imageProperties.getProperty(key); - props[index++] = key; - props[index++] = value; - } - return props; - } - - /** Returns information displayed by Image/Show Info command. */ - public String getPropsInfo() { - if (imageProperties==null || imageProperties.size()==0) - return "0"; - String info2 = ""; - for (Enumeration en=imageProperties.keys(); en.hasMoreElements();) { - String key = (String)en.nextElement(); - if (info2.length()>50) { - info2 += "..."; - break; - } else - info2 += " " + key; - } - if (info2.length()>1) - info2 = " (" + info2.substring(1) + ")"; - return imageProperties.size() + info2; - } - - /** Creates a set of image properties from an array of strings. - * @see #getPropertiesAsArray - * @see #getProp(String) - * @see #setProp(String,String) - */ - public void setProperties(String[] props) { - imageProperties = null; - if (props==null) - return; - //IJ.log("setProperties: "+props.length+" "+getTitle()); - for (int i=0; i>16; - int g = (c&0xff00)>>8; - int b = c&0xff; - pvalue[0] = r; - pvalue[1] = g; - pvalue[2] = b; - break; - case GRAY16: case GRAY32: - if (ip!=null) pvalue[0] = ip.getPixel(x, y); - break; - } - return pvalue; - } - - /** Returns an empty image stack that has the same - width, height and color table as this image. */ - public ImageStack createEmptyStack() { - ColorModel cm; - if (ip!=null) - cm = ip.getColorModel(); - else - cm = createLut().getColorModel(); - return new ImageStack(width, height, cm); - } - - /** Returns the image stack. The stack may have only - one slice. After adding or removing slices, call - setStack() to update the image and - the window that is displaying it. - @see #setStack - */ - public ImageStack getStack() { - ImageStack s; - if (stack==null) { - s = createEmptyStack(); - ImageProcessor ip2 = getProcessor(); - if (ip2==null) - return s; - String label = getProp("Slice_Label"); - if (label==null) { - String info = (String)getProperty("Info"); - label = info!=null?getTitle()+"\n"+info:null; // DICOM metadata - } - s.addSlice(label, ip2); - s.update(ip2); - this.stack = s; - ip = ip2; - oneSliceStack = true; - setCurrentSlice(1); - } else { - s = stack; - if (ip!=null) { - Calibration cal = getCalibration(); - if (cal.calibrated()) - ip.setCalibrationTable(cal.getCTable()); - else - ip.setCalibrationTable(null); - } - s.update(ip); - } - if (roi!=null) - s.setRoi(roi.getBounds()); - else - s.setRoi(null); - return s; - } - - /** Returns the base image stack. */ - public ImageStack getImageStack() { - if (stack==null) - return getStack(); - else { - stack.update(ip); - return stack; - } - } - - /** Returns the current stack index (one-based) or 1 if this is a single image. */ - public int getCurrentSlice() { - if (currentSlice<1) setCurrentSlice(1); - if (currentSlice>getStackSize()) - setCurrentSlice(getStackSize()); - return currentSlice; - } - - final void setCurrentSlice(int slice) { - currentSlice = slice; - int stackSize = getStackSize(); - if (nChannels==stackSize) updatePosition(currentSlice, 1, 1); - if (nSlices==stackSize) updatePosition(1, currentSlice, 1); - if (nFrames==stackSize) updatePosition(1, 1, currentSlice); - } - - public int getChannel() { - return position[0]; - } - - public int getSlice() { - return position[1]; - } - - public int getFrame() { - return position[2]; - } - - public void killStack() { - setStackNull(); - trimProcessor(); - } - - /** Sets the current hyperstack position and updates the display, - where 'channel', 'slice' and 'frame' are one-based indexes. */ - public void setPosition(int channel, int slice, int frame) { - //IJ.log("setPosition: "+channel+" "+slice+" "+frame+" "+noUpdateMode); - verifyDimensions(); - if (channel<0) channel=0; - if (slice<0) slice=0; - if (frame<0) frame=0; - if (channel==0) channel=getC(); - if (slice==0) slice=getZ(); - if (frame==0) frame=getT(); - if (channel>nChannels) channel=nChannels; - if (slice>nSlices) slice=nSlices; - if (frame>nFrames) frame=nFrames; - if (isDisplayedHyperStack()) { - if (noUpdateMode) { - setSlice((frame-1)*nChannels*nSlices + (slice-1)*nChannels + channel); - updatePosition(channel, slice, frame); - } else - ((StackWindow)win).setPosition(channel, slice, frame); - } else { - boolean channelChanged = channel!=getChannel(); - setSlice((frame-1)*nChannels*nSlices + (slice-1)*nChannels + channel); - updatePosition(channel, slice, frame); - if (channelChanged && isComposite() && !noUpdateMode) - updateImage(); - } - } - - /** Sets the current hyperstack position without updating the display, - where 'channel', 'slice' and 'frame' are one-based indexes. */ - public void setPositionWithoutUpdate(int channel, int slice, int frame) { - noUpdateMode = true; - setPosition(channel, slice, frame); - noUpdateMode = false; - } - - /** Sets the hyperstack channel position (one based). */ - public void setC(int channel) { - setPosition(channel, getZ(), getT()); - } - - /** Sets the hyperstack slice position (one based). */ - public void setZ(int slice) { - setPosition(getC(), slice, getT()); - } - - /** Sets the hyperstack frame position (one based). */ - public void setT(int frame) { - setPosition(getC(), getZ(), frame); - } - - /** Returns the current hyperstack channel position. */ - public int getC() { - return position[0]; - } - - /** Returns the current hyperstack slice position. */ - public int getZ() { - return position[1]; - } - - /** Returns the current hyperstack frame position. */ - public int getT() { - return position[2]; - } - - /** Returns that stack index (one-based) corresponding to the specified position. */ - public int getStackIndex(int channel, int slice, int frame) { - if (channel<1) channel = 1; - if (channel>nChannels) channel = nChannels; - if (slice<1) slice = 1; - if (slice>nSlices) slice = nSlices; - if (frame<1) frame = 1; - if (frame>nFrames) frame = nFrames; - return (frame-1)*nChannels*nSlices + (slice-1)*nChannels + channel; - } - - /* Hack needed to make the HyperStackReducer work. */ - public void resetStack() { - if (currentSlice==1 && stack!=null && stack.size()>0) { - ColorModel cm = ip.getColorModel(); - double min = ip.getMin(); - double max = ip.getMax(); - ImageProcessor ip2 = stack.getProcessor(1); - if (ip2!=null) { - ip = ip2; - ip.setColorModel(cm); - ip.setMinAndMax(min, max); - } - } - } - - /** Set the current hyperstack position based on the stack index 'n' (one-based). */ - public void setPosition(int n) { - int[] pos = convertIndexToPosition(n); - setPosition(pos[0], pos[1], pos[2]); - } - - /** Converts the stack index 'n' (one-based) into a hyperstack position (channel, slice, frame). */ - public int[] convertIndexToPosition(int n) { - if (n<1 || n>getStackSize()) - throw new IllegalArgumentException("n out of range: "+n); - int[] position = new int[3]; - int[] dim = getDimensions(); - position[0] = ((n-1)%dim[2])+1; - position[1] = (((n-1)/dim[2])%dim[3])+1; - position[2] = (((n-1)/(dim[2]*dim[3]))%dim[4])+1; - return position; - } - - /** Displays the specified stack image, where {@literal 1<=n<=stackSize}. - * Does nothing if this image is not a stack. - * @see #setPosition - * @see #setC - * @see #setZ - * @see #setT - */ - public synchronized void setSlice(int n) { - if (stack==null || (n==currentSlice&&ip!=null)) { - if (!noUpdateMode) - updateAndRepaintWindow(); - return; - } - if (n>=1 && n<=stack.size()) { - Roi roi = getRoi(); - if (roi!=null) - roi.endPaste(); - if (isProcessor()) { - if (currentSlice==0) currentSlice=1; - stack.setPixels(ip.getPixels(),currentSlice); - } - setCurrentSlice(n); - Object pixels = null; - Overlay overlay2 = null; - if (stack.isVirtual() && !((stack instanceof FileInfoVirtualStack)||(stack instanceof AVI_Reader))) { - ImageProcessor ip2 = stack.getProcessor(currentSlice); - overlay2 = ip2!=null?ip2.getOverlay():null; - if (overlay2!=null) - setOverlay(overlay2); - if (stack instanceof VirtualStack) { - Properties props = ((VirtualStack)stack).getProperties(); - if (props!=null) - setProperty("FHT", props.get("FHT")); - } - if (ip2!=null) pixels=ip2.getPixels(); - } else - pixels = stack.getPixels(currentSlice); - if (ip!=null && pixels!=null) { - try { - ip.setPixels(pixels); - ip.setSnapshotPixels(null); - } catch(Exception e) {} - } else { - ImageProcessor ip2 = stack.getProcessor(n); - if (ip2!=null) ip = ip2; - } - if (compositeImage && getCompositeMode()==IJ.COMPOSITE && ip!=null) { - int channel = getC(); - if (channel>0 && channel<=getNChannels()) - ip.setLut(((CompositeImage)this).getChannelLut(channel)); - } - if (win!=null && win instanceof StackWindow) - ((StackWindow)win).updateSliceSelector(); - if (Prefs.autoContrast && nChannels==1 && imageType!=COLOR_RGB) { - (new ContrastEnhancer()).stretchHistogram(ip,0.35,ip.getStats()); - ContrastAdjuster.update(); - //IJ.showStatus(n+": min="+ip.getMin()+", max="+ip.getMax()); - } - if (imageType==COLOR_RGB) - ContrastAdjuster.update(); - if (!noUpdateMode) - updateAndRepaintWindow(); - else - img = null; - if (ip!=null) - ip.setSliceNumber(n); - } - } - - /** Displays the specified stack image ({@literal 1<=n<=stackSize}) - without updating the display. */ - public void setSliceWithoutUpdate(int n) { - noUpdateMode = true; - setSlice(n); - noUpdateMode = false; - } - - /** Returns the current selection, or null if there is no selection. */ - public Roi getRoi() { - return roi; - } - - /** Assigns the specified ROI to this image and displays it. Any existing - ROI is deleted if roi is null or its width or height is zero. */ - public void setRoi(Roi newRoi) { - setRoi(newRoi, true); - } - - /** Assigns 'newRoi' to this image and displays it if 'updateDisplay' is true. */ - public void setRoi(Roi newRoi, boolean updateDisplay) { - if (newRoi==null) { - deleteRoi(); - return; - } - if (IJ.recording()) { - Recorder recorder = Recorder.getInstance(); - if (recorder!=null) recorder.imageUpdated(this); - } - Rectangle bounds = newRoi.getBounds(); - if (newRoi.isVisible()) { - if ((newRoi instanceof Arrow) && newRoi.getState()==Roi.CONSTRUCTING && bounds.width==0 && bounds.height==0) { - deleteRoi(); - roi = newRoi; - return; - } - if (newRoi==null) { - deleteRoi(); - return; - } - ImagePlus imp = newRoi.getImage(); - if (imp!=null && imp.getID()!=getID()) - newRoi = (Roi)newRoi.clone(); - newRoi.setImage(null); - } - if (bounds.width==0 && bounds.height==0 && !(newRoi.getType()==Roi.POINT||newRoi.getType()==Roi.LINE)) { - deleteRoi(); - return; - } - roi = newRoi; - if (ip!=null) { - ip.setMask(null); - if (roi.isArea()) - ip.setRoi(bounds); - else - ip.resetRoi(); - } - roi.setImage(this); - if ((roi instanceof PointRoi) && ((PointRoi)roi).addToOverlay()) { - IJ.run(this, "Add Selection...", ""); - roi = null; - return; - } - if (updateDisplay) - draw(); - if (roi!=null) - roi.notifyListeners(RoiListener.CREATED); - } - - /** Creates a rectangular selection. */ - public void setRoi(int x, int y, int width, int height) { - setRoi(new Rectangle(x, y, width, height)); - } - - /** Creates a rectangular selection. */ - public void setRoi(Rectangle r) { - setRoi(new Roi(r.x, r.y, r.width, r.height)); - } - - /** Starts the process of creating a new selection, where sx and sy are the - starting screen coordinates. The selection type is determined by which tool in - the tool bar is active. The user interactively sets the selection size and shape. */ - public void createNewRoi(int sx, int sy) { - Roi previousRoi = roi; - deleteRoi(); //also saves the roi as Roi.previousRoi if non-null - Roi prevRoi = Roi.getPreviousRoi(); - if (prevRoi != null) - prevRoi.setImage(previousRoi==null ? null : this); //with 'this' it will be recalled in case of ESC - switch (Toolbar.getToolId()) { - case Toolbar.RECTANGLE: - if (Toolbar.getRectToolType()==Toolbar.ROTATED_RECT_ROI) - roi = new RotatedRectRoi(sx, sy, this); - else - roi = new Roi(sx, sy, this, Toolbar.getRoundRectArcSize()); - break; - case Toolbar.OVAL: - if (Toolbar.getOvalToolType()==Toolbar.ELLIPSE_ROI) - roi = new EllipseRoi(sx, sy, this); - else - roi = new OvalRoi(sx, sy, this); - break; - case Toolbar.POLYGON: - case Toolbar.POLYLINE: - case Toolbar.ANGLE: - roi = new PolygonRoi(sx, sy, this); - break; - case Toolbar.FREEROI: - case Toolbar.FREELINE: - roi = new FreehandRoi(sx, sy, this); - break; - case Toolbar.LINE: - if ("arrow".equals(Toolbar.getToolName())) - roi = new Arrow(sx, sy, this); - else - roi = new Line(sx, sy, this); - break; - case Toolbar.TEXT: - roi = new TextRoi(sx, sy, this); - ((TextRoi)roi).setPreviousTextRoi(previousRoi); - break; - case Toolbar.POINT: - roi = new PointRoi(sx, sy, this); - if (Prefs.pointAddToOverlay) { - int measurements = Analyzer.getMeasurements(); - if (!(Prefs.pointAutoMeasure && (measurements&Measurements.ADD_TO_OVERLAY)!=0)) - IJ.run(this, "Add Selection...", ""); - Overlay overlay2 = getOverlay(); - if (overlay2!=null) - overlay2.drawLabels(!Prefs.noPointLabels); - Prefs.pointAddToManager = false; - } - if (Prefs.pointAutoMeasure || (Prefs.pointAutoNextSlice&&!Prefs.pointAddToManager)) - IJ.run(this, "Measure", ""); - if (Prefs.pointAddToManager) { - IJ.run(this, "Add to Manager ", ""); - ImageCanvas ic = getCanvas(); - if (ic!=null) { - RoiManager rm = RoiManager.getInstance(); - if (rm!=null) { - if (Prefs.noPointLabels) - rm.runCommand("show all without labels"); - else - rm.runCommand("show all with labels"); - } - } - } - if (Prefs.pointAutoNextSlice && getStackSize()>1) { - boolean order = Prefs.reverseNextPreviousOrder; - Prefs.reverseNextPreviousOrder = true; - IJ.run(this, "Next Slice [>]", ""); - Prefs.reverseNextPreviousOrder = order; - deleteRoi(); - } - break; - } - if (roi!=null) - roi.notifyListeners(RoiListener.CREATED); - } - - /** Deletes the current region of interest. Makes a copy of the ROI - so it can be recovered by Edit/Selection/Restore Selection. */ - public void deleteRoi() { - if (roi==null) - return; - saveRoi(); - if (!(IJ.altKeyDown()||IJ.shiftKeyDown())) { - RoiManager rm = RoiManager.getRawInstance(); - if (rm!=null) - rm.deselect(roi); - } - if (roi!=null) - roi.notifyListeners(RoiListener.DELETED); - roi = null; - if (ip!=null) - ip.resetRoi(); - draw(); - } - - /** Removes the spatial scaling of this image. */ - public void removeScale() { - Calibration cal = getCalibration(); - cal.pixelWidth = 1.0; - cal.pixelHeight = 1.0; - cal.pixelDepth = 1.0; - cal.setUnit("pixel"); - ImageWindow win = getWindow(); - if (win!=null) - win.repaint(); - } - - public boolean okToDeleteRoi() { - if (roi!=null && (roi instanceof PointRoi) && getWindow()!=null && ((PointRoi)roi).promptBeforeDeleting()) { - int npoints = ((PolygonRoi)roi).getNCoordinates(); - int counters = ((PointRoi)roi).getNCounters(); - String msg = "Delete this multi-point selection ("+npoints+" points, "+counters+" counter"+(counters>1?"s":"")+")?"; - GenericDialog gd=new GenericDialog("Delete Points?"); - gd.addMessage(msg+"\nRestore using Edit>Selection>Restore Selection."); - gd.addHelp(PointToolOptions.help); - gd.setOKLabel("Keep"); - gd.setCancelLabel("Delete"); - gd.showDialog(); - if (gd.wasOKed()) - return false; - } - return true; - } - - /** Deletes the current region of interest. */ - public void killRoi() { - deleteRoi(); - } - - /** Deletes the current region of interest. */ - public void resetRoi() { - deleteRoi(); - } - - public void saveRoi() { - Roi roi2 = roi; - if (roi2!=null) { - roi2.endPaste(); - Rectangle r = roi2.getBounds(); - if ((r.width>0 || r.height>0)) { - Roi.setPreviousRoi(roi2); - if (IJ.debugMode) IJ.log("saveRoi: "+roi2); - } - if ((roi2 instanceof PointRoi) && ((PointRoi)roi2).promptBeforeDeleting()) { - PointRoi.savedPoints = (PointRoi)roi2.clone(); - if (IJ.debugMode) IJ.log("saveRoi: saving multi-point selection"); - } - } - } - - public void restoreRoi() { - if (Toolbar.getToolId()==Toolbar.POINT && PointRoi.savedPoints!=null) { - roi = (Roi)PointRoi.savedPoints.clone(); - draw(); - roi.notifyListeners(RoiListener.MODIFIED); - return; - } - Roi previousRoi = Roi.getPreviousRoi(); - if (previousRoi!=null) { - Roi pRoi = previousRoi; - Rectangle r = pRoi.getBounds(); - if (r.width<=width||r.height<=height||(r.x=width || r.y>=height || (r.x+r.width)<0 || (r.y+r.height)<0) // does it need to be moved? - roi.setLocation((width-r.width)/2, (height-r.height)/2); - else if (r.width==width && r.height==height) // is it the same size as the image - roi.setLocation(0, 0); - draw(); - roi.notifyListeners(RoiListener.MODIFIED); - } - } - } - - boolean isSmaller(Roi r) { - ImageProcessor mask = r.getMask(); - if (mask==null) return false; - mask.setThreshold(255, 255, ImageProcessor.NO_LUT_UPDATE); - ImageStatistics stats = ImageStatistics.getStatistics(mask, MEAN+LIMIT, null); - return stats.area<=width*height; - } - - /** Implements the File/Revert command. */ - public void revert() { - if (getStackSize()>1 && getStack().isVirtual()) { - int thisSlice = currentSlice; - currentSlice = 0; - setSlice(thisSlice); - return; - } - FileInfo fi = getOriginalFileInfo(); - boolean isFileInfo = fi!=null && fi.fileFormat!=FileInfo.UNKNOWN; - if (!isFileInfo && url==null) - return; - if (fi.directory==null && url==null) - return; - if (ij!=null && changes && isFileInfo && !Interpreter.isBatchMode() && !IJ.isMacro() && !IJ.altKeyDown()) { - if (!IJ.showMessageWithCancel("Revert?", "Revert to saved version of\n\""+getTitle()+"\"?")) - return; - } - Roi saveRoi = null; - if (roi!=null) { - roi.endPaste(); - saveRoi = (Roi)roi.clone(); - } - trimProcessor(); - new FileOpener(fi).revertToSaved(this); - if (Prefs.useInvertingLut && getBitDepth()==8 && ip!=null && !ip.isInvertedLut()&& !ip.isColorLut()) - invertLookupTable(); - if (getProperty("FHT")!=null) { - properties.remove("FHT"); - if (getTitle().startsWith("FFT of ")) - setTitle(getTitle().substring(7)); - } - ContrastAdjuster.update(); - if (saveRoi!=null) setRoi(saveRoi); - repaintWindow(); - IJ.showStatus(""); - changes = false; - notifyListeners(UPDATED); - } - - void revertStack(FileInfo fi) { - String path = null; - String url2 = null; - if (url!=null && !url.equals("")) { - path = url; - url2 = url; - } else if (fi!=null && !((fi.directory==null||fi.directory.equals("")))) { - path = fi.getFilePath(); - } else if (fi!=null && fi.url!=null && !fi.url.equals("")) { - path = fi.url; - url2 = fi.url; - } else - return; - IJ.showStatus("Loading: " + path); - ImagePlus imp = IJ.openImage(path); - if (imp!=null) { - int n = imp.getStackSize(); - int c = imp.getNChannels(); - int z = imp.getNSlices(); - int t = imp.getNFrames(); - if (z==n || t==n || (c==getNChannels()&&z==getNSlices()&&t==getNFrames())) { - setCalibration(imp.getCalibration()); - setStack(imp.getStack(), c, z, t); - } else { - ImageWindow win = getWindow(); - Point loc = null; - if (win!=null) loc = win.getLocation(); - changes = false; - close(); - FileInfo fi2 = imp.getOriginalFileInfo(); - if (fi2!=null && (fi2.url==null || fi2.url.length()==0)) { - fi2.url = url2; - imp.setFileInfo(fi2); - } - ImageWindow.setNextLocation(loc); - imp.show(); - } - } - } - - /** Returns a FileInfo object containing information, including the - pixel array, needed to save this image. Use getOriginalFileInfo() - to get a copy of the FileInfo object used to open the image. - @see ij.io.FileInfo - @see #getOriginalFileInfo - @see #setFileInfo - */ - public FileInfo getFileInfo() { - FileInfo fi = new FileInfo(); - fi.width = width; - fi.height = height; - fi.nImages = getStackSize(); - if (compositeImage) - fi.nImages = getImageStackSize(); - fi.whiteIsZero = isInvertedLut(); - fi.intelByteOrder = false; - if (fi.nImages==1 && ip!=null) - fi.pixels = ip.getPixels(); - else if (stack!=null) - fi.pixels = stack.getImageArray(); - Calibration cal = getCalibration(); - if (cal.scaled()) { - fi.pixelWidth = cal.pixelWidth; - fi.pixelHeight = cal.pixelHeight; - fi.unit = cal.getUnit(); - } - if (fi.nImages>1) - fi.pixelDepth = cal.pixelDepth; - fi.frameInterval = cal.frameInterval; - if (cal.calibrated()) { - fi.calibrationFunction = cal.getFunction(); - fi.coefficients = cal.getCoefficients(); - fi.valueUnit = cal.getValueUnit(); - } else if (!Calibration.DEFAULT_VALUE_UNIT.equals(cal.getValueUnit())) - fi.valueUnit = cal.getValueUnit(); - - switch (imageType) { - case GRAY8: case COLOR_256: - LookUpTable lut = createLut(); - boolean customLut = !lut.isGrayscale() || (ip!=null&&!ip.isDefaultLut()); - if (imageType==COLOR_256 || customLut) - fi.fileType = FileInfo.COLOR8; - else - fi.fileType = FileInfo.GRAY8; - addLut(lut, fi); - break; - case GRAY16: - if (compositeImage && fi.nImages==3) { - if ("Red".equals(getStack().getSliceLabel(1))) - fi.fileType = fi.RGB48; - else - fi.fileType = fi.GRAY16_UNSIGNED; - } else - fi.fileType = fi.GRAY16_UNSIGNED; - if (!compositeImage) { - lut = createLut(); - if (!lut.isGrayscale() || (ip!=null&&!ip.isDefaultLut())) - addLut(lut, fi); - } - break; - case GRAY32: - fi.fileType = fi.GRAY32_FLOAT; - if (!compositeImage) { - lut = createLut(); - if (!lut.isGrayscale() || (ip!=null&&!ip.isDefaultLut())) - addLut(lut, fi); - } - break; - case COLOR_RGB: - fi.fileType = fi.RGB; - break; - default: - } - return fi; - } - - private void addLut(LookUpTable lut, FileInfo fi) { - fi.lutSize = lut.getMapSize(); - fi.reds = lut.getReds(); - fi.greens = lut.getGreens(); - fi.blues = lut.getBlues(); - } - - /** Returns the FileInfo object that was used to open this image. - Returns null for images created using the File/New command. - @see ij.io.FileInfo - @see #getFileInfo - */ - public FileInfo getOriginalFileInfo() { - if (fileInfo==null & url!=null) { - fileInfo = new FileInfo(); - fileInfo.width = width; - fileInfo.height = height; - fileInfo.url = url; - fileInfo.directory = null; - } - return fileInfo; - } - - /** Used by ImagePlus to monitor loading of images. */ - public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) { - imageUpdateY = y; - imageUpdateW = w; - if ((flags & ERROR) != 0) { - errorLoadingImage = true; - return false; - } - imageLoaded = (flags & (ALLBITS|FRAMEBITS|ABORT)) != 0; - return !imageLoaded; - } - - /** Sets the ImageProcessor, Roi, AWT Image and stack image - arrays to null. Does nothing if the image is locked. */ - public synchronized void flush() { - notifyListeners(CLOSED); - if (locked || ignoreFlush) return; - ip = null; - if (roi!=null) roi.setImage(null); - roi = null; - if (stack!=null && stack.viewers(-1)<=0) { - Object[] arrays = stack.getImageArray(); - if (arrays!=null) { - for (int i=0; istackSize) s2 = stackSize; - if (s1>s2) {s1=1; s2=stackSize;} - return new Duplicator().run(this, (int)s1, (int)s2); - } - } - - /** Returns an array of cropped images based on the provided - * list of rois. 'options' applies with stacks and can be "stack", - * "slice" or a range (e.g., "20-30"). - * @see #crop(ij.gui.Roi[]) - */ - public ImagePlus[] crop(Roi[] rois, String options) { - int nRois = rois.length; - ImagePlus[] cropImps = new ImagePlus[nRois]; - for (int i=0; i1) { - int position = cropRoi.getPosition(); - this.setSlice(position); // no effect if roi position is undefined (=0), ok - } - this.setRoi(cropRoi); - ImagePlus cropped = this.crop(options); - if (cropRoi.getType()!=Roi.RECTANGLE) { - Roi cropRoi2 = (Roi)cropRoi.clone(); - cropRoi2.setLocation(0,0); - cropped.setRoi(cropRoi2); - } - String name2 = IJ.pad(i+1,3)+"_"+this.getTitle(); - cropped.setTitle(name!=null?name:name2); - cropped.setOverlay(null); - cropImps[i] = cropped; - } - return cropImps; - } - - /** Multi-roi cropping with default "slice" option. */ - public ImagePlus[] crop(Roi[] rois) { - return this.crop(rois, "slice"); - } - - /** Saves the contents of the ROIs in this overlay as separate images, - * where 'directory' is the directory path and 'format' is "tif", "png" or "jpg". - * Set 'format' to "show" and the images will be displayed in a stack - * and not saved. - */ - public void cropAndSave(Roi[] rois, String directory, String format) { - ImagePlus[] images = crop(rois); - if (format==null) format = ""; - if (format.contains("show")) { - ImageStack stack = ImageStack.create(images); - new ImagePlus("CROPPED_"+getTitle(),stack).show(); - return; - } - String fileFormat = "tif"; - if (format.contains("png")) fileFormat = "png"; - if (format.contains("jpg")) fileFormat = "jpg"; - for (int i=0; icut is true. */ - public void copy(boolean cut) { - Roi roi = getRoi(); - if (roi!=null && !roi.isArea()) - roi = null; - if (cut && roi==null && !IJ.isMacro()) { - IJ.error("Edit>Cut", "This command requires an area selection"); - return; - } - boolean batchMode = Interpreter.isBatchMode(); - String msg = (cut)?"Cut":"Copy"; - if (!batchMode) IJ.showStatus(msg+ "ing..."); - ImageProcessor ip = getProcessor(); - ImageProcessor ip2; - ip2 = ip.crop(); - clipboard = new ImagePlus("Clipboard", ip2); - if (roi!=null) - clipboard.setRoi((Roi)roi.clone()); - if (cut) { - ip.snapshot(); - ip.setColor(Toolbar.getBackgroundColor()); - ip.fill(); - if (roi!=null && roi.getType()!=Roi.RECTANGLE) { - getMask(); - ip.reset(ip.getMask()); - } setColor(Toolbar.getForegroundColor()); - Undo.setup(Undo.FILTER, this); - updateAndDraw(); - } - int bytesPerPixel = 1; - switch (clipboard.getType()) { - case ImagePlus.GRAY16: bytesPerPixel = 2; break; - case ImagePlus.GRAY32: case ImagePlus.COLOR_RGB: bytesPerPixel = 4; - } - if (!batchMode) { - msg = (cut)?"Cut":"Copy"; - IJ.showStatus(msg + ": " + (clipboard.getWidth()*clipboard.getHeight()*bytesPerPixel)/1024 + "k"); - } - } - - /** Inserts the contents of the internal clipboard into this image. If there - is a selection the same size as the image on the clipboard, the image is inserted - into that selection, otherwise the selection is inserted into the center of the image.*/ - public void paste() { - if (clipboard==null) - return; - int cType = clipboard.getType(); - int iType = getType(); - int w = clipboard.getWidth(); - int h = clipboard.getHeight(); - Roi cRoi = clipboard.getRoi(); - Rectangle r = null; - Rectangle cr = null; - Roi roi = getRoi(); - if (roi!=null) - r = roi.getBounds(); - if (cRoi!=null) - cr = cRoi.getBounds(); - if (cr==null) - cr = new Rectangle(0, 0, w, h); - if (r==null || (cr.width!=r.width || cr.height!=r.height)) { - // Create a new roi centered on visible part of image, or centered on image if clipboard is >= image - ImageCanvas ic = win!=null?ic = win.getCanvas():null; - Rectangle srcRect = ic!=null?ic.getSrcRect():new Rectangle(0,0,width,height); - int xCenter = w>=width ? width/2 : srcRect.x + srcRect.width/2; - int yCenter = h>=height ? height/2 : srcRect.y + srcRect.height/2; - if (cRoi!=null && cRoi.getType()!=Roi.RECTANGLE) { - cRoi.setImage(this); - cRoi.setLocation(xCenter-w/2, yCenter-h/2); - setRoi(cRoi); - } else - setRoi(xCenter-w/2, yCenter-h/2, w, h); - roi = getRoi(); - } - if (IJ.isMacro()) { - //non-interactive paste - int pasteMode = Roi.getCurrentPasteMode(); - boolean nonRect = roi.getType()!=Roi.RECTANGLE; - ImageProcessor ip = getProcessor(); - if (nonRect) ip.snapshot(); - r = roi.getBounds(); - int xoffset = cr.x<0?-cr.x:0; - int yoffset = cr.y<0?-cr.y:0; - ip.copyBits(clipboard.getProcessor(), r.x+xoffset, r.y+yoffset, pasteMode); - if (nonRect) { - ImageProcessor mask = roi.getMask(); - ip.setMask(mask); - ip.setRoi(roi.getBounds()); - ip.reset(ip.getMask()); - } - updateAndDraw(); - } else if (roi!=null) { - roi.startPaste(clipboard); - Undo.setup(Undo.PASTE, this); - } - changes = true; - } - - /** Inserts the contents of the internal clipboard at the - specified location, without updating the display. */ - public void paste(int x, int y) { - paste(x, y, null); - } - - /** Copies the contents of the internal clipboard to the - * specified location using the specified transfer mode - * ("Copy", "Blend", "Average", "Difference", "Transparent", - * "Transparent2", "AND", "OR", "XOR", "Add", "Subtract", - * "Multiply", or "Divide"). The display is not updating. - */ - public void paste(int x, int y, String mode) { - if (clipboard==null) - return; - Roi roi = clipboard.getRoi(); - boolean nonRect = roi!=null && roi.getType()!=Roi.RECTANGLE; - if (nonRect) - ip.snapshot(); - if (mode==null) - ip.insert(clipboard.getProcessor(), x, y); - else { - int pasteMode = IJ.stringToPasteMode(mode); - ip.copyBits(clipboard.getProcessor(), x, y, pasteMode); - } - if (nonRect) { - ImageProcessor mask = roi.getMask(); - ip.setRoi(x, y, mask.getWidth(), mask.getHeight()); - ip.setMask(mask); - ip.reset(ip.getMask()); - } - } - - /** Returns the internal clipboard or null if the internal clipboard is empty. */ - public static ImagePlus getClipboard() { - return clipboard; - } - - /** Clears the internal clipboard. */ - public static void resetClipboard() { - clipboard = null; - } - - /** Copies the contents of the current selection, or the entire - image if there is no selection, to the system clipboard. */ - public void copyToSystem() { - Clipboard.copyToSystem(this); - } - - protected void notifyListeners(final int id) { - if (temporary) - return; - final ImagePlus imp = this; - EventQueue.invokeLater(new Runnable() { - public void run() { - for (int i=0; i=1 && imageType!=COLOR_RGB && (this instanceof CompositeImage); - } - - /** Returns the display mode (IJ.COMPOSITE, IJ.COLOR - or IJ.GRAYSCALE) if this is a CompositeImage, otherwise returns -1. */ - public int getCompositeMode() { - if (isComposite()) - return ((CompositeImage)this).getMode(); - else - return -1; - } - - /** Sets the display range of the current channel. With non-composite - * images it is identical to ip.setMinAndMax(min, max). - * Call updateAndDraw() to update the display. - */ - public void setDisplayRange(double min, double max) { - if (ip!=null) - ip.setMinAndMax(min, max); - } - - /** Returns the display range minimum of the current channel. - * @see ij.process.ImageProcessor#getMin - * @see #getLuts - */ - public double getDisplayRangeMin() { - return ip.getMin(); - } - - /** Returns the display range maximum of the current channel. - * @see ij.process.ImageProcessor#getMax - * @see #getLuts - */ - public double getDisplayRangeMax() { - return ip.getMax(); - } - - /** Sets the display range of specified channels in an RGB image, where 4=red, - 2=green, 1=blue, 6=red+green, etc. With non-RGB images, this method is - identical to setDisplayRange(min, max). This method is used by the - Image/Adjust/Color Balance tool . - */ - public void setDisplayRange(double min, double max, int channels) { - if (ip instanceof ColorProcessor) - ((ColorProcessor)ip).setMinAndMax(min, max, channels); - else - ip.setMinAndMax(min, max); - } - - public void resetDisplayRange() { - if (defaultMin!=0.0 || defaultMax!=0.0) - setDisplayRange(defaultMin, defaultMax); - else if (imageType==GRAY16 && default16bitDisplayRange>=8 && default16bitDisplayRange<=16 && !(getCalibration().isSigned16Bit())) - ip.setMinAndMax(0, Math.pow(2,default16bitDisplayRange)-1); - else - ip.resetMinAndMax(); - } - - public void setDefaultDisplayRange(double min, double max) { - this.defaultMin = min; - this.defaultMax = max; - } - - /** Uses the specified method to set the threshold levels - * of this image. Use AutoThresholder.getMethods() - * to get a list of the available methods. Add " dark" - * to the method name if the image has a dark background. - * Add " 16-bit" to use the full 16-bit histogram - * when calculating the threshold of 16-bit images. - * Add " stack" to use the histogram of the entire - * stack when calculating the threshold. - */ - public void setAutoThreshold(String method) { - IJ.setAutoThreshold(this, method); - } - - /** Returns 'true' if this image is thresholded. - * @see ij.process.ImageProcessor#isThreshold - */ - public boolean isThreshold() { - return ip!=null && ip.getMinThreshold()!=ImageProcessor.NO_THRESHOLD; - } - - /** Set the default 16-bit display range, where 'bitDepth' must be 0 (auto-scaling), - 8 (0-255), 10 (0-1023), 12 (0-4095, 14 (0-16383), 15 (0-32767) or 16 (0-65535). */ - public static void setDefault16bitRange(int bitDepth) { - if (!(bitDepth==8 || bitDepth==10 || bitDepth==12 || bitDepth==14 || bitDepth==15 || bitDepth==16)) - bitDepth = 0; - default16bitDisplayRange = bitDepth; - } - - /** Returns the default 16-bit display range, 0 (auto-scaling), 8, 10, 12, 14, 15 or 16. */ - public static int getDefault16bitRange() { - return default16bitDisplayRange; - } - - public void updatePosition(int c, int z, int t) { - position[0] = c; - position[1] = z; - position[2] = t; - } - - /** Returns a "flattened" version of this image, or stack slice, in RGB format. */ - public ImagePlus flatten() { - if (IJ.debugMode) IJ.log("flatten"); - ImagePlus impCopy = this; - if (getStackSize()>1) - impCopy = crop("whole-slice"); - ImagePlus imp2 = impCopy.createImagePlus(); - imp2.setOverlay(impCopy.getOverlay()); - imp2.setTitle(flattenTitle); - ImageCanvas ic2 = new ImageCanvas(imp2); - imp2.flatteningCanvas = ic2; - imp2.setRoi(getRoi()); - Overlay overlay2 = getOverlay(); - if (overlay2!=null && imp2.getRoi()!=null && !(imp2.getRoi() instanceof PointRoi)) { - imp2.deleteRoi(); - if (getWindow()!=null) IJ.wait(100); - } - setPointScale(imp2.getRoi(), overlay2); - ImageCanvas ic = getCanvas(); - if (ic!=null) - ic2.setShowAllList(ic.getShowAllList()); - BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = (Graphics2D)bi.getGraphics(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - antialiasRendering?RenderingHints.VALUE_ANTIALIAS_ON:RenderingHints.VALUE_ANTIALIAS_OFF); - g.drawImage(getImage(), 0, 0, null); - ic2.paint(g); - imp2.flatteningCanvas = null; - ImagePlus imp3 = new ImagePlus("Flat_"+getTitle(), new ColorProcessor(bi)); - imp3.copyScale(this); - imp3.setProperty("Info", getProperty("Info")); - imp3.setProperties(getPropertiesAsArray()); - return imp3; - } - - /** Flattens all slices of this stack or HyperStack. - * @throws UnsupportedOperationException if this image - * does not have an overlay and the RoiManager overlay is null. - * Non-RGB stacks are converted to RGB. - * Copied from OverlayCommands and modified by Marcel Boeglin - * on 2014.01.08 to work with HyperStacks. - */ - public void flattenStack() { - if (IJ.debugMode) IJ.log("flattenStack"); - boolean composite = isComposite(); - if (getBitDepth()!=24) - new ImageConverter(this).convertToRGB(); - Overlay overlay1 = getOverlay(); - Overlay roiManagerOverlay = null; - boolean roiManagerShowAllMode = !Prefs.showAllSliceOnly; - ImageCanvas ic = getCanvas(); - if (ic!=null) - roiManagerOverlay = ic.getShowAllList(); - setOverlay(null); - if (roiManagerOverlay!=null) { - RoiManager rm = RoiManager.getInstance(); - if (rm!=null) - rm.runCommand("show none"); - } - Overlay overlay2 = overlay1!=null?overlay1:roiManagerOverlay; - if (composite && overlay2==null) - return; - if (overlay2==null || overlay2.size()==0) - throw new UnsupportedOperationException("A non-empty overlay is required"); - ImageStack stack2 = getStack(); - boolean showAll = overlay1!=null?false:roiManagerShowAllMode; - if (isHyperStack()) { - int Z = getNSlices(); - for (int z=1; z<=Z; z++) { - for (int t=1; t<=getNFrames(); t++) { - int image = z + (t-1)*Z; - flattenImage(stack2, image, overlay2.duplicate(), showAll, z, t); - } - } - } else { - for (int s=1; s<=stack2.getSize(); s++) { - flattenImage(stack2, s, overlay2.duplicate(), showAll); - } - } - setStack(stack2); - } - - /** Flattens Overlay 'overlay' on slice 'slice' of ImageStack 'stack'. - * Copied from OverlayCommands by Marcel Boeglin 2014.01.08. - */ - private void flattenImage(ImageStack stack, int slice, Overlay overlay, boolean showAll) { - ImageProcessor ips = stack.getProcessor(slice); - ImagePlus imp1 = new ImagePlus("temp", ips); - int w = imp1.getWidth(); - int h = imp1.getHeight(); - for (int i=0; i1) { - if (!IJ.isMacro()) rm.toFront(); - rm.runCommand("show all with labels"); - } - } - } - return hideOverlay; - } - - /** Enable/disable use of antialiasing by the flatten() method. */ - public void setAntialiasRendering(boolean antialiasRendering) { - this.antialiasRendering = antialiasRendering; - } - - /** Returns a shallow copy of this ImagePlus. */ - public synchronized Object clone() { - try { - ImagePlus copy = (ImagePlus)super.clone(); - copy.win = null; - return copy; - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** Plots a 256 bin histogram of this image and returns the PlotWindow. */ - public PlotWindow plotHistogram() { - return plotHistogram(256); - } - - /** Plots a histogram of this image using the specified - number of bins and returns the PlotWindow. */ - public PlotWindow plotHistogram(int bins) { - ImageStatistics stats = getStatistics(AREA+MEAN+MODE+MIN_MAX, bins); - Plot plot = new Plot("Hist_"+getTitle(), "Value", "Frequency"); - plot.setColor("black", "#999999"); - plot.setFont(new Font("SansSerif",Font.PLAIN,14)); - double[] y = stats.histogram(); - int n = y.length; - double[] x = new double[n]; - int bits = getBitDepth(); - boolean eightBit = bits==8 || bits==24; - double min = !eightBit?stats.min:0; - for (int i=0; i=size) { - Object[] tmp1 = new Object[size*2]; - System.arraycopy(stack, 0, tmp1, 0, size); - stack = tmp1; - String[] tmp2 = new String[size*2]; - System.arraycopy(label, 0, tmp2, 0, size); - label = tmp2; - } - stack[nSlices-1] = pixels; - this.label[nSlices-1] = sliceLabel; - if (this.bitDepth==0) - setBitDepth(pixels); - } - - private void setBitDepth(Object pixels) { - if (pixels==null) - return; - if (pixels instanceof byte[]) - this.bitDepth = 8; - else if (pixels instanceof short[]) - this.bitDepth = 16; - else if (pixels instanceof float[]) - this.bitDepth = 32; - else if (pixels instanceof int[]) - this.bitDepth = 24; - } - - /** - * @deprecated - * Short images are always unsigned. - */ - public void addUnsignedShortSlice(String sliceLabel, Object pixels) { - addSlice(sliceLabel, pixels); - } - - /** Adds the image in 'ip' to the end of the stack. */ - public void addSlice(ImageProcessor ip) { - addSlice(null, ip); - } - - /** Adds the image in 'ip' to the end of the stack, setting - the string 'sliceLabel' as the slice metadata. */ - public void addSlice(String sliceLabel, ImageProcessor ip) { - ip = convertType(ip); - if (ip.getWidth()!=this.width || ip.getHeight()!=this.height) { - if (this.width==0 && this.height==0) - init(ip.getWidth(), ip.getHeight()); - else { - ImageProcessor ip2 = ip.createProcessor(this.width,this.height); - ip2.insert(ip, 0, 0); - ip = ip2; - } - } - if (nSlices==0) { - cm = ip.getColorModel(); - min = ip.getMin(); - max = ip.getMax(); - } - addSlice(sliceLabel, ip.getPixels()); - } - - private void init(int width, int height) { - this.width = width; - this.height = height; - stack = new Object[INITIAL_SIZE]; - label = new String[INITIAL_SIZE]; - } - - private ImageProcessor convertType(ImageProcessor ip) { - int newBitDepth = ip.getBitDepth(); - if (this.bitDepth==0) - this.bitDepth = newBitDepth; - if (this.bitDepth!=newBitDepth) { - switch (this.bitDepth) { - case 8: ip=ip.convertToByte(true); break; - case 16: ip=ip.convertToShort(true); break; - case 24: ip=ip.convertToRGB(); break; - case 32: ip=ip.convertToFloat(); break; - } - } - return ip; - } - - /** Adds the image in 'ip' to the stack following slice 'n'. Adds - the slice to the beginning of the stack if 'n' is zero. */ - public void addSlice(String sliceLabel, ImageProcessor ip, int n) { - if (n<0 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - addSlice(sliceLabel, ip); - Object tempSlice = stack[nSlices-1]; - String tempLabel = label[nSlices-1]; - int first = n>0?n:1; - for (int i=nSlices-1; i>=first; i--) { - stack[i] = stack[i-1]; - label[i] = label[i-1]; - } - stack[n] = tempSlice; - label[n] = tempLabel; - } - - /** Deletes the specified slice, where {@literal 1<=n<=nslices}. */ - public void deleteSlice(int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - if (nSlices<1) - return; - for (int i=n; i0) - deleteSlice(nSlices); - } - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public void setRoi(Rectangle roi) { - this.roi = roi; - } - - public Rectangle getRoi() { - if (roi==null) - return new Rectangle(0, 0, width, height); - else - return(roi); - } - - /** Updates this stack so its attributes, such as min, max, - calibration table and color model, are the same as 'ip'. */ - public void update(ImageProcessor ip) { - if (ip!=null) { - min = ip.getMin(); - max = ip.getMax(); - cTable = ip.getCalibrationTable(); - cm = ip.getColorModel(); - } - } - - /** Returns the pixel array for the specified slice, where {@literal 1<=n<=nslices}. */ - public Object getPixels(int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - return stack[n-1]; - } - - /** Assigns a pixel array to the specified slice, where {@literal 1<=n<=nslices}. */ - public void setPixels(Object pixels, int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - stack[n-1] = pixels; - if (this.bitDepth==0) - setBitDepth(pixels); - } - - /** Returns the stack as an array of 1D pixel arrays. Note - that the size of the returned array may be greater than - the number of slices currently in the stack, with - unused elements set to null. */ - public Object[] getImageArray() { - return stack; - } - - /** Returns the number of slices in this stack. */ - public int size() { - return getSize(); - } - - public int getSize() { - return nSlices; - } - - /** Returns the slice labels as an array of Strings. Note - that the size of the returned array may be greater than - the number of slices currently in the stack. Returns null - if the stack is empty or the label of the first slice is null. */ - public String[] getSliceLabels() { - if (nSlices==0) - return null; - else - return label; - } - - /** Returns the label of the specified slice, where {@literal 1<=n<=nslices}. - Returns null if the slice does not have a label or 'n'; - is out of range. For DICOM and FITS stacks, labels may - contain header information. - */ - public String getSliceLabel(int n) { - if (n<1 || n>nSlices) - return null; - else - return label[n-1]; - } - - /** Returns a shortened version (up to the first 60 characters - * or first newline), with the extension removed, of the specified - * slice label, or null if the slice does not have a label. - */ - public String getShortSliceLabel(int n) { - return getShortSliceLabel(n, 60); - } - - /** Returns a shortened version (up to the first 'max' characters - * or first newline), with the extension removed, of the specified - * slice label, or null if the slice does not have a label. - */ - public String getShortSliceLabel(int n, int max) { - String shortLabel = getSliceLabel(n); - if (shortLabel==null) return null; - int newline = shortLabel.indexOf('\n'); - if (newline==0) return null; - if (newline>0) - shortLabel = shortLabel.substring(0, newline); - int len = shortLabel.length(); - if (len>4 && shortLabel.charAt(len-4)=='.' && !Character.isDigit(shortLabel.charAt(len-1))) - shortLabel = shortLabel.substring(0,len-4); - if (shortLabel.length()>max) - shortLabel = shortLabel.substring(0, max); - return shortLabel; - } - - /** Sets the label of the specified slice, where {@literal 1<=n<=nslices}. */ - public void setSliceLabel(String label, int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - this.label[n-1] = label; - } - - /** Returns an ImageProcessor for the specified slice, - * where {@literal 1<=n<=nslices}. - * Returns null if the stack is empty. - */ - public ImageProcessor getProcessor(int n) { - ImageProcessor ip; - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - if (nSlices==0) - return null; - if (stack[n-1]==null) - throw new IllegalArgumentException("Pixel array is null"); - if (stack[n-1] instanceof byte[]) - ip = new ByteProcessor(width, height, null, cm); - else if (stack[n-1] instanceof short[]) - ip = new ShortProcessor(width, height, null, cm); - else if (stack[n-1] instanceof int[]) { - if (signedInt) - ip = new IntProcessor(width, height); - else - ip = new ColorProcessor(width, height, null); - } else if (stack[n-1] instanceof float[]) - ip = new FloatProcessor(width, height, null, cm); - else - throw new IllegalArgumentException("Unknown stack type"); - ip.setPixels(stack[n-1]); - if (min!=Double.MAX_VALUE && ip!=null && !(ip instanceof ColorProcessor)) - ip.setMinAndMax(min, max); - if (cTable!=null) - ip.setCalibrationTable(cTable); - ip.setSliceNumber(n); - return ip; - } - - /** Assigns the pixel array of an ImageProcessor to the specified slice, - * where {@literal 1<=n<=nslices}. - */ - public void setProcessor(ImageProcessor ip, int n) { - if (n<1 || n>nSlices) - throw new IllegalArgumentException(outOfRange+n); - ip = convertType(ip); - if (ip.getWidth()!=width || ip.getHeight()!=height) - throw new IllegalArgumentException("Wrong dimensions for this stack"); - stack[n-1] = ip.getPixels(); - } - - /** Assigns a new color model to this stack. */ - public void setColorModel(ColorModel cm) { - this.cm = cm; - } - - /** Returns this stack's color model. May return null. */ - public ColorModel getColorModel() { - return cm; - } - - /** Returns true if this is a 3-slice, 8-bit RGB stack. */ - public boolean isRGB() { - return getSize()==3 && (stack[0] instanceof byte[]) && getSliceLabel(1)!=null && getSliceLabel(1).equals("Red"); - } - - /** Returns true if this is a 3-slice HSB stack. */ - public boolean isHSB() { - return getSize()==3 && bitDepth==8 && getSliceLabel(1)!=null && getSliceLabel(1).equals("Hue"); - } - - /** Returns true if this is a 3-slice 32-bit HSB stack. */ - public boolean isHSB32() { - return getSize()==3 && bitDepth==32 && getSliceLabel(1)!=null && getSliceLabel(1).equals("Hue"); - } - - /** Returns true if this is a Lab stack. */ - public boolean isLab() { - return getSize()==3 && getSliceLabel(1)!=null && getSliceLabel(1).equals("L*"); - } - - /** Returns true if this is a virtual (disk resident) stack. - This method is overridden by the VirtualStack subclass. */ - public boolean isVirtual() { - return false; - } - - /** Frees memory by deleting a few slices from the end of the stack. */ - public void trim() { - int n = (int)Math.round(Math.log(nSlices)+1.0); - for (int i=0; i=0 && x=0 && y=0 && z=0 && x=0 && y=0 && z255.0) - value = 255.0; - else if (value<0.0) - value = 0.0; - bytes[y*width+x] = (byte)(value+0.5); - break; - case 16: - short[] shorts = (short[])stack[z]; - if (value>65535.0) - value = 65535.0; - else if (value<0.0) - value = 0.0; - shorts[y*width+x] = (short)(value+0.5); - break; - case 32: - float[] floats = (float[])stack[z]; - floats[y*width+x] = (float)value; - break; - case 24: - int[] ints = (int[])stack[z]; - ints[y*width+x] = (int)value; - break; - } - } - } - - public float[] getVoxels(int x0, int y0, int z0, int w, int h, int d, float[] voxels) { - boolean inBounds = x0>=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - voxels = new float[w*h*d]; - int i = 0; - int offset; - for (int z=z0; z=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - voxels = new float[w*h*d]; - int i = 0; - for (int z=z0; z>16; break; - case 1: value=(value&0xff00)>>8; break; - case 2: value=value&0xff;; break; - } - voxels[i++] = (float)value; - } - } - } - return voxels; - } - - /** Experimental */ - public void setVoxels(int x0, int y0, int z0, int w, int h, int d, float[] voxels) { - boolean inBounds = x0>=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - ; - int i = 0; - float value; - for (int z=z0; z255f) - value = 255f; - else if (value<0f) - value = 0f; - bytes[y*width+x] = (byte)(value+0.5f); - } - break; - case 16: - short[] shorts = (short[])stack[z]; - for (int x=x0; x65535f) - value = 65535f; - else if (value<0f) - value = 0f; - shorts[y*width+x] = (short)(value+0.5f); - } - break; - case 32: - float[] floats = (float[])stack[z]; - for (int x=x0; x=0 && x0+w<=width && y0>=0 && y0+h<=height && z0>=0 && z0+d<=nSlices; - if (voxels==null || voxels.length!=w*h*d) - ; - int i = 0; - for (int z=z0; z0) - setBitDepth(stack[0]); - return this.bitDepth; - } - - /** Sets the bit depth (8=byte, 16=short, 24=RGB, 32=float). */ - public void setBitDepth(int depth) { - if (size()==0 && (depth==8||depth==16||depth==24||depth==32)) - this.bitDepth = depth; - } - - /** Creates a new ImageStack. - * @param width width in pixels - * @param height height in pixels - * @param depth number of images - * @param bitdepth 8, 16, 32 (float) or 24 (RGB) - */ - public static ImageStack create(int width, int height, int depth, int bitdepth) { - ImageStack stack = IJ.createImage("", width, height, depth, bitdepth).getStack(); - if (bitdepth==16 || bitdepth==32) { - stack.min = Double.MAX_VALUE; - stack.max = 0.0; - } - return stack; - } - - /** Creates an ImageStack from an ImagePlus array. */ - public static ImageStack create(ImagePlus[] images) { - int w = 0; - int h = 0; - for (int i=0; iw) w=images[i].getWidth(); - if (images[i].getHeight()>h) h=images[i].getHeight(); - } - ImageStack stack = new ImageStack(w, h); - stack.init(w, h); - for (int i=0; ithis.width||y+height>this.height||z+depth>size()) - throw new IllegalArgumentException("Argument out of range"); - ImageStack stack2 = new ImageStack(width, height, getColorModel()); - for (int i=z; itrue if this is a 256 entry grayscale LUT. - @see ij.process.ImageProcessor#isColorLut - */ - public boolean isGrayscale() { - boolean isGray = true; - if (mapSize < 256) - return false; - for (int i=0; i 1) - return fs.saveAsTiffStack(path); - else - return fs.saveAsTiff(path); - } - - public static String getName(String path) { - int i = path.lastIndexOf('/'); - if (i == -1) - i = path.lastIndexOf('\\'); - if (i > 0) - return path.substring(i + 1); - else - return path; - } - - public static String getDir(String path) { - int i = path.lastIndexOf('/'); - if (i == -1) - i = path.lastIndexOf('\\'); - if (i > 0) - return path.substring(0, i + 1); - else - return ""; - } - - /** Aborts the currently running macro or any plugin using IJ.run(). */ - public static void abort() { - // IJ.log("Abort: "+Thread.currentThread().getName()); - abort = true; - if (Thread.currentThread().getName().endsWith("Macro$")) { - table.remove(Thread.currentThread()); - /* Changed for Bio7 to get a message instead of the stack trace! */ - try { - throw new RuntimeException(MACRO_CANCELED); - } catch (Exception e) { - System.out.println(MACRO_CANCELED); - } - - } - } - - /** - * If a command started using run(name, options) is running, and the current - * thread is the same thread, returns the options string, otherwise, returns - * null. - * - * @see ij.gui.GenericDialog - * @see ij.io.OpenDialog - */ - public static String getOptions() { - String threadName = Thread.currentThread().getName(); - - // IJ.log("getOptions: "+threadName+" "+Thread.currentThread().hashCode()); //ts - /*Changed for Bio7. Added Eclipse 'Worker' thread name!*/ - if (threadName.startsWith("Run$_") || threadName.contains("Worker")||threadName.startsWith("RMI TCP")) { - Object options = table.get(Thread.currentThread()); - return options == null ? null : options + " "; - } else - return null; - } - - /** Define a set of Macro options for the current Thread. */ - public static void setOptions(String options) { - // IJ.log("setOptions: "+Thread.currentThread().getName()+" - // "+Thread.currentThread().hashCode()+" "+options); //ts - if (options == null || options.equals("")) - table.remove(Thread.currentThread()); - else - table.put(Thread.currentThread(), options); - } - - /** Define a set of Macro options for a Thread. */ - public static void setOptions(Thread thread, String options) { - if (null == thread) - throw new RuntimeException("Need a non-null thread instance"); - if (null == options) - table.remove(thread); - else - table.put(thread, options); - } - - public static String getValue(String options, String key, String defaultValue) { - key = trimKey(key); - if (!options.endsWith(" ")) - options = options + " "; - key += '='; - int index = -1; - do { // Require that key not be preceded by a letter - index = options.indexOf(key, ++index); - if (index < 0) - return defaultValue; - } while (index != 0 && Character.isLetter(options.charAt(index - 1))); - options = options.substring(index + key.length(), options.length()); - if (options.charAt(0) == '\'') { - index = options.indexOf("'", 1); - if (index < 0) - return defaultValue; - else - return options.substring(1, index); - } else if (options.charAt(0) == '[') { - int count = 1; - index = -1; - for (int i = 1; i < options.length(); i++) { - char ch = options.charAt(i); - if (ch == '[') - count++; - else if (ch == ']') - count--; - if (count == 0) { - index = i; - break; - } - } - if (index < 0) - return defaultValue; - else - return options.substring(1, index); - } else { - index = options.indexOf(" "); - if (index < 0) - return defaultValue; - else - return options.substring(0, index); - } - } - - public static String trimKey(String key) { - if (key==null) - return key; - int index = key.indexOf(" "); - if (index > -1) - key = key.substring(0, index); - index = key.indexOf(":"); - if (index > -1) - key = key.substring(0, index); - key = key.toLowerCase(Locale.US); - return key; - } - - /** - * Evaluates 'code' and returns the output, or any error, as a String (e.g., - * Macro.eval("2+2") returns "4"). - */ - public static String eval(String code) { - return new Interpreter().eval(code); - } - -} diff --git a/com.eco.bio7.image/src/ij/Menus.java b/com.eco.bio7.image/src/ij/Menus.java deleted file mode 100644 index 6546f62fc..000000000 --- a/com.eco.bio7.image/src/ij/Menus.java +++ /dev/null @@ -1,1946 +0,0 @@ -package ij; - -import ij.process.*; -import ij.util.*; -import ij.gui.ImageWindow; -import ij.plugin.MacroInstaller; -import ij.gui.Toolbar; -import ij.macro.Interpreter; -import java.awt.*; -import java.awt.image.*; -import java.awt.event.*; -import java.util.*; -import java.io.*; -import java.net.URL; -import java.applet.Applet; -import java.awt.event.*; -import java.util.zip.*; - -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Platform; -import org.eclipse.jface.action.IContributionItem; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IViewSite; -import org.osgi.framework.Bundle; - -import com.eco.bio7.ImageJPluginActions.ImageJExtensionAction; -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.Util; - -/** - * This class installs and updates ImageJ's menus. Note that menu labels, even - * in submenus, must be unique. This is because ImageJ uses a single hash table - * for all menu labels. If you look closely, you will see that - * File->Import->Text Image... and File->Save As->Text Image... do not use the - * same label. One of the labels has an extra space. - * - * @see ImageJ - */ - -public class Menus { - - public static final char PLUGINS_MENU = 'p'; - public static final char IMPORT_MENU = 'i'; - public static final char SAVE_AS_MENU = 's'; - public static final char SHORTCUTS_MENU = 'h'; // 'h'=hotkey - public static final char ABOUT_MENU = 'a'; - public static final char FILTERS_MENU = 'f'; - public static final char TOOLS_MENU = 't'; - public static final char UTILITIES_MENU = 'u'; - - public static final int WINDOW_MENU_ITEMS = 6; // fixed items at top of - // Window menu - public static final int NORMAL_RETURN = 0; - public static final int COMMAND_IN_USE = -1; - public static final int INVALID_SHORTCUT = -2; - public static final int SHORTCUT_IN_USE = -3; - public static final int NOT_INSTALLED = -4; - public static final int COMMAND_NOT_FOUND = -5; - - public static final int MAX_OPEN_RECENT_ITEMS = 15; - - private static Menus instance; - private static MenuBar mbar; - private static CheckboxMenuItem gray8Item, gray16Item, gray32Item, color256Item, colorRGBItem, RGBStackItem, - HSBStackItem, LabStackItem, HSB32Item; - private static PopupMenu popup; - - private static ImageJ ij; - private static Applet applet; - private Hashtable demoImagesTable = new Hashtable(); - private static String ImageJPath, pluginsPath, macrosPath; - private static Properties menus; - private static Properties menuSeparators; - private static Menu pluginsMenu, saveAsMenu, shortcutsMenu, utilitiesMenu, macrosMenu; - static Menu window, openRecentMenu; - private static Hashtable pluginsTable; - - private static int nPlugins, nMacros; - private static Hashtable shortcuts; - private static Hashtable macroShortcuts; - private static Vector pluginsPrefs; // commands saved in IJ_Prefs - static int windowMenuItems2; // non-image windows listed in Window menu + - // separator - private String error; - private String jarError; - private String pluginError; - private boolean isJarErrorHeading; - private static boolean installingJars, duplicateCommand; - private static Vector jarFiles; // JAR files in plugins folder with "_" in - // their name - private Map menuEntry2jarFile = new HashMap(); - private static Vector macroFiles; // Macros and scripts in the plugins - // folder - private static int userPluginsIndex; // First user plugin or submenu in - // Plugins menu - private static boolean addSorted; - private static int defaultFontSize = IJ.isWindows() ? 15 : 0; - private static int fontSize; - private static double scale = 1.0; - private static Font cachedFont;//Not used since we are using SWT menus! - - static boolean jnlp; // true when using Java WebStart - public static int setMenuBarCount; - /* Changed for Bio7! */ - public static Vector bio7JarAllCommand; - - Menus(ImageJ ijInstance, Applet appletInstance) { - ij = ijInstance; - String title = ij != null ? ij.getTitle() : null; - applet = appletInstance; - instance = this; - fontSize = Prefs.getInt(Prefs.MENU_SIZE, defaultFontSize); - - } - - String addMenuBar() { - - scale = Prefs.getGuiScale(); - //if ((scale >= 1.5 && scale < 2.0) || (scale >= 2.5 && scale < 3.0)) - // scale = (int) Math.round(scale); - nPlugins = nMacros = userPluginsIndex = 0; - addSorted = installingJars = duplicateCommand = false; - error = null; - mbar = null; - menus = new Properties(); - pluginsTable = new Hashtable(); - - /* Changed for Bio7! */ - bio7JarAllCommand = new Vector(); - - shortcuts = new Hashtable(); - pluginsPrefs = new Vector(); - macroShortcuts = null; - setupPluginsAndMacrosPaths(); - Menu file = getMenu("File"); - Menu newMenu = getMenu("File>New", true); - addPlugInItem(file, "Open...", "ij.plugin.Commands(\"open\")", KeyEvent.VK_O, false); - addPlugInItem(file, "Open Next", "ij.plugin.NextImageOpener", KeyEvent.VK_O, true); - Menu openSamples = getMenu("File>Open Samples", true); - openSamples.addSeparator(); - addPlugInItem(openSamples, "Cache Sample Images ", "ij.plugin.URLOpener(\"cache\")", 0, false); - addOpenRecentSubMenu(file); - Menu importMenu = getMenu("File>Import", true); - Menu showFolderMenu = new Menu("Show Folder"); - file.add(showFolderMenu); - addPlugInItem(showFolderMenu, "Image", "ij.plugin.SimpleCommands(\"showdirImage\")", 0, false); - addPlugInItem(showFolderMenu, "Plugins", "ij.plugin.SimpleCommands(\"showdirPlugins\")", 0, false); - addPlugInItem(showFolderMenu, "Macros", "ij.plugin.SimpleCommands(\"showdirMacros\")", 0, false); - addPlugInItem(showFolderMenu, "LUTs", "ij.plugin.SimpleCommands(\"showdirLuts\")", 0, false); - addPlugInItem(showFolderMenu, "ImageJ", "ij.plugin.SimpleCommands(\"showdirImageJ\")", 0, false); - addPlugInItem(showFolderMenu, "temp", "ij.plugin.SimpleCommands(\"showdirTemp\")", 0, false); - addPlugInItem(showFolderMenu, "Home", "ij.plugin.SimpleCommands(\"showdirHome\")", 0, false); - file.addSeparator(); - addPlugInItem(file, "Close", "ij.plugin.Commands(\"close\")", KeyEvent.VK_W, false); - addPlugInItem(file, "Close All", "ij.plugin.Commands(\"close-all\")", KeyEvent.VK_W, true); - addPlugInItem(file, "Save", "ij.plugin.Commands(\"save\")", KeyEvent.VK_S, false); - saveAsMenu = getMenu("File>Save As", true); - addPlugInItem(file, "Revert", "ij.plugin.Commands(\"revert\")", KeyEvent.VK_R, true); - file.addSeparator(); - addPlugInItem(file, "Page Setup...", "ij.plugin.filter.Printer(\"setup\")", 0, false); - addPlugInItem(file, "Print...", "ij.plugin.filter.Printer(\"print\")", KeyEvent.VK_P, false); - - Menu edit = getMenu("Edit"); - addPlugInItem(edit, "Undo", "ij.plugin.Commands(\"undo\")", KeyEvent.VK_Z, false); - edit.addSeparator(); - addPlugInItem(edit, "Cut", "ij.plugin.Clipboard(\"cut\")", KeyEvent.VK_X, false); - addPlugInItem(edit, "Copy", "ij.plugin.Clipboard(\"copy\")", KeyEvent.VK_C, false); - addPlugInItem(edit, "Copy to System", "ij.plugin.Clipboard(\"scopy\")", 0, false); - addPlugInItem(edit, "Paste", "ij.plugin.Clipboard(\"paste\")", KeyEvent.VK_V, false); - addPlugInItem(edit, "Paste Control...", "ij.plugin.frame.PasteController", 0, false); - edit.addSeparator(); - addPlugInItem(edit, "Clear", "ij.plugin.filter.Filler(\"clear\")", 0, false); - addPlugInItem(edit, "Clear Outside", "ij.plugin.filter.Filler(\"outside\")", 0, false); - addPlugInItem(edit, "Fill", "ij.plugin.filter.Filler(\"fill\")", KeyEvent.VK_F, false); - addPlugInItem(edit, "Draw", "ij.plugin.filter.Filler(\"draw\")", KeyEvent.VK_D, false); - addPlugInItem(edit, "Invert", "ij.plugin.filter.Filters(\"invert\")", KeyEvent.VK_I, true); - edit.addSeparator(); - getMenu("Edit>Selection", true); - Menu optionsMenu = getMenu("Edit>Options", true); - - Menu image = getMenu("Image"); - Menu imageType = getMenu("Image>Type"); - gray8Item = addCheckboxItem(imageType, "8-bit", "ij.plugin.Converter(\"8-bit\")"); - gray16Item = addCheckboxItem(imageType, "16-bit", "ij.plugin.Converter(\"16-bit\")"); - gray32Item = addCheckboxItem(imageType, "32-bit", "ij.plugin.Converter(\"32-bit\")"); - color256Item = addCheckboxItem(imageType, "8-bit Color", "ij.plugin.Converter(\"8-bit Color\")"); - colorRGBItem = addCheckboxItem(imageType, "RGB Color", "ij.plugin.Converter(\"RGB Color\")"); - imageType.add(new MenuItem("-")); - RGBStackItem = addCheckboxItem(imageType, "RGB Stack", "ij.plugin.Converter(\"RGB Stack\")"); - HSBStackItem = addCheckboxItem(imageType, "HSB Stack", "ij.plugin.Converter(\"HSB Stack\")"); - HSB32Item = addCheckboxItem(imageType, "HSB (32-bit)", "ij.plugin.Converter(\"HSB (32-bit)\")"); - LabStackItem = addCheckboxItem(imageType, "Lab Stack", "ij.plugin.Converter(\"Lab Stack\")"); - image.add(imageType); - - image.addSeparator(); - getMenu("Image>Adjust", true); - addPlugInItem(image, "Show Info...", "ij.plugin.ImageInfo", KeyEvent.VK_I, false); - addPlugInItem(image, "Properties...", "ij.plugin.filter.ImageProperties", KeyEvent.VK_P, true); - getMenu("Image>Color", true); - getMenu("Image>Stacks", true); - getMenu("Image>Stacks>Animation_", true); - getMenu("Image>Stacks>Tools_", true); - Menu hyperstacksMenu = getMenu("Image>Hyperstacks", true); - image.addSeparator(); - addPlugInItem(image, "Crop", "ij.plugin.Resizer(\"crop\")", KeyEvent.VK_X, true); - addPlugInItem(image, "Duplicate...", "ij.plugin.Duplicator", KeyEvent.VK_D, true); - addPlugInItem(image, "Rename...", "ij.plugin.SimpleCommands(\"rename\")", 0, false); - addPlugInItem(image, "Scale...", "ij.plugin.Scaler", KeyEvent.VK_E, false); - getMenu("Image>Transform", true); - getMenu("Image>Zoom", true); - getMenu("Image>Overlay", true); - image.addSeparator(); - getMenu("Image>Lookup Tables", true); - - Menu process = getMenu("Process"); - addPlugInItem(process, "Smooth", "ij.plugin.filter.Filters(\"smooth\")", KeyEvent.VK_S, true); - addPlugInItem(process, "Sharpen", "ij.plugin.filter.Filters(\"sharpen\")", 0, false); - addPlugInItem(process, "Find Edges", "ij.plugin.filter.Filters(\"edge\")", 0, false); - addPlugInItem(process, "Find Maxima...", "ij.plugin.filter.MaximumFinder", 0, false); - addPlugInItem(process, "Enhance Contrast...", "ij.plugin.ContrastEnhancer", 0, false); - getMenu("Process>Noise", true); - getMenu("Process>Shadows", true); - getMenu("Process>Binary", true); - getMenu("Process>Math", true); - getMenu("Process>FFT", true); - Menu filtersMenu = getMenu("Process>Filters", true); - process.addSeparator(); - getMenu("Process>Batch", true); - addPlugInItem(process, "Image Calculator...", "ij.plugin.ImageCalculator", 0, false); - addPlugInItem(process, "Subtract Background...", "ij.plugin.filter.BackgroundSubtracter", 0, false); - addItem(process, "Repeat Command", KeyEvent.VK_R, false); - - Menu analyzeMenu = getMenu("Analyze"); - addPlugInItem(analyzeMenu, "Measure", "ij.plugin.filter.Analyzer", KeyEvent.VK_M, false); - addPlugInItem(analyzeMenu, "Analyze Particles...", "ij.plugin.filter.ParticleAnalyzer", 0, false); - addPlugInItem(analyzeMenu, "Summarize", "ij.plugin.filter.Analyzer(\"sum\")", 0, false); - addPlugInItem(analyzeMenu, "Distribution...", "ij.plugin.Distribution", 0, false); - addPlugInItem(analyzeMenu, "Label", "ij.plugin.filter.Filler(\"label\")", 0, false); - addPlugInItem(analyzeMenu, "Clear Results", "ij.plugin.filter.Analyzer(\"clear\")", 0, false); - addPlugInItem(analyzeMenu, "Set Measurements...", "ij.plugin.filter.Analyzer(\"set\")", 0, false); - analyzeMenu.addSeparator(); - addPlugInItem(analyzeMenu, "Set Scale...", "ij.plugin.filter.ScaleDialog", 0, false); - addPlugInItem(analyzeMenu, "Calibrate...", "ij.plugin.filter.Calibrator", 0, false); - if (IJ.isMacOSX()) { - addPlugInItem(analyzeMenu, "Histogram", "ij.plugin.Histogram", 0, false); - shortcuts.put(Integer.valueOf(KeyEvent.VK_H), "Histogram"); - } else - addPlugInItem(analyzeMenu, "Histogram", "ij.plugin.Histogram", KeyEvent.VK_H, false); - addPlugInItem(analyzeMenu, "Plot Profile", "ij.plugin.Profiler(\"plot\")", KeyEvent.VK_K, false); - addPlugInItem(analyzeMenu, "Surface Plot...", "ij.plugin.SurfacePlotter", 0, false); - getMenu("Analyze>Gels", true); - Menu toolsMenu = getMenu("Analyze>Tools", true); - - // the plugins will be added later, after a separator - addPluginsMenu(); - - Menu window = getMenu("Window"); - /*Changed for Bio7. We have a tabbed structure!*/ - addPlugInItem(window, "Show All", "ij.plugin.WindowOrganizer(\"show\")", KeyEvent.VK_CLOSE_BRACKET, false); - String key = IJ.isWindows() ? "enter" : "return"; - addPlugInItem(window, "Main Window [" + key + "]", "ij.plugin.WindowOrganizer(\"imagej\")", 0, false); - addPlugInItem(window, "Put Behind [tab]", "ij.plugin.Commands(\"tab\")", 0, false); - addPlugInItem(window, "Cascade", "ij.plugin.WindowOrganizer(\"cascade\")", 0, false); - addPlugInItem(window, "Tile", "ij.plugin.WindowOrganizer(\"tile\")", 0, false); - window.addSeparator(); - - Menu help = getMenu("Help"); - addPlugInItem(help, "ImageJ Website...", "ij.plugin.BrowserLauncher", 0, false); - help.addSeparator(); - addPlugInItem(help, "Dev. Resources...", "ij.plugin.BrowserLauncher(\"" + IJ.URL2 + "/developer/index.html\")", - 0, false); - addPlugInItem(help, "Macro Functions...", "ij.plugin.BrowserLauncher(\"https://wsr.imagej.net/developer/macro/functions.html\")", 0, false); - Menu examplesMenu = getExamplesMenu(ij); - addPlugInItem(examplesMenu, "Open as Panel", "ij.plugin.SimpleCommands(\"opencp\")", 0, false); - help.add(examplesMenu); - help.addSeparator(); - /* Changed for Bio7! Left out ImageJ update! */ - // addPlugInItem(help, "Update ImageJ...", "ij.plugin.ImageJ_Updater", - // 0, false); - addPlugInItem(help, "Release Notes...", "ij.plugin.BrowserLauncher(\"https://wsr.imagej.net/notes.html\")", 0, false); - addPlugInItem(help, "Refresh Menus", "ij.plugin.ImageJ_Updater(\"menus\")", 0, false); - help.addSeparator(); - Menu aboutMenu = getMenu("Help>About Plugins", true); - addPlugInItem(help, "About ImageJ...", "ij.plugin.AboutBox", 0, false); - - if (applet == null) { - menuSeparators = new Properties(); - installPlugins(); - } - - // make sure "Quit" is the last item in the File menu - file.addSeparator(); - addPlugInItem(file, "Quit", "ij.plugin.Commands(\"quit\")", 0, false); - - // System.out.println("MenuBar.setFont: "+fontSize+" "+scale+" "+getFont()); - if (fontSize != 0 || scale > 1.0) - mbar.setFont(getFont()); - if (ij != null) { - ij.setMenuBar(mbar); - Menus.setMenuBarCount++; - } - // Add deleted sample images to commands table - pluginsTable.put("Lena (68K)", "ij.plugin.URLOpener(\"lena-std.tif\")"); - pluginsTable.put("Bridge (174K)", "ij.plugin.URLOpener(\"bridge.gif\")"); - - if (pluginError != null) - error = error != null ? error += "\n" + pluginError : pluginError; - if (jarError != null) - error = error != null ? error += "\n" + jarError : jarError; - return error; - } - - public static Menu getExamplesMenu(ActionListener listener) { - Menu menu = new Menu("Examples"); - Menu submenu = new Menu("Plots"); - - addExample(submenu, "Example Plot", "Example_Plot_.ijm"); - addExample(submenu, "Semi-log Plot", "Semi-log_Plot_.ijm"); - addExample(submenu, "Arrow Plot", "Arrow_Plot_.ijm"); - addExample(submenu, "Damped Wave Plot", "Damped_Wave_Plot_.ijm"); - addExample(submenu, "Dynamic Plot", "Dynamic_Plot_.ijm"); - addExample(submenu, "Dynamic Plot 2D", "Dynamic_Plot_2D_.ijm"); - addExample(submenu, "Custom Plot Symbols", "Custom_Plot_Symbols_.ijm"); - addExample(submenu, "Histograms", "Histograms_.ijm"); - addExample(submenu, "Bar Charts", "Bar_Charts_.ijm"); - addExample(submenu, "Shapes", "Plot_Shapes_.ijm"); - addExample(submenu, "Plot Styles", "Plot_Styles_.ijm"); - addExample(submenu, "Random Data", "Random_Data_.ijm"); - addExample(submenu, "Plot Results", "Plot_Results_.ijm"); - addExample(submenu, "Plot With Spectrum", "Plot_With_Spectrum_.ijm"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Tools"); - addExample(submenu, "Annular Selection", "Annular_Selection_Tool.ijm"); - addExample(submenu, "Big Cursor", "Big_Cursor_Tool.ijm"); - addExample(submenu, "Circle Tool", "Circle_Tool.ijm"); - addExample(submenu, "Point Picker", "Point_Picker_Tool.ijm"); - addExample(submenu, "Star Tool", "Star_Tool.ijm"); - addExample(submenu, "Animated Icon Tool", "Animated_Icon_Tool.ijm"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Macro"); - addExample(submenu, "Sphere", "Sphere.ijm"); - addExample(submenu, "Dialog Box", "Dialog_Box.ijm"); - addExample(submenu, "Process Folder", "Batch_Process_Folder.ijm"); - addExample(submenu, "OpenDialog Demo", "OpenDialog_Demo.ijm"); - addExample(submenu, "Save All Images", "Save_All_Images.ijm"); - addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.ijm"); - addExample(submenu, "Non-numeric Table", "Non-numeric_Table.ijm"); - addExample(submenu, "Overlay", "Overlay.ijm"); - addExample(submenu, "Stack Overlay", "Stack_Overlay.ijm"); - addExample(submenu, "Array Functions", "Array_Functions.ijm"); - addExample(submenu, "Dual Progress Bars", "Dual_Progress_Bars.ijm"); - addExample(submenu, "Grab Viridis Colormap", "Grab_Viridis_Colormap.ijm"); - addExample(submenu, "Custom Measurement", "Custom_Measurement.ijm"); - addExample(submenu, "Synthetic Images", "Synthetic_Images.ijm"); - addExample(submenu, "Spiral Rotation", "Spiral_Rotation.ijm"); - addExample(submenu, "Curve Fitting", "Curve_Fitting.ijm"); - addExample(submenu, "Colors of 2021", "Colors_of_2021.ijm"); - addExample(submenu, "Turtle Graphics", "Turtle_Graphics.ijm"); - addExample(submenu, "Easter Eggs", "Easter_Eggs.ijm"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("JavaScript"); - addExample(submenu, "Sphere", "Sphere.js"); - addExample(submenu, "Plasma Cloud", "Plasma_Cloud.js"); - addExample(submenu, "Cloud Debugger", "Cloud_Debugger.js"); - addExample(submenu, "Synthetic Images", "Synthetic_Images.js"); - addExample(submenu, "Points", "Points.js"); - addExample(submenu, "Spiral Rotation", "Spiral_Rotation.js"); - addExample(submenu, "Example Plot", "Example_Plot.js"); - addExample(submenu, "Semi-log Plot", "Semi-log_Plot.js"); - addExample(submenu, "Arrow Plot", "Arrow_Plot.js"); - addExample(submenu, "Dynamic Plot", "Dynamic_Plot.js"); - addExample(submenu, "Plot Styles", "Plot_Styles.js"); - addExample(submenu, "Plot Random Data", "Plot_Random_Data.js"); - addExample(submenu, "Histogram Plots", "Histogram_Plots.js"); - addExample(submenu, "JPEG Quality Plot", "JPEG_Quality_Plot.js"); - addExample(submenu, "Process Folder", "Batch_Process_Folder.js"); - addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.js"); - addExample(submenu, "Non-numeric Table", "Non-numeric_Table.js"); - addExample(submenu, "Overlay", "Overlay.js"); - addExample(submenu, "Stack Overlay", "Stack_Overlay.js"); - addExample(submenu, "Dual Progress Bars", "Dual_Progress_Bars.js"); - addExample(submenu, "Gamma Adjuster", "Gamma_Adjuster.js"); - addExample(submenu, "Custom Measurement", "Custom_Measurement.js"); - addExample(submenu, "Terabyte VirtualStack", "Terabyte_VirtualStack.js"); - addExample(submenu, "Event Listener", "Event_Listener.js"); - addExample(submenu, "FFT Filter", "FFT_Filter.js"); - addExample(submenu, "Curve Fitting", "Curve_Fitting.js"); - addExample(submenu, "Overlay Text", "Overlay_Text.js"); - addExample(submenu, "Crop Multiple Rois", "Crop_Multiple_Rois.js"); - addExample(submenu, "Show all LUTs", "Show_all_LUTs.js"); - addExample(submenu, "Dialog Demo", "Dialog_Demo.js"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("BeanShell"); - addExample(submenu, "Sphere", "Sphere.bsh"); - addExample(submenu, "Example Plot", "Example_Plot.bsh"); - addExample(submenu, "Semi-log Plot", "Semi-log_Plot.bsh"); - addExample(submenu, "Arrow Plot", "Arrow_Plot.bsh"); - addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.bsh"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Python"); - addExample(submenu, "Sphere", "Sphere.py"); - addExample(submenu, "Animated Gaussian Blur", "Animated_Gaussian_Blur.py"); - addExample(submenu, "Spiral Rotation", "Spiral_Rotation.py"); - addExample(submenu, "Overlay", "Overlay.py"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Java"); - addExample(submenu, "Sphere", "Sphere_.java"); - addExample(submenu, "Plasma Cloud", "Plasma_Cloud.java"); - addExample(submenu, "Gamma Adjuster", "Gamma_Adjuster.java"); - addExample(submenu, "Plugin", "My_Plugin.java"); - addExample(submenu, "Plugin Filter", "Filter_Plugin.java"); - addExample(submenu, "Plugin Frame", "Plugin_Frame.java"); - addExample(submenu, "Plugin Tool", "Prototype_Tool.java"); - submenu.addActionListener(listener); - menu.add(submenu); - submenu = new Menu("Games"); - addExample(submenu, "2048", "2048.ijm"); - addExample(submenu, "Asteroids", "Asteroids.js"); - addExample(submenu, "Breakout", "Breakout.ijm"); - addExample(submenu, "Life", "GameOfLife.js"); - addExample(submenu, "Pong", "Pong.ijm"); - addExample(submenu, "Snake", "Snake.ijm"); - addExample(submenu, "Tetris", "Tetris.js"); - submenu.addActionListener(listener); - menu.add(submenu); - menu.addSeparator(); - CheckboxMenuItem item = new CheckboxMenuItem("Autorun Examples"); - menu.add(item); - item.addItemListener(ij); - item.setState(Prefs.autoRunExamples); - return menu; - } - - private static void addExample(Menu menu, String label, String command) { - MenuItem item = new MenuItem(label); - menu.add(item); - item.setActionCommand(command); - } - - void addOpenRecentSubMenu(Menu menu) { - openRecentMenu = getMenu("File>Open Recent"); - for (int i = 0; i < MAX_OPEN_RECENT_ITEMS; i++) { - String path = Prefs.getString("recent" + (i / 10) % 10 + i % 10); - if (path == null) - break; - MenuItem item = new MenuItem(path); - openRecentMenu.add(item); - item.addActionListener(ij); - } - menu.add(openRecentMenu); - } - - static void addItem(Menu menu, String label, int shortcut, boolean shift) { - if (menu == null) - return; - MenuItem item; - if (shortcut == 0) - item = new MenuItem(label); - else { - if (shift) { - item = new MenuItem(label, new MenuShortcut(shortcut, true)); - shortcuts.put(Integer.valueOf(shortcut + 200), label); - } else { - item = new MenuItem(label, new MenuShortcut(shortcut)); - shortcuts.put(Integer.valueOf(shortcut), label); - } - } - if (addSorted) { - if (menu == pluginsMenu) - addItemSorted(menu, item, userPluginsIndex); - else - addOrdered(menu, item); - } else - menu.add(item); - item.addActionListener(ij); - } - - void addPlugInItem(Menu menu, String label, String className, int shortcut, boolean shift) { - pluginsTable.put(label, className); - nPlugins++; - addItem(menu, label, shortcut, shift); - } - - CheckboxMenuItem addCheckboxItem(Menu menu, String label, String className) { - pluginsTable.put(label, className); - nPlugins++; - CheckboxMenuItem item = new CheckboxMenuItem(label); - menu.add(item); - item.addItemListener(ij); - item.setState(false); - return item; - } - - static Menu addSubMenu(Menu menu, String name) { - String value; - String key = name.toLowerCase(Locale.US); - int index; - Menu submenu = new Menu(name.replace('_', ' ')); - index = key.indexOf(' '); - if (index > 0) - key = key.substring(0, index); - for (int count = 1; count < 100; count++) { - value = Prefs.getString(key + (count / 10) % 10 + count % 10); - if (value == null) - break; - if (count == 1) - menu.add(submenu); - if (value.equals("-")) - submenu.addSeparator(); - else - addPluginItem(submenu, value); - } - if (name.equals("Lookup Tables") && applet == null) - addLuts(submenu); - return submenu; - } - - static void addLuts(Menu submenu) { - String path = IJ.getDirectory("luts"); - if (path == null) - return; - File f = new File(path); - String[] list = null; - if (applet == null && f.exists() && f.isDirectory()) - list = f.list(); - if (list == null) - return; - if (IJ.isLinux() || IJ.isMacOSX()) - Arrays.sort(list); - submenu.addSeparator(); - for (int i = 0; i < list.length; i++) { - String name = list[i]; - if (name.endsWith(".lut")) { - name = name.substring(0, name.length() - 4); - if (name.contains("_") && !name.contains(" ")) - name = name.replace("_", " "); - MenuItem item = new MenuItem(name); - submenu.add(item); - item.addActionListener(ij); - nPlugins++; - } - } - } - - static void addPluginItem(Menu submenu, String s) { - if (s.startsWith("\"-\"")) { - // add menu separator if command="-" - addSeparator(submenu); - return; - } - int lastComma = s.lastIndexOf(','); - if (lastComma <= 0) - return; - String command = s.substring(1, lastComma - 1); - int keyCode = 0; - boolean shift = false; - if (command.endsWith("]")) { - int openBracket = command.lastIndexOf('['); - if (openBracket > 0) { - String shortcut = command.substring(openBracket + 1, command.length() - 1); - keyCode = convertShortcutToCode(shortcut); - boolean functionKey = keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12; - if (keyCode > 0 && !functionKey) - command = command.substring(0, openBracket); - } - } - if (keyCode >= KeyEvent.VK_F1 && keyCode <= KeyEvent.VK_F12) { - shortcuts.put(Integer.valueOf(keyCode), command); - keyCode = 0; - } else if (keyCode >= 265 && keyCode <= 290) { - keyCode -= 200; - shift = true; - } - addItem(submenu, command, keyCode, shift); - while (s.charAt(lastComma + 1) == ' ' && lastComma + 2 < s.length()) - lastComma++; // remove leading spaces - String className = s.substring(lastComma + 1, s.length()); - // IJ.log(command+" "+className); - if (installingJars) - duplicateCommand = pluginsTable.get(command) != null; - pluginsTable.put(command, className); - nPlugins++; - } - - void checkForDuplicate(String command) { - if (pluginsTable.get(command) != null) { - } - } - - void addPluginsMenu() { - String value, label, className; - int index; - // pluginsMenu = new Menu("Plugins"); - pluginsMenu = getMenu("Plugins"); - for (int count = 1; count < 100; count++) { - value = Prefs.getString("plug-in" + (count / 10) % 10 + count % 10); - if (value == null) - break; - char firstChar = value.charAt(0); - if (firstChar == '-') - pluginsMenu.addSeparator(); - else if (firstChar == '>') { - String submenu = value.substring(2, value.length() - 1); - // Menu menu = getMenu("Plugins>" + submenu, true); - Menu menu = addSubMenu(pluginsMenu, submenu); - if (submenu.equals("Shortcuts")) - shortcutsMenu = menu; - else if (submenu.equals("Utilities")) - utilitiesMenu = menu; - else if (submenu.equals("Macros")) - macrosMenu = menu; - } else - addPluginItem(pluginsMenu, value); - } - userPluginsIndex = pluginsMenu.getItemCount(); - if (userPluginsIndex < 0) - userPluginsIndex = 0; - } - - /** - * Install plugins using "pluginxx=" keys in IJ_Prefs.txt. Plugins not listed in - * IJ_Prefs are added to the end of the Plugins menu. - */ - void installPlugins() { - int nPlugins0 = nPlugins; - String value, className; - char menuCode; - Menu menu; - String[] pluginList = getPlugins(); - String[] pluginsList2 = null; - Hashtable skipList = new Hashtable(); - for (int index = 0; index < 100; index++) { - value = Prefs.getString("plugin" + (index / 10) % 10 + index % 10); - if (value == null) - break; - menuCode = value.charAt(0); - switch (menuCode) { - case PLUGINS_MENU: - default: - menu = pluginsMenu; - break; - case IMPORT_MENU: - menu = getMenu("File>Import"); - break; - case SAVE_AS_MENU: - menu = getMenu("File>Save As"); - break; - case SHORTCUTS_MENU: - menu = shortcutsMenu; - break; - case ABOUT_MENU: - menu = getMenu("Help>About Plugins"); - break; - case FILTERS_MENU: - menu = getMenu("Process>Filters"); - break; - case TOOLS_MENU: - menu = getMenu("Analyze>Tools"); - break; - case UTILITIES_MENU: - menu = utilitiesMenu; - break; - } - String prefsValue = value; - value = value.substring(2, value.length()); // remove menu code and - // coma - className = value.substring(value.lastIndexOf(',') + 1, value.length()); - boolean found = className.startsWith("ij."); - if (!found && pluginList != null) { // does this plugin exist? - if (pluginsList2 == null) - pluginsList2 = getStrippedPlugins(pluginList); - for (int i = 0; i < pluginsList2.length; i++) { - if (className.startsWith(pluginsList2[i])) { - found = true; - break; - } - } - } - if (found && menu != pluginsMenu) { - addPluginItem(menu, value); - pluginsPrefs.addElement(prefsValue); - if (className.endsWith("\")")) { // remove any argument - int argStart = className.lastIndexOf("(\""); - if (argStart > 0) - className = className.substring(0, argStart); - } - skipList.put(className, ""); - } - } - if (pluginList != null) { - for (int i = 0; i < pluginList.length; i++) { - if (!skipList.containsKey(pluginList[i])) - installUserPlugin(pluginList[i]); - } - } - if ((nPlugins - nPlugins0) <= 1 && IJ.getDir("imagej") != null && IJ.getDir("imagej").startsWith("/private")) { - pluginsMenu.addSeparator(); - addPlugInItem(pluginsMenu, "Why are Plugins Missing?", "ij.plugin.SimpleCommands(\"missing\")", 0, false); - } - installJarPlugins(); - installMacros(); - } - - /** Installs macros and scripts located in the plugins folder. */ - void installMacros() { - if (macroFiles == null) - return; - for (int i = 0; i < macroFiles.size(); i++) { - String name = (String) macroFiles.elementAt(i); - installMacro(name); - } - } - - /** - * Installs a macro or script in the Plugins menu, or submenu, with with - * underscores in the file name replaced by spaces. - */ - void installMacro(String name) { - Menu menu = pluginsMenu; - String dir = null; - int slashIndex = name.indexOf('/'); - if (slashIndex > 0) { - dir = name.substring(0, slashIndex); - name = name.substring(slashIndex + 1, name.length()); - menu = getPluginsSubmenu(dir); - slashIndex = name.indexOf('/'); - if (slashIndex > 0) { - String dir2 = name.substring(0, slashIndex); - name = name.substring(slashIndex + 1, name.length()); - String menuName = "Plugins>" + dir + ">" + dir2; - menu = getMenu(menuName); - dir += File.separator + dir2; - } - } - String command = name.replace('_', ' '); - if (command.endsWith(".js") || command.endsWith(".py")) - command = command.substring(0, command.length() - 3); // remove - // ".js" or - // ".py" - else - command = command.substring(0, command.length() - 4); // remove - // ".txt", - // ".ijm" or - // ".bsh" - command = command.trim(); - if (pluginsTable.get(command) != null) // duplicate command? - command = command + " Macro"; - MenuItem item = new MenuItem(command); - addOrdered(menu, item); - item.addActionListener(ij); - String path = (dir != null ? dir + File.separator : "") + name; - pluginsTable.put(command, "ij.plugin.Macro_Runner(\"" + path + "\")"); - nMacros++; - } - - static int addPluginSeparatorIfNeeded(Menu menu) { - if (menuSeparators == null) - return 0; - Integer i = (Integer) menuSeparators.get(menu); - if (i == null) { - if (menu.getItemCount() > 0) - addSeparator(menu); - i = Integer.valueOf(menu.getItemCount()); - menuSeparators.put(menu, i); - } - return i.intValue(); - } - - /** Inserts 'item' into 'menu' in alphanumeric order. */ - static void addOrdered(Menu menu, MenuItem item) { - String label = item.getLabel(); - int start = addPluginSeparatorIfNeeded(menu); - for (int i = start; i < menu.getItemCount(); i++) { - if (label.compareTo(menu.getItem(i).getLabel()) < 0) { - menu.insert(item, i); - return; - } - } - menu.add(item); - } - - public static String getJarFileForMenuEntry(String menuEntry) { - if (instance == null) - return null; - return (String) instance.menuEntry2jarFile.get(menuEntry); - } - - /** Install plugins located in JAR files. */ - void installJarPlugins() { - if (jarFiles == null) - return; - installingJars = true; - for (int i = 0; i < jarFiles.size(); i++) { - isJarErrorHeading = false; - String jar = (String) jarFiles.elementAt(i); - InputStream is = getConfigurationFile(jar); - if (is == null) - continue; - ArrayList entries = new ArrayList(20); - LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is)); - try { - while (true) { - String s = lnr.readLine(); - if (s == null) - break; - - if (s.length() >= 3 && !s.startsWith("#")) - entries.add(s); - } - } catch (IOException e) { - } finally { - try { - if (lnr != null) - lnr.close(); - } catch (IOException e) { - } - } - - for (int j = 0; j < entries.size(); j++) { - installJarPlugin(jar, (String) entries.get(j)); - /* Changed for Bio7! */ - bio7JarAllCommand.add((String) entries.get(j)); - - } - } - } - - /** Install a plugin located in a JAR file. */ - void installJarPlugin(String jar, String s) { - addSorted = false; - Menu menu; - s = s.trim(); - // System.out.println(s); - if (s.startsWith("Plugins>")) { - // extract name after Plugins> - int firstComma = s.indexOf(','); - // no comma or smaller than word plugins - if (firstComma == -1 || firstComma <= 8) - menu = null; - else { - // Extract name to first comma (before name of plugin) - String name = s.substring(8, firstComma); - menu = getPluginsSubmenu(name); - } - // Plugins>FeatureJ, "FeatureJ Derivatives", featurej.FJ_Derivatives - // give the name of the jar is description is empty or is 'plugins' - } else if (s.startsWith("\"") || s.startsWith("Plugins")) { - String name = getSubmenuName(jar); - if (name != null) - menu = getPluginsSubmenu(name); - else - menu = pluginsMenu; - addSorted = true; - } else { - // Creates a menu from the text! - int firstQuote = s.indexOf('"'); - String name = firstQuote < 0 ? s : s.substring(0, firstQuote).trim(); - int comma = name.indexOf(','); - if (comma >= 0) - name = name.substring(0, comma); - if (name.startsWith("Help>About")) // for backward compatibility - name = "Help>About Plugins"; - menu = getMenu(name); - } - int firstQuote = s.indexOf('"'); - if (firstQuote == -1) - return; - s = s.substring(firstQuote, s.length()); // remove menu - if (menu != null) { - addPluginSeparatorIfNeeded(menu); - // Adds the command to the hashtable and create a menuItem! - addPluginItem(menu, s); - addSorted = false; - } - String menuEntry = s; - if (s.startsWith("\"")) { - int quote = s.indexOf('"', 1); - menuEntry = quote < 0 ? s.substring(1) : s.substring(1, quote); - } else { - int comma = s.indexOf(','); - if (comma > 0) - menuEntry = s.substring(0, comma); - } - if (duplicateCommand) { - if (jarError == null) - jarError = ""; - addJarErrorHeading(jar); - String jar2 = (String) menuEntry2jarFile.get(menuEntry); - if (jar2 != null && jar2.startsWith(pluginsPath)) - jar2 = jar2.substring(pluginsPath.length()); - jarError += " Duplicate command: " + s + (jar2 != null ? " (already in " + jar2 + ")" : "") + "\n"; - } else - menuEntry2jarFile.put(menuEntry, jar); - duplicateCommand = false; - } - - void addJarErrorHeading(String jar) { - if (!isJarErrorHeading) { - if (!jarError.equals("")) - jarError += " \n"; - jarError += "Plugin configuration error: " + jar + "\n"; - isJarErrorHeading = true; - } - } - - /** - * Returns the specified ImageJ menu (e.g., "File>New") or null if it is not - * found. - */ - public static Menu getImageJMenu(String menuPath) { - if (menus==null && !GraphicsEnvironment.isHeadless()) - IJ.init(); - if (menus == null) - return null; - if (menus.get(menuPath) != null) - return getMenu(menuPath, false); - else - return null; - } - - private static Menu getMenu(String menuPath) { - if (GraphicsEnvironment.isHeadless()) - return null; - else - return getMenu(menuPath, false); - } - - /* Creates the menu and adds menus for the jar plugins! */ - private static Menu getMenu(String menuName, boolean readFromProps) { - if (menuName.endsWith(">")) - menuName = menuName.substring(0, menuName.length() - 1); - - Menu result = (Menu) menus.get(menuName); - if (result == null) { - int offset = menuName.lastIndexOf('>'); - if (offset < 0) { - result = new Menu(menuName); - if (mbar == null) - mbar = new MenuBar(); - if (menuName.equals("Help")) - mbar.setHelpMenu(result); - else - mbar.add(result); - if (menuName.equals("Window")) - window = result; - else if (menuName.equals("Plugins")) - pluginsMenu = result; - } else { - // B identifying the last index of > we can get the parent menu. - // Names are store as e.g. 'plugins>submenu' - String parentName = menuName.substring(0, offset); - String menuItemName = menuName.substring(offset + 1); - // Recursive call to get all parent menus! - Menu parentMenu = getMenu(parentName); - - result = new Menu(menuItemName); - addPluginSeparatorIfNeeded(parentMenu); - if (readFromProps) - result = addSubMenu(parentMenu, menuItemName); - else if (parentName.startsWith("Plugins") && menuSeparators != null) - addItemSorted(parentMenu, result, parentName.equals("Plugins") ? userPluginsIndex : 0); - else - parentMenu.add(result); - if (menuName.equals("File>Open Recent")) - openRecentMenu = result; - } - menus.put(menuName, result); - } - return result; - } - - Menu getPluginsSubmenu(String submenuName) { - return getMenu("Plugins>" + submenuName); - } - - String getSubmenuName(String jarPath) { - // IJ.log("getSubmenuName: \n"+jarPath+"\n"+pluginsPath); - if (pluginsPath == null) - return null; - if (jarPath.startsWith(pluginsPath)) - jarPath = jarPath.substring(pluginsPath.length() - 1); - int index = jarPath.lastIndexOf(File.separatorChar); - if (index < 0) - return null; - String name = jarPath.substring(0, index); - index = name.lastIndexOf(File.separatorChar); - if (index < 0) - return null; - name = name.substring(index + 1); - if (name.equals("plugins")) - return null; - return name; - } - - static void addItemSorted(Menu menu, MenuItem item, int startingIndex) { - String itemLabel = item.getLabel(); - int count = menu.getItemCount(); - boolean inserted = false; - for (int i = startingIndex; i < count; i++) { - MenuItem mi = menu.getItem(i); - String label = mi.getLabel(); - // IJ.log(i+ " "+itemLabel+" "+label + - // " "+(itemLabel.compareTo(label))); - if (itemLabel.compareTo(label) < 0) { - menu.insert(item, i); - inserted = true; - break; - } - } - if (!inserted) - menu.add(item); - } - - static void addSeparator(Menu menu) { - menu.addSeparator(); - } - - /** - * Opens the configuration file ("plugins.config") from a JAR file and returns - * it as an InputStream. - */ - InputStream getConfigurationFile(String jar) { - try { - ZipFile jarFile = new ZipFile(jar); - Enumeration entries = jarFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - if (entry.getName().endsWith("plugins.config")) - return jarFile.getInputStream(entry); - } - jarFile.close(); - } catch (Throwable e) { - IJ.log(jar + ": " + e); - } - return autoGenerateConfigFile(jar); - } - - /** Creates a configuration file for JAR/ZIP files that do not have one. */ - InputStream autoGenerateConfigFile(String jar) { - StringBuffer sb = null; - try { - ZipFile jarFile = new ZipFile(jar); - Enumeration entries = jarFile.entries(); - while (entries.hasMoreElements()) { - ZipEntry entry = (ZipEntry) entries.nextElement(); - String name = entry.getName(); - if (name.endsWith(".class") && name.indexOf("_") > 0 && name.indexOf("$") == -1 - && name.indexOf("/_") == -1 && !name.startsWith("_")) { - if (Character.isLowerCase(name.charAt(0)) && name.indexOf("/") != -1) - continue; - if (sb == null) - sb = new StringBuffer(); - String className = name.substring(0, name.length() - 6); - int slashIndex = className.lastIndexOf('/'); - String plugins = "Plugins"; - if (slashIndex >= 0) { - plugins += ">" + className.substring(0, slashIndex).replace('/', '>').replace('_', ' '); - name = className.substring(slashIndex + 1); - } else - name = className; - name = name.replace('_', ' '); - className = className.replace('/', '.'); - sb.append(plugins + ", \"" + name + "\", " + className + "\n"); - } - } - jarFile.close(); - } catch (Throwable e) { - IJ.log(jar + ": " + e); - } - if (sb == null) - return null; - else - return new ByteArrayInputStream(sb.toString().getBytes()); - } - - /** Returns a list of the plugins with directory names removed. */ - String[] getStrippedPlugins(String[] plugins) { - String[] plugins2 = new String[plugins.length]; - int slashPos; - for (int i = 0; i < plugins2.length; i++) { - plugins2[i] = plugins[i]; - slashPos = plugins2[i].lastIndexOf('/'); - if (slashPos >= 0) - plugins2[i] = plugins[i].substring(slashPos + 1, plugins2[i].length()); - } - return plugins2; - } - - void setupPluginsAndMacrosPaths() { - /* - * ImageJPath = pluginsPath = macrosPath = null; String currentDir = - * Prefs.getHomeDir(); // "user.dir" if (currentDir==null) return; if - * (currentDir.endsWith("plugins")) ImageJPath = pluginsPath = - * currentDir+File.separator; else { String pluginsDir = - * System.getProperty("plugins.dir"); if (pluginsDir!=null) { if - * (pluginsDir.endsWith("/")||pluginsDir.endsWith("\\")) pluginsDir = - * pluginsDir.substring(0, pluginsDir.length()-1); if - * (pluginsDir.endsWith("/plugins")||pluginsDir.endsWith("\\plugins")) - * pluginsDir = pluginsDir.substring(0, pluginsDir.length()-8); } if - * (pluginsDir==null) pluginsDir = currentDir; else if - * (pluginsDir.equals("user.home")) { pluginsDir = - * System.getProperty("user.home"); if (!(new - * File(pluginsDir+File.separator+"plugins")).isDirectory()) pluginsDir = - * pluginsDir + File.separator + "ImageJ"; // needed to run plugins when ImageJ - * launched using Java WebStart if (applet==null) - * System.setSecurityManager(null); jnlp = true; } pluginsPath = - * pluginsDir+File.separator+"plugins"+File.separator; macrosPath = - * pluginsDir+File.separator+"macros"+File.separator; ImageJPath = - * pluginsDir+File.separator; } - */ - - /* Changed for Bio7! */ - - pluginsPath = macrosPath = null; - IPreferenceStore store = Activator.getDefault().getPreferenceStore(); - /* We need an extra seperator here else the plugins are not found! */ - pluginsPath = store.getString("PLUGINS_PATH") + File.separator; - macrosPath = store.getString("MACROS_PATH") + File.separator; - /* Get the installation directory of the ImageJ plugin! */ - String currentDir = Util.getImageJPath(); - ImageJPath = Util.getImageJPath() + File.separator; - - File f = pluginsPath != null ? new File(pluginsPath) : null; - if (f == null || !f.isDirectory()) { - ImageJPath = currentDir + File.separator; - pluginsPath = ImageJPath + "plugins" + File.separator; - f = new File(pluginsPath); - if (!f.isDirectory()) { - String altPluginsPath = System.getProperty("plugins.dir"); - if (altPluginsPath != null) { - f = new File(altPluginsPath); - if (!f.isDirectory()) - altPluginsPath = null; - else { - ImageJPath = f.getParent() + File.separator; - pluginsPath = ImageJPath + f.getName() + File.separator; - macrosPath = ImageJPath + "macros" + File.separator; - } - } - if (altPluginsPath == null) - ImageJPath = pluginsPath = null; - } - } - f = macrosPath != null ? new File(macrosPath) : null; - if (f != null && !f.isDirectory()) { - macrosPath = currentDir + File.separator + "macros" + File.separator; - f = new File(macrosPath); - if (!f.isDirectory()) - macrosPath = null; - } - if (IJ.debugMode) { - IJ.log("Menus.setupPluginsAndMacrosPaths"); - IJ.log(" user.dir: " + currentDir); - IJ.log(" plugins.dir: " + System.getProperty("plugins.dir")); - IJ.log(" ImageJPath: " + ImageJPath); - IJ.log(" pluginsPath: " + pluginsPath); - } - } - - /** Returns a list of the plugins in the plugins menu. */ - public static synchronized String[] getPlugins() { - File f = pluginsPath != null ? new File(pluginsPath) : null; - if (f == null || (f != null && !f.isDirectory())) - return null; - String[] list = f.list(); - if (list == null) - return null; - Vector v = new Vector(); - jarFiles = null; - macroFiles = null; - for (int i = 0; i < list.length; i++) { - String name = list[i]; - boolean isClassFile = name.endsWith(".class"); - boolean hasUnderscore = name.indexOf('_') >= 0; - if (hasUnderscore && isClassFile && name.indexOf('$') < 0) { - name = name.substring(0, name.length() - 6); // remove ".class" - v.addElement(name); - } else if (hasUnderscore && (name.endsWith(".jar") || name.endsWith(".zip"))) { - if (jarFiles == null) - jarFiles = new Vector(); - jarFiles.addElement(pluginsPath + name); - } else if (validMacroName(name, hasUnderscore)) { - if (macroFiles == null) - macroFiles = new Vector(); - macroFiles.addElement(name); - } else { - if (!isClassFile) - checkSubdirectory(pluginsPath, name, v); - } - } - list = new String[v.size()]; - v.copyInto((String[]) list); - StringSorter.sort(list); - return list; - } - - /** - * Looks for plugins and jar files in a subdirectory of the plugins directory. - */ - private static void checkSubdirectory(String path, String dir, Vector v) { - if (dir.endsWith(".java")) - return; - File f = new File(path, dir); - if (!f.isDirectory()) - return; - String[] list = f.list(); - if (list == null) - return; - dir += "/"; - int classCount = 0, otherCount = 0; - String className = null; - for (int i = 0; i < list.length; i++) { - String name = list[i]; - boolean hasUnderscore = name.indexOf('_') >= 0; - if (hasUnderscore && name.endsWith(".class") && name.indexOf('$') < 0) { - name = name.substring(0, name.length() - 6); // remove ".class" - v.addElement(dir + name); - classCount++; - className = name; - } else if (hasUnderscore && (name.endsWith(".jar") || name.endsWith(".zip"))) { - if (jarFiles == null) - jarFiles = new Vector(); - jarFiles.addElement(f.getPath() + File.separator + name); - otherCount++; - } else if (validMacroName(name, hasUnderscore)) { - if (macroFiles == null) - macroFiles = new Vector(); - macroFiles.addElement(dir + name); - otherCount++; - } else { - File f2 = new File(f, name); - if (f2.isDirectory()) - installSubdirectorMacros(f2, dir + name); - } - } - if (Prefs.moveToMisc && classCount == 1 && otherCount == 0 && dir.indexOf("_") == -1) - v.setElementAt("Miscellaneous/" + className, v.size() - 1); - } - - /** Installs macros and scripts located in subdirectories. */ - private static void installSubdirectorMacros(File f2, String dir) { - if (dir.endsWith("Launchers")) - return; - String[] list = f2.list(); - if (list == null) - return; - for (int i = 0; i < list.length; i++) { - String name = list[i]; - boolean hasUnderscore = name.indexOf('_') >= 0; - if (validMacroName(name, hasUnderscore)) { - if (macroFiles == null) - macroFiles = new Vector(); - macroFiles.addElement(dir + "/" + name); - } - } - } - - private static boolean validMacroName(String name, boolean hasUnderscore) { - return (hasUnderscore && name.endsWith(".txt")) || name.endsWith(".ijm") || name.endsWith(".js") - || name.endsWith(".bsh") || name.endsWith(".py"); - } - - /** - * Installs a plugin in the Plugins menu using the class name, with underscores - * replaced by spaces, as the command. - */ - void installUserPlugin(String className) { - installUserPlugin(className, false); - } - - public void installUserPlugin(String className, boolean force) { - int slashIndex = className.indexOf('/'); - String menuName = slashIndex < 0 ? "Plugins" - : "Plugins>" + className.substring(0, slashIndex).replace('/', '>'); - Menu menu = getMenu(menuName); - String command = className; - if (slashIndex > 0) { - command = className.substring(slashIndex + 1); - } - command = command.replace('_', ' '); - //command = command.trim(); - boolean itemExists = (pluginsTable.get(command) != null); - if (force && itemExists) - return; - - if (!force && itemExists) // duplicate command? - command = command + " Plugin"; - MenuItem item = new MenuItem(command); - if (force) - addItemSorted(menu, item, 0); - else - addOrdered(menu, item); - item.addActionListener(ij); - pluginsTable.put(command, className.replace('/', '.')); - nPlugins++; - } - - void installPopupMenu(ImageJ ij) { - String s; - int count = 0; - MenuItem mi; - popup = new PopupMenu(""); - if (fontSize != 0 || scale > 1.0) - popup.setFont(getFont()); - - while (true) { - count++; - s = Prefs.getString("popup" + (count / 10) % 10 + count % 10); - if (s == null) - break; - if (s.equals("-")) - popup.addSeparator(); - else if (!s.equals("")) { - mi = new MenuItem(s); - mi.addActionListener(ij); - popup.add(mi); - } - } - } - - public static MenuBar getMenuBar() { - return mbar; - } - - public static Menu getMacrosMenu() { - return macrosMenu; - } - - public static Menu getOpenRecentMenu() { - return openRecentMenu; - } - - public int getMacroCount() { - return nMacros; - } - - public int getPluginCount() { - return nPlugins; - } - - static final int RGB_STACK = 10, HSB_STACK = 11, LAB_STACK = 12, HSB32_STACK = 13; - - /** Updates the Image/Type and Window menus. */ - public static void updateMenus() { - if (ij == null) - return; - gray8Item.setState(false); - gray16Item.setState(false); - gray32Item.setState(false); - color256Item.setState(false); - colorRGBItem.setState(false); - RGBStackItem.setState(false); - HSBStackItem.setState(false); - LabStackItem.setState(false); - HSB32Item.setState(false); - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp == null) - return; - int type = imp.getType(); - if (imp.getStackSize() > 1) { - ImageStack stack = imp.getStack(); - if (stack.isRGB()) - type = RGB_STACK; - else if (stack.isHSB()) - type = HSB_STACK; - else if (stack.isLab()) - type = LAB_STACK; - else if (stack.isHSB32()) - type = HSB32_STACK; - } - - switch (type) { - case ImagePlus.GRAY8: - gray8Item.setState(true); - break; - case ImagePlus.GRAY16: - gray16Item.setState(true); - break; - case ImagePlus.GRAY32: - gray32Item.setState(true); - break; - case ImagePlus.COLOR_256: - color256Item.setState(true); - break; - case ImagePlus.COLOR_RGB: - colorRGBItem.setState(true); - break; - case RGB_STACK: - RGBStackItem.setState(true); - break; - case HSB_STACK: - HSBStackItem.setState(true); - break; - case LAB_STACK: - LabStackItem.setState(true); - break; - case HSB32_STACK: - HSB32Item.setState(true); - break; - - } - - // update Window menu - int nItems = window.getItemCount(); - int start = WINDOW_MENU_ITEMS + windowMenuItems2; - int index = start + WindowManager.getCurrentIndex(); - try { // workaround for Linux/Java 5.0/bug - for (int i = start; i < nItems; i++) { - CheckboxMenuItem item = (CheckboxMenuItem) window.getItem(i); - item.setState(i == index); - } - } catch (Exception e) { - } - } - - static boolean isColorLut(ImagePlus imp) { - ImageProcessor ip = imp.getProcessor(); - IndexColorModel cm = (IndexColorModel) ip.getColorModel(); - if (cm == null) - return false; - int mapSize = cm.getMapSize(); - byte[] reds = new byte[mapSize]; - byte[] greens = new byte[mapSize]; - byte[] blues = new byte[mapSize]; - cm.getReds(reds); - cm.getGreens(greens); - cm.getBlues(blues); - boolean isColor = false; - for (int i = 0; i < mapSize; i++) { - if ((reds[i] != greens[i]) || (greens[i] != blues[i])) { - isColor = true; - break; - } - } - return isColor; - } - - /** Use Prefs.getImageJDir() to get the path to the ImageJ directory. */ - static String getImageJPath() { - return ImageJPath; - } - - /** - * Returns the path to the user plugins directory or null if the plugins - * directory was not found. - */ - public static String getPlugInsPath() { - return pluginsPath; - } - - /** - * Returns the path to the macros directory or null if the macros directory was - * not found. - */ - public static String getMacrosPath() { - return macrosPath; - } - - /** Returns the hashtable that associates commands with plugins. */ - public static Hashtable getCommands() { - if (pluginsTable==null && !GraphicsEnvironment.isHeadless()) - IJ.init(); - return pluginsTable; - } - - /** - * Returns the hashtable that associates shortcuts with commands. The keys in - * the hashtable are Integer keycodes, or keycode+200 for uppercase. - */ - public static Hashtable getShortcuts() { - return shortcuts; - } - - /** - * Returns the hashtable that associates keyboard shortcuts with macros. The - * keys in the hashtable are Integer keycodes, or keycode+200 for uppercase. - */ - public static Hashtable getMacroShortcuts() { - if (macroShortcuts == null) - macroShortcuts = new Hashtable(); - return macroShortcuts; - } - - /** Inserts one item (a non-image window) into the Window menu. */ - static synchronized void insertWindowMenuItem(Window win) { - if (ij == null || win == null) - return; - String title = win instanceof Frame ? ((Frame) win).getTitle() : ((Dialog) win).getTitle(); - CheckboxMenuItem item = new CheckboxMenuItem(title); - item.addItemListener(ij); - int index = WINDOW_MENU_ITEMS + windowMenuItems2; - if (windowMenuItems2 >= 2) - index--; - window.insert(item, index); - windowMenuItems2++; - if (windowMenuItems2 == 1) { - window.insertSeparator(WINDOW_MENU_ITEMS + windowMenuItems2); - windowMenuItems2++; - } - } - - /** Adds one image to the end of the Window menu. */ - static synchronized void addWindowMenuItem(ImagePlus imp) { - if (ij==null) - return; - String name = imp.getTitle(); - String size = ImageWindow.getImageSize(imp); - CheckboxMenuItem item = new CheckboxMenuItem(name + " " + size); - item.setActionCommand("" + imp.getID()); - window.add(item); - item.addItemListener(ij); - } - - /** Removes the specified item from the Window menu. */ - static synchronized void removeWindowMenuItem(int index) { - // IJ.log("removeWindowMenuItem: "+index+" "+windowMenuItems2+" - // "+window.getItemCount()); - if (ij == null) - return; - try { - if (index >= 0 && index < window.getItemCount()) { - window.remove(WINDOW_MENU_ITEMS + index); - if (index < windowMenuItems2) { - windowMenuItems2--; - if (windowMenuItems2 == 1) { - window.remove(WINDOW_MENU_ITEMS); - windowMenuItems2 = 0; - } - } - } - } catch (Exception e) { - } - } - - /** Changes the name of an item in the Window menu. */ - public static synchronized void updateWindowMenuItem(String oldLabel, String newLabel) { - updateWindowMenuItem(null, oldLabel, newLabel); - } - - /** Changes the name of an item in the Window menu. */ - public static synchronized void updateWindowMenuItem(ImagePlus imp, String oldLabel, String newLabel) { - if (oldLabel == null || newLabel == null) - return; - int first = WINDOW_MENU_ITEMS; - int count = window.getItemCount(); - try { // workaround for Linux/Java 5.0/bug - for (int i = first; i < count; i++) { - MenuItem item = window.getItem(i); - String label = item.getLabel(); - String cmd = item.getActionCommand(); - if (imp != null) { // remove size (e.g. " 24MB") - int index = label.lastIndexOf(" "); - if (index > -1) - label = label.substring(0, index); - } - if (item!=null && label.equals(oldLabel) && (imp==null||(""+imp.getID()).equals(cmd))) { - String size = ""; - if (imp != null) - size = " " + ImageWindow.getImageSize(imp); - item.setLabel(newLabel + size); - return; - } - } - } catch (Exception e) { - } - } - - /** Adds a file path to the beginning of the File/Open Recent submenu. */ - public static synchronized void addOpenRecentItem(String path) { - if (ij == null) - return; - int count = openRecentMenu.getItemCount(); - for (int i = 0; i < count;) { - if (openRecentMenu.getItem(i).getLabel().equals(path)) { - openRecentMenu.remove(i); - count--; - } else - i++; - } - if (count == MAX_OPEN_RECENT_ITEMS) - openRecentMenu.remove(MAX_OPEN_RECENT_ITEMS - 1); - MenuItem item = new MenuItem(path); - openRecentMenu.insert(item, 0); - item.addActionListener(ij); - } - - public static PopupMenu getPopupMenu() { - return popup; - } - - public static Menu getSaveAsMenu() { - return saveAsMenu; - } - - /** - * Adds a plugin based command to the end of a specified menu. - * - * @param plugin the plugin (e.g. "Inverter_", "Inverter_("arg")") - * @param menuCode PLUGINS_MENU, IMPORT_MENU, SAVE_AS_MENU or HOT_KEYS - * @param command the menu item label (set to "" to uninstall) - * @param shortcut the keyboard shortcut (e.g. "y", "Y", "F1") - * @param ij ImageJ (the action listener) - * - * @return returns an error code(NORMAL_RETURN,COMMAND_IN_USE_ERROR, etc.) - */ - public static int installPlugin(String plugin, char menuCode, String command, String shortcut, ImageJ ij) { - if (command.equals("")) // uninstall - return NORMAL_RETURN; - - if (commandInUse(command)) - return COMMAND_IN_USE; - if (!validShortcut(shortcut)) - return INVALID_SHORTCUT; - if (shortcutInUse(shortcut)) - return SHORTCUT_IN_USE; - - Menu menu; - switch (menuCode) { - case PLUGINS_MENU: - menu = pluginsMenu; - break; - case IMPORT_MENU: - menu = getMenu("File>Import"); - break; - case SAVE_AS_MENU: - menu = getMenu("File>Save As"); - break; - case SHORTCUTS_MENU: - menu = shortcutsMenu; - break; - case ABOUT_MENU: - menu = getMenu("Help>About Plugins"); - break; - case FILTERS_MENU: - menu = getMenu("Process>Filters"); - break; - case TOOLS_MENU: - menu = getMenu("Analyze>Tools"); - break; - case UTILITIES_MENU: - menu = utilitiesMenu; - break; - default: - return 0; - } - int code = convertShortcutToCode(shortcut); - MenuItem item; - boolean functionKey = code >= KeyEvent.VK_F1 && code <= KeyEvent.VK_F12; - if (code == 0) - item = new MenuItem(command); - else if (functionKey) { - command += " [F" + (code - KeyEvent.VK_F1 + 1) + "]"; - shortcuts.put(Integer.valueOf(code), command); - item = new MenuItem(command); - } else { - shortcuts.put(Integer.valueOf(code), command); - int keyCode = code; - boolean shift = false; - if (keyCode >= 265 && keyCode <= 290) { - keyCode -= 200; - shift = true; - } - item = new MenuItem(command, new MenuShortcut(keyCode, shift)); - } - menu.add(item); - item.addActionListener(ij); - pluginsTable.put(command, plugin); - shortcut = code > 0 && !functionKey ? "[" + shortcut + "]" : ""; - pluginsPrefs.addElement(menuCode + ",\"" + command + shortcut + "\"," + plugin); - return NORMAL_RETURN; - } - - /** Deletes a command installed by Plugins/Shortcuts/Add Shortcut. */ - public static int uninstallPlugin(String command) { - boolean found = false; - for (Enumeration en = pluginsPrefs.elements(); en.hasMoreElements();) { - String cmd = (String) en.nextElement(); - if (cmd.contains(command)) { - boolean ok = pluginsPrefs.removeElement((Object) cmd); - found = true; - break; - } - } - if (found) - return NORMAL_RETURN; - else - return COMMAND_NOT_FOUND; - - } - - public static boolean commandInUse(String command) { - if (pluginsTable.get(command) != null) - return true; - else - return false; - } - - public static int convertShortcutToCode(String shortcut) { - int code = 0; - int len = shortcut.length(); - if (len==2 && shortcut.charAt(0)=='A') { //arrow key shortcuts - if (shortcut.charAt(1)=='L') code=37; - if (shortcut.charAt(1)=='U') code=38; - if (shortcut.charAt(1)=='R') code=39; - if (shortcut.charAt(1)=='D') code=40; - return code; - } - if (len == 2 && shortcut.charAt(0) == 'F') { - code = KeyEvent.VK_F1 + (int) shortcut.charAt(1) - 49; - if (code >= KeyEvent.VK_F1 && code <= KeyEvent.VK_F9) - return code; - else - return 0; - } - if (len == 3 && shortcut.charAt(0) == 'F') { - code = KeyEvent.VK_F10 + (int) shortcut.charAt(2) - 48; - if (code >= KeyEvent.VK_F10 && code <= KeyEvent.VK_F12) - return code; - else - return 0; - } - if (len == 2 && shortcut.charAt(0) == 'N') { // numeric keypad - code = KeyEvent.VK_NUMPAD0 + (int) shortcut.charAt(1) - 48; - if (code >= KeyEvent.VK_NUMPAD0 && code <= KeyEvent.VK_NUMPAD9) - return code; - switch (shortcut.charAt(1)) { - case '/': - return KeyEvent.VK_DIVIDE; - case '*': - return KeyEvent.VK_MULTIPLY; - case '-': - return KeyEvent.VK_SUBTRACT; - case '+': - return KeyEvent.VK_ADD; - case '.': - return KeyEvent.VK_DECIMAL; - default: - return 0; - } - } - if (len != 1) - return 0; - int c = (int) shortcut.charAt(0); - if (c >= 65 && c <= 90) // A-Z - code = KeyEvent.VK_A + c - 65 + 200; - else if (c >= 97 && c <= 122) // a-z - code = KeyEvent.VK_A + c - 97; - else if (c >= 48 && c <= 57) // 0-9 - code = KeyEvent.VK_0 + c - 48; - return code; - } - - void installStartupMacroSet() { - if (macrosPath == null) { - MacroInstaller.installFromJar("/macros/StartupMacros.txt"); - return; - } - String path = macrosPath + "StartupMacros.txt"; - File f = new File(path); - if (!f.exists()) { - path = macrosPath + "StartupMacros.ijm"; - f = new File(path); - if (!f.exists()) { - (new MacroInstaller()).installFromIJJar("/macros/StartupMacros.txt"); - return; - } - } else { - if ("StartupMacros.fiji.ijm".equals(f.getName())) - path = f.getPath(); - } - String libraryPath = macrosPath + "Library.txt"; - f = new File(libraryPath); - boolean isLibrary = f.exists(); - try { - MacroInstaller mi = new MacroInstaller(); - if (isLibrary) - mi.installLibrary(libraryPath); - mi.installStartupMacros(path); - nMacros += mi.getMacroCount(); - } catch (Exception e) { - } - } - - static boolean validShortcut(String shortcut) { - int len = shortcut.length(); - if (shortcut.equals("")) - return true; - else if (len == 1) - return true; - else if (shortcut.startsWith("F") && (len == 2 || len == 3)) - return true; - else - return false; - } - - /** Returns 'true' if this keyboard shortcut is in use. */ - public static boolean shortcutInUse(String shortcut) { - int code = convertShortcutToCode(shortcut); - if (shortcuts.get(Integer.valueOf(code)) != null) - return true; - else - return false; - } - - /** - * Set the size (in points) used for the fonts in ImageJ menus. Set the size to - * 0 to use the Java default size. - */ - public static void setFontSize(int size) { - if (size < 9 && size != 0) - size = 9; - if (size > 24) - size = 24; - fontSize = size; - } - - /** - * Returns the size (in points) used for the fonts in ImageJ menus. Returns 0 if - * the default font size is being used or if this is a Macintosh. - */ - public static int getFontSize() { - return fontSize; - } - - public static Font getFont() { - return getFont(true); - } - - public static Font getFont(boolean checkSize) { - int size = fontSize==0?13:fontSize; - size = (int)Math.round(size*scale); - int size0 = size; - if (checkSize && IJ.isWindows() && scale>1.0 && size>17) - size = 17; // Java resets size to 12 if you try to set it to 18 or greater - Font menuFont = new Font("SanSerif", Font.PLAIN, size); - //System.out.println("getFont: "+checkSize+" "+scale+" "+size0+" "+size+" "+menuFont); - return menuFont; - } - - /** Called once when ImageJ quits. */ - public static void savePreferences(Properties prefs) { - if (pluginsPrefs==null) - return; - int index = 0; - for (Enumeration en = pluginsPrefs.elements(); en.hasMoreElements();) { - String key = "plugin" + (index / 10) % 10 + index % 10; - String value = (String) en.nextElement(); - prefs.put(key, value); - index++; - } - int n = openRecentMenu.getItemCount(); - for (int i = 0; i < n; i++) { - String key = "" + i; - if (key.length() == 1) - key = "0" + key; - key = "recent" + key; - prefs.put(key, openRecentMenu.getItem(i).getLabel()); - } - prefs.put(Prefs.MENU_SIZE, Integer.toString(fontSize)); - } - - public static void updateImageJMenus() { - jarFiles = macroFiles = null; - Menus m = new Menus(IJ.getInstance(), IJ.getApplet()); - String err = m.addMenuBar(); - if (err != null) - IJ.error(err); - m.installStartupMacroSet(); - IJ.resetClassLoader(); - //IJ.runPlugIn("ij.plugin.ClassChecker", ""); - IJ.showStatus("Menus updated: " + m.nPlugins + " commands, " + m.nMacros + " macros"); - /*Changed for Bio7!*/ - updateBio7ImageJMenu(); - - } - - public static void updateBio7ImageJMenu() { - Display dis = Util.getDisplay(); - dis.asyncExec(new Runnable() { - public void run() { - CanvasView canvasView = CanvasView.getCanvas_view(); - IViewSite viewSite = canvasView.getViewSite(); - IActionBars actionBars = viewSite.getActionBars(); - IContributionItem[] it = actionBars.getToolBarManager().getItems(); - for (int j = 0; j < it.length; j++) { - //String name = Menus.getMenuBar().getMenu(j).getName(); - String name = it[j].getId(); - if (name.equals("File") == false && name.equals("Edit") == false && name.equals("Image") == false - && name.equals("Process") == false && name.equals("Analyze") == false - && name.equals("Plugins") == false && name.equals("Window") == false - && name.equals("Help") == false) { - - actionBars.getToolBarManager().remove(name); - actionBars.getToolBarManager().update(true); - } - } - int count = Menus.getMenuBar().getMenuCount(); - for (int i = 0; i < count; i++) { - String name = Menus.getMenuBar().getMenu(i).getLabel(); - if (name.equals("File") == false && name.equals("Edit") == false && name.equals("Image") == false - && name.equals("Process") == false && name.equals("Analyze") == false - && name.equals("Plugins") == false && name.equals("Window") == false - && name.equals("Help") == false) { - if (name.isEmpty() == false) { - actionBars.getToolBarManager().add(new ImageJExtensionAction(name)); - actionBars.getToolBarManager().update(true); - } - } - } - } - }); - } - - public static void updateFont() { - scale = (int) Math.round(Prefs.getGuiScale()); - Font font = getFont(); - mbar.setFont(font); - if (ij != null) - ij.setMenuBar(mbar); - popup.setFont(font); - } - - /** Adds a command to the ImageJ menu bar. */ - public static void add(String menuPath, String plugin) { - if (pluginsTable == null) - return; - int index = menuPath.lastIndexOf(">"); - if (index == -1 || index == menuPath.length() - 1) - return; - String label = menuPath.substring(index + 1, menuPath.length()); - menuPath = menuPath.substring(0, index); - pluginsTable.put(label, plugin); - addItem(getMenu(menuPath), label, 0, false); - } - -} diff --git a/com.eco.bio7.image/src/ij/OtherInstance.java b/com.eco.bio7.image/src/ij/OtherInstance.java deleted file mode 100644 index a440dab69..000000000 --- a/com.eco.bio7.image/src/ij/OtherInstance.java +++ /dev/null @@ -1,243 +0,0 @@ -package ij; - -import ij.IJ; -import ij.ImageJ; -import ij.Prefs; - -import ij.io.OpenDialog; -import ij.io.Opener; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import java.lang.reflect.Method; - -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.rmi.server.UnicastRemoteObject; - -import java.util.Properties; - -/* - * This class tries to contact another instance on the same machine, started - * by the current user. If such an instance is found, the arguments are - * sent to that instance. If no such an instance is found, listen for clients. - * - * No need for extra security, as the stub (and its serialization) contain - * a hard-to-guess hash code. - * - * @author Johannes Schindelin - */ -public class OtherInstance { - private static final String DELIMETER = "~!~"; // Separates macro name and argument - - interface ImageJInstance extends Remote { - void sendArgument(String arg) throws RemoteException; - } - - static class Implementation implements ImageJInstance { - int counter = 0; - - public void sendArgument(String cmd) { - if (IJ.debugMode) IJ.log("SocketServer.sendArgument: \""+ cmd+"\""); - if (cmd.startsWith("open ")) - (new Opener()).openAndAddToRecent(cmd.substring(5)); - else if (cmd.startsWith("macro ")) { - String name = cmd.substring(6); - String name2 = name; - String arg = null; - int index = name2.indexOf(DELIMETER); - if (index!=-1) { - name = name2.substring(0, index); - arg = name2.substring(index+DELIMETER.length(), name2.length()); - } - IJ.runMacroFile(name, arg); - } else if (cmd.startsWith("run ")) - IJ.run(cmd.substring(4)); - else if (cmd.startsWith("eval ")) { - String rtn = IJ.runMacro(cmd.substring(5)); - if (rtn!=null) - System.out.print(rtn); - } else if (cmd.startsWith("user.dir ")) { - OpenDialog.setDefaultDirectory(cmd.substring(9)); - System.setProperty("user.dir", cmd.substring(9)); - } - } - } - - public static String getStubPath() { - String display = System.getenv("DISPLAY"); - if (display!=null) { - display = display.replace(':', '_'); - display = display.replace('/', '_'); - } - String tmpDir = System.getProperty("java.io.tmpdir"); - tmpDir = IJ.addSeparator(tmpDir); - return tmpDir + "ImageJ-" - + System.getProperty("user.name") + "-" - + (display == null ? "" : display + "-") - + ImageJ.getPort() + ".stub"; - } - - public static void makeFilePrivate(String path) { - try { - File file = new File(path); - file.deleteOnExit(); - - // File.setReadable() is Java 6 - Class[] types = { boolean.class, boolean.class }; - Method m = File.class.getMethod("setReadable", types); - Object[] arguments = { Boolean.FALSE, Boolean.FALSE }; - m.invoke(file, arguments); - arguments = new Object[] { Boolean.TRUE, Boolean.TRUE }; - m.invoke(file, arguments); - types = new Class[] { boolean.class }; - m = File.class.getMethod("setWritable", types); - arguments = new Object[] { Boolean.FALSE }; - m.invoke(file, arguments); - return; - } catch (Exception e) { - if (IJ.debugMode) - System.err.println("Java < 6 detected," - + " trying chmod 0600 " + path); - } - if (!IJ.isWindows()) { - try { - String[] command = { - "chmod", "0600", path - }; - Runtime.getRuntime().exec(command); - } catch (Exception e) { - if (IJ.debugMode) - System.err.println("Even chmod failed."); - } - } - } - - public static boolean sendArguments(String[] args) { - if (!isRMIEnabled()) - return false; - String file = getStubPath(); - try { - FileInputStream in = new FileInputStream(file); - ImageJInstance instance = (ImageJInstance) new ObjectInputStream(in).readObject(); - in.close(); - if (instance==null) - return false; - instance.sendArgument("user.dir "+System.getProperty("user.dir")); - int macros = 0; - for (int i=0; itext in the preferences file using - * the keyword key. The string can be retrieved using the - * appropriate get() method. - * - * @see #get(String,String) - */ - public static void set(String key, String text) { - if (key.indexOf('.') < 1) - throw new IllegalArgumentException("Key must have a prefix"); - if (text == null) - ijPrefs.remove(KEY_PREFIX + key); - else - ijPrefs.put(KEY_PREFIX + key, text); - } - - /** - * Saves the value of the integer value in the preferences file - * using the keyword key. The value can be retrieved using the - * appropriate get() method. - * - * @see #get(String,double) - */ - public static void set(String key, int value) { - set(key, Integer.toString(value)); - } - - /** - * Saves the value of the double value in the preferences file - * using the keyword key. The value can be retrieved using the - * appropriate get() method. - * - * @see #get(String,double) - */ - public static void set(String key, double value) { - set(key, "" + value); - } - - /** - * Saves the value of the boolean value in the preferences file - * using the keyword key. The value can be retrieved using the - * appropriate get() method. - * - * @see #get(String,boolean) - */ - public static void set(String key, boolean value) { - set(key, "" + value); - } - - /** - * Uses the keyword key to retrieve a string from the preferences - * file. Returns defaultValue if the key is not found. - */ - public static String get(String key, String defaultValue) { - String value = ijPrefs.getProperty(KEY_PREFIX + key); - if (value == null) - return defaultValue; - else - return value; - } - - /** - * Uses the keyword key to retrieve a number from the preferences - * file. Returns defaultValue if the key is not found. - */ - public static double get(String key, double defaultValue) { - String s = ijPrefs.getProperty(KEY_PREFIX + key); - Double d = null; - if (s != null) { - try { - d = Double.valueOf(s); - } catch (NumberFormatException e) { - d = null; - } - if (d != null) - return (d.doubleValue()); - } - return defaultValue; - } - - /** - * Uses the keyword key to retrieve a boolean from the preferences - * file. Returns defaultValue if the key is not found. - */ - public static boolean get(String key, boolean defaultValue) { - String value = ijPrefs.getProperty(KEY_PREFIX + key); - if (value == null) - return defaultValue; - else - return value.equals("true"); - } - - /** - * Finds and loads the configuration file ("IJ_Props.txt") and the preferences - * file ("IJ_Prefs.txt"). - * - * @return an error message if "IJ_Props.txt" not found. - */ - public static String load(Object ij, Applet applet) { - /* Changed for Bio7! */ - - String path = Util.getImageJPath(); - - InputStream f = ij.getClass().getResourceAsStream(path + PROPS_NAME); - if (applet != null) - return loadAppletProps(f, applet); - if (ImageJDir == null) - /* /*Changed for Bio7! */ - ImageJDir = path;// System.getProperty("user.dir"); - /* - * String userHome = path;// System.getProperty("user.home"); if - * (IJ.isWindows()) { prefsDir = homeDir; // ImageJ folder on Windows if - * (prefsDir.endsWith("Desktop")) prefsDir = userHome; } else { prefsDir = - * homeDir; // prefsDir = userHome; // Mac Preferences folder or Unix home dir - * if (IJ.isMacOSX()) // prefsDir += "/Library/Preferences"; prefsDir = homeDir; - * // else // prefsDir += File.separator + ".imagej"; } - */ - if (f == null) { - try { - f = new FileInputStream(ImageJDir + "/" + PROPS_NAME); - propertiesPath = ImageJDir + "/" + PROPS_NAME; - } catch (FileNotFoundException e) { - f = null; - } - } - if (f == null) - return PROPS_NAME + " not found in ij.jar or in " + ImageJDir; - f = new BufferedInputStream(f); - try { - props.load(f); - f.close(); - } catch (IOException e) { - return ("Error loading " + PROPS_NAME); - } - imagesURL = props.getProperty(IJ.isJava18() ? "images.location" : "images.location2"); - loadPreferences(); - loadOptions(); - guiScale = get(GUI_SCALE, 1.0); - return null; - } - - /* - * static void dumpPrefs(String title) { IJ.log(""); IJ.log(title); static void - * dumpPrefs() { System.out.println(""); Enumeration e = ijPrefs.keys(); while - * (e.hasMoreElements()) { String key = (String) e.nextElement(); - * IJ.log(key+": "+ijPrefs.getProperty(key)); - * System.out.println(key+": "+ijPrefs.getProperty(key)); } } - */ - - static String loadAppletProps(InputStream f, Applet applet) { - if (f == null) - return PROPS_NAME + " not found in ij.jar"; - try { - props.load(f); - f.close(); - } catch (IOException e) { - return ("Error loading " + PROPS_NAME); - } - try { - URL url = new URL(applet.getDocumentBase(), "images/"); - imagesURL = url.toString(); - } catch (Exception e) { - } - return null; - } - - /** - * Returns the URL of the directory that contains the ImageJ sample images. - */ - public static String getImagesURL() { - return imagesURL; - } - - /** Sets the URL of the directory that contains the ImageJ sample images. */ - public static void setImagesURL(String url) { - imagesURL = url; - } - - /** - * Obsolete, replaced by getImageJDir(), which, unlike this method, returns a - * path that ends with File.separator. - */ - public static String getHomeDir() { - return ImageJDir; - } - - /** Returns the path, ending in File.separator, to the ImageJ directory. */ - public static String getImageJDir() { - /* Changed for Bio7! */ - String path = Util.getImageJPath(); - if (path == null) - return ImageJDir + File.separator; - else - return path + File.separator; - } - - public static String getPluginsDirProperty() { - if (pluginsDirProperty==null) { - String ijDir = System.getProperty("plugins.dir"); - if (ijDir!=null) { - if (ijDir.endsWith("/")||ijDir.endsWith("\\")) - ijDir = ijDir.substring(0, ijDir.length()-1); - if (ijDir.endsWith("/plugins")||ijDir.endsWith("\\plugins")) - ijDir = ijDir.substring(0, ijDir.length()-8); - pluginsDirProperty = ijDir; - } else - pluginsDirProperty = ""; - } - return pluginsDirProperty.length()>0?pluginsDirProperty:null; - } - - /** - * Returns the path to the directory where the preferences file (IJPrefs.txt) is - * saved. - */ - public static String getPrefsDir() { - /* Changed for Bio7! */ - String path = Util.getImageJPath(); - if (prefsDir == null) { - - /* - * if (IJ.isMacOSX()) dir += "/Library/Preferences"; else dir += - * File.separator+".imagej"; - */ - prefsDir = path; - preferencesPath = path + "/" + PREFS_NAME; - } - return prefsDir; - } - - /** Sets the path to the ImageJ directory. */ - static void setHomeDir(String path) { - if (path.endsWith(File.separator) || path.endsWith("/")) - path = path.substring(0, path.length() - 1); - ImageJDir = path; - } - - /** Returns the default directory, if any, or null. */ - public static String getDefaultDirectory() { - if (commandLineMacro) - return null; - else - return getString(DIR_IMAGE); - } - - /** Returns the file.separator system property. */ - public static String getFileSeparator() { - return separator; - } - - /** Opens the ImageJ preferences file ("IJ_Prefs.txt") file. */ - static void loadPreferences() { - String path = getPrefsDir() + separator + PREFS_NAME; - boolean ok = loadPrefs(path); - if (!ok) { // not found - if (IJ.isWindows()) - path = ImageJDir + separator + PREFS_NAME; - else - path = System.getProperty("user.home") + separator + PREFS_NAME; // User's - // home - // dir - ok = loadPrefs(path); - if (ok) - new File(path).delete(); - } - - } - - static boolean loadPrefs(String path) { - try { - InputStream is = new BufferedInputStream(new FileInputStream(path)); - ijPrefs.load(is); - is.close(); - return true; - } catch (Exception e) { - return false; - } - } - - /** Saves user preferences in the IJ_Prefs.txt properties file. */ - public static void savePreferences() { - String path = null; - commandLineMacro = false; - try { - Properties prefs = new Properties(); - String dir = OpenDialog.getDefaultDirectory(); - if (dir != null) - prefs.put(DIR_IMAGE, dir); - prefs.put(ROICOLOR, Tools.c2hex(Roi.getColor())); - prefs.put(SHOW_ALL_COLOR, Tools.c2hex(ImageCanvas.getShowAllColor())); - prefs.put(FCOLOR, Tools.c2hex(Toolbar.getForegroundColor())); - prefs.put(BCOLOR, Tools.c2hex(Toolbar.getBackgroundColor())); - prefs.put(JPEG, Integer.toString(FileSaver.getJpegQuality())); - prefs.put(FPS, Double.toString(Animator.getFrameRate())); - prefs.put(DIV_BY_ZERO_VALUE, Double.toString(FloatBlitter.divideByZeroValue)); - prefs.put(NOISE_SD, Double.toString(Filters.getSD())); - if (threads > 1) - prefs.put(THREADS, Integer.toString(threads)); - if (IJ.isMacOSX()) - useJFileChooser = false; - if (!IJ.isLinux()) - dialogCancelButtonOnRight = false; - saveOptions(prefs); - savePluginPrefs(prefs); - ImageJ ij = IJ.getInstance(); - if (ij!=null) - ij.savePreferences(prefs); - Menus.savePreferences(prefs); - ParticleAnalyzer.savePreferences(prefs); - Analyzer.savePreferences(prefs); - ImportDialog.savePreferences(prefs); - PlotWindow.savePreferences(prefs); - NewImage.savePreferences(prefs); - String prefsDir = getPrefsDir(); - path = prefsDir + separator + PREFS_NAME; - if (prefsDir.endsWith(".imagej")) { - File f = new File(prefsDir); - if (!f.exists()) - f.mkdir(); // create .imagej directory - } - if (resetPreferences) { - File f = new File(path); - if (!f.exists()) - IJ.error("Edit>Options>Reset", "Unable to reset preferences. File not found at\n" + path); - boolean rtn = f.delete(); - resetPreferences = false; - } else - savePrefs(prefs, path); - } catch (Throwable t) { - String msg = t.getMessage(); - if (msg == null) - msg = "" + t; - int delay = 4000; - try { - new TextWindow("Error Saving Preferences:\n" + path, msg, 500, 200); - IJ.wait(delay); - } catch (Throwable t2) { - } - } - } - - /** Delete the preferences file when ImageJ quits. */ - public static void resetPreferences() { - resetPreferences = true; - } - - static void loadOptions() { - // Changed for Bio7. On Win 10 we use the SWT file dialog by default. No need to - // switch to JFileChooser! - int defaultOptions = ANTIALIASING + AVOID_RESLICE_INTERPOLATION + ANTIALIASED_TOOLS + MULTI_POINT_MODE - + (!IJ.isMacOSX() ? RUN_SOCKET_LISTENER : 0) + BLACK_BACKGROUND; - int options = getInt(OPTIONS, defaultOptions); - usePointerCursor = (options & USE_POINTER) != 0; - // antialiasedText = (options&ANTIALIASING)!=0; - antialiasedText = false; - interpolateScaledImages = (options & INTERPOLATE) != 0; - open100Percent = (options & ONE_HUNDRED_PERCENT) != 0; - //blackBackground = (options&BLACK_BACKGROUND)!=0; - useJFileChooser = (options & JFILE_CHOOSER) != 0; - weightedColor = (options & WEIGHTED) != 0; - if (weightedColor) - ColorProcessor.setWeightingFactors(0.299, 0.587, 0.114); - blackCanvas = (options & BLACK_CANVAS) != 0; - requireControlKey = (options & REQUIRE_CONTROL) != 0; - useInvertingLut = (options & USE_INVERTING_LUT) != 0; - antialiasedTools = (options & ANTIALIASED_TOOLS) != 0; - intelByteOrder = (options & INTEL_BYTE_ORDER) != 0; - noBorder = (options & NO_BORDER) != 0; - //showAllSliceOnly = (options & SHOW_ALL_SLICE_ONLY) != 0; - copyColumnHeaders = (options & COPY_HEADERS) != 0; - noRowNumbers = (options & NO_ROW_NUMBERS) != 0; - moveToMisc = (options & MOVE_TO_MISC) != 0; - runSocketListener = (options & RUN_SOCKET_LISTENER) != 0; - multiPointMode = (options & MULTI_POINT_MODE) != 0; - rotateYZ = (options & ROTATE_YZ) != 0; - flipXZ = (options & FLIP_XZ) != 0; - // dontSaveHeaders = (options&DONT_SAVE_HEADERS)!=0; - // dontSaveRowNumbers = (options&DONT_SAVE_ROW_NUMBERS)!=0; - noClickToGC = (options & NO_CLICK_TO_GC) != 0; - avoidResliceInterpolation = (options & AVOID_RESLICE_INTERPOLATION) != 0; - keepUndoBuffers = (options & KEEP_UNDO_BUFFERS) != 0; - - defaultOptions = (!IJ.isMacOSX() ? USE_FILE_CHOOSER : 0); - int options2 = getInt(OPTIONS2, defaultOptions); - useSystemProxies = (options2 & USE_SYSTEM_PROXIES) != 0; - useFileChooser = (options2 & USE_FILE_CHOOSER) != 0; - subPixelResolution = (options2 & SUBPIXEL_RESOLUTION) != 0; - enhancedLineTool = (options2 & ENHANCED_LINE_TOOL) != 0; - skipRawDialog = (options2 & SKIP_RAW_DIALOG) != 0; - reverseNextPreviousOrder = (options2 & REVERSE_NEXT_PREVIOUS_ORDER) != 0; - autoRunExamples = (options2 & AUTO_RUN_EXAMPLES) != 0; - showAllPoints = (options2 & SHOW_ALL_POINTS) != 0; - doNotSaveWindowLocations = (options2 & DO_NOT_SAVE_WINDOW_LOCS) != 0; - jFileChooserSettingChanged = (options2 & JFILE_CHOOSER_CHANGED) != 0; - dialogCancelButtonOnRight = (options2 & CANCEL_BUTTON_ON_RIGHT) != 0; - ignoreRescaleSlope = (options2 & IGNORE_RESCALE_SLOPE) != 0; - nonBlockingFilterDialogs = (options2 & NON_BLOCKING_DIALOGS) != 0; - fixedDicomScaling = (options2&FIXED_DICOM_SCALING)!=0; - //calibrateConversions = (options2&CALIBRATE_CONVERSIONS)!=0; - } - - static void saveOptions(Properties prefs) { - int options = (usePointerCursor ? USE_POINTER : 0) + (antialiasedText ? ANTIALIASING : 0) - + (interpolateScaledImages ? INTERPOLATE : 0) + (open100Percent ? ONE_HUNDRED_PERCENT : 0) - + (blackBackground ? BLACK_BACKGROUND : 0) + (useJFileChooser ? JFILE_CHOOSER : 0) - + (blackCanvas ? BLACK_CANVAS : 0) + (weightedColor ? WEIGHTED : 0) - + (requireControlKey ? REQUIRE_CONTROL : 0) + (useInvertingLut ? USE_INVERTING_LUT : 0) - + (intelByteOrder ? INTEL_BYTE_ORDER : 0) + (doubleBuffer ? DOUBLE_BUFFER : 0) - + (noPointLabels ? NO_POINT_LABELS : 0) + (noBorder ? NO_BORDER : 0) - + (showAllSliceOnly ? SHOW_ALL_SLICE_ONLY : 0) + (copyColumnHeaders ? COPY_HEADERS : 0) - + (noRowNumbers ? NO_ROW_NUMBERS : 0) + (moveToMisc ? MOVE_TO_MISC : 0) - + (runSocketListener ? RUN_SOCKET_LISTENER : 0) + (multiPointMode ? MULTI_POINT_MODE : 0) - + (rotateYZ ? ROTATE_YZ : 0) + (flipXZ ? FLIP_XZ : 0) + (dontSaveHeaders ? DONT_SAVE_HEADERS : 0) - + (dontSaveRowNumbers ? DONT_SAVE_ROW_NUMBERS : 0) + (noClickToGC ? NO_CLICK_TO_GC : 0) - + (avoidResliceInterpolation ? AVOID_RESLICE_INTERPOLATION : 0) - + (keepUndoBuffers ? KEEP_UNDO_BUFFERS : 0); - prefs.put(OPTIONS, Integer.toString(options)); - - int options2 = (useSystemProxies ? USE_SYSTEM_PROXIES : 0) + (useFileChooser ? USE_FILE_CHOOSER : 0) - + (subPixelResolution ? SUBPIXEL_RESOLUTION : 0) + (enhancedLineTool ? ENHANCED_LINE_TOOL : 0) - + (skipRawDialog ? SKIP_RAW_DIALOG : 0) + (reverseNextPreviousOrder ? REVERSE_NEXT_PREVIOUS_ORDER : 0) - + (autoRunExamples ? AUTO_RUN_EXAMPLES : 0) + (showAllPoints ? SHOW_ALL_POINTS : 0) - + (doNotSaveWindowLocations ? DO_NOT_SAVE_WINDOW_LOCS : 0) - + (jFileChooserSettingChanged ? JFILE_CHOOSER_CHANGED : 0) - + (dialogCancelButtonOnRight ? CANCEL_BUTTON_ON_RIGHT : 0) - + (ignoreRescaleSlope ? IGNORE_RESCALE_SLOPE : 0) - + (nonBlockingFilterDialogs?NON_BLOCKING_DIALOGS:0) - + (fixedDicomScaling?FIXED_DICOM_SCALING:0); - //+ (calibrateConversions?CALIBRATE_CONVERSIONS:0); - prefs.put(OPTIONS2, Integer.toString(options2)); - } - - /** - * Saves the Point loc in the preferences file as a string using - * the keyword key. - */ - public static void saveLocation(String key, Point loc) { - if (!doNotSaveWindowLocations) - set(key, loc != null ? loc.x + "," + loc.y : null); - } - - /** - * Uses the keyword key to retrieve a location from the preferences - * file. Returns null if the key is not found or the location is not valid - * (e.g., offscreen). - */ - public static Point getLocation(String key) { - String value = ijPrefs.getProperty(KEY_PREFIX + key); - if (value == null) - return null; - int index = value.indexOf(","); - if (index == -1) - return null; - double xloc = Tools.parseDouble(value.substring(0, index)); - if (Double.isNaN(xloc) || index == value.length() - 1) - return null; - double yloc = Tools.parseDouble(value.substring(index + 1)); - if (Double.isNaN(yloc)) - return null; - Point p = new Point((int) xloc, (int) yloc); - Rectangle bounds = GUI.getScreenBounds(p); // get bounds of screen that contains p - if (bounds != null && p.x + 100 <= bounds.x + bounds.width && p.y + 40 <= bounds.y + bounds.height) { - if (locKeys.get(key) == null) { // first time for this key? - locKeys.setProperty(key, ""); - Rectangle primaryScreen = GUI.getMaxWindowBounds(); - ImageJ ij = IJ.getInstance(); - Point ijLoc = ij != null ? ij.getLocation() : null; - //System.out.println("getLoc: "+key+" "+(ijLoc!=null&&primaryScreen.contains(ijLoc)) + " "+!primaryScreen.contains(p)); - if ((ijLoc != null && primaryScreen.contains(ijLoc)) && !primaryScreen.contains(p)) - return null; // return null if "ImageJ" window on primary screen and this location is not - } - return p; - } else - return null; - } - - /** Save plugin preferences. */ - static void savePluginPrefs(Properties prefs) { - Enumeration e = ijPrefs.keys(); - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - if (key.indexOf(KEY_PREFIX) == 0) - prefs.put(key, ijPrefs.getProperty(key)); - } - } - - public static void savePrefs(Properties prefs, String path) throws IOException { - FileOutputStream fos = new FileOutputStream(path); - BufferedOutputStream bos = new BufferedOutputStream(fos); - prefs.store(bos, "ImageJ " + ImageJ.VERSION + " Preferences"); - bos.close(); - } - - /** - * Returns the number of threads used by PlugInFilters to process images and - * stacks. - */ - public static int getThreads() { - if (threads == 0) { - threads = getInt(THREADS, 0); - int processors = Runtime.getRuntime().availableProcessors(); - if (threads < 1 || threads > processors) - threads = processors; - } - return threads; - } - - /** - * Sets the number of threads (1-32) used by PlugInFilters to process stacks. - */ - public static void setThreads(int n) { - if (n < 1) - n = 1; - threads = n; - } - - /** - * Sets the transparent index (0-255), or set to -1 to disable transparency. - */ - public static void setTransparentIndex(int index) { - if (index < -1 || index > 255) - index = -1; - transparentIndex = index; - } - - /** - * Returns the transparent index (0-255), or -1 if transparency is disabled. - */ - public static int getTransparentIndex() { - return transparentIndex; - } - - public static Properties getControlPanelProperties() { - return ijPrefs; - } - - public static String defaultResultsExtension() { - return get("options.ext", ".csv"); - } - - /** Sets the GenericDialog and Command Finder text scale (0.5 to 3.0). */ - public static void setGuiScale(double scale) { - if (scale >= 0.5 && scale <= 3.0) { - guiScale = scale; - set(GUI_SCALE, guiScale); - Roi.resetDefaultHandleSize(); - } - } - - /** Returns the GenericDialog and Command Finder text scale. */ - public static double getGuiScale() { - return guiScale; - } - - /** Returns the custom properties (IJ_Props.txt) file path. */ - public static String getCustomPropsPath() { - return propertiesPath; - } - - /** Returns the custom preferences (IJ_Prefs.txt) file path. */ - public static String getCustomPrefsPath() { - return preferencesPath; - } - - /** - * Retrieves a string from IJ_Props or IJ_Prefs.txt. Does not retrieve strings - * set using Prefs.set(). - */ - public static String getString(String key, String defaultString) { - if (props == null) - return defaultString; - String s = props.getProperty(key); - if (s == null) - return defaultString; - else - return s; - } - - /** Retrieves a string from string in IJ_Props or IJ_Prefs.txt. */ - public static String getString(String key) { - return props.getProperty(key); - } - - /** - * Retrieves a number from IJ_Props or IJ_Prefs.txt. Does not retrieve numbers - * set using Prefs.set(). - */ - public static int getInt(String key, int defaultValue) { - if (props == null) //workaround for Netscape JIT bug - return defaultValue; - String s = props.getProperty(key); - if (s != null) { - try { - return Integer.decode(s).intValue(); - } catch (NumberFormatException e) { - IJ.log("" + e); - } - } - return defaultValue; - } - - /** - * Retrieves a number from IJ_Props or IJ_Prefs.txt. Does not retrieve numbers - * set using Prefs.set(). - */ - public static double getDouble(String key, double defaultValue) { - if (props == null) - return defaultValue; - String s = props.getProperty(key); - Double d = null; - if (s != null) { - try { - d = Double.valueOf(s); - } catch (NumberFormatException e) { - d = null; - } - if (d != null) - return (d.doubleValue()); - } - return defaultValue; - } - - /** - * Retrieves a boolean from IJ_Props or IJ_Prefs.txt. Does not retrieve boolean - * set using Prefs.set(). - */ - public static boolean getBoolean(String key, boolean defaultValue) { - if (props == null) - return defaultValue; - String s = props.getProperty(key); - if (s == null) - return defaultValue; - else - return s.equals("true"); - } - - /** Finds a color in IJ_Props or IJ_Prefs.txt. */ - public static Color getColor(String key, Color defaultColor) { - int i = getInt(key, 0xaaa); - if (i == 0xaaa) - return defaultColor; - return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF); - } - - public static boolean commandLineMacro() { - return commandLineMacro; - } - -} diff --git a/com.eco.bio7.image/src/ij/RecentOpener.java b/com.eco.bio7.image/src/ij/RecentOpener.java deleted file mode 100644 index 8f0416209..000000000 --- a/com.eco.bio7.image/src/ij/RecentOpener.java +++ /dev/null @@ -1,37 +0,0 @@ -package ij; -import ij.io.*; -import java.awt.*; -import java.io.*; - -/** Opens, in a separate thread, files selected from the File/Open Recent submenu.*/ -public class RecentOpener implements Runnable { - private String path; - - RecentOpener(String path) { - this.path = path; - Thread thread = new Thread(this, "RecentOpener"); - thread.start(); - } - - /** Open the file and move the path to top of the submenu. */ - public void run() { - Opener o = new Opener(); - o.open(path); - Menu menu = Menus.getOpenRecentMenu(); - int n = menu.getItemCount(); - int index = 0; - for (int i=0; i0) { - MenuItem item = menu.getItem(index); - menu.remove(index); - menu.insert(item, 0); - } - } - -} - diff --git a/com.eco.bio7.image/src/ij/Undo.java b/com.eco.bio7.image/src/ij/Undo.java deleted file mode 100644 index ebdfcc64b..000000000 --- a/com.eco.bio7.image/src/ij/Undo.java +++ /dev/null @@ -1,233 +0,0 @@ -/**Implements the Edit/Undo command.*/ - -package ij; -import ij.process.*; -import ij.gui.*; -import ij.measure.Calibration; -import java.awt.*; -import java.awt.image.*; - -/** This class consists of static methods and - fields that implement ImageJ's Undo command. */ -public class Undo { - - public static final int NOTHING = 0; - /** Undo using ImageProcessor.snapshot. */ - public static final int FILTER = 1; - /** Undo using an ImageProcessor copy. */ - public static final int TYPE_CONVERSION = 2; - public static final int PASTE = 3; - public static final int COMPOUND_FILTER = 4; - public static final int COMPOUND_FILTER_DONE = 5; - /** Undo using a single image, or composite color stack, copy (limited to 200MB). */ - public static final int TRANSFORM = 6; - public static final int OVERLAY_ADDITION = 7; - public static final int ROI = 8; - public static final int MACRO = 9; - /** Undo of overlay modification */ - public static final int OVERLAY = 10; - - private static int whatToUndo = NOTHING; - private static int imageID; - private static ImageProcessor ipCopy = null; - private static ImagePlus impCopy; - private static Calibration calCopy; - private static Roi roiCopy; - private static double displayRangeMin, displayRangeMax; - private static LUT lutCopy; - private static Overlay overlayCopy; - private static int overlayImageID; - - public static void setup(int what, ImagePlus imp) { - if (imp==null) { - whatToUndo = NOTHING; - reset(); - return; - } - if (IJ.debugMode) IJ.log("Undo.setup: "+what+" "+imp); - if (what==FILTER && whatToUndo==COMPOUND_FILTER) - return; - if (what==COMPOUND_FILTER_DONE) { - if (whatToUndo==COMPOUND_FILTER) - whatToUndo = what; - return; - } - whatToUndo = what; - imageID = imp.getID(); - if (what==TYPE_CONVERSION) { - ipCopy = imp.getProcessor(); - calCopy = (Calibration)imp.getCalibration().clone(); - } else if (what==TRANSFORM) { - if ((!IJ.macroRunning()||Prefs.supportMacroUndo) && (imp.getStackSize()==1||imp.getDisplayMode()==IJ.COMPOSITE) && imp.getSizeInBytes()<209715200) - impCopy = imp.duplicate(); - else - reset(); - } else if (what==MACRO) { - ipCopy = imp.getProcessor().duplicate(); - calCopy = (Calibration)imp.getCalibration().clone(); - impCopy = null; - } else if (what==COMPOUND_FILTER) { - ImageProcessor ip = imp.getProcessor(); - if (ip!=null) - ipCopy = ip.duplicate(); - else - ipCopy = null; - } else if (what==OVERLAY_ADDITION) { - impCopy = null; - ipCopy = null; - } else if (what==ROI) { - impCopy = null; - ipCopy = null; - Roi roi = imp.getRoi(); - if (roi!=null) { - roiCopy = (Roi)roi.clone(); - roiCopy.setImage(null); - } else - whatToUndo = NOTHING; - } else if (what==OVERLAY) { - saveOverlay(imp); - } else { - ipCopy = null; - //ImageProcessor ip = imp.getProcessor(); - //lutCopy = (LUT)ip.getLut().clone(); - } - } - - /** This function should be called from PlugInFilters that modify the overlay prior to the operation. - * For the type 'FILTER', undo of overlays requires that the modified image also has an overlay. */ - public static void saveOverlay(ImagePlus imp) { - Overlay overlay = imp!=null?imp.getOverlay():null; - if (overlay!=null) { - overlayCopy = overlay.duplicate(); - overlayImageID = imp.getID(); - } else - overlayCopy = null; - } - - public static void reset() { - //if (IJ.debugMode) IJ.log("Undo.reset: "+ whatToUndo+" "+impCopy); - if (whatToUndo==COMPOUND_FILTER || whatToUndo==OVERLAY_ADDITION) - return; - whatToUndo = NOTHING; - imageID = 0; - ipCopy = null; - impCopy = null; - calCopy = null; - roiCopy = null; - lutCopy = null; - overlayCopy = null; - } - - public static void undo() { - ImagePlus imp = WindowManager.getCurrentImage(); - if (IJ.debugMode) IJ.log("Undo.undo: "+ whatToUndo+" "+imp+" "+impCopy); - if (imp==null || imageID!=imp.getID()) { - if (imp!=null && !IJ.macroRunning()) { // does foreground image still have an undo buffer? - ImageProcessor ip2 = imp.getProcessor(); - ip2.swapPixelArrays(); - imp.updateAndDraw(); - } else - reset(); - return; - } - switch (whatToUndo) { - case FILTER: - undoOverlay(imp, true); - ImageProcessor ip = imp.getProcessor(); - if (ip!=null) { - if (!IJ.macroRunning()) { - ip.swapPixelArrays(); - imp.updateAndDraw(); - return; // don't reset - } else { - ip.reset(); - imp.updateAndDraw(); - } - } - break; - case TYPE_CONVERSION: - case COMPOUND_FILTER: - case COMPOUND_FILTER_DONE: - if (ipCopy!=null) { - if (whatToUndo==TYPE_CONVERSION && calCopy!=null) - imp.setCalibration(calCopy); - if (swapImages(new ImagePlus("",ipCopy), imp)) { - imp.updateAndDraw(); - return; - } else - imp.setProcessor(null, ipCopy); - if (whatToUndo==COMPOUND_FILTER_DONE || whatToUndo==TYPE_CONVERSION) - undoOverlay(imp, true); - } - break; - case TRANSFORM: - if (impCopy!=null) - imp.setStack(impCopy.getStack()); - break; - case PASTE: - Roi roi = imp.getRoi(); - if (roi!=null) - roi.abortPaste(); - break; - case ROI: - Roi roiCopy2 = roiCopy; - setup(ROI, imp); // setup redo - imp.setRoi(roiCopy2); - return; //don't reset - case MACRO: - if (ipCopy!=null) { - imp.setProcessor(ipCopy); - if (calCopy!=null) imp.setCalibration(calCopy); - } - break; - case OVERLAY_ADDITION: - Overlay overlay = imp.getOverlay(); - if (overlay==null) - {IJ.beep(); return;} - int size = overlay.size(); - if (size>0) { - overlay.remove(size-1); - imp.draw(); - } else { - IJ.beep(); - return; - } - return; //don't reset; successive undo removes further rois - case OVERLAY: - undoOverlay(imp, false); - imp.draw(); - break; - } - reset(); - } - - /** Reverts the overlay to the saved version. */ - private static void undoOverlay(ImagePlus imp, boolean onlyModifyOvly) { - if (overlayCopy!=null && imp.getID()==overlayImageID) { - Overlay overlay = imp.getOverlay(); - imp.setOverlay(overlayCopy); - if (overlay != null) - overlayCopy = overlay.duplicate(); //swap - } - } - - static boolean swapImages(ImagePlus imp1, ImagePlus imp2) { - if (imp1.getWidth()!=imp2.getWidth() || imp1.getHeight()!=imp2.getHeight() - || imp1.getBitDepth()!=imp2.getBitDepth() || IJ.macroRunning()) - return false; - ImageProcessor ip1 = imp1.getProcessor(); - ImageProcessor ip2 = imp2.getProcessor(); - double min1 = ip1.getMin(); - double max1 = ip1.getMax(); - double min2 = ip2.getMin(); - double max2 = ip2.getMax(); - ip2.setSnapshotPixels(ip1.getPixels()); - ip2.swapPixelArrays(); - ip1.setPixels(ip2.getSnapshotPixels()); - ip2.setSnapshotPixels(null); - ip1.setMinAndMax(min2, max2); - ip2.setMinAndMax(min1, max1); - return true; - } - -} diff --git a/com.eco.bio7.image/src/ij/VirtualStack.java b/com.eco.bio7.image/src/ij/VirtualStack.java deleted file mode 100644 index 72a5ebd64..000000000 --- a/com.eco.bio7.image/src/ij/VirtualStack.java +++ /dev/null @@ -1,433 +0,0 @@ -package ij; -import ij.process.*; -import ij.io.*; -import ij.gui.ImageCanvas; -import ij.util.Tools; -import ij.plugin.FolderOpener; -import java.io.*; -import java.awt.*; -import java.awt.image.ColorModel; -import java.util.Properties; - -/** This class represents an array of disk-resident images. */ -public class VirtualStack extends ImageStack { - private static final int INITIAL_SIZE = 100; - private String path; - private int nSlices; - private String[] names; - private String[] labels; - private int bitDepth; - private int delay; - private Properties properties; - private boolean generateData; - private int[] indexes; // used to translate non-CZT hyperstack slice numbers (0-based) - /** subclasses that support translation of slice indices (by calling translate) should set this to true */ - protected boolean canTranslate; - - - /** Default constructor. */ - public VirtualStack() { } - - public VirtualStack(int width, int height) { - super(width, height); - } - - /** Creates an empty virtual stack. - * @param width image width - * @param height image height - * @param cm ColorModel or null - * @param path file path of directory containing the images - * @see #addSlice(String) - * @see OpenAsVirtualStack.js - */ - public VirtualStack(int width, int height, ColorModel cm, String path) { - super(width, height, cm); - path = IJ.addSeparator(path); - this.path = path; - if (path != null) - canTranslate = true; - names = new String[INITIAL_SIZE]; - labels = new String[INITIAL_SIZE]; - } - - /** Creates a virtual stack with no backing storage. - * See: Help>Examples>JavaScript>Terabyte VirtualStack - */ - public VirtualStack(int width, int height, int slices) { - this(width, height, slices, "8-bit"); - } - - /** Creates a virtual stack with no backing storage. - * See: Help>Examples>JavaScript>Terabyte VirtualStack - */ - public VirtualStack(int width, int height, int slices, String options) { - super(width, height, null); - nSlices = slices; - int depth = 8; - if (options.contains("16-bit")) depth=16; - if (options.contains("RGB")) depth=24; - if (options.contains("32-bit")) depth=32; - if (options.contains("delay")) delay=250; - this.generateData = options.contains("fill"); - this.bitDepth = depth; - } - - /** Adds an image to the end of a virtual stack created using the - * VirtualStack(w,h,cm,path) constructor. The argument - * can be a full file path (e.g., "C:/Users/wayne/dir1/image.tif") - * if the 'path' argument in the constructor is "". File names - * that start with '.' are ignored. - */ - public void addSlice(String fileName) { - if (fileName==null) - throw new IllegalArgumentException("'fileName' is null!"); - if (fileName.startsWith(".")) - return; - if (names==null) - throw new IllegalArgumentException("This Virtual Stack cannot be modified [VirtualStack(w,h,cm,path) constructor not used]"); - if (isTranslatingIndices()) - throw new IllegalArgumentException("Virtual hyperstack with non-czt order cannot be modified"); - nSlices++; - expandArrays(nSlices); - names[nSlices-1] = fileName; - } - - /** Expands the 'names' and 'labels' arrays if existing and smaller than minSize. - * This should be called each time the stack is enlarged */ - protected void expandArrays(int minSize) { - if (indexes != null && minSize < indexes.length) - minSize = indexes.length; //min size if slices were deleted previously - if (names != null && names.length < minSize) { - String[] tmp = new String[minSize*2]; - System.arraycopy(names, 0, tmp, 0, names.length); - names = tmp; - } - if (labels != null && labels.length < minSize) { - String[] tmp = new String[minSize*2]; - System.arraycopy(labels, 0, tmp, 0, labels.length); - labels = tmp; - } - } - - /** Does nothing. */ - public void addSlice(String sliceLabel, Object pixels) { - } - - /** Does nothing.. */ - public void addSlice(String sliceLabel, ImageProcessor ip) { - } - - /** Does nothing. */ - public void addSlice(String sliceLabel, ImageProcessor ip, int n) { - } - - /** Deletes the specified slice, where {@literal 1<=n<=nslices}. */ - public void deleteSlice(int n) { - if (nSlices==0) - return; - if (n<1 || n>nSlices) - throw new IllegalArgumentException("Argument out of range: "+n); - if (names==null) - throw new IllegalArgumentException("This Virtual Stack cannot be modified [VirtualStack(w,h,cm,path) constructor not used]"); - if (isTranslatingIndices()) - throw new IllegalArgumentException("Virtual hyperstack with non-czt order cannot be modified"); - for (int i=n; i0) - deleteSlice(n); - } - - /** Returns the pixel array for the specified slice, where {@literal 1<=n<=nslices}. */ - public Object getPixels(int n) { - ImageProcessor ip = getProcessor(n); - if (ip!=null) - return ip.getPixels(); - else - return null; - } - - public void setPixels(Object pixels, int n) { - } - - /** Returns an ImageProcessor for the specified slice, - * where {@literal 1<=n<=nslices}. Returns null if - * the stack is empty. - * When overriding this function, note that the ImageProcessor - * may be modified at a later time. Its pixel array - * can get replaced by the pixel array of another slice. - * This is because the ImageProcessor may be re-used when a - * different slice is accessed via ImagePlus.setSlice. - * {@link Example} - */ - public ImageProcessor getProcessor(int n) { - if (path==null) { //Help>Examples>JavaScript>Terabyte VirtualStack - ImageProcessor ip = null; - int w=getWidth(), h=getHeight(); - switch (bitDepth) { - case 8: ip = new ByteProcessor(w,h); break; - case 16: ip = new ShortProcessor(w,h); break; - case 24: ip = new ColorProcessor(w,h); break; - case 32: ip = new FloatProcessor(w,h); break; - } - String hlabel = null; - if (generateData) { - int value = 0; - ImagePlus img = WindowManager.getCurrentImage(); - if (img!=null && img.getStackSize()==nSlices) - value = img.getCurrentSlice()-1; - if (bitDepth==16) - value *= 256; - if (bitDepth!=32) { - for (int i=0; i0) - IJ.wait(delay); - return ip; - } - n = translate(n); // update n for hyperstacks not in the default CZT order - Opener opener = new Opener(); - opener.setSilentMode(true); - IJ.redirectErrorMessages(true); - ImagePlus imp = opener.openTempImage(path, names[n-1]); - IJ.redirectErrorMessages(false); - ImageProcessor ip = null; - int depthThisImage = 0; - if (imp!=null) { - int w = imp.getWidth(); - int h = imp.getHeight(); - int type = imp.getType(); - ColorModel cm = imp.getProcessor().getColorModel(); - String info = (String)imp.getProperty("Info"); - if (info!=null) { - if (FolderOpener.useInfo(info)) - setSliceLabel(info, n); - } else { - String sliceLabel = imp.getStack().getSliceLabel(1); - if (FolderOpener.useInfo(sliceLabel)) - setSliceLabel("Label: "+sliceLabel, n); - } - depthThisImage = imp.getBitDepth(); - ip = imp.getProcessor(); - ip.setOverlay(imp.getOverlay()); - properties = imp.getProperty("FHT")!=null?imp.getProperties():null; - } else { - File f = new File(path, names[n-1]); - String msg = f.exists()?"Error opening ":"File not found: "; - ip = new ByteProcessor(getWidth(), getHeight()); - ip.invert(); - label(ip, msg+names[n-1], Color.black); - depthThisImage = 8; - } - if (depthThisImage!=bitDepth) { - switch (bitDepth) { - case 8: ip=ip.convertToByte(true); break; - case 16: ip=ip.convertToShort(true); break; - case 24: ip=ip.convertToRGB(); break; - case 32: ip=ip.convertToFloat(); break; - } - } - if (ip.getWidth()!=getWidth() || ip.getHeight()!=getHeight()) { - ImageProcessor ip2 = ip.createProcessor(getWidth(), getHeight()); - ip2.insert(ip, 0, 0); - ip = ip2; - } - if (cTable!=null) - ip.setCalibrationTable(cTable); - ip.setSliceNumber(n); - return ip; - } - - /** Draw label for Help>Examples>JavaScript>Terabyte VirtualStack */ - private void label(ImageProcessor ip, String msg, Color color) { - int size = getHeight()/20; - if (size<9) size=9; - Font font = new Font("Helvetica", Font.PLAIN, size); - ip.setFont(font); - ip.setAntialiasedText(true); - ip.setColor(color); - ip.drawString(msg, size, size*2); - } - - /** Currently not implemented */ - public int saveChanges(int n) { - return -1; - } - - /** Returns the number of slices in this stack. */ - public int size() { - return getSize(); - } - - /** Returns the number of slices in this stack. Subclasses shold override this function. */ - public int getSize() { - return nSlices; - } - - /** Returns the label of the Nth image. */ - public String getSliceLabel(int n) { - if (isTranslatingIndices()) - n = translate(n); - if (labels==null) - return null; - String label = (n<=labels.length) ? labels[n-1] : null; //subclass may have grown stack without adding labels - if (names == null) - return label; - if (label==null) - return names[n-1]; - else { - if (label.startsWith("Label: ")) // slice label - return label.substring(7,label.length()); - else - return names[n-1]+"\n"+label; - } - } - - /** Returns null. */ - public Object[] getImageArray() { - return null; - } - - /** Sets the label of the specified slice, where {@literal 1<=n<=nSlices}. */ - public void setSliceLabel(String label, int n) { - if (n <= 0 || n > getSize()) - throw new IllegalArgumentException(outOfRange+n); - if (isTranslatingIndices()) - n = translate(n); - if (labels == null) - labels = new String[getSize()]; - expandArrays(getSize()); - labels[n-1] = label; - } - - /** Sets the array of slice labels. The array size must be the stack size or larger */ - protected void setSliceLabels(String[] labels) { - if (labels != null && labels.length < getSize()) - throw new IllegalArgumentException("Labels array too short: "+labels.length); - this.labels = labels; - } - - /** Always returns true. */ - public boolean isVirtual() { - return true; - } - - /** Does nothing. */ - public void trim() { - } - - /** Returns the path to the directory containing the images. */ - public String getDirectory() { - return IJ.addSeparator(path); - } - - /** Returns the file name of the specified slice, where {@literal 1<=n<=nslices}. */ - public String getFileName(int n) { - return names[n-1]; - } - - /** Sets the bit depth (8, 16, 24 or 32). */ - public void setBitDepth(int bitDepth) { - this.bitDepth = bitDepth; - } - - /** Returns the bit depth (8, 16, 24 or 32), or 0 if the bit depth is not known. */ - public int getBitDepth() { - return bitDepth; - } - - public ImageStack sortDicom(String[] strings, String[] info, int maxDigits) { - int n = size(); - String[] names2 = new String[n]; - for (int i=0; ihyperstack>stack>hyperstack to reshuffle) - indexes = indexes.clone(); - for (int i=0; i 0) { - ImagePlus imp = getFocusManagerActiveImage(); - if (imp != null) - return imp; - ImageWindow win = (ImageWindow) imageList.get(imageList.size() - 1); - return win.getImagePlus(); - } else - return Interpreter.getLastBatchModeImage(); - } - - private static ImagePlus getFocusManagerActiveImage() { - if (IJ.isMacro()) - return null; - KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); - Window win = kfm.getActiveWindow(); - ImagePlus imp = null; - if (win != null && (win instanceof ImageWindow)) - imp = ((ImageWindow) win).getImagePlus(); - return imp; - } - - /** Returns the number of open image windows. */ - public static int getWindowCount() { - int count = imageList.size(); - return count; - } - - /** Returns the number of open images. */ - public static int getImageCount() { - int count = imageList.size(); - count += Interpreter.getBatchModeImageCount(); - if (count == 0 && getCurrentImage() != null) - count = 1; - return count; - } - - /** Returns the front most window or null. */ - public static Window getActiveWindow() { - return frontWindow; - } - - /** Returns the Window containing the active table, or null. - * @see ij.measure.ResultsTable#getActiveTable - */ - public static Window getActiveTable() { - return frontTable; - } - - - - /** Obsolete; replaced by getActiveWindow. */ - public static Frame getFrontWindow() { - return frontFrame; - } - - /** - * Returns a list of the IDs of open images. Returns null if no image windows - * are open. - */ - public synchronized static int[] getIDList() { - int nWindows = imageList.size(); - int[] batchModeImages = Interpreter.getBatchModeImageIDs(); - int nBatchImages = batchModeImages.length; - if ((nWindows + nBatchImages) == 0) - return null; - int[] list = new int[nWindows + nBatchImages]; - for (int i=0; i 0) - imageID = getNthImageID(imageID); - if (imageID == 0 || getImageCount() == 0) - return null; - ImagePlus imp2 = Interpreter.getBatchModeImage(imageID); - if (imp2 != null) - return imp2; - ImagePlus imp = null; - for (int i = 0; i < imageList.size(); i++) { - ImageWindow win = (ImageWindow) imageList.get(i); - imp2 = win.getImagePlus(); - if (imageID == imp2.getID()) { - imp = imp2; - break; - } - } - imp2 = getCurrentImage(); - if (imp == null && imp2 != null && imp2.getID() == imageID) - return imp2; - return imp; - } - - /** - * Returns the ID of the Nth open image. Returns zero if n<=0 or n greater than - * the number of open image windows. - */ - public synchronized static int getNthImageID(int n) { - if (n <= 0) - return 0; - if (Interpreter.isBatchMode()) { - int[] list = getIDList(); - if (n > list.length) - return 0; - else - return list[n - 1]; - } else { - if (n > imageList.size()) - return 0; - ImageWindow win = (ImageWindow) imageList.get(n - 1); - if (win != null) - return win.getImagePlus().getID(); - else - return 0; - } - } - - /** - * Returns the first image that has the specified title or null if it is not - * found. - */ - public synchronized static ImagePlus getImage(String title) { - int[] wList = getIDList(); - if (wList == null) - return null; - for (int i = 0; i < wList.length; i++) { - ImagePlus imp = getImage(wList[i]); - if (imp != null && imp.getTitle().equals(title)) - return imp; - } - return null; - } - - /** Adds the specified window to the Window menu. */ - public synchronized static void addWindow(Window win) { - if (win == null) - return; - else if (win instanceof ImageWindow) - addImageWindow((ImageWindow) win); - else { - /* Changed for Bio7! */ - Menus.insertWindowMenuItem(win); - nonImageList.add(win); - } - } - - /** Adds the specified Frame to the Window menu. */ - public static void addWindow(Frame win) { - addWindow((Window) win); - } - - private static void addImageWindow(ImageWindow win) { - ImagePlus imp = win.getImagePlus(); - if (imp == null) - return; - checkForDuplicateName(imp); - imageList.add(win); - Menus.addWindowMenuItem(imp); - setCurrentWindow(win); - } - - static void checkForDuplicateName(ImagePlus imp) { - if (checkForDuplicateName) { - String name = imp.getTitle(); - if (isDuplicateName(name)) - imp.setTitle(getUniqueName(name)); - } - checkForDuplicateName = false; - } - - static boolean isDuplicateName(String name) { - if (name==null) - return false; - int n = imageList.size(); - for (int i = 0; i < n; i++) { - ImageWindow win = (ImageWindow) imageList.get(i); - String name2 = win.getImagePlus().getTitle(); - if (name.equals(name2)) - return true; - } - return false; - } - - /* - static boolean isDuplicateBatchModeName(String name) { - int[] list = getIDList(); - for (int i=0; i= 0) { - Menus.removeWindowMenuItem(index); - nonImageList.removeElement(win); - } - if (win!=null && win==frontTable) - frontTable = null; - } - setWindow(null); - } - - /** Removes the specified Frame from the Window menu. */ - public static void removeWindow(Frame win) { - removeWindow((Window) win); - } - - private static void removeImageWindow(ImageWindow win) { - int index = imageList.indexOf(win); - if (index == -1) - return; // not on the window list - try { - synchronized(WindowManager.class) { - imageList.remove(win); - } - activations.remove(win); - if (imageList.size() > 1 && !Prefs.closingAll) { - ImageWindow win2 = activations.size() > 0 ? (ImageWindow) activations.get(activations.size() - 1) : null; - setCurrentWindow(win2); - } else - currentWindow = null; - setTempCurrentImage(null); // ??? - int nonImageCount = nonImageList.size(); - if (nonImageCount > 0) - nonImageCount++; - Menus.removeWindowMenuItem(nonImageCount + index); - Menus.updateMenus(); - Undo.reset(); - } catch (Exception e) { - } - } - - /** The specified Window becomes the front window. */ - public static void setWindow(Window win) { - /* Changed for Bio7? - Probably not necessary! */ - // System.out.println("setWindow(W): "+win); - frontWindow = win; - if (win instanceof Frame) - frontFrame = (Frame) win; - - - } - - /** - * The specified frame becomes the front window, the one returnd by - * getFrontWindow(). - */ - public static void setWindow(Frame win) { - /* Changed for Bio7? - Probably not necessary! */ - - frontWindow = win; - frontFrame = win; - if (win!=null && win instanceof TextWindow && !(win instanceof Editor) && !"Log".equals(((TextWindow)win).getTitle())) - frontTable = win; - - // System.out.println("Set window(F): "+(win!=null?win.getTitle():"null")); - } - - /** - * Closes all windows. Stops and returns false if an image or Editor "save - * changes" dialog is canceled. - */ - public synchronized static boolean closeAllWindows() { - Prefs.closingAll = true; - while (imageList.size() > 0) { - /* Changed for Bio7! */ - if (!((ImageWindow) imageList.get(0)).bio7TabClose(true)) { - Prefs.closingAll = false; - return false; - } - if (!quittingViaMacro()) - IJ.wait(100); - } - Prefs.closingAll = false; - JFrame[] nonImages = getNonImageWindows(); - for (int i = 0; i < nonImages.length; i++) { - Frame frame = nonImages[i]; - if (frame != null && frame instanceof Commands) - ((Commands) frame).close(); - else if (frame != null && (frame instanceof Editor)) { - ((Editor) frame).close(); - if (((Editor) frame).fileChanged()) - return false; - if (!quittingViaMacro()) - IJ.wait(100); - } - } - ImageJ ij = IJ.getInstance(); - if (ij != null && ij.quitting() && IJ.getApplet() == null) - return true; - for (int i = 0; i < nonImages.length; i++) { - Frame frame = nonImages[i]; - if ((frame instanceof PlugInFrame) && !(frame instanceof Editor)) - ((PlugInFrame) frame).close(); - else if (frame instanceof TextWindow) - ((TextWindow) frame).close(); - else { - // frame.setVisible(false); - frame.dispose(); - } - } - return true; - } - - private static boolean quittingViaMacro() { - ImageJ ij = IJ.getInstance(); - return ij != null && ij.quittingViaMacro(); - } - - /** Activates the next image window on the window list. */ - public static void putBehind() { - if (IJ.debugMode) - IJ.log("putBehind"); - if (imageList.size() < 1 || currentWindow == null) - return; - int index = imageList.indexOf(currentWindow); - ImageWindow win = null; - int count = 0; - do { - index--; - if (index < 0) - index = imageList.size() - 1; - win = (ImageWindow) imageList.get(index); - if (++count == imageList.size()) - return; - } while (win instanceof HistogramWindow || win instanceof PlotWindow); - if (win == null) - return; - ImagePlus imp = win.getImagePlus(); - if (imp != null) - IJ.selectWindow(imp.getID()); - } - - /** Returns the temporary current image for this thread, or null. */ - public static ImagePlus getTempCurrentImage() { - return (ImagePlus) tempImageTable.get(Thread.currentThread()); - } - - /** - * Returns the window (a Frame or a Dialog) with the specified title, or null if - * a window with that title is not found. - */ - public static Window getWindow(String title) { - for (int i = 0; i < nonImageList.size(); i++) { - Object win = nonImageList.get(i); - String winTitle = win instanceof Frame ? ((Frame) win).getTitle() : ((Dialog) win).getTitle(); - if (title.equals(winTitle)) - return (Window) win; - } - return getImageWindow(title); - } - - /** Obsolete; replaced by getWindow(). */ - public static Frame getFrame(String title) { - for (int i = 0; i < nonImageList.size(); i++) { - Object win = nonImageList.get(i); - String winTitle = win instanceof Frame ? ((Frame) win).getTitle() : null; - if (title.equals(winTitle)) - return (Frame) win; - } - Frame frame = getImageWindow(title); - if (frame == null) { - Window win = getWindow(title); - if (win != null) - frame = new Frame("Proxy"); - } - return frame; - } - - private static Frame getImageWindow(String title) { - int[] wList = getIDList(); - int len = wList != null ? wList.length : 0; - for (int i = 0; i < len; i++) { - ImagePlus imp = getImage(wList[i]); - if (imp != null) { - if (imp.getTitle().equals(title)) - return imp.getWindow(); - } - } - return null; - } - - /** Activates a window selected from the Window menu. */ - public synchronized static void activateWindow(String menuItemLabel, MenuItem item) { - for (int i = 0; i < nonImageList.size(); i++) { - Object win = nonImageList.get(i); - String title = win instanceof Frame ? ((Frame) win).getTitle() : ((Dialog) win).getTitle(); - if (menuItemLabel.equals(title)) { - if (win instanceof Frame) { - toFront((Frame) win); - /* Changed for Bio7! */ - // IJTabs.setActiveTab(menuItemLabel); - } else - ((Dialog) win).toFront(); - ((CheckboxMenuItem) item).setState(false); - if (IJ.recording() && !IJ.isMacro()) - Recorder.record("selectWindow", title); - return; - } - } - int lastSpace = menuItemLabel.lastIndexOf(' '); - if (lastSpace > 0) // remove image size (e.g., " 90K") - menuItemLabel = menuItemLabel.substring(0, lastSpace); - String idString = item.getActionCommand(); - int id = (int) Tools.parseDouble(idString, 0); - ImagePlus imp = WindowManager.getImage(id); - if (imp == null) - return; - ImageWindow win1 = imp.getWindow(); - if (win1 == null) - return; - setCurrentWindow(win1); - toFront(win1); - /* Changed for Bio7! */ - // IJTabs.setActiveTabWindow(win1); - int index = imageList.indexOf(win1); - int n = Menus.window.getItemCount(); - int start = Menus.WINDOW_MENU_ITEMS + Menus.windowMenuItems2; - for (int j = start; j < n; j++) { - MenuItem mi = Menus.window.getItem(j); - if (mi instanceof CheckboxMenuItem) - ((CheckboxMenuItem) mi).setState((j - start) == index); - } - } - - /** Repaints all open image windows. */ - public synchronized static void repaintImageWindows() { - int[] list = getIDList(); - if (list == null) - return; - for (int i = 0; i < list.length; i++) { - ImagePlus imp2 = getImage(list[i]); - if (imp2 != null) { - imp2.setTitle(imp2.getTitle()); // update "(G)" flag (global - // calibration) - ImageWindow win = imp2.getWindow(); - if (win != null) - win.repaint(); - } - } - } - - public static void showList() { - for (int i = 0; i < imageList.size(); i++) { - ImageWindow win = (ImageWindow) imageList.get(i); - ImagePlus imp = win.getImagePlus(); - IJ.log(i + " " + imp.getTitle() + (win == currentWindow ? "*" : "") + " " + imp.getID()); - } - for (int i = 0; i < activations.size(); i++) { - ImageWindow win = (ImageWindow) activations.get(i); - ImagePlus imp = win.getImagePlus(); - IJ.log(i + " " + imp.getTitle() + " " + imp.getID()); - } - if (imageList.size() == 0) - IJ.log("imageList is empty"); - if (activations.size() == 0) - IJ.log("activations list is empty"); - IJ.log(" "); - } - - public static void toFront(Frame frame) { - if (frame == null) - return; - if (frame.getState() == Frame.ICONIFIED) - frame.setState(Frame.NORMAL); - frame.toFront(); - } - - public static void toFront(Window window) { - if (window == null) - return; - if (window instanceof Frame && ((Frame) window).getState() == Frame.ICONIFIED) - ((Frame) window).setState(Frame.NORMAL); - window.toFront(); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/Arrow.java b/com.eco.bio7.image/src/ij/gui/Arrow.java deleted file mode 100644 index 4427a0903..000000000 --- a/com.eco.bio7.image/src/ij/gui/Arrow.java +++ /dev/null @@ -1,421 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import java.awt.*; -import java.awt.geom.*; - - -/** This is an Roi subclass for creating and displaying arrows. */ -public class Arrow extends Line { - public static final String STYLE_KEY = "arrow.style"; - public static final String WIDTH_KEY = "arrow.width"; - public static final String SIZE_KEY = "arrow.size"; - public static final String DOUBLE_HEADED_KEY = "arrow.double"; - public static final String OUTLINE_KEY = "arrow.outline"; - public static final int FILLED=0, NOTCHED=1, OPEN=2, HEADLESS=3, BAR=4; - public static final String[] styles = {"Filled", "Notched", "Open", "Headless", "Bar"}; - private static int defaultStyle = (int)Prefs.get(STYLE_KEY, FILLED); - private static float defaultWidth = (float)Prefs.get(WIDTH_KEY, 2); - private static double defaultHeadSize = (int)Prefs.get(SIZE_KEY, 10); // 0-30; - private static boolean defaultDoubleHeaded = Prefs.get(DOUBLE_HEADED_KEY, false); - private static boolean defaultOutline = Prefs.get(OUTLINE_KEY, false); - private int style; - private double headSize = 10; // 0-30 - private boolean doubleHeaded; - private boolean outline; - private float[] points = new float[2*5]; - private GeneralPath path = new GeneralPath(); - private static Stroke defaultStroke = new BasicStroke(); - double headShaftRatio; - - static { - if (defaultStyleHEADLESS) - defaultStyle = FILLED; - } - - public Arrow(double ox1, double oy1, double ox2, double oy2) { - super(ox1, oy1, ox2, oy2); - setStrokeWidth(2); - } - - public Arrow(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - setStrokeWidth(defaultWidth); - style = defaultStyle; - headSize = defaultHeadSize; - doubleHeaded = defaultDoubleHeaded; - outline = defaultOutline; - setStrokeColor(Toolbar.getForegroundColor()); - } - - /** Draws this arrow on the image. */ - public void draw(Graphics g) { - Shape shape2 = null; - if (doubleHeaded) { - flipEnds(); - shape2 = getShape(); - flipEnds(); - } - Shape shape = getShape(); - if (shape==null) - return; - Color color = strokeColor!=null? strokeColor:ROIColor; - if (fillColor!=null) color = fillColor; - g.setColor(color); - Graphics2D g2 = (Graphics2D)g; - setRenderingHint(g2); - AffineTransform at = g2.getDeviceConfiguration().getDefaultTransform(); - double mag = getMagnification(); - int xbase=0, ybase=0; - if (ic!=null) { - Rectangle r = ic.getSrcRect(); - xbase = r.x; ybase = r.y; - } - at.setTransform(mag, 0.0, 0.0, mag, (-xbase+0.5)*mag, (-ybase+0.5)*mag); //0.5: int coordinate at pixel center - if (outline) { - float lineWidth = (float)(getOutlineWidth()*mag); - g2.setStroke(new BasicStroke(lineWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)); - g2.draw(at.createTransformedShape(shape)); - if (doubleHeaded) g2.draw(at.createTransformedShape(shape2)); - g2.setStroke(defaultStroke); - } else { - g2.fill(at.createTransformedShape(shape)); - if (doubleHeaded) g2.fill(at.createTransformedShape(shape2)); - } - if (!overlay) { - handleColor=Color.white; - drawHandle(g, screenXD(x1d), screenYD(y1d)); - drawHandle(g, screenXD(x2d), screenYD(y2d)); - drawHandle(g, screenXD(x1d+(x2d-x1d)/2.0), screenYD(y1d+(y2d-y1d)/2.0)); - } - if (state!=NORMAL && imp!=null && imp.getRoi()!=null) - showStatus(); - if (updateFullWindow) - {updateFullWindow = false; imp.draw();} - } - - private void flipEnds() { - double tmp = x1R; - x1R=x2R; - x2R=tmp; - tmp=y1R; - y1R=y2R; - y2R=tmp; - } - - private Shape getPath() { - path.reset(); - path = new GeneralPath(); - calculatePoints(); - float tailx = points[0]; - float taily = points[1]; - float headbackx = points[2*1]; - float headbacky = points[2*1+1]; - float headtipx = points[2*3]; - float headtipy = points[2*3+1]; - if (outline) { - double dx = headtipx - tailx; - double dy = headtipy - taily; - double shaftLength = Math.sqrt(dx*dx+dy*dy); - dx = headtipx - headbackx; - dy = headtipy- headbacky; - double headLength = Math.sqrt(dx*dx+dy*dy); - headShaftRatio = headLength/shaftLength; - if (headShaftRatio>1.0) - headShaftRatio = 1.0; - //IJ.log(headShaftRatio+" "+(int)shaftLength+" "+(int)headLength+" "+(int)tailx+" "+(int)taily+" "+(int)headtipx+" "+(int)headtipy); - } - path.moveTo(tailx, taily); // tail - path.lineTo(headbackx, headbacky); // head back - path.moveTo(headbackx, headbacky); // head back - if (style==OPEN) - path.moveTo(points[2 * 2], points[2 * 2 + 1]); - else - path.lineTo(points[2 * 2], points[2 * 2 + 1]); // left point - path.lineTo(headtipx, headtipy); // head tip - path.lineTo(points[2 * 4], points[2 * 4 + 1]); // right point - path.lineTo(headbackx, headbacky); // back to the head back - return path; - } - - /** Based on the method with the same name in Fiji's Arrow plugin, - written by Jean-Yves Tinevez and Johannes Schindelin. */ - private void calculatePoints() { - double tip = 0.0; - double base; - double shaftWidth = getStrokeWidth(); - double length = 8+10*shaftWidth*0.5; - length = length*(headSize/10.0); - length -= shaftWidth*1.42; - if (style==NOTCHED) length*=0.74; - if (style==OPEN) length*=1.32; - if (length<0.0 || style==HEADLESS) length=0.0; - double x = getXBase(); - double y = getYBase(); - x1d=x+x1R; y1d=y+y1R; x2d=x+x2R; y2d=y+y2R; - x1=(int)x1d; y1=(int)y1d; x2=(int)x2d; y2=(int)y2d; - double dx=x2d-x1d, dy=y2d-y1d; - double arrowLength = Math.sqrt(dx*dx+dy*dy); - dx=dx/arrowLength; dy=dy/arrowLength; - if (doubleHeaded && style!=HEADLESS) { - points[0] = (float)(x1d+dx*shaftWidth*2.0); - points[1] = (float)(y1d+dy*shaftWidth*2.0); - } else { - points[0] = (float)x1d; - points[1] = (float)y1d; - } - if (length>0) { - double factor = style==OPEN?1.3:1.42; - points[2*3] = (float)(x2d-dx*shaftWidth*factor); - points[2*3+1] = (float)(y2d-dy*shaftWidth*factor); - if (style==BAR) { - points[2*3] = (float)(x2d-dx*shaftWidth*0.5); - points[2*3+1] = (float)(y2d-dy*shaftWidth*0.5); - } - } else { - points[2*3] = (float)x2d; - points[2*3+1] = (float)y2d; - } - final double alpha = Math.atan2(points[2*3+1]-points[1], points[2*3]-points[0]); - double SL = 0.0; - switch (style) { - case FILLED: case HEADLESS: - tip = Math.toRadians(20.0); - base = Math.toRadians(90.0); - points[1*2] = (float) (points[2*3] - length*Math.cos(alpha)); - points[1*2+1] = (float) (points[2*3+1] - length*Math.sin(alpha)); - SL = length*Math.sin(base)/Math.sin(base+tip);; - break; - case NOTCHED: - tip = Math.toRadians(20); - base = Math.toRadians(120); - points[1*2] = (float) (points[2*3] - length*Math.cos(alpha)); - points[1*2+1] = (float) (points[2*3+1] - length*Math.sin(alpha)); - SL = length*Math.sin(base)/Math.sin(base+tip);; - break; - case OPEN: - tip = Math.toRadians(25); //30 - points[1*2] = points[2*3]; - points[1*2+1] = points[2*3+1]; - SL = length; - break; - case BAR: - tip = Math.toRadians(90); //30 - points[1*2] = points[2*3]; - points[1*2+1] = points[2*3+1]; - SL = length; - updateFullWindow = true; - break; - } - // P2 = P3 - SL*alpha+tip - points[2*2] = (float) (points[2*3] - SL*Math.cos(alpha+tip)); - points[2*2+1] = (float) (points[2*3+1] - SL*Math.sin(alpha+tip)); - // P4 = P3 - SL*alpha-tip - points[2*4] = (float) (points[2*3] - SL*Math.cos(alpha-tip)); - points[2*4+1] = (float) (points[2*3+1] - SL*Math.sin(alpha-tip)); - } - - private Shape getShape() { - try { - Shape arrow = getPath(); - BasicStroke stroke = new BasicStroke((float)getStrokeWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); - Shape outlineShape = stroke.createStrokedShape(arrow); - Area a1 = new Area(arrow); - Area a2 = new Area(outlineShape); - a1.add(a2); - return a1; - } catch(Exception e) {}; - return null; - } - - private ShapeRoi getShapeRoi() { - try { - Shape arrow = getPath(); - BasicStroke stroke = new BasicStroke(getStrokeWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); - ShapeRoi sroi = new ShapeRoi(arrow); - Shape outlineShape = stroke.createStrokedShape(arrow); - sroi.or(new ShapeRoi(outlineShape)); - return sroi; - } catch(Exception e) {}; - return null; - } - - public ImageProcessor getMask() { - Roi roi = getShapeRoi(); - if ((width==0 && height==0) || roi==null) - return null; - else - return roi.getMask(); - } - - private double getOutlineWidth() { - double width = getStrokeWidth()/8.0; - double head = headSize/7.0; - double lineWidth = width + head + headShaftRatio; - if (lineWidth<1.0) lineWidth = 1.0; - //if (width<1) width=1; - //if (head<1) head=1; - //IJ.log(getStrokeWidth()+" "+IJ.d2s(width,2)+" "+IJ.d2s(head,2)+" "+IJ.d2s(headShaftRatio,2)+" "+IJ.d2s(lineWidth,2)+" "+IJ.d2s(width*head,2)); - return lineWidth; - } - - public void drawPixels(ImageProcessor ip) { - ShapeRoi shapeRoi = getShapeRoi(); - if (shapeRoi==null) - return; - ShapeRoi shapeRoi2 = null; - if (doubleHeaded) { - flipEnds(); - shapeRoi2 = getShapeRoi(); - flipEnds(); - } - if (outline) { - int lineWidth = ip.getLineWidth(); - ip.setLineWidth((int)Math.round(getOutlineWidth())); - shapeRoi.drawPixels(ip); - if (doubleHeaded) shapeRoi2.drawPixels(ip); - ip.setLineWidth(lineWidth); - } else { - ip.fill(shapeRoi); - if (doubleHeaded) ip.fill(shapeRoi2); - } - } - - public boolean contains(int x, int y) { - Roi roi = getShapeRoi(); - return roi!=null?roi.contains(x,y):false; - } - - /** Return the bounding rectangle of this arrow. */ - public Rectangle getBounds() { - Roi roi = getShapeRoi(); - if (roi!=null) - return roi.getBounds(); - else - return super.getBounds(); - } - - protected void handleMouseDown(int sx, int sy) { - super.handleMouseDown(sx, sy); - startxd = ic!=null?ic.offScreenXD(sx):sx; - startyd = ic!=null?ic.offScreenYD(sy):sy; - } - - protected int clipRectMargin() { - double mag = getMagnification(); - double arrowWidth = getStrokeWidth(); - double size = 8+10*arrowWidth*mag*0.5; - return (int)Math.max(size*2.0, headSize); - } - - public boolean isDrawingTool() { - return true; - } - - public static void setDefaultWidth(double width) { - defaultWidth = (float)width; - } - - public static double getDefaultWidth() { - return defaultWidth; - } - - public void setStyle(int style) { - this.style = style; - } - - /* Set the style, where 'style' is "filled", "notched", "open", "headless" or "bar", - plus optionial modifiers of "outline", "double", "small", "medium" and "large". */ - public void setStyle(String style) { - style = style.toLowerCase(); - int newStyle = Arrow.FILLED; - if (style.contains("notched")) - newStyle = Arrow.NOTCHED; - else if (style.contains("open")) - newStyle = Arrow.OPEN; - else if (style.contains("headless")) - newStyle = Arrow.HEADLESS; - else if (style.contains("bar")) - newStyle = Arrow.BAR; - setStyle(newStyle); - setOutline(style.contains("outline")); - setDoubleHeaded(style.contains("double")); - if (style.contains("small")) - setHeadSize(5); - else if (style.contains("large")) - setHeadSize(15); - } - - public int getStyle() { - return style; - } - - public static void setDefaultStyle(int style) { - defaultStyle = style; - } - - public static int getDefaultStyle() { - return defaultStyle; - } - - public void setHeadSize(double headSize) { - this.headSize = headSize; - } - - public double getHeadSize() { - return headSize; - } - - public static void setDefaultHeadSize(double size) { - defaultHeadSize = size; - } - - public static double getDefaultHeadSize() { - return defaultHeadSize; - } - - public void setDoubleHeaded(boolean b) { - doubleHeaded = b; - } - - public boolean getDoubleHeaded() { - return doubleHeaded; - } - - public static void setDefaultDoubleHeaded(boolean b) { - defaultDoubleHeaded = b; - } - - public static boolean getDefaultDoubleHeaded() { - return defaultDoubleHeaded; - } - - public void setOutline(boolean b) { - outline = b; - } - - public boolean getOutline() { - return outline; - } - - public static void setDefaultOutline(boolean b) { - defaultOutline = b; - } - - public static boolean getDefaultOutline() { - return defaultOutline; - } - - @Override - public void copyAttributes(Roi roi2) { - super.copyAttributes(roi2); - if (roi2 instanceof Arrow) { - Arrow a2 = (Arrow)roi2; - this.style = a2.getStyle(); - this.headSize = a2.getHeadSize(); - this.doubleHeaded = a2.getDoubleHeaded(); - this.outline = a2.getOutline(); - } - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ColorChooser.java b/com.eco.bio7.image/src/ij/gui/ColorChooser.java deleted file mode 100644 index eb2c3ad47..000000000 --- a/com.eco.bio7.image/src/ij/gui/ColorChooser.java +++ /dev/null @@ -1,121 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.util.*; -import ij.plugin.Colors; -import java.awt.*; -import java.util.Vector; -import java.awt.event.*; - - - /** Displays a dialog that allows the user to select a color using three sliders. */ -public class ColorChooser implements TextListener, AdjustmentListener { - Vector colors, sliders; - ColorPanel panel; - Color initialColor; - int red, green, blue; - boolean useHSB; - String title; - Frame frame; - double scale = Prefs.getGuiScale(); - - /** Constructs a ColorChooser using the specified title and initial color. */ - public ColorChooser(String title, Color initialColor, boolean useHSB) { - this(title, initialColor, useHSB, null); - } - - public ColorChooser(String title, Color initialColor, boolean useHSB, Frame frame) { - this.title = title; - if (initialColor==null) initialColor = Color.black; - this.initialColor = initialColor; - red = initialColor.getRed(); - green = initialColor.getGreen(); - blue = initialColor.getBlue(); - this.useHSB = useHSB; - this.frame = frame; - } - - /** Displays a color selection dialog and returns the color selected by the user. */ - public Color getColor() { - GenericDialog gd = frame!=null?new GenericDialog(title, frame):new GenericDialog(title); - gd.addSlider("Red:", 0, 255, red); - gd.addSlider("Green:", 0, 255, green); - gd.addSlider("Blue:", 0, 255, blue); - panel = new ColorPanel(initialColor, scale); - gd.addPanel(panel, GridBagConstraints.CENTER, new Insets(10, 0, 0, 0)); - colors = gd.getNumericFields(); - for (int i=0; i255) red=255; - if (green<0) green=0; if (green>255) green=255; - if (blue<0) blue=0; if (blue>255) blue=255; - panel.setColor(new Color(red, green, blue)); - panel.repaint(); - } - - public synchronized void adjustmentValueChanged(AdjustmentEvent e) { - Object source = e.getSource(); - for (int i=0; ie is null if the - * dialogItemChanged method is called after the user has pressed the - * OK button or if the GenericDialog has read its parameters from a - * macro. - * @param gd A reference to the GenericDialog. - * @return Should be true if the dialog input is valid. False disables the - * OK button and preview (if any). - */ - boolean dialogItemChanged(GenericDialog gd, AWTEvent e); -} diff --git a/com.eco.bio7.image/src/ij/gui/EllipseRoi.java b/com.eco.bio7.image/src/ij/gui/EllipseRoi.java deleted file mode 100644 index c7dc16823..000000000 --- a/com.eco.bio7.image/src/ij/gui/EllipseRoi.java +++ /dev/null @@ -1,270 +0,0 @@ -package ij.gui; -import java.awt.*; -import java.awt.image.*; -import java.awt.event.*; -import ij.*; -import ij.plugin.frame.Recorder; -import ij.process.FloatPolygon; -import ij.measure.Calibration; - -/** This class implements the ellipse selection tool. */ -public class EllipseRoi extends PolygonRoi { - private static final int vertices = 72; - private static double defaultRatio = 0.6; - private double xstart, ystart; - private double aspectRatio = defaultRatio; - private int[] handle = {0, vertices/4, vertices/2, vertices/2+vertices/4}; - - public EllipseRoi(double x1, double y1, double x2, double y2, double aspectRatio) { - super(new float[vertices], new float[vertices], vertices, FREEROI); - if (aspectRatio<0.0) aspectRatio = 0.0; - if (aspectRatio>1.0) aspectRatio = 1.0; - this.aspectRatio = aspectRatio; - makeEllipse(x1, y1, x2, y2); - state = NORMAL; - bounds = null; - } - - public EllipseRoi(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - type = FREEROI; - xstart = offScreenXD(sx); - ystart = offScreenYD(sy); - setDrawOffset(false); - bounds = null; - } - - public void draw(Graphics g) { - super.draw(g); - if (!overlay) { - for (int i=0; i1.0) aspectRatio = 1.0; - defaultRatio = aspectRatio; - } - - public int isHandle(int sx, int sy) { - int size = getHandleSize()+5; - int halfSize = size/2; - int index = -1; - for (int i=0; i=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) { - index = i; - break; - } - } - return index; - } - - /** Returns the perimeter of this ellipse. */ - public double getLength() { - double length = 0.0; - double dx, dy; - double w2=1.0, h2=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - w2 = cal.pixelWidth*cal.pixelWidth; - h2 = cal.pixelHeight*cal.pixelHeight; - } - for (int i=0; i<(nPoints-1); i++) { - dx = xpf[i+1]-xpf[i]; - dy = ypf[i+1]-ypf[i]; - length += Math.sqrt(dx*dx*w2+dy*dy*h2); - } - dx = xpf[0]-xpf[nPoints-1]; - dy = ypf[0]-ypf[nPoints-1]; - length += Math.sqrt(dx*dx*w2+dy*dy*h2); - return length; - } - - /** Returns x1, y1, x2, y2 and aspectRatio as a 5 element array. */ - public double[] getParams() { - double[] params = new double[5]; - params[0] = xpf[handle[2]]+x; - params[1] = ypf[handle[2]]+y; - params[2] = xpf[handle[0]]+x; - params[3] = ypf[handle[0]]+y; - params[4] = aspectRatio; - return params; - } - - public double[] getFeretValues() { - double a[] = super.getFeretValues(); - double pw=1.0, ph=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - pw = cal.pixelWidth; - ph = cal.pixelHeight; - } - if (pw != ph) //the following calculation holds only for pixel aspect ratio == 1 (otherwise different axes in distorted ellipse) - return a; - double[] p = getParams(); - double dx = p[2] - p[0]; //this is always major axis; aspect ratio p[4] is limited to <= 1 - double dy = p[3] - p[1]; - double major = Math.sqrt(dx*dx + dy*dy); - double minor = major*p[4]; - a[0] = major*pw; //Feret from convex hull should be accurate anyhow - a[2] = minor*pw; //here our own calculation is better - System.arraycopy(p, 0, a, 8, 4); //MaxFeret endpoints - double xCenter = 0.5*(p[2] + p[0]); - double yCenter = 0.5*(p[3] + p[1]); - double semiMinorX = dy * 0.5 * p[4]; - double semiMinorY = dx * (-0.5) * p[4]; - a[12] = xCenter + semiMinorX; a[14] = xCenter - semiMinorX; - a[13] = yCenter + semiMinorY; a[15] = yCenter - semiMinorY; - return a; - } - - /** Always returns true. */ - public boolean subPixelResolution() { - return true; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/FreehandRoi.java b/com.eco.bio7.image/src/ij/gui/FreehandRoi.java deleted file mode 100644 index 7cf4c463c..000000000 --- a/com.eco.bio7.image/src/ij/gui/FreehandRoi.java +++ /dev/null @@ -1,98 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.image.*; -import ij.*; - -/** Freehand region of interest or freehand line of interest*/ -public class FreehandRoi extends PolygonRoi { - - public FreehandRoi(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - if (Toolbar.getToolId()==Toolbar.FREEROI) - type = FREEROI; - else - type = FREELINE; - if (nPoints==2) nPoints--; - } - - protected void grow(int sx, int sy) { - if (subPixelResolution() && xpf!=null) { - growFloat(sx, sy); - return; - } - int ox = offScreenX(sx); - int oy = offScreenY(sy); - if (ox<0) ox = 0; - if (oy<0) oy = 0; - if (ox>xMax) ox = xMax; - if (oy>yMax) oy = yMax; - if (ox!=xp[nPoints-1]+x || oy!=yp[nPoints-1]+y) { - xp[nPoints] = ox-x; - yp[nPoints] = oy-y; - nPoints++; - if (IJ.altKeyDown()) - wipeBack(); - if (nPoints==xp.length) - enlargeArrays(); - drawLine(); - } - } - - private void growFloat(int sx, int sy) { - double ox = offScreenXD(sx); - double oy = offScreenYD(sy); - if (ox<0.0) ox = 0.0; - if (oy<0.0) oy = 0.0; - if (ox>xMax) ox = xMax; - if (oy>yMax) oy = yMax; - double xbase = getXBase(); - double ybase = getYBase(); - if (ox!=xpf[nPoints-1]+xbase || oy!=ypf[nPoints-1]+ybase) { - xpf[nPoints] = (float)(ox-xbase); - ypf[nPoints] = (float)(oy-ybase); - nPoints++; - if (nPoints==xpf.length) - enlargeArrays(); - drawLine(); - } - } - - void drawLine() { - int x1, y1, x2, y2; - if (xpf!=null) { - x1 = (int)Math.round(xpf[nPoints-2]+x); - y1 = (int)Math.round(ypf[nPoints-2]+y); - x2 = (int)Math.round(xpf[nPoints-1]+x); - y2 = (int)Math.round(ypf[nPoints-1]+y); - } else { - x1 = xp[nPoints-2]+x; - y1 = yp[nPoints-2]+y; - x2 = xp[nPoints-1]+x; - y2 = yp[nPoints-1]+y; - } - int xmin = Math.min(x1, x2); - int xmax = Math.max(x1, x2); - int ymin = Math.min(y1, y2); - int ymax = Math.max(y1, y2); - int margin = 4; - if (lineWidth>margin && isLine()) - margin = lineWidth; - if (ic!=null) { - double mag = ic.getMagnification(); - if (mag<1.0) margin = (int)(margin/mag); - } - if (IJ.altKeyDown()) - margin += 20; // for wipeBack - imp.draw(xmin-margin, ymin-margin, (xmax-xmin)+margin*2, (ymax-ymin)+margin*2); - } - - protected void handleMouseUp(int screenX, int screenY) { - if (state==CONSTRUCTING) { - addOffset(); - finishPolygon(); - } - state = NORMAL; - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/GUI.java b/com.eco.bio7.image/src/ij/gui/GUI.java deleted file mode 100644 index d687725ba..000000000 --- a/com.eco.bio7.image/src/ij/gui/GUI.java +++ /dev/null @@ -1,323 +0,0 @@ -package ij.gui; - -import ij.*; -import java.awt.*; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JScrollBar; -import javax.swing.JTable; -import javax.swing.UIManager; - -/** This class consists of static GUI utility methods. */ -public class GUI { - private static final Font DEFAULT_FONT = ImageJ.SansSerif12; - private static Color lightGray = new Color(240, 240, 240); - private static boolean isWindows8; - private static Color scrollbarBackground = new Color(245, 245, 245); - - static { - if (IJ.isWindows()) { - String osname = System.getProperty("os.name"); - isWindows8 = osname.contains("unknown") || osname.contains("8"); - } - } - - /** - * Positions the specified window in the center of the screen that contains - * target. - */ - public static void center(Window win, Component target) { - if (win == null) - return; - Rectangle bounds = getMaxWindowBounds(target); - Dimension window = win.getSize(); - if (window.width == 0) - return; - int left = bounds.x + Math.max(0, (bounds.width - window.width) / 2); - int top = bounds.y + Math.max(0, (bounds.height - window.height) / 4); - win.setLocation(left, top); - } - - /** - * Positions the specified window in the center of the screen containing the - * "ImageJ" window. - */ - public static void centerOnImageJScreen(Window win) { - center(win, IJ.getInstance()); - } - - public static void center(Window win) { - center(win, win); - } - - private static java.util.List getScreenConfigs() { - java.util.ArrayList configs = new java.util.ArrayList(); - for (GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) { - configs.add(device.getDefaultConfiguration()); - } - return configs; - } - - /** - * Get maximum bounds for the screen that contains a given point. - * - * @param point Coordinates of point. - * @param accountForInsets Deduct the space taken up by menu and status bars, - * etc. (after point is found to be inside bonds) - * @return Rectangle of bounds or null if point not inside of any - * screen. - */ - public static Rectangle getScreenBounds(Point point, boolean accountForInsets) { - if (GraphicsEnvironment.isHeadless()) - return new Rectangle(0, 0, 0, 0); - for (GraphicsConfiguration config : getScreenConfigs()) { - Rectangle bounds = config.getBounds(); - if (bounds != null && bounds.contains(point)) { - Insets insets = accountForInsets ? Toolkit.getDefaultToolkit().getScreenInsets(config) : null; - return shrinkByInsets(bounds, insets); - } - } - return null; - } - - /** - * Get maximum bounds for the screen that contains a given component. - * - * @param component An AWT component located on the desired screen. If - * null is provided, the default screen is - * used. - * @param accountForInsets Deduct the space taken up by menu and status bars, - * etc. - * @return Rectangle of bounds. - */ - public static Rectangle getScreenBounds(Component component, boolean accountForInsets) { - if (GraphicsEnvironment.isHeadless()) - return new Rectangle(0, 0, 0, 0); - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsConfiguration gc = component == null ? ge.getDefaultScreenDevice().getDefaultConfiguration() - : component.getGraphicsConfiguration(); - Insets insets = accountForInsets ? Toolkit.getDefaultToolkit().getScreenInsets(gc) : null; - return shrinkByInsets(gc.getBounds(), insets); - } - - public static Rectangle getScreenBounds(Point point) { - return getScreenBounds(point, false); - } - - public static Rectangle getScreenBounds(Component component) { - return getScreenBounds(component, false); - } - - public static Rectangle getScreenBounds() { - return getScreenBounds((Component) null); - } - - public static Rectangle getMaxWindowBounds(Point point) { - return getScreenBounds(point, true); - } - - public static Rectangle getMaxWindowBounds(Component component) { - return getScreenBounds(component, true); - } - - public static Rectangle getMaxWindowBounds() { - return getMaxWindowBounds((Component) null); - } - - private static Rectangle shrinkByInsets(Rectangle bounds, Insets insets) { - Rectangle shrunk = new Rectangle(bounds); - if (insets == null) - return shrunk; - shrunk.x += insets.left; - shrunk.y += insets.top; - shrunk.width -= insets.left + insets.right; - shrunk.height -= insets.top + insets.bottom; - return shrunk; - } - - public static Rectangle getZeroBasedMaxBounds() { - for (GraphicsConfiguration config : getScreenConfigs()) { - Rectangle bounds = config.getBounds(); - if (bounds != null && bounds.x == 0 && bounds.y == 0) - return bounds; - } - return null; - } - - public static Rectangle getUnionOfBounds() { - Rectangle unionOfBounds = new Rectangle(); - for (GraphicsConfiguration config : getScreenConfigs()) { - unionOfBounds = unionOfBounds.union(config.getBounds()); - } - return unionOfBounds; - } - - static private Frame frame; - - /** Obsolete */ - public static Image createBlankImage(int width, int height) { - if (width == 0 || height == 0) - throw new IllegalArgumentException(""); - if (frame == null) { - frame = new Frame(); - frame.pack(); - frame.setBackground(Color.white); - } - Image img = frame.createImage(width, height); - return img; - } - - /** Lightens overly dark scrollbar background on Windows 8. */ - public static void fix(Scrollbar sb) { - } - - public static boolean showCompositeAdvisory(ImagePlus imp, String title) { - if (imp == null || imp.getCompositeMode() != IJ.COMPOSITE || imp.getNChannels() == 1 || IJ.macroRunning()) - return true; - String msg = "Channel " + imp.getC() + " of this color composite image will be processed."; - GenericDialog gd = new GenericDialog(title); - gd.addMessage(msg); - gd.showDialog(); - return !gd.wasCanceled(); - } - - /** - * Scales an AWT component according to {@link Prefs#getGuiScale()}. - * - * @param component the AWT component to be scaled. If a container, scaling is - * applied to all its child components - */ - public static void scale(final Component component) { - final float scale = (float) Prefs.getGuiScale(); - if (scale == 1f) - return; - if (component instanceof Container) - scaleComponents((Container) component, scale); - else - scaleComponent(component, scale); - } - - private static void scaleComponents(final Container container, final float scale) { - for (final Component child : container.getComponents()) { - if (child instanceof Container) - scaleComponents((Container) child, scale); - else - scaleComponent(child, scale); - } - } - - private static void scaleComponent(final Component component, final float scale) { - Font font = component.getFont(); - if (font == null) - font = DEFAULT_FONT; - font = font.deriveFont(scale * font.getSize()); - component.setFont(font); - } - - public static void scalePopupMenu(final PopupMenu popup) { - //System.out.println("scalePopupMenu1: "+popup); - if (Menus.getFontSize()!=0) { - popup.setFont(Menus.getFont(false)); - //System.out.println("scalePopupMenu2: "+popup.getFont()); - return; - } - final float scale = (float)Prefs.getGuiScale(); - if (scale == 1f) - return; - Font font=popup.getFont(); - if (font==null) - font = new Font("SansSerif", Font.PLAIN, (int)(scale*13)); - else - font = font.deriveFont(scale*font.getSize()); - popup.setFont(font); - //System.out.println("scalePopupMenu3: "+popup.getFont()); - } - - /** - * Tries to detect if a Swing component is unscaled and scales it it according - * to {@link #getGuiScale()}. - * - * This is mainly relevant to linux: Swing components scale automatically on - * most platforms, specially since Java 8. However there are still exceptions to - * this on linux: e.g., In Ubuntu, Swing components do scale, but only under the - * GTK L&F. (On the other hand AWT components do not scale at all on - * hiDPI screens on linux). - * - * - * This method tries to avoid exaggerated font sizes by detecting if a component - * has been already scaled by the UIManager, applying only - * {@link #getGuiScale()} to the component's font if not. - * - * - * @param component the component to be scaled - * @return true, if component's font was resized - */ - public static boolean scale(final JComponent component) { - final double guiScale = Prefs.getGuiScale(); - if (guiScale == 1d) - return false; - Font font = component.getFont(); - if (font == null && component instanceof JList) - font = UIManager.getFont("List.font"); - else if (font == null && component instanceof JTable) - font = UIManager.getFont("Table.font"); - else if (font == null) - font = UIManager.getFont("Label.font"); - if (font.getSize() > DEFAULT_FONT.getSize()) - return false; - if (component instanceof JTable) - ((JTable) component).setRowHeight((int) (((JTable) component).getRowHeight() * guiScale * 0.9)); - else if (component instanceof JList) - ((JList>) component) - .setFixedCellHeight((int) (((JList>) component).getFixedCellHeight() * guiScale * 0.9)); - component.setFont(font.deriveFont((float) guiScale * font.getSize())); - return true; - } - - /** - * Works around an OpenJDK bug on Windows that causes the scrollbar thumb color - * and background color to be almost identical. - */ - public static final void fixScrollbar(Scrollbar sb) { - if (IJ.isWindows()) - sb.setBackground(scrollbarBackground); - } - - /*Changed for Bio7!*/ - /** - * Works around an OpenJDK bug on Windows that causes the scrollbar thumb color - * and background color to be almost identical. - */ - public static final void fixScrollbar(JScrollBar sb) { - if (IJ.isWindows()) - sb.setBackground(scrollbarBackground); - } - - /** - * Returns a new NonBlockingGenericDialog with the given title, except when Java - * is running in headless mode, in which case a GenericDialog is be returned. - */ - public static GenericDialog newNonBlockingDialog(String title) { - if (GraphicsEnvironment.isHeadless()) - return new GenericDialog(title); - else - return new NonBlockingGenericDialog(title); - } - - /** Returns a new NonBlockingGenericDialog with the given title - * if Prefs.nonBlockingFilterDialogs is 'true' and 'imp' is - * displayed, otherwise returns a GenericDialog. - * - * @param title Dialog title - * @param imp The image associated with this dialog - */ - public static GenericDialog newNonBlockingDialog(String title, ImagePlus imp) { - if (Prefs.nonBlockingFilterDialogs && imp != null && imp.getWindow() != null) { - NonBlockingGenericDialog gd = new NonBlockingGenericDialog(title); - gd.imp = imp; - return gd; - } else - return new GenericDialog(title); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/GenericDialog.java b/com.eco.bio7.image/src/ij/gui/GenericDialog.java deleted file mode 100644 index 82fb76716..000000000 --- a/com.eco.bio7.image/src/ij/gui/GenericDialog.java +++ /dev/null @@ -1,2345 +0,0 @@ -package ij.gui; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JPanel; -import com.eco.bio7.image.Util; -import ij.*; -import ij.plugin.frame.Recorder; -import ij.plugin.ScreenGrabber; -import ij.plugin.filter.PlugInFilter; -import ij.plugin.filter.PlugInFilterRunner; -import ij.util.Tools; -import ij.macro.*; -import ij.io.OpenDialog; -import java.awt.*; -import java.io.*; -import java.awt.event.*; -import java.util.*; -import java.awt.datatransfer.*; -import java.awt.dnd.*; - -/** - * This class is a customizable modal dialog box. Here is an example - * GenericDialog with one string field and two numeric fields: - * - * - * public class Generic_Dialog_Example implements PlugIn { - * static String title = "Example"; - * static int width = 512, height = 512; - * - * public void run(String arg) { - * GenericDialog gd = new GenericDialog("New Image"); - * gd.addStringField("Title: ", title); - * gd.addNumericField("Width: ", width, 0); - * gd.addNumericField("Height: ", height, 0); - * gd.showDialog(); - * if (gd.wasCanceled()) - * return; - * title = gd.getNextString(); - * width = (int) gd.getNextNumber(); - * height = (int) gd.getNextNumber(); - * IJ.newImage(title, "8-bit", width, height, 1); - * } - * } - * - * - * To work with macros, the first word of each component label must be unique. - * If this is not the case, add underscores, which will be converted to spaces - * when the dialog is displayed. For example, change the checkbox labels "Show - * Quality" and "Show Residue" to "Show_Quality" and "Show_Residue". - */ -public class GenericDialog extends Dialog implements ActionListener, TextListener, FocusListener, ItemListener, KeyListener, AdjustmentListener, WindowListener, ComponentListener { - - protected Vector numberField, stringField, checkbox, choice, slider, radioButtonGroups; - protected TextArea textArea1, textArea2; - protected Vector defaultValues, defaultText, defaultStrings, defaultChoiceIndexes; - protected Component theLabel; - private Button okay; - private Button cancel; - private Button no, help; - private String helpLabel = "Help"; - private boolean wasCanceled, wasOKed; - private int nfIndex, sfIndex, cbIndex, choiceIndex, textAreaIndex, radioButtonIndex; - private GridBagConstraints c; - private boolean firstNumericField = true; - private boolean firstSlider = true; - private boolean invalidNumber; - private String errorMessage; - private Hashtable labels; - private boolean macro; - private String macroOptions; - private boolean addToSameRow; - private boolean addToSameRowCalled; - private int topInset, leftInset, bottomInset; - private boolean customInsets; - private Vector sliderIndexes, sliderScales, sliderDigits; - private Checkbox previewCheckbox; // the "Preview" Checkbox, if any - private Vector dialogListeners; // the Objects to notify on user input - private PlugInFilterRunner pfr; // the PlugInFilterRunner for automatic preview - private String previewLabel = " Preview"; - private final static String previewRunning = "wait..."; - private boolean recorderOn; // whether recording is allowed (after the dialog is closed) - private char echoChar; - private boolean hideCancelButton; - private boolean centerDialog = true; - private String helpURL; - private boolean smartRecording; - private Vector imagePanels; - protected static GenericDialog instance; - private boolean firstPaint = true; - private boolean fontSizeSet; - private boolean showDialogCalled; - private boolean optionsRecorded; // have dialogListeners been called to record options? - private Label lastLabelAdded; - private int[] windowIDs; - private String[] windowTitles; - - /** - * Creates a new GenericDialog with the specified title. Uses the current image - * image window as the parent frame or the ImageJ frame if no image windows are - * open. Dialog parameters are recorded by ImageJ's command recorder but this - * requires that the first word of each label be unique. - */ - public GenericDialog(String title) { - this(title, null); - } - - private static Frame getParentFrame() { - return null; - } - - /** Creates a new GenericDialog using the specified title and parent frame. */ - public GenericDialog(String title, Frame parent) { - super(parent, title, true); - ImageJ ij = IJ.getInstance(); - if (ij != null) - setFont(ij.getFont()); - okay = new Button(" OK "); - cancel = new Button("Cancel"); - if (Prefs.blackCanvas) { - setForeground(SystemColor.controlText); - setBackground(SystemColor.control); - } - // if (IJ.isMacOSX() && System.getProperty("java.vendor").contains("Azul")) - // setForeground(Color.black); // work around bug on Azul Java 8 on Apple - // Silicon - GridBagLayout grid = new GridBagLayout(); - c = new GridBagConstraints(); - setLayout(grid); - macroOptions = Macro.getOptions(); - macro = macroOptions != null; - addKeyListener(this); - addWindowListener(this); - // Added for Bio7! - addComponentListener(this); - /* Changed for Bio7! */ - Font font = Util.getOSFontToAwt(); - if (font != null) { - setFont(Util.getOSFontToAwt()); - } - /* - * Changed for Bio7! AWT must be colored per component. All JPanels will get the - * SWT background from the definition of the CanvasView (UIManager)! - */ - - if (Util.isThemeBlack()) { - if (Util.getOS().equals("Linux") || Util.getOS().equals("Mac")) { - setBackground(Util.getSWTBackgroundToAWT()); - setForeground(Util.getSWTForegroundToAWT()); - - } - } - } - - /** - * Adds a numeric field. The first word of the label must be unique or command - * recording will not work. - * - * @param label the label - * @param defaultValue value to be initially displayed - */ - public void addNumericField(String label, double defaultValue) { - int decimalPlaces = (int) defaultValue == defaultValue ? 0 : 3; - int columnWidth = decimalPlaces == 3 ? 8 : 6; - addNumericField(label, defaultValue, decimalPlaces, columnWidth, null); - } - - /** - * Adds a numeric field. The first word of the label must be unique or command - * recording will not work. - * - * @param label the label - * @param defaultValue value to be initially displayed - * @param digits number of digits to right of decimal point - */ - public void addNumericField(String label, double defaultValue, int digits) { - addNumericField(label, defaultValue, digits, 6, null); - } - - /** - * Adds a numeric field. The first word of the label must be unique or command - * recording will not work. - * - * @param label the label - * @param defaultValue value to be initially displayed - * @param digits number of digits to right of decimal point - * @param columns width of field in characters - * @param units a string displayed to the right of the field - */ - public void addNumericField(String label, double defaultValue, int digits, int columns, String units) { - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - c.insets.left = 10; - } else { - c.gridx = 0; - c.gridy++; - if (firstNumericField) - c.insets = getInsets(5, 0, 3, 0); // top, left, bottom, right - else - c.insets = getInsets(0, 0, 3, 0); - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - // IJ.log("x="+c.gridx+", y= "+c.gridy+", width="+c.gridwidth+", ancher= - // "+c.anchor+" "+c.insets); - add(fieldLabel, c); - if (addToSameRow) { - c.insets.left = 0; - addToSameRow = false; - } - if (numberField == null) { - numberField = new Vector(5); - defaultValues = new Vector(5); - defaultText = new Vector(5); - } - if (IJ.isWindows()) - columns -= 2; - if (columns < 1) - columns = 1; - boolean scientificNotationAsNeeded = false; - if (digits < 0) { - digits = -digits; - scientificNotationAsNeeded = true; - } - String defaultString = IJ.d2s(defaultValue, digits); - if (scientificNotationAsNeeded) - defaultString = ij.measure.ResultsTable.d2s(defaultValue, digits); - if (Double.isNaN(defaultValue)) - defaultString = ""; - TextField tf = newTextField(defaultString, columns); - if (IJ.isLinux()) - tf.setBackground(Color.white); - tf.addActionListener(this); - tf.addTextListener(this); - tf.addFocusListener(this); - tf.addKeyListener(this); - numberField.addElement(tf); - defaultValues.addElement(Double.valueOf(defaultValue)); - defaultText.addElement(tf.getText()); - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - tf.setEditable(true); - // if (firstNumericField) tf.selectAll(); - firstNumericField = false; - if (units == null || units.equals("")) { - add(tf, c); - } else { - JPanel panel = new JPanel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - panel.add(tf); - panel.add(new Label(" " + units)); - add(panel, c); - } - if (IJ.recording() || macro) - saveLabel(tf, label); - } - - private Label makeLabel(String label) { - if (IJ.isMacintosh()) - label += " "; - return new Label(label); - } - - /** - * Saves the label for given component, for macro recording and for accessing - * the component in macros. - */ - private void saveLabel(Object component, String label) { - if (labels == null) - labels = new Hashtable(); - if (label.length() > 0) - label = Macro.trimKey(label.trim()); - if (label.length() > 0 && hasLabel(label)) { // not a unique label? - label += "_0"; - for (int n = 1; hasLabel(label); n++) { // while still not a unique label - label = label.substring(0, label.lastIndexOf('_')); // remove counter - label += "_" + n; - } - } - labels.put(component, label); - } - - /** - * Returns whether the list of labels for macro recording or macro creation - * contains a given label. - */ - private boolean hasLabel(String label) { - for (Object o : labels.keySet()) - if (labels.get(o).equals(label)) - return true; - return false; - } - - /** - * Adds an 8 column text field. - * - * @param label the label - * @param defaultText the text initially displayed - */ - public void addStringField(String label, String defaultText) { - addStringField(label, defaultText, 8); - } - - /** - * Adds a text field. - * - * @param label the label - * @param defaultText text initially displayed - * @param columns width of the text field. If columns is 8 or more, - * additional items may be added to this line with - * addToSameRow() - */ - public void addStringField(String label, String defaultText, int columns) { - if (addToSameRow && label.equals("_")) - label = ""; - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - boolean custom = customInsets; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - if (stringField == null) - c.insets = getInsets(5, 0, 5, 0); // top, left, bottom, right - else - c.insets = getInsets(0, 0, 5, 0); - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - add(fieldLabel, c); - if (stringField == null) { - stringField = new Vector(4); - defaultStrings = new Vector(4); - } - - TextField tf = newTextField(defaultText, columns); - if (IJ.isLinux()) - tf.setBackground(Color.white); - - tf.setEchoChar(echoChar); - echoChar = 0; - tf.addActionListener(this); - tf.addTextListener(this); - tf.addFocusListener(this); - tf.addKeyListener(this); - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - c.gridwidth = columns <= 8 ? 1 : GridBagConstraints.REMAINDER; - c.insets.left = 0; - tf.setEditable(true); - add(tf, c); - stringField.addElement(tf); - defaultStrings.addElement(defaultText); - tf.setDropTarget(null); - new DropTarget(tf, new TextDropTarget(tf)); - if (IJ.recording() || macro) - saveLabel(tf, label); - } - - /** Sets the echo character for the next string field. */ - public void setEchoChar(char echoChar) { - this.echoChar = echoChar; - } - - /** - * Adds a directory text field and "Browse" button, where the field width is - * determined by the length of 'defaultPath', with a minimum of 25 columns. Use - * getNextString to retrieve the directory path. Call - * OpenDialog.setDefaultDirectory() to set the default directory used when the - * user clicks on "Browse". Based on the addDirectoryField() method in Fiji's - * GenericDialogPlus class. * @see ij.io.OpenDialog#setDefaultDirectory(String) - */ - public void addDirectoryField(String label, String defaultPath) { - int columns = defaultPath != null ? Math.max(defaultPath.length(), 25) : 25; - if (columns > 60) - columns = 60; - addDirectoryField(label, defaultPath, columns); - } - - public void addDirectoryField(String label, String defaultPath, int columns) { - defaultPath = IJ.addSeparator(defaultPath); - addStringField(label, defaultPath, columns); - if (GraphicsEnvironment.isHeadless()) - return; - TextField text = (TextField) stringField.lastElement(); - GridBagLayout layout = (GridBagLayout) getLayout(); - GridBagConstraints constraints = layout.getConstraints(text); - JButton button = new TrimmedButton("Browse", IJ.isMacOSX() ? 10 : 0); - BrowseButtonListener listener = new BrowseButtonListener(label, text, "dir"); - button.addActionListener(listener); - Panel panel = new Panel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - panel.add(text); - panel.add(button); - layout.setConstraints(panel, constraints); - add(panel); - if (IJ.recording() || macro) - saveLabel(panel, label); - } - - /** - * Adds a file text field and "Browse" button, where the field width is - * determined by the length of 'defaultPath', with a minimum of 25 columns. Use - * getNextString to retrieve the file path. Based on the addFileField() method - * in Fiji's GenericDialogPlus class. - */ - public void addFileField(String label, String defaultPath) { - int columns = defaultPath != null ? Math.max(defaultPath.length(), 25) : 25; - if (columns > 60) - columns = 60; - addFileField(label, defaultPath, columns); - } - - public void addFileField(String label, String defaultPath, int columns) { - addStringField(label, defaultPath, columns); - if (GraphicsEnvironment.isHeadless()) - return; - TextField text = (TextField) stringField.lastElement(); - GridBagLayout layout = (GridBagLayout) getLayout(); - GridBagConstraints constraints = layout.getConstraints(text); - JButton button = new TrimmedButton("Browse", IJ.isMacOSX() ? 10 : 0); - BrowseButtonListener listener = new BrowseButtonListener(label, text, "file"); - button.addActionListener(listener); - Panel panel = new Panel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - panel.add(text); - panel.add(button); - layout.setConstraints(panel, constraints); - add(panel); - if (IJ.recording() || macro) - saveLabel(panel, label); - } - - /** - * Add button to the dialog - * - * @param label button label - * @param listener listener to handle the action when pressing the button - */ - public void addButton(String label, ActionListener listener) { - if (GraphicsEnvironment.isHeadless()) - return; - Button button = new Button(label); - button.addActionListener(listener); - button.addKeyListener(this); - GridBagLayout layout = (GridBagLayout) getLayout(); - Panel panel = new Panel(); - addPanel(panel); - GridBagConstraints constraints = layout.getConstraints(panel); - remove(panel); - layout.setConstraints(button, constraints); - add(button); - } - - /** - * Adds a popup menu that lists the currently open images. Call getNextImage() - * to retrieve the selected image. Based on the addImageChoice() method in - * Fiji's GenericDialogPlus class. - * - * @param label the label - * @param defaultImage the image title initially selected in the menu or the - * first image if null - */ - public void addImageChoice(String label, String defaultImage) { - if (windowTitles == null) { - windowIDs = WindowManager.getIDList(); - if (windowIDs == null) - windowIDs = new int[0]; - windowTitles = new String[windowIDs.length]; - for (int i = 0; i < windowIDs.length; i++) { - ImagePlus image = WindowManager.getImage(windowIDs[i]); - windowTitles[i] = image == null ? "" : image.getTitle(); - } - } - addChoice(label, windowTitles, defaultImage); - } - - public ImagePlus getNextImage() { - int index = getNextChoiceIndex(); - return index < 0 ? null : WindowManager.getImage(windowIDs[index]); - } - - /** - * Adds a group of choices to the dialog with menu items taken from the - * enum class of the specified default item (enum constant). The - * default item is automatically set. Calls the original (string-based) - * {@link GenericDialog#addChoice(String, String[], String)} method. Usage - * example: - * - * - * import ij.process.AutoThresholder.Method; - * ... - * Method method = Method.Otsu; - * - * GenericDialog gd = new GenericDialog("Select AutoThresholder Method"); - * gd.addEnumChoice("All threshold methods", method); - * ... - * gd.showDialog(); - * ... - * method = gd.getNextEnumChoice(Method.class); - * - * - * @param the generic enum type containing the items to chose from - * @param label the label displayed for this choice group - * @param defaultItem the menu item initially selected - * - * @see #addEnumChoice(String, Enum[], Enum) - * @see #getNextEnumChoice(Class) - */ - public > void addEnumChoice(String label, E defaultItem) { - Class enumClass = defaultItem.getDeclaringClass(); - E[] enums = enumClass.getEnumConstants(); - String[] items = new String[enums.length]; - for (int i = 0; i < enums.length; i++) { - items[i] = enums[i].name(); - } - this.addChoice(label, items, defaultItem.name()); - } - - /** - * Adds a group of choices to the dialog with menu items taken from the supplied - * array of enum elements. This allows to present only a subset of - * enum choices in a specified order. A default item (enum constant) must be - * specified which, if {@code null} of not contained in the enum array, is - * replaced by the first element of the enum array. Calls the original - * (string-based) {@link GenericDialog#addChoice(String, String[], String)} - * method. Usage example: - * - * - * import ij.process.AutoThresholder.Method; - * ... - * Method[] selectMethods = {Method.Triangle, Method.Otsu, Method.Huang}; - * Method method = Method.Otsu; - * - * GenericDialog gd = new GenericDialog("Select AutoThresholder Method"); - * gd.addEnumChoice("Select threshold methods", selectMethods, method); - * ... - * gd.showDialog(); - * ... - * method = gd.getNextEnumChoice(Method.class); - * - * - * @param the generic enum type containing the items to choose from - * @param label the label displayed for this choice group - * @param enumArray an array of enum items (of type E) - * @param defaultItem the menu item initially selected (of type E, may be - * {@code null}) - * - * @see #addEnumChoice(String, Enum) - * @see #getNextEnumChoice(Class) - */ - public > void addEnumChoice(String label, E[] enumArray, E defaultItem) { - String[] items = new String[enumArray.length]; - boolean contained = false; // to check if defaultItem is contained in enumArray - for (int i = 0; i < enumArray.length; i++) { - if (enumArray[i] == defaultItem) { - contained = true; - } - items[i] = enumArray[i].name(); - } - if (!contained) { - defaultItem = enumArray[0]; - } - this.addChoice(label, items, defaultItem.name()); - } - - /** - * Returns the selected item in the next enum choice menu. Note that 'enumClass' - * is required to infer the proper enum type. Throws - * {@code IllegalArgumentException} if the selected item is not a defined - * constant in the specified enum class. - * - * @param the generic enum type - * @param enumClass the enum type - * @return the selected item - */ - public > E getNextEnumChoice(Class enumClass) { - String choiceString = this.getNextChoice(); - return Enum.valueOf(enumClass, choiceString); - } - - /** - * Adds a checkbox. - * - * @param label the label - * @param defaultValue the initial state - */ - public void addCheckbox(String label, boolean defaultValue) { - addCheckbox(label, defaultValue, false); - } - - /** - * Adds a checkbox; does not make it recordable if isPreview is true. With - * isPreview true, the checkbox can be referred to as previewCheckbox from - * hereon. - */ - private void addCheckbox(String label, boolean defaultValue, boolean isPreview) { - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - c.insets.left = 10; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - if (checkbox == null) - c.insets = getInsets(15, 20, 0, 0); // top, left, bottom, right - else - c.insets = getInsets(0, 20, 0, 0); - } - c.anchor = GridBagConstraints.WEST; - c.gridwidth = 2; - if (checkbox == null) - checkbox = new Vector(4); - Checkbox cb = new Checkbox(label2); - cb.setState(defaultValue); - cb.addItemListener(this); - cb.addKeyListener(this); - add(cb, c); - c.insets.left = 0; - checkbox.addElement(cb); - if (!isPreview && (Recorder.record || macro)) // preview checkbox is not recordable - saveLabel(cb, label); - if (isPreview) - previewCheckbox = cb; - } - - /** - * Adds a checkbox labelled "Preview" for "automatic" preview. The reference to - * this checkbox can be retrieved by getPreviewCheckbox() and it provides the - * additional method previewRunning for optical feedback while preview is - * prepared. PlugInFilters can have their "run" method automatically called for - * preview under the following conditions: - the PlugInFilter must pass a - * reference to itself (i.e., "this") as an argument to the AddPreviewCheckbox - - * it must implement the DialogListener interface and set the filter parameters - * in the dialogItemChanged method. - it must have DIALOG and PREVIEW set in its - * flags. A previewCheckbox is always off when the filter is started and does - * not get recorded by the Macro Recorder. - * - * @param pfr A reference to the PlugInFilterRunner calling the PlugInFilter if - * automatic preview is desired, null otherwise. - */ - public void addPreviewCheckbox(PlugInFilterRunner pfr) { - if (previewCheckbox != null) - return; - ImagePlus imp = WindowManager.getCurrentImage(); - if (imp != null && imp.isComposite() && ((CompositeImage) imp).getMode() == IJ.COMPOSITE) - return; - this.pfr = pfr; - addCheckbox(previewLabel, false, true); - } - - /** - * Add the preview checkbox with user-defined label; for details see the - * addPreviewCheckbox method with standard "Preview" label. Adds the checkbox - * when the current image is a CompositeImage in "Composite" mode, unlike the - * one argument version. Note that a GenericDialog can have only one - * PreviewCheckbox. - */ - public void addPreviewCheckbox(PlugInFilterRunner pfr, String label) { - if (previewCheckbox != null) - return; - previewLabel = label; - this.pfr = pfr; - addCheckbox(previewLabel, false, true); - } - - /** - * Adds a group of checkboxs using a grid layout. - * - * @param rows the number of rows - * @param columns the number of columns - * @param labels the labels - * @param defaultValues the initial states - */ - public void addCheckboxGroup(int rows, int columns, String[] labels, boolean[] defaultValues) { - addCheckboxGroup(rows, columns, labels, defaultValues, null); - } - - /** - * Adds a group of checkboxs using a grid layout. - * - * @param rows the number of rows - * @param columns the number of columns - * @param labels the labels - * @param defaultValues the initial states - * @param headings the column headings Example: Example: - * http://imagej.net/ij/plugins/multi-column-dialog/index.html - */ - public void addCheckboxGroup(int rows, int columns, String[] labels, boolean[] defaultValues, String[] headings) { - JPanel panel = new JPanel(); - int nRows = headings != null ? rows + 1 : rows; - panel.setLayout(new GridLayout(nRows, columns, 6, 0)); - int startCBIndex = cbIndex; - if (checkbox == null) - checkbox = new Vector(12); - if (headings != null) { - Font font = new Font("SansSerif", Font.BOLD, 12); - for (int i = 0; i < columns; i++) { - if (i > headings.length - 1 || headings[i] == null) - panel.add(new Label("")); - else { - Label label = new Label(headings[i]); - label.setFont(font); - panel.add(label); - } - } - } - int i1 = 0; - int[] index = new int[labels.length]; - for (int row = 0; row < rows; row++) { - for (int col = 0; col < columns; col++) { - int i2 = col * rows + row; - if (i2 >= labels.length) - break; - index[i1] = i2; - String label = labels[i1]; - if (label == null || label.length() == 0) { - Label lbl = new Label(""); - panel.add(lbl); - i1++; - continue; - } - if (label.indexOf('_') != -1) - label = label.replace('_', ' '); - Checkbox cb = new Checkbox(label); - checkbox.addElement(cb); - cb.setState(defaultValues[i1]); - cb.addItemListener(this); - if (IJ.recording() || macro) - saveLabel(cb, labels[i1]); - if (IJ.isLinux()) { - JPanel panel2 = new JPanel(); - panel2.setLayout(new BorderLayout()); - panel2.add("West", cb); - panel.add(panel2); - } else - panel.add(cb); - i1++; - } - } - c.gridx = 0; - c.gridy++; - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.insets = getInsets(10, 0, 0, 0); - addToSameRow = false; - add(panel, c); - } - - /** - * Adds a radio button group. - * - * @param label group label (or null) - * @param items radio button labels - * @param rows number of rows - * @param columns number of columns - * @param defaultItem button initially selected - */ - public void addRadioButtonGroup(String label, String[] items, int rows, int columns, String defaultItem) { - addToSameRow = false; - JPanel panel = new JPanel(); - int n = items.length; - panel.setLayout(new GridLayout(rows, columns, 0, 0)); - CheckboxGroup cg = new CheckboxGroup(); - for (int i = 0; i < n; i++) { - Checkbox cb = new Checkbox(items[i], cg, items[i].equals(defaultItem)); - cb.addItemListener(this); - panel.add(cb); - } - if (radioButtonGroups == null) - radioButtonGroups = new Vector(); - radioButtonGroups.addElement(cg); - Insets insets = getInsets(5, 10, 0, 0); - if (label == null || label.equals("")) { - label = "rbg" + radioButtonGroups.size(); - insets.top += 5; - } else { - setInsets(10, insets.left, 0); - addMessage(label); - insets.top = 2; - insets.left += 10; - } - c.gridx = 0; - c.gridy++; - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.insets = new Insets(insets.top, insets.left, 0, 0); - add(panel, c); - if (IJ.recording() || macro) - saveLabel(cg, label); - } - - /** - * Adds a popup menu. - * - * @param label the label - * @param items the menu items - * @param defaultItem the menu item initially selected - */ - public void addChoice(String label, String[] items, String defaultItem) { - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - if (choice == null) - c.insets = getInsets(5, 0, 5, 0); - else - c.insets = getInsets(0, 0, 5, 0); - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - if (choice == null) { - choice = new Vector(4); - defaultChoiceIndexes = new Vector(4); - } - add(fieldLabel, c); - Choice thisChoice = new Choice(); - thisChoice.addKeyListener(this); - thisChoice.addItemListener(this); - for (int i = 0; i < items.length; i++) - thisChoice.addItem(items[i]); - if (defaultItem != null) - thisChoice.select(defaultItem); - else - thisChoice.select(0); - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - add(thisChoice, c); - choice.addElement(thisChoice); - int index = thisChoice.getSelectedIndex(); - defaultChoiceIndexes.addElement(Integer.valueOf(index)); - if (IJ.recording() || macro) - saveLabel(thisChoice, label); - } - - /** Adds a message consisting of one or more lines of text. */ - public void addMessage(String text) { - addMessage(text, null, null); - } - - /** - * Adds a message consisting of one or more lines of text, which will be - * displayed using the specified font. - */ - public void addMessage(String text, Font font) { - addMessage(text, font, null); - } - - /** - * Adds a message consisting of one or more lines of text, which will be - * displayed using the specified font and color. - */ - public void addMessage(String text, Font font, Color color) { - theLabel = null; - if (text.indexOf('\n') >= 0) - theLabel = new MultiLineLabel(text); - else - theLabel = new Label(text); - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - c.insets = getInsets("".equals(text) ? 0 : 10, 20, 0, 0); // top, left, bottom, right - } - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.HORIZONTAL; - if (font != null) { - if (Prefs.getGuiScale() > 1.0) - font = font.deriveFont((float) (font.getSize() * Prefs.getGuiScale())); - theLabel.setFont(font); - } - if (color != null) - theLabel.setForeground(color); - add(theLabel, c); - c.fill = GridBagConstraints.NONE; - } - - /** - * Adds one or two (side by side) text areas. Append "SCROLLBARS_VERTICAL_ONLY" - * to the text of the first text area to get vertical scrollbars and - * "SCROLLBARS_BOTH" to get both vertical and horizontal scrollbars. - * - * @param text1 initial contents of the first text area - * @param text2 initial contents of the second text area or null - * @param rows the number of rows - * @param columns the number of columns - */ - public void addTextAreas(String text1, String text2, int rows, int columns) { - if (textArea1 != null) - return; - Panel panel = new Panel(); - int scrollbars = TextArea.SCROLLBARS_NONE; - if (text1 != null && text1.endsWith("SCROLLBARS_BOTH")) { - scrollbars = TextArea.SCROLLBARS_BOTH; - text1 = text1.substring(0, text1.length() - 15); - } - if (text1 != null && text1.endsWith("SCROLLBARS_VERTICAL_ONLY")) { - scrollbars = TextArea.SCROLLBARS_VERTICAL_ONLY; - text1 = text1.substring(0, text1.length() - 24); - } - Font font = new Font("SansSerif", Font.PLAIN, (int) (14 * Prefs.getGuiScale())); - textArea1 = new TextArea(text1, rows, columns, scrollbars); - if (IJ.isLinux()) - textArea1.setBackground(Color.white); - /* Changed for Bio7! */ - if (Util.isThemeBlack()) { - textArea1.setBackground(Util.getSWTBackgroundToAWT()); - textArea1.setForeground(Util.getSWTForegroundToAWT()); - } - if (Util.isThemeBlack()) { - Util.getSWTBackgroundToAWT(); - } - textArea1.setFont(font); - textArea1.addTextListener(this); - panel.add(textArea1); - if (text2 != null) { - textArea2 = new TextArea(text2, rows, columns, scrollbars); - if (IJ.isLinux()) - textArea2.setBackground(Color.white); - - /* Changed for Bio7! */ - if (Util.isThemeBlack()) { - textArea2.setBackground(Util.getSWTBackgroundToAWT()); - textArea2.setForeground(Util.getSWTForegroundToAWT()); - - } - textArea2.setFont(font); - panel.add(textArea2); - } - - c.gridx = 0; - c.gridy++; - c.gridwidth = GridBagConstraints.REMAINDER; - c.anchor = GridBagConstraints.WEST; - c.insets = getInsets(15, 20, 0, 0); - addToSameRow = false; - add(panel, c); - } - - /** - * Adds a slider (scroll bar) to the dialog box. Floating point values are used - * if (maxValue-minValue)<=5.0 and either defaultValue or minValue are - * non-integer. - * - * @param label the label - * @param minValue the minimum value of the slider - * @param maxValue the maximum value of the slider - * @param defaultValue the initial value of the slider - */ - public void addSlider(String label, double minValue, double maxValue, double defaultValue) { - if (defaultValue < minValue) - defaultValue = minValue; - if (defaultValue > maxValue) - defaultValue = maxValue; - int digits = 0; - double scale = 1.0; - if ((maxValue - minValue) <= 5.0 && (minValue != (int) minValue || maxValue != (int) maxValue || defaultValue != (int) defaultValue)) { - scale = 50.0; - minValue *= scale; - maxValue *= scale; - defaultValue *= scale; - digits = 2; - } - addSlider(label, minValue, maxValue, defaultValue, scale, digits); - } - - /** - * This vesion of addSlider() adds a 'stepSize' argument. - * Example: http://wsr.imagej.net/macros/SliderDemo.txt - */ - public void addSlider(String label, double minValue, double maxValue, double defaultValue, double stepSize) { - if (stepSize <= 0) - stepSize = 1; - int digits = digits(stepSize); - if (digits == 1 && "Angle:".equals(label)) - digits = 2; - double scale = 1.0 / Math.abs(stepSize); - if (scale <= 0) - scale = 1; - if (defaultValue < minValue) - defaultValue = minValue; - if (defaultValue > maxValue) - defaultValue = maxValue; - minValue *= scale; - maxValue *= scale; - defaultValue *= scale; - addSlider(label, minValue, maxValue, defaultValue, scale, digits); - } - - /** Author: Michael Kaul */ - private static int digits(double d) { - if (d == (int) d) - return 0; - String s = Double.toString(d); - int ePos = s.indexOf("E"); - if (ePos == -1) - ePos = s.indexOf("e"); - int dotPos = s.indexOf("."); - int digits = 0; - if (ePos == -1) - digits = s.substring(dotPos + 1).length(); - else { - String number = s.substring(dotPos + 1, ePos); - if (!number.equals("0")) - digits += number.length(); - digits = digits - Integer.valueOf(s.substring(ePos + 1)); - } - return digits; - } - - private void addSlider(String label, double minValue, double maxValue, double defaultValue, double scale, int digits) { - int columns = 4 + digits - 2; - if (columns < 4) - columns = 4; - if (minValue < 0.0) - columns++; - String mv = IJ.d2s(maxValue, 0); - if (mv.length() > 4 && digits == 0) - columns += mv.length() - 4; - String label2 = label; - if (label2.indexOf('_') != -1) - label2 = label2.replace('_', ' '); - Label fieldLabel = makeLabel(label2); - this.lastLabelAdded = fieldLabel; - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - c.insets.bottom += 3; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - c.insets = getInsets(0, 0, 3, 0); // top, left, bottom, right - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = 1; - add(fieldLabel, c); - - if (slider == null) { - slider = new Vector(5); - sliderIndexes = new Vector(5); - sliderScales = new Vector(5); - sliderDigits = new Vector(5); - } - Scrollbar s = new Scrollbar(Scrollbar.HORIZONTAL, (int) defaultValue, 1, (int) minValue, (int) maxValue + 1); - if (IJ.debugMode) - IJ.log("Scrollbar: " + scale + " " + defaultValue + " " + minValue + " " + maxValue); - GUI.fixScrollbar(s); - slider.addElement(s); - s.addAdjustmentListener(this); - s.setUnitIncrement(1); - if (IJ.isMacOSX()) - s.addKeyListener(this); - s.addMouseWheelListener(new MouseWheelListener() { - public void mouseWheelMoved(MouseWheelEvent e) { - Scrollbar sb = (Scrollbar) e.getSource(); - int value = sb.getValue() + e.getWheelRotation(); - sb.setValue(value); - for (int i = 0; i < slider.size(); i++) { - if (sb == slider.elementAt(i)) { - int index = ((Integer) sliderIndexes.get(i)).intValue(); - TextField tf = (TextField) numberField.elementAt(index); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - int digits = ((Integer) sliderDigits.get(i)).intValue(); - tf.setText("" + IJ.d2s(sb.getValue() / scale, digits)); - } - } - } - }); - - if (numberField == null) { - numberField = new Vector(5); - defaultValues = new Vector(5); - defaultText = new Vector(5); - } - if (IJ.isWindows()) - columns -= 2; - if (columns < 1) - columns = 1; - // IJ.log("scale=" + scale + ", columns=" + columns + ", digits=" + digits); - TextField tf = newTextField(IJ.d2s(defaultValue / scale, digits), columns); - // if (IJ.isLinux()) tf.setBackground(Color.white); - tf.setBackground(Color.white); - tf.addActionListener(this); - tf.addTextListener(this); - tf.addFocusListener(this); - tf.addKeyListener(this); - numberField.addElement(tf); - sliderIndexes.add(Integer.valueOf(numberField.size() - 1)); - sliderScales.add(Double.valueOf(scale)); - sliderDigits.add(Integer.valueOf(digits)); - defaultValues.addElement(Double.valueOf(defaultValue / scale)); - defaultText.addElement(tf.getText()); - tf.setEditable(true); - firstSlider = false; - - JPanel panel = new JPanel(); - GridBagLayout pgrid = new GridBagLayout(); - GridBagConstraints pc = new GridBagConstraints(); - panel.setLayout(pgrid); - pc.gridx = 0; - pc.gridy = 0; - pc.gridwidth = 1; - pc.ipadx = 85; - pc.anchor = GridBagConstraints.WEST; - panel.add(s, pc); - pc.ipadx = 0; // reset - // text field - pc.gridx = 1; - pc.insets = new Insets(5, 5, 0, 0); - pc.anchor = GridBagConstraints.EAST; - panel.add(tf, pc); - - c.gridx = GridBagConstraints.RELATIVE; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - c.insets.left = 0; - c.insets.bottom -= 3; - add(panel, c); - if (IJ.recording() || macro) - saveLabel(tf, label); - } - - private TextField newTextField(String txt, int columns) { - if (IJ.isLinux()) - return new TrimmedTextField(txt, columns); - else - return new TextField(txt, columns); - } - - /* Changed for Bio7! -> Added JPanel method! */ - public void addPanel(JPanel panel) { - addPanel(panel, GridBagConstraints.WEST, addToSameRow ? c.insets : getInsets(5, 0, 0, 0)); - } - - /** Adds a Panel to the dialog. */ - /** Adds a Panel to the dialog. */ - public void addPanel(Panel panel) { - addPanel(panel, GridBagConstraints.WEST, addToSameRow ? c.insets : getInsets(5, 0, 0, 0)); - } - - /* - * public void addPanel(Panel panel) { addPanel(panel , GridBagConstraints.WEST, - * new Insets(5, 0, 0, 0)); } - */ - // extra method to avoid plugin mistake - /* - * public void addPanel(Panel panel) { JPanel panel2 = new JPanel(); Component[] - * comp = panel.getComponents(); for (int i = 0; i < comp.length; i++) { - * panel2.add(comp[i]); } - * - * addPanel(panel, GridBagConstraints.WEST, addToSameRow ? c.insets : - * getInsets(5, 0, 0, 0)); } - */ - - /* Changed for Bio7! -> Extra method for plugins! */ - public void addPanel(Panel panel, int constraints, Insets insets) { - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - } - c.gridwidth = 2; - c.anchor = constraints; - c.insets = insets; - add(panel, c); - } - - /** - * Adds a Panel to the dialog with custom contraint and insets. The defaults are - * GridBagConstraints.WEST (left justified) and "new Insets(5, 0, 0, 0)" (5 - * pixels of padding at the top). - */ - public void addPanel(JPanel panel, int constraints, Insets insets) { - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - addToSameRow = false; - } else { - c.gridx = 0; - c.gridy++; - } - c.gridwidth = 2; - c.anchor = constraints; - c.insets = insets; - add(panel, c); - } - - /** Adds an image to the dialog. */ - public void addImage(ImagePlus image) { - if (image == null) - return; - ImagePanel imagePanel = new ImagePanel(image); - addPanel(imagePanel); - if (imagePanels == null) - imagePanels = new Vector(); - imagePanels.add(imagePanel); - } - - /** - * Set the insets (margins), in pixels, that will be used for the next component - * added to the dialog (except components added to the same row with - * addToSameRow) - * - * - Default insets: - addMessage: 0,20,0 (empty string) or 10,20,0 - addCheckbox: 15,20,0 (first checkbox) or 0,20,0 - addCheckboxGroup: 10,0,0 - addRadioButtonGroup: 5,10,0 - addNumericField: 5,0,3 (first field) or 0,0,3 - addStringField: 5,0,5 (first field) or 0,0,5 - addChoice: 5,0,5 (first field) or 0,0,5 - * - */ - public void setInsets(int top, int left, int bottom) { - topInset = top; - leftInset = left; - bottomInset = bottom; - customInsets = true; - } - - /** - * Makes the next item appear in the same row as the previous. May be used for - * addNumericField, addSlider, addChoice, addCheckbox, addStringField, - * addMessage, addPanel, and before the showDialog() method (in the latter case, - * the buttons appear to the right of the previous item). Note that addMessage - * (and addStringField, if its column width is more than 8) use the remaining - * width, so it must be the last item of a row. - */ - public void addToSameRow() { - addToSameRow = true; - addToSameRowCalled = true; - } - - /** Sets a replacement label for the "OK" button. */ - public void setOKLabel(String label) { - okay.setLabel(label); - } - - /** Sets a replacement label for the "Cancel" button. */ - public void setCancelLabel(String label) { - cancel.setLabel(label); - } - - /** Sets a replacement label for the "Help" button. */ - public void setHelpLabel(String label) { - helpLabel = label; - } - - /** Unchanged parameters are not recorder in 'smart recording' mode. */ - public void setSmartRecording(boolean smartRecording) { - this.smartRecording = smartRecording; - } - - /** Make this a "Yes No Cancel" dialog. */ - public void enableYesNoCancel() { - enableYesNoCancel(" Yes ", " No "); - } - - /** - * Make this a "Yes No Cancel" dialog with custom labels. Here is an example: - * - * - * GenericDialog gd = new GenericDialog("YesNoCancel Demo"); - * gd.addMessage("This is a custom YesNoCancel dialog"); - * gd.enableYesNoCancel("Do something", "Do something else"); - * gd.showDialog(); - * if (gd.wasCanceled()) - * IJ.log("User clicked 'Cancel'"); - * else if (gd.wasOKed()) - * IJ.log("User clicked 'Yes'"); - * else - * IJ.log("User clicked 'No'"); - * - */ - public void enableYesNoCancel(String yesLabel, String noLabel) { - okay.setLabel(yesLabel); - if (no != null) - no.setLabel(noLabel); - else if (noLabel != null) - no = new Button(noLabel); - } - - /** Do not display "Cancel" button. */ - public void hideCancelButton() { - hideCancelButton = true; - } - - Insets getInsets(int top, int left, int bottom, int right) { - if (customInsets) { - customInsets = false; - return new Insets(topInset, leftInset, bottomInset, 0); - } else - return new Insets(top, left, bottom, right); - } - - /** - * Add an Object implementing the DialogListener interface. This object will be - * notified by its dialogItemChanged method of input to the dialog. The first - * DialogListener will be also called after the user has typed 'OK' or if the - * dialog has been invoked by a macro; it should read all input fields of the - * dialog. For other listeners, the OK button will not cause a call to - * dialogItemChanged; the CANCEL button will never cause such a call. - * - * @param dl the Object that wants to listen. - */ - public void addDialogListener(DialogListener dl) { - if (dialogListeners == null) - dialogListeners = new Vector(); - dialogListeners.addElement(dl); - } - - /** Returns true if the user clicked on "Cancel". */ - public boolean wasCanceled() { - if (wasCanceled && !Thread.currentThread().getName().endsWith("Script_Macro$")) - Macro.abort(); - return wasCanceled; - } - - /** Returns true if the user has clicked on "OK" or a macro is running. */ - public boolean wasOKed() { - return wasOKed || macro; - } - - /** - * Returns the contents of the next numeric field, or NaN if the field does not - * contain a number. - */ - public double getNextNumber() { - if (numberField == null) - return -1.0; - TextField tf = (TextField) numberField.elementAt(nfIndex); - String theText = tf.getText(); - String label = null; - if (macro) { - label = (String) labels.get((Object) tf); - theText = Macro.getValue(macroOptions, label, theText); - } - String originalText = (String) defaultText.elementAt(nfIndex); - double defaultValue = ((Double) (defaultValues.elementAt(nfIndex))).doubleValue(); - double value; - boolean skipRecording = false; - if (theText.equals(originalText)) { - value = defaultValue; - if (smartRecording) - skipRecording = true; - } else if (theText.startsWith("0x")) { - value = parseHex(theText.substring(2)); - } else { - Double d = getValue(theText); - if (d != null) - value = d.doubleValue(); - else { - // Is the value a macro variable? - if (theText.startsWith("&")) - theText = theText.substring(1); - Interpreter interp = Interpreter.getInstance(); - value = interp != null ? interp.getVariable2(theText) : Double.NaN; - if (Double.isNaN(value)) { - invalidNumber = true; - errorMessage = "\"" + theText + "\" is an invalid number"; - value = Double.NaN; - if (macro) { - IJ.error("Macro Error", "Numeric value expected in run() function\n \n" + " Dialog box title: \"" + getTitle() + "\"\n" + " Key: \"" + label.toLowerCase(Locale.US) + "\"\n" - + " Value or variable name: \"" + theText + "\""); - } - } - } - } - if (recorderOn && !skipRecording) { - recordOption(tf, trim(theText)); - } - nfIndex++; - return value; - } - - int parseHex(String hexString) { - int n = 0; - ; - try { - n = Integer.parseInt(hexString, 16); - } catch (NumberFormatException e) { - } - return n; - } - - private String trim(String value) { - if (value.endsWith(".0")) - value = value.substring(0, value.length() - 2); - if (value.endsWith(".00")) - value = value.substring(0, value.length() - 3); - return value; - } - - private void recordOption(Object component, String value) { - if (labels == null) - return; - String label = (String) labels.get(component); - if (value.equals("")) - value = "[]"; - Recorder.recordOption(label, value); - } - - private void recordCheckboxOption(Checkbox cb) { - if (labels == null) - return; - String label = (String) labels.get((Object) cb); - if (label != null) { - if (cb.getState()) // checked - Recorder.recordOption(label); - else if (Recorder.getCommandOptions() == null) - Recorder.recordOption(" "); - } - } - - /* Bio7 extra method! */ - private void recordCheckboxOption(JCheckBox cb) { - if (labels == null) - return; - String label = (String) labels.get((Object) cb); - if (label != null) { - if (cb.isSelected()) // checked - Recorder.recordOption(label); - else if (Recorder.getCommandOptions() == null) - Recorder.recordOption(" "); - } - } - - protected Double getValue(String text) { - Double d; - try { - d = Double.valueOf(text); - } catch (NumberFormatException e) { - d = null; - } - return d; - } - - public double parseDouble(String s) { - if (s == null) - return Double.NaN; - double value = Tools.parseDouble(s); - if (Double.isNaN(value)) { - if (s.startsWith("&")) - s = s.substring(1); - Interpreter interp = Interpreter.getInstance(); - value = interp != null ? interp.getVariable2(s) : Double.NaN; - } - return value; - } - - /** - * Returns true if one or more of the numeric fields contained an invalid - * number. Must be called after one or more calls to getNextNumber(). - */ - public boolean invalidNumber() { - boolean wasInvalid = invalidNumber; - invalidNumber = false; - return wasInvalid; - } - - /** - * Returns an error message if getNextNumber was unable to convert a string into - * a number, otherwise, returns null. - */ - public String getErrorMessage() { - return errorMessage; - } - - /** Returns the contents of the next text field. */ - public String getNextString() { - String theText; - if (stringField == null) - return ""; - TextField tf = (TextField) (stringField.elementAt(sfIndex)); - theText = tf.getText(); - String label = labels != null ? (String) labels.get((Object) tf) : ""; - boolean numberExpected = theText != null && theText.length() > 0 && (Character.isDigit(theText.charAt(0)) || theText.startsWith("-")); - if (macro) { - theText = Macro.getValue(macroOptions, label, theText); - if (theText != null && (theText.startsWith("&") || numberExpected || label.toLowerCase(Locale.US).startsWith(theText))) { - // Is the value a macro variable? - if (theText.startsWith("&")) - theText = theText.substring(1); - Interpreter interp = Interpreter.getInstance(); - String s = interp != null ? interp.getVariableAsString(theText) : null; - if (s != null) - theText = s; - } - } - if (recorderOn && !label.equals("")) { - String s = theText; - if (s != null && s.length() >= 3 && Character.isLetter(s.charAt(0)) && s.charAt(1) == ':' && s.charAt(2) == '\\') - s = s.replaceAll("\\\\", "/"); // replace "\" with "/" in Windows file paths - s = Recorder.fixString(s); - if (!smartRecording || !s.equals((String) defaultStrings.elementAt(sfIndex))) - recordOption(tf, s); - else if (Recorder.getCommandOptions() == null) - Recorder.recordOption(" "); - } - sfIndex++; - return theText; - } - - /** Returns the state of the next checkbox. */ - public boolean getNextBoolean() { - if (checkbox == null) - return false; - /* Bio7 extra check for JCheckBox! */ - if (checkbox.elementAt(cbIndex) instanceof JCheckBox) { - JCheckBox cb = (JCheckBox) (checkbox.elementAt(cbIndex)); - if (recorderOn) - recordCheckboxOption(cb); - boolean state = cb.isSelected(); - if (macro) { - String label = (String) labels.get((Object) cb); - String key = Macro.trimKey(label); - state = isMatch(macroOptions, key + " "); - } - cbIndex++; - return state; - } else { - Checkbox cb = (Checkbox) (checkbox.elementAt(cbIndex)); - if (recorderOn) - recordCheckboxOption(cb); - boolean state = cb.getState(); - if (macro) { - String label = (String) labels.get((Object) cb); - String key = Macro.trimKey(label); - state = isMatch(macroOptions, key + " "); - } - cbIndex++; - return state; - - } - - } - - // Returns true if s2 is in s1 and not in a bracketed literal (e.g., - // "[literal]") - boolean isMatch(String s1, String s2) { - if (s1.startsWith(s2)) - return true; - s2 = " " + s2; - int len1 = s1.length(); - int len2 = s2.length(); - boolean match, inLiteral = false; - char c; - for (int i = 0; i < len1 - len2 + 1; i++) { - c = s1.charAt(i); - if (inLiteral && c == ']') - inLiteral = false; - else if (c == '[') - inLiteral = true; - if (c != s2.charAt(0) || inLiteral || (i > 1 && s1.charAt(i - 1) == '=')) - continue; - match = true; - for (int j = 0; j < len2; j++) { - if (s2.charAt(j) != s1.charAt(i + j)) { - match = false; - break; - } - } - if (match) - return true; - } - return false; - } - - /** Returns the selected item in the next popup menu. */ - public String getNextChoice() { - if (choice == null) - return ""; - Choice thisChoice = (Choice) (choice.elementAt(choiceIndex)); - String item = thisChoice.getSelectedItem(); - if (macro) { - String label = (String) labels.get((Object) thisChoice); - item = Macro.getValue(macroOptions, label, item); - if (item != null && item.startsWith("&")) // value is macro variable - item = getChoiceVariable(item); - } - if (recorderOn) - recordOption(thisChoice, item); - choiceIndex++; - return item; - } - - /** Returns the index of the selected item in the next popup menu. */ - public int getNextChoiceIndex() { - if (choice == null) - return -1; - Choice thisChoice = (Choice) (choice.elementAt(choiceIndex)); - int index = thisChoice.getSelectedIndex(); - if (macro) { - String label = (String) labels.get((Object) thisChoice); - String oldItem = thisChoice.getSelectedItem(); - int oldIndex = thisChoice.getSelectedIndex(); - String item = Macro.getValue(macroOptions, label, oldItem); - if (item != null && item.startsWith("&")) // value is macro variable - item = getChoiceVariable(item); - thisChoice.select(item); - index = thisChoice.getSelectedIndex(); - if (index == oldIndex && !item.equals(oldItem)) { - // is value a macro variable? - Interpreter interp = Interpreter.getInstance(); - String s = interp != null ? interp.getStringVariable(item) : null; - if (s == null) - IJ.error(getTitle(), "\"" + item + "\" is not a valid choice for \"" + label + "\""); - else - item = s; - } - } - if (recorderOn) { - int defaultIndex = ((Integer) (defaultChoiceIndexes.elementAt(choiceIndex))).intValue(); - if (!(smartRecording && index == defaultIndex)) { - String item = thisChoice.getSelectedItem(); - if (!(item.equals("*None*") && getTitle().equals("Merge Channels"))) - recordOption(thisChoice, thisChoice.getSelectedItem()); - } - } - choiceIndex++; - return index; - } - - /** Returns the selected item in the next radio button group. */ - public String getNextRadioButton() { - if (radioButtonGroups == null) - return null; - CheckboxGroup cg = (CheckboxGroup) (radioButtonGroups.elementAt(radioButtonIndex)); - radioButtonIndex++; - Checkbox checkbox = cg.getSelectedCheckbox(); - String item = "null"; - if (checkbox != null) - item = checkbox.getLabel(); - if (macro) { - String label = (String) labels.get((Object) cg); - item = Macro.getValue(macroOptions, label, item); - } - if (recorderOn) - recordOption(cg, item); - return item; - } - - private String getChoiceVariable(String item) { - item = item.substring(1); - Interpreter interp = Interpreter.getInstance(); - String s = interp != null ? interp.getStringVariable(item) : null; - if (s == null) { - double value = interp != null ? interp.getVariable2(item) : Double.NaN; - if (!Double.isNaN(value)) { - if ((int) value == value) - s = "" + (int) value; - else - s = "" + value; - } - } - if (s != null) - item = s; - return item; - } - - /** Returns the contents of the next text area. */ - public String getNextText() { - String text = null; - String key = "text1"; - if (textAreaIndex == 0 && textArea1 != null) { - text = textArea1.getText(); - if (macro) - text = Macro.getValue(macroOptions, "text1", text); - } else if (textAreaIndex == 1 && textArea2 != null) { - text = textArea2.getText(); - if (macro) - text = Macro.getValue(macroOptions, "text2", text); - key = "text2"; - } - textAreaIndex++; - if (recorderOn && text != null) { - String text2 = text; - String cmd = Recorder.getCommand(); - if (cmd != null && cmd.equals("Calibrate...")) - text2 = text2.replace('\n', ' '); - if (cmd != null && cmd.equals("Convolve...")) { - if (!text2.endsWith("\n")) - text2 += "\n"; - } - text2 = Recorder.fixString(text2); - Recorder.recordOption(key, text2); - } - return text; - } - - /** Displays this dialog box. */ - public void showDialog() { - showDialogCalled = true; - addToSameRow = false; - if (macro) { - dispose(); - recorderOn = Recorder.record && Recorder.recordInMacros; - } else { - if (pfr != null) // prepare preview (not in macro mode): tell the PlugInFilterRunner to listen - pfr.setDialog(this); - JPanel buttons = new JPanel(); - buttons.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 0)); - okay.addActionListener(this); - okay.addKeyListener(this); - if (!hideCancelButton) { - cancel.addActionListener(this); - cancel.addKeyListener(this); - } - if (no != null) { - no.addActionListener(this); - no.addKeyListener(this); - } - - boolean addHelp = helpURL != null; - if (addHelp) { - help.setLabel(helpLabel); - help.addActionListener(this); - help.addKeyListener(this); - } - if (IJ.isWindows() || Prefs.dialogCancelButtonOnRight) { - buttons.add(okay); - if (no != null) - buttons.add(no); - ; - if (!hideCancelButton) - buttons.add(cancel); - if (addHelp) - buttons.add(help); - } else { - if (addHelp) - buttons.add(help); - if (no != null) - buttons.add(no); - if (!hideCancelButton) - buttons.add(cancel); - buttons.add(okay); - } - if (addToSameRow) { - c.gridx = GridBagConstraints.RELATIVE; - } else { - c.gridx = 0; - c.gridy++; - } - c.anchor = GridBagConstraints.EAST; - c.gridwidth = addToSameRowCalled ? GridBagConstraints.REMAINDER : 2; - c.insets = new Insets(15, 0, 0, 0); - add(buttons, c); - instance = this; - Font font = getFont(); - if (!fontSizeSet && font != null && Prefs.getGuiScale() != 1.0) { - fontSizeSet = true; - setFont(font.deriveFont((float) (font.getSize() * Prefs.getGuiScale()))); - } - pack(); - if (okay != null && numberField == null && stringField == null && checkbox == null && choice == null && slider == null && radioButtonGroups == null && textArea1 == null) - okay.requestFocusInWindow(); - setup(); - if (centerDialog) - GUI.centerOnImageJScreen(this); - resetCounters(); - setVisible(true); // except for NonBlockingGenericDialog, returns after 'dispose' by OK or Cancel - } - } - - /** - * For plugins that read their input only via dialogItemChanged, call it at - * least once, then stop recording - */ - void finalizeRecording() { - if (optionsRecorded) - return; - optionsRecorded = true; - if (!wasCanceled && dialogListeners != null && dialogListeners.size() > 0) { - try { - resetCounters(); - ((DialogListener) dialogListeners.elementAt(0)).dialogItemChanged(this, null); - } catch (Exception err) { // for exceptions, don't cover the input by a window - IJ.beep(); // but show them at in the "Log" - IJ.log("ERROR: " + err + "\nin DialogListener of " + dialogListeners.elementAt(0) + "\nat " + (err.getStackTrace()[0]) + "\nfrom " + (err.getStackTrace()[1])); - } - recorderOn = false; - } - resetCounters(); - } - - @Override - public void setFont(Font font) { - super.setFont(!fontSizeSet && Prefs.getGuiScale() != 1.0 && font != null ? font.deriveFont((float) (font.getSize() * Prefs.getGuiScale())) : font); - fontSizeSet = true; - } - - /** Reset the counters before reading the dialog parameters */ - public void resetCounters() { - nfIndex = 0; // prepare for readout - sfIndex = 0; - cbIndex = 0; - choiceIndex = 0; - textAreaIndex = 0; - radioButtonIndex = 0; - invalidNumber = false; - } - - /** Returns the Vector containing the numeric TextFields. */ - public Vector getNumericFields() { - return numberField; - } - - /** Returns the Vector containing the string TextFields. */ - public Vector getStringFields() { - return stringField; - } - - /** Returns the Vector containing the Checkboxes. */ - public Vector getCheckboxes() { - return checkbox; - } - - /** Returns the Vector containing the Choices. */ - public Vector getChoices() { - return choice; - } - - /** Returns the Vector containing the sliders (Scrollbars). */ - public Vector getSliders() { - return slider; - } - - /** Returns the Vector that contains the RadioButtonGroups. */ - public Vector getRadioButtonGroups() { - return radioButtonGroups; - } - - /** Returns a reference to textArea1. */ - public TextArea getTextArea1() { - return textArea1; - } - - /** Returns a reference to textArea2. */ - public TextArea getTextArea2() { - return textArea2; - } - - /** - * Returns a reference to the Label or MultiLineLabel created by the last - * addMessage() call. Otherwise returns null. - */ - public Component getMessage() { - return theLabel; - } - - /** Returns a reference to the Preview checkbox. */ - public Checkbox getPreviewCheckbox() { - return previewCheckbox; - } - - /** Returns 'true' if this dialog has a "Preview" checkbox and it is enabled. */ - public boolean isPreviewActive() { - return previewCheckbox != null && previewCheckbox.getState(); - } - - /** - * Returns references to the "OK" ("Yes"), "Cancel", * "No", and "Help" buttons - * as an array of length 4. If a button is not present, the corresponding array - * element is null. - */ - public Button[] getButtons() { - return new Button[] { okay, cancel, no, help }; - } - - /** - * Used by PlugInFilterRunner to provide visable feedback whether preview is - * running or not by switching from "Preview" to "wait..." - */ - public void previewRunning(boolean isRunning) { - if (previewCheckbox != null) { - previewCheckbox.setLabel(isRunning ? previewRunning : previewLabel); - if (IJ.isMacOSX()) - repaint(); // workaround OSX 10.4 refresh bug - } - } - - /** Display dialog centered on the primary screen. */ - public void centerDialog(boolean b) { - centerDialog = b; - } - - /* Display the dialog at the specified location. */ - public void setLocation(int x, int y) { - super.setLocation(x, y); - centerDialog = false; - } - - public void setDefaultString(int index, String str) { - if (defaultStrings != null && index >= 0 && index < defaultStrings.size()) - defaultStrings.set(index, str); - } - - protected void setup() { - } - - public void actionPerformed(ActionEvent e) { - Object source = e.getSource(); - if (source == okay || source == cancel | source == no) { - wasCanceled = source == cancel; - wasOKed = source == okay; - dispose(); - } else if (source == help) { - if (hideCancelButton) { - if (helpURL != null && helpURL.equals("")) { - notifyListeners(e); - return; - } else { - wasOKed = true; - dispose(); - } - } - showHelp(); - } else - notifyListeners(e); - } - - public void textValueChanged(TextEvent e) { - notifyListeners(e); - if (slider == null) - return; - Object source = e.getSource(); - for (int i = 0; i < slider.size(); i++) { - int index = ((Integer) sliderIndexes.get(i)).intValue(); - if (source == numberField.elementAt(index)) { - TextField tf = (TextField) numberField.elementAt(index); - double value = Tools.parseDouble(tf.getText()); - if (!Double.isNaN(value)) { - Scrollbar sb = (Scrollbar) slider.elementAt(i); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - sb.setValue((int) Math.round(value * scale)); - } - } - } - } - - public void itemStateChanged(ItemEvent e) { - notifyListeners(e); - } - - public void focusGained(FocusEvent e) { - Component c = e.getComponent(); - // IJ.log("focusGained: "+c); - if (c instanceof TextField) - ((TextField) c).selectAll(); - } - - public void focusLost(FocusEvent e) { - Component c = e.getComponent(); - if (c instanceof TextField) - ((TextField) c).select(0, 0); - } - - public void keyPressed(KeyEvent e) { - Component component = e.getComponent(); - int keyCode = e.getKeyCode(); - IJ.setKeyDown(keyCode); - if ((component instanceof Scrollbar) && (keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT)) { - Scrollbar sb = (Scrollbar) component; - int value = sb.getValue(); - if (keyCode == KeyEvent.VK_RIGHT) - sb.setValue(value + 1); - else - sb.setValue(value - 1); - for (int i = 0; i < slider.size(); i++) { - if (sb == slider.elementAt(i)) { - int index = ((Integer) sliderIndexes.get(i)).intValue(); - TextField tf = (TextField) numberField.elementAt(index); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - int digits = ((Integer) sliderDigits.get(i)).intValue(); - tf.setText("" + IJ.d2s(sb.getValue() / scale, digits)); - } - } - notifyListeners(e); - return; - } - if (keyCode == KeyEvent.VK_ENTER && textArea1 == null && okay != null && okay.isEnabled()) { - wasOKed = true; - if (IJ.isMacOSX()) - accessTextFields(); - dispose(); - } else if (keyCode == KeyEvent.VK_ESCAPE) { - wasCanceled = true; - dispose(); - IJ.resetEscape(); - } else if (keyCode == KeyEvent.VK_W && (e.getModifiers() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0) { - wasCanceled = true; - dispose(); - } - } - - void accessTextFields() { - if (stringField != null) { - for (int i = 0; i < stringField.size(); i++) - ((TextField) (stringField.elementAt(i))).getText(); - } - if (numberField != null) { - for (int i = 0; i < numberField.size(); i++) - ((TextField) (numberField.elementAt(i))).getText(); - } - } - - public void keyReleased(KeyEvent e) { - int keyCode = e.getKeyCode(); - IJ.setKeyUp(keyCode); - int flags = e.getModifiers(); - boolean control = (flags & KeyEvent.CTRL_MASK) != 0; - boolean meta = (flags & KeyEvent.META_MASK) != 0; - boolean shift = (flags & e.SHIFT_MASK) != 0; - if (keyCode == KeyEvent.VK_G && shift && (control || meta)) - new ScreenGrabber().run(""); - } - - public void keyTyped(KeyEvent e) { - } - - public Insets getInsets() { - Insets i = super.getInsets(); - return new Insets(i.top + 10, i.left + 10, i.bottom + 10, i.right + 10); - } - - /** Callback for sliders */ - public void adjustmentValueChanged(AdjustmentEvent e) { - Object source = e.getSource(); - for (int i = 0; i < slider.size(); i++) { - if (source == slider.elementAt(i)) { - Scrollbar sb = (Scrollbar) source; - int index = ((Integer) sliderIndexes.get(i)).intValue(); - TextField tf = (TextField) numberField.elementAt(index); - double scale = ((Double) sliderScales.get(i)).doubleValue(); - int digits = ((Integer) sliderDigits.get(i)).intValue(); - tf.setText("" + IJ.d2s(sb.getValue() / scale, digits)); - } - } - } - - /** - * Notify any DialogListeners of changes having occurred If a listener returns - * false, do not call further listeners and disable the OK button and preview - * Checkbox (if it exists). For PlugInFilters, this ensures that the - * PlugInFilterRunner, which listens as the last one, is not called if the - * PlugInFilter has detected invalid parameters. Thus, unnecessary calling the - * run(ip) method of the PlugInFilter for preview is avoided in that case. - */ - private void notifyListeners(AWTEvent e) { - if (dialogListeners == null) - return; - boolean everythingOk = true; - for (int i = 0; everythingOk && i < dialogListeners.size(); i++) { - try { - resetCounters(); - if (this instanceof NonBlockingGenericDialog) - Recorder.resetCommandOptions(); - if (!((DialogListener) dialogListeners.elementAt(i)).dialogItemChanged(this, e)) - everythingOk = false; // disable further listeners if false (invalid parameters) returned - } catch (Exception err) { // for exceptions, don't cover the input by a window but - IJ.beep(); // show them at in the "Log" - IJ.log("ERROR: " + err + "\nin DialogListener of " + dialogListeners.elementAt(i) + "\nat " + (err.getStackTrace()[0]) + "\nfrom " + (err.getStackTrace()[1])); - } - } - resetCounters(); - boolean workaroundOSXbug = IJ.isMacOSX() && okay != null && !okay.isEnabled() && everythingOk; - if (everythingOk && recorderOn) - optionsRecorded = true; - if (previewCheckbox != null) - previewCheckbox.setEnabled(everythingOk); - if (okay != null) - okay.setEnabled(everythingOk); - if (workaroundOSXbug) - repaint(); // OSX 10.4 bug delays update of enabled until the next input - } - - public void repaint() { - super.repaint(); - if (imagePanels != null) { - for (int i = 0; i < imagePanels.size(); i++) - ((ImagePanel) imagePanels.get(i)).repaint(); - } - } - - public void paint(Graphics g) { - super.paint(g); - if (firstPaint && IJ.isMacOSX() && IJ.isJava18()) { // fix for incompletely drawn dialogs on Macs - EventQueue.invokeLater(new Runnable() { - public void run() { - IJ.wait(50); - Dimension size = getSize(); - if (size != null) - setSize(size.width + 2, size.height + 2); - firstPaint = false; - } - }); - } - } - - public void windowClosing(WindowEvent e) { - wasCanceled = true; - dispose(); - } - - /** - * Adds a "Help" button that opens the specified URL in the default browser. - * With v1.46b or later, displays an HTML formatted message if 'url' starts with - * "". There is an example at - * http://imagej.net/ij/macros/js/DialogWithHelp.js If url is an empty String, - * pressing the "Help" button does nothing except calling the DialogListeners - * (if any). See also: setHelpLabel. - */ - public void addHelp(String url) { - help = new Button(helpLabel); - helpURL = url; - } - - void showHelp() { - if (helpURL.startsWith("")) { - String title = getTitle() + " " + helpLabel; - if (this instanceof NonBlockingGenericDialog) - new HTMLDialog(title, helpURL, false); // non blocking - else - new HTMLDialog(this, title, helpURL); // modal - } else { - String macro = "call('ij.plugin.BrowserLauncher.open', '" + helpURL + "');"; - new MacroRunner(macro); // open on separate thread using BrowserLauncher - } - } - - protected boolean isMacro() { - return macro; - } - - public static GenericDialog getInstance() { - return instance; - } - - /** Closes the dialog; records the options */ - public void dispose() { - super.dispose(); - instance = null; - if (!macro) { - recorderOn = Recorder.record; - IJ.wait(25); - } - resetCounters(); - finalizeRecording(); - resetCounters(); - } - - /** - * Returns a reference to the label of the most recently added numeric field, - * string field, choice or slider. - */ - public Label getLabel() { - return lastLabelAdded; - } - - public void windowActivated(WindowEvent e) { - } - - public void windowOpened(WindowEvent e) { - } - - public void windowClosed(WindowEvent e) { - } - - public void windowIconified(WindowEvent e) { - } - - public void windowDeiconified(WindowEvent e) { - } - - public void windowDeactivated(WindowEvent e) { - } - - @SuppressWarnings("unchecked") - static String getString(DropTargetDropEvent event) throws IOException, UnsupportedFlavorException { - String text = null; - DataFlavor fileList = DataFlavor.javaFileListFlavor; - - if (event.isDataFlavorSupported(fileList)) { - event.acceptDrop(DnDConstants.ACTION_COPY); - java.util.List list = (java.util.List) event.getTransferable().getTransferData(fileList); - text = list.get(0).getAbsolutePath(); - } else if (event.isDataFlavorSupported(DataFlavor.stringFlavor)) { - event.acceptDrop(DnDConstants.ACTION_COPY); - text = (String) event.getTransferable().getTransferData(DataFlavor.stringFlavor); - if (text.startsWith("file://")) - text = text.substring(7); - text = stripSuffix(stripSuffix(text, "\n"), "\r").replaceAll("%20", " "); - } else { - event.rejectDrop(); - return null; - } - - event.dropComplete(text != null); - return text; - } - - static String stripSuffix(String s, String suffix) { - return !s.endsWith(suffix) ? s : s.substring(0, s.length() - suffix.length()); - } - - static class TextDropTarget extends DropTargetAdapter { - TextField text; - DataFlavor flavor = DataFlavor.stringFlavor; - - public TextDropTarget(TextField text) { - this.text = text; - } - - @Override - public void drop(DropTargetDropEvent event) { - try { - String path = getString(event); - path = Recorder.fixPath(path); - if (!path.endsWith("/") && (new File(path)).isDirectory()) - path = path + "/"; - text.setText(path); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - private class BrowseButtonListener implements ActionListener { - private String label; - private TextField textField; - private String mode; - - public BrowseButtonListener(String label, TextField textField, String mode) { - this.label = label; - this.textField = textField; - this.mode = mode; - } - - public void actionPerformed(ActionEvent e) { - String path = null; - String dialogTitle = label; - if (dialogTitle == null || dialogTitle.length() == 0) - dialogTitle = mode.equals("dir") ? "a Folder" : "a File"; - else if (dialogTitle.endsWith(":")) // remove trailing colon - dialogTitle = dialogTitle.substring(0, dialogTitle.length() - 1); - dialogTitle = "Select " + dialogTitle; - if (mode.equals("dir")) { - String saveDefaultDir = OpenDialog.getDefaultDirectory(); - String dir = this.textField.getText(); - boolean setDefaultDir = dir != null && !dir.equals(""); - if (setDefaultDir) - OpenDialog.setDefaultDirectory(dir); - path = IJ.getDir(dialogTitle); - if (setDefaultDir) - OpenDialog.setDefaultDirectory(saveDefaultDir); - } else { - OpenDialog od = new OpenDialog(dialogTitle, null); - String directory = od.getDirectory(); - String name = od.getFileName(); - if (name != null) - path = directory + name; - } - if (path != null) { - // if (IJ.isWindows()) - // path = path.replaceAll("\\\\", "/"); // replace "\" with "/" - this.textField.setText(path); - } - } - - } - - private class TrimmedTextField extends TextField { - - public TrimmedTextField(String text, int columns) { - super(text, columns); - } - - public Dimension getMinimumSize() { - Dimension d = super.getMinimumSize(); - if (d != null) { - d.width = d.width; - d.height = d.height * 3 / 4; - } - return d; - } - - public Dimension getPreferredSize() { - return getMinimumSize(); - } - - } - - /* Changed for Bio7! */ - - public void componentResized(ComponentEvent e) { - // TODO Auto-generated method stub - validate(); - repaint(); - - } - - @Override - public void componentMoved(ComponentEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void componentShown(ComponentEvent e) { - // TODO Auto-generated method stub - - } - - @Override - public void componentHidden(ComponentEvent e) { - // TODO Auto-generated method stub - - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/HTMLDialog.java b/com.eco.bio7.image/src/ij/gui/HTMLDialog.java deleted file mode 100644 index eb3e98866..000000000 --- a/com.eco.bio7.image/src/ij/gui/HTMLDialog.java +++ /dev/null @@ -1,154 +0,0 @@ -package ij.gui; -import ij.*; -import ij.plugin.URLOpener; -import ij.macro.MacroRunner; -import ij.util.Java2; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.text.*; -import javax.swing.text.html.*; -import javax.swing.event.HyperlinkListener; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkEvent.EventType; -import java.net.URL; - -/** This is modal or non-modal dialog box that displays HTML formated text. */ -public class HTMLDialog extends JDialog implements ActionListener, KeyListener, HyperlinkListener, WindowListener { - private boolean escapePressed; - private JEditorPane editorPane; - private boolean modal = true; - - public HTMLDialog(String title, String message) { - super(ij.IJ.getInstance(), title, true); - init(message); - } - - public HTMLDialog(Dialog parent, String title, String message) { - super(parent, title, true); - init(message); - } - - public HTMLDialog(String title, String message, boolean modal) { - super(ij.IJ.getInstance(), title, modal); - this.modal = modal; - init(message); - } - - private void init(String message) { - LookAndFeel saveLookAndFeel = Java2.getLookAndFeel(); - Java2.setSystemLookAndFeel(); - Container container = getContentPane(); - container.setLayout(new BorderLayout()); - if (message==null) message = ""; - editorPane = new JEditorPane("text/html",""); - editorPane.setEditable(false); - HTMLEditorKit kit = new HTMLEditorKit(); - editorPane.setEditorKit(kit); - StyleSheet styleSheet = kit.getStyleSheet(); - styleSheet.addRule("body{font-family:Verdana,sans-serif; font-size:11.5pt; margin:5px 10px 5px 10px;}"); //top right bottom left - styleSheet.addRule("h1{font-size:18pt;}"); - styleSheet.addRule("h2{font-size:15pt;}"); - styleSheet.addRule("dl dt{font-face:bold;}"); - editorPane.setText(message); //display the html text with the above style - editorPane.getActionMap().put("insert-break", new AbstractAction(){ - public void actionPerformed(ActionEvent e) {} - }); //suppress beep on key - JScrollPane scrollPane = new JScrollPane(editorPane); - container.add(scrollPane); - JButton button = new JButton("OK"); - button.addActionListener(this); - button.addKeyListener(this); - editorPane.addKeyListener(this); - editorPane.addHyperlinkListener(this); - JPanel panel = new JPanel(); - panel.add(button); - container.add(panel, "South"); - setForeground(Color.black); - addWindowListener(this); - pack(); - Dimension screenD = IJ.getScreenSize(); - Dimension dialogD = getSize(); - int maxWidth = (int)(Math.min(0.70*screenD.width, 800)); //max 70% of screen width, but not more than 800 pxl - if (maxWidth>400 && dialogD.width>maxWidth) - dialogD.width = maxWidth; - if ("Channels".equals(getTitle())) - dialogD.height = 1000; - if (dialogD.height>0.80*screenD.height && screenD.height>400) //max 80% of screen height - dialogD.height = (int)(0.80*screenD.height); - setSize(dialogD); - GUI.centerOnImageJScreen(this); - if (!modal) { - WindowManager.addWindow(this); - show(); - } - final JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar(); - if (verticalScrollBar!=null) { - EventQueue.invokeLater(new Runnable() { - public void run() { - verticalScrollBar.setValue(verticalScrollBar.getMinimum()); //start scrollbar at top - } - }); - } - if (modal) show(); - Java2.setLookAndFeel(saveLookAndFeel); - } - - public void actionPerformed(ActionEvent e) { - dispose(); - } - - public void keyPressed(KeyEvent e) { - int keyCode = e.getKeyCode(); - ij.IJ.setKeyDown(keyCode); - escapePressed = keyCode==KeyEvent.VK_ESCAPE; - if (keyCode==KeyEvent.VK_C) { - if (editorPane.getSelectedText()==null || editorPane.getSelectedText().length()==0) - editorPane.selectAll(); - editorPane.copy(); - editorPane.select(0,0); - } else if (keyCode==KeyEvent.VK_ENTER || keyCode==KeyEvent.VK_W || escapePressed) - dispose(); - } - - public void keyReleased(KeyEvent e) { - int keyCode = e.getKeyCode(); - ij.IJ.setKeyUp(keyCode); - } - - public void keyTyped(KeyEvent e) {} - - public boolean escapePressed() { - return escapePressed; - } - - public void hyperlinkUpdate(HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - String url = e.getDescription(); //getURL does not work for relative links within document such as "#top" - if (url==null) return; - if (url.startsWith("#")) - editorPane.scrollToReference(url.substring(1)); - else { - String macro = "run('URL...', 'url="+url+"');"; - new MacroRunner(macro); - } - } - } - - public void dispose() { - super.dispose(); - if (!modal) WindowManager.removeWindow(this); - } - - public void windowClosing(WindowEvent e) { - dispose(); - } - - public void windowActivated(WindowEvent e) {} - public void windowOpened(WindowEvent e) {} - public void windowClosed(WindowEvent e) {} - public void windowIconified(WindowEvent e) {} - public void windowDeiconified(WindowEvent e) {} - public void windowDeactivated(WindowEvent e) {} - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/HistogramPlot.java b/com.eco.bio7.image/src/ij/gui/HistogramPlot.java deleted file mode 100644 index 9271aef4c..000000000 --- a/com.eco.bio7.image/src/ij/gui/HistogramPlot.java +++ /dev/null @@ -1,409 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.plugin.filter.Analyzer; -import ij.measure.*; -import ij.macro.Interpreter; -import java.awt.*; -import java.awt.image.*; - -public class HistogramPlot extends ImagePlus { - static final double SCALE = Prefs.getGuiScale(); - static final int HIST_WIDTH = (int)(SCALE*256); - static final int HIST_HEIGHT = (int)(SCALE*128); - static final int XMARGIN = (int)(20*SCALE); - static final int YMARGIN = (int)(10*SCALE); - /* Changed for Bio7! Correction for the width else no plot is drawn! */ - static final int WIN_WIDTH = HIST_WIDTH + (int) (41 * SCALE); - static final int WIN_HEIGHT = HIST_HEIGHT + (int)(118*SCALE); - static final int BAR_HEIGHT = (int)(SCALE*12); - static final int INTENSITY1=0, INTENSITY2=1, RGB=2, RED=3, GREEN=4, BLUE=5; - static final Color frameColor = new Color(30,60,120); - - int rgbMode = -1; - ImageStatistics stats; - boolean stackHistogram; - Calibration cal; - long[] histogram; - LookUpTable lut; - int decimalPlaces; - int digits; - long newMaxCount; - boolean logScale; - int yMax; - int srcImageID; - Rectangle frame; - Font font = new Font("SansSerif",Font.PLAIN,(int)(12*SCALE)); - boolean showBins; - int col1, col2, row1, row2, row3, row4, row5; - - public HistogramPlot() { - setImage(NewImage.createRGBImage("Histogram", WIN_WIDTH, WIN_HEIGHT, 1, NewImage.FILL_WHITE)); - } - - /** Plots a histogram using the specified title and number of bins. - Currently, the number of bins must be 256 expect for 32 bit images. */ - public void draw(String title, ImagePlus imp, int bins) { - draw(imp, bins, 0.0, 0.0, 0); - } - - /** Plots a histogram using the specified title, number of bins and histogram range. - Currently, the number of bins must be 256 and the histogram range range must be - the same as the image range expect for 32 bit images. */ - public void draw(ImagePlus imp, int bins, double histMin, double histMax, int yMax) { - boolean limitToThreshold = (Analyzer.getMeasurements()&LIMIT)!=0; - ImageProcessor ip = imp.getProcessor(); - if (ip.isThreshold() && ip.getLutUpdateMode()==ImageProcessor.NO_LUT_UPDATE) - limitToThreshold = false; // ignore invisible thresholds - if (imp.isRGB() && rgbMode maxCount2) && (i != stats.mode)) { - maxCount2 = histogram[i]; - mode2 = i; - } - } - newMaxCount = histogram[stats.mode]; - if ((newMaxCount>(maxCount2 * 2)) && (maxCount2 != 0)) - newMaxCount = (int)(maxCount2 * 1.5); - if (logScale) - drawLogPlot(yMax>0?yMax:newMaxCount, ip); - drawPlot(yMax>0?yMax:newMaxCount, ip); - histogram[stats.mode] = saveModalCount; - x = XMARGIN + 1; - y = YMARGIN + HIST_HEIGHT + 2; - if (imp==null) - lut.drawUnscaledColorBar(ip, x-1, y, HIST_WIDTH, BAR_HEIGHT); - else - drawAlignedColorBar(imp, xMin, xMax, ip, x-1, y, HIST_WIDTH, BAR_HEIGHT); - y += BAR_HEIGHT+(int)(15*SCALE); - drawText(ip, x, y); - srcImageID = imp.getID(); - } - - void drawAlignedColorBar(ImagePlus imp, double xMin, double xMax, ImageProcessor ip, int x, int y, int width, int height) { - ImageProcessor ipSource = imp.getProcessor(); - float[] pixels = null; - ImageProcessor ipRamp = null; - if (rgbMode>=INTENSITY1) { - ipRamp = new FloatProcessor(width, height); - if (rgbMode==RED) - ipRamp.setColorModel(LUT.createLutFromColor(Color.red)); - else if (rgbMode==GREEN) - ipRamp.setColorModel(LUT.createLutFromColor(Color.green)); - else if (rgbMode==BLUE) - ipRamp.setColorModel(LUT.createLutFromColor(Color.blue)); - pixels = (float[])ipRamp.getPixels(); - } else - pixels = new float[width*height]; - for (int j=0; jipSource.getPixelCount()) { // stack histogram - cm = LUT.createLutFromColor(Color.white); - min = stats.min; - max = stats.max; - } else - cm = ((CompositeImage)imp).getChannelLut(); - } else if (!ipSource.isThreshold()) - cm = ipSource.getColorModel(); - else - cm = ipSource.getCurrentColorModel(); - ipRamp = new FloatProcessor(width, height, pixels, cm); - } - ipRamp.setMinAndMax(min,max); - ImageProcessor bar = null; - if (ip instanceof ColorProcessor) - bar = ipRamp.convertToRGB(); - else - bar = ipRamp.convertToByte(true); - ip.insert(bar, x,y); - ip.setColor(Color.black); - ip.drawRect(x-1, y, width+2, height); - } - - /** Scales a threshold level to the range 0-255. */ - int scaleDown(ImageProcessor ip, double threshold) { - double min = ip.getMin(); - double max = ip.getMax(); - if (max>min) - return (int)(((threshold-min)/(max-min))*255.0); - else - return 0; - } - - void drawPlot(long maxCount, ImageProcessor ip) { - if (frame == null) - frame = getDefaultFrame(); - drawPlot(histogram, maxCount, ip, frame, frameColor); - } - - /** Draws the histogram with linear scaling and the frame. - * Also used by HistogramWindow */ - static void drawPlot(long[] histogram, long maxCount, ImageProcessor ip, Rectangle frame, Color frameColor) { - if (maxCount==0) maxCount = 1; - if (histogram.length==256) { - double scale2 = HIST_WIDTH/256.0; - int barWidth = 1; - if (SCALE>1) barWidth=2; - if (SCALE>2) barWidth=3; - for (int i = 0; i < 256; i++) { - int x =(int)(i*scale2); - int y = (int)(((double)HIST_HEIGHT*(double)histogram[i])/maxCount); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - for (int j = 0; jHIST_HEIGHT) y = HIST_HEIGHT; - ip.drawLine(i+XMARGIN, YMARGIN+HIST_HEIGHT, i+XMARGIN, YMARGIN+HIST_HEIGHT-y); - } - } else { - double xscale = (double)HIST_WIDTH/histogram.length; - for (int i=0; i0L) { - int y = (int)(((double)HIST_HEIGHT*(double)value)/maxCount); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - int x = (int)(i*xscale)+XMARGIN; - ip.drawLine(x, YMARGIN+HIST_HEIGHT, x, YMARGIN+HIST_HEIGHT-y); - } - } - } - ip.setColor(frameColor); - ip.drawRect(frame.x-1, frame.y, frame.width+2, frame.height+1); - ip.setColor(Color.black); - } - - void drawLogPlot (long maxCount, ImageProcessor ip) { - if (frame == null) - frame = getDefaultFrame(); - drawLogPlot(histogram, maxCount, ip, frame); - } - - /** Draws the logarithm of histogram values in gray. To be called before the regular plot, - * which is then in the foreground. - * Also used by HistogramWindow */ - static void drawLogPlot(long[] histogram, long maxCount, ImageProcessor ip, Rectangle frame) { - ip.drawRect(frame.x-1, frame.y, frame.width+2, frame.height+1); - double max = Math.log(maxCount + 0.5); - ip.setColor(Color.gray); - if (histogram.length==256) { - double scale2 = HIST_WIDTH/256.0; - int barWidth = 1; - if (SCALE>1) barWidth=2; - if (SCALE>2) barWidth=3; - for (int i=0; i < 256; i++) { - int x =(int)(i*scale2); - int y = histogram[i]==0?0:(int)Math.max(HIST_HEIGHT*Math.log(histogram[i]+0.5)/max, 1); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - for (int j = 0; jHIST_HEIGHT) y = HIST_HEIGHT; - ip.drawLine(i+XMARGIN, YMARGIN+HIST_HEIGHT, i+XMARGIN, YMARGIN+HIST_HEIGHT-y); - } - } else { - double xscale = (double)HIST_WIDTH/histogram.length; - for (int i=0; i0L) { - int y = (int)Math.max(HIST_HEIGHT*Math.log(value+0.5)/max, 1); - if (y>HIST_HEIGHT) y = HIST_HEIGHT; - int x = (int)(i*xscale)+XMARGIN; - ip.drawLine(x, YMARGIN+HIST_HEIGHT, x, YMARGIN+HIST_HEIGHT-y); - } - } - } - ip.setColor(Color.black); - } - - void drawText(ImageProcessor ip, int x, int y) { - ip.setFont(font); - ip.setAntialiasedText(true); - double hmin = cal.getCValue(stats.histMin); - double hmax = cal.getCValue(stats.histMax); - ip.drawString(d2s(hmin), x - 4, y); - ip.drawString(d2s(hmax), x + HIST_WIDTH - getWidth(hmax, ip) + 10, y); - if (rgbMode>=INTENSITY1) { - x += HIST_WIDTH/2; - y += 1; - ip.setJustification(ImageProcessor.CENTER_JUSTIFY); - boolean weighted = ((ColorProcessor)ip).weightedHistogram(); - switch (rgbMode) { - case INTENSITY1: ip.drawString((weighted?"Intensity (weighted)":"Intensity (unweighted)"), x, y); break; - case INTENSITY2: ip.drawString((weighted?"Intensity (unweighted)":"Intensity (weighted)"), x, y); break; - case RGB: ip.drawString("R+G+B", x, y); break; - case RED: ip.drawString("Red", x, y); break; - case GREEN: ip.drawString("Green", x, y); break; - case BLUE: ip.drawString("Blue", x, y); break; - } - ip.setJustification(ImageProcessor.LEFT_JUSTIFY); - } - //double range = hmax-hmin; - //if (fixedRange&&!cal.calibrated()&&hmin==0&&hmax==255) - // range = 256; - double binWidth = stats.binSize; - binWidth = Math.abs(binWidth); - showBins = binWidth!=1.0; - col1 = XMARGIN + 5; - col2 = XMARGIN + HIST_WIDTH/2; - row1 = y+(int)(25*SCALE); - if (showBins) row1 -= (int)(8*SCALE); - row2 = row1 + (int)(15*SCALE); - row3 = row2 + (int)(15*SCALE); - row4 = row3 + (int)(15*SCALE); - row5 = row4 + (int)(15*SCALE); - long count = stats.longPixelCount>0?stats.longPixelCount:stats.pixelCount; - String modeCount = " (" + stats.maxCount + ")"; - if (histogram!=null) {// Add '*' if multi-modal histogram - int mcount = 0;; - for (int i=0; i1) break; - } - if (mcount>1) modeCount=modeCount+"*"; - } - if (modeCount.length()>12) modeCount = ""; - ip.drawString("N: " + count, col1, row1); - ip.drawString("Min: " + d2s(stats.min), col2, row1); - ip.drawString("Mean: " + d2s(stats.mean), col1, row2); - ip.drawString("Max: " + d2s(stats.max), col2, row2); - ip.drawString("StdDev: " + d2s(stats.stdDev), col1, row3); - ip.drawString("Mode: " + d2s(stats.dmode) + modeCount, col2, row3); - if (showBins) { - ip.drawString("Bins: " + d2s(stats.nBins), col1, row4); - ip.drawString("Bin Width: " + d2s(binWidth), col2, row4); - } - } - - /** Returns the default frame size. This is the size of the plot area excluding the - * line around. */ - static Rectangle getDefaultFrame() { - return new Rectangle(XMARGIN, YMARGIN, HIST_WIDTH, HIST_HEIGHT); - } - - private String d2s(double d) { - if ((int)d==d) - return IJ.d2s(d, 0); - else - return IJ.d2s(d, 3, 8); - } - - int getWidth(double d, ImageProcessor ip) { - return ip.getStringWidth(d2s(d)); - } - - public int[] getHistogram() { - int[] hist = new int[histogram.length]; - for (int i=0; i) ctab.getSelection().getData(); - JPanel current = (JPanel) ve.get(2); - current.add(buttons); - GUI.scale(buttons); - } - }); - CanvasView.getCanvas_view().getCurrent().validate(); - - } - - public void setup() { - setup(null); - } - - public void mouseMoved(int x, int y) { - ImageProcessor ip = this.imp != null ? this.imp.getProcessor() : null; - if (ip == null) - return; - if ((frame != null) && x >= frame.x && x <= (frame.x + frame.width)) { - /* Changed for Bio7! We have no frame margin! */ - x = x + 20 - frame.x; - x = (x - frame.x); - int index = (int) (x * (SCALE * histogram.length) / HIST_WIDTH / SCALE); - if (index < 0) - index = 0; - if (index >= histogram.length) - index = histogram.length - 1; - double value = cal.getCValue(stats.histMin + index * stats.binSize); - drawValueAndCount(ip, value, histogram[index]); - } else - drawValueAndCount(ip, Double.NaN, -1); - this.imp.updateAndDraw(); - } - - protected void drawHistogram(ImageProcessor ip, boolean fixedRange) { - drawHistogram(null, ip, fixedRange, 0.0, 0.0); - } - - void drawHistogram(ImagePlus imp, ImageProcessor ip, boolean fixedRange, double xMin, double xMax) { - if (frame == null) - frame = HistogramPlot.getDefaultFrame(); - int x, y; - long maxCount2 = 0; - int mode2 = 0; - long saveModalCount; - ip.setColor(Color.black); - ip.setLineWidth(1); - decimalPlaces = Analyzer.getPrecision(); - digits = cal.calibrated() || stats.binSize != 1.0 ? decimalPlaces : 0; - saveModalCount = histogram[stats.mode]; - for (int i = 0; i < histogram.length; i++) { - if ((histogram[i] > maxCount2) && (i != stats.mode)) { - maxCount2 = histogram[i]; - mode2 = i; - } - } - newMaxCount = histogram[stats.mode]; - if ((newMaxCount > (maxCount2 * 2)) && (maxCount2 != 0)) - newMaxCount = (int) (maxCount2 * 1.5); - if (logScale || IJ.shiftKeyDown() && !liveMode()) - HistogramPlot.drawLogPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame); - HistogramPlot.drawPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame, Color.BLACK); - histogram[stats.mode] = saveModalCount; - x = XMARGIN + 1; - y = YMARGIN + HIST_HEIGHT + 2; - if (imp == null) - lut.drawUnscaledColorBar(ip, x - 1, y, HIST_WIDTH, BAR_HEIGHT); - else - drawAlignedColorBar(imp, xMin, xMax, ip, x - 1, y, HIST_WIDTH, BAR_HEIGHT); - y += BAR_HEIGHT + (int) (15 * SCALE); - drawText(ip, x, y, fixedRange); - srcImageID = imp.getID(); - } - - void drawAlignedColorBar(ImagePlus imp, double xMin, double xMax, ImageProcessor ip, int x, int y, int width, int height) { - ImageProcessor ipSource = imp.getProcessor(); - float[] pixels = null; - ImageProcessor ipRamp = null; - if (rgbMode >= INTENSITY1) { - ipRamp = new FloatProcessor(width, height); - if (rgbMode == RED) - ipRamp.setColorModel(LUT.createLutFromColor(Color.red)); - else if (rgbMode == GREEN) - ipRamp.setColorModel(LUT.createLutFromColor(Color.green)); - else if (rgbMode == BLUE) - ipRamp.setColorModel(LUT.createLutFromColor(Color.blue)); - pixels = (float[]) ipRamp.getPixels(); - } else - pixels = new float[width * height]; - for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i++) - pixels[i + width * j] = (float) (xMin + i * (xMax - xMin) / (width - 1)); - } - double min = ipSource.getMin(); - double max = ipSource.getMax(); - if (ipSource.getNChannels() == 1) { - ColorModel cm = null; - if (imp.isComposite()) { - if (stats != null && stats.pixelCount > ipSource.getPixelCount()) { // stack histogram - cm = LUT.createLutFromColor(Color.white); - min = stats.min; - max = stats.max; - } else - cm = ((CompositeImage) imp).getChannelLut(); - } else if (!ipSource.isThreshold()) - cm = ipSource.getColorModel(); - else - cm = ipSource.getCurrentColorModel(); - ipRamp = new FloatProcessor(width, height, pixels, cm); - } - ipRamp.setMinAndMax(min, max); - ImageProcessor bar = null; - if (ip instanceof ColorProcessor) - bar = ipRamp.convertToRGB(); - else - bar = ipRamp.convertToByte(true); - ip.insert(bar, x, y); - ip.setColor(Color.black); - ip.drawRect(x - 1, y, width + 2, height); - } - - /** Scales a threshold level to the range 0-255. */ - int scaleDown(ImageProcessor ip, double threshold) { - double min = ip.getMin(); - double max = ip.getMax(); - if (max > min) - return (int) (((threshold - min) / (max - min)) * 255.0); - else - return 0; - } - - void drawText(ImageProcessor ip, int x, int y, boolean fixedRange) { - ip.setFont(font); - ip.setAntialiasedText(true); - double hmin = cal.getCValue(stats.histMin); - double hmax = cal.getCValue(stats.histMax); - ip.drawString(d2s(hmin), x - 4, y); - ip.drawString(d2s(hmax), x + HIST_WIDTH - getWidth(hmax, ip) + 10, y); - if (rgbMode >= INTENSITY1) { - x += HIST_WIDTH / 2; - y += 1; - ip.setJustification(ImageProcessor.CENTER_JUSTIFY); - boolean weighted = ((ColorProcessor) ip).weightedHistogram(); - switch (rgbMode) { - case INTENSITY1: - ip.drawString((weighted ? "Intensity (weighted)" : "Intensity (unweighted)"), x, y); - break; - case INTENSITY2: - ip.drawString((weighted ? "Intensity (unweighted)" : "Intensity (weighted)"), x, y); - break; - case RGB: - ip.drawString("R+G+B", x, y); - break; - case RED: - ip.drawString("Red", x, y); - break; - case GREEN: - ip.drawString("Green", x, y); - break; - case BLUE: - ip.drawString("Blue", x, y); - break; - } - ip.setJustification(ImageProcessor.LEFT_JUSTIFY); - } - double binWidth = stats.binSize; - binWidth = Math.abs(binWidth); - showBins = binWidth != 1.0 || !fixedRange; - col1 = XMARGIN + 5; - col2 = XMARGIN + HIST_WIDTH / 2; - row1 = y + (int) (25 * SCALE); - if (showBins) - row1 -= (int) (8 * SCALE); - row2 = row1 + (int) (15 * SCALE); - row3 = row2 + (int) (15 * SCALE); - row4 = row3 + (int) (15 * SCALE); - row5 = row4 + (int) (15 * SCALE); - long count = stats.longPixelCount > 0 ? stats.longPixelCount : stats.pixelCount; - String modeCount = " (" + stats.maxCount + ")"; - if (histogram != null) {// Add '*' if multi-modal histogram - int mcount = 0; - ; - for (int i = 0; i < histogram.length; i++) - if (histogram[i] == stats.maxCount) - mcount++; - if (mcount > 1) - modeCount = modeCount + "*"; - } - if (modeCount.length() > 12) - modeCount = ""; - - ip.drawString("N: " + count, col1, row1); - ip.drawString("Min: " + d2s(stats.min), col2, row1); - ip.drawString("Mean: " + d2s(stats.mean), col1, row2); - ip.drawString("Max: " + d2s(stats.max), col2, row2); - ip.drawString("StdDev: " + d2s(stats.stdDev), col1, row3); - ip.drawString("Mode: " + d2s(stats.dmode) + modeCount, col2, row3); - if (showBins) { - ip.drawString("Bins: " + d2s(stats.nBins), col1, row4); - ip.drawString("Bin Width: " + d2s(binWidth), col2, row4); - } - drawValueAndCount(ip, Double.NaN, -1); - } - - private void drawValueAndCount(ImageProcessor ip, double value, long count) { - int y = showBins ? row4 : row3; - ip.setRoi(0, y, WIN_WIDTH, WIN_HEIGHT - y); - ip.setColor(Color.white); - ip.fill(); - ip.setColor(Color.black); - String sValue = Double.isNaN(value) ? "---" : d2s(value); - String sCount = count == -1 ? "---" : "" + count; - int row = showBins ? row5 : row4; - ip.drawString("Value: " + sValue, col1, row); - ip.drawString("Count: " + sCount, col2, row); - } - - private String d2s(double d) { - if ((int) d == d) - return IJ.d2s(d, 0); - else - return IJ.d2s(d, 3, 8); - } - - int getWidth(double d, ImageProcessor ip) { - return ip.getStringWidth(d2s(d)); - } - - /** Returns the histogram values as a ResultsTable. */ - public ResultsTable getResultsTable() { - int decimalPlaces = Analyzer.getPrecision(); - if (digits == 0 && stats.binSize != 1.0) - digits = decimalPlaces; - ResultsTable rt = new ResultsTable(); - rt.setPrecision(digits); - String vheading = stats.binSize == 1.0 ? "value" : "bin start"; - if (cal.calibrated() && !cal.isSigned16Bit()) { - for (int i = 0; i < stats.nBins; i++) { - rt.setValue("level", i, i); - rt.setValue(vheading, i, cal.getCValue(stats.histMin + i * stats.binSize)); - rt.setValue("count", i, histogram[i]); - } - } else { - for (int i = 0; i < stats.nBins; i++) { - if (stats.binSize != 1.0) - rt.setValue("index", i, i); - rt.setValue(vheading, i, cal.getCValue(stats.histMin + i * stats.binSize)); - rt.setValue("count", i, histogram[i]); - } - } - return rt; - } - - public void showList() { - ResultsTable rt = getResultsTable(); - rt.show(getTitle()); - } - - protected void copyToClipboard() { - Clipboard systemClipboard = null; - try { - systemClipboard = getToolkit().getSystemClipboard(); - } catch (Exception e) { - systemClipboard = null; - } - if (systemClipboard == null) { - IJ.error("Unable to copy to Clipboard."); - return; - } - IJ.showStatus("Copying histogram values..."); - CharArrayWriter aw = new CharArrayWriter(stats.nBins * 4); - PrintWriter pw = new PrintWriter(aw); - for (int i = 0; i < stats.nBins; i++) - pw.print(ResultsTable.d2s(cal.getCValue(stats.histMin + i * stats.binSize), digits) + "\t" + histogram[i] + "\n"); - String text = aw.toString(); - pw.close(); - StringSelection contents = new StringSelection(text); - systemClipboard.setContents(contents, this); - IJ.showStatus(text.length() + " characters copied to Clipboard"); - } - - void replot() { - ImageProcessor ip = this.imp.getProcessor(); - frame = new Rectangle(XMARGIN, YMARGIN, HIST_WIDTH, HIST_HEIGHT); - ip.setColor(Color.white); - ip.setRoi(frame.x - 1, frame.y, frame.width + 2, frame.height); - ip.fill(); - ip.resetRoi(); - ip.setColor(Color.black); - ip.setLineWidth(1); - if (logScale) - HistogramPlot.drawLogPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame); - HistogramPlot.drawPlot(histogram, yMax>0?yMax:newMaxCount, ip, frame, Color.BLACK); - this.imp.updateAndDraw(); - } - - public void actionPerformed(ActionEvent e) { - Object b = e.getSource(); - if (b == live) - toggleLiveMode(); - else if (b == rgb) - changeChannel(); - else if (b == list) { - showList(); - if (!Recorder.scriptMode()) - Recorder.record("Table.showHistogramTable"); - } else if (b == copy) - copyToClipboard(); - else if (b == log) { - logScale = !logScale; - replot(); - } - } - - public void lostOwnership(Clipboard clipboard, Transferable contents) { - } - - public int[] getHistogram() { - int[] hist = new int[histogram.length]; - for (int i = 0; i < histogram.length; i++) - hist[i] = (int) histogram[i]; - return hist; - } - - public double[] getXValues() { - double[] values = new double[stats.nBins]; - for (int i = 0; i < stats.nBins; i++) - values[i] = cal.getCValue(stats.histMin + i * stats.binSize); - return values; - } - - private void toggleLiveMode() { - if (liveMode()) - removeListeners(); - else - enableLiveMode(); - } - - private void changeChannel() { - ImagePlus imp = WindowManager.getImage(srcImageID); - if (imp == null || !imp.isRGB()) - return; - else { - rgbMode++; - if (rgbMode > BLUE) - rgbMode = INTENSITY1; - ColorProcessor cp = (ColorProcessor) imp.getProcessor(); - boolean weighted = cp.weightedHistogram(); - if (rgbMode == INTENSITY2) { - double[] weights = cp.getRGBWeights(); - if (weighted) - cp.setRGBWeights(1d / 3d, 1d / 3d, 1d / 3d); - else - cp.setRGBWeights(0.299, 0.587, 0.114); - showHistogram(imp, 256); - cp.setRGBWeights(weights); - } else - showHistogram(imp, 256); - } - } - - private boolean liveMode() { - return live != null && live.getForeground() == Color.red; - } - - private void enableLiveMode() { - if (bgThread == null) { - srcImp = WindowManager.getImage(srcImageID); - if (srcImp == null) - return; - bgThread = new Thread(this, "Live Histogram"); - bgThread.setPriority(Math.max(bgThread.getPriority() - 3, Thread.MIN_PRIORITY)); - bgThread.start(); - imageUpdated(srcImp); - } - createListeners(); - if (srcImp != null) - imageUpdated(srcImp); - } - - // Unused - public void imageOpened(ImagePlus imp) { - } - - // This listener is called if the source image content is changed - public synchronized void imageUpdated(ImagePlus imp) { - if (imp == srcImp) { - doUpdate = true; - notify(); - } - } - - public synchronized void roiModified(ImagePlus img, int id) { - if (img == srcImp) { - doUpdate = true; - notify(); - } - } - - // If either the source image or this image are closed, exit - public void imageClosed(ImagePlus imp) { - if (imp == srcImp || imp == this.imp) { - if (bgThread != null) - bgThread.interrupt(); - bgThread = null; - removeListeners(); - srcImp = null; - } - } - - // the background thread for live plotting. - public void run() { - while (true) { - if (doUpdate && srcImp != null) { - if (srcImp.getRoi() != null) - IJ.wait(50); // delay to make sure the roi has been updated - if (srcImp != null) { - if (srcImp.getBitDepth() == 16 && ImagePlus.getDefault16bitRange() != 0) - showHistogram(srcImp, 256, 0, Math.pow(2, ImagePlus.getDefault16bitRange()) - 1); - else - showHistogram(srcImp, 256); - } - } - synchronized (this) { - if (doUpdate) { - doUpdate = false; // and loop again - } else { - try { - wait(); - } // notify wakes up the thread - catch (InterruptedException e) { // interrupted tells the thread to exit - return; - } - } - } - } - } - - private void createListeners() { - if (srcImp == null) - return; - ImagePlus.addImageListener(this); - Roi.addRoiListener(this); - if (live != null) { - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); - live.setForeground(Color.red); - } - } - - private void removeListeners() { - if (srcImp == null) - return; - ImagePlus.removeImageListener(this); - Roi.removeRoiListener(this); - if (live != null) { - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.PLAIN, font.getSize())); - // live.setForeground(Color.black); - Color swtForegroundToAWT = Util.getSWTForegroundToAWT(); - live.setForeground(swtForegroundToAWT); - } - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImageCanvas.java b/com.eco.bio7.image/src/ij/gui/ImageCanvas.java deleted file mode 100644 index 70d1014fd..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageCanvas.java +++ /dev/null @@ -1,2236 +0,0 @@ -package ij.gui; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Event; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Frame; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Insets; -import java.awt.MenuItem; -import java.awt.Point; -import java.awt.PopupMenu; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.Shape; -import java.awt.event.InputEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; -import java.awt.event.WindowEvent; -import java.awt.image.IndexColorModel; -import java.util.Timer; -import java.util.TimerTask; -import java.util.Vector; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.swing.JPanel; - -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; - -import com.eco.bio7.ImageJPluginActions.ImageJContextMenuAction; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.Util; - -import ij.IJ; -import ij.ImageJ; -import ij.ImagePlus; -import ij.Menus; -import ij.Prefs; -import ij.WindowManager; -import ij.macro.MacroRunner; -import ij.measure.ResultsTable; -import ij.plugin.PointToolOptions; -import ij.plugin.WandToolOptions; -import ij.plugin.frame.Recorder; -import ij.plugin.frame.RoiManager; -import ij.plugin.tool.PlugInTool; -import ij.process.FloatPolygon; -import ij.util.Tools; - -/** This is a Canvas used to display images in a Window. */ -public class ImageCanvas extends JPanel implements MouseListener, MouseWheelListener, MouseMotionListener, Cloneable { - - protected static Cursor defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR); - protected static Cursor handCursor = new Cursor(Cursor.HAND_CURSOR); - protected static Cursor moveCursor = new Cursor(Cursor.MOVE_CURSOR); - protected static Cursor crosshairCursor = new Cursor(Cursor.CROSSHAIR_CURSOR); - - public static boolean usePointer = Prefs.usePointerCursor; - - protected ImagePlus imp; - protected boolean imageUpdated; - protected Rectangle srcRect; - protected int imageWidth, imageHeight; - protected int xMouse; // current cursor offscreen x location - protected int yMouse; // current cursor offscreen y location - - private boolean showCursorStatus = true; - private int sx2, sy2; - private boolean disablePopupMenu; - private static Color zoomIndicatorColor; - private static Font smallFont, largeFont; - private Font font; - private Rectangle[] labelRects; - private boolean maxBoundsReset; - private Overlay showAllOverlay; - private static final int LIST_OFFSET = 100000; - private static Color showAllColor = Prefs.getColor(Prefs.SHOW_ALL_COLOR, new Color(0, 255, 255)); - private Color defaultColor = showAllColor; - private static Color labelColor, bgColor; - private int resetMaxBoundsCount; - private Roi currentRoi; - private int mousePressedX, mousePressedY; - private long mousePressedTime; - private boolean overOverlayLabel; - private Shell tempShell; - - /** - * If the mouse moves less than this in screen pixels, successive zoom - * operations are on the same image pixel - */ - protected final static int MAX_MOUSEMOVE_ZOOM = 10; - /** - * Screen coordinates where the last zoom operation was done (initialized to - * impossible value) - */ - protected int lastZoomSX = -9999999; - protected int lastZoomSY = -9999999; - /** - * Image (=offscreen) coordinates where the cursor was moved to for zooming - */ - protected int zoomTargetOX = -1; - protected int zoomTargetOY; - - protected ImageJ ij; - protected double magnification; - protected int dstWidth, dstHeight; - - protected int xMouseStart; - protected int yMouseStart; - protected int xSrcStart; - protected int ySrcStart; - protected int flags; - - private Image offScreenImage; - private int offScreenWidth = 0; - private int offScreenHeight = 0; - private boolean mouseExited = true; - private boolean customRoi; - private boolean drawNames; - private AtomicBoolean paintPending; - private boolean scaleToFit; - private boolean painted; - private boolean hideZoomIndicator; - private boolean flattening; - private Timer pressTimer; - private PopupMenu roiPopupMenu; - private static int longClickDelay = 1000; // ms - - public ImageCanvas(ImagePlus imp) { - this.imp = imp; - paintPending = new AtomicBoolean(false); - ij = IJ.getInstance(); - int width = imp.getWidth(); - int height = imp.getHeight(); - imageWidth = width; - imageHeight = height; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize(imageWidth, imageHeight); - magnification = 1.0; - addMouseListener(this); - addMouseMotionListener(this); - /* Changed for Bio7! */ - addMouseWheelListener(this); - addKeyListener(ij); // ImageJ handles keyboard shortcuts - setFocusTraversalKeysEnabled(false); - setFocusable(true); - } - - void updateImage(ImagePlus imp) { - this.imp = imp; - int width = imp.getWidth(); - int height = imp.getHeight(); - imageWidth = width; - imageHeight = height; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize(imageWidth, imageHeight); - magnification = 1.0; - } - - /** - * Update this ImageCanvas to have the same zoom and scale settings as the one - * specified. - */ - void update(ImageCanvas ic) { - if (ic == null || ic == this || ic.imp == null) - return; - if (ic.imp.getWidth() != imageWidth || ic.imp.getHeight() != imageHeight) - return; - srcRect = new Rectangle(ic.srcRect.x, ic.srcRect.y, ic.srcRect.width, ic.srcRect.height); - setMagnification(ic.magnification); - setSize(ic.dstWidth, ic.dstHeight); - } - - /** Sets the region of the image (in pixels) to be displayed. */ - public void setSourceRect(Rectangle r) { - if (r == null) - return; - r = new Rectangle(r.x, r.y, r.width, r.height); - imageWidth = imp.getWidth(); - imageHeight = imp.getHeight(); - if (r.x < 0) - r.x = 0; - if (r.y < 0) - r.y = 0; - if (r.width < 1) - r.width = 1; - if (r.height < 1) - r.height = 1; - if (r.width > imageWidth) - r.width = imageWidth; - if (r.height > imageHeight) - r.height = imageHeight; - if (r.x + r.width > imageWidth) - r.x = imageWidth - r.width; - if (r.y + r.height > imageHeight) - r.y = imageHeight - r.height; - if (srcRect == null) - srcRect = r; - else { - srcRect.x = r.x; - srcRect.y = r.y; - srcRect.width = r.width; - srcRect.height = r.height; - } - if (dstWidth == 0) { - Dimension size = getSize(); - dstWidth = size.width; - dstHeight = size.height; - } - magnification = (double) dstWidth / srcRect.width; - imp.setTitle(imp.getTitle()); - if (IJ.debugMode) - IJ.log("setSourceRect: " + magnification + " " + (int) (srcRect.height * magnification + 0.5) + " " + dstHeight + " " + srcRect); - } - - void setSrcRect(Rectangle srcRect) { - setSourceRect(srcRect); - } - - public Rectangle getSrcRect() { - return srcRect; - } - - /** Obsolete; replaced by setSize() */ - public void setDrawingSize(int width, int height) { - dstWidth = width; - dstHeight = height; - setSize(dstWidth, dstHeight); - } - - public void setSize(int width, int height) { - super.setSize(width, height); - dstWidth = width; - dstHeight = height; - } - - /** - * ImagePlus.updateAndDraw calls this method to force the paint() method to - * update the image from the ImageProcessor. - */ - public void setImageUpdated() { - imageUpdated = true; - } - - public void setPaintPending(boolean state) { - paintPending.set(state); - } - - public boolean getPaintPending() { - return paintPending.get(); - } - - /* Changed for Bio7! */ - /* - * public void update(Graphics g) { paint(g); } - */ - /* Changed for Bio7! */ - public void paintComponent(Graphics g) { - super.paintComponent(g); - painted = true; - Roi roi = imp.getRoi(); - - Overlay overlay = imp.getOverlay(); - if (roi != null || overlay != null || showAllOverlay != null || Prefs.paintDoubleBuffered || (IJ.isLinux() && magnification < 0.25)) { - if (roi != null) - roi.updatePaste(); - } - - /* Changed for Bio7! */ - // Already double buffered because we use a JPanel here! - - /* - * if (roi != null || overlay != null || showAllOverlay != null || - * Prefs.paintDoubleBuffered || (IJ.isLinux() && magnification < 0.25)) { // Use - * double buffering to avoid flickering of ROIs and to work around // a Linux - * problem with large images not showing at low magnification. if (roi != null) - * roi.updatePaste(); if (imageWidth != 0) { paintDoubleBuffered(g); - * setPaintPending(false); return; } } - */ - try { - if (imageUpdated) { - imageUpdated = false; - imp.updateImage(); - } - setInterpolation(g, Prefs.interpolateScaledImages); - Image img = imp.getImage(); - if (img != null) - g.drawImage(img, 0, 0, (int) (srcRect.width * magnification + 0.5), (int) (srcRect.height * magnification + 0.5), srcRect.x, srcRect.y, srcRect.x + srcRect.width, - srcRect.y + srcRect.height, null); - if (overlay != null) - drawOverlay(overlay, g); - if (showAllOverlay != null) - drawOverlay(showAllOverlay, g); - if (roi != null) - drawRoi(roi, g); - if (srcRect.width < imageWidth || srcRect.height < imageHeight) - drawZoomIndicator(g); - /* Changed for Bio7! */ - JPanel current = CanvasView.getCanvas_view().getCurrent(); - if (current != null) { - Rectangle maxWindow = current.getBounds(); - if (maxWindow.width / magnification < imageWidth || maxWindow.height / magnification < imageHeight) - drawZoomIndicator(g); - // if (IJ.debugMode) - // showFrameRate(g); - } - } catch (OutOfMemoryError e) { - IJ.outOfMemory("Paint"); - } - setPaintPending(false); - } - - private void setInterpolation(Graphics g, boolean interpolate) { - if (magnification == 1) - return; - else if (magnification < 1.0 || interpolate) { - Object value = RenderingHints.VALUE_RENDER_QUALITY; - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, value); - } else if (magnification > 1.0) { - Object value = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_INTERPOLATION, value); - } - } - - private void drawRoi(Roi roi, Graphics g) { - if (roi == currentRoi) { - Color lineColor = roi.getStrokeColor(); - Color fillColor = roi.getFillColor(); - float lineWidth = roi.getStrokeWidth(); - roi.setStrokeColor(null); - roi.setFillColor(null); - boolean strokeSet = roi.getStroke() != null; - if (strokeSet) - roi.setStrokeWidth(1); - roi.draw(g); - roi.setStrokeColor(lineColor); - if (strokeSet) - roi.setStrokeWidth(lineWidth); - roi.setFillColor(fillColor); - currentRoi = null; - } else - roi.draw(g); - } - - public int getSliceNumber(String label) { - if (label == null) - return 0; - int slice = 0; - if (label.length() >= 14 && label.charAt(4) == '-' && label.charAt(9) == '-') - slice = (int) Tools.parseDouble(label.substring(0, 4), 0); - else if (label.length() >= 17 && label.charAt(5) == '-' && label.charAt(11) == '-') - slice = (int) Tools.parseDouble(label.substring(0, 5), 0); - else if (label.length() >= 20 && label.charAt(6) == '-' && label.charAt(13) == '-') - slice = (int) Tools.parseDouble(label.substring(0, 6), 0); - return slice; - } - - private void drawOverlay(Overlay overlay, Graphics g) { - if (imp != null && imp.getHideOverlay() && overlay != showAllOverlay) - return; - flattening = imp != null && ImagePlus.flattenTitle.equals(imp.getTitle()); - if (imp != null && showAllOverlay != null && overlay != showAllOverlay) - overlay.drawLabels(false); - Color labelColor = overlay.getLabelColor(); - if (labelColor == null) - labelColor = Color.white; - initGraphics(overlay, g, labelColor, Roi.getColor()); - int n = overlay.size(); - int currentImage = imp != null ? imp.getCurrentSlice() : -1; - int stackSize = imp.getStackSize(); - if (stackSize == 1) - currentImage = -1; - int channel = 0, slice = 0, frame = 0; - boolean hyperstack = imp.isHyperStack(); - if (imp.getNChannels() > 1) - hyperstack = true; - if (hyperstack) { - channel = imp.getChannel(); - slice = imp.getSlice(); - frame = imp.getFrame(); - } - drawNames = overlay.getDrawNames() && overlay.getDrawLabels(); - boolean drawLabels = drawNames || overlay.getDrawLabels(); - if (drawLabels) - labelRects = new Rectangle[n]; - else - labelRects = null; - font = overlay.getLabelFont(); - if (overlay.scalableLabels() && font != null) { - double mag = getMagnification(); - if (mag != 1.0) - font = font.deriveFont((float) (font.getSize() * mag)); - } - Roi activeRoi = imp.getRoi(); - boolean roiManagerShowAllMode = overlay == showAllOverlay && !Prefs.showAllSliceOnly; - for (int i = 0; i < n; i++) { - if (overlay == null) - break; - Roi roi = overlay.get(i); - if (roi == null) - break; - int c = roi.getCPosition(); - int z = roi.getZPosition(); - int t = roi.getTPosition(); - if (hyperstack) { - int position = roi.getPosition(); - if (position > 0) { - if (imp.getNChannels() == stackSize) { - c = position; - z = t = 0; - - } else if (imp.getNSlices() == stackSize) { - z = position; - c = t = 0; - } else if (imp.getNFrames() == stackSize) { - t = position; - c = z = 0; - - } - } - boolean match = (c == 0 || c == channel) && (z == 0 || z == slice) && (t == 0 || t == frame); - // IJ.log("drawOverlay1: i="+i+", pos="+roi.getPosition()+" "+c+" "+z+" "+t+" - // "+match+" "+roiManagerShowAllMode); - if (match || roiManagerShowAllMode || position == PointRoi.POINTWISE_POSITION) - drawRoi(g, roi, drawLabels ? i + LIST_OFFSET : -1); - } else { - int position = stackSize > 1 ? roi.getPosition() : 0; - if (stackSize > 1 && position == 0 && c == 1) { - if (z == 1) - position = t; - else if (t == 1) - position = z; - } - if (position == 0 && stackSize > 1) - position = getSliceNumber(roi.getName()); - if (position > 0 && imp.getCompositeMode() == IJ.COMPOSITE) - position = 0; - if (position == PointRoi.POINTWISE_POSITION) - position = 0; - if ((roi instanceof PointRoi) && Prefs.showAllPoints) - position = 0; - if (position == 0 || position == currentImage || roiManagerShowAllMode) - drawRoi(g, roi, drawLabels ? i + LIST_OFFSET : -1); - } - } - ((Graphics2D) g).setStroke(Roi.onePixelWide); - drawNames = false; - font = null; - } - - void drawOverlay(Graphics g) { - drawOverlay(imp.getOverlay(), g); - } - - private void initGraphics(Overlay overlay, Graphics g, Color textColor, Color defaultColor) { - if (smallFont == null) { - smallFont = new Font("SansSerif", Font.PLAIN, 9); - largeFont = IJ.font12; - } - if (textColor != null) { - labelColor = textColor; - if (overlay != null && overlay.getDrawBackgrounds()) { - double brightness = (labelColor.getRed() + labelColor.getGreen() + labelColor.getBlue()) / 3.0; - if (labelColor == Color.green) - brightness = 255; - bgColor = brightness <= 85 ? Color.white : Color.black; - } else - bgColor = null; - } else { - int red = defaultColor.getRed(); - int green = defaultColor.getGreen(); - int blue = defaultColor.getBlue(); - if ((red + green + blue) / 3 < 128) - labelColor = Color.white; - else - labelColor = Color.black; - bgColor = defaultColor; - } - this.defaultColor = defaultColor; - Font font = overlay != null ? overlay.getLabelFont() : null; - if (font != null && font.getSize() > 12) - ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - g.setColor(defaultColor); - } - - void drawRoi(Graphics g, Roi roi, int index) { - ImagePlus imp2 = roi.getImage(); - roi.setImage(imp); - Color saveColor = roi.getStrokeColor(); - if (saveColor == null && roi.getFillColor() == null) - roi.setStrokeColor(defaultColor); - if (roi.getStroke() == null) - ((Graphics2D) g).setStroke(Roi.onePixelWide); - if (roi instanceof TextRoi) - ((TextRoi) roi).drawText(g); - else - roi.drawOverlay(g); - roi.setStrokeColor(saveColor); - if (index >= 0) { - if (roi == currentRoi) - g.setColor(Roi.getColor()); - else - g.setColor(defaultColor); - drawRoiLabel(g, index, roi); - } - if (imp2 != null) - roi.setImage(imp2); - else - roi.setImage(null); - } - - void drawRoiLabel(Graphics g, int index, Roi roi) { - if (roi.isCursor()) - return; - boolean pointRoi = roi instanceof PointRoi; - Rectangle r = roi.getBounds(); - int x = screenX(r.x); - int y = screenY(r.y); - double mag = getMagnification(); - int width = (int) (r.width * mag); - int height = (int) (r.height * mag); - int size = width > 40 || height > 40 ? 12 : 9; - int pointSize = 0; - int crossSize = 0; - if (pointRoi) { - pointSize = ((PointRoi) roi).getSize(); - switch (pointSize) { - case 0: - case 1: - size = 9; - break; - case 2: - case 3: - size = 10; - break; - case 4: - size = 12; - break; - } - crossSize = pointSize + 10 + 2 * pointSize; - } - if (font != null) { - g.setFont(font); - size = font.getSize(); - } else if (size == 12) - g.setFont(largeFont); - else - g.setFont(smallFont); - boolean drawingList = index >= LIST_OFFSET; - if (drawingList) - index -= LIST_OFFSET; - String label = "" + (index + 1); - if (drawNames) - label = roi.getName(); - if (label == null) - return; - FontMetrics metrics = g.getFontMetrics(); - int w = metrics.stringWidth(label); - x = x + width / 2 - w / 2; - y = y + height / 2 + Math.max(size / 2, 6); - int h = metrics.getAscent() + metrics.getDescent(); - int xoffset = 0, yoffset = 0; - if (pointRoi) { - xoffset = 6 + pointSize; - yoffset = h - 6 + pointSize; - } - if (bgColor != null) { - int h2 = h; - if (font != null && font.getSize() > 14) - h2 = (int) (h2 * 0.8); - g.setColor(bgColor); - g.fillRoundRect(x - 1 + xoffset, y - h2 + 2 + yoffset, w + 1, h2 - 2, 5, 5); - } - if (labelRects != null && index < labelRects.length) { - if (pointRoi) { - int x2 = screenX(r.x); - int y2 = screenY(r.y); - int crossSize2 = crossSize / 2; - labelRects[index] = new Rectangle(x2 - crossSize2, y2 - crossSize2, crossSize, crossSize); - } else - labelRects[index] = new Rectangle(x - 3, y - h + 1, w + 4, h); - } - g.setColor(labelColor); - g.drawString(label, x + xoffset, y - 2 + yoffset); - g.setColor(defaultColor); - } - - void drawZoomIndicator(Graphics g) { - if (hideZoomIndicator) - return; - int x1 = 10; - int y1 = 10; - double aspectRatio = (double) imageHeight / imageWidth; - int w1 = 64; - if (aspectRatio > 1.0) - w1 = (int) (w1 / aspectRatio); - int h1 = (int) (w1 * aspectRatio); - if (w1 < 4) - w1 = 4; - if (h1 < 4) - h1 = 4; - int w2 = (int) (w1 * ((double) srcRect.width / imageWidth)); - int h2 = (int) (h1 * ((double) srcRect.height / imageHeight)); - if (w2 < 1) - w2 = 1; - if (h2 < 1) - h2 = 1; - int x2 = (int) (w1 * ((double) srcRect.x / imageWidth)); - int y2 = (int) (h1 * ((double) srcRect.y / imageHeight)); - if (zoomIndicatorColor == null) - zoomIndicatorColor = new Color(128, 128, 255); - g.setColor(zoomIndicatorColor); - ((Graphics2D) g).setStroke(Roi.onePixelWide); - g.drawRect(x1, y1, w1, h1); - if (w2 * h2 <= 200 || w2 < 10 || h2 < 10) - g.fillRect(x1 + x2, y1 + y2, w2, h2); - else - g.drawRect(x1 + x2, y1 + y2, w2, h2); - } - - // Use double buffer to reduce flicker when drawing complex ROIs. - // Author: Erik Meijering - void paintDoubleBuffered(Graphics g) { - final int srcRectWidthMag = (int) (srcRect.width * magnification + 0.5); - final int srcRectHeightMag = (int) (srcRect.height * magnification + 0.5); - if (offScreenImage == null || offScreenWidth != srcRectWidthMag || offScreenHeight != srcRectHeightMag) { - offScreenImage = createImage(srcRectWidthMag, srcRectHeightMag); - offScreenWidth = srcRectWidthMag; - offScreenHeight = srcRectHeightMag; - } - Roi roi = imp.getRoi(); - try { - if (imageUpdated) { - imageUpdated = false; - imp.updateImage(); - } - Graphics offScreenGraphics = offScreenImage.getGraphics(); - setInterpolation(offScreenGraphics, Prefs.interpolateScaledImages); - Image img = imp.getImage(); - if (img != null) - offScreenGraphics.drawImage(img, 0, 0, srcRectWidthMag, srcRectHeightMag, srcRect.x, srcRect.y, srcRect.x + srcRect.width, srcRect.y + srcRect.height, null); - Overlay overlay = imp.getOverlay(); - if (overlay != null) - drawOverlay(overlay, offScreenGraphics); - if (showAllOverlay != null) - drawOverlay(showAllOverlay, offScreenGraphics); - if (roi != null) - drawRoi(roi, offScreenGraphics); - if (srcRect.width < imageWidth || srcRect.height < imageHeight) - drawZoomIndicator(offScreenGraphics); - // if (IJ.debugMode) - // showFrameRate(offScreenGraphics); - g.drawImage(offScreenImage, 0, 0, null); - } catch (OutOfMemoryError e) { - IJ.outOfMemory("Paint"); - } - } - - public void resetDoubleBuffer() { - offScreenImage = null; - } - - long firstFrame; - int frames, fps; - - void showFrameRate(Graphics g) { - frames++; - if (System.currentTimeMillis() > firstFrame + 1000) { - firstFrame = System.currentTimeMillis(); - fps = frames; - frames = 0; - } - g.setColor(Color.white); - g.fillRect(10, 12, 50, 15); - g.setColor(Color.black); - g.drawString((int) (fps + 0.5) + " fps", 10, 25); - } - - public Dimension getPreferredSize() { - return new Dimension(dstWidth, dstHeight); - } - - /** Returns the current cursor location in image coordinates. */ - public Point getCursorLoc() { - return new Point(xMouse, yMouse); - } - - /** Returns 'true' if the cursor is over this image. */ - public boolean cursorOverImage() { - return !mouseExited; - } - - /** Returns the mouse event modifiers. */ - public int getModifiers() { - return flags; - } - - /** - * Returns the ImagePlus object that is associated with this ImageCanvas. - */ - public ImagePlus getImage() { - return imp; - } - - /** Sets the cursor based on the current tool and cursor location. */ - public void setCursor(int sx, int sy, int ox, int oy) { - xMouse = ox; - yMouse = oy; - mouseExited = false; - Roi roi = imp.getRoi(); - ImageWindow win = imp.getWindow(); - overOverlayLabel = false; - if (win == null) - return; - if (IJ.spaceBarDown()) { - setCursor(handCursor); - return; - } - int id = Toolbar.getToolId(); - switch (id) { - case Toolbar.MAGNIFIER: - setCursor(moveCursor); - break; - case Toolbar.HAND: - setCursor(handCursor); - break; - default: // selection tool - PlugInTool tool = Toolbar.getPlugInTool(); - boolean arrowTool = roi != null && (roi instanceof Arrow) && tool != null && "Arrow Tool".equals(tool.getToolName()); - if ((id >= Toolbar.CUSTOM1) && !arrowTool) { - if (Prefs.usePointerCursor) - setCursor(defaultCursor); - else - setCursor(crosshairCursor); - } else if (roi != null && roi.getState() != roi.CONSTRUCTING && roi.isHandle(sx, sy) >= 0) { - setCursor(handCursor); - } else if ((imp.getOverlay() != null || showAllOverlay != null) && overOverlayLabel(sx, sy, ox, oy) && (roi == null || roi.getState() != roi.CONSTRUCTING)) { - overOverlayLabel = true; - setCursor(handCursor); - } else if (Prefs.usePointerCursor || (roi != null && roi.getState() != roi.CONSTRUCTING && roi.contains(ox, oy))) - setCursor(defaultCursor); - else - setCursor(crosshairCursor); - } - } - - private boolean overOverlayLabel(int sx, int sy, int ox, int oy) { - Overlay o = showAllOverlay; - if (o == null) - o = imp.getOverlay(); - if (o == null || !o.isSelectable() || !o.isDraggable() || !o.getDrawLabels() || labelRects == null) - return false; - for (int i = o.size() - 1; i >= 0; i--) { - if (labelRects != null && labelRects[i] != null && labelRects[i].contains(sx, sy)) { - Roi roi = imp.getRoi(); - if (roi == null || !roi.contains(ox, oy)) - return true; - else - return false; - } - } - return false; - } - - /** - * Converts a screen x-coordinate to an offscreen x-coordinate (nearest pixel - * center). - */ - public int offScreenX(int sx) { - return srcRect.x + (int) (sx / magnification); - } - - /** - * Converts a screen y-coordinate to an offscreen y-coordinate (nearest pixel - * center). - */ - public int offScreenY(int sy) { - return srcRect.y + (int) (sy / magnification); - } - - /** - * Converts a screen x-coordinate to an offscreen x-coordinate (Roi coordinate - * of nearest pixel border). - */ - public int offScreenX2(int sx) { - return srcRect.x + (int) Math.round(sx / magnification); - } - - /** - * Converts a screen y-coordinate to an offscreen y-coordinate (Roi coordinate - * of nearest pixel border). - */ - public int offScreenY2(int sy) { - return srcRect.y + (int) Math.round(sy / magnification); - } - - /** - * Converts a screen x-coordinate to a floating-point offscreen x-coordinate. - */ - public double offScreenXD(int sx) { - return srcRect.x + sx / magnification; - } - - /** - * Converts a screen y-coordinate to a floating-point offscreen y-coordinate. - */ - public double offScreenYD(int sy) { - return srcRect.y + sy / magnification; - - } - - /** Converts an offscreen x-coordinate to a screen x-coordinate. */ - public int screenX(int ox) { - return (int) ((ox - srcRect.x) * magnification); - } - - /** Converts an offscreen y-coordinate to a screen y-coordinate. */ - public int screenY(int oy) { - return (int) ((oy - srcRect.y) * magnification); - } - - /** - * Converts a floating-point offscreen x-coordinate to a screen x-coordinate. - */ - public int screenXD(double ox) { - return (int) ((ox - srcRect.x) * magnification); - } - - /** - * Converts a floating-point offscreen x-coordinate to a screen x-coordinate. - */ - public int screenYD(double oy) { - return (int) ((oy - srcRect.y) * magnification); - } - - public double getMagnification() { - return magnification; - } - - public void setMagnification(double magnification) { - setMagnification2(magnification); - } - - void setMagnification2(double magnification) { - if (magnification > 32.0) - magnification = 32.0; - if (magnification < zoomLevels[0]) - magnification = zoomLevels[0]; - this.magnification = magnification; - imp.setTitle(imp.getTitle()); - } - - /** Resizes the canvas when the user resizes the window. */ - void resizeCanvas(int width, int height) { - ImageWindow win = imp.getWindow(); - if (!maxBoundsReset && (width > dstWidth || height > dstHeight) && win != null && win.maxBounds != null && width != win.maxBounds.width - 10) { - if (resetMaxBoundsCount != 0) - resetMaxBounds(); // Works around problem that prevented window - // from being larger than maximized size - resetMaxBoundsCount++; - } - if (scaleToFit || IJ.altKeyDown()) { - fitToWindow(); - return; - } - if (width > imageWidth * magnification) - width = (int) (imageWidth * magnification); - if (height > imageHeight * magnification) - height = (int) (imageHeight * magnification); - Dimension size = getSize(); - if (srcRect.width < imageWidth || srcRect.height < imageHeight || (painted && (width != size.width || height != size.height))) { - setSize(width, height); - srcRect.width = (int) (dstWidth / magnification); - srcRect.height = (int) (dstHeight / magnification); - if ((srcRect.x + srcRect.width) > imageWidth) - srcRect.x = imageWidth - srcRect.width; - if ((srcRect.y + srcRect.height) > imageHeight) - srcRect.y = imageHeight - srcRect.height; - repaint(); - } - } - - public void fitToWindow() { - ImageWindow win = imp.getWindow(); - if (win == null) - return; - Rectangle bounds = win.getBounds(); - Insets insets = win.getInsets(); // do not include small window padding - int sliderHeight = win.getSliderHeight(); - double xmag = (double) (bounds.width - (insets.left + insets.right + ImageWindow.HGAP * 2)) / srcRect.width; - double ymag = (double) (bounds.height - (ImageWindow.VGAP * 2 + insets.top + insets.bottom + sliderHeight)) / srcRect.height; - setMagnification(Math.min(xmag, ymag)); - int width = (int) (imageWidth * magnification); - int height = (int) (imageHeight * magnification); - if (width == dstWidth && height == dstHeight) - return; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize(width, height); - // getParent().validate(); - /* Changed for Bio7 */ - CanvasView.getCurrent().validate(); - } - - void setMaxBounds() { - if (maxBoundsReset) { - maxBoundsReset = false; - ImageWindow win = imp.getWindow(); - if (win != null && !IJ.isLinux() && win.maxBounds != null) { - win.setMaximizedBounds(win.maxBounds); - win.setMaxBoundsTime = System.currentTimeMillis(); - } - } - } - - void resetMaxBounds() { - ImageWindow win = imp.getWindow(); - if (win != null && (System.currentTimeMillis() - win.setMaxBoundsTime) > 500L) { - win.setMaximizedBounds(win.maxWindowBounds); - maxBoundsReset = true; - } - } - - private static final double[] zoomLevels = { 1 / 72.0, 1 / 48.0, 1 / 32.0, 1 / 24.0, 1 / 16.0, 1 / 12.0, 1 / 8.0, 1 / 6.0, 1 / 4.0, 1 / 3.0, 1 / 2.0, 0.75, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0, - 16.0, 24.0, 32.0 }; - - public static double getLowerZoomLevel(double currentMag) { - double newMag = zoomLevels[0]; - for (int i = 0; i < zoomLevels.length; i++) { - if (zoomLevels[i] < currentMag) - newMag = zoomLevels[i]; - else - break; - } - return newMag; - } - - public static double getHigherZoomLevel(double currentMag) { - double newMag = 32.0; - for (int i = zoomLevels.length - 1; i >= 0; i--) { - if (zoomLevels[i] > currentMag) - newMag = zoomLevels[i]; - else - break; - } - return newMag; - } - - /** - * Zooms in by making the window bigger. If it can't be made bigger, then makes - * the source rectangle (srcRect) smaller and centers it on the position in the - * image where the cursor was when zooming has started. Note that sx and sy are - * screen coordinates. - */ - public void zoomIn(int sx, int sy) { - - if (magnification >= 32) - return; - scaleToFit = false; - boolean mouseMoved = sqr(sx - lastZoomSX) + sqr(sy - lastZoomSY) > MAX_MOUSEMOVE_ZOOM * MAX_MOUSEMOVE_ZOOM; - lastZoomSX = sx; - lastZoomSY = sy; - if (mouseMoved || zoomTargetOX < 0) { - boolean cursorInside = sx >= 0 && sy >= 0 && sx < dstWidth && sy < dstHeight; - zoomTargetOX = offScreenX(cursorInside ? sx : dstWidth / 2); // where to zoom, offscreen (image) coordinates - zoomTargetOY = offScreenY(cursorInside ? sy : dstHeight / 2); - } - double newMag = getHigherZoomLevel(magnification); - int newWidth = (int) (imageWidth * newMag); - int newHeight = (int) (imageHeight * newMag); - Rectangle dim = CanvasView.getCurrent().getBounds(); - Dimension newSize = new Dimension(newWidth, newHeight); - // System.out.println(newWidth+" "+dim.width+" "+newHeight+" "+dim.height); - if (newWidth < dim.width && newHeight < dim.height) { - - setSize(newSize.width, newSize.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - - if (newSize.width != newWidth || newSize.height != newHeight) - adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); - else - setMagnification(newMag); - - } else if (newWidth > dim.width && newHeight < dim.height) { - setSize(newSize.width, newSize.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - setMagnification(newMag); - - } else if (newWidth < dim.width && newHeight > dim.height) { - setSize(newSize.width, newSize.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - setMagnification(newMag); - - } - - // Dimension newSize = canEnlarge(newWidth, newHeight); - else // can't enlarge window - setSize(dim.width, dim.height); - setLocation(dim.width / 2 - this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); - adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); - // CanvasView.getCurrent().validate(); - repaint(); - if (srcRect.width < imageWidth || srcRect.height < imageHeight) - resetMaxBounds(); - // fitToWindow(); - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the layout! */ - CanvasView.parent2.layout(); - - } - }); - CanvasView.getCurrent().validate(); - IJTabs.doSecondaryViewLayout(); - } - - /** Centers the viewable area on offscreen (image) coordinates x, y */ - void adjustSourceRect(double newMag, int x, int y) { - int w = (int) Math.round(dstWidth / newMag); - if (w * newMag < dstWidth) - w++; - int h = (int) Math.round(dstHeight / newMag); - if (h * newMag < dstHeight) - h++; - Rectangle r = new Rectangle(x - w / 2, y - h / 2, w, h); - if (r.x < 0) - r.x = 0; - if (r.y < 0) - r.y = 0; - if (r.x + w > imageWidth) - r.x = imageWidth - w; - if (r.y + h > imageHeight) - r.y = imageHeight - h; - srcRect = r; - setMagnification(newMag); - } - - /** - * Zooms in by making the window bigger. If it can't be made bigger, then makes - * the source rectangle (srcRect) smaller and centers it on the position in the - * image where the cursor was when zooming has started. Note that sx and sy are - * screen coordinates. - */ - /* - * public void zoomIn(int sx, int sy) { - * - * if (magnification >= 32) return; scaleToFit = false; boolean mouseMoved = - * sqr(sx - lastZoomSX) + sqr(sy - lastZoomSY) > MAX_MOUSEMOVE_ZOOM * - * MAX_MOUSEMOVE_ZOOM; lastZoomSX = sx; lastZoomSY = sy; if (mouseMoved || - * zoomTargetOX < 0) { boolean cursorInside = sx >= 0 && sy >= 0 && sx < - * dstWidth && sy < dstHeight; zoomTargetOX = offScreenX(cursorInside ? sx : - * dstWidth / 2); // where to zoom, offscreen (image) coordinates zoomTargetOY = - * offScreenY(cursorInside ? sy : dstHeight / 2); } double newMag = - * getHigherZoomLevel(magnification); // System.out.println(newMag); int - * newWidth = (int) (imageWidth * newMag); int newHeight = (int) (imageHeight * - * newMag); Dimension newSize = canEnlarge(newWidth, newHeight); Rectangle - * clientArea = CanvasView.getCurrent().getBounds(); if (newSize != null) { - * setSize(newSize.width, newSize.height); - * //imp.getWindow().scResizeEvent(newSize.width, newSize.height); - * - * if (newSize.width != newWidth || newSize.height != newHeight) { - * - * Changed for the SWT parent. If the next zoom level runs out of the max width - * we increase the size to the max of the parent! - * - * if (newSize.width != newWidth) { newSize = new Dimension(clientArea.width, - * newSize.height); setSize(newSize.width, newSize.height); // - * System.out.println("resize"); //imp.getWindow().scResizeEvent(newSize.width, - * newSize.height); } - * - * If the next zoom level runs out of the max height we increase the height to - * the max of the parent! - * - * else { Changed for the SWT parent. Resize to max parent! newSize = new - * Dimension(newSize.width, clientArea.height); setSize(newSize.width, - * newSize.height); // System.out.println("resize"); - * //imp.getWindow().scResizeEvent(newSize.width, newSize.height); - * - * } adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); } else { - * - * setMagnification(newMag); } imp.getWindow().pack(); - * //imp.getWindow().parentComposite.layout(); } else { // can't enlarge window. - * Maximize it! - * - * newSize = new Dimension(clientArea.width, clientArea.height); - * setSize(newSize.width, newSize.height); // System.out.println("resize"); - * //imp.getWindow().scResizeEvent(newSize.width, newSize.height); - * adjustSourceRect(newMag, zoomTargetOX, zoomTargetOY); // - * System.out.println("this is null"); } repaint(); - * - * - * - * } - */ - - /** - * Returns the size to which the window can be enlarged, or null if it can't be - * enlarged. newWidth, newHeight is the size needed for showing the - * full image at the magnification needed - */ - protected Dimension canEnlarge(int newWidth, int newHeight) { - if (IJ.altKeyDown()) - return null; - ImageWindow win = imp.getWindow(); - if (win == null) - return null; - Rectangle r1 = win.getBounds(); - Insets insets = win.getInsets(); - Point loc = getLocation(); - if (loc.x > insets.left + 5 || loc.y > insets.top + 5) { - r1.width = newWidth + insets.left + insets.right + ImageWindow.HGAP * 2; - r1.height = newHeight + insets.top + insets.bottom + ImageWindow.VGAP * 2 + win.getSliderHeight(); - } else { - r1.width = r1.width - dstWidth + newWidth; - r1.height = r1.height - dstHeight + newHeight; - } - Rectangle max = GUI.getMaxWindowBounds(win); - boolean fitsHorizontally = r1.x + r1.width < max.x + max.width; - boolean fitsVertically = r1.y + r1.height < max.y + max.height; - if (fitsHorizontally && fitsVertically) - return new Dimension(newWidth, newHeight); - else if (fitsVertically && newHeight < dstWidth) - return new Dimension(dstWidth, newHeight); - else if (fitsHorizontally && newWidth < dstHeight) - return new Dimension(newWidth, dstHeight); - /* - * else return null; - */ - /* Changed for Bio7! */ - else - return new Dimension(max.width, max.height); - } - - /** - * Zooms out by making the source rectangle (srcRect) larger and centering it on - * (x,y). If we can't make it larger, then make the window smaller. Note that sx - * and sy are screen coordinates. - */ - public void zoomOut(int sx, int sy) { - if (magnification <= zoomLevels[0]) - return; - boolean mouseMoved = sqr(sx - lastZoomSX) + sqr(sy - lastZoomSY) > MAX_MOUSEMOVE_ZOOM * MAX_MOUSEMOVE_ZOOM; - lastZoomSX = sx; - lastZoomSY = sy; - if (mouseMoved || zoomTargetOX < 0) { - boolean cursorInside = sx >= 0 && sy >= 0 && sx < dstWidth && sy < dstHeight; - zoomTargetOX = offScreenX(cursorInside ? sx : dstWidth / 2); // where - // to - // zoom, - // offscreen - // (image) - // coordinates - zoomTargetOY = offScreenY(cursorInside ? sy : dstHeight / 2); - } - double oldMag = magnification; - double newMag = getLowerZoomLevel(magnification); - double srcRatio = (double) srcRect.width / srcRect.height; - double imageRatio = (double) imageWidth / imageHeight; - double initialMag = imp.getWindow().getInitialMagnification(); - if (Math.abs(srcRatio - imageRatio) > 0.05) { - double scale = oldMag / newMag; - int newSrcWidth = (int) Math.round(srcRect.width * scale); - int newSrcHeight = (int) Math.round(srcRect.height * scale); - if (newSrcWidth > imageWidth) - newSrcWidth = imageWidth; - if (newSrcHeight > imageHeight) - newSrcHeight = imageHeight; - int newSrcX = srcRect.x - (newSrcWidth - srcRect.width) / 2; - int newSrcY = srcRect.y - (newSrcHeight - srcRect.height) / 2; - if (newSrcX + newSrcWidth > imageWidth) - newSrcX = imageWidth - newSrcWidth; - if (newSrcY + newSrcHeight > imageHeight) - newSrcY = imageHeight - newSrcHeight; - if (newSrcX < 0) - newSrcX = 0; - if (newSrcY < 0) - newSrcY = 0; - srcRect = new Rectangle(newSrcX, newSrcY, newSrcWidth, newSrcHeight); - int newDstWidth = (int) (srcRect.width * newMag); - int newDstHeight = (int) (srcRect.height * newMag); - setMagnification(newMag); - setMaxBounds(); - if (newDstWidth < dstWidth || newDstHeight < dstHeight) { - setSize(newDstWidth, newDstHeight); - imp.getWindow().pack(); - } else - repaint(); - /* Changes for Bio7! */ - // CanvasView.getCurrent().invalidate(); - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the layout! */ - CanvasView.parent2.layout(); - - } - }); - CanvasView.getCurrent().validate(); - // adjustSourceRect(newMag, sx, sy); - - return; - } - if (imageWidth * newMag > dstWidth) { - int w = (int) Math.round(dstWidth / newMag); - if (w * newMag < dstWidth) - w++; - int h = (int) Math.round(dstHeight / newMag); - if (h * newMag < dstHeight) - h++; - Rectangle r = new Rectangle(zoomTargetOX - w / 2, zoomTargetOY - h / 2, w, h); - if (r.x < 0) - r.x = 0; - if (r.y < 0) - r.y = 0; - if (r.x + w > imageWidth) - r.x = imageWidth - w; - if (r.y + h > imageHeight) - r.y = imageHeight - h; - srcRect = r; - setMagnification(newMag); - } else { - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - setSize((int) (imageWidth * newMag), (int) (imageHeight * newMag)); - setMagnification(newMag); - imp.getWindow().pack(); - } - setMaxBounds(); - repaint(); - /* Changes for Bio7! */ - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - /* Call parent layout before the layout! */ - CanvasView.parent2.layout(); - - } - - }); - CanvasView.getCurrent().doLayout(); - IJTabs.doSecondaryViewLayout(); - // adjustSourceRect(newMag, sx, sy); - } - - int sqr(int x) { - return x * x; - } - - /** Implements the Image/Zoom/Original Scale command. */ - public void unzoom() { - double imag = imp.getWindow().getInitialMagnification(); - if (magnification == imag) - return; - srcRect = new Rectangle(0, 0, imageWidth, imageHeight); - ImageWindow win = imp.getWindow(); - setSize((int) (imageWidth * imag), (int) (imageHeight * imag)); - setMagnification(imag); - setMaxBounds(); - win.pack(); - setMaxBounds(); - repaint(); - /* Changed for Bio7! */ - CanvasView.getCurrent().validate(); - } - - /** Implements the Image/Zoom/View 100% command. */ - public void zoom100Percent() { - if (magnification == 1.0) - return; - double imag = imp.getWindow().getInitialMagnification(); - if (magnification != imag) - unzoom(); - if (magnification == 1.0) - return; - if (magnification < 1.0) { - while (magnification < 1.0) - zoomIn(imageWidth / 2, imageHeight / 2); - } else if (magnification > 1.0) { - while (magnification > 1.0) - zoomOut(imageWidth / 2, imageHeight / 2); - } else - return; - int x = xMouse, y = yMouse; - if (mouseExited) { - x = imageWidth / 2; - y = imageHeight / 2; - } - int sx = screenX(x); - int sy = screenY(y); - adjustSourceRect(1.0, sx, sy); - repaint(); - /* Changed for Bio7! */ - CanvasView.getCurrent().validate(); - } - - protected void scroll(int sx, int sy) { - int ox = xSrcStart + (int) (sx / magnification); // convert to offscreen - // coordinates - int oy = ySrcStart + (int) (sy / magnification); - int newx = xSrcStart + (xMouseStart - ox); - int newy = ySrcStart + (yMouseStart - oy); - if (newx < 0) - newx = 0; - if (newy < 0) - newy = 0; - if ((newx + srcRect.width) > imageWidth) - newx = imageWidth - srcRect.width; - if ((newy + srcRect.height) > imageHeight) - newy = imageHeight - srcRect.height; - srcRect.x = newx; - srcRect.y = newy; - imp.draw(); - Thread.yield(); - } - - Color getColor(int index) { - IndexColorModel cm = (IndexColorModel) imp.getProcessor().getColorModel(); - // IJ.write(""+index+" "+(new Color(cm.getRGB(index)))); - return new Color(cm.getRGB(index)); - } - - /** - * Sets the foreground drawing color (or background color if 'setBackground' is - * true) to the color of the pixel at (ox,oy). - */ - public void setDrawingColor(int ox, int oy, boolean setBackground) { - int type = imp.getType(); - int[] v = imp.getPixel(ox, oy); - switch (type) { - case ImagePlus.GRAY8: { - if (setBackground) - setBackgroundColor(getColor(v[0])); - else - setForegroundColor(getColor(v[0])); - break; - } - case ImagePlus.GRAY16: - case ImagePlus.GRAY32: { - double min = imp.getProcessor().getMin(); - double max = imp.getProcessor().getMax(); - double value = (type == ImagePlus.GRAY32) ? Float.intBitsToFloat(v[0]) : v[0]; - int index = (int) (255.0 * ((value - min) / (max - min))); - if (index < 0) - index = 0; - if (index > 255) - index = 255; - if (setBackground) - setBackgroundColor(getColor(index)); - else - setForegroundColor(getColor(index)); - break; - } - case ImagePlus.COLOR_RGB: - case ImagePlus.COLOR_256: { - Color c = new Color(v[0], v[1], v[2]); - if (setBackground) - setBackgroundColor(c); - else - setForegroundColor(c); - break; - } - } - Color c; - if (setBackground) - c = Toolbar.getBackgroundColor(); - else { - c = Toolbar.getForegroundColor(); - imp.setColor(c); - } - IJ.showStatus("(" + c.getRed() + ", " + c.getGreen() + ", " + c.getBlue() + ")"); - } - - private void setForegroundColor(Color c) { - Toolbar.setForegroundColor(c); - if (IJ.recording()) - Recorder.record("setForegroundColor", c.getRed(), c.getGreen(), c.getBlue()); - } - - private void setBackgroundColor(Color c) { - Toolbar.setBackgroundColor(c); - if (IJ.recording()) - Recorder.record("setBackgroundColor", c.getRed(), c.getGreen(), c.getBlue()); - } - - public void mousePressed(final MouseEvent e) { - /* Changed for Bio7! */ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - ImageWindow wind = imp.getWindow(); - if (wind != null) { - Frame frameSwtAwt = wind.getSwtAwtMain().getFrame(); - if (frameSwtAwt != null) { - - if (frameSwtAwt != null) - frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, WindowEvent.WINDOW_ACTIVATED)); - // frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, - // WindowEvent.WINDOW_GAINED_FOCUS)); - - if (ImageCanvas.this.isFocusOwner() == false) { - ImageCanvas.this.requestFocus(); - - } - } - } - } - }); - /* Search for detached views and activate them on mouse pressed events! */ - Util.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - String secId = Integer.toString(ImageCanvas.this.getImage().getID()); - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - IViewReference ref2 = page.findViewReference("com.eco.bio7.image.detachedImage", secId); - if (ref2 != null) { - IViewPart activated = null; - try { - - activated = page.showView("com.eco.bio7.image.detachedImage", secId, IWorkbenchPage.VIEW_ACTIVATE); - } catch (PartInitException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - // CustomDetachedImageJView customView = (CustomDetachedImageJView) activated; - // ImageJ.setCustomView(customView); - } - } - }); - - showCursorStatus = true; - int toolID = Toolbar.getToolId(); - ImageWindow win = imp.getWindow(); - if (win != null && win.running2 && toolID != Toolbar.MAGNIFIER) { - if (win instanceof StackWindow) - ((StackWindow) win).setAnimate(false); - else - win.running2 = false; - return; - } - - int x = e.getX(); - int y = e.getY(); - flags = e.getModifiers(); - - if (toolID != Toolbar.MAGNIFIER && (e.isPopupTrigger() || (!IJ.isMacintosh() && (flags & Event.META_MASK) != 0))) { - handlePopupMenu(e); - return; - } - - int ox = offScreenX(x); - int oy = offScreenY(y); - xMouse = ox; - yMouse = oy; - if (IJ.spaceBarDown()) { - // temporarily switch to "hand" tool of space bar down - setupScroll(ox, oy); - return; - } - - if (overOverlayLabel && (imp.getOverlay() != null || showAllOverlay != null)) { - if (activateOverlayRoi(ox, oy)) - return; - } - - if ((System.currentTimeMillis() - mousePressedTime) < 300L && !drawingTool()) { - if (activateOverlayRoi(ox, oy)) - return; - } - - mousePressedX = ox; - mousePressedY = oy; - mousePressedTime = System.currentTimeMillis(); - - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mousePressed(imp, e); - if (e.isConsumed()) - return; - } - if (customRoi && imp.getOverlay() != null) - return; - - if (toolID >= Toolbar.CUSTOM1) { - if (tool != null && "Arrow Tool".equals(tool.getToolName())) - handleRoiMouseDown(e); - else - Toolbar.getInstance().runMacroTool(toolID); - return; - } - - final Roi roi1 = imp.getRoi(); - final int size1 = roi1 != null ? roi1.size() : 0; - final Rectangle r1 = roi1 != null ? roi1.getBounds() : null; - - switch (toolID) { - case Toolbar.MAGNIFIER: - if (IJ.shiftKeyDown()) - zoomToSelection(ox, oy); - else if ((flags & (Event.ALT_MASK | Event.META_MASK | Event.CTRL_MASK)) != 0) { - - zoomOut(x, y); - if (getMagnification() < 1.0) - imp.repaintWindow(); - } else { - - zoomIn(x, y); - if (getMagnification() <= 1.0) - imp.repaintWindow(); - } - break; - case Toolbar.HAND: - setupScroll(ox, oy); - break; - case Toolbar.DROPPER: - setDrawingColor(ox, oy, IJ.altKeyDown()); - break; - case Toolbar.WAND: - double tolerance = WandToolOptions.getTolerance(); - Roi roi = imp.getRoi(); - if (roi != null && (tolerance == 0.0 || imp.isThreshold()) && roi.contains(ox, oy)) { - Rectangle r = roi.getBounds(); - if (r.width == imageWidth && r.height == imageHeight) - imp.deleteRoi(); - else if (!e.isAltDown()) { - handleRoiMouseDown(e); - return; - } - } - if (roi != null) { - int handle = roi.isHandle(x, y); - if (handle >= 0) { - roi.mouseDownInHandle(handle, x, y); - return; - } - } - if (!imp.okToDeleteRoi()) - break; - setRoiModState(e, roi, -1); - String mode = WandToolOptions.getMode(); - if (Prefs.smoothWand) - mode = mode + " smooth"; - int npoints = IJ.doWand(imp, ox, oy, tolerance, mode); - if (IJ.recording() && npoints > 0) { - if (Recorder.scriptMode()) - Recorder.recordCall("IJ.doWand(imp, " + ox + ", " + oy + ", " + tolerance + ", \"" + mode + "\");"); - else { - if (tolerance == 0.0 && mode.equals("Legacy")) - Recorder.record("doWand", ox, oy); - else - Recorder.recordString("doWand(" + ox + ", " + oy + ", " + tolerance + ", \"" + mode + "\");\n"); - } - } - break; - case Toolbar.OVAL: - if (Toolbar.getBrushSize() > 0) - new RoiBrush(); - else - handleRoiMouseDown(e); - break; - default: // selection tool - handleRoiMouseDown(e); - } - if (longClickDelay > 0) { - if (pressTimer == null) - pressTimer = new java.util.Timer(); - final Point cursorLoc = getCursorLoc(); - pressTimer.schedule(new TimerTask() { - public void run() { - if (pressTimer != null) { - pressTimer.cancel(); - pressTimer = null; - } - Roi roi2 = imp.getRoi(); - int size2 = roi2 != null ? roi2.size() : 0; - Rectangle r2 = roi2 != null ? roi2.getBounds() : null; - boolean empty = r2 != null && r2.width == 0 && r2.height == 0; - int state = roi2 != null ? roi2.getState() : -1; - boolean unchanged = state != Roi.MOVING_HANDLE && r1 != null && r2 != null && r2.x == r1.x && r2.y == r1.y && r2.width == r1.width && r2.height == r1.height && size2 == size1 - && !(size2 > 1 && state == Roi.CONSTRUCTING); - boolean cursorMoved = !getCursorLoc().equals(cursorLoc); - if ((roi1 == null && (size2 <= 1 || empty)) || unchanged) { - if (roi1 == null) - imp.deleteRoi(); - if (!cursorMoved && Toolbar.getToolId() != Toolbar.HAND) - handlePopupMenu(e); - } - } - }, longClickDelay); - } - } - - private boolean drawingTool() { - int id = Toolbar.getToolId(); - return id == Toolbar.POLYLINE || id == Toolbar.FREELINE || id >= Toolbar.CUSTOM1; - } - - void zoomToSelection(int x, int y) { - IJ.setKeyUp(IJ.ALL_KEYS); - String macro = "args = split(getArgument);\n" + "x1=parseInt(args[0]); y1=parseInt(args[1]); flags=20;\n" + "while (flags&20!=0) {\n" + "getCursorLoc(x2, y2, z, flags);\n" - + "if (x2>=x1) x=x1; else x=x2;\n" + "if (y2>=y1) y=y1; else y=y2;\n" + "makeRectangle(x, y, abs(x2-x1), abs(y2-y1));\n" + "wait(10);\n" + "}\n" + "run('To Selection');\n"; - new MacroRunner(macro, x + " " + y); - } - - protected void setupScroll(int ox, int oy) { - xMouseStart = ox; - yMouseStart = oy; - xSrcStart = srcRect.x; - ySrcStart = srcRect.y; - } - - protected void handlePopupMenu(MouseEvent e) { - if (disablePopupMenu) - return; - if (IJ.debugMode) - IJ.log("show popup: " + (e.isPopupTrigger() ? "true" : "false")); - int sx = e.getX(); - int sy = e.getY(); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - Roi roi = imp.getRoi(); - if (roi != null && roi.getType() == Roi.COMPOSITE && Toolbar.getToolId() == Toolbar.OVAL && Toolbar.getBrushSize() > 0) - return; // selection brush tool - if (roi != null && (roi.getType() == Roi.POLYGON || roi.getType() == Roi.POLYLINE || roi.getType() == Roi.ANGLE) && roi.getState() == roi.CONSTRUCTING) { - roi.handleMouseUp(sx, sy); // simulate double-click to finalize - roi.handleMouseUp(sx, sy); // polygon or polyline selection - return; - } - if (roi != null && !(e.isAltDown() || e.isShiftDown())) { // show ROI popup? - if (roi.contains(ox, oy)) { - if (roiPopupMenu == null) - addRoiPopupMenu(); - if (IJ.isMacOSX()) - IJ.wait(10); - /* Changed for Bio7! */ - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction imageContextMenuAction = instance.getImageContextMenuAction(); - imageContextMenuAction.swtPopupMenu(e, roiPopupMenu, this); - // roiPopupMenu.show(this, sx, sy); - return; - } - } - PopupMenu popup = Menus.getPopupMenu(); - if (popup != null) { - add(popup); - if (IJ.isMacOSX()) - IJ.wait(10); - /* Changed for Bio7! SWT Popup Menu! */ - // popup.show(this, x, y); - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction imageContextMenuAction = instance.getImageContextMenuAction(); - imageContextMenuAction.swtPopupMenu(e, popup, this); - } - } - - public void mouseExited(MouseEvent e) { - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseExited(imp, e); - if (e.isConsumed()) - return; - } - ImageWindow win = imp.getWindow(); - if (win != null) - setCursor(defaultCursor); - IJ.showStatus(""); - mouseExited = true; - /* - * Change for Bio7! On Linux the editors don't receive key events when the - * ImageCanvas receives focus. We workaround this by open and close a SWT Shell - * to transfer back the focus to SWT. This could also solve the problem of a - * broken editor hoover in the Bio7 editors! - */ - /* - * if (Util.getOS().equals("Linux")) { Display dis = Util.getDisplay(); - * dis.syncExec(new Runnable() { - * - * public void run() { - * - * if (tempShell != null) { if (tempShell.isDisposed() == false) { - * tempShell.dispose(); } } tempShell = new Shell(); tempShell.setVisible(true); - * tempShell.setVisible(false); } }); } - */ - - } - - public void mouseDragged(MouseEvent e) { - int x = e.getX(); - int y = e.getY(); - xMouse = offScreenX(x); - yMouse = offScreenY(y); - flags = e.getModifiers(); - mousePressedX = mousePressedY = -1; - if (flags == 0) // workaround for Mac OS 9 bug - flags = InputEvent.BUTTON1_MASK; - if (Toolbar.getToolId() == Toolbar.HAND || IJ.spaceBarDown()) - scroll(x, y); - else { - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseDragged(imp, e); - if (e.isConsumed()) - return; - } - IJ.setInputEvent(e); - Roi roi = imp.getRoi(); - if (roi != null) - roi.handleMouseDrag(x, y, flags); - } - } - - protected void handleRoiMouseDown(MouseEvent e) { - int sx = e.getX(); - int sy = e.getY(); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - Roi roi = imp.getRoi(); - int tool = Toolbar.getToolId(); - int handle = roi != null ? roi.isHandle(sx, sy) : -1; - boolean multiPointMode = roi != null && (roi instanceof PointRoi) && handle == -1 && tool == Toolbar.POINT && Toolbar.getMultiPointMode(); - if (multiPointMode) { - double oxd = roi.offScreenXD(sx); - double oyd = roi.offScreenYD(sy); - if (e.isShiftDown() && !IJ.isMacro()) { - FloatPolygon points = roi.getFloatPolygon(); - if (points.npoints > 0) { - double x0 = points.xpoints[0]; - double y0 = points.ypoints[0]; - double slope = Math.abs((oxd - x0) / (oyd - y0)); - if (slope >= 1.0) - oyd = points.ypoints[0]; - else - oxd = points.xpoints[0]; - } - } - ((PointRoi) roi).addUserPoint(imp, oxd, oyd); - imp.setRoi(roi); - return; - } - - if (roi != null && (roi instanceof PointRoi)) { - int npoints = ((PolygonRoi) roi).getNCoordinates(); - if (npoints > 1 && handle == -1 && !IJ.altKeyDown() && !(tool == Toolbar.POINT && !Toolbar.getMultiPointMode() && IJ.shiftKeyDown())) { - String msg = "Type shift-a (Edit>Selection>Select None) to delete\npoints. Use multi-point tool to add points."; - GenericDialog gd = new GenericDialog("Point Selection"); - gd.addMessage(msg); - gd.addHelp(PointToolOptions.help); - gd.hideCancelButton(); - gd.showDialog(); - return; - } - } - - setRoiModState(e, roi, handle); - if (roi != null) { - if (handle >= 0) { - roi.mouseDownInHandle(handle, sx, sy); - return; - } - Rectangle r = roi.getBounds(); - int type = roi.getType(); - if (type == Roi.RECTANGLE && r.width == imp.getWidth() && r.height == imp.getHeight() && roi.getPasteMode() == Roi.NOT_PASTING && !(roi instanceof ImageRoi)) { - imp.deleteRoi(); - return; - } - if (roi.contains(ox, oy)) { - if (roi.modState == Roi.NO_MODS) - roi.handleMouseDown(sx, sy); - else { - imp.deleteRoi(); - imp.createNewRoi(sx, sy); - } - return; - } - boolean segmentedTool = tool == Toolbar.POLYGON || tool == Toolbar.POLYLINE || tool == Toolbar.ANGLE; - if (segmentedTool && (type == Roi.POLYGON || type == Roi.POLYLINE || type == Roi.ANGLE) && roi.getState() == roi.CONSTRUCTING) - return; - - if (segmentedTool && !(IJ.shiftKeyDown() || IJ.altKeyDown())) { - imp.deleteRoi(); - return; - } - } - imp.createNewRoi(sx, sy); - } - - void setRoiModState(MouseEvent e, Roi roi, int handle) { - if (roi == null || (handle >= 0 && roi.modState == Roi.NO_MODS)) - return; - if (roi.state == Roi.CONSTRUCTING) - return; - int tool = Toolbar.getToolId(); - if (tool > Toolbar.FREEROI && tool != Toolbar.WAND && tool != Toolbar.POINT) { - roi.modState = Roi.NO_MODS; - return; - } - if (e.isShiftDown()) - roi.modState = Roi.ADD_TO_ROI; - else if (e.isAltDown()) - roi.modState = Roi.SUBTRACT_FROM_ROI; - else - roi.modState = Roi.NO_MODS; - } - - /** Disable/enable popup menu. */ - public void disablePopupMenu(boolean status) { - disablePopupMenu = status; - } - - public void setShowAllList(Overlay showAllList) { - this.showAllOverlay = showAllList; - labelRects = null; - } - - public Overlay getShowAllList() { - return showAllOverlay; - } - - /** Obsolete */ - public void setShowAllROIs(boolean showAllROIs) { - RoiManager rm = RoiManager.getInstance(); - if (rm != null) - rm.runCommand(showAllROIs ? "show all" : "show none"); - } - - /** Obsolete */ - public boolean getShowAllROIs() { - return getShowAllList() != null; - } - - /** Obsolete */ - public static Color getShowAllColor() { - if (showAllColor != null && showAllColor.getRGB() == 0xff80ffff) - showAllColor = Color.cyan; - return showAllColor; - } - - /** Obsolete */ - public static void setShowAllColor(Color c) { - if (c == null) - return; - showAllColor = c; - labelColor = null; - } - - /** Experimental */ - public static void setCursor(Cursor cursor, int type) { - crosshairCursor = cursor; - } - - /** Use ImagePlus.setOverlay(ij.gui.Overlay). */ - public void setOverlay(Overlay overlay) { - imp.setOverlay(overlay); - } - - /** Use ImagePlus.getOverlay(). */ - public Overlay getOverlay() { - return imp.getOverlay(); - } - - /** - * @deprecated replaced by ImagePlus.setOverlay(ij.gui.Overlay) - */ - public void setDisplayList(Vector list) { - if (list != null) { - Overlay list2 = new Overlay(); - list2.setVector(list); - imp.setOverlay(list2); - } else - imp.setOverlay(null); - Overlay overlay = imp.getOverlay(); - if (overlay != null) - overlay.drawLabels(overlay.size() > 0 && overlay.get(0).getStrokeColor() == null); - else - customRoi = false; - repaint(); - } - - /** - * @deprecated replaced by ImagePlus.setOverlay(Shape, Color, BasicStroke) - */ - public void setDisplayList(Shape shape, Color color, BasicStroke stroke) { - imp.setOverlay(shape, color, stroke); - } - - /** - * @deprecated replaced by ImagePlus.setOverlay(Roi, Color, int, Color) - */ - public void setDisplayList(Roi roi, Color color) { - roi.setStrokeColor(color); - Overlay list = new Overlay(); - list.add(roi); - imp.setOverlay(list); - } - - /** - * @deprecated replaced by ImagePlus.getOverlay() - */ - public Vector getDisplayList() { - Overlay overlay = imp.getOverlay(); - if (overlay == null) - return null; - Vector displayList = new Vector(); - for (int i = 0; i < overlay.size(); i++) - displayList.add(overlay.get(i)); - return displayList; - } - - /** - * Allows plugins (e.g., Orthogonal_Views) to create a custom ROI using a - * display list. - */ - public void setCustomRoi(boolean customRoi) { - this.customRoi = customRoi; - } - - public boolean getCustomRoi() { - return customRoi; - } - - /** - * Called by IJ.showStatus() to prevent status bar text from being overwritten - * until the cursor moves at least 12 pixels. - */ - public void setShowCursorStatus(boolean status) { - showCursorStatus = status; - if (status == true) - sx2 = sy2 = -1000; - else { - sx2 = screenX(xMouse); - sy2 = screenY(yMouse); - } - } - - public void mouseReleased(MouseEvent e) { - - if (pressTimer != null) { - pressTimer.cancel(); - pressTimer = null; - } - - int ox = offScreenX(e.getX()); - int oy = offScreenY(e.getY()); - Overlay overlay = imp.getOverlay(); - if ((overlay != null || showAllOverlay != null) && ox == mousePressedX && oy == mousePressedY) { - boolean cmdDown = IJ.isMacOSX() && e.isMetaDown(); - Roi roi = imp.getRoi(); - if (roi != null && roi.getBounds().width == 0) - roi = null; - if ((e.isAltDown() || e.isControlDown() || cmdDown) && roi == null) { - if (activateOverlayRoi(ox, oy)) - return; - } else if ((System.currentTimeMillis() - mousePressedTime) > 250L && !drawingTool()) { // long press - if (activateOverlayRoi(ox, oy)) - return; - } - - } - - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseReleased(imp, e); - if (e.isConsumed()) - return; - } - flags = e.getModifiers(); - flags &= ~InputEvent.BUTTON1_MASK; // make sure button 1 bit is not set - flags &= ~InputEvent.BUTTON2_MASK; // make sure button 2 bit is not set - flags &= ~InputEvent.BUTTON3_MASK; // make sure button 3 bit is not set - Roi roi = imp.getRoi(); - if (roi != null) { - Rectangle r = roi.getBounds(); - int type = roi.getType(); - if ((r.width == 0 || r.height == 0) && !(type == Roi.POLYGON || type == Roi.POLYLINE || type == Roi.ANGLE || type == Roi.LINE) && !(roi instanceof TextRoi) - && roi.getState() == roi.CONSTRUCTING && type != roi.POINT) - imp.deleteRoi(); - else - roi.handleMouseUp(e.getX(), e.getY()); - } - } - - private boolean activateOverlayRoi(int ox, int oy) { - int currentImage = -1; - int stackSize = imp.getStackSize(); - if (stackSize > 1) - currentImage = imp.getCurrentSlice(); - int channel = 0, slice = 0, frame = 0; - boolean hyperstack = imp.isHyperStack(); - if (hyperstack) { - channel = imp.getChannel(); - slice = imp.getSlice(); - frame = imp.getFrame(); - } - Overlay o = showAllOverlay; - if (o == null) - o = imp.getOverlay(); - if (o == null || !o.isSelectable()) - return false; - boolean roiManagerShowAllMode = o == showAllOverlay && !Prefs.showAllSliceOnly; - boolean labels = o.getDrawLabels(); - int sx = screenX(ox); - int sy = screenY(oy); - for (int i = o.size() - 1; i >= 0; i--) { - Roi roi = o.get(i); - if (roi == null) - continue; - boolean containsMousePoint = false; - if (roi instanceof Line) { // grab line roi near its center - double grabLineWidth = 1.1 + 5. / magnification; - containsMousePoint = (((Line) roi).getFloatPolygon(grabLineWidth)).contains(ox, oy); - } else - containsMousePoint = roi.contains(ox, oy); - if (containsMousePoint || (labels && labelRects != null && labelRects[i] != null && labelRects[i].contains(sx, sy))) { - if (hyperstack && roi.getPosition() == 0) { - int c = roi.getCPosition(); - int z = roi.getZPosition(); - int t = roi.getTPosition(); - if (!((c == 0 || c == channel) && (z == 0 || z == slice) && (t == 0 || t == frame) || roiManagerShowAllMode)) - continue; - } else { - int position = stackSize > 1 ? roi.getPosition() : 0; - if (!(position == 0 || position == currentImage || roiManagerShowAllMode)) - continue; - } - if (!IJ.altKeyDown() && roi.getType() == Roi.COMPOSITE && roi.getBounds().width == imp.getWidth() && roi.getBounds().height == imp.getHeight()) - return false; - // if (Toolbar.getToolId()==Toolbar.OVAL && Toolbar.getBrushSize()>0) - // Toolbar.getInstance().setTool(Toolbar.RECTANGLE); - roi.setImage(null); - imp.setRoi(roi); - roi.handleMouseDown(sx, sy); - roiManagerSelect(roi, false); - ResultsTable.selectRow(roi); - return true; - } - } - return false; - } - - public boolean roiManagerSelect(Roi roi, boolean delete) { - RoiManager rm = RoiManager.getInstance(); - if (rm == null) - return false; - int index = rm.getRoiIndex(roi); - if (index < 0) - return false; - if (delete) { - rm.select(imp, index); - rm.runCommand("delete"); - } else - rm.selectAndMakeVisible(imp, index); - return true; - } - - public void mouseMoved(MouseEvent e) { - // if (ij==null) return; - int sx = e.getX(); - int sy = e.getY(); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - flags = e.getModifiers(); - setCursor(sx, sy, ox, oy); - mousePressedX = mousePressedY = -1; - IJ.setInputEvent(e); - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) { - tool.mouseMoved(imp, e); - if (e.isConsumed()) - return; - } - Roi roi = imp.getRoi(); - int type = roi != null ? roi.getType() : -1; - if (type > 0 && (type == Roi.POLYGON || type == Roi.POLYLINE || type == Roi.ANGLE || type == Roi.LINE) && roi.getState() == roi.CONSTRUCTING) - roi.mouseMoved(e); - else { - if (ox < imageWidth && oy < imageHeight) { - ImageWindow win = imp.getWindow(); - // Cursor must move at least 12 pixels before text - // displayed using IJ.showStatus() is overwritten. - if ((sx - sx2) * (sx - sx2) + (sy - sy2) * (sy - sy2) > 144) - showCursorStatus = true; - if (win != null && showCursorStatus) - win.mouseMoved(ox, oy); - } else - IJ.showStatus(""); - } - } - - public void mouseEntered(MouseEvent e) { - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) - tool.mouseEntered(imp, e); - } - - public void mouseClicked(MouseEvent e) { - Util.activateView("com.eco.bio7.imagej"); - /* Changed for Bio7! */ - if (this.isFocusOwner() == false) { - this.requestFocus(); - - } - WindowManager.setTempCurrentImage(imp); - WindowManager.setCurrentWindow(imp.getWindow()); - - /* import to set current Panel! */ - CanvasView.setCurrent((JPanel) this.getParent()); - - PlugInTool tool = Toolbar.getPlugInTool(); - if (tool != null) - tool.mouseClicked(imp, e); - } - - /* Changed for Bio7! */ - public void mouseWheelMoved(MouseWheelEvent e) { - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - if (IJ.debugMode) { - IJ.log("mouseWheelMoved: " + e); - IJ.log(" type: " + e.getScrollType()); - IJ.log(" ctrl: " + ctrl); - IJ.log(" rotation: " + rotation); - IJ.log(" amount: " + amount); - } - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - int width = imp.getWidth(); - int height = imp.getHeight(); - Rectangle srcRect = getSrcRect(); - int xstart = srcRect.x; - int ystart = srcRect.y; - if ((ctrl || IJ.shiftKeyDown()) && this != null) { - int ox = offScreenX(e.getX()); - int oy = offScreenY(e.getX()); - if (IJ.debugMode) - IJ.log(" x,y: " + ox + "," + oy); - if (rotation < 0) - zoomIn(ox, oy); - else - zoomOut(ox, oy); - return; - } else if (IJ.spaceBarDown() || srcRect.height == height) { - srcRect.x += rotation * amount * Math.max(width / 200, 1); - if (srcRect.x < 0) - srcRect.x = 0; - if (srcRect.x + srcRect.width > width) - srcRect.x = width - srcRect.width; - } else { - srcRect.y += rotation * amount * Math.max(height / 200, 1); - if (srcRect.y < 0) - srcRect.y = 0; - if (srcRect.y + srcRect.height > height) - srcRect.y = height - srcRect.height; - } - if (srcRect.x != xstart || srcRect.y != ystart) - repaint(); - - } - - public void setScaleToFit(boolean scaleToFit) { - this.scaleToFit = scaleToFit; - } - - public boolean getScaleToFit() { - return scaleToFit; - } - - public boolean hideZoomIndicator(boolean hide) { - boolean hidden = this.hideZoomIndicator; - if (!(srcRect.width < imageWidth || srcRect.height < imageHeight)) - return hidden; - this.hideZoomIndicator = hide; - setPaintPending(true); - repaint(); - long t0 = System.currentTimeMillis(); - while (getPaintPending() && (System.currentTimeMillis() - t0) < 500L) - IJ.wait(10); - return hidden; - } - - public void repaintOverlay() { - labelRects = null; - repaint(); - } - - /** - * Sets the context menu long click delay in milliseconds (default is 1000). Set - * to 0 to disable long click triggering. - */ - public static void setLongClickDelay(int delay) { - longClickDelay = delay; - } - - void addRoiPopupMenu() { - ImageJ ij = IJ.getInstance(); - if (ij == null) - return; - roiPopupMenu = new PopupMenu(); - GUI.scalePopupMenu(roiPopupMenu); - addPopupItem("ROI Properties... ", "Properties... ", roiPopupMenu, ij); - addPopupItem("Roi Defaults...", null, roiPopupMenu, ij); - addPopupItem("Add to Overlay", "Add Selection...", roiPopupMenu, ij); - addPopupItem("Add to ROI Manager", "Add to Manager", roiPopupMenu, ij); - addPopupItem("Duplicate...", null, roiPopupMenu, ij); - addPopupItem("Fit Spline", null, roiPopupMenu, ij); - addPopupItem("Create Mask", null, roiPopupMenu, ij); - addPopupItem("Measure", null, roiPopupMenu, ij); - add(roiPopupMenu); - } - - private void addPopupItem(String label, String command, PopupMenu pm, ImageJ ij) { - MenuItem mi = new MenuItem(label); - if (command != null) - mi.setActionCommand(command); - mi.addActionListener(ij); - pm.add(mi); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImageLayout.java b/com.eco.bio7.image/src/ij/gui/ImageLayout.java deleted file mode 100644 index 7888616c7..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageLayout.java +++ /dev/null @@ -1,113 +0,0 @@ -package ij.gui; -import java.awt.*; -import ij.*; - -/** This is a custom layout manager that supports resizing of zoomed -images. It's based on FlowLayout, but with vertical and centered flow. */ -public class ImageLayout implements LayoutManager { - - int hgap = ImageWindow.HGAP; - int vgap = ImageWindow.VGAP; - ImageCanvas ic; - boolean ignoreNonImageWidths; - - /** Creates a new ImageLayout with center alignment. */ - public ImageLayout(ImageCanvas ic) { - this.ic = ic; - } - - /** Not used by this class. */ - public void addLayoutComponent(String name, Component comp) { - } - - /** Not used by this class. */ - public void removeLayoutComponent(Component comp) { - } - - /** Returns the preferred dimensions for this layout. */ - public Dimension preferredLayoutSize(Container target) { - Dimension dim = new Dimension(0,0); - int nmembers = target.getComponentCount(); - for (int i=0; i0) dim.height += vgap; - dim.height += d.height; - } - Insets insets = target.getInsets(); - dim.width += insets.left + insets.right + hgap*2; - dim.height += insets.top + insets.bottom + vgap*2; - return dim; - } - - /** Returns the minimum dimensions for this layout. */ - public Dimension minimumLayoutSize(Container target) { - return preferredLayoutSize(target); - } - - /** Determines whether to ignore the width of non-image components when calculating - * the preferred width (default false, i.e. the maximum of the widths of all components is used). - * When true, components that do not fit the window will be truncated at the right. - * The width of the 0th component (the ImageCanvas) is always taken into account. */ - public void ignoreNonImageWidths(boolean ignoreNonImageWidths) { - this.ignoreNonImageWidths = ignoreNonImageWidths; - } - - /** Centers the elements in the specified column, if there is any slack.*/ - private void moveComponents(Container target, int x, int y, int width, int height, int nmembers) { - int x2 = 0; - y += height / 2; - for (int i=0; i60) - x2 = x + (width - d.width)/2; - m.setLocation(x2, y); - y += vgap + d.height; - } - } - - /** Lays out the container and calls ImageCanvas.resizeCanvas() - to adjust the image canvas size as needed. */ - public void layoutContainer(Container target) { - Insets insets = target.getInsets(); - int nmembers = target.getComponentCount(); - Dimension d; - int extraHeight = 0; - for (int i=1; i 0) y += vgap; - y += d.height; - if (i==0 || !ignoreNonImageWidths) - colw = Math.max(colw, d.width); - } - moveComponents(target, x, insets.top + vgap, colw, maxheight - y, nmembers); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImagePanel.java b/com.eco.bio7.image/src/ij/gui/ImagePanel.java deleted file mode 100644 index 13481eedb..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImagePanel.java +++ /dev/null @@ -1,25 +0,0 @@ -package ij.gui; -import java.awt.*; -import ij.*; - -/** This class is used by GenericDialog to add images to dialogs. */ -public class ImagePanel extends Panel { - private ImagePlus img; - - public ImagePanel(ImagePlus img) { - this.img = img; - } - - public Dimension getPreferredSize() { - return new Dimension(img.getWidth(), img.getHeight()); - } - - public Dimension getMinimumSize() { - return new Dimension(img.getWidth(), img.getHeight()); - } - - public void paint(Graphics g) { - g.drawImage(img.getProcessor().createImage(), 0, 0, null); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ImageRoi.java b/com.eco.bio7.image/src/ij/gui/ImageRoi.java deleted file mode 100644 index 1f2bd6e2f..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageRoi.java +++ /dev/null @@ -1,152 +0,0 @@ -package ij.gui; -import ij.ImagePlus; -import ij.process.*; -import ij.io.FileSaver; -import java.awt.*; -import java.awt.image.*; - -/** An ImageRoi is an Roi that overlays an image. -* @see ij.ImagePlus#setOverlay(ij.gui.Overlay) -*/ -public class ImageRoi extends Roi { - private Image img; - private Composite composite; - private double opacity = 1.0; - private double angle = 0.0; - private boolean zeroTransparent; - private ImageProcessor ip; - - /** Creates a new ImageRoi from a BufferedImage.*/ - public ImageRoi(int x, int y, BufferedImage bi) { - super(x, y, bi.getWidth(), bi.getHeight()); - img = bi; - setStrokeColor(Color.black); - } - - /** Creates a new ImageRoi from a ImageProcessor.*/ - public ImageRoi(int x, int y, ImageProcessor ip) { - super(x, y, ip.getWidth(), ip.getHeight()); - img = ip.createImage(); - this.ip = ip; - setStrokeColor(Color.black); - } - - public void draw(Graphics g) { - Graphics2D g2d = (Graphics2D)g; - double mag = getMagnification(); - int sx2 = screenX(x+width); - int sy2 = screenY(y+height); - Composite saveComposite = null; - if (composite!=null) { - saveComposite = g2d.getComposite(); - g2d.setComposite(composite); - } - Image img2 = img; - if (angle!=0.0) { - ImageProcessor ip = new ColorProcessor(img); - ip.setInterpolate(true); - ip.setBackgroundValue(0.0); - ip.rotate(angle); - if (zeroTransparent) - ip = makeZeroTransparent(ip, true); - img2 = ip.createImage(); - } - g.drawImage(img2, screenX(x), screenY(y), sx2, sy2, 0, 0, img.getWidth(null), img.getHeight(null), null); - if (composite!=null) g2d.setComposite(saveComposite); - if (isActiveOverlayRoi() && !overlay) - super.draw(g); - } - - /** Sets the composite mode. */ - public void setComposite(Composite composite) { - this.composite = composite; - } - - /** Sets the composite mode using the specified opacity (alpha), in the - range 0.0-1.0, where 0.0 is fully transparent and 1.0 is fully opaque. */ - public void setOpacity(double opacity) { - if (opacity<0.0) opacity = 0.0; - if (opacity>1.0) opacity = 1.0; - this.opacity = opacity; - if (opacity!=1.0) - composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)opacity); - else - composite = null; - } - - /** Returns a serialized version of the image. */ - public byte[] getSerializedImage() { - ImagePlus imp = new ImagePlus("",img); - return new FileSaver(imp).serialize(); - } - - /** Returns the current opacity. */ - public double getOpacity() { - return opacity; - } - - public void rotate(double angle) { - this.angle += angle; - } - - public void setAngle(double angle) { - this.angle = angle; - } - - public void setZeroTransparent(boolean zeroTransparent) { - if (this.zeroTransparent!=zeroTransparent) { - ip = makeZeroTransparent(new ColorProcessor(img), zeroTransparent); - img = ip.createImage(); - } - this.zeroTransparent = zeroTransparent; - } - - public boolean getZeroTransparent() { - return zeroTransparent; - } - - private ImageProcessor makeZeroTransparent(ImageProcessor ip, boolean transparent) { - if (transparent) { - ip.setColorModel(new DirectColorModel(32,0x00ff0000,0x0000ff00,0x000000ff,0xff000000)); - for (int x=0; x1) - ip.set(x, y, ip.get(x,y)|0xff000000); // set alpha bits - else - ip.set(x, y, ip.get(x,y)&0xffffff); // clear alpha bits - } - } - } - return ip; - } - - public synchronized Object clone() { - ImageRoi roi2 = (ImageRoi)super.clone(); - ImagePlus imp = new ImagePlus("", img); - roi2.setProcessor(imp.getProcessor()); - roi2.setOpacity(getOpacity()); - return roi2; - } - - public ImageProcessor getProcessor() { - if (ip!=null) - return ip; - else { - ip = new ColorProcessor(img); - return ip; - } - } - - public void setProcessor(ImageProcessor ip) { - img = ip.createImage(); - this.ip = ip; - if (zeroTransparent) { - setZeroTransparent(false); - setZeroTransparent(true); - } - width = ip.getWidth(); - height = ip.getHeight(); - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/ImageWindow.java b/com.eco.bio7.image/src/ij/gui/ImageWindow.java deleted file mode 100644 index a7fbf16bd..000000000 --- a/com.eco.bio7.image/src/ij/gui/ImageWindow.java +++ /dev/null @@ -1,1120 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.image.*; -import java.util.Properties; -import java.util.Vector; - -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - -import java.awt.event.*; - -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.swt.custom.CTabItem; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IViewReference; -import org.eclipse.ui.PlatformUI; - -import com.eco.bio7.image.Activator; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.CustomDetachedImageJView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.SwtAwtImageJ; -import com.eco.bio7.image.Util; - -import ij.*; -import ij.process.*; -import ij.io.*; -import ij.measure.*; -import ij.plugin.frame.*; -import ij.plugin.PointToolOptions; -import ij.macro.Interpreter; -import ij.util.*; - -/** A frame for displaying images. */ -public class ImageWindow extends JFrame - implements FocusListener, WindowListener, WindowStateListener, MouseWheelListener { - - public static final int MIN_WIDTH = 128; - public static final int MIN_HEIGHT = 32; - public static final int HGAP = 5; - public static final int VGAP = 5; - public static final String LOC_KEY = "image.loc"; - - protected ImagePlus imp; - protected ImageJ ij; - protected ImageCanvas ic; - private double initialMagnification = 1; - private int newWidth, newHeight; - protected boolean closed; - private boolean newCanvas; - private boolean unzoomWhenMinimizing = true; - Rectangle maxWindowBounds; // largest possible window on this screen - Rectangle maxBounds; // Size of this window after it is maximized - long setMaxBoundsTime; - private int sliderHeight; - private static final int XINC = 12; - private static final int YINC = 16; - private final double SCALE = Prefs.getGuiScale(); - private int TEXT_GAP = 11; - private static int xbase = -1; - private static int ybase; - private static int xloc; - private static int yloc; - private static int count; - private static boolean centerOnScreen; - private static Point nextLocation; - public static long setMenuBarTime; - private int textGap = centerOnScreen ? 0 : TEXT_GAP; - private int screenHeight, screenWidth; - public SwtAwtImageJ swtAwtMain;// Changed for Bio7! - public boolean running2; - protected boolean imageInTab; - protected ImageWindow win2; - /** - * This variable is set false if the user presses the escape key or closes the - * window. - */ - public boolean running; - - /** - * This variable is set false if the user clicks in this window, presses the - * escape key, or closes the window. - */ - - // private ImageWindow windowInstance;// Changed for Bio7! - public SwtAwtImageJ getSwtAwtMain() { - return swtAwtMain; - } - - public void setSwtAwtMain(SwtAwtImageJ swtAwtMainFrame) { - this.swtAwtMain = swtAwtMainFrame; - } - - public ImageWindow(String title) { - super(title); - } - - public ImageWindow(ImagePlus imp) { - this(imp, null); - /// * Changed for Bio7! */ - // windowInstance = this; - } - - /* Changed for Bio7 setting the tab title and not the JFrame title! */ - public void setTitle(String title) { - - final CTabItem[] items = CanvasView.getCanvas_view().tabFolder.getItems(); - Display dis = CanvasView.getParent2().getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - for (int i = 0; i < items.length; i++) { - - Vector ve = (Vector) items[i].getData(); - - final ImageWindow win2 = (ImageWindow) ve.get(1); - - /* Search for the tab which embeds this instance! */ - if (ImageWindow.this.equals(win2)) { - // Rename the tab! - CanvasView.tabFolder.getItem(i).setText(title); - - return; - - } - - } - - /* - * CustomDetachedImageJView customImageJView = ImageJ.customImageJView; if - * (customImageJView != null) { customImageJView.setPartName(title); } - */ - - IViewReference[] viewRefs = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() - .getViewReferences(); - for (int i = 0; i < viewRefs.length; i++) { - String id = viewRefs[i].getId(); - if (id.equals("com.eco.bio7.image.detachedImage")) { - IViewPart view = viewRefs[i].getView(false); - String secId = viewRefs[i].getSecondaryId(); - CustomDetachedImageJView cdview = (CustomDetachedImageJView) view; - /* Get the image from the detached secondary view id (same id)! */ - ImagePlus ip = WindowManager.getImage(Integer.valueOf(secId)); - if (ip != null) { - if (ImageWindow.this.equals(ip.getWindow())) { - cdview.setPartName(title); - } - } - - } - } - - } - }); - - } - - public ImageWindow(ImagePlus imp, ImageCanvas ic) { - super(imp.getTitle()); - if (SCALE > 1.0) { - TEXT_GAP = (int) (TEXT_GAP * SCALE); - textGap = centerOnScreen ? 0 : TEXT_GAP; - } - boolean openAsHyperStack = imp.getOpenAsHyperStack(); - ij = IJ.getInstance(); - this.imp = imp; - if (ic == null) { - ic = (this instanceof PlotWindow) ? new PlotCanvas(imp) : new ImageCanvas(imp); - newCanvas = true; - } - this.ic = ic; - ImageWindow previousWindow = imp.getWindow(); - - setLayout(new ImageLayout(ic)); - add(ic); - addFocusListener(this); - addWindowListener(this); - addWindowStateListener(this); - addKeyListener(ij); - - setFocusTraversalKeysEnabled(false); - if (!(this instanceof StackWindow)) - addMouseWheelListener(this); - - setResizable(true); - if (!(this instanceof HistogramWindow && IJ.isMacro() && Interpreter.isBatchMode())) { - WindowManager.addWindow(this); - imp.setWindow(this); - } - if (previousWindow != null) { - /* Hide the tab without to close the image! */ - IJTabs.hideTab(); - if (newCanvas) - setLocationAndSize(false); - else - ic.update(previousWindow.getCanvas()); - - if (!(this instanceof StackWindow || this instanceof PlotWindow)) { // layout now unless components will be - // added later - swtAwtMain = new SwtAwtImageJ(null, null, null, ic, imp, this); - /* Add the panel to the tab folder with the image */ - swtAwtMain.addTab(imp.getTitle()); - imp.setWindow(this); - - /* - * The next seems to be important for Mac. Else at the first zoom level the - * image disapears! - */ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - pack(); - } - }); - /* Necessary for highDPI layout SWT_AWT! */ - CanvasView canvasView = CanvasView.getCanvas_view(); - canvasView.recalculateLayout(); - /* - * The next seems to be important for Mac. Else at the first zoom level the - * image disapears! - */ - if (IJ.isMacro()) - imp.setDeactivated(); // prepare for waitTillActivated (imp may have been activated before if it - // gets a new Window now) - // show(); - } - if (ic.getMagnification() != 0.0) - imp.setTitle(imp.getTitle()); - boolean unlocked = imp.lockSilently(); - boolean changes = imp.changes; - imp.changes = false; - /* - * Changed for Bio7. We have to call the default ImageJ close function which is - * renamed to bio7TabClose because we have hidden the tab already (close - * searches for the tab and closes it)! - */ - previousWindow.bio7TabClose(true); - imp.changes = changes; - if (unlocked) - imp.unlock(); - if (this.imp != null) - this.imp.setOpenAsHyperStack(openAsHyperStack); - WindowManager.setCurrentWindow(this); - } else { - // setLocationAndSize(false); - /* - * if (ij != null && !IJ.isMacintosh()) { Image img = ij.getIconImage(); if (img!=null) try { - setIconImage(img); - } catch (Exception e) {} - */ - - if (Interpreter.isBatchMode() || (IJ.getInstance() == null && this instanceof HistogramWindow)) { - WindowManager.setTempCurrentImage(imp); - Interpreter.addBatchModeImage(imp); - } - - else { - if (IJ.isMacro()) - imp.setDeactivated(); // prepare for waitTillActivated (imp may have been activated previously and - // gets a new Window now) - - if (!(this instanceof StackWindow)) { - swtAwtMain = new SwtAwtImageJ(null, null, null, ic, imp, this); - /* Add the panel to the tab folder with the image */ - swtAwtMain.addTab(imp.getTitle()); - imp.setWindow(this); - /* - * The next seems to be important for Mac. Else at the first zoom level the - * image disapears! - */ - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - pack(); - } - }); - /* Necessary for highDPI layout SWT_AWT! */ - CanvasView canvasView = CanvasView.getCanvas_view(); - canvasView.recalculateLayout(); - - } - - } - - } - - } - - private void setLocationAndSize(boolean updating) { - if (imp == null) - return; - int width = imp.getWidth(); - int height = imp.getHeight(); - - // load preferences file location - Point loc = Prefs.getLocation(LOC_KEY); - Rectangle bounds = null; - if (loc != null) { - bounds = GUI.getMaxWindowBounds(loc); - if (bounds != null && (loc.x > bounds.x + bounds.width / 3 || loc.y > bounds.y + bounds.height / 3) - && (loc.x + width > bounds.x + bounds.width || loc.y + height > bounds.y + bounds.height)) { - loc = null; - bounds = null; - } - } - // if loc not valid, use screen bounds of visible window (this) or of main - // window (ij) if not visible yet (updating == false) - Rectangle maxWindow = bounds != null ? bounds : GUI.getMaxWindowBounds(updating ? this : ij); - - if (WindowManager.getWindowCount() <= 1) - xbase = -1; - if (width > maxWindow.width / 2 && xbase > maxWindow.x + 5 + XINC * 6) - xbase = -1; - if (xbase == -1) { - count = 0; - if (loc != null) { - xbase = loc.x; - ybase = loc.y; - } else if (ij != null) { - Rectangle ijBounds = ij.getBounds(); - if (ijBounds.y - maxWindow.x < maxWindow.height / 8) { - xbase = ijBounds.x; - if (xbase + width > maxWindow.x + maxWindow.width) { - xbase = maxWindow.x + maxWindow.width - width - 10; - if (xbase < maxWindow.x) - xbase = maxWindow.x + 5; - ; - } - ybase = ijBounds.y + ijBounds.height + 5; - } else { - xbase = maxWindow.x + (maxWindow.width - width) / 2; - ybase = maxWindow.y + (maxWindow.height - height) / 4; - } - } else { - xbase = maxWindow.x + (maxWindow.width - width) / 2; - ybase = maxWindow.y + (maxWindow.height - height) / 4; - } - xbase = Math.max(xbase, maxWindow.x); - ybase = Math.max(ybase, maxWindow.y); - //if (IJ.debugMode) - //IJ.log("ImageWindow.xbase: " + xbase); - xloc = xbase; - yloc = ybase; - } - int x = xloc; - int y = yloc; - xloc += XINC; - yloc += YINC; - count++; - if (count % 6 == 0) { - xloc = xbase; - yloc = ybase; - } - - screenHeight = maxWindow.y + maxWindow.height - sliderHeight; - screenWidth = maxWindow.x + maxWindow.width; - double mag = 1; - if (!(this instanceof PlotWindow)) { // unless a plot (always at 100%), zoom out to show all of image - while (xbase + width * mag > screenWidth || ybase + height * mag >= screenHeight) { - double mag2 = ImageCanvas.getLowerZoomLevel(mag); - if (mag2 == mag) - break; - mag = mag2; - } - } - - if (mag < 1.0) { - initialMagnification = mag; - ic.setSize((int) (width * mag), (int) (height * mag)); - } - ic.setMagnification(mag); - if (y + height * mag > screenHeight) - y = ybase; - if (Prefs.open100Percent && ic.getMagnification() < 1.0) { - while (ic.getMagnification() < 1.0) - ic.zoomIn(0, 0); - setSize(Math.min(width, screenWidth - x), Math.min(height, screenHeight - y)); - validate(); - } else - pack(); - if (!updating) - setLocation(x, y); - } - - Rectangle getMaxWindow(int xloc, int yloc) { - - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - /* Changed for Bio7! */ - Rectangle bounds = CanvasView.getCanvas_view().getCurrent().getBounds(); - - // return GUI.getMaxWindowBounds(new Point(xloc, yloc)); - - return bounds; - } - - /* - * public Rectangle getBounds() { - * - * Changed for Bio7! Rectangle bounds = - * CanvasView.getCanvas_view().getCurrent().getBounds(); - * - * return bounds; } - */ - - public double getInitialMagnification() { - return initialMagnification; - } - - /** - * Override Container getInsets() to make room for some text above the image. - */ - /* - * public Insets getInsets() { Insets insets = super.getInsets(); if (imp == - * null) return insets; double mag = ic.getMagnification(); int extraWidth = - * (int) ((MIN_WIDTH - imp.getWidth() * mag) / 2.0); if (extraWidth < 0) - * extraWidth = 0; int extraHeight = (int) ((MIN_HEIGHT - imp.getHeight() * mag) - * / 2.0); if (extraHeight < 0) extraHeight = 0; insets = new Insets(insets.top - * + textGap + extraHeight, insets.left + extraWidth, insets.bottom + - * extraHeight, insets.right + extraWidth); return insets; } - */ - - /** Draws the subtitle. */ - public void drawInfo(Graphics g) { - if (imp == null) - return; - if (textGap != 0) { - Insets insets = super.getInsets(); - Color savec = null; - if (imp.isComposite()) { - CompositeImage ci = (CompositeImage) imp; - if (ci.getMode() == IJ.COMPOSITE) { - savec = g.getColor(); - Color c = ci.getChannelColor(); - if (Color.green.equals(c)) - c = new Color(0, 180, 0); - g.setColor(c); - } - } - Java2.setAntialiasedText(g, true); - if (SCALE > 1.0) { - Font font = new Font("SansSerif", Font.PLAIN, (int) (12 * SCALE)); - g.setFont(font); - } - g.drawString(createSubtitle(), insets.left + 5, insets.top + TEXT_GAP); - if (savec != null) - g.setColor(savec); - } - } - - /** Creates the subtitle. */ - public String createSubtitle() { - String s = ""; - if (imp == null) - return s; - int stackSize = imp.getStackSize(); - if (stackSize > 1) { - ImageStack stack = imp.getStack(); - int currentSlice = imp.getCurrentSlice(); - s += currentSlice + "/" + stackSize; - String label = stack.getShortSliceLabel(currentSlice); - if (label != null && label.length() > 0) { - if (imp.isHyperStack()) - label = label.replace(';', ' '); - s += " (" + label + ")"; - } - if ((this instanceof StackWindow) && running2) { - return s; - } - s += "; "; - } else { - String label = imp.getProp("Slice_Label"); - if (label==null && imp.hasImageStack()) - label = imp.getStack().getSliceLabel(1); - if (label != null && label.length() > 0) { - int newline = label.indexOf('\n'); - if (newline > 0) - label = label.substring(0, newline); - int len = label.length(); - if (len > 4 && label.charAt(len - 4) == '.' && !Character.isDigit(label.charAt(len - 1))) - label = label.substring(0, len - 4); - if (label.length() > 60) - label = label.substring(0, 60) + "..."; - s = "\"" + label + "\"; "; - } - } - int type = imp.getType(); - Calibration cal = imp.getCalibration(); - if (cal.scaled()) { - boolean unitsMatch = cal.getXUnit().equals(cal.getYUnit()); - double cwidth = imp.getWidth() * cal.pixelWidth; - double cheight = imp.getHeight() * cal.pixelHeight; - int digits = Tools.getDecimalPlaces(cwidth, cheight); - if (digits > 2) - digits = 2; - if (unitsMatch) { - s += IJ.d2s(cwidth, digits) + "x" + IJ.d2s(cheight, digits) + " " + cal.getUnits() + " (" - + imp.getWidth() + "x" + imp.getHeight() + "); "; - } else { - s += d2s(cwidth) + " " + cal.getXUnit() + " x " + d2s(cheight) + " " + cal.getYUnit() + " (" - + imp.getWidth() + "x" + imp.getHeight() + "); "; - } - } else - s += imp.getWidth() + "x" + imp.getHeight() + " pixels; "; - switch (type) { - case ImagePlus.GRAY8: - case ImagePlus.COLOR_256: - s += "8-bit"; - break; - case ImagePlus.GRAY16: - s += "16-bit"; - break; - case ImagePlus.GRAY32: - s += "32-bit"; - break; - case ImagePlus.COLOR_RGB: - s += imp.isRGB() ? "RGB" : "32-bit (int)"; - break; - } - if (imp.isInvertedLut()) - s += " (inverting LUT)"; - return s + "; " + getImageSize(imp); - } - - public static String getImageSize(ImagePlus imp) { - if (imp == null) - return null; - double size = imp.getSizeInBytes() / 1024.0; - String s2 = null, s3 = null; - if (size < 1024.0) { - s2 = IJ.d2s(size, 0); - s3 = "K"; - } else if (size < 10000.0) { - s2 = IJ.d2s(size / 1024.0, 1); - s3 = "MB"; - } else if (size < 1048576.0) { - s2 = IJ.d2s(Math.round(size / 1024.0), 0); - s3 = "MB"; - } else { - s2 = IJ.d2s(size / 1048576.0, 1); - s3 = "GB"; - } - if (s2.endsWith(".0")) - s2 = s2.substring(0, s2.length() - 2); - return s2 + s3; - } - - private String d2s(double n) { - int digits = Tools.getDecimalPlaces(n); - if (digits > 2) - digits = 2; - return IJ.d2s(n, digits); - } - - /* Changed for Bio7! */ - /* - * public Rectangle getBounds(){ GraphicsEnvironment ge = - * GraphicsEnvironment.getLocalGraphicsEnvironment(); Changed for Bio7! - * Rectangle bounds = CanvasView.getCanvas_view().getCurrent().getBounds(); - * return bounds; } - */ - - public void paintComponents(Graphics g) { - super.paintComponents(g); - drawInfo(g); - Rectangle r = ic.getBounds(); - int extraWidth = MIN_WIDTH - r.width; - int extraHeight = MIN_HEIGHT - r.height; - if (extraWidth <= 0 && extraHeight <= 0 && !Prefs.noBorder && !IJ.isLinux()) - g.drawRect(r.x - 1, r.y - 1, r.width + 1, r.height + 1); - } - - /** - * Removes this window from the window list and disposes of it. Returns false if - * the user cancels the "save changes" dialog. - */ - public boolean close() { - /* - * boolean isRunning = running || running2; running = running2 = false; if - * (imp==null) return true; boolean virtual = imp.getStackSize()>1 && - * imp.getStack().isVirtual(); if (isRunning) IJ.wait(500); if (ij==null || - * IJ.getApplet()!=null || Interpreter.isBatchMode() || IJ.macroRunning() || - * virtual) imp.changes = false; if (imp.changes) { String msg; String name = - * imp.getTitle(); if (name.length()>22) msg = "Save changes to\n" + "\"" + name - * + "\"?"; else msg = "Save changes to \"" + name + "\"?"; YesNoCancelDialog d - * = new YesNoCancelDialog(this, "ImageJ", msg); if (d.cancelPressed()) return - * false; else if (d.yesPressed()) { FileSaver fs = new FileSaver(imp); if - * (!fs.save()) return false; } } closed = true; if - * (WindowManager.getWindowCount()==0) {xloc = 0; yloc = 0;} if - * (firstSmallWindow) Prefs.saveLocation(LOC_KEY, getLocation()); - * WindowManager.removeWindow(this); - if (ij!=null && ij.quitting()) // this may help avoid thread deadlocks - return true; - Rectangle bounds = getBounds(); - if (initialLoc!=null && !bounds.equals(initialLoc) && !IJ.isMacro() - && bounds.y 1 && imp.getStack().isVirtual(); - if (isRunning) - IJ.wait(500); - if (ij == null || ij.quittingViaMacro() || IJ.getApplet() != null || Interpreter.isBatchMode() - || IJ.macroRunning() || virtual) - imp.changes = false; - /* Changed for Bio7! */ - /* - * if (imp.changes) { String msg; String name = imp.getTitle(); if - * (name.length()>22) msg = "Save changes to\n" + "\"" + name + "\"?"; else msg - * = "Save changes to \"" + name + "\"?"; YesNoCancelDialog d = new - * YesNoCancelDialog(this, "ImageJ", msg); if (d.cancelPressed()) return false; - * else if (d.yesPressed()) { FileSaver fs = new FileSaver(imp); if (!fs.save()) - * return false; } } - */ - closed = true; - if (WindowManager.getWindowCount() == 0) { - xloc = 0; - yloc = 0; - } - Point currentLoc = getLocation(); - if (!IJ.isMacro()) { - Prefs.saveLocation(LOC_KEY, currentLoc); - xbase = -1; - } - WindowManager.removeWindow(this); - setVisible(false); - if (ij != null && ij.quitting()) // this may help avoid thread deadlocks - return true; - /*Changed for Bio7! - Avoid deadlock situation by disposing the JFrame!*/ - if (disposeFrame) { - dispose(); - } - if (imp != null) - imp.flush(); - imp = null; - return true; - } - - public ImagePlus getImagePlus() { - return imp; - } - - public void setImage(ImagePlus imp2) { - ImageCanvas ic = getCanvas(); - if (ic == null || imp2 == null) - return; - imp = imp2; - imp.setWindow(this); - ic.updateImage(imp); - ic.setImageUpdated(); - ic.repaint(); - repaint(); - } - - /*Changed for Bio7. Overwrite repaint to send a message to the swt statusline!*/ - public void repaint() { - Display display = Util.getDisplay(); - /* - * MacOSX only seems to work with async method! Also on Windows async works best - * (avoids deadlocks when mouse moved in and out the canvas opening several - * images at once in the background!). - */ - - display.asyncExec(new Runnable() { - public void run() { - if (imp != null) { - - if (imp.isComposite()) { - CompositeImage ci = (CompositeImage) imp; - if (ci.getMode() == IJ.COMPOSITE) { - Color c = ci.getChannelColor(); - if (Color.green.equals(c)) - c = new Color(0, 180, 0); - // g.setColor(c); - int red = c.getRed(); - int green = c.getGreen(); - int blue = c.getBlue(); - org.eclipse.swt.graphics.Color color = new org.eclipse.swt.graphics.Color(display, - new RGB(red, green, blue)); - // CanvasView.tabFolder.setSelectionForeground(color); - /*On MacOSX we get NullPointerException when we call the status line first. - * So we place the call to the status line here!*/ - CanvasView canvasView = CanvasView.getCanvas_view(); - if (canvasView != null) { - canvasView.setStatusLineColor(createSubtitle(), color); - } - - } - - } else { - CanvasView canvasView = CanvasView.getCanvas_view(); - if (canvasView != null) { - canvasView.setstatusline(createSubtitle()); - } - } - - } - } - }); - super.repaint(); - } - - public void show() { - /*Changed for Bio7! - * Empty function. - * The overwrite implementation avoids the opening - * of a JFrame ImageWindow and a reference to the image from the - * Functions class method: displayBatchModeImage in a macro when calling - * setBatchMode(false) - * */ - // System.out.println("Show"); - } - - public void updateImage(ImagePlus imp) { - if (imp != this.imp) - throw new IllegalArgumentException("imp!=this.imp"); - this.imp = imp; - ic.updateImage(imp); - setLocationAndSize(true); - if (this instanceof StackWindow) { - StackWindow sw = (StackWindow) this; - int stackSize = imp.getStackSize(); - int nScrollbars = sw.getNScrollbars(); - if (stackSize == 1 && nScrollbars > 0) - sw.removeScrollbars(); - else if (stackSize > 1 && nScrollbars == 0) - sw.addScrollbars(imp); - } - pack(); - repaint(); - maxBounds = getMaximumBounds(); - setMaximizedBounds(maxBounds); - setMaxBoundsTime = System.currentTimeMillis(); - } - - public ImageCanvas getCanvas() { - return ic; - } - - static ImagePlus getClipboard() { - return ImagePlus.getClipboard(); - } - - public Rectangle getBounds() { - Rectangle rec; - JPanel current = CanvasView.getCanvas_view().getCurrent(); - JPanel pan = current; - if (pan != null) { - rec = current.getBounds(); - } else { - rec = new Rectangle(400, 400); - } - - return rec; - - } - - public Rectangle getMaximumBounds() { - Rectangle rec; - JPanel pan = CanvasView.getCanvas_view().getCurrent(); - if (pan != null) { - rec = CanvasView.getCanvas_view().getCurrent().getBounds(); - } else { - rec = new Rectangle(400, 400); - } - - /* - * Rectangle maxWindow = GUI.getMaxWindowBounds(); if (imp == null) return - * maxWindow; double width = imp.getWidth(); double height = imp.getHeight(); - * double iAspectRatio = width / height; - * - * maxWindowBounds = maxWindow; if (iAspectRatio / ((double) maxWindow.width / - * maxWindow.height) > 0.75) { maxWindow.y += 22; // uncover ImageJ menu bar - * maxWindow.height -= 22; } Dimension extraSize = getExtraSize(); double - * maxWidth = maxWindow.width - extraSize.width; double maxHeight = - * maxWindow.height - extraSize.height; double mAspectRatio = maxWidth / - * maxHeight; int wWidth, wHeight; double mag; if (iAspectRatio >= mAspectRatio) - * { mag = maxWidth / width; wWidth = maxWindow.width; wHeight = (int) (height * - * mag + extraSize.height); } else { mag = maxHeight / height; wHeight = - * maxWindow.height; wWidth = (int) (width * mag + extraSize.width); } int xloc - * = (int) (maxWidth - wWidth) / 2; if (xloc < 0) xloc = 0; - */ - return rec; - } - - Dimension getExtraSize() { - Insets insets = getInsets(); - int extraWidth = insets.left + insets.right + 10; - int extraHeight = insets.top + insets.bottom + 10; - if (extraHeight == 20) - extraHeight = 42; - int members = getComponentCount(); - for (int i = 1; i < members; i++) { - Component m = getComponent(i); - Dimension d = m.getPreferredSize(); - extraHeight += d.height + 5; - if (IJ.debugMode) - IJ.log(i + " " + d.height + " " + extraHeight); - } - return new Dimension(extraWidth, extraHeight); - } - - public Component add(Component comp) { - comp = super.add(comp); - maxBounds = getMaximumBounds(); - setMaximizedBounds(maxBounds); - setMaxBoundsTime = System.currentTimeMillis(); - return comp; - } - - public void maximize() { - if (GenericDialog.getInstance() != null && IJ.isMacOSX() && IJ.isJava18()) - return; // workaround for OSX/Java 8 maximize bug - Rectangle rect = getMaximumBounds(); - if (IJ.debugMode) - IJ.log("maximize: " + rect); - setLocationAndSize(rect.x, rect.y, rect.width, rect.height); - } - - public void minimize() { - if (IJ.debugMode) - IJ.log("minimize: " + unzoomWhenMinimizing); - if (unzoomWhenMinimizing) - ic.unzoom(); - unzoomWhenMinimizing = true; - } - - /** Has this window been closed? */ - public boolean isClosed() { - return closed; - } - - public void focusGained(FocusEvent e) { - if (!Interpreter.isBatchMode() && ij != null && !ij.quitting() && imp != null) { - //if (IJ.debugMode) - //IJ.log("focusGained: " + imp); - WindowManager.setCurrentWindow(this); - } - } - - public void windowActivated(WindowEvent e) { - if (IJ.debugMode) - IJ.log("windowActivated: " + imp.getTitle()); - if (IJ.isMacOSX() && Prefs.setIJMenuBar && !IJ.isMacro()) - setImageJMenuBar(this); - if (imp == null) - return; - ImageJ ij = IJ.getInstance(); - if (ij != null && !closed && !ij.quitting() && !Interpreter.isBatchMode()) - WindowManager.setCurrentWindow(this); - Roi roi = imp.getRoi(); - if (roi != null && (roi instanceof PointRoi)) - PointToolOptions.update(); - if (imp.isComposite()) - Channels.updateChannels(); - imp.setActivated(); // notify ImagePlus that image has been activated - } - - public void windowClosing(WindowEvent e) { - if (closed) - return; - if (ij != null) { - WindowManager.setCurrentWindow(this); - IJ.doCommand("Close"); - } else { - dispose(); - WindowManager.removeWindow(this); - } - } - - public void windowStateChanged(WindowEvent e) { - int oldState = e.getOldState(); - int newState = e.getNewState(); - if (IJ.debugMode) - IJ.log("windowStateChanged: " + oldState + " " + newState); - if ((oldState & Frame.MAXIMIZED_BOTH) == 0 && (newState & Frame.MAXIMIZED_BOTH) != 0) - maximize(); - - } - - public void windowClosed(WindowEvent e) { - } - - public void windowDeactivated(WindowEvent e) { - } - - public void focusLost(FocusEvent e) { - } - - public void windowDeiconified(WindowEvent e) { - } - - public void windowIconified(WindowEvent e) { - } - - public void windowOpened(WindowEvent e) { - } - - public synchronized void mouseWheelMoved(MouseWheelEvent e) { - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - //if (IJ.debugMode) { - // IJ.log("mouseWheelMoved: "+e); - // IJ.log(" type: "+e.getScrollType()); - // IJ.log(" ctrl: "+ctrl); - // IJ.log(" rotation: "+rotation); - // IJ.log(" amount: "+amount); - //} - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - int width = imp.getWidth(); - int height = imp.getHeight(); - Rectangle srcRect = ic.getSrcRect(); - int xstart = srcRect.x; - int ystart = srcRect.y; - if ((ctrl || IJ.shiftKeyDown()) && ic != null) { - int ox = ic.offScreenX(e.getX()); - int oy = ic.offScreenY(e.getX()); - if (IJ.debugMode) - IJ.log(" x,y: " + ox + "," + oy); - if (rotation < 0) - ic.zoomIn(ox, oy); - else - ic.zoomOut(ox, oy); - return; - } else if (IJ.spaceBarDown() || srcRect.height == height) { - srcRect.x += rotation * amount * Math.max(width / 200, 1); - if (srcRect.x < 0) - srcRect.x = 0; - if (srcRect.x + srcRect.width > width) - srcRect.x = width - srcRect.width; - } else { - srcRect.y += rotation * amount * Math.max(height / 200, 1); - if (srcRect.y < 0) - srcRect.y = 0; - if (srcRect.y + srcRect.height > height) - srcRect.y = height - srcRect.height; - } - if (srcRect.x != xstart || srcRect.y != ystart) - ic.repaint(); - } - - /** - * Copies the current ROI to the clipboard. The entire image is copied if there - * is no ROI. - */ - public void copy(boolean cut) { - imp.copy(cut); - } - - public void paste() { - imp.paste(); - } - - /** - * This method is called by ImageCanvas.mouseMoved(MouseEvent). - * - * @see ij.gui.ImageCanvas#mouseMoved - */ - public void mouseMoved(int x, int y) { - imp.mouseMoved(x, y); - } - - public String toString() { - return imp != null ? imp.getTitle() : ""; - } - - /** - * Causes the next image to be opened to be centered on the screen and displayed - * without informational text above the image. - */ - public static void centerNextImage() { - centerOnScreen = true; - } - - /** Causes the next image to be displayed at the specified location. */ - public static void setNextLocation(Point loc) { - nextLocation = loc; - } - - /** Causes the next image to be displayed at the specified location. */ - public static void setNextLocation(int x, int y) { - nextLocation = new Point(x, y); - } - - /** - * Moves and resizes this window. Changes the magnification so the image fills - * the window. - */ - public void setLocationAndSize(int x, int y, int width, int height) { - /*Changed for Bio7 for detached views only!*/ - String idValue = Integer.toString(getImagePlus().getID()); - IJTabs.setSecondaryViewShellLocAndSize(idValue, new org.eclipse.swt.graphics.Rectangle(x, y, width, height)); - } - - @Override - public void setLocation(int x, int y) { - super.setLocation(x, y); - } - - public void setSliderHeight(int height) { - sliderHeight = height; - } - - public int getSliderHeight() { - return sliderHeight; - } - - public static void setImageJMenuBar(ImageWindow win) { - ImageJ ij = IJ.getInstance(); - boolean setMenuBar = true; - ImagePlus imp = win.getImagePlus(); - if (imp != null) - setMenuBar = imp.setIJMenuBar(); - MenuBar mb = Menus.getMenuBar(); - if (mb != null && mb == win.getMenuBar()) - setMenuBar = false; - setMenuBarTime = 0L; - if (setMenuBar && ij!=null && !ij.quitting()) { - IJ.wait(10); // may be needed for Java 1.4 on OS X - long t0 = System.currentTimeMillis(); - win.setMenuBar(mb); - long time = System.currentTimeMillis() - t0; - setMenuBarTime = time; - Menus.setMenuBarCount++; - if (time > 2000L) - Prefs.setIJMenuBar = false; - - } - if (imp != null) - imp.setIJMenuBar(true); - } - -} // class ImageWindow diff --git a/com.eco.bio7.image/src/ij/gui/Line.java b/com.eco.bio7.image/src/ij/gui/Line.java deleted file mode 100644 index 3149cffd0..000000000 --- a/com.eco.bio7.image/src/ij/gui/Line.java +++ /dev/null @@ -1,841 +0,0 @@ -package ij.gui; - -import ij.*; -import ij.process.*; -import ij.measure.*; -import ij.plugin.Straightener; -import ij.plugin.frame.Recorder; -import ij.plugin.CalibrationBar; -import java.awt.*; -import java.awt.image.*; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.awt.event.*; -import java.awt.geom.*; - -/** This class represents a straight line selection. */ -public class Line extends Roi { - public int x1, y1, x2, y2; // the line end points as integer coordinates, for compatibility only - public double x1d, y1d, x2d, y2d; // the line using sub-pixel coordinates - protected double x1R, y1R, x2R, y2R; // the line, relative to base of subpixel bounding rect 'bounds' - protected double startxd, startyd; - static boolean widthChanged; - private boolean dragged; - private int mouseUpCount; - - /** - * Creates a new straight line selection using the specified starting and ending - * offscreen integer coordinates. - */ - public Line(int ox1, int oy1, int ox2, int oy2) { - this((double) ox1, (double) oy1, (double) ox2, (double) oy2); - } - - /** - * Creates a new straight line selection using the specified starting and ending - * offscreen double coordinates. - */ - public Line(double ox1, double oy1, double ox2, double oy2) { - super((int) (ox1 + 0.5), (int) (oy1 + 0.5), 0, 0); - type = LINE; - updateCoordinates(ox1, oy1, ox2, oy2); - if (!(this instanceof Arrow) && lineWidth > 1) - updateWideLine(lineWidth); - updateClipRect(); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - state = NORMAL; - } - - /** - * Creates a new straight line selection using the specified starting and ending - * offscreen coordinates. - */ - public static Line create(double x1, double y1, double x2, double y2) { - return new Line(x1, y1, x2, y2); - } - - /** - * Starts the process of creating a new user-generated straight line selection. - * 'sx' and 'sy' are screen coordinates that specify the start of the line. The - * user will determine the end of the line interactively using rubber banding. - */ - public Line(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - type = LINE; - startxd = offScreenXD(sx); - startyd = offScreenYD(sy); - if (!magnificationForSubPixel()) { - startxd = Math.round(startxd); - startyd = Math.round(startyd); - } - updateCoordinates(startxd, startyd, startxd, startyd); - if (!(this instanceof Arrow) && lineWidth > 1) - updateWideLine(lineWidth); - } - - /** - * @deprecated replaced by Line(int, int, int, int) - */ - public Line(int ox1, int oy1, int ox2, int oy2, ImagePlus imp) { - this(ox1, oy1, ox2, oy2); - setImage(imp); - } - - protected void grow(int sx, int sy) { // mouseDragged - drawLine(sx, sy); - dragged = true; - } - - public void mouseMoved(MouseEvent e) { - drawLine(e.getX(), e.getY()); - } - - protected void handleMouseUp(int screenX, int screenY) { - mouseUpCount++; - if (Prefs.enhancedLineTool && mouseUpCount == 1 && !dragged) - return; - state = NORMAL; - if (imp == null) - return; - imp.draw(clipX - 5, clipY - 5, clipWidth + 10, clipHeight + 10); - if (IJ.recording()) { - String method = (this instanceof Arrow) ? "makeArrow" : "makeLine"; - Recorder.record(method, x1, y1, x2, y2); - } - if (getLength() == 0.0) - imp.deleteRoi(); - } - - protected void drawLine(int sx, int sy) { - double xend = offScreenXD(sx); - double yend = offScreenYD(sy); - if (xend < 0.0) - xend = 0.0; - if (yend < 0.0) - yend = 0.0; - if (xend > xMax - 1) - xend = xMax - 1; - if (yend > yMax - 1) - yend = yMax - 1; - double xstart = getXBase() + x1R, ystart = getYBase() + y1R; - if (constrain) { - int i = 0; - double dy = Math.abs(yend - ystart); - double dx = Math.abs(xend - xstart); - double comp = dy / dx; - for (; i < PI_SEARCH.length; i++) { - if (comp < PI_SEARCH[i]) { - break; - } - } - if (i < PI_SEARCH.length) { - if (yend > ystart) { - yend = ystart + dx * PI_MULT[i]; - } else { - yend = ystart - dx * PI_MULT[i]; - } - } else { - xend = xstart; - } - } - if (!magnificationForSubPixel() || IJ.controlKeyDown()) { // during creation, CTRL enforces integer coordinates - xstart = Math.round(xstart); - ystart = Math.round(ystart); - xend = Math.round(xend); - yend = Math.round(yend); - } - updateCoordinates(xstart, ystart, xend, yend); - updateClipRect(); - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - } - - /** - * Used for angle searches in line ROI creation: tan = y/x for angle limits - * 1/2*45 degrees, and 3/2*45 deg - */ - private static final double[] PI_SEARCH = { Math.tan(Math.PI / 8), Math.tan((3 * Math.PI) / 8) }; - private static final double[] PI_MULT = { 0, 1 }; // y/x for horizontal (0 degrees) and 45 deg - - void move(int sx, int sy) { - int xNew = offScreenX(sx); - int yNew = offScreenY(sy); - x += xNew - startxd; - y += yNew - startyd; - clipboard = null; - startxd = xNew; - startyd = yNew; - updateClipRect(); - if (ignoreClipRect) - imp.draw(); - else - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - } - - protected void moveHandle(int sx, int sy) { - if (constrain && activeHandle == 2) { // constrain translation in 90deg steps - int dx = sx - previousSX; - int dy = sy - previousSY; - if (Math.abs(dx) > Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - double ox = offScreenXD(sx); - double oy = offScreenYD(sy); - double x1d = getXBase() + x1R, y1d = getYBase() + y1R; - double x2d = getXBase() + x2R, y2d = getYBase() + y2R; - double length = Math.sqrt(sqr(x2d - x1d) + sqr(y2d - y1d)); - switch (activeHandle) { - case 0: - double dx = ox - x1d; - double dy = oy - y1d; - x1d = ox; - y1d = oy; - if (center) { - x2d -= dx; - y2d -= dy; - } - if (aspect) { - double ratio = length / (Math.sqrt(sqr(x2d - x1d) + sqr(y2d - y1d))); - double xcd = x1d + (x2d - x1d) / 2; - double ycd = y1d + (y2d - y1d) / 2; - - if (center) { - x1d = xcd - ratio * (xcd - x1d); - x2d = xcd + ratio * (x2d - xcd); - y1d = ycd - ratio * (ycd - y1d); - y2d = ycd + ratio * (y2d - ycd); - } else { - x1d = x2d - ratio * (x2d - x1d); - y1d = y2d - ratio * (y2d - y1d); - } - - } - break; - case 1: - dx = ox - x2d; - dy = oy - y2d; - x2d = ox; - y2d = oy; - if (center) { - x1d -= dx; - y1d -= dy; - } - if (aspect) { - double ratio = length / (Math.sqrt((x2d - x1d) * (x2d - x1d) + (y2d - y1d) * (y2d - y1d))); - double xcd = x1d + (x2d - x1d) / 2; - double ycd = y1d + (y2d - y1d) / 2; - - if (center) { - x1d = xcd - ratio * (xcd - x1d); - x2d = xcd + ratio * (x2d - xcd); - y1d = ycd - ratio * (ycd - y1d); - y2d = ycd + ratio * (y2d - ycd); - } else { - x2d = x1d + ratio * (x2d - x1d); - y2d = y1d + ratio * (y2d - y1d); - } - - } - break; - case 2: - dx = ox - (x1d + (x2d - x1d) / 2); - dy = oy - (y1d + (y2d - y1d) / 2); - x1d += dx; - y1d += dy; - x2d += dx; - y2d += dy; - break; - } - if (constrain) { - double dx = Math.abs(x1d - x2d); - double dy = Math.abs(y1d - y2d); - double xcd = Math.min(x1d, x2d) + dx / 2; - double ycd = Math.min(y1d, y2d) + dy / 2; - - // double ratio = length/(Math.sqrt((x2d-x1d)*(x2d-x1d) + (y2d-y1d)*(y2d-y1d))); - if (activeHandle == 0) { - if (dx >= dy) { - if (aspect) { - if (x2d > x1d) - x1d = x2d - length; - else - x1d = x2d + length; - } - y1d = y2d; - if (center) { - y1d = y2d = ycd; - if (aspect) { - if (xcd > x1d) { - x1d = xcd - length / 2; - x2d = xcd + length / 2; - } else { - x1d = xcd + length / 2; - x2d = xcd - length / 2; - } - } - } - } else { - if (aspect) { - if (y2d > y1d) - y1d = y2d - length; - else - y1d = y2d + length; - } - x1d = x2d; - if (center) { - x1d = x2d = xcd; - if (aspect) { - if (ycd > y1d) { - y1d = ycd - length / 2; - y2d = ycd + length / 2; - } else { - y1d = ycd + length / 2; - y2d = ycd - length / 2; - } - } - } - } - } else if (activeHandle == 1) { - if (dx >= dy) { - if (aspect) { - if (x1d > x2d) - x2d = x1d - length; - else - x2d = x1d + length; - } - y2d = y1d; - if (center) { - y1d = y2d = ycd; - if (aspect) { - if (xcd > x1d) { - x1d = xcd - length / 2; - x2d = xcd + length / 2; - } else { - x1d = xcd + length / 2; - x2d = xcd - length / 2; - } - } - } - } else { - if (aspect) { - if (y1d > y2d) - y2d = y1d - length; - else - y2d = y1d + length; - } - x2d = x1d; - if (center) { - x1d = x2d = xcd; - if (aspect) { - if (ycd > y1d) { - y1d = ycd - length / 2; - y2d = ycd + length / 2; - } else { - y1d = ycd + length / 2; - y2d = ycd - length / 2; - } - } - } - } - } - } - if (!magnificationForSubPixel()) { - x1d = Math.round(x1d); - y1d = Math.round(y1d); - x2d = Math.round(x2d); - y2d = Math.round(y2d); - } - updateCoordinates(x1d, y1d, x2d, y2d); - updateClipRect(); - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX = x; - oldY = y; - oldWidth = width; - oldHeight = height; - } - - protected void mouseDownInHandle(int handle, int sx, int sy) { - super.mouseDownInHandle(handle, sx, sy); // sets state, activeHandle, previousSX&Y - if (getStrokeWidth() <= 3) - ic.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR)); - } - - /** - * Sets the x1d, y1d, x2d, y2d line end points, the (legacy) integer coordinates - * of the end points x1, y1, x2, y2 the 'bounds' subpixel rectangle of the Roi - * superclass (spanned by the end points), the int x, y, width, height integer - * bounds of the superclass (these enclose the 'draw' area for 1 pixel width), - * and the coordinates x1R, y1R, x2R, y2R relative to the base x, y of the - * 'bounds' - */ - void updateCoordinates(double x1d, double y1d, double x2d, double y2d) { - this.x1d = x1d; - this.y1d = y1d; - this.x2d = x2d; - this.y2d = y2d; - Rectangle2D.Double bounds = this.bounds; // local variable (this.bounds may become null asynchronously upon nudge) - if (bounds == null) - bounds = new Rectangle2D.Double(); - bounds.x = Math.min(x1d, x2d); - bounds.y = Math.min(y1d, y2d); - bounds.width = Math.abs(x2d - x1d); - bounds.height = Math.abs(y2d - y1d); - setIntBounds(bounds); // sets x, y, width, height - x1R = x1d - bounds.x; - y1R = y1d - bounds.y; - x2R = x2d - bounds.x; - y2R = y2d - bounds.y; - x1 = (int) x1d; - y1 = (int) y1d; - x2 = (int) x2d; - y2 = (int) y2d; - this.bounds = bounds; - } - - /** Draws this line on the image. */ - public void draw(Graphics g) { - Color color = strokeColor != null ? strokeColor : ROIColor; - boolean isActiveOverlayRoi = !overlay && isActiveOverlayRoi(); - mag = getMagnification(); - if (isActiveOverlayRoi) { - if (color == Color.cyan) - color = Color.magenta; - else - color = Color.cyan; - } - g.setColor(color); - x1d = getXBase() + x1R; - y1d = getYBase() + y1R; - x2d = getXBase() + x2R; - y2d = getYBase() + y2R; - x1 = (int) x1d; - y1 = (int) y1d; - x2 = (int) x2d; - y2 = (int) y2d; - int sx1 = screenXD(x1d); - int sy1 = screenYD(y1d); - int sx2 = screenXD(x2d); - int sy2 = screenYD(y2d); - int sx3 = sx1 + (sx2 - sx1) / 2; - int sy3 = sy1 + (sy2 - sy1) / 2; - Graphics2D g2d = (Graphics2D) g; - setRenderingHint(g2d); - boolean cbar = overlay && mag < 1.0 && Math.abs(getStrokeWidth() - CalibrationBar.STROKE_WIDTH) < 0.0001; - if (stroke != null && !isActiveOverlayRoi && !cbar) - g2d.setStroke(getScaledStroke()); - else if (cbar) - g2d.setStroke(onePixelWide); - if (wideLine && !isActiveOverlayRoi && !cbar) { - double dx = sx2 - sx1; - double dy = sy2 - sy1; - double len = length(dx, dy); - dx *= 0.5 * mag / len; // half-pixel extension, corresponding to getFloatPolygon or convertLineToArea - dy *= 0.5 * mag / len; - g2d.draw(new Line2D.Double(sx1 - dx, sy1 - dy, sx2 + dx, sy2 + dy)); - } else - g.drawLine(sx1, sy1, sx2, sy2); - if (wideLine && !overlay) { - g2d.setStroke(onePixelWide); - g.setColor(getColor()); - g.drawLine(sx1, sy1, sx2, sy2); - } - if (!overlay) { - handleColor = strokeColor != null ? strokeColor : ROIColor; - drawHandle(g, sx1, sy1); - handleColor = Color.white; - drawHandle(g, sx2, sy2); - drawHandle(g, sx3, sy3); - } - if (state != NORMAL) - showStatus(); - if (updateFullWindow) { - updateFullWindow = false; - imp.draw(); - } - } - - public void showStatus() { - IJ.showStatus(imp.getLocationAsString((int) Math.round(x2d), (int) Math.round(y2d)) + ", angle=" + IJ.d2s(getAngle()) + ", length=" + IJ.d2s(getLength())); - } - - public double getAngle() { - return getFloatAngle(x1d, y1d, x2d, y2d); - } - - /** Returns the length of this line. */ - public double getLength() { - if (imp == null || IJ.altKeyDown()) - return getRawLength(); - else { - Calibration cal = imp.getCalibration(); - return Math.sqrt(sqr((x2d - x1d) * cal.pixelWidth) + sqr((y2d - y1d) * cal.pixelHeight)); - } - } - - /** Returns the length of this line in pixels. */ - public double getRawLength() { - return Math.sqrt(sqr(x2d - x1d) + sqr(y2d - y1d)); - } - - /** - * Returns the pixel values along this line. The line roi must have an - * associated ImagePlus. - */ - public double[] getPixels() { - double[] profile; - if (getStrokeWidth() <= 1) { - ImageProcessor ip = imp.getProcessor(); - profile = ip.getLine(x1d, y1d, x2d, y2d); - } else { - Straightener s = new Straightener(); - ImageProcessor ip2 = s.straightenLine(imp, this, 0); - if (ip2 == null) - return new double[0]; - int width = ip2.getWidth(); - int height = ip2.getHeight(); - if (ip2 instanceof FloatProcessor) - return ProfilePlot.getColumnAverageProfile(new Rectangle(0, 0, width, height), ip2); - profile = new double[width]; - double[] aLine; - ip2.setInterpolate(false); - for (int y = 0; y < height; y++) { - aLine = ip2.getLine(0, y, width - 1, y); - for (int i = 0; i < width; i++) - profile[i] += aLine[i]; - } - for (int i = 0; i < width; i++) - profile[i] /= height; - } - return profile; - } - - /** Returns, as a Polygon, the two points that define this line. */ - public Polygon getPoints() { - Polygon p = new Polygon(); - p.addPoint((int) Math.round(x1d), (int) Math.round(y1d)); - p.addPoint((int) Math.round(x2d), (int) Math.round(y2d)); - return p; - } - - /** Returns, as a FloatPolygon, the two points that define this line. */ - public FloatPolygon getFloatPoints() { - FloatPolygon p = new FloatPolygon(); - p.addPoint((float) x1d, (float) y1d); - p.addPoint((float) x2d, (float) y2d); - return p; - } - - /** - * If the width of this line is less than or equal to one, returns the starting - * and ending coordinates as a 2-point Polygon, or, if the width is greater than - * one, returns an outline of the line as a 4-point Polygon. - * - * @see #getFloatPolygon - * @see #getPoints - */ - public Polygon getPolygon() { - FloatPolygon p = getFloatPolygon(); - return new Polygon(toIntR(p.xpoints), toIntR(p.ypoints), p.npoints); - } - - /** - * If the width of this line is less than or equal to one, returns the starting - * and ending coordinates as a 2-point FloatPolygon, or, if the width is greater - * than one, returns an outline of the line as a 4-point FloatPolygon. - * - * @see #getFloatPoints - */ - public FloatPolygon getFloatPolygon() { - return getFloatPolygon(getStrokeWidth()); - } - - /** Obsolete */ - public FloatPolygon getFloatPolygon(double strokeWidth) { - FloatPolygon p = new FloatPolygon(); - if (strokeWidth <= 1) { - p.addPoint((float) x1d, (float) y1d); - p.addPoint((float) x2d, (float) y2d); - } else { - double dx = x2d - x1d; - double dy = y2d - y1d; - double len = length(dx, dy); - dx *= 0.5 / len; // half unit vector in the direction of the line - dy *= 0.5 / len; // when rotated 90 deg cw, this yields the vector (-dx, dy) - double p1x = x1d + 0.5 - dx + dy * strokeWidth; // 0.5 pxl shift: area vs. line coordinate convention - double p1y = y1d + 0.5 - dy - dx * strokeWidth; - double p2x = x1d + 0.5 - dx - dy * strokeWidth; - double p2y = y1d + 0.5 - dy + dx * strokeWidth; - double p3x = x2d + 0.5 + dx - dy * strokeWidth; - double p3y = y2d + 0.5 + dy + dx * strokeWidth; - double p4x = x2d + 0.5 + dx + dy * strokeWidth; - double p4y = y2d + 0.5 + dy - dx * strokeWidth; - p.addPoint((float) p1x, (float) p1y); - p.addPoint((float) p2x, (float) p2y); - p.addPoint((float) p3x, (float) p3y); - p.addPoint((float) p4x, (float) p4y); - } - return p; - } - - /** - * Returns the number of points in this selection; equivalent to - * getPolygon().npoints. - */ - public int size() { - return getStrokeWidth() <= 1 ? 2 : 4; - } - - /** - * If the width of this line is less than or equal to one, draws the line. - * Otherwise draws the outline of the area of this line. - */ - public void drawPixels(ImageProcessor ip) { - boolean fillLine = getStrokeWidth() > 1 && getWidth() <= 1; - if (fillLine) - ip.setLineWidth((int) Math.round(getStrokeWidth())); - else - ip.setLineWidth(1); - double x = getXBase(); - double y = getYBase(); - x1d = getXBase() + x1R; - y1d = getYBase() + y1R; - x2d = getXBase() + x2R; - y2d = getYBase() + y2R; - if (getStrokeWidth() <= 1 || fillLine) { - ip.moveTo((int) Math.round(x1d), (int) Math.round(y1d)); - ip.lineTo((int) Math.round(x2d), (int) Math.round(y2d)); - } else { - Polygon p = getPolygon(); - ip.drawPolygon(p); - updateFullWindow = true; - } - } - - public boolean contains(int x, int y) { - if (getStrokeWidth() > 1) { - if ((x == x1 && y == y1) || (x == x2 && y == y2)) - return true; - else - return getPolygon().contains(x, y); - } else - return false; - } - - protected void handleMouseDown(int sx, int sy) { - super.handleMouseDown(sx, sy); - startxd = ic.offScreenXD(sx); - startyd = ic.offScreenYD(sy); - } - - /** - * Returns a handle number if the specified screen coordinates are inside or - * near a handle, otherwise returns -1. - */ - public int isHandle(int sx, int sy) { - int size = HANDLE_SIZE + 5; - if (getStrokeWidth() > 1) - size += (int) Math.log(getStrokeWidth()); - int halfSize = size / 2; - int sx1 = screenXD(getXBase() + x1R) - halfSize; - int sy1 = screenYD(getYBase() + y1R) - halfSize; - int sx2 = screenXD(getXBase() + x2R) - halfSize; - int sy2 = screenYD(getYBase() + y2R) - halfSize; - int sx3 = sx1 + (sx2 - sx1) / 2 - 1; - int sy3 = sy1 + (sy2 - sy1) / 2 - 1; - if (sx >= sx1 && sx <= sx1 + size && sy >= sy1 && sy <= sy1 + size) - return 0; - if (sx >= sx2 && sx <= sx2 + size && sy >= sy2 && sy <= sy2 + size) - return 1; - if (sx >= sx3 && sx <= sx3 + size + 2 && sy >= sy3 && sy <= sy3 + size + 2) - return 2; - return -1; - } - - /** - * Returns the default line width. Use getStrokeWidth()to get the width of a - * Line instance. - * - * @see #getStrokeWidth - */ - public static int getWidth() { - return lineWidth; - } - - /** - * Sets the default line width. Use setStrokeWidth() to set the width of a Line - * instance. - * - * @see #setStrokeWidth - */ - public static void setWidth(int w) { - if (w < 1) - w = 1; - int max = 500; - if (w > max) { - ImagePlus imp2 = WindowManager.getCurrentImage(); - if (imp2 != null) { - max = Math.max(max, imp2.getWidth()); - max = Math.max(max, imp2.getHeight()); - } - if (w > max) - w = max; - } - lineWidth = w; - widthChanged = true; - } - - /* Sets the width of this line. */ - public void setStrokeWidth(float width) { - super.setStrokeWidth(width); - if (getStrokeColor() == Roi.getColor()) - wideLine = true; - } - - protected int clipRectMargin() { - return 4; - } - - /** Nudge end point of line by one pixel. */ - public void nudgeCorner(int key) { - if (ic == null) - return; - double inc = 1.0 / ic.getMagnification(); - switch (key) { - case KeyEvent.VK_UP: - y2R -= inc; - break; - case KeyEvent.VK_DOWN: - y2R += inc; - break; - case KeyEvent.VK_LEFT: - x2R -= inc; - break; - case KeyEvent.VK_RIGHT: - x2R += inc; - break; - } - grow(screenXD(x + x2R), screenYD(y + y2R)); - notifyListeners(RoiListener.MOVED); - showStatus(); - } - - /** Always returns true. */ - public boolean subPixelResolution() { - return true; - } - - public void setLocation(int x, int y) { - setLocation((double) x, (double) y); - } - - /** - * Sets the x coordinate of the leftmost and y coordinate of the topmost end - * point - */ - public void setLocation(double x, double y) { - updateCoordinates(x + x1R, y + y1R, x + x2R, y + y2R); - } - - public FloatPolygon getRotationCenter() { - double xcenter = x1d + (x2d - x1d) / 2.0; - double ycenter = y1d + (y2d - y1d) / 2.0; - FloatPolygon p = new FloatPolygon(); - p.addPoint(xcenter, ycenter); - return p; - } - - /** - * Dedicated point iterator for thin lines. The iterator is based on (an - * improved version of) the algorithm used by the original method - * {@code ImageProcessor.getLine(double, double, double, double)}. Improvements - * are (a) that the endpoint is drawn too and (b) every line point is visited - * only once, duplicates are skipped. - * - * Author: Wilhelm Burger (04/2017) - */ - public static class PointIterator implements Iterator { - private double x1, y1; - private final int n; - private final double xinc, yinc; - private double x, y; - private int u, v; - private int u_prev, v_prev; - private int i; - - public PointIterator(Line line) { - this(line.x1d, line.y1d, line.x2d, line.y2d); - } - - public PointIterator(double x1, double y1, double x2, double y2) { - this.x1 = x1; - this.y1 = y1; - double dx = x2 - x1; - double dy = y2 - y1; - this.n = (int) Math.ceil(Math.sqrt(dx * dx + dy * dy)); - this.xinc = dx / n; - this.yinc = dy / n; - x = x1; - y = y1; - u = (int) Math.round(x - 0.5); - v = (int) Math.round(y - 0.5); - u_prev = Integer.MIN_VALUE; - v_prev = Integer.MIN_VALUE; - i = 0; - } - - @Override - public boolean hasNext() { - return i <= n; // needs to be '<=' to include last segment (point)! - } - - @Override - public Point next() { - if (i > n) - throw new NoSuchElementException(); - Point p = new Point(u, v); // the current (next) point - moveToNext(); - return p; - } - - // move to next point by skipping duplicate points - private void moveToNext() { - do { - i = i + 1; - x = x1 + i * xinc; - y = y1 + i * yinc; - u_prev = u; - v_prev = v; - u = (int) Math.round(x - 0.5); - v = (int) Math.round(y - 0.5); - } while (i <= n && u == u_prev && v == v_prev); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } - - @Override - public Iterator iterator() { - if (getStrokeWidth() <= 1.0) - return new PointIterator(this); // use the specific thin-line iterator - else - return super.iterator(); // fall back on Roi's iterator - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/MessageDialog.java b/com.eco.bio7.image/src/ij/gui/MessageDialog.java deleted file mode 100644 index 3f02e1b55..000000000 --- a/com.eco.bio7.image/src/ij/gui/MessageDialog.java +++ /dev/null @@ -1,62 +0,0 @@ -/*Message Dialog copied from the Bio7 project. - * Author: Marcel Austenfeld*/ -package ij.gui; - -import java.awt.Frame; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.MessageBox; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.ui.IWorkbenchWindow; -import org.eclipse.ui.PlatformUI; - -/* Changed for Bio7! A modal dialog base on SWT as a replacement for the ImageJ message dialog! */ - -public class MessageDialog { - protected MultiLineLabel label; - private boolean escapePressed; - protected int result; - - public MessageDialog(Frame parent, String title, String message) { - - Display display = PlatformUI.getWorkbench().getDisplay(); - display.syncExec(new Runnable() { - public void run() { - MessageBox messageBox = new MessageBox(getShell(), - - SWT.ICON_WARNING); - - messageBox.setText(title); - messageBox.setMessage(message); - result = messageBox.open(); - if (result == SWT.OK) { - escapePressed = true; - } - } - }); - - } - - /** - * Returns a platform shell for dialogs, etc. - * - * @return a shell - */ - public static Shell getShell() { - IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - if (window == null) { - IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); - if (windows.length > 0) { - return windows[0].getShell(); - } - } else { - return window.getShell(); - } - return null; - } - - public boolean escapePressed() { - return escapePressed; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/MultiLineLabel.java b/com.eco.bio7.image/src/ij/gui/MultiLineLabel.java deleted file mode 100644 index 4aed7d6e9..000000000 --- a/com.eco.bio7.image/src/ij/gui/MultiLineLabel.java +++ /dev/null @@ -1,111 +0,0 @@ -package ij.gui; -import java.awt.*; -import java.util.*; - -import javax.swing.JPanel; - -/**Custom component for displaying multiple lines. Based on - MultiLineLabel class from "Java in a Nutshell" by David Flanagan.*/ -public class MultiLineLabel extends JPanel { - String[] lines; - int num_lines; - int margin_width = 6; - int margin_height = 6; - int line_height; - int line_ascent; - int[] line_widths; - int min_width, max_width; - - // Breaks the specified label up into an array of lines. - public MultiLineLabel(String label) { - init(label); - } - - public MultiLineLabel(String label, int minimumWidth) { - init(label); - min_width = minimumWidth; - } - - private void init(String text) { - StringTokenizer t = new StringTokenizer(text, "\n"); - num_lines = t.countTokens(); - lines = new String[num_lines]; - line_widths = new int[num_lines]; - for (int i=0; i max_width) max_width = line_widths[i]; - } - } - - - public void setText(String text) { - init(text); - measure(); - repaint(); - } - - public void setFont(Font f) { - super.setFont(f); - measure(); - repaint(); - } - - - // This method is invoked after our Canvas is first created - // but before it can actually be displayed. After we've - // invoked our superclass's addNotify() method, we have font - // metrics and can successfully call measure() to figure out - // how big the label is. - public void addNotify() { - super.addNotify(); - measure(); - } - - - // Called by a layout manager when it wants to - // know how big we'd like to be. - public Dimension getPreferredSize() { - return new Dimension(Math.max(min_width, max_width + 2*margin_width), - num_lines * line_height + 2*margin_height); - } - - - // Called when the layout manager wants to know - // the bare minimum amount of space we need to get by. - public Dimension getMinimumSize() { - return new Dimension(Math.max(min_width, max_width), num_lines * line_height); - } - - // Draws the label - public void paintComponent(Graphics g) { - super.paintComponent(g); - int x, y; - Dimension d = this.getSize(); - if (!ij.IJ.isLinux()) setAntialiasedText(g); - y = line_ascent + (d.height - num_lines * line_height)/2; - for(int i = 0; i < num_lines; i++, y += line_height) { - x = margin_width; - g.drawString(lines[i], x, y); - } - } - - void setAntialiasedText(Graphics g) { - Graphics2D g2d = (Graphics2D)g; - g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/NewImage.java b/com.eco.bio7.image/src/ij/gui/NewImage.java deleted file mode 100644 index 2075ac427..000000000 --- a/com.eco.bio7.image/src/ij/gui/NewImage.java +++ /dev/null @@ -1,466 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.image.*; -import java.io.*; -import java.awt.event.*; -import java.util.*; -import ij.*; -import ij.process.*; - -/** New image dialog box plus several static utility methods for creating images.*/ -public class NewImage { - - public static final int GRAY8=0, GRAY16=1, GRAY32=2, RGB=3; - public static final int FILL_BLACK=1, FILL_RAMP=2, FILL_NOISE=3, FILL_RANDOM=3, - FILL_WHITE=4, CHECK_AVAILABLE_MEMORY=8, SIGNED_INT=16; - private static final int OLD_FILL_WHITE=0; - - static final String TYPE = "new.type"; - static final String FILL = "new.fill"; - static final String WIDTH = "new.width"; - static final String HEIGHT = "new.height"; - static final String SLICES = "new.slices"; - - private static String name = "Untitled"; - private static int staticWidth = Prefs.getInt(WIDTH, 512); - private static int staticHeight = Prefs.getInt(HEIGHT, 512); - private static int staticSlices = Prefs.getInt(SLICES, 1); - private static int staticType = Prefs.getInt(TYPE, GRAY8); - private static int staticFillWith = Prefs.getInt(FILL, FILL_BLACK); - private static String[] types = {"8-bit", "16-bit", "32-bit", "RGB"}; - private static String[] fill = {"White", "Black", "Ramp", "Noise"}; - private int gwidth, gheight, gslices, gtype, gfill; - - public NewImage() { - openImage(); - } - - static boolean createStack(ImagePlus imp, ImageProcessor ip, int nSlices, int type, int options) { - int fill = getFill(options); - int width = imp.getWidth(); - int height = imp.getHeight(); - long bytesPerPixel = 1; - if (type==GRAY16) bytesPerPixel = 2; - else if (type==GRAY32||type==RGB) bytesPerPixel = 4; - long size = (long)width*height*nSlices*bytesPerPixel; - int sizeThreshold = fill==FILL_NOISE?10:250; - boolean bigStack = size/(1024*1024)>=sizeThreshold; - String size2 = size/(1024*1024)+"MB ("+width+"x"+height+"x"+nSlices+")"; - if ((options&CHECK_AVAILABLE_MEMORY)!=0) { - long max = IJ.maxMemory(); // - 100*1024*1024; - if (max>0) { - long inUse = IJ.currentMemory(); - long available = max - inUse; - if (size>available) - System.gc(); - inUse = IJ.currentMemory(); - available = max-inUse; - if (size>available) { - IJ.error("Insufficient Memory", "There is not enough free memory to allocate a \n" - + size2+" stack.\n \n" - + "Memory available: "+available/(1024*1024)+"MB\n" - + "Memory in use: "+IJ.freeMemory()+"\n \n" - + "More information can be found in the \"Memory\"\n" - + "sections of the ImageJ installation notes at\n" - + "\""+IJ.URL2+"/docs/install/\"."); - return false; - } - } - } - ImageStack stack = imp.createEmptyStack(); - boolean signedInt = (options&SIGNED_INT)!=0; - if (type==RGB && signedInt) - stack.setOptions("32-bit int"); - int inc = nSlices/40; - if (inc<1) inc = 1; - if (bigStack) - IJ.showStatus("Allocating "+size2+". Press 'Esc' to abort."); - IJ.resetEscape(); - try { - stack.addSlice(null, ip); - for (int i=2; i<=nSlices; i++) { - if ((i%inc)==0 && bigStack) - IJ.showProgress(i, nSlices); - Object pixels2 = null; - switch (type) { - case GRAY8: pixels2 = new byte[width*height]; - if (fill==FILL_NOISE) - fillNoiseByte(new ByteProcessor(width,height,(byte[])pixels2)); - break; - case GRAY16: pixels2 = new short[width*height]; - if (fill==FILL_NOISE) - fillNoiseShort(new ShortProcessor(width,height,(short[])pixels2,null)); - break; - case GRAY32: pixels2 = new float[width*height]; - if (fill==FILL_NOISE) - fillNoiseFloat(new FloatProcessor(width,height,(float[])pixels2,null)); - break; - case RGB: pixels2 = new int[width*height]; - if (fill==FILL_NOISE) { - if (signedInt) - fillNoiseInt(new IntProcessor(width,height,(int[])pixels2)); - else - fillNoiseRGB(new ColorProcessor(width,height,(int[])pixels2), false); - } - break; - } - if (fill==FILL_WHITE||fill==FILL_RAMP) - System.arraycopy(ip.getPixels(), 0, pixels2, 0, width*height); - stack.addSlice(null, pixels2); - if (IJ.escapePressed()) {IJ.beep(); break;}; - } - } - catch(OutOfMemoryError e) { - IJ.outOfMemory(imp.getTitle()); - stack.trim(); - } - IJ.showStatus(""); - if (bigStack) - IJ.showProgress(nSlices, nSlices); - if (stack.size()>1) - imp.setStack(null, stack); - return true; - } - - static int getFill(int options) { - int fill = options&7; - if (fill==OLD_FILL_WHITE) - fill = FILL_WHITE; - if (fill==7||fill==6||fill==5) - fill = FILL_BLACK; - return fill; - } - - public static ImagePlus createByteImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - byte[] pixels = new byte[size]; - ImageProcessor ip = new ByteProcessor(width, height, pixels, null); - switch (fill) { - case FILL_WHITE: - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, GRAY8, options); - if (!ok) imp = null; - } - return imp; - } - - private static void fillNoiseByte(ImageProcessor ip) { - ip.add(127); - ip.noise(31); - } - - public static ImagePlus createRGBImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - int[] pixels = new int[size]; - ColorProcessor ip = new ColorProcessor(width, height, pixels); - switch (fill) { - case FILL_WHITE: - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, RGB, options); - if (!ok) imp = null; - } - return imp; - } - - public static ImagePlus createIntImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - int[] pixels = new int[size]; - IntProcessor ip = new IntProcessor(width, height, pixels); - switch (fill) { - case FILL_RAMP: - int[] ramp = new int[width]; - double inc = ((double)Integer.MAX_VALUE - (double)Integer.MIN_VALUE)/width; - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, RGB, options); - if (!ok) imp = null; - } - return imp; - } - - private static void fillNoiseRGB(ColorProcessor ip, boolean sp) { - int width = ip.getWidth(); - int height = ip.getHeight(); - ByteProcessor rr = new ByteProcessor(width, height); - ByteProcessor gg = new ByteProcessor(width, height); - ByteProcessor bb = new ByteProcessor(width, height); - if (sp) IJ.showProgress(0.0); - rr.add(127); if (sp) IJ.showProgress(0.05); - gg.add(127); if (sp) IJ.showProgress(0.10); - bb.add(127); if (sp) IJ.showProgress(0.15); - rr.noise(31); if (sp) IJ.showProgress(0.40); - gg.noise(31); if (sp) IJ.showProgress(0.65); - bb.noise(31); if (sp) IJ.showProgress(0.90); - if (sp) IJ.showProgress(1.0); - ip.setChannel(1,rr); ip.setChannel(2,gg); ip.setChannel(3,bb); - } - - private static void fillNoiseInt(ImageProcessor ip) { - Random rnd = new Random(); - int n = ip.getPixelCount(); - double std =((double)Integer.MAX_VALUE - (double)Integer.MIN_VALUE)*0.12; - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, GRAY16, options); - if (!ok) imp = null; - } - imp.getProcessor().setMinAndMax(0, 65535); // default display range - return imp; - } - - private static void fillNoiseShort(ImageProcessor ip) { - ip.add(32767); - ip.noise(7940); - } - - /** - * @deprecated - * Short images are always unsigned. - */ - public static ImagePlus createUnsignedShortImage(String title, int width, int height, int slices, int options) { - return createShortImage(title, width, height, slices, options); - } - - public static ImagePlus createFloatImage(String title, int width, int height, int slices, int options) { - int fill = getFill(options); - int size = getSize(width, height); - if (size<0) return null; - float[] pixels = new float[size]; - ImageProcessor ip = new FloatProcessor(width, height, pixels, null); - switch (fill) { - case FILL_WHITE: case FILL_BLACK: - break; - case FILL_RAMP: - float[] ramp = new float[width]; - for (int i=0; i1) { - boolean ok = createStack(imp, ip, slices, GRAY32, options); - if (!ok) imp = null; - } - if (fill!=FILL_NOISE) - imp.getProcessor().setMinAndMax(0.0, 1.0); // default display range - return imp; - } - - private static void fillNoiseFloat(ImageProcessor ip) { - ip.noise(1); - } - - private static int getSize(int width, int height) { - long size = (long)width*height; - if (size>Integer.MAX_VALUE) { - IJ.error("Image is too large. ImageJ does not support\nsingle images larger than 2 gigapixels."); - return -1; - } else - return (int)size; - } - - public static void open(String title, int width, int height, int nSlices, int type, int options) { - int bitDepth = 8; - if (type==GRAY16) bitDepth = 16; - else if (type==GRAY32) bitDepth = 32; - else if (type==RGB) bitDepth = 24; - long startTime = System.currentTimeMillis(); - ImagePlus imp = createImage(title, width, height, nSlices, bitDepth, options); - if (imp!=null) { - WindowManager.checkForDuplicateName = true; - imp.show(); - IJ.showStatus(IJ.d2s(((System.currentTimeMillis()-startTime)/1000.0),2)+" seconds"); - } - } - - public static ImagePlus createImage(String title, int width, int height, int nSlices, int bitDepth, int options) { - ImagePlus imp = null; - switch (bitDepth) { - case 8: imp = createByteImage(title, width, height, nSlices, options); break; - case 16: imp = createShortImage(title, width, height, nSlices, options); break; - case 32: imp = createFloatImage(title, width, height, nSlices, options); break; - case 24: - if ((options&SIGNED_INT)!=0) - imp = createIntImage(title, width, height, nSlices, options); - else - imp = createRGBImage(title, width, height, nSlices, options); - break; - default: throw new IllegalArgumentException("Invalid bitDepth: "+bitDepth); - } - return imp; - } - - boolean showDialog() { - if (staticTypeRGB) - staticType = GRAY8; - if (staticFillWithFILL_NOISE) - staticFillWith = FILL_WHITE; - GenericDialog gd = new GenericDialog("New Image..."); - gd.addStringField("Name:", name, 12); - gd.addChoice("Type:", types, types[staticType]); - gd.addChoice("Fill with:", fill, fill[staticFillWith]); - gd.addNumericField("Width:", staticWidth, 0, 5, "pixels"); - gd.addNumericField("Height:", staticHeight, 0, 5, "pixels"); - gd.addNumericField("Slices:", staticSlices, 0, 5, ""); - gd.showDialog(); - if (gd.wasCanceled()) - return false; - name = gd.getNextString(); - String s = gd.getNextChoice(); - if (s.startsWith("8")) - gtype = GRAY8; - else if (s.startsWith("16")) - gtype = GRAY16; - else if (s.endsWith("RGB") || s.endsWith("rgb")) - gtype = RGB; - else - gtype = GRAY32; - gfill = gd.getNextChoiceIndex(); - gwidth = (int)gd.getNextNumber(); - gheight = (int)gd.getNextNumber(); - gslices = (int)gd.getNextNumber(); - if (gslices<1) gslices = 1; - if (gwidth<1 || gheight<1) { - IJ.error("New Image", "Width and height must be >0"); - return false; - } else { - if (!IJ.isMacro()) { - staticWidth = gwidth; - staticHeight = gheight; - staticSlices = gslices; - staticType = gtype; - staticFillWith = gfill; - } - return true; - } - } - - void openImage() { - if (!showDialog()) - return; - try { - open(name, gwidth, gheight, gslices, gtype, gfill); - } catch(OutOfMemoryError e) { - IJ.outOfMemory("New Image..."); - } - } - - /** Called when ImageJ quits. */ - public static void savePreferences(Properties prefs) { - prefs.put(TYPE, Integer.toString(staticType)); - prefs.put(FILL, Integer.toString(staticFillWith)); - prefs.put(WIDTH, Integer.toString(staticWidth)); - prefs.put(HEIGHT, Integer.toString(staticHeight)); - prefs.put(SLICES, Integer.toString(staticSlices)); - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/NonBlockingGenericDialog.java b/com.eco.bio7.image/src/ij/gui/NonBlockingGenericDialog.java deleted file mode 100644 index 44381da6d..000000000 --- a/com.eco.bio7.image/src/ij/gui/NonBlockingGenericDialog.java +++ /dev/null @@ -1,104 +0,0 @@ -package ij.gui; -import ij.*; -import java.awt.event.*; -import java.awt.EventQueue; -import java.awt.GraphicsEnvironment; -import java.awt.Frame; - -/** This is an extension of GenericDialog that is non-modal. - * @author Johannes Schindelin - */ -public class NonBlockingGenericDialog extends GenericDialog { - ImagePlus imp; //when non-null, this dialog gets closed when the image is closed - WindowListener windowListener; //checking for whether the associated window gets closed - - public NonBlockingGenericDialog(String title) { - super(title, null); - setModal(false); - IJ.protectStatusBar(false); - instance = this; - } - - public synchronized void showDialog() { - super.showDialog(); - if (isMacro()) - return; - if (EventQueue.isDispatchThread()) - throw new RuntimeException("To avoid a deadlock, NonBlockingGenericDialog must not be called from the Event Queue"); - if (!IJ.macroRunning()) { // add to Window menu on event dispatch thread - final NonBlockingGenericDialog thisDialog = this; - EventQueue.invokeLater(new Runnable() { - public void run() { - WindowManager.addWindow(thisDialog); - } - }); - } - if (imp != null) { - ImageWindow win = imp.getWindow(); - if (win != null) { //when the associated image closes, also close the dialog - final NonBlockingGenericDialog gd = this; - windowListener = new WindowAdapter() { - public void windowClosed(WindowEvent e) { - cancelDialogAndClose(); - } - }; - win.addWindowListener(windowListener); - } - } - try { - wait(); - } catch (InterruptedException e) { } - } - - /** Gets called if the associated image window is closed */ - private void cancelDialogAndClose() { - super.windowClosing(null); // sets wasCanceled=true and does dispose() - } - - public synchronized void actionPerformed(ActionEvent e) { - super.actionPerformed(e); - if (!isVisible()) - notify(); - } - - public synchronized void keyPressed(KeyEvent e) { - super.keyPressed(e); - if (wasOKed() || wasCanceled()) - notify(); - } - - public synchronized void windowClosing(WindowEvent e) { - super.windowClosing(e); - if (wasOKed() || wasCanceled()) - notify(); - } - - public void dispose() { - super.dispose(); - WindowManager.removeWindow(this); - if (imp != null) { - ImageWindow win = imp.getWindow(); - if (win != null && windowListener != null) - win.removeWindowListener(windowListener); - } - } - - /** Obsolete, replaced by GUI.newNonBlockingDialog(String,ImagePlus). */ - public static GenericDialog newDialog(String title, ImagePlus imp) { - return GUI.newNonBlockingDialog(title, imp); - } - - /** Obsolete, replaced by GUI.newNonBlockingDialog(String). */ - public static GenericDialog newDialog(String title) { - return GUI.newNonBlockingDialog(title); - } - - /** Put the dialog into the foreground when the image we work on gets into the foreground */ - @Override - public void windowActivated(WindowEvent e) { - if ((e.getWindow() instanceof ImageWindow) && e.getOppositeWindow()!=this) - toFront(); - WindowManager.setWindow(this); - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/OvalRoi.java b/com.eco.bio7.image/src/ij/gui/OvalRoi.java deleted file mode 100644 index fc1770808..000000000 --- a/com.eco.bio7.image/src/ij/gui/OvalRoi.java +++ /dev/null @@ -1,440 +0,0 @@ -package ij.gui; -import java.awt.*; -import java.awt.image.*; -import java.awt.geom.*; -import ij.*; -import ij.process.*; -import ij.measure.Calibration; - -/** Oval region of interest */ -public class OvalRoi extends Roi { - - /** Creates an OvalRoi.*/ - public OvalRoi(int x, int y, int width, int height) { - super(x, y, width, height); - type = OVAL; - } - - /** Creates an OvalRoi using double arguments.*/ - public OvalRoi(double x, double y, double width, double height) { - super(x, y, width, height); - type = OVAL; - } - - /** Creates an OvalRoi. */ - public static OvalRoi create(double x, double y, double width, double height) { - return new OvalRoi(x, y, width, height); - } - - /** Starts the process of creating a user-defined OvalRoi. */ - public OvalRoi(int x, int y, ImagePlus imp) { - super(x, y, imp); - type = OVAL; - } - - /** @deprecated */ - public OvalRoi(int x, int y, int width, int height, ImagePlus imp) { - this(x, y, width, height); - setImage(imp); - } - - /** Feret (caliper width) values, see ij.gui.Roi.getFeretValues(). - * The superclass method of calculating this via the convex hull is less accurate for the MinFeret - * because it does not get the exact minor axis. */ - public double[] getFeretValues() { - double[] a = new double[FERET_ARRAYSIZE]; - double pw=1.0, ph=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - pw = cal.pixelWidth; - ph = cal.pixelHeight; - } - boolean highAspect = ph*height > pw*width; - a[0] = highAspect ? height*ph : width*pw; // (max)Feret - a[1] = highAspect ? 90.0 : 0.0; // (max)Feret angle - a[2] = highAspect ? width*pw : height*ph; // MinFeret - a[3] = (x + (highAspect ? 0.5*width : 0)) * pw; //FeretX scaled - a[4] = (y + (highAspect ? height : 0.5*height)) * ph;//FeretY scaled - int i = FERET_ARRAY_POINTOFFSET; - a[i++] = x + (highAspect ? 0.5*width : 0); //MaxFeret start - a[i++] = y + (highAspect ? height : 0.5*height); - a[i++] = x + (highAspect ? 0.5*width : width); //MaxFeret end - a[i++] = y + (highAspect ? 0 : 0.5*height); - a[i++] = x + (highAspect ? 0 : 0.5*width); //MinFeret start - a[i++] = y + (highAspect ? 0.5*height : height); - a[i++] = x + (highAspect ? width : 0.5*width); //MinFeret end - a[i++] = y + (highAspect ? 0.5*height : 0); - return a; - } - - protected void moveHandle(int sx, int sy) { - double asp; - if (clipboard!=null) return; - int ox = offScreenX(sx); - int oy = offScreenY(sy); - //IJ.log("moveHandle: "+activeHandle+" "+ox+" "+oy); - int x1=x, y1=y, x2=x+width, y2=y+height, xc=x+width/2, yc=y+height/2; - int w2 = (int)(0.14645*width); - int h2 = (int)(0.14645*height); - if (width > 7 && height > 7) { - asp = (double)width/(double)height; - asp_bk = asp; - } else - asp = asp_bk; - switch (activeHandle) { - case 0: x=ox-w2; y=oy-h2; break; - case 1: y=oy; break; - case 2: x2=ox+w2; y=oy-h2; break; - case 3: x2=ox; break; - case 4: x2=ox+w2; y2=oy+h2; break; - case 5: y2=oy; break; - case 6: x=ox-w2; y2=oy+h2; break; - case 7: x=ox; break; - } - //if (x<0) x=0; if (y<0) y=0; - if (x=x2) { - width=1; - x=x2=xc; - } - if (y>=y2) { - height=1; - y=y2=yc; - } - - } - - if (constrain) { - if (activeHandle==1 || activeHandle==5) width=height; - else height=width; - - if (x>=x2) { - width=1; - x=x2=xc; - } - if (y>=y2) { - height=1; - y=y2=yc; - } - switch(activeHandle){ - case 0: - x=x2-width; - y=y2-height; - break; - case 1: - x=xc-width/2; - y=y2-height; - break; - case 2: - y=y2-height; - break; - case 3: - y=yc-height/2; - break; - case 5: - x=xc-width/2; - break; - case 6: - x=x2-width; - break; - case 7: - y=yc-height/2; - x=x2-width; - break; - } - if (center){ - x=xc-width/2; - y=yc-height/2; - } - } - - if (aspect && !constrain) { - if (activeHandle==1 || activeHandle==5) width=(int)Math.rint((double)height*asp); - else height=(int)Math.rint((double)width/asp); - - switch (activeHandle) { - case 0: - x=x2-width; - y=y2-height; - break; - case 1: - x=xc-width/2; - y=y2-height; - break; - case 2: - y=y2-height; - break; - case 3: - y=yc-height/2; - break; - case 5: - x=xc-width/2; - break; - case 6: - x=x2-width; - break; - case 7: - y=yc-height/2; - x=x2-width; - break; - } - if (center) { - x=xc-width/2; - y=yc-height/2; - } - // Attempt to preserve aspect ratio when roi very small: - if (width<8) { - if (width<1) width = 1; - height=(int)Math.rint((double)width/asp_bk); - } - if (height<8) { - if (height<1) height =1; - width=(int)Math.rint((double)height*asp_bk); - } - } - - updateClipRect(); - imp.draw(clipX, clipY, clipWidth, clipHeight); - oldX=x; oldY=y; - oldWidth=width; oldHeight=height; - cachedMask = null; - bounds = null; - } - - public void draw(Graphics g) { - Color color = strokeColor!=null? strokeColor:ROIColor; - if (fillColor!=null) color = fillColor; - g.setColor(color); - mag = getMagnification(); - int sw = (int)(width*mag); - int sh = (int)(height*mag); - int sx1 = screenX(x); - int sy1 = screenY(y); - if (subPixelResolution() && bounds!=null) { - sw = (int)(bounds.width*mag); - sh = (int)(bounds.height*mag); - sx1 = screenXD(bounds.x); - sy1 = screenYD(bounds.y); - } - int sw2 = (int)(0.14645*width*mag); - int sh2 = (int)(0.14645*height*mag); - int sx2 = sx1+sw/2; - int sy2 = sy1+sh/2; - int sx3 = sx1+sw; - int sy3 = sy1+sh; - Graphics2D g2d = (Graphics2D)g; - if (stroke!=null) - g2d.setStroke(getScaledStroke()); - setRenderingHint(g2d); - if (fillColor!=null) { - if (!overlay && isActiveOverlayRoi()) { - g.setColor(Color.cyan); - g.drawOval(sx1, sy1, sw, sh); - } else { - g.fillOval(sx1, sy1, sw, sh); - if (strokeColor!=null) { - g.setColor(strokeColor); - g.drawOval(sx1, sy1, sw, sh); - } - } - } else - g.drawOval(sx1, sy1, sw, sh); - if (clipboard==null && !overlay) { - drawHandle(g, sx1+sw2, sy1+sh2); - drawHandle(g, sx3-sw2, sy1+sh2); - drawHandle(g, sx3-sw2, sy3-sh2); - drawHandle(g, sx1+sw2, sy3-sh2); - drawHandle(g, sx2, sy1); - drawHandle(g, sx3, sy2); - drawHandle(g, sx2, sy3); - drawHandle(g, sx1, sy2); - } - drawPreviousRoi(g); - if (updateFullWindow) - {updateFullWindow = false; imp.draw();} - if (state!=NORMAL) showStatus(); - } - - /** Draws an outline of this OvalRoi on the image. */ - public void drawPixels(ImageProcessor ip) { - Polygon p = getPolygon(); - if (p.npoints>0) { - int saveWidth = ip.getLineWidth(); - if (getStrokeWidth()>1f) - ip.setLineWidth((int)Math.round(getStrokeWidth())); - ip.drawPolygon(p); - ip.setLineWidth(saveWidth); - } - if (Line.getWidth()>1 || getStrokeWidth()>1) - updateFullWindow = true; - } - - /** Returns this OvalRoi as a Polygon that outlines the mask, in image pixel coordinates. */ - public Polygon getPolygon() { - return getPolygon(true); - } - - /** Returns this OvalRoi as a Polygon that outlines the mask. - * @param absoluteCoordinates determines whether to use image pixel coordinates - * instead of coordinates relative to roi origin. */ - Polygon getPolygon(boolean absoluteCoordinates) { - ImageProcessor mask = getMask(); - Wand wand = new Wand(mask); - wand.autoOutline(width/2,height/2, 255, 255); - if (absoluteCoordinates) - for (int i=0; i=sx1+sw2&&sx<=sx1+sw2+size&&sy>=sy1+sh2&&sy<=sy1+sh2+size) return 0; - if (sx>=sx2&&sx<=sx2+size&&sy>=sy1&&sy<=sy1+size) return 1; - if (sx>=sx3-sw2&&sx<=sx3-sw2+size&&sy>=sy1+sh2&&sy<=sy1+sh2+size) return 2; - if (sx>=sx3&&sx<=sx3+size&&sy>=sy2&&sy<=sy2+size) return 3; - if (sx>=sx3-sw2&&sx<=sx3-sw2+size&&sy>=sy3-sh2&&sy<=sy3-sh2+size) return 4; - if (sx>=sx2&&sx<=sx2+size&&sy>=sy3&&sy<=sy3+size) return 5; - if (sx>=sx1+sw2&&sx<=sx1+sw2+size&&sy>=sy3-sh2&&sy<=sy3-sh2+size) return 6; - if (sx>=sx1&&sx<=sx1+size&&sy>=sy2&&sy<=sy2+size) return 7; - return -1; - } - - public ImageProcessor getMask() { - ImageProcessor mask = cachedMask; - if (mask!=null && mask.getPixels()!=null && mask.getWidth()==width && mask.getHeight()==height) - return mask; - mask = new ByteProcessor(width, height); - double a=width/2.0, b=height/2.0; - double a2=a*a, b2=b*b; - a -= 0.5; b -= 0.5; - double xx, yy; - int offset; - byte[] pixels = (byte[])mask.getPixels(); - for (int y=0; y { - private Vector list; - private boolean label; - private boolean drawNames; - private boolean drawBackgrounds; - private Color labelColor; - private Font labelFont; - private boolean scalableLabels; - private boolean isCalibrationBar; - private boolean selectable = true; - private boolean draggable = true; - - /** Constructs an empty Overlay. */ - public Overlay() { - list = new Vector(); - } - - /** Constructs an Overlay and adds the specified ROI. */ - public Overlay(Roi roi) { - list = new Vector(); - if (roi!=null) - list.add(roi); - } - - /** Adds an ROI to this Overlay. */ - public void add(Roi roi) { - if (roi!=null) - list.add(roi); - } - - /** Adds an ROI to this Overlay using the specified name. */ - public void add(Roi roi, String name) { - roi.setName(name); - add(roi); - } - - /** Adds the ROIs in 'overlay2' to this overlay. */ - public Overlay add(Overlay overlay2) { - for (int i=0; i=list.size()) - throw new IllegalArgumentException("set: index out of range"); - if (roi!=null) - list.set(index, roi); - } - - /** Removes the ROI with the specified index from this Overlay. */ - public void remove(int index) { - if (index>=0) - list.remove(index); - } - - /** Removes the specified ROI from this Overlay. */ - public void remove(Roi roi) { - list.remove(roi); - } - - /** Removes all ROIs that have the specified name. */ - public void remove(String name) { - if (name==null) return; - for (int i=size()-1; i>=0; i--) { - if (name.equals(get(i).getName())) - remove(i); - } - } - - /** Removes all the ROIs in this Overlay. */ - public void clear() { - list.clear(); - } - - /** Returns the ROI with the specified index or null if the index is invalid. */ - public Roi get(int index) { - try { - return (Roi)list.get(index); - } catch(Exception e) { - return null; - } - } - - /** Returns the ROI with the specified name or null if not found. */ - public Roi get(String name) { - int index = getIndex(name); - if (index==-1) - return null; - else - return get(index); - } - - /** Returns the index of the ROI with the specified name, or -1 if not found. */ - public int getIndex(String name) { - if (name==null) return -1; - Roi[] rois = toArray(); - for (int i=rois.length-1; i>=0; i--) { - if (name.equals(rois[i].getName())) - return i; - } - return -1; - } - - /** Returns the index of the last ROI that contains the point (x,y) - or null if no ROI contains the point. */ - public int indexAt(int x, int y) { - Roi[] rois = toArray(); - for (int i=rois.length-1; i>=0; i--) { - if (contains(rois[i],x,y)) - return i; - } - return -1; - } - - private boolean contains(Roi roi, int x, int y) { - if (roi==null) return false; - if (roi instanceof Line) - return (((Line)roi).getFloatPolygon(10)).contains(x,y); - else - return roi.contains(x,y); - } - - /** Returns 'true' if this Overlay contains the specified ROI. */ - public boolean contains(Roi roi) { - return list.contains(roi); - } - - /** Returns the number of ROIs in this Overlay. */ - public int size() { - return list.size(); - } - - /** Returns on array containing the ROIs in this Overlay. */ - public Roi[] toArray() { - Roi[] array = new Roi[list.size()]; - return (Roi[])list.toArray(array); - } - - /** Returns on array containing the ROIs with the specified indexes. */ - public Roi[] toArray(int[] indexes) { - ArrayList rois = new ArrayList(); - for (int i=0; i=0 && indexes[i]0?bounds.x:0; - int dy = bounds.y>0?bounds.y:0; - if (dx>0 || dy>0) - overlay2.translate(-dx, -dy); - return overlay2; - } - - /** Removes ROIs having positions outside of the - * interval defined by firstSlice and lastSlice. - * Marcel Boeglin, September 2013 - */ - public void crop(int firstSlice, int lastSlice) { - for (int i=size()-1; i>=0; i--) { - Roi roi = get(i); - int position = roi.getPosition(); - if (position>0) { - if (positionlastSlice) - remove(i); - else - roi.setPosition(position-firstSlice+1); - } - } - } - - /** Removes ROIs having a C, Z or T coordinate outside the volume - * defined by firstC, lastC, firstZ, lastZ, firstT and lastT. - * Marcel Boeglin, September 2013 - */ - public void crop(int firstC, int lastC, int firstZ, int lastZ, int firstT, int lastT) { - int nc = lastC-firstC+1, nz = lastZ-firstZ+1, nt = lastT-firstT+1; - boolean toCStack = nz==1 && nt==1; - boolean toZStack = nt==1 && nc==1; - boolean toTStack = nc==1 && nz==1; - Roi roi; - int c, z, t, c2, z2, t2; - for (int i=size()-1; i>=0; i--) { - roi = get(i); - c = roi.getCPosition(); - z = roi.getZPosition(); - t = roi.getTPosition(); - c2 = c-firstC+1; - z2 = z-firstZ+1; - t2 = t-firstT+1; - if (toCStack) - roi.setPosition(c2); - else if (toZStack) - roi.setPosition(z2); - else if (toTStack) - roi.setPosition(t2); - else - roi.setPosition(c2, z2, t2); - if ((c2<1||c2>nc) && c>0 || (z2<1||z2>nz) && z>0 || (t2<1||t2>nt) && t>0) - remove(i); - } - } - - /** Returns the bounds of this overlay. */ - /* - public Rectangle getBounds() { - if (size()==0) - return new Rectangle(0,0,0,0); - int xmin = Integer.MAX_VALUE; - int xmax = -Integer.MAX_VALUE; - int ymin = Integer.MAX_VALUE; - int ymax = -Integer.MAX_VALUE; - Roi[] rois = toArray(); - for (int i=0; ixmax) xmax = r.x+r.width; - if (r.y+r.height>ymax) ymax = r.y+r.height; - } - return new Rectangle(xmin, ymin, xmax-xmin, ymax-ymin); - } - */ - - /* Returns the Roi that results from XORing all the ROIs - * in this overlay that have an index in the array ‘indexes’. - */ - public Roi xor(int[] indexes) { - return Roi.xor(toArray(indexes)); - } - - /** Returns a new Overlay that has the same properties as this one. */ - public Overlay create() { - Overlay overlay2 = new Overlay(); - overlay2.drawLabels(label); - overlay2.drawNames(drawNames); - overlay2.drawBackgrounds(drawBackgrounds); - overlay2.setLabelColor(labelColor); - overlay2.setLabelFont(labelFont, scalableLabels); - overlay2.setIsCalibrationBar(isCalibrationBar); - overlay2.selectable(selectable); - overlay2.setDraggable(draggable); - return overlay2; - } - - /** Returns a clone of this Overlay. */ - public Overlay duplicate() { - Roi[] rois = toArray(); - Overlay overlay2 = create(); - for (int i=0; i v) {list = v;} - - Vector getVector() {return list;} - - /** Set 'false' to prevent ROIs in this overlay from being activated - by clicking on their labels or by a long clicking. */ - public void selectable(boolean selectable) { - this.selectable = selectable; - } - - /** Returns 'true' if ROIs in this overlay can be activated - by clicking on their labels or by a long press. */ - public boolean isSelectable() { - return selectable; - } - - /** Set 'false' to prevent ROIs in this overlay from being dragged by their labels. */ - public void setDraggable(boolean draggable) { - this.draggable = draggable; - } - - /** Returns 'true' if ROIs in this overlay can be dragged by their labels. */ - public boolean isDraggable() { - return draggable; - } - - public boolean scalableLabels() { - return scalableLabels; - } - - public String toString() { - return "Overlay[size="+size()+" "+(scalableLabels?"scale":"")+" "+Colors.colorToString(getLabelColor())+"]"; - } - - /** Updates overlays created by the particle analyzer - after rows are deleted from the Results table. */ - public static void updateTableOverlay(ImagePlus imp, int first, int last, int tableSize) { - if (imp==null) - return; - Overlay overlay = imp.getOverlay(); - if (overlay==null) - return; - if (overlay.size()!=tableSize) - return; - if (first<0) - first = 0; - if (last>tableSize-1) - last = tableSize-1; - if (first>last) - return; - String name1 = overlay.get(0).getName(); - String name2 = overlay.get(overlay.size()-1).getName(); - if (!"1".equals(name1) || !(""+tableSize).equals(name2)) - return; - int count = last-first+1; - if (overlay.size()==count && !IJ.isMacro()) { - if (count==1 || IJ.showMessageWithCancel("ImageJ", "Delete "+overlay.size()+" element overlay? ")) - imp.setOverlay(null); - return; - } - for (int i=0; i iterator() { - final Overlay overlay = this; - - Iterator it = new Iterator() { - private int index = -1; - - /** Returns 'true' if next element exists. */ - @Override - public boolean hasNext() { - if (index+12 - private static final int LEGEND_PADDING = 4; //pixels around legend text etc - private static final int LEGEND_LINELENGTH = 20; //length of lines in legend - private static final int USUALLY_ENLARGE = 1, ALWAYS_ENLARGE = 2; //enlargeRange settings - private static final double RELATIVE_ARROWHEAD_SIZE = 0.2; //arrow heads have 1/5 of vector length - private static final int MIN_ARROWHEAD_LENGTH = 3; - private static final int MAX_ARROWHEAD_LENGTH = 20; - private static final String MULTIPLY_SYMBOL = "\u00B7"; //middot, default multiplication symbol for scientific notation. Use setOptions("msymbol=\\u00d7") for '×' - - PlotProperties pp = new PlotProperties(); //size, range, formatting etc, for easy serialization - PlotProperties ppSnapshot; //copy for reverting - Vector allPlotObjects = new Vector(); //all curves, labels etc., also serialized for saving/reading - Vector allPlotObjectsSnapshot; //copy for reverting - private PlotVirtualStack stack; - /** For high-resolution plots, everything will be scaled with this number. Otherwise, must be 1.0. - * (creating margins, saving PlotProperties etc only supports scale=1.0) */ - float scale = 1.0f; - Rectangle frame = null; //the clip frame, do not use for image scale - //The following are the margin sizes actually used. They are modified for font size and also scaled for high-resolution plots - public int leftMargin = LEFT_MARGIN; - public int rightMargin = RIGHT_MARGIN; - public int topMargin = TOP_MARGIN; - public int bottomMargin = BOTTOM_MARGIN; - int frameWidth; //width corresponding to plot range; frame.width is larger by 1 - int frameHeight; //height corresponding to plot range; frame.height is larger by 1 - int preferredPlotWidth = PlotWindow.plotWidth; //default size of plot frame (not taking 'High-Resolution' scale factor into account) - int preferredPlotHeight = PlotWindow.plotHeight; - - double xMin = Double.NaN, xMax, yMin, yMax; //current plot range, logarithm if log axis - double[] currentMinMax = new double[]{Double.NaN, 0, Double.NaN, 0}; //current plot range, xMin, xMax, yMin, yMax (values, not logarithm if log axis) - double[] defaultMinMax = new double[]{Double.NaN, 0, Double.NaN, 0}; //default plot range - double[] savedMinMax = new double[]{Double.NaN, 0, Double.NaN, 0}; //keeps previous range for revert - int[] enlargeRange; // whether to enlarge the range slightly to avoid values at the border (0=off, USUALLY_ENLARGE, ALWAYS_ENLARGE) - boolean logXAxis, logYAxis; // whether to really use log axis (never for small relative range) - //for passing on what should be kept when 'live' plotting (PlotMaker), but note that 'COPY_EXTRA_OBJECTS' is also on for live plotting: - int templateFlags = COPY_SIZE | COPY_LABELS | COPY_AXIS_STYLE | COPY_CONTENTS_STYLE | COPY_LEGEND; - private int dsize = PlotWindow.getDefaultFontSize(); - Font defaultFont = FontUtil.getFont("Arial",Font.PLAIN,dsize); //default font for labels, axis, etc. - Font currentFont = defaultFont; // font as changed by setFont or setFontSize, must never be null - private double xScale, yScale; // pixels per data unit - private int xBasePxl, yBasePxl; // pixel coordinates corresponding to 0 - private int maxIntervals = 12; // maximum number of intervals between ticks or grid lines - private int tickLength = 7; // length of major ticks - private int minorTickLength = 3; // length of minor ticks - private Color gridColor = new Color(0xc0c0c0); // light gray - private ImageProcessor ip; - private ImagePlus imp; // if we have an ImagePlus, updateAndDraw on changes - private String title; - private boolean invertedLut; // grayscale plots only, set in Edit>Options>Appearance - private boolean plotDrawn; - PlotMaker plotMaker; // for PlotMaker interface, handled by PlotWindow - private Color currentColor; // for next objects added - private Color currentColor2; // 2nd color for next object added (e.g. line for CONNECTED_CIRCLES) - float currentLineWidth; - private int currentJustification = LEFT; - private boolean ignoreForce2Grid; // after explicit setting of range (limits), ignore 'FORCE2GRID' flags - //private boolean snapToMinorGrid; // snap to grid when zooming to selection - private static double SEPARATED_BAR_WIDTH=0.5; // for plots with separate bars (e.g. categories), fraction of space, 0.1-1.0 - double[] steps; // x & y interval between numbers, major ticks & grid lines, remembered for redrawing the grid - private int objectToReplace = -1; // index in allPlotObjects, for replace - //private Point2D.Double textLoc; // remembers position of previous addLabel call (replaces text if at the same position) - //private int textIndex; // remembers index of previous addLabel call (for replacing if at the same position) - - /** Constructs a new Plot with the default options. - * Use add(shape,xvalues,yvalues) to add curves. - * @param title the window title - * @param xLabel the x-axis label; see setXYLabels for seting categories on an axis via the label - * @param yLabel the y-axis label; see setXYLabels for seting categories on an axis via the label - * @see #add(String,double[],double[]) - * @see #add(String,double[]) - */ - public Plot(String title, String xLabel, String yLabel) { - this(title, xLabel, yLabel, (float[])null, (float[])null, getDefaultFlags()); - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, float[] x, float[] y) { - this(title, xLabel, yLabel, x, y, getDefaultFlags()); - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, double[] x, double[] y) { - this(title, xLabel, yLabel, x!=null?Tools.toFloat(x):null, y!=null?Tools.toFloat(y):null, getDefaultFlags()); - } - - /** This version of the constructor has a 'flags' argument for - controlling whether ticks, grid, etc. are present and whether - the axes are logarithmic */ - public Plot(String title, String xLabel, String yLabel, int flags) { - this(title, xLabel, yLabel, (float[])null, (float[])null, flags); - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel,flags); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, float[] xValues, float[] yValues, int flags) { - this.title = title; - pp.axisFlags = flags; - setXYLabels(xLabel, yLabel); - if (yValues != null && yValues.length>0) { - addPoints(xValues, yValues, /*yErrorBars=*/null, LINE, /*label=*/null); - allPlotObjects.get(0).flags = PlotObject.CONSTRUCTOR_DATA; - } - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel,flags); add(shape,x,y);". - * @deprecated - */ - public Plot(String title, String xLabel, String yLabel, double[] x, double[] y, int flags) { - this(title, xLabel, yLabel, x!=null?Tools.toFloat(x):null, y!=null?Tools.toFloat(y):null, flags); - } - - /** Constructs a new plot from an InputStream and closes the stream. If the ImagePlus is - * non-null, its title and ImageProcessor are used, but the image displayed is not modified. - */ - public Plot(ImagePlus imp, InputStream is) throws IOException, ClassNotFoundException { - ObjectInputStream in = new ObjectInputStream(is); - pp = (PlotProperties)in.readObject(); - allPlotObjects = (Vector)in.readObject(); - in.close(); - if (pp.xLabel.type==8) { - pp.xLabel.updateType(); //convert old (pre-1.52i) type codes for the PlotObjects - pp.yLabel.updateType(); - pp.frame.updateType(); - if (pp.legend != null) pp.legend.updateType(); - for (PlotObject plotObject : allPlotObjects) - plotObject.updateType(); - } - - defaultMinMax = pp.rangeMinMax; - currentFont = nonNullFont(pp.frame.getFont(), currentFont); // best guess in case we want to add a legend - getProcessor(); //prepares scale, calibration etc, but does not plot it yet - this.title = imp != null ? imp.getTitle() : "Untitled Plot"; - if (imp != null) { - this.imp = imp; - ip = imp.getProcessor(); - imp.setIgnoreGlobalCalibration(true); - adjustCalibration(imp.getCalibration()); - imp.setProperty(PROPERTY_KEY, this); - } - } - - /** Obsolete, replaced by "new Plot(title,xLabel,yLabel); add(shape,x,y);". - * @deprecated - */ - public Plot(String dummy, String title, String xLabel, String yLabel, float[] x, float[] y) { - this(title, xLabel, yLabel, x, y, getDefaultFlags()); - } - - /** Writes this plot into an OutputStream containing (1) the serialized PlotProperties and - * (2) the serialized Vector of all 'added' PlotObjects. The stream is NOT closed. - * The plot should have been drawn already. - */ - // Conversion to Streams can be also used to clone plots (not a shallow clone), but this is rather slow. - // Sample code: - // try { - // final PipedOutputStream pos = new PipedOutputStream(); - // final PipedInputStream pis = new PipedInputStream(pos); - // new Thread(new Runnable() { - // final public void run() { - // try { - // Plot p = new Plot(null, pis); - // pis.close(); - // pos.close(); - // p.show(); - // } catch(Exception e) {IJ.handleException(e);}; - // } - // }, "threadMakingPlotFromStream").start(); - // toStream(pos); - // } catch(Exception e) {IJ.handleException(e);} - void toStream(OutputStream os) throws IOException { - //prepare - for (PlotObject plotObject : pp.getAllPlotObjects()) //make sure all fonts are set properly - if (plotObject != null) - plotObject.setFont(nonNullFont(plotObject.getFont(), currentFont)); - pp.rangeMinMax = currentMinMax; - //write - ObjectOutputStream out = new ObjectOutputStream(os); - out.writeObject(pp); - out.writeObject(allPlotObjects); - } - - /** Writes this plot into a byte array containing (1) the serialized PlotProperties and - * (2) the serialized Vector of all 'added' PlotObjects. - * The plot should have been drawn already. Returns null on error (which should never happen). */ - public byte[] toByteArray() { - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - toStream(bos); - bos.close(); - return bos.toByteArray(); - } catch (Exception e) { - IJ.handleException(e); - return null; - } - } - - /** Returns the title of the image showing the plot (if any) or title of the plot */ - public String getTitle() { - return imp == null ? title : imp.getTitle(); - } - - /** Sets the x-axis and y-axis range. Saves the new limits as default (so the 'R' field sets the limits to these). - * Updates the image if existing. - * Accepts NaN values to indicate auto-range. */ - public void setLimits(double xMin, double xMax, double yMin, double yMax) { - setLimitsNoUpdate(xMin, xMax, yMin, yMax); - makeLimitsDefault(); - ignoreForce2Grid = true; - if (plotDrawn) - setLimitsToDefaults(true); - } - - /** Sets the x-axis and y-axis range. Accepts NaN values to indicate auto range. - * Does not update the image and leaves the default limits (for reset via the 'R' field) untouched. */ - void setLimitsNoUpdate(double xMin, double xMax, double yMin, double yMax) { - boolean containsNaN = (Double.isNaN(xMin + xMax + yMin + yMax)); - if (containsNaN && getNumPlotObjects(PlotObject.XY_DATA|PlotObject.ARROWS, false)==0)//can't apply auto-range without data - return; - double[] range = {xMin, xMax, yMin, yMax}; - if (containsNaN) { //auto range for at least one limit - double[] extrema = getMinAndMax(true, ALL_AXES_RANGE); - boolean[] auto = new boolean[range.length]; - for (int i = 0; i < range.length; i++) - if (Double.isNaN(range[i])) { - auto[i] = true; - range[i] = extrema[i]; - } - for (int a = 0; aOptions>Plots. - * @see #setFrameSize(int,int) - * @see #setWindowSize(int,int) - */ - public void setSize(int width, int height) { - if (ip != null && width == ip.getWidth() && height == ip.getHeight()) - return; - Dimension minSize = getMinimumSize(); - pp.width = Math.max(width, minSize.width); - pp.height = Math.max(height, minSize.height); - scale = 1.0f; - ip = null; - if (plotDrawn) updateImage(); - } - - /** The size of the plot including borders with axis labels etc., in pixels */ - public Dimension getSize() { - if (ip == null) - getBlankProcessor(); - return new Dimension(ip.getWidth(), ip.getHeight()); - } - - /** Sets the plot frame size in (unscaled) pixels. This size does not include the - * borders with the axis labels. Also sets the scale to 1.0. - * This frame size in pixels divided by the data range defines the image scale. - * This method does not check for the minimum size MIN_FRAMEWIDTH, MIN_FRAMEHEIGHT. - * Note that the black frame will have an outer size that is one pixel larger - * (when plotted with a linewidth of one pixel). - * @see #setWindowSize(int,int) - */ - public void setFrameSize(int width, int height) { - if (pp.width <= 0) { //plot not drawn yet? Just remember as preferred size - preferredPlotWidth = width; - preferredPlotHeight = height; - scale = 1.0f; - } else { - makeMarginValues(); - width += leftMargin+rightMargin; - height += topMargin+bottomMargin; - setSize(width, height); - } - } - - /** Sets the plot window size in pixels. - * @see #setFrameSize(int,int) - */ - public void setWindowSize(int width, int height) { - scale = 1.0f; - makeMarginValues(); - int titleBarHeight = 22; - int infoHeight = 11; - double scale = Prefs.getGuiScale(); - if (scale>1.0) - infoHeight = (int)(infoHeight*scale); - int buttonPanelHeight = 45; - if (pp.width <= 0) { //plot not drawn yet? - int extraWidth = leftMargin+rightMargin+ImageWindow.HGAP*2; - int extraHeight = topMargin+bottomMargin+titleBarHeight+infoHeight+buttonPanelHeight; - if (extraWidthplot may be null; then the call has no effect. */ - public void useTemplate(Plot plot) { - useTemplate(plot, templateFlags); - } - - /** Adjusts the format (style) with another plot as a template. Flags determine what to - * copy from the template; these can be X_RANGE, Y_RANGE, COPY_SIZE, COPY_LABELS, COPY_AXIS_STYLE, - * COPY_CONTENTS_STYLE (hidden items are ignored), and COPY_LEGEND. - * plot may be null; then the call has no effect. */ - public void useTemplate(Plot plot, int templateFlags) { - if (plot == null) return; - this.defaultFont = plot.defaultFont; - this.currentFont = plot.currentFont; - this.currentLineWidth = plot.currentLineWidth; - this.currentColor = plot.currentColor; - if ((templateFlags & COPY_AXIS_STYLE) != 0) { - this.pp.axisFlags = plot.pp.axisFlags; - this.pp.frame = plot.pp.frame.deepClone(); - } - if ((templateFlags & COPY_LABELS) != 0) { - this.pp.xLabel.label = plot.pp.xLabel.label; - this.pp.yLabel.label = plot.pp.yLabel.label; - this.pp.xLabel.setFont(plot.pp.xLabel.getFont()); - this.pp.yLabel.setFont(plot.pp.yLabel.getFont()); - } - for (int i=0; i>(i/2)&0x1) != 0) { - currentMinMax[i] = plot.currentMinMax[i]; - if (!plotDrawn) defaultMinMax[i] = plot.currentMinMax[i]; - } - if ((templateFlags & COPY_LEGEND) != 0 && plot.pp.legend != null) - this.pp.legend = plot.pp.legend.deepClone(); - if ((templateFlags & (COPY_LEGEND | COPY_CONTENTS_STYLE)) != 0) { - int plotPObjectIndex = 0; //points to PlotObjects of the templatePlot - int plotPObjectsSize = plot.allPlotObjects.size(); - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN)) { - while(plotPObjectIndex=plotPObjectsSize) break; - if ((templateFlags & COPY_LEGEND) != 0) - plotObject.label = plot.allPlotObjects.get(plotPObjectIndex).label; - if ((templateFlags & COPY_CONTENTS_STYLE) != 0) - setPlotObjectStyle(plotObject, getPlotObjectStyle(plot.allPlotObjects.get(plotPObjectIndex))); - plotPObjectIndex++; - } - } - } - if ((templateFlags & COPY_SIZE) != 0) - setSize(plot.pp.width, plot.pp.height); - - if ((templateFlags & COPY_EXTRA_OBJECTS) != 0) - for (int p = allPlotObjects.size(); p < plot.allPlotObjects.size(); p++) - allPlotObjects.add(plot.allPlotObjects.get(p)); - this.templateFlags = templateFlags; - } - - /** Sets the scale. Everything, including labels, line thicknesses, etc will be scaled by this factor. - * Also multiplies the plot size by this value. Used for 'Create high-resolution plot'. - * Should be called before creating the plot. - * Note that plots with a scale different from 1.0 must not be shown in a PlotWindow, but only as - * simple image in a normal ImageWindow. */ - public void setScale(float scale) { - this.scale = scale; - if (scale > 20f) scale = 20f; - if (scale < 0.7f) scale = 0.7f; - pp.width = sc(pp.width); - pp.height = sc(pp.height); - plotDrawn = false; - } - - /** Sets the labels of the x and y axes. 'xLabel', 'yLabel' may be null. - * If a label has the form {txt1,txt2,txt3}, the corresponding axis will be labeled - * not by numbers but rather with the texts "txt1", "txt2" ... instead of 0, 1, ... - * In this special case, there will be no label for the axis on the plot. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setXYLabels(String xLabel, String yLabel) { - pp.xLabel.label = xLabel!=null ? xLabel : ""; - pp.yLabel.label = yLabel!=null ? yLabel : ""; - } - - /** Sets the maximum number of intervals in a plot. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setMaxIntervals(int intervals) { - maxIntervals = intervals; - } - - /** Sets the length of the major tick in pixels. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setTickLength(int tickLength) { - this.tickLength = tickLength; - } - - /** Sets the length of the minor tick in pixels. */ - public void setMinorTickLength(int minorTickLength) { - this.minorTickLength = minorTickLength; - } - - /** Sets the flags that control the axes format. - * Does not modify the flags for logarithmic axes on/off and the FORCE2GRID flags. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setFormatFlags(int flags) { - int unchangedFlags = X_LOG_NUMBERS | Y_LOG_NUMBERS | X_FORCE2GRID | Y_FORCE2GRID; - flags = flags & (~unchangedFlags); //remove flags that should not be affected - pp.axisFlags = (pp.axisFlags & unchangedFlags) | flags; - } - - /** Returns the flags that control the axes */ - public int getFlags() { - return pp.axisFlags; - } - - /** Sets the X Axis format to Log or Linear. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setAxisXLog(boolean axisXLog) { - pp.axisFlags = axisXLog ? pp.axisFlags | X_LOG_NUMBERS : pp.axisFlags & (~X_LOG_NUMBERS); - } - - /** Sets the Y Axis format to Log or Linear. - * Call update() thereafter to make the change visible (if it is shown already). */ - public void setAxisYLog(boolean axisYLog) { - pp.axisFlags = axisYLog ? pp.axisFlags | Y_LOG_NUMBERS : pp.axisFlags & (~Y_LOG_NUMBERS); - } - - /** Sets whether to show major ticks at the x axis. - * Call update() thereafter to make the change visible (if the image is shown already). */ - - public void setXTicks(boolean xTicks) { - pp.axisFlags = xTicks ? pp.axisFlags | X_TICKS : pp.axisFlags & (~X_TICKS); - } - - /** Sets whether to show major ticks at the y axis. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setYTicks(boolean yTicks) { - pp.axisFlags = yTicks ? pp.axisFlags | Y_TICKS : pp.axisFlags & (~Y_TICKS); - } - - /** Sets whether to show minor ticks on the x axis (if linear). Also sets major ticks if true and no grid is set. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setXMinorTicks(boolean xMinorTicks) { - pp.axisFlags = xMinorTicks ? pp.axisFlags | X_MINOR_TICKS : pp.axisFlags & (~X_MINOR_TICKS); - if (xMinorTicks && !hasFlag(X_GRID)) - pp.axisFlags |= X_TICKS; - } - - /** Sets whether to show minor ticks on the y axis (if linear). Also sets major ticks if true and no grid is set. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setYMinorTicks(boolean yMinorTicks) { - pp.axisFlags = yMinorTicks ? pp.axisFlags | Y_MINOR_TICKS : pp.axisFlags & (~Y_MINOR_TICKS); - if (yMinorTicks && !hasFlag(Y_GRID)) - pp.axisFlags |= Y_TICKS; - } - - /** Sets the properties of the axes. Call update() thereafter to make the change visible - * (if the image is shown already). */ - public void setAxes(boolean xLog, boolean yLog, boolean xTicks, boolean yTicks, boolean xMinorTicks, boolean yMinorTicks, - int tickLenght, int minorTickLenght) { - setAxisXLog (xLog); - setAxisYLog (yLog); - setXMinorTicks (xMinorTicks); - setYMinorTicks (yMinorTicks); - setXTicks (xTicks); - setYTicks (yTicks); - setTickLength (tickLenght); - setMinorTickLength(minorTickLenght); - } - - /** Sets log scale in x. Call update() thereafter to make the change visible - * (if the image is shown already). */ - - public void setLogScaleX() { - setAxisXLog(true); - } - - public void setLogScaleY() { - setAxisYLog(true); - } - - /** The default flags, taking PlotWindow.noGridLines, PlotWindow.noTicks into account */ - public static int getDefaultFlags() { - int defaultFlags = 0; - if (!PlotWindow.noGridLines) //note that log ticks are also needed because the range may span less than a decade, then no grid is visible - defaultFlags |= X_GRID | Y_GRID | X_NUMBERS | Y_NUMBERS | X_LOG_TICKS | Y_LOG_TICKS; - if (!PlotWindow.noTicks) - defaultFlags |= X_TICKS | Y_TICKS | X_MINOR_TICKS | Y_MINOR_TICKS | X_NUMBERS | Y_NUMBERS | X_LOG_TICKS | Y_LOG_TICKS; - return defaultFlags; - } - - /** Adds a curve or set of points to this plot, where 'type' is - * "line", "connected circle", "filled", "bar", "separated bar", "circle", "box", "triangle", "diamond", "cross", - * "x" or "dot". Run Help>Examples>JavaScript>Graph Types to see examples. - * If 'type' is in the form "code: ", the macro given is executed to draw the symbol; - * macro variables 'x' and 'y' are the pixel coordinates of the point, 'xval' and 'yval' are the plot data - * and 'i' is the index of the data point (starting with 0 for the first point in the array). - * The drawing including line thickness, font size, etc. be scaled by scale factor 's' (to make high-resolution plots work). - * Example: "code: setFont('sanserif',12*s,'bold anti');drawString(d2s(yval,1),x-14*s,y-4*s);" - * writes the y value for each point above the point. - */ - public void add(String type, double[] xvalues, double[] yvalues) { - int iShape = toShape(type); - addPoints(Tools.toFloat(xvalues), Tools.toFloat(yvalues), null, iShape, iShape==CUSTOM?type.substring(5, type.length()):null); - } - - /** Replaces the specified plot object (curve or set of points). - * Equivalent to add() if there are no plot objects. */ - public void replace(int index, String type, double[] xvalues, double[] yvalues) { - if (index>=0 && index0?index:-1; - add(type, xvalues, yvalues); - } - } - - /** Adds a curve, set of points or error bars to this plot, where 'type' is - * "line", "connected circle", "filled", "bar", "separated bar", "circle", "box", - * "triangle", "diamond", "cross", "x", "dot", "error bars" or "xerror bars". - */ - public void add(String type, double[] yvalues) { - int iShape = toShape(type); - if (iShape==-1) - addErrorBars(yvalues); - else if (iShape==-2) - addHorizontalErrorBars(yvalues); - else - addPoints(null, Tools.toFloat(yvalues), null, iShape, iShape==CUSTOM?type.substring(5, type.length()):null); - } - - /** Adds a set of points to the plot or adds a curve if shape is set to LINE. - * @param xValues the x coordinates, or null. If null, integers starting at 0 will be used for x. - * @param yValues the y coordinates (must not be null) - * @param yErrorBars error bars in y, may be null - * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS, DIAMOND, DOT, LINE, CONNECTED_CIRCLES - * @param label Label for this curve or set of points, used for a legend and for listing the plots. - * For shape type CUSTOM, the 'label' String should contain the macro code as in "Custom Plot Symbols" - * example macro and in add(String, double[], double[]) (without the 'code:') - */ - public void addPoints(float[] xValues, float[] yValues, float[] yErrorBars, int shape, String label) { - if (xValues==null || xValues.length==0) { - xValues = new float[yValues.length]; - for (int i=0; i=0) - allPlotObjects.set(objectToReplace, new PlotObject(xValues, yValues, yErrorBars, shape, currentLineWidth, currentColor, currentColor2, label)); - else - allPlotObjects.add(new PlotObject(xValues, yValues, yErrorBars, shape, currentLineWidth, currentColor, currentColor2, label)); - objectToReplace = -1; - if (plotDrawn) updateImage(); - } - - /** Adds a set of points to the plot or adds a curve if shape is set to LINE. - * @param x the x coordinates - * @param y the y coordinates - * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS, DIAMOND, DOT, LINE, CONNECTED_CIRCLES - */ - public void addPoints(float[] x, float[] y, int shape) { - addPoints(x, y, null, shape, null); - } - - /** Adds a set of points to the plot using double arrays. */ - public void addPoints(double[] x, double[] y, int shape) { - addPoints(Tools.toFloat(x), Tools.toFloat(y), shape); - } - - /** Returns the number for a given plot symbol shape, -1 for xError and -2 for yError (all case-insensitive) */ - public static int toShape(String str) { - str = str.toLowerCase(Locale.US); - int shape = Plot.CIRCLE; - if (str.contains("curve") || str.contains("line")) - shape = Plot.LINE; - else if (str.contains("connected")) - shape = Plot.CONNECTED_CIRCLES; - else if (str.contains("filled")) - shape = Plot.FILLED; - else if (str.contains("circle")) - shape = Plot.CIRCLE; - else if (str.contains("box")) - shape = Plot.BOX; - else if (str.contains("triangle")) - shape = Plot.TRIANGLE; - else if (str.contains("cross") || str.contains("+")) - shape = Plot.CROSS; - else if (str.contains("diamond")) - shape = Plot.DIAMOND; - else if (str.contains("dot")) - shape = Plot.DOT; - else if (str.contains("xerror")) - shape = -2; - else if (str.contains("error")) - shape = -1; - else if (str.contains("x")) - shape = Plot.X; - else if (str.contains("separate")) - shape = Plot.SEPARATED_BAR; - else if (str.contains("bar")) - shape = Plot.BAR; - if (str.startsWith("code:")) - shape = CUSTOM; - return shape; - } - - /** Adds a set of points to the plot using double ArrayLists. - * Must be called before the plot is displayed. */ - public void addPoints(ArrayList x, ArrayList y, int shape) { - addPoints(getDoubleFromArrayList(x), getDoubleFromArrayList(y), shape); - } - - /** Adds a set of points to the plot or adds a curve if shape is set to LINE. - * @param x the x-coodinates - * @param y the y-coodinates - * @param errorBars half-lengths of the vertical error bars, may be null - * @param shape CIRCLE, X, BOX, TRIANGLE, CROSS, DIAMOND, DOT or LINE - */ - public void addPoints(double[] x, double[] y, double[] errorBars, int shape) { - addPoints(Tools.toFloat(x), Tools.toFloat(y), Tools.toFloat(errorBars), shape, null); - } - - /** Adds a set of points to the plot using double ArrayLists. - * Must be called before the plot is displayed. */ - public void addPoints(ArrayList x, ArrayList y, ArrayList errorBars, int shape) { - addPoints(getDoubleFromArrayList(x), getDoubleFromArrayList(y), getDoubleFromArrayList(errorBars), shape); - } - - public double[] getDoubleFromArrayList(ArrayList list) { - if (list == null) return null; - double[] targ = new double[list.size()]; - for (int i = 0; i < list.size(); i++) - targ[i] = ((Double) list.get(i)).doubleValue(); - return targ; - } - - /** Adds a set of points that will be drawn as ARROWs. - * @param x1 the x-coodinates of the beginning of the arrow - * @param y1 the y-coodinates of the beginning of the arrow - * @param x2 the x-coodinates of the end of the arrow - * @param y2 the y-coodinates of the end of the arrow - */ - public void drawVectors(double[] x1, double[] y1, double[] x2, double[] y2) { - allPlotObjects.add(new PlotObject(Tools.toFloat(x1), Tools.toFloat(y1), - Tools.toFloat(x2), Tools.toFloat(y2), currentLineWidth, currentColor)); - } - - /** - * Adds a set of 'shapes' such as boxes and whiskers - * - * @param shapeType e.g. "boxes width=20" - * @param floatCoords eg[6][3] holding 1 Xval + 5 Yvals for 3 boxes - */ - public void drawShapes(String shapeType, ArrayList floatCoords) { - allPlotObjects.add(new PlotObject(shapeType, floatCoords, currentLineWidth, currentColor, currentColor2)); - } - - public static double calculateDistance(int x1, int y1, int x2, int y2) { - return java.lang.Math.sqrt((x2 - x1)*(double)(x2 - x1) + (y2 - y1)*(double)(y2 - y1)); - } - - /** Adds a set of vectors to the plot using double ArrayLists. - * Does not support logarithmic axes. - * Must be called before the plot is displayed. */ - public void drawVectors(ArrayList x1, ArrayList y1, ArrayList x2, ArrayList y2) { - drawVectors(getDoubleFromArrayList(x1), getDoubleFromArrayList(y1), getDoubleFromArrayList(x2), getDoubleFromArrayList(y2)); - } - - /** Adds vertical error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addErrorBars(float[] errorBars) { - PlotObject mainObject = getLastCurveObject(); - if (mainObject != null) - mainObject.yEValues = errorBars; - else throw new RuntimeException("Plot can't add y error bars without data"); - } - - /** Adds vertical error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addErrorBars(double[] errorBars) { - addErrorBars(Tools.toFloat(errorBars)); - } - - /** Adds horizontal error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addHorizontalErrorBars(float[] xErrorBars) { - PlotObject mainObject = getLastCurveObject(); - if (mainObject != null) - mainObject.xEValues = xErrorBars; - else throw new RuntimeException("Plot can't add x error bars without data"); - } - - /** Adds horizontal error bars to the last data passed to the plot (via the constructor or addPoints). */ - public void addHorizontalErrorBars(double[] xErrorBars) { - addHorizontalErrorBars(Tools.toFloat(xErrorBars)); - } - - /** Draws text at the specified location, where (0,0) - * is the upper left corner of the the plot frame and (1,1) is - * the lower right corner. Uses the justification specified by setJustification(). - * When called with the same position as the previous addLabel call, the text of that previous call is replaced */ - public void addLabel(double x, double y, String label) { - for (int i=allPlotObjects.size()-1; i>=0; i--) { - PlotObject plotObject = allPlotObjects.get(i); - if (plotObject.type == PlotObject.NORMALIZED_LABEL) { //result of previous addLabel - if (plotObject.x == x && plotObject.y == y) { - allPlotObjects.set(i, new PlotObject(label, x, y, currentJustification, - currentFont, currentColor, PlotObject.NORMALIZED_LABEL)); - return; - } - break; - } - } - allPlotObjects.add(new PlotObject(label, x, y, currentJustification, currentFont, currentColor, PlotObject.NORMALIZED_LABEL)); - } - - /* Draws text at the specified location, using the coordinate system defined - * by setLimits() and the justification specified by setJustification(). */ - public void addText(String label, double x, double y) { - allPlotObjects.add(new PlotObject(label, x, y, currentJustification, currentFont, currentColor, PlotObject.LABEL)); - } - - /** Adds an automatically positioned legend, where 'labels' can be a tab-delimited or - newline-delimited list of curve or point labels in the sequence these data were added. - Hidden data sets are ignored. - If 'labels' is null or empty, the labels of the data set previously (if any) are used. - To modify the legend's style, call 'setFont' and 'setLineWidth' before 'addLegend'. */ - public void addLegend(String labels) { - addLegend(labels, "auto"); - } - - /** Adds a legend at the position given in 'options', where 'labels' can be tab-delimited or - * newline-delimited list of curve or point labels in the sequence these data were added. - * Hidden data sets are ignored; no labels (and no delimiters) should be provided for these. - * Apart from top to bottom and bottom to top (controlled by "bottom-to-top" in the options), - * the sequence may be altered by preceding numbers followed by double underscores, such as - * "1__Other Data Set\t0__First Data Set" (the number and double underscore won't be displayed). - * When this possibility is used, only items with double underscores will be shown in the legend - * (preceding double underscores without a number make the item appear in the legend without altering the sequence). - * If 'labels' is null or empty, the labels of the data set previously (if any) are used. - To modify the legend's style, call 'setFont' and 'setLineWidth' before 'addLegend'. */ - public void addLegend(String labels, String options) { - int flags = 0; - if (options!=null) { - options = options.toLowerCase(); - if (options.contains("top-left")) - flags |= Plot.TOP_LEFT; - else if (options.contains("top-right")) - flags |= Plot.TOP_RIGHT; - else if (options.contains("bottom-left")) - flags |= Plot.BOTTOM_LEFT; - else if (options.contains("bottom-right")) - flags |= Plot.BOTTOM_RIGHT; - else if (!options.contains("off") && !options.contains("no")) - flags |= Plot.AUTO_POSITION; - if (options.contains("bottom-to-top")) - flags |= Plot.LEGEND_BOTTOM_UP; - if (options.contains("transparent")) - flags |= Plot.LEGEND_TRANSPARENT; - } - setLegend(labels, flags); - } - - /** Adds a legend. The legend will be always drawn last (on top of everything). - * To modify the legend's style, call 'setFont' and 'setLineWidth' before 'addLegend' - * @param labels labels of the points or curves in the sequence of the data were added, tab-delimited or linefeed-delimited. - * The labels of the datasets will be set to these values. If null or not given, the labels set - * previously (if any) will be used. - * Hidden data sets are ignored; no labels (and no delimiters) should be provided for these. - * Apart from top to bottom and bottom to top (controlled by the LEGEND_BOTTOM_UP flag), - * the sequence may be altered by preceding numbers followed by double underscores, such as - * "1__Other Data Set\t0__First Data Set" (the number and double underscore won't be displayed). - * When this possibility is used, only items with double underscores will be shown in the legend - * (preceding double underscores without a number make the item appear in the legend without altering the sequence). - * @param flags Bitwise or of position (AUTO_POSITION, TOP_LEFT etc.), LEGEND_TRANSPARENT, and LEGEND_BOTTOM_UP if desired. - * Updates the image (if it is shown already). */ - public void setLegend(String labels, int flags) { - if (labels != null && labels.length()>0) { - String[] allLabels = labels.split("[\n\t]"); - int iPart = 0; - for (PlotObject plotObject : allPlotObjects) - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN)) - if (iPart < allLabels.length) { - String label = allLabels[iPart++]; - if (label!=null && label.length()>0) - plotObject.label = label; - } - } - pp.legend = new PlotObject(currentLineWidth == 0 ? 1 : currentLineWidth, - currentFont, currentColor == null ? Color.black : currentColor, flags); - if (plotDrawn) updateImage(); - } - - /** Sets the label for the plot object number 'index' in the sequence they were added. - * With index=-1, sets the label for the last object added. - * For x/y data, the label is used for the legend and as header in getResultsTableWithLabels. - * For Text/Label objects, it affects the label shown (but the plot is not redisplayed). - */ - public void setLabel(int index, String label) { - if (index < 0) index = allPlotObjects.size() + index; - allPlotObjects.get(index).label = label; - } - - /** Removes NaNs from the xValues and yValues arrays of all plot objects. */ - public void removeNaNs() { - for (PlotObject plotObj : allPlotObjects){ - if(plotObj != null && plotObj.xValues!= null && plotObj.yValues != null ){ - int oldSize = plotObj.xValues.length; - float[] xVals = new float[oldSize]; - float[] yVals = new float[oldSize]; - int newSize = 0; - for (int kk = 0; kk < oldSize; kk++) { - if (!Float.isNaN(plotObj.xValues[kk] + plotObj.yValues[kk])) { - xVals[newSize] = plotObj.xValues[kk]; - yVals[newSize] = plotObj.yValues[kk]; - newSize++; - } - } - if (newSize < oldSize) { - plotObj.xValues = new float[newSize]; - plotObj.yValues = new float[newSize]; - System.arraycopy(xVals, 0, plotObj.xValues, 0, newSize); - System.arraycopy(yVals, 0, plotObj.yValues, 0, newSize); - } - } - } - } - - /** Returns an array of the available curve types ("Line", "Bar", "Circle", etc). */ - public String[] getTypes() { - return SORTED_SHAPES; - } - - /** Sets the justification used by addLabel(), where justification - * is Plot.LEFT, Plot.CENTER or Plot.RIGHT. Default is LEFT. */ - public void setJustification(int justification) { - currentJustification = justification; - } - - /** Changes the drawing color for the next objects that will be added to the plot. - * For selecting the color of the curve passed with the constructor, - * use setColor before draw. - * The frame and labels are always drawn in black. */ - public void setColor(Color c) { - currentColor = c; - currentColor2 = null; - } - - public void setColor(String color) { - setColor(Colors.decode(color, Color.black)); - } - - /** Changes the drawing color for the next objects that will be added to the plot. - * It also sets secondary color: This is the color of the line for CONNECTED_CIRCLES, - * and the color for filling open symbols (CIRCLE, BOX, TRIANGLE). - * Set it to null or use the one-argument call setColor(color) to disable filling. - * For selecting the color of the curve passed with the constructor, - * use setColor before draw. - * The frame and labels are always drawn in black. */ - public void setColor(Color c, Color c2) { - currentColor = c; - currentColor2 = c2; - } - - /** Sets the drawing colors for the next objects that will be added to the plot. */ - public void setColor(String c1, String c2) { - setColor(Colors.decode(c1, Color.black), Colors.decode(c2, null)); - } - - /** Set the plot frame background color. */ - public void setBackgroundColor(Color c) { - pp.frame.color2 = c; - } - - /** Set the plot frame background color. */ - public void setBackgroundColor(String c) { - setBackgroundColor(Colors.decode(c,Color.white)); - } - - /** Changes the line width for the next objects that will be added to the plot. */ - public void setLineWidth(int lineWidth) { - currentLineWidth = lineWidth > 0 ? lineWidth : 0.01f; - } - - /** Changes the line width for the next objects that will be added to the plot. - * After all objects have been added, set the line width to the width desired - * for the frame around the plot (max. 3) */ - public void setLineWidth(float lineWidth) { - currentLineWidth = lineWidth > 0.01 ? lineWidth : 0.01f; - } - - /** Draws a line using the coordinate system defined by setLimits(). */ - public void drawLine(double x1, double y1, double x2, double y2) { - allPlotObjects.add(new PlotObject(x1, y1, x2, y2, currentLineWidth, 0, currentColor, PlotObject.LINE)); - } - - /** Draws a line using a normalized 0-1, 0-1 coordinate system, - * with (0,0) at the top left and (1,1) at the lower right corner. - * This is the same coordinate system used by addLabel(x,y,label). - */ - public void drawNormalizedLine(double x1, double y1, double x2, double y2) { - allPlotObjects.add(new PlotObject(x1, y1, x2, y2, currentLineWidth, 0, currentColor, PlotObject.NORMALIZED_LINE)); - } - - /** Draws a line using the coordinate system defined by setLimits(). */ - public void drawDottedLine(double x1, double y1, double x2, double y2, int step) { - allPlotObjects.add(new PlotObject(x1, y1, x2, y2, currentLineWidth, step, currentColor, PlotObject.DOTTED_LINE)); - } - - /** Sets the font size for all following addLabel() etc. operations. The currently set font when - * displaying the plot determines the font of all labels & numbers. - * After the plot has been shown, sets the font for the numbers and the legend (if present). - * If the plot is hown already, call update() thereafter to make the change visible. */ - public void setFontSize(int size) { - setFont(-1, (float)size); - } - - /** Sets the font for all following addLabel() etc. operations. The currently set font when - * displaying the plot determines the font of all labels & numbers. - * After the plot has been shown, sets the font for the numbers and the legend (if present); - * use setFont(char, Font) to set these fonts individually. - * If the plot is hown already, call update() thereafter to make the change visible. */ - public void setFont(Font font) { - if (font == null) font = defaultFont; - currentFont = font; - if (plotDrawn) { - pp.frame.setFont(font); - if (pp.legend != null) - pp.legend.setFont(font); - } - } - - /** Sets the font size and style for all following addLabel() etc. operations. This leaves - * the font name and style of the previously used fonts unchanged. The currently set font - * when displaying the plot determines the font of the numbers at the axes. - * That font also sets the default label font size, which may be overridden by - * setAxisLabelFontSize or setXLabelFont, setYLabelFont. - * After the plot has been shown, sets the font for the numbers and the legend (if present); - * use setFont(char, Font) to set these fonts individually. - * Styles are defined in the Font class, e.g. Font.PLAIN, Font.BOLD. - * Set style to -1 to leave the style unchanged. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setFont(int style, float size) { - if (size < 9) size = 9f; - if (size > 36) size = 36f; - Font previousFont = nonNullFont(pp.frame.getFont(), currentFont); - if (style < 0) style = previousFont.getStyle(); - setFont(previousFont.deriveFont(style, size)); - } - - /** Sets the x and y label font size and style. Styles are defined - * in the Font class, e.g. Font.PLAIN, Font.BOLD. - * Set style to -1 to leave the style unchanged. - * Call update() thereafter to make the change visible (if the image is shown already). */ - public void setAxisLabelFont(int style, float size) { - if (size < 9) size = 9f; - if (size > 33) size = 33f; - pp.xLabel.setFont(nonNullFont(pp.xLabel.getFont(), currentFont)); - pp.yLabel.setFont(nonNullFont(pp.yLabel.getFont(), currentFont)); - setXLabelFont(pp.xLabel.getFont().deriveFont(style < 0 ? pp.xLabel.getFont().getStyle() : style, size)); - setYLabelFont(pp.xLabel.getFont().deriveFont(style < 0 ? pp.yLabel.getFont().getStyle() : style, size)); - } - - /** Sets the xLabelFont; must not be null. If this method is not used, the last setFont - * of setFontSize call before displaying the plot determines the font, or if neither - * was called, the font size of the Plot Options is used. */ - public void setXLabelFont(Font font) { - pp.xLabel.setFont(font); - } - - /** Sets the yLabelFont; must not be null. */ - public void setYLabelFont(Font font) { - pp.yLabel.setFont(font); - } - - /** Determines whether to use antialiased text (default true) */ - public void setAntialiasedText(boolean antialiasedText) { - pp.antialiasedText = antialiasedText; - } - - /** Returns the font currently used (e.g. for the next 'addLabel') */ - public Font getCurrentFont() { - return currentFont != null ? currentFont : defaultFont; - } - - /** Returns the default font for the plot */ - public Font getDefaultFont() { - return defaultFont; - } - - /** Gets the font for xLabel ('x'), yLabel('y'), numbers ('f' for 'frame') or the legend ('l'). - * Returns null if the given PlotObject does not exist or its font is null */ - public Font getFont(char c) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - return plotObject.getFont(); - else - return null; - } - - /** Sets the font for xLabel ('x'), yLabel('y'), numbers ('f' for 'frame') or the legend ('l') */ - public void setFont(char c, Font font) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - plotObject.setFont(font); - } - - /** Gets the label String of the xLabel ('x'), yLabel('y') or the legend ('l'). - * Returns null if the given PlotObject does not exist or its label is null */ - public String getLabel(char c) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - return plotObject.label; - else - return null; - } - - /** Gets the flags of the xLabel ('x'), yLabel('y') or the legend ('l'). - * Returns -1 if the given PlotObject does not exist */ - public int getObjectFlags(char c) { - PlotObject plotObject = pp.getPlotObject(c); - if (plotObject != null) - return plotObject.flags; - else - return -1; - } - - /** Get the x coordinates of the data set passed with the constructor (if not null) - * or otherwise of the data set of the first 'addPoints'. Returns null if neither exists */ - public float[] getXValues() { - PlotObject p = getMainCurveObject(); - return p==null ? null : p.xValues; - } - - /** Get the y coordinates of the data set passed with the constructor (if not null) - * or otherwise of the data set of the first 'addPoints'. Returns null if neither exists */ - public float[] getYValues() { - PlotObject p = getMainCurveObject(); - return p==null ? null : p.yValues; - } - - /** Get the data of the n-th Plot Object containing xy data in the sequence they were added - * (Other Plot Objects such as labels, arrows, lines, shapes and hidden PlotObjects are not counted). - * The array returned has elements [0] x data, [1] y data, [2] x error bars, [3] y error bars. - * If no error bars are given, the corresponding arrays are null. - * Returns null if there is no Plot Object with xy data with this index. - * @see #getDataObjectDesignations() - **/ - public float[][] getDataObjectArrays(int index) { - int i = 0; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type != PlotObject.XY_DATA || plotObject.hasFlag(PlotObject.HIDDEN)) continue; - if (index == i) - return new float[][] {plotObject.xValues, plotObject.yValues, plotObject.xEValues, plotObject.yEValues}; - i++; - } - return null; - } - - /** Gets an array with human-readable designations of the PlotObjects (curves, labels, ...) - * in the sequence they were added (the object passed with the constructor is first, - * even though it is plotted last). Hidden PlotObjects are included. **/ - public String[] getPlotObjectDesignations() { - return getPlotObjectDesignations(-1, true); - } - - /** Gets an array with human-readable designations of the PlotObjects containing xy data - * in the sequence they were added. Other Plot Objects such as labels, arrows, lines, - * shapes and hidden PlotObjects are not counted. - * (the object passed with the constructor is first, even though it is plotted last). */ - public String[] getDataObjectDesignations() { - return getPlotObjectDesignations(PlotObject.XY_DATA, false); - } - - /** Returns the number of PlotObjects (curves, labels, ...) passed with the constructor or added by 'add' or 'draw' methods. - * Legend, frame and axes (though internally PlotObjects) are not included */ - public int getNumPlotObjects() { - return allPlotObjects.size(); - } - - /** Returns the number of PlotObjects fitting the mask. - * Legend, frame and axes (though internally PlotObjects) are not included */ - int getNumPlotObjects(int mask, boolean includeHidden) { - int nObjects = 0; - for (PlotObject plotObject : allPlotObjects) - if ((plotObject.type & mask) != 0 && (includeHidden || !plotObject.hasFlag(PlotObject.HIDDEN))) - nObjects++; - return nObjects; - } - - /** Gets an array with human-readable designations of the PlotObjects with types fitting the mask - * (i.e., 'mask' should be a bitwise or of the types desired: XY_DATA = 1, ARROWS = 2, LINE = 4, - * NORMALIZED_LINE = 8, DOTTED_LINE = 16, LABEL = 32, NORMALIZED_LABEL = 64, LEGEND = 128) */ - String[] getPlotObjectDesignations(int mask, boolean includeHidden) { - int nObjects = getNumPlotObjects(mask, includeHidden); - String[] names = new String[nObjects]; - if (names.length == 0) return names; - int iData = 1, iArrow = 1, iLine = 1, iText = 1, iBox = 1, iShape = 1; //Human readable counters of each object type - int i = 0; - for (PlotObject plotObject : allPlotObjects) { - int type = plotObject.type; - if ((type & mask) == 0 || (!includeHidden && plotObject.hasFlag(PlotObject.HIDDEN))) continue; - String label = plotObject.label; - switch (type) { - case PlotObject.XY_DATA: - names[i] = "Data Set "+iData+": "+(plotObject.label != null ? - plotObject.label : "(" + plotObject.yValues.length + " data points)"); - iData++; - break; - case PlotObject.ARROWS: - names[i] = "Arrow Set "+iArrow+" ("+ plotObject.xValues.length + ")"; - iArrow++; - break; - case PlotObject.LINE: case PlotObject.NORMALIZED_LINE: case PlotObject.DOTTED_LINE: - String detail = ""; - if (type == PlotObject.DOTTED_LINE) detail = "dotted "; - if (plotObject.x ==plotObject.xEnd) detail += "vertical"; - else if (plotObject.y ==plotObject.yEnd) detail += "horizontal"; - if (detail.length()>0) detail = " ("+detail.trim()+")"; - names[i] = "Straight Line "+iLine+detail; - iLine++; - break; - case PlotObject.LABEL: case PlotObject.NORMALIZED_LABEL: - String text = plotObject.label.replaceAll("\n"," "); - if (text.length()>45) text = text.substring(0, 40)+"..."; - names[i] = "Text "+iText+": \""+text+'"'; - iText++; - break; - case PlotObject.SHAPES: - String s = plotObject.shapeType; - String[] words = s.split(" "); - names[i] = "Shapes (" + words[0] +") " + iShape; - iShape++; - break; - } - i++; - } - return names; - } - - /** Add the i-th PlotObject (in the sequence how they were added, including hidden ones) - * from another plot to this one. PlotObjects here refers to curves, arrows, labels etc. - * (not legend, axes and frame, though implemented as PlotObjects) - * Use 'update' to update the plot thereafter. - * @return Index of the plotObject added in the sequence they were added */ - public int addObjectFromPlot(Plot plot, int i) { - PlotObject plotObject = plot.getPlotObjectDeepClone(i); - plotObject.unsetFlag(PlotObject.CONSTRUCTOR_DATA); - allPlotObjects.add(plotObject); - int index = allPlotObjects.size() - 1; - return index; - } - - /** Get the style of the i-th PlotObject (curve, label, ...) in the sequence - * they were added (including hidden ones), as String with comma delimiters: - * Main Color, Secondary Color (or "none"), Line Width [, Symbol shape for XY_DATA] [,hidden] - * PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public String getPlotObjectStyle(int i) { - return getPlotObjectStyle(allPlotObjects.get(i)); - } - - String getPlotObjectStyle(PlotObject plotObject) { - String styleString = Colors.colorToString(plotObject.color) + "," + - Colors.colorToString(plotObject.color2) + "," + - plotObject.lineWidth; - if (plotObject.type == PlotObject.XY_DATA) - styleString += ","+SHAPE_NAMES[plotObject.shape]; - if (plotObject.hasFlag(PlotObject.HIDDEN)) - styleString += ",hidden"; - return styleString; - } - - /** Get the label the i-th PlotObject (in the sequence how they were added, including hidden ones). - * Returns null if no label. PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public String getPlotObjectLabel(int i) { - return allPlotObjects.get(i).label; - } - - /** Set the label the i-th PlotObject (in the sequence how they were added, including hidden ones) - * PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public void setPlotObjectLabel(int i, String label) { - allPlotObjects.get(i).label = label; - } - - /** Sets the style of the specified PlotObject (curve, label, etc.) from a - * comma-delimited string ("color1,color2,lineWidth[,symbol][,hidden]"), - * where "color2" can be "none" and "symbol" and "hidden" are optional. - * PlotObjects here refers to curves, arrows, labels etc. - * (not legend, exes and frame, though implemented as PlotObjects) */ - public void setStyle(int index, String style) { - if (index<0 || index>=allPlotObjects.size()) - throw new IllegalArgumentException("Index out of range"); - setPlotObjectStyle(allPlotObjects.get(index), style); - } - - public void setPlotObjectStyle(int i, String styleString) { - setStyle(i, styleString); - } - - void setPlotObjectStyle(PlotObject plotObject, String styleString) { - String[] items = styleString.split(","); - int nItems = items.length; - if (items[nItems-1].indexOf("hidden") >= 0) { - plotObject.setFlag(PlotObject.HIDDEN); - nItems = items.length - 1; - } else - plotObject.unsetFlag(PlotObject.HIDDEN); - plotObject.color = Colors.decode(items[0].trim(), plotObject.color); - plotObject.color2 = Colors.decode(items[1].trim(), null); - float lineWidth = plotObject.lineWidth; - if (items.length >= 3) try { - plotObject.lineWidth = Float.parseFloat(items[2].trim()); - } catch (NumberFormatException e) {}; - if (items.length >= 4 && plotObject.shape!=CUSTOM) - plotObject.shape = toShape(items[3].trim()); - updateImage(); - return; - } - - /** Returns the index of the first plot object with x,y data (points, line) or arrows - * with all data equal to those given. Returns or -1 is no such plot object exists. - * The array 'values' should contain the x, y, x error bar, yerror bar data. The 'values' array may have any size; - * only the data given are compared (e.g. for an array with length 2, there is no check for erro bars). - * Used when adding data from a table not to suggest the same data twice. */ - public int getPlotObjectIndex(float[][] values) { - return getPlotObjectIndex(PlotObject.XY_DATA|PlotObject.ARROWS, values); - } - - /** Returns the index of the first plot object fitting the type mask and with all data equal to those given. - * ('mask' should be a bitwise or of the types desired) - * Returns or -1 is no such plot object exists. - * The array 'values' should contain the x, y, x error bar, yerror bar data. The 'values' array may have any size; - * only the data given are compared (e.g. for an array with length 2, there is no check for erro bars). - * Used when adding data from a table not to suggest the same data twice. */ - int getPlotObjectIndex(int typeMask, float[][] values) { - for (int i=0; i(allPlotObjects.size()); - copyPlotObjectsVector(allPlotObjects, allPlotObjectsSnapshot); - } - - /** Restores the plot contents (not including axis formats etc) from the snapshot - * previously created by savePlotObjects(). See also killPlotObjectsSnapshot - * Use 'update' to update the plot thereafter. */ - public void restorePlotObjects() { - if (allPlotObjectsSnapshot != null) - copyPlotObjectsVector(allPlotObjectsSnapshot, allPlotObjects); - } - - /** Deletes the snapshot of the plot contents to make space */ - public void killPlotObjectsSnapshot() { - allPlotObjectsSnapshot = null; - } - - /** Creates a snapshot of the plot properties (formatting, range etc., not PlotObjects such as data and corresponding curves etc.), - * for later undo by restorePlotProperties. See also killPlotPropertiesSnapshot */ - public void savePlotPlotProperties() { - pp.rangeMinMax = currentMinMax; - ppSnapshot = pp.deepClone(); - } - - /** Restores the plot properties (formatting, range etc., not PlotObjects such as data and corresponding curves etc.) - * from a snapshot previously created by savePlotPlotProperties. See also killPlotPropertiesSnapshot. - * Use 'update' to update the plot thereafter. */ - public void restorePlotProperties() { - pp = ppSnapshot.deepClone(); - System.arraycopy(pp.rangeMinMax, 0, currentMinMax, 0, Math.min(pp.rangeMinMax.length, currentMinMax.length)); - } - - /** Deletes the snapshot of the plot properties to make space */ - public void killPlotPropertiesSnapshot() { - ppSnapshot = null; - } - - private void copyPlotObjectsVector(Vector src, Vectordest) { - if (dest.size() > 0) dest.removeAllElements(); - for (PlotObject plotObject : src) - dest.add(plotObject.deepClone()); - } - - PlotObject getPlotObjectDeepClone(int i) { - return allPlotObjects.get(i).deepClone(); - } - - /** Sets the plot range to the initial value determined from minima&maxima or given by setLimits. - * Updates the image if existing and updateImg is true */ - public void setLimitsToDefaults(boolean updateImg) { - saveMinMax(); - System.arraycopy(defaultMinMax, 0, currentMinMax, 0, defaultMinMax.length); - if (plotDrawn && updateImg) updateImage(); - } - - /** Sets the plot range to encompass all data. Updates the image if existing and updateImg is true. */ - public void setLimitsToFit(boolean updateImg) { - saveMinMax(); - currentMinMax = getMinAndMax(true, ALL_AXES_RANGE); - if (Double.isNaN(defaultMinMax[0]) && Double.isNaN(defaultMinMax[2])) //no range at all so far - System.arraycopy(currentMinMax, 0, defaultMinMax, 0, Math.min(currentMinMax.length, defaultMinMax.length)); - - enlargeRange(currentMinMax); //avoid points exactly at the border - //System.arraycopy(currentMinMax, 0, defaultMinMax, 0, currentMinMax.length); - if (plotDrawn && updateImg) updateImage(); - } - - /** reverts plot range to previous values and updates the image */ - public void setPreviousMinMax() { - if (Double.isNaN(savedMinMax[0])) return; //no saved values yet - double[] swap = new double[currentMinMax.length]; - System.arraycopy(currentMinMax, 0, swap, 0, currentMinMax.length); - System.arraycopy(savedMinMax, 0, currentMinMax, 0, currentMinMax.length); - System.arraycopy(swap, 0, savedMinMax, 0, currentMinMax.length); - updateImage(); - } - - /** Draws the plot (if not done before) in an ImageProcessor and returns the ImageProcessor with the plot. */ - public ImageProcessor getProcessor() { - draw(); - return ip; - } - - /** Returns the plot as an ImagePlus. - * If an ImagePlus for this plot already exists, displays the plot in that ImagePlus and returns it. */ - public ImagePlus getImagePlus() { - if (stack != null) { - if (imp != null) - return imp; - else { - imp = new ImagePlus(title, stack); - adjustCalibration(imp.getCalibration()); - return imp; - } - } - if (plotDrawn) - updateImage(); - else - draw(); - if (imp != null) { - if (imp.getProcessor() != ip) - imp.setProcessor(ip); - return imp; - } else { - ImagePlus imp = new ImagePlus(title, ip); - setImagePlus(imp); - return imp; - } - } - - /** Sets the ImagePlus where the plot will be displayed. If the ImagePlus is not - * known otherwise (e.g. from getImagePlus), this is needed for changes such as - * zooming in to work correctly. It also sets the calibration of the ImagePlus. - * The ImagePlus is not displayed or updated unless its ImageProcessor is - * no that of the current Plot (then it gets this ImageProcessor). - * Does nothing if imp is unchanged and has the ImageProcessor of this plot. - * 'imp' may be null to disconnect the plot from its ImagePlus. - * Does nothing for Plot Stacks. */ - public void setImagePlus(ImagePlus imp) { - if (imp != null && imp == this.imp && imp.getProcessor() == ip) - return; - if (stack != null) - return; - if (this.imp != null) - this.imp.setProperty(PROPERTY_KEY, null); - this.imp = imp; - if (imp != null) { - imp.setIgnoreGlobalCalibration(true); - adjustCalibration(imp.getCalibration()); - imp.setProperty(PROPERTY_KEY, this); - if (ip != null && imp.getProcessor() != ip) - imp.setProcessor(ip); - } - } - - /** Adjusts a Calibration object to fit the current axes. - * For log axes, the calibration refers to the base-10 logarithm of the value */ - public void adjustCalibration(Calibration cal) { - if (xMin == xMax) //tiff images can't handle infinity in scale, see TiffEncoder.writeScale - xScale = 1e6; - if (yMin == yMax) - yScale = 1e6; - cal.xOrigin = xBasePxl-xMin*xScale; - cal.pixelWidth = 1.0/Math.abs(xScale); //Calibration must not have negative pixel size - cal.yOrigin = yBasePxl+yMin*yScale; - cal.pixelHeight = 1.0/Math.abs(yScale); - cal.setInvertY(yScale >= 0); - cal.setXUnit(" "); // avoid 'pixels' for scaled units - if (xMin == xMax) - xScale = Double.POSITIVE_INFINITY; - if (yMin == yMax) - yScale = Double.POSITIVE_INFINITY; - } - - /** Displays the plot in a PlotWindow. - * Plot stacks are shown in a StackWindow, not in a PlotWindow; - * in this case the return value is null (use getImagePlus().getWindow() instead). - * Also returns null in BatchMode. Note that the PlotWindow might get closed - * immediately if its 'listValues' and 'autoClose' flags are set. - * @see #update() - */ - public PlotWindow show() { - PlotVirtualStack stack = getStack(); - if (stack!=null) { - getImagePlus().show(); - return null; - } - if ((IJ.macroRunning() && IJ.getInstance()==null) || Interpreter.isBatchMode()) { - imp = getImagePlus(); - imp.setPlot(this); - WindowManager.setTempCurrentImage(imp); - if (getMainCurveObject() != null) { - imp.setProperty("XValues", getXValues()); // Allows values to be retrieved by - imp.setProperty("YValues", getYValues()); // by Plot.getValues() macro function - } - Interpreter.addBatchModeImage(imp); - return null; - } - if (imp != null) { - Window win = imp.getWindow(); - if (win instanceof PlotWindow && win.isVisible()) { - updateImage(); // show in existing window - return (PlotWindow)win; - } else - setImagePlus(null); - } - PlotWindow pw = new PlotWindow(this); //note: this may set imp to null if pw has listValues and autoClose are set - if (IJ.isMacro() && imp!=null) // wait for plot to be displayed - IJ.selectWindow(imp.getID()); - return pw; - } - - /** - * Appends the current plot to a virtual stack and resets allPlotObjects - * for next slice - * N. Vischer - */ - public void addToStack() { - if (stack==null) - stack = new PlotVirtualStack(getSize().width,getSize().height); - draw(); - stack.addPlot(this); - IJ.showStatus("addToPlotStack: "+stack.size()); - allPlotObjects.clear(); - } - - /** Alias for addToStack(). */ - public void appendToStack() { - addToStack(); - } - - /** Returns the virtual stack created by addToStack(). */ - public PlotVirtualStack getStack() { - IJ.showStatus(""); - return stack; - } - - /** Draws the plot specified for the first time. Does nothing if the plot has been drawn already. - * Call getProcessor to retrieve the ImageProcessor with it. - * Does no action with respect to the ImagePlus (if any) */ - public void draw() { - //IJ.log("draw(); plotDrawn="+plotDrawn); - if (plotDrawn) return; - getInitialMinAndMax(); - pp.frame.setFont(nonNullFont(pp.frame.getFont(), currentFont)); //make sure we have a number font for calculating the margins - getBlankProcessor(); - drawContents(ip); - } - - /** Freezes or unfreezes the plot. In the frozen state, the plot cannot be resized or updated, - * and the Plot class does no modifications to the ImageProcessor. - * Changes are recorded nevertheless and become effective with setFrozen(false). */ - public void setFrozen(boolean frozen) { - pp.isFrozen = frozen; - if (!pp.isFrozen) { // unfreeze operations ... - if (imp != null && ip != null) { - ImageCanvas ic = imp.getCanvas(); - if (ic instanceof PlotCanvas) { - ((PlotCanvas)ic).resetMagnification(); - imp.setTitle(imp.getTitle()); //update magnification in title - } - Undo.setup(Undo.TRANSFORM, imp); - } - updateImage(); - ImageWindow win = imp == null ? null : imp.getWindow(); - if (win != null) win.updateImage(imp); //show any changes made during the frozen state - } - } - - public boolean isFrozen() { - return pp.isFrozen; - } - - /** Draws the plot again, ignored if the plot has not been drawn before or the plot is frozen. */ - public void update() { - updateImage(); - } - - /** Draws the plot again, ignored if the plot has not been drawn before or the plot is frozen. - * If the ImagePlus exist, updates it and its calibration. */ - public void updateImage() { - if (!plotDrawn || pp.isFrozen) return; - getBlankProcessor(); - drawContents(ip); - if (imp == null || stack != null) return; - adjustCalibration(imp.getCalibration()); - imp.updateAndDraw(); - if (ip != imp.getProcessor()) - imp.setProcessor(ip); - } - - /** Returns the rectangle where the data are plotted. - * This rectangle includes the black outline frame at the top and left, but not at the bottom - * and right (when the frame is plotted with 1 pxl width). - * The image scale is its width or height in pixels divided by the data range in x or y. */ - public Rectangle getDrawingFrame() { - if (frame == null) - getBlankProcessor(); //setup frame if not done yet - return new Rectangle(frame.x, frame.y, frameWidth, frameHeight); - } - - /** Creates a new high-resolution plot by scaling it and displays that plot if showIt is true. - * title may be null, then a default title is used. */ - public ImagePlus makeHighResolution(String title, float scale, boolean antialiasedText, boolean showIt) { - Plot hiresPlot = null; - try { - hiresPlot = (Plot)clone(); //shallow clone, thus arrays&objects are not cloned, but they will be used only now - } catch (Exception e) {return null;} - hiresPlot.ip = null; - hiresPlot.imp = null; - hiresPlot.pp = pp.clone(); - if (!plotDrawn) hiresPlot.getInitialMinAndMax(); - hiresPlot.setScale(scale); - hiresPlot.setAntialiasedText(antialiasedText); - hiresPlot.defaultMinMax = currentMinMax.clone(); - ImageProcessor hiresIp = hiresPlot.getProcessor(); - if (title == null || title.length() == 0) - title = getTitle()+"_HiRes"; - title = WindowManager.makeUniqueName(title); - ImagePlus hiresImp = new ImagePlus(title, hiresIp); - Calibration cal = hiresImp.getCalibration(); - hiresPlot.adjustCalibration(cal); - if (showIt) { - hiresImp.setIgnoreGlobalCalibration(true); - hiresImp.show(); - } - hiresPlot.dispose(); //after drawing, we don't need the plot of the high-resolution image any more - return hiresImp; - } - - /** Releases the ImageProcessor and ImagePlus associated with the plot. - * May help garbage collection because some garbage collectors - * are said to be inefficient with circular references. */ - public void dispose() { - if (imp != null) - imp.setProperty(PROPERTY_KEY, null); - imp = null; - ip = null; - } - - /** Converts pixels to calibrated coordinates. In contrast to the image calibration, also - * works with log axes and inverted x axes */ - public double descaleX(int x) { - if (xMin == xMax) return xMin; - double xv = (x-xBasePxl)/xScale + xMin; - if (logXAxis) xv = Math.pow(10, xv); - return xv; - } - - /** Converts pixels to calibrated coordinates. In contrast to the image calibration, also - * works with log axes */ - public double descaleY(int y) { - if (yMin == yMax) return yMin; - double yv = (yBasePxl-y)/yScale +yMin; - if (logYAxis) yv = Math.pow(10, yv); - return yv; - } - - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log x axis and inverted x axis */ - public double scaleXtoPxl(double x) { - if (xMin == xMax) { - if (x==xMin) return xBasePxl; - else return x>xMin ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; - } - if (logXAxis) - return xBasePxl+(Math.log10(x)-xMin)*xScale; - else - return xBasePxl+(x-xMin)*xScale; - } - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log y axis */ - public double scaleYtoPxl(double y) { - if (yMin == yMax) { - if (y==xMin) return yBasePxl; - else return y>yMin ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY; - } - if (logYAxis) - return yBasePxl-(Math.log10(y)-yMin)*yScale; - else - return yBasePxl-(y-yMin)*yScale; - } - - /** Converts calibrated coordinates to integer pixel coordinates. */ - private int scaleX(double x) { - double xPxl = scaleXtoPxl(x); - return pxlToInt(xPxl); - } - - /** Converts calibrated coordinates to integer pixel coordinates. */ - private int scaleY(double y) { - double yPxl = scaleYtoPxl(y); - return pxlToInt(yPxl); - } - - /** Converts a double-precision pixel coordinate value 'v' to integer, - * with overflow handling: Limits are +/-Integer.MAX_VALUE/2. - * This ensures that the difference between two points is in the range - * that can be handled by ImageProcessor.moveTo. - * NaN values are converted to -Integer.MAX_VALUE (negative). - **/ - private int pxlToInt(double v) { - if (Double.isNaN(v)) - return -Integer.MAX_VALUE; - else if (v > -Integer.MAX_VALUE/2 && v < Integer.MAX_VALUE/2) - return (int)Math.round(v); - else - return v > 0 ? Integer.MAX_VALUE/2 : -Integer.MAX_VALUE/2; - } - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log axes and inverted x axes. Returns a large number instead NaN for log x axis and zero or negative x */ - private int scaleXWithOverflow(double x) { - if (!logXAxis || x>0) - return scaleX(x); - else - return xScale > 0 ? -1000000 : 1000000; - } - - /** Converts calibrated coordinates to pixel coordinates. In contrast to the image calibration, also - * works with log axes and inverted x axes. Returns a large number instead NaN for log y axis and zero or negative y */ - private int scaleYWithOverflow(double y) { - if (!logYAxis || y>0) - return scaleY(y); - else - return yScale > 0 ? 1000000 : -1000000; - } - - /** Scales a value of the original plot for a high-resolution plot. Returns an integer number of pixels >=1 */ - int sc(float length) { - int pixels = (int)(length*scale + 0.5); - if (pixels < 1) pixels = 1; - return pixels; - } - - /** Scales a font of the original plot for a high-resolution plot. */ - Font scFont(Font font) { - float size = font.getSize2D(); - return scale==1 ? font : font.deriveFont(size*scale); - } - - /** Returns whether the plot requires color (not grayscale) */ - boolean isColored() { - for (PlotObject plotObject : allPlotObjects) - if (isColored(plotObject.color) || isColored(plotObject.color2)) - return true; - for (PlotObject plotObject : pp.getAllPlotObjects()) - if (plotObject != null && (isColored(plotObject.color) || isColored(plotObject.color2))) - return true; - return false; - } - - /** Whether a color is non-grayscale, which requires color (not grayscale) for the plot */ - boolean isColored(Color c) { - if (c == null) return false; - return c.getRed() != c.getGreen() || c.getGreen() != c.getBlue(); - } - - /** Draws the plot contents (all PlotObjects and the frame and legend), without axes etc. */ - void drawContents(ImageProcessor ip) { - makeRangeGetSteps(); - ip.setColor(Color.black); - ip.setLineWidth(sc(1)); - float lineWidth = 1; - Color color = Color.black; - Font font = defaultFont; - - // draw all the plot objects in the sequence they were added, except for the one of the constructor - for (PlotObject plotObject : allPlotObjects) - if (!plotObject.hasFlag(PlotObject.CONSTRUCTOR_DATA)) { - //properties lineWidth, Font, Color set for one object remain for the next object unless changed - if (plotObject.lineWidth > 0) - lineWidth = plotObject.lineWidth; - else - plotObject.lineWidth = lineWidth; - if (plotObject.color != null) - color = plotObject.color; - else - plotObject.color = color; - if (plotObject.getFont() != null) - font = plotObject.getFont(); - else - plotObject.setFont(font); - //IJ.log("type="+plotObject.type+" color="+plotObject.color); - drawPlotObject(plotObject, ip); - } - - // draw the line passed with the constructor last, using the settings present when calling 'draw' - if (allPlotObjects.size()>0 && allPlotObjects.get(0).hasFlag(PlotObject.CONSTRUCTOR_DATA)) { - PlotObject mainPlotObject = allPlotObjects.get(0); - if (mainPlotObject.lineWidth == 0) - mainPlotObject.lineWidth = currentLineWidth == 0 ? 1 : currentLineWidth; - lineWidth = mainPlotObject.lineWidth; - if (mainPlotObject.color == null) - mainPlotObject.color = currentColor == null ? Color.black : currentColor; - drawPlotObject(mainPlotObject, ip); - } else { - if (currentLineWidth > 0) lineWidth = currentLineWidth; //linewidth when drawing determines frame linewidth - } - - // finally draw the frame & legend - if (!plotDrawn && pp.frame.lineWidth==DEFAULT_FRAME_LINE_WIDTH) { //when modifying PlotObjects styles later, don't change the frame line width any more - pp.frame.lineWidth = lineWidth; - if (pp.frame.lineWidth == 0) pp.frame.lineWidth = 1; - if (pp.frame.lineWidth > 3) pp.frame.lineWidth = 3; - } - ip.setLineWidth(sc(pp.frame.lineWidth)); - ip.setColor(pp.frame.color); - int x2 = frame.x + frame.width - 1; - int y2 = frame.y + frame.height - 1; - ip.moveTo(frame.x, frame.y); // draw the frame. Can't use ip.drawRect because it is inconsistent for different lineWidths - ip.lineTo(x2, frame.y); - ip.lineTo(x2, y2); - ip.lineTo(frame.x, y2); - ip.lineTo(frame.x, frame.y); - if (pp.legend != null && (pp.legend.flags & LEGEND_POSITION_MASK) != 0) - drawPlotObject(pp.legend, ip); - - plotDrawn = true; - } - - /** Creates the processor if not existing, clears the background and prepares - * it for plotting. Also called by the PlotWindow class to prepare the window. */ - ImageProcessor getBlankProcessor() { - makeMarginValues(); - //IJ.log("Plot.getBlankPr preferredH="+preferredPlotHeight+" pp.h="+pp.height); - if (pp.width <= 0 || pp.height <= 0) { - pp.width = sc(preferredPlotWidth) + leftMargin + rightMargin; - pp.height = sc(preferredPlotHeight) + topMargin + bottomMargin; - } - frameWidth = pp.width - (leftMargin + rightMargin); - frameHeight = pp.height - (topMargin + bottomMargin); - boolean isColored = isColored(); //color, not grayscale required? - if (ip == null || pp.width != ip.getWidth() || pp.height != ip.getHeight() || (isColored != (ip instanceof ColorProcessor))) { - if (isColored) { - ip = new ColorProcessor(pp.width, pp.height); - } else { - ip = new ByteProcessor(pp.width, pp.height); - invertedLut = Prefs.useInvertingLut && !Interpreter.isBatchMode() && IJ.getInstance()!=null; - if (invertedLut) ip.invertLut(); - } - if (imp != null && stack == null) - imp.setProcessor(ip); - } - if (ip instanceof ColorProcessor) - Arrays.fill((int[])(ip.getPixels()), 0xffffff); - else - Arrays.fill((byte[])(ip.getPixels()), invertedLut ? (byte)0 : (byte)0xff); - - ip.setFont(scFont(defaultFont)); - ip.setLineWidth(sc(1)); - ip.setAntialiasedText(pp.antialiasedText); - frame = new Rectangle(leftMargin, topMargin, frameWidth+1, frameHeight+1); - if (pp.frame.color2 != null) { //background color - ip.setColor(pp.frame.color2); - ip.setRoi(frame); - ip.fill(); - ip.resetRoi(); - } - ip.setColor(Color.black); - return ip; - } - - /** Calculates the margin sizes and sets the class variables accordingly */ - void makeMarginValues() { - Font font = nonNullFont(pp.frame.getFont(), currentFont); - float marginScale = 0.1f + 0.9f*font.getSize2D()/12f; - if (marginScale < 0.7f) marginScale = 0.7f; - if (marginScale > 2f) marginScale = 2f; - int addHspace = (int)Tools.getNumberFromList(pp.frame.options, "addhspace="); //user-defined extra space - int addVspace = (int)Tools.getNumberFromList(pp.frame.options, "addvspace="); - leftMargin = sc(LEFT_MARGIN*marginScale + addHspace); - rightMargin = sc(RIGHT_MARGIN*marginScale + addHspace); - topMargin = sc(TOP_MARGIN*marginScale + addVspace); - bottomMargin = sc(BOTTOM_MARGIN*marginScale + 2 + addVspace); - if(pp != null && pp.xLabel != null && pp.xLabel.getFont() != null){ - float numberSize = font.getSize2D(); - float labelSize = pp.xLabel.getFont().getSize2D(); - float extraHeight = 1.5f *(labelSize - numberSize); - if(extraHeight > 0){ - bottomMargin += sc(extraHeight); - leftMargin += sc(extraHeight); - } - } - } - - /** Calculate the actual range, major step interval and set variables for data <-> pixels scaling */ - double[] makeRangeGetSteps() { - steps = new double[2]; - logXAxis = hasFlag(X_LOG_NUMBERS); - logYAxis = hasFlag(Y_LOG_NUMBERS); - - for (int i=0; i MIN_LOG_RATIO || 1./rangeRatio > MIN_LOG_RATIO) || - !(currentMinMax[i] > 10*Float.MIN_VALUE) || !(currentMinMax[i+1] > 10*Float.MIN_VALUE)) - logAxis = false; - } - //for log axes, temporarily work on the logarithm - if (logAxis) { - currentMinMax[i] = Math.log10(currentMinMax[i]); - currentMinMax[i+1] = Math.log10(currentMinMax[i+1]); - } - // calculate grid or major tick interval - if ((i==0 && !simpleXAxis()) || (i==2 && !simpleYAxis())) { - int minGridspacing = i==0 ? MIN_X_GRIDSPACING : MIN_Y_GRIDSPACING; - int frameSize = i==0 ? frameWidth : frameHeight; - double step = Tools.getNumberFromList(pp.frame.options, i==0 ? "xinterval=" : "yinterval="); //user-defined interval - if (!Double.isNaN(step)) { - int nSteps = (int)(Math.floor(currentMinMax[i+1]/step+1e-10) - Math.ceil(currentMinMax[i]/step-1e-10)); - if (nSteps < 1) step = Double.NaN; //user-suppied interval too large, less than two numbers would be shown - if ((i==0 && nSteps*sc(minGridspacing)*0.5 > frameSize) || i!=0 && nSteps*sc(pp.frame.getFont().getSize()) > frameSize) - step = Double.NaN; //user-suppied interval too small, too many numbers would be shown - } - if (Double.isNaN(step)) { //automatic interval - step = Math.abs((currentMinMax[i+1] - currentMinMax[i]) * - Math.max(1.0/maxIntervals, (float)sc(minGridspacing)/frameSize+(maxIntervals>12 ? 0.02 : 0.06))); //the smallest allowable step - step = niceNumber(step); - } - if (logAxis && step < 1) - step = 1; - steps[i/2] = step; - //modify limits to grid or minor ticks if desired - boolean force2grid = hasFlag(i==0 ? X_FORCE2GRID : Y_FORCE2GRID) && !ignoreForce2Grid; - if (force2grid) { - int i1 = (int)Math.floor(Math.min(currentMinMax[i],currentMinMax[i+1])/step+1.e-10); - int i2 = (int)Math.ceil (Math.max(currentMinMax[i],currentMinMax[i+1])/step-1.e-10); - if (currentMinMax[i+1] > currentMinMax[i]) { // care about inverted axes with max= 0.999) { //don't snap on log axis if minor ticks are not full decades - // currentMinMax[i] = stepForSnap * Math.round(currentMinMax[i]/stepForSnap); - // currentMinMax[i+1] = stepForSnap * Math.round(currentMinMax[i+1]/stepForSnap); - // } - } - } - if (i==0) { - xMin = currentMinMax[i]; - xMax = currentMinMax[i+1]; - logXAxis = logAxis; - } else { - yMin = currentMinMax[i]; - yMax = currentMinMax[i+1]; - logYAxis = logAxis; - } - if (logAxis) { - currentMinMax[i] = Math.pow(10, currentMinMax[i]); - currentMinMax[i+1] = Math.pow(10, currentMinMax[i+1]); - } - } - //snapToMinorGrid = false; - ignoreForce2Grid = false; - - // calculate what we need to convert the data to screen pixels - xBasePxl = leftMargin; - yBasePxl = topMargin + frameHeight; - xScale = frameWidth/(xMax-xMin); - if (!(xMax-xMin!=0.0)) //if range==0 (all data the same), or NaN shift zero level so one can see the curve - xBasePxl += sc(10); - yScale = frameHeight/(yMax-yMin); - if (!(yMax-yMin!=0.0)) - yBasePxl -= sc(10); - //IJ.log("x,yScale="+(float)xScale+","+(float)yScale+" xMin,max="+(float)xMin+","+(float)xMax+" yMin.max="+(float)yMin+","+(float)yMax); - - drawAxesTicksGridNumbers(steps); - return steps; - } - - public void redrawGrid(){ - if (ip != null) { - ip.setColor(Color.black); - drawAxesTicksGridNumbers(steps); - ip.setColor(Color.black); - } - } - - /** Gets the initial plot limits (i.e., x&y ranges). For compatibility with previous versions of ImageJ, - * only the first PlotObject (with numeric data) is used to determine the limits. */ - void getInitialMinAndMax() { - int axisRangeFlags = 0; - if (Double.isNaN(defaultMinMax[0])) axisRangeFlags |= X_RANGE; - if (Double.isNaN(defaultMinMax[2])) axisRangeFlags |= Y_RANGE; - if (axisRangeFlags != 0) { - defaultMinMax = getMinAndMax(false, axisRangeFlags); - enlargeRange(defaultMinMax); - } - setLimitsToDefaults(false); //use the range values to start with, but don't draw yet - } - - /** Gets the minimum and maximum values from the first XY_DATA or ARROWS plotObject or all such plotObjects; - * axisRangeFlags determine for which axis to calculate the min&max (X_RANGE for x axis, Y_RANGE for y axis); - * for the other axes the limit is taken from defaultMinMax - * Array elements returned are xMin, xMax, yMin, yMax. Also sets enlargeRange to tell which limits should be enlarged - * beyond the minimum or maximum of the data */ - double[] getMinAndMax(boolean allObjects, int axisRangeFlags) { - boolean invertedXAxis = currentMinMax[1] < currentMinMax[0]; - boolean invertedYAxis = currentMinMax[3] < currentMinMax[2]; - double xSign = invertedXAxis ? -1 : 1; - double ySign = invertedYAxis ? -1 : 1; - double[] allMinMax = new double[]{xSign*Double.MAX_VALUE, -xSign*Double.MAX_VALUE, ySign*Double.MAX_VALUE, -ySign*Double.MAX_VALUE}; - for (int i=0; i>i/2) & 1)==0) //keep default min & max for this axis - allMinMax[i] = defaultMinMax[i]; - enlargeRange = new int[allMinMax.length]; - for (PlotObject plotObject : allPlotObjects) { - if ((plotObject.type == PlotObject.XY_DATA || plotObject.type == PlotObject.ARROWS) && !plotObject.hasFlag(PlotObject.HIDDEN)) { - getMinAndMax(allMinMax, enlargeRange, plotObject, axisRangeFlags); - if (!allObjects) break; - } - } - if ((axisRangeFlags & X_RANGE) != 0) { - String[] xCats = labelsInBraces('x'); // if we have categories at the axis, make some space for this text - if (xCats != null) { - allMinMax[0] = Math.min(allMinMax[0], -0.5); - allMinMax[1] = Math.min(allMinMax[1], xCats.length+0.5); - } - } - if ((axisRangeFlags & Y_RANGE) != 0) { - String[] yCats = labelsInBraces('y'); - if (yCats != null) { - allMinMax[2] = Math.min(allMinMax[2], -0.5); - allMinMax[3] = Math.min(allMinMax[3], yCats.length+0.5); - } - } - if (allMinMax[0]==Double.MAX_VALUE && allMinMax[1]==-Double.MAX_VALUE) { // no x values at all? keep previous - allMinMax[0] = defaultMinMax[0]; - allMinMax[1] = defaultMinMax[1]; - } - if (allMinMax[2]==Double.MAX_VALUE && allMinMax[3]==-Double.MAX_VALUE) { // no y values at all? keep previous - allMinMax[2] = defaultMinMax[2]; - allMinMax[3] = defaultMinMax[3]; - } - return allMinMax; - } - - /** Enlarges the current minimum and maximum ranges to include the data range of the last plotObject added, - * if it is an XY_DATA or ARROWS plotObject. - * Does not set the new limits as default, does not redraw the plot. */ - void fitRangeToLastPlotObject() { - if (allPlotObjects.size() < 1) return; - PlotObject plotObject = allPlotObjects.lastElement(); - if (Double.isNaN(currentMinMax[0]) || Double.isNaN(currentMinMax[2])) { // no range determined yet? - setLimitsToFit(false); - } else { //we have min&max already, just extend the range if necessary - enlargeRange = new int[currentMinMax.length]; - getMinAndMax(currentMinMax, enlargeRange, plotObject, ALL_AXES_RANGE); - enlargeRange(currentMinMax); - } - } - - /** Gets the minimum and maximum values from an XY_DATA or ARROWS plotObject; - * axisRangeFlags determine for which axis (X_RANGE for x axis, Y_RANGE for y axis) - * The minimum modifies allMinAndMax[0] (x), allMinAndMax[2] (y); the maximum modifies [1], [3]. - * If allMinAndMax values are modified, the corresponding enlargeRange array elements are also set */ - void getMinAndMax(double[] allMinAndMax, int[] enlargeRange, PlotObject plotObject, int axisRangeFlags) { - boolean invertedXAxis = currentMinMax[1] < currentMinMax[0]; - boolean invertedYAxis = currentMinMax[3] < currentMinMax[2]; - if (plotObject.type == PlotObject.XY_DATA) { - if ((axisRangeFlags & X_RANGE) != 0) { - int suggestedEnlarge = 0; - if (!(plotObject.shape == LINE || plotObject.shape == FILLED) || plotObject.yEValues != null) - suggestedEnlarge = ALWAYS_ENLARGE; //enlarge to make space at the obrders (we don't try to keep x=0 at the frame border) - getMinAndMax(allMinAndMax, enlargeRange, suggestedEnlarge, 0, plotObject.xValues, plotObject.xEValues, invertedXAxis); - if ((plotObject.shape == BAR || plotObject.shape == SEPARATED_BAR)&& plotObject.xValues.length > 1) { - int n = plotObject.xValues.length; - allMinAndMax[0] -= 0.5 * Math.abs(plotObject.xValues[1] - plotObject.xValues[0]); - allMinAndMax[1] += 0.5 * Math.abs(plotObject.xValues[n - 1] - plotObject.xValues[n - 2]); - } - } - if ((axisRangeFlags & Y_RANGE) != 0) { - int suggestedEnlarge = 0; - if (plotObject.shape==DOT || plotObject.xEValues != null) //these can't be seen if merging with the frame - suggestedEnlarge = ALWAYS_ENLARGE; - else if (!(plotObject.shape == LINE || plotObject.shape == FILLED)) - suggestedEnlarge = USUALLY_ENLARGE; - getMinAndMax(allMinAndMax, enlargeRange, suggestedEnlarge, 2, plotObject.yValues, plotObject.yEValues, invertedYAxis); - if ((plotObject.shape == BAR || plotObject.shape == SEPARATED_BAR) && - (allMinAndMax[2] > 0 && allMinAndMax[3]/allMinAndMax[2] >= 2) && !logYAxis) - allMinAndMax[2] = 0; // for bar plots, y min = 0 unless values differ less than a factor of 2 - } - } else if (plotObject.type == PlotObject.ARROWS) { - if ((axisRangeFlags & X_RANGE) != 0) { - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 0, plotObject.xValues, null, invertedXAxis); - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 0, plotObject.xEValues, null, invertedXAxis); - } - if ((axisRangeFlags & Y_RANGE) != 0) { - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 2, plotObject.yValues, null, invertedYAxis); - getMinAndMax(allMinAndMax, enlargeRange, ALWAYS_ENLARGE, 2, plotObject.yEValues, null, invertedYAxis); - } - } - } - - /** Gets the minimum and maximum values for a dataset (one direction, x or y), - * taking error bars (if not null) into account. - * The minimum modifies allMinAndMax[axisIndex] the maximum modifies allMinAndMax[axisIndex+1]. - * Also cares about whether the range should be enlarged to avoid hiding markers at the borders: - * suggestedEnlarge is 0 for lines or a suggestion for the data type; if the allMinAndMax is - * range is extended, the corresponding enlargeRange item is set accordingly */ - void getMinAndMax(double[] allMinAndMax, int[] enlargeRange, int suggestedEnlarge, - int axisIndex, float[] data, float[] errorBars, boolean invertedAxis) { - int nMinEqual = 0, nMaxEqual = 0; - int minIndex = invertedAxis ? axisIndex+1 : axisIndex; // index of 'min' value in allMinAndMax, enlargeRange - int maxIndex = invertedAxis ? axisIndex : axisIndex+1; - for (int i=0; i0 && i allMinAndMax[maxIndex] && !Double.isInfinite(v1)) { - allMinAndMax[maxIndex] = v2; - nMaxEqual = 1; - enlargeRange[maxIndex] = suggestedEnlarge; - if (suggestedEnlarge == 0 && ((i>0 && i10%) at min or max? Add extra space at borders ('usually', i.e. unless limit is zero) - if (enlargeRange[minIndex] == 0 && nMinEqual > 2 && nMinEqual*10 > data.length) - enlargeRange[minIndex] = USUALLY_ENLARGE; - if (enlargeRange[maxIndex] == 0 && nMaxEqual > 2 && nMaxEqual*10 > data.length) - enlargeRange[maxIndex] = USUALLY_ENLARGE; - //all data at min or max? Always add space to avoid hiding the line behind the frame - if (nMinEqual == data.length) - enlargeRange[minIndex] = ALWAYS_ENLARGE; - if (nMaxEqual == data.length) - enlargeRange[maxIndex] = ALWAYS_ENLARGE; - //same min or max as for current data set found already previously, but not asking yet for added space at borders? - if (nMinEqual>0 && enlargeRange[minIndex]0 && enlargeRange[maxIndex] frame.x && x < frame.x + frame.width; - boolean insideY = y > frame.y && y < frame.y + frame.height; - if (!insideX && !insideY) { - insideX = true; - insideY = true; - x = frame.x + frame.width / 2; - y = frame.y + frame.height / 2; - } - int leftPart = x - frame.x; - int rightPart = frame.x + frame.width - x; - int highPart = y - frame.y; - int lowPart = frame.y + frame.height - y; - - if (insideX) { - currentMinMax[0] = descaleX((int) (x - leftPart / zoomFactor)); - currentMinMax[1] = descaleX((int) (x + rightPart / zoomFactor)); - } - if (insideY) { - currentMinMax[2] = descaleY((int) (y + lowPart / zoomFactor)); - currentMinMax[3] = descaleY((int) (y - highPart / zoomFactor)); - } - updateImage(); - if (wasLogX != logXAxis ){//log-lin was automatically changed - int changedX = (int) scaleXtoPxl(plotX); - int left = changedX - leftPart; - int right = changedX + rightPart; - currentMinMax[0] = descaleX(left); - currentMinMax[1] = descaleX(right); - updateImage(); - } - if (wasLogY != logYAxis){//log-lin was automatically changed - int changedY = (int) scaleYtoPxl(plotY); - int bottom = changedY + lowPart; - int top = changedY + highPart; - currentMinMax[2] = descaleY(bottom); - currentMinMax[3] = descaleY(top); - updateImage(); - } - } - - /** Moves the plot range by a given number of pixels and updates the image */ - void scroll(int dx, int dy) { - if (logXAxis) { - currentMinMax[0] /= Math.pow(10, dx/xScale); - currentMinMax[1] /= Math.pow(10, dx/xScale); - } else { - currentMinMax[0] -= dx/xScale; - currentMinMax[1] -= dx/xScale; - } - if (logYAxis) { - currentMinMax[2] *= Math.pow(10, dy/yScale); - currentMinMax[3] *= Math.pow(10, dy/yScale); - } else { - currentMinMax[2] += dy/yScale; - currentMinMax[3] += dy/yScale; - } - updateImage(); - } - - /** Whether to draw simple axes without ticks, grid and numbers only for min, max*/ - private boolean simpleXAxis() { - return !hasFlag(X_TICKS | X_MINOR_TICKS | X_LOG_TICKS | X_GRID | X_NUMBERS); - } - - private boolean simpleYAxis() { - return !hasFlag(Y_TICKS | Y_MINOR_TICKS | Y_LOG_TICKS | Y_GRID | Y_NUMBERS); - } - - /** Draws ticks, grid and axis label for each tick/grid line. - * The grid or major tick spacing in each direction is given by steps */ - void drawAxesTicksGridNumbers(double[] steps) { - - if (ip==null) - return; - String[] xCats = labelsInBraces('x'); // create categories for the axes (if any) - String[] yCats = labelsInBraces('y'); - String multiplySymbol = getMultiplySymbol(); // for scientific notation - Font scFont = scFont(pp.frame.getFont()); - Font scFontMedium = scFont.deriveFont(scFont.getSize2D()*10f/12f); //for axis numbers if full size does not fit - Font scFontSmall = scFont.deriveFont(scFont.getSize2D()*9f/12f); //for subscripts - ip.setFont(scFont); - FontMetrics fm = ip.getFontMetrics(); - int fontAscent = fm.getAscent(); - ip.setJustification(LEFT); - // --- A l o n g X A x i s - int yOfXAxisNumbers = topMargin + frameHeight + fm.getHeight()*5/4 + sc(2); - if (hasFlag(X_NUMBERS | (logXAxis ? (X_TICKS | X_MINOR_TICKS) : X_LOG_TICKS) + X_GRID)) { - Font baseFont = scFont; - boolean majorTicks = logXAxis ? hasFlag(X_LOG_TICKS) : hasFlag(X_TICKS); - boolean minorTicks = hasFlag(X_MINOR_TICKS); - minorTicks = minorTicks && (xCats == null); - double step = steps[0]; - int i1 = (int)Math.ceil (Math.min(xMin, xMax)/step-1.e-10); - int i2 = (int)Math.floor(Math.max(xMin, xMax)/step+1.e-10); - int suggestedDigits = (int)Tools.getNumberFromList(pp.frame.options, "xdecimals="); //is not given, NaN cast to 0 - int digits = getDigits(xMin, xMax, step, 7, suggestedDigits); - int y1 = topMargin; - int y2 = topMargin + frameHeight; - if (xMin==xMax) { - if (hasFlag(X_NUMBERS)) { - String s = IJ.d2s(xMin,getDigits(xMin, 0.001*xMin, 5, suggestedDigits)); - int y = yBasePxl; - ip.drawString(s, xBasePxl-ip.getStringWidth(s)/2, yOfXAxisNumbers); - } - } else { - if (hasFlag(X_NUMBERS)) { - int w1 = ip.getStringWidth(IJ.d2s(currentMinMax[0], logXAxis ? -1 : digits)); - int w2 = ip.getStringWidth(IJ.d2s(currentMinMax[1], logXAxis ? -1 : digits)); - int wMax = Math.max(w1,w2); - if (wMax > Math.abs(step*xScale)-sc(8)) { - baseFont = scFontMedium; //small font if there is not enough space for the numbers - ip.setFont(baseFont); - } - } - - for (int i=0; i<=(i2-i1); i++) { - double v = (i+i1)*step; - int x = (int)Math.round((v - xMin)*xScale) + leftMargin; - - if (xCats!= null) { - int index = (int) v; - double remainder = Math.abs(v - Math.round(v)); - if(index >= 0 && index < xCats.length && remainder < 1e-9){ - String s = xCats[index]; - String[] parts = s.split("\n"); - int w = 0; - for(int jj = 0; jj < parts.length; jj++) - w = Math.max(w, ip.getStringWidth(parts[jj])); - - ip.drawString(s, x-w/2, yOfXAxisNumbers); - //ip.drawString(s, x-ip.getStringWidth(s)/2, yOfXAxisNumbers); - } - continue; - } - - if (hasFlag(X_GRID)) { - ip.setColor(gridColor); - ip.drawLine(x, y1, x, y2); - ip.setColor(Color.black); - } - if (majorTicks) { - ip.drawLine(x, y1, x, y1+sc(tickLength)); - ip.drawLine(x, y2, x, y2-sc(tickLength)); - } - if (hasFlag(X_NUMBERS)) { - if (logXAxis || digits<0) { - drawExpString(logXAxis ? Math.pow(10,v) : v, logXAxis ? -1 : -digits, - x, yOfXAxisNumbers-fontAscent/2, CENTER, fontAscent, baseFont, scFontSmall, multiplySymbol); - } else { - String s = IJ.d2s(v,digits); - ip.drawString(s, x-ip.getStringWidth(s)/2, yOfXAxisNumbers); - } - } - } - boolean haveMinorLogNumbers = i2-i1 < 2; //nunbers on log minor ticks only if < 2 decades - if (minorTicks && (!logXAxis || step > 1.1)) { //'standard' log minor ticks only for full decades - double mstep = niceNumber(step*0.19); //non-log: 4 or 5 minor ticks per major tick - double minorPerMajor = step/mstep; - if (Math.abs(minorPerMajor-Math.round(minorPerMajor)) > 1e-10) //major steps are not an integer multiple of minor steps? (e.g. user step 90 deg) - mstep = step/4; - if (logXAxis && mstep < 1) mstep = 1; - i1 = (int)Math.ceil (Math.min(xMin,xMax)/mstep-1.e-10); - i2 = (int)Math.floor(Math.max(xMin,xMax)/mstep+1.e-10); - for (int i=i1; i<=i2; i++) { - double v = i*mstep; - int x = (int)Math.round((v - xMin)*xScale) + leftMargin; - ip.drawLine(x, y1, x, y1+sc(minorTickLength)); - ip.drawLine(x, y2, x, y2-sc(minorTickLength)); - } - } else if (logXAxis && majorTicks && Math.abs(xScale)>sc(MIN_X_GRIDSPACING)) { //minor ticks for log - int minorNumberLimit = haveMinorLogNumbers ? (int)(0.12*Math.abs(xScale)/(fm.charWidth('0')+sc(2))) : 0; //more numbers on minor ticks when zoomed in - i1 = (int)Math.floor(Math.min(xMin,xMax)-1.e-10); - i2 = (int)Math.ceil (Math.max(xMin,xMax)+1.e-10); - for (int i=i1; i<=i2; i++) { - for (int m=2; m<10; m++) { - double v = i+Math.log10(m); - if (v > Math.min(xMin,xMax) && v < Math.max(xMin,xMax)) { - int x = (int)Math.round((v - xMin)*xScale) + leftMargin; - ip.drawLine(x, y1, x, y1+sc(minorTickLength)); - ip.drawLine(x, y2, x, y2-sc(minorTickLength)); - if (m<=minorNumberLimit) - drawExpString(Math.pow(10,v), 0, x, yOfXAxisNumbers-fontAscent/2, CENTER, - fontAscent, baseFont, scFontSmall, multiplySymbol); - } - } - } - } - } - } - // --- A l o n g Y A x i s - ip.setFont(scFont); - int maxNumWidth = 0; - int xNumberRight = leftMargin-sc(2)-ip.getStringWidth("0")/2; - Rectangle rect = ip.getStringBounds("0169"); - int yNumberOffset = -rect.y-rect.height/2; - if (hasFlag(Y_NUMBERS | (logYAxis ? (Y_TICKS | Y_MINOR_TICKS) : Y_LOG_TICKS) + Y_GRID)) { - ip.setJustification(RIGHT); - Font baseFont = scFont; - boolean majorTicks = logYAxis ? hasFlag(Y_LOG_TICKS) : hasFlag(Y_TICKS); - boolean minorTicks = logYAxis ? hasFlag(Y_LOG_TICKS) : hasFlag(Y_MINOR_TICKS); - minorTicks = minorTicks && (yCats == null); - double step = steps[1]; - int i1 = (int)Math.ceil (Math.min(yMin, yMax)/step-1.e-10); - int i2 = (int)Math.floor(Math.max(yMin, yMax)/step+1.e-10); - int suggestedDigits = (int)Tools.getNumberFromList(pp.frame.options, "ydecimals="); //is not given, NaN cast to 0 - int digits = getDigits(yMin, yMax, step, 5, suggestedDigits); - int x1 = leftMargin; - int x2 = leftMargin + frameWidth; - if (yMin==yMax) { - if (hasFlag(Y_NUMBERS)) { - String s = IJ.d2s(yMin,getDigits(yMin, 0.001*yMin, 5, suggestedDigits)); - maxNumWidth = ip.getStringWidth(s); - int y = yBasePxl; - ip.drawString(s, xNumberRight, y+fontAscent/2+sc(1)); - } - } else { - int digitsForWidth = logYAxis ? -1 : digits; - if (digitsForWidth < 0) { - digitsForWidth--; //"1.0*10^5" etc. needs more space than 1.0*5, simulate by adding one decimal - xNumberRight += sc(1)+ip.getStringWidth("0")/4; - } - String str1 = IJ.d2s(currentMinMax[2], digitsForWidth); - String str2 = IJ.d2s(currentMinMax[3], digitsForWidth); - if (digitsForWidth < 0) { - str1 = str1.replaceFirst("E",multiplySymbol); - str2 = str2.replaceFirst("E",multiplySymbol); - } - int w1 = ip.getStringWidth(str1); - int w2 = ip.getStringWidth(str2); - int wMax = Math.max(w1,w2); - if (hasFlag(Y_NUMBERS)) { - if (wMax > xNumberRight - sc(4) - (pp.yLabel.label.length()>0 ? fm.getHeight() : 0)) { - baseFont = scFontMedium; //small font if there is not enough space for the numbers - ip.setFont(baseFont); - } - } - //IJ.log(IJ.d2s(currentMinMax[2],digits)+": w="+w1+"; "+IJ.d2s(currentMinMax[3],digits)+": w="+w2+baseFont+" Space="+(leftMargin-sc(4+5)-fm.getHeight())); - for (int i=i1; i<=i2; i++) { - double v = step==0 ? yMin : i*step; - int y = topMargin + frameHeight - (int)Math.round((v - yMin)*yScale); - - if (yCats != null){ - int index = (int) v; - double remainder = Math.abs(v - Math.round(v)); - if(index >= 0 && index < yCats.length && remainder < 1e-9){ - String s = yCats[index]; - int multiLineOffset = 0; // multi-line cat labels - for(int jj = 0; jj < s.length(); jj++) - if(s.charAt(jj) == '\n') - multiLineOffset -= rect.height/2; - - ip.drawString(s, xNumberRight, y+yNumberOffset+ multiLineOffset); - } - continue; - } - - if (hasFlag(Y_GRID)) { - ip.setColor(gridColor); - ip.drawLine(x1, y, x2, y); - ip.setColor(Color.black); - } - if (majorTicks) { - ip.drawLine(x1, y, x1+sc(tickLength), y); - ip.drawLine(x2, y, x2-sc(tickLength), y); - } - if (hasFlag(Y_NUMBERS)) { - int w = 0; - if (logYAxis || digits<0) { - w = drawExpString(logYAxis ? Math.pow(10,v) : v, logYAxis ? -1 : -digits, - xNumberRight, y, RIGHT, fontAscent, baseFont, scFontSmall, multiplySymbol); - } else { - String s = IJ.d2s(v,digits); - w = ip.getStringWidth(s); - ip.drawString(s, xNumberRight, y+yNumberOffset); - } - if (w > maxNumWidth) maxNumWidth = w; - } - } - boolean haveMinorLogNumbers = i2-i1 < 2; //numbers on log minor ticks only if < 2 decades - if (minorTicks && (!logYAxis || step > 1.1)) { //'standard' log minor ticks only for full decades - double mstep = niceNumber(step*0.19); //non-log: 4 or 5 minor ticks per major tick - double minorPerMajor = step/mstep; - if (Math.abs(minorPerMajor-Math.round(minorPerMajor)) > 1e-10) //major steps are not an integer multiple of minor steps? (e.g. user step 90 deg) - mstep = step/4; - if (logYAxis && step < 1) mstep = 1; - i1 = (int)Math.ceil (Math.min(yMin,yMax)/mstep-1.e-10); - i2 = (int)Math.floor(Math.max(yMin,yMax)/mstep+1.e-10); - for (int i=i1; i<=i2; i++) { - double v = i*mstep; - int y = topMargin + frameHeight - (int)Math.round((v - yMin)*yScale); - ip.drawLine(x1, y, x1+sc(minorTickLength), y); - ip.drawLine(x2, y, x2-sc(minorTickLength), y); - } - } - if (logYAxis && majorTicks && Math.abs(yScale)>sc(MIN_X_GRIDSPACING)) { //minor ticks for log within the decade - int minorNumberLimit = haveMinorLogNumbers ? (int)(0.4*Math.abs(yScale)/fm.getHeight()) : 0; //more numbers on minor ticks when zoomed in - i1 = (int)Math.floor(Math.min(yMin,yMax)-1.e-10); - i2 = (int)Math.ceil(Math.max(yMin,yMax)+1.e-10); - for (int i=i1; i<=i2; i++) { - for (int m=2; m<10; m++) { - double v = i+Math.log10(m); - if (v > Math.min(yMin,yMax) && v < Math.max(yMin,yMax)) { - int y = topMargin + frameHeight - (int)Math.round((v - yMin)*yScale); - ip.drawLine(x1, y, x1+sc(minorTickLength), y); - ip.drawLine(x2, y, x2-sc(minorTickLength), y); - if (m<=minorNumberLimit) { - int w = drawExpString(Math.pow(10,v), 0, xNumberRight, y, RIGHT, - fontAscent, baseFont, scFontSmall, multiplySymbol); - if (w > maxNumWidth) maxNumWidth = w; - } - } - } - } - } - } - } - // --- Write min&max of range if simple style without any axis format flags - ip.setFont(scFont); - ip.setJustification(LEFT); - String xLabelToDraw = pp.xLabel.label; - String yLabelToDraw = pp.yLabel.label; - if (simpleYAxis()) { // y-axis min&max - int digits = getDigits(yMin, yMax, 0.001*(yMax-yMin), 6, 0); - String s = IJ.d2s(yMax, digits); - int sw = ip.getStringWidth(s); - if ((sw+sc(4)) > leftMargin) - ip.drawString(s, sc(4), topMargin-sc(4)); - else - ip.drawString(s, leftMargin-ip.getStringWidth(s)-sc(4), topMargin+10); - s = IJ.d2s(yMin, digits); - sw = ip.getStringWidth(s); - if ((sw+4)>leftMargin) - ip.drawString(s, sc(4), topMargin+frame.height); - else - ip.drawString(s, leftMargin-ip.getStringWidth(s)-sc(4), topMargin+frame.height); - if (logYAxis) yLabelToDraw += " (LOG)"; - } - int y = yOfXAxisNumbers; - if (simpleXAxis()) { // x-axis min&max - int digits = getDigits(xMin, xMax, 0.001*(xMax-xMin), 7, 0); - ip.drawString(IJ.d2s(xMin,digits), leftMargin, y); - String s = IJ.d2s(xMax,digits); - ip.drawString(s, leftMargin + frame.width-ip.getStringWidth(s)+6, y); - y -= fm.getHeight(); - if (logXAxis) xLabelToDraw += " (LOG)"; - } else - y += sc(1); - // --- Write x and y axis text labels - if (xCats == null) { - ip.setFont(pp.xLabel.getFont() == null ? scFont : scFont(pp.xLabel.getFont())); - ImageProcessor xLabel = stringToPixels(xLabelToDraw); - if(xLabel != null){ - int xpos = leftMargin+(frame.width-xLabel.getWidth())/2; - int ypos = y + scFont.getSize()/3;//topMargin + frame.height + bottomMargin-xLabel.getHeight(); - ip.insert(xLabel, xpos, ypos); - } - } - if (yCats == null) { - ip.setFont(pp.yLabel.getFont() == null ? scFont : scFont(pp.yLabel.getFont())); - ImageProcessor yLabel = stringToPixels(yLabelToDraw); - if(yLabel != null){ - yLabel = yLabel.rotateLeft(); - int xRightOfYLabel = xNumberRight - maxNumWidth - sc(2); - int xpos = xRightOfYLabel - yLabel.getWidth() - sc(2); - int ypos = topMargin + (frame.height -yLabel.getHeight())/2; - ip.insert(yLabel, xpos, ypos); - } - } - } - - /** Returns the array of categories from an axis label in the form {cat1,cat2,cat3}, or null if not this form - * @param labelCode can be 'x' or 'y', for the x or y axis label*/ - String[] labelsInBraces(char labelCode) { - String s = getLabel(labelCode); - if (s.startsWith("{") && s.endsWith("}")) { - String inBraces = s.substring(1, s.length() - 1); - String[] catLabels = inBraces.split(","); - return catLabels; - } else { - return null; - } - } - - /** Returns the smallest "nice" number >= v. "Nice" numbers are .. 0.5, 1, 2, 5, 10, 20 ... */ - double niceNumber(double v) { - double base = Math.pow(10,Math.floor(Math.log10(v)-1.e-6)); - if (v > 5.0000001*base) return 10*base; - else if (v > 2.0000001*base) return 5*base; - else return 2*base; - } - - /** draw something like 1.2 10^-9; returns the width of the string drawn. - * 'Digits' should be >=0 for drawing the mantissa (=1.38 in this example), negative to draw only 10^exponent - * Currently only supports center justification and right justification (y of center line) - * Fonts baseFont, smallFont should be scaled already - * Returns the width of the String */ - int drawExpString(double value, int digits, int x, int y, int justification, - int fontAscent, Font baseFont, Font smallFont, String multiplySymbol) { - String base = "10"; - String exponent = null; - String s = IJ.d2s(value, digits<=0 ? -1 : -digits); - if (Tools.parseDouble(s) == 0) s = "0"; //don't write 0 as 0*10^0 - int ePos = s.indexOf('E'); - if (ePos < 0) - base = s; //can't have exponential format, e.g. NaN - else { - if (digits>=0) { - base = s.substring(0,ePos); - if (digits == 0) - base = Integer.toString((int)Math.round(Tools.parseDouble(base))); - base += multiplySymbol+"10"; - } - exponent = s.substring(ePos+1); - } - //IJ.log(s+" -> "+base+"^"+exponent+" maxAsc="+fontAscent+" font="+baseFont); - ip.setJustification(RIGHT); - int width = ip.getStringWidth(base); - if (exponent != null) { - ip.setFont(smallFont); - int wExponent = ip.getStringWidth(exponent); - width += wExponent; - if (justification == CENTER) x += width/2; - ip.drawString(exponent, x, y+fontAscent*3/10); - x -= wExponent; - ip.setFont(baseFont); - } - ip.drawString(base, x, y+fontAscent*7/10); - return width; - } - - /** Returns the user-supplied (via setOptions) or default multiplication symbol (middot) */ - String getMultiplySymbol() { - String multiplySymbol = Tools.getStringFromList(pp.frame.options, "msymbol="); - if (multiplySymbol==null) - multiplySymbol = Tools.getStringFromList(pp.frame.options, "multiplysymbol="); - return multiplySymbol != null ? multiplySymbol : MULTIPLY_SYMBOL; - } - - //Returns a pixelMap containting labelStr. - //Uses font of current ImageProcessor. - //Returns null for empty or blank-only strings - //Supports !!subscript!! and ^^superscript^^ - ByteProcessor stringToPixels(String labelStr) { - Font bigFont = ip.getFont(); - Rectangle rect = ip.getStringBounds(labelStr); - int ww = rect.width * 2; - int hh = rect.height * 3;//enough space, will be cropped later - int y0 = rect.height * 2;//base line - if (ww <= 0 || hh <= 0) { - return null; - } - ByteProcessor box = new ByteProcessor(ww, hh); - box.setColor(Color.WHITE); - //box.setColor(Color.LIGHT_GRAY); //make box visible for test - box.fill(); - box.setColor(Color.black); - box.setAntialiasedText(pp.antialiasedText); - if (invertedLut) { - box.invertLut(); - } - box.setFont(bigFont); - - FontMetrics fm = box.getFontMetrics(); - int ascent = fm.getAscent(); - int offSub = ascent / 6; - int offSuper = -ascent / 2; - Font smallFont = bigFont.deriveFont((float) (bigFont.getSize() * 0.7)); - - Rectangle bigBounds = box.getStringBounds(labelStr); - boolean doParse = (labelStr.indexOf("^^") >= 0 || labelStr.indexOf("!!") >= 0); - doParse = doParse && (labelStr.indexOf("^^^") < 0 && labelStr.indexOf("!!!") < 0); - if (!doParse) { - box.drawString(labelStr, 0, y0); - Rectangle cropRect = new Rectangle(bigBounds); - cropRect.y += y0; - box.setRoi(cropRect); - ImageProcessor boxI = box.crop(); - box = boxI.convertToByteProcessor(); - return box; - } - - if (labelStr.endsWith("^^") || labelStr.endsWith("!!")) { - labelStr = labelStr.substring(0, labelStr.length() - 2); - } - if (labelStr.startsWith("^^") || labelStr.startsWith("!!")) { - labelStr = " " + labelStr; - } - - box.setFont(smallFont); - Rectangle smallBounds = box.getStringBounds(labelStr); - box.setFont(bigFont); - int upperBound = y0 + smallBounds.y + offSuper; - int lowerBound = y0 + smallBounds.y + smallBounds.height + offSub; - - int h = fm.getHeight(); - int len = labelStr.length(); - int[] tags = new int[len]; - int nTags = 0; - - for (int jj = 0; jj < len - 2; jj++) {//get positions where font size changes - if (labelStr.substring(jj, jj + 2).equals("^^")) { - tags[nTags++] = jj; - } - if (labelStr.substring(jj, jj + 2).equals("!!")) { - tags[nTags++] = -jj; - } - } - tags[nTags++] = len; - tags = Arrays.copyOf(tags, nTags); - - int leftIndex = 0; - int xRight = 0; - int y2 = y0; - - boolean subscript = labelStr.startsWith("!!"); - for (int pp = 0; pp < tags.length; pp++) {//draw all text fragments - int rightIndex = tags[pp]; - rightIndex = Math.abs(rightIndex); - String part = labelStr.substring(leftIndex, rightIndex); - boolean small = pp % 2 == 1;//toggle odd/even - if (small) { - box.setFont(smallFont); - if (subscript) { - y2 = y0 + offSub; - } else {//superscript: - y2 = y0 + offSuper; - } - } else { - box.setFont(bigFont); - y2 = y0; - } - xRight++; - int partWidth = box.getStringWidth(part); - box.drawString(part, xRight, y2); - leftIndex = rightIndex + 2; - subscript = tags[pp] < 0;//negative positions = subscript - xRight += partWidth; - } - xRight += h / 4; - Rectangle cropRect = new Rectangle(0, upperBound, xRight, lowerBound - upperBound); - box.setRoi(cropRect); - ImageProcessor boxI = box.crop(); - box = boxI.convertToByteProcessor(); - return box; - } - - /** Returns the number of digits to display the number n with resolution 'resolution'; - * (if n is integer and small enough to display without scientific notation, - * no decimals are needed, irrespective of 'resolution') - * Scientific notation is used for more than 'maxDigits' (must be >=3), and indicated - * by a negative return value, or if suggestedDigits is negative - * Returns 'suggestedDigits' if not 0 and compatible with the resolution; negative values of - * 'suggestedDigits' switch to scientific notation. */ - static int getDigits(double n, double resolution, int maxDigits, int suggestedDigits) { - if (n==Math.round(n) && Math.abs(n) < Math.pow(10,maxDigits-1)-1) //integers and not too big - return suggestedDigits; - else - return getDigits2(n, resolution, maxDigits, suggestedDigits); - } - - /** Number of digits to display the range between n1 and n2 with resolution 'resolution'; - * Scientific notation is used for more than 'maxDigits' (must be >=3), and indicated - * by a negative return value - * Returns 'suggestedDigits' if not 0 and compatible with the resolution; negative values of - * 'suggestedDigits' switch to sceintific notation. */ - static int getDigits(double n1, double n2, double resolution, int maxDigits, int suggestedDigits) { - if (n1==0 && n2==0) return suggestedDigits; - return getDigits2(Math.max(Math.abs(n1),Math.abs(n2)), resolution, maxDigits, suggestedDigits); - } - - static int getDigits2(double n, double resolution, int maxDigits, int suggestedDigits) { - if (Double.isNaN(n) || Double.isInfinite(n)) - return 0; //no scientific notation - int log10ofN = (int)Math.floor(Math.log10(Math.abs(n))+1e-7); - int digits = resolution != 0 ? - -(int)Math.floor(Math.log10(Math.abs(resolution))+1e-7) : - Math.max(0, -log10ofN+maxDigits-2); - int sciDigits = -Math.max((log10ofN+digits),1); - //IJ.log("n="+(float)n+"digitsRaw="+digits+" log10ofN="+log10ofN+" sciDigits="+sciDigits); - if ((digits < -2 && log10ofN >= maxDigits) || suggestedDigits < 0) - digits = sciDigits; //scientific notation for large numbers or if desired via suggestedDigits (plot.setOptions) - else if (digits < 0) - digits = 0; - else if (digits > maxDigits-1 && log10ofN < -2) - digits = sciDigits; // scientific notation for small numbers - return digits < 0 ? Math.min(sciDigits, suggestedDigits) : Math.max(digits, suggestedDigits); - } - - static boolean isInteger(double n) { - return n==Math.round(n); - } - - private void drawPlotObject(PlotObject plotObject, ImageProcessor ip) { - //IJ.log("DRAWING type="+plotObject.type+" lineWidth="+plotObject.lineWidth+" shape="+plotObject.shape); - if (plotObject.hasFlag(PlotObject.HIDDEN)) return; - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - int type = plotObject.type; - switch (type) { - case PlotObject.XY_DATA: - ip.setClipRect(frame); - int nPoints = Math.min(plotObject.xValues.length, plotObject.yValues.length); - - if (plotObject.shape==BAR || plotObject.shape==SEPARATED_BAR) - drawBarChart(plotObject); // (separated) bars - - if (plotObject.shape == FILLED) { // filling below line - ip.setColor(plotObject.color2 != null ? plotObject.color2 : plotObject.color); - drawFloatPolyLineFilled(ip, plotObject.xValues, plotObject.yValues, nPoints); - } - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - - if (plotObject.yEValues != null) // error bars in front of bars and fill area below the line, but behind lines and marker symbols - drawVerticalErrorBars(plotObject.xValues, plotObject.yValues, plotObject.yEValues); - if (plotObject.xEValues != null) - drawHorizontalErrorBars(plotObject.xValues, plotObject.yValues, plotObject.xEValues); - - if (plotObject.hasFilledMarker()) { // fill markers with secondary color - int markSize = plotObject.getMarkerSize(); - ip.setColor(plotObject.color2); - ip.setLineWidth(1); - for (int i=0; i0) && (!logYAxis || plotObject.yValues[i]>0) - && !Double.isNaN(plotObject.xValues[i]) && !Double.isNaN(plotObject.yValues[i])) - fillShape(plotObject.shape, scaleX(plotObject.xValues[i]), scaleY(plotObject.yValues[i]), markSize); - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - } - if (plotObject.hasCurve()) { // draw the lines between the points - if (plotObject.shape == CONNECTED_CIRCLES) - ip.setColor(plotObject.color2 == null ? Color.black : plotObject.color2); - drawFloatPolyline(ip, plotObject.xValues, plotObject.yValues, nPoints); - ip.setColor(plotObject.color); - } - if (plotObject.hasMarker()) { // draw the marker symbols - int markSize = plotObject.getMarkerSize(); - ip.setColor(plotObject.color); - Font saveFont = ip.getFont(); - for (int i=0; i0) && (!logYAxis || plotObject.yValues[i]>0) - && !Double.isNaN(plotObject.xValues[i]) && !Double.isNaN(plotObject.yValues[i])) - drawShape(plotObject, scaleX(plotObject.xValues[i]), scaleY(plotObject.yValues[i]), plotObject.shape, markSize, i); - } - if (plotObject.shape==CUSTOM) - ip.setFont(saveFont); - } - ip.setClipRect(null); - break; - case PlotObject.ARROWS: - ip.setClipRect(frame); - for (int i=0; i sc(MAX_ARROWHEAD_LENGTH)) arrowHeadLength = sc(MAX_ARROWHEAD_LENGTH); - if (arrowHeadLength < sc(MIN_ARROWHEAD_LENGTH)) arrowHeadLength = sc(MIN_ARROWHEAD_LENGTH); - drawArrow(xt1, yt1, xt2, yt2, arrowHeadLength); - } - } - ip.setClipRect(null); - break; - - case PlotObject.SHAPES: - int iBoxWidth = 20; - ip.setClipRect(frame); - String shType = plotObject.shapeType.toLowerCase(); - if (shType.contains("rectangles")) { - int nShapes = plotObject.shapeData.size(); - - for (int i = 0; i < nShapes; i++) { - float[] corners = (float[])(plotObject.shapeData.get(i)); - int x1 = scaleX(corners[0]); - int y1 = scaleY(corners[1]); - int x2 = scaleX(corners[2]); - int y2 = scaleY(corners[3]); - - ip.setLineWidth(sc(plotObject.lineWidth)); - int left = Math.min(x1, x2); - int right = Math.max(x1, x2); - int top = Math.min(y1, y2); - int bottom = Math.max(y1, y2); - - Rectangle r1 = new Rectangle(left, top, right-left, bottom - top); - Rectangle cBox = frame.intersection(r1); - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - ip.fillRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setColor(plotObject.color); - ip.drawRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setClipRect(null); - break; - } - if (shType.equals("redraw_grid")) { - ip.setLineWidth(sc(1)); - redrawGrid(); - ip.setClipRect(null); - break; - } - if (shType.contains("boxes")) { - - String[] parts = Tools.split(shType); - for (int jj = 0; jj < parts.length; jj++) { - String[] pairs = parts[jj].split("="); - if ((pairs.length == 2) && pairs[0].equals("width")) { - iBoxWidth = Integer.parseInt(pairs[1]); - } - } - boolean horizontal = shType.contains("boxesx"); - int nShapes = plotObject.shapeData.size(); - int halfWidth = Math.round(sc(iBoxWidth / 2)); - for (int i = 0; i < nShapes; i++) { - - float[] coords = (float[])(plotObject.shapeData.get(i)); - - if (!horizontal) { - - int x = scaleX(coords[0]); - int y1 = scaleY(coords[1]); - int y2 = scaleY(coords[2]); - int y3 = scaleY(coords[3]); - int y4 = scaleY(coords[4]); - int y5 = scaleY(coords[5]); - ip.setLineWidth(sc(plotObject.lineWidth)); - - Rectangle r1 = new Rectangle(x - halfWidth, y4, halfWidth * 2, y2 - y4); - Rectangle cBox = frame.intersection(r1); - if (y1 != y2 || y4 != y5)//otherwise omit whiskers - { - ip.drawLine(x, y1, x, y5);//whiskers - } - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - ip.fillRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setColor(plotObject.color); - ip.drawRect(cBox.x, cBox.y, cBox.width, cBox.height); - ip.setClipRect(frame); - ip.drawLine(x - halfWidth, y3, x + halfWidth - 1, y3); - } - - if (horizontal) { - - int y = scaleY(coords[0]); - int x1 = scaleX(coords[1]); - int x2 = scaleX(coords[2]); - int x3 = scaleX(coords[3]); - int x4 = scaleX(coords[4]); - int x5 = scaleX(coords[5]); - ip.setLineWidth(sc(plotObject.lineWidth)); - if(x1 !=x2 || x4 != x5)//otherwise omit whiskers - ip.drawLine(x1, y, x5, y);//whiskers - Rectangle r1 = new Rectangle(x2, y - halfWidth, x4 - x2, halfWidth * 2); - Rectangle cBox = frame.intersection(r1); - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - ip.fillRect(cBox.x, cBox.y, cBox.width, cBox.height); - } - ip.setColor(plotObject.color); - ip.drawRect(cBox.x, cBox.y, cBox.width, cBox.height); - ip.setClipRect(frame); - ip.drawLine(x3, y - halfWidth, x3, y + halfWidth - 1); - } - } - ip.setClipRect(null); - break; - } - case PlotObject.LINE: - if (Double.isNaN(plotObject.x) || Double.isNaN(plotObject.y)) break; - ip.setClipRect(frame); - ip.drawLine(scaleX(plotObject.x), scaleY(plotObject.y), scaleX(plotObject.xEnd), scaleY(plotObject.yEnd)); - ip.setClipRect(null); - break; - case PlotObject.NORMALIZED_LINE: - ip.setClipRect(frame); - int ix1 = leftMargin + (int)(plotObject.x*frameWidth); - int iy1 = topMargin + (int)(plotObject.y*frameHeight); - int ix2 = leftMargin + (int)(plotObject.xEnd*frameWidth); - int iy2 = topMargin + (int)(plotObject.yEnd*frameHeight); - ip.drawLine(ix1, iy1, ix2, iy2); - ip.setClipRect(null); - break; - case PlotObject.DOTTED_LINE: - ip.setClipRect(frame); - ix1 = scaleX(plotObject.x); - iy1 = scaleY(plotObject.y); - ix2 = scaleX(plotObject.xEnd); - iy2 = scaleY(plotObject.yEnd); - double length = calculateDistance(ix1, ix2, iy1, iy2) + 0.1; - int n = (int)(length/plotObject.step); - for (int i = 0; i<=n; i++) - ip.drawDot(ix1 + (int)Math.round((ix2-ix1)*(double)i/n), iy1 + (int)Math.round((iy2-iy1)*(double)i/n)); - ip.setClipRect(null); - break; - case PlotObject.LABEL: - case PlotObject.NORMALIZED_LABEL: - ip.setJustification(plotObject.justification); - if (plotObject.getFont() != null) - ip.setFont(scFont(plotObject.getFont())); - int xt = type==PlotObject.LABEL ? scaleX(plotObject.x) : leftMargin + (int)(plotObject.x*frameWidth); - int yt = type==PlotObject.LABEL ? scaleY(plotObject.y) : topMargin + (int)(plotObject.y*frameHeight); - ip.drawString(plotObject.label, xt, yt); - break; - case PlotObject.LEGEND: - drawLegend(plotObject, ip); - break; - } - } - - /** Draw a bar at each point */ - void drawBarChart(PlotObject plotObject) { - int n = Math.min(plotObject.xValues.length, plotObject.yValues.length); - String[] xCats = labelsInBraces('x'); // do we have categories at the x axis instead of numbers? - boolean separatedBars = plotObject.shape == SEPARATED_BAR || xCats != null; - int halfBarWidthInPixels = n <= 1 ? Math.max(1, frameWidth/2-2) : 0; - if (separatedBars && n > 1) - halfBarWidthInPixels = Math.max(1, (int)Math.round(Math.abs - (0.5*(plotObject.xValues[n-1] - plotObject.xValues[0])/(n-1) * xScale * SEPARATED_BAR_WIDTH))); - int y0 = scaleYWithOverflow(0); - boolean yZeroInFrame = !logYAxis && yBasePxl>frame.y && yBasePxl 0 ? 0.5f*(plotObject.xValues[i-1]+plotObject.xValues[i]) : - 1.5f*plotObject.xValues[i] - 0.5f*plotObject.xValues[i+1]); - right = scaleX(i < n-1 ? 0.5f*(plotObject.xValues[i]+plotObject.xValues[i+1]) : - 1.5f*plotObject.xValues[i] - 0.5f*plotObject.xValues[i-1]); - } else { - int x = scaleX(plotObject.xValues[i]); - left = x - halfBarWidthInPixels; //separated bars or n<=1 : fixed bar width - right = x + halfBarWidthInPixels; - } - if (left < frame.x) left = frame.x; - if (left > frame.x+frame.width) left = frame.x+frame.width; - if (right < frame.x) right = frame.x; - if (right > frame.x+frame.width) right = frame.x+frame.width; - int y = scaleYWithOverflow(plotObject.yValues[i]); - if (plotObject.color2 != null) { - ip.setColor(plotObject.color2); - for (int x2 = Math.min(left,right); x2 <= Math.max(left,right); x2++) - ip.drawLine(x2, y0, x2, y); //cant use ip.fillRect (ignores the clipRect), so we it fill line by line - } - ip.setColor(plotObject.color); - ip.setLineWidth(sc(plotObject.lineWidth)); - if (separatedBars) { - ip.drawLine(left, y0, left, y); //up - ip.drawLine(left, y, right, y); //right - ip.drawLine(right, y, right, y0); //down - if (yZeroInFrame) - ip.drawLine(left, y0, right, y0);//baseline - } else { - ip.drawLine(left, prevY, left, y); //up or down - ip.drawLine(left, y, right, y); //right - if (i == n - 1) - ip.drawLine(right, y, right, y0);//last down - prevY = y; - } - } - } - - /** Draw the symbol for the data point number 'pointIndex' (pointIndex < 0 when drawing the legend) */ - void drawShape(PlotObject plotObject, int x, int y, int shape, int size, int pointIndex) { - if (ip==null) - return; - int lineWidth = ip.getLineWidth(); - if (shape == DIAMOND) - size = (int)(size*1.21); - int xbase = x-sc(size/2); - int ybase = y-sc(size/2); - int xend = x+sc(size/2); - int yend = y+sc(size/2); - if (lineWidth>3) { - int newLineWidth = 3; - ip.setLineWidth(newLineWidth); - } - //IJ.log("drawShape: "+size+" "+size); - switch(shape) { - case X: - ip.drawLine(xbase,ybase,xend,yend); - ip.drawLine(xend,ybase,xbase,yend); - break; - case BOX: - ip.drawLine(xbase,ybase,xend,ybase); - ip.drawLine(xend,ybase,xend,yend); - ip.drawLine(xend,yend,xbase,yend); - ip.drawLine(xbase,yend,xbase,ybase); - break; - case TRIANGLE: - ip.drawLine(x,ybase-sc(1),xend+sc(1),yend); //height must be odd, otherwise rounding leads to asymmetric shape - ip.drawLine(x,ybase-sc(1),xbase-sc(1),yend); - ip.drawLine(xend+sc(1),yend,xbase-sc(1),yend); - break; - case CROSS: - ip.drawLine(xbase,y,xend,y); - ip.drawLine(x,ybase,x,yend); - break; - case DIAMOND: - ip.drawLine(xbase,y,x,ybase); - ip.drawLine(x,ybase,xend,y); - ip.drawLine(xend,y,x,yend); - ip.drawLine(x,yend,xbase,y); - break; - case DOT: - ip.drawDot(x, y); //uses current line width - break; - case CUSTOM: - if (plotObject.macroCode==null || frame==null) - break; - if (x=frame.x+frame.width || y>=frame.y+frame.height) - break; - ImagePlus imp = new ImagePlus("", ip); - WindowManager.setTempCurrentImage(imp); - StringBuilder sb = new StringBuilder(140+plotObject.macroCode.length()); - sb.append("x="); sb.append(x); - sb.append(";y="); sb.append(y); - sb.append(";setColor('"); - sb.append(Tools.c2hex(plotObject.color)); - sb.append("');s="); sb.append(sc(1)); - boolean drawingLegend = pointIndex < 0; - double xVal = 0; - double yVal = 0; - if (!drawingLegend) { - xVal = plotObject.xValues[pointIndex]; - yVal = plotObject.yValues[pointIndex]; - } - sb.append(";i="); sb.append(drawingLegend ? 0 : pointIndex); - sb.append(";xval=" + xVal); - sb.append(";yval=" + yVal); - sb.append(";"); - sb.append(plotObject.macroCode); - if (!drawingLegend ||!sb.toString().contains("d2s") ) {// a graphical symbol won't contain "d2s" .. - String rtn = IJ.runMacro(sb.toString());//.. so it can go to the legend - if ("[aborted]".equals(rtn)) - plotObject.macroCode = null; - } - WindowManager.setTempCurrentImage(null); - break; - default: // CIRCLE, CONNECTED_CIRCLES: 5x5 oval approximated by 5x5 square without corners - if (sc(size) < 5.01) { - ip.drawLine(x-1, y-2, x+1, y-2); - ip.drawLine(x-1, y+2, x+1, y+2); - ip.drawLine(x+2, y+1, x+2, y-1); - ip.drawLine(x-2, y+1, x-2, y-1); - } else { - int r = sc(0.5f*size-0.5f); - ip.drawOval(x-r, y-r, 2*r, 2*r); - } - break; - } - ip.setLineWidth(lineWidth); - } - - /** Fill the area of the symbols for data points (except for shape=DOT) - * Note that ip.fill, ip.fillOval etc. can't be used here: they do not care about the clip rectangle */ - void fillShape(int shape, int x0, int y0, int size) { - if (shape == DIAMOND) size = (int)(size*1.21); - int r = sc(size/2)-1; - switch(shape) { - case BOX: - for (int dy=-r; dy<=r; dy++) - for (int dx=-r; dx<=r; dx++) - ip.drawDot(x0+dx, y0+dy); - break; - case TRIANGLE: - int ybase = y0 - r - sc(1); - int yend = y0 + r; - double halfWidth = sc(size/2)+sc(1)-1; - double hwStep = halfWidth/(yend-ybase+1); - for (int y=yend; y>=ybase; y--, halfWidth -= hwStep) { - int dx = (int)(Math.round(halfWidth)); - for (int x=x0-dx; x<=x0+dx; x++) - ip.drawDot(x,y); - } - break; - case DIAMOND: - ybase = y0 - r - sc(1); - yend = y0 + r; - halfWidth = sc(size/2)+sc(1)-1; - hwStep = halfWidth/(yend-ybase+1); - for (int y=yend; y>=ybase; y--) { - int dx = (int)(Math.round(halfWidth-(hwStep+1)*Math.abs(y-y0))); - for (int x=x0-dx; x<=x0+dx; x++) - ip.drawDot(x,y); - } - break; - case CIRCLE: case CONNECTED_CIRCLES: - int rsquare = (r+1)*(r+1); - for (int dy=-r; dy<=r; dy++) - for (int dx=-r; dx<=r; dx++) - if (dx*dx + dy*dy <= rsquare) - ip.drawDot(x0+dx, y0+dy); - break; - } - } - - /** Adds an arrow from position 1 to 2 given in pixels; 'size' is the length of the arrowhead - * @deprecated Use as a public method is not supported any more because it is incompatible with rescaling */ - @Deprecated - public void drawArrow(int x1, int y1, int x2, int y2, double size) { - double dx = x2 - x1; - double dy = y2 - y1; - double ra = Math.sqrt(dx * dx + dy * dy); - dx /= ra; - dy /= ra; - int x3 = (int) Math.round(x2 - dx * size); //arrow base - int y3 = (int) Math.round(y2 - dy * size); - double r = 0.3 * size; - int x4 = (int) Math.round(x3 + dy * r); - int y4 = (int) Math.round(y3 - dx * r); - int x5 = (int) Math.round(x3 - dy * r); - int y5 = (int) Math.round(y3 + dx * r); - ip.moveTo(x1, y1); ip.lineTo(x2, y2); - ip.moveTo(x4, y4); ip.lineTo(x2, y2); ip.lineTo(x5, y5); - } - - private void drawVerticalErrorBars(float[] x, float[] y, float[] e) { - int nPoints = Math.min(Math.min(x.length, y.length), e.length); - for (int i=0; i0))) continue; - int x0 = scaleX(x[i]); - int yPlus = scaleYWithOverflow(y[i] + e[i]); - int yMinus = scaleYWithOverflow(y[i] - e[i]); - ip.moveTo(x0,yMinus); - ip.lineTo(x0, yPlus); - } - } - - private void drawHorizontalErrorBars(float[] x, float[] y, float[] e) { - int nPoints = Math.min(Math.min(x.length, y.length), e.length); - float[] xpoints = new float[2]; - float[] ypoints = new float[2]; - for (int i=0; i0))) continue; - int y0 = scaleY(y[i]); - int xPlus = scaleXWithOverflow(x[i] + e[i]); - int xMinus = scaleXWithOverflow(x[i] - e[i]); - ip.moveTo(xMinus,y0); - ip.lineTo(xPlus, y0); - } - } - - /** Draw a polygon line; NaN values interrupt it. */ - void drawFloatPolyline(ImageProcessor ip, float[] x, float[] y, int n) { - if (x==null || x.length==0) return; - int x1, y1; - boolean isNaN0; - boolean isNaN1 = true; //no previous point - int x2 = scaleX(x[0]); - int y2 = scaleY(y[0]); - boolean isNaN2 = Float.isNaN(x[0]) || Float.isNaN(y[0]) || (logXAxis && x[0]<=0) || (logYAxis && y[0]<=0); - for (int i=1; i= frame.x+frame.width && right >= frame.x+frame.width) continue; - if (left < frame.x) left = frame.x; - if (left >= frame.x+frame.width) left = frame.x+frame.width-1; - if (right < frame.x) right = frame.x; - if (right >= frame.x+frame.width) right = frame.x+frame.width-1; - if (left != right) { - for (int xi = Math.min(left,right); xi <= Math.max(left,right); xi++) { - int yi = (int)Math.round(y1 + (double)(y2 - y1)*(double)(xi - x1)/(double)(x2 - x1)); - /* double yMin = Math.min(yF[i-1], yF[i]); - double yMax = Math.max(yF[i-1], yF[i]); - if (y < yMin) y = yMin; // dont extrapolate (in case rounding to pixels falls outside [xi, xi+1] interval) - if (y > yMax) y = yMax;*/ - ip.drawLine(xi, y0, xi, yi); - } - } else { - ip.drawLine(left, y0, left, y2); - } - } - } - - /** Returns only indexed and sorted plot objects, if at least one label is indexed like "1__MyLabel" */ - Vector getIndexedPlotObjects(){ - boolean withIndex = false; - int len = allPlotObjects.size(); - String[] labels = new String[len]; - Vector indexedObjects = new Vector(); - for(int jj = 0; jj < len; jj++){ - PlotObject plotObject = allPlotObjects.get(jj); - labels[jj] = ""; - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN) && plotObject.label != null) { - String label = plotObject.label; - if(label.indexOf("__") >=0 && label.indexOf("__") <= 2){ - labels[jj]= plotObject.label; - withIndex = true; - } - } - } - int[] ranks = Tools.rank(labels); - for(int jj = 0; jj < len; jj++){ - if(labels[ranks[jj]] != ""){ - int index = ranks[jj]; - indexedObjects.add(allPlotObjects.get(index)); - } - } - if(!withIndex) - return null; - return indexedObjects; - } - - /** Draw the legend */ - void drawLegend(PlotObject legendObject, ImageProcessor ip) { - ip.setFont(scFont(legendObject.getFont())); - int nLabels = 0; - int maxStringWidth = 0; - float maxLineThickness = 0; - Vector usedPlotObjects = allPlotObjects; - Vector indexedObjects = getIndexedPlotObjects(); - if(indexedObjects != null) - usedPlotObjects= indexedObjects; - - for (PlotObject plotObject : usedPlotObjects) - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN) && plotObject.label != null) { //label exists: was set now or previously - nLabels++; - String label = plotObject.label; - if (indexedObjects != null) - label = label.substring(label.indexOf("__") + 2); - int w = ip.getStringWidth(label); - if (w > maxStringWidth) maxStringWidth = w; - if (plotObject.lineWidth > maxLineThickness) maxLineThickness = plotObject.lineWidth; - } - if (nLabels == 0) return; - if (pp.antialiasedText && scale > 1) //fix incorrect width of large fonts - maxStringWidth = (int)((1 + 0.004*scale) * maxStringWidth); - int frameThickness = sc(legendObject.lineWidth > 0 ? legendObject.lineWidth : 1); - FontMetrics fm = ip.getFontMetrics(); - ip.setJustification(LEFT); - int lineHeight = fm.getHeight(); - int height = nLabels*lineHeight + 2*sc(LEGEND_PADDING); - int width = maxStringWidth + sc(3*LEGEND_PADDING + LEGEND_LINELENGTH + maxLineThickness); - int positionCode = legendObject.flags & LEGEND_POSITION_MASK; - if (positionCode == AUTO_POSITION) - positionCode = autoLegendPosition(width, height, frameThickness); - Rectangle rect = legendRect(positionCode, width, height, frameThickness); - int x0 = rect.x; - int y0 = rect.y; - - ip.setColor(Color.white); - ip.setLineWidth(1); - if (!legendObject.hasFlag(LEGEND_TRANSPARENT)) { - ip.setRoi(x0, y0, width, height); - ip.fill(); - } else if (hasFlag(X_GRID | Y_GRID)) { //erase grid - int grid = ip instanceof ColorProcessor ? (gridColor.getRGB() & 0xffffff) : ip.getBestIndex(gridColor); - for (int y=y0; y=0) - label = label.substring(start+2); - } - ip.drawString(label, xText, y+ lineHeight/2); - y += bottomUp ? -lineHeight : lineHeight; - } - } - - /** The legend area; positionCode should be TOP_LEFT, TOP_RIGHT, etc. */ - Rectangle legendRect(int positionCode, int width, int height, int frameThickness) { - boolean leftPosition = positionCode == TOP_LEFT || positionCode == BOTTOM_LEFT; - boolean topPosition = positionCode == TOP_LEFT || positionCode == TOP_RIGHT; - int x0 = (leftPosition) ? - leftMargin + sc(2*LEGEND_PADDING) + frameThickness/2 : - leftMargin + frameWidth - width - sc(2*LEGEND_PADDING) - frameThickness/2; - int y0 = (topPosition) ? - topMargin + sc(LEGEND_PADDING) + frameThickness/2 : - topMargin + frameHeight - height - sc(LEGEND_PADDING) + frameThickness/2; - if (hasFlag(Y_TICKS)) - x0 += (leftPosition ? 1 : -1) * sc(tickLength - LEGEND_PADDING); - if (hasFlag(X_TICKS)) - y0 += (topPosition ? 1 : -1) * sc(tickLength - LEGEND_PADDING/2); - return new Rectangle(x0, y0, width, height); - } - - /** The position code of the legend position where the smallest amount of foreground pixels is covered */ - int autoLegendPosition(int width, int height, int frameThickness) { - int background = ip instanceof ColorProcessor ? (0xffffff) : (ip.isInvertedLut() ? 0 : 0xff); - int grid = ip instanceof ColorProcessor ? (gridColor.getRGB() & 0xffffff) : ip.getBestIndex(gridColor); - int bestPosition = 0; - int minCoveredPixels = Integer.MAX_VALUE; - for (int positionCode : new int[]{TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT}) { - Rectangle rect = legendRect(positionCode, width, height, frameThickness); - int coveredPixels = 0; - for (int y = rect.y - frameThickness/2; y <= rect.y + rect.height + frameThickness/2; y++) - for (int x = rect.x - frameThickness/2; x <= rect.x + rect.width + frameThickness/2; x++) { - int pixel = ip.getPixel(x, y) & 0xffffff; - if (pixel != background && pixel != grid) - coveredPixels ++; - } - if (coveredPixels < minCoveredPixels) { - minCoveredPixels = coveredPixels; - bestPosition = positionCode; - } - } - return bestPosition; - } - - /** Returns the x, y coordinates at the cursor position or the nearest point as a String */ - String getCoordinates(int x, int y) { - if (frame==null) return ""; - String text = ""; - if (!frame.contains(x, y)) - return text; - double xv = descaleX(x); // cursor location - double yv = descaleY(y); - boolean yIsValue = false; - if (!hasMultiplePlots()) { - PlotObject p = getMainCurveObject(); // display x and f(x) instead of cursor y - if (p != null) { - double bestDx = Double.MAX_VALUE; - double xBest = 0, yBest = 0; - for (int i=0; i=0; i--) { - if (allPlotObjects.get(i).type == PlotObject.XY_DATA) - return allPlotObjects.get(i); - } - return null; - } - - /** returns whether there are several plots so that one cannot give a single y value for a given x value */ - private boolean hasMultiplePlots() { - int nPlots = 0; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type == PlotObject.ARROWS) - return true; - else if (plotObject.type == PlotObject.XY_DATA) { - nPlots ++; - if (nPlots > 1) return true; - } - } - return nPlots > 1; - } - - public void setPlotMaker(PlotMaker plotMaker) { - this.plotMaker = plotMaker; - } - - PlotMaker getPlotMaker() { - return plotMaker; - } - - /** Returns the labels of the (non-hidden) datasets as linefeed-delimited String. - * If the label is not set, a blank line is added. */ - String getDataLabels() { - String labels = ""; - boolean first = true; - for (PlotObject plotObject : allPlotObjects) - if (plotObject.type == PlotObject.XY_DATA && !plotObject.hasFlag(PlotObject.HIDDEN)) { - if (first) - first = false; - else - labels += '\n'; - if (plotObject.label != null) labels += plotObject.label; - } - return labels; - } - - /** Creates a ResultsTable with the plot data. Returns an empty table if no data. */ - public ResultsTable getResultsTable() { - return getResultsTable(true); - } - - /** Creates a ResultsTable with the data of the plot. Returns null if no data. - * Does not write the first x column if writeFirstXColumn is false. - * When all columns are the same length, x columns equal to the first x column are - * not written, independent of writeFirstXColumn. - * Column headings are "X", "Y", "X1", "Y1", etc, irrespective of any labels of the data sets - */ - public ResultsTable getResultsTable(boolean writeFirstXColumn) { - return getResultsTable(writeFirstXColumn, false); - } - - /** Creates a ResultsTable with the data of the plot. Returns null if no data. - * When all columns are the same length, x columns equal to the first x column are - * not written, independent of writeFirstXColumn. - * When the data sets have labels, they are used for column headings - */ - public ResultsTable getResultsTableWithLabels() { - return getResultsTable(true, true); - } - - /** Creates a ResultsTable with the data of the plot. Returns null if no data. - * Does not write the first x column if writeFirstXColumn is false. - * When all columns are the same length, x columns equal to the first x column are - * not written, independent of writeFirstXColumn. - * When the data sets have labels and useLabels is true, they are used for column headings, - * otherwise columns are named X, Y, X1, Y1, ... */ - ResultsTable getResultsTable(boolean writeFirstXColumn, boolean useLabels) { - ResultsTable rt = new ResultsTable(); - // find the longest x-value data set and count the data sets - int nDataSets = 0; - int tableLength = 0; - for (PlotObject plotObject : allPlotObjects) - if (plotObject.xValues != null) { - nDataSets++; - tableLength = Math.max(tableLength, plotObject.xValues.length); - } - if (nDataSets == 0) - return null; - // enter columns one by one to lists of data and headings - ArrayList headings = new ArrayList(2*nDataSets); - ArrayList data = new ArrayList(2*nDataSets); - int dataSetNumber = 0; - int arrowsNumber = 0; - PlotObject firstXYobject = null; - boolean allSameLength = true; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type==PlotObject.XY_DATA) { - if (firstXYobject != null && firstXYobject.xValues.length!=plotObject.xValues.length) { - allSameLength = false; - break; - } - if (firstXYobject==null) - firstXYobject = plotObject; - } - } - firstXYobject = null; - for (PlotObject plotObject : allPlotObjects) { - if (plotObject.type==PlotObject.XY_DATA) { - boolean sameX = firstXYobject!=null && Arrays.equals(firstXYobject.xValues, plotObject.xValues) && allSameLength; - boolean sameXY = sameX && Arrays.equals(firstXYobject.yValues, plotObject.yValues); //ignore duplicates (e.g. Markers plus Curve) - boolean writeX = firstXYobject==null ? writeFirstXColumn : !sameX; - addToLists(headings, data, plotObject, dataSetNumber, writeX, /*writeY=*/!sameXY, /*multipleSets=*/nDataSets>1, useLabels); - if (firstXYobject == null) - firstXYobject = plotObject; - dataSetNumber++; - } else if (plotObject.type==PlotObject.ARROWS) { - addToLists(headings, data, plotObject, arrowsNumber, /*writeX=*/true, /*writeY=*/true, /*multipleSets=*/nDataSets>1, /*useLabels=*/false); - arrowsNumber++; - } - } - // populate the ResultsTable - int nColumns = headings.size(); - for (int line=0; line headings, ArrayListdata, PlotObject plotObject, - int dataSetNumber, boolean writeX, boolean writeY, boolean multipleSets, boolean useLabels) { - String plotObjectLabel = useLabels ? replaceSpacesEtc(plotObject.label) : null; - if (writeX) { - String label = null; // column header for x column - if (plotObject.type!=PlotObject.ARROWS) { - String plotXLabel = getLabel('x'); - if (dataSetNumber==0 && plotXLabel!=null) { // use x axis label for 1st dataset if permitted - if (useLabels) - label = replaceSpacesEtc(plotXLabel); - else if (plotXLabel.startsWith(" ") && plotXLabel.endsWith(" ")) // legacy: always use axis label for 1st data if spaces at start&end - label = plotXLabel.substring(1,plotXLabel.length()-1); - } else if (plotObjectLabel != null && dataSetNumber>0) - label = "X_"+plotObjectLabel; // use "X_" + dataset label - if (label != null && headings.contains(label)) - label = null; // avoid duplicate labels (not possible in ResultsTable) - } - if (label == null) { // create default label if no specific label yet - label = plotObject.type == PlotObject.ARROWS ? "XStart" : "X"; - if (multipleSets) label += dataSetNumber; - } - headings.add(label); - data.add(plotObject.xValues); - } - if (writeY) { - String label = null;; // column header for y column - if (plotObject.type!=PlotObject.ARROWS) { - String plotYLabel = getLabel('y'); - if (dataSetNumber==0 && plotYLabel!=null) { - if (useLabels && plotObjectLabel == null) // use y axis label for 1st dataset if no data set label - label = replaceSpacesEtc(plotYLabel); - else if (plotYLabel.startsWith(" ") && plotYLabel.endsWith(" ")) // legacy: always use axis label for 1st data if spaces at start&end - label = plotYLabel.substring(1,plotYLabel.length()-1); - } - if (plotObjectLabel != null) - label = plotObjectLabel; - if (label != null && headings.contains(label)) - label = null; // avoid duplicate labels (not possible in ResultsTable) - } - if (label == null) { // create default label if no specific label yet - label = plotObject.type == PlotObject.ARROWS ? "YStart" : "Y"; - if (multipleSets) label += dataSetNumber; - } - headings.add(label); - data.add(plotObject.yValues); - } - if (plotObject.xEValues != null) { - String label = plotObject.type == PlotObject.ARROWS ? "XEnd" : "XERR"; - if (multipleSets) label += dataSetNumber; - headings.add(label); - data.add(plotObject.xEValues); - } - if (plotObject.yEValues != null) { - String label = plotObject.type == PlotObject.ARROWS ? "YEnd" : "ERR"; - if (multipleSets) label += dataSetNumber; - headings.add(label); - data.add(plotObject.yEValues); - } - } - - /** Convert a string to a label suitable for a ResultsTable without whitespace, quotes or commas, - * to avoid problems when saving and reading the table. Returns null if an empty string or null. */ - static String replaceSpacesEtc(String s) { - if (s == null) return null; - s = s.trim().replaceAll("[\\s,]", "_").replace("\"","''"); - if (s.length() == 0) return null; - return s; - } - - /** get the number of digits for writing a column to the results table or the clipboard */ - static int getPrecision(float[] values) { - int setDigits = Analyzer.getPrecision(); - int measurements = Analyzer.getMeasurements(); - boolean scientificNotation = (measurements&Measurements.SCIENTIFIC_NOTATION)!=0; - if (scientificNotation) { - if (setDigits max) max = values[i]; - } - } - if (allInteger) - return 0; - int digits = (max - min) > 0 ? getDigits(min, max, MIN_FLOAT_PRECISION*(max-min), 15, 0) : - getDigits(max, MIN_FLOAT_PRECISION*Math.abs(max), 15, 0); - if (setDigits>Math.abs(digits)) - digits = setDigits * (digits < 0 ? -1 : 1); //use scientific notation if needed - return digits; - } - - /** Whether a given flag 'what' is set */ - boolean hasFlag(int what) { - return (pp.axisFlags&what) != 0; - } - - /* Obsolete, replaced by add(shape,x,y). */ - public void addPoints(String dummy, float[] x, float[] y, int shape) { - addPoints(x, y, shape); - } - - /** Plots a histogram from an array using auto-binning. - * @param values array containing the population - * N.Vischer - */ - public void addHistogram(double[] values) { - addHistogram(values, 0, 0); - } - - /** Plots a histogram from an array using the specified bin width. - * @param values array containing the population - * @param binWidth set zero for auto-binning - * N.Vischer - */ - public void addHistogram(double[] values, double binWidth) { - addHistogram(values, binWidth, 0); - } - - /** Plots a histogram of the value distribution (bin counts) from an array - * @param values array containing the values for the population - * @param binWidth set zero for auto-binning - * @param binCenter any x value can be the center of a bin - * N.Vischer - */ - public void addHistogram(double[] values, double binWidth, double binCenter) { - int len = values.length; - double min = Double.POSITIVE_INFINITY; - double max = Double.NEGATIVE_INFINITY; - double[] cleanVals = new double[len]; - int count = 0; - double sum = 0, sum2 = 0; - for (int i = 0; i < len; i++) { - double val = values[i]; - if (!Double.isNaN(val)) { - cleanVals[count++] = val; - sum += val; - sum2 += val * val; - if (val < min) - min = val; - if (val > max) - max = val; - } - } - if (binWidth <= 0) {//autobinning - double stdDev = Math.sqrt(((count * sum2 - sum * sum) / count) / count);//not count - 1 - // use Scott's method (1979 Biometrika, 66:605-610) for optimal binning: 3.49*sd*N^-1/3 - binWidth = 3.49 * stdDev * (Math.pow(count, -1.0 / 3)); - - } - double modCenter = binCenter % binWidth; - double modMin = min % binWidth; - double diff = modMin - modCenter; - double firstBin = min-diff; - while(firstBin - binWidth * 0.499 > min) - firstBin -= binWidth; - int nBins = (int) ((max - firstBin)/binWidth); - double lastBin = firstBin + nBins * binWidth; - while(lastBin + binWidth * 0.499 < max) - lastBin += binWidth; - nBins = (int) Math.round((lastBin - firstBin)/binWidth) + 1; - if (nBins == 1) - nBins = 2; - if (nBins > 9999) { - IJ.error("max bins > 9999"); - return; - } - double[] histo = new double[nBins]; - double[] xValues = new double[nBins]; - for (int i = 0; i < nBins; i++) - xValues[i] = firstBin + i * binWidth; - for (int i = 0; i < count; i++) { - double val = cleanVals[i]; - double indexD = (val - firstBin) / binWidth; - int index = (int) Math.round(indexD); - if (index < 0 || index >= nBins) { - IJ.error("index out of range"); - return; - } else - histo[index]++; - } - add("bar", xValues, histo); - } - - /* Obsolete, replaced by add("error bars",errorBars). */ - public void addErrorBars(String dummy, float[] errorBars) { - addErrorBars(errorBars); - } - - /* Obsolete; replaced by setFont(). */ - public void changeFont(Font font) { - setFont(font); - } - -} - -/** This class contains the properties of the plot, such as size, format, range, etc, except for the data+format (plot contents). - * To enable reading serialized PlotObjects of plots created with previous versions of ImageJ, - * the variable names MUST NEVER be changed! Also any additions should be made after careful thought, - * since they have to be kept for all future versions. */ -class PlotProperties implements Cloneable, Serializable { - /** The serialVersionUID should not be modified, otherwise saved plots won't be readable any more */ - static final long serialVersionUID = 1L; - // - PlotObject frame = new PlotObject(Plot.DEFAULT_FRAME_LINE_WIDTH); //the frame, including background color and axis numbering - PlotObject xLabel = new PlotObject(PlotObject.AXIS_LABEL); //the x axis label (string & font) - PlotObject yLabel = new PlotObject(PlotObject.AXIS_LABEL); //the x axis label (string & font) - PlotObject legend; //the legend (if any) - int width = 0; //canvas width (note: when stored, this must fit the image) - int height = 0; - int axisFlags; //these define axis layout - double[] rangeMinMax; //currentMinMax when writing, sets defaultMinMax when reading - boolean antialiasedText = true; - boolean isFrozen; //modifications (size, range, contents) don't update the ImageProcessor - - /** Returns an array of all PlotObjects defined as PlotProperties. Note that some may be null */ - PlotObject[] getAllPlotObjects() { - return new PlotObject[]{frame, xLabel, xLabel, legend}; - } - - /** Returns the PlotObject for xLabel ('x'), yLabel('y'), frame ('f'; includes number font) or the legend ('l'). */ - PlotObject getPlotObject(char c) { - switch(c) { - case 'x': return xLabel; - case 'y': return yLabel; - case 'f': return frame; - case 'l': return legend; - default: return null; - } - } - - /** A shallow clone that does not duplicate arrays or objects */ - public PlotProperties clone() { - try { - return (PlotProperties)(super.clone()); - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** A deep clone; it also duplicates arrays and pPlotObjects */ - public PlotProperties deepClone() { - PlotProperties pp2 = clone(); //shallow clone - if (frame != null) pp2.frame = frame.deepClone(); - if (xLabel != null) pp2.xLabel = xLabel.deepClone(); - if (yLabel != null) pp2.yLabel = yLabel.deepClone(); - if (legend != null) pp2.legend = legend.deepClone(); - if (rangeMinMax != null) pp2.rangeMinMax = rangeMinMax.clone(); - return pp2; - } - -} // class PlotProperties - -/** This class contains the data and properties for displaying a curve, a set of arrows, a line or a label in a plot, - * as well as the legend, axis labels, and frame (including background and fonts of axis numbering). - * Note that all properties such as lineWidths and Fonts have to be scaled up for high-resolution plots. - * This class allows serialization for writing into tiff files. - * To enable reading serialized PlotObjects of plots created with previous versions of ImageJ, - * the variable names MUST NEVER be changed! Also any additions should be made after careful thought, - * since they have to be kept for all future versions. */ -class PlotObject implements Cloneable, Serializable { - /** The serialVersionUID should not be modified, otherwise saved plots won't be readable any more */ - static final long serialVersionUID = 1L; - /** Constants for the type of objects. These are powers of two so one can use them as masks */ - public final static int XY_DATA = 1, ARROWS = 2, LINE = 4, NORMALIZED_LINE = 8, DOTTED_LINE = 16, - LABEL = 32, NORMALIZED_LABEL = 64, LEGEND = 128, AXIS_LABEL = 256, FRAME = 512, SHAPES = 1024; - /** mask for recovering font style from the flags */ - final static int FONT_STYLE_MASK = 0x0f; - /** flag for the data set passed with the constructor. Note that 0 to 0x0f are reserved for fonts modifiers, 0x010-0x800 are reserved for legend modifiers */ - public final static int CONSTRUCTOR_DATA = 0x1000; - /** flag for hiding a PlotObject */ - public final static int HIDDEN = 0x2000; - /** Type of the object; XY_DATA stands for curve or markers, can be also ARROWS ... SHAPES */ - public int type = XY_DATA; - /** bitwise combination of flags, or the position of a legend */ - public int flags; - /** Options, currently only for FRAME, see Plot.setOptions */ - public String options; - /** The x and y data arrays and the error bars (if non-null). These arrays also serve as x0, y0, x1, y1 - * arrays for plotting arrays of arrows */ - public float[] xValues, yValues, xEValues, yEValues; - /** For SHAPES: For boxplots with whiskers ('boxes'), elements of the ArrayList are float[6] with x and all 5 y values - * (for 'boxesx', y and all 5 x values), for 'rectangles', float[4] with x1, y1, x2, y2. */ - public ArrayList shapeData; - /** For SHAPES only, shape type & options. Currently implemented: 'boxes', 'boxesx' (box plots with whiskers), 'rectangles', 'redraw_grid' */ - public String shapeType; //e.g. "boxes width=20" - /** Type of the points, such as Plot.LINE, Plot.CROSS etc. (for type = XY_DATA) */ - public int shape; - /** The line width in pixels for 'normal' plots (for high-resolution plots, to be multiplied by a scale factor) */ - public float lineWidth; - /** The color of the object, must not be null */ - public Color color; - /** The secondary color (for filling closed symbols and for the line of CIRCLES_AND_LINE, may be null for unfilled/default */ - public Color color2; - /** Labels and lines: Position (NORMALIZED objects: relative units 0...1). */ - public double x, y; - /** Lines only: End position */ - public double xEnd, yEnd; - /** Dotted lines only: step */ - public int step; - /** A label for the y data of the curve, a text to draw, or the text of a legend (tab-delimited lines) */ - public String label; - /** Labels only: Justification can be Plot.LEFT, Plot.CENTER or Plot.RIGHT */ - public int justification; - /** Macro code for drawing symbols */ - public String macroCode; - /** Text objects (labels, legend, axis labels) only: the font; maybe null for default. This is not serialized (transient) */ - private transient Font font; - /** String for representation of the font family (for Serialization); may be null for default. Font style is in flags, font size in fontSize. */ - private String fontFamily; - /** Font size (for Serialization), for 'normal' plots (for high-resolution plots, to be multiplied by a scale factor) */ - private float fontSize; - - - /** Generic constructor */ - PlotObject(int type) { - this.type = type; - } - - /** Constructor for XY_DATA, i.e., a curve or set of points */ - PlotObject(float[] xValues, float[] yValues, float[] yErrorBars, int shape, float lineWidth, Color color, Color color2, String yLabel) { - this.type = XY_DATA; - this.xValues = xValues; - this.yValues = yValues; - this.yEValues = yErrorBars; - this.shape = shape; - this.lineWidth = lineWidth; - this.color = color; - this.color2 = color2; - this.label = yLabel; - if (shape==Plot.CUSTOM) - this.macroCode = yLabel; - } - - /** Constructor for a set of arrows */ - PlotObject(float[] x1, float[] y1, float[] x2, float[] y2, float lineWidth, Color color) { - this.type = ARROWS; - this.xValues = x1; - this.yValues = y1; - this.xEValues = x2; - this.yEValues = y2; - this.lineWidth = lineWidth; - this.color = color; - } - - /** Constructor for a set of shapes */ - PlotObject(String shapeType, ArrayList shapeData, float lineWidth, Color color, Color color2) { - this.type = SHAPES; - this.shapeData = shapeData; - this.shapeType = shapeType; - this.lineWidth = lineWidth; - this.color = color; - this.color2 = color2; - } - - /** Constructor for a line */ - PlotObject(double x, double y, double xEnd, double yEnd, float lineWidth, int step, Color color, int type) { - this.type = type; - this.x = x; - this.y = y; - this.xEnd = xEnd; - this.yEnd = yEnd; - this.lineWidth = lineWidth; - this.step = step; - this.color = color; - } - - /** Constructor for a label or NORMALIZED_LABEL */ - PlotObject(String label, double x, double y, int justification, Font font, Color color, int type) { - this.type = type; - this.label = label; - this.x = x; - this.y = y; - this.justification = justification; - setFont(font); - this.color = color; - } - - /** Constructor for the legend. flags is bitwise or of TOP_LEFT etc. and LEGEND_TRANSPARENT if desired. - * Note that the labels in the legend are those of the data plotObjects */ - PlotObject(float lineWidth, Font font, Color color, int flags) { - this.type = LEGEND; - this.lineWidth = lineWidth; - setFont(font); - this.color = color; - this.flags = flags; - } - - /** Constructor for the frame, including axis numbers. In the current version, the primary color (line color) is always black */ - PlotObject(float lineWidth) { - this.type = FRAME; - this.color = Color.black; - this.lineWidth = lineWidth; - } - - /** Whether a given flag 'what' is set */ - boolean hasFlag(int what) { - return (flags&what) != 0; - } - - /** Sets a given flag */ - void setFlag(int what) { - flags |= what; - } - - /** Unsets a given flag */ - void unsetFlag(int what) { - flags = flags & (~what); - } - - /** Whether an XY_DATA object has a curve to draw */ - boolean hasCurve() { - return type == XY_DATA && (shape == Plot.LINE || shape == Plot.CONNECTED_CIRCLES || shape == Plot.FILLED); - } - - /** Whether an XY_DATA object has markers to draw */ - boolean hasMarker() { - return type == XY_DATA && (shape == Plot.CIRCLE || shape == Plot.X || shape == Plot.BOX || shape == Plot.TRIANGLE - || shape == Plot.CROSS || shape == Plot.DIAMOND || shape == Plot.DOT || shape == Plot.CONNECTED_CIRCLES - || shape == Plot.CUSTOM); - } - - /** Whether an XY_DATA object has markers that can be filled */ - boolean hasFilledMarker() { - return type == XY_DATA && color2 != null && (shape == Plot.CIRCLE || shape == Plot.BOX || shape == Plot.TRIANGLE || - shape == Plot.DIAMOND || shape == Plot.CONNECTED_CIRCLES); - } - - /** Size of the markers for an XY_DATA object with markers */ - int getMarkerSize() { - if (lineWidth<=1) - return 5; - else if (lineWidth<=3) - return 7; - else - return (int)(lineWidth+4); - } - - /** Sets the font. Also writes font properties for serialization. */ - void setFont(Font font) { - if (font == this.font) return; - this.font = font; - if (font == null) { - fontFamily = null; - } else { - fontFamily = font.getFamily(); - flags = (flags & ~FONT_STYLE_MASK) | font.getStyle(); - fontSize = font.getSize2D(); - } - } - - /** Returns the font, or null if none specified */ - Font getFont() { - if (font == null && fontFamily != null) //after recovery from serialization, create the font from its description - font = FontUtil.getFont(fontFamily, flags&FONT_STYLE_MASK, fontSize); - return font; - } - - /** Returns the font size */ - float getFontSize() { - return fontSize; - } - - /** Returns all data xValues, yValues, xEValues, yEValues as a float[][] array. Note that future versions may have more data. */ - float[][] getAllDataValues() { - return new float[][] {xValues, yValues, xEValues, yEValues}; - } - - /** A shallow clone that does not duplicate arrays or objects */ - public PlotObject clone() { - try { - return (PlotObject)(super.clone()); - } catch (CloneNotSupportedException e) { - return null; - } - } - - /** A deep clone, which duplicates arrays etc. - * Note that colors & font are not cloned; it is assumed that these wil not be modified but replaced, - * so the clone remains unaffected */ - public PlotObject deepClone() { - PlotObject po2 = clone(); - if (xValues != null) po2.xValues = xValues.clone(); - if (yValues != null) po2.yValues = yValues.clone(); - if (xEValues != null) po2.xEValues = xEValues.clone(); - if (yEValues != null) po2.yEValues = yEValues.clone(); - if (shapeData != null) po2.shapeData = cloneArrayList(shapeData); - return po2; - } - - /** A clone of an array list one level deeper than a shallow clone. - * The clone() method of the objects in the list must be accessible */ - private ArrayList cloneArrayList(ArrayList src) { - ArrayList dest = (ArrayList)(src.clone()); //shallow clone - Class[] noClasses = new Class[0]; - Object[] noObjects = new Object[0]; - for (int i=0; i 1) - super.zoomIn(sx, sy); - else - super.zoomOut(sx, sy); - return; - } - plot.zoom(sx, sy, zoomFactor); - } - - /** - * Implements the Image/Zoom/Original Scale command. Sets the original range of - * the x, y axes (unless the plot is frozen) - */ - public void unzoom() { - if (plot == null || plot.isFrozen()) { - super.unzoom(); - return; - } - resetMagnification(); - plot.setLimitsToDefaults(true); - } - - /** - * Implements the Image/Zoom/View 100% command: Sets the original frame size as - * specified in Edit/Options/Plots (unless the plot is frozen) - */ - public void zoom100Percent() { - if (plot == null || plot.isFrozen()) { - super.zoom100Percent(); - return; - } - resetMagnification(); - plot.setFrameSize(PlotWindow.plotWidth, PlotWindow.plotHeight); - } - - /** Resizes the plot (unless frozen) to fit the window */ - public void fitToWindow() { - if (plot == null || plot.isFrozen()) { - super.fitToWindow(); - return; - } - ImageWindow win = imp.getWindow(); - if (win == null) - return; - Rectangle bounds = win.getBounds(); - Dimension extraSize = win.getExtraSize(); - int width = bounds.width - extraSize.width;// (insets.left+insets.right+ImageWindow.HGAP*2); - int height = bounds.height - extraSize.height;// (insets.top+insets.bottom+ImageWindow.VGAP*2); - // IJ.log("fitToWindow "+bounds+"-> w*h="+width+"*"+height); - resizeCanvas(width, height); - getParent().doLayout(); - } - - /** - * Resizes the canvas when the user resizes the window. To avoid a race - * condition while creating a new window, this is ignored if no window exists or - * the window has not been activated yet. - */ - void resizeCanvas(int width, int height) { - if (plot == null || plot.isFrozen()) { - super.resizeCanvas(width, height); - return; - } - resetMagnification(); - if (width == oldWidth && height == oldHeight) - return; - if (plot == null) - return; - ImageWindow win = imp.getWindow(); - if (win == null || !(win instanceof PlotWindow)) - return; - if (!win.isVisible()) - return; - if (!((PlotWindow) win).wasActivated) - return; // window layout not finished yet? - Dimension minSize = plot.getMinimumSize(); - int plotWidth = width < minSize.width ? minSize.width : width; - int plotHeight = height < minSize.height ? minSize.height : height; - plot.setSize(plotWidth, plotHeight); - setSize(width, height); - oldWidth = width; - oldHeight = height; - ((PlotWindow)win).canvasResized(); - } - - /** - * The image of a PlotCanvas is always shown at 100% magnification unless the - * plot is frozen - */ - public void setMagnification(double magnification) { - if (plot == null || plot.isFrozen()) - super.setMagnification(magnification); - else - resetMagnification(); - } - - /** - * Scrolling a PlotCanvas is updating the plot, not viewing part of the plot, - * unless the plot is frozen - */ - public void setSourceRect(Rectangle r) { - if (plot.isFrozen()) - super.setSourceRect(r); - else - resetMagnification(); - } - - void resetMagnification() { - magnification = 1.0; - srcRect.x = 0; - srcRect.y = 0; - } - - /** - * overrides ImageCanvas.setupScroll; if plot is not frozen, scrolling modifies - * the plot data range - */ - protected void setupScroll(int ox, int oy) { - if (plot.isFrozen()) { - super.setupScroll(ox, oy); - return; - } - xMouseStart = ox; - yMouseStart = oy; - xScrolled = 0; - yScrolled = 0; - } - - /** - * overrides ImageCanvas.scroll; if plot is not frozen, scrolling modifies the - * plot data range - */ - protected void scroll(int sx, int sy) { - if (plot.isFrozen()) { - super.scroll(sx, sy); - return; - } - if (sx == 0 && sy == 0) - return; - if (xScrolled == 0 && yScrolled == 0) - plot.saveMinMax(); - int dx = sx - xMouseStart; - int dy = sy - yMouseStart; - plot.scroll(dx - xScrolled, dy - yScrolled); - xScrolled = dx; - yScrolled = dy; - Thread.yield(); - } - - /** overrides ImageCanvas.mouseExited; removes 'range' arrows */ - public void mouseExited(MouseEvent e) { - ImageWindow win = imp.getWindow(); - if (win instanceof PlotWindow) - ((PlotWindow) win).mouseExited(e); - super.mouseExited(e); - } - - /** - * overrides ImageCanvas.mousePressed: no further processing of clicks on - * 'range' arrows - */ - public void mousePressed(MouseEvent e) { - /* Changed for Bio7! */ - - WindowManager.setTempCurrentImage(imp); - WindowManager.setCurrentWindow(imp.getWindow()); - - /* import to set current Panel! */ - CanvasView.setCurrent((JPanel) this.getParent()); - - java.awt.EventQueue.invokeLater(new Runnable() { - public void run() { - ImageWindow wind = imp.getWindow(); - if (wind != null) { - Frame frameSwtAwt = wind.getSwtAwtMain().getFrame(); - if (frameSwtAwt != null) { - - if (frameSwtAwt != null) - frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, WindowEvent.WINDOW_ACTIVATED)); - // frameSwtAwt.dispatchEvent(new WindowEvent(frameSwtAwt, - // WindowEvent.WINDOW_GAINED_FOCUS)); - - if (PlotCanvas.this.isFocusOwner() == false) { - PlotCanvas.this.requestFocus(); - - } - } - } - } - }); - - rangeArrowIndexWhenPressed = getRangeArrowIndex(e); - if (rangeArrowIndexWhenPressed < 0) - super.mousePressed(e); - } - - /** Overrides ImageCanvas.mouseReleased, handles clicks on 'range' arrows */ - public void mouseReleased(MouseEvent e) { - if (rangeArrowIndexWhenPressed >= 0 && rangeArrowIndexWhenPressed == getRangeArrowIndex(e)) - plot.zoomOnRangeArrow(rangeArrowIndexWhenPressed); - else - super.mouseReleased(e); - } - - /* - * Changed for Bio7! We have no visible PlotWindow so we implement the mouse - * listener here! - */ - - public void mouseWheelMoved(MouseWheelEvent e) { - ImageCanvas ic = imp.getCanvas(); - if (plot.isFrozen() || !(ic instanceof PlotCanvas)) { // frozen plots are like normal images - super.mouseWheelMoved(e); - return; - } - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - if (e.getX() < plot.leftMargin || e.getX() > plot.leftMargin + plot.frameWidth)// n__ - return; - if (e.getY() < plot.topMargin || e.getY() > plot.topMargin + plot.frameHeight) - return; - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - if (ctrl || IJ.shiftKeyDown()) { - double zoomFactor = rotation < 0 ? Math.pow(2, 0.2) : Math.pow(0.5, 0.2); - Point loc = ic.getCursorLoc(); - int x = ic.screenX(loc.x); - int y = ic.screenY(loc.y); - ((PlotCanvas) ic).zoom(x, y, zoomFactor); - } else if (IJ.spaceBarDown()) - plot.scroll(rotation * amount * Math.max(ic.imageWidth / 50, 1), 0); - else - plot.scroll(0, rotation * amount * Math.max(ic.imageHeight / 50, 1)); - } - - /** - * Returns the index of the arrow for modifying the range when the mouse click - * was at such an arrow, otherwise -1 - */ - int getRangeArrowIndex(MouseEvent e) { - ImageWindow win = imp.getWindow(); - int rangeArrowIndex = -1; - if (win instanceof PlotWindow) { - int x = e.getX(); - int y = e.getY(); - rangeArrowIndex = ((PlotWindow) win).getRangeArrowIndex(x, y); - } - return rangeArrowIndex; - } -} diff --git a/com.eco.bio7.image/src/ij/gui/PlotContentsDialog.java b/com.eco.bio7.image/src/ij/gui/PlotContentsDialog.java deleted file mode 100644 index 5fe72bfed..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotContentsDialog.java +++ /dev/null @@ -1,670 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.measure.CurveFitter; -import ij.measure.Minimizer; -import ij.text.TextWindow; -import ij.measure.ResultsTable; -import ij.plugin.Colors; -import ij.plugin.frame.Recorder; -import ij.util.Tools; -import java.awt.*; -import java.awt.event.*; -import java.util.Arrays; -import java.util.Vector; -import java.util.ArrayList; - -/** This class implements the Plot Window's Data>"Add from Plot", "Add form Table", "Add Fit" and - * "More>Contents Style" dialogs - */ -public class PlotContentsDialog implements DialogListener { - /** Types of dialog (ERROR suppresses the dialog after an invalid call of a constructor) */ - public final static int ERROR=-1, STYLE=0, ADD_FROM_PLOT=1, ADD_FROM_TABLE=2, ADD_FROM_ARRAYS=3, ADD_FIT=4; - /** Dialog headings for each dialogType >= 0 */ - private static final String[] HEADINGS = new String[] {"Plot Contents Style", "Add From Plot", "Plot From Table", "Add Plot Data", "Add Fit"}; - private Plot plot; // the plot we work on - private int dialogType; // determines what to do: ADD_FORM_PLOT, etc. - private double[] savedLimits; // previous plot range, for undo upon cancel - GenericDialog gd; - private int currentObjectIndex = -1; - private Choice objectChoice; - private Choice symbolChoice; - private TextField colorField, color2Field, labelField, widthField; - private Checkbox visibleCheckbox; - private boolean creatingPlot; // for creating plots; dialogType determines source - private Choice plotChoice; // for "Add from Plot" - private Plot[] allPlots; - private String[] allPlotNames; - private static Plot previousPlot; - private static int previousPlotObjectIndex; - private int defaultPlotIndex, defaultObjectIndex; - private int currentPlotNumObjects; - private Choice tableChoice; // for "Add from Table" - final static int N_COLUMNS = 4; // number of data columns that we can have; x, y, xE, yE - private int nColumnsToUse = N_COLUMNS; // user may restrict to 2, for not having error bars - private Choice[] columnChoice = new Choice[N_COLUMNS]; - private final static String[] COLUMN_NAMES = new String[] {"X:", "Y:", "X Error:", "Y Error:"}; - private final static boolean[] COLUMN_ALLOW_NONE = new boolean[] {true, false, true, true}; //y data cannot be null - private ResultsTable[] allTables; - private String[] allTableNames; - private static String previousTableName; - private static int[] previousColumns = new int[]{1, 1, 0, 0}; //must be N_COLUMNS elements - private static int defaultTableIndex; - private static int[] defaultColumnIndex = new int[N_COLUMNS]; - private String[] arrayHeadings; // for "Add from Arrays" - private ArrayList arrayData; - private Choice fitDataChoice; // for "Add Fit" - private Choice fitFunctionChoice; - private Thread fittingThread; - private static String lastFitFunction = CurveFitter.fitList[0]; - private String curveFitterStatusString; - private static String previousColor="blue", previousColor2="#a0a0ff", previousSymbol="Circle"; - private static double previousLineWidth = 1; - private static final String[] PLOT_COLORS = new String[] {"blue", "red", "black", "#00c0ff", "#00e000", "gray", "#c08060", "magenta"}; - - - /** Prepares a new PlotContentsDialog for an existing plot. Use showDialog thereafter. - * @param dialogType may be STYLE (contents style), ADD_FROM_PLOT (add object from other plot), ADD_FROM_TABLE, and ADD_FIT */ - public PlotContentsDialog(Plot plot, int dialogType) { - this.plot = plot; - this.dialogType = plot == null ? ERROR : dialogType; - if (plot != null) currentPlotNumObjects = plot.getNumPlotObjects(); - } - - /** Prepares a new PlotContentsDialog for creating a new plot using data from a ResultsTable. - * Use showDialog thereafter. */ - public PlotContentsDialog(String title, ResultsTable rt) { - creatingPlot = true; - dialogType = ADD_FROM_TABLE; - if (rt == null || !isValid(rt)) { - IJ.error("Cant Create Plot","No (results) table or no data in "+title); - dialogType = ERROR; - } - plot = new Plot("Plot of "+title, "x", "y"); - allTables = new ResultsTable[] {rt}; - allTableNames = new String[] {title}; - } - - /** Prepares a new PlotContentsDialog for creating a new plot using float[] arrays as data. - * Each 'data' array in the ArrayList must have a corresponding element in the 'headings' array. - * 'defaultHeadings' may contain the headings of the items selected initially for x, y, x error and y error, respectively. - * 'defaultHeadings' and each of its entries may be null, and the array may have any length. */ - public PlotContentsDialog(String title, String[] headings, String[] defaultHeadings, ArrayList data) { - creatingPlot = true; - dialogType = ADD_FROM_ARRAYS; - this.arrayHeadings = headings; - this.arrayData = data; - plot = new Plot(title, "x", "y"); - setDefaultColumns(defaultHeadings); - } - - /** Prepares a new PlotContentsDialog for adding data from float[] arrays to a plot. - * Each 'data' array in the ArrayList must have a corresponding element in the 'headings' array. - * 'defaultHeadings' may contain the headings of the items selected initially for x, y, x error and y error, respectively. - * 'defaultHeadings' and each of its entries may be null, and the array may have any length. */ - public PlotContentsDialog(Plot plot, String[] headings, String[] defaultHeadings, ArrayList data) { - dialogType = ADD_FROM_ARRAYS; - this.plot = plot; - this.arrayHeadings = headings; - this.arrayData = data; - setDefaultColumns(defaultHeadings); - } - - /** Avoids showing a selection for the error bars; must be called before showDialog. */ - public void noErrorBars() { - nColumnsToUse = 2; // only x, y columns can be selected - } - - /** Shows the dialog, with a given parent Frame (may be null) */ - public void showDialog(Frame parent) { - if (dialogType == ERROR) return; - if (!creatingPlot) savedLimits = plot.getLimits(); - plot.savePlotObjects(); - String[] designations = plot.getPlotObjectDesignations(); - if (dialogType == STYLE && designations.length==0) { - IJ.error("Empty Plot"); - return; - } else if (dialogType == ADD_FROM_PLOT) { - prepareAddFromPlot(); - if (allPlots.length == 0) return; //should never happen; we have at least the current plot - } else if (dialogType == ADD_FROM_TABLE && !creatingPlot) { - prepareAddFromTable(); - if (allTables.length == 0) return; //should never happen; PlotWindow should not enable if no table - } - if ((dialogType == ADD_FROM_TABLE || dialogType == ADD_FROM_ARRAYS) && !creatingPlot) - suggestColor(); - if (parent == null && plot.getImagePlus() != null) - parent = plot.getImagePlus().getWindow(); - gd = parent == null ? new GenericDialog(HEADINGS[dialogType]) : - new GenericDialog(HEADINGS[dialogType], parent); - IJ.wait(100); //sometimes needed to avoid hanging? - if (dialogType == STYLE) { - gd.addChoice("Item:", designations, designations[0]); - objectChoice = (Choice)(gd.getChoices().get(0)); - currentObjectIndex = objectChoice.getSelectedIndex(); - } else if (dialogType == ADD_FROM_PLOT) { - gd.addChoice("Select Plot:", allPlotNames, allPlotNames[defaultPlotIndex]); - gd.addChoice("Item to Add:", new String[]{""}, ""); // will be set up by makeSourcePlotObjects - Vector choices = gd.getChoices(); - plotChoice = (Choice)(choices.get(0)); - objectChoice = (Choice)(choices.get(1)); - makeSourcePlotObjects(); - } else if (dialogType == ADD_FROM_TABLE) { - gd.addChoice("Select Table:", allTableNames, allTableNames[defaultTableIndex]); - tableChoice = (Choice)(gd.getChoices().get(0)); - if (creatingPlot) tableChoice.setEnabled(false); // we can't select the table, we have only one - } else if (dialogType == ADD_FIT) { - String[] dataSources = plot.getDataObjectDesignations(); - if (dataSources.length == 0) { - IJ.error("No Data For Fitting"); - return; - } - gd.addChoice("Fit Data Set:", dataSources, dataSources[0]); - gd.addChoice("Fit Function:", new String[0], ""); - Vector choices = gd.getChoices(); - fitDataChoice = (Choice)(choices.get(0)); - fitFunctionChoice = (Choice)(choices.get(1)); - if (dataSources.length == 1) - fitDataChoice.setEnabled(false); - for (int i=0; i 0) - Recorder.recordString("Plot.add(\"xerror\", Table.getColumn(\""+ - columnChoice[2].getSelectedItem()+"\", \""+tableChoice.getSelectedItem()+"\"));\n"); - if (columnChoice[3].getSelectedIndex() > 0) - Recorder.recordString("Plot.add(\"error\", Table.getColumn(\""+ - columnChoice[3].getSelectedItem()+"\", \""+tableChoice.getSelectedItem()+"\"));\n"); - } - Recorder.recordString("Plot.setStyle("+currentObjectIndex+", \""+getStyleString()+"\");\n"); - } - } - - public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { - if (e==null) - return true; //gets called with e=null upon OK - boolean setStyle = false; - if (dialogType == STYLE) { - int objectIndex = objectChoice.getSelectedIndex(); // no getNextChoice since Choices depend on dialog type - setStyle = (e.getSource() != objectChoice); - if (e.getSource() == objectChoice) { - setDialogStyleFields(objectIndex); - currentObjectIndex = objectIndex; - } else - setStyle = true; - } else if (dialogType == ADD_FROM_PLOT) { - if (e.getSource() == plotChoice) { - makeSourcePlotObjects(); - addObjectFromPlot(); - } else if (e.getSource() == objectChoice) { - addObjectFromPlot(); - } else - setStyle = true; - } else if (dialogType == ADD_FROM_TABLE || dialogType == ADD_FROM_ARRAYS) { - if (e.getSource() == tableChoice) { - makeSourceColumns(); - addObjectFromTable(); - } else { - boolean columnChanged = false; - for (int c=0; c 0 ? label : null); - } - } - - /** Returns the style String for Plot.setPlotObjectStyle from the dialog fields */ - private String getStyleString() { - String color = colorField.getText(); - String color2 = color2Field.getText(); - double width = Tools.parseDouble(widthField.getText()); - String symbol = symbolChoice.getSelectedItem(); - Boolean visible = visibleCheckbox.getState(); - String style = color.trim()+","+color2.trim()+","+(float)width+","+ symbol+(visible?"":"hidden"); - return style; - } - - /** Sets the style fields of the dialog according to the style of the PlotObject having the - * index given. Does nothing with index < 0 */ - private void setDialogStyleFields(int index) { - if (index < 0) return; - Checkbox visibleC = (Checkbox)gd.getCheckboxes().get(0); - String styleString = plot.getPlotObjectStyle(index); - String designation = plot.getPlotObjectDesignations()[index].toLowerCase(); - boolean isData = designation.startsWith("data"); - boolean isText = designation.startsWith("text"); - boolean isBox = designation.startsWith("shapes") && - (designation.contains("boxes") || designation.contains("rectangles")); - boolean isGrid = designation.startsWith("shapes") && designation.contains("redraw_grid"); - - String[] items = styleString.split(","); - colorField.setText(items[0]); - color2Field.setText(items[1]); - widthField.setText(items[2]); - if (items.length >= 4) - symbolChoice.select(items[3]); - labelField.setText(isData ? plot.getPlotObjectLabel(index) : ""); - visibleC.setState(!styleString.contains("hidden")); - - colorField.setEnabled(!isGrid); //grid color is fixed - color2Field.setEnabled(isData || isBox);//only (some) data symbols and boxes have secondary (fill) color - widthField.setEnabled(!isText && !isGrid); //all non-Text types have line width - // visibleC.setEnabled(!isGrid); //allow to hide everything - symbolChoice.setEnabled(isData); //only data have a symbol to choose - labelField.setEnabled(isData); //only data have a label in the legend - } - - - /** Prepare the lists 'allPlots', 'allPlotNames' for the "Add from Plot" dialog. - * Also sets 'defaultPlotIndex', 'defaultObjectIndex' */ - private void prepareAddFromPlot() { - int[] windowIDlist = WindowManager.getIDList(); - ArrayList plotImps = new ArrayList(); - ImagePlus currentPlotImp = null; - for (int windowID : windowIDlist) { - ImagePlus imp = WindowManager.getImage(windowID); - if (imp == null || imp.getWindow() == null) continue; - Plot thePlot = (Plot)(imp.getProperty(Plot.PROPERTY_KEY)); - if (thePlot != null) { - if (thePlot == plot) - currentPlotImp = imp; - else - plotImps.add(imp); - } - } - if (currentPlotImp != null) - plotImps.add(currentPlotImp); // add current plot as the last one (usually not used) - if (plotImps.size() == 0) return; // should never happen; we have at least the current plot - - allPlots = new Plot[plotImps.size()]; - allPlotNames = new String[plotImps.size()]; - defaultPlotIndex = 0; - for (int i=0; i tableWindows = new ArrayList(); - Frame[] windows = WindowManager.getNonImageWindows(); - for (Frame win : windows) { - if (!(win instanceof TextWindow)) continue; - ResultsTable rt = ((TextWindow)win).getResultsTable(); - if (isValid(rt)) - tableWindows.add((TextWindow)win); - } - allTables = new ResultsTable[tableWindows.size()]; - allTableNames = new String[tableWindows.size()]; - defaultTableIndex = 0; - for (int i=0; i 0) { - String[] newHeadings = new String[columnHeadings.length - nBadColumns]; - int i=0; - for (String heading : columnHeadings) //copy 'good' headings - if (heading != null) - newHeadings[i++] = heading; - columnHeadings = newHeadings; - } - } else { // if (dialogType == ADD_FROM_ARRAYS) - columnHeadings = new String[arrayHeadings.length+1]; - System.arraycopy(arrayHeadings, 0, columnHeadings, 1, arrayHeadings.length); - } - columnHeadings[0] = "---"; - for (int c=0; c 0 && previousColumns[c] >= 0) - columnChoice[c].select(Math.min(columnChoice[c].getItemCount()-1, previousColumns[c])); - } - } - - /** For "Add from Table" and "Add from Arrays" adds item to the plot according to the current Choice settings - * and sets the Style fields for it. */ - private void addObjectFromTable() { - float[][] data = getDataArrays(); - if (data[1] == null) return; //no y data? then can't plot - String label = columnChoice[1].getSelectedItem(); //take label from y - int shape = Plot.toShape(symbolChoice.getSelectedItem()); - float lineWidth = (float)(Tools.parseDouble(widthField.getText())); - if (lineWidth > 0) - plot.setLineWidth(lineWidth); - plot.restorePlotObjects(); - if (savedLimits != null) - plot.setLimits(savedLimits); - plot.setColor(colorField.getText(), color2Field.getText()); - plot.addPoints(data[0], data[1], data[3], shape, label); - if (data[2] != null) - plot.addHorizontalErrorBars(data[2]); - if (creatingPlot) { - plot.setXYLabels(data[0]==null ? "x" : columnChoice[0].getSelectedItem(), columnChoice[1].getSelectedItem()); - plot.setLimitsToFit(false); - } else - plot.fitRangeToLastPlotObject(); - currentObjectIndex = plot.getNumPlotObjects()-1; - setDialogStyleFields(currentObjectIndex); - if (dialogType == ADD_FROM_TABLE) - previousTableName = allTableNames[tableChoice.getSelectedIndex()]; - } - - /** For "Add from Table" and "Add from Arrays", tries to set a 'y' data column that has not been plotted yet. */ - private void suggestNewYColumn() { - int nYcolumns = columnChoice[1].getItemCount(); - int currentIndex = columnChoice[1].getSelectedIndex(); - for (int i=0; i= 0) - data[c] = rt.getColumn(index); - previousColumns[c] = columnChoice[c].getSelectedIndex(); - } - } else { //if (dialogType == ADD_FROM_ARRAYS) - for (int c=0; c= 0) - data[c] = arrayData.get(index); - previousColumns[c] = columnChoice[c].getSelectedIndex(); - } - } - return data; - } - - /** Does the curve fit and adds the fit curve to the plot */ - private void addFitCurve() { - plot.restorePlotObjects(); - if (savedLimits != null) - plot.setLimits(savedLimits); - int dataIndex = fitDataChoice.getSelectedIndex(); - float[][] data = plot.getDataObjectArrays(dataIndex); - String fitName = fitFunctionChoice.getSelectedItem(); - int fitType = getIndex(CurveFitter.fitList, fitName); - CurveFitter cf = new CurveFitter(Tools.toDouble(data[0]), Tools.toDouble(data[1])); - cf.doFit(fitType); - String statusString = "Fit: "+Minimizer.STATUS_STRING[cf.getStatus()]; - if (cf.getStatus() == Minimizer.SUCCESS) - statusString += ", sum residuals ^2 = "+(float)(cf.getSumResidualsSqr()); - IJ.showStatus(statusString); - curveFitterStatusString = "Fit for "+plot.getTitle()+": "+fitDataChoice.getSelectedItem()+cf.getResultString(); //will be shown in Log when done - - double[] plotMinMax = plot.getLimits(); - double[] dataMinMax = Tools.getMinMax(data[0]); - double min = Math.min(plotMinMax[0], dataMinMax[0]); - double max = Math.max(plotMinMax[1], dataMinMax[1]); - double plotSpan = Math.abs(plotMinMax[1] - plotMinMax[0]); - double dataSpan = Math.abs(dataMinMax[1] - dataMinMax[0]); - double rangeFactor = Math.max(plotSpan/dataSpan, dataSpan/plotSpan); - if (rangeFactor > 20) rangeFactor = 20; - int nPoints = (int)(1000*rangeFactor); //finer data point spacing if we will want to zoom out or in - float[] xFit = new float[nPoints]; - float[] yFit = new float[nPoints]; - for (int i=0; i=3; - else - return columnHeadingStr.length() >= 1; - - } - - /** For "Add from Arrays", sets default columns from the colums titles */ - private void setDefaultColumns(String[] defaultHeadings) { - if (defaultHeadings == null) return; - for (int i=0; i 190 ? 255 : 255 - (int)(0.4*(255-v)); - } -} diff --git a/com.eco.bio7.image/src/ij/gui/PlotDialog.java b/com.eco.bio7.image/src/ij/gui/PlotDialog.java deleted file mode 100644 index bad6e4e9e..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotDialog.java +++ /dev/null @@ -1,606 +0,0 @@ -package ij.gui; - -import ij.*; -import ij.process.*; -import ij.plugin.frame.Recorder; -import java.awt.*; -import java.util.Vector; - -import org.eclipse.swt.widgets.Display; - -import com.eco.bio7.image.Util; - -/* - * This class contains dialogs for formatting of plots (range, axes, labels, legend, creating a high-resolution plot) - * Adding and formatting of contents (curves, symbols, ...) is in PlotContentsStyleDialog - */ - -public class PlotDialog implements DialogListener { - - /** - * Types of dialog. Note that 10-14 must be the same as the corresponding - * PlotWindow.rangeArrow numbers - */ - public static final int SET_RANGE = 0, AXIS_OPTIONS = 1, LEGEND = 2, HI_RESOLUTION = 3, TEMPLATE = 4, //5-9 spare - X_LEFT = 10, X_RIGHT = 11, Y_BOTTOM = 12, Y_TOP = 13, X_AXIS = 14, Y_AXIS = 15; - /** Dialog headings for the dialogTypes */ - private static final String[] HEADINGS = new String[] { "Plot Range", "Axis Options", "Add Legend", "High-Resolution Plot", "Use Template", null, null, null, null, null, // 5-9 spare - "X Left", "X Right", "Y Bottom", "Y Top", "X Axis", "Y Axis" }; - /** Positions and corresponding codes for legend position */ - 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 }; - /** - * Template "copy what" flag: dialog texts and corresponding bit masks, in the - * sequence as they appear in the dialog - */ - private static final String[] TEMPLATE_FLAG_NAMES = new String[] { "X Range", "Y Range", "Axis Style", "Labels", "Legend", "Contents Style", "Extra Objects (Curves...)", "Window Size" }; - private static final int[] TEMPLATE_FLAGS = new int[] { Plot.X_RANGE, Plot.Y_RANGE, Plot.COPY_AXIS_STYLE, Plot.COPY_LABELS, Plot.COPY_LEGEND, Plot.COPY_CONTENTS_STYLE, Plot.COPY_EXTRA_OBJECTS, - Plot.COPY_SIZE }; - - private Plot plot; - private int dialogType; - private boolean minMaxSaved; //whether plot min&max has been saved for "previous range" - private boolean dialogShowing; //when the dialog is showing, ignore the last call with event null - private Plot[] templatePlots; - - private Checkbox xLogCheckbox, yLogCheckbox; - - //saved dialog options: legend - private static int legendPosNumber = 0; - private static boolean bottomUp; - private static boolean transparentBackground; - //saved dialog options: Axis labels - private static String lastXLabel, lastYLabel; - private static float plotFontSize; - //saved dialog options: High-resolution plot - private static float hiResFactor = 4.0f; - private static boolean hiResAntiAliased = true; - //saved dialog options: Use Template - private static int templateID; - private static int lastTemplateFlags = Plot.COPY_AXIS_STYLE | Plot.COPY_CONTENTS_STYLE; - - /** Constructs a new PlotDialog for a given plot and sets the type of dialog */ - public PlotDialog(Plot plot, int dialogType) { - this.plot = plot; - this.dialogType = dialogType; - } - - /** - * Asks the user for axis scaling; then replot with new scale on the same - * ImageProcessor. The 'parent' frame may be null - */ - public void showDialog(Frame parent) { - if (dialogType == HI_RESOLUTION) { //'make high-resolution plot' dialog has no preview, handled separately - doHighResolutionDialog(parent); - return; - } - plot.savePlotPlotProperties(); - if (dialogType == TEMPLATE) - plot.savePlotObjects(); - - String dialogTitle = dialogType >= X_LEFT && dialogType <= Y_TOP ? "Set Axis Limit..." : (HEADINGS[dialogType] + "..."); - GenericDialog gd = parent == null ? new GenericDialog(dialogTitle) : new GenericDialog(dialogTitle, parent); - if (!setupDialog(gd)) - return; - gd.addDialogListener(this); - dialogItemChanged(gd, null); //preview immediately - dialogShowing = true; - gd.showDialog(); - if (gd.wasCanceled()) { - plot.restorePlotProperties(); - if (dialogType == TEMPLATE) - plot.restorePlotObjects(); - plot.update(); - } else { - if (IJ.recording()) - record(); - String xAxisLabel = plot.getLabel('x'); - if ((dialogType == AXIS_OPTIONS || dialogType == X_AXIS) && xAxisLabel != null && xAxisLabel.length() > 0) - lastXLabel = xAxisLabel; //remember for next time, in case we have none - String yAxisLabel = plot.getLabel('y'); - if ((dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) && yAxisLabel != null && yAxisLabel.length() > 0) - lastYLabel = yAxisLabel; - if (dialogType == SET_RANGE || dialogType == X_AXIS || dialogType == Y_AXIS) - plot.makeLimitsDefault(); - if (dialogType == TEMPLATE) - lastTemplateFlags = plot.templateFlags; - - } - plot.killPlotPropertiesSnapshot(); - if (dialogType == TEMPLATE) - plot.killPlotObjectsSnapshot(); - - ImagePlus imp = plot.getImagePlus(); - ImageWindow win = imp == null ? null : imp.getWindow(); - if (win instanceof PlotWindow) - ((PlotWindow) win).hideRangeArrows(); // arrows etc might be still visible, but the mouse maybe elsewhere - - if (!gd.wasCanceled() && !gd.wasOKed()) { // user has pressed "Set all limits" or "Set Axis Options" button - int newDialogType = (dialogType == SET_RANGE) ? AXIS_OPTIONS : SET_RANGE; - new PlotDialog(plot, newDialogType).showDialog(parent); - } - } - - /** - * Setting up the dialog fields and initial parameters. The input is read in the - * dialogItemChanged method, which must have exactly the same structure of 'if' - * blocks and matching 'get' methods for each input field. - * - * @return false on error - */ - private boolean setupDialog(GenericDialog gd) { - double[] currentMinMax = plot.getLimits(); - 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, 0); - if (dialogType == SET_RANGE || dialogType == X_AXIS) { - gd.addNumericField("X_From", currentMinMax[0], xDigits, 6, "*"); - gd.addToSameRow(); - gd.addNumericField("To", currentMinMax[1], xDigits, 6, "*"); - gd.setInsets(0, 20, 0); //top, left, bottom - 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))); - xLogCheckbox = lastCheckboxAdded(gd); - enableDisableLogCheckbox(xLogCheckbox, currentMinMax[0], currentMinMax[1]); - } - int yDigits = plot.logYAxis ? -2 : Plot.getDigits(currentMinMax[2], currentMinMax[3], 0.005 * Math.abs(currentMinMax[3] - currentMinMax[2]), 6, 0); - if (dialogType == SET_RANGE || dialogType == Y_AXIS) { - gd.setInsets(20, 0, 3); //top, left, bottom - gd.addNumericField("Y_From", currentMinMax[2], yDigits, 6, "*"); - gd.addToSameRow(); - gd.addNumericField("To", currentMinMax[3], yDigits, 6, "*"); - 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))); - yLogCheckbox = lastCheckboxAdded(gd); - enableDisableLogCheckbox(yLogCheckbox, currentMinMax[2], currentMinMax[3]); - } - if (dialogType >= X_LEFT && dialogType <= Y_TOP) { - int digits = dialogType < Y_BOTTOM ? xDigits : yDigits; - gd.addNumericField(HEADINGS[dialogType], currentMinMax[dialogType - X_LEFT], digits, 6, "*"); - } - - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS || dialogType == Y_AXIS) { - int flags = plot.getFlags(); - 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 }; - int rows = xFlags.length; - int columns = dialogType == AXIS_OPTIONS ? 2 : 1; - String[] allLabels = new String[rows * columns]; - boolean[] defaultValues = new boolean[rows * columns]; - String[] headings = dialogType == AXIS_OPTIONS ? new String[] { "X Axis", "Y Axis" } : null; - int i = 0; - for (int l = 0; l < xFlags.length; l++) { - String label = labels[l]; - boolean xFlag = getFlag(flags, xFlags[l]); - boolean yFlag = getFlag(flags, xFlags[l] << 1); //y flags are shifted up one bit - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) { - allLabels[i] = labels[l]; - defaultValues[i++] = xFlag; - } - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) { - allLabels[i] = labels[l]; - defaultValues[i++] = yFlag; - } - } - if (dialogType == X_AXIS || dialogType == Y_AXIS) - gd.setInsets(15, 20, 0); //top, left, bottom - gd.addCheckboxGroup(rows, columns, allLabels, defaultValues, headings); - if (dialogType == AXIS_OPTIONS) - gd.setInsets(15, 0, 5); //top, left, bottom - - String plotXLabel = plot.getLabel('x'); - String plotYLabel = plot.getLabel('y'); - if ((plotXLabel == null || plotXLabel.equals("Distance (pixels)") || plotXLabel.equals("Distance ( )")) && lastXLabel != null) - plotXLabel = lastXLabel; // suggest last dialog entry if default profile label - if ((plotYLabel == null || plotYLabel.equals("Gray Value")) && lastYLabel != null) - plotYLabel = lastYLabel; - int nChars = 20; - if ((plotXLabel != null && plotXLabel.startsWith("{")) || (plotYLabel != null && plotYLabel.startsWith("{"))) { - nChars = Math.max(nChars, plotXLabel.length()); - nChars = Math.max(nChars, plotYLabel.length()); - } - if (nChars > 80) - nChars = 80; - //plotXLabel = plotXLabel.replace("\n", "|"); //multiline label currently no supported by Plot class - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) - gd.addStringField("X Axis Label", plotXLabel, nChars); - //plotYLabel = plotYLabel.replace("\n", "|"); - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) - gd.addStringField("Y Axis Label", plotYLabel, nChars); - } - if (dialogType == SET_RANGE || dialogType == X_AXIS || dialogType == Y_AXIS) { - Font smallFont = IJ.font10; - gd.setInsets(10, 0, 0); //top, left, bottom - gd.addMessage("* Leave empty for automatic range", smallFont, Color.gray); - gd.setInsets(0, 0, 0); - gd.addMessage("** Requires limits > 0 and max/min > 3", smallFont, Color.gray); - if (dialogType == X_AXIS || dialogType == Y_AXIS) { - gd.setInsets(0, 0, 0); - gd.addMessage(" Label supports !!sub-!! and ^^superscript^^", smallFont, Color.gray); - } - } - - if (dialogType == AXIS_OPTIONS) { - Font plotFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - Font labelFont = plot.getFont('x'); - if (labelFont == null) - labelFont = plotFont; - Font numberFont = plot.getFont('f'); - if (numberFont == null) - numberFont = plotFont; - gd.addNumericField("Number Font Size", numberFont.getSize2D(), 1); - gd.addNumericField("Label Font Size", labelFont.getSize2D(), 1); - //gd.setInsets(0, 20, 0); // no extra space - gd.addToSameRow(); - gd.addCheckbox("Bold", labelFont.isBold()); - } - if (dialogType == LEGEND) { - String labels = plot.getDataLabels(); - int nLines = labels.split("\n", -1).length; - Font legendFont = plot.getFont('l'); - if (legendFont == null) - legendFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - int lFlags = plot.getObjectFlags('l'); - if (lFlags != -1) { //if we have a legend already - for (int i = 0; i < LEGEND_POSITION_N.length; i++) //determine the position option from the flags - if ((lFlags & Plot.LEGEND_POSITION_MASK) == LEGEND_POSITION_N[i]) { - legendPosNumber = i; - break; - } - transparentBackground = getFlag(lFlags, Plot.LEGEND_TRANSPARENT); - bottomUp = getFlag(lFlags, Plot.LEGEND_BOTTOM_UP); - } - gd.addMessage("Enter Labels for the datasets, one per line.\n"); - - Font smallFont = IJ.font10; - gd.setInsets(0, 20, 0); //top, left, bottom - String msg = "Prepend index plus dual underscore (e.g. '1__MyLabel' )\nto control legend order and to hide non-indexed labels"; - gd.addMessage(msg, smallFont, Color.darkGray); - gd.setInsets(0, 0, 0); - - gd.addTextAreas(labels, null, Math.min(nLines + 1, 20), 40); - gd.addChoice("Legend position", LEGEND_POSITIONS, LEGEND_POSITIONS[legendPosNumber]); - gd.addNumericField("Font Size", legendFont.getSize2D(), 1); - - gd.addCheckbox("Transparent background", transparentBackground); - gd.addCheckbox("Bottom-to-top", bottomUp); - } - if (dialogType == TEMPLATE) { - int[] idList = WindowManager.getIDList(); //create list of plots to use as template - int[] plotIdList = new int[idList.length]; - templatePlots = new Plot[idList.length]; - int nPlots = 0; - for (int id : idList) { - ImagePlus imp = WindowManager.getImage(id); - if (imp == null) - continue; - Plot impPlot = (Plot) (imp.getProperty(Plot.PROPERTY_KEY)); - if (impPlot != null && impPlot != this.plot) { - templatePlots[nPlots] = impPlot; - plotIdList[nPlots++] = id; - } - } - if (nPlots == 0) { - IJ.error("No plot to use as template"); - return false; - } - String[] plotImpTitles = new String[nPlots]; - int defaultTemplateIndex = 0; - for (int i = 0; i < nPlots; i++) { - ImagePlus imp = WindowManager.getImage(plotIdList[i]); - plotImpTitles[i] = imp == null ? "" : imp.getTitle(); - if (imp.getID() == templateID) - defaultTemplateIndex = i; - } - gd.addChoice("Template Plot", plotImpTitles, plotImpTitles[defaultTemplateIndex]); - gd.setInsets(10, 0, 0); //top, left, bottom - gd.addMessage("Copy From Template:"); - gd.setInsets(5, 20, 0); //top, left, bottom - if (lastTemplateFlags == 0) - lastTemplateFlags = Plot.COPY_AXIS_STYLE | Plot.COPY_CONTENTS_STYLE; - for (int i = 0; i < TEMPLATE_FLAGS.length; i++) { - boolean flag = getFlag(lastTemplateFlags, TEMPLATE_FLAGS[i]); - gd.addCheckbox(TEMPLATE_FLAG_NAMES[i], flag); - } - } - // Add a button to access another dialog that might be also desired - if (dialogType >= X_LEFT && dialogType <= Y_TOP) - gd.enableYesNoCancel("OK", "Set All Limits..."); - else if (dialogType == AXIS_OPTIONS) - gd.enableYesNoCancel("OK", "Set Range..."); - else if (dialogType == SET_RANGE) - gd.enableYesNoCancel("OK", "Set Axis Options..."); - return true; - } //setupDialog - - /** - * This method is called when the user changes something in the dialog. Note - * that the 'if's for reading the fields must be exactly the same as those for - * setting up the fields in 'setupDialog' (fields must be also read in the same - * sequence). - */ - public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { - if (dialogShowing && e==null) - return true; //gets called with e=null upon OK; ignore this - boolean livePlot = plot.plotMaker != null; - - if (dialogType == SET_RANGE || dialogType == X_AXIS) { - double[] currentMinMax = plot.getLimits(); - double linXMin = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linXMin = Double.NaN; - double linXMax = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linXMax = Double.NaN; - if (linXMin == linXMax) - return false; - if (!minMaxSaved) { - plot.saveMinMax(); //save for 'Previous Range' in plot menu - minMaxSaved = true; - } - if (livePlot) - plot.templateFlags = setFlag(plot.templateFlags, Plot.X_RANGE, gd.getNextBoolean()); - boolean xLog = gd.getNextBoolean(); - plot.setAxisXLog(xLog); - plot.setLimitsNoUpdate(linXMin, linXMax, currentMinMax[2], currentMinMax[3]); - currentMinMax = plot.getLimits(); - enableDisableLogCheckbox(xLogCheckbox, currentMinMax[0], currentMinMax[1]); - } - if (dialogType == SET_RANGE || dialogType == Y_AXIS) { - double[] currentMinMax = plot.getLimits(); - double linYMin = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linYMin = Double.NaN; - double linYMax = gd.getNextNumber(); - //if (gd.invalidNumber()) - //linYMax = Double.NaN; - if (linYMin == linYMax) - return false; - if (!minMaxSaved) { - plot.saveMinMax(); //save for 'Previous Range' in plot menu - minMaxSaved = true; - } - - if (livePlot) - plot.templateFlags = setFlag(plot.templateFlags, Plot.Y_RANGE, gd.getNextBoolean()); - boolean yLog = gd.getNextBoolean(); - plot.setAxisYLog(yLog); - plot.setLimitsNoUpdate(currentMinMax[0], currentMinMax[1], linYMin, linYMax); - currentMinMax = plot.getLimits(); - enableDisableLogCheckbox(yLogCheckbox, currentMinMax[2], currentMinMax[3]); - } - if (dialogType >= X_LEFT && dialogType <= Y_TOP) { - double newLimit = gd.getNextNumber(); - double[] minMaxCopy = (double[]) (plot.getLimits().clone()); - minMaxCopy[dialogType - X_LEFT] = newLimit; - plot.setLimitsNoUpdate(minMaxCopy[0], minMaxCopy[1], minMaxCopy[2], minMaxCopy[3]); - } - - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS || dialogType == Y_AXIS) { - final int[] xFlags = new int[] { Plot.X_GRID, Plot.X_TICKS, Plot.X_MINOR_TICKS, Plot.X_LOG_TICKS, Plot.X_NUMBERS }; - int rows = xFlags.length; - int columns = dialogType == AXIS_OPTIONS ? 2 : 1; - int flags = 0; - if (dialogType == X_AXIS) - flags = plot.getFlags() & 0xaaaaaaaa; //keep y flags, i.e., odd bits - if (dialogType == Y_AXIS) - flags = plot.getFlags() & 0x55555555; //keep x flags, i.e., even bits - for (int l = 0; l < xFlags.length; l++) { - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) - if (gd.getNextBoolean()) - flags |= xFlags[l]; - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) - if (gd.getNextBoolean()) - flags |= xFlags[l] << 1; //y flags are shifted up one bit; - } - plot.setFormatFlags(flags); - - String xAxisLabel = plot.getLabel('x'); - String yAxisLabel = plot.getLabel('y'); - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS) { - xAxisLabel = gd.getNextString(); - //xAxisLabel = xAxisLabel.replace("|", "\n"); //multiline label currently not supported by Plot class - } - if (dialogType == AXIS_OPTIONS || dialogType == Y_AXIS) { - yAxisLabel = gd.getNextString(); - //yAxisLabel = yAxisLabel.replace("|", "\n"); - } - plot.setXYLabels(xAxisLabel, yAxisLabel); - } - if (dialogType == AXIS_OPTIONS) { - Font plotFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - Font labelFont = plot.getFont('x'); - if (labelFont == null) - labelFont = plotFont; - Font numberFont = plot.getFont('f'); - if (numberFont == null) - numberFont = plotFont; - - float numberFontSize = (float) gd.getNextNumber(); - if (gd.invalidNumber()) - numberFontSize = numberFont.getSize2D(); - if (numberFontSize < 9) - numberFontSize = 9f; - if (numberFontSize > 24) - numberFontSize = 24f; - float labelFontSize = (float) gd.getNextNumber(); - if (gd.invalidNumber()) - labelFontSize = labelFont.getSize2D(); - boolean axisLabelBold = gd.getNextBoolean(); - plot.setFont('f', numberFont.deriveFont(numberFont.getStyle(), numberFontSize)); - plot.setAxisLabelFont(axisLabelBold ? Font.BOLD : Font.PLAIN, labelFontSize); - Font smallFont = new Font("SansSerif", Font.PLAIN, (int) (10 * Prefs.getGuiScale())); - gd.addMessage("Labels support !!sub-!! and ^^superscript^^", smallFont, Color.gray); - } - if (dialogType == LEGEND) { - Font legendFont = plot.getFont('l'); - if (legendFont == null) - legendFont = (plot.currentFont != null) ? plot.currentFont : plot.defaultFont; - - String labels = gd.getNextText(); - legendPosNumber = gd.getNextChoiceIndex(); - int lFlags = LEGEND_POSITION_N[legendPosNumber]; - float legendFontSize = (float) gd.getNextNumber(); - transparentBackground = gd.getNextBoolean(); - bottomUp = gd.getNextBoolean(); - if (bottomUp) - lFlags |= Plot.LEGEND_BOTTOM_UP; - if (transparentBackground) - lFlags |= Plot.LEGEND_TRANSPARENT; - plot.setColor(Color.black); - plot.setLineWidth(1); - plot.setLegend(labels, lFlags); - plot.setFont('l', legendFont.deriveFont(legendFont.getStyle(), legendFontSize)); - } - if (dialogType == TEMPLATE) { - Plot templatePlot = templatePlots[gd.getNextChoiceIndex()]; - ImagePlus imp = templatePlot.getImagePlus(); - if (imp != null) - templateID = imp.getID(); //remember for next time - int templateFlags = 0; - for (int i = 0; i < TEMPLATE_FLAGS.length; i++) - if (gd.getNextBoolean()) - templateFlags |= TEMPLATE_FLAGS[i]; - plot.restorePlotProperties(); - plot.restorePlotObjects(); - plot.useTemplate(templatePlot, templateFlags); - } - - plot.updateImage(); - return true; - } //dialogItemChanged - - /** Macro recording */ - private void record() { - if (Recorder.scriptMode()) - Recorder.recordCall("//plot = IJ.getImage().getProperty(Plot.PROPERTY_KEY);"); - String plotDot = Recorder.scriptMode() ? "plot." : "Plot."; - - if (dialogType == SET_RANGE || dialogType == X_AXIS) - Recorder.recordString(plotDot + (Recorder.scriptMode() ? "setAxisXLog(" : "setLogScaleX(") + plot.hasFlag(Plot.X_LOG_NUMBERS) + ");\n"); - if (dialogType == SET_RANGE || dialogType == Y_AXIS) - Recorder.recordString(plotDot + (Recorder.scriptMode() ? "setAxisYLog(" : "setLogScaleY(") + plot.hasFlag(Plot.Y_LOG_NUMBERS) + ");\n"); - if (dialogType == SET_RANGE || dialogType == X_AXIS || dialogType == Y_AXIS) { - double[] currentMinMax = plot.getLimits(); - int xDigits = plot.logXAxis ? -2 : Plot.getDigits(currentMinMax[0], currentMinMax[1], 0.005 * Math.abs(currentMinMax[1] - currentMinMax[0]), 6, 0); - int yDigits = plot.logYAxis ? -2 : Plot.getDigits(currentMinMax[2], currentMinMax[3], 0.005 * Math.abs(currentMinMax[3] - currentMinMax[2]), 6, 0); - Recorder.recordString(plotDot + "setLimits(" + IJ.d2s(currentMinMax[0], xDigits) + "," + IJ.d2s(currentMinMax[1], xDigits) + "," + IJ.d2s(currentMinMax[2], yDigits) + "," - + IJ.d2s(currentMinMax[3], yDigits) + ");\n"); - } - if (dialogType == AXIS_OPTIONS || dialogType == X_AXIS || dialogType == Y_AXIS) { - int flags = plot.getFlags(); - String xAxisLabel = Recorder.fixString(plot.getLabel('x')); - String yAxisLabel = Recorder.fixString(plot.getLabel('y')); - Font labelFont = plot.getFont('x'); - Font numberFont = plot.getFont('f'); - if (labelFont != null) { - if (Recorder.scriptMode()) - Recorder.recordString("plot.setAxisLabelFont(" + (labelFont.isBold() ? "Font.BOLD," : "Font.PLAIN,") + IJ.d2s(labelFont.getSize2D(), 1) + ");\n"); - else - Recorder.recordString("Plot.setAxisLabelSize(" + IJ.d2s(labelFont.getSize2D(), 1) + ", \"" + (labelFont.isBold() ? "bold" : "plain") + "\");\n"); - } - if (numberFont != null) - Recorder.recordString(plotDot + (Recorder.scriptMode() ? "setFont(-1, " : "setFontSize(") + IJ.d2s(numberFont.getSize2D(), 1) + ");\n"); - Recorder.recordString(plotDot + "setXYLabels(\"" + xAxisLabel + "\", \"" + yAxisLabel + "\");\n"); - Recorder.recordString(plotDot + "setFormatFlags(" + (Recorder.scriptMode() ? "0x" + Integer.toHexString(flags) : '\"' + Integer.toString(flags, 2) + '\"') + ");\n"); - } - if (dialogType == LEGEND) { - String labels = Recorder.fixString(plot.getDataLabels()); - int lFlags = plot.getObjectFlags('l'); - if (Recorder.scriptMode()) { - Recorder.recordCall("plot.setColor(Color.black);"); - Recorder.recordCall("plot.setLineWidth(1);"); - Recorder.recordCall("plot.addLegend(\"" + labels + "\", 0x" + Integer.toHexString(lFlags) + ");"); - } else { - String options = LEGEND_POSITIONS[legendPosNumber]; - if (getFlag(lFlags, Plot.LEGEND_BOTTOM_UP)) - options += " Bottom-To-Top"; - if (getFlag(lFlags, Plot.LEGEND_TRANSPARENT)) - options += " Transparent"; - Recorder.recordString("Plot.addLegend(\"" + labels + "\", \"" + options + "\");\n"); - } - } - - if (Recorder.scriptMode()) - Recorder.recordCall("plot.update();"); - } - - /** The dialog for "Make High Resolution Plot"; it has no preview */ - private void doHighResolutionDialog(Frame parent) { - GenericDialog gd = parent == null ? new GenericDialog(HEADINGS[dialogType]) : new GenericDialog(HEADINGS[dialogType], parent); - String title = plot.getTitle(); - if (title.toLowerCase().endsWith(".tif") || title.toLowerCase().endsWith(".zip")) - title = title.substring(0, title.length()-4); - title += "_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) //more range checking is done in Plot.setScale - hiResFactor = (float) scale; - hiResAntiAliased = !gd.getNextBoolean(); - /*final ImagePlus hiresImp = plot.makeHighResolution(title, hiResFactor, hiResAntiAliased, showIt=true); - *//** - * The following command is needed to have the high-resolution plot as front - * window. Otherwise, as the dialog is owned by the original PlotWindow, the - * WindowManager will see the original plot as active, but the user interface - * will show the high-res plot as foreground window - *//* - EventQueue.invokeLater(new Runnable() {public void run() {IJ.selectWindow(hiresImp.getID());}});*/ - /* Changed for Bio7. Deadlock with activate tab function! */ - Display dis = Util.getDisplay(); - dis.syncExec(new Runnable() { - - public void run() { - String title = plot.getTitle() + "_HiRes"; - - final ImagePlus hiresImp = plot.makeHighResolution(title, hiResFactor, hiResAntiAliased, /* showIt= */true); - IJ.selectWindow(hiresImp.getID()); - } - }); - - if (IJ.recording()) { - if (Recorder.scriptMode()) { - Recorder.recordCall("plot.makeHighResolution(\"" + title + "\"," + hiResFactor + "," + hiResAntiAliased + ",true);"); - } else { - String options = !hiResAntiAliased ? "disable" : ""; - if (options.length() > 0) - options = ",\"" + options + "\""; - Recorder.recordString("Plot.makeHighResolution(\"" + title + "\"," + hiResFactor + options + ");\n"); - } - } - } - - /** - * Disables switching on a checkbox for log range if the axis limits do not - * allow it. The checkbox can be always switched off. - */ - void enableDisableLogCheckbox(Checkbox checkbox, double limit1, double limit2) { - boolean logPossible = limit1 > 0 && limit2 > 0 && (limit1 > 3 * limit2 || limit2 > 3 * limit1); - checkbox.setEnabled(logPossible); - } - - 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; - } - - Checkbox lastCheckboxAdded(GenericDialog gd) { - Vector checkboxes = gd.getCheckboxes(); - return (Checkbox) (checkboxes.get(checkboxes.size() - 1)); - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/PlotMaker.java b/com.eco.bio7.image/src/ij/gui/PlotMaker.java deleted file mode 100644 index ddaef8a3b..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotMaker.java +++ /dev/null @@ -1,15 +0,0 @@ -package ij.gui; -import ij.ImagePlus; - -/** Plugins that generate "Live" profile plots (Profiler and ZAxisProfiler) - displayed in PlotWindows implement this interface. */ -public interface PlotMaker { - - /** Returns a profile plot. */ - public Plot getPlot(); - - /** Returns the ImagePlus used to generate the profile plots. */ - public ImagePlus getSourceImage(); - -} - diff --git a/com.eco.bio7.image/src/ij/gui/PlotVirtualStack.java b/com.eco.bio7.image/src/ij/gui/PlotVirtualStack.java deleted file mode 100644 index 7bac94ed2..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotVirtualStack.java +++ /dev/null @@ -1,84 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import java.util.*; -import java.io.*; - -/** This is a virtual stack of frozen plots. */ -public class PlotVirtualStack extends VirtualStack { - private Vector plots = new Vector(50); - private int bitDepth = 8; - - public PlotVirtualStack(int width, int height) { - super(width, height); - } - - /** Adds a plot to the end of the stack. */ - public void addPlot(Plot plot) { - plots.add(plot.toByteArray()); - if (plot.isColored()) - bitDepth = 24; - } - - /** Returns the pixel array for the specified slice, where {@literal 1<=n<=nslices}. */ - public Object getPixels(int n) { - ImageProcessor ip = getProcessor(n); - if (ip!=null) - return ip.getPixels(); - else - return null; - } - - /** Returns an ImageProcessor for the specified slice, - where {@literal 1<=n<=nslices}. Returns null if the stack is empty. */ - public ImageProcessor getProcessor(int n) { - byte[] bytes = (byte[])plots.get(n-1); - if (bytes!=null) { - try { - Plot plot = new Plot(null, new ByteArrayInputStream(bytes)); - ImageProcessor ip = plot.getProcessor(); - if (bitDepth==24) - ip = ip.convertToRGB(); - else if (bitDepth==8) - ip = ip.convertToByte(false); - ip.setSliceNumber(n); - return ip; - } catch (Exception e) { - IJ.handleException(e); - } - } - return null; - } - - /** Returns the number of slices in this stack. */ - public int getSize() { - return plots.size(); - } - - /** Returns either 24 (RGB) or 8 (grayscale). */ - public int getBitDepth() { - return bitDepth; - } - - public void setBitDepth(int bitDepth) { - this.bitDepth = bitDepth; - } - - public String getSliceLabel(int n) { - return null; - } - - public void setPixels(Object pixels, int n) { - } - - /** Deletes the specified slice, where {@literal 1<=n<=nslices}. */ - public void deleteSlice(int n) { - if (n<1 || n>plots.size()) - throw new IllegalArgumentException("Argument out of range: "+n); - if (plots.size()<1) - return; - plots.remove(n-1); - } - - -} // PlotVirtualStack \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/PlotWindow.java b/com.eco.bio7.image/src/ij/gui/PlotWindow.java deleted file mode 100644 index 7236b2045..000000000 --- a/com.eco.bio7.image/src/ij/gui/PlotWindow.java +++ /dev/null @@ -1,1156 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import java.awt.datatransfer.*; -import java.util.*; - -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import ij.*; -import ij.process.*; -import ij.util.*; -import ij.text.TextWindow; -import ij.plugin.filter.Analyzer; -import ij.plugin.filter.PlugInFilterRunner; -import ij.measure.*; -import ij.io.SaveDialog; -import org.eclipse.swt.custom.CTabFolder; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.PlatformUI; - -import com.eco.bio7.ImageJPluginActions.ImageJContextMenuAction; -import com.eco.bio7.image.CanvasView; -import com.eco.bio7.image.CustomDetachedImageJView; -import com.eco.bio7.image.IJTabs; -import com.eco.bio7.image.Util; - -/** - * This class implements the Analyze/Plot Profile command. - * - * @author Michael Schmid - * @author Wayne Rasband - */ -public class PlotWindow extends ImageWindow - implements ActionListener, ItemListener, ClipboardOwner, ImageListener, RoiListener, Runnable { - - private static final int WIDTH = 600; - private static final int HEIGHT = 340; - private static final int FONT_SIZE = 14; - private static final String PREFS_WIDTH = "pp.width"; - private static final String PREFS_HEIGHT = "pp.height"; - private static final String PREFS_FONT_SIZE = "pp.fontsize"; - - /** @deprecated */ - public static final int CIRCLE = Plot.CIRCLE; - /** @deprecated */ - public static final int X = Plot.X; - /** @deprecated */ - public static final int BOX = Plot.BOX; - /** @deprecated */ - public static final int TRIANGLE = Plot.TRIANGLE; - /** @deprecated */ - public static final int CROSS = Plot.CROSS; - /** @deprecated */ - public static final int LINE = Plot.LINE; - /** Write first X column when listing or saving. */ - public static boolean saveXValues = true; - /** - * Automatically close window after saving values. To set, use - * Edit/Options/Plots. - */ - public static boolean autoClose; - /** - * Display the XY coordinates in a separate window. To set, use - * Edit/Options/Plots. - */ - public static boolean listValues; - /** - * Interpolate line profiles. To set, use Edit/Options/Plots or - * setOption("InterpolateLines",boolean). - */ - public static boolean interpolate = true; - // default values for new installations; values will be then saved in prefs - private static int defaultFontSize = Prefs.getInt(PREFS_FONT_SIZE, FONT_SIZE); - /** The width of the plot (without frame) in pixels. */ - public static int plotWidth = WIDTH; - /** The height of the plot in pixels. */ - public static int plotHeight = HEIGHT; - /** - * The plot text size, can be overridden by Plot.setFont, Plot.setFontSize, - * Plot.setXLabelFont etc. - */ - public static int fontSize = defaultFontSize; - /** - * Have axes with no grid lines. If both noGridLines and noTicks are true, only - * min&max value of the axes are given - */ - public static boolean noGridLines; - /** - * Have axes with no ticks. If both noGridLines and noTicks are true, only - * min&max value of the axes are given - */ - public static boolean noTicks; - private static final String OPTIONS = "pp.options"; - private static final int SAVE_X_VALUES = 1; - private static final int AUTO_CLOSE = 2; - private static final int LIST_VALUES = 4; - private static final int INTERPOLATE = 8; - private static final int NO_GRID_LINES = 16; - private static final int NO_TICKS = 32; - private static String moreButtonLabel = "More " + '\u00bb'; - private static String dataButtonLabel = "Data " + '\u00bb'; - - boolean wasActivated; // true after window has been activated once, needed by PlotCanvas - - JButton list; - private JButton data, more, live; - private PopupMenu dataPopupMenu, morePopupMenu; - private static final int NUM_MENU_ITEMS = 20; // how many menu items we have in total - private MenuItem[] menuItems = new MenuItem[NUM_MENU_ITEMS]; - private JLabel statusLabel; - private String userStatusText; - private static String defaultDirectory = null; - private static int options; - private int defaultDigits = -1; - private int markSize = 5; - private static Plot staticPlot; - private Plot plot; - - private PlotMaker plotMaker; - private ImagePlus srcImp; // the source image for live plotting - private Thread bgThread; // thread for plotting (in the background) - private boolean doUpdate; // tells the background thread to update - - private Roi[] rangeArrowRois; // the overlays (arrows etc) for changing the range. Note: #10-15 must - // correspond to PlotDialog.dialogType! - private boolean rangeArrowsVisible; - private int activeRangeArrow = -1; - private static Color inactiveRangeArrowColor = Color.GRAY; - private static Color inactiveRangeRectColor = new Color(0x20404040, true); // transparent gray - private static Color activeRangeArrowColor = Color.RED; - private static Color activeRangeRectColor = new Color(0x18ff0000, true); // transparent red - protected Vector ve; - - // static initializer - static { - options = Prefs.getInt(OPTIONS, SAVE_X_VALUES); - autoClose = (options & AUTO_CLOSE) != 0; - plotWidth = Prefs.getInt(PREFS_WIDTH, WIDTH); - plotHeight = Prefs.getInt(PREFS_HEIGHT, HEIGHT); - Dimension screen = IJ.getScreenSize(); - if (plotWidth > screen.width && plotHeight > screen.height) { - plotWidth = WIDTH; - plotHeight = HEIGHT; - } - } - - /** - * @deprecated replaced by the Plot class. - */ - public PlotWindow(String title, String xLabel, String yLabel, float[] xValues, float[] yValues) { - super(createImage(title, xLabel, yLabel, xValues, yValues)); - plot = staticPlot; - // Changed for Bio7! - ((PlotCanvas) getCanvas()).setPlot(plot); - } - - /** - * @deprecated replaced by the Plot class. - */ - public PlotWindow(String title, String xLabel, String yLabel, double[] xValues, double[] yValues) { - this(title, xLabel, yLabel, Tools.toFloat(xValues), Tools.toFloat(yValues)); - } - - /** - * Creates a PlotWindow from a given ImagePlus with a Plot object. (called when - * reading an ImagePlus with an associated plot from a file) - */ - public PlotWindow(ImagePlus imp, Plot plot) { - super(imp); - // Changed for Bio7! - ((PlotCanvas) getCanvas()).setPlot(plot); - this.plot = plot; - draw(); - } - - /** Creates a PlotWindow from a Plot object. */ - PlotWindow(Plot plot) { - super(plot.getImagePlus()); - // Changed for Bio7! - ((PlotCanvas) getCanvas()).setPlot(plot); - this.plot = plot; - draw(); - } - - /** - * Called by the constructor to generate the image the plot will be drawn on. - * This is a static method because constructors cannot call instance methods. - */ - static ImagePlus createImage(String title, String xLabel, String yLabel, float[] xValues, float[] yValues) { - staticPlot = new Plot(title, xLabel, yLabel, xValues, yValues); - return new ImagePlus(title, staticPlot.getBlankProcessor()); - } - - /** - * Sets the x-axis and y-axis range. - * - * @deprecated use the corresponding method of the Plot class - */ - public void setLimits(double xMin, double xMax, double yMin, double yMax) { - plot.setLimits(xMin, xMax, yMin, yMax); - } - - /** - * Adds a set of points to the plot or adds a curve if shape is set to LINE. - * Note that there are more options available by using the methods of the Plot - * class instead. - * - * @param x the x-coodinates - * @param y the y-coodinates - * @param shape Plot.CIRCLE, X, BOX, TRIANGLE, CROSS, LINE etc. - * @deprecated use the corresponding method of the Plot class - */ - public void addPoints(float[] x, float[] y, int shape) { - plot.addPoints(x, y, shape); - } - - /** - * Adds a set of points to the plot using double arrays. Must be called before - * the plot is displayed. Note that there are more options available by using - * the methods of the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void addPoints(double[] x, double[] y, int shape) { - addPoints(Tools.toFloat(x), Tools.toFloat(y), shape); - } - - /** - * Adds vertical error bars to the plot. Must be called before the plot is - * displayed. Note that there are more options available by using the methods of - * the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void addErrorBars(float[] errorBars) { - plot.addErrorBars(errorBars); - } - - /** - * Draws a label. Note that there are more options available by using the - * methods of the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void addLabel(double x, double y, String label) { - plot.addLabel(x, y, label); - } - - /** - * Changes the drawing color. The frame and labels are always drawn in black. - * Must be called before the plot is displayed. Note that there are more options - * available by using the methods of the Plot class instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void setColor(Color c) { - plot.setColor(c); - } - - /** - * Changes the line width. Must be called before the plot is displayed. Note - * that there are more options available by using the methods of the Plot class - * instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void setLineWidth(int lineWidth) { - plot.setLineWidth(lineWidth); - } - - /** - * Changes the font. Must be called before the plot is displayed. Note that - * there are more options available by using the methods of the Plot class - * instead. - * - * @deprecated use the corresponding method of the Plot class - */ - public void changeFont(Font font) { - plot.changeFont(font); - } - - /** Displays the plot. */ - public void draw() { - JPanel bottomPanel = new JPanel(); - Color primarySWTToAwtColor = ImageJ.getPrimarySWTToAwtColor(); - /* - * Changed for Bio7! AWT must be colored per component. All JPanels will get the - * SWT background from the definition of the CanvasView (UIManager)! - */ - Color swtBackgroundToAWT = Util.getSWTBackgroundToAWT(); - Color swtForegroundToAWT = Util.getSWTForegroundToAWT(); - //if (Util.getOS().equals("Linux")) { - bottomPanel.setBackground(swtBackgroundToAWT); - bottomPanel.setForeground(swtForegroundToAWT); - //} - //bottomPanel.setBackground(primarySWTToAwtColor); - int hgap = IJ.isMacOSX() ? 1 : 5; - - list = new JButton(" List "); - list.setBackground(swtBackgroundToAWT); - list.setForeground(swtForegroundToAWT); - list.setBorderPainted(false); - list.addActionListener(this); - bottomPanel.add(list); - bottomPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, hgap, 0)); - data = new JButton(dataButtonLabel); - data.setBackground(swtBackgroundToAWT); - data.setForeground(swtForegroundToAWT); - data.setBorderPainted(false); - data.addActionListener(this); - bottomPanel.add(data); - more = new JButton(moreButtonLabel); - more.setBackground(swtBackgroundToAWT); - more.setForeground(swtForegroundToAWT); - more.setBorderPainted(false); - more.addActionListener(this); - bottomPanel.add(more); - if (plot != null && plot.getPlotMaker() != null) { - live = new JButton("Live"); - live.setBorderPainted(false); - live.setBackground(swtBackgroundToAWT); - live.setForeground(swtForegroundToAWT); - live.addActionListener(this); - bottomPanel.add(live); - } - statusLabel = new JLabel(); - statusLabel.setFont(new Font("Monospaced", Font.PLAIN, 12)); - statusLabel.setBackground(new Color(220, 220, 220)); - // bottomPanel.add(statusLabel); - - // Changed for Bio7! - //statusLabel.setBackground(primarySWTToAwtColor); - /* - * Changed for Bio7! AWT must be colored per component. All JPanels will get the - * SWT background from the definition of the CanvasView (UIManager)! - */ - //if (Util.getOS().equals("Linux")) { - statusLabel.setBackground(swtBackgroundToAWT); - statusLabel.setForeground(swtForegroundToAWT); - //} - - bottomPanel.add(statusLabel); - add(bottomPanel); - data.add(getDataPopupMenu()); - more.add(getMorePopupMenu()); - plot.draw(); - LayoutManager lm = getLayout(); - if (lm instanceof ImageLayout) - ((ImageLayout) lm).ignoreNonImageWidths(true); // don't expand size to make the panel fit - GUI.scale(bottomPanel); - maximizeCoordinatesLabelWidth(); - /* Changed for Bio7. Pack causes deadlock on MacOSX with detached view! */ - // pack(); - /* Changed for Bio7. Introduced a pause for the plot display!*/ - IJ.wait(200); - ImageProcessor ip = plot.getProcessor(); - boolean ipIsColor = ip instanceof ColorProcessor; - boolean impIsColor = imp.getProcessor() instanceof ColorProcessor; - if (ipIsColor != impIsColor) - imp.setProcessor(null, ip); - else - imp.updateAndDraw(); - if (listValues) - showList(/*useLabels=*/false); - else - ic.requestFocus(); // have focus on the canvas, not the button, so that pressing the space bar - // allows panning - if (Prefs.autoLivePlots && bgThread==null) - enableLivePlot(); - /* - * Changed for Bio7! - */ - - Display display = Util.getDisplay(); - display.syncExec(new Runnable() { - public void run() { - CanvasView.parent2.layout(); - CTabFolder ctab = CanvasView.getCanvas_view().tabFolder; - ve = (Vector>) ctab.getSelection().getData(); - JPanel current = (JPanel) ve.get(2); - current.add(bottomPanel); - } - }); - CanvasView.getCanvas_view().getCurrent().validate(); - } - - /** - * Sets the Plot object shown in this PlotWindow. Does not update the window. - */ - public void setPlot(Plot plot) { - this.plot = plot; - ((PlotCanvas) getCanvas()).setPlot(plot); - } - - /** Releases the resources used by this PlotWindow */ - public void dispose() { - if (plot != null) - plot.dispose(); - disableLivePlot(); - plot = null; - plotMaker = null; - srcImp = null; - super.dispose(); - } - - /** - * Called when the window is activated (WindowListener) Window layout is - * finished at latest a few millisec after windowActivated, then the - * 'wasActivated' boolean is set to tell the ImageCanvas that resize events - * should lead to resizing the canvas (before, creating the layout can lead to - * resize events) - */ - public void windowActivated(WindowEvent e) { - super.windowActivated(e); - if (!wasActivated) { - new Thread(new Runnable() { - public void run() { - IJ.wait(50); // sometimes, window layout is done only a few millisec after windowActivated - wasActivated = true; - } - }).start(); - } - } - - /** Called when the canvas is resized */ - void canvasResized() { - if (plot == null) - return; - /*Dimension d1 = getExtraSize(); - Dimension d2 = plot.getMinimumSize(); - setMinimumSize(new Dimension(d1.width + d2.width, d1.height + d2.height));*/ - maximizeCoordinatesLabelWidth(); - } - - /** - * Maximizes the width for the coordinate&status readout field and its parent - * bottomPanel - */ - void maximizeCoordinatesLabelWidth() { - Insets insets = getInsets(); // by default, left & right insets are 0 anyhow - Component parent = statusLabel.getParent(); // the bottomPanel, has insets of 0 - if (!parent.isValid()) - parent.validate(); - int cWidth = getWidth() - 2 * HGAP - statusLabel.getX() - insets.left - insets.right; - int cHeight = statusLabel.getPreferredSize().height; - statusLabel.setPreferredSize(new Dimension(cWidth, cHeight)); - parent.setSize(getWidth() - 2 * HGAP, parent.getHeight()); - } - - /** - * Shows the text in the coordinate&status readout field at the bottom. This - * text may get temporarily replaced for 'tooltips' (mouse over range arrows - * etc.). Call with a null argument to enable coordinate readout again. - */ - public void showStatus(String text) { - userStatusText = text; - if (statusLabel != null) - statusLabel.setText(text == null ? "" : text); - } - - /** - * Names for popupMenu items. Update NUM_MENU_ITEMS at the top when adding new - * ones! - */ - private static int SAVE = 0, COPY = 1, COPY_ALL = 2, LIST_SIMPLE = 3, ADD_FROM_TABLE = 4, ADD_FROM_PLOT = 5, - ADD_FIT = 6, // data menu - SET_RANGE = 7, PREV_RANGE = 8, RESET_RANGE = 9, FIT_RANGE = 10, // the rest is in the more menu - ZOOM_SELECTION = 11, AXIS_OPTIONS = 12, LEGEND = 13, STYLE = 14, TEMPLATE = 15, RESET_PLOT = 16, - FREEZE = 17, HI_RESOLUTION = 18, PROFILE_PLOT_OPTIONS = 19; - // the following commands are disabled when the plot is frozen - private static int[] DISABLED_WHEN_FROZEN = new int[] { ADD_FROM_TABLE, ADD_FROM_PLOT, ADD_FIT, SET_RANGE, - PREV_RANGE, RESET_RANGE, FIT_RANGE, ZOOM_SELECTION, AXIS_OPTIONS, LEGEND, STYLE, RESET_PLOT }; - - /** Prepares and returns the popupMenu of the Data>> button */ - PopupMenu getDataPopupMenu() { - dataPopupMenu = new PopupMenu(); - GUI.scalePopupMenu(dataPopupMenu); - menuItems[SAVE] = addPopupItem(dataPopupMenu, "Save Data..."); - menuItems[COPY] = addPopupItem(dataPopupMenu, "Copy 1st Data Set"); - menuItems[COPY_ALL] = addPopupItem(dataPopupMenu, "Copy All Data"); - menuItems[LIST_SIMPLE] = addPopupItem(dataPopupMenu, "List (Simple Headings)"); - dataPopupMenu.addSeparator(); - menuItems[ADD_FROM_TABLE] = addPopupItem(dataPopupMenu, "Add from Table..."); - menuItems[ADD_FROM_PLOT] = addPopupItem(dataPopupMenu, "Add from Plot..."); - menuItems[ADD_FIT] = addPopupItem(dataPopupMenu, "Add Fit..."); - return dataPopupMenu; - } - - /** Prepares and returns the popupMenu of the More>> button */ - PopupMenu getMorePopupMenu() { - morePopupMenu = new PopupMenu(); - GUI.scalePopupMenu(morePopupMenu); - menuItems[SET_RANGE] = addPopupItem(morePopupMenu, "Set Range..."); - menuItems[PREV_RANGE] = addPopupItem(morePopupMenu, "Previous Range"); - menuItems[RESET_RANGE] = addPopupItem(morePopupMenu, "Reset Range"); - menuItems[FIT_RANGE] = addPopupItem(morePopupMenu, "Set Range to Fit All"); - menuItems[ZOOM_SELECTION] = addPopupItem(morePopupMenu, "Zoom to Selection"); - morePopupMenu.addSeparator(); - menuItems[AXIS_OPTIONS] = addPopupItem(morePopupMenu, "Axis Options..."); - menuItems[LEGEND] = addPopupItem(morePopupMenu, "Legend..."); - menuItems[STYLE] = addPopupItem(morePopupMenu, "Contents Style..."); - menuItems[TEMPLATE] = addPopupItem(morePopupMenu, "Use Template..."); - menuItems[RESET_PLOT] = addPopupItem(morePopupMenu, "Reset Format"); - menuItems[FREEZE] = addPopupItem(morePopupMenu, "Freeze Plot", true); - menuItems[HI_RESOLUTION] = addPopupItem(morePopupMenu, "High-Resolution Plot..."); - morePopupMenu.addSeparator(); - menuItems[PROFILE_PLOT_OPTIONS] = addPopupItem(morePopupMenu, "Plot Defaults..."); - return morePopupMenu; - } - - MenuItem addPopupItem(PopupMenu popupMenu, String s) { - return addPopupItem(popupMenu, s, false); - } - - MenuItem addPopupItem(PopupMenu popupMenu, String s, boolean isCheckboxItem) { - MenuItem mi = null; - if (isCheckboxItem) { - mi = new CheckboxMenuItem(s); - ((CheckboxMenuItem) mi).addItemListener(this); - } else { - mi = new MenuItem(s); - mi.addActionListener(this); - } - popupMenu.add(mi); - return mi; - } - - /*Changed for Bio7*/ - public void actionPerformed(ActionEvent e) { - // String label = e.getActionCommand(); - Object b = e.getSource(); - if (b == live) { - toggleLivePlot(); - } else if (b == data) { - enableDisableMenuItems(); - Component c = (Component) b; - Point loc = c.getLocationOnScreen(); - // dataPopupMenu.show((Component) b, 1, 1); - /*Changed for Bio7*/ - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction icma = instance.getImageContextMenuAction(); - icma.swtPopupMenu(e, dataPopupMenu, new Point(loc.x, loc.y), this); - } else if (b == more) { - enableDisableMenuItems(); - Component c = (Component) b; - Point loc = c.getLocationOnScreen(); - // morePopupMenu.show((Component) b, 1, 1); - /*Changed for Bio7*/ - ImageJ instance = IJ.getInstance(); - ImageJContextMenuAction imageContextMenuAction = instance.getImageContextMenuAction(); - imageContextMenuAction.swtPopupMenu(e, morePopupMenu, new Point(loc.x, loc.y), this); - } - - actionPerformed(b); - } - - /*Changed for Bio7 - see above!*/ - /** Called if user has activated a button or popup menu item */ - public void actionPerformed(Object b) { - try { - //System.out.println(b.toString()); - // Object b = e.getSource(); - // if (b == live) - // toggleLiveProfiling(); - if (b == list) - showList(/*useLabels=*/true); - else if (b == data) { - // enableDisableMenuItems(); - // dataPopupMenu.show((Component) b, 1, 1); - } else if (b == more) { - // enableDisableMenuItems(); - // morePopupMenu.show((Component) b, 1, 1); - } else if (b == menuItems[SAVE]) - saveAsText(); - else if (b == menuItems[COPY]) - copyToClipboard(false); - else if (b == menuItems[COPY_ALL]) - copyToClipboard(true); - else if (b == menuItems[LIST_SIMPLE]) - showList(/*useLabels=*/false); - else if (b == menuItems[ADD_FROM_TABLE]) - new PlotContentsDialog(plot, PlotContentsDialog.ADD_FROM_TABLE).showDialog(this); - else if (b == menuItems[ADD_FROM_PLOT]) - new PlotContentsDialog(plot, PlotContentsDialog.ADD_FROM_PLOT).showDialog(this); - else if (b == menuItems[ADD_FIT]) - new PlotContentsDialog(plot, PlotContentsDialog.ADD_FIT).showDialog(this); - else if (b == menuItems[ZOOM_SELECTION]) { - if (imp != null && imp.getRoi() != null && imp.getRoi().isArea()) - plot.zoomToRect(imp.getRoi().getBounds()); - } else if (b == menuItems[SET_RANGE]) - new PlotDialog(plot, PlotDialog.SET_RANGE).showDialog(this); - else if (b == menuItems[PREV_RANGE]) - plot.setPreviousMinMax(); - else if (b == menuItems[RESET_RANGE]) - plot.setLimitsToDefaults(true); - else if (b == menuItems[FIT_RANGE]) - plot.setLimitsToFit(true); - else if (b == menuItems[AXIS_OPTIONS]) - new PlotDialog(plot, PlotDialog.AXIS_OPTIONS).showDialog(this); - else if (b == menuItems[LEGEND]) - new PlotDialog(plot, PlotDialog.LEGEND).showDialog(this); - else if (b == menuItems[STYLE]) - new PlotContentsDialog(plot, PlotContentsDialog.STYLE).showDialog(this); - else if (b == menuItems[TEMPLATE]) - new PlotDialog(plot, PlotDialog.TEMPLATE).showDialog(this); - else if (b == menuItems[RESET_PLOT]) { - plot.setFont(Font.PLAIN, fontSize); - plot.setAxisLabelFont(Font.PLAIN, fontSize); - plot.setFormatFlags(Plot.getDefaultFlags()); - plot.setFrameSize(plotWidth, plotHeight); // updates the image only when size changed - int correctionX = plot.leftMargin + plot.rightMargin; - int correctionY = plot.topMargin + plot.bottomMargin; - /* Changed for Bio7. We have no window and have to resize the canvas! */ - plot.getImagePlus().getCanvas().setSize(plotWidth + correctionX, plotHeight + correctionY); - plot.updateImage(); - /* Changed for Bio7 */ - CanvasView view = CanvasView.getCanvas_view(); - if (view != null) { - view.updatePlotCanvas(); - } - } else if (b == menuItems[HI_RESOLUTION]) - new PlotDialog(plot, PlotDialog.HI_RESOLUTION).showDialog(this); - else if (b == menuItems[PROFILE_PLOT_OPTIONS]) - IJ.doCommand("Plots..."); - ic.requestFocus(); // have focus on the canvas, not the button, so that pressing the space bar - // allows panning - } catch (Exception ex) { - IJ.handleException(ex); - } - } - - private void enableDisableMenuItems() { - boolean frozen = plot.isFrozen(); // prepare menu according to 'frozen' state of plot - ((CheckboxMenuItem) menuItems[FREEZE]).setState(frozen); - for (int i : DISABLED_WHEN_FROZEN) - menuItems[i].setEnabled(!frozen); - if (!PlotContentsDialog.tableWindowExists()) - menuItems[ADD_FROM_TABLE].setEnabled(false); - if (plot.getDataObjectDesignations().length == 0) - menuItems[ADD_FIT].setEnabled(false); - } - - /** Called if the user activates/deactivates a CheckboxMenuItem */ - public void itemStateChanged(ItemEvent e) { - if (e.getSource() == menuItems[FREEZE]) { - boolean frozen = ((CheckboxMenuItem) menuItems[FREEZE]).getState(); - plot.setFrozen(frozen); - } - } - - /** - * Updates the X and Y values when the mouse is moved and, if appropriate, - * shows/hides the overlay with the triangular buttons for changing the axis - * range limits. Overrides mouseMoved() in ImageWindow. - * - * @see ij.gui.ImageWindow#mouseMoved - */ - public void mouseMoved(int x, int y) { - super.mouseMoved(x, y); - if (plot == null) - return; - String statusText = null; // coordinate readout, status or tooltip, will be shown in coordinate&status - // line - - // arrows and other symbols for modifying the plot range - if (x < plot.leftMargin || y > plot.topMargin + plot.frameHeight) { - if (!rangeArrowsVisible && !plot.isFrozen()) - showRangeArrows(); - if (activeRangeArrow < 0) // mouse is not on one of the symbols, ignore (nothing to display) - { - } else if (activeRangeArrow < 8) // mouse over an arrow: 0,3,4,7 for increase, 1,2,5,6 for decrease - statusText = ((activeRangeArrow + 1) & 0x02) != 0 ? "Decrease Range" : "Increase Range"; - else if (activeRangeArrow == 8) // it's the 'R' icon - statusText = "Reset Range"; - else if (activeRangeArrow == 9) // it's the 'F' icon - statusText = "Full Range (Fit All)"; - else if (activeRangeArrow >= 10 && activeRangeArrow < 14) // space between arrow-pairs for single number - statusText = "Set limit..."; - else if (activeRangeArrow >= 14) - statusText = "Axis Range & Options..."; - boolean repaint = false; - if (activeRangeArrow >= 0 && !rangeArrowRois[activeRangeArrow].contains(x, y)) { - rangeArrowRois[activeRangeArrow] - .setFillColor(activeRangeArrow < 10 ? inactiveRangeArrowColor : inactiveRangeRectColor); - repaint = true; // de-highlight arrow where cursor has moved out - activeRangeArrow = -1; - } - if (activeRangeArrow < 0) { // no currently highlighted arrow, do we have a new one? - int i = getRangeArrowIndex(x, y); - if (i >= 0) { // we have an arrow or symbol at cursor position - rangeArrowRois[i].setFillColor(i < 14 ? activeRangeArrowColor : activeRangeRectColor); - activeRangeArrow = i; - repaint = true; - } - } - if (repaint) - ic.repaint(); - } else if (rangeArrowsVisible) - hideRangeArrows(); - if (statusText == null) - statusText = userStatusText != null ? userStatusText : plot.getCoordinates(x, y); - if (statusLabel != null) - statusLabel.setText(statusText); - } - - /** Called by PlotCanvas */ - void mouseExited(MouseEvent e) { - if (rangeArrowsVisible) - hideRangeArrows(); - } - - /** - * Mouse wheel: zooms when shift or ctrl is pressed, scrolls in x if space bar - * down, in y otherwise. - */ - public synchronized void mouseWheelMoved(MouseWheelEvent e) { - if (plot.isFrozen() || !(ic instanceof PlotCanvas)) { // frozen plots are like normal images - super.mouseWheelMoved(e); - return; - } - int rotation = e.getWheelRotation(); - int amount = e.getScrollAmount(); - if (e.getX() < plot.leftMargin || e.getX() > plot.leftMargin + plot.frameWidth)// n__ - return; - if (e.getY() < plot.topMargin || e.getY() > plot.topMargin + plot.frameHeight) - return; - boolean ctrl = (e.getModifiers() & Event.CTRL_MASK) != 0; - if (amount < 1) - amount = 1; - if (rotation == 0) - return; - if (ctrl || IJ.shiftKeyDown()) { - double zoomFactor = rotation < 0 ? Math.pow(2, 0.2) : Math.pow(0.5, 0.2); - Point loc = ic.getCursorLoc(); - int x = ic.screenX(loc.x); - int y = ic.screenY(loc.y); - ((PlotCanvas) ic).zoom(x, y, zoomFactor); - } else if (IJ.spaceBarDown()) - plot.scroll(rotation * amount * Math.max(ic.imageWidth / 50, 1), 0); - else - plot.scroll(0, rotation * amount * Math.max(ic.imageHeight / 50, 1)); - } - - /** - * Creates an overlay with triangular buttons and other symbols for changing the - * axis range limits and shows it - */ - void showRangeArrows() { - if (imp == null) - return; - hideRangeArrows(); // in case we have old arrows from a different plot size or so - rangeArrowRois = new Roi[4 * 2 + 2 + 4 + 2]; // 4 arrows per axis, + 'Reset' and 'Fit All' icons, + 4 numerical - // input boxes + 2 axes - int i = 0; - int height = imp.getHeight(); - int arrowH = plot.topMargin < 14 ? 6 : 8; // height of arrows and distance between them; base is twice that - // value - float[] yP = new float[] { height - arrowH / 2, height - 3 * arrowH / 2, height - 5 * arrowH / 2 - 0.1f }; - - for (float x : new float[] { plot.leftMargin, plot.leftMargin + plot.frameWidth }) { // create arrows for x axis - float[] x0 = new float[] { x - arrowH / 2, x - 3 * arrowH / 2 - 0.1f, x - arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(x0, yP, 3, Roi.POLYGON); - float[] x1 = new float[] { x + arrowH / 2, x + 3 * arrowH / 2 + 0.1f, x + arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(x1, yP, 3, Roi.POLYGON); - } - float[] xP = new float[] { arrowH / 2 - 0.1f, 3 * arrowH / 2, 5 * arrowH / 2 + 0.1f }; - for (float y : new float[] { plot.topMargin + plot.frameHeight, plot.topMargin }) { // create arrows for y axis - float[] y0 = new float[] { y + arrowH / 2, y + 3 * arrowH / 2 + 0.1f, y + arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(xP, y0, 3, Roi.POLYGON); - float[] y1 = new float[] { y - arrowH / 2, y - 3 * arrowH / 2 - 0.1f, y - arrowH / 2 }; - rangeArrowRois[i++] = new PolygonRoi(xP, y1, 3, Roi.POLYGON); - } - Font theFont = new Font("SansSerif", Font.BOLD, 13); - - TextRoi txtRoi = new TextRoi(1, height - 19, "\u2009R\u2009", theFont); // thin spaces to make roi slightly - // wider - rangeArrowRois[8] = txtRoi; - TextRoi txtRoi2 = new TextRoi(20, height - 19, "\u2009F\u2009", theFont); - rangeArrowRois[9] = txtRoi2; - - rangeArrowRois[10] = new Roi(plot.leftMargin - arrowH / 2 + 1, height - 5 * arrowH / 2, arrowH - 2, arrowH * 2);// numerical - // box - // left - rangeArrowRois[11] = new Roi(plot.leftMargin + plot.frameWidth - arrowH / 2 + 1, height - 5 * arrowH / 2, - arrowH - 2, arrowH * 2);// numerical box right - rangeArrowRois[12] = new Roi(arrowH / 2, plot.topMargin + plot.frameHeight - arrowH / 2 + 1, arrowH * 2, - arrowH - 2);// numerical box bottom - rangeArrowRois[13] = new Roi(arrowH / 2, plot.topMargin - arrowH / 2 + 1, arrowH * 2, arrowH - 2);// numerical - // box top - - int topMargin = plot.topMargin; - int bottomMargin = topMargin + plot.frameHeight; - int leftMargin = plot.leftMargin; - int rightMargin = plot.leftMargin + plot.frameWidth; - rangeArrowRois[14] = new Roi(leftMargin, bottomMargin + 2, // area to click for x axis options - rightMargin - leftMargin + 1, 2 * arrowH); - rangeArrowRois[15] = new Roi(leftMargin - 2 * arrowH - 2, topMargin, // area to click for y axis options - 2 * arrowH, bottomMargin - topMargin + 1); - - Overlay ovly = imp.getOverlay(); - if (ovly == null) - ovly = new Overlay(); - for (Roi roi : rangeArrowRois) { - if (roi instanceof PolygonRoi) - roi.setFillColor(inactiveRangeArrowColor); - else if (roi instanceof TextRoi) { - roi.setStrokeColor(Color.WHITE); - roi.setFillColor(inactiveRangeArrowColor); - } else - roi.setFillColor(inactiveRangeRectColor); // transparent gray for single number boxes and axis range - ovly.add(roi); - } - imp.setOverlay(ovly); - ic.repaint(); - rangeArrowsVisible = true; - } - - public void hideRangeArrows() { - if (imp == null || rangeArrowRois == null) - return; - Overlay ovly = imp.getOverlay(); - if (ovly == null) - return; - for (Roi roi : rangeArrowRois) - ovly.remove(roi); - ic.repaint(); - rangeArrowsVisible = false; - activeRangeArrow = -1; - } - - /** - * Returns the index of the range-modifying symbol or axis at the cursor - * position x,y, or -1 of none. Index numbers for arrows start with 0 at the - * 'down' arrow of the lower side of the x axis and end with 7 the up arrow at - * the upper side of the y axis. Numbers 8 & 9 are for "Reset Range" and "Fit - * All"; numbers 10-13 for a dialog to set a single limit, and 14-15 for the - * axis options. - */ - - int getRangeArrowIndex(int x, int y) { - if (!rangeArrowsVisible) - return -1; - for (int i = 0; i < rangeArrowRois.length; i++) - if (rangeArrowRois[i].getBounds().contains(x, y)) - return i; - return -1; - } - - /** Shows the data of the backing plot in a Textwindow with columns */ - void showList(boolean useLabels) { - ResultsTable rt = plot.getResultsTable(saveXValues, useLabels); - if (rt == null) - return; - rt.show("Plot Values"); - if (autoClose) { - imp.changes = false; - close(); - } - } - - /** - * Returns the plot values with simple headings (X, Y, Y1 etc, not the labels) - * as a ResultsTable. Use plot.getResultsTableWithLabels for a table with data - * set labels as column headings - */ - public ResultsTable getResultsTable() { - return plot.getResultsTable(saveXValues); - } - - /** creates the data that fills the showList() function values */ - private String getValuesAsString() { - ResultsTable rt = getResultsTable(); - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < rt.size(); i++) { - sb.append(rt.getRowAsString(i)); - sb.append("\n"); - } - return sb.toString(); - } - - /** Saves the data of the plot in a text file */ - void saveAsText() { - if (plot.getXValues() == null) { - IJ.error("Plot has no data"); - return; - } - SaveDialog sd = new SaveDialog("Save as Text", "Values", Prefs.defaultResultsExtension()); - String name = sd.getFileName(); - if (name == null) - return; - String directory = sd.getDirectory(); - IJ.wait(250); // give system time to redraw ImageJ window - IJ.showStatus("Saving plot values..."); - ResultsTable rt = plot.getResultsTable(/*writeFirstXColumn=*/saveXValues, /*useLabels=*/true); - try { - rt.saveAs(directory + name); - } catch (IOException e) { - IJ.error("" + e); - return; - } - if (autoClose) { - imp.changes = false; - close(); - } - } - - /** Copy the first dataset or all values to the clipboard */ - void copyToClipboard(boolean writeAllColumns) { - float[] xValues = plot.getXValues(); - float[] yValues = plot.getYValues(); - if (xValues == null) - return; - Clipboard systemClipboard = null; - try { - systemClipboard = getToolkit().getSystemClipboard(); - } catch (Exception e) { - systemClipboard = null; - } - if (systemClipboard == null) { - IJ.error("Unable to copy to Clipboard."); - return; - } - IJ.showStatus("Copying plot values..."); - CharArrayWriter aw = new CharArrayWriter(10 * xValues.length); - PrintWriter pw = new PrintWriter(aw); // uses platform's line termination characters - - if (writeAllColumns) { - ResultsTable rt = plot.getResultsTableWithLabels(); - if (!Prefs.dontSaveHeaders) { - String headings = rt.getColumnHeadings(); - pw.println(headings); - } - for (int i = 0; i < rt.size(); i++) - pw.println(rt.getRowAsString(i)); - } else { - int xdigits = 0; - if (saveXValues) - xdigits = plot.getPrecision(xValues); - int ydigits = plot.getPrecision(yValues); - for (int i = 0; i < Math.min(xValues.length, yValues.length); i++) { - if (saveXValues) - pw.println(IJ.d2s(xValues[i], xdigits) + "\t" + IJ.d2s(yValues[i], ydigits)); - else - pw.println(IJ.d2s(yValues[i], ydigits)); - } - } - String text = aw.toString(); - pw.close(); - StringSelection contents = new StringSelection(text); - systemClipboard.setContents(contents, this); - IJ.showStatus(text.length() + " characters copied to Clipboard"); - if (autoClose) { - imp.changes = false; - close(); - } - } - - public void lostOwnership(Clipboard clipboard, Transferable contents) { - } - - public float[] getXValues() { - return plot.getXValues(); - } - - public float[] getYValues() { - return plot.getYValues(); - } - - /** Draws a new plot in this window. */ - public void drawPlot(Plot plot) { - this.plot = plot; - if (imp != null) { - if (ic instanceof PlotCanvas) - ((PlotCanvas) ic).setPlot(plot); - imp.setProcessor(null, plot.getProcessor()); - plot.setImagePlus(imp); // also adjusts the calibration of imp - } - } - - /** Called once when ImageJ quits. */ - public static void savePreferences(Properties prefs) { - double min = ProfilePlot.getFixedMin(); - double max = ProfilePlot.getFixedMax(); - prefs.put(PREFS_WIDTH, Integer.toString(plotWidth)); - prefs.put(PREFS_HEIGHT, Integer.toString(plotHeight)); - prefs.put(PREFS_FONT_SIZE, Integer.toString(defaultFontSize)); - int options = 0; - if (!interpolate) - options |= INTERPOLATE; // true=0, false=1 - prefs.put(OPTIONS, Integer.toString(options)); - } - - /** Enables or disables live plotting. - * Does nothing if the plot has no PlotMaker (then there is no 'live' button). */ - public void enableLivePlot(boolean b) { - if (plot==null || plot.getPlotMaker()==null || live == null) - return; - if (b && bgThread == null) - enableLivePlot(); - else if (!b && bgThread != null) - disableLivePlot(); - } - - private void toggleLivePlot() { - boolean liveMode = bgThread != null; - enableLivePlot(!liveMode); - } - - /** Enables live plotting. - * This requires that the PlotWindow has been initialized with a Plot having a PlotMaker. - * Live plotting runs in a background thread. */ - private void enableLivePlot() { - if (plotMaker == null) - plotMaker = plot != null ? plot.getPlotMaker() : null; - if (plotMaker == null) - return; - srcImp = plotMaker.getSourceImage(); - if (srcImp == null) - return; - if (bgThread == null) { - bgThread = new Thread(this, "Live Plot"); - bgThread.setPriority(Math.max(bgThread.getPriority() - 3, Thread.MIN_PRIORITY)); - doUpdate = true; - bgThread.start(); - } - if (IJ.debugMode) - IJ.log("PlotWindow.createListeners"); - ImagePlus.addImageListener(this); - Roi.addRoiListener(this); - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.BOLD, font.getSize())); - live.setForeground(Color.red); - } - - /** Disables live plotting (when currently active) */ - private void disableLivePlot() { - if (IJ.debugMode) - IJ.log("PlotWindow.disableLivePlot: " + srcImp); - if (srcImp == null) - return; - if (bgThread != null) - bgThread.interrupt(); - bgThread = null; - ImagePlus.removeImageListener(this); - Roi.removeRoiListener(this); - if (live != null) { - Font font = live.getFont(); - live.setFont(new Font(font.getName(), Font.PLAIN, font.getSize())); - //live.setForeground(Color.black); - /*Changed for Bio7!*/ - //Color swtBackgroundToAWT = Util.getSWTBackgroundToAWT(); - Color swtForegroundToAWT = Util.getSWTForegroundToAWT(); - //live.setBackground(swtBackgroundToAWT); - live.setForeground(swtForegroundToAWT); - } - } - - /** For live plots, update the plot if the ROI of the source image changes */ - public synchronized void roiModified(ImagePlus img, int id) { - if (IJ.debugMode) - IJ.log("PlotWindow.roiModified: " + img + " " + id); - if (img == srcImp) { - doUpdate = true; - notify(); - } - } - - // Unused - public void imageOpened(ImagePlus imp) { - } - - /** - * For live plots, this method is called if the source image content is changed. - */ - public synchronized void imageUpdated(ImagePlus imp) { - if (imp == srcImp) { - doUpdate = true; - notify(); - } - } - - /** - * For live plots, if either the source image or this image are closed, exit - * live mode - */ - public void imageClosed(ImagePlus imp) { - if (imp == srcImp || imp == this.imp) { - disableLivePlot(); - srcImp = null; - plotMaker = null; - } - } - - // the background thread for live plotting. - public void run() { - while (true) { - IJ.wait(50); // delay to make sure the roi has been updated - Plot plot = plotMaker != null ? plotMaker.getPlot() : null; - if (doUpdate && plot != null && plot.getNumPlotObjects() > 0) { - plot.useTemplate(this.plot, this.plot.templateFlags | Plot.COPY_SIZE | Plot.COPY_LABELS - | Plot.COPY_AXIS_STYLE | Plot.COPY_CONTENTS_STYLE | Plot.COPY_LEGEND | Plot.COPY_EXTRA_OBJECTS); - plot.setPlotMaker(plotMaker); - this.plot = plot; - /* Changed for Bio7! */ - // ((PlotCanvas)ic).setPlot(plot); - ImageProcessor ip = plot.getProcessor(); - if (ip != null && imp != null) { - imp.setProcessor(null, ip); - plot.setImagePlus(imp); - } - } - synchronized (this) { - if (doUpdate) { - doUpdate = false; // and loop again - } else { - try { - wait(); - } // notify wakes up the thread - catch (InterruptedException e) { // interrupted tells the thread to exit - return; - } - } - } - } - } - - /** Returns the Plot associated with this PlotWindow. */ - public Plot getPlot() { - return plot; - } - - /** - * Freezes the active plot window, so the image does not get redrawn for - * zooming, setting the range, etc. - */ - public static void freeze() { - Window win = WindowManager.getActiveWindow(); - if (win != null && (win instanceof PlotWindow)) - ((PlotWindow) win).getPlot().setFrozen(true); - } - - public static void setDefaultFontSize(int size) { - if (size < 9) - size = 9; - defaultFontSize = size; - } - - public static int getDefaultFontSize() { - return defaultFontSize; - } - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/PointRoi.java b/com.eco.bio7.image/src/ij/gui/PointRoi.java deleted file mode 100644 index d349965b3..000000000 --- a/com.eco.bio7.image/src/ij/gui/PointRoi.java +++ /dev/null @@ -1,1064 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.measure.*; -import ij.plugin.Colors; -import ij.plugin.PointToolOptions; -import ij.plugin.filter.Analyzer; -import ij.plugin.frame.Recorder; -import ij.util.Tools; -import ij.util.Java2; -import java.awt.*; -import java.awt.image.*; -import java.awt.event.KeyEvent; -import java.util.*; -import java.awt.geom.*; - -/** This class represents a collection of points that can be associated - * with counters. Use the getPolygon() or getFloatPolygon() methods - * to retrieve the coordinates of the points. - * @see PointProperties.js -*/ -public class PointRoi extends PolygonRoi { - public static final String[] sizes = {"Tiny", "Small", "Medium", "Large", "Extra Large", "XXL", "XXXL"}; - public static final String[] types = {"Hybrid", "Cross", "Dot", "Circle"}; - public static final int HYBRID=0, CROSS=1, CROSSHAIR=1, DOT=2, CIRCLE=3; - /** Returned by getPosition if point stack positions are different */ - public static final int POINTWISE_POSITION = -2; - private static final String TYPE_KEY = "point.type"; - private static final String SIZE_KEY = "point.size"; - private static final String CROSS_COLOR_KEY = "point.cross.color"; - private static final int TINY=1, SMALL=3, MEDIUM=5, LARGE=7, EXTRA_LARGE=11, XXL=17, XXXL=25; - private static final BasicStroke twoPixelsWide = new BasicStroke(2); - private static final BasicStroke threePixelsWide = new BasicStroke(3); - private static final BasicStroke fivePixelsWide = new BasicStroke(5); - private static int defaultType = HYBRID; - private static int defaultSize = SMALL; - private static Font font; - private static Color defaultCrossColor = Color.white; - private static int fontSize = 9; - public static final int MAX_COUNTERS = 100; - private static String[] counterChoices; - private static Color[] colors; - private boolean showLabels; - private int type = HYBRID; - private int size = SMALL; - private static int defaultCounter; - private int counter; - private int nCounters = 1; - private short[] counters; //for each point, 0-100 for counter (=category that can be defined by the user) - private int[] positions; //for each point, the stack slice, or 0 for 'show on all' - private int[] counts = new int[MAX_COUNTERS]; - private ResultsTable rt; - private long lastPointTime; - private int[] counterInfo; - private boolean promptBeforeDeleting; - private boolean promptBeforeDeletingCalled; - private int nMarkers; - private boolean addToOverlay; - public static PointRoi savedPoints; - - static { - setDefaultType((int)Prefs.get(TYPE_KEY, HYBRID)); - setDefaultSize((int)Prefs.get(SIZE_KEY, 1)); - } - - public PointRoi() { - this(0.0, 0.0); - deletePoint(0); - } - - /** Creates a new PointRoi using the specified int arrays of offscreen coordinates. */ - public PointRoi(int[] ox, int[] oy, int points) { - super(itof(ox), itof(oy), points, POINT); - updateCounts(); - } - - /** Creates a new PointRoi using the specified float arrays of offscreen coordinates. */ - public PointRoi(float[] ox, float[] oy, int points) { - super(ox, oy, points, POINT); - updateCounts(); - } - - /** Creates a new PointRoi using the specified float arrays of offscreen coordinates. */ - public PointRoi(float[] ox, float[] oy) { - this(ox, oy, ox.length); - } - - /** Creates a new PointRoi using the specified coordinate arrays and options. */ - public PointRoi(float[] ox, float[] oy, String options) { - this(ox, oy, ox.length); - setOptions(options); - } - - /** Creates a new PointRoi from a FloatPolygon. */ - public PointRoi(FloatPolygon poly) { - this(poly.xpoints, poly.ypoints, poly.npoints); - } - - /** Creates a new PointRoi from a Polygon. */ - public PointRoi(Polygon poly) { - this(itof(poly.xpoints), itof(poly.ypoints), poly.npoints); - } - - /** Creates a new PointRoi using the specified coordinates and options. */ - public PointRoi(double ox, double oy, String options) { - super(makeXorYArray(ox, null, false), makeXorYArray(oy, null, true), 1, POINT); - width=1; height=1; - incrementCounter(null); - setOptions(options); - } - - /** Creates a new PointRoi using the specified offscreen int coordinates. */ - public PointRoi(int ox, int oy) { - super(makeXorYArray(ox, null, false), makeXorYArray(oy, null, true), 1, POINT); - width=1; height=1; - incrementCounter(null); - } - - /** Creates a new PointRoi using the specified offscreen double coordinates. */ - public PointRoi(double ox, double oy) { - super(makeXorYArray(ox, null, false), makeXorYArray(oy, null, true), 1, POINT); - width=1; height=1; - incrementCounter(null); - } - - /** Creates a new PointRoi using the specified screen coordinates. */ - public PointRoi(int sx, int sy, ImagePlus imp) { - super(makeXorYArray(sx, imp, false), makeXorYArray(sy, imp, true), 1, POINT); - //defaultCounter = 0; - setImage(imp); - width=1; height=1; - type = defaultType; - size = defaultSize; - showLabels = !Prefs.noPointLabels; - if (imp!=null) { - int r = 10 + size; - double mag = ic!=null?ic.getMagnification():1; - if (mag<1) - r = (int)(r/mag); - imp.draw(x-r, y-r, 2*r, 2*r); - } - setCounter(Toolbar.getMultiPointMode()?defaultCounter:0); - incrementCounter(imp); - enlargeArrays(50); - record(x, y, false); - } - - private void record(int xx, int yy, boolean addingPoint) { - if (!IJ.recording()) - return; - String add = Prefs.pointAddToOverlay?" add":""; - String options = sizes[convertSizeToIndex(size)]+" "+Colors.colorToString(getColor())+" "+types[type]+add; - options = options.toLowerCase(); - if (addingPoint) - options = "add"; - if (Recorder.scriptMode()) - Recorder.recordCall("imp.setRoi(new PointRoi("+xx+","+yy+",\""+options+"\"));"); - else - Recorder.record("makePoint", xx, yy, options); - } - - public void setOptions(String options) { - if (options==null) - return; - if (options.contains("tiny")) size=TINY; - else if (options.contains("medium")) size=MEDIUM; - else if (options.contains("extra")) size=EXTRA_LARGE; - else if (options.contains("large")) size=LARGE; - else if (options.contains("xxxl")) size=XXXL; - else if (options.contains("xxl")) size=XXL; - if (options.contains("cross")) type=CROSS; - else if (options.contains("dot")) type=DOT; - else if (options.contains("circle")) type=CIRCLE; - if (options.contains("nolabel")) setShowLabels(false); - else if (options.contains("label")) setShowLabels(true); - setStrokeColor(Colors.getColor(options,Roi.getColor())); - addToOverlay = options.contains("add"); - } - - static float[] itof(int[] arr) { - if (arr==null) - return null; - int n = arr.length; - float[] temp = new float[n]; - for (int i=0; i1) { - fontSize = 8; - double scale = size>=XXL?2:1.5; - fontSize += scale*convertSizeToIndex(size); - fontSize = (int)Math.round(fontSize); - font = new Font("SansSerif", Font.PLAIN, fontSize); - g.setFont(font); - if (fontSize>9) - Java2.setAntialiasedText(g, true); - } - int[] positions = this.positions; //use a copy to avoid NullPointerException on asynchronous change to null - int slice = imp!=null && positions!=null && imp.getStackSize()>1?imp.getCurrentSlice():0; - ImageCanvas ic = imp!=null?imp.getCanvas():null; - if (ic!=null && overlay && ic.getShowAllList()!=null && ic.getShowAllList().contains(this) && !Prefs.showAllSliceOnly) - slice = 0; // In RoiManager's "show all" mode and not "associate with slice", draw point irrespective of currently selected slice - if (Prefs.showAllPoints) - slice = 0; // "Show on all slices" in Point tool options - for (int i=0; i1.0) { - saveXform = g2d.getTransform(); - g2d.translate(x, y); - g2d.scale(flattenScale, flattenScale); - x = y = 0; - } - Color color = strokeColor!=null?strokeColor:ROIColor; - if (!overlay && isActiveOverlayRoi()) { - if (color==Color.cyan) - color = Color.magenta; - else - color = Color.cyan; - } - if (nCounters>1 && counters!=null && n<=counters.length) - color = getColor(counters[n-1]); - if (type==HYBRID || type==CROSS) { - if (type==HYBRID) - g.setColor(Color.white); - else { - g.setColor(color); - colorSet = true; - } - if (size>XXL) - g2d.setStroke(fivePixelsWide); - else if (size>LARGE) - g2d.setStroke(threePixelsWide); - g.drawLine(x-(size+2), y, x+size+2, y); - g.drawLine(x, y-(size+2), x, y+size+2); - } - if (type!=CROSS && size>SMALL) - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - if (type==HYBRID || type==DOT) { - if (!colorSet) { - g.setColor(color); - colorSet = true; - } - if (size>LARGE) - g2d.setStroke(onePixelWide); - if (size>LARGE && type==DOT) - g.fillOval(x-size2, y-size2, size, size); - else if (size>LARGE && type==HYBRID) - g.fillRect(x-(size2-2), y-(size2-2), size-4, size-4); - else if (size>SMALL && type==HYBRID) - g.fillRect(x-(size2-1), y-(size2-1), size-2, size-2); - else - g.fillRect(x-size2, y-size2, size, size); - } - if (showLabels && nPoints>1) { - int xoffset = 2; - if (size==LARGE) xoffset=3; - if (size==EXTRA_LARGE) xoffset=4; - if (size==XXL) xoffset=5; - if (size==XXXL) xoffset=7; - int yoffset = xoffset; - if (size>=LARGE) yoffset=yoffset-1; - if (nCounters==1) { - if (!colorSet) - g.setColor(color); - g.drawString(""+n, x+xoffset, y+yoffset+fontSize); - } else if (counters!=null) { - g.setColor(getColor(counters[n-1])); - g.drawString(""+counters[n-1], x+xoffset, y+yoffset+fontSize); - } - } - if ((size>TINY||type==DOT) && (type==HYBRID||type==DOT)) { - g.setColor(Color.black); - if (size>LARGE && type==HYBRID) - g.drawOval(x-(size2-1), y-(size2-1), size-3, size-3); - else if (size>SMALL && type==HYBRID) - g.drawOval(x-size2, y-size2, size-1, size-1); - else - g.drawOval(x-(size2+1), y-(size2+1), size+1, size+1); - } - if (type==CIRCLE) { - int scaledSize = (int)Math.round(size+1); - g.setColor(color); - if (size>LARGE) - g2d.setStroke(twoPixelsWide); - g.drawOval(x-scaledSize/2, y-scaledSize/2, scaledSize, scaledSize); - } - if (saveXform!=null) - g2d.setTransform(saveXform); - } - - public void drawPixels(ImageProcessor ip) { - ip.setLineWidth(Analyzer.markWidth); - double x0 = bounds == null ? x : bounds.x; - double y0 = bounds == null ? y : bounds.y; - for (int i=0; i=0 && index<=nPoints && counters!=null) { - counts[counters[index]]--; - for (int i=index; i1; - if (counter!=0 || isStack || counters!=null) { - if (counters==null) { - int size = nPoints*2; - if (size<100) size=100; - counters = new short[size]; - positions = new int[size]; - } - if (nPoints>=counters.length) { - short[] temp = new short[counters.length*2]; - System.arraycopy(counters, 0, temp, 0, counters.length); - counters = temp; - int[] temp1 = new int[counters.length*2]; - System.arraycopy(positions, 0, temp1, 0, positions.length); - positions = temp1; - } - counters[nPoints-1] = (short)counter; - if (imp!=null) - positions[nPoints-1] = imp.getStackSize()>1 ? imp.getCurrentSlice() : 0; - } - if (rt!=null && WindowManager.getFrame(getCountsTitle())!=null) - displayCounts(); - } - - /** Returns the index of the current counter. */ - public int getCounter() { - return counter; - } - - /** Returns the count associated with the specified counter index. - * @see #getLastCounter - * @see PointProperties.js - */ - public int getCount(int counter) { - if (counter==0 && counters==null) - return nPoints; - else - return counts[counter]; - } - - /** Returns the index of the last counter. */ - public int getLastCounter() { - return nCounters - 1; - } - - /** Returns the number of counters. */ - public int getNCounters() { - int n = 0; - for (int counter=0; counter0) n++; - } - return n; - } - - /** Returns the counter assocated with the specified point. */ - public int getCounter(int index) { - if (counters==null || index>=counters.length) - return 0; - else - return counters[index]; - } - - /** Deletes all counters and stack position associations */ - public void resetCounters() { - for (int i=0; iroi if keepContained is true (false). */ - PointRoi checkContained(Roi roi, boolean keepContained) { - if (!roi.isArea()) return null; - FloatPolygon points = getFloatPolygon(); - FloatPolygon points2 = new FloatPolygon(); - for (int i=0; i=0 && type=0 && type=0 && index=0 && sizenCounters-1 && nCounters8||getNCounters()>1) && imp!=null && imp.getWindow()!=null; - } - - public void promptBeforeDeleting(Boolean prompt) { - promptBeforeDeleting = prompt; - promptBeforeDeletingCalled = true; - } - - public static void setDefaultCounter(int counter) { - defaultCounter = counter; - } - - /** Returns an array containing for each point: - * The counter number (0-100) in the lower 8 bits, and the slice number - * (or 0, if the point appears on all slices) in the higher 24 bits. - * Used when writing a Roi to file (RoiEncoder) */ - public int[] getCounters() { - if (nPoints>65535) - return null; - int[] temp = new int[nPoints]; - if (counters!=null) { - for (int i=0; i>8; - this.counters[i] = (short)counter; - this.positions[i] = position; - if (counternCounters-1) - nCounters = counter + 1; - } - updateCounts(); - } - } - - /** Updates the counts for each category in 'counters' */ - public void updateCounts() { - Arrays.fill(counts, 0); - for (int i=0; i=counts.length) ? 0 : counters[i]] ++; - } - - /** Sets the stack position (image number) of all points in this Roi. - * The points are only displayed when the stack is at the specified position. - * Set to zero to have the points displayed on all images in the stack. - * The stack position, when set, determines the visibility of this Roi - * (i) if it is part of an overlay (normal overlay or the RoiManager's - * 'Show All' overlay), or - * (ii) if it is the currently active Roi and Prefs.showAllPoints - * ('Show an all slices' in the Point Tool Options dialog) is off. - * Clears any association of this Roi to a hyperstack position. - * Stack positions of individual points are overwritten. - * - * Note that the behavior differs from that of the other Roi types: - * For the other Roi types, setPosition does not restrict the visibility - * to stack slice 'n' if that roi is the currently active Roi; it only - * affects the visibility if that Roi is part of an overlay. - */ - public void setPosition(int n) { - if (n<0 && n!=POINTWISE_POSITION) - n = 0; - if (n == 0) { - positions = null; - } else { - if (positions == null) { - if (counters == null) - counters = new short[nPoints*2]; - positions = new int[counters.length]; - } - if (n != POINTWISE_POSITION) - Arrays.fill(positions, n); - } - super.setPosition(nPoints>1?0:n); - } - - /** Returns the stack position (image number) of the points in this Roi, if - * all points have the same position. Returns 0 if none of the points is - * associated with a particular stack image, and PointRoi.POINTWISE_POSITION = -2 - * if there are different stack positions for different points. - */ - public int getPosition() { - int position = 0; - if (positions==null || nPoints<1) - position = 0; - else if (nPoints==1) - return super.getPosition(); - else { - position = positions[0]; - for (int i=1; i= 0; - } - - public void displayCounts() { - ImagePlus imp = getImage(); - String firstColumnHdr = "Slice"; - rt = new ResultsTable(); - int row = 0; - if (imp!=null && imp.getStackSize()>1 && positions!=null) { - int nChannels = 1; - int nSlices = 1; - int nFrames = 1; - boolean isHyperstack = true; - if (imp.isComposite() || imp.isHyperStack()) { - nChannels = imp.getNChannels(); - nSlices = imp.getNSlices(); - nFrames = imp.getNFrames(); - int nDimensions = 2; - if (nChannels>1) nDimensions++; - if (nSlices>1) nDimensions++; - if (nFrames>1) nDimensions++; - if (nDimensions==3) { - isHyperstack = false; - if (nChannels>1) - firstColumnHdr = "Channel"; - } else - firstColumnHdr = "Image"; - } - int firstSlice = Integer.MAX_VALUE; - for (int i=0; i0 && positions[i]0) { - for (int i=0; ilastSlice) - lastSlice = positions[i]; - } - } - if (firstSlice>0) { - for (int slice=firstSlice; slice<=lastSlice; slice++) { - rt.setValue(firstColumnHdr, row, slice); - if (isHyperstack) { - int[] position = imp.convertIndexToPosition(slice); - if (nChannels>1) - rt.setValue("Channel", row, position[0]); - if (nSlices>1) - rt.setValue("Slice", row, position[1]); - if (nFrames>1) - rt.setValue("Frame", row, position[2]); - } - for (int counter=0; counter1?imp.getCurrentSlice():0; - for (int i=0; i=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) { - handle = i; - break; - } - } - return handle; - } - - /** Returns the points as an array of Points. - * Wilhelm Burger: modified to use FloatPolygon for correct point positions. - */ - public Point[] getContainedPoints() { - FloatPolygon p = getFloatPolygon(); - Point[] points = new Point[p.npoints]; - for (int i=0; i iterator() { - return new Iterator() { - final Point[] pnts = getContainedPoints(); - final int n = pnts.length; - int next = (n == 0) ? 1 : 0; - @Override - public boolean hasNext() { - return next < n; - } - @Override - public Point next() { - if (next >= n) { - throw new NoSuchElementException(); - } - Point pnt = pnts[next]; - next = next + 1; - return pnt; - } - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - protected int getClosestPoint(double x, double y, FloatPolygon points) { - int index = -1; - double distance = Double.MAX_VALUE; - int slice = imp!=null&&positions!=null&&imp.getStackSize()>1?imp.getCurrentSlice():0; - if (Prefs.showAllPoints) - slice = 0; - for (int i=0; i=0; i--) { - if (!roi.contains(p.xpoints[i],p.ypoints[i])) { - points.deletePoint(i); - } - } - return points; - } - - @Override - public void copyAttributes(Roi roi2) { - super.copyAttributes(roi2); - if (roi2 instanceof PointRoi) { - PointRoi p2 = (PointRoi)roi2; - this.type = p2.type; - this.size = p2.size; - this.showLabels = p2.showLabels; - this.fontSize = p2.fontSize; - } - } - - public void setCounterInfo(int[] info) { - counterInfo = info; - } - - public int[] getCounterInfo() { - return counterInfo; - } - - public boolean addToOverlay() { - return addToOverlay; - } - - public String toString() { - if (nPoints>1) - return ("Roi[Points, count="+nPoints+", pos="+getPositionAsString()+", psize="+size+"]"); - else - return ("Roi[Point, x="+x+", y="+y+", pos="+getPositionAsString()+", psize="+size+"]"); - } - - /** @deprecated */ - public void setHideLabels(boolean hideLabels) { - this.showLabels = !hideLabels; - } - - /** @deprecated */ - public static void setDefaultMarkerSize(String size) { - } - - /** @deprecated */ - public static String getDefaultMarkerSize() { - return sizes[defaultSize]; - } - - /** Deprecated */ - public static void setDefaultCrossColor(Color color) { - } - - /** Deprecated */ - public static Color getDefaultCrossColor() { - return null; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/PolygonRoi.java b/com.eco.bio7.image/src/ij/gui/PolygonRoi.java deleted file mode 100644 index 2b58adde9..000000000 --- a/com.eco.bio7.image/src/ij/gui/PolygonRoi.java +++ /dev/null @@ -1,1705 +0,0 @@ -package ij.gui; -import ij.*; -import ij.process.*; -import ij.measure.*; -import ij.plugin.frame.*; -import ij.util.Tools; -import ij.util.FloatArray; -import java.awt.*; -import java.awt.image.*; -import java.awt.geom.*; -import java.awt.event.*; - -/** This class represents a polygon region of interest or polyline of interest. */ -public class PolygonRoi extends Roi { - - protected int maxPoints = 1000; // will be increased if necessary - protected int[] xp, yp; // image coordinates relative to origin of roi bounding box - protected float[] xpf, ypf; // or alternative sub-pixel coordinates - protected int[] xp2, yp2; // absolute screen coordinates - protected int nPoints; - protected float[] xSpline,ySpline; // relative image coordinates - protected int splinePoints = 200; - Rectangle clip; - - private double angle1, degrees=Double.NaN; - private int xClipMin, yClipMin, xClipMax, yClipMax; - private boolean userCreated; - private int boxSize = 8; - - long mouseUpTime = 0; - - /** Creates a new polygon or polyline ROI from x and y coordinate arrays. - Type must be Roi.POLYGON, Roi.FREEROI, Roi.TRACED_ROI, Roi.POLYLINE, Roi.FREELINE or Roi.ANGLE.*/ - public PolygonRoi(int[] xPoints, int[] yPoints, int nPoints, int type) { - super(0, 0, null); - init1(nPoints, type); - xp = xPoints; - yp = yPoints; - if (type!=TRACED_ROI) { - xp = new int[nPoints]; - yp = new int[nPoints]; - for (int i=0; i1 && isLine()) - updateWideLine(lineWidth); - finishPolygon(); - } - - /** Creates a new polygon or polyline ROI from a Polygon. Type must be Roi.POLYGON, - Roi.FREEROI, Roi.TRACED_ROI, Roi.POLYLINE, Roi.FREELINE or Roi.ANGLE.*/ - public PolygonRoi(Polygon p, int type) { - this(p.xpoints, p.ypoints, p.npoints, type); - } - - /** Creates a new polygon or polyline ROI from a FloatPolygon. Type must be Roi.POLYGON, - Roi.FREEROI, Roi.TRACED_ROI, Roi.POLYLINE, Roi.FREELINE or Roi.ANGLE.*/ - public PolygonRoi(FloatPolygon p, int type) { - this(p.xpoints, p.ypoints, p.npoints, type); - } - - /** @deprecated */ - public PolygonRoi(int[] xPoints, int[] yPoints, int nPoints, ImagePlus imp, int type) { - this(xPoints, yPoints, nPoints, type); - setImage(imp); - } - - /** Starts the process of creating a new user-generated polygon or polyline ROI. */ - public PolygonRoi(int sx, int sy, ImagePlus imp) { - super(sx, sy, imp); - int tool = Toolbar.getToolId(); - switch (tool) { - case Toolbar.POLYGON: - type = POLYGON; - break; - case Toolbar.FREEROI: - type = FREEROI; - break; - case Toolbar.FREELINE: - type = FREELINE; - break; - case Toolbar.ANGLE: - type = ANGLE; - break; - default: - type = POLYLINE; - break; - } - if (magnificationForSubPixel()) - enableSubPixelResolution(); - previousSX = sx; - previousSY = sy; - x = offScreenX(sx); - y = offScreenY(sy); - startXD = offScreenXD(sx); - startYD = offScreenYD(sy); - if (subPixelResolution()) { - setLocation(startXD, startYD); - xpf = new float[maxPoints]; - ypf = new float[maxPoints]; - double xbase = getXBase(); - double ybase = getYBase(); - xpf[0] = (float)(startXD-xbase); - ypf[0] = (float)(startYD-ybase); - xpf[1] = xpf[0]; - ypf[1] = ypf[0]; - } else { - xp = new int[maxPoints]; - yp = new int[maxPoints]; - } - xp2 = new int[maxPoints]; - yp2 = new int[maxPoints]; - nPoints = 2; - width=1; - height=1; - clipX = x; - clipY = y; - clipWidth = 1; - clipHeight = 1; - state = CONSTRUCTING; - userCreated = true; - if (lineWidth>1 && isLine()) - updateWideLine(lineWidth); - boxSize = (int)(boxSize*Prefs.getGuiScale()); - } - - private void drawStartBox(Graphics g) { - if (type!=ANGLE) - g.drawRect(screenXD(startXD)-4, screenYD(startYD)-4, 8, 8); - } - - public void draw(Graphics g) { - updatePolygon(); - Color color = strokeColor!=null?strokeColor:ROIColor; - boolean hasHandles = xSpline!=null||type==POLYGON||type==POLYLINE||type==ANGLE; - boolean isActiveOverlayRoi = !overlay && isActiveOverlayRoi(); - if (isActiveOverlayRoi) { - if (color==Color.cyan) - color = Color.magenta; - else - color = Color.cyan; - } - boolean fill = false; - mag = getMagnification(); - if (fillColor!=null && !isLine() && state!=CONSTRUCTING) { - color = fillColor; - fill = true; - } - g.setColor(color); - Graphics2D g2d = (Graphics2D)g; - setRenderingHint(g2d); - if (stroke!=null && !isActiveOverlayRoi) - g2d.setStroke(getScaledStroke()); - if (xSpline!=null) { - if (type==POLYLINE || type==FREELINE) { - drawSpline(g, xSpline, ySpline, splinePoints, false, fill, isActiveOverlayRoi); - if (wideLine && !overlay) { - g2d.setStroke(onePixelWide); - g.setColor(getColor()); - drawSpline(g, xSpline, ySpline, splinePoints, false, fill, isActiveOverlayRoi); - } - } else - drawSpline(g, xSpline, ySpline, splinePoints, true, fill, isActiveOverlayRoi); - } else { - if (type==POLYLINE || type==FREELINE || type==ANGLE || (state==CONSTRUCTING && !(this instanceof RotatedRectRoi))) { g.drawPolyline(xp2, yp2, nPoints); - if (wideLine && !overlay) { - g2d.setStroke(onePixelWide); - g.setColor(getColor()); - g.drawPolyline(xp2, yp2, nPoints); - } - } else { - if (fill) { - if (isActiveOverlayRoi) { - g.setColor(Color.cyan); - g.drawPolygon(xp2, yp2, nPoints); - } else - g.fillPolygon(xp2, yp2, nPoints); - if (strokeColor!=null) { - g.setColor(strokeColor); - g.drawPolygon(xp2, yp2, nPoints); - } - } else - g.drawPolygon(xp2, yp2, nPoints); - } - if (state==CONSTRUCTING && type!=FREEROI && type!=FREELINE) - drawStartBox(g); - } - if (hasHandles && clipboard==null && !overlay) { - if (activeHandle>0) - drawHandle(g, xp2[activeHandle-1], yp2[activeHandle-1]); - if (activeHandle1f) - ip.setLineWidth((int)Math.round(getStrokeWidth())); - double xbase = getXBase(); - double ybase = getYBase(); - if (xSpline!=null) { - ip.moveTo((int)Math.round(xbase+xSpline[0]), (int)Math.round(ybase+ySpline[0])); - for (int i=1; i Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - - // Do rubber banding - int tool = Toolbar.getToolId(); - if (!(tool==Toolbar.POLYGON || tool==Toolbar.POLYLINE || tool==Toolbar.ANGLE)) { - imp.deleteRoi(); - imp.draw(); - return; - } - if (IJ.altKeyDown()) - wipeBack(); - - drawRubberBand(sx, sy); - - // show status: length & angle - degrees = Double.NaN; - double len = -1; - if (nPoints>1) { - double x1, y1, x2, y2; - if (xpf!=null) { - x1 = xpf[nPoints-2]; - y1 = ypf[nPoints-2]; - x2 = xpf[nPoints-1]; - y2 = ypf[nPoints-1]; - } else { - x1 = xp[nPoints-2]; - y1 = yp[nPoints-2]; - x2 = xp[nPoints-1]; - y2 = yp[nPoints-1]; - } - degrees = getFloatAngle(x1, y1, x2, y2); - if (tool!=Toolbar.ANGLE) { - Calibration cal = imp.getCalibration(); - double pw=cal.pixelWidth, ph=cal.pixelHeight; - if (IJ.altKeyDown()) {pw=1.0; ph=1.0;} - len = Math.sqrt((x2-x1)*pw*(x2-x1)*pw + (y2-y1)*ph*(y2-y1)*ph); - } - } - if (tool==Toolbar.ANGLE) { - if (nPoints==2) - angle1 = degrees; - else if (nPoints==3) { - double angle2 = xpf != null ? getFloatAngle(xpf[1], ypf[1], xpf[2], ypf[2]) : - getAngle(xp[1], yp[1], xp[2], yp[2]); - degrees = Math.abs(180-Math.abs(angle1-angle2)); - if (degrees>180.0) - degrees = 360.0-degrees; - } - } - String length = len!=-1?", length=" + IJ.d2s(len):""; - double degrees2 = tool==Toolbar.ANGLE&&nPoints==3&&Prefs.reflexAngle?360.0-degrees:degrees; - String angle = !Double.isNaN(degrees)?", angle=" + IJ.d2s(degrees2):""; - int ox = ic.offScreenX(sx); - int oy = ic.offScreenY(sy); - IJ.showStatus(imp.getLocationAsString(ox,oy) + length + angle); - } - - //Mouse behaves like an eraser when moved backwards with alt key down. - //Within correction circle, all vertices with sharp angles are removed. - //Norbert Vischer - protected void wipeBack() { - Roi prevRoi = Roi.getPreviousRoi(); - if (prevRoi!=null && prevRoi.modState==SUBTRACT_FROM_ROI) - return; - double correctionRadius = 20; - if (ic!=null) - correctionRadius /= ic.getMagnification(); - boolean found = false; - int p3 = nPoints - 1; - int p1 = p3; - while (p1 > 0 && !found) { - p1--; - double dx = xpf != null ? xpf[p3] - xpf[p1] : xp[p3] - xp[p1]; - double dy = xpf != null ? ypf[p3] - ypf[p1] : yp[p3] - yp[p1]; - double dist = Math.sqrt(dx * dx + dy * dy); - if (dist > correctionRadius) - found = true; - } - //examine all angles p1-p2-p3 - boolean killed = false; - int safety = 10; //don't delete more than this number of points at once - do { - killed = false; - safety--; - for (int p2 = p1 + 1; p2 < p3; p2++) { - double dx1 = xpf != null ? xpf[p2] - xpf[p1] : xp[p2] - xp[p1]; - double dy1 = xpf != null ? ypf[p2] - ypf[p1] : yp[p2] - yp[p1]; - double dx2 = xpf != null ? xpf[p3] - xpf[p1] : xp[p3] - xp[p1]; - double dy2 = xpf != null ? ypf[p3] - ypf[p1] : yp[p3] - yp[p1]; - double kk = 1;//allowed sharpness - if (this instanceof FreehandRoi) - kk = 0.8; - if ((dx1 * dx1 + dy1 * dy1) > kk * (dx2 * dx2 + dy2 * dy2)) { - if (xpf != null) { - xpf[p2] = xpf[p3]; ypf[p2] = ypf[p3]; //replace sharp vertex with end point - } else { - xp[p2] = xp[p3]; yp[p2] = yp[p3]; - } - p3 = p2; - nPoints = p2 + 1; //shorten array - killed = true; - } - } - } while (killed && safety > 0); - } - - void drawRubberBand(int sx, int sy) { - double oxd = offScreenXD(sx); - double oyd = offScreenYD(sy); - int ox = offScreenX(sx); - int oy = offScreenY(sy); - int x1, y1, x2, y2; - if (xpf!=null) { - x1 = (int)xpf[nPoints-2]+x; - y1 = (int)ypf[nPoints-2]+y; - x2 = (int)xpf[nPoints-1]+x; - y2 = (int)ypf[nPoints-1]+y; - } else { - x1 = xp[nPoints-2]+x; - y1 = yp[nPoints-2]+y; - x2 = xp[nPoints-1]+x; - y2 = yp[nPoints-1]+y; - } - int xmin=Integer.MAX_VALUE, ymin=Integer.MAX_VALUE, xmax=0, ymax=0; - if (x1xmax) xmax=x1; - if (x2>xmax) xmax=x2; - if (ox>xmax) xmax=ox; - if (y1ymax) ymax=y1; - if (y2>ymax) ymax=y2; - if (oy>ymax) ymax=oy; - int margin = boxSize; - if (ic!=null) { - double mag = ic.getMagnification(); - if (mag<1.0) margin = (int)(margin/mag); - } - margin = (int)(margin+getStrokeWidth()); - if (IJ.altKeyDown()) - margin+=20; - if (xpf!=null) { - xpf[nPoints-1] = (float)(oxd-getXBase()); - ypf[nPoints-1] = (float)(oyd-getYBase()); - } else { - xp[nPoints-1] = ox-x; - yp[nPoints-1] = oy-y; - } - if (type==POLYLINE && Prefs.splineFitLines) { - fitSpline(); - imp.draw(); - } else - imp.draw(xmin-margin, ymin-margin, (xmax-xmin)+margin*2, (ymax-ymin)+margin*2); - } - - void finishPolygon() { - if (xpf!=null) { - double xbase0 = getXBase(); - double ybase0 = getYBase(); - FloatPolygon poly = new FloatPolygon(xpf, ypf, nPoints); - bounds = poly.getFloatBounds(); - for (int i=0; i Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - - if (clipboard!=null) return; - - int ox = offScreenX(sx); - int oy = offScreenY(sy); - if (xpf!=null) { - xpf[activeHandle] = (float)(offScreenXD(sx)-getXBase()); - ypf[activeHandle] = (float)(offScreenYD(sy)-getYBase()); - } else { - xp[activeHandle] = ox-x; - yp[activeHandle] = oy-y; - } - if (xSpline!=null) { - fitSpline(splinePoints); - imp.draw(); - } else { - if (!subPixelResolution() || (type==POINT&&nPoints==1)) - resetBoundingRect(); - if (type==POINT && width==0 && height==0) - {width=1; height=1;} - updateClipRectAndDraw(); - } - String angle = type==ANGLE?getAngleAsString():""; - IJ.showStatus(imp.getLocationAsString(ox,oy) + angle); - } - - /** After handle is moved, find clip rect and repaint. */ - void updateClipRectAndDraw() { - if (xpf!=null) { - xp = toInt(xpf, xp, nPoints); - yp = toInt(ypf, yp, nPoints); - } - int xmin=Integer.MAX_VALUE, ymin=Integer.MAX_VALUE, xmax=0, ymax=0; - int x2, y2; - if (activeHandle>0) - {x2=x+xp[activeHandle-1]; y2=y+yp[activeHandle-1];} - else - {x2=x+xp[nPoints-1]; y2=y+yp[nPoints-1];} - if (x2xmax) xmax = x2; - if (y2>ymax) ymax = y2; - x2=x+xp[activeHandle]; y2=y+yp[activeHandle]; - if (x2xmax) xmax = x2; - if (y2>ymax) ymax = y2; - if (activeHandlexmax) xmax = x2; - if (y2>ymax) ymax = y2; - int xmin2=xmin, ymin2=ymin, xmax2=xmax, ymax2=ymax; - if (xClipMinxmax2) xmax2 = xClipMax; - if (yClipMax>ymax2) ymax2 = yClipMax; - xClipMin=xmin; yClipMin=ymin; xClipMax=xmax; yClipMax=ymax; - double mag = ic.getMagnification(); - int handleSize = type==POINT?getHandleSize()+25:getHandleSize(); - double strokeWidth = getStrokeWidth(); - if (strokeWidth<1.0) strokeWidth=1.0; - if (handleSizexmax) xmax=xx; - yy = yp[i]; - if (yyymax) ymax=yy; - } - if (xmin!=0) { - for (int i=0; i180.0) - degrees = 360.0-degrees; - double degrees2 = Prefs.reflexAngle&&type==ANGLE?360.0-degrees:degrees; - return ", angle=" + IJ.d2s(degrees2); - } - - protected void mouseDownInHandle(int handle, int sx, int sy) { - if (state==CONSTRUCTING) - return; - int ox = offScreenX(sx); - int oy = offScreenY(sy); - double oxd = offScreenXD(sx); - double oyd = offScreenYD(sy); - if ((IJ.altKeyDown()||IJ.controlKeyDown()) && !(nPoints<=3 && type!=POINT) && !(this instanceof RotatedRectRoi)) { - deleteHandle(oxd, oyd); - return; - } else if (IJ.shiftKeyDown() && type!=POINT && !(this instanceof RotatedRectRoi)) { - addHandle(oxd, oyd); - return; - } - super.mouseDownInHandle(handle, sx, sy); //sets state, activeHandle, previousSX&Y - int m = ic!=null?(int)(10.0/ic.getMagnification()):1; - xClipMin=ox-m; yClipMin=oy-m; xClipMax=ox+m; yClipMax=oy+m; - } - - public void deleteHandle(double ox, double oy) { - if (imp==null) - return; - if (nPoints<=1) { - imp.deleteRoi(); - return; - } - boolean splineFit = xSpline!=null; - if (splineFit) - removeSplineFit(); - FloatPolygon points = getFloatPolygon(); - int pointToDelete = getClosestPoint(ox, oy, points); - if (pointToDelete>=0) { - deletePoint(pointToDelete); - if (splineFit) - fitSpline(splinePoints); - imp.draw(); - } - } - - protected void deletePoint(int index) { - if (index<0 || index>=nPoints) - return; - for (int i=index; i=maxPoints) - enlargeArrays(); - float xbase = (float)getXBase(); - float ybase = (float)getYBase(); - if (xp==null) { - xp = new int[maxPoints]; - yp = new int[maxPoints]; - } - for (int i=0; i= 0.0 || i==npoints-1) && pointsWritten < npOut) { // we have to write a new point - double fractionOverNextWrite = distanceOverNextWrite/distance; - if (distance==0) fractionOverNextWrite = 0; - xpOut[pointsWritten] = (float)(x2 - fractionOverNextWrite*dx); - ypOut[pointsWritten] = (float)(y2 - fractionOverNextWrite*dy); - distanceOverNextWrite -= step; - pointsWritten++; - } - } - return new float[][] {xpOut, ypOut, new float[] {(float)step}}; - } - - /** With segmented selections, ignore first mouse up and finalize - when user double-clicks, control-clicks or clicks in start box. */ - protected void handleMouseUp(int sx, int sy) { - if (state==MOVING) { - state = NORMAL; - return; - } - if (state==MOVING_HANDLE) { - cachedMask = null; //mask is no longer valid - state = NORMAL; - updateClipRect(); - oldX=x; oldY=y; - oldWidth=width; oldHeight=height; - if (subPixelResolution()) - resetBoundingRect(); - return; - } - if (state!=CONSTRUCTING) - return; - if (IJ.spaceBarDown()) // is user scrolling image? - return; - boolean samePoint = false; - if (xpf!=null) - samePoint = (xpf[nPoints-2]==xpf[nPoints-1] && ypf[nPoints-2]==ypf[nPoints-1]); - else - samePoint = (xp[nPoints-2]==xp[nPoints-1] && yp[nPoints-2]==yp[nPoints-1]); - boolean doubleClick = (System.currentTimeMillis()-mouseUpTime)<=300; - int size = boxSize+2; - int size2 = boxSize/2 +1; - Rectangle biggerStartBox = new Rectangle(screenXD(startXD)-5, screenYD(startYD)-5, 10, 10); - if (nPoints>2 && (biggerStartBox.contains(sx, sy) - || (offScreenXD(sx)==startXD && offScreenYD(sy)==startYD) - || (samePoint && doubleClick))) { - boolean okayToFinish = true; - if (type==POLYGON && samePoint && doubleClick && nPoints>25) { - okayToFinish = IJ.showMessageWithCancel("Polygon Tool", "Complete the selection?"); - } - if (okayToFinish) { - nPoints--; - addOffset(); - finishPolygon(); - return; - } - } else if (!samePoint) { - mouseUpTime = System.currentTimeMillis(); - if (type==ANGLE && nPoints==3) { - addOffset(); - finishPolygon(); - return; - } - //add point to polygon - if (xpf!=null) { - xpf[nPoints] = xpf[nPoints-1]; - ypf[nPoints] = ypf[nPoints-1]; - nPoints++; - if (nPoints==xpf.length) - enlargeArrays(); - } else { - xp[nPoints] = xp[nPoints-1]; - yp[nPoints] = yp[nPoints-1]; - nPoints++; - if (nPoints==xp.length) - enlargeArrays(); - } - if (constrain) { // this point was constrained in 90deg steps; correct coordinates - int dx = sx - previousSX; - int dy = sy - previousSY; - if (Math.abs(dx) > Math.abs(dy)) - dy = 0; - else - dx = 0; - sx = previousSX + dx; - sy = previousSY + dy; - } - previousSX = sx; //save for constraining next line if desired - previousSY = sy; - notifyListeners(RoiListener.EXTENDED); - } - } - - protected void addOffset() { - if (xpf!=null) { - float xbase = (float)getXBase(); - float ybase = (float)getYBase(); - for (int i=0; i=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) { - handle = i; - break; - } - } - return handle; - } - - public ImageProcessor getMask() { - ImageProcessor mask = cachedMask; - if (mask!=null && mask.getPixels()!=null - && mask.getWidth()==width && mask.getHeight()==height) - return mask; - PolygonFiller pf = new PolygonFiller(); - if (xSpline!=null) - pf.setPolygon(xSpline, ySpline, splinePoints, getXBase()-x, getYBase()-y); - else if (xpf!=null) - pf.setPolygon(xpf, ypf, nPoints, getXBase()-x, getYBase()-y); - else - pf.setPolygon(xp, yp, nPoints); - mask = pf.getMask(width, height); - cachedMask = mask; - return mask; - } - - /** Returns the length of this line selection after - smoothing using a 3-point running average.*/ - double getSmoothedLineLength(ImagePlus imp) { - if (subPixelResolution() && xpf!=null) - return getFloatSmoothedLineLength(imp); - double length = 0.0; - double w2 = 1.0; - double h2 = 1.0; - double dx, dy; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - w2 = cal.pixelWidth*cal.pixelWidth; - h2 = cal.pixelHeight*cal.pixelHeight; - } - dx = (xp[0]+xp[1]+xp[2])/3.0-xp[0]; - dy = (yp[0]+yp[1]+yp[2])/3.0-yp[0]; - length += Math.sqrt(dx*dx*w2+dy*dy*h2); - for (int i=1; i1 || !corner) { - corner = true; - nCorners++; - } else - corner = false; - dx1 = dx2; - dy1 = dy2; - side1 = side2; - } - double w=1.0,h=1.0; - if (imp!=null) { - Calibration cal = imp.getCalibration(); - w = cal.pixelWidth; - h = cal.pixelHeight; - } - return sumdx*w+sumdy*h-(nCorners*((w+h)-Math.sqrt(w*w+h*h))); - } - - /** Returns the perimeter (for ROIs) or length (for lines).*/ - public double getLength() { - return getLength(imp); - } - - public double getUncalibratedLength() { - return getLength(null); - } - - /** Returns the perimeter (for ROIs) or length (for lines), using calibration if imp is not null */ - double getLength(ImagePlus imp) { - if (isTraced()) - return getTracedPerimeter(imp); - - if (nPoints>2) { - if (type==FREEROI) - return getSmoothedPerimeter(imp); - else if (type==FREELINE && !(width==0 || height==0)) - return getSmoothedLineLength(imp); - } - - boolean closeShape = isArea(); - if (xSpline!=null) - return getLength(xSpline, ySpline, splinePoints, closeShape, imp); - else if (xpf!=null) - return getLength(xpf, ypf, nPoints, closeShape, imp); - else - return getLength(xp, yp, nPoints, closeShape, imp); - } - - /** Returns 'true' if this ROI was created using - * the wand tool or the particle analyzer. - */ - private boolean isTraced() { - if (type==TRACED_ROI) - return true; - else if (type!=POLYGON || (this instanceof RotatedRectRoi)) - return false; - else if (xp==null) { - if (xpf==null) - return false; - for (int i=0; i "+newSize); - maxPoints = newSize; - } - - public void setLocation(double x, double y) { - super.setLocation(x, y); - if ((int)x!=x || (int)y!=y) - enableSubPixelResolution(); - } - - public void enableSubPixelResolution() { - super.enableSubPixelResolution(); - if (xpf==null && xp!=null) { - xpf = toFloat(xp); - ypf = toFloat(yp); - } - } - - public String getDebugInfo() { - String s = "ROI Debug Properties\n"; - s += " bounds: "+bounds+"\n"; - s += " x,y,w,h: "+x+","+y+","+width+","+height+"\n"; - if (xpf!=null && xpf.length>0) - s += " xpf[0],ypf[0]: "+xpf[0]+","+ypf[0]+"\n"; - return s; - } - -} diff --git a/com.eco.bio7.image/src/ij/gui/ProfilePlot.java b/com.eco.bio7.image/src/ij/gui/ProfilePlot.java deleted file mode 100644 index 1bc063da9..000000000 --- a/com.eco.bio7.image/src/ij/gui/ProfilePlot.java +++ /dev/null @@ -1,340 +0,0 @@ -package ij.gui; - -import java.awt.*; -import java.util.ArrayList; -import ij.*; -import ij.process.*; -import ij.util.*; -import ij.measure.*; -import ij.plugin.Straightener; - -/** Creates a density profile plot of a line or rectangular selection. */ -public class ProfilePlot { - - static final int MIN_WIDTH = 350; - static final double ASPECT_RATIO = 0.5; - private double min, max; - private boolean minAndMaxCalculated; - private static double fixedMin; - private static double fixedMax; - - protected ImagePlus imp; - protected double[] profile; - protected double magnification; - protected double xInc; - protected String units; - protected String yLabel; - protected float[] xValues; - - - public ProfilePlot() { - } - - /** Based on the current line or rectangular selection, - * creates a profile plot that can be retrieved using - * the getPlot() method. - */ - public ProfilePlot(ImagePlus imp) { - this(imp, false); - } - - /** Based on the current rectangular selection, - * creates profile plot, which is a vertical if - * verticalPlot is 'true'. Use the getPlot() method - * to retrieve the plot. - */ - public ProfilePlot(ImagePlus imp, boolean verticalPlot) { - this.imp = imp; - boolean averageHorizontally = verticalPlot; - Roi roi = imp.getRoi(); - if (roi==null) { - IJ.error("Profile Plot", "Selection required."); - return; - } - int roiType = roi.getType(); - boolean rotatedRect = roi!=null && (roi instanceof RotatedRectRoi); - if (!(roi.isLine()||roiType==Roi.RECTANGLE||rotatedRect)) { - IJ.error("Line or rectangular selection required."); - return; - } - if (rotatedRect) { - double[] p = ((RotatedRectRoi)roi).getParams(); - roi = new Line(p[0], p[1], p[2], p[3]); - roi.setStrokeWidth(p[4]); - roi.setImage(imp); - roiType = Roi.LINE; - } - Calibration cal = imp.getCalibration(); - xInc = cal.pixelWidth; - units = cal.getUnits(); - yLabel = cal.getValueUnit(); - ImageProcessor ip = imp.getProcessor(); - if (roiType==Roi.LINE) - profile = getStraightLineProfile(roi, cal, ip); - else if (roiType==Roi.POLYLINE || roiType==Roi.FREELINE) { - int lineWidth = (int)Math.round(roi.getStrokeWidth()); - if (lineWidth<=1) - profile = getIrregularProfile(roi, ip, cal); - else - profile = getWideLineProfile(imp, lineWidth); - } else if (averageHorizontally) - profile = getRowAverageProfile(roi.getBounds(), cal, ip); - else - profile = getColumnAverageProfile(roi.getBounds(), ip); - ip.setCalibrationTable(null); - ImageCanvas ic = imp.getCanvas(); - if (ic!=null) - magnification = ic.getMagnification(); - else - magnification = 1.0; - } - - /** Returns the size of the plot that createWindow() creates. */ - public Dimension getPlotSize() { - if (profile==null) return null; - int width = (int)(profile.length*magnification); - int height = (int)(width*ASPECT_RATIO); - if (widthmaxWidth) { - width = maxWidth; - height = (int)(width*ASPECT_RATIO); - } - return new Dimension(width, height); - } - - /** Displays this profile plot in a window. */ - public void createWindow() { - Plot plot = getPlot(); - if (plot!=null) - plot.show(); - } - - /** Returns the profile plot as a Plot object. */ - public Plot getPlot() { - if (profile==null) - return null; - String xLabel = "Distance ("+units+")"; - int n = profile.length; - if (xValues==null) { - xValues = new float[n]; - for (int i=0; i0 && (title.length()-index)<=5) - title = title.substring(0, index); - return title; - } - - /** Returns the profile plot data. */ - public double[] getProfile() { - return profile; - } - - /** Returns the calculated minimum value. */ - public double getMin() { - if (!minAndMaxCalculated) - findMinAndMax(); - return min; - } - - /** Returns the calculated maximum value. */ - public double getMax() { - if (!minAndMaxCalculated) - findMinAndMax(); - return max; - } - - /** Sets the y-axis min and max. Specify (0,0) to autoscale. */ - public static void setMinAndMax(double min, double max) { - fixedMin = min; - fixedMax = max; - IJ.register(ProfilePlot.class); - } - - /** Returns the profile plot y-axis min. Auto-scaling is used if min=max=0. */ - public static double getFixedMin() { - return fixedMin; - } - - /** Returns the profile plot y-axis max. Auto-scaling is used if min=max=0. */ - public static double getFixedMax() { - return fixedMax; - } - - double[] getStraightLineProfile(Roi roi, Calibration cal, ImageProcessor ip) { - ip.setInterpolate(PlotWindow.interpolate); - Line line = (Line)roi; - double[] values = line.getPixels(); - if (values==null) return null; - if (cal!=null && cal.pixelWidth!=cal.pixelHeight) { - FloatPolygon p = line.getFloatPoints(); - double dx = p.xpoints[1] - p.xpoints[0]; - double dy = p.ypoints[1] - p.ypoints[0]; - double pixelLength = Math.sqrt(dx*dx + dy*dy); - dx = cal.pixelWidth*dx; - dy = cal.pixelHeight*dy; - double calibratedLength = Math.sqrt(dx*dx + dy*dy); - xInc = calibratedLength * 1.0/pixelLength; - } - return values; - } - - double[] getRowAverageProfile(Rectangle rect, Calibration cal, ImageProcessor ip) { - double[] profile = new double[rect.height]; - int[] counts = new int[rect.height]; - double[] aLine; - ip.setInterpolate(false); - for (int x=rect.x; xsubpixel resolution), - * the line coordinates are interpreted as the roi line shown at high zoom level, - * i.e., integer (x,y) is at the top left corner of pixel (x,y). - * Thus, the coordinates of the pixel center are taken as (x+0.5, y+0.5). - * If subpixel resolution if off, the coordinates of the pixel centers are taken - * as integer (x,y). */ - double[] getIrregularProfile(Roi roi, ImageProcessor ip, Calibration cal) { - boolean interpolate = PlotWindow.interpolate; - boolean calcXValues = cal!=null && cal.pixelWidth!=cal.pixelHeight; - FloatPolygon p = roi.getFloatPolygon(); - int n = p.npoints; - float[] xpoints = p.xpoints; - float[] ypoints = p.ypoints; - ArrayList values = new ArrayList(); - int n2; - double inc = 0.01; - double distance=0.0, distance2=0.0, dx=0.0, dy=0.0, xinc, yinc; - double x, y, lastx=0.0, lasty=0.0, x1, y1, x2=xpoints[0], y2=ypoints[0]; - double value; - for (int i=1; i=1.0-inc/2.0) { - if (interpolate) - value = ip.getInterpolatedValue(x, y); - else - value = ip.getPixelValue((int)Math.round(x), (int)Math.round(y)); - values.add(Double.valueOf(value)); - lastx=x; lasty=y; - } - x += xinc; - y += yinc; - } while (--n2>0); - } - double[] values2 = new double[values.size()]; - for (int i=0; imax) - max = value; - } - this.min = min; - this.max = max; - } - - -} \ No newline at end of file diff --git a/com.eco.bio7.image/src/ij/gui/ProgressBar.java b/com.eco.bio7.image/src/ij/gui/ProgressBar.java deleted file mode 100644 index 87e7cfd9f..000000000 --- a/com.eco.bio7.image/src/ij/gui/ProgressBar.java +++ /dev/null @@ -1,174 +0,0 @@ -package ij.gui; - -import ij.IJ; -import ij.ImageJ; -import ij.macro.Interpreter; - -import java.awt.*; -import java.awt.image.*; - -import javax.swing.JPanel; - -/** - * This is the progress bar that is displayed in the lower right hand corner of - * the ImageJ window. Use one of the static IJ.showProgress() methods to display - * and update the progress bar. - */ -public class ProgressBar extends JPanel { - public static final int WIDTH = 120; - public static final int HEIGHT = 20; - private int canvasWidth, canvasHeight; - private int x, y, width, height; - private long lastTime = 0; - private boolean showBar; - private boolean batchMode; - - private Color barColor = Color.gray; - private Color fillColor = new Color(204, 204, 255); - private Color backgroundColor = ImageJ.getSystemColour();// Changed for Bio7! - private Color frameBrighter = backgroundColor.brighter(); - private Color frameDarker = backgroundColor.darker(); - private boolean dualDisplay = false; - private double slowX = 0.0;// box - private double fastX = 0.0;// dot - - /** - * This constructor is called once by ImageJ at startup. - */ - public ProgressBar(int canvasWidth, int canvasHeight) { - init(canvasWidth, canvasHeight); - } - - public void init(int canvasWidth, int canvasHeight) { - this.canvasWidth = canvasWidth; - this.canvasHeight = canvasHeight; - x = 3; - y = 5; - width = canvasWidth - 8; - height = canvasHeight - 7; - /* Changed for Bio7! */ - this.setBackground(ImageJ.getSystemColour()); - } - - void fill3DRect(Graphics g, int x, int y, int width, int height) { - g.setColor(fillColor); - g.fillRect(x + 1, y + 1, width - 2, height - 2); - g.setColor(frameDarker); - g.drawLine(x, y, x, y + height); - g.drawLine(x + 1, y, x + width - 1, y); - g.setColor(frameBrighter); - g.drawLine(x + 1, y + height, x + width, y + height); - g.drawLine(x + width, y, x + width, y + height - 1); - } - - /** - * Updates the progress bar, where abs(progress) should run from 0 to 1. If - * abs(
- * Javascript example: - *
- * luts = imp.getLuts(); - * for (i=0; i - * IJ.log((i+1)+“: “+luts[i].min+”-”+luts[i].max); - *
ImagePlus.show()
new StackWindow(ImagePlus)
nChannels
nSlices
nFrames
setStack()
roi
Roi.previousRoi
key
get()
value
defaultValue
loc
null
- * This is mainly relevant to linux: Swing components scale automatically on - * most platforms, specially since Java 8. However there are still exceptions to - * this on linux: e.g., In Ubuntu, Swing components do scale, but only under the - * GTK L&F. (On the other hand AWT components do not scale at all on - * hiDPI screens on linux). - *
- * This method tries to avoid exaggerated font sizes by detecting if a component - * has been already scaled by the UIManager, applying only - * {@link #getGuiScale()} to the component's font if not. - *
- * public class Generic_Dialog_Example implements PlugIn { - * static String title = "Example"; - * static int width = 512, height = 512; - * - * public void run(String arg) { - * GenericDialog gd = new GenericDialog("New Image"); - * gd.addStringField("Title: ", title); - * gd.addNumericField("Width: ", width, 0); - * gd.addNumericField("Height: ", height, 0); - * gd.showDialog(); - * if (gd.wasCanceled()) - * return; - * title = gd.getNextString(); - * width = (int) gd.getNextNumber(); - * height = (int) gd.getNextNumber(); - * IJ.newImage(title, "8-bit", width, height, 1); - * } - * } - *
enum
- * import ij.process.AutoThresholder.Method; - * ... - * Method method = Method.Otsu; - * - * GenericDialog gd = new GenericDialog("Select AutoThresholder Method"); - * gd.addEnumChoice("All threshold methods", method); - * ... - * gd.showDialog(); - * ... - * method = gd.getNextEnumChoice(Method.class); - *
- * import ij.process.AutoThresholder.Method; - * ... - * Method[] selectMethods = {Method.Triangle, Method.Otsu, Method.Huang}; - * Method method = Method.Otsu; - * - * GenericDialog gd = new GenericDialog("Select AutoThresholder Method"); - * gd.addEnumChoice("Select threshold methods", selectMethods, method); - * ... - * gd.showDialog(); - * ... - * method = gd.getNextEnumChoice(Method.class); - *
- Default insets: - addMessage: 0,20,0 (empty string) or 10,20,0 - addCheckbox: 15,20,0 (first checkbox) or 0,20,0 - addCheckboxGroup: 10,0,0 - addRadioButtonGroup: 5,10,0 - addNumericField: 5,0,3 (first field) or 0,0,3 - addStringField: 5,0,5 (first field) or 0,0,5 - addChoice: 5,0,5 (first field) or 0,0,5 - *
- * GenericDialog gd = new GenericDialog("YesNoCancel Demo"); - * gd.addMessage("This is a custom YesNoCancel dialog"); - * gd.enableYesNoCancel("Do something", "Do something else"); - * gd.showDialog(); - * if (gd.wasCanceled()) - * IJ.log("User clicked 'Cancel'"); - * else if (gd.wasOKed()) - * IJ.log("User clicked 'Yes'"); - * else - * IJ.log("User clicked 'No'"); - *
newWidth, newHeight
plot
justification
setColor
draw
style
setFrozen(false)
flags
keepContained