package org.testng.eclipse.ui.util;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
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.graphics.Image;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.dialogs.SelectionDialog;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.StringMatcher;
import org.eclipse.ui.model.WorkbenchLabelProvider;
/**
* This class/interface
*/
public class SuiteListSelectionDialog extends SelectionDialog {
private static final String DIALOG_SETTINGS_SECTION = "ResourceListSelectionDialogSettings"; //$NON-NLS-1$
Table resourceNames;
Table folderNames;
int typeMask;
private static Collator collator = Collator.getInstance();
StringMatcher stringMatcher;
ResourceDescriptor[] descriptors;
int descriptorsSize;
WorkbenchLabelProvider labelProvider = new WorkbenchLabelProvider();
boolean okEnabled = false;
static class ResourceDescriptor implements Comparable {
String label;
ArrayList resources = new ArrayList();
boolean resourcesSorted = true;
public int compareTo(Object o) {
return collator.compare(label, ((ResourceDescriptor) o).label);
}
}
/**
* Creates a new instance of the class.
*
* @param parentShell shell to parent the dialog on
* @param resources resources to display in the dialog
*/
public SuiteListSelectionDialog(Shell parentShell, IResource[] resources) {
super(parentShell);
setShellStyle(getShellStyle() | SWT.RESIZE);
initDescriptors(resources);
}
/**
* @see org.eclipse.jface.dialogs.Dialog#cancelPressed()
*/
protected void cancelPressed() {
setResult(null);
super.cancelPressed();
}
/**
* @see org.eclipse.jface.window.Window#close()
*/
public boolean close() {
boolean result = super.close();
labelProvider.dispose();
return result;
}
/**
* @see org.eclipse.jface.window.Window#create()
*/
public void create() {
super.create();
getButton(IDialogConstants.OK_ID).setEnabled(okEnabled);
}
/**
* Creates the contents of this dialog, initializes the
* listener and the update thread.
*
* @param parent parent to create the dialog widgets in
*/
protected Control createDialogArea(Composite parent) {
Composite dialogArea = (Composite) super.createDialogArea(parent);
Label l = new Label(dialogArea, SWT.NONE);
l = new Label(dialogArea, SWT.NONE);
l.setText(IDEWorkbenchMessages.ResourceSelectionDialog_matching);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
l.setLayoutData(data);
resourceNames = new Table(dialogArea, SWT.SINGLE | SWT.BORDER
| SWT.V_SCROLL);
data = new GridData(GridData.FILL_BOTH);
data.heightHint = 12 * resourceNames.getItemHeight();
resourceNames.setLayoutData(data);
l = new Label(dialogArea, SWT.NONE);
l.setText(IDEWorkbenchMessages.ResourceSelectionDialog_folders);
data = new GridData(GridData.FILL_HORIZONTAL);
l.setLayoutData(data);
folderNames = new Table(dialogArea, SWT.SINGLE | SWT.BORDER
| SWT.V_SCROLL | SWT.H_SCROLL);
data = new GridData(GridData.FILL_BOTH);
data.widthHint = 300;
data.heightHint = 4 * folderNames.getItemHeight();
folderNames.setLayoutData(data);
resourceNames.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
updateFolders((ResourceDescriptor) e.item.getData());
}
public void widgetDefaultSelected(SelectionEvent e) {
okPressed();
}
});
folderNames.addSelectionListener(new SelectionAdapter() {
public void widgetDefaultSelected(SelectionEvent e) {
okPressed();
}
});
applyDialogFont(dialogArea);
return dialogArea;
}
/**
* Return an image for a resource descriptor.
*
* @param desc resource descriptor to return image for
* @return an image for a resource descriptor.
*/
private Image getImage(ResourceDescriptor desc) {
IResource r = (IResource) desc.resources.get(0);
return labelProvider.getImage(r);
}
private Image getParentImage(IResource resource) {
IResource parent = resource.getParent();
return labelProvider.getImage(parent);
}
private String getParentLabel(IResource resource) {
IResource parent = resource.getParent();
String text;
if (parent.getType() == IResource.ROOT) {
// Get readable name for workspace root ("Workspace"), without duplicating language-specific string here.
text = labelProvider.getText(parent);
} else {
text = parent.getFullPath().makeRelative().toString();
}
if(text == null) {
return ""; //$NON-NLS-1$
}
return text;
}
/**
* Creates a ResourceDescriptor for each IResource,
* sorts them and removes the duplicated ones.
*
* @param resources resources to create resource descriptors for
*/
private void initDescriptors(final IResource resources[]) {
BusyIndicator.showWhile(null, new Runnable() {
public void run() {
descriptors = new ResourceDescriptor[resources.length];
for (int i = 0; i < resources.length; i++) {
IResource r = resources[i];
ResourceDescriptor d = new ResourceDescriptor();
//TDB: Should use the label provider and compare performance.
d.label = r.getName();
d.resources.add(r);
descriptors[i] = d;
}
Arrays.sort(descriptors);
descriptorsSize = descriptors.length;
//Merge the resource descriptor with the same label and type.
int index = 0;
if (descriptorsSize < 2) {
return;
}
ResourceDescriptor current = descriptors[index];
IResource currentResource = (IResource) current.resources.get(0);
for (int i = 1; i < descriptorsSize; i++) {
ResourceDescriptor next = descriptors[i];
IResource nextResource = (IResource) next.resources.get(0);
if (nextResource.getType() == currentResource.getType()
&& next.label.equals(current.label)) {
current.resources.add(nextResource);
// If we are merging resources with the same name, into a single descriptor,
// then we must mark the descriptor unsorted so that we will sort the folder
// names.
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=76496
current.resourcesSorted = false;
} else {
if (current.resources.size() > 1) {
current.resourcesSorted = false;
}
descriptors[index + 1] = descriptors[i];
index++;
current = descriptors[index];
currentResource = (IResource) current.resources.get(0);
}
}
descriptorsSize = index + 1;
}
});
}
/**
* The user has selected a resource and the dialog is closing.
* Set the selected resource as the dialog result.
*/
protected void okPressed() {
TableItem items[] = folderNames.getSelection();
if (items.length == 1) {
ArrayList result = new ArrayList();
result.add(items[0].getData());
setResult(result);
}
super.okPressed();
}
/**
* Use this method to further filter resources. As resources are gathered,
* if a resource matches the current pattern string, this method will be called.
* If this method answers false, the resource will not be included in the list
* of matches and the resource's children will NOT be considered for matching.
*/
protected boolean select(IResource resource) {
return true;
}
/**
* A new resource has been selected. Change the contents
* of the folder names list.
*
* @desc resource descriptor of the selected resource
*/
private void updateFolders(final ResourceDescriptor desc) {
BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
public void run() {
if (!desc.resourcesSorted) {
// sort the folder names
Collections.sort(desc.resources, new Comparator() {
public int compare(Object o1, Object o2) {
String s1 = getParentLabel((IResource) o1);
String s2 = getParentLabel((IResource) o2);
return collator.compare(s1, s2);
}
});
desc.resourcesSorted = true;
}
folderNames.removeAll();
for (int i = 0; i < desc.resources.size(); i++) {
TableItem newItem = new TableItem(folderNames, SWT.NONE);
IResource r = (IResource) desc.resources.get(i);
newItem.setText(getParentLabel(r));
newItem.setImage(getParentImage(r));
newItem.setData(r);
}
folderNames.setSelection(0);
}
});
}
/**
* Update the specified item with the new info from the resource
* descriptor.
* Create a new table item if there is no item.
*
* @param index index of the resource descriptor
* @param itemPos position of the existing item to update
* @param itemCount number of items in the resources table widget
*/
private void updateItem(int index, int itemPos, int itemCount) {
ResourceDescriptor desc = descriptors[index];
TableItem item;
if (itemPos < itemCount) {
item = resourceNames.getItem(itemPos);
if (item.getData() != desc) {
item.setText(desc.label);
item.setData(desc);
item.setImage(getImage(desc));
if (itemPos == 0) {
resourceNames.setSelection(0);
updateFolders(desc);
}
}
} else {
item = new TableItem(resourceNames, SWT.NONE);
item.setText(desc.label);
item.setData(desc);
item.setImage(getImage(desc));
if (itemPos == 0) {
resourceNames.setSelection(0);
updateFolders(desc);
}
}
updateOKState(true);
}
protected Control createContents(Composite parent) {
Control ctrl= super.createContents(parent);
for(int i= 0; i < descriptorsSize; i++ ) {
updateItem(i, i, 0);
}
return ctrl;
}
/**
* Update the enabled state of the OK button. To be called when
* the resource list is updated.
* @param state the new enabled state of the button
*/
protected void updateOKState(boolean state) {
Button okButton = getButton(IDialogConstants.OK_ID);
if(okButton != null && !okButton.isDisposed() && state != okEnabled) {
okButton.setEnabled(state);
okEnabled = state;
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.window.Dialog#getDialogBoundsSettings()
*
* @since 3.2
*/
protected IDialogSettings getDialogBoundsSettings() {
IDialogSettings settings = IDEWorkbenchPlugin.getDefault().getDialogSettings();
IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION);
if (section == null) {
section = settings.addNewSection(DIALOG_SETTINGS_SECTION);
}
return section;
}
}