tinyos.dlrc.jobs.InvokeMakeJob.java Source code

Java tutorial

Introduction

Here is the source code for tinyos.dlrc.jobs.InvokeMakeJob.java

Source

/*
 * Dlrc 2, NesC development in Eclipse.
 * Copyright (C) 2009 DLRC
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Web:  http://tos-ide.ethz.ch
 * Mail: tos-ide@tik.ee.ethz.ch
 */
package tinyos.dlrc.jobs;

import java.io.IOException;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import tinyos.dlrc.ProjectTOS;
import tinyos.dlrc.TinyOSConsole;
import tinyos.dlrc.TinyOSCore;
import tinyos.dlrc.TinyOSPlugin;
import tinyos.dlrc.ep.IEnvironment;
import tinyos.dlrc.ep.MakeExtra;
import tinyos.dlrc.make.IMakeTarget;
import tinyos.dlrc.nature.MissingNatureException;

/**
 * This job not only calls <code>make</code>, but also shows a dialog
 * to set extra make options. This job can loop if the make target is
 * set to {@link IMakeTarget#getLoop()}.
 */
public class InvokeMakeJob extends Job {
    private boolean shouldContinue = true;
    private IMakeTarget target;

    private boolean result = false;

    // Keys for dialog/position in preference store
    private final static String posX = "BuildTargetAsk.x";
    private final static String posY = "BuildTargetAsk.y";

    public InvokeMakeJob(IMakeTarget target) {
        super("Invoking Make");
        this.target = target;
    }

    public void execShouldContinue() {
        Display.getDefault().syncExec(new Runnable() {
            public void run() {
                IStatus ready = target.ready();
                if (ready != null) {
                    int type = -1;
                    String title = null;
                    String message = null;

                    switch (ready.getSeverity()) {
                    case IStatus.ERROR:
                        title = "Error";
                        message = "an error";
                        type = MessageDialog.ERROR;
                        break;
                    case IStatus.WARNING:
                        title = "Warning";
                        message = "a warning";
                        type = MessageDialog.WARNING;
                        break;
                    case IStatus.INFO:
                        title = "Info";
                        message = "a message";
                        type = MessageDialog.INFORMATION;
                        break;
                    }

                    if (type >= 0) {
                        message = "There is " + message + " associated with this make-option:\n\n" + "'"
                                + ready.getMessage() + "'\n\n" + "Would you like to continue anyway?";

                        MessageDialog dialog = new MessageDialog(Display.getCurrent().getActiveShell(), title, null,
                                message, type,
                                new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL }, 0);

                        if (dialog.open() != 0) {
                            shouldContinue = false;
                        }
                    }
                }
            }
        });
    }

    public void execShouldContinue(final boolean firstrun) {
        Display.getDefault().syncExec(new Runnable() {
            public void run() {
                shouldContinue = showDialogToAskForParameters(target, firstrun);
            }
        });
    }

    @Override
    public IStatus run(IProgressMonitor monitor) {
        monitor.beginTask("Make", IProgressMonitor.UNKNOWN);

        execShouldContinue();
        if (!shouldContinue) {
            monitor.done();
            return Status.CANCEL_STATUS;
        }
        execShouldContinue(true);
        if (!shouldContinue) {
            monitor.done();
            return Status.CANCEL_STATUS;
        }

        final TinyOSConsole console = TinyOSPlugin.getDefault().getConsole();

        try {
            final ProjectTOS project = TinyOSPlugin.getDefault().getProjectTOS(target.getProject());

            console.setProject(project);

            IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
                public void run(IProgressMonitor monitor) throws CoreException {
                    while (shouldContinue) {
                        ProjectTOS project = target.getProjectTOS();
                        IEnvironment environment = project.getEnvironment();

                        environment.executeMake(console.info(), console.out(), console.err(),
                                target.getProject().getLocation().toFile(), project, target, monitor);
                        // refresh project
                        project.getProject().refreshLocal(IResource.DEPTH_INFINITE, null);
                        if (monitor.isCanceled()) {
                            return;
                        }

                        if (target.getLoop()) {
                            execShouldContinue(false);
                        } else {
                            shouldContinue = false;
                        }
                    }
                }
            };
            TinyOSPlugin.getWorkspace().run(runnable, new SubProgressMonitor(monitor, 1));

            console.out().flush();
            console.err().flush();
        } catch (CoreException e) {
            return e.getStatus();
        } catch (OperationCanceledException e) {
        } catch (MissingNatureException ex) {
            TinyOSCore.inform("build", ex);
        } catch (IOException e) {
            TinyOSPlugin.log(e);
        } finally {
            monitor.done();
        }

        return Status.OK_STATUS;
    }

    private void setResult(boolean b) {
        this.result = b;
    }

    /**
     * 
     * @param target
     * @param firstrun 
     * @return
     * @return false if user hits cancel
     */
    private boolean showDialogToAskForParameters(final IMakeTarget target, boolean firstrun) {
        MakeExtra[] extras = target.getMakeExtras();

        // ------------
        final Shell dialogShell = new Shell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
        dialogShell.setLayout(new GridLayout());

        Composite top = new Composite(dialogShell, SWT.NONE);
        GridLayout topLayout = new GridLayout();
        topLayout.numColumns = 2;
        GridData topLData = new GridData();
        topLData.grabExcessHorizontalSpace = true;
        topLData.grabExcessVerticalSpace = true;
        topLData.horizontalAlignment = GridData.FILL;
        topLData.verticalAlignment = GridData.FILL;
        top.setLayoutData(topLData);
        top.setLayout(topLayout);

        Composite bottom = new Composite(dialogShell, SWT.NONE);
        final Button okButton = new Button(bottom, SWT.PUSH | SWT.CENTER);
        Button cancelButton;
        Text text2;
        Label label1;

        position(dialogShell);

        // Insert MakeExtras
        int count = 0;

        if (extras != null) {
            for (int i = 0; i < extras.length; i++) {
                final MakeExtra extra = extras[i];

                if (extra.askParameterAtCompileTime()) {
                    count++;
                    label1 = new Label(top, SWT.NONE);
                    label1.setText(extra.getName() + " - " + extra.getParameterName() + ":");

                    text2 = new Text(top, SWT.BORDER);
                    GridData text2LData = new GridData();
                    text2LData.grabExcessHorizontalSpace = true;
                    text2LData.horizontalAlignment = GridData.FILL;
                    text2.setLayoutData(text2LData);

                    String value = extra.getParameterValue();

                    text2.setText(value == null ? "" : value);
                    text2.addModifyListener(new ModifyListener() {

                        public void modifyText(ModifyEvent e) {
                            extra.setParameterValue(((Text) e.widget).getText());
                        }
                    });
                }
            }
        }

        GridLayout bottomLayout = new GridLayout();
        bottomLayout.makeColumnsEqualWidth = true;
        bottomLayout.numColumns = 2;
        GridData bottomLData = new GridData();
        bottomLData.grabExcessHorizontalSpace = true;
        bottomLData.horizontalAlignment = GridData.CENTER;
        bottom.setLayoutData(bottomLData);
        bottom.setLayout(bottomLayout);

        // show dialog with counter if no parameter is asked for
        if (count == 0) {
            if (firstrun)
                return true;

            Runnable r = new Runnable() {
                public void run() {
                    if (target.getLoopTime() > 0) {
                        final long start = System.currentTimeMillis();
                        while ((System.currentTimeMillis() - start) < (target.getLoopTime() * 1000)) {
                            try {
                                Thread.sleep(300);
                                Display.getDefault().asyncExec(new Runnable() {

                                    public void run() {
                                        if (!okButton.isDisposed()) {
                                            okButton.setText("Waiting... "
                                                    + (target.getLoopTime()
                                                            - (System.currentTimeMillis() - start) / 1000)
                                                    + " sec");
                                        }
                                    }
                                });

                            } catch (InterruptedException e1) {
                                // TODO Auto-generated catch block
                                //e1.printStackTrace();
                            }

                        }
                        Display.getDefault().asyncExec(new Runnable() {

                            public void run() {
                                if (!dialogShell.isDisposed()) {
                                    savePosition(dialogShell);
                                    dialogShell.close();
                                    setResult(true);
                                }
                            }
                        });

                    }
                }
            };

            final Thread thread = new Thread(r);
            dialogShell.setText("Waiting for next run, click to cancel");

            GridData button1LData = new GridData();
            button1LData.horizontalAlignment = GridData.CENTER;
            button1LData.widthHint = 200;
            button1LData.heightHint = 23;
            okButton.setLayoutData(button1LData);
            okButton.setText("Waiting... " + target.getLoopTime() + " sec");
            okButton.setSize(200, 23);
            okButton.addSelectionListener(new SelectionListener() {

                public void widgetSelected(SelectionEvent e) {
                    savePosition(dialogShell);
                    dialogShell.close();

                    if ((thread != null) && (thread.isAlive())) {
                        thread.interrupt();
                    }
                    setResult(false);
                }

                public void widgetDefaultSelected(SelectionEvent e) {

                }
            });

            dialogShell.setDefaultButton(okButton);
            dialogShell.layout();
            dialogShell.pack();

            dialogShell.setSize(220, dialogShell.getBounds().height);
            dialogShell.open();
            Display display = dialogShell.getDisplay();

            thread.start();

            while (!dialogShell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }

            return result;
        } else {
            dialogShell.setText("Please specify the parameter(s)");

            GridData button1LData = new GridData();
            button1LData.horizontalAlignment = GridData.CENTER;
            button1LData.widthHint = 60;
            button1LData.heightHint = 23;
            okButton.setLayoutData(button1LData);
            okButton.setText("OK");
            okButton.setSize(60, 23);
            okButton.addSelectionListener(new SelectionListener() {

                public void widgetSelected(SelectionEvent e) {
                    savePosition(dialogShell);
                    dialogShell.close();
                    setResult(true);
                }

                public void widgetDefaultSelected(SelectionEvent e) {

                }
            });

            cancelButton = new Button(bottom, SWT.PUSH | SWT.CENTER);
            GridData cancelButtonLData = new GridData();
            cancelButtonLData.widthHint = 60;
            cancelButton.setLayoutData(cancelButtonLData);
            cancelButton.setText("Cancel");
            cancelButton.addSelectionListener(new SelectionListener() {

                public void widgetSelected(SelectionEvent e) {
                    savePosition(dialogShell);
                    dialogShell.close();
                    setResult(false);
                }

                public void widgetDefaultSelected(SelectionEvent e) {
                }
            });

            dialogShell.setDefaultButton(okButton);
            dialogShell.layout();
            dialogShell.pack();

            dialogShell.setSize(300, dialogShell.getBounds().height);
            dialogShell.open();
            Display display = dialogShell.getDisplay();
            while (!dialogShell.isDisposed()) {
                if (!display.readAndDispatch())
                    display.sleep();
            }

            return result;
        }
    }

    protected void savePosition(Shell dialogShell) {
        // Save dialog position for next use
        try {
            TinyOSPlugin.getDefault().getDialogSettings().put(posY, dialogShell.getLocation().y);
            TinyOSPlugin.getDefault().getDialogSettings().put(posX, dialogShell.getLocation().x);
        } catch (Exception e) {

        }
    }

    private void position(Shell dialogShell) {
        // Set location based on saved values
        String posX_str = TinyOSPlugin.getDefault().getDialogSettings().get(posX);
        String posY_str = TinyOSPlugin.getDefault().getDialogSettings().get(posY);

        if ((posX_str != null) && (posY_str != null)) {
            dialogShell.setLocation(Integer.parseInt(posX_str), Integer.parseInt(posY_str));
        }
    }

}