Skip to content

Commit

Permalink
Added DirectoryOpenPicker to the jpro-file module. This allows the us…
Browse files Browse the repository at this point in the history
…er to select a directory instead of a file.
  • Loading branch information
FlorianKirmaier committed Feb 4, 2025
1 parent 9cd4a27 commit c689ee4
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
### 0.5.2-SNAPSHOT (TBD)
#### Features
* Added DirectoryOpenPicker to the jpro-file module. This allows the user to select a directory instead of a file.

#### Bufixes
* Fixed issue, with jpro-file. Drag&Drop file extensions are now handled case-insensitive, like in the rest of jpro-file.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import one.jpro.platform.file.ExtensionFilter;
import one.jpro.platform.file.FileSource;
import one.jpro.platform.file.dropper.FileDropper;
import one.jpro.platform.file.picker.DirectoryOpenPicker;
import one.jpro.platform.file.picker.FileOpenPicker;
import one.jpro.platform.file.picker.FileSavePicker;
import org.apache.commons.io.FilenameUtils;
Expand Down Expand Up @@ -88,6 +89,7 @@ public Parent createRoot(Stage stage) {

FileDropper fileDropper = FileDropper.create(contentPane);
fileDropper.setExtensionFilter(SUBTITLE_EXTENSION_FILTER);
// Nah?
fileDropper.setOnDragEntered(event -> {
dropPane.pseudoClassStateChanged(FILES_DRAG_OVER_PSEUDO_CLASS, true);
contentPane.getChildren().setAll(textArea, dropPane);
Expand Down Expand Up @@ -115,9 +117,18 @@ public Parent createRoot(Stage stage) {
contentPane.getChildren().setAll(textArea);
});

Button openDirectory = new Button("Open Directory", new FontIcon(Material2AL.FOLDER_OPEN));
DirectoryOpenPicker directoryOpenPicker = DirectoryOpenPicker.create(openDirectory);
directoryOpenPicker.setOnFilesSelected(fileSources -> {
fileSources.stream().findFirst().ifPresent(fileSource -> {
// Note: We only test whether choosing a directory works
System.out.println("Chosen directory: " + fileSource.uploadFileAsync().join().getAbsolutePath());
});
});

Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
HBox controlsBox = new HBox(newButton, openButton, spacer);
HBox controlsBox = new HBox(newButton, openButton, openDirectory, spacer);
controlsBox.getStyleClass().add("controls-box");

final Button saveAsButton;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package one.jpro.platform.file.picker;

import javafx.scene.Node;

/**
* This is an abstract class that implements the {@link DirectoryOpenPicker} interface.
* It provides a base implementation for common functionality used by native implementation.
*
* @author Florian Kirmaier
*/
abstract class BaseDirectoryOpenPicker extends BaseFileOpenPicker implements DirectoryOpenPicker {
/**
* {@inheritDoc}
*/
BaseDirectoryOpenPicker(Node node) {
super(node);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package one.jpro.platform.file.picker;

import com.jpro.webapi.WebAPI;
import javafx.scene.Node;
import one.jpro.platform.file.MultipleFileSelector;

import java.util.Objects;

/**
* {@link FilePicker} interface extension for file open operations.
*
* @author Florian Kirmaier
*/
public interface DirectoryOpenPicker extends FileOpenPicker {

/**
* Creates a file picker.
* It only works in desktop applications.
*
* @param node the associated node for this file picker
* @return a {@link DirectoryOpenPicker} object.
* @throws NullPointerException if the node is null
*/
static DirectoryOpenPicker create(Node node) {
Objects.requireNonNull(node, "node must not be null");
if (WebAPI.isBrowser()) {
throw new UnsupportedOperationException("DirectoryOpenPicker is not supported in the browser");
}
return new NativeDirectoryOpenPicker(node);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package one.jpro.platform.file.picker;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Node;
import javafx.scene.control.SelectionMode;
import javafx.scene.input.MouseEvent;
import javafx.stage.DirectoryChooser;
import javafx.stage.Window;
import one.jpro.platform.file.FileSource;
import one.jpro.platform.file.NativeFileSource;
import one.jpro.platform.file.util.NodeUtils;

import java.io.File;
import java.util.List;
import java.util.function.Consumer;

/**
* Represents a {@link DirectoryOpenPicker} implementation for JavaFX desktop/mobile
* applications. This class specializes for selecting and opening directories from
* the native file system.
*
* @author Florian Kirmaier
*/
public class NativeDirectoryOpenPicker extends BaseDirectoryOpenPicker {

private final DirectoryChooser fileChooser = new DirectoryChooser();
private List<NativeFileSource> nativeFileSources = List.of();


/**
* Initializes a new instance associated with the specified node.
*
* @param node The node associated with this file picker.
*/
public NativeDirectoryOpenPicker(Node node) {
super(node);

// Define the action that should be performed when the user clicks on the node.
NodeUtils.addEventHandler(node, MouseEvent.MOUSE_CLICKED, actionEvent -> {
Window window = node.getScene().getWindow();
final File file = fileChooser.showDialog(window);
if (file != null) {
// Create a list of native file sources from the selected file.
nativeFileSources = List.of(new NativeFileSource(file));

// Invoke the onFilesSelected consumer.
Consumer<List<? extends FileSource>> onFilesSelectedConsumer = getOnFilesSelected();
if (onFilesSelectedConsumer != null) {
onFilesSelectedConsumer.accept(nativeFileSources);
}
}
});
}

@Override
public final String getTitle() {
return fileChooser.getTitle();
}

@Override
public final void setTitle(final String value) {
fileChooser.setTitle(value);
}

@Override
public final StringProperty titleProperty() {
return fileChooser.titleProperty();
}

@Override
public final StringProperty initialFileNameProperty() {
if (initialFileName == null) {
initialFileName = new SimpleStringProperty(this, "initialFileName");
}
return initialFileName;
}

@Override
public final File getInitialDirectory() {
return fileChooser.getInitialDirectory();
}

@Override
public final void setInitialDirectory(final File value) {
fileChooser.setInitialDirectory(value);
}

@Override
public final ObjectProperty<File> initialDirectoryProperty() {
return fileChooser.initialDirectoryProperty();
}

@Override
public final ObjectProperty<SelectionMode> selectionModeProperty() {
if (selectionMode == null) {
selectionMode = new SimpleObjectProperty<>(this, "selectionMode", SelectionMode.SINGLE);
}
return selectionMode;
}
}

0 comments on commit c689ee4

Please sign in to comment.