Skip to content

Commit 22b60ec

Browse files
committed
Fix actions in navigation toolbar and misc. improvements
1 parent 207a0f7 commit 22b60ec

2 files changed

Lines changed: 62 additions & 40 deletions

File tree

‎src/main/java/sc/fiji/snt/PathManagerUI.java‎

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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() {

‎src/main/java/sc/fiji/snt/gui/IconFactory.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public enum GLYPH {
118118
EXPORT('\uf56e', true), //
119119
EXTERNAL_LINK('\uf35d', true), //
120120
EYE('\uf06e', false), //
121+
EYE_LOW_VISION('\uf2a8', true), //
121122
EYE_SLASH('\uf070', false), //
122123
FILE('\uf15b', false), //
123124
FILE_IMAGE('\uf1c5', false), //

0 commit comments

Comments
 (0)