org.pdfsam.PdfsamApp.java Source code

Java tutorial

Introduction

Here is the source code for org.pdfsam.PdfsamApp.java

Source

/* 
 * This file is part of the PDF Split And Merge source code
 * Created on 16/ott/2013
 * Copyright 2013 by Andrea Vacondio (andrea.vacondio@gmail.com).
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.pdfsam;

import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.pdfsam.ui.event.SetActiveModuleRequest.activeteModule;
import static org.sejda.eventstudio.StaticStudio.eventStudio;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Paths;

import javafx.application.Application;
import javafx.application.HostServices;
import javafx.application.Platform;
import javafx.application.Preloader.ProgressNotification;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import org.apache.commons.lang3.time.DurationFormatUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.pdfsam.configuration.ApplicationContextHolder;
import org.pdfsam.configuration.StylesConfig;
import org.pdfsam.context.DefaultUserContext;
import org.pdfsam.context.UserContext;
import org.pdfsam.i18n.DefaultI18nContext;
import org.pdfsam.i18n.SetLocaleEvent;
import org.pdfsam.ui.MainPane;
import org.pdfsam.ui.commons.OpenUrlRequest;
import org.pdfsam.ui.commons.ShowStageRequest;
import org.pdfsam.ui.dialog.OverwriteConfirmationDialog;
import org.pdfsam.ui.io.SetLatestDirectoryEvent;
import org.pdfsam.ui.notification.NotificationsContainer;
import org.pdfsam.update.UpdateCheckRequest;
import org.sejda.core.Sejda;
import org.sejda.eventstudio.EventStudio;
import org.sejda.eventstudio.annotation.EventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * PDFsam application
 * 
 * @author Andrea Vacondio
 * 
 */
public class PdfsamApp extends Application {
    private static final Logger LOG = LoggerFactory.getLogger(PdfsamApp.class);
    private static StopWatch STOPWATCH = new StopWatch();

    private Scene mainScene;

    @Override
    public void init() {
        STOPWATCH.start();
        LOG.info("Starting PDFsam");
        notifyPreloader(new ProgressNotification(0));
        System.setProperty(Sejda.UNETHICAL_READ_PROPERTY_NAME, "true");
        System.setProperty(EventStudio.MAX_QUEUE_SIZE_PROP, "20");
        UserContext userContext = initUserContext();
        String localeString = userContext.getLocale();
        if (isNotBlank(localeString)) {
            eventStudio().broadcast(new SetLocaleEvent(localeString));
        }
        notifyPreloader(new ProgressNotification(0.1));
        String defaultworkingPath = userContext.getDefaultWorkingPath();
        if (isNotBlank(defaultworkingPath)) {
            try {
                if (Files.isDirectory(Paths.get(defaultworkingPath))) {
                    eventStudio().broadcast(new SetLatestDirectoryEvent(new File(defaultworkingPath)));
                }
            } catch (InvalidPathException e) {
                LOG.warn("Unable to set initial directory, default path is invalid.", e);
            }
        }
        notifyPreloader(new ProgressNotification(0.3));
        Platform.runLater(() -> ApplicationContextHolder.getContext());
        notifyPreloader(new ProgressNotification(0.6));
        Platform.runLater(() -> initScene());
        notifyPreloader(new ProgressNotification(0.8));

    }

    private UserContext initUserContext() {
        UserContext userContext = new DefaultUserContext();
        if (getParameters().getRaw().contains("-clean")) {
            userContext.clear();
            LOG.info("Cleared user preferences");
        }
        return userContext;
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setScene(mainScene);
        primaryStage.getIcons().addAll(ApplicationContextHolder.getContext().getBeansOfType(Image.class).values());
        primaryStage.setTitle(ApplicationContextHolder.getContext().getBean(Pdfsam.class).name());

        initWindowsStatusController(primaryStage);
        initOverwriteDialogController(primaryStage);
        initActiveModule();
        primaryStage.show();
        Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger());
        requestCheckForUpdateIfNecessary();
        requestLatestNewsPanelDisplay();
        eventStudio().addAnnotatedListeners(this);
        STOPWATCH.stop();
        LOG.info(DefaultI18nContext.getInstance().i18n("Started in {0}",
                DurationFormatUtils.formatDurationWords(STOPWATCH.getTime(), true, true)));
    }

    private void initScene() {
        MainPane mainPane = ApplicationContextHolder.getContext().getBean(MainPane.class);

        NotificationsContainer notifications = ApplicationContextHolder.getContext()
                .getBean(NotificationsContainer.class);
        StackPane main = new StackPane();
        StackPane.setAlignment(notifications, Pos.BOTTOM_RIGHT);
        StackPane.setAlignment(mainPane, Pos.TOP_LEFT);
        main.getChildren().addAll(mainPane, notifications);

        StylesConfig styles = ApplicationContextHolder.getContext().getBean(StylesConfig.class);

        mainScene = new Scene(main);
        mainScene.getStylesheets().addAll(styles.styles());
        mainScene.getAccelerators().put(new KeyCodeCombination(KeyCode.L, KeyCombination.SHORTCUT_DOWN),
                () -> eventStudio().broadcast(new ShowStageRequest(), "LogStage"));
    }

    @Override
    public void stop() {
        LOG.info(DefaultI18nContext.getInstance().i18n("Closing PDFsam..."));
        ApplicationContextHolder.getContext().close();
    }

    private static void requestCheckForUpdateIfNecessary() {
        if (ApplicationContextHolder.getContext().getBean(UserContext.class).isCheckForUpdates()) {
            eventStudio().broadcast(new UpdateCheckRequest());
        }
    }

    private static void requestLatestNewsPanelDisplay() {
        eventStudio().broadcast(new ShowStageRequest(), "NewsStage");
    }

    @EventListener
    public void openUrl(OpenUrlRequest event) {
        HostServices services = getHostServices();
        if (services != null) {
            services.showDocument(event.getUrl());
        } else {
            LOG.warn("Unable to open '{}', please copy and paste the url to your browser.", event.getUrl());
        }
    }

    private void initOverwriteDialogController(Stage primaryStage) {
        OverwriteConfirmationDialog overwriteDialog = ApplicationContextHolder.getContext()
                .getBean(OverwriteConfirmationDialog.class);
        overwriteDialog.setOwner(primaryStage);
    }

    private void initWindowsStatusController(Stage primaryStage) {
        WindowStatusController stageStatusController = ApplicationContextHolder.getContext()
                .getBean(WindowStatusController.class);
        stageStatusController.setStage(primaryStage);
    }

    private void initActiveModule() {
        String startupModule = new DefaultUserContext().getStartupModule();
        if (isNotBlank(startupModule)) {
            LOG.trace("Activating startup module '{}'", startupModule);
            eventStudio().broadcast(activeteModule(startupModule));
        }
    }
}