org.polymap.p4.process.ModuleProcessPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.polymap.p4.process.ModuleProcessPanel.java

Source

/* 
 * polymap.org
 * Copyright (C) 2017, the @authors. All rights reserved.
 *
 * This 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.0 of
 * the License, or (at your option) any later version.
 *
 * This software 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.
 */
package org.polymap.p4.process;

import static org.apache.commons.lang3.StringUtils.defaultString;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import org.jgrasstools.gears.libs.modules.JGTModel;
import org.jgrasstools.gears.libs.monitor.IJGTProgressMonitor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.common.base.Throwables;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;

import org.eclipse.jface.layout.RowDataFactory;
import org.eclipse.jface.layout.RowLayoutFactory;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;

import org.polymap.core.data.process.FieldInfo;
import org.polymap.core.data.process.ModuleInfo;
import org.polymap.core.data.process.ui.FieldIO;
import org.polymap.core.data.process.ui.FieldViewer;
import org.polymap.core.data.process.ui.FieldViewerSite;
import org.polymap.core.project.ILayer;
import org.polymap.core.runtime.UIJob;
import org.polymap.core.runtime.UIThreadExecutor;
import org.polymap.core.ui.ColumnDataFactory;
import org.polymap.core.ui.ColumnLayoutFactory;
import org.polymap.core.ui.FormDataFactory;
import org.polymap.core.ui.FormLayoutFactory;
import org.polymap.core.ui.UIUtils;

import org.polymap.rhei.batik.Context;
import org.polymap.rhei.batik.PanelIdentifier;
import org.polymap.rhei.batik.Scope;
import org.polymap.rhei.batik.app.SvgImageRegistryHelper;
import org.polymap.rhei.batik.toolkit.DefaultToolkit;
import org.polymap.rhei.batik.toolkit.IPanelSection;

import org.polymap.p4.P4Panel;
import org.polymap.p4.P4Plugin;

/**
 * Processes a given module ({@link JGTModel}). 
 *
 * @author Falko Brutigam
 */
public class ModuleProcessPanel extends P4Panel {

    private static final Log log = LogFactory.getLog(ModuleProcessPanel.class);

    public static final PanelIdentifier ID = PanelIdentifier.parse("processModule");

    static {
        FieldIO.ALL.add(LayerRasterSupplier.class);
        FieldIO.ALL.add(LayerRasterConsumer.class);
        FieldIO.ALL.add(0, CoordinateSupplier.class); // higher prio than Number
        FieldIO.ALL.add(BoundingBoxSupplier.class);
    }

    // instance *******************************************

    /** Inbound: */
    @Scope(P4Plugin.Scope)
    private Context<ILayer> layer;

    /** Inbound: */
    @Scope(P4Plugin.Scope)
    private Context<ModuleInfo> moduleInfo;

    private JGTModel module;

    private IPanelSection outputSection;

    private IPanelSection inputSection;

    private Composite buttons;

    private Button startBtn;

    private Composite parent;

    private List<FieldViewer> inputFields = new ArrayList();

    private UIJob job;

    @Override
    public void init() {
        super.init();
        module = moduleInfo.get().createInstance();
    }

    @Override
    public void dispose() {
        if (job != null) {
            job.cancelAndInterrupt();
            job = null;
        }
    }

    @Override
    public void createContents(@SuppressWarnings("hiding") Composite parent) {
        this.parent = parent;
        site().title.set(moduleInfo.get().title());

        parent.setLayout(FormLayoutFactory.defaults().spacing(8).margins(2, 8).create());

        inputSection = createInputSection();
        FormDataFactory.on(inputSection.getControl()).fill().noBottom().width(500);

        buttons = createButtonsSection();
        FormDataFactory.on(buttons).fill().top(inputSection.getControl()).noBottom();

        //        outputSection = createOutputSection();
        //        FormDataFactory.on( outputSection.getControl() ).fill().top( buttons ).noBottom();
    }

    protected IPanelSection createInputSection() {
        IPanelSection section = tk().createPanelSection(parent, "Input", SWT.BORDER);
        section.getBody()
                .setLayout(ColumnLayoutFactory.defaults().columns(1, 1).margins(0, 8).spacing(10).create());

        Label label = tk().createLabel(section.getBody(),
                moduleInfo.get().description.get().orElse("No description."), SWT.WRAP);
        label.setLayoutData(ColumnDataFactory.defaults().widthHint(300).create());
        label.setEnabled(false);

        AtomicBoolean isFirst = new AtomicBoolean(true);
        for (FieldInfo fieldInfo : moduleInfo.get().inputFields()) {
            // skip
            if (IJGTProgressMonitor.class.isAssignableFrom(fieldInfo.type.get())
                    || !fieldInfo.description.get().isPresent()) {
                continue;
            }
            // separator
            if (!isFirst.getAndSet(false)) {
                Label sep = new Label(section.getBody(), SWT.SEPARATOR | SWT.HORIZONTAL);
                UIUtils.setVariant(sep, DefaultToolkit.CSS_SECTION_SEPARATOR); // XXX
            }
            // field
            FieldViewer fieldViewer = new FieldViewer(
                    new FieldViewerSite().moduleInfo.put(moduleInfo.get()).module.put(module).fieldInfo
                            .put(fieldInfo).layer.put(layer.get()));
            fieldViewer.createContents(section.getBody())
                    .setLayoutData(ColumnDataFactory.defaults().widthHint(300).create());
            inputFields.add(fieldViewer);
        }

        return section;
    }

    protected IPanelSection createOutputSection() {
        IPanelSection section = tk().createPanelSection(parent, "Output", SWT.BORDER);
        return section;
    }

    protected Composite createButtonsSection() {
        Composite section = tk().createComposite(parent);
        section.setLayout(
                RowLayoutFactory.fillDefaults().spacing(8).margins(2, 2).fill(true).justify(true).create());

        startBtn = tk().createButton(section, "", SWT.PUSH);
        startBtn.setLayoutData(RowDataFactory.swtDefaults().hint(150, SWT.DEFAULT).create());
        startBtn.addSelectionListener(UIUtils.selectionListener(ev -> {
            if (job == null) {
                startProcess();
            } else {
                stopProcess();
                //startBtn.setEnabled( false );
            }
        }));
        updateStartBtn();
        return section;
    }

    protected void updateStartBtn() {
        if (job != null && job.getState() != Job.NONE) {
            startBtn.setText("STOP");
            startBtn.setImage(
                    P4Plugin.images().svgImage("stop-circle-outline.svg", SvgImageRegistryHelper.WHITE24));
        } else {
            startBtn.setText("RUN");
            startBtn.setImage(
                    P4Plugin.images().svgImage("play-circle-outline.svg", SvgImageRegistryHelper.WHITE24));
        }
    }

    protected void stopProcess() {
        if (job != null) {
            module.pm.setCanceled(true);
            job.cancelAndInterrupt();
        }
        updateStartBtn();
        UIUtils.disposeChildren(outputSection.getBody());
        Label msg = new Label(outputSection.getBody(), SWT.NONE);
        msg.setText("Cancel requested...");
        parent.layout(true, true);
    }

    protected void startProcess() {
        if (outputSection == null) {
            outputSection = createOutputSection();
            FormDataFactory.on(outputSection.getControl()).fill().top(buttons).noBottom();
        } else {
            UIUtils.disposeChildren(outputSection.getBody());
        }

        // the default Polymap executor is unbound
        // ExecutionPlanner.defaultExecutor = Polymap.executorService();

        module.pm = new ProcessProgressMonitor(outputSection.getBody());
        parent.layout(true, true);

        job = new UIJob("Processing") {
            @Override
            protected void runWithException(IProgressMonitor monitor) throws Exception {
                moduleInfo.get().execute(module, null);
            }
        };
        job.addJobChangeListenerWithContext(new JobChangeAdapter() {
            @Override
            public void done(IJobChangeEvent ev) {
                UIThreadExecutor.async(() -> {
                    if (!outputSection.getBody().isDisposed()) {
                        job = null;
                        updateStartBtn();

                        UIUtils.disposeChildren(outputSection.getBody());
                        if (ev.getResult().isOK()) {
                            fillOutputFields();
                        } else {
                            Throwable e = ev.getResult().getException();
                            Label msg = new Label(outputSection.getBody(), SWT.WRAP);
                            msg.setForeground(FieldViewer.errorColor());
                            msg.setText(defaultString(e != null ? Throwables.getRootCause(e).getMessage()
                                    : ev.getResult().getMessage(), "-"));
                            FormDataFactory.on(msg).fill().width(200);
                        }
                        parent.layout(true, true);
                    }
                });
            }
        });
        job.schedule();
        updateStartBtn();
    }

    protected void fillOutputFields() {
        outputSection.getBody()
                .setLayout(ColumnLayoutFactory.defaults().columns(1, 1).margins(0, 8).spacing(10).create());

        AtomicBoolean isFirst = new AtomicBoolean(true);
        for (FieldInfo fieldInfo : moduleInfo.get().outputFields()) {
            if (fieldInfo.description.get().isPresent()) {
                // separator
                if (!isFirst.getAndSet(false)) {
                    Label sep = new Label(outputSection.getBody(), SWT.SEPARATOR | SWT.HORIZONTAL);
                    UIUtils.setVariant(sep, DefaultToolkit.CSS_SECTION_SEPARATOR); // XXX
                }
                // field
                FieldViewer fieldViewer = new FieldViewer(
                        new FieldViewerSite().moduleInfo.put(moduleInfo.get()).module.put(module).fieldInfo
                                .put(fieldInfo).layer.put(layer.get()));
                fieldViewer.createContents(outputSection.getBody())
                        .setLayoutData(ColumnDataFactory.defaults().widthHint(300).create());
                inputFields.add(fieldViewer);
            }
        }
    }

}