org.eclipse.e4.ui.internal.progress.ProgressMonitorFocusJobDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.e4.ui.internal.progress.ProgressMonitorFocusJobDialog.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM - Initial API and implementation
 *******************************************************************************/
package org.eclipse.e4.ui.internal.progress;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.e4.ui.progress.IProgressConstants;
import org.eclipse.e4.ui.progress.WorkbenchJob;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.osgi.service.prefs.BackingStoreException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The ProgressMonitorFocusJobDialog is a dialog that shows progress for a
 * particular job in a modal dialog so as to give a user accustomed to a modal
 * UI a more familiar feel.
 */
class ProgressMonitorFocusJobDialog extends ProgressMonitorJobsDialog {

    private static final Logger logger = LoggerFactory.getLogger(ProgressMonitorFocusJobDialog.class);

    Job job;

    private boolean showDialog;

    /**
     * Create a new instance of the receiver with progress reported on the job.
     * 
     * @param parentShell
     *            The shell this is parented from.
     */
    public ProgressMonitorFocusJobDialog(Shell parentShell) {
        super(parentShell == null ? ProgressManagerUtil.getNonModalShell() : parentShell);
        setShellStyle(getDefaultOrientation() | SWT.BORDER | SWT.TITLE | SWT.RESIZE | SWT.MAX | SWT.MODELESS);
        setCancelable(true);
        enableDetailsButton = true;
    }

    @Override
    protected void cancelPressed() {
        job.cancel();
        super.cancelPressed();
    }

    @Override
    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setText(job.getName());
    }

    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        Button runInWorkspace = createButton(parent, IDialogConstants.CLOSE_ID,
                ProgressMessages.ProgressMonitorFocusJobDialog_RunInBackgroundButton, true);
        runInWorkspace.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                job.setProperty(IProgressConstants.PROPERTY_IN_DIALOG, Boolean.FALSE);
                finishedRun();
            }
        });
        runInWorkspace.setCursor(arrowCursor);

        cancel = createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
        cancel.setCursor(arrowCursor);

        createDetailsButton(parent);
    }

    /**
     * Returns a listener that will close the dialog when the job completes.
     * 
     * @return IJobChangeListener
     */
    private IJobChangeListener createCloseListener() {
        return new JobChangeAdapter() {
            @Override
            public void done(IJobChangeEvent event) {
                // first of all, make sure this listener is removed
                event.getJob().removeJobChangeListener(this);
                // nothing to do if the dialog is already closed
                if (getShell() == null) {
                    return;
                }
                WorkbenchJob closeJob = new WorkbenchJob(
                        ProgressMessages.ProgressMonitorFocusJobDialog_CLoseDialogJob) {
                    @Override
                    public IStatus runInUIThread(IProgressMonitor monitor) {
                        Shell currentShell = getShell();
                        if (currentShell == null || currentShell.isDisposed()) {
                            return Status.CANCEL_STATUS;
                        }
                        finishedRun();
                        return Status.OK_STATUS;
                    }
                };
                closeJob.setSystem(true);
                closeJob.schedule();
            }
        };
    }

    /**
     * Return the ProgressMonitorWithBlocking for the receiver.
     * 
     * @return IProgressMonitorWithBlocking
     */
    private IProgressMonitorWithBlocking getBlockingProgressMonitor() {
        return new IProgressMonitorWithBlocking() {
            @Override
            public void beginTask(String name, int totalWork) {
                final String finalName = name;
                final int finalWork = totalWork;
                runAsync(new Runnable() {
                    @Override
                    public void run() {
                        getProgressMonitor().beginTask(finalName, finalWork);
                    }
                });
            }

            @Override
            public void clearBlocked() {
                runAsync(new Runnable() {
                    @Override
                    public void run() {
                        ((IProgressMonitorWithBlocking) getProgressMonitor()).clearBlocked();
                    }
                });
            }

            @Override
            public void done() {
                runAsync(new Runnable() {
                    @Override
                    public void run() {
                        getProgressMonitor().done();
                    }
                });
            }

            @Override
            public void internalWorked(double work) {
                final double finalWork = work;
                runAsync(new Runnable() {
                    @Override
                    public void run() {
                        getProgressMonitor().internalWorked(finalWork);
                    }
                });
            }

            @Override
            public boolean isCanceled() {
                return getProgressMonitor().isCanceled();
            }

            /**
             * Run the runnable as an asyncExec if we are already open.
             * 
             * @param runnable
             */
            private void runAsync(final Runnable runnable) {

                if (alreadyClosed) {
                    return;
                }
                Shell currentShell = getShell();

                Display display;
                if (currentShell == null) {
                    display = Display.getDefault();
                } else {
                    if (currentShell.isDisposed())// Don't bother if it has
                        // been closed
                        return;
                    display = currentShell.getDisplay();
                }

                display.asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        if (alreadyClosed) {
                            return;// Check again as the async may come too
                            // late
                        }
                        Shell shell = getShell();
                        if (shell != null && shell.isDisposed())
                            return;

                        runnable.run();
                    }
                });
            }

            @Override
            public void setBlocked(IStatus reason) {
                final IStatus finalReason = reason;
                runAsync(new Runnable() {
                    @Override
                    public void run() {
                        ((IProgressMonitorWithBlocking) getProgressMonitor()).setBlocked(finalReason);
                    }
                });
            }

            @Override
            public void setCanceled(boolean value) {
                // Just a listener - doesn't matter.
            }

            @Override
            public void setTaskName(String name) {
                final String finalName = name;
                runAsync(new Runnable() {
                    @Override
                    public void run() {
                        getProgressMonitor().setTaskName(finalName);
                    }
                });
            }

            @Override
            public void subTask(String name) {
                final String finalName = name;
                runAsync(new Runnable() {
                    @Override
                    public void run() {
                        getProgressMonitor().subTask(finalName);
                    }
                });
            }

            @Override
            public void worked(int work) {
                internalWorked(work);
            }
        };
    }

    @Override
    public int open() {
        int result = super.open();

        // add a listener that will close the dialog when the job completes.
        IJobChangeListener listener = createCloseListener();
        job.addJobChangeListener(listener);
        if (job.getState() == Job.NONE) {
            // if the job completed before we had a chance to add
            // the listener, just remove the listener and return
            job.removeJobChangeListener(listener);
            finishedRun();
            cleanUpFinishedJob();
        }

        return result;
    }

    /**
     * Opens this dialog for the duration that the given job is running.
     * 
     * @param jobToWatch
     * @param originatingShell
     *            The shell this request was created from. Do not block on this
     *            shell.
     */
    public void show(Job jobToWatch, final Shell originatingShell) {
        job = jobToWatch;
        // after the dialog is opened we can get access to its monitor
        job.setProperty(IProgressConstants.PROPERTY_IN_DIALOG, Boolean.TRUE);

        ProgressManager.getInstance().progressFor(job).addProgressListener(getBlockingProgressMonitor());

        setOpenOnRun(false);
        aboutToRun();
        // start with a quick busy indicator. Lock the UI as we
        // want to preserve modality
        BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
            public void run() {
                try {
                    Thread.sleep(ProgressManagerUtil.SHORT_OPERATION_TIME);
                } catch (InterruptedException e) {
                    // Do not log as this is a common operation from the
                    // lock listener
                }
            }
        });

        WorkbenchJob openJob = new WorkbenchJob(ProgressMessages.ProgressMonitorFocusJobDialog_UserDialogJob) {
            @Override
            public IStatus runInUIThread(IProgressMonitor monitor) {

                // if the job is done at this point, we don't need the dialog
                if (job.getState() == Job.NONE) {
                    finishedRun();
                    cleanUpFinishedJob();
                    return Status.CANCEL_STATUS;
                }

                // now open the progress dialog if nothing else is
                if (!ProgressManagerUtil.safeToOpen(ProgressMonitorFocusJobDialog.this, originatingShell)) {
                    return Status.CANCEL_STATUS;
                }

                // Do not bother if the parent is disposed
                if (getParentShell() != null && getParentShell().isDisposed()) {
                    return Status.CANCEL_STATUS;
                }

                open();

                return Status.OK_STATUS;
            }
        };
        openJob.setSystem(true);
        openJob.schedule();

    }

    /**
     * The job finished before we did anything so clean up the finished
     * reference.
     */
    private void cleanUpFinishedJob() {
        ProgressManager.getInstance().checkForStaleness(job);
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Control area = super.createDialogArea(parent);
        // Give the job info as the initial details
        getProgressMonitor().setTaskName(ProgressManager.getInstance().getJobInfo(this.job).getDisplayString());
        return area;
    }

    @Override
    protected void createExtendedDialogArea(Composite parent) {

        final IEclipsePreferences preferences = DefaultScope.INSTANCE.getNode(IProgressConstants.PROPERTY_PREFIX);
        showDialog = preferences.getBoolean(IProgressConstants.RUN_IN_BACKGROUND, true);
        final Button showUserDialogButton = new Button(parent, SWT.CHECK);
        showUserDialogButton.setText(ProgressMessages.WorkbenchPreference_RunInBackgroundButton);
        showUserDialogButton.setToolTipText(ProgressMessages.WorkbenchPreference_RunInBackgroundToolTip);
        GridData gd = new GridData();
        gd.horizontalSpan = 2;
        gd.horizontalAlignment = GridData.FILL;
        showUserDialogButton.setLayoutData(gd);

        showUserDialogButton.addSelectionListener(new SelectionAdapter() {
            /*
             * (non-Javadoc)
             * 
             * @see
             * org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse
             * .swt.events.SelectionEvent)
             */
            public void widgetSelected(SelectionEvent e) {
                showDialog = !showUserDialogButton.getSelection();
                preferences.putBoolean(IProgressConstants.RUN_IN_BACKGROUND, showDialog);
                try {
                    preferences.flush();
                } catch (BackingStoreException e1) {
                    logger.error(e1.getMessage());
                }
            }
        });

        super.createExtendedDialogArea(parent);
    }

    @Override
    public boolean close() {
        return super.close();
    }
}