de.ks.text.view.AsciiDocViewer.java Source code

Java tutorial

Introduction

Here is the source code for de.ks.text.view.AsciiDocViewer.java

Source

/*
 * Copyright [2014] [Christian Loehnert, krampenschiesser@gmail.com]
 * 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.
 */
package de.ks.text.view;

import de.ks.activity.ActivityController;
import de.ks.activity.executor.ActivityExecutor;
import de.ks.activity.initialization.ActivityCallback;
import de.ks.activity.initialization.ActivityInitialization;
import de.ks.application.fxml.DefaultLoader;
import de.ks.executor.JavaFXExecutorService;
import de.ks.text.AsciiDocParser;
import de.ks.text.process.AsciiDocPreProcessor;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Control;
import javafx.scene.layout.StackPane;
import javafx.scene.web.WebView;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.CDI;
import javax.inject.Inject;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

public class AsciiDocViewer implements Initializable, ActivityCallback {

    public static final String DEFAULT = "default";

    public static CompletableFuture<DefaultLoader<Node, AsciiDocViewer>> load(Consumer<StackPane> viewConsumer,
            Consumer<AsciiDocViewer> controllerConsumer) {
        ActivityInitialization initialization = CDI.current().select(ActivityInitialization.class).get();
        return initialization.loadAdditionalControllerWithFuture(AsciiDocViewer.class)//
                .thenApply(loader -> {
                    viewConsumer.accept((StackPane) loader.getView());
                    controllerConsumer.accept(loader.getController());
                    return loader;
                });
    }

    private static final Logger log = LoggerFactory.getLogger(AsciiDocViewer.class);

    protected final Map<String, String> preloaded = new ConcurrentHashMap<>();
    protected final List<AsciiDocPreProcessor> preProcessors = new ArrayList<>();
    @Inject
    ActivityController controller;
    @Inject
    AsciiDocParser parser;
    @Inject
    Instance<AsciiDocPreProcessor> preProcessorProvider;

    @FXML
    protected StackPane root;
    protected WebView webView;

    protected final SimpleStringProperty currentHtml = new SimpleStringProperty();
    protected final SimpleStringProperty currentIdentifier = new SimpleStringProperty();

    protected Set<Runnable> supensionRunnables = new HashSet<>();

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        CompletableFuture.supplyAsync(() -> new WebView(), controller.getJavaFXExecutor()).thenAccept(view -> {
            webView = view;
            webView.setMinSize(100, 100);
            webView.setPrefSize(Control.USE_COMPUTED_SIZE, Control.USE_COMPUTED_SIZE);
            root.getChildren().add(webView);
        });

        Iterator<AsciiDocPreProcessor> iterator = preProcessorProvider.iterator();
        while (iterator.hasNext()) {
            AsciiDocPreProcessor next = iterator.next();
            addPreProcessor(next);
        }
    }

    public void reset() {
        webView.getEngine().loadContent("");
        currentIdentifier.set("");
    }

    public void showDirect(String content) {
        currentIdentifier.set(DEFAULT);
        preloaded.remove(DEFAULT);
        preload(Collections.singletonList(new AsciiDocContent(DEFAULT, content)));
    }

    public void show(AsciiDocContent content) {
        String identifier = content.getIdentifier();
        currentIdentifier.set(identifier);
        if (preloaded.containsKey(identifier)) {
            String html = preloaded.get(identifier);
            currentHtml.set(html);
            webView.getEngine().loadContent(html == null ? "" : html);
        } else {
            preload(Collections.singletonList(content));
            webView.getEngine().loadContent(content.getAdoc() == null ? "" : content.getAdoc());
        }
    }

    public void preload(Collection<AsciiDocContent> load) {
        ActivityExecutor executorService = controller.getExecutorService();
        JavaFXExecutorService javaFXExecutor = controller.getJavaFXExecutor();
        load.forEach(t -> {
            CompletableFuture<Pair<String, String>> completableFuture = CompletableFuture
                    .supplyAsync(() -> preProcess(t.getAdoc()), executorService)//
                    .thenApply(desc -> {
                        if (desc == null || desc.trim().isEmpty()) {
                            return "";
                        } else {
                            return parser.parse(desc);
                        }
                    })//
                    .thenApply(html -> Pair.of(t.getIdentifier(), html));
            completableFuture.thenApply(pair -> {
                preloaded.put(pair.getKey(), pair.getValue());
                return pair;
            }).thenAcceptAsync(pair -> {
                if (currentIdentifier.getValueSafe().equals(pair.getKey())) {
                    String html = pair.getValue();
                    currentHtml.set(html);
                    webView.getEngine().loadContent(html);
                }
            }, javaFXExecutor)//
                    .exceptionally(e -> {
                        log.error("Could not parse adoc", e);
                        return null;
                    });
        });
    }

    protected String preProcess(String input) {
        for (AsciiDocPreProcessor preProcessor : preProcessors) {
            input = preProcessor.preProcess(input, this);
        }
        return input;
    }

    public void addPreProcessor(AsciiDocPreProcessor processor) {
        this.preProcessors.add(processor);
    }

    public void clear() {
        preloaded.clear();
    }

    public void requestFocus() {
        webView.requestFocus();
    }

    public WebView getWebView() {
        return webView;
    }

    public String getCurrentHtml() {
        return currentHtml.get();
    }

    public SimpleStringProperty currentHtmlProperty() {
        return currentHtml;
    }

    public void setCurrentHtml(String currentHtml) {
        this.currentHtml.set(currentHtml);
    }

    public void addSuspensionRunnable(Runnable r) {
        supensionRunnables.add(r);
    }

    @Override
    public void onSuspend() {
        supensionRunnables.forEach(r -> r.run());
    }

    @Override
    public void onStop() {
        onSuspend();
    }
}