diff --git a/src/main/java/sc/fiji/snt/PathManagerUI.java b/src/main/java/sc/fiji/snt/PathManagerUI.java index 521c7391..3ab4e064 100644 --- a/src/main/java/sc/fiji/snt/PathManagerUI.java +++ b/src/main/java/sc/fiji/snt/PathManagerUI.java @@ -487,19 +487,7 @@ private JMenu getTimeSequenceMenu(final MultiPathActionListener multiPathListene final JMenu menu = new JMenu("Time-lapse Utilities"); final String tooltip = "Assumes selected path(s) belong to a time-lapse series"; menu.setIcon(IconFactory.getMenuIcon(IconFactory.GLYPH.VIDEO)); - JMenuItem jmi = new JMenuItem("Apply 3D Drift Corrections..."); - jmi.setToolTipText("Assumes loaded image is a time-lapse series. Should be run before tracing operations"); - jmi.addActionListener( e-> { - if (!plugin.accessToValidImageData() || plugin.getImagePlus().getNFrames() == 1) { - guiUtils.error("A timelapse is required but none seems to be loaded."); - } - else if (!ScriptInstaller.runScript("Plugins/Registration/Correct_3D_drift.py")) { - guiUtils.error("Could not find 'Correct 3D Drift'. " + - "Make sure no files are missing from your Fiji install."); - } - }); - menu.add(jmi); - jmi = new JMenuItem(MultiPathActionListener.MATCH_PATHS_ACROSS_TIME_CMD); + JMenuItem jmi = new JMenuItem(MultiPathActionListener.MATCH_PATHS_ACROSS_TIME_CMD); jmi.setToolTipText(tooltip); jmi.addActionListener(multiPathListener); menu.add(jmi); diff --git a/src/main/java/sc/fiji/snt/SNTUI.java b/src/main/java/sc/fiji/snt/SNTUI.java index 0020d55d..8b4b644b 100644 --- a/src/main/java/sc/fiji/snt/SNTUI.java +++ b/src/main/java/sc/fiji/snt/SNTUI.java @@ -113,7 +113,6 @@ public class SNTUI extends JDialog { private JButton showOrHidePathList; private JButton showOrHideFillList = new JButton(); // must be initialized private JMenuItem saveMenuItem; - private JMenuItem exportCSVMenuItem; private JMenuItem quitMenuItem; private JMenuItem sendToTrakEM2; private JLabel statusText; @@ -880,7 +879,6 @@ public void changeState(final int newState) { fmUI.setEnabledWhileNotFilling(); saveMenuItem.setEnabled(true); - exportCSVMenuItem.setEnabled(true); sendToTrakEM2.setEnabled(plugin.anyListeners()); quitMenuItem.setEnabled(true); showPathsSelected.setEnabled(true); @@ -902,7 +900,6 @@ public void changeState(final int newState) { // setFillListVisible(false); saveMenuItem.setEnabled(true); - exportCSVMenuItem.setEnabled(true); sendToTrakEM2.setEnabled(plugin.anyListeners()); quitMenuItem.setEnabled(true); showPathsSelected.setEnabled(true); @@ -1085,7 +1082,8 @@ private JPanel sourcePanel(final ImagePlus imp) { positionPanel.add(applyPositionButton); final JCheckBox autoCTcheckbox = new JCheckBox("Auto-load CT position of new paths", plugin.autoCT); - commandFinder.register(autoCTcheckbox, "Main Tab", "Data Source"); + commandFinder.register(autoCTcheckbox, "Toggle Auto-load CT Position of New Paths", + "Main Tab", "Data Source"); GuiUtils.addTooltip(autoCTcheckbox, "Automatically loads the active channel and frame of the starting " + "node of newly created paths.
" + "NB: This option may be incompatible with secondary layers and Z-projection overlays."); @@ -1181,7 +1179,7 @@ private JPanel viewsPanel() { final CheckboxSpinner mipCS = new CheckboxSpinner(new JCheckBox("Overlay MIP(s) at"), GuiUtils.integerSpinner(20, 10, 80, 1, true)); - registerInCommandFinder(mipCS.getCheckBox(), "Overlay MIP(s)", "Options Tab"); + registerInCommandFinder(mipCS.getCheckBox(), "Toggle Overlay MIP(s)", "Options Tab"); mipCS.getSpinner().addChangeListener(e -> mipCS.setSelected(false)); mipCS.appendLabel(" % opacity"); mipCS.getCheckBox().addActionListener(e -> { @@ -1201,6 +1199,8 @@ private JPanel viewsPanel() { final JCheckBox zoomAllPanesCheckBox = new JCheckBox("Apply zoom changes to all views", !plugin.isZoomAllPanesDisabled()); + registerInCommandFinder(zoomAllPanesCheckBox, "Toggle Apply Zoom Changes to All Views'", + "Options Tab"); zoomAllPanesCheckBox .addItemListener(e -> plugin.disableZoomAllPanes(e.getStateChange() == ItemEvent.DESELECTED)); viewsPanel.add(zoomAllPanesCheckBox, gdb); @@ -1353,7 +1353,8 @@ private JPanel tracingPanel() { final JCheckBox confirmTemporarySegmentsCheckbox = new JCheckBox("Confirm temporary segments", confirmTemporarySegments); - registerInCommandFinder(confirmTemporarySegmentsCheckbox, null, "Options Tab"); + registerInCommandFinder(confirmTemporarySegmentsCheckbox, "Toggle Confirm Temporary Segments", + "Options Tab"); tPanel.add(confirmTemporarySegmentsCheckbox, gdb); ++gdb.gridy; @@ -1376,13 +1377,16 @@ private JPanel tracingPanel() { final JCheckBox activateFinishedPathCheckbox = new JCheckBox("Finishing a path selects it", plugin.activateFinishedPath); - registerInCommandFinder(activateFinishedPathCheckbox, null, "Options Tab"); + registerInCommandFinder(activateFinishedPathCheckbox, "Toggle Finishing a Path Selects It", + "Options Tab"); GuiUtils.addTooltip(activateFinishedPathCheckbox, "Whether the path being traced should automatically be selected once finished."); activateFinishedPathCheckbox.addItemListener(e -> plugin.enableAutoSelectionOfFinishedPath(e.getStateChange() == ItemEvent.SELECTED)); tPanel.add(activateFinishedPathCheckbox, gdb); ++gdb.gridy; final JCheckBox requireShiftToForkCheckbox = new JCheckBox("Require 'Shift' to branch off a path", plugin.requireShiftToFork); + registerInCommandFinder(requireShiftToForkCheckbox, "Toggle Require 'Shift' to Branch Off a Path", + "Options Tab"); GuiUtils.addTooltip(requireShiftToForkCheckbox, "When branching off a path: Use Shift+Alt+click or Alt+click at the forking node? " + "NB: Alt+click is a common trigger for window dragging on Linux. Use Super+Alt+click to circumvent OS conflics."); requireShiftToForkCheckbox.addItemListener(e ->plugin.requireShiftToFork = e.getStateChange() == ItemEvent.SELECTED); @@ -1395,7 +1399,7 @@ private JPanel pathOptionsPanel() { final JPanel intPanel = new JPanel(new GridBagLayout()); final GridBagConstraints gdb = GuiUtils.defaultGbc(); final JCheckBox diametersCheckBox = new JCheckBox("Draw diameters", plugin.getDrawDiameters()); - registerInCommandFinder(diametersCheckBox, null, "Options Tab"); + registerInCommandFinder(diametersCheckBox, "Toggle Draw Diameters", "Options Tab"); diametersCheckBox.addItemListener(e -> plugin.setDrawDiameters(e.getStateChange() == ItemEvent.SELECTED)); intPanel.add(diametersCheckBox, gdb); ++gdb.gridy; @@ -1618,12 +1622,16 @@ private JPanel miscPanel() { ++gdb.gridy; final JCheckBox canvasCheckBox = new JCheckBox("Activate canvas on mouse hovering", plugin.autoCanvasActivation); + registerInCommandFinder(canvasCheckBox, "Toggle Activate Canvas on Mouse Hovering", + "Options Tab"); GuiUtils.addTooltip(canvasCheckBox, "Whether the image window should be brought to front as soon as the mouse " + "pointer enters it. This may be needed to ensure single key shortcuts work as expected when tracing."); canvasCheckBox.addItemListener(e -> plugin.enableAutoActivation(e.getStateChange() == ItemEvent.SELECTED)); miscPanel.add(canvasCheckBox, gdb); ++gdb.gridy; final JCheckBox askUserConfirmationCheckBox = new JCheckBox("Skip confirmation dialogs", !askUserConfirmation); + registerInCommandFinder(askUserConfirmationCheckBox, "Toggle Skip Confirmation Dialogs", + "Options Tab"); GuiUtils.addTooltip(askUserConfirmationCheckBox, "Whether \"Are you sure?\" type of prompts should precede major operations"); askUserConfirmationCheckBox @@ -2286,7 +2294,8 @@ private JPanel secondaryDataPanel() { c.insets.left *= 2; secLayerImgOverlayCSpinner = new CheckboxSpinner(new JCheckBox("Render in overlay at "), GuiUtils.integerSpinner(20, 10, 80, 1, true)); - registerInCommandFinder(secLayerImgOverlayCSpinner.getCheckBox(), "Toggle secondary layer overlay", "Main Tab"); + registerInCommandFinder(secLayerImgOverlayCSpinner.getCheckBox(), "Toggle Secondary Layer Overlay", + "Main Tab"); secLayerImgOverlayCSpinner.getSpinner().addChangeListener(e -> { secLayerImgOverlayCSpinner.setSelected(false); }); @@ -2658,17 +2667,10 @@ private JMenuBar createMenuBar() { getPathManager().quickMeasurementsCmdError(guiUtils); } }); - final JMenuItem plotMenuItem = new JMenuItem("Reconstruction Plotter...", IconFactory.getMenuIcon(IconFactory.GLYPH.DRAFT)); - plotMenuItem.setToolTipText("Renders traced paths as vector graphics (2D)"); - plotMenuItem.addActionListener( e -> { - if (noPathsError()) return; - final Tree tree = getPathManager().getSingleTree(); - if (tree == null) return; - final Map input = new HashMap<>(); - input.put("tree", tree); - final CommandService cmdService = plugin.getContext().getService(CommandService.class); - cmdService.run(PlotterCmd.class, true, input); - }); + + analysisMenu.add(getBrainAnnotationMenu()); + analysisMenu.add(getPathAnalysisMenu()); + analysisMenu.addSeparator(); final JMenuItem convexHullMenuItem = GuiUtils.MenuItems.convexHull(); convexHullMenuItem.addActionListener(e -> { @@ -2682,36 +2684,6 @@ private JMenuBar createMenuBar() { (new CmdRunner(ConvexHullCmd.class, inputs, getState())).execute(); }); analysisMenu.add(convexHullMenuItem); - analysisMenu.addSeparator(); - - final JMenuItem pathOrderAnalysis = new JMenuItem("Path Order Analysis", - IconFactory.getMenuIcon(IconFactory.GLYPH.BRANCH_CODE)); - pathOrderAnalysis.setToolTipText("Horton-Strahler-like analysis based on paths rather than branches"); - pathOrderAnalysis.addActionListener(e -> { - if (noPathsError()) return; - final Tree tree = getPathManager().getSingleTree(); - if (tree == null) return; - final PathOrderAnalysisCmd pa = new PathOrderAnalysisCmd(tree); - pa.setContext(plugin.getContext()); - pa.setTable(new SNTTable(), "SNT: Path Order Analysis"); - pa.run(); - }); - analysisMenu.add(pathOrderAnalysis); - exportCSVMenuItem = new JMenuItem("Path Properties: Export CSV...", IconFactory.getMenuIcon(IconFactory.GLYPH.CSV)); - exportCSVMenuItem.setToolTipText("Export details (metrics, relationships, ...) of existing paths as tabular data"); - exportCSVMenuItem.addActionListener(listener); - analysisMenu.add(exportCSVMenuItem); - analysisMenu.addSeparator(); - final JMenuItem brainMenuItem = GuiUtils.MenuItems.brainAreaAnalysis(); - brainMenuItem.addActionListener(e -> { - if (noPathsError()) return; - final Tree tree = getPathManager().getSingleTree(); - if (tree == null) return; - final HashMap inputs = new HashMap<>(); - inputs.put("tree", tree); - new DynamicCmdRunner(BrainAnnotationCmd.class, inputs).run(); - }); - analysisMenu.add(brainMenuItem); final JMenuItem tmdMenuItem = GuiUtils.MenuItems.persistenceAnalysis(); tmdMenuItem.addActionListener(e -> { if (noPathsError()) return; @@ -2785,19 +2757,8 @@ private JMenuBar createMenuBar() { (new DynamicCmdRunner(GroupAnalyzerCmd.class, null)).run(); } }); - utilitiesMenu.add(plotMenuItem); + utilitiesMenu.add(getRecPlotterMenuItem()); utilitiesMenu.addSeparator(); - - final JMenuItem annotGenerator = GuiUtils.MenuItems.createAnnotionGraph(); - utilitiesMenu.add(annotGenerator); - annotGenerator.addActionListener(e -> { - if (noPathsError()) return; - final Collection trees = getPathManager().getMultipleTrees(); - if (trees == null) return; - final HashMap inputs = new HashMap<>(); - inputs.put("trees", trees); - (new DynamicCmdRunner(AnnotationGraphGeneratorCmd.class, inputs)).run(); - }); final JMenuItem graphGenerator = GuiUtils.MenuItems.createDendrogram(); utilitiesMenu.add(graphGenerator); graphGenerator.addActionListener(e -> { @@ -2820,6 +2781,7 @@ private JMenuBar createMenuBar() { utilitiesMenu.add(figureGenerator); utilitiesMenu.addSeparator(); + utilitiesMenu.add(getDriftCorrectionMenuItem()); // similar to File>Autotrace Segmented Image File... but assuming current image as source, // which does not require file validations etc. final JMenuItem autotraceJMI = new JMenuItem("Autotrace Segmented Image...", @@ -2828,7 +2790,6 @@ private JMenuBar createMenuBar() { utilitiesMenu.add(autotraceJMI); ScriptRecorder.setRecordingCall(autotraceJMI, "snt.getUI().runAutotracingWizard(false)"); autotraceJMI.addActionListener(e -> runAutotracingOnImage(false)); - // View menu final JMenuItem arrangeDialogsMenuItem = new JMenuItem("Arrange Dialogs", IconFactory.getMenuIcon(IconFactory.GLYPH.WINDOWS2)); @@ -2905,6 +2866,109 @@ private JMenuBar createMenuBar() { return menuBar; } + private JMenuItem getDriftCorrectionMenuItem() { + final JMenuItem driftJMI = new JMenuItem("Apply 3D Drift Corrections...", IconFactory.getMenuIcon(GLYPH.VIDEO)); + driftJMI.setToolTipText("Assumes loaded image is a time-lapse series. Should be run before tracing operations"); + driftJMI.addActionListener( e-> { + if (!plugin.accessToValidImageData() || plugin.getImagePlus().getNFrames() == 1) { + guiUtils.error("A timelapse is required but none seems to be loaded."); + } + else if (!ScriptInstaller.runScript("Plugins/Registration/Correct_3D_drift.py")) { + guiUtils.error("Could not find 'Correct 3D Drift'. " + + "Make sure no files are missing from your Fiji install."); + } + }); + return driftJMI; + } + + private JMenuItem getRecPlotterMenuItem() { + final JMenuItem plotMenuItem = new JMenuItem("Reconstruction Plotter...", IconFactory.getMenuIcon(IconFactory.GLYPH.DRAFT)); + plotMenuItem.setToolTipText("Renders traced paths as vector graphics (2D)"); + plotMenuItem.addActionListener( e -> { + if (noPathsError()) return; + final Tree tree = getPathManager().getSingleTree(); + if (tree == null) return; + final Map input = new HashMap<>(); + input.put("tree", tree); + final CommandService cmdService = plugin.getContext().getService(CommandService.class); + cmdService.run(PlotterCmd.class, true, input); + }); + return plotMenuItem; + } + + private JMenu getBrainAnnotationMenu() { + final JMenu menu = new JMenu("Atlas-based"); + menu.setIcon(IconFactory.getMenuIcon(GLYPH.ATLAS)); + JMenuItem mi = GuiUtils.MenuItems.createAnnotionGraph(); + mi.addActionListener(e -> { + if (noPathsError()) return; + final Collection trees = getPathManager().getMultipleTrees(); + if (trees == null) return; + final HashMap inputs = new HashMap<>(); + inputs.put("trees", trees); + (new DynamicCmdRunner(AnnotationGraphGeneratorCmd.class, inputs)).run(); + }); + menu.add(mi); + mi = GuiUtils.MenuItems.brainAreaAnalysis(); + mi.addActionListener(e -> { + if (noPathsError()) return; + final Tree tree = getPathManager().getSingleTree(); + if (tree == null) return; + final HashMap inputs = new HashMap<>(); + inputs.put("tree", tree); + new DynamicCmdRunner(BrainAnnotationCmd.class, inputs).run(); + }); + menu.add(mi); + return menu; + } + + private JMenu getPathAnalysisMenu() { + final JMenu menu = new JMenu("Path-based"); + menu.setIcon(IconFactory.getMenuIcon(GLYPH.ROUTE)); + JMenuItem mi = new JMenuItem("Path Order Analysis", IconFactory.getMenuIcon(IconFactory.GLYPH.BRANCH_CODE)); + mi.setToolTipText("Horton-Strahler-like analysis based on paths rather than branches"); + mi.addActionListener(e -> { + if (noPathsError()) return; + final Tree tree = getPathManager().getSingleTree(); + if (tree == null) return; + final PathOrderAnalysisCmd pa = new PathOrderAnalysisCmd(tree); + pa.setContext(plugin.getContext()); + pa.setTable(new SNTTable(), "SNT: Path Order Analysis"); + pa.run(); + }); + menu.add(mi); + mi = new JMenuItem("Path Properties: Export CSV...", IconFactory.getMenuIcon(IconFactory.GLYPH.CSV)); + mi.setToolTipText("Export details (metrics, relationships, ...) of existing paths as tabular data"); + mi.addActionListener(e -> { + final File saveFile = saveFile("Export All Paths as CSV...", "CSV_Properties.csv", "csv"); + if (saveFile == null) + return; // user pressed cancel + if (saveFile.exists() && !guiUtils.getConfirmation( + "The file " + saveFile.getAbsolutePath() + " already exists. " + "Do you want to replace it?", + "Override CSV file?")) { + return; + } + final String savePath = saveFile.getAbsolutePath(); + showStatus("Exporting as CSV to " + savePath, false); + final int preExportingState = currentState; + changeState(SAVING); + // Export here... + try { + pathAndFillManager.exportToCSV(saveFile); + } catch (final IOException ioe) { + showStatus("Exporting failed.", true); + guiUtils.error("Writing traces to '" + savePath + "' failed. See Console for details."); + changeState(preExportingState); + ioe.printStackTrace(); + return; + } + showStatus("Export complete.", true); + changeState(preExportingState); + }); + menu.add(mi); + return menu; + } + private JMenuItem getExportSWCMenuItem() { final JMenuItem exportAllSWCMenuItem = new JMenuItem("Export As SWC..."); exportAllSWCMenuItem.addActionListener( e -> { @@ -3037,7 +3101,7 @@ private JPanel colorOptionsPanel() { GuiUtils.addTooltip(jcheckbox, "Whether default colors above should be used even when color tags have been applied in the Path Manager.

" + "NB: This option does not affect color-coded paths, or paths with multi-color nodes"); - registerInCommandFinder(jcheckbox, "Enforce Default Colors", "Main Tab"); + registerInCommandFinder(jcheckbox, "Toggle Enforce Default Colors", "Main Tab"); jcheckbox.addActionListener(e -> { plugin.displayCustomPathColors = !jcheckbox.isSelected(); plugin.updateTracingViewers(true); @@ -4077,34 +4141,6 @@ public void actionPerformed(final ActionEvent e) { plugin.enableSecondaryLayerTracing(false); } - } else if (source == exportCSVMenuItem && !noPathsError()) { - - final File saveFile = saveFile("Export All Paths as CSV...", "CSV_Properties.csv", "csv"); - if (saveFile == null) - return; // user pressed cancel - if (saveFile.exists() && !guiUtils.getConfirmation( - "The file " + saveFile.getAbsolutePath() + " already exists. " + "Do you want to replace it?", - "Override CSV file?")) { - return; - } - final String savePath = saveFile.getAbsolutePath(); - showStatus("Exporting as CSV to " + savePath, false); - - final int preExportingState = currentState; - changeState(SAVING); - // Export here... - try { - pathAndFillManager.exportToCSV(saveFile); - } catch (final IOException ioe) { - showStatus("Exporting failed.", true); - guiUtils.error("Writing traces to '" + savePath + "' failed. See Console for details."); - changeState(preExportingState); - ioe.printStackTrace(); - return; - } - showStatus("Export complete.", true); - changeState(preExportingState); - } else if (source == keepSegment) { plugin.confirmTemporary(true); diff --git a/src/main/java/sc/fiji/snt/gui/GuiUtils.java b/src/main/java/sc/fiji/snt/gui/GuiUtils.java index 4ea139e3..0286272a 100644 --- a/src/main/java/sc/fiji/snt/gui/GuiUtils.java +++ b/src/main/java/sc/fiji/snt/gui/GuiUtils.java @@ -2628,7 +2628,7 @@ public static JMenuItem persistenceAnalysis() { } public static JMenuItem brainAreaAnalysis() { - final JMenuItem jmi = new JMenuItem("Brain Area Analysis...", IconFactory.getMenuIcon(GLYPH.BRAIN)); + final JMenuItem jmi = new JMenuItem("Brain Area Frequencies...", IconFactory.getMenuIcon(GLYPH.BRAIN)); jmi.setToolTipText("Distribution analysis of projection patterns across brain areas"); return jmi; } @@ -2665,14 +2665,14 @@ public static JMenuItem createDendrogram() { } public static JMenuItem createAnnotionGraph() { - final JMenuItem jmi = new JMenuItem("Create Annotation Graph...", IconFactory.getMenuIcon(GLYPH.BRAIN)); + final JMenuItem jmi = new JMenuItem("Annotation Graph...", IconFactory.getMenuIcon(GLYPH.BRAIN)); jmi.setToolTipText("Flow Plots and Ferris-Wheel diagrams from annotated trees"); return jmi; } public static JMenuItem measureOptions() { final JMenuItem jmi = new JMenuItem("Measure...", IconFactory.getMenuIcon(GLYPH.TABLE)); - jmi.setToolTipText("Compute detailed metrics from single cells"); + jmi.setToolTipText("Compute detailed metrics from single cells"); return jmi; } diff --git a/src/main/java/sc/fiji/snt/viewer/Viewer3D.java b/src/main/java/sc/fiji/snt/viewer/Viewer3D.java index 7ffcfeee..cf2f19f7 100644 --- a/src/main/java/sc/fiji/snt/viewer/Viewer3D.java +++ b/src/main/java/sc/fiji/snt/viewer/Viewer3D.java @@ -4033,6 +4033,10 @@ private JButton menuButton(final GLYPH glyph, final JPopupMenu menu, final Strin private JPopupMenu sceneMenu() { final JPopupMenu sceneMenu = new JPopupMenu(); + final JMenuItem dark = new JMenuItem(new Action(Action.TOGGLE_DARK_MODE, KeyEvent.VK_D, false, false)); + dark.setIcon(IconFactory.getMenuIcon(GLYPH.SUN)); + sceneMenu.add(dark); + sceneMenu.addSeparator(); final JMenuItem fit = new JMenuItem(new Action(Action.FIT, KeyEvent.VK_F, false, false)); fit.setIcon(IconFactory.getMenuIcon(GLYPH.EXPAND)); sceneMenu.add(fit); @@ -4576,7 +4580,7 @@ private JPopupMenu measureMenu() { }); }); measureMenu.add(mi); - GuiUtils.addSeparator(measureMenu, "Distribution Analysis:"); + GuiUtils.addSeparator(measureMenu, "Distribution Analyses:"); mi = new JMenuItem("Branch Properties...", IconFactory.getMenuIcon(GLYPH.CHART)); mi.setToolTipText("Computes distributions of metrics from all the branches of selected trees"); mi.addActionListener(e -> { @@ -4599,7 +4603,7 @@ private JPopupMenu measureMenu() { runCmd(DistributionCPCmd.class, inputs, CmdWorker.DO_NOTHING, false, true); }); measureMenu.add(mi); - GuiUtils.addSeparator(measureMenu, "Specialized Analysis:"); + GuiUtils.addSeparator(measureMenu, "Specialized Analyses:"); final JMenuItem convexHullMenuItem = GuiUtils.MenuItems.convexHull(); convexHullMenuItem.addActionListener(e -> { final List trees = getSelectedTrees(); @@ -4612,6 +4616,15 @@ private JPopupMenu measureMenu() { runCmd(ConvexHullCmd.class, inputs, CmdWorker.DO_NOTHING, true, true); }); measureMenu.add(convexHullMenuItem); + mi = GuiUtils.MenuItems.createDendrogram(); + mi.addActionListener(e -> { + final Tree tree = getSingleSelectionTreeWithPromptForType(); + if (tree == null) return; + final Map inputs = new HashMap<>(); + inputs.put("tree", tree); + runCmd(GraphGeneratorCmd.class, inputs, CmdWorker.DO_NOTHING, false, true); + }); + measureMenu.add(mi); mi = GuiUtils.MenuItems.persistenceAnalysis(); mi.addActionListener(e -> { final List trees = getSelectedTrees(); @@ -4645,35 +4658,26 @@ private JPopupMenu measureMenu() { runCmd(StrahlerCmd.class, inputs, CmdWorker.DO_NOTHING, false, true); }); measureMenu.add(mi); - GuiUtils.addSeparator(measureMenu, "Graph-based Analysis:"); - mi = GuiUtils.MenuItems.brainAreaAnalysis(); + GuiUtils.addSeparator(measureMenu, "Atlas-based Analyses:"); + mi = GuiUtils.MenuItems.createAnnotionGraph(); mi.addActionListener(e -> { - final Tree tree = getSingleSelectionTree(); - if (tree == null) return; + final List trees = getSelectedTrees(); + if (trees == null || trees.isEmpty()) return; final Map inputs = new HashMap<>(); - inputs.put("tree", tree); - runCmd(BrainAnnotationCmd.class, inputs, CmdWorker.DO_NOTHING, false, true); + inputs.put("trees", trees); + runCmd(AnnotationGraphGeneratorCmd.class, inputs, CmdWorker.DO_NOTHING, false, true); }); measureMenu.add(mi); - mi = GuiUtils.MenuItems.createDendrogram(); + mi = GuiUtils.MenuItems.brainAreaAnalysis(); mi.addActionListener(e -> { - final Tree tree = getSingleSelectionTreeWithPromptForType(); + final Tree tree = getSingleSelectionTree(); if (tree == null) return; final Map inputs = new HashMap<>(); inputs.put("tree", tree); - runCmd(GraphGeneratorCmd.class, inputs, CmdWorker.DO_NOTHING, false, true); - }); - measureMenu.add(mi); - mi = GuiUtils.MenuItems.createAnnotionGraph(); - mi.addActionListener(e -> { - final List trees = getSelectedTrees(); - if (trees == null || trees.isEmpty()) return; - final Map inputs = new HashMap<>(); - inputs.put("trees", trees); - runCmd(AnnotationGraphGeneratorCmd.class, inputs, CmdWorker.DO_NOTHING, false, true); + runCmd(BrainAnnotationCmd.class, inputs, CmdWorker.DO_NOTHING, false, true); }); measureMenu.add(mi); - GuiUtils.addSeparator(measureMenu, "Data Export & Utilities:"); + GuiUtils.addSeparator(measureMenu, "Data Export:"); mi = GuiUtils.MenuItems.saveTablesAndPlots(GLYPH.SAVE); mi.addActionListener(e -> { runCmd(SaveMeasurementsCmd.class, null, CmdWorker.DO_NOTHING, false, true); @@ -4949,16 +4953,6 @@ private JPopupMenu utilsMenu() { }); utilsMenu.add(mi); utilsMenu.add(legendMenu()); - final JMenuItem light = new JMenuItem("Light Controls...", IconFactory.getMenuIcon(GLYPH.BULB)); - light.addActionListener(e -> frame.displayLightController(null)); - utilsMenu.add(light); - final JMenuItem dark = new JMenuItem(new Action(Action.TOGGLE_DARK_MODE, KeyEvent.VK_D, false, false)); - dark.setIcon(IconFactory.getMenuIcon(GLYPH.SUN)); - utilsMenu.add(dark); - GuiUtils.addSeparator(utilsMenu, "Actions:"); - final JMenuItem hide = new JMenuItem(new Action(Action.TOGGLE_CONTROL_PANEL, KeyEvent.VK_C, false, true)); - hide.setIcon(IconFactory.getMenuIcon(GLYPH.EYE_SLASH)); - utilsMenu.add(hide); if (!isSNTInstance()) { final JMenuItem jmi = GuiUtils.MenuItems.renderQuick(); jmi.addActionListener(e -> { @@ -4970,6 +4964,9 @@ private JPopupMenu utilsMenu() { }); utilsMenu.add(jmi); } + final JMenuItem light = new JMenuItem("Light Controls...", IconFactory.getMenuIcon(GLYPH.BULB)); + light.addActionListener(e -> frame.displayLightController(null)); + utilsMenu.add(light); mi = new JMenuItem("Record Rotation", IconFactory.getMenuIcon(GLYPH.VIDEO)); mi.addActionListener(e -> { SwingUtilities.invokeLater(() -> { @@ -5020,6 +5017,10 @@ private JPopupMenu scriptingMenu() { private JPopupMenu prefsMenu() { final JPopupMenu prefsMenu = new JPopupMenu(); + GuiUtils.addSeparator(prefsMenu, "Layout:"); + final JMenuItem hide = new JMenuItem(new Action(Action.TOGGLE_CONTROL_PANEL, KeyEvent.VK_C, false, true)); + hide.setIcon(IconFactory.getMenuIcon(GLYPH.WINDOWS)); + prefsMenu.add(hide); GuiUtils.addSeparator(prefsMenu, "Keyboard & Mouse Sensitivity:"); prefsMenu.add(panMenu()); prefsMenu.add(zoomMenu());