eu.hydrologis.jgrass.uibuilder.jgrassdependent.GuiBuilderDialog.java Source code

Java tutorial

Introduction

Here is the source code for eu.hydrologis.jgrass.uibuilder.jgrassdependent.GuiBuilderDialog.java

Source

/*
 * JGrass - Free Open Source Java GIS http://www.jgrass.org 
 * (C) HydroloGIS - www.hydrologis.com 
 *
 * This program 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 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 <http://www.gnu.org/licenses/>.
 */
package eu.hydrologis.jgrass.uibuilder.jgrassdependent;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.preferences.ScopedPreferenceStore;
import org.eclipse.ui.progress.IProgressService;
import org.w3c.dom.NodeList;

import eu.hydrologis.jgrass.console.editor.ConsoleEditorPlugin;
import eu.hydrologis.jgrass.console.editor.preferences.PreferencesInitializer;
import eu.hydrologis.jgrass.ui.console.ConsoleCommandExecutor;
import eu.hydrologis.jgrass.uibuilder.UIBuilder;
import eu.hydrologis.jgrass.uibuilder.UIBuilderPlugin;
import eu.hydrologis.jgrass.uibuilder.fields.MissingValueException;
import eu.hydrologis.jgrass.uibuilder.renderers.SWTRendererFactory;
import eu.hydrologis.jgrass.uibuilder.swt.SWTSpreadsheetLayout;

/**
 * A class that builds a dialog with the contents given by the description in the nodelist.
 * 
 * @author Andrea Antonello (www.hydrologis.com)
 */
public class GuiBuilderDialog extends Dialog {
    private static final int HELP_ID = -9999;
    private UIBuilder guiBuilder;
    private Properties properties;
    private final NodeList commandNodeList;
    private final Shell parent;
    private final boolean isJGrass;
    private String commandName;
    private String helpCommand;
    private PrintStream out;
    private Object ret;
    private final boolean isTimeDependent;
    private DateTime startDate;
    private DateTime startTime;
    private DateTime endDate;
    private DateTime endTime;
    private Text deltaText;

    /**
     * Instantiate a new <code>SWTDialog</code>.
     * 
     * @param parent the parent of this <code>Dialog</code>
     * @param xmlFile the path to the XML file containing fields' definitions.
     * @param properties a <code>Properties</code> object used to pass values. This object will
     *        hold the output of the gui, but also be capable of adding value to the dialog, as for
     *        example define a title (key = {@link UIBuilderJGrassConstants#DIALOG_TITLE}) or a
     *        size (key = {@link UIBuilderJGrassConstants#DIALOG_SIZE})
     * @param isJGrass 
     */
    public GuiBuilderDialog(Shell parent, NodeList commandNodeList, Properties properties, boolean isJGrass,
            boolean isTimeDependent) {
        super(parent);
        this.parent = parent;
        this.commandNodeList = commandNodeList;

        /*
         *  TODO this is fine only until we have GRASS and JGrass. 
         *  To be solved when new things come in (ex. R).
         */
        this.isJGrass = isJGrass;
        this.isTimeDependent = isTimeDependent;
        setShellStyle(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.RESIZE);
        this.properties = properties;
    }

    protected void configureShell(Shell newShell) {
        commandName = properties.getProperty(UIBuilderJGrassConstants.DIALOG_TITLE);
        if (commandName != null) {
            newShell.setText(commandName);
        }

        // set the position of the shell
        Point cursorLocation = parent.getDisplay().getCursorLocation();
        cursorLocation.x = cursorLocation.x - newShell.getSize().x / 2;
        newShell.setLocation(cursorLocation);

        super.configureShell(newShell);
    }

    protected Control createDialogArea(Composite parent) {
        Composite composite = (Composite) super.createDialogArea(parent);
        Object sizeObj = properties.get(UIBuilderJGrassConstants.DIALOG_SIZE);
        GridData gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL);
        // set a width dimension if given
        if (sizeObj != null && sizeObj instanceof Point) {
            Point size = (Point) sizeObj;
            gd.widthHint = size.x;
        }
        composite.setLayoutData(gd);
        try {
            composite.setLayout(new SWTSpreadsheetLayout("B=D"));
            int childOffset = 0;
            // add the time widgets, if needed
            if (isTimeDependent) {
                childOffset = 3;
                Label startDateLabel = new Label(composite, SWT.NONE);
                startDateLabel.setLayoutData("A0");
                startDateLabel.setText("Start time");
                startDate = new DateTime(composite, SWT.DATE | SWT.MEDIUM);
                startDate.setLayoutData("B0");
                startTime = new DateTime(composite, SWT.TIME | SWT.SHORT);
                startTime.setLayoutData("C0");
                Label endDateLabel = new Label(composite, SWT.NONE);
                endDateLabel.setLayoutData("A1");
                endDateLabel.setText("End time");
                endDate = new DateTime(composite, SWT.DATE | SWT.MEDIUM);
                endDate.setLayoutData("B1");
                endTime = new DateTime(composite, SWT.TIME | SWT.SHORT);
                endTime.setLayoutData("C1");
                Label deltaLabel = new Label(composite, SWT.NONE);
                deltaLabel.setLayoutData("A2");
                deltaLabel.setText("Timestep");
                deltaText = new Text(composite, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
                deltaText.setLayoutData("B2");
                deltaText.setText("30");
                deltaText.addKeyListener(new KeyAdapter() {
                    public void keyReleased(KeyEvent e) {
                        String text = deltaText.getText();
                        try {
                            Double.parseDouble(text);
                        } catch (Exception ex) {
                            // if the text is not a positive number, reset
                            deltaText.setText("");
                        }
                    }
                });
            }

            this.guiBuilder = new UIBuilder(commandNodeList, composite, new SWTRendererFactory(), childOffset);
        } catch (Exception e) {
            UIBuilderPlugin.log(
                    "UIBuilderPlugin problem: eu.hydrologis.jgrass.uibuilder.jgrassdependent#GuiBuilderDialog#createDialogArea", //$NON-NLS-1$
                    e);
            e.printStackTrace();
        }

        return composite;
    }

    protected void createButtonsForButtonBar(Composite parent) {

        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
        createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
        /*
         * add the help button
         */
        ((GridLayout) parent.getLayout()).numColumns++;
        Button helpButton = new Button(parent, SWT.PUSH);
        Image helpImg = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_INFO_TSK);
        helpButton.setImage(helpImg);
        helpButton.setFont(JFaceResources.getDialogFont());
        helpButton.setData(new Integer(HELP_ID));
        helpButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                buttonPressed(((Integer) event.widget.getData()).intValue());
            }
        });
    }

    protected void buttonPressed(int buttonId) {
        if (buttonId == OK) {
            String commandLineRepr;
            try {
                commandLineRepr = this.guiBuilder.getCommandLineRepresentation();
                this.properties.put(UIBuilder.COMMANDLINEPROPERTY, commandLineRepr);
                if (isTimeDependent) {
                    String tmp = startDate.getYear() + "-";
                    int month = startDate.getMonth() + 1;
                    tmp = tmp + (month < 10 ? "0" + month : "" + month) + "-";
                    int day = startDate.getDay();
                    tmp = tmp + (day < 10 ? "0" + day : "" + day) + " ";
                    int hour = startTime.getHours();
                    tmp = tmp + (hour < 10 ? "0" + hour : "" + hour) + ":";
                    int minute = startTime.getMinutes();
                    tmp = tmp + (minute < 10 ? "0" + minute : "" + minute);
                    this.properties.put(UIBuilder.STARTDATEPROPERTY, tmp);

                    tmp = endDate.getYear() + "-";
                    month = endDate.getMonth() + 1;
                    tmp = tmp + (month < 10 ? "0" + month : "" + month) + "-";
                    day = endDate.getDay();
                    tmp = tmp + (day < 10 ? "0" + day : "" + day) + " ";
                    hour = endTime.getHours();
                    tmp = tmp + (hour < 10 ? "0" + hour : "" + hour) + ":";
                    minute = endTime.getMinutes();
                    tmp = tmp + (minute < 10 ? "0" + minute : "" + minute);
                    this.properties.put(UIBuilder.ENDDATEPROPERTY, tmp);

                    String timeStepString = deltaText.getText();
                    this.properties.put(UIBuilder.TIMESTEPPROPERTY, timeStepString);

                }
                close();
            } catch (MissingValueException e) {
                MessageBox m = new MessageBox(getShell(), SWT.OK);
                m.setMessage(e.getMessage());
                m.open();
            }
        } else if (buttonId == HELP_ID) {
            launchHelp();
        } else {
            close();
        }
    }

    private void launchHelp() {
        helpCommand = null;

        try {
            String basePackage = "eu.hydrologis.jgrass.models";
            String[] split = commandName.split("\\.");
            String className = basePackage;
            for (String string : split) {
                className = className + "." + string;
            }
            className = className + "." + commandName.replaceAll("\\.", "_");

            Class<?> classForName = Class.forName(className);
            Method method = classForName.getMethod("getModelDescription", null);
            Object newInstance = classForName.newInstance();
            String helpString = (String) method.invoke(newInstance, null);

            openHelpResult(helpString);
            return;
        } catch (Exception e) {
            e.printStackTrace();
            if (true)
                return;
            // ignore it and do it the usual way
        }

        StringBuilder cmdBuilder = new StringBuilder();
        cmdBuilder.append(" ");
        if (Platform.getOS().equals(Platform.OS_WIN32) && !isJGrass) {
            commandName = commandName + ".exe";
        }
        cmdBuilder.append(commandName);
        cmdBuilder.append(" --help");
        ScopedPreferenceStore m_preferences = (ScopedPreferenceStore) ConsoleEditorPlugin.getDefault()
                .getPreferenceStore();
        final String mapset = m_preferences.getString(PreferencesInitializer.CONSOLE_ARGV_MAPSET);
        final String gisbase = m_preferences.getString(PreferencesInitializer.CONSOLE_ARGV_GISBASE);
        if (isJGrass) {
            helpCommand = UIBuilderJGrassConstants.JGRASS_MODEL_ENDSPACE + cmdBuilder.toString();
        } else {
            if (gisbase == null || !(new File(gisbase).exists())) {
                MessageBox msgBox = new MessageBox(this.getShell(), SWT.ICON_ERROR);
                msgBox.setMessage("No gisbase has been defined or doesn't exist. Please check your preferences");
                msgBox.open();
                return;
            }
            helpCommand = UIBuilderJGrassConstants.GRASS_MODEL_ENDSPACE + cmdBuilder.toString();
        }

        IWorkbench wb = PlatformUI.getWorkbench();
        IProgressService ps = wb.getProgressService();
        try {
            ps.busyCursorWhile(new IRunnableWithProgress() {
                public void run(IProgressMonitor pm) {
                    pm.beginTask(commandName, IProgressMonitor.UNKNOWN);
                    ConsoleCommandExecutor c = new ConsoleCommandExecutor();

                    final StringBuilder sB = new StringBuilder();
                    OutputStream outS = new OutputStream() {
                        public void write(final int b) throws IOException {
                            sB.append(String.valueOf((char) b));
                        }
                    };
                    out = new PrintStream(outS);
                    ret = c.execute(commandName, helpCommand, mapset, gisbase,
                            ConsoleCommandExecutor.OUTPUTTYPE_SUPPLIED, out, out);
                    int waitI = 0;
                    while (ret == null && waitI++ < 50) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                    while (((Thread) ret).isAlive()) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    pm.done();

                    openHelpResult(sB.toString());
                }
            });
        } catch (Exception e1) {
            e1.printStackTrace();
        }

    }

    private void openHelpResult(final String helpString) {
        Display.getDefault().asyncExec(new Runnable() {

            public void run() {
                Dialog helpDialog = new Dialog(getShell()) {

                    protected void configureShell(Shell newShell) {
                        commandName = properties.getProperty(UIBuilderJGrassConstants.DIALOG_TITLE);
                        if (commandName != null) {
                            newShell.setText("Help for: " + commandName);
                            newShell.setSize(600, 400);
                        }

                        // set the position of the shell
                        Point cursorLocation = parent.getDisplay().getCursorLocation();
                        cursorLocation.x = cursorLocation.x - newShell.getSize().x / 2;
                        newShell.setLocation(cursorLocation);

                        super.configureShell(newShell);
                    }

                    protected Control createDialogArea(Composite parent) {
                        Composite composite = (Composite) super.createDialogArea(parent);
                        final Text text = new Text(composite,
                                SWT.READ_ONLY | SWT.WRAP | SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
                        text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
                        if (helpString.contains("Total run time")) {
                            String[] split1 = helpString.split("Running model... -------------------------------");
                            String[] split2 = split1[1].split("Total run time");
                            text.setText(split2[0].trim());
                        } else {
                            text.setText(helpString);
                        }
                        return composite;
                    }
                };

                helpDialog.open();
            }
        });
    }
}