| /******************************************************************************* |
| * 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); |
| } |
| } |
| }); |
| } |
| } |
| } |