blob: fe60f67dbb3d1beda1a2d3446e485586cac70a2d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* 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:
******************************************************************************/
package org.eclipse.emf.ecp.editor.mecontrols.melinkcontrol.associationclasscontrol;
import java.util.List;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecp.common.model.ECPAssociationClassElement;
import org.eclipse.emf.ecp.common.model.ECPModelelementContext;
import org.eclipse.emf.ecp.common.model.workSpaceModel.util.AssociationClassHelper;
import org.eclipse.emf.ecp.common.utilities.ModelElementClassTooltip;
import org.eclipse.emf.ecp.common.utilities.ShortLabelProvider;
import org.eclipse.emf.ecp.editor.ControlFactory;
import org.eclipse.emf.ecp.editor.ModelElementChangeListener;
import org.eclipse.emf.ecp.editor.mecontrols.AbstractMEControl;
import org.eclipse.emf.ecp.editor.mecontrols.melinkcontrol.MEHyperLinkAdapter;
import org.eclipse.emf.ecp.editor.mecontrols.melinkcontrol.MEHyperLinkDeleteAdapter;
import org.eclipse.emf.ecp.editor.mecontrols.melinkcontrol.MELinkControl;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IDecoratorManager;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
/**
* This is the association widget. It is displayed instead of the reference to the AssociationClassElement. The other
* side of the association is displayed and in addition a widget if the AssociationClassElement has only one feature to
* setup else the link to the association.
*
* @author Michael Haeger
*/
public class AssociationClassLink extends MELinkControl {
private static final int PRIORITY = 2;
private Composite composite;
private ILabelProvider labelProvider;
private ImageHyperlink imgHyperlink;
private Hyperlink hyperlink;
private Image deleteImage;
private ModelElementChangeListener meChangeListener;
private ModelElementChangeListener associationChangeListener;
private IHyperlinkListener linkToMEListener;
private MEHyperLinkDeleteAdapter delAssociationListener;
private EObject association;
private EObject modelElement;
private EObject relatedModelElement;
private List<EStructuralFeature> eAttribute;
private ShortLabelProvider shortLabelProvider = new ShortLabelProvider();
private EReference eReference;
private Composite parent;
private ComposedAdapterFactory adapterFactory;
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecp.editor.mecontrols.melinkcontrol.MELinkControl#canRender(org.eclipse.emf.edit.provider.IItemPropertyDescriptor,
* org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EObject)
*/
@Override
public int canRender(IItemPropertyDescriptor itemPropertyDescriptor, EObject link, EObject contextModelElement) {
Object ref = itemPropertyDescriptor.getFeature(contextModelElement);
if (getContext() != null) {
if (getContext().getMetaModelElementContext().isAssociationClassElement(link) && ref instanceof EReference) {
ECPAssociationClassElement association = getContext().getMetaModelElementContext()
.getAssociationClassElement(link);
if (association.getSourceFeature().equals(((EReference) ref).getEOpposite())
|| association.getTargetFeature().equals(((EReference) ref).getEOpposite())) {
return PRIORITY;
}
}
}
return AbstractMEControl.DO_NOT_RENDER;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecp.editor.mecontrols.melinkcontrol.MELinkControl#createControl(org.eclipse.swt.widgets.Composite,
* int, org.eclipse.emf.edit.provider.IItemPropertyDescriptor, org.eclipse.emf.ecore.EObject,
* org.eclipse.emf.ecore.EObject, org.eclipse.ui.forms.widgets.FormToolkit,
* org.eclipse.emf.ecp.model.ECPModelelementContext)
*/
@Override
public Control createControl(final Composite parent, int style, IItemPropertyDescriptor itemPropertyDescriptor,
final EObject link, EObject contextModelElement, FormToolkit toolkit, ECPModelelementContext context) {
association = link;
modelElement = contextModelElement;
eReference = (EReference) itemPropertyDescriptor.getFeature(association);
eAttribute = AssociationClassHelper.getAssociationFeatures(association, context.getMetaModelElementContext());
setToolkit(toolkit);
setContext(context);
this.parent = parent;
// create components
createComponents(parent, style);
// set all values that depends on other elements
setupComponents();
return composite;
}
private boolean setupComponents() {
boolean changed = false;
if (composite != null && !composite.isDisposed()) {
EObject newRelatedModelElement = AssociationClassHelper.getRelatedModelElement(modelElement, association,
getContext());
// check whether it is a new linked goal
if (newRelatedModelElement != null && !newRelatedModelElement.equals(relatedModelElement)) {
// new goal
relatedModelElement = newRelatedModelElement;
// remove old listeners
if (linkToMEListener != null) {
imgHyperlink.removeHyperlinkListener(linkToMEListener);
hyperlink.removeHyperlinkListener(linkToMEListener);
}
// add new listeners
linkToMEListener = new MEHyperLinkAdapter(relatedModelElement, modelElement, eReference.getName());
imgHyperlink.addHyperlinkListener(linkToMEListener);
hyperlink.addHyperlinkListener(linkToMEListener);
if (meChangeListener != null) {
meChangeListener.remove();
}
meChangeListener = new AssociationChangeListener(relatedModelElement);
} else if (newRelatedModelElement == null && relatedModelElement != null) {
// link to goal is removed so remove listener
relatedModelElement = newRelatedModelElement;
imgHyperlink.removeHyperlinkListener(linkToMEListener);
hyperlink.removeHyperlinkListener(linkToMEListener);
}
if (relatedModelElement != null) {
// create components for linked goal
imgHyperlink.setData(relatedModelElement.eClass());
String text = shortLabelProvider.getText(relatedModelElement);
hyperlink.setText(text);
hyperlink.setToolTipText(text);
} else {
imgHyperlink.setData(null);
hyperlink.setToolTipText("NULL");
hyperlink.setText("NULL");
}
imgHyperlink.setImage(labelProvider.getImage(relatedModelElement));
changed = true;
}
return changed;
}
private void createComponents(final Composite parent, int style) {
composite = getToolkit().createComposite(parent, style);
composite.setLayout(new GridLayout(5, false));
// handle element deletion
delAssociationListener = new MEHyperLinkDeleteAdapter(modelElement, eReference, association, getContext());
// listen for changes of the goal reference instance
associationChangeListener = new AssociationChangeListener(association);
adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
AdapterFactoryLabelProvider adapterFactoryLabelProvider = new AdapterFactoryLabelProvider(adapterFactory);
IDecoratorManager decoratorManager = PlatformUI.getWorkbench().getDecoratorManager();
labelProvider = new DecoratingLabelProvider(adapterFactoryLabelProvider, decoratorManager.getLabelDecorator());
imgHyperlink = getToolkit().createImageHyperlink(composite, style);
ModelElementClassTooltip.enableFor(imgHyperlink);
hyperlink = getToolkit().createHyperlink(composite, "", style);
if (eAttribute.size() == 1) {
ControlFactory controlFactory = new ControlFactory();
ItemPropertyDescriptor itemPropertyDescriptor = new ItemPropertyDescriptor(null, "", "", eAttribute.get(0));
AbstractMEControl meControl = controlFactory.createControl(itemPropertyDescriptor, association,
getContext());
meControl.createControl(composite, style, itemPropertyDescriptor, association, getContext(), getToolkit());
} else if (eAttribute.size() > 1) {
Hyperlink associationLink = getToolkit().createHyperlink(composite, "[edit]", style);
associationLink
.addHyperlinkListener(new MEHyperLinkAdapter(association, modelElement, eReference.getName()));
}
if (eReference.isContainment()
&& (getContext().getMetaModelElementContext().isNonDomainElement(association.eClass()))) {
deleteImage = org.eclipse.emf.ecp.common.Activator.getImageDescriptor("icons/delete.gif").createImage();
} else {
deleteImage = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_DELETE);
}
ImageHyperlink delHyperlink = getToolkit().createImageHyperlink(composite, style);
delHyperlink.setImage(deleteImage);
delHyperlink.addMouseListener(delAssociationListener);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.emf.ecp.editor.mecontrols.melinkcontrol.MELinkControl#dispose()
*/
@Override
public void dispose() {
if (meChangeListener != null) {
meChangeListener.remove();
}
if (associationChangeListener != null) {
associationChangeListener.remove();
}
if (labelProvider != null) {
labelProvider.dispose();
}
if (composite != null) {
composite.dispose();
}
if (adapterFactory != null) {
adapterFactory.dispose();
}
super.dispose();
}
/**
* Change listener to rebuild links if content changes.
*
* @author Michael Haeger
*/
private class AssociationChangeListener extends ModelElementChangeListener {
public AssociationChangeListener(EObject modelElement) {
super(modelElement);
}
@Override
public void onChange(Notification notification) {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// if something changes do layouts again
if (setupComponents()) {
composite.pack();
composite.layout(true);
parent.getParent().layout(true);
}
}
});
}
}
}