blob: 6400791ce5dfe2fe0e6d9febc2d64ec1cac2c144 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2013 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Ansgar Radermacher ansgar.radermacher@cea.fr
*
*****************************************************************************/
package org.eclipse.papyrus.designer.components.transformation.ui.dialogs;
import java.util.Arrays;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.papyrus.designer.components.FCM.InteractionComponent;
import org.eclipse.papyrus.designer.components.transformation.templates.ConnectorBinding;
import org.eclipse.papyrus.designer.components.transformation.ui.Activator;
import org.eclipse.papyrus.designer.languages.common.base.ElementUtils;
import org.eclipse.papyrus.designer.languages.common.base.StringConstants;
import org.eclipse.papyrus.designer.transformation.base.utils.DescriptionUtils;
import org.eclipse.papyrus.designer.transformation.base.utils.TransformationException;
import org.eclipse.papyrus.designer.transformation.ui.provider.QNameLabelProvider;
import org.eclipse.papyrus.infra.widgets.toolbox.utils.DialogUtils;
import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog;
import org.eclipse.ui.dialogs.FilteredList;
import org.eclipse.ui.dialogs.SelectionStatusDialog;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Feature;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.util.UMLUtil;
/**
* Select a connector type and implementation (group)
*
*/
public class ConnectorSelectionDialog extends AbstractElementListSelectionDialog {
protected Package m_model;
protected EList<Package> visitedPackages;
protected Text m_description;
protected Button fTypeOnly;
private EList<Class> connectorList;
private Feature m_selectedConnector;
private Object[] fUpperElements;
protected FilteredList fUpper;
protected FilteredList fLower;
private InteractionComponent initialSelection = null;
public ConnectorSelectionDialog(Shell parent, Package model, Feature selectedConnector) {
super(parent, new QNameLabelProvider());
connectorList = new BasicEList<Class>();
visitedPackages = new BasicEList<Package>();
getAllConnectors(model, selectedConnector, connectorList);
m_selectedConnector = selectedConnector;
setMultipleSelection(false);
m_model = model;
}
@Override
public Control createDialogArea(Composite parent) {
Composite contents = (Composite) super.createDialogArea(parent);
createMessageArea(contents);
// createLabel(contents, "Connector type");
GridData gridData = DialogUtils.createFillGridData();
gridData.heightHint = 200;
Group fUpperGroup = new Group(contents, SWT.NONE);
fUpperGroup.setLayout(new GridLayout());
fUpperGroup.setLayoutData(gridData);
fUpperGroup.setText(" Abstract interaction components "); //$NON-NLS-1$
createFilterText(fUpperGroup);
fUpper = createFilteredList(fUpperGroup);
final Group fLowerGroup = new Group(contents, SWT.NONE);
fLowerGroup.setLayout(new GridLayout());
fLowerGroup.setLayoutData(gridData);
fLowerGroup.setText(" Realizations/groups of interaction components "); //$NON-NLS-1$
// createLabel(contents, lowerLabel);
fLower = createFilteredList(fLowerGroup);
fFilteredList = fUpper;
org.eclipse.papyrus.designer.components.FCM.Connector fcmConnector = UMLUtil.getStereotypeApplication(m_selectedConnector, org.eclipse.papyrus.designer.components.FCM.Connector.class);
if (fcmConnector != null) {
// getInitialElementSelections();
initialSelection = fcmConnector.getIc();
} else {
initialSelection = null;
}
fTypeOnly = new Button(contents, SWT.CHECK);
fTypeOnly.setText("Select type only"); //$NON-NLS-1$
SelectionListener fTypeOnlySL = new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
if (fTypeOnly.getSelection()) {
fLower.setEnabled(false);
fLowerGroup.setEnabled(false);
fLower.setSelection(new int[0]);
fLower.setElements(null);
}
else {
fLower.setEnabled(true);
fLowerGroup.setEnabled(true);
handleSelectionChanged();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
};
fTypeOnly.addSelectionListener(fTypeOnlySL);
fUpper.setElements(connectorList.toArray());
// create initial selections
if (initialSelection instanceof InteractionComponent) {
InteractionComponent componentComp = initialSelection;
Class componentCompBase = componentComp.getBase_Class();
if (!componentCompBase.isAbstract()) {
// get first superclass that is a component type
Class componentTypeBase = ElementUtils.componentType(componentCompBase);
componentComp = UMLUtil.getStereotypeApplication(componentTypeBase, InteractionComponent.class);
} else {
// fLower.setEnabled (false);
// fLowerGroup.setEnabled(false);
fTypeOnly.setSelection(true);
}
// update status (listener does not evaluate passed data)
fTypeOnlySL.widgetSelected(null);
// set initial selections
fUpper.setSelection(new Object[] { componentComp.getBase_Class() });
}
Label info = createMessageArea(contents);
info.setText("Information about connector implementation:"); //$NON-NLS-1$
// m_description = createMessageArea(contents);
GridData descriptionGD = new GridData();
descriptionGD.horizontalAlignment = GridData.FILL;
descriptionGD.grabExcessHorizontalSpace = true;
descriptionGD.heightHint = 80;
descriptionGD.grabExcessVerticalSpace = true;
descriptionGD.verticalAlignment = GridData.FILL;
m_description = new Text(contents, SWT.NONE | SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY);
m_description.setLayoutData(descriptionGD);
fLower.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
Object[] selected = fLower.getSelection();
if ((selected.length > 0) && (selected[0] instanceof NamedElement)) {
NamedElement selectedNE = (NamedElement) selected[0];
m_description.setText(DescriptionUtils.getDescription(selectedNE));
}
else {
m_description.setText(StringConstants.EMPTY);
updateOkState();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
return contents;
}
@Override
/**
* Update the enablement of the OK button based on whether or not there
* is a selection.
*
*/
protected void updateOkState() {
if (fTypeOnly.getSelection()) {
super.updateOkState();
} else {
Button okButton = getOkButton();
if (okButton != null) {
okButton.setEnabled(fLower.getSelection().length != 0);
}
}
}
protected Label createLabel(Composite parent, String name) {
if (name == null) {
return null;
}
Label label = new Label(parent, SWT.NONE);
label.setText(name);
label.setFont(parent.getFont());
return label;
}
/**
* Creates a label if name was not <code>null</code>.
*
* @param parent
* the parent composite.
* @param name
* the name of the label.
* @return returns a label if a name was given, <code>null</code> otherwise.
*/
/**
* @see SelectionStatusDialog#computeResult()
*/
@Override
protected void computeResult() {
Object[] result = new Object[] { getSelectedElement(fTypeOnly.getSelection()) };
setResult(Arrays.asList(result));
}
/**
* @see AbstractElementListSelectionDialog#handleDefaultSelected()
*/
@Override
protected void handleDefaultSelected() {
if (validateCurrentSelection() && (getSelectedElement(false) != null)) {
buttonPressed(IDialogConstants.OK_ID);
}
}
/**
* @see AbstractElementListSelectionDialog#handleSelectionChanged()
*/
@Override
protected void handleSelectionChanged() {
handleUpperSelectionChanged();
}
private void handleUpperSelectionChanged() {
int index = getSelectionIndex();
if (index >= 0) {
fUpperElements = getFoldedElements(index);
if ((fUpperElements == null) || fTypeOnly.getSelection()) {
// lower list remains empty, if typeOnly is true
fLower.setElements(new Object[] {});
} else {
fLower.setElements(getLowerList(fUpperElements[0]));
if (initialSelection instanceof InteractionComponent) {
// select existing selection in lower section
fLower.setSelection(new Object[] { initialSelection });
// do not try to set it again.
initialSelection = null;
}
}
}
validateCurrentSelection();
}
/**
* Returns the selected element from the upper or lower pane.
*
* @return Object
*/
protected Object getSelectedElement(boolean upper) {
Object[] selection;
if (upper) {
selection = fFilteredList.getSelection();
} else {
selection = fLower.getSelection();
}
if (selection.length > 0) {
return selection[0];
}
return null;
}
protected Object[] getLowerList(Object selectedUpperObj) {
EList<Class> connectorList = new UniqueEList<Class>();
if (selectedUpperObj instanceof Class) {
visitedPackages = new BasicEList<Package>();
getImplGroups(m_model, (Class) selectedUpperObj, connectorList);
}
return connectorList.toArray();
}
void getAllConnectors(Package pkg, Feature selectedConnector, EList<Class> connectorList) {
for (Element el : pkg.getMembers()) {
if (el instanceof Package) {
if (!visitedPackages.contains(el)) {
visitedPackages.add((Package) el);
getAllConnectors((Package) el, selectedConnector, connectorList);
}
} else if (el instanceof Class) {
if (StereotypeUtil.isApplied(el, InteractionComponent.class) && ((Class) el).isAbstract()) {
if (selectedConnector == null) {
connectorList.add((Class) el);
} else {
try {
Element owner = selectedConnector.getOwner();
if (owner instanceof Class) {
Class composite = (Class) owner;
Activator.log.info("ConnectorSelectionDialog.getAllConnectors: try to bind connector " + //$NON-NLS-1$
((Class) el).getQualifiedName());
ConnectorBinding.obtainBinding(composite, selectedConnector, (Class) el, false);
connectorList.add((Class) el);
} else {
connectorList.add((Class) el);
}
} catch (TransformationException e) {
// silently ignore exception: it is normal that we cannot find a binding for some connectors
}
}
}
}
}
}
void getImplGroups(Package pkg, Class selectedConnType, EList<Class> implGroupList) {
for (Element el : pkg.getMembers()) {
if (el instanceof Package) {
if (!visitedPackages.contains(el)) {
visitedPackages.add((Package) el);
getImplGroups((Package) el, selectedConnType, implGroupList);
}
} else if (el instanceof Class) {
Class class_ = (Class) el;
if (class_.getGeneralization(selectedConnType) != null) {
implGroupList.add((Class) el);
}
}
}
}
}