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

org.jhotdraw8.application.action.file.AbstractOpenFileAction Maven / Gradle / Ivy

/*
 * @(#)AbstractOpenFileAction.java
 * Copyright © 2023 The authors and contributors of JHotDraw. MIT License.
 */
package org.jhotdraw8.application.action.file;

import javafx.event.ActionEvent;
import javafx.scene.control.Alert;
import javafx.scene.control.TextArea;
import javafx.scene.input.DataFormat;
import org.jhotdraw8.annotation.NonNull;
import org.jhotdraw8.annotation.Nullable;
import org.jhotdraw8.application.Activity;
import org.jhotdraw8.application.Application;
import org.jhotdraw8.application.ApplicationLabels;
import org.jhotdraw8.application.FileBasedActivity;
import org.jhotdraw8.application.FileBasedApplication;
import org.jhotdraw8.application.action.AbstractApplicationAction;
import org.jhotdraw8.application.controls.urichooser.FileURIChooser;
import org.jhotdraw8.application.controls.urichooser.URIChooser;
import org.jhotdraw8.application.resources.Resources;
import org.jhotdraw8.base.net.UriUtil;
import org.jhotdraw8.fxbase.concurrent.SimpleWorkState;
import org.jhotdraw8.fxbase.concurrent.WorkState;
import org.jhotdraw8.fxcollection.typesafekey.Key;
import org.jhotdraw8.fxcollection.typesafekey.NullableObjectKey;
import org.jhotdraw8.fxcollection.typesafekey.SimpleParameterizedType;
import org.jhotdraw8.icollection.ChampMap;

import java.net.URI;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;


public abstract class AbstractOpenFileAction extends AbstractApplicationAction {
    public static final @NonNull Key OPEN_CHOOSER_KEY = new NullableObjectKey<>("openChooser", URIChooser.class);
    public static final @NonNull Key> OPEN_CHOOSER_FACTORY_KEY = new NullableObjectKey<>("openChooserFactory",
            new SimpleParameterizedType(Supplier.class, URIChooser.class));

    public AbstractOpenFileAction(@NonNull FileBasedApplication app) {
        super(app);
    }

    protected @Nullable URIChooser getChooser(FileBasedActivity view) {
        URIChooser chooser = app.get(OPEN_CHOOSER_KEY);
        if (chooser == null) {
            Supplier factory = app.get(OPEN_CHOOSER_FACTORY_KEY);
            chooser = factory == null ? new FileURIChooser() : factory.get();
            app.set(OPEN_CHOOSER_KEY, chooser);
        }
        return chooser;
    }

    protected abstract boolean isReuseEmptyViews();

    @Override
    protected void onActionPerformed(@NonNull ActionEvent evt, @NonNull Application app) {
        {
            WorkState workState = new SimpleWorkState<>(getLabel());
            app.addDisabler(workState);
            // Search for an empty view
            FileBasedActivity emptyView;
            if (isReuseEmptyViews()) {
                emptyView = (FileBasedActivity) app.getActiveActivity(); // FIXME class cast exception
                if (emptyView == null
                        || !emptyView.isEmpty()
                        || emptyView.isDisabled()) {
                    emptyView = null;
                }
            } else {
                emptyView = null;
            }

            if (emptyView == null) {
                app.createActivity().thenAccept(v -> doIt((FileBasedActivity) v, true, workState));
            } else {
                doIt(emptyView, false, workState);
            }
        }
    }


    public void doIt(@NonNull FileBasedActivity view, boolean disposeView, WorkState workState) {
        URIChooser chooser = getChooser(view);
        URI uri = chooser.showDialog(app.getNode());
        if (uri != null) {
            app.getActivities().add(view);

            // Prevent same URI from being opened more than once
            if (!getApplication().getNonNull(FileBasedApplication.ALLOW_MULTIPLE_ACTIVITIES_WITH_SAME_URI)) {
                for (Activity vp : getApplication().getActivities()) {
                    FileBasedActivity v = (FileBasedActivity) vp;
                    if (v.getURI() != null && v.getURI().equals(uri)) {
                        if (disposeView) {
                            app.getActivities().remove(view);
                        }
                        app.removeDisabler(workState);
                        v.getNode().getScene().getWindow().requestFocus();
                        v.getNode().requestFocus();
                        return;
                    }
                }
            }

            openActivityFromURI(view, uri, chooser, workState);
        } else {
            if (disposeView) {
                app.getActivities().remove(view);
            }
            app.removeDisabler(workState);
        }
    }

    protected void openActivityFromURI(final @NonNull FileBasedActivity v, final @NonNull URI uri, final @NonNull URIChooser chooser, WorkState workState) {
        final Application app = getApplication();
        Map, Object> options = getReadOptions();
        app.removeDisabler(workState);

        v.addDisabler(workState);
        final DataFormat chosenFormat = chooser.getDataFormat();
        v.setDataFormat(chosenFormat);

        // Open the file
        v.read(uri, chosenFormat, ChampMap.copyOf(options), false, workState).whenComplete((actualFormat, exception) -> {
            if (exception instanceof CancellationException) {
                v.removeDisabler(workState);
            } else if (exception != null) {
                Logger.getLogger(getClass().getName()).log(Level.WARNING, "Unexpected Exception " + exception.getMessage(), exception);

                Resources labels = ApplicationLabels.getResources();

                TextArea textArea = new TextArea(createErrorMessage(exception));
                textArea.setEditable(false);
                textArea.setWrapText(true);

                Alert alert = new Alert(Alert.AlertType.ERROR);
                alert.getDialogPane().setMaxWidth(640.0);
                alert.setHeaderText(labels.getFormatted("file.open.couldntOpen.message", UriUtil.getName(uri)));
                alert.getDialogPane().setContent(textArea);
                alert.showAndWait();
                v.removeDisabler(workState);
            } else {
                v.setURI(uri);
                v.setDataFormat(actualFormat);
                v.clearModified();
                getApplication().getRecentUris().put(uri, actualFormat);
                v.removeDisabler(workState);
            }
        });
    }

    /**
     * Gets options for {@link FileBasedActivity#read}.
     * The options can be null, a constant, or from user input through a dialog window.
     * 

* The value null means that the user has aborted the dialog window. In this case, the action * will not open a file! * * @return options or null if the user has aborted the dialog window */ protected abstract @NonNull Map, Object> getReadOptions(); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy