Skip to content

Commit 12f00f7

Browse files
committed
Multiple fixes/improvements to UI components
- Streamline Fill Manager's operations: - Loading fills before export is no longer needed - Improve fill list with contextual menu Misc Fixes: - Deletion of bookmarks unaware of sorting orders - Exceptions in certain operations in Delineations Manager - Erratic Console toggling - Modernize Editor themes
1 parent b14cd24 commit 12f00f7

7 files changed

Lines changed: 1027 additions & 921 deletions

File tree

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

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
* it under the terms of the GNU General Public License as
99
* published by the Free Software Foundation, either version 3 of the
1010
* License, or (at your option) any later version.
11-
*
11+
*
1212
* This program is distributed in the hope that it will be useful,
1313
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1414
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1515
* GNU General Public License for more details.
16-
*
16+
*
1717
* You should have received a copy of the GNU General Public
1818
* License along with this program. If not, see
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
@@ -111,15 +111,15 @@ private BookmarkTable assembleTable(final BookmarkModel model) {
111111
table.addMouseListener(new MouseAdapter() {
112112
@Override
113113
public void mousePressed(final MouseEvent me) {
114-
if (noBookmarksError()) return;
115-
final int row = table.getSelectedRow();
116-
if (row == -1) {
117-
sntui.guiUtils.error("No bookmark selected.");
118-
return;
119-
}
120114
if (me.getClickCount() == 2) {
115+
if (noBookmarksError()) return;
116+
final int row = table.getSelectedRow();
117+
if (row == -1) {
118+
sntui.guiUtils.error("No bookmark selected.");
119+
return;
120+
}
121121
final ImagePlus imp = sntui.plugin.getImagePlus();
122-
if (imp == null) sntui.guiUtils.error("No bookmark selected or no image is currently open.");
122+
if (imp == null) sntui.guiUtils.error("No image is currently open.");
123123
else goTo(row, imp);
124124
}
125125
}
@@ -128,8 +128,8 @@ public void mousePressed(final MouseEvent me) {
128128
}
129129

130130
private void resetOrResizeColumns(final boolean reset, final boolean resize) {
131-
assert table != null;
132-
assert model != null;
131+
assert table != null;
132+
assert model != null;
133133
if (reset) { // https://stackoverflow.com/q/63420045
134134
final TableColumnModel tcm = table.getColumnModel();
135135
for (int i = 0; i < model.getColumnCount() - 1; i++) {
@@ -153,31 +153,46 @@ private void resetOrResizeColumns(final boolean reset, final boolean resize) {
153153

154154
private JPopupMenu assembleTablePopupMenu() {
155155
final JPopupMenu pMenu = new JPopupMenu();
156-
JMenuItem mi = new JMenuItem("Deselect / Select All");
156+
JMenuItem mi = new JMenuItem("Deselect / Select All", IconFactory.menuIcon(IconFactory.GLYPH.CHECK_DOUBLE));
157157
mi.addActionListener(e -> {
158-
clearSelection();
159-
recordCmd("clearSelection()");
158+
if (table.getSelectedRows().length > 0) {
159+
table.clearSelection();
160+
} else if (model.getRowCount() > 0) {
161+
table.setRowSelectionInterval(0, model.getRowCount() - 1);
162+
}
163+
recordCmd("clearSelection()"); // Note: only records clear, not select all
160164
});
161165
pMenu.add(mi);
162166
pMenu.addSeparator();
163-
mi = new JMenuItem("Remove All...");
167+
mi = new JMenuItem("Remove All...", IconFactory.menuIcon(IconFactory.GLYPH.TRASH));
164168
mi.addActionListener(e -> {
165169
if (!noBookmarksError() && sntui.guiUtils.getConfirmation("Delete all bookmarks?", "Delete All?")) {
166170
reset();
167171
recordCmd("reset()");
168172
}
169173
});
170174
pMenu.add(mi);
171-
mi = new JMenuItem("Remove Selected Row(s)");
172-
mi.addActionListener( e -> {
175+
mi = new JMenuItem("Remove Selected Row(s)", IconFactory.menuIcon(IconFactory.GLYPH.TRASH));
176+
mi.addActionListener(e -> {
173177
if (noBookmarksError()) return;
174-
final int[] rows = table.getSelectedRows();
175-
for (int i = 0; i < rows.length; i++)
176-
model.removeRow(rows[i] - i);
178+
final int[] viewRows = table.getSelectedRows();
179+
if (viewRows.length == 0) {
180+
sntui.guiUtils.error("No bookmark selected.");
181+
return;
182+
}
183+
// Convert view indices to model indices (handles sorted table)
184+
final int[] modelRows = Arrays.stream(viewRows)
185+
.map(table::convertRowIndexToModel)
186+
.boxed()
187+
.sorted(Comparator.reverseOrder()) // Delete from end to preserve indices
188+
.mapToInt(Integer::intValue)
189+
.toArray();
190+
for (final int modelRow : modelRows)
191+
model.removeRow(modelRow);
177192
});
178193
pMenu.add(mi);
179194
pMenu.addSeparator();
180-
mi = new JMenuItem("Rename Selected Bookmark...");
195+
mi = new JMenuItem("Rename Selected Bookmark...", IconFactory.menuIcon(IconFactory.GLYPH.PEN));
181196
mi.addActionListener(e -> {
182197
if (noBookmarksError()) return;
183198
final int row = table.getSelectedRow();
@@ -191,7 +206,7 @@ private JPopupMenu assembleTablePopupMenu() {
191206
});
192207
pMenu.add(mi);
193208
pMenu.addSeparator();
194-
mi = new JMenuItem("Reset Columns");
209+
mi = new JMenuItem("Reset Columns", IconFactory.menuIcon(IconFactory.GLYPH.UNDO));
195210
mi.addActionListener(e -> {
196211
resetOrResizeColumns(true, true);
197212
recordComment("Bookmark Manager: resizeColumns()");
@@ -303,7 +318,13 @@ private JPopupMenu exportMenu() {
303318

304319
void resetVisitingZoom() {
305320
try {
306-
final double currentMag = sntui.plugin.getImagePlus().getCanvas().getMagnification();
321+
final ImagePlus imp = sntui.plugin.getImagePlus();
322+
final ImageCanvas canvas = (imp == null) ? null : imp.getCanvas();
323+
if (canvas == null) {
324+
visitingZoomPercentage = 600;
325+
return;
326+
}
327+
final double currentMag = canvas.getMagnification();
307328
final double nextUp1x = ImageCanvas.getHigherZoomLevel(currentMag);
308329
final double nextUp2x = ImageCanvas.getHigherZoomLevel(nextUp1x);
309330
visitingZoomPercentage = (int) Math.round(nextUp2x * 100);
@@ -379,7 +400,7 @@ private boolean saveBookMarksToFile(final File file) {
379400
exportTable.save(file);
380401
return true;
381402
} catch (final IOException ioe) {
382-
ioe.printStackTrace();
403+
SNTUtils.error("saveBookMarksToFile() failure", ioe);
383404
}
384405
return false;
385406
}
@@ -438,7 +459,7 @@ public void add(final String label, final List<double[]> xyzctLocations) {
438459
AtomicInteger ai = new AtomicInteger(1);
439460
xyzctLocations.forEach(loc -> model.getDataList().add( //
440461
new Bookmark(model.getUniqueLabel(label + ai.getAndIncrement()), //
441-
(int) loc[0], (int) loc[1], (int) loc[2], (int) loc[3], (int) loc[4])));
462+
(int) loc[0], (int) loc[1], (int) loc[2], (int) loc[3], (int) loc[4])));
442463
resetOrResizeColumns(false, true);
443464
model.fireTableDataChanged();
444465
}
@@ -560,7 +581,7 @@ public boolean save(final String filePath) {
560581
* @return the number of bookmarks currently stored in the manager.
561582
*/
562583
public int getCount() {
563-
return model.getRowCount();
584+
return model.getRowCount();
564585
}
565586

566587
/**
@@ -575,7 +596,10 @@ public List<Roi> getROIs(final boolean onlySelectedRows) {
575596
if (onlySelectedRows && rows.length == 0) // no selection exists: assume all rows
576597
rows = IntStream.range(0, model.getRowCount()).toArray();
577598
for (final int row : rows) {
578-
final Bookmark b = model.getDataList().get(row);
599+
// Convert view index to model index (handles sorted table)
600+
final int modelRow = (onlySelectedRows && table.getRowSorter() != null)
601+
? table.convertRowIndexToModel(row) : row;
602+
final Bookmark b = model.getDataList().get(modelRow);
579603
final PointRoi roi = new PointRoi(b.x, b.y);
580604
roi.setPosition(b.c, (int) b.z, b.t);
581605
roi.setName(b.label);
@@ -596,7 +620,10 @@ public List<SNTPoint> getPixelPositions(final boolean onlySelectedRows) {
596620
if (onlySelectedRows && rows.length == 0) // no selection exists: assume all rows
597621
rows = IntStream.range(0, model.getRowCount()).toArray();
598622
for (final int row : rows) {
599-
final Bookmark b = model.getDataList().get(row);
623+
// Convert view index to model index (handles sorted table)
624+
final int modelRow = (onlySelectedRows && table.getRowSorter() != null)
625+
? table.convertRowIndexToModel(row) : row;
626+
final Bookmark b = model.getDataList().get(modelRow);
600627
points.add(SNTPoint.of(b.x, b.y, b.z));
601628
}
602629
return points;
@@ -807,4 +834,3 @@ public Class<?> getColumnClass(int column) {
807834
}
808835

809836
}
810-

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

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
* it under the terms of the GNU General Public License as
99
* published by the Free Software Foundation, either version 3 of the
1010
* License, or (at your option) any later version.
11-
*
11+
*
1212
* This program is distributed in the hope that it will be useful,
1313
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1414
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1515
* GNU General Public License for more details.
16-
*
16+
*
1717
* You should have received a copy of the GNU General Public
1818
* License along with this program. If not, see
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
@@ -130,7 +130,7 @@ private JToolBar outsideColorAndAddMoreEntriesWidget() {
130130
addToCapacity(n.intValue());
131131
});
132132
final JButton sortButton = new JButton(IconFactory.buttonIcon(IconFactory.GLYPH.SORT, 1.1f));
133-
sortButton.setToolTipText("Sort entries");
133+
sortButton.setToolTipText("Sort entries alphabetically");
134134
toolbar.add(sortButton);
135135
toolbar.add(Box.createHorizontalStrut(5));
136136

@@ -140,8 +140,16 @@ private JToolBar outsideColorAndAddMoreEntriesWidget() {
140140
mergeButton.addActionListener(e -> {
141141
if (noAssignmentsExistError()) return;
142142
final String[] choices = delineations.stream().filter(d -> d.roi != null).map(d -> d.name).toArray(String[]::new);
143+
if (choices.length < 2) {
144+
sntui.guiUtils.error("At least two delineations with assignments are required for merging.");
145+
return;
146+
}
143147
final List<String> chosenChoices = sntui.guiUtils.getMultipleChoices("Select categories to merge", choices, null);
144-
if (chosenChoices == null || chosenChoices.isEmpty()) return;
148+
if (chosenChoices == null || chosenChoices.size() < 2) {
149+
if (chosenChoices != null && chosenChoices.size() == 1)
150+
sntui.guiUtils.error("At least two delineations must be selected for merging.");
151+
return;
152+
}
145153
final Delineation template = getDelineation(chosenChoices.getFirst());
146154
final List<Delineation> toDelete = chosenChoices.stream().skip(1).map(this::getDelineation).toList();
147155
template.rename(chosenChoices.toString());
@@ -162,7 +170,7 @@ private JToolBar outsideColorAndAddMoreEntriesWidget() {
162170
final Color[] colors = (choices[0].equals(choice))
163171
? defaultDelineationColors(Math.min(256, delineations.size()))
164172
: ColorMaps.discreteColorsAWT(ColorMaps.get(choice), Math.min(256, delineations.size()));
165-
applyColorScheme(colors);
173+
applyColorScheme(colors);
166174
});
167175
final JButton colorSchemeUndoButton = GuiUtils.Buttons.undo();
168176
colorSchemeUndoButton.setToolTipText("Reset color scheme");
@@ -190,10 +198,12 @@ private JToolBar outsideColorAndAddMoreEntriesWidget() {
190198

191199
sortButton.addActionListener(e -> {
192200
delineations.sort((d1, d2) -> {
193-
final boolean def1 = d1.name.toLowerCase().startsWith("delineation");
194-
final boolean def2 = d2.name.toLowerCase().startsWith("delineation");
201+
final String name1 = (d1.name == null) ? "" : d1.name;
202+
final String name2 = (d2.name == null) ? "" : d2.name;
203+
final boolean def1 = name1.toLowerCase().startsWith("delineation");
204+
final boolean def2 = name2.toLowerCase().startsWith("delineation");
195205
if (def1 && def2) return Long.compare(d1.label, d2.label);
196-
return d1.name.compareToIgnoreCase(d2.name);
206+
return name1.compareToIgnoreCase(name2);
197207
});
198208
directEditingButton.setSelected(false);
199209
delineationsPanel.removeAll();
@@ -247,7 +257,7 @@ private void expandCapacityTo(final int n) {
247257
private void addToCapacity(final int n) {
248258
final int currentN = delineations.size();
249259
final Color[] colors = defaultDelineationColors(Math.min(256, currentN + n));
250-
final long lastLabel = delineations.getLast().label;
260+
final long lastLabel = delineations.isEmpty() ? 0 : delineations.getLast().label;
251261
int colorIdx = 0;
252262
for (int i = 0; i < n; i++) {
253263
final Delineation del = new Delineation(lastLabel + i + 1, colors[colorIdx++]);
@@ -628,16 +638,16 @@ private void mergeDelineations(final Delineation receiver, final List<Delineatio
628638

629639
private List<Path> getFallbackColorPaths() {
630640
return pafm.getPaths().stream().filter(p -> {
631-
for (int i = 0; i < p.size(); i++) if (fallbackColor.equals(p.getNodeColor(i))) return true;
632-
return false;
633-
}).toList();
641+
for (int i = 0; i < p.size(); i++) if (fallbackColor.equals(p.getNodeColor(i))) return true;
642+
return false;
643+
}).toList();
634644
}
635645

636646
private boolean resetAuthorizedByUser() {
637647
final boolean needed = delineations.stream().anyMatch(d -> d.roi != null);
638648
if (!needed) return true;
639649
if (sntui.guiUtils.getConfirmation("Existing assignments will be cleared. Proceed?",
640-
"Remove All Assignments?")) {
650+
"Remove All Assignments?")) {
641651
reset();
642652
return true;
643653
}

0 commit comments

Comments
 (0)