From 4a7adeaa55a953f850e6681b200ace5d96e67996 Mon Sep 17 00:00:00 2001 From: Ric Emery Date: Wed, 13 Jul 2022 21:33:11 -0700 Subject: [PATCH] Add ability to include custom javafx node within choosers. Refs #18. Rename initialFilenameProperty to filenameProperty. Refs #19. Update dependencies. --- pom.xml | 10 +-- .../filechooser/DirectoryChooserFx.java | 11 +++ .../filechooser/DirectoryChooserFxImpl.java | 10 ++- .../filechooser/FileChooserFx.java | 27 ++++++- .../filechooser/FileChooserFxImpl.java | 56 +++++++++----- .../filechooser/FileChooserDemo.java | 73 +++++++++++++++---- 6 files changed, 146 insertions(+), 41 deletions(-) diff --git a/pom.xml b/pom.xml index 613ac2e..b972371 100644 --- a/pom.xml +++ b/pom.xml @@ -15,8 +15,8 @@ UTF-8 - 5.7.0 - 1.7.0 + 5.8.2 + 1.8.2 @@ -36,12 +36,12 @@ commons-io commons-io - 2.8.0 + 2.11.0 org.apache.commons commons-lang3 - 3.11 + 3.12.0 org.controlsfx @@ -70,7 +70,7 @@ org.assertj assertj-core - 3.19.0 + 3.23.1 test diff --git a/src/main/java/com/chainstaysoftware/filechooser/DirectoryChooserFx.java b/src/main/java/com/chainstaysoftware/filechooser/DirectoryChooserFx.java index 8f16113..b1dcfa3 100644 --- a/src/main/java/com/chainstaysoftware/filechooser/DirectoryChooserFx.java +++ b/src/main/java/com/chainstaysoftware/filechooser/DirectoryChooserFx.java @@ -5,6 +5,7 @@ import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.StringProperty; import javafx.collections.ObservableList; +import javafx.scene.Node; import javafx.stage.Window; import java.io.File; @@ -144,5 +145,15 @@ public interface DirectoryChooserFx { */ void setHelpCallback(HelpCallback helpCallback); + /** + * Show the directory chooser dialog. + */ void showDialog(Window ownerWindow, FileChooserCallback fileChooserCallback); + + /** + * Show the directory chooser dialog with user content {@link Node} placed just above + * the bottom row of dialog buttons. + */ + void showDialog(Window ownerWindow, Node userContent, FileChooserCallback fileChooserCallback); + } diff --git a/src/main/java/com/chainstaysoftware/filechooser/DirectoryChooserFxImpl.java b/src/main/java/com/chainstaysoftware/filechooser/DirectoryChooserFxImpl.java index 4b1e052..ba0ef6b 100644 --- a/src/main/java/com/chainstaysoftware/filechooser/DirectoryChooserFxImpl.java +++ b/src/main/java/com/chainstaysoftware/filechooser/DirectoryChooserFxImpl.java @@ -5,6 +5,7 @@ import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.StringProperty; import javafx.collections.ObservableList; +import javafx.scene.Node; import javafx.stage.Window; import java.io.File; @@ -242,6 +243,13 @@ public void setHelpCallback(final HelpCallback helpCallback) { @Override public void showDialog(final Window ownerWindow, final FileChooserCallback fileChooserCallback) { - fileChooser.showOpenDialog(ownerWindow, fileChooserCallback, true); + showDialog(ownerWindow, null, fileChooserCallback); + } + + @Override + public void showDialog(final Window ownerWindow, + final Node userContent, + final FileChooserCallback fileChooserCallback) { + fileChooser.showOpenDialog(ownerWindow, userContent, fileChooserCallback, true); } } diff --git a/src/main/java/com/chainstaysoftware/filechooser/FileChooserFx.java b/src/main/java/com/chainstaysoftware/filechooser/FileChooserFx.java index 4109be4..3e6d955 100644 --- a/src/main/java/com/chainstaysoftware/filechooser/FileChooserFx.java +++ b/src/main/java/com/chainstaysoftware/filechooser/FileChooserFx.java @@ -8,6 +8,7 @@ import javafx.beans.property.StringProperty; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; +import javafx.scene.Node; import javafx.stage.FileChooser; import javafx.stage.Window; @@ -80,11 +81,11 @@ public interface FileChooserFx { ObjectProperty initialDirectoryProperty(); - void setInitialFileName(String value); + void setFileName(String value); - String getInitialFileName(); + String getFileName(); - ObjectProperty initialFileNameProperty(); + ObjectProperty fileNameProperty(); void setTitle(String value); @@ -189,7 +190,27 @@ public interface FileChooserFx { */ void setIcons(Icons icons); + /** + * Show the file open dialog. + */ void showOpenDialog(Window ownerWindow, FileChooserCallback fileChooserCallback); + /** + * Show the file open dialog with user content {@link Node} placed just above + * the bottom row of dialog buttons. + */ + void showOpenDialog(Window ownerWindow, Node userContent, + FileChooserCallback fileChooserCallback); + + /** + * Show the file save dialog. + */ void showSaveDialog(Window ownerWindow, FileChooserCallback fileChooserCallback); + + /** + * Show the file save dialog with user content {@link Node} placed just above + * the bottom row of dialog buttons. + */ + void showSaveDialog(Window ownerWindow, Node userContent, + FileChooserCallback fileChooserCallback); } diff --git a/src/main/java/com/chainstaysoftware/filechooser/FileChooserFxImpl.java b/src/main/java/com/chainstaysoftware/filechooser/FileChooserFxImpl.java index 4297521..587d193 100644 --- a/src/main/java/com/chainstaysoftware/filechooser/FileChooserFxImpl.java +++ b/src/main/java/com/chainstaysoftware/filechooser/FileChooserFxImpl.java @@ -97,7 +97,7 @@ public final class FileChooserFxImpl implements FileChooserFx { private double previewDivider = PREVIEW_DIVIDER_POSITION; private StringProperty title; private ObjectProperty initialDirectory; - private ObjectProperty initialFileName; + private ObjectProperty fileName; private ObjectProperty selectedExtensionFilter; private ObjectProperty viewTypeProperty; private BooleanProperty showHiddenFiles; @@ -262,23 +262,23 @@ public ObjectProperty initialDirectoryProperty() { } @Override - public void setInitialFileName(final String value) { - initialFileNameProperty().set(value); + public void setFileName(final String value) { + fileNameProperty().set(value); } @Override - public String getInitialFileName() { - return (initialFileName != null) ? initialFileName.get() : null; + public String getFileName() { + return (fileName != null) ? fileName.get() : null; } @Override - public ObjectProperty initialFileNameProperty() { - if (initialFileName == null) { - initialFileName = + public ObjectProperty fileNameProperty() { + if (fileName == null) { + fileName = new SimpleObjectProperty<>(this, "initialFileName"); } - return initialFileName; + return fileName; } @Override @@ -488,27 +488,43 @@ public void setIcons(final Icons icons) { @Override public void showOpenDialog(final Window ownerWindow, final FileChooserCallback fileChooserCallback) { + showOpenDialog(ownerWindow, null, fileChooserCallback); + } + + @Override + public void showOpenDialog(final Window ownerWindow, + final Node userContent, + final FileChooserCallback fileChooserCallback) { saveMode = false; - showOpenDialog(ownerWindow, fileChooserCallback, false); + showOpenDialog(ownerWindow, userContent, fileChooserCallback, false); } void showOpenDialog(final Window ownerWindow, + final Node userContent, final FileChooserCallback fileChooserCallback, final boolean hideFiles) { saveMode = false; this.hideFiles.setValue(hideFiles); - showDialog(ownerWindow, fileChooserCallback); + showDialog(ownerWindow, userContent, fileChooserCallback); } @Override public void showSaveDialog(final Window ownerWindow, final FileChooserCallback fileChooserCallback) { + showSaveDialog(ownerWindow, null, fileChooserCallback); + } + + @Override + public void showSaveDialog(final Window ownerWindow, + final Node userContent, + final FileChooserCallback fileChooserCallback) { saveMode = true; hideFiles.set(false); - showDialog(ownerWindow, fileChooserCallback); + showDialog(ownerWindow, userContent, fileChooserCallback); } private void showDialog(final Window ownerWindow, + final Node userContent, final FileChooserCallback fileChooserCallback) { this.fileChooserCallback = fileChooserCallback; @@ -516,7 +532,7 @@ private void showDialog(final Window ownerWindow, final VBox topVbox = createTopVBox(); splitPane = createSplitPane(); - final VBox bottomVbox = createBottomVBox(); + final VBox bottomVbox = createBottomVBox(userContent); final BorderPane borderPane = new BorderPane(); borderPane.setTop(topVbox); @@ -626,11 +642,15 @@ private VBox createTopVBox() { /** * Create a VBox to hold the bottom buttons and file extensions dropdown. */ - private VBox createBottomVBox() { + private VBox createBottomVBox(final Node userContent) { final ButtonBar buttonBar = createButtonBar(); final Pane extensionsPane = createExtensionsPane(); final VBox vBox = new VBox(); - vBox.getChildren().addAll(extensionsPane, buttonBar); + if (userContent == null) { + vBox.getChildren().addAll(extensionsPane, buttonBar); + } else { + vBox.getChildren().addAll(extensionsPane, userContent, buttonBar); + } return vBox; } @@ -640,9 +660,11 @@ private Node createFileNameBar() { fileNameField = new TextField(); fileNameField.setId("nameField"); - fileNameField.setText(getInitialFileName()); + fileNameField.setText(getFileName()); fileNameField.setPrefWidth(400); + fileNameField.textProperty().bindBidirectional(fileNameProperty()); + currentSelection.addListener((observable, oldValue, newValue) -> { if (newValue != null && newValue.isFile()) { fileNameField.setText(newValue.getName()); @@ -848,7 +870,7 @@ private Button createDoneButton() { final Button button = new Button(text); ButtonBar.setButtonData(button, ButtonBar.ButtonData.OK_DONE); button.setId("doneButton"); - button.setDisable(!saveMode || getInitialFileName() == null); + button.setDisable(!saveMode || getFileName() == null); button.setOnAction(saveMode ? new SaveDoneEventHandler() : new BrowseDoneEventHandler()); if (saveMode) { diff --git a/src/test/java/com/chainstaysoftware/filechooser/FileChooserDemo.java b/src/test/java/com/chainstaysoftware/filechooser/FileChooserDemo.java index 77042de..f474422 100644 --- a/src/test/java/com/chainstaysoftware/filechooser/FileChooserDemo.java +++ b/src/test/java/com/chainstaysoftware/filechooser/FileChooserDemo.java @@ -4,10 +4,12 @@ import com.chainstaysoftware.filechooser.preview.ImagePreviewPane; import com.chainstaysoftware.filechooser.preview.PreviewPane; import javafx.application.Application; +import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ToolBar; import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; import javafx.scene.text.Text; import javafx.scene.text.TextFlow; import javafx.stage.FileChooser; @@ -15,10 +17,11 @@ import java.util.Arrays; import java.util.HashMap; +import java.util.Map; public class FileChooserDemo extends Application { @Override - public void start(Stage primaryStage) throws Exception { + public void start(Stage primaryStage) { final HashMap> previewHandlers = new HashMap<>(); previewHandlers.put("image/png", ImagePreviewPane.class); previewHandlers.put("image/jpg", ImagePreviewPane.class); @@ -26,6 +29,31 @@ public void start(Stage primaryStage) throws Exception { final TextFlow textFlow = new TextFlow(); + final Button fileChooserButton = createFileChooserButton(primaryStage, previewHandlers, textFlow); + final Button fileSaveButton = createFileSaveButton(primaryStage, previewHandlers, textFlow, null); + + final Button userButton = new Button("User action"); + final HBox userHbox = new HBox(userButton); + final Button fileSaveWithUserButton + = createFileSaveButton(primaryStage, previewHandlers, textFlow, userHbox); + + final Button dirChooserButton = createDirChooserButton(primaryStage, textFlow); + + final ToolBar toolBar = new ToolBar(); + toolBar.getItems().addAll(fileChooserButton, fileSaveButton, + fileSaveWithUserButton, dirChooserButton); + + final BorderPane borderPane = new BorderPane(); + borderPane.setTop(toolBar); + borderPane.setCenter(textFlow); + + primaryStage.setScene(new Scene(borderPane, 800, 600)); + primaryStage.show(); + } + + private Button createFileChooserButton(final Stage primaryStage, + final Map> previewHandlers, + final TextFlow textFlow) { final Button fileChooserButton = new Button("Choose File"); fileChooserButton.setOnAction(event -> { final FileChooserFx fileChooser = new FileChooserFxImpl(); @@ -55,21 +83,45 @@ public void start(Stage primaryStage) throws Exception { + "Window size - " + fileChooser.getWidth() + " " + fileChooser.getHeight() + "\r\n" + "Divider positions - " + Arrays.toString(fileChooser.getDividerPositions()) + "\r\n"))); }); + return fileChooserButton; + } + + private Button createFileSaveButton(final Stage primaryStage, + final Map> previewHandlers, + final TextFlow textFlow, + final Node userContent) { + final Button fileSaveButton = new Button(); + if (userContent == null) { + fileSaveButton.setText("Save File"); + } else { + fileSaveButton.setText("Save File with user content"); + } - final Button fileSaveButton = new Button("Save File"); fileSaveButton.setOnAction(event -> { final FileChooserFx fileChooser = new FileChooserFxImpl(); - fileChooser.setTitle("File Save"); fileChooser.setShowHiddenFiles(false); fileChooser.getPreviewHandlers().putAll(previewHandlers); fileChooser.setHelpCallback(() -> System.out.println("Help invoked")); //fileChooser.setInitialFileName("foo.txt"); - fileChooser.showSaveDialog(primaryStage, + if (userContent == null) { + fileChooser.setTitle("File Save"); + fileChooser.showSaveDialog(primaryStage, fileOptional -> textFlow.getChildren() - .add(new Text("File to save - " + fileOptional.toString() + "\r\n"))); + .add(new Text("File to save - " + fileOptional.toString() + "\r\n"))); + } else { + fileChooser.setTitle("File Save with user content"); + fileChooser.showSaveDialog(primaryStage, + userContent, + fileOptional -> textFlow.getChildren() + .add(new Text("File to save - " + fileOptional.toString() + "\r\n"))); + } }); + return fileSaveButton; + } + private Button createDirChooserButton(final Stage primaryStage, + final TextFlow textFlow) { final Button dirChooserButton = new Button("Choose Directory"); dirChooserButton.setOnAction(event -> { final DirectoryChooserFx dirChooser = new DirectoryChooserFxImpl(); @@ -86,16 +138,7 @@ public void start(Stage primaryStage) throws Exception { + "Window size - " + dirChooser.getWidth() + " " + dirChooser.getHeight() + "\r\n" + "Divider position - " + dirChooser.getDividerPosition() + "\r\n"))); }); - - final ToolBar toolBar = new ToolBar(); - toolBar.getItems().addAll(fileChooserButton, fileSaveButton, dirChooserButton); - - final BorderPane borderPane = new BorderPane(); - borderPane.setTop(toolBar); - borderPane.setCenter(textFlow); - - primaryStage.setScene(new Scene(borderPane, 800, 600)); - primaryStage.show(); + return dirChooserButton; } public static void main(String[] args) {