use of org.controlsfx.control.action.Action in project qupath by qupath.
the class DefaultScriptEditor method createRevertAction.
Action createRevertAction(final String name) {
Action action = new Action(name, e -> {
ScriptTab tab = getCurrentScriptObject();
if (tab != null) {
tab.refreshFileContents();
setToggle(tab.getLanguage());
}
});
return action;
}
use of org.controlsfx.control.action.Action in project qupath by qupath.
the class DefaultScriptEditor method createRunProjectScriptAction.
Action createRunProjectScriptAction(final String name, final boolean doSave) {
Action action = new Action(name, e -> handleRunProject(doSave));
action.disabledProperty().bind(disableRun.or(qupath.projectProperty().isNull()));
return action;
}
use of org.controlsfx.control.action.Action in project qupath by qupath.
the class QuPathGUI method updateSetAnnotationPathClassMenu.
void updateSetAnnotationPathClassMenu(final ObservableList<MenuItem> menuSetClassItems, final QuPathViewer viewer, final boolean useFancyIcons) {
// We need a viewer and an annotation, as well as some PathClasses, otherwise we just need to ensure the menu isn't visible
if (viewer == null || !(viewer.getSelectedObject() instanceof PathAnnotationObject) || availablePathClasses.isEmpty()) {
menuSetClassItems.clear();
return;
}
PathObject mainPathObject = viewer.getSelectedObject();
PathClass currentClass = mainPathObject.getPathClass();
ToggleGroup group = new ToggleGroup();
List<MenuItem> itemList = new ArrayList<>();
RadioMenuItem selected = null;
for (PathClass pathClass : availablePathClasses) {
PathClass pathClassToSet = pathClass.getName() == null ? null : pathClass;
String name = pathClass.getName() == null ? "None" : pathClass.toString();
Action actionSetClass = new Action(name, e -> {
List<PathObject> changed = new ArrayList<>();
for (PathObject pathObject : viewer.getAllSelectedObjects()) {
if (!pathObject.isAnnotation() || pathObject.getPathClass() == pathClassToSet)
continue;
pathObject.setPathClass(pathClassToSet);
changed.add(pathObject);
}
if (!changed.isEmpty())
viewer.getHierarchy().fireObjectClassificationsChangedEvent(this, changed);
});
Node shape;
if (useFancyIcons) {
Ellipse r = new Ellipse(TOOLBAR_ICON_SIZE / 2.0, TOOLBAR_ICON_SIZE / 2.0, TOOLBAR_ICON_SIZE, TOOLBAR_ICON_SIZE);
if ("None".equals(name)) {
r.setFill(Color.rgb(255, 255, 255, 0.75));
} else
r.setFill(ColorToolsFX.getCachedColor(pathClass.getColor()));
r.setOpacity(0.8);
DropShadow effect = new DropShadow(6, -3, 3, Color.GRAY);
r.setEffect(effect);
shape = r;
} else {
Rectangle r = new Rectangle(0, 0, 8, 8);
r.setFill("None".equals(name) ? Color.TRANSPARENT : ColorToolsFX.getCachedColor(pathClass.getColor()));
shape = r;
}
// actionSetClass.setGraphic(r);
RadioMenuItem item = ActionUtils.createRadioMenuItem(actionSetClass);
item.graphicProperty().unbind();
item.setGraphic(shape);
item.setToggleGroup(group);
itemList.add(item);
if (pathClassToSet == currentClass)
selected = item;
}
group.selectToggle(selected);
menuSetClassItems.setAll(itemList);
}
use of org.controlsfx.control.action.Action in project qupath by qupath.
the class PathClassPane method createClassPane.
private Pane createClassPane() {
listClasses = new ListView<>();
var filteredList = qupath.getAvailablePathClasses().filtered(createPredicate(null));
listClasses.setItems(filteredList);
listClasses.setTooltip(new Tooltip("Annotation classes available (right-click to add or remove)"));
listClasses.getSelectionModel().selectedItemProperty().addListener((v, o, n) -> updateAutoSetPathClassProperty());
listClasses.setCellFactory(v -> new PathClassListCell(qupath));
listClasses.getSelectionModel().select(0);
listClasses.setPrefSize(100, 200);
listClasses.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
var copyCombo = new KeyCodeCombination(KeyCode.C, KeyCodeCombination.SHORTCUT_DOWN);
var pasteCombo = new KeyCodeCombination(KeyCode.V, KeyCodeCombination.SHORTCUT_DOWN);
// Intercept space presses because we handle them elsewhere
listClasses.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
if (e.getCode() == KeyCode.SPACE || e.getCode() == KeyCode.T) {
toggleSelectedClassesVisibility();
e.consume();
return;
} else if (e.getCode() == KeyCode.S) {
setSelectedClassesVisibility(true);
e.consume();
return;
} else if (e.getCode() == KeyCode.H) {
setSelectedClassesVisibility(false);
e.consume();
return;
}
});
listClasses.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
if (e.isConsumed())
return;
if (e.getCode() == KeyCode.BACK_SPACE) {
promptToRemoveSelectedClasses();
e.consume();
return;
} else if (e.getCode() == KeyCode.ENTER) {
promptToEditSelectedClass();
e.consume();
return;
} else if (copyCombo.match(e)) {
// Copy the list if needed
String s = listClasses.getSelectionModel().getSelectedItems().stream().map(p -> p.toString()).collect(Collectors.joining(System.lineSeparator()));
if (!s.isBlank()) {
Clipboard.getSystemClipboard().setContent(Map.of(DataFormat.PLAIN_TEXT, s));
}
e.consume();
return;
} else if (pasteCombo.match(e)) {
logger.debug("Paste not implemented for classification list!");
e.consume();
return;
}
});
listClasses.setOnMouseClicked(e -> {
if (!e.isPopupTrigger() && e.getClickCount() == 2)
promptToEditSelectedClass();
});
ContextMenu menuClasses = createClassesMenu();
listClasses.setContextMenu(menuClasses);
// Add the class list
BorderPane paneClasses = new BorderPane();
paneClasses.setCenter(listClasses);
Action setSelectedObjectClassAction = new Action("Set class", e -> {
var hierarchy = getHierarchy();
if (hierarchy == null)
return;
PathClass pathClass = getSelectedPathClass();
if (pathClass == PathClassFactory.getPathClassUnclassified())
pathClass = null;
var pathObjects = new ArrayList<>(hierarchy.getSelectionModel().getSelectedObjects());
List<PathObject> changed = new ArrayList<>();
for (PathObject pathObject : pathObjects) {
if (pathObject.isTMACore())
continue;
if (pathObject.getPathClass() == pathClass)
continue;
pathObject.setPathClass(pathClass);
changed.add(pathObject);
}
if (!changed.isEmpty()) {
hierarchy.fireObjectClassificationsChangedEvent(this, changed);
GuiTools.refreshList(listClasses);
}
});
setSelectedObjectClassAction.setLongText("Set the class of the currently-selected annotation(s)");
Action autoClassifyAnnotationsAction = new Action("Auto set");
autoClassifyAnnotationsAction.setLongText("Automatically set all new annotations to the selected class");
autoClassifyAnnotationsAction.selectedProperty().bindBidirectional(doAutoSetPathClass);
doAutoSetPathClass.addListener((e, f, g) -> updateAutoSetPathClassProperty());
Button btnSetClass = ActionUtils.createButton(setSelectedObjectClassAction);
ToggleButton btnAutoClass = ActionUtils.createToggleButton(autoClassifyAnnotationsAction);
// Create a button to show context menu (makes it more obvious to the user that it exists)
Button btnMore = GuiTools.createMoreButton(menuClasses, Side.RIGHT);
GridPane paneClassButtons = new GridPane();
paneClassButtons.add(btnSetClass, 0, 0);
paneClassButtons.add(btnAutoClass, 1, 0);
paneClassButtons.add(btnMore, 2, 0);
GridPane.setHgrow(btnSetClass, Priority.ALWAYS);
GridPane.setHgrow(btnAutoClass, Priority.ALWAYS);
var tfFilter = new TextField();
tfFilter.setTooltip(new Tooltip("Type to filter classifications in list"));
tfFilter.setPromptText("Filter classifications in list");
filterText.bind(tfFilter.textProperty());
filterText.addListener((v, o, n) -> filteredList.setPredicate(createPredicate(n)));
var paneBottom = PaneTools.createRowGrid(tfFilter, paneClassButtons);
PaneTools.setMaxWidth(Double.MAX_VALUE, btnSetClass, btnAutoClass, tfFilter);
paneClasses.setBottom(paneBottom);
return paneClasses;
}
use of org.controlsfx.control.action.Action in project qupath by qupath.
the class PathClassPane method createClassesMenu.
ContextMenu createClassesMenu() {
ContextMenu menu = new ContextMenu();
Action actionAddClass = new Action("Add class", e -> promptToAddClass());
Action actionRemoveClass = new Action("Remove class", e -> promptToRemoveSelectedClasses());
Action actionResetClasses = new Action("Reset to default classes", e -> promptToResetClasses());
Action actionImportClasses = new Action("Import classes from project", e -> promptToImportClasses());
actionRemoveClass.disabledProperty().bind(Bindings.createBooleanBinding(() -> {
PathClass item = listClasses.getSelectionModel().getSelectedItem();
return item == null || PathClassFactory.getPathClassUnclassified() == item;
}, listClasses.getSelectionModel().selectedItemProperty()));
MenuItem miRemoveClass = ActionUtils.createMenuItem(actionRemoveClass);
MenuItem miAddClass = ActionUtils.createMenuItem(actionAddClass);
MenuItem miResetAllClasses = ActionUtils.createMenuItem(actionResetClasses);
// MenuItem miPopulateFromImage = ActionUtils.createMenuItem(actionPopulateFromImage);
// MenuItem miPopulateFromImageBase = ActionUtils.createMenuItem(actionPopulateFromImageBase);
// MenuItem miClearAllClasses = new MenuItem("Clear all classes");
// miClearAllClasses.setOnAction(e -> promptToClearClasses());
MenuItem miPopulateFromImage = new MenuItem("All classes (including sub-classes)");
miPopulateFromImage.setOnAction(e -> promptToPopulateFromImage(false));
MenuItem miPopulateFromImageBase = new MenuItem("Base classes only");
miPopulateFromImageBase.setOnAction(e -> promptToPopulateFromImage(true));
MenuItem miPopulateFromChannels = new MenuItem("Populate from image channels");
miPopulateFromChannels.setOnAction(e -> promptToPopulateFromChannels());
Menu menuPopulate = new Menu("Populate from existing objects");
menuPopulate.getItems().addAll(miPopulateFromImage, miPopulateFromImageBase);
MenuItem miSelectObjects = new MenuItem("Select objects by classification");
miSelectObjects.disableProperty().bind(Bindings.createBooleanBinding(() -> {
var item = listClasses.getSelectionModel().getSelectedItem();
return item == null;
}, listClasses.getSelectionModel().selectedItemProperty()));
miSelectObjects.setOnAction(e -> {
var imageData = qupath.getImageData();
if (imageData == null)
return;
selectObjectsByClassification(imageData, getSelectedPathClasses().toArray(PathClass[]::new));
});
MenuItem miSetHidden = new MenuItem("Hide classes in viewer");
miSetHidden.setOnAction(e -> setSelectedClassesVisibility(false));
MenuItem miSetVisible = new MenuItem("Show classes in viewer");
miSetVisible.setOnAction(e -> setSelectedClassesVisibility(true));
// MenuItem miToggleClassVisible = new MenuItem("Toggle display class");
// miToggleClassVisible.setOnAction(e -> {
// OverlayOptions overlayOptions = qupath.getViewer().getOverlayOptions();
// for (var pathClass : getSelectedPathClasses()) {
// if (pathClass == null || pathClass == PathClassFactory.getPathClassUnclassified())
// continue;
// overlayOptions.setPathClassHidden(pathClass, !overlayOptions.isPathClassHidden(pathClass));
// }
// listClasses.refresh();
// });
menu.setOnShowing(e -> {
var hierarchy = getHierarchy();
menuPopulate.setDisable(hierarchy == null);
miPopulateFromImage.setDisable(hierarchy == null);
miPopulateFromImageBase.setDisable(hierarchy == null);
miPopulateFromChannels.setDisable(qupath.getImageData() == null);
var selected = getSelectedPathClasses();
boolean hasClasses = !selected.isEmpty();
// boolean hasClasses = selected.size() > 1 ||
// (selected.size() == 1 && selected.get(0) != null && selected.get(0) != PathClassFactory.getPathClassUnclassified());
miSetVisible.setDisable(!hasClasses);
miSetHidden.setDisable(!hasClasses);
// miRemoveClass.setDisable(!hasClasses);
});
MenuItem miImportFromProject = ActionUtils.createMenuItem(actionImportClasses);
menu.getItems().addAll(MenuTools.createMenu("Add/Remove...", miAddClass, miRemoveClass), menuPopulate, miPopulateFromChannels, miResetAllClasses, miImportFromProject, new SeparatorMenuItem(), MenuTools.createMenu("Show/Hide...", miSetVisible, miSetHidden), // new SeparatorMenuItem(),
miSelectObjects);
return menu;
}
Aggregations