Search in sources :

Example 1 with QuPathViewerPlus

use of qupath.lib.gui.viewer.QuPathViewerPlus in project qupath by qupath.

the class QuPathGUI method setViewerPopupMenu.

private void setViewerPopupMenu(final QuPathViewerPlus viewer) {
    final ContextMenu popup = new ContextMenu();
    MenuItem miAddRow = new MenuItem("Add row");
    miAddRow.setOnAction(e -> viewerManager.addRow(viewer));
    MenuItem miAddColumn = new MenuItem("Add column");
    miAddColumn.setOnAction(e -> viewerManager.addColumn(viewer));
    MenuItem miRemoveRow = new MenuItem("Remove row");
    miRemoveRow.setOnAction(e -> viewerManager.removeViewerRow(viewer));
    MenuItem miRemoveColumn = new MenuItem("Remove column");
    miRemoveColumn.setOnAction(e -> viewerManager.removeViewerColumn(viewer));
    MenuItem miCloseViewer = new MenuItem("Close viewer");
    miCloseViewer.setOnAction(e -> {
        viewerManager.closeViewer(viewer);
    // viewerManager.removeViewer(viewer);
    });
    MenuItem miResizeGrid = new MenuItem("Reset grid size");
    miResizeGrid.setOnAction(e -> {
        viewerManager.resetGridSize();
    });
    MenuItem miToggleSync = ActionTools.createCheckMenuItem(defaultActions.TOGGLE_SYNCHRONIZE_VIEWERS, null);
    MenuItem miMatchResolutions = ActionTools.createMenuItem(defaultActions.MATCH_VIEWER_RESOLUTIONS);
    Menu menuMultiview = MenuTools.createMenu("Multi-view", miToggleSync, miMatchResolutions, miCloseViewer, null, miResizeGrid, null, // null,
    miAddRow, miAddColumn, null, miRemoveRow, miRemoveColumn);
    Menu menuView = MenuTools.createMenu("Display", ActionTools.createCheckMenuItem(defaultActions.SHOW_ANALYSIS_PANE, null), defaultActions.BRIGHTNESS_CONTRAST, null, ActionTools.createAction(() -> Commands.setViewerDownsample(viewer, 0.25), "400%"), ActionTools.createAction(() -> Commands.setViewerDownsample(viewer, 1), "100%"), ActionTools.createAction(() -> Commands.setViewerDownsample(viewer, 2), "50%"), ActionTools.createAction(() -> Commands.setViewerDownsample(viewer, 10), "10%"), ActionTools.createAction(() -> Commands.setViewerDownsample(viewer, 100), "1%"));
    ToggleGroup groupTools = new ToggleGroup();
    Menu menuTools = MenuTools.createMenu("Set tool", ActionTools.createCheckMenuItem(defaultActions.MOVE_TOOL, groupTools), ActionTools.createCheckMenuItem(defaultActions.RECTANGLE_TOOL, groupTools), ActionTools.createCheckMenuItem(defaultActions.ELLIPSE_TOOL, groupTools), ActionTools.createCheckMenuItem(defaultActions.LINE_TOOL, groupTools), ActionTools.createCheckMenuItem(defaultActions.POLYGON_TOOL, groupTools), ActionTools.createCheckMenuItem(defaultActions.POLYLINE_TOOL, groupTools), ActionTools.createCheckMenuItem(defaultActions.BRUSH_TOOL, groupTools), ActionTools.createCheckMenuItem(defaultActions.POINTS_TOOL, groupTools), null, ActionTools.createCheckMenuItem(defaultActions.SELECTION_MODE));
    // Handle awkward 'TMA core missing' option
    CheckMenuItem miTMAValid = new CheckMenuItem("Set core valid");
    miTMAValid.setOnAction(e -> setTMACoreMissing(viewer.getHierarchy(), false));
    CheckMenuItem miTMAMissing = new CheckMenuItem("Set core missing");
    miTMAMissing.setOnAction(e -> setTMACoreMissing(viewer.getHierarchy(), true));
    Menu menuTMA = new Menu("TMA");
    MenuTools.addMenuItems(menuTMA, miTMAValid, miTMAMissing, null, defaultActions.TMA_ADD_NOTE, null, MenuTools.createMenu("Add", createImageDataAction(imageData -> TMACommands.promptToAddRowBeforeSelected(imageData), "Add TMA row before"), createImageDataAction(imageData -> TMACommands.promptToAddRowAfterSelected(imageData), "Add TMA row after"), createImageDataAction(imageData -> TMACommands.promptToAddColumnBeforeSelected(imageData), "Add TMA column before"), createImageDataAction(imageData -> TMACommands.promptToAddColumnAfterSelected(imageData), "Add TMA column after")), MenuTools.createMenu("Remove", createImageDataAction(imageData -> TMACommands.promptToDeleteTMAGridRow(imageData), "Remove TMA row"), createImageDataAction(imageData -> TMACommands.promptToDeleteTMAGridColumn(imageData), "column")));
    // Create an empty placeholder menu
    Menu menuSetClass = MenuTools.createMenu("Set class");
    // CheckMenuItem miTMAValid = new CheckMenuItem("Set core valid");
    // miTMAValid.setOnAction(e -> setTMACoreMissing(viewer.getHierarchy(), false));
    // CheckMenuItem miTMAMissing = new CheckMenuItem("Set core missing");
    // miTMAMissing.setOnAction(e -> setTMACoreMissing(viewer.getHierarchy(), true));
    Menu menuCells = MenuTools.createMenu("Cells", ActionTools.createCheckMenuItem(defaultActions.SHOW_CELL_BOUNDARIES_AND_NUCLEI, null), ActionTools.createCheckMenuItem(defaultActions.SHOW_CELL_NUCLEI, null), ActionTools.createCheckMenuItem(defaultActions.SHOW_CELL_BOUNDARIES, null), ActionTools.createCheckMenuItem(defaultActions.SHOW_CELL_CENTROIDS, null));
    MenuItem miClearSelectedObjects = new MenuItem("Delete object");
    miClearSelectedObjects.setOnAction(e -> {
        PathObjectHierarchy hierarchy = viewer.getHierarchy();
        if (hierarchy == null)
            return;
        if (hierarchy.getSelectionModel().singleSelection()) {
            GuiTools.promptToRemoveSelectedObject(hierarchy.getSelectionModel().getSelectedObject(), hierarchy);
        } else {
            GuiTools.promptToClearAllSelectedObjects(viewer.getImageData());
        }
    });
    // Create a standard annotations menu
    Menu menuAnnotations = GuiTools.populateAnnotationsMenu(this, new Menu("Annotations"));
    SeparatorMenuItem topSeparator = new SeparatorMenuItem();
    popup.setOnShowing(e -> {
        // Check if we have any cells
        ImageData<?> imageData = viewer.getImageData();
        if (imageData == null)
            menuCells.setVisible(false);
        else
            menuCells.setVisible(!imageData.getHierarchy().getDetectionObjects().isEmpty());
        // Check what to show for TMA cores or annotations
        Collection<PathObject> selectedObjects = viewer.getAllSelectedObjects();
        PathObject pathObject = viewer.getSelectedObject();
        menuTMA.setVisible(false);
        if (pathObject instanceof TMACoreObject) {
            boolean isMissing = ((TMACoreObject) pathObject).isMissing();
            miTMAValid.setSelected(!isMissing);
            miTMAMissing.setSelected(isMissing);
            menuTMA.setVisible(true);
        }
        // Add clear objects option if we have more than one non-TMA object
        if (imageData == null || imageData.getHierarchy().getSelectionModel().noSelection() || imageData.getHierarchy().getSelectionModel().getSelectedObject() instanceof TMACoreObject)
            miClearSelectedObjects.setVisible(false);
        else {
            if (imageData.getHierarchy().getSelectionModel().singleSelection()) {
                miClearSelectedObjects.setText("Delete object");
                miClearSelectedObjects.setVisible(true);
            } else {
                miClearSelectedObjects.setText("Delete objects");
                miClearSelectedObjects.setVisible(true);
            }
        }
        boolean hasAnnotations = pathObject instanceof PathAnnotationObject || (!selectedObjects.isEmpty() && selectedObjects.stream().allMatch(p -> p.isAnnotation()));
        updateSetAnnotationPathClassMenu(menuSetClass, viewer);
        menuAnnotations.setVisible(hasAnnotations);
        topSeparator.setVisible(hasAnnotations || pathObject instanceof TMACoreObject);
        // Occasionally, the newly-visible top part of a popup menu can have the wrong size?
        popup.setWidth(popup.getPrefWidth());
    });
    // popup.add(menuClassify);
    popup.getItems().addAll(miClearSelectedObjects, menuTMA, menuSetClass, menuAnnotations, topSeparator, menuMultiview, menuCells, menuView, menuTools);
    popup.setAutoHide(true);
    // Enable circle pop-up for quick classification on right-click
    CirclePopupMenu circlePopup = new CirclePopupMenu(viewer.getView(), null);
    viewer.getView().addEventHandler(MouseEvent.MOUSE_PRESSED, e -> {
        if ((e.isPopupTrigger() || e.isSecondaryButtonDown()) && e.isShiftDown() && !getAvailablePathClasses().isEmpty()) {
            circlePopup.setAnimationDuration(Duration.millis(200));
            updateSetAnnotationPathClassMenu(circlePopup, viewer);
            circlePopup.show(e.getScreenX(), e.getScreenY());
            e.consume();
            return;
        } else if (circlePopup.isShown())
            circlePopup.hide();
        if (e.isPopupTrigger() || e.isSecondaryButtonDown()) {
            popup.show(viewer.getView().getScene().getWindow(), e.getScreenX(), e.getScreenY());
            e.consume();
        }
    });
// // It's necessary to make the Window the owner, since otherwise the context menu does not disappear when clicking elsewhere on the viewer
// viewer.getView().setOnContextMenuRequested(e -> {
// popup.show(viewer.getView().getScene().getWindow(), e.getScreenX(), e.getScreenY());
// //			popup.show(viewer.getView(), e.getScreenX(), e.getScreenY());
// });
}
Also used : Change(javafx.collections.ListChangeListener.Change) PathObjectHierarchyView(qupath.lib.gui.panes.PathObjectHierarchyView) SelectedMeasurementTableView(qupath.lib.gui.panes.SelectedMeasurementTableView) Version(qupath.lib.common.Version) ProjectBrowser(qupath.lib.gui.panes.ProjectBrowser) ListChangeListener(javafx.collections.ListChangeListener) Map(java.util.Map) Path(java.nio.file.Path) ReleaseVersion(qupath.lib.gui.extensions.UpdateChecker.ReleaseVersion) Rectangle2D(javafx.geometry.Rectangle2D) PathObjects(qupath.lib.objects.PathObjects) Rectangle(javafx.scene.shape.Rectangle) BooleanProperty(javafx.beans.property.BooleanProperty) Project(qupath.lib.projects.Project) ObservableList(javafx.collections.ObservableList) Divider(javafx.scene.control.SplitPane.Divider) QuPathExtension(qupath.lib.gui.extensions.QuPathExtension) ByteArrayOutputStream(java.io.ByteArrayOutputStream) FXCollections(javafx.collections.FXCollections) PathIcons(qupath.lib.gui.tools.IconFactory.PathIcons) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Bindings(javafx.beans.binding.Bindings) LinkedHashMap(java.util.LinkedHashMap) TreeTableView(javafx.scene.control.TreeTableView) PreferencePane(qupath.lib.gui.panes.PreferencePane) Commands(qupath.lib.gui.commands.Commands) QuPathStyleManager(qupath.lib.gui.prefs.QuPathStyleManager) IOException(java.io.IOException) OverlayOptions(qupath.lib.gui.viewer.OverlayOptions) Preferences(java.util.prefs.Preferences) ROI(qupath.lib.roi.interfaces.ROI) PathTools(qupath.lib.gui.viewer.tools.PathTools) ParameterPanelFX(qupath.lib.gui.dialogs.ParameterPanelFX) DragDropImportListener(qupath.lib.gui.viewer.DragDropImportListener) ImageView(javafx.scene.image.ImageView) TMAGrid(qupath.lib.objects.hierarchy.TMAGrid) Image(javafx.scene.image.Image) PathIO(qupath.lib.io.PathIO) EventHandler(javafx.event.EventHandler) ImageServer(qupath.lib.images.servers.ImageServer) BooleanBinding(javafx.beans.binding.BooleanBinding) TextInputControl(javafx.scene.control.TextInputControl) URLDecoder(java.net.URLDecoder) UncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) Date(java.util.Date) URISyntaxException(java.net.URISyntaxException) ObjectInputStream(java.io.ObjectInputStream) KeyCombination(javafx.scene.input.KeyCombination) DefaultImageRegionStore(qupath.lib.gui.images.stores.DefaultImageRegionStore) ByteArrayInputStream(java.io.ByteArrayInputStream) Locale(java.util.Locale) GitHubProject(qupath.lib.gui.extensions.GitHubProject) ImageIO(javax.imageio.ImageIO) RotateEvent(javafx.scene.input.RotateEvent) WindowEvent(javafx.stage.WindowEvent) PathInteractivePlugin(qupath.lib.plugins.PathInteractivePlugin) Orientation(javafx.geometry.Orientation) MenuItem(javafx.scene.control.MenuItem) Ellipse(javafx.scene.shape.Ellipse) ImageServerProvider(qupath.lib.images.servers.ImageServerProvider) Collection(java.util.Collection) Font(javafx.scene.text.Font) ServiceLoader(java.util.ServiceLoader) Collectors(java.util.stream.Collectors) BorderStroke(javafx.scene.layout.BorderStroke) PathObject(qupath.lib.objects.PathObject) Objects(java.util.Objects) ImageTypeSetting(qupath.lib.gui.prefs.PathPrefs.ImageTypeSetting) ProjectIO(qupath.lib.projects.ProjectIO) GuiTools(qupath.lib.gui.tools.GuiTools) ExecutorCompletionService(java.util.concurrent.ExecutorCompletionService) Scene(javafx.scene.Scene) ListView(javafx.scene.control.ListView) ReadOnlyObjectProperty(javafx.beans.property.ReadOnlyObjectProperty) SimpleStringProperty(javafx.beans.property.SimpleStringProperty) Action(org.controlsfx.control.action.Action) PathClassFactory(qupath.lib.objects.classes.PathClassFactory) ScriptEditor(qupath.lib.gui.scripting.ScriptEditor) TableColumn(javafx.scene.control.TableColumn) HashSet(java.util.HashSet) Insets(javafx.geometry.Insets) DetectionDisplayMode(qupath.lib.gui.viewer.OverlayOptions.DetectionDisplayMode) ExecutorService(java.util.concurrent.ExecutorService) KeyCode(javafx.scene.input.KeyCode) ActionAccelerator(qupath.lib.gui.ActionTools.ActionAccelerator) Logger(org.slf4j.Logger) Dialog(javafx.scene.control.Dialog) Label(javafx.scene.control.Label) MenuBar(javafx.scene.control.MenuBar) ActionIcon(qupath.lib.gui.ActionTools.ActionIcon) ServerBuilder(qupath.lib.images.servers.ImageServerBuilder.ServerBuilder) ScrollEvent(javafx.scene.input.ScrollEvent) Consumer(java.util.function.Consumer) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) Stage(javafx.stage.Stage) ViewerPlusDisplayOptions(qupath.lib.gui.viewer.ViewerPlusDisplayOptions) Comparator(java.util.Comparator) PathTool(qupath.lib.gui.viewer.tools.PathTool) Arrays(java.util.Arrays) ServerTools(qupath.lib.images.servers.ServerTools) ActionUtils(org.controlsfx.control.action.ActionUtils) ActionDescription(qupath.lib.gui.ActionTools.ActionDescription) ReadOnlyBooleanProperty(javafx.beans.property.ReadOnlyBooleanProperty) StackPane(javafx.scene.layout.StackPane) AnnotationPane(qupath.lib.gui.panes.AnnotationPane) JFXPanel(javafx.embed.swing.JFXPanel) Category(java.util.Locale.Category) ParameterList(qupath.lib.plugins.parameters.ParameterList) TabPane(javafx.scene.control.TabPane) ScriptException(javax.script.ScriptException) CountingPanelCommand(qupath.lib.gui.commands.CountingPanelCommand) SplitPane(javafx.scene.control.SplitPane) Border(javafx.scene.layout.Border) Event(javafx.event.Event) Set(java.util.Set) KeyEvent(javafx.scene.input.KeyEvent) Screen(javafx.stage.Screen) AffineTransform(java.awt.geom.AffineTransform) QuPathViewerListener(qupath.lib.gui.viewer.QuPathViewerListener) StandardCharsets(java.nio.charset.StandardCharsets) Executors(java.util.concurrent.Executors) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) Platform(javafx.application.Platform) Region(javafx.scene.layout.Region) CommandFinderTools(qupath.lib.gui.tools.CommandFinderTools) InputDisplayCommand(qupath.lib.gui.commands.InputDisplayCommand) ImageRegionStoreFactory(qupath.lib.gui.images.stores.ImageRegionStoreFactory) ThreadTools(qupath.lib.common.ThreadTools) DefaultScriptEditor(qupath.lib.gui.scripting.DefaultScriptEditor) GitHubRepo(qupath.lib.gui.extensions.GitHubProject.GitHubRepo) BorderPane(javafx.scene.layout.BorderPane) ButtonData(javafx.scene.control.ButtonBar.ButtonData) SimpleDateFormat(java.text.SimpleDateFormat) PathPlugin(qupath.lib.plugins.PathPlugin) Projects(qupath.lib.projects.Projects) StandardCopyOption(java.nio.file.StandardCopyOption) ArrayList(java.util.ArrayList) TabClosingPolicy(javafx.scene.control.TabPane.TabClosingPolicy) QuPathViewerPlus(qupath.lib.gui.viewer.QuPathViewerPlus) ObjectOutputStream(java.io.ObjectOutputStream) LinkedHashSet(java.util.LinkedHashSet) Color(javafx.scene.paint.Color) CirclePopupMenu(jfxtras.scene.menu.CirclePopupMenu) TitledPane(javafx.scene.control.TitledPane) Files(java.nio.file.Files) ToolBar(javafx.scene.control.ToolBar) GeneralTools(qupath.lib.common.GeneralTools) Node(javafx.scene.Node) CheckBox(javafx.scene.control.CheckBox) ProjectCommands(qupath.lib.gui.commands.ProjectCommands) File(java.io.File) PathObjectTools(qupath.lib.objects.PathObjectTools) Menu(javafx.scene.control.Menu) Cursor(javafx.scene.Cursor) KeyCodeCombination(javafx.scene.input.KeyCodeCombination) Paths(java.nio.file.Paths) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) Tab(javafx.scene.control.Tab) PathPrefs(qupath.lib.gui.prefs.PathPrefs) StringBinding(javafx.beans.binding.StringBinding) Pos(javafx.geometry.Pos) Area(java.awt.geom.Area) CheckMenuItem(javafx.scene.control.CheckMenuItem) LoggerFactory(org.slf4j.LoggerFactory) UpdateChecker(qupath.lib.gui.extensions.UpdateChecker) Parent(javafx.scene.Parent) ContextMenu(javafx.scene.control.ContextMenu) URI(java.net.URI) ImageServers(qupath.lib.images.servers.ImageServers) TableView(javafx.scene.control.TableView) ImageType(qupath.lib.images.ImageData.ImageType) Shape(java.awt.Shape) BufferedImage(java.awt.image.BufferedImage) GroovyLanguage(qupath.lib.gui.scripting.languages.GroovyLanguage) ImageServerBuilder(qupath.lib.images.servers.ImageServerBuilder) FileNotFoundException(java.io.FileNotFoundException) TreeView(javafx.scene.control.TreeView) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer) List(java.util.List) Duration(javafx.util.Duration) ColorToolsFX(qupath.lib.gui.tools.ColorToolsFX) Optional(java.util.Optional) LogManager(qupath.lib.gui.logging.LogManager) RadioMenuItem(javafx.scene.control.RadioMenuItem) WorkflowCommandLogView(qupath.lib.gui.panes.WorkflowCommandLogView) TextArea(javafx.scene.control.TextArea) ButtonType(javafx.scene.control.ButtonType) MouseEvent(javafx.scene.input.MouseEvent) HashMap(java.util.HashMap) BrightnessContrastCommand(qupath.lib.gui.commands.BrightnessContrastCommand) UriImageSupport(qupath.lib.images.servers.ImageServerBuilder.UriImageSupport) Dialogs(qupath.lib.gui.dialogs.Dialogs) SwingUtilities(javax.swing.SwingUtilities) HostServices(javafx.application.HostServices) ZoomEvent(javafx.scene.input.ZoomEvent) TMACommands(qupath.lib.gui.commands.TMACommands) Tooltip(javafx.scene.control.Tooltip) ImageDetailsPane(qupath.lib.gui.panes.ImageDetailsPane) ImageData(qupath.lib.images.ImageData) Desktop(java.awt.Desktop) RoiTools(qupath.lib.roi.RoiTools) ObjectProperty(javafx.beans.property.ObjectProperty) Iterator(java.util.Iterator) ProjectImageEntry(qupath.lib.projects.ProjectImageEntry) TableRow(javafx.scene.control.TableRow) PathClass(qupath.lib.objects.classes.PathClass) TMACoreObject(qupath.lib.objects.TMACoreObject) DropShadow(javafx.scene.effect.DropShadow) MenuTools(qupath.lib.gui.tools.MenuTools) BorderStrokeStyle(javafx.scene.layout.BorderStrokeStyle) ActionEvent(javafx.event.ActionEvent) ToggleGroup(javafx.scene.control.ToggleGroup) LogViewerCommand(qupath.lib.gui.commands.LogViewerCommand) SwingFXUtils(javafx.embed.swing.SwingFXUtils) Collections(java.util.Collections) InputStream(java.io.InputStream) DialogButton(qupath.lib.gui.dialogs.Dialogs.DialogButton) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) CirclePopupMenu(jfxtras.scene.menu.CirclePopupMenu) TMACoreObject(qupath.lib.objects.TMACoreObject) ContextMenu(javafx.scene.control.ContextMenu) MenuItem(javafx.scene.control.MenuItem) CheckMenuItem(javafx.scene.control.CheckMenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) RadioMenuItem(javafx.scene.control.RadioMenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) CheckMenuItem(javafx.scene.control.CheckMenuItem) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject) ToggleGroup(javafx.scene.control.ToggleGroup) CirclePopupMenu(jfxtras.scene.menu.CirclePopupMenu) Menu(javafx.scene.control.Menu) ContextMenu(javafx.scene.control.ContextMenu)

Example 2 with QuPathViewerPlus

use of qupath.lib.gui.viewer.QuPathViewerPlus in project qupath by qupath.

the class QuPathGUI method initializeMainComponent.

private BorderPane initializeMainComponent() {
    pane = new BorderPane();
    // Create a reasonably-sized viewer
    QuPathViewerPlus viewer = new QuPathViewerPlus(null, imageRegionStore, overlayOptions, viewerDisplayOptions);
    // Add analysis panel & viewer to split pane
    viewerManager = new MultiviewManager(viewer);
    viewerProperty.bind(viewerManager.activeViewerProperty());
    // Now that we have a viewer, we can create an undo/redo manager
    undoRedoManager = new UndoRedoManager(this);
    // TODO: MOVE INITIALIZING MANAGERS ELSEWHERE
    actions.addAll(new Menus(this).getActions());
    // Add a recent projects menu
    getMenu("File", true).getItems().add(1, createRecentProjectsMenu());
    // analysisPanel = createAnalysisPanel();
    initializeAnalysisPanel();
    analysisPanel.setMinWidth(300);
    analysisPanel.setPrefWidth(400);
    splitPane.setMinWidth(analysisPanel.getMinWidth() + 200);
    splitPane.setPrefWidth(analysisPanel.getPrefWidth() + 200);
    SplitPane.setResizableWithParent(analysisPanel, Boolean.FALSE);
    // paneCommands.setRight(cbPin);
    mainViewerPane = CommandFinderTools.createCommandFinderPane(this, viewerManager.getNode(), CommandFinderTools.commandBarDisplayProperty());
    // paneViewer.setTop(tfCommands);
    // paneViewer.setCenter(viewerManager.getNode());
    splitPane.getItems().addAll(analysisPanel, mainViewerPane);
    // splitPane.getItems().addAll(viewerManager.getComponent());
    SplitPane.setResizableWithParent(viewerManager.getNode(), Boolean.TRUE);
    pane.setCenter(splitPane);
    toolbar = new ToolBarComponent(this);
    pane.setTop(toolbar.getToolBar());
    setAnalysisPaneVisible(showAnalysisPane.get());
    showAnalysisPane.addListener((v, o, n) -> setAnalysisPaneVisible(n));
    // setInitialLocationAndMagnification(getViewer());
    // Prepare the viewer
    setupViewer(viewerManager.getActiveViewer());
    // Ensure the mode is set
    // Ensure actions are set appropriately
    selectedToolProperty.addListener((v, o, n) -> {
        Action action = toolActions.get(n);
        if (action != null)
            action.setSelected(true);
        activateTools(getViewer());
        if (n == PathTools.POINTS)
            defaultActions.COUNTING_PANEL.handle(null);
        updateCursor();
    });
    setSelectedTool(getSelectedTool());
    return pane;
}
Also used : BorderPane(javafx.scene.layout.BorderPane) Action(org.controlsfx.control.action.Action) QuPathViewerPlus(qupath.lib.gui.viewer.QuPathViewerPlus)

Example 3 with QuPathViewerPlus

use of qupath.lib.gui.viewer.QuPathViewerPlus in project qupath by qupath.

the class QuPathGUI method openImageEntry.

/**
 * Open the image represented by the specified ProjectImageEntry.
 * <p>
 * If an image is currently open, this command will prompt to save any changes.
 *
 * @param entry
 * @return
 */
public boolean openImageEntry(ProjectImageEntry<BufferedImage> entry) {
    Project<BufferedImage> project = getProject();
    if (entry == null || project == null)
        return false;
    // Check if we're changing ImageData at all
    var viewer = getViewer();
    ImageData<BufferedImage> imageData = viewer.getImageData();
    if (imageData != null && project.getEntry(imageData) == entry) {
        return false;
    }
    // String path = entry.getServerPath();
    for (QuPathViewerPlus v : viewerManager.getViewers()) {
        ImageData<BufferedImage> data = v.getImageData();
        if (data != null && project.getEntry(data) == entry) {
            // if (data != null && data.getServer().getPath().equals(path)) {
            viewerManager.setActiveViewer(v);
            return true;
        }
    }
    // If the current ImageData belongs to the current project, check if there are changes to save
    if (imageData != null && project != null) {
        if (!checkSaveChanges(imageData))
            return false;
    }
    // Check if we need to rotate the image
    try {
        imageData = entry.readImageData();
        viewer.setImageData(imageData);
        // setInitialLocationAndMagnification(viewer);
        if (imageData != null && (imageData.getImageType() == null || imageData.getImageType() == ImageType.UNSET)) {
            var setType = PathPrefs.imageTypeSettingProperty().get();
            if (setType == ImageTypeSetting.AUTO_ESTIMATE || setType == ImageTypeSetting.PROMPT) {
                var type = GuiTools.estimateImageType(imageData.getServer(), imageRegionStore.getThumbnail(imageData.getServer(), 0, 0, true));
                logger.info("Image type estimated to be {}", type);
                if (setType == ImageTypeSetting.PROMPT) {
                    ImageDetailsPane.promptToSetImageType(imageData, type);
                } else {
                    imageData.setImageType(type);
                    // Don't want to retain this as a change resulting in a prompt to save the data
                    imageData.setChanged(false);
                }
            }
        }
        return true;
    } catch (Exception e) {
        Dialogs.showErrorMessage("Load ImageData", e);
        return false;
    }
}
Also used : BufferedImage(java.awt.image.BufferedImage) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) ScriptException(javax.script.ScriptException) FileNotFoundException(java.io.FileNotFoundException) QuPathViewerPlus(qupath.lib.gui.viewer.QuPathViewerPlus)

Example 4 with QuPathViewerPlus

use of qupath.lib.gui.viewer.QuPathViewerPlus in project qupath by qupath.

the class QuPathGUI method openSavedData.

/**
 * Open a saved data file within a particular viewer, optionally keeping the same ImageServer as is currently open.
 * The purpose of this is to make it possible for a project (for example) to open the correct server prior to
 * opening the data file, enabling it to make use of relative path names and not have to rely on the absolute path
 * encoded within the ImageData.
 *
 * @param viewer
 * @param file
 * @param keepExistingServer if true and the viewer already has an ImageServer, then any ImageServer path recorded within the data file will be ignored
 * @param promptToSaveChanges if true, the user will be prompted to ask whether to save changes or not
 * @return
 * @throws IOException
 */
public boolean openSavedData(QuPathViewer viewer, final File file, final boolean keepExistingServer, boolean promptToSaveChanges) throws IOException {
    if (viewer == null) {
        if (getViewers().size() == 1)
            viewer = getViewer();
        else {
            Dialogs.showErrorMessage("Open saved data", "Please specify the viewer where the data should be opened!");
            return false;
        }
    }
    // First check to see if the ImageData is already open - if so, just activate the viewer
    for (QuPathViewerPlus v : viewerManager.getViewers()) {
        ImageData<?> data = v.getImageData();
        if (data != null && data.getLastSavedPath() != null && new File(data.getLastSavedPath()).equals(file)) {
            viewerManager.setActiveViewer(v);
            return true;
        }
    }
    ServerBuilder<BufferedImage> serverBuilder = null;
    ImageData<BufferedImage> imageData = viewer.getImageData();
    // If we are loading data related to the same image server, load into that - otherwise open a new image if we can find it
    try {
        serverBuilder = PathIO.extractServerBuilder(file.toPath());
    } catch (Exception e) {
        logger.warn("Unable to read server path from file: {}", e.getLocalizedMessage());
    }
    var existingBuilder = imageData == null || imageData.getServer() == null ? null : imageData.getServer().getBuilder();
    boolean sameServer = Objects.equals(existingBuilder, serverBuilder);
    // If we don't have the same server, try to check the path is valid.
    // If it isn't, then prompt to enter a new path.
    // Currently, URLs are always assumed to be valid, but files may have moved.
    // TODO: Make it possible to recover data if a stored URL ceases to be valid.
    ImageServer<BufferedImage> server = null;
    if (sameServer || (imageData != null && keepExistingServer))
        server = imageData.getServer();
    else {
        try {
            server = serverBuilder.build();
        } catch (Exception e) {
            logger.error("Unable to build server " + serverBuilder, e);
        }
        // TODO: Ideally we would use an interface like ProjectCheckUris instead
        if (server == null && serverBuilder != null) {
            var uris = serverBuilder.getURIs();
            var urisUpdated = new HashMap<URI, URI>();
            for (var uri : uris) {
                var pathUri = GeneralTools.toPath(uri);
                if (pathUri != null && Files.exists(pathUri)) {
                    urisUpdated.put(uri, uri);
                    continue;
                }
                String currentPath = pathUri == null ? uri.toString() : pathUri.toString();
                var newPath = Dialogs.promptForFilePathOrURL("Set path to missing image", currentPath, file.getParentFile(), null);
                if (newPath == null)
                    return false;
                try {
                    urisUpdated.put(uri, GeneralTools.toURI(newPath));
                } catch (URISyntaxException e) {
                    throw new IOException(e);
                }
            }
            serverBuilder = serverBuilder.updateURIs(urisUpdated);
            try {
                server = serverBuilder.build();
            } catch (Exception e) {
                logger.error("Unable to build server " + serverBuilder, e);
            }
        }
        if (server == null)
            return false;
        // 
        // Small optimization... put in a thumbnail request early in a background thread.
        // This way that it will be fetched while the image data is being read -
        // generally leading to improved performance in the viewer's setImageData method
        // (specifically the updating of the ImageDisplay, which needs a thumbnail)
        final ImageServer<BufferedImage> serverTemp = server;
        poolMultipleThreads.submit(() -> {
            imageRegionStore.getThumbnail(serverTemp, 0, 0, true);
        });
    }
    if (promptToSaveChanges && imageData != null && imageData.isChanged()) {
        if (!isReadOnly() && !promptToSaveChangesOrCancel("Save changes", imageData))
            return false;
    }
    try {
        ImageData<BufferedImage> imageData2 = PathIO.readImageData(file, imageData, server, BufferedImage.class);
        if (imageData2 != imageData) {
            viewer.setImageData(imageData2);
        }
    } catch (IOException e) {
        Dialogs.showErrorMessage("Read image data", e);
    }
    return true;
}
Also used : LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) URISyntaxException(java.net.URISyntaxException) IOException(java.io.IOException) BufferedImage(java.awt.image.BufferedImage) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) ScriptException(javax.script.ScriptException) FileNotFoundException(java.io.FileNotFoundException) File(java.io.File) QuPathViewerPlus(qupath.lib.gui.viewer.QuPathViewerPlus)

Aggregations

QuPathViewerPlus (qupath.lib.gui.viewer.QuPathViewerPlus)4 BufferedImage (java.awt.image.BufferedImage)3 FileNotFoundException (java.io.FileNotFoundException)3 IOException (java.io.IOException)3 URISyntaxException (java.net.URISyntaxException)3 ScriptException (javax.script.ScriptException)3 File (java.io.File)2 HashMap (java.util.HashMap)2 LinkedHashMap (java.util.LinkedHashMap)2 BorderPane (javafx.scene.layout.BorderPane)2 Action (org.controlsfx.control.action.Action)2 Desktop (java.awt.Desktop)1 Shape (java.awt.Shape)1 AffineTransform (java.awt.geom.AffineTransform)1 Area (java.awt.geom.Area)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 InputStream (java.io.InputStream)1 ObjectInputStream (java.io.ObjectInputStream)1 ObjectOutputStream (java.io.ObjectOutputStream)1