Search in sources :

Example 1 with MasterDetailPane

use of org.controlsfx.control.MasterDetailPane in project qupath by qupath.

the class ScriptInterpreter method initialize.

private void initialize() {
    MenuBar menuBar = new MenuBar();
    Menu menuLanguages = new Menu("Language");
    menuBar.getMenus().add(menuLanguages);
    ToggleGroup group = new ToggleGroup();
    // Attempt to 'sanitize' the names
    for (ScriptEngineFactory factory : manager.getEngineFactories()) {
        // logger.info(factory.getEngineName() + ", " + factory.getEngineVersion());
        // logger.info(factory.getLanguageName() + ", " + factory.getLanguageVersion());
        logger.info("{}", factory.getNames());
        String name;
        List<String> allNames = factory.getNames();
        if (allNames.contains("groovy"))
            name = "Groovy";
        else if (allNames.contains("jython"))
            name = "Jython";
        else if (allNames.contains("python"))
            name = "Python";
        else if (allNames.contains("r"))
            name = "R";
        else if (allNames.contains("ruby"))
            name = "Ruby";
        else if (allNames.contains("javascript"))
            name = "JavaScript";
        else
            name = factory.getLanguageName();
        RadioMenuItem menuItem = new RadioMenuItem(name);
        menuItem.setToggleGroup(group);
        menuItem.selectedProperty().addListener((o, v, n) -> {
            if (n) {
                engine = factory.getScriptEngine();
                try {
                    engine.setContext(preferredContext);
                    context = preferredContext;
                } catch (Exception e) {
                    logger.warn("Could not set preferred script context for {}: {}", engine, e.getLocalizedMessage());
                    context = engine.getContext();
                    setWriters(context);
                }
                updateVariableTable();
            }
        });
        if (// Prefer Groovy if we can get it
        group.getSelectedToggle() == null || "Groovy".equals(name))
            group.selectToggle(menuItem);
        menuLanguages.getItems().add(menuItem);
    }
    FXCollections.sort(menuLanguages.getItems(), (m1, m2) -> m1.getText().compareTo(m2.getText()));
    // Script menu
    Menu menuScript = new Menu("Script");
    MenuItem miGenerateScript = new MenuItem("Generate script");
    miGenerateScript.setOnAction(e -> {
        String script = String.join("\n", historyList);
        qupath.getScriptEditor().showScript("From interpreter", script);
    });
    menuScript.getItems().add(miGenerateScript);
    menuBar.getMenus().add(menuScript);
    /*
		 * Create the main area
		 */
    // Simple TextArea-based command log (no syntax coloring)
    // TextArea textArea = new TextArea();
    // textArea.setPrefColumnCount(50);
    // textArea.setPrefRowCount(40);
    // textArea.textProperty().bindBidirectional(historyText);
    // textArea.setWrapText(true);
    // textArea.setFont(font);
    // textArea.setEditable(false);
    // textArea.textProperty().addListener((v, o, n) -> {
    // //				if (textArea.getSelection().getLength() == 0) {
    // //					textArea.setScrollTop(Double.MAX_VALUE);
    // //				}
    // Platform.runLater(() -> textArea.appendText(""));
    // });
    // Command log with some color coding
    WebView textArea = new WebView();
    historyText.addListener((v, o, n) -> {
        String styleAll = "* {\n  " + "font-family: \"Courier New\", Courier, monospace;\n" + "font-size: 0.95em;\n " + "}";
        String styleError = ".error {\n  " + "color: red;\n" + "}";
        String styleWarning = ".warning {\n  " + "color: orange;\n" + "}";
        String styleCommand = ".command {\n  " + "color: black;\n" + "}";
        String styleOther = ".other {\n  " + "color: gray;\n" + "}";
        String styleVariable = ".variable {\n  " + "color: purple;\n" + "}";
        StringBuilder sb = new StringBuilder();
        sb.append("<html>").append("\n");
        sb.append("<head>").append("\n");
        sb.append("<script language=\"javascript\" type=\"text/javascript\">").append("\n");
        sb.append("function scrollToEnd(){").append("\n");
        sb.append("window.scrollTo(0, document.body.scrollHeight);").append("\n");
        sb.append("}").append("\n");
        sb.append("</script>").append("\n");
        sb.append("<style>").append("\n");
        sb.append(styleAll).append("\n");
        sb.append(styleError).append("\n");
        sb.append(styleWarning).append("\n");
        sb.append(styleCommand).append("\n");
        sb.append(styleOther).append("\n");
        sb.append(styleVariable).append("\n");
        sb.append("</style>").append("\n");
        sb.append("</head>").append("\n");
        sb.append("<body onload='scrollToEnd()'>").append("\n");
        sb.append(n.replace("\n", "<br/>"));
        sb.append("</body>");
        // String content = String.format("<html><head><style>%s</style></head><body>%s</body></html>", style, n.replace("\n", "<br/>"));
        textArea.getEngine().loadContent(sb.toString());
    });
    // TextArea textArea = new TextArea();
    // textArea.setPrefColumnCount(50);
    // textArea.setPrefRowCount(40);
    // textArea.textProperty().bindBidirectional(historyText);
    // textArea.setWrapText(true);
    // textArea.setFont(font);
    // textArea.setEditable(false);
    // textArea.textProperty().addListener((v, o, n) -> {
    // //				if (textArea.getSelection().getLength() == 0) {
    // //					textArea.setScrollTop(Double.MAX_VALUE);
    // //				}
    // Platform.runLater(() -> textArea.appendText(""));
    // });
    // Input
    textAreaInput = new TextArea();
    textAreaInput.setPrefRowCount(4);
    textAreaInput.textProperty().bindBidirectional(currentText);
    textAreaInput.addEventFilter(KeyEvent.KEY_PRESSED, e -> {
        if (e.getCode() == KeyCode.ENTER) {
            runLine();
            e.consume();
        }
    });
    textAreaInput.addEventFilter(KeyEvent.KEY_RELEASED, e -> {
        if (e.getCode() == KeyCode.ENTER) {
            // Already handled with key press
            return;
        } else if (e.getCode() == KeyCode.UP || (e.getCode() == KeyCode.DOWN)) {
            // Don't do anything if we're using autocomplete
            if (menuAutocomplete.isShowing())
                return;
            if (e.getCode() == KeyCode.UP) {
                if (!decrementHistoryPointer()) {
                    e.consume();
                    return;
                }
            } else {
                if (!incrementHistoryPointer()) {
                    e.consume();
                    return;
                }
            }
            // textAreaInput.setText(listHistory.getSelectionModel().getSelectedItem());
            // textAreaInput.appendText(""); // To move caret
            e.consume();
            return;
        }
        // resetHistoryPointer();
        if (menuAutocomplete.isShowing() || (e.isControlDown() && e.getCode() == KeyCode.SPACE)) {
            updateAutocompleteMenu();
            // Using reflection for compatibility with Java 8 and Java 9
            Skin<?> skin = textAreaInput.getSkin();
            Bounds b = null;
            try {
                b = (Bounds) skin.getClass().getMethod("getCaretBounds").invoke(skin);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e1) {
                logger.error("Error requesting caret bounds - cannot display autocomplete menu", e1);
            }
            // If there's only one open, and we aren't already showing, just use it
            if (!menuAutocomplete.isShowing() && menuAutocomplete.getItems().size() == 1) {
                menuAutocomplete.getItems().get(0).fire();
                e.consume();
                return;
            }
            if (b != null && !menuAutocomplete.getItems().isEmpty()) {
                menuAutocomplete.show(textAreaInput, Side.TOP, b.getMaxX() + 5, b.getMaxY() + 5);
            }
        } else if (menuAutocomplete.isShowing() && e.getCode() == KeyCode.TAB) {
            menuAutocomplete.hide();
            e.consume();
        }
    });
    textAreaInput.addEventHandler(KeyEvent.KEY_RELEASED, e -> {
        if (!e.isConsumed())
            updateLastHistoryListEntry();
    });
    historyList.add("");
    // currentText.addListener((v, o, n) -> {
    // historyList.set(historyList.size()-1, n);
    // }); // Keep last entry updated
    textAreaInput.setFont(font);
    // Create the variable table
    TableColumn<String, String> colKeys = new TableColumn<>("Name");
    colKeys.setCellValueFactory(c -> new SimpleStringProperty(c.getValue()));
    colKeys.setCellFactory(c -> new VariableTableCell(VariableInfoType.NAME));
    TableColumn<String, String> colClasses = new TableColumn<>("Class");
    colClasses.setCellValueFactory(c -> new SimpleStringProperty(c.getValue()));
    colClasses.setCellFactory(c -> new VariableTableCell(VariableInfoType.CLASS));
    TableColumn<String, String> colValues = new TableColumn<>("Value");
    colValues.setCellValueFactory(c -> new SimpleStringProperty(c.getValue()));
    colValues.setCellFactory(c -> new VariableTableCell(VariableInfoType.VALUE));
    tableVariables.setPlaceholder(new Label("No variables set"));
    tableVariables.getColumns().add(colKeys);
    tableVariables.getColumns().add(colClasses);
    tableVariables.getColumns().add(colValues);
    tableVariables.setTableMenuButtonVisible(true);
    tableVariables.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    Button btnClear = new Button("Clear variables");
    btnClear.setOnAction(e -> {
        Bindings bindings = context.getBindings(ScriptContext.ENGINE_SCOPE);
        List<String> variables = getSelectedVariableNames();
        if (variables.isEmpty())
            variables = getCurrentVariableNames();
        if (variables.isEmpty())
            return;
        if (variables.size() == 1) {
            if (!Dialogs.showConfirmDialog("Clear variables", "Clear variable '" + variables.get(0) + "'?"))
                return;
        } else {
            if (!Dialogs.showConfirmDialog("Clear variables", "Clear " + variables.size() + " variables?"))
                return;
        }
        for (String v : variables) bindings.remove(v);
        logger.info("Removed variables from interpreter workspace: {}", variables);
        updateVariableTable();
    });
    btnClear.setMaxWidth(Double.MAX_VALUE);
    btnClear.disableProperty().bind(javafx.beans.binding.Bindings.createBooleanBinding(() -> tableVariables.getItems().isEmpty(), tableVariables.getItems()));
    Button btnAdd = new Button("Add...");
    ContextMenu menuAdd = new ContextMenu();
    MenuItem miAddImageData = new MenuItem("Image data");
    miAddImageData.setOnAction(e -> {
        ImageData<?> imageData = qupath.getImageData();
        engine.put(defaultImageDataName, imageData);
        updateVariableTable();
    });
    MenuItem miAddHierarchy = new MenuItem("Hierarchy");
    miAddHierarchy.setOnAction(e -> {
        ImageData<?> imageData = qupath.getImageData();
        engine.put(defaultHierarchyName, imageData == null ? null : imageData.getHierarchy());
        updateVariableTable();
    });
    MenuItem miAddSelectionModel = new MenuItem("Selection model");
    miAddSelectionModel.setOnAction(e -> {
        ImageData<?> imageData = qupath.getImageData();
        engine.put(defaultSelectionModelName, imageData == null ? null : imageData.getHierarchy().getSelectionModel());
        updateVariableTable();
    });
    MenuItem miAddServer = new MenuItem("Image server");
    miAddServer.setOnAction(e -> {
        ImageData<?> imageData = qupath.getImageData();
        engine.put(defaultImageServerName, imageData == null ? null : imageData.getServer());
        updateVariableTable();
    });
    MenuItem miAddProject = new MenuItem("Project");
    miAddProject.setOnAction(e -> {
        engine.put(defaultProjectName, qupath.getProject());
        updateVariableTable();
    });
    MenuItem miAddScriptingHelpers = new MenuItem("Scripting helpers");
    miAddScriptingHelpers.setOnAction(e -> {
        engine.put(defaultScriptingHelperName, new QPEx());
        updateVariableTable();
    });
    menuAdd.getItems().addAll(miAddImageData, miAddHierarchy, miAddSelectionModel, miAddServer, miAddProject, miAddScriptingHelpers);
    btnAdd.setOnMouseClicked(e -> {
        menuAdd.show(btnAdd, e.getScreenX(), e.getScreenY());
    });
    btnAdd.setMaxWidth(Double.MAX_VALUE);
    GridPane paneTable = new GridPane();
    paneTable.add(tableVariables, 0, 0, 2, 1);
    paneTable.add(btnAdd, 0, 1, 1, 1);
    paneTable.add(btnClear, 1, 1, 1, 1);
    GridPane.setVgrow(tableVariables, Priority.ALWAYS);
    GridPane.setHgrow(tableVariables, Priority.ALWAYS);
    GridPane.setHgrow(btnAdd, Priority.ALWAYS);
    GridPane.setHgrow(btnClear, Priority.ALWAYS);
    ColumnConstraints col1 = new ColumnConstraints();
    col1.setPercentWidth(50);
    ColumnConstraints col2 = new ColumnConstraints();
    col2.setPercentWidth(50);
    paneTable.getColumnConstraints().addAll(col1, col2);
    // Handle list
    listHistory.setEditable(false);
    listHistory.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
    listHistory.setStyle("-fx-font-family: \"Courier New\", Courier, monospace;");
    listHistory.getSelectionModel().selectedIndexProperty().addListener((v, o, n) -> {
        if (o.intValue() < 0 || n.intValue() < 0)
            return;
        textAreaInput.setText(listHistory.getSelectionModel().getSelectedItem());
        // To move caret
        textAreaInput.appendText("");
    // e.consume();
    // return;
    });
    // Create tabbed pane
    TabPane tabPane = new TabPane();
    tabPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
    tabPane.getTabs().add(new Tab("Variables", paneTable));
    tabPane.getTabs().add(new Tab("History", listHistory));
    // Set the stage
    BorderPane pane = new BorderPane();
    MasterDetailPane paneMasterDetail = new MasterDetailPane(Side.LEFT);
    BorderPane paneInner = new BorderPane();
    paneInner.setCenter(textArea);
    paneInner.setBottom(textAreaInput);
    paneMasterDetail.setMasterNode(paneInner);
    paneMasterDetail.setDetailNode(tabPane);
    pane.setTop(menuBar);
    pane.setCenter(paneMasterDetail);
    // menuBar.setUseSystemMenuBar(true);
    menuBar.useSystemMenuBarProperty().bindBidirectional(PathPrefs.useSystemMenubarProperty());
    stage.setScene(new Scene(pane, 800, 600));
    textAreaInput.requestFocus();
// paneMasterDetail.setDividerPosition(350);
}
Also used : BorderPane(javafx.scene.layout.BorderPane) TextArea(javafx.scene.control.TextArea) ColumnConstraints(javafx.scene.layout.ColumnConstraints) MasterDetailPane(org.controlsfx.control.MasterDetailPane) Label(javafx.scene.control.Label) MenuBar(javafx.scene.control.MenuBar) ContextMenu(javafx.scene.control.ContextMenu) RadioMenuItem(javafx.scene.control.RadioMenuItem) Bindings(javax.script.Bindings) QPEx(qupath.lib.gui.scripting.QPEx) Button(javafx.scene.control.Button) ContextMenu(javafx.scene.control.ContextMenu) Menu(javafx.scene.control.Menu) WebView(javafx.scene.web.WebView) TabPane(javafx.scene.control.TabPane) GridPane(jfxtras.scene.layout.GridPane) Bounds(javafx.geometry.Bounds) CustomMenuItem(javafx.scene.control.CustomMenuItem) MenuItem(javafx.scene.control.MenuItem) RadioMenuItem(javafx.scene.control.RadioMenuItem) SimpleStringProperty(javafx.beans.property.SimpleStringProperty) Scene(javafx.scene.Scene) TableColumn(javafx.scene.control.TableColumn) InvocationTargetException(java.lang.reflect.InvocationTargetException) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) Tab(javafx.scene.control.Tab) ToggleGroup(javafx.scene.control.ToggleGroup) ScriptEngineFactory(javax.script.ScriptEngineFactory)

Example 2 with MasterDetailPane

use of org.controlsfx.control.MasterDetailPane in project qupath by qupath.

the class TMASummaryViewer method initialize.

private void initialize() {
    model = new TMATableModel();
    groupByIDProperty.addListener((v, o, n) -> refreshTableData());
    MenuBar menuBar = new MenuBar();
    Menu menuFile = new Menu("File");
    MenuItem miOpen = new MenuItem("Open...");
    miOpen.setAccelerator(new KeyCodeCombination(KeyCode.O, KeyCombination.SHORTCUT_DOWN));
    miOpen.setOnAction(e -> {
        File file = Dialogs.getChooser(stage).promptForFile(null, null, "TMA data files", new String[] { "qptma" });
        if (file == null)
            return;
        setInputFile(file);
    });
    MenuItem miSave = new MenuItem("Save As...");
    miSave.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN, KeyCombination.SHIFT_DOWN));
    miSave.setOnAction(e -> SummaryMeasurementTableCommand.saveTableModel(model, null, Collections.emptyList()));
    MenuItem miImportFromImage = new MenuItem("Import from current image...");
    miImportFromImage.setAccelerator(new KeyCodeCombination(KeyCode.I, KeyCombination.SHORTCUT_DOWN, KeyCombination.SHIFT_DOWN));
    miImportFromImage.setOnAction(e -> setTMAEntriesFromOpenImage());
    MenuItem miImportFromProject = new MenuItem("Import from current project... (experimental)");
    miImportFromProject.setAccelerator(new KeyCodeCombination(KeyCode.P, KeyCombination.SHORTCUT_DOWN, KeyCombination.SHIFT_DOWN));
    miImportFromProject.setOnAction(e -> setTMAEntriesFromOpenProject());
    MenuItem miImportClipboard = new MenuItem("Import from clipboard...");
    miImportClipboard.setOnAction(e -> {
        String text = Clipboard.getSystemClipboard().getString();
        if (text == null) {
            Dialogs.showErrorMessage("Import scores", "Clipboard is empty!");
            return;
        }
        int n = importScores(text);
        if (n > 0) {
            setTMAEntries(new ArrayList<>(entriesBase));
        }
        Dialogs.showMessageDialog("Import scores", "Number of scores imported: " + n);
    });
    Menu menuEdit = new Menu("Edit");
    MenuItem miCopy = new MenuItem("Copy table to clipboard");
    miCopy.setOnAction(e -> {
        SummaryMeasurementTableCommand.copyTableContentsToClipboard(model, Collections.emptyList());
    });
    combinedPredicate.addListener((v, o, n) -> {
        // We want any other changes triggered by this to have happened,
        // so that the data has already been updated
        Platform.runLater(() -> handleTableContentChange());
    });
    // Reset the scores for missing cores - this ensures they will be NaN and not influence subsequent results
    MenuItem miResetMissingScores = new MenuItem("Reset scores for missing cores");
    miResetMissingScores.setOnAction(e -> {
        int changes = 0;
        for (TMAEntry entry : entriesBase) {
            if (!entry.isMissing())
                continue;
            boolean changed = false;
            for (String m : entry.getMeasurementNames().toArray(new String[0])) {
                if (!TMASummaryEntry.isSurvivalColumn(m) && !Double.isNaN(entry.getMeasurementAsDouble(m))) {
                    entry.putMeasurement(m, null);
                    changed = true;
                }
            }
            if (changed)
                changes++;
        }
        if (changes == 0) {
            logger.info("No changes made when resetting scores for missing cores!");
            return;
        }
        logger.info("{} change(s) made when resetting scores for missing cores!", changes);
        table.refresh();
        updateSurvivalCurves();
        if (scatterPane != null)
            scatterPane.updateChart();
        if (histogramDisplay != null)
            histogramDisplay.refreshHistogram();
    });
    menuEdit.getItems().add(miResetMissingScores);
    MenuTools.addMenuItems(menuFile, miOpen, miSave, null, miImportClipboard, null, miImportFromImage, miImportFromProject);
    menuBar.getMenus().add(menuFile);
    menuEdit.getItems().add(miCopy);
    menuBar.getMenus().add(menuEdit);
    menuFile.setOnShowing(e -> {
        boolean imageDataAvailable = QuPathGUI.getInstance() != null && QuPathGUI.getInstance().getImageData() != null && QuPathGUI.getInstance().getImageData().getHierarchy().getTMAGrid() != null;
        miImportFromImage.setDisable(!imageDataAvailable);
        boolean projectAvailable = QuPathGUI.getInstance() != null && QuPathGUI.getInstance().getProject() != null && !QuPathGUI.getInstance().getProject().getImageList().isEmpty();
        miImportFromProject.setDisable(!projectAvailable);
    });
    // Double-clicking previously used for comments... but conflicts with tree table expansion
    // table.setOnMouseClicked(e -> {
    // if (!e.isPopupTrigger() && e.getClickCount() > 1)
    // promptForComment();
    // });
    table.setPlaceholder(new Text("Drag TMA data folder onto window, or choose File -> Open"));
    table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    BorderPane pane = new BorderPane();
    pane.setTop(menuBar);
    menuBar.useSystemMenuBarProperty().bindBidirectional(PathPrefs.useSystemMenubarProperty());
    // menuBar.setUseSystemMenuBar(true);
    // Create options
    ToolBar toolbar = new ToolBar();
    Label labelMeasurementMethod = new Label("Combination method");
    labelMeasurementMethod.setLabelFor(comboMeasurementMethod);
    labelMeasurementMethod.setTooltip(new Tooltip("Method whereby measurements for multiple cores with the same " + TMACoreObject.KEY_UNIQUE_ID + " will be combined"));
    CheckBox cbHidePane = new CheckBox("Hide pane");
    cbHidePane.setSelected(hidePaneProperty.get());
    cbHidePane.selectedProperty().bindBidirectional(hidePaneProperty);
    CheckBox cbGroupByID = new CheckBox("Group by ID");
    entriesBase.addListener((Change<? extends TMAEntry> event) -> {
        if (!event.getList().stream().anyMatch(e -> e.getMetadataValue(TMACoreObject.KEY_UNIQUE_ID) != null)) {
            cbGroupByID.setSelected(false);
            cbGroupByID.setDisable(true);
        } else {
            cbGroupByID.setDisable(false);
        }
    });
    cbGroupByID.setSelected(groupByIDProperty.get());
    cbGroupByID.selectedProperty().bindBidirectional(groupByIDProperty);
    CheckBox cbUseSelected = new CheckBox("Use selection only");
    cbUseSelected.selectedProperty().bindBidirectional(useSelectedProperty);
    CheckBox cbSkipMissing = new CheckBox("Hide missing cores");
    cbSkipMissing.selectedProperty().bindBidirectional(skipMissingCoresProperty);
    skipMissingCoresProperty.addListener((v, o, n) -> {
        table.refresh();
        updateSurvivalCurves();
        if (histogramDisplay != null)
            histogramDisplay.refreshHistogram();
        updateSurvivalCurves();
        if (scatterPane != null)
            scatterPane.updateChart();
    });
    toolbar.getItems().addAll(labelMeasurementMethod, comboMeasurementMethod, new Separator(Orientation.VERTICAL), cbHidePane, new Separator(Orientation.VERTICAL), cbGroupByID, new Separator(Orientation.VERTICAL), cbUseSelected, new Separator(Orientation.VERTICAL), cbSkipMissing);
    comboMeasurementMethod.getItems().addAll(TMAEntries.MeasurementCombinationMethod.values());
    comboMeasurementMethod.getSelectionModel().select(TMAEntries.MeasurementCombinationMethod.MEDIAN);
    selectedMeasurementCombinationProperty.addListener((v, o, n) -> table.refresh());
    ContextMenu popup = new ContextMenu();
    MenuItem miSetMissing = new MenuItem("Set missing");
    miSetMissing.setOnAction(e -> setSelectedMissingStatus(true));
    MenuItem miSetAvailable = new MenuItem("Set available");
    miSetAvailable.setOnAction(e -> setSelectedMissingStatus(false));
    MenuItem miExpand = new MenuItem("Expand all");
    miExpand.setOnAction(e -> {
        if (table.getRoot() == null)
            return;
        for (TreeItem<?> item : table.getRoot().getChildren()) {
            item.setExpanded(true);
        }
    });
    MenuItem miCollapse = new MenuItem("Collapse all");
    miCollapse.setOnAction(e -> {
        if (table.getRoot() == null)
            return;
        for (TreeItem<?> item : table.getRoot().getChildren()) {
            item.setExpanded(false);
        }
    });
    popup.getItems().addAll(miSetMissing, miSetAvailable, new SeparatorMenuItem(), miExpand, miCollapse);
    table.setContextMenu(popup);
    table.setRowFactory(e -> {
        TreeTableRow<TMAEntry> row = new TreeTableRow<>();
        // // Make rows invisible if they don't pass the predicate
        // row.visibleProperty().bind(Bindings.createBooleanBinding(() -> {
        // TMAEntry entry = row.getItem();
        // if (entry == null || (entry.isMissing() && skipMissingCoresProperty.get()))
        // return false;
        // return entries.getPredicate() == null || entries.getPredicate().test(entry);
        // },
        // skipMissingCoresProperty,
        // entries.predicateProperty()));
        // Style rows according to what they contain
        row.styleProperty().bind(Bindings.createStringBinding(() -> {
            if (row.isSelected())
                return "";
            TMAEntry entry = row.getItem();
            if (entry == null || entry instanceof TMASummaryEntry)
                return "";
            else if (entry.isMissing())
                return "-fx-background-color:rgb(225,225,232)";
            else
                return "-fx-background-color:rgb(240,240,245)";
        }, row.itemProperty(), row.selectedProperty()));
        // });
        return row;
    });
    BorderPane paneTable = new BorderPane();
    paneTable.setTop(toolbar);
    paneTable.setCenter(table);
    MasterDetailPane mdTablePane = new MasterDetailPane(Side.RIGHT, paneTable, createSidePane(), true);
    mdTablePane.showDetailNodeProperty().bind(Bindings.createBooleanBinding(() -> !hidePaneProperty.get() && !entriesBase.isEmpty(), hidePaneProperty, entriesBase));
    mdTablePane.setDividerPosition(2.0 / 3.0);
    pane.setCenter(mdTablePane);
    model.getItems().addListener(new ListChangeListener<TMAEntry>() {

        @Override
        public void onChanged(ListChangeListener.Change<? extends TMAEntry> c) {
            if (histogramDisplay != null)
                histogramDisplay.refreshHistogram();
            updateSurvivalCurves();
            if (scatterPane != null)
                scatterPane.updateChart();
        }
    });
    Label labelPredicate = new Label();
    labelPredicate.setPadding(new Insets(5, 5, 5, 5));
    labelPredicate.setAlignment(Pos.CENTER);
    // labelPredicate.setStyle("-fx-background-color: rgba(20, 120, 20, 0.15);");
    labelPredicate.setStyle("-fx-background-color: rgba(120, 20, 20, 0.15);");
    labelPredicate.textProperty().addListener((v, o, n) -> {
        if (n.trim().length() > 0)
            pane.setBottom(labelPredicate);
        else
            pane.setBottom(null);
    });
    labelPredicate.setMaxWidth(Double.MAX_VALUE);
    labelPredicate.setMaxHeight(labelPredicate.getPrefHeight());
    labelPredicate.setTextAlignment(TextAlignment.CENTER);
    predicateMeasurements.addListener((v, o, n) -> {
        if (n == null)
            labelPredicate.setText("");
        else if (n instanceof TablePredicate) {
            TablePredicate tp = (TablePredicate) n;
            if (tp.getOriginalCommand().trim().isEmpty())
                labelPredicate.setText("");
            else
                labelPredicate.setText("Predicate: " + tp.getOriginalCommand());
        } else
            labelPredicate.setText("Predicate: " + n.toString());
    });
    // predicate.set(new TablePredicate("\"Tumor\" > 100"));
    scene = new Scene(pane);
    scene.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
        KeyCode code = e.getCode();
        if ((code == KeyCode.SPACE || code == KeyCode.ENTER) && entrySelected != null) {
            promptForComment();
            return;
        }
    });
}
Also used : Arrays(java.util.Arrays) Change(javafx.collections.ListChangeListener.Change) ServerTools(qupath.lib.images.servers.ServerTools) ActionUtils(org.controlsfx.control.action.ActionUtils) HistogramDisplay(qupath.lib.gui.charts.HistogramDisplay) PathTableData(qupath.lib.gui.measure.PathTableData) MasterDetailPane(org.controlsfx.control.MasterDetailPane) ScrollPane(javafx.scene.control.ScrollPane) TabPane(javafx.scene.control.TabPane) ListChangeListener(javafx.collections.ListChangeListener) SpearmansCorrelation(org.apache.commons.math3.stat.correlation.SpearmansCorrelation) Map(java.util.Map) SimpleIntegerProperty(javafx.beans.property.SimpleIntegerProperty) ScriptException(javax.script.ScriptException) Set(java.util.Set) KeyEvent(javafx.scene.input.KeyEvent) Executors(java.util.concurrent.Executors) Platform(javafx.application.Platform) Separator(javafx.scene.control.Separator) BooleanProperty(javafx.beans.property.BooleanProperty) Project(qupath.lib.projects.Project) Clipboard(javafx.scene.input.Clipboard) ScrollBarPolicy(javafx.scene.control.ScrollPane.ScrollBarPolicy) CheckBoxTableCell(javafx.scene.control.cell.CheckBoxTableCell) SimpleDoubleProperty(javafx.beans.property.SimpleDoubleProperty) SummaryMeasurementTableCommand(qupath.lib.gui.commands.SummaryMeasurementTableCommand) ObservableList(javafx.collections.ObservableList) BorderPane(javafx.scene.layout.BorderPane) TMAObjectEntry(qupath.lib.gui.tma.TMAEntries.TMAObjectEntry) WeakChangeListener(javafx.beans.value.WeakChangeListener) TreeItem(javafx.scene.control.TreeItem) FXCollections(javafx.collections.FXCollections) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Bindings(javafx.beans.binding.Bindings) IntegerProperty(javafx.beans.property.IntegerProperty) ArrayList(java.util.ArrayList) MeasurementList(qupath.lib.measurements.MeasurementList) LinkedHashMap(java.util.LinkedHashMap) TabClosingPolicy(javafx.scene.control.TabPane.TabClosingPolicy) TextFields(org.controlsfx.control.textfield.TextFields) TreeTableView(javafx.scene.control.TreeTableView) TextAlignment(javafx.scene.text.TextAlignment) LinkedHashSet(java.util.LinkedHashSet) GridPane(javafx.scene.layout.GridPane) TitledPane(javafx.scene.control.TitledPane) ToolBar(javafx.scene.control.ToolBar) GeneralTools(qupath.lib.common.GeneralTools) Node(javafx.scene.Node) CheckBox(javafx.scene.control.CheckBox) IOException(java.io.IOException) ChartTools(qupath.lib.gui.charts.ChartTools) File(java.io.File) Menu(javafx.scene.control.Menu) DefaultTMAGrid(qupath.lib.objects.hierarchy.DefaultTMAGrid) KeyCodeCombination(javafx.scene.input.KeyCodeCombination) SelectionMode(javafx.scene.control.SelectionMode) TreeMap(java.util.TreeMap) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) Tab(javafx.scene.control.Tab) ObservableValue(javafx.beans.value.ObservableValue) TMAGrid(qupath.lib.objects.hierarchy.TMAGrid) PathPrefs(qupath.lib.gui.prefs.PathPrefs) PaneTools(qupath.lib.gui.tools.PaneTools) PathIO(qupath.lib.io.PathIO) Button(javafx.scene.control.Button) Pos(javafx.geometry.Pos) LoggerFactory(org.slf4j.LoggerFactory) Scanner(java.util.Scanner) XYChart(javafx.scene.chart.XYChart) VBox(javafx.scene.layout.VBox) Side(javafx.geometry.Side) KeyCombination(javafx.scene.input.KeyCombination) ObservableMeasurementTableData(qupath.lib.gui.measure.ObservableMeasurementTableData) ComboBox(javafx.scene.control.ComboBox) ContextMenu(javafx.scene.control.ContextMenu) TableView(javafx.scene.control.TableView) QuPathGUI(qupath.lib.gui.QuPathGUI) SortedList(javafx.collections.transformation.SortedList) Pane(javafx.scene.layout.Pane) Orientation(javafx.geometry.Orientation) TextField(javafx.scene.control.TextField) MenuItem(javafx.scene.control.MenuItem) BufferedImage(java.awt.image.BufferedImage) Predicate(java.util.function.Predicate) Collection(java.util.Collection) FilteredList(javafx.collections.transformation.FilteredList) Collectors(java.util.stream.Collectors) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) Text(javafx.scene.text.Text) SimpleBindings(javax.script.SimpleBindings) Priority(javafx.scene.layout.Priority) List(java.util.List) Entry(java.util.Map.Entry) Optional(java.util.Optional) NumberAxis(javafx.scene.chart.NumberAxis) 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) HashMap(java.util.HashMap) DoubleProperty(javafx.beans.property.DoubleProperty) TMAScoreImporter(qupath.lib.io.TMAScoreImporter) TreeTableRow(javafx.scene.control.TreeTableRow) TableColumn(javafx.scene.control.TableColumn) HashSet(java.util.HashSet) Dialogs(qupath.lib.gui.dialogs.Dialogs) ScatterChart(javafx.scene.chart.ScatterChart) Insets(javafx.geometry.Insets) Callback(javafx.util.Callback) Tooltip(javafx.scene.control.Tooltip) ExecutorService(java.util.concurrent.ExecutorService) ImageData(qupath.lib.images.ImageData) KeyCode(javafx.scene.input.KeyCode) ObjectProperty(javafx.beans.property.ObjectProperty) Logger(org.slf4j.Logger) Label(javafx.scene.control.Label) MenuBar(javafx.scene.control.MenuBar) CellDataFeatures(javafx.scene.control.TreeTableColumn.CellDataFeatures) ProjectImageEntry(qupath.lib.projects.ProjectImageEntry) ScriptEngineManager(javax.script.ScriptEngineManager) TMACoreObject(qupath.lib.objects.TMACoreObject) PearsonsCorrelation(org.apache.commons.math3.stat.correlation.PearsonsCorrelation) DropShadow(javafx.scene.effect.DropShadow) MenuTools(qupath.lib.gui.tools.MenuTools) ScriptContext(javax.script.ScriptContext) TMAEntry(qupath.lib.gui.tma.TMAEntries.TMAEntry) TreeTableColumn(javafx.scene.control.TreeTableColumn) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) Stage(javafx.stage.Stage) ScriptEngine(javax.script.ScriptEngine) ChangeListener(javafx.beans.value.ChangeListener) Collections(java.util.Collections) BorderPane(javafx.scene.layout.BorderPane) Insets(javafx.geometry.Insets) MasterDetailPane(org.controlsfx.control.MasterDetailPane) Label(javafx.scene.control.Label) MenuBar(javafx.scene.control.MenuBar) ContextMenu(javafx.scene.control.ContextMenu) ListChangeListener(javafx.collections.ListChangeListener) KeyCode(javafx.scene.input.KeyCode) Menu(javafx.scene.control.Menu) ContextMenu(javafx.scene.control.ContextMenu) TreeTableRow(javafx.scene.control.TreeTableRow) TMAEntry(qupath.lib.gui.tma.TMAEntries.TMAEntry) Tooltip(javafx.scene.control.Tooltip) MenuItem(javafx.scene.control.MenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) KeyCodeCombination(javafx.scene.input.KeyCodeCombination) Text(javafx.scene.text.Text) Change(javafx.collections.ListChangeListener.Change) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) Scene(javafx.scene.Scene) CheckBox(javafx.scene.control.CheckBox) ToolBar(javafx.scene.control.ToolBar) File(java.io.File) Separator(javafx.scene.control.Separator)

Aggregations

IOException (java.io.IOException)2 SimpleStringProperty (javafx.beans.property.SimpleStringProperty)2 Scene (javafx.scene.Scene)2 Button (javafx.scene.control.Button)2 ContextMenu (javafx.scene.control.ContextMenu)2 Label (javafx.scene.control.Label)2 Menu (javafx.scene.control.Menu)2 MenuBar (javafx.scene.control.MenuBar)2 MenuItem (javafx.scene.control.MenuItem)2 Tab (javafx.scene.control.Tab)2 TabPane (javafx.scene.control.TabPane)2 TableColumn (javafx.scene.control.TableColumn)2 BorderPane (javafx.scene.layout.BorderPane)2 MasterDetailPane (org.controlsfx.control.MasterDetailPane)2 BufferedImage (java.awt.image.BufferedImage)1 File (java.io.File)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Collection (java.util.Collection)1