Skip to content

Commit

Permalink
Highlight when model directory not set
Browse files Browse the repository at this point in the history
  • Loading branch information
petebankhead committed Sep 5, 2024
1 parent 68fe859 commit cb6de7a
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 33 deletions.
57 changes: 46 additions & 11 deletions src/main/java/qupath/ext/instanseg/ui/InstanSegController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
Expand Down Expand Up @@ -119,6 +120,8 @@ public class InstanSegController extends BorderPane {
private CheckBox makeMeasurementsCheckBox;
@FXML
private Button infoButton;
@FXML
private Label modelDirLabel;

private final ExecutorService pool = Executors.newSingleThreadExecutor(ThreadTools.createThreadFactory("instanseg", true));
private final QuPathGUI qupath;
Expand All @@ -127,6 +130,19 @@ public class InstanSegController extends BorderPane {

private final BooleanProperty needsUpdating = new SimpleBooleanProperty();

private static final ObjectBinding<Path> modelDirectoryProperty = Bindings.createObjectBinding(
() -> tryToGetPath(InstanSegPreferences.modelDirectoryProperty().get()),
InstanSegPreferences.modelDirectoryProperty()
);

private final BooleanBinding isModelDirectoryValid = Bindings.createBooleanBinding(
() -> {
var path = modelDirectoryProperty.get();
return path != null && Files.isDirectory(path);
},
modelDirectoryProperty
);

/**
* Create an instance of the InstanSeg GUI pane.
* @param qupath The QuPath GUI it should be attached to.
Expand All @@ -147,13 +163,24 @@ private InstanSegController(QuPathGUI qupath) throws IOException {
watcher = new Watcher(modelChoiceBox);

configureMessageLabel();
configureDirectoryLabel();
configureTileSizes();
configureDeviceChoices();
configureModelChoices();
configureSelectButtons();
configureRunning();
configureThreadSpinner();
BooleanBinding currentModelIsDownloaded = Bindings.createBooleanBinding(
BooleanBinding currentModelIsDownloaded = createModelDownloadedBinding();
infoButton.disableProperty().bind(currentModelIsDownloaded.not());
downloadButton.disableProperty().bind(
currentModelIsDownloaded.or(
modelChoiceBox.getSelectionModel().selectedItemProperty().isNull())
);
configureChannelPicker();
}

private BooleanBinding createModelDownloadedBinding() {
return Bindings.createBooleanBinding(
() -> {
var model = modelChoiceBox.getSelectionModel().getSelectedItem();
if (model == null) {
Expand All @@ -164,12 +191,6 @@ private InstanSegController(QuPathGUI qupath) throws IOException {
},
modelChoiceBox.getSelectionModel().selectedItemProperty(), needsUpdating,
InstanSegPreferences.modelDirectoryProperty());

infoButton.disableProperty().bind(currentModelIsDownloaded.not());
downloadButton.disableProperty().bind(
currentModelIsDownloaded.or(modelChoiceBox.getSelectionModel().selectedItemProperty().isNull())
);
configureChannelPicker();
}


Expand Down Expand Up @@ -374,8 +395,7 @@ private static Path tryToGetPath(String path) {
}

static Optional<Path> getModelDirectory() {
var path = InstanSegPreferences.modelDirectoryProperty().get();
return Optional.ofNullable(tryToGetPath(path));
return Optional.ofNullable(modelDirectoryProperty.get());
}

private void configureModelChoices() {
Expand Down Expand Up @@ -419,8 +439,8 @@ private void downloadModel() {
try {
var modelDir = getModelDirectory().orElse(null);
if (modelDir == null || !Files.exists(modelDir)) {
logger.warn("Can't download model {}, model directory not found",
modelChoiceBox.getSelectionModel().getSelectedItem());
Dialogs.showErrorMessage(resources.getString("title"),
resources.getString("ui.model-directory.choose-prompt"));
return;
}
var model = modelChoiceBox.getSelectionModel().getSelectedItem();
Expand Down Expand Up @@ -552,6 +572,21 @@ private void configureMessageLabel() {
});
}

private void configureDirectoryLabel() {
isModelDirectoryValid.addListener((v, o, n) -> updateModelDirectoryLabel());
updateModelDirectoryLabel();
}

private void updateModelDirectoryLabel() {
if (isModelDirectoryValid.get()) {
modelDirLabel.getStyleClass().setAll("standard-message");
modelDirLabel.setText(resources.getString("ui.options.directory"));
} else {
modelDirLabel.getStyleClass().setAll("warning-message");
modelDirLabel.setText(resources.getString("ui.options.directory-not-set"));
}
}

static void addModelsFromPath(Path path, ComboBox<InstanSegModel> box) {
if (path == null || !Files.exists(path) || !Files.isDirectory(path)) return;
// See https://github.com/controlsfx/controlsfx/issues/1320
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/qupath/ext/instanseg/ui/MessageTextHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
* Helper class for determining which text to display in the message label.
*/
class MessageTextHelper {

private static final ResourceBundle resources = ResourceBundle.getBundle("qupath.ext.instanseg.ui.strings");
private static final QuPathGUI qupath = QuPathGUI.getInstance();

private final QuPathGUI qupath = QuPathGUI.getInstance();
private final SelectedObjectCounter selectedObjectCounter;
private final SearchableComboBox<InstanSegModel> modelChoiceBox;
private final ChoiceBox<String> deviceChoiceBox;
Expand Down
56 changes: 36 additions & 20 deletions src/main/resources/qupath/ext/instanseg/ui/instanseg_control.fxml
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import org.controlsfx.control.*?>

<?import java.lang.String?>
<?import javafx.geometry.Insets?>
<fx:root type="BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="330" stylesheets="@instanseg.css" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1">
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.Spinner?>
<?import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import org.controlsfx.control.CheckComboBox?>
<?import org.controlsfx.control.SearchableComboBox?>
<?import org.controlsfx.control.SegmentedButton?>

<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="330" stylesheets="@instanseg.css" type="BorderPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1">
<center>
<VBox fx:id="vBox">
<TitledPane fx:id="pane1" styleClass="uncollapsible-titled-pane" animated="false" collapsible="false" prefHeight="262.0" prefWidth="330.0" text="%ui.processing.pane" VBox.vgrow="NEVER">
<TitledPane fx:id="pane1" animated="false" collapsible="false" prefHeight="262.0" prefWidth="330.0" styleClass="uncollapsible-titled-pane" text="%ui.processing.pane" VBox.vgrow="NEVER">
<VBox alignment="TOP_CENTER" styleClass="standard-spacing ">
<children>
<!-- **********************Models**********************-->
Expand Down Expand Up @@ -91,11 +107,11 @@
<!-- Device Selection-->
<HBox alignment="CENTER_RIGHT" styleClass="standard-spacing">
<padding>
<Insets left="10" right="10" top="10"/>
<Insets left="10" right="10" top="10" />
</padding>
<children>
<Label styleClass="regular" text="%ui.options.device" />
<Pane minWidth="5" HBox.hgrow="ALWAYS"/>
<Pane minWidth="5" HBox.hgrow="ALWAYS" />
<ChoiceBox fx:id="deviceChoices">
<tooltip><Tooltip text="%ui.options.device.tooltip" /></tooltip>
</ChoiceBox>
Expand All @@ -108,7 +124,7 @@
</padding>
<children>
<Label styleClass="regular" text="%ui.options.threads" />
<Pane minWidth="5" HBox.hgrow="ALWAYS"/>
<Pane minWidth="5" HBox.hgrow="ALWAYS" />
<Spinner fx:id="threadSpinner" prefWidth="75.0">
<tooltip>
<Tooltip text="%ui.options.threads.tooltip" />
Expand All @@ -125,7 +141,7 @@
</padding>
<children>
<Label styleClass="regular" text="%ui.options.nuclei-only" />
<Pane minWidth="5" HBox.hgrow="ALWAYS"/>
<Pane minWidth="5" HBox.hgrow="ALWAYS" />
<CheckBox fx:id="nucleiOnlyCheckBox">
<tooltip>
<Tooltip text="%ui.options.nuclei-only.tooltip" />
Expand All @@ -140,8 +156,8 @@
</padding>
<children>
<Label styleClass="regular" text="%ui.options.tilesize" />
<Pane minWidth="5" HBox.hgrow="ALWAYS"/>
<ChoiceBox prefWidth="75.0" fx:id="tileSizeChoiceBox">
<Pane minWidth="5" HBox.hgrow="ALWAYS" />
<ChoiceBox fx:id="tileSizeChoiceBox" prefWidth="75.0">
<tooltip>
<Tooltip text="%ui.options.tilesize.tooltip" />
</tooltip>
Expand All @@ -155,7 +171,7 @@
</padding>
<children>
<Label styleClass="regular" text="%ui.options.channel" />
<Pane minWidth="5" HBox.hgrow="ALWAYS"/>
<Pane minWidth="5" HBox.hgrow="ALWAYS" />
<CheckComboBox fx:id="comboChannels">
<tooltip>
<Tooltip text="%ui.options.channel.tooltip" />
Expand All @@ -165,12 +181,12 @@
</HBox>
<HBox alignment="CENTER_RIGHT" styleClass="standard-spacing">
<padding>
<Insets left="10" right="10" bottom="10"/>
<Insets bottom="10" left="10" right="10" />
</padding>
<children>
<Label text="%ui.options.makeMeasurements"/>
<Pane minWidth="5" HBox.hgrow="ALWAYS"/>
<CheckBox styleClass="regular" fx:id="makeMeasurementsCheckBox">
<Label text="%ui.options.makeMeasurements" />
<Pane minWidth="5" HBox.hgrow="ALWAYS" />
<CheckBox fx:id="makeMeasurementsCheckBox" styleClass="regular">
<tooltip>
<Tooltip text="%ui.options.makeMeasurements.tooltip" />
</tooltip>
Expand All @@ -185,7 +201,7 @@
<!-- Model Directory Selection-->
<VBox alignment="CENTER" styleClass="standard-vertical-spacing">
<children>
<Label onMouseClicked="#handleModelDirectoryLabelClick" styleClass="regular" text="%ui.options.directory" />
<Label fx:id="modelDirLabel" onMouseClicked="#handleModelDirectoryLabelClick" styleClass="regular" text="%ui.options.directory" />
<HBox styleClass="standard-spacing">
<children>
<TextField fx:id="tfModelDirectory" HBox.hgrow="ALWAYS">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,11 @@ ui.options.oneChannelSelected = 1 channel selected
ui.options.nChannelSelected = %d channels selected
ui.options.directory = Downloaded model directory
ui.options.directory.tooltip = Choose the directory where models should be stored
ui.options.directory-not-set = Please choose the model directory

# Model directories
ui.model-directory.choose-directory = Choose directory
ui.model-directory.choose-prompt = Please choose a folder to store models
ui.model-directory.choose-prompt = Please choose the directory to store InstanSeg models

## Other Windows
# Processing Window and progress pop-ups
Expand Down

0 comments on commit cb6de7a

Please sign in to comment.