blob: bd4093a4039baa3f59836425fd600dd69a50a193 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 CEA LIST and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Nicolas Bros (Mia-Software) - Bug 372865 - FacetSet selection dialog
* Gregoire Dupe (Mia-Software) - Bug 372626 - Aggregates
* Nicolas Bros (Mia-Software) - Bug 372626 - Aggregates
*******************************************************************************/
package org.eclipse.modisco.facet.efacet.ui.internal.widget;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ICheckStateProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.modisco.facet.efacet.core.internal.exported.IResolverManager;
import org.eclipse.modisco.facet.efacet.metamodel.v0_2_0.efacet.FacetSet;
import org.eclipse.modisco.facet.efacet.ui.internal.Activator;
import org.eclipse.modisco.facet.efacet.ui.internal.Messages;
import org.eclipse.modisco.facet.efacet.ui.internal.dialogs.FacetSetTreeContentProvider;
import org.eclipse.modisco.facet.efacet.ui.internal.exported.widget.IFacetSetSelectionWidget;
import org.eclipse.modisco.facet.util.emf.ui.internal.utils.ImageUtils;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
/** A control that displays a tree of FacetSets with checkboxes to select them. */
public class FacetSetSelectionControl implements IFacetSetSelectionWidget {
/** An OK status, but without the "OK" message, because we don't want "OK" to appear in the status bar */
protected static final IStatus OK_STATUS = new Status(IStatus.OK, Activator.PLUGIN_ID, ""); //$NON-NLS-1$
protected static final String INVALID_ELEMENTS = Messages.FacetSetSelectionControl_selectionContainsInvalidElements;
protected static final String ONLY_FACET_SETS = Messages.FacetSetSelectionControl_onlyFacetSetsAllowedInSelection;
private final Composite cParent;
private CheckboxTreeViewer treeViewer;
private Collection<? extends FacetSet> available;
private final int selectionMaxSize;
private final boolean allowEmpty;
private IStatus validationStatus;
private final Runnable onChange;
private final Set<FacetSet> selected = new HashSet<FacetSet>();
/** Create a checkbox tree to select FacetSets. */
public FacetSetSelectionControl(final Composite parentComposite, final int selectionMaxSize, final boolean allowEmpty, final Runnable onChange) {
this.cParent = parentComposite;
this.selectionMaxSize = selectionMaxSize;
this.allowEmpty = allowEmpty;
this.onChange = onChange;
}
public void createContents() {
final Composite composite = new Composite(this.cParent, SWT.NONE);
composite.setLayout(new GridLayout());
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
createCheckboxTreeViewer(composite);
updateValidationStatus();
}
protected void notifyChanged() {
if (this.onChange != null) {
this.onChange.run();
}
}
public void setAvailableFacetSets(final Collection<? extends FacetSet> newAvailable) {
this.available = newAvailable;
this.treeViewer.setInput(newAvailable.toArray());
updateValidationStatus();
notifyChanged();
}
public Collection<? extends FacetSet> getAvailableFacetSets() {
return Collections.unmodifiableCollection(this.available);
}
public List<FacetSet> getSelectedFacetSets() {
return Collections.unmodifiableList(new ArrayList<FacetSet>(this.selected));
}
public void setSelectedFacetSets(final Collection<? extends FacetSet> facetSetsToSelect) {
if (facetSetsToSelect == null) {
throw new IllegalArgumentException();
}
this.selected.clear();
this.selected.addAll(facetSetsToSelect);
updateValidationStatus();
notifyChanged();
this.treeViewer.refresh();
}
public final void addCheckStateListener(final ICheckStateListener listener) {
this.treeViewer.addCheckStateListener(listener);
}
protected void createCheckboxTreeViewer(final Composite parentComposite) {
this.treeViewer = new CheckboxTreeViewer(parentComposite, SWT.BORDER);
this.treeViewer.setContentProvider(createContentProvider());
this.treeViewer.setLabelProvider(createLabelProvider());
this.treeViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
getTreeViewer().setCheckStateProvider(createCheckStateProvider());
addCheckStateListener(new ICheckStateListener() {
public void checkStateChanged(final CheckStateChangedEvent event) {
FacetSetSelectionControl.this.checkStateChanged(event);
}
});
getTreeViewer().refresh();
}
protected void checkStateChanged(final CheckStateChangedEvent event) {
handleCheckStateChange(event);
getTreeViewer().refresh();
updateValidationStatus();
notifyChanged();
}
protected void handleCheckStateChange(final CheckStateChangedEvent event) {
final Object element = event.getElement();
if (event.getElement() instanceof FacetSet) {
final FacetSet facetSet = (FacetSet) event.getElement();
FacetSet propagation = IResolverManager.DEFAULT
.selectionRoot(element, FacetSet.class);
if (propagation == null) {
propagation = facetSet;
}
if (event.getChecked()) {
this.selected.add(propagation);
} else {
this.selected.remove(propagation);
}
}
this.treeViewer.refresh();
}
protected boolean isUnderCheckedSuperPackage(final Object element) {
boolean result = false;
if (element instanceof FacetSet) {
final FacetSet facetSet = (FacetSet) element;
EObject eSuperPackage = facetSet.eContainer();
while (eSuperPackage != null) {
if (this.selected.contains(eSuperPackage)) {
result = true;
break;
}
eSuperPackage = eSuperPackage.eContainer();
}
}
return result;
}
protected ICheckStateProvider createCheckStateProvider() {
return new ICheckStateProvider() {
public boolean isGrayed(final Object element) {
return FacetSetSelectionControl.this.isGrayed(element);
}
public boolean isChecked(final Object element) {
return FacetSetSelectionControl.this.isChecked(element);
}
};
}
protected boolean isGrayed(final Object element) {
final List<FacetSet> propagation = IResolverManager.DEFAULT
.selectionPropagation(element, FacetSet.class);
boolean contains = false;
if (element instanceof EObject) {
final EObject eObject = (EObject) element;
contains = containsSelectedElement(eObject);
}
return (contains || isUnderCheckedSuperPackage(element) || propagation
.contains(element)) && !this.selected.contains(element);
}
protected boolean containsSelectedElement(final EObject eObject) {
boolean contains = false;
final Iterator<EObject> iterator = eObject.eAllContents();
while (iterator.hasNext()) {
final EObject subObject = iterator.next();
contains = this.selected.contains(subObject);
if (contains) {
break;
}
}
return contains;
}
protected boolean isChecked(final Object element) {
// This "|| isGrayed(element)" has been added avoid problems with
// Windows 7.
return this.selected.contains(element) || isGrayed(element);
}
protected void updateValidationStatus() {
if (this.treeViewer == null) {
return;
}
final Object[] checkedElements = this.treeViewer.getCheckedElements();
IStatus newStatus = FacetSetSelectionControl.OK_STATUS;
if (!this.allowEmpty && checkedElements.length == 0) {
newStatus = new Status(IStatus.ERROR, Activator.PLUGIN_ID, NLS.bind(Messages.FacetSetSelectionControl_mustSelectAtLeastOneElement,
Integer.valueOf(this.selectionMaxSize)));
} else if (checkedElements.length > this.selectionMaxSize) {
newStatus = new Status(IStatus.ERROR, Activator.PLUGIN_ID, NLS.bind(Messages.FacetSetSelectionControl_mustSelectAtMostNElements,
Integer.valueOf(this.selectionMaxSize)));
} else {
for (final Object checkedElement : checkedElements) {
final IStatus elementStatus = validateElement(checkedElement);
if (elementStatus.getSeverity() >= IStatus.ERROR) {
newStatus = elementStatus;
break;
}
}
}
setValidationStatus(newStatus);
}
protected static IStatus validateElement(final Object checkedElement) {
IStatus status = FacetSetSelectionControl.OK_STATUS;
if (!(checkedElement instanceof FacetSet)) {
status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, FacetSetSelectionControl.ONLY_FACET_SETS);
}
return status;
}
protected boolean isAvailable(final FacetSet facetSet) {
boolean bAvailable = false;
if (this.available.contains(facetSet)) {
bAvailable = true;
} else {
EPackage parent = facetSet.getESuperPackage();
while (parent != null) {
if (this.available.contains(parent)) {
bAvailable = true;
break;
}
parent = parent.getESuperPackage();
}
}
return bAvailable;
}
protected void setValidationStatus(final IStatus status) {
this.validationStatus = status;
}
public IStatus getValidationStatus() {
return this.validationStatus;
}
public boolean isErrorStatus() {
return this.validationStatus == null || this.validationStatus.getSeverity() >= IStatus.ERROR;
}
protected ILabelProvider createLabelProvider() {
return new LabelProvider() {
@Override
public String getText(final Object element) {
String text;
if (element instanceof ENamedElement) {
final ENamedElement namedElement = (ENamedElement) element;
text = namedElement.getName();
} else {
text = super.getText(element);
}
return text;
}
@Override
public Image getImage(final Object element) {
return ImageUtils.getImage(element);
}
};
}
// @SuppressWarnings("static-method") : meant to be overridden
@SuppressWarnings("static-method")
protected IContentProvider createContentProvider() {
return new FacetSetTreeContentProvider(false, true, true);
}
public CheckboxTreeViewer getTreeViewer() {
return this.treeViewer;
}
public boolean isDisposed() {
return this.treeViewer.getTree().isDisposed();
}
public void selectAll() {
this.selected.clear();
this.selected.addAll(this.available);
this.treeViewer.refresh();
}
public void deselectAll() {
this.selected.clear();
this.treeViewer.refresh();
}
public Control getControl() {
Control control = null;
if (this.treeViewer != null) {
control = this.treeViewer.getTree();
}
return control;
}
}