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

com.googlecode.lanterna.gui2.dialogs.FileDialog Maven / Gradle / Ivy

There is a newer version: 3.2.0-alpha1
Show newest version
/*
 * This file is part of lanterna (https://github.com/mabe02/lanterna).
 *
 * lanterna is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 * Copyright (C) 2010-2020 Martin Berglund
 */
package com.googlecode.lanterna.gui2.dialogs;

import com.googlecode.lanterna.TerminalTextUtils;
import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.gui2.*;

import java.io.File;
import java.util.Arrays;
import java.util.Comparator;

/**
 * Dialog that allows the user to iterate the file system and pick file to open/save
 *
 * @author Martin
 */
public class FileDialog extends DialogWindow {

    private final ActionListBox fileListBox;
    private final ActionListBox directoryListBox;
    private final TextBox fileBox;
    private final Button okButton;
    private final boolean showHiddenFilesAndDirs;

    private File directory;
    private File selectedFile;

    /**
     * Default constructor for {@code FileDialog}
     * @param title Title of the dialog
     * @param description Description of the dialog, is displayed at the top of the content area
     * @param actionLabel Label to use on the "confirm" button, for example "open" or "save"
     * @param dialogSize Rough estimation of how big you want the dialog to be
     * @param showHiddenFilesAndDirs If {@code true}, hidden files and directories will be visible
     * @param selectedObject Initially selected file node
     */
    public FileDialog(
            String title,
            String description,
            String actionLabel,
            TerminalSize dialogSize,
            boolean showHiddenFilesAndDirs,
            File selectedObject) {
        super(title);
        this.selectedFile = null;
        this.showHiddenFilesAndDirs = showHiddenFilesAndDirs;

        if(selectedObject == null || !selectedObject.exists()) {
            selectedObject = new File("").getAbsoluteFile();
        }
        selectedObject = selectedObject.getAbsoluteFile();

        Panel contentPane = new Panel();
        contentPane.setLayoutManager(new GridLayout(2));

        if(description != null) {
            new Label(description)
                    .setLayoutData(
                            GridLayout.createLayoutData(
                                    GridLayout.Alignment.BEGINNING,
                                    GridLayout.Alignment.CENTER,
                                    false,
                                    false,
                                    2,
                                    1))
                    .addTo(contentPane);
        }

        int unitWidth = dialogSize.getColumns() / 3;
        int unitHeight = dialogSize.getRows();

        new FileSystemLocationLabel()
                .setLayoutData(GridLayout.createLayoutData(
                        GridLayout.Alignment.FILL,
                        GridLayout.Alignment.CENTER,
                        true,
                        false,
                        2,
                        1))
                .addTo(contentPane);

        fileListBox = new ActionListBox(new TerminalSize(unitWidth * 2, unitHeight));
        fileListBox.withBorder(Borders.singleLine())
                .setLayoutData(GridLayout.createLayoutData(
                        GridLayout.Alignment.BEGINNING,
                        GridLayout.Alignment.CENTER,
                        false,
                        false))
                .addTo(contentPane);
        directoryListBox = new ActionListBox(new TerminalSize(unitWidth, unitHeight));
        directoryListBox.withBorder(Borders.singleLine())
                .addTo(contentPane);

        fileBox = new TextBox()
                .setLayoutData(GridLayout.createLayoutData(
                        GridLayout.Alignment.FILL,
                        GridLayout.Alignment.CENTER,
                        true,
                        false,
                        2,
                        1))
                .addTo(contentPane);

        new Separator(Direction.HORIZONTAL)
                .setLayoutData(
                        GridLayout.createLayoutData(
                                GridLayout.Alignment.FILL,
                                GridLayout.Alignment.CENTER,
                                true,
                                false,
                                2,
                                1))
                .addTo(contentPane);

        okButton = new Button(actionLabel, new OkHandler());
        Panels.grid(2,
                okButton,
                new Button(LocalizedString.Cancel.toString(), new CancelHandler()))
                .setLayoutData(GridLayout.createLayoutData(GridLayout.Alignment.END, GridLayout.Alignment.CENTER, false, false, 2, 1))
                .addTo(contentPane);

        if(selectedObject.isFile()) {
            directory = selectedObject.getParentFile();
            fileBox.setText(selectedObject.getName());
        }
        else if(selectedObject.isDirectory()) {
            directory = selectedObject;
        }

        reloadViews(directory);
        setComponent(contentPane);
    }

    /**
     * {@inheritDoc}
     * @param textGUI Text GUI to add the dialog to
     * @return The file which was selected in the dialog or {@code null} if the dialog was cancelled
     */
    @Override
    public File showDialog(WindowBasedTextGUI textGUI) {
        selectedFile = null;
        super.showDialog(textGUI);
        return selectedFile;
    }

    private class OkHandler implements Runnable {
        @Override
        public void run() {
            if(!fileBox.getText().isEmpty()) {
                File file = new File(fileBox.getText());
                selectedFile = file.isAbsolute() ? file : new File(directory, fileBox.getText());
                close();
            }
            else {
                MessageDialog.showMessageDialog(getTextGUI(), "Error", "Please select a valid file name", MessageDialogButton.OK);
            }
        }
    }

    private class CancelHandler implements Runnable {
        @Override
        public void run() {
            selectedFile = null;
            close();
        }
    }

    private static class DoNothing implements Runnable {
        @Override
        public void run() {
        }
    }

    private void reloadViews(final File directory) {
        directoryListBox.clearItems();
        fileListBox.clearItems();
        File []entries = directory.listFiles();
        if(entries == null) {
            return;
        }
        Arrays.sort(entries, Comparator.comparing(o -> o.getName().toLowerCase()));
        if (directory.getAbsoluteFile().getParentFile() !=null){
            directoryListBox.addItem("..", () -> {
                FileDialog.this.directory = directory.getAbsoluteFile().getParentFile();
                reloadViews(directory.getAbsoluteFile().getParentFile());
            });
        } else {
            File[] roots = File.listRoots();
            for (final File entry : roots) {
                if (entry.canRead()) {
                    directoryListBox.addItem('[' + entry.getPath() + ']', () -> {
                        FileDialog.this.directory = entry;
                        reloadViews(entry);
                    });
                }
            }
        }
        for(final File entry: entries) {
            if(entry.isHidden() && !showHiddenFilesAndDirs) {
                continue;
            }
            if(entry.isDirectory()) {
                directoryListBox.addItem(entry.getName(), () -> {
                    FileDialog.this.directory = entry;
                    reloadViews(entry);
                });
            }
            else {
                fileListBox.addItem(entry.getName(), () -> {
                    fileBox.setText(entry.getName());
                    setFocusedInteractable(okButton);
                });
            }
        }
        if(fileListBox.isEmpty()) {
            fileListBox.addItem("", new DoNothing());
        }
    }

    private class FileSystemLocationLabel extends Label {
        public FileSystemLocationLabel() {
            super("");
            setPreferredSize(TerminalSize.ONE);
        }

        @Override
        public void onBeforeDrawing() {
            TerminalSize area = getSize();
            String absolutePath = directory.getAbsolutePath();
            int absolutePathLengthInColumns = TerminalTextUtils.getColumnWidth(absolutePath);
            if(area.getColumns() < absolutePathLengthInColumns) {
                absolutePath = absolutePath.substring(absolutePathLengthInColumns - area.getColumns());
                absolutePath = "..." + absolutePath.substring(Math.min(absolutePathLengthInColumns, 3));
            }
            setText(absolutePath);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy