/*******************************************************************************
* Copyright (c) 2000, 2011 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 Corporation - initial API and implementation
* William Chen (Wind River) [354578] Add support for working sets
*******************************************************************************/
package org.eclipse.tm.te.ui.views.workingsets.pages;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.WizardPage;
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.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.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.tm.te.runtime.interfaces.workingsets.IWorkingSetElement;
import org.eclipse.tm.te.ui.views.nls.Messages;
import org.eclipse.tm.te.ui.views.workingsets.WorkingSetElementHolder;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.IWorkingSetPage;
/**
* A tree viewer on the left is used to show the workspace content, a table viewer on the right is
* used to show the working set content. Buttons to move content from right to left and vice versa
* are available between the two viewers. A text field allows to set/change the working sets name.
* <p>
* Copied and adapted from <code>org.eclipse.jdt.internal.ui.workingsets.AbstractWorkingSetWizardPage</code>.
*/
public abstract class AbstractWorkingSetWizardPage extends WizardPage implements IWorkingSetPage {
final class AddedElementsFilter extends ViewerFilter {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
return !selectedElements.contains(element);
}
}
/* default */ Text workingSetNameControl;
/* default */ TreeViewer tree;
/* default */ TableViewer table;
/* default */ ITreeContentProvider treeContentProvider;
/* default */ boolean firstCheck;
/* default */ final HashSet<Object> selectedElements;
/* default */ IWorkingSet workingSet;
/**
* Constructor.
*
* @param pageName
* @param title
* @param titleImage
*/
protected AbstractWorkingSetWizardPage(String pageName, String title, ImageDescriptor titleImage) {
super(pageName, title, titleImage);
selectedElements = new HashSet<Object>();
firstCheck = true;
}
/**
* Returns the page id as specified in the extension point.
*
* @return the page id
*/
protected abstract String getPageId();
/**
* Configure the tree viewer used on the left side of the dialog.
*
* Implementors must set:
* <ul>
* <li>The content provider</li>
* <li>The label provider</li>
* <li>The viewers input</li>
* </ul>
* They may also set:
* <ul>
* <li>The viewer comparator</li>
* <li>Any viewer filter</li>
* <li>The selection</li>
* </ul>
*
* @param tree
* the tree to configure
*/
protected abstract void configureTree(TreeViewer tree);
/**
* Configure the table viewer used on the right side of the dialog.
*
* Implementors must set:
* <ul>
* <li>The label provider</li>
* </ul>
* They may also set:
* <ul>
* <li>The viewer comparator</li>
* </ul>
* They must not set:
* <ul>
* <li>The viewers content provider</li>
* <li>The viewers input</li>
* <li>Any viewer filter</li>
* </ul>
*
* @param table
* the table to configure
*/
protected abstract void configureTable(TableViewer table);
/**
* Returns the elements which are shown in the table initially. Return an
* empty array if the table should be empty. The given working set is the
* working set which will be configured by this dialog, or <b>null</b> if it
* does not yet exist.
*
* @param workingSet
* the working set to configure or <b>null</b> if not yet exist
* @return the elements to show in the table
*/
protected abstract Object[] getInitialWorkingSetElements(IWorkingSet workingSet);
/*
* @see
* org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
* .Composite)
*/
@Override
public void createControl(Composite parent) {
initializeDialogUnits(parent);
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout());
composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
setControl(composite);
Label label = new Label(composite, SWT.WRAP);
label.setText(Messages.TargetWorkingSetPage_workingSet_name);
GridData gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);
label.setLayoutData(gd);
workingSetNameControl = new Text(composite, SWT.SINGLE | SWT.BORDER);
workingSetNameControl.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
workingSetNameControl.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
validateInput();
}
});
Composite leftCenterRightComposite = new Composite(composite, SWT.NONE);
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.heightHint = convertHeightInCharsToPixels(20);
leftCenterRightComposite.setLayoutData(gridData);
GridLayout gridLayout = new GridLayout(3, false);
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
leftCenterRightComposite.setLayout(gridLayout);
Composite leftComposite = new Composite(leftCenterRightComposite, SWT.NONE);
gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.widthHint = convertWidthInCharsToPixels(40);
leftComposite.setLayoutData(gridData);
gridLayout = new GridLayout(1, false);
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
leftComposite.setLayout(gridLayout);
Composite centerComposite = new Composite(leftCenterRightComposite, SWT.NONE);
gridLayout = new GridLayout(1, false);
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
centerComposite.setLayout(gridLayout);
centerComposite.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, false, false));
Composite rightComposite = new Composite(leftCenterRightComposite, SWT.NONE);
gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.widthHint = convertWidthInCharsToPixels(40);
rightComposite.setLayoutData(gridData);
gridLayout = new GridLayout(1, false);
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
rightComposite.setLayout(gridLayout);
createTree(leftComposite);
createTable(rightComposite);
if (workingSet != null)
workingSetNameControl.setText(workingSet.getName());
initializeSelectedElements();
validateInput();
table.setInput(selectedElements);
table.refresh(true);
tree.refresh(true);
createButtonBar(centerComposite);
workingSetNameControl.setFocus();
workingSetNameControl.setSelection(0, workingSetNameControl.getText().length());
Dialog.applyDialogFont(composite);
}
private void createTree(Composite parent) {
Label label = new Label(parent, SWT.NONE);
label.setLayoutData(new GridData(SWT.LEAD, SWT.CENTER, false, false));
label.setText(Messages.TargetWorkingSetPage_workspace_content);
tree = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI);
tree.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
tree.addFilter(new AddedElementsFilter());
tree.setUseHashlookup(true);
configureTree(tree);
treeContentProvider = (ITreeContentProvider) tree.getContentProvider();
}
private void createButtonBar(Composite parent) {
Label spacer = new Label(parent, SWT.NONE);
spacer.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
final Button addButton = new Button(parent, SWT.PUSH);
addButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
addButton.setText(Messages.TargetWorkingSetPage_add_button);
addButton.setEnabled(!tree.getSelection().isEmpty());
final Button addAllButton = new Button(parent, SWT.PUSH);
addAllButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
addAllButton.setText(Messages.TargetWorkingSetPage_addAll_button);
addAllButton.setEnabled(tree.getTree().getItems().length > 0);
final Button removeButton = new Button(parent, SWT.PUSH);
removeButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
removeButton.setText(Messages.TargetWorkingSetPage_remove_button);
removeButton.setEnabled(!table.getSelection().isEmpty());
final Button removeAllButton = new Button(parent, SWT.PUSH);
removeAllButton.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, false, false));
removeAllButton.setText(Messages.TargetWorkingSetPage_removeAll_button);
removeAllButton.setEnabled(!selectedElements.isEmpty());
tree.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
addButton.setEnabled(!event.getSelection().isEmpty());
}
});
addButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
addTreeSelection();
removeAllButton.setEnabled(true);
addAllButton.setEnabled(tree.getTree().getItems().length > 0);
}
});
tree.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
addTreeSelection();
removeAllButton.setEnabled(true);
addAllButton.setEnabled(tree.getTree().getItems().length > 0);
}
});
table.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
removeButton.setEnabled(!event.getSelection().isEmpty());
}
});
removeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
removeTableSelection();
addAllButton.setEnabled(true);
removeAllButton.setEnabled(!selectedElements.isEmpty());
}
});
table.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
removeTableSelection();
addAllButton.setEnabled(true);
removeAllButton.setEnabled(!selectedElements.isEmpty());
}
});
addAllButton.addSelectionListener(new SelectionAdapter() {
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected(SelectionEvent e) {
TreeItem[] items = tree.getTree().getItems();
for (int i = 0; i < items.length; i++) {
selectedElements.add(items[i].getData());
}
table.refresh();
tree.refresh();
addAllButton.setEnabled(false);
removeAllButton.setEnabled(true);
}
});
removeAllButton.addSelectionListener(new SelectionAdapter() {
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
@Override
public void widgetSelected(SelectionEvent e) {
selectedElements.clear();
table.refresh();
tree.refresh();
removeAllButton.setEnabled(false);
addAllButton.setEnabled(true);
}
});
}
/**
* Moves selected elements in the tree into the table
*/
void addTreeSelection() {
IStructuredSelection selection = (IStructuredSelection) tree.getSelection();
selectedElements.addAll(selection.toList());
Object[] selectedElements = selection.toArray();
table.add(selectedElements);
tree.remove(selectedElements);
table.setSelection(selection);
table.getControl().setFocus();
validateInput();
}
/**
* Moves the selected elements in the table into the tree
*/
void removeTableSelection() {
IStructuredSelection selection = (IStructuredSelection) table.getSelection();
selectedElements.removeAll(selection.toList());
Object[] selectedElements = selection.toArray();
table.remove(selectedElements);
try {
tree.getTree().setRedraw(false);
for (int i = 0; i < selectedElements.length; i++) {
tree.refresh(treeContentProvider.getParent(selectedElements[i]), true);
}
} finally {
tree.getTree().setRedraw(true);
}
tree.setSelection(selection);
tree.getControl().setFocus();
validateInput();
}
private void createTable(Composite parent) {
Label label = new Label(parent, SWT.WRAP);
label.setText(Messages.TargetWorkingSetPage_workingSet_content);
label.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
table = new TableViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI);
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
table.getControl().setLayoutData(gd);
table.setUseHashlookup(true);
configureTable(table);
table.setContentProvider(new IStructuredContentProvider() {
@Override
public Object[] getElements(Object inputElement) {
return selectedElements.toArray();
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
});
}
/*
* Implements method from IWorkingSetPage
*/
@Override
public IWorkingSet getSelection() {
return workingSet;
}
/*
* Implements method from IWorkingSetPage
*/
@Override
public void setSelection(IWorkingSet workingSet) {
Assert.isNotNull(workingSet, "Working set must not be null"); //$NON-NLS-1$
this.workingSet = workingSet;
if (getContainer() != null && getShell() != null && workingSetNameControl != null) {
firstCheck = false;
workingSetNameControl.setText(workingSet.getName());
initializeSelectedElements();
validateInput();
}
}
/*
* Implements method from IWorkingSetPage
*/
@Override
public void finish() {
String workingSetName = workingSetNameControl.getText();
List<IAdaptable> elements = new ArrayList<IAdaptable>();
for (Object candidate : selectedElements) {
if (candidate instanceof IWorkingSetElement) {
WorkingSetElementHolder holder = new WorkingSetElementHolder(workingSetName, ((IWorkingSetElement)candidate).getElementId());
holder.setElement((IWorkingSetElement)candidate);
elements.add(holder);
}
}
if (workingSet == null) {
IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
workingSet = workingSetManager.createWorkingSet(workingSetName, elements.toArray(new IAdaptable[elements.size()]));
workingSet.setId(getPageId());
} else {
workingSet.setName(workingSetName);
workingSet.setElements(elements.toArray(new IAdaptable[elements.size()]));
}
}
void validateInput() {
String errorMessage = null;
String infoMessage = null;
String newText = workingSetNameControl.getText();
if (newText.equals(newText.trim()) == false)
errorMessage = Messages.TargetWorkingSetPage_warning_nameWhitespace;
if (newText.equals("")) { //$NON-NLS-1$
if (firstCheck) {
setPageComplete(false);
firstCheck = false;
return;
}
errorMessage = Messages.TargetWorkingSetPage_warning_nameMustNotBeEmpty;
}
firstCheck = false;
if (errorMessage == null && (workingSet == null || newText.equals(workingSet.getName()) == false)) {
IWorkingSet[] workingSets = PlatformUI.getWorkbench().getWorkingSetManager().getAllWorkingSets();
for (int i = 0; i < workingSets.length; i++) {
if (newText.equals(workingSets[i].getName())) {
errorMessage = Messages.TargetWorkingSetPage_warning_workingSetExists;
}
}
}
if (!hasSelectedElement())
infoMessage = Messages.TargetWorkingSetPage_warning_resourceMustBeChecked;
setMessage(infoMessage, INFORMATION);
setErrorMessage(errorMessage);
setPageComplete(errorMessage == null);
}
private boolean hasSelectedElement() {
return !selectedElements.isEmpty();
}
private void initializeSelectedElements() {
selectedElements.addAll(Arrays.asList(getInitialWorkingSetElements(workingSet)));
}
}