/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* 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
*******************************************************************************/
package gov.redhawk.ide.sdr.ui.internal.handlers;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.databinding.Binding;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.PojoProperties;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.operation.ModalContext;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.ProgressMonitorPart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Cursor;
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.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import gov.redhawk.ide.sdr.SdrRoot;
import gov.redhawk.ide.sdr.nodebooter.DebugLevel;
import gov.redhawk.ide.sdr.nodebooter.DeviceManagerLaunchConfiguration;
import gov.redhawk.ide.sdr.nodebooter.DomainManagerLaunchConfiguration;
import gov.redhawk.ide.sdr.ui.SdrUiPlugin;
import gov.redhawk.ide.sdr.ui.navigator.LaunchDomainContentProvider;
import gov.redhawk.ide.sdr.ui.navigator.SdrNavigatorLabelProvider;
import gov.redhawk.model.sca.ScaDomainManager;
import gov.redhawk.model.sca.ScaDomainManagerRegistry;
import gov.redhawk.sca.ScaPlugin;
import gov.redhawk.sca.preferences.ScaPreferenceConstants;
import gov.redhawk.sca.ui.ScaUiPlugin;
import mil.jpeojtrs.sca.dcd.DeviceConfiguration;
public class LaunchDomainManagerWithOptionsDialog extends ElementTreeSelectionDialog {
/**
* A delay in milliseconds that reduces the risk that the user accidentally triggers a
* button by pressing the 'Enter' key immediately after a job has finished.
*
* @since 3.6
*/
private static final int RESTORE_ENTER_DELAY = 500;
private final Set<String> takenDomainNames = new HashSet<String>();
private boolean lockedUI = false;
public static final String INVALID_DOMAIN_NAME_ERR = "Please provide a valid Domain Manager name.";
public static final String NON_DEFAULT_ERR = "This name is registered against a non-default name server and cannot be launched";
public static final String DUPLICATE_NAME = "Domain of this name is in use, please select a different name.";
private WritableList<DeviceConfiguration> nodes = new WritableList<DeviceConfiguration>();
private WritableValue<DebugLevel> nodeDebugLevel = new WritableValue<DebugLevel>(DebugLevel.Info, DebugLevel.class);
private WritableValue<String> nodeArguments = new WritableValue<String>();
private final DomainManagerLaunchConfiguration model;
private final DataBindingContext context = new DataBindingContext();
private Binding nameBinding = null;
private boolean useCustomProgressMonitorPart;
private ProgressMonitorPart progressMonitorPart;
private TreeViewer treeViewer;
private int activeRunningOperations;
private long timeWhenLastJobFinished;
private Cursor waitCursor;
private Cursor arrowCursor;
private Button cancelButton;
private final SelectionListener cancelListener = new SelectionAdapter() {
@Override
public void widgetSelected(final SelectionEvent e) {
cancelPressed();
}
};
// Load the domains that are on the Naming service already
private final IRunnableWithProgress scanForTakenDomainNames = new IRunnableWithProgress() {
@Override
public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.beginTask("Scanning for running domains...", IProgressMonitor.UNKNOWN);
LaunchDomainManagerWithOptionsDialog.this.takenDomainNames.clear();
String[] names;
try {
names = ScaPlugin.findDomainNamesOnDefaultNameServer(monitor);
} catch (CoreException e) {
// Ignore errors
names = new String[0];
}
LaunchDomainManagerWithOptionsDialog.this.takenDomainNames.addAll(Arrays.asList(names));
// We also need to handle the case where the default name server doesn't have the domain name in use
// but we have a domain definition against an alternate name server...in this case you cannot use
// the domain name regardless because we cannot alter or remove the connection setting.
final String namingService = ScaUiPlugin.getDefault().getScaPreferenceStore().getString(ScaPreferenceConstants.SCA_DEFAULT_NAMING_SERVICE);
for (final ScaDomainManager dom : dmReg.getDomains()) {
if (monitor.isCanceled()) {
break;
}
if (dom != null) {
if (!namingService.equals(dom.getConnectionProperties().get(ScaDomainManager.NAMING_SERVICE_PROP))) {
// if the domain connection registry uses a different name server we cannot
// use this name regardless of the connection state because to do so would
// require us to modify the domain registry entry...which is not allowable
LaunchDomainManagerWithOptionsDialog.this.takenDomainNames.add(dom.getLabel());
}
}
}
if (nameBinding != null) {
LaunchDomainManagerWithOptionsDialog.this.nameBinding.validateTargetToModel();
}
}
};
// Load the domains that are on the Naming service already
private final IRunnableWithProgress checkDomainName = new IRunnableWithProgress() {
@Override
public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
monitor.beginTask("Checking domain name...", IProgressMonitor.UNKNOWN);
final String domainName = LaunchDomainManagerWithOptionsDialog.this.model.getDomainName();
final String namingService = ScaUiPlugin.getDefault().getScaPreferenceStore().getString(ScaPreferenceConstants.SCA_DEFAULT_NAMING_SERVICE);
final ScaDomainManager dom = dmReg.findDomain(domainName);
if (dom != null) {
if (!namingService.equals(dom.getConnectionProperties().get(ScaDomainManager.NAMING_SERVICE_PROP))) {
LaunchDomainManagerWithOptionsDialog.this.takenDomainNames.add(domainName);
}
}
// Check again just in case the domain started up since the last scan.
try {
if (ScaPlugin.isDomainOnline(domainName, monitor)) {
LaunchDomainManagerWithOptionsDialog.this.takenDomainNames.add(domainName);
}
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
LaunchDomainManagerWithOptionsDialog.this.nameBinding.validateTargetToModel();
}
};
private SdrRoot sdrRoot;
private final ScaDomainManagerRegistry dmReg;
public LaunchDomainManagerWithOptionsDialog(final Shell parentShell, final DomainManagerLaunchConfiguration model, SdrRoot root) {
super(parentShell, new SdrNavigatorLabelProvider(), new LaunchDomainContentProvider());
this.model = model;
this.sdrRoot = root;
this.dmReg = ScaPlugin.getDefault().getDomainManagerRegistry(parentShell.getDisplay());
this.setTitle("Launch Domain Manager");
setComparator(new ViewerComparator());
setEmptyListMessage("No nodes found");
setStatusLineAboveButtons(true);
super.setInput(root.getNodesContainer());
}
@Override
protected Control createDialogArea(final Composite root) {
final Composite composite = new Composite(root, SWT.NONE);
final GridLayout layout = new GridLayout();
layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
final GridLayout gridLayout = new GridLayout(3, false);
final GridDataFactory textFactory = GridDataFactory.fillDefaults().grab(true, false).span(2, 1);
final GridData data;
final Group domainManagerGroup = new Group(composite, SWT.NONE);
domainManagerGroup.setText("Domain Manager");
domainManagerGroup.setLayout(gridLayout);
domainManagerGroup.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
Label label = new Label(domainManagerGroup, SWT.NONE);
label.setText("Domain Name: ");
Text text = new Text(domainManagerGroup, SWT.BORDER);
data = textFactory.create();
data.horizontalSpan = 2;
text.setLayoutData(data);
@SuppressWarnings("unchecked")
IObservableValue< ? > domainNameObservable = PojoProperties.value(this.model.getClass(), DomainManagerLaunchConfiguration.PROP_DOMAIN_NAME).observe(this.model);
this.nameBinding = this.context.bindValue(WidgetProperties.text(SWT.Modify).observe(text), domainNameObservable,
new UpdateValueStrategy().setAfterConvertValidator(new DomainValidator()), null);
text.addModifyListener(new ModifyListener() {
@Override
public void modifyText(final ModifyEvent e) {
updateButtonsEnableState((IStatus) LaunchDomainManagerWithOptionsDialog.this.nameBinding.getValidationStatus().getValue());
}
});
label = new Label(domainManagerGroup, SWT.NONE);
label.setText("Debug Level: ");
ComboViewer debugViewer = new ComboViewer(domainManagerGroup, SWT.READ_ONLY | SWT.SINGLE | SWT.DROP_DOWN | SWT.BORDER);
debugViewer.setLabelProvider(new LabelProvider());
debugViewer.setContentProvider(new ArrayContentProvider());
debugViewer.setInput(DebugLevel.values());
debugViewer.getControl().setLayoutData(data);
@SuppressWarnings("unchecked")
IObservableValue< ? > debugLevelObservable = PojoProperties.value(this.model.getClass(), DomainManagerLaunchConfiguration.PROP_DEBUG_LEVEL).observe(
this.model);
this.context.bindValue(ViewersObservables.observeSingleSelection(debugViewer), debugLevelObservable);
label = new Label(domainManagerGroup, SWT.NONE);
label.setText("Arguments:");
text = new Text(domainManagerGroup, SWT.BORDER);
text.setLayoutData(data);
@SuppressWarnings("unchecked")
IObservableValue< ? > argumentsObservable = PojoProperties.value(this.model.getClass(), DomainManagerLaunchConfiguration.PROP_ARGUMENTS).observe(this.model);
this.context.bindValue(WidgetProperties.text(SWT.Modify).observe(text), argumentsObservable);
final Group deviceManagerGroup = new Group(composite, SWT.NONE);
deviceManagerGroup.setText("Device Manager(s)");
deviceManagerGroup.setLayout(GridLayoutFactory.fillDefaults().margins(5, 5).create());
deviceManagerGroup.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).minSize(450, 1).create());
deviceManagerGroup.setVisible(!this.sdrRoot.getNodesContainer().getNodes().isEmpty());
treeViewer = super.createTreeViewer(deviceManagerGroup);
treeViewer.getControl().setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
final Control buttonComposite = createSelectionButtons(deviceManagerGroup);
buttonComposite.setLayoutData(GridDataFactory.fillDefaults().create());
context.bindList(ViewersObservables.observeMultiPostSelection(treeViewer), nodes);
// Insert a progress monitor
this.progressMonitorPart = createProgressMonitorPart(composite, new GridLayout());
final GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
this.progressMonitorPart.setLayoutData(gridData);
this.progressMonitorPart.setVisible(false);
// Build the separator line
final Label separator = new Label(composite, SWT.HORIZONTAL | SWT.SEPARATOR);
separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Dialog.applyDialogFont(composite);
getShell().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
try {
LaunchDomainManagerWithOptionsDialog.this.run(true, true, scanForTakenDomainNames);
updateButtonsEnableState(Status.OK_STATUS);
} catch (final InvocationTargetException e) {
SdrUiPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID, "Error scanning for domain names", e));
} catch (final InterruptedException e) {
updateButtonsEnableState(Status.OK_STATUS);
}
}
});
return composite;
}
// Inner class used to check for error states in the Dialog page
class DomainValidator implements IValidator {
@Override
public IStatus validate(Object value) {
String errorMessage = null;
IStatus status = null;
// IMPORTANT - DO NOT ISSUE CORBA CALLS HERE BECAUSE THEY CAN HANG POTENTIALLY FOREVER
// AND BLOCK THE UI THREAD
String s = (String) value;
if ((s == null) || (s.trim().length() == 0)) {
errorMessage = INVALID_DOMAIN_NAME_ERR;
}
s = s.trim();
final String namingService = ScaUiPlugin.getDefault().getScaPreferenceStore().getString(ScaPreferenceConstants.SCA_DEFAULT_NAMING_SERVICE);
final ScaDomainManager dom = dmReg.findDomain(s);
if ((dom != null) && (!namingService.equals(dom.getConnectionProperties().get(ScaDomainManager.NAMING_SERVICE_PROP)))) {
errorMessage = NON_DEFAULT_ERR;
}
if (LaunchDomainManagerWithOptionsDialog.this.takenDomainNames.contains(s)) {
errorMessage = DUPLICATE_NAME;
}
if (errorMessage != null) {
status = ValidationStatus.error(errorMessage);
LaunchDomainManagerWithOptionsDialog.this.updateStatus(status);
return ValidationStatus.error(errorMessage);
}
status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK, "", null);
LaunchDomainManagerWithOptionsDialog.this.updateStatus(status);
return ValidationStatus.ok();
}
} // End DomainValidator inner class
/**
* Hook method for subclasses to create a custom progress monitor part.
* <p>
* The default implementation creates a progress monitor with a stop button will be created.
* </p>
*
* @param composite the parent composite
* @param pmlayout the layout
* @return ProgressMonitorPart the progress monitor part
*/
protected ProgressMonitorPart createProgressMonitorPart(final Composite composite, final GridLayout pmlayout) {
this.useCustomProgressMonitorPart = false;
return new ProgressMonitorPart(composite, pmlayout, true) {
private String currentTask = null;
@Override
public void setBlocked(final IStatus reason) {
super.setBlocked(reason);
if (!LaunchDomainManagerWithOptionsDialog.this.lockedUI) {
Dialog.getBlockedHandler().showBlocked(getShell(), this, reason, this.currentTask);
}
}
@Override
public void clearBlocked() {
super.clearBlocked();
if (!LaunchDomainManagerWithOptionsDialog.this.lockedUI) {
Dialog.getBlockedHandler().clearBlocked();
}
}
@Override
public void beginTask(final String name, final int totalWork) {
super.beginTask(name, totalWork);
this.currentTask = name;
}
@Override
public void setTaskName(final String name) {
super.setTaskName(name);
this.currentTask = name;
}
@Override
public void subTask(final String name) {
super.subTask(name);
// If we haven't got anything yet use this value for more context
if (this.currentTask == null) {
this.currentTask = name;
}
}
};
}
@Override
public void create() {
super.create();
updateButtonsEnableState((IStatus) LaunchDomainManagerWithOptionsDialog.this.nameBinding.getValidationStatus().getValue());
}
protected Composite createSelectionButtons(final Composite parent) {
final Composite root = new Composite(parent, SWT.NONE);
root.setLayout(new GridLayout(2, false));
final Composite subContainer = new Composite(root, SWT.NONE);
final GridLayout gridLayout = new GridLayout(2, false);
subContainer.setLayout(gridLayout);
subContainer.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
Label label = new Label(subContainer, SWT.NONE);
label.setText("Debug Level: ");
final ComboViewer debugViewer = new ComboViewer(subContainer, SWT.READ_ONLY | SWT.SINGLE | SWT.DROP_DOWN | SWT.BORDER);
debugViewer.setContentProvider(new ArrayContentProvider());
debugViewer.setInput(DebugLevel.values());
debugViewer.setSelection(new StructuredSelection("Info"));
debugViewer.getControl().setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
context.bindValue(ViewersObservables.observeSingleSelection(debugViewer), nodeDebugLevel);
label = new Label(subContainer, SWT.NONE);
label.setText("Arguments:");
Text text = new Text(subContainer, SWT.BORDER);
text.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
this.context.bindValue(WidgetProperties.text(SWT.Modify).observe(text), nodeArguments, null, null);
return root;
}
@Override
protected void okPressed() {
try {
run(true, true, checkDomainName);
} catch (final InvocationTargetException e) {
SdrUiPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID, "Error scanning for domain names", e));
} catch (final InterruptedException e) {
updateButtonsEnableState(Status.OK_STATUS);
return;
}
this.nameBinding.validateTargetToModel();
updateButtonsEnableState(Status.OK_STATUS);
// If the name isn't valid after the final scan, then abort
if (!((IStatus) this.nameBinding.getValidationStatus().getValue()).isOK()) {
return;
}
super.okPressed();
}
/**
* This implementation of IRunnableContext#run(boolean, boolean,
* IRunnableWithProgress) blocks until the runnable has been run, regardless
* of the value of <code>fork</code>. It is recommended that
* <code>fork</code> is set to true in most cases. If <code>fork</code>
* is set to <code>false</code>, the runnable will run in the UI thread
* and it is the runnable's responsibility to call
* <code>Display.readAndDispatch()</code> to ensure UI responsiveness.
*
* UI state is saved prior to executing the long-running operation and is
* restored after the long-running operation completes executing. Any
* attempt to change the UI state of the wizard in the long-running
* operation will be nullified when original UI state is restored.
*
*/
public void run(final boolean fork, final boolean cancelable, final IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException {
// The operation can only be canceled if it is executed in a separate thread.
// Otherwise the UI is blocked anyway.
getOkButton().setEnabled(false);
if (this.activeRunningOperations == 0) {
aboutToStart(fork && cancelable);
}
this.activeRunningOperations++;
try {
if (!fork) {
this.lockedUI = true;
}
ModalContext.run(runnable, fork, getProgressMonitor(), getShell().getDisplay());
this.lockedUI = false;
} finally {
// explicitly invoke done() on our progress monitor so that its
// label does not spill over to the next invocation, see bug 271530
if (getProgressMonitor() != null && getReturnCode() != Status.CANCEL) {
getProgressMonitor().done();
}
// Stop if this is the last one
this.timeWhenLastJobFinished = System.currentTimeMillis();
stopped();
this.activeRunningOperations--;
}
if (getOkButton() != null) {
getOkButton().setEnabled(true);
}
}
protected IProgressMonitor getProgressMonitor() {
return this.progressMonitorPart;
}
/**
* A long running operation triggered through the wizard was stopped either
* by user input or by normal end. Hides the progress monitor and restores
* the enable state wizard's buttons and controls.
*
* @param savedState
* the saved UI state as returned by <code>aboutToStart</code>
* @see #aboutToStart
*/
private void stopped() {
if (getShell() != null && !getShell().isDisposed()) {
if (progressMonitorPart != null) {
this.progressMonitorPart.setVisible(false);
this.progressMonitorPart.removeFromCancelComponent(this.cancelButton);
}
setDisplayCursor(null);
if (this.useCustomProgressMonitorPart) {
this.cancelButton.addSelectionListener(this.cancelListener);
this.cancelButton.setCursor(null);
this.arrowCursor.dispose();
this.arrowCursor = null;
}
if (this.waitCursor != null) {
this.waitCursor.dispose();
this.waitCursor = null;
}
}
}
/**
* Creates the buttons for this dialog's button bar.
* <p>
* The <code>WizardDialog</code> implementation of this framework method
* prevents the parent composite's columns from being made equal width in
* order to remove the margin between the Back and Next buttons.
* </p>
*
* @param parent
* the parent composite to contain the buttons
*/
@Override
protected void createButtonsForButtonBar(final Composite parent) {
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
((GridLayout) parent.getLayout()).makeColumnsEqualWidth = false;
this.cancelButton = createCancelButton(parent);
// also add cancel operation to the shell
getShell().addListener(SWT.Traverse, new Listener() {
public void handleEvent(Event event) {
switch (event.detail) {
case SWT.TRAVERSE_ESCAPE:
cancelPressed();
break;
default:
}
}
});
}
/**
* Creates the Cancel button for this wizard dialog. Creates a standard (<code>SWT.PUSH</code>)
* button and registers for its selection events. Note that the number of
* columns in the button bar composite is incremented. The Cancel button is
* created specially to give it a removeable listener.
*
* @param parent
* the parent button bar
* @return the new Cancel button
*/
private Button createCancelButton(final Composite parent) {
// increment the number of columns in the button bar
((GridLayout) parent.getLayout()).numColumns++;
final Button button = new Button(parent, SWT.PUSH);
button.setText(IDialogConstants.CANCEL_LABEL);
setButtonLayoutData(button);
button.setFont(parent.getFont());
button.setData(new Integer(IDialogConstants.CANCEL_ID));
button.addSelectionListener(this.cancelListener);
return button;
}
/**
* About to start a long running operation triggered through the wizard.
* Shows the progress monitor and disables the wizard's buttons and
* controls.
*
* @param enableCancelButton
* <code>true</code> if the Cancel button should be enabled,
* and <code>false</code> if it should be disabled
* @return the saved UI state
*/
private void aboutToStart(final boolean enableCancelButton) {
if (getShell() != null) {
// Save focus control
Control focusControl = getShell().getDisplay().getFocusControl();
if (focusControl != null && focusControl.getShell() != getShell()) {
focusControl = null;
}
// Set the busy cursor to all shells.
final Display d = getShell().getDisplay();
this.waitCursor = new Cursor(d, SWT.CURSOR_WAIT);
setDisplayCursor(this.waitCursor);
if (this.useCustomProgressMonitorPart) {
this.cancelButton.removeSelectionListener(this.cancelListener);
// Set the arrow cursor to the cancel component.
this.arrowCursor = new Cursor(d, SWT.CURSOR_ARROW);
this.cancelButton.setCursor(this.arrowCursor);
}
// Deactivate shell
// Activate cancel behavior.
if (enableCancelButton || this.useCustomProgressMonitorPart) {
this.progressMonitorPart.attachToCancelComponent(this.cancelButton);
}
this.progressMonitorPart.setVisible(true);
// Install traverse listener once in order to implement 'Enter' and 'Space' key blocking
if (this.timeWhenLastJobFinished == -1) {
this.timeWhenLastJobFinished = 0;
getShell().addTraverseListener(new TraverseListener() {
@Override
public void keyTraversed(final TraverseEvent e) {
if (e.detail == SWT.TRAVERSE_RETURN || (e.detail == SWT.TRAVERSE_MNEMONIC && e.keyCode == 32)) {
// We want to ignore the keystroke when we detect that it has been received within the
// delay period after the last operation has finished. This prevents the user from
// accidentally hitting "Enter" or "Space", intending to cancel an operation, but having it
// processed exactly when the operation finished, thus traversing the wizard. If there is
// another operation still running, the UI is locked anyway so we are not in this code. This
// listener should fire only after the UI state is restored (which by definition means all
// jobs are done.
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=287887
if (LaunchDomainManagerWithOptionsDialog.this.timeWhenLastJobFinished != 0 && System.currentTimeMillis()
- LaunchDomainManagerWithOptionsDialog.this.timeWhenLastJobFinished < LaunchDomainManagerWithOptionsDialog.RESTORE_ENTER_DELAY) {
e.doit = false;
return;
}
LaunchDomainManagerWithOptionsDialog.this.timeWhenLastJobFinished = 0;
}
}
});
}
}
}
/*
* (non-Javadoc) Method declared on Dialog.
*/
@Override
protected void cancelPressed() {
if (this.activeRunningOperations <= 0) {
// Close the dialog. The check whether the dialog can be
// closed or not is done in <code>okToClose</code>.
// This ensures that the check is also evaluated when the user
// presses the window's close button.
setReturnCode(Window.CANCEL);
close();
} else {
nameBinding.dispose();
nameBinding = null;
context.dispose();
setReturnCode(Window.CANCEL);
IProgressMonitor monitor = getProgressMonitor();
this.progressMonitorPart = null;
monitor.setCanceled(true);
stopped();
close();
}
}
/**
* Sets the given cursor for all shells currently active for this window's
* display.
*
* @param c
* the cursor
*/
private void setDisplayCursor(final Cursor c) {
final Shell[] shells = getShell().getDisplay().getShells();
for (int i = 0; i < shells.length; i++) {
shells[i].setCursor(c);
}
}
@Override
protected Control createButtonBar(final Composite parent) {
// return createButtonBarTray(parent);
return super.createButtonBar(parent);
}
/**
* Override the method so that we always return the Status of our name binding field since he is the one that
* determines the validity of the Dialog
*
* {@inheritDoc}
*/
@Override
protected void updateButtonsEnableState(final IStatus status) {
if (!treeViewer.getSelection().isEmpty()) {
StructuredSelection selection = (StructuredSelection) treeViewer.getSelection();
for (Iterator< ? > iterator = selection.iterator(); iterator.hasNext();) {
if (!(iterator.next() instanceof DeviceConfiguration)) {
super.updateButtonsEnableState(new Status(IStatus.ERROR, SdrUiPlugin.PLUGIN_ID, "", null));
return;
}
}
}
if (nameBinding != null) {
super.updateButtonsEnableState((IStatus) this.nameBinding.getValidationStatus().getValue());
}
}
public List<DeviceManagerLaunchConfiguration> getDeviceManagerLaunchConfigurations() {
List<DeviceManagerLaunchConfiguration> retVal = new ArrayList<DeviceManagerLaunchConfiguration>();
for (DeviceConfiguration dcd : this.nodes) {
DeviceManagerLaunchConfiguration conf = new DeviceManagerLaunchConfiguration(model.getDomainName(), dcd, nodeDebugLevel.getValue(),
nodeArguments.getValue(), null);
retVal.add(conf);
}
return retVal;
}
public DomainManagerLaunchConfiguration getDomainManagerLaunchConfiguration() {
return model;
}
}