Example usage for javafx.scene.text TextAlignment CENTER

List of usage examples for javafx.scene.text TextAlignment CENTER

Introduction

In this page you can find the example usage for javafx.scene.text TextAlignment CENTER.

Prototype

TextAlignment CENTER

To view the source code for javafx.scene.text TextAlignment CENTER.

Click Source Link

Document

Represents centered text alignment (ragged left and right).

Usage

From source file:org.sleuthkit.autopsy.timeline.ui.AbstractTimelineChart.java

/**
 * Add a Text Node to the specific label container for the decluttered axis
 * labels./*from  w w w.  j  a v  a  2  s  .  com*/
 *
 * @param labelText  The String to add.
 * @param labelWidth The width, in pixels, of the space available for the
 *                   text.
 * @param labelX     The horizontal position, in pixels, in the specificPane
 *                   of the text.
 * @param bold       True if the text should be bold, false otherwise.
 */
private synchronized void addSpecificLabel(String labelText, double labelWidth, double labelX, boolean bold) {
    Text label = new Text(" " + labelText + " "); //NON-NLS
    label.setTextAlignment(TextAlignment.CENTER);
    label.setFont(Font.font(null, bold ? FontWeight.BOLD : FontWeight.NORMAL, 10));
    //position label accounting for width
    label.relocate(labelX + labelWidth / 2 - label.getBoundsInLocal().getWidth() / 2, 0);
    label.autosize();

    if (specificLabelPane.getChildren().isEmpty()) {
        //just add first label
        specificLabelPane.getChildren().add(label);
    } else {
        //otherwise don't actually add the label if it would intersect with previous label

        final Node lastLabel = specificLabelPane.getChildren().get(specificLabelPane.getChildren().size() - 1);

        if (false == lastLabel.getBoundsInParent().intersects(label.getBoundsInParent())) {
            specificLabelPane.getChildren().add(label);
        }
    }
}

From source file:org.sleuthkit.autopsy.timeline.ui.AbstractTimelineChart.java

/**
 * Add a Label Node to the contextual label container for the decluttered
 * axis labels./*w  ww  .j  a  v a  2 s.  c o  m*/
 *
 * @param labelText  The String to add.
 * @param labelWidth The width, in pixels, of the space to use for the label
 * @param labelX     The horizontal position, in pixels, in the specificPane
 *                   of the text
 */
private synchronized void addContextLabel(String labelText, double labelWidth, double labelX) {
    Label label = new Label(labelText);
    label.setAlignment(Pos.CENTER);
    label.setTextAlignment(TextAlignment.CENTER);
    label.setFont(Font.font(10));
    //use a leading ellipse since that is the lowest frequency part,
    //and can be infered more easily from other surrounding labels
    label.setTextOverrun(OverrunStyle.LEADING_ELLIPSIS);
    //force size
    label.setMinWidth(labelWidth);
    label.setPrefWidth(labelWidth);
    label.setMaxWidth(labelWidth);
    label.relocate(labelX, 0);

    if (labelX == 0) { // first label has no border
        label.setBorder(null);
    } else { // subsequent labels have border on left to create dividers
        label.setBorder(ONLY_LEFT_BORDER);
    }

    contextLabelPane.getChildren().add(label);
}

From source file:org.sleuthkit.autopsy.timeline.ui.AbstractVisualization.java

/** add a {@link Text} node to the leaf container for the decluttered axis
 * labels/* w w w  . j a v a  2 s . c  o m*/
 *
 * @param labelText  the string to add
 * @param labelWidth the width of the space available for the text
 * @param labelX     the horizontal position in the partPane of the text
 * @param bold       true if the text should be bold, false otherwise
 */
private synchronized void assignLeafLabel(String labelText, double labelWidth, double labelX, boolean bold) {

    Text label = new Text(" " + labelText + " ");
    label.setTextAlignment(TextAlignment.CENTER);
    label.setFont(Font.font(null, bold ? FontWeight.BOLD : FontWeight.NORMAL, 10));
    //position label accounting for width
    label.relocate(labelX + labelWidth / 2 - label.getBoundsInLocal().getWidth() / 2, 0);
    label.autosize();

    if (leafPane.getChildren().isEmpty()) {
        //just add first label
        leafPane.getChildren().add(label);
    } else {
        //otherwise don't actually add the label if it would intersect with previous label
        final Text lastLabel = (Text) leafPane.getChildren().get(leafPane.getChildren().size() - 1);

        if (!lastLabel.getBoundsInParent().intersects(label.getBoundsInParent())) {
            leafPane.getChildren().add(label);
        }
    }
}

From source file:org.sleuthkit.autopsy.timeline.ui.AbstractVisualization.java

/** add a {@link Label} node to the branch container for the decluttered
 * axis labels/* w  w w  .  j a va  2s .co  m*/
 *
 * @param labelText  the string to add
 * @param labelWidth the width of the space to use for the label
 * @param labelX     the horizontal position in the partPane of the text
 */
private synchronized void assignBranchLabel(String labelText, double labelWidth, double labelX) {

    Label label = new Label(labelText);
    label.setAlignment(Pos.CENTER);
    label.setTextAlignment(TextAlignment.CENTER);
    label.setFont(Font.font(10));
    //use a leading ellipse since that is the lowest frequency part,
    //and can be infered more easily from other surrounding labels
    label.setTextOverrun(OverrunStyle.LEADING_ELLIPSIS);
    //force size
    label.setMinWidth(labelWidth);
    label.setPrefWidth(labelWidth);
    label.setMaxWidth(labelWidth);
    label.relocate(labelX, 0);

    if (labelX == 0) { // first label has no border
        label.setStyle("-fx-border-width: 0 0 0 0 ; -fx-border-color:black;"); // NON-NLS
    } else { // subsequent labels have border on left to create dividers
        label.setStyle("-fx-border-width: 0 0 0 1; -fx-border-color:black;"); // NON-NLS
    }

    branchPane.getChildren().add(label);
}

From source file:org.sleuthkit.autopsy.timeline.ui.AbstractVisualizationPane.java

/**
 * add a {@link Text} node to the leaf container for the decluttered axis
 * labels//from www .  j  ava 2 s. co m
 *
 * @param labelText  the string to add
 * @param labelWidth the width of the space available for the text
 * @param labelX     the horizontal position in the partPane of the text
 * @param bold       true if the text should be bold, false otherwise
 */
private synchronized void assignLeafLabel(String labelText, double labelWidth, double labelX, boolean bold) {

    Text label = new Text(" " + labelText + " "); //NOI18N
    label.setTextAlignment(TextAlignment.CENTER);
    label.setFont(Font.font(null, bold ? FontWeight.BOLD : FontWeight.NORMAL, 10));
    //position label accounting for width
    label.relocate(labelX + labelWidth / 2 - label.getBoundsInLocal().getWidth() / 2, 0);
    label.autosize();

    if (leafPane.getChildren().isEmpty()) {
        //just add first label
        leafPane.getChildren().add(label);
    } else {
        //otherwise don't actually add the label if it would intersect with previous label
        final Text lastLabel = (Text) leafPane.getChildren().get(leafPane.getChildren().size() - 1);

        if (!lastLabel.getBoundsInParent().intersects(label.getBoundsInParent())) {
            leafPane.getChildren().add(label);
        }
    }
}

From source file:org.sleuthkit.autopsy.timeline.ui.AbstractVisualizationPane.java

/**
 * add a {@link Label} node to the branch container for the decluttered axis
 * labels// w  w  w .  ja  va2  s  .  co  m
 *
 * @param labelText  the string to add
 * @param labelWidth the width of the space to use for the label
 * @param labelX     the horizontal position in the partPane of the text
 */
private synchronized void assignBranchLabel(String labelText, double labelWidth, double labelX) {

    Label label = new Label(labelText);
    label.setAlignment(Pos.CENTER);
    label.setTextAlignment(TextAlignment.CENTER);
    label.setFont(Font.font(10));
    //use a leading ellipse since that is the lowest frequency part,
    //and can be infered more easily from other surrounding labels
    label.setTextOverrun(OverrunStyle.LEADING_ELLIPSIS);
    //force size
    label.setMinWidth(labelWidth);
    label.setPrefWidth(labelWidth);
    label.setMaxWidth(labelWidth);
    label.relocate(labelX, 0);

    if (labelX == 0) { // first label has no border
        label.setStyle("-fx-border-width: 0 0 0 0 ; -fx-border-color:black;"); // NON-NLS //NOI18N
    } else { // subsequent labels have border on left to create dividers
        label.setStyle("-fx-border-width: 0 0 0 1; -fx-border-color:black;"); // NON-NLS //NOI18N
    }

    branchPane.getChildren().add(label);
}

From source file:photobooth.views.EmailPane.java

private void addLabel() {
    String text = Global.getPhrase("email_pane_text");
    Label label = new Label(text);
    label.setWrapText(true);/*www  .jav  a  2 s  .c o  m*/
    label.setLayoutX(50);
    label.setLayoutY(150);
    label.setMaxWidth(700);
    label.setTextAlignment(TextAlignment.CENTER);
    label.setFont(new Font(40));
    label.setTextFill(Color.web("#000"));
    this.getChildren().add(label);
}

From source file:qupath.lib.gui.panels.classify.RandomTrainingRegionSelector.java

private void createDialog() {
    dialog = new Stage();
    dialog.initOwner(qupath.getStage());
    dialog.setTitle("Training sample selector");

    pointCreator = new RandomPointCreator();

    for (PathClass pathClass : pathClassListModel) {
        if (pathClass != null && pathClass.getName() != null)
            pointCreator.addPathClass(pathClass,
                    KeyCode.getKeyCode(pathClass.getName().toUpperCase().substring(0, 1)));
        //            pointCreator.addPathClass(pathClass, KeyStroke.getKeyStroke(new pathClass.getName().toLowerCase().charAt(0), 0).getKeyCode());
    }//  ww  w.  ja  v  a 2 s .co m
    //      PathClass tumourClass = PathClassFactory.getDefaultPathClass(PathClasses.TUMOR);
    //      PathClass stromaClass = PathClassFactory.getDefaultPathClass(PathClasses.STROMA);
    //      pointCreator.addPathClass(tumourClass, KeyCode.T);
    //      pointCreator.addPathClass(stromaClass, KeyCode.S);
    QuPathViewer viewer = qupath.getViewer();
    pointCreator.registerViewer(viewer);

    // Adapt to changing active viewers
    ImageDataChangeListener<BufferedImage> listener = new ImageDataChangeListener<BufferedImage>() {

        @Override
        public void imageDataChanged(ImageDataWrapper<BufferedImage> source,
                ImageData<BufferedImage> imageDataOld, ImageData<BufferedImage> imageDataNew) {
            if (pointCreator != null) {
                QuPathViewer viewer = qupath.getViewer();
                pointCreator.registerViewer(viewer);
                updateObjectCache(viewer);
            }
            refreshList();
            updateLabel();
        }

    };
    qupath.addImageDataChangeListener(listener);

    // Remove listeners for cleanup
    dialog.setOnCloseRequest(e -> {
        pointCreator.deregisterViewer();
        qupath.removeImageDataChangeListener(listener);
        dialog.setOnCloseRequest(null);
        dialog = null;
        // Re-enable mode switching
        qupath.setModeSwitchingEnabled(true);
    });

    ParameterPanelFX paramPanel = new ParameterPanelFX(params);
    paramPanel.getPane().setPadding(new Insets(2, 5, 5, 5));

    list = new ListView<PathClass>(pathClassListModel);
    list.setPrefSize(400, 200);

    // TODO: ADD A SENSIBLE RENDERER!
    // For now, this is simply duplicated from PathAnnotationPanel
    list.setCellFactory(new Callback<ListView<PathClass>, ListCell<PathClass>>() {

        @Override
        public ListCell<PathClass> call(ListView<PathClass> p) {

            ListCell<PathClass> cell = new ListCell<PathClass>() {

                @Override
                protected void updateItem(PathClass value, boolean bln) {
                    super.updateItem(value, bln);
                    int size = 10;
                    if (value == null) {
                        setText(null);
                        setGraphic(null);
                    } else if (value.getName() == null) {
                        setText("None");
                        setGraphic(new Rectangle(size, size, ColorToolsFX.getCachedColor(0, 0, 0, 0)));
                    } else {
                        setText(value.getName());
                        setGraphic(new Rectangle(size, size, ColorToolsFX.getPathClassColor(value)));
                    }
                }

            };

            return cell;
        }
    });

    //      list.setCellRenderer(new PathClassListCellRendererPoints());

    list.setTooltip(new Tooltip("Available classes"));

    labelCount = new Label();
    labelCount.setTextAlignment(TextAlignment.CENTER);
    labelCount.setPadding(new Insets(5, 0, 5, 0));
    BorderPane panelTop = new BorderPane();
    panelTop.setTop(paramPanel.getPane());
    panelTop.setCenter(list);
    panelTop.setBottom(labelCount);
    labelCount.prefWidthProperty().bind(panelTop.widthProperty());
    updateLabel();

    //      panelButtons.add(new JButton(new UndoAction("Undo")));
    Action actionAdd = new Action("Add to class", e -> {
        if (list == null || pointCreator == null)
            return;
        PathClass pathClass = list.getSelectionModel().getSelectedItem();
        pointCreator.addPoint(pathClass);
    });
    Action actionSkip = new Action("Skip", e -> {
        if (pointCreator != null)
            pointCreator.addPoint(null);
    });

    GridPane panelButtons = PanelToolsFX.createColumnGridControls(ActionUtils.createButton(actionAdd),
            ActionUtils.createButton(actionSkip));

    BorderPane pane = new BorderPane();
    pane.setCenter(panelTop);
    pane.setBottom(panelButtons);

    pane.setPadding(new Insets(10, 10, 10, 10));
    Scene scene = new Scene(pane);
    dialog.setScene(scene);
}

From source file:qupath.lib.gui.panels.classify.RandomTrainingRegionSelector.java

void updateLabel() {
    if (labelCount == null)
        return;/* www  . j a  v a 2  s.co  m*/
    int n = 0;
    for (PathClass pathClass : pathClassListModel) {
        if (pathClass != null)
            n += pointCreator.objectCache.getPointsPerClass(pathClass);
    }
    labelCount.setTextAlignment(TextAlignment.CENTER);
    labelCount.setText("Total count: " + n);
}

From source file:qupath.lib.gui.tma.TMASummaryViewer.java

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 -> {/* ww  w. jav a2 s  .  c  o m*/
        File file = QuPathGUI.getDialogHelper(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) {
            DisplayHelpers.showErrorMessage("Import scores", "Clipboard is empty!");
            return;
        }
        int n = importScores(text);
        if (n > 0) {
            setTMAEntries(new ArrayList<>(entriesBase));
        }
        DisplayHelpers.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);

    QuPathGUI.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.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(MeasurementCombinationMethod.values());
    comboMeasurementMethod.getSelectionModel().select(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()));
        //         row.itemProperty().addListener((v, o, n) -> {
        //            if (n == null || n instanceof TMASummaryEntry || row.isSelected())
        //               row.setStyle("");
        //            else if (n.isMissing())
        //               row.setStyle("-fx-background-color:rgb(225,225,232)");            
        //            else
        //               row.setStyle("-fx-background-color:rgb(240,240,245)");            
        //         });
        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.getEntries().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;
        }
    });

}