@@ -5328,7 +5328,7 @@ private class NavigationToolBar extends JToolBar {
53285328 private final JComponent embeddingParent ;
53295329 private final JComboBox <String > arborChoiceCombo ;
53305330 private final JToggleButton hideOthersButton ;
5331- private final JButton showAllArborsButton ;
5331+ private final JToggleButton showAllArborsButton ;
53325332 private final JButton sortArborsButton ;
53335333 private final JButton nextArborButton ;
53345334 private String arborChoice = null ; // currently chosen tree label
@@ -5346,13 +5346,16 @@ private class NavigationToolBar extends JToolBar {
53465346
53475347 this .embeddingParent = scrollPaneOfJTree .getColumnHeader ();
53485348 arborChoiceCombo = new JComboBox <>();
5349- hideOthersButton = new JToggleButton ();
53505349 sortArborsButton = sortButton ();
53515350 nextArborButton = nextArborButton ();
5352- showAllArborsButton = showAllButton ();
5351+ showAllArborsButton = GuiUtils .Buttons .toolbarToggleButton (showAllAction (), "Show all structures" ,
5352+ IconFactory .GLYPH .EYE , IconFactory .GLYPH .EYE );
5353+ showAllArborsButton .setSelected (true );
5354+ hideOthersButton = GuiUtils .Buttons .toolbarToggleButton (hideOthersAction (), "Show only selected structure" ,
5355+ IconFactory .GLYPH .EYE_LOW_VISION , IconFactory .GLYPH .EYE_LOW_VISION );
53535356
53545357 // assemble combo box
5355- arborChoiceCombo .setToolTipText ("Jump to an arbor ( rooted structure )" );
5358+ arborChoiceCombo .setToolTipText ("Jump to a structure (arbor / rooted tree )" );
53565359 arborChoiceCombo .setPrototypeDisplayValue ("XXXXXXXXXXXXXX" ); // 14 chars - safe cross-platform!?
53575360 arborChoiceCombo .addActionListener (e -> {
53585361 if (navSyncGuard ) return ;
@@ -5364,26 +5367,22 @@ private class NavigationToolBar extends JToolBar {
53645367 expandAndRevealTree (arborChoice );
53655368 });
53665369
5367- // assemble "hide others" button
5368- IconFactory .assignIcon (hideOthersButton , IconFactory .GLYPH .ARROWS_TO_EYE , IconFactory .GLYPH .ARROWS_TO_EYE );
5369- hideOthersButton .setToolTipText ("When selected, list only paths from the chosen arbor/structure" );
5370- hideOthersButton .addActionListener (e -> {
5371- if (arborChoiceCombo .getSelectedIndex () == -1 ) {
5372- hideOthersButton .setSelected (false );
5373- guiUtils .error ("No arbor/structure chosen." );
5374- } else
5375- applyHideOthers (hideOthersButton .isSelected ());
5376- });
53775370
5378- // add components
5371+ // add sorter, choice combo, and prev/next button
53795372 add (sortArborsButton );
53805373 addSeparator ();
5381- add (showAllArborsButton );
53825374 add (arborChoiceCombo );
53835375 add (nextArborButton );
5376+
5377+ // add show all/selected as a group
53845378 add (hideOthersButton );
5379+ add (showAllArborsButton );
5380+ final ButtonGroup group = new ButtonGroup ();
5381+ group .add (showAllArborsButton );
5382+ group .add (hideOthersButton );
53855383 addSeparator ();
53865384
5385+ // zoom/go to
53875386 add (zoomToPathsButton ());
53885387 add (zoomToNodeButton ());
53895388 addSeparator ();
@@ -5396,7 +5395,7 @@ private void readArborChoice() {
53965395 final String label = (String ) arborChoiceCombo .getSelectedItem ();
53975396 arborChoice = (label == null || label .isEmpty ()) ? null : label ;
53985397 // Keep the toggle enabled if filtering is active, even if combo shows no selection
5399- hideOthersButton .setEnabled (arborChoice != null || hideOthersButton .isSelected ());
5398+ // hideOthersButton.setEnabled(arborChoice != null || hideOthersButton.isSelected());
54005399 }
54015400
54025401 private Collection <Path > getSelectedPathsUsingToolbarOptions (final boolean ifNoneSelectedGetAll ) {
@@ -5416,8 +5415,8 @@ private Collection<Path> getSelectedPathsUsingToolbarOptions(final boolean ifNon
54165415
54175416 private JButton nextArborButton () {
54185417 final JButton b = new JButton (); //
5419- IconFactory .assignIcon (b , IconFactory .GLYPH .CARET_UP_DOWN , IconFactory .GLYPH .CARET_UP_DOWN , 1f );
5420- b .setToolTipText ("Next arbor " );
5418+ IconFactory .assignIcon (b , IconFactory .GLYPH .NEXT , IconFactory .GLYPH .NEXT , 1f );
5419+ b .setToolTipText ("Next structure " );
54215420 b .addActionListener (e -> {
54225421 final int n = arborChoiceCombo .getItemCount ();
54235422 if ( n == 0 ) return ;
@@ -5434,25 +5433,36 @@ private JButton nextArborButton() {
54345433 private JButton sortButton () {
54355434 final JButton b = new JButton (); //
54365435 IconFactory .assignIcon (b , IconFactory .GLYPH .SORT , IconFactory .GLYPH .SORT , 1f );
5437- b .setToolTipText ("Sort Arbors/Root-level Paths ..." );
5438- b .setActionCommand ("Sort Arbors/Root-level Paths ..." );
5436+ b .setToolTipText ("Sort Structures ..." );
5437+ b .setActionCommand ("Sort Structures ..." );
54395438 b .addActionListener ( e -> {
54405439 sortArbors (); // full model will be restored
54415440 arborChoiceCombo .setSelectedIndex (-1 );
54425441 });
54435442 return b ;
54445443 }
54455444
5446- private JButton showAllButton () {
5447- final JButton b = new JButton (); // home
5448- IconFactory .assignIcon (b , IconFactory .GLYPH .UNDO , IconFactory .GLYPH .UNDO , .8f );
5449- b .setToolTipText ("Show all arbors" );
5450- b .setActionCommand ("Show All Arbors" );
5451- b .addActionListener (e -> {
5452- restoreFullModelState (); // Reset to full model, clear filtering, and ensure hide others is off
5453- arborChoiceCombo .setSelectedIndex (-1 );
5454- });
5455- return b ;
5445+ private Action showAllAction () {
5446+ return new AbstractAction ("Show All Structures" ) {
5447+ @ Override
5448+ public void actionPerformed (final java .awt .event .ActionEvent e ) {
5449+ restoreFullModelState (); // Reset to full model, clear filtering, and ensure hide others is off
5450+ arborChoiceCombo .setSelectedIndex (-1 );
5451+ }
5452+ };
5453+ }
5454+
5455+ private Action hideOthersAction () {
5456+ return new AbstractAction ("Show Only Selected Structure" ) {
5457+ @ Override
5458+ public void actionPerformed (final java .awt .event .ActionEvent e ) {
5459+ if (arborChoiceCombo .getSelectedIndex () == -1 ) {
5460+ showAllArborsButton .setSelected (true );
5461+ guiUtils .error ("No structure selected. Choose one from the list first." );
5462+ } else
5463+ applyHideOthers (hideOthersButton .isSelected ());
5464+ }
5465+ };
54565466 }
54575467
54585468 private JButton zoomToNodeButton () {
@@ -5480,7 +5490,10 @@ private JButton zoomToNodeButton() {
54805490 final boolean intensitySearch = "min value" .equals (filter );
54815491 final Map <Path , double []> snapshot = intensitySearch ? snapshotNodeValues (paths ) : null ;
54825492 try {
5483- if (intensitySearch ) ensureNodeValues (paths );
5493+ // Abort the whole operation if there is no image to sample intensities from:
5494+ // ensureNodeValues has already shown the error. Proceeding would search
5495+ // unpopulated values and zoom to an arbitrary node.
5496+ if (intensitySearch && !ensureNodeValues (paths )) return ;
54845497 Path .PathNode globalExtremum = null ;
54855498 for (final Path path : paths ) {
54865499 final Path .PathNode local = path .getNode (filter );
@@ -5591,11 +5604,14 @@ private boolean isBetter(final String filter, final Path.PathNode candidate, fin
55915604
55925605 /**
55935606 * Populates per-node intensity values via {@link PathProfiler} for any
5594- * path in {@code paths} that does not already carry them. No-op when
5595- * the SNT instance has no image.
5607+ * path in {@code paths} that does not already carry them.
5608+ *
5609+ * @return {@code true} if values could be assigned; {@code false} when no
5610+ * valid image is available (in which case an error has already been
5611+ * shown and the caller should abort the intensity-based operation)
55965612 */
5597- private void ensureNodeValues (final Collection <Path > paths ) {
5598- if (noValidImageDataError ()) return ;
5613+ private boolean ensureNodeValues (final Collection <Path > paths ) {
5614+ if (noValidImageDataError ()) return false ;
55995615 for (final Path p : paths ) {
56005616 // Always (re)assign with point sampling so the values array is densely populated. PathProfiler's
56015617 // default LINE shape skips the first and last node, leaving them as a literal 0.0 in the values
@@ -5608,6 +5624,7 @@ private void ensureNodeValues(final Collection<Path> paths) {
56085624 // Out of bounds, missing channel, etc.: leave path without values.
56095625 }
56105626 }
5627+ return true ;
56115628 }
56125629
56135630 /**
@@ -5794,6 +5811,10 @@ void restoreFullModelState() {
57945811 arborChoice = null ;
57955812 tree .setModel (fullTreeModel );
57965813 hideOthersButton .setSelected (false );
5814+ // Re-enable sorting now that the full (multi-arbor) model is restored:
5815+ // applyHideOthers(true) disables it while a single arbor is isolated, and
5816+ // this path (e.g. the "show all structures" button) must undo that.
5817+ sortArborsButton .setEnabled (getAllTreeLabels ().size () > 1 );
57975818 GuiUtils .JTrees .expandAllNodes (tree );
57985819 }
57995820
@@ -6026,16 +6047,16 @@ JCheckBoxMenuItem getToggleMenuItem() {
60266047
60276048 void addExtras () {
60286049 final JPopupMenu popupMenu = new JPopupMenu ();
6029- final JMenuItem customizeItem = new JMenuItem ("Change Colors..." , IconFactory .menuIcon (IconFactory .GLYPH .EYE_DROPPER ));
6050+ final JMenuItem customizeItem = new JMenuItem ("Change Tag Colors..." , IconFactory .menuIcon (IconFactory .GLYPH .EYE_DROPPER ));
60306051 customizeItem .addActionListener (e -> showColorCustomizationDialog ());
60316052 popupMenu .add (customizeItem );
6032- popupMenu .addSeparator ();
60336053 final JMenuItem hideItem = new JMenuItem ("Hide " + getName (), IconFactory .menuIcon ('\uf070' , true ));
60346054 hideItem .addActionListener (e -> setVisible (false ));
60356055 popupMenu .add (hideItem );
6036- setComponentPopupMenu (popupMenu );
6056+ popupMenu .addSeparator ();
6057+ popupMenu .add (GuiUtils .MenuItems .openHelpURL ("Help on Proofreading Tags" , "https://imagej.net/plugins/snt/manual#tag-" ));
60376058 add (Box .createHorizontalGlue ());
6038- add (GuiUtils .Buttons .help ( "https://imagej.net/plugins/snt/manual#tag-" ));
6059+ add (GuiUtils .Buttons .OptionsButton ( IconFactory . GLYPH . SLIDERS , 1f , popupMenu ));
60396060 }
60406061
60416062 private void showColorCustomizationDialog () {
0 commit comments