org.eclipse.emf.ecp.editor.mecontrols.melinkcontrol.associationclasscontrol.AssociationClassLink.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.emf.ecp.editor.mecontrols.melinkcontrol.associationclasscontrol.AssociationClassLink.java

Source

/*******************************************************************************
 * 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());
        this.toolkit = 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 = toolkit.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 = toolkit.createImageHyperlink(composite, style);
        ModelElementClassTooltip.enableFor(imgHyperlink);
        hyperlink = toolkit.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(), toolkit);
        } else if (eAttribute.size() > 1) {
            Hyperlink associationLink = toolkit.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 = toolkit.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);
                    }
                }
            });
        }
    }
}