blob: f4101a701d231beb0b28c00295becb9f1eb78c03 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2017 Wojciech Sudol and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Wojciech Sudol - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.ui.examples.jobs.views;
import java.lang.reflect.InvocationTargetException;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.e4.core.contexts.Active;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.examples.jobs.TestJob;
import org.eclipse.e4.ui.examples.jobs.TestJobRule;
import org.eclipse.e4.ui.examples.jobs.UITestJob;
import org.eclipse.e4.ui.progress.IProgressConstants;
import org.eclipse.e4.ui.progress.IProgressService;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
/**
* A view that allows a user to create jobs of various types, and interact with
* and test other job-related APIs.
*/
public class JobsView {
private Combo durationField;
private Button lockField, failureField, threadField, systemField,
userField, groupField, rescheduleField, keepField, keepOneField,
unknownField, gotoActionField;
private Text quantityField, delayField, rescheduleDelay;
private Button schedulingRuleField;
private Button noPromptField;
Composite parent;
@Inject
@Optional
IProgressService progressService;
@Inject
@Optional
@Active
Shell shell;
protected void busyCursorWhile() {
try {
final long duration = getDuration();
final boolean shouldLock = lockField.getSelection();
progressService.busyCursorWhile(
new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) {
if (shouldLock)
doRunInWorkspace(duration, monitor);
else
doRun(duration, monitor);
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
// ignore - interrupt means cancel in this context
}
}
protected void createJobs() {
int jobCount = Integer.parseInt(quantityField.getText());
boolean ui = threadField.getSelection();
long duration = getDuration();
boolean lock = lockField.getSelection();
boolean failure = failureField.getSelection();
boolean noPrompt = noPromptField.getSelection();
boolean system = systemField.getSelection();
boolean useGroup = groupField.getSelection();
boolean unknown = unknownField.getSelection();
boolean user = userField.getSelection();
boolean reschedule = rescheduleField.getSelection();
final long rescheduleWait = Long.parseLong(rescheduleDelay.getText());
boolean keep = keepField.getSelection();
boolean keepOne = keepOneField.getSelection();
boolean gotoAction = gotoActionField.getSelection();
boolean schedulingRule = schedulingRuleField.getSelection();
int groupIncrement = IProgressMonitor.UNKNOWN;
IProgressMonitor group = new NullProgressMonitor();
int total = IProgressMonitor.UNKNOWN;
if (jobCount > 1) {
total = 100;
groupIncrement = 100 / jobCount;
}
if (useGroup) {
group = Job.getJobManager().createProgressGroup();
group.beginTask("Group", total); //$NON-NLS-1$
}
long delay = Integer.parseInt(delayField.getText());
for (int i = 0; i < jobCount; i++) {
Job result;
if (ui)
result = new UITestJob(duration, lock, failure, unknown);
else
result = new TestJob(duration, lock, failure, unknown,
reschedule, rescheduleWait);
result.setProperty(IProgressConstants.KEEP_PROPERTY, Boolean
.valueOf(keep));
result.setProperty(IProgressConstants.KEEPONE_PROPERTY, Boolean
.valueOf(keepOne));
result.setProperty(
IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY,
Boolean.valueOf(noPrompt));
if (gotoAction)
result.setProperty(IProgressConstants.ACTION_PROPERTY,
new Action("Pop up a dialog") { //$NON-NLS-1$
@Override
public void run() {
MessageDialog
.openInformation(
parent.getShell(),
"Goto Action", "The job can have an action associated with it"); //$NON-NLS-1$ //$NON-NLS-2$
}
});
result.setProgressGroup(group, groupIncrement);
result.setSystem(system);
result.setUser(user);
if (schedulingRule)
result.setRule(new TestJobRule(i));
result.schedule(delay);
}
}
/**
* @see ViewPart#createPartControl(Composite)
*/
@PostConstruct
public void createPartControl(Composite parent) {
this.parent = parent;
Composite body = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.makeColumnsEqualWidth = false;
body.setLayout(layout);
createEntryFieldGroup(body);
createPushButtonGroup(body);
createCheckboxGroup(body);
}
/**
* Create all push button parts for the jobs view.
*
* @param parent
*/
private void createPushButtonGroup(Composite parent) {
Composite group = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
group.setLayout(layout);
group.setLayoutData(new GridData(GridData.FILL_BOTH));
// create jobs
Button create = new Button(group, SWT.PUSH);
create.setText("Create jobs"); //$NON-NLS-1$
create
.setToolTipText("Creates and schedules jobs according to above parameters"); //$NON-NLS-1$
create.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
create.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
createJobs();
}
});
// busy cursor while
Button busyWhile = new Button(group, SWT.PUSH);
busyWhile.setText("busyCursorWhile"); //$NON-NLS-1$
busyWhile.setToolTipText("Uses IProgressService.busyCursorWhile"); //$NON-NLS-1$
busyWhile.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
busyWhile.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
busyCursorWhile();
}
});
// progress monitor dialog with fork=false
Button noFork = new Button(group, SWT.PUSH);
noFork.setText("runInUI"); //$NON-NLS-1$
noFork.setToolTipText("Uses IProgressService.runInUI"); //$NON-NLS-1$
noFork.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
noFork.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
progressNoFork();
}
});
// progress monitor dialog with fork=false
Button exception = new Button(group, SWT.PUSH);
exception.setText("Runtime Exception"); //$NON-NLS-1$
exception.setToolTipText("NullPointerException when running"); //$NON-NLS-1$
exception.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
exception.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
jobWithRuntimeException();
}
});
// join the running test jobs
Button join = new Button(group, SWT.PUSH);
join.setText("Join Test Jobs"); //$NON-NLS-1$
join.setToolTipText("IJobManager.join() on test jobs"); //$NON-NLS-1$
join.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
join.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
joinTestJobs();
}
});
// join the running test jobs
Button sleep = new Button(group, SWT.PUSH);
sleep.setText("Sleep"); //$NON-NLS-1$
sleep.setToolTipText("Calls sleep() on all TestJobs"); //$NON-NLS-1$
sleep.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
sleep.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
doSleep();
}
});
// join the running test jobs
Button wake = new Button(group, SWT.PUSH);
wake.setText("WakeUp"); //$NON-NLS-1$
wake.setToolTipText("Calls wakeUp() on all TestJobs"); //$NON-NLS-1$
wake.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
wake.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
doWakeUp();
}
});
// show in dialog
Button showInDialog = new Button(group, SWT.PUSH);
showInDialog.setText("showInDialog"); //$NON-NLS-1$
showInDialog.setToolTipText("Uses IProgressService.showInDialog"); //$NON-NLS-1$
showInDialog.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
showInDialog.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
showInDialog();
}
});
}
/**
* Test the showInDialog API
*
*/
protected void showInDialog() {
Job showJob = new Job("Show In Dialog") {//$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
SubMonitor subMonitor = SubMonitor.convert(monitor, "Run in dialog", 100);//$NON-NLS-1$
for (int i = 0; i < 100; i++) {
subMonitor.split(1);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return Status.CANCEL_STATUS;
}
}
return Status.OK_STATUS;
}
};
showJob.schedule();
progressService.showInDialog(shell, showJob);
}
/**
* Wakes up all sleeping test jobs.
*/
protected void doWakeUp() {
Job.getJobManager().wakeUp(TestJob.FAMILY_TEST_JOB);
}
/**
* Puts to sleep all waiting test jobs.
*/
protected void doSleep() {
Job.getJobManager().sleep(TestJob.FAMILY_TEST_JOB);
}
/**
* @param body
*/
private void createEntryFieldGroup(Composite body) {
// duration
Label label = new Label(body, SWT.NONE);
label.setText("Duration:"); //$NON-NLS-1$
durationField = new Combo(body, SWT.DROP_DOWN | SWT.READ_ONLY);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
durationField.setLayoutData(data);
durationField.add("0"); //$NON-NLS-1$
durationField.add("1 millisecond"); //$NON-NLS-1$
durationField.add("1 second"); //$NON-NLS-1$
durationField.add("10 seconds"); //$NON-NLS-1$
durationField.add("1 minute"); //$NON-NLS-1$
durationField.add("10 minutes"); //$NON-NLS-1$
durationField.select(4);
// delay
label = new Label(body, SWT.NONE);
label.setText("Start delay (ms):"); //$NON-NLS-1$
delayField = new Text(body, SWT.BORDER);
data = new GridData(GridData.FILL_HORIZONTAL);
data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
delayField.setLayoutData(data);
delayField.setText("0"); //$NON-NLS-1$
// quantity
label = new Label(body, SWT.NONE);
label.setText("Quantity:"); //$NON-NLS-1$
quantityField = new Text(body, SWT.BORDER);
data = new GridData(GridData.FILL_HORIZONTAL);
data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
quantityField.setLayoutData(data);
quantityField.setText("1"); //$NON-NLS-1$
// reschedule delay
label = new Label(body, SWT.NONE);
label.setText("Reschedule Delay (ms):"); //$NON-NLS-1$
rescheduleDelay = new Text(body, SWT.BORDER);
data = new GridData(GridData.FILL_HORIZONTAL);
data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
rescheduleDelay.setLayoutData(data);
rescheduleDelay.setText("1000"); //$NON-NLS-1$
}
/**
* Creates all of the checkbox buttons.
*/
private void createCheckboxGroup(Composite parent) {
Composite group = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
group.setLayout(layout);
group.setLayoutData(new GridData(GridData.FILL_BOTH));
// lock
lockField = new Button(group, SWT.CHECK);
lockField.setText("Lock the workspace"); //$NON-NLS-1$
GridData data = new GridData(GridData.FILL_HORIZONTAL);
lockField.setLayoutData(data);
// system
systemField = new Button(group, SWT.CHECK);
systemField.setText("System job"); //$NON-NLS-1$
data = new GridData(GridData.FILL_HORIZONTAL);
systemField.setLayoutData(data);
// thread
threadField = new Button(group, SWT.CHECK);
threadField.setText("Run in UI thread"); //$NON-NLS-1$
data = new GridData(GridData.FILL_HORIZONTAL);
threadField.setLayoutData(data);
// groups
groupField = new Button(group, SWT.CHECK);
groupField.setText("Run in Group"); //$NON-NLS-1$
data = new GridData(GridData.FILL_HORIZONTAL);
groupField.setLayoutData(data);
// reschedule
rescheduleField = new Button(group, SWT.CHECK);
rescheduleField.setText("Reschedule"); //$NON-NLS-1$
data = new GridData(GridData.FILL_HORIZONTAL);
rescheduleField.setLayoutData(data);
// keep
keepField = new Button(group, SWT.CHECK);
keepField.setText("Keep"); //$NON-NLS-1$
data = new GridData(GridData.FILL_HORIZONTAL);
keepField.setLayoutData(data);
// keep one
keepOneField = new Button(group, SWT.CHECK);
keepOneField.setText("KeepOne"); //$NON-NLS-1$
data = new GridData(GridData.FILL_HORIZONTAL);
keepOneField.setLayoutData(data);
// IProgressMonitor.UNKNOWN
unknownField = new Button(group, SWT.CHECK);
unknownField.setText("Indeterminate Progress"); //$NON-NLS-1$
data = new GridData(GridData.FILL_HORIZONTAL);
unknownField.setLayoutData(data);
// whether the job is a user job
userField = new Button(group, SWT.CHECK);
userField.setText("User job"); //$NON-NLS-1$
data = new GridData(GridData.FILL_HORIZONTAL);
userField.setLayoutData(data);
// whether the job has a goto action
gotoActionField = new Button(group, SWT.CHECK);
gotoActionField.setText("Goto action"); //$NON-NLS-1$
data = new GridData(GridData.FILL_HORIZONTAL);
gotoActionField.setLayoutData(data);
// whether the job should use a scheduling rule
schedulingRuleField = new Button(group, SWT.CHECK);
schedulingRuleField.setText("Schedule sequentially"); //$NON-NLS-1$
schedulingRuleField
.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// failure
failureField = new Button(group, SWT.CHECK);
failureField.setText("Fail"); //$NON-NLS-1$
failureField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// failure
noPromptField = new Button(group, SWT.CHECK);
noPromptField.setText("No Prompt"); //$NON-NLS-1$
noPromptField
.setToolTipText("Set the IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY to true");
noPromptField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
}
protected void doRun(long duration, IProgressMonitor monitor) {
final long sleep = 10;
int ticks = (int) (duration / sleep);
SubMonitor subMonitor = SubMonitor.convert(monitor,
"Spinning inside IProgressService.busyCursorWhile", ticks); //$NON-NLS-1$
subMonitor.setTaskName("Spinning inside IProgressService.busyCursorWhile"); //$NON-NLS-1$
for (int i = 0; i < ticks; i++) {
subMonitor.subTask("Processing tick #" + i); //$NON-NLS-1$
subMonitor.split(1);
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
// ignore
}
}
}
protected void doRunInWorkspace(final long duration,
IProgressMonitor monitor) {
try {
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
doRun(duration, monitor);
}
}, monitor);
} catch (CoreException e) {
e.printStackTrace();
}
}
protected long getDuration() {
switch (durationField.getSelectionIndex()) {
case 0:
return 0;
case 1:
return 1;
case 2:
return 1000;
case 3:
return 10000;
case 4:
return 60000;
case 5:
default:
return 600000;
}
}
protected void jobWithRuntimeException() {
Job runtimeExceptionJob = new Job("Job with Runtime exception") { //$NON-NLS-1$
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
throw new NullPointerException();
}
};
runtimeExceptionJob.schedule();
}
/**
* Example usage of the IJobManager.join method.
*/
protected void joinTestJobs() {
try {
// note that when a null progress monitor is used when in the UI
// thread, the workbench will create a default progress monitor
// that reports progress in a modal dialog with details area
progressService.busyCursorWhile(
new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor)
throws InterruptedException {
Job.getJobManager().join(TestJob.FAMILY_TEST_JOB,
monitor);
}
});
} catch (InterruptedException e) {
// thrown if the user interrupts the join by canceling the progress
// monitor
// A UI component should swallow the exception and finish the action
// or operation. A lower level component should just propagate the
// exception
e.printStackTrace();
} catch (InvocationTargetException e) {
// Thrown when the operation running within busyCursorWhile throws
// an
// exception. This should either be propagated or displayed to the
// user
e.printStackTrace();
}
}
protected void progressNoFork() {
try {
final long duration = getDuration();
final boolean shouldLock = lockField.getSelection();
progressService.runInUI(progressService,
new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor)
throws InterruptedException {
if (shouldLock)
doRunInWorkspace(duration, monitor);
else
doRun(duration, monitor);
}
}, ResourcesPlugin.getWorkspace().getRoot());
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* @see ViewPart#setFocus()
*/
@Focus
public void setFocus() {
if (durationField != null && !durationField.isDisposed())
durationField.setFocus();
}
}