/*************************************************************************************
* Copyright (c) 2010-2011 Red Hat, Inc. 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:
* JBoss by Red Hat - Initial implementation.
************************************************************************************/
package org.jboss.tools.runtime.ui.internal.dialogs;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressIndicator;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ColumnViewerEditor;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.TreeViewerEditor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Image;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
import org.jboss.tools.runtime.core.model.RuntimeDefinition;
import org.jboss.tools.runtime.core.model.RuntimePath;
import org.jboss.tools.runtime.core.util.RuntimeInitializerUtil;
import org.jboss.tools.runtime.core.util.RuntimeModelUtil;
import org.jboss.tools.runtime.ui.RuntimeUIActivator;
import org.jboss.tools.runtime.ui.internal.Messages;
import org.jboss.tools.runtime.ui.internal.RuntimeWorkbenchUtils;
/**
* @author snjeza
*
*/
public class SearchRuntimePathDialog extends ProgressMonitorDialog {
/*
* Moved a method from UIActivator to here bc it clearly
* didnt belong there
*/
public static SearchRuntimePathDialog launchSearchRuntimePathDialog(Shell shell,
final RuntimePath[] runtimePaths, boolean needRefresh, int heightHint) {
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
RuntimeInitializerUtil.createRuntimeDefinitions(runtimePaths, monitor);
}
};
try {
HashSet<RuntimePath> set = new HashSet<RuntimePath>(Arrays.asList(runtimePaths));
SearchRuntimePathDialog dialog = new SearchRuntimePathDialog(shell, set, needRefresh, heightHint);
dialog.run(true, true, op);
return dialog;
} catch (InvocationTargetException e1) {
RuntimeUIActivator.pluginLog().logError(e1);
} catch (InterruptedException e1) {
// ignore
}
return null;
}
private Set<RuntimePath> runtimePaths = new HashSet<RuntimePath>();
private boolean running = true;
private CheckboxTreeViewer treeViewer;
private boolean canceled;
private boolean needRefresh;
private boolean addPath;
private Label foundRuntimesLabel;
private Button hideCreatedRuntimes, addPathBtn;
private int heightHint;
public SearchRuntimePathDialog(Shell parent, Set<RuntimePath> runtimePaths, boolean needRefresh, int heightHint) {
super(parent);
setShellStyle(SWT.CLOSE | SWT.MAX | SWT.TITLE | SWT.BORDER
| SWT.APPLICATION_MODAL | SWT.RESIZE | getDefaultOrientation());
this.runtimePaths = runtimePaths;
this.needRefresh = needRefresh;
this.heightHint = heightHint;
}
/**
* Set the message in the message label.
*
* @param messageString
* The string for the new message.
* @param force
* If force is true then always set the message text.
*/
private void setMessage(String messageString, boolean force) {
// must not set null text in a label
message = messageString == null ? "" : messageString; //$NON-NLS-1$
if (messageLabel == null || messageLabel.isDisposed()) {
return;
}
if (force || messageLabel.isVisible()) {
messageLabel.setToolTipText(message);
messageLabel.setText(shortenText(message, messageLabel));
}
}
@Override
protected Control createDialogArea(Composite parent) {
getShell().setText(Messages.SearchRuntimePathDialog_Searching_for_runtimes);
Composite composite = new Composite(parent, SWT.NONE);
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.horizontalSpan = 2;
//gd.heightHint = convertVerticalDLUsToPixels(15);
gd.minimumHeight = convertVerticalDLUsToPixels(heightHint);
composite.setLayoutData(gd);
composite.setLayout(new GridLayout(1, false));
foundRuntimesLabel = new Label(composite, SWT.NONE);
gd = new GridData(GridData.FILL, SWT.FILL, true, false);
gd.horizontalSpan = 2;
foundRuntimesLabel.setLayoutData(gd);
foundRuntimesLabel.setFont(parent.getFont());
foundRuntimesLabel.setText(""); //$NON-NLS-1$
setMessage(Messages.SearchRuntimePathDialog_Searching, false);
createMessageArea(composite);
// Only set for backwards compatibility
taskLabel = messageLabel;
treeViewer = createRuntimeViewer(runtimePaths, composite, heightHint);
treeViewer.addCheckStateListener(new ICheckStateListener() {
@Override
public void checkStateChanged(CheckStateChangedEvent event) {
RuntimeDefinition definition = (RuntimeDefinition) event.getElement();
definition.setEnabled(!definition.isEnabled());
}
});
ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(treeViewer) {
protected boolean isEditorActivationEvent(
ColumnViewerEditorActivationEvent event) {
return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
|| event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
|| event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
}
};
TreeViewerEditor.create(treeViewer, actSupport,
ColumnViewerEditor.TABBING_HORIZONTAL
| ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
| ColumnViewerEditor.TABBING_VERTICAL
| ColumnViewerEditor.KEYBOARD_ACTIVATION);
// label showing current task
subTaskLabel = new Label(parent, SWT.LEFT | SWT.WRAP);
gd = new GridData(GridData.FILL, SWT.FILL, true, false);
gd.horizontalSpan = 2;
gd.heightHint = 0;
subTaskLabel.setLayoutData(gd);
subTaskLabel.setFont(parent.getFont());
// progress indicator
progressIndicator = new ProgressIndicator(parent);
gd = new GridData(GridData.FILL, SWT.FILL, true, false);
gd.horizontalSpan = 2;
gd.heightHint = 0;
progressIndicator.setLayoutData(gd);
hideCreatedRuntimes = new Button(parent, SWT.CHECK);
gd = new GridData(GridData.FILL, SWT.FILL, true, false);
gd.horizontalSpan = 2;
hideCreatedRuntimes.setLayoutData(gd);
hideCreatedRuntimes.setText(Messages.SearchRuntimePathDialog_Hide_already_created_runtimes);
hideCreatedRuntimes.setSelection(true);
hideCreatedRuntimes.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
refresh(null);
}
});
addPathBtn = new Button(parent, SWT.CHECK);
gd = new GridData(GridData.FILL, SWT.FILL, true, false);
gd.horizontalSpan = 2;
addPathBtn.setLayoutData(gd);
addPathBtn.setText(Messages.SearchRuntimePathDialog_add_path);
addPathBtn.setSelection(true);
addPath = true;
addPathBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
addPath = addPathBtn.getSelection();
}
});
super.createDialogArea(parent);
return parent;
}
public static RuntimeCheckboxTreeViewer createRuntimeViewer(final Set<RuntimePath> runtimePaths2, Composite composite, int heightHint) {
return new RuntimeCheckboxTreeViewer(composite, runtimePaths2, heightHint);
}
public boolean getAddPath() {
return addPath;
}
/* are there any definitions enabled / checked? */
private boolean anyDefinitionsChecked() {
boolean enableOk = false;
List<RuntimeDefinition> runtimeDefinitions = getRuntimeDefinitions(true);
for (RuntimeDefinition runtimeDefinition:runtimeDefinitions) {
if (runtimeDefinition.isEnabled()) {
enableOk = true;
} else {
for (RuntimeDefinition includedDefinition:runtimeDefinition.getIncludedRuntimeDefinitions()) {
if (includedDefinition.isEnabled()) {
enableOk = true;
break;
}
}
}
if (enableOk) {
break;
}
}
return enableOk;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
// OK button
Button okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
false);
okButton.setEnabled(true);
createButton(parent, IDialogConstants.SELECT_ALL_ID, Messages.SearchRuntimePathDialog_Select_All);
createButton(parent, IDialogConstants.DESELECT_ALL_ID, Messages.SearchRuntimePathDialog_Deselect_All);
// cancel button
createCancelButton(parent);
}
private Button createButton(Composite parent, int id, String label) {
Button button = createButton(parent, id, label, false);
button.setEnabled(false);
return button;
}
@Override
protected void createCancelButton(Composite parent) {
cancel = createButton(parent, IDialogConstants.CANCEL_ID,
IDialogConstants.CANCEL_LABEL, false);
if (arrowCursor == null) {
arrowCursor = new Cursor(cancel.getDisplay(), SWT.CURSOR_ARROW);
}
cancel.setCursor(arrowCursor);
setOperationCancelButtonEnabled(enableCancelButton);
}
@Override
protected void cancelPressed() {
getProgressMonitor().setCanceled(true);
if (running) {
canceled = true;
} else {
setReturnCode(CANCEL);
close();
}
}
@Override
protected void buttonPressed(int buttonId) {
super.buttonPressed(buttonId);
if (IDialogConstants.SELECT_ALL_ID == buttonId) {
selectAllPressed();
} else if (IDialogConstants.DESELECT_ALL_ID == buttonId) {
deselectAllPressed();
}
}
private void deselectAllPressed() {
setChecked(false);
}
private void setChecked(boolean checked) {
List<RuntimeDefinition> runtimeDefinitions = getRuntimeDefinitions(hideCreatedRuntimes.getSelection());
for (RuntimeDefinition definition:runtimeDefinitions) {
treeViewer.setChecked(definition, checked);
definition.setEnabled(checked);
for (RuntimeDefinition included:definition.getIncludedRuntimeDefinitions()) {
treeViewer.setChecked(included, checked);
included.setEnabled(checked);
}
}
treeViewer.refresh();
}
private void selectAllPressed() {
setChecked(true);
}
private static boolean runtimeExists(RuntimeDefinition runtimeDefinition) {
return RuntimeModelUtil.verifyRuntimeDefinitionCreated(runtimeDefinition, false);
}
private void refresh(String message) {
running = false;
treeViewer.setInput(null);
List<RuntimeDefinition> runtimeDefinitions = getRuntimeDefinitions(hideCreatedRuntimes.getSelection());
treeViewer.setInput(runtimeDefinitions);
for (RuntimeDefinition definition:runtimeDefinitions) {
treeViewer.setChecked(definition, definition.isEnabled());
for (RuntimeDefinition included:definition.getIncludedRuntimeDefinitions()) {
treeViewer.setChecked(included, included.isEnabled());
}
}
TreeItem[] treeItems = treeViewer.getTree().getItems();
for (TreeItem treeItem:treeItems) {
Object data = treeItem.getData();
if (data instanceof RuntimeDefinition) {
RuntimeDefinition runtimeDefinition = (RuntimeDefinition) data;
boolean exists = runtimeExists(runtimeDefinition);
if (exists) {
treeItem.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY));
treeViewer.setChecked(runtimeDefinition, runtimeDefinition.isEnabled());
}
}
}
if (message != null) {
setMessage(message, false);
}
}
@Override
protected void okPressed() {
getShell().setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_WAIT));
// Get the definitions to be initialized
final List<RuntimeDefinition> definitions = getEnabledRuntimeDefinitions();
getShell().setCursor(null);
setReturnCode(OK);
close();
final boolean needRefresh = this.needRefresh;
new Job(Messages.SearchRuntimePathDialog_Initializing_runtimes) {
protected IStatus run(IProgressMonitor monitor) {
IStatus ret = RuntimeInitializerUtil.initializeRuntimes(definitions);
if (needRefresh) {
// Util class runs this in ui thread
RuntimeWorkbenchUtils.refreshPreferencePage(getShell());
}
return ret;
}
}.schedule();
}
@Override
protected void finishedRun() {
if (getShell() == null || getShell().isDisposed()) {
return;
}
decrementNestingDepth();
getShell().setCursor(null);
int count = getRuntimeDefinitions(true).size();
if (count == 0) {
hideCreatedRuntimes.setSelection(false);
}
if (canceled) {
refresh(Messages.SearchRuntimePathDialog_Searching_runtimes_is_canceled);
} else {
refresh(Messages.SearchRuntimePathDialog_Searching_runtimes_is_finished);
RuntimeModelUtil.updateTimestamps(runtimePaths.toArray(new RuntimePath[runtimePaths.size()]));
}
String foundRuntimes;
if (count == 0) {
foundRuntimes = Messages.SearchRuntimePathDialog_No_runtime_found;
} else {
if (count == 1) {
foundRuntimes = NLS.bind(Messages.SearchRuntimePathDialog_New_runtime_found, count);
} else {
foundRuntimes = NLS.bind(Messages.SearchRuntimePathDialog_New_runtimes_found, count);
}
getButton(IDialogConstants.SELECT_ALL_ID).setEnabled(true);
getButton(IDialogConstants.DESELECT_ALL_ID).setEnabled(true);
}
foundRuntimesLabel.setText(foundRuntimes);
}
@Override
protected Image getImage() {
return null;
}
@Override
protected Control createMessageArea(Composite composite) {
// create message
if (messageLabel == null) {
messageLabel = new Label(composite, getMessageLabelStyle());
if( message != null ) {
messageLabel.setText(message);
}
GridDataFactory
.fillDefaults()
.align(SWT.FILL, SWT.BEGINNING)
.grab(true, false)
.applyTo(messageLabel);
}
return composite;
}
private List<RuntimeDefinition> getEnabledRuntimeDefinitions() {
List<RuntimeDefinition> all = getRuntimeDefinitions(true);
Iterator<RuntimeDefinition> i = all.iterator();
while(i.hasNext()) {
RuntimeDefinition rd = i.next();
if( !rd.isEnabled()) {
boolean add = false;
for (RuntimeDefinition ird:rd.getIncludedRuntimeDefinitions() ) {
if (ird.isEnabled()) {
add = true;
break;
}
}
if (!add) {
i.remove();
}
}
}
return all;
}
private List<RuntimeDefinition> getRuntimeDefinitions(
boolean hideCreatedRuntimes) {
List<RuntimeDefinition> runtimeDefinitions = new ArrayList<RuntimeDefinition>();
List<RuntimeDefinition> allDefinitions = RuntimeModelUtil.getAllDefinitions(runtimePaths.toArray(new RuntimePath[0]));
for (RuntimePath runtimePath : runtimePaths) {
List<RuntimeDefinition> pathDefinitions = RuntimeModelUtil.getAllDefinitions(runtimePath);
for (RuntimeDefinition runtimeDefinition : pathDefinitions) {
if (!RuntimeModelUtil.verifyRuntimeDefinitionCreated(runtimeDefinition)) {
String name = runtimeDefinition.getName();
int i = 2;
while (runtimeDefinitionExists(runtimeDefinition, allDefinitions)) {
runtimeDefinition.setName(name + " (" + i++ + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
}
for (RuntimePath runtimePath : runtimePaths) {
for (RuntimeDefinition runtimeDefinition : runtimePath.getRuntimeDefinitions()) {
if (runtimeDefinitions.contains(runtimeDefinition)) {
continue;
}
if (!hideCreatedRuntimes) {
runtimeDefinitions.add(runtimeDefinition);
} else if (!RuntimeModelUtil.verifyRuntimeDefinitionCreated(runtimeDefinition)) {
runtimeDefinitions.add(runtimeDefinition);
}
}
}
Collections.sort(runtimeDefinitions, new Comparator<RuntimeDefinition>() {
@Override
public int compare(RuntimeDefinition o1, RuntimeDefinition o2) {
if (o1 == null && o2 == null) {
return 0;
}
if (o1 == null || o1.getName() == null) {
return -1;
}
if (o2 == null) {
return 1;
}
return o1.getName().compareTo(o2.getName());
}
});
return runtimeDefinitions;
}
private boolean runtimeDefinitionExists(RuntimeDefinition runtimeDefinition,
List<RuntimeDefinition> allRuntimeDefinitions) {
String name = runtimeDefinition.getName();
File location = runtimeDefinition.getLocation();
String type = runtimeDefinition.getType();
if (name == null || location == null || type == null) {
return false;
}
String path = location.getAbsolutePath();
if (path == null) {
return false;
}
for (RuntimeDefinition definition:allRuntimeDefinitions) {
if (name.equals(definition.getName()) && type.equals(definition.getType())) {
File loc = definition.getLocation();
if (loc == null) {
continue;
}
String dPath = loc.getAbsolutePath();
if (dPath == null) {
continue;
}
if (!path.equals(dPath)) {
return true;
}
}
}
return false;
}
}