All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.raumzeitfalle.fx.filechooser.SwingFileChooser Maven / Gradle / Ivy

The newest version!
/*-
 * #%L
 * FXFileChooser
 * %%
 * Copyright (C) 2017 - 2019 Oliver Loeffler, Raumzeitfalle.net
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package net.raumzeitfalle.fx.filechooser;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import javax.swing.JDialog;
import javax.swing.JOptionPane;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import net.raumzeitfalle.fx.dirchooser.DirectoryChooser;
import net.raumzeitfalle.fx.filechooser.locations.Location;

/*
 * TODO: Review usage schema  and assign proper mouse and keyboard actions
 * TODO: Rework demos and show new way to select directories
 * TODO: Add a transition for the scene change between file chooser and dir chooser.
 */
public class SwingFileChooser extends JFXPanel implements HideableView {

    private static final String CHOOSE_FILE_DIALOG_TITLE = "Choose file:";

    public static void setUseJavaFxDirectoryChooser(boolean toggle) {
        SwingFileChooserProperties.setUseJavaFXDirectoryChooser(toggle);
    }

    private static final long serialVersionUID = -5879082370711306802L;

    /**
     * Return value if cancel is chosen.
     */
    public static final int CANCEL_OPTION = 1;

    /**
     * Return value if approve (yes, ok) is chosen.
     */
    public static final int APPROVE_OPTION = 0;

    /**
     * Creates a new {@link FileChooser} within a Swing {@link JDialog} window. File browsing will start
     * in current working directory.
     * 
     * @param skin   {@link Skin} Defines the visual appearance of FileChooser. Defaults to dark skin.
     * @param filter {@link PathFilter} argument of variable length, accepts all path filters as needed.
     *               In case no filter is provided, a filter accepting all files will be used.
     * @return A configured {@link SwingFileChooser}.
     */
    public static SwingFileChooser create(Skin skin, PathFilter... filter) {
        return create(skin, CHOOSE_FILE_DIALOG_TITLE, ".", filter);
    }

    /**
     * Creates a new {@link FileChooser} within a Swing {@link JDialog} window. File browsing will start
     * in current working directory.
     * 
     * @param skin   {@link Skin} Defines the visual appearance of FileChooser. Defaults to dark skin.
     * @param title  {@link String} title of the {@link FileChooser} view. In case of having the JavaFX
     *               based {@link DirectoryChooser} configured, the window titles for the directory and
     *               file choosers will be identical.
     * @param filter {@link PathFilter} argument of variable length, accepts all path filters as needed.
     *               In case no filter is provided, a filter accepting all files will be used.
     * @return A configured {@link SwingFileChooser}.
     */
    public static SwingFileChooser create(Skin skin, String title, PathFilter... filter) {
        return create(skin, title, ".", filter);
    }

    /**
     * Creates a new {@link FileChooser} within a Swing {@link JDialog} window.
     * 
     * @param skin         {@link Skin} Defines the visual appearance of FileChooser. Defaults to dark
     *                     skin.
     * @param title        {@link String} title of the {@link FileChooser} view. In case of having the
     *                     JavaFX based {@link DirectoryChooser} configured, the window titles for the
     *                     directory and file choosers will be identical.
     * @param pathToBrowse {@link Path} Location to start file browsing in. If the argument is null or
     *                     the denoted location does not exist, the control will default to current
     *                     working directory.
     * @param filter       {@link PathFilter} argument of variable length, accepts all path filters as
     *                     needed. In case no filter is provided, a filter accepting all files will be
     *                     used.
     * @return A configured {@link SwingFileChooser}.
     */
    public static SwingFileChooser create(Skin skin, String title, String pathToBrowse, PathFilter... filter) {
        return create(skin, title, title, pathToBrowse, filter);
    }

    /**
     * Creates a new {@link FileChooser} within a Swing {@link JDialog} window.
     * 
     * @param skin            {@link Skin} Defines the visual appearance of FileChooser. Defaults to
     *                        dark skin.
     * @param title           {@link String} title of the {@link FileChooser} view
     * @param dirChooserTitle {@link String} title of the {@link DirectoryChooser} view when enabled. By
     *                        default, the same title is used as for the {@link FileChooser} view.
     * @param pathToBrowse    {@link Path} Location to start file browsing in. If the argument is null
     *                        or the denoted location does not exist, the control will default to
     *                        current working directory.
     * @param filter          {@link PathFilter} argument of variable length, accepts all path filters
     *                        as needed. In case no filter is provided, a filter accepting all files
     *                        will be used.
     * @return A configured {@link SwingFileChooser}.
     */
    public static SwingFileChooser create(Skin skin, String title, String dirChooserTitle, String pathToBrowse, PathFilter... filter) {

        String fcTitle = (title == null) ? CHOOSE_FILE_DIALOG_TITLE : title;
        String dcTitle = (dirChooserTitle == null) ? fcTitle : dirChooserTitle;
        Skin skinToUse = (skin == null) ? Skin.DARK : skin;
        String location = (pathToBrowse == null) ? "." : pathToBrowse;
        Path startHere = startPath(location);

        PathFilter[] filters = filter;
        if (filters.length == 0) {
            filters = new PathFilter[] {PathFilter.acceptAllFiles()};
        }

        SwingFileChooser fc = new SwingFileChooser(fcTitle, dcTitle);
        fc.model = FileChooserModel.startingIn(startHere);
        for (PathFilter f : filters) {
            fc.model.addOrRemoveFilter(f);
        }
        // do all JavaFX work
        Platform.runLater(() -> {
            PathUpdateHandler pathSupplier = configureDirectoryChooser(skin, startHere, fc);
            FileChooser view = new FileChooser(pathSupplier, fc, fc.model, skinToUse, FileChooserViewOption.STAGE);
                               
            Scene fileChooserScene = new Scene(view);
            fc.setScene(fileChooserScene);
        });

        return fc;
    }

    private static PathUpdateHandler configureDirectoryChooser(Skin skin, Path startHere, SwingFileChooser fc) {
        PathUpdateHandler onPathUpdate = null;
        if (SwingFileChooserProperties.usesJavaFXDirectoryChooser()) {
            onPathUpdate = FXDirectoryChooser.createIn(startHere, () -> fc.getScene().getWindow());
        } else {
            DirectoryChooser dirChooser = new DirectoryChooser(skin);
            dirChooser.useChooseFileButtonProperty().setValue(true);
            dirChooser.useCancelButtonProperty().setValue(true);
            Scene dirChooserScene = new Scene(dirChooser);
            onPathUpdate = update->{
                    Scene previousScene = fc.getScene();
                    String previousTitle = fc.title;
                    fc.setTitle(fc.dirChooserTitle);
                    fc.setScene(dirChooserScene);

                    dirChooser.onSelect(() -> {
                        Path selectedDir = dirChooser.selectedDirectoryProperty().get();
                        if (null != selectedDir) {
                            fc.setTitle(selectedDir.toString());
                            update.accept(selectedDir);
                        }
                        fc.setTitle(previousTitle);
                        fc.setScene(previousScene);
                    });

                    dirChooser.onCancel(() -> {
                        fc.setTitle(previousTitle);
                        fc.setScene(previousScene);
                    });
                };
        }
        return onPathUpdate;
    }

    private static Path startPath(String pathToBrowse) {
        Path startHere = Paths.get(pathToBrowse);
        if (pathToBrowse.equals("")) {
            startHere = Paths.get("./");
        }
        if (Files.notExists(startHere)) {
            return Paths.get("./");
        }
        return startHere;
    }

    private transient FileChooserModel model;

    private JDialog dialog;

    private String title;

    private String dirChooserTitle;

    private SwingFileChooser(String title, String dirChooserTitle) {
        this.title = (null != title) ? title : CHOOSE_FILE_DIALOG_TITLE;
        this.dirChooserTitle = (null != dirChooserTitle) ? dirChooserTitle : "Choose directory:";
    }

    public int showOpenDialog(Component parent) {
        if (null == this.dialog) {
            Frame frame = JOptionPane.getFrameForComponent(parent);
            dialog = new JDialog(frame, this.title, true);
            dialog.setContentPane(this);
            Dimension size = new Dimension(750, 550);
            this.setPreferredSize(size);
            this.setMinimumSize(size);
            dialog.pack();
            dialog.setResizable(true);
        }

        this.dialog.setVisible(true);
        if (this.model.invalidSelectionProperty().getValue()) {
            return CANCEL_OPTION;
        } else {
            return APPROVE_OPTION;
        }
    }

    public File getSelectedFile() {
        if (null != this.model.getSelectedFile()) {
            return this.model.getSelectedFile().toFile();
        } else {
            return null;
        }
    }

    @Override
    public void closeView() {
        this.dialog.setVisible(false);
    }

    public void addLocations(List locations) {
        locations.forEach(model::addLocation);
    }

    protected void setTitle(String newTitle) {
        this.title = newTitle;
        this.dialog.setTitle(title);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy