diff --git a/pom.xml b/pom.xml index 16e45d68f..8a80f3706 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ sc.fiji Simple_Neurite_Tracer - 3.1.5-SNAPSHOT + 3.1.5 Simple Neurite Tracer The ImageJ framework for semi-automated tracing of neurons and other tube-like structures. diff --git a/src/main/java/tracing/NeuriteTracerResultsDialog.java b/src/main/java/tracing/NeuriteTracerResultsDialog.java index 760323332..5975bc37a 100644 --- a/src/main/java/tracing/NeuriteTracerResultsDialog.java +++ b/src/main/java/tracing/NeuriteTracerResultsDialog.java @@ -38,6 +38,7 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; +import java.awt.Point; import java.awt.Rectangle; import java.awt.TextField; import java.awt.event.ActionEvent; @@ -101,8 +102,9 @@ public class NeuriteTracerResultsDialog extends JDialog implements ActionListene public static final boolean verbose = SimpleNeuriteTracer.verbose; - public PathWindow pw; - public FillWindow fw; + private PathWindow pw; + private FillWindow fw; + private SNTPrefs prefs; protected JMenuBar menuBar; protected JMenu fileMenu; @@ -478,7 +480,7 @@ protected void exitRequested() { plugin.cancelSearch(true); plugin.notifyListeners(new SNTEvent(SNTEvent.QUIT)); - new SNTPrefs(plugin).savePluginPrefs(); + prefs.savePluginPrefs(); pw.dispose(); fw.dispose(); dispose(); @@ -762,6 +764,7 @@ public NeuriteTracerResultsDialog(final String title, final SimpleNeuriteTracer new ClarifyingKeyListener().addKeyAndContainerListenerRecursively(this); this.plugin = plugin; + prefs = plugin.prefs; final SimpleNeuriteTracer thisPlugin = plugin; this.launchedByArchive = launchedByArchive; @@ -1175,7 +1178,8 @@ protected void displayOnStarting() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - arrangeDialogs(); + if (plugin.prefs.isSaveWinLocations()) + arrangeDialogs(); arrangeCanvases(); setVisible(true); setPathListVisible(true, false); @@ -1600,14 +1604,20 @@ else if (reset) } private void arrangeDialogs() { - final GraphicsDevice activeScreen = getGraphicsConfiguration().getDevice(); - final int screenWidth = activeScreen.getDisplayMode().getWidth(); - final int screenHeight = activeScreen.getDisplayMode().getHeight(); - final Rectangle bounds = activeScreen.getDefaultConfiguration().getBounds(); - - setLocation(bounds.x, bounds.y); - pw.setLocation(screenWidth - pw.getWidth(), bounds.y); - fw.setLocation(bounds.x + getWidth(), screenHeight - fw.getHeight()); + Point loc = prefs.getPathWindowLocation(); + if (loc != null) + pw.setLocation(loc); + loc = prefs.getFillWindowLocation(); + if (loc != null) + fw.setLocation(loc); +// final GraphicsDevice activeScreen = getGraphicsConfiguration().getDevice(); +// final int screenWidth = activeScreen.getDisplayMode().getWidth(); +// final int screenHeight = activeScreen.getDisplayMode().getHeight(); +// final Rectangle bounds = activeScreen.getDefaultConfiguration().getBounds(); +// +// setLocation(bounds.x, bounds.y); +// pw.setLocation(screenWidth - pw.getWidth(), bounds.y); +// fw.setLocation(bounds.x + getWidth(), screenHeight - fw.getHeight()); } private void arrangeCanvases() { @@ -1885,7 +1895,7 @@ private JMenu tracingMenu() { optionsMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { - new SNTPrefs(plugin).promptForOptions(); + prefs.promptForOptions(); } }); tracingMenu.add(optionsMenuItem); @@ -1976,4 +1986,12 @@ public void actionPerformed(final ActionEvent e) { return mi; } + public PathWindow getPathWindow() { + return pw; + } + + public FillWindow getFillWindow() { + return fw; + } + } diff --git a/src/main/java/tracing/PathAndFillManager.java b/src/main/java/tracing/PathAndFillManager.java index 26d8a63fe..862b91c20 100644 --- a/src/main/java/tracing/PathAndFillManager.java +++ b/src/main/java/tracing/PathAndFillManager.java @@ -2024,7 +2024,17 @@ synchronized void setPathPointsInVolume(final ArrayList paths, final byte[ */ final List pointsToDraw = Bresenham3D.bresenham3D(previous, current); for (final Bresenham3D.IntegerPoint ip : pointsToDraw) { - slices[ip.z][ip.y * width + ip.x] = (byte) 255; + try { + slices[ip.z][ip.y * width + ip.x] = (byte) 255; + } catch (final ArrayIndexOutOfBoundsException ignored) { + final int x = Math.min(width - 1, Math.max(0, ip.x)); + final int y = Math.min(height - 1, Math.max(0, ip.y)); + final int z = Math.min(depth - 1, Math.max(0, ip.z)); + slices[z][y * width + x] = (byte) 255; + if (SimpleNeuriteTracer.verbose) + SNT.log(String.format("Bresenham3D: Forced out-of-bounds point to [%d][%d * %d + %d]", + z, y, width, x)); + } } } diff --git a/src/main/java/tracing/SNTPrefs.java b/src/main/java/tracing/SNTPrefs.java index ffe850b1f..a68411e54 100644 --- a/src/main/java/tracing/SNTPrefs.java +++ b/src/main/java/tracing/SNTPrefs.java @@ -1,6 +1,7 @@ package tracing; import java.awt.Font; +import java.awt.Point; import ij.Prefs; import ij.gui.GenericDialog; @@ -22,6 +23,7 @@ public class SNTPrefs { private static final int LOOK_FOR_TUBES = 128; private static final int LOOK_FOR_OOF = 256; private static final int SHOW_ONLY_SELECTED = 512; + private static final int STORE_WIN_LOCATIONS = 1024; // private static final int JUST_NEAR_SLICES = 1024; private static final int ENFORCE_DEFAULT_PATH_COLORS = 2048; private static final int DEBUG = 4096; @@ -31,6 +33,11 @@ public class SNTPrefs { private static final String BOOLEANS = "tracing.snt.booleans"; private static final String SNAP_XY = "tracing.snt.xysnap"; private static final String SNAP_Z = "tracing.snt.zsnap"; + private static final String PATHWIN_LOC = "tracing.snt.pwloc"; + private static final String FILLWIN_LOC = "tracing.snt.fwloc"; + + //private static final String SNAP_Z = "tracing.snt.zsnap"; + // private final static String NEARBY_VIEW = "tracing.snt.nearbyview"; private final int UNSET_PREFS = -1; @@ -60,6 +67,7 @@ private void getBooleans() { } protected void loadPluginPrefs() { + getBooleans(); snt.useCompressedXML = getPref(COMPRESSED_XML); snt.autoCanvasActivation = getPref(AUTO_CANVAS_ACTIVATION); snt.snapCursor = getPref(SNAP_CURSOR); @@ -121,6 +129,21 @@ protected void savePluginPrefs() { setPref(DEBUG, SimpleNeuriteTracer.verbose); Prefs.set(BOOLEANS, currentBooleans); clearLegacyPrefs(); + if (isSaveWinLocations()) { + final NeuriteTracerResultsDialog rd = snt.resultsDialog; + if (rd == null) + return; + final PathWindow pw = rd.getPathWindow(); + if (pw != null) + Prefs.saveLocation(PATHWIN_LOC, pw.getLocation()); + final FillWindow fw = rd.getFillWindow(); + if (fw != null) + Prefs.saveLocation(FILLWIN_LOC, fw.getLocation()); + } + } + + protected boolean isSaveWinLocations() { + return getPref(STORE_WIN_LOCATIONS); } private void setPref(final int key, final boolean value) { @@ -130,11 +153,21 @@ private void setPref(final int key, final boolean value) { currentBooleans &= ~key; } + protected Point getPathWindowLocation() { + return Prefs.getLocation(PATHWIN_LOC); + } + + protected Point getFillWindowLocation() { + return Prefs.getLocation(FILLWIN_LOC); + } + private void resetOptions() { clearLegacyPrefs(); Prefs.set(BOOLEANS, null); Prefs.set(SNAP_XY, null); Prefs.set(SNAP_Z, null); + Prefs.set(FILLWIN_LOC, null); + Prefs.set(PATHWIN_LOC, null); currentBooleans = UNSET_PREFS; } @@ -144,7 +177,7 @@ private void clearLegacyPrefs() { protected void promptForOptions() { - final int startupOptions = 6; + final int startupOptions = 7; final int pluginOptions = 2; final String[] startupLabels = new String[startupOptions]; @@ -176,6 +209,10 @@ protected void promptForOptions() { startupLabels[idx] = "Load_default \".traces\" file (if present)"; startupStates[idx++] = snt.look4tracesFile; + startupItems[idx] = STORE_WIN_LOCATIONS; + startupLabels[idx] = "Remember window locations across restarts"; + startupStates[idx++] = isSaveWinLocations(); + final String[] pluginLabels = new String[pluginOptions]; final int[] pluginItems = new int[pluginOptions]; final boolean[] pluginStates = new boolean[pluginOptions]; diff --git a/src/main/java/tracing/ShollAnalysisPlugin.java b/src/main/java/tracing/ShollAnalysisPlugin.java index 00c9bad5c..7d97080f1 100644 --- a/src/main/java/tracing/ShollAnalysisPlugin.java +++ b/src/main/java/tracing/ShollAnalysisPlugin.java @@ -285,7 +285,7 @@ private boolean showDialog() { if (gd.wasCanceled()) return false; else if (gd.wasOKed()) { - sholl.gui.Utils.improveRecording(); + Utils.improveRecording(); return dialogItemChanged(gd, null); } return false; @@ -317,7 +317,7 @@ public void run() { popup.addSeparator(); mi = Utils.menuItemTrigerringURL("Online Documentation", Sholl_Analysis.URL + "#Traces"); popup.add(mi); - mi = sholl.gui.Utils.menuItemTriggeringResources(); + mi = Utils.menuItemTriggeringResources(); popup.add(mi); return popup; } @@ -356,15 +356,15 @@ public boolean dialogItemChanged(final GenericDialog arg0, final AWTEvent event) for (int i = 2; i < cbxs.size(); i++) ((Checkbox) cbxs.get(i)).setEnabled(restrictBySWCType); - boolean enableOK = true; + //boolean enableOK = true; String warning = ""; if (impRequired && !validImageFile(new File(imgPath))) { - enableOK = false; + //enableOK = false; warning += "Not a valid image. "; } if (!validTracesFile(new File(tracesPath))) { - enableOK = false; + //enableOK = false; warning += "Not a valid .traces/.(e)swc file"; } if (!warning.isEmpty()) { @@ -375,7 +375,7 @@ public boolean dialogItemChanged(final GenericDialog arg0, final AWTEvent event) infoMsg.setText(defaultInfoMsg); } - return enableOK; + return true; //enableOK } private String getFilePathWithoutExtension(final String filePath) { @@ -451,10 +451,8 @@ private boolean validTracesFile(final File file) { * We'll need to remove those to avoid I/O errors. */ private String normalizedPath(final String path) { - // This is way to simplistic: See // chase-seibert.github.io/blog/2009/04/10/java-replaceall-fileseparator.html - return path.replaceAll(Matcher.quoteReplacement(File.separator) + "+", - Matcher.quoteReplacement(File.separator)); + return path.replaceAll("(? fromPaths) { // currentlyFilling = true; - resultsDialog.fw.pauseOrRestartFilling.setText("Pause"); + resultsDialog.getFillWindow().pauseOrRestartFilling.setText("Pause"); filler = new FillerThread(xy, stackMin, stackMax, false, // startPaused true, // reciprocal @@ -1246,7 +1247,7 @@ synchronized public void startFillingPaths(final Set fromPaths) { addThreadToDraw(filler); filler.addProgressListener(this); - filler.addProgressListener(resultsDialog.fw); + filler.addProgressListener(resultsDialog.getFillWindow()); filler.setSourcePaths(fromPaths); @@ -1565,14 +1566,14 @@ public void selectPath(final Path p, final boolean addToExistingSelection) { else pathsToSelect.add(p); if (addToExistingSelection) { - pathsToSelect.addAll(resultsDialog.pw.getSelectedPaths()); + pathsToSelect.addAll(resultsDialog.getPathWindow().getSelectedPaths()); } - resultsDialog.pw.setSelectedPaths(pathsToSelect, this); + resultsDialog.getPathWindow().setSelectedPaths(pathsToSelect, this); } public Set getSelectedPaths() { - if (resultsDialog.pw != null) { - return resultsDialog.pw.getSelectedPaths(); + if (resultsDialog.getPathWindow() != null) { + return resultsDialog.getPathWindow().getSelectedPaths(); } throw new RuntimeException("getSelectedPaths was called when resultsDialog.pw was null"); } diff --git a/src/main/java/tracing/Simple_Neurite_Tracer.java b/src/main/java/tracing/Simple_Neurite_Tracer.java index d32b5bc80..6e14f10aa 100644 --- a/src/main/java/tracing/Simple_Neurite_Tracer.java +++ b/src/main/java/tracing/Simple_Neurite_Tracer.java @@ -184,7 +184,7 @@ public void run(final String ignoredArguments) { spacing_units = "" + calibration.getUnit(); } - final SNTPrefs prefs = new SNTPrefs(this); + prefs = new SNTPrefs(this); prefs.loadStartupPrefs(); final GenericDialog gd = new GenericDialog("Simple Neurite Tracer (v" + SNT.VERSION + ")");