Search in sources :

Example 26 with Action

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;
}
Also used : Action(org.controlsfx.control.action.Action)

Example 27 with 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;
}
Also used : Action(org.controlsfx.control.action.Action)

Example 28 with 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);
}
Also used : Action(org.controlsfx.control.action.Action) Ellipse(javafx.scene.shape.Ellipse) Node(javafx.scene.Node) ArrayList(java.util.ArrayList) Rectangle(javafx.scene.shape.Rectangle) MenuItem(javafx.scene.control.MenuItem) CheckMenuItem(javafx.scene.control.CheckMenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) RadioMenuItem(javafx.scene.control.RadioMenuItem) RadioMenuItem(javafx.scene.control.RadioMenuItem) DropShadow(javafx.scene.effect.DropShadow) PathClass(qupath.lib.objects.classes.PathClass) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject) ToggleGroup(javafx.scene.control.ToggleGroup)

Example 29 with Action

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;
}
Also used : Button(javafx.scene.control.Button) Arrays(java.util.Arrays) ImageServer(qupath.lib.images.servers.ImageServer) ListCell(javafx.scene.control.ListCell) ActionUtils(org.controlsfx.control.action.ActionUtils) LoggerFactory(org.slf4j.LoggerFactory) Side(javafx.geometry.Side) ContextMenu(javafx.scene.control.ContextMenu) Map(java.util.Map) StandardPathClasses(qupath.lib.objects.classes.PathClassFactory.StandardPathClasses) QuPathGUI(qupath.lib.gui.QuPathGUI) Pane(javafx.scene.layout.Pane) TextField(javafx.scene.control.TextField) MenuItem(javafx.scene.control.MenuItem) BufferedImage(java.awt.image.BufferedImage) Predicate(java.util.function.Predicate) Set(java.util.Set) Rectangle(javafx.scene.shape.Rectangle) KeyEvent(javafx.scene.input.KeyEvent) Collectors(java.util.stream.Collectors) PathObject(qupath.lib.objects.PathObject) Platform(javafx.application.Platform) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer) Priority(javafx.scene.layout.Priority) List(java.util.List) BooleanProperty(javafx.beans.property.BooleanProperty) Project(qupath.lib.projects.Project) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) ProjectIO(qupath.lib.projects.ProjectIO) ToggleButton(javafx.scene.control.ToggleButton) Clipboard(javafx.scene.input.Clipboard) DataFormat(javafx.scene.input.DataFormat) GuiTools(qupath.lib.gui.tools.GuiTools) ColorToolsFX(qupath.lib.gui.tools.ColorToolsFX) ObservableList(javafx.collections.ObservableList) BorderPane(javafx.scene.layout.BorderPane) StringProperty(javafx.beans.property.StringProperty) ListView(javafx.scene.control.ListView) SimpleStringProperty(javafx.beans.property.SimpleStringProperty) Action(org.controlsfx.control.action.Action) PathClassFactory(qupath.lib.objects.classes.PathClassFactory) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Bindings(javafx.beans.binding.Bindings) ArrayList(java.util.ArrayList) Dialogs(qupath.lib.gui.dialogs.Dialogs) Insets(javafx.geometry.Insets) Tooltip(javafx.scene.control.Tooltip) GridPane(javafx.scene.layout.GridPane) ColorPicker(javafx.scene.control.ColorPicker) ImageData(qupath.lib.images.ImageData) KeyCode(javafx.scene.input.KeyCode) Color(javafx.scene.paint.Color) Logger(org.slf4j.Logger) Label(javafx.scene.control.Label) PathClass(qupath.lib.objects.classes.PathClass) MenuTools(qupath.lib.gui.tools.MenuTools) File(java.io.File) OverlayOptions(qupath.lib.gui.viewer.OverlayOptions) Menu(javafx.scene.control.Menu) KeyCodeCombination(javafx.scene.input.KeyCodeCombination) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) SelectionMode(javafx.scene.control.SelectionMode) QP(qupath.lib.scripting.QP) Collections(java.util.Collections) PathPrefs(qupath.lib.gui.prefs.PathPrefs) DialogButton(qupath.lib.gui.dialogs.Dialogs.DialogButton) PaneTools(qupath.lib.gui.tools.PaneTools) BorderPane(javafx.scene.layout.BorderPane) Action(org.controlsfx.control.action.Action) ToggleButton(javafx.scene.control.ToggleButton) GridPane(javafx.scene.layout.GridPane) Tooltip(javafx.scene.control.Tooltip) ArrayList(java.util.ArrayList) KeyCodeCombination(javafx.scene.input.KeyCodeCombination) ContextMenu(javafx.scene.control.ContextMenu) PathClass(qupath.lib.objects.classes.PathClass) PathObject(qupath.lib.objects.PathObject) Button(javafx.scene.control.Button) ToggleButton(javafx.scene.control.ToggleButton) DialogButton(qupath.lib.gui.dialogs.Dialogs.DialogButton) TextField(javafx.scene.control.TextField)

Example 30 with Action

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;
}
Also used : PathClass(qupath.lib.objects.classes.PathClass) Action(org.controlsfx.control.action.Action) ContextMenu(javafx.scene.control.ContextMenu) MenuItem(javafx.scene.control.MenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) ContextMenu(javafx.scene.control.ContextMenu) Menu(javafx.scene.control.Menu) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem)

Aggregations

Action (org.controlsfx.control.action.Action)31 KeyCodeCombination (javafx.scene.input.KeyCodeCombination)13 BorderPane (javafx.scene.layout.BorderPane)10 File (java.io.File)7 MenuItem (javafx.scene.control.MenuItem)7 SeparatorMenuItem (javafx.scene.control.SeparatorMenuItem)7 IOException (java.io.IOException)6 ArrayList (java.util.ArrayList)6 Button (javafx.scene.control.Button)6 KeyCode (javafx.scene.input.KeyCode)6 Stage (javafx.stage.Stage)6 ActionUtils (org.controlsfx.control.action.ActionUtils)6 List (java.util.List)5 Node (javafx.scene.Node)5 ButtonType (javafx.scene.control.ButtonType)5 ContextMenu (javafx.scene.control.ContextMenu)5 Label (javafx.scene.control.Label)5 Menu (javafx.scene.control.Menu)5 Tooltip (javafx.scene.control.Tooltip)5 KeyCombination (javafx.scene.input.KeyCombination)5