diff options
44 files changed, 2397 insertions, 1465 deletions
diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/contentprovider/AbstractPageModel.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/contentprovider/AbstractPageModel.java new file mode 100644 index 00000000000..394b6887aa8 --- /dev/null +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/contentprovider/AbstractPageModel.java @@ -0,0 +1,86 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus and others. + * + * 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.core.sasheditor.contentprovider; + +import java.util.Objects; +import java.util.function.Consumer; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.swt.graphics.Image; + +/** + * Partial implementation of the {@link IPageModel} protocol. + * + * @since 2.0 + */ +public abstract class AbstractPageModel implements IPageModel { + + private ILabelProvider tabLabelProvider; + private Consumer<String> onLabelChanged = this::noop; + + private final ILabelProviderListener labelListener = event -> { + if (event.getElement() == getRawModel()) { + onLabelChanged.accept(getTabTitle()); + } + }; + + /** + * Initializes me with the label provider to use to render tabs. + * + * @param tabLabelProvider + * a label provider accepting my {@linkplain IPageModel#getRawModel() model}. + * This label provider should not be shared with other clients; I will dispose it when I am {@linkplain #dispose() disposed} + * + * @throws NullPointerException + * if the {@code tabLabelProvider} is {@code null} + */ + public AbstractPageModel(ILabelProvider tabLabelProvider) { + super(); + + this.tabLabelProvider = Objects.requireNonNull(tabLabelProvider, "null tabLabelProvider"); //$NON-NLS-1$ + tabLabelProvider.addListener(labelListener); + } + + /** + * I remove listener from my label provider. + */ + @Override + public void dispose() { + tabLabelProvider.removeListener(labelListener); + tabLabelProvider.dispose(); + } + + protected ILabelProvider getTabLabelProvider() { + return tabLabelProvider; + } + + @Override + public String getTabTitle() { + return tabLabelProvider.getText(getRawModel()); + } + + @Override + public Image getTabIcon() { + return tabLabelProvider.getImage(getRawModel()); + } + + public void onLabelChanged(Consumer<? super String> handler) { + onLabelChanged = onLabelChanged.andThen(handler); + } + + private void noop(String label) { + // Pass + } +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/EditorPart.java b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/EditorPart.java index 1abf8c91d38..695848cec83 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/EditorPart.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core.sasheditor/src/org/eclipse/papyrus/infra/core/sasheditor/internal/EditorPart.java @@ -1,750 +1,754 @@ -/*****************************************************************************
- * Copyright (c) 2009, 2015 CEA LIST & LIFL, Christian W. Damus, and others
- *
- *
- * 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:
- * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation
- * Christian W. Damus - bug 469188
- *
- *****************************************************************************/
-package org.eclipse.papyrus.infra.core.sasheditor.internal;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-import org.eclipse.core.runtime.ISafeRunnable;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.SafeRunner;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jface.window.Window;
-import org.eclipse.papyrus.infra.core.sasheditor.Activator;
-import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IEditorModel;
-import org.eclipse.papyrus.infra.core.sasheditor.editor.IEditorPage;
-import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IMultiPageEditorSite;
-import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.MultiPageEditorSite;
-import org.eclipse.papyrus.infra.tools.util.PlatformHelper;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Event;
-import org.eclipse.swt.widgets.Listener;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IEditorSite;
-import org.eclipse.ui.IPropertyListener;
-import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.IWorkbenchPartSite;
-import org.eclipse.ui.PartInitException;
-import org.eclipse.ui.internal.ErrorEditorPart;
-import org.eclipse.ui.internal.dnd.IDropTarget;
-import org.eclipse.ui.internal.misc.StatusUtil;
-import org.eclipse.ui.part.EditorActionBarContributor;
-import org.eclipse.ui.part.IWorkbenchPartOrientation;
-
-
-/**
- * This is a controler/part for an Editor. It is associated to a {@link IEditorModel}.
- * This Part encapsulate an Eclipse Editor implementing {@link IEditorPart}.
- *
- * @author dumoulin
- * @author <a href="mailto:thomas.szadel@atosorigin.com">Thomas SZADEL</a> Improve the error text (avoid NPE)
- */
-@SuppressWarnings("restriction")
-public class EditorPart extends PagePart implements IEditorPage {
-
- /**
- * The model representing the editor.
- */
- private IEditorModel editorModel;
-
- /**
- * The created Eclipse editor.
- */
- private IEditorPart editorPart;
-
- /**
- * The SWT Control containning the editor's controls.
- */
- private Composite editorControl;
-
- /**
- * The MultiPageContainer system. This is the manager of all tiles.
- */
- // private SashWindowsContainer tilesContainer;
-
- /**
- * The manager used to access main editor properties like site, actionbars, ...
- */
- private IMultiEditorManager multiEditorManager;
-
- /**
- * Parent owning this PagePart.
- * Can be null if the Part is orphaned. Even if it is orphaned, the Item still set.
- */
- // protected TabFolderPart parent;
-
- /**
- * Listen on mouse enter event.
- * Try to get an event indicating that the mouse enter over the editor.
- * This can be used to switch the active editor.
- * TODO This doesn't work yet.
- */
- private Listener mouseEnterListener = new Listener() {
-
- /**
- * (non-Javadoc)
- *
- * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
- */
- @Override
- public void handleEvent(Event event) {
- // Point globalPos = new Point(event.x, event.y);
- // System.out.println(this.getClass().getSimpleName() + ".handleEvent(" + eventName(event.type) + ", " + globalPos + ")");
- }
- };
-
- /**
- * Listener on widget disposed event. When the widget is disposed, the associated IEditor dispose()
- * method is called.
- *
- */
- private DisposeListener widgetDisposedListener = new DisposeListener() {
-
- /**
- * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
- * @see SashWindowsContainer#dispose()
- * @param e
- */
- @Override
- public void widgetDisposed(DisposeEvent e) {
- // We dispose the associated editor.
- disposeEditorPart();
- }
- };
-
- // To be removed
- // private String eventName(int eventType) {
- // switch(eventType) {
- // case SWT.MouseEnter:
- // return "MouseEnter";
- // case SWT.MouseDown:
- // return "MouseDown";
- // case SWT.MouseExit:
- // return "MouseExit";
- // case SWT.MouseHover:
- // return "MouseHover";
- // case SWT.FocusIn:
- // return "FocusIn";
- // case SWT.FocusOut:
- // return "FocusOut";
- // case SWT.MouseMove:
- // return "MouseMove";
- // case SWT.MouseUp:
- // return "MouseUp";
- // case SWT.Activate:
- // return "Activate";
- // default:
- // return Integer.toString(eventType);
- // }
- // }
-
- /**
- * Constructor.
- *
- * @param editorModel
- * The model of the editor.
- */
- public EditorPart(TabFolderPart parent, IEditorModel editorModel, Object rawModel, IMultiEditorManager multiEditorManager) {
- super(parent, rawModel);
- this.editorModel = editorModel;
- this.multiEditorManager = multiEditorManager;
- }
-
- @Override
- public <T> T getAdapter(Class<T> adapter) {
- return PlatformHelper.getAdapter(editorPart, adapter, ()//
- -> PlatformHelper.getAdapter(editorModel, adapter, ()//
- -> super.getAdapter(adapter)));
- }
-
- /**
- * Create the control of this Part, and children's controls.
- *
- * @param parent
- * The SWT parent of this EditorPart. This is usually the {@link TabFolderPart}'s control.
- */
- @Override
- public void createPartControl(Composite parent) {
-
- try {
- // Create the editor.
- editorPart = createIEditorPart();
- // Initialize it and create its controls.
- editorControl = createEditorPartControl(parent, editorPart);
- attachListeners(editorControl, true);
- } catch (PartInitException e) {
- Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e));
- // TODO Create a fake Error Page and initialize this part with.
- // editorPart = new ErrorEditorPart();
- // editorControl = createEditorPartControl(parent, editorPart);
- // editorControl = createErrorPartControl(parent, e);
- createErrorEditorPart(parent, e);
- } catch (Exception e) {
- Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e));
- // TODO Create a fake Error Page and initialize this part with.
- // editorControl = createErrorPartControl(parent, e);
- createErrorEditorPart(parent, e);
- }
- }
-
- /**
- * Create a Control showing the error.
- *
- * @param parent
- * Parent Control to which the Created Control should be attached
- * @param e
- * Exception containing the error.
- */
- private Composite createErrorPartControl(Composite parent, Exception e) {
-
- Composite comp = new Composite(parent, SWT.NONE);
- comp.setLayout(new FillLayout());
- // Show the stack trace
- StringWriter strOut = new StringWriter();
- PrintWriter out = new PrintWriter(strOut);
- e.printStackTrace(out);
- out.flush();
- out.close();
-
- Text diag = new Text(comp, SWT.MULTI);
- diag.setSize(64, 32);
-
- diag.setText(strOut.toString());
- return comp;
- }
-
- /**
- * Create an EditorPart showing the Exception.
- * This is used when the creation of the regular IEditorPart failed.
- *
- * @param e
- */
- private void createErrorEditorPart(Composite parent, Exception e) {
-
- try {
- PartInitException partInitException = new PartInitException(StatusUtil.getLocalizedMessage(e), StatusUtil.getCause(e));
- editorPart = new ErrorEditorPart(partInitException.getStatus());
- // Initialize it and create its controls.
- editorControl = createEditorPartControl(parent, editorPart);
-
- } catch (Exception ex) {
- // Even the ErrorEditorPart creation fail.
- // Use a more simple renderer.
- Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e));
- // TODO Create a fake Error Page and initialize this part with.
- editorControl = createErrorPartControl(parent, e);
- }
-
- }
-
- /**
- * Create the editor associated to this TabPart.
- *
- * @return
- * @throws PartInitException
- */
- private IEditorPart createIEditorPart() throws PartInitException {
-
- return editorModel.createIEditorPart();
- }
-
- /**
- * Create the controls required by the editor.
- * Init the editor.
- *
- * @param viewer
- * @param editorInput
- * @param model
- * @return
- * @throws PartInitException
- */
- private Composite createEditorPartControl(Composite parentControl, IEditorPart editor) throws PartInitException {
- IEditorSite site = createSite(editor);
- // call init first so that if an exception is thrown, we have created no
- // new widgets
- editor.init(site, getIMultiEditorManager().getEditorInput());
- Composite editorParent = new Composite(parentControl, getOrientation(editor));
- editorParent.setLayout(new FillLayout());
- // Listen to dispose event
- editorParent.addDisposeListener(widgetDisposedListener);
- // Create editor controls
- editor.createPartControl(editorParent);
- editor.addPropertyListener(new IPropertyListener() {
-
- @Override
- public void propertyChanged(Object source, int propertyId) {
- EditorPart.this.handlePropertyChange(propertyId);
- }
- });
-
- // TODO test to be removed
- // attachListeners(editorParent, false);
- return editorParent;
- }
-
- /**
- * Attach SWT listeners.
- */
- private void attachListeners(Control theControl, boolean recursive) {
-
- // All following methods listen to the same event.
- // So use only one of them
- // theControl.addListener(SWT.MouseEnter, mouseEnterListener);
- //
- // theControl.addListener(SWT.FocusIn, mouseEnterListener);
- // theControl.addListener(SWT.MouseMove, mouseEnterListener);
- // theControl.addListener(SWT.MouseHover, mouseEnterListener);
- // theControl.addListener(SWT.MouseUp, mouseEnterListener);
- // theControl.addListener(SWT.MouseDown, mouseEnterListener);
- theControl.addListener(SWT.Activate, mouseEnterListener);
-
- // if (recursive && theControl instanceof Composite) {
- // Composite composite = (Composite) theControl;
- // Control[] children = composite.getChildren();
- //
- // for (int i = 0; i < children.length; i++) {
- // Control control = children[i];
- //
- // attachListeners(control, true);
- // }
- // }
- }
-
- /**
- * Detach SWT listeners
- */
- private void detachListeners(Control theControl, boolean recursive) {
- // theControl.removeListener(SWT.MouseEnter, mouseEnterListener);
- // theControl.removeListener(SWT.FocusIn, mouseEnterListener);
- // theControl.removeListener(SWT.MouseMove, mouseEnterListener);
- // theControl.removeListener(SWT.MouseHover, mouseEnterListener);
- // theControl.removeListener(SWT.MouseUp, mouseEnterListener);
- // theControl.removeListener(SWT.MouseDown, mouseEnterListener);
- theControl.removeListener(SWT.Activate, mouseEnterListener);
-
- // if (recursive && theControl instanceof Composite) {
- // Composite composite = (Composite) theControl;
- // Control[] children = composite.getChildren();
- //
- // for (int i = 0; i < children.length; i++) {
- // Control control = children[i];
- //
- // detachListeners(control, false);
- // }
- // }
- }
-
-
- /**
- * Handles a property change notification from a nested editor. The default implementation simply forwards
- * the change to listeners on this multi-page editor by calling <code>firePropertyChange</code> with the same property id. For example, if the
- * dirty state of a nested
- * editor changes (property id <code>IEditorPart.PROP_DIRTY</code>), this method handles it
- * by firing a property change event for <code>IEditorPart.PROP_DIRTY</code> to property listeners on this
- * multi-page editor.
- * <p>
- * Subclasses may extend or reimplement this method.
- * </p>
- *
- * @param propertyId
- * the id of the property that changed
- */
- private void handlePropertyChange(int propertyId) {
- // cedric : old fashion, deprecated ?
- getSashWindowContainer().firePropertyChange(propertyId);
- // relay the event to the page lifecycle event notifier
- getSashWindowContainer().getLifeCycleEventProvider().firePageFirePropertyChangeEvent(this, propertyId);
- }
-
- /**
- * Creates the site for the given nested editor. The <code>MultiPageEditorPart</code> implementation
- * of this method creates an instance of <code>MultiPageEditorSite</code>. Subclasses may
- * reimplement to create more specialized sites.
- *
- * @param editor
- * the nested editor
- * @return the editor site
- */
- protected IEditorSite createSite(IEditorPart editor) {
- EditorActionBarContributor contributor = createEditorActionBarContributor();
-
- return new MultiPageEditorSite(multiEditorManager.getEditorSite(), editor, contributor);
- }
-
- /**
- * Create the EditorActionBarContributor requested by the editor.
- * Creation is done by delegating to the IMultiEditorNestedPartManager.
- *
- * @return
- */
- private EditorActionBarContributor createEditorActionBarContributor() {
- EditorActionBarContributor contributor = editorModel.getActionBarContributor();
- return contributor;
- }
-
- /**
- * Get the orientation of the editor.
- *
- * @param editor
- * @return int the orientation flag
- * @see SWT#RIGHT_TO_LEFT
- * @see SWT#LEFT_TO_RIGHT
- * @see SWT#NONE
- */
- private int getOrientation(IEditorPart editor) {
- if (editor instanceof IWorkbenchPartOrientation) {
- return ((IWorkbenchPartOrientation) editor).getOrientation();
- }
- return Window.getDefaultOrientation();
- }
-
- /**
- * Get the nested part manager.
- *
- * @return
- */
- private IMultiEditorManager getIMultiEditorManager() {
- return multiEditorManager;
- }
-
-
- /**
- * /**
- * Dispose all resources used by this part. <br/>
- * The Part should not be used after it has been disposed.
- */
- @Override
- public void dispose() {
-
- detachListeners(editorControl, true);
- // dispose the SWT root control
- // This should also trigger the disposal of associated editor.
- editorControl.dispose();
- // Dispose the editor.
- // disposeEditorPart();
-
- // clean up properties to help GC
- editorModel = null;
- // editorPart = null;
- rawModel = null;
- }
-
- /**
- * Dispose this part and all its children.
- * The method is called recursively on children of the part. <br/>
- * SWT resources have already been disposed. We don't need to dispose them again.
- *
- */
- @Override
- public void disposeThisAndChildren() {
-
- // Dispose the editor (normally this should be already done).
- disposeEditorPart();
-
- // clean up properties to help GC
- editorModel = null;
- // editorPart = null;
- rawModel = null;
- }
-
-
- /**
- * Disposes the associated editor and its site.
- * Do not dispose it twice.
- *
- * @param part
- * The part to dispose; must not be <code>null</code>.
- * @copy copied from org.eclipse.ui.part.MultiPageEditorPart.disposePart(IWorkbenchPart) v3.8
- */
- private void disposeEditorPart() {
-
- // Is the editor already disposed ?
- if (editorPart == null) {
- return;
- }
-
- final IWorkbenchPart part = editorPart;
- editorPart = null;
-
- SafeRunner.run(new ISafeRunnable() {
-
- @Override
- public void run() {
- IWorkbenchPartSite partSite = part.getSite();
- part.dispose();
- if (partSite instanceof IMultiPageEditorSite) {
- ((IMultiPageEditorSite) partSite).dispose();
- }
- }
-
- @Override
- public void handleException(Throwable e) {
- // Exception has already being logged by Core. Do nothing.
- }
- });
- }
-
-
- /**
- * As we are a final Tile, we should be the requested part.
- * Return this TilePart.
- *
- * @param toFind
- * @return
- */
- public PagePart findPart(Point toFind) {
- return this;
- }
-
- /**
- * Locates the part that intersects the given point and that have the expected type
- *
- * @param toFind
- * @return
- */
- @Override
- public PagePart findPartAt(Point toFind, Class<?> expectedTileType) {
-
- if (expectedTileType == this.getClass()) {
- return this;
- }
-
- // Not found !!
- // The tile contains the position, but the type is not found.
- throw new UnsupportedOperationException("Tile match the expected position '" + toFind + "' but there is no Tile of requested type '" + expectedTileType.getClass().getName() + "'");
- }
-
- /**
- * @param control
- * @return
- */
- public PagePart findPart(Object control) {
- if (getControl() == control) {
- return this;
- }
-
- // Not found
- return null;
- }
-
- /**
- * Returns the active nested editor if there is one.
- * <p>
- * Subclasses should not override this method
- * </p>
- *
- * @return the active nested editor, or <code>null</code> if none
- */
- @Override
- public IEditorPart getIEditorPart() {
- return editorPart;
- }
-
- /**
- * Get associated SWT Control.
- *
- * @return
- */
- @Override
- public Composite getControl() {
- return editorControl;
- }
-
-
- /**
- * This is a container method. Not necessary in Leaf Tile.
- * TODO: change the interface.
- *
- * @param draggedObject
- * @param position
- * @return
- */
- public IDropTarget getDropTarget(Object draggedObject, TabFolderPart sourcePart, Point position) {
- return null;
- }
-
-
- /**
- * @return
- */
- @Override
- public GarbageState getGarbageState() {
- return garbageState;
- }
-
-
- /**
- * Is the associated editor dirty ?
- * Delegate to {@link IEditorPart.isDirty()}
- *
- * @return true if the associated editor is dirty.
- *
- * @unused
- */
- public boolean isDirty() {
- return editorPart.isDirty();
- }
-
-
-
- /**
- * Change the parent of the Tile. The parent is changed, and the control is
- * attached to the parent control. Change garbage state to {@link GarbageState.REPARENTED}.
- * Do not detach the Tile from its old parent.
- *
- * @param newParent
- * The tilePart that should be used as part parent.
- * @param compositeParent
- * The composite that should be used as parent.
- */
- @Override
- public void reparent(TabFolderPart newParent) {
-
- // Change the tile parent
- this.parent = newParent;
- // Change the SWT parent.
- editorControl.setParent(newParent.getControl());
-
- // Change state
- if (garbageState == GarbageState.UNVISITED || garbageState == GarbageState.ORPHANED || garbageState == GarbageState.CREATED) {
- garbageState = GarbageState.REPARENTED;
- } else {
- // Bad state, this is an internal error
- // TODO : log a warning ?
- throw new IllegalStateException("Try to change state from " + garbageState.toString() + " to REPARENTED. This is forbidden.");
- }
-
- }
-
-
- /**
- * Asks this part to take focus within the workbench.
- * Set the focus on the active nested part if the part is a container.
- */
- @Override
- public void setFocus() {
- if (editorPart != null) {
- try {
- editorPart.setFocus();
- } catch (Exception ex) {
- Activator.log.error(ex);
- }
- }
- }
-
-
- /**
- * Synchronize the Part, and its children. PartMap contains a snapshot of the available part before
- * the synchronization. After synchronization, unreachable parts should be marked "orphaned" (= no
- * parent).
- * Do nothing in this implementation, as we are a final leaf, and there is nothing to synchronize
- * with the underlying model.
- *
- * @param partMap
- */
- public void synchronize2(PartLists partMap) {
-
- }
-
-
- /**
- * Garbage this part.
- * This part will be not used anymore.
- * The part is already marked as ORPHANED. It is not used anymore. It is already detached
- * from its parent. <br>
- * This method is called by the sashwindows garbage mechanism after the Part has been marked as ORPHANED.
- * All resources associated to this part can be disposed.
- *
- */
- @Override
- public void garbage() {
- dispose();
- // fire appropriate life cycle event
- getSashWindowContainer().getLifeCycleEventProvider().firePageClosedEvent(this);
- }
-
-
- /**
- * Accept the provided visitor.
- * Call the corresponding accept method in the visitor.
- *
- * @param visitor
- * @return
- */
- @Override
- public boolean visit(IPartVisitor visitor) {
- return visitor.accept(this);
- }
-
- /**
- * Visit the children of this Tile.
- * There is no child, so do nothing.
- *
- * @param visitor
- */
- public boolean visitChildren(IPartVisitor visitor) {
- return true;
- }
-
-
- /**
- * Show item status.
- */
- protected void showStatus() {
- // System.out.println( "EditorTile: "
- // + " disposed=" + editorControl.isDisposed()
- // + ", visible=" + editorControl.isVisible()
- // + ", garbState=" + garbageState
- // + ", '" + editorPart.getTitle()
- // + "', " + this);
- String title = (editorPart != null ? editorPart.getTitle() : "no editorPart");
- System.out.printf("EditorTile: disposed=%-5b, visible=%-5b, garbState=%-10s, %s, %s\n", editorControl.isDisposed(), (editorControl.isDisposed() ? false : editorControl.isVisible()), garbageState, title, this);
-
- }
-
- /**
- * Get the title for this part. {@inheritDoc}
- */
- @Override
- public String getPageTitle() {
- try {
- return editorModel.getTabTitle();
- } catch (Exception ex) {
- Activator.log.error(ex);
- return "Error";
- }
- }
-
- /**
- * Return an icon for this part. {@inheritDoc}
- */
- @Override
- public Image getPageIcon() {
- try {
- return editorModel.getTabIcon();
- } catch (Exception ex) {
- Activator.log.error(ex);
- return null;
- }
- }
-}
+/***************************************************************************** + * Copyright (c) 2009, 2016 CEA LIST, LIFL, Christian W. Damus, and others. + * + * 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: + * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation + * Christian W. Damus - bugs 469188, 474467 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.core.sasheditor.internal; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.window.Window; +import org.eclipse.papyrus.infra.core.sasheditor.Activator; +import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.AbstractPageModel; +import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IEditorModel; +import org.eclipse.papyrus.infra.core.sasheditor.editor.IEditorPage; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.IMultiPageEditorSite; +import org.eclipse.papyrus.infra.core.sasheditor.internal.eclipsecopy.MultiPageEditorSite; +import org.eclipse.papyrus.infra.tools.util.PlatformHelper; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.IPropertyListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.internal.ErrorEditorPart; +import org.eclipse.ui.internal.dnd.IDropTarget; +import org.eclipse.ui.internal.misc.StatusUtil; +import org.eclipse.ui.part.EditorActionBarContributor; +import org.eclipse.ui.part.IWorkbenchPartOrientation; + + +/** + * This is a controler/part for an Editor. It is associated to a {@link IEditorModel}. + * This Part encapsulate an Eclipse Editor implementing {@link IEditorPart}. + * + * @author dumoulin + * @author <a href="mailto:thomas.szadel@atosorigin.com">Thomas SZADEL</a> Improve the error text (avoid NPE) + */ +@SuppressWarnings("restriction") +public class EditorPart extends PagePart implements IEditorPage { + + /** + * The model representing the editor. + */ + private IEditorModel editorModel; + + /** + * The created Eclipse editor. + */ + private IEditorPart editorPart; + + /** + * The SWT Control containning the editor's controls. + */ + private Composite editorControl; + + /** + * The MultiPageContainer system. This is the manager of all tiles. + */ + // private SashWindowsContainer tilesContainer; + + /** + * The manager used to access main editor properties like site, actionbars, ... + */ + private IMultiEditorManager multiEditorManager; + + /** + * Parent owning this PagePart. + * Can be null if the Part is orphaned. Even if it is orphaned, the Item still set. + */ + // protected TabFolderPart parent; + + /** + * Listen on mouse enter event. + * Try to get an event indicating that the mouse enter over the editor. + * This can be used to switch the active editor. + * TODO This doesn't work yet. + */ + private Listener mouseEnterListener = new Listener() { + + /** + * (non-Javadoc) + * + * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) + */ + @Override + public void handleEvent(Event event) { + // Point globalPos = new Point(event.x, event.y); + // System.out.println(this.getClass().getSimpleName() + ".handleEvent(" + eventName(event.type) + ", " + globalPos + ")"); + } + }; + + /** + * Listener on widget disposed event. When the widget is disposed, the associated IEditor dispose() + * method is called. + * + */ + private DisposeListener widgetDisposedListener = new DisposeListener() { + + /** + * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) + * @see SashWindowsContainer#dispose() + * @param e + */ + @Override + public void widgetDisposed(DisposeEvent e) { + // We dispose the associated editor. + disposeEditorPart(); + } + }; + + // To be removed + // private String eventName(int eventType) { + // switch(eventType) { + // case SWT.MouseEnter: + // return "MouseEnter"; + // case SWT.MouseDown: + // return "MouseDown"; + // case SWT.MouseExit: + // return "MouseExit"; + // case SWT.MouseHover: + // return "MouseHover"; + // case SWT.FocusIn: + // return "FocusIn"; + // case SWT.FocusOut: + // return "FocusOut"; + // case SWT.MouseMove: + // return "MouseMove"; + // case SWT.MouseUp: + // return "MouseUp"; + // case SWT.Activate: + // return "Activate"; + // default: + // return Integer.toString(eventType); + // } + // } + + /** + * Constructor. + * + * @param editorModel + * The model of the editor. + */ + public EditorPart(TabFolderPart parent, IEditorModel editorModel, Object rawModel, IMultiEditorManager multiEditorManager) { + super(parent, rawModel); + this.editorModel = editorModel; + this.multiEditorManager = multiEditorManager; + + if (editorModel instanceof AbstractPageModel) { + ((AbstractPageModel) editorModel).onLabelChanged(label -> refreshTab()); + } + } + + @Override + public <T> T getAdapter(Class<T> adapter) { + return PlatformHelper.getAdapter(editorPart, adapter, ()// + -> PlatformHelper.getAdapter(editorModel, adapter, ()// + -> super.getAdapter(adapter))); + } + + /** + * Create the control of this Part, and children's controls. + * + * @param parent + * The SWT parent of this EditorPart. This is usually the {@link TabFolderPart}'s control. + */ + @Override + public void createPartControl(Composite parent) { + + try { + // Create the editor. + editorPart = createIEditorPart(); + // Initialize it and create its controls. + editorControl = createEditorPartControl(parent, editorPart); + attachListeners(editorControl, true); + } catch (PartInitException e) { + Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e)); + // TODO Create a fake Error Page and initialize this part with. + // editorPart = new ErrorEditorPart(); + // editorControl = createEditorPartControl(parent, editorPart); + // editorControl = createErrorPartControl(parent, e); + createErrorEditorPart(parent, e); + } catch (Exception e) { + Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e)); + // TODO Create a fake Error Page and initialize this part with. + // editorControl = createErrorPartControl(parent, e); + createErrorEditorPart(parent, e); + } + } + + /** + * Create a Control showing the error. + * + * @param parent + * Parent Control to which the Created Control should be attached + * @param e + * Exception containing the error. + */ + private Composite createErrorPartControl(Composite parent, Exception e) { + + Composite comp = new Composite(parent, SWT.NONE); + comp.setLayout(new FillLayout()); + // Show the stack trace + StringWriter strOut = new StringWriter(); + PrintWriter out = new PrintWriter(strOut); + e.printStackTrace(out); + out.flush(); + out.close(); + + Text diag = new Text(comp, SWT.MULTI); + diag.setSize(64, 32); + + diag.setText(strOut.toString()); + return comp; + } + + /** + * Create an EditorPart showing the Exception. + * This is used when the creation of the regular IEditorPart failed. + * + * @param e + */ + private void createErrorEditorPart(Composite parent, Exception e) { + + try { + PartInitException partInitException = new PartInitException(StatusUtil.getLocalizedMessage(e), StatusUtil.getCause(e)); + editorPart = new ErrorEditorPart(partInitException.getStatus()); + // Initialize it and create its controls. + editorControl = createEditorPartControl(parent, editorPart); + + } catch (Exception ex) { + // Even the ErrorEditorPart creation fail. + // Use a more simple renderer. + Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getLocalizedMessage(), e)); + // TODO Create a fake Error Page and initialize this part with. + editorControl = createErrorPartControl(parent, e); + } + + } + + /** + * Create the editor associated to this TabPart. + * + * @return + * @throws PartInitException + */ + private IEditorPart createIEditorPart() throws PartInitException { + + return editorModel.createIEditorPart(); + } + + /** + * Create the controls required by the editor. + * Init the editor. + * + * @param viewer + * @param editorInput + * @param model + * @return + * @throws PartInitException + */ + private Composite createEditorPartControl(Composite parentControl, IEditorPart editor) throws PartInitException { + IEditorSite site = createSite(editor); + // call init first so that if an exception is thrown, we have created no + // new widgets + editor.init(site, getIMultiEditorManager().getEditorInput()); + Composite editorParent = new Composite(parentControl, getOrientation(editor)); + editorParent.setLayout(new FillLayout()); + // Listen to dispose event + editorParent.addDisposeListener(widgetDisposedListener); + // Create editor controls + editor.createPartControl(editorParent); + editor.addPropertyListener(new IPropertyListener() { + + @Override + public void propertyChanged(Object source, int propertyId) { + EditorPart.this.handlePropertyChange(propertyId); + } + }); + + // TODO test to be removed + // attachListeners(editorParent, false); + return editorParent; + } + + /** + * Attach SWT listeners. + */ + private void attachListeners(Control theControl, boolean recursive) { + + // All following methods listen to the same event. + // So use only one of them + // theControl.addListener(SWT.MouseEnter, mouseEnterListener); + // + // theControl.addListener(SWT.FocusIn, mouseEnterListener); + // theControl.addListener(SWT.MouseMove, mouseEnterListener); + // theControl.addListener(SWT.MouseHover, mouseEnterListener); + // theControl.addListener(SWT.MouseUp, mouseEnterListener); + // theControl.addListener(SWT.MouseDown, mouseEnterListener); + theControl.addListener(SWT.Activate, mouseEnterListener); + + // if (recursive && theControl instanceof Composite) { + // Composite composite = (Composite) theControl; + // Control[] children = composite.getChildren(); + // + // for (int i = 0; i < children.length; i++) { + // Control control = children[i]; + // + // attachListeners(control, true); + // } + // } + } + + /** + * Detach SWT listeners + */ + private void detachListeners(Control theControl, boolean recursive) { + // theControl.removeListener(SWT.MouseEnter, mouseEnterListener); + // theControl.removeListener(SWT.FocusIn, mouseEnterListener); + // theControl.removeListener(SWT.MouseMove, mouseEnterListener); + // theControl.removeListener(SWT.MouseHover, mouseEnterListener); + // theControl.removeListener(SWT.MouseUp, mouseEnterListener); + // theControl.removeListener(SWT.MouseDown, mouseEnterListener); + theControl.removeListener(SWT.Activate, mouseEnterListener); + + // if (recursive && theControl instanceof Composite) { + // Composite composite = (Composite) theControl; + // Control[] children = composite.getChildren(); + // + // for (int i = 0; i < children.length; i++) { + // Control control = children[i]; + // + // detachListeners(control, false); + // } + // } + } + + + /** + * Handles a property change notification from a nested editor. The default implementation simply forwards + * the change to listeners on this multi-page editor by calling <code>firePropertyChange</code> with the same property id. For example, if the + * dirty state of a nested + * editor changes (property id <code>IEditorPart.PROP_DIRTY</code>), this method handles it + * by firing a property change event for <code>IEditorPart.PROP_DIRTY</code> to property listeners on this + * multi-page editor. + * <p> + * Subclasses may extend or reimplement this method. + * </p> + * + * @param propertyId + * the id of the property that changed + */ + private void handlePropertyChange(int propertyId) { + // cedric : old fashion, deprecated ? + getSashWindowContainer().firePropertyChange(propertyId); + // relay the event to the page lifecycle event notifier + getSashWindowContainer().getLifeCycleEventProvider().firePageFirePropertyChangeEvent(this, propertyId); + } + + /** + * Creates the site for the given nested editor. The <code>MultiPageEditorPart</code> implementation + * of this method creates an instance of <code>MultiPageEditorSite</code>. Subclasses may + * reimplement to create more specialized sites. + * + * @param editor + * the nested editor + * @return the editor site + */ + protected IEditorSite createSite(IEditorPart editor) { + EditorActionBarContributor contributor = createEditorActionBarContributor(); + + return new MultiPageEditorSite(multiEditorManager.getEditorSite(), editor, contributor); + } + + /** + * Create the EditorActionBarContributor requested by the editor. + * Creation is done by delegating to the IMultiEditorNestedPartManager. + * + * @return + */ + private EditorActionBarContributor createEditorActionBarContributor() { + EditorActionBarContributor contributor = editorModel.getActionBarContributor(); + return contributor; + } + + /** + * Get the orientation of the editor. + * + * @param editor + * @return int the orientation flag + * @see SWT#RIGHT_TO_LEFT + * @see SWT#LEFT_TO_RIGHT + * @see SWT#NONE + */ + private int getOrientation(IEditorPart editor) { + if (editor instanceof IWorkbenchPartOrientation) { + return ((IWorkbenchPartOrientation) editor).getOrientation(); + } + return Window.getDefaultOrientation(); + } + + /** + * Get the nested part manager. + * + * @return + */ + private IMultiEditorManager getIMultiEditorManager() { + return multiEditorManager; + } + + + /** + * /** + * Dispose all resources used by this part. <br/> + * The Part should not be used after it has been disposed. + */ + @Override + public void dispose() { + + detachListeners(editorControl, true); + // dispose the SWT root control + // This should also trigger the disposal of associated editor. + editorControl.dispose(); + // Dispose the editor. + // disposeEditorPart(); + + // clean up properties to help GC + editorModel = null; + // editorPart = null; + rawModel = null; + } + + /** + * Dispose this part and all its children. + * The method is called recursively on children of the part. <br/> + * SWT resources have already been disposed. We don't need to dispose them again. + * + */ + @Override + public void disposeThisAndChildren() { + + // Dispose the editor (normally this should be already done). + disposeEditorPart(); + + // clean up properties to help GC + editorModel = null; + // editorPart = null; + rawModel = null; + } + + + /** + * Disposes the associated editor and its site. + * Do not dispose it twice. + * + * @param part + * The part to dispose; must not be <code>null</code>. + * @copy copied from org.eclipse.ui.part.MultiPageEditorPart.disposePart(IWorkbenchPart) v3.8 + */ + private void disposeEditorPart() { + + // Is the editor already disposed ? + if (editorPart == null) { + return; + } + + final IWorkbenchPart part = editorPart; + editorPart = null; + + SafeRunner.run(new ISafeRunnable() { + + @Override + public void run() { + IWorkbenchPartSite partSite = part.getSite(); + part.dispose(); + if (partSite instanceof IMultiPageEditorSite) { + ((IMultiPageEditorSite) partSite).dispose(); + } + } + + @Override + public void handleException(Throwable e) { + // Exception has already being logged by Core. Do nothing. + } + }); + } + + + /** + * As we are a final Tile, we should be the requested part. + * Return this TilePart. + * + * @param toFind + * @return + */ + public PagePart findPart(Point toFind) { + return this; + } + + /** + * Locates the part that intersects the given point and that have the expected type + * + * @param toFind + * @return + */ + @Override + public PagePart findPartAt(Point toFind, Class<?> expectedTileType) { + + if (expectedTileType == this.getClass()) { + return this; + } + + // Not found !! + // The tile contains the position, but the type is not found. + throw new UnsupportedOperationException("Tile match the expected position '" + toFind + "' but there is no Tile of requested type '" + expectedTileType.getClass().getName() + "'"); + } + + /** + * @param control + * @return + */ + public PagePart findPart(Object control) { + if (getControl() == control) { + return this; + } + + // Not found + return null; + } + + /** + * Returns the active nested editor if there is one. + * <p> + * Subclasses should not override this method + * </p> + * + * @return the active nested editor, or <code>null</code> if none + */ + @Override + public IEditorPart getIEditorPart() { + return editorPart; + } + + /** + * Get associated SWT Control. + * + * @return + */ + @Override + public Composite getControl() { + return editorControl; + } + + + /** + * This is a container method. Not necessary in Leaf Tile. + * TODO: change the interface. + * + * @param draggedObject + * @param position + * @return + */ + public IDropTarget getDropTarget(Object draggedObject, TabFolderPart sourcePart, Point position) { + return null; + } + + + /** + * @return + */ + @Override + public GarbageState getGarbageState() { + return garbageState; + } + + + /** + * Is the associated editor dirty ? + * Delegate to {@link IEditorPart.isDirty()} + * + * @return true if the associated editor is dirty. + * + * @unused + */ + public boolean isDirty() { + return editorPart.isDirty(); + } + + + + /** + * Change the parent of the Tile. The parent is changed, and the control is + * attached to the parent control. Change garbage state to {@link GarbageState.REPARENTED}. + * Do not detach the Tile from its old parent. + * + * @param newParent + * The tilePart that should be used as part parent. + * @param compositeParent + * The composite that should be used as parent. + */ + @Override + public void reparent(TabFolderPart newParent) { + + // Change the tile parent + this.parent = newParent; + // Change the SWT parent. + editorControl.setParent(newParent.getControl()); + + // Change state + if (garbageState == GarbageState.UNVISITED || garbageState == GarbageState.ORPHANED || garbageState == GarbageState.CREATED) { + garbageState = GarbageState.REPARENTED; + } else { + // Bad state, this is an internal error + // TODO : log a warning ? + throw new IllegalStateException("Try to change state from " + garbageState.toString() + " to REPARENTED. This is forbidden."); + } + + } + + + /** + * Asks this part to take focus within the workbench. + * Set the focus on the active nested part if the part is a container. + */ + @Override + public void setFocus() { + if (editorPart != null) { + try { + editorPart.setFocus(); + } catch (Exception ex) { + Activator.log.error(ex); + } + } + } + + + /** + * Synchronize the Part, and its children. PartMap contains a snapshot of the available part before + * the synchronization. After synchronization, unreachable parts should be marked "orphaned" (= no + * parent). + * Do nothing in this implementation, as we are a final leaf, and there is nothing to synchronize + * with the underlying model. + * + * @param partMap + */ + public void synchronize2(PartLists partMap) { + + } + + + /** + * Garbage this part. + * This part will be not used anymore. + * The part is already marked as ORPHANED. It is not used anymore. It is already detached + * from its parent. <br> + * This method is called by the sashwindows garbage mechanism after the Part has been marked as ORPHANED. + * All resources associated to this part can be disposed. + * + */ + @Override + public void garbage() { + dispose(); + // fire appropriate life cycle event + getSashWindowContainer().getLifeCycleEventProvider().firePageClosedEvent(this); + } + + + /** + * Accept the provided visitor. + * Call the corresponding accept method in the visitor. + * + * @param visitor + * @return + */ + @Override + public boolean visit(IPartVisitor visitor) { + return visitor.accept(this); + } + + /** + * Visit the children of this Tile. + * There is no child, so do nothing. + * + * @param visitor + */ + public boolean visitChildren(IPartVisitor visitor) { + return true; + } + + + /** + * Show item status. + */ + protected void showStatus() { + // System.out.println( "EditorTile: " + // + " disposed=" + editorControl.isDisposed() + // + ", visible=" + editorControl.isVisible() + // + ", garbState=" + garbageState + // + ", '" + editorPart.getTitle() + // + "', " + this); + String title = (editorPart != null ? editorPart.getTitle() : "no editorPart"); + System.out.printf("EditorTile: disposed=%-5b, visible=%-5b, garbState=%-10s, %s, %s\n", editorControl.isDisposed(), (editorControl.isDisposed() ? false : editorControl.isVisible()), garbageState, title, this); + + } + + /** + * Get the title for this part. {@inheritDoc} + */ + @Override + public String getPageTitle() { + try { + return editorModel.getTabTitle(); + } catch (Exception ex) { + Activator.log.error(ex); + return "Error"; + } + } + + /** + * Return an icon for this part. {@inheritDoc} + */ + @Override + public Image getPageIcon() { + try { + return editorModel.getTabIcon(); + } catch (Exception ex) { + Activator.log.error(ex); + return null; + } + } +} diff --git a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/AbstractServiceUtils.java b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/AbstractServiceUtils.java index 54fd40a134c..5176b8d88d2 100644 --- a/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/AbstractServiceUtils.java +++ b/plugins/infra/core/org.eclipse.papyrus.infra.core/src/org/eclipse/papyrus/infra/core/utils/AbstractServiceUtils.java @@ -1,7 +1,6 @@ /***************************************************************************** * Copyright (c) 2010, 2016 LIFL, CEA LIST, Christian W. Damus, and others. * - * * 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 @@ -9,13 +8,14 @@ * * Contributors: * Cedric Dumoulin (LIFL) cedric.dumoulin@lifl.fr - Initial API and implementation - * Christian W. Damus - bug 468030 - * Christian W. Damus - bug 485220 + * Christian W. Damus - bugs 468030, 485220, 474467 * *****************************************************************************/ package org.eclipse.papyrus.infra.core.utils; +import java.util.Optional; + import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.papyrus.infra.core.Activator; @@ -226,4 +226,45 @@ public abstract class AbstractServiceUtils<T> { } }; } + + /** + * Attempts to obtain the service registry from the given context object. + * + * @param from + * the context object + * @return maybe the registry + * + * @since 2.0 + */ + protected Optional<ServicesRegistry> tryServiceRegistry(T from) { + try { + return Optional.ofNullable(getServiceRegistry(from)); + } catch (ServiceException e) { + Activator.log.error(e); + return Optional.empty(); + } + } + + /** + * Attempts to obtain the requested from the registry associated with + * the given context object. + * + * @param from + * the context object + * @param serviceType + * the type of service to obtain + * @return maybe the service + * + * @since 2.0 + */ + public <S> Optional<S> tryService(T from, Class<S> serviceType) { + return tryServiceRegistry(from).map(services -> { + try { + return services.getService(serviceType); + } catch (ServiceException e) { + Activator.log.error(e); + return (S) null; + } + }); + } } diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/DependentEMFLabelProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/DependentEMFLabelProvider.java new file mode 100644 index 00000000000..172c59496c0 --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/DependentEMFLabelProvider.java @@ -0,0 +1,161 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus and others. + * + * 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.ui.emf.providers; + +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.LabelProviderChangedEvent; + +import com.google.common.collect.MapMaker; +import com.google.common.collect.Sets; + +/** + * A specialized {@link EMFLabelProvider} for label providers that compute labels + * for objects from labels of objects on which they depend. For example, in a + * banking system, an account label may be something like "Fred's Chequing" + * in which the label depends on the label of the account holder. If the holder's + * name changes from "Fred" to something else, the account's label also must be + * recomputed. + */ +public class DependentEMFLabelProvider extends EMFLabelProvider { + + private SubscriptionListener subscriptionListener; + + private final CopyOnWriteArrayList<ILabelProviderListener> listeners = new CopyOnWriteArrayList<>(); + + public DependentEMFLabelProvider() { + super(new ForwardingEMFLabelProvider()); + } + + @Override + public void dispose() { + if (subscriptionListener != null) { + subscriptionListener.dispose(); + } + + super.dispose(); + } + + /** + * Subscribe to label changes of the given {@code object} to notify that its + * {@code dependent}'s label accordingly changes. + * + * @param object + * an object to listen to + * @param dependent + * an object that depends on its labels + */ + protected void subscribe(EObject object, EObject dependent) { + if (baseEMFLabelProvider instanceof ForwardingEMFLabelProvider) { + SubscriptionListener subs = getSubscriptionListener(); + subs.add(object, dependent); + } + } + + /** + * Unsubscribe from label changes of the given {@code object} because the + * {@link dependent}'s labels no longer depend on it. + * + * @param object + * an object to listen to + * @param dependent + * an object that no longer depends on its labels + */ + protected void unsubscribe(EObject object, EObject dependent) { + // If we didn't create the listener, yet, then it can't be attached to anything + if (subscriptionListener != null) { + subscriptionListener.remove(object, dependent); + } + } + + private SubscriptionListener getSubscriptionListener() { + if (subscriptionListener == null) { + subscriptionListener = new SubscriptionListener(); + ((ForwardingEMFLabelProvider) baseEMFLabelProvider).addListener(subscriptionListener); + } + + return subscriptionListener; + } + + @Override + public void addListener(ILabelProviderListener listener) { + super.addListener(listener); + listeners.addIfAbsent(listener); + } + + @Override + public void removeListener(ILabelProviderListener listener) { + listeners.remove(listener); + super.removeListener(listener); + } + + protected void fireLabelProviderChange(Object object) { + if (!listeners.isEmpty()) { + LabelProviderChangedEvent event = new LabelProviderChangedEvent(this, object); + listeners.forEach(l -> l.labelProviderChanged(event)); + } + } + + // + // Nested types + // + + private class SubscriptionListener implements ILabelProviderListener { + private final Map<EObject, Set<EObject>> subscriptions = new MapMaker().weakKeys().makeMap(); + + @Override + public void labelProviderChanged(LabelProviderChangedEvent event) { + Set<EObject> dependents = subscriptions.get(event.getElement()); + if (dependents != null) { + dependents.forEach(DependentEMFLabelProvider.this::fireLabelProviderChange); + } + } + + void add(EObject subscription, EObject dependent) { + subscriptions.computeIfAbsent(subscription, x -> Sets.newSetFromMap(new WeakHashMap<>())) + .add(dependent); + } + + void remove(EObject subscription, EObject dependent) { + Set<EObject> dependents = subscriptions.get(subscription); + if (dependents != null) { + dependents.remove(dependent); + if (dependents.isEmpty()) { + subscriptions.remove(subscription); + } + if (subscriptions.isEmpty()) { + this.dispose(); + } + } + } + + void dispose() { + if (baseEMFLabelProvider instanceof ForwardingEMFLabelProvider) { + ((ForwardingEMFLabelProvider) baseEMFLabelProvider).removeListener(this); + } + + subscriptions.clear(); + + if (subscriptionListener == this) { + subscriptionListener = null; + } + } + } + +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/EMFLabelProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/EMFLabelProvider.java index 20e055e6a78..0a970d1c29c 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/EMFLabelProvider.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/EMFLabelProvider.java @@ -1,302 +1,346 @@ -/*****************************************************************************
- * Copyright (c) 2011 CEA LIST.
- *
- * 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:
- * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
- *****************************************************************************/
-package org.eclipse.papyrus.infra.ui.emf.providers;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.internal.treeproxy.TreeElement;
-import org.eclipse.papyrus.emf.facet.custom.ui.internal.DecoratingCustomizedLabelProvider;
-import org.eclipse.papyrus.emf.facet.custom.ui.internal.ResolvingCustomizedLabelProvider;
-import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
-import org.eclipse.papyrus.infra.services.labelprovider.service.IDetailLabelProvider;
-import org.eclipse.papyrus.infra.services.labelprovider.service.IQualifierLabelProvider;
-import org.eclipse.papyrus.infra.ui.internal.emf.Activator;
-import org.eclipse.swt.graphics.Image;
-
-/**
- * This class handles labels for EMF Objects
- * The class can handle the following cases :
- * - An EObject (Which can be resolved with {@link EMFHelper#getEObject(Object)})
- * - A IStructuredSelection containing EObject(s)
- *
- * @author Camille Letavernier
- */
-public class EMFLabelProvider extends ResolvingCustomizedLabelProvider implements IDetailLabelProvider, IQualifierLabelProvider {
-
- protected ILabelProvider baseEMFLabelProvider;
-
- /**
- * Creates a new EMFObjectLabelProvider.
- */
- public EMFLabelProvider() {
- super(new DecoratingCustomizedLabelProvider(Activator.getDefault().getCustomizationManager())); // Note: CustomizableModelLabelProvider doesn't use the CustomizationManager. It relies on the content provider's CustomizationManager
- baseEMFLabelProvider = new StandardEMFLabelProvider();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getText(Object element) {
- if (element == null) {
- return ""; //$NON-NLS-1$
- }
-
- if (element instanceof TreeElement) {
- return super.getText(element);
- }
-
- EObject eObject = EMFHelper.getEObject(element);
- if (eObject != null) {
- return getText(eObject);
- }
-
- if (element instanceof IStructuredSelection) {
- return getText((IStructuredSelection) element);
- }
-
- return element.toString();
- }
-
- protected String getText(EObject element) {
- return baseEMFLabelProvider.getText(element);
- }
-
- protected String getText(IStructuredSelection selection) {
- if (selection.isEmpty()) {
- return ""; //$NON-NLS-1$
- }
-
- if (selection.size() == 1) {
- return getText(selection.getFirstElement());
- } else {
- final List<?> selectionAsList = selection.toList();
- String str = "";
- for (int i = 0; i < selectionAsList.size(); i++) {
- final String txt = getText(selectionAsList.get(i));
- if (txt != null) {
- str += txt;
- }
- if (i < selectionAsList.size() - 1) {
- str += ", ";
- }
- }
- return str;
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Image getImage(Object element) {
- if (element instanceof TreeElement) {
- return super.getImage(element);
- }
-
- EObject eObject = EMFHelper.getEObject(element);
- if (eObject != null) {
- return getImage(eObject);
- }
-
- if (element instanceof IStructuredSelection) {
- return getImage((IStructuredSelection) element);
- }
-
- return null;
- }
-
- protected Image getImage(EObject eObject) {
- return baseEMFLabelProvider.getImage(eObject);
- }
-
- protected Image getImage(IStructuredSelection selection) {
- if (selection.isEmpty()) {
- return null;
- } else if (selection.size() == 1) {
- return getImage(selection.getFirstElement());
- }
-
- final List<?> selectionAsList = selection.toList();
- final Set<EObject> selectedEObject = new HashSet<EObject>();
- boolean isEObjectSelection = true;
- for (final Object current : selectionAsList) {
- final EObject obj = EMFHelper.getEObject(current);
- if (obj != null) {
- selectedEObject.add(obj);
- } else {
- isEObjectSelection = false;
- }
- }
-
- if (isEObjectSelection) {// all selected elements are EObject
- if (selectedEObject.size() == 1 || hasCommonImage(selectedEObject)) {
- return getImage(selectedEObject.toArray()[0]);
- } else {
- final EClass common = org.eclipse.papyrus.emf.facet.util.emf.core.internal.EMFUtils.computeLeastCommonSupertype(getEClasses(selectedEObject));
- if (!common.isAbstract()) {
- // FIXME : the label provider service should manage this case
- final Object instance = common.getEPackage().getEFactoryInstance().create(common);
- return getNonCommonIcon(instance);
- }
- }
- } else if (selectedEObject.size() == 0) {
- // the multiple selection contains any EObject
- } else {
- // the selection contains EObject and others elements
- }
- return null;
- }
-
- /**
- *
- * @param objects
- * a collection of objects
- * @return
- * <code>true</code> if the image found for each object is the same <code>false</code> of if the collection is empty or the image returned
- * for each object is not the same
- */
- protected boolean hasCommonImage(final Collection<?> objects) {
- if (!objects.isEmpty()) {
- final Image lastImage = getImage(objects.toArray()[0]);
- for (final Object current : objects) {
- if (lastImage != getImage(current)) {
- return false;
- }
- }
- } else {
- return false;
- }
- return true;
- }
-
- /**
- *
- * @param commonEClass
- * the eClass
- * @return
- * the icon to use for this eclass
- */
- protected Image getNonCommonIcon(final Object commonObject) {
- return getImage(commonObject);
- }
-
- /**
- *
- * @param objects
- * a collection of eobject
- * @return
- * the set of eclasses for the parameter objects
- */
- private Set<EClass> getEClasses(final Collection<EObject> objects) {
- final Set<EClass> eclasses = new HashSet<EClass>();
- for (final EObject current : objects) {
- eclasses.add(current.eClass());
- }
- return eclasses;
- }
-
- public String getDetail(Object object) {
- object = EMFHelper.getEObject(object);
- return getText(object) + " - " + getQualifiedClassName(object); //$NON-NLS-1$
- }
-
- /**
- * Returns the qualified Class name of the given EObject, or an
- * empty String if the object is not an EObject
- *
- * @param object
- * @return The qualified name of this object's class, or an empty
- * String if the object is not an EObject
- */
- protected String getQualifiedClassName(Object object) {
- if (object instanceof EObject) {
- EObject eObject = (EObject) object;
- EClass eClass = eObject.eClass();
- return EMFHelper.getQualifiedName(eClass, "::"); //$NON-NLS-1$
- }
- return ""; //$NON-NLS-1$
- }
-
-
-
- public String getQualifierText(Object element) {
- String result = null;
-
- EObject parent = getParentObject(element);
- if (parent != null) {
- result = getQualifiedText(parent);
- }
-
- return result;
- }
-
- private EObject getParentObject(Object element) {
- EObject result = null;
-
- if (element != null) {
- EObject eObject = EMFHelper.getEObject(element);
- if (eObject != null) {
- result = getParent(eObject);
- }
- }
-
- return result;
- }
-
- public Image getQualifierImage(Object element) {
- Image result = null;
-
- EObject parent = getParentObject(element);
- if (parent != null) {
- result = getImage(parent);
- }
-
- return result;
- }
-
- protected EObject getParent(EObject object) {
- return object.eContainer();
- }
-
- protected String getQualifiedText(EObject object) {
- StringBuilder result = new StringBuilder();
-
- appendQualifiedText(object, result);
-
- return result.toString();
- }
-
- protected void appendQualifiedText(EObject object, StringBuilder buf) {
- EObject parent = getParent(object);
- if (parent != null) {
- appendQualifiedText(parent, buf);
- }
-
- if (buf.length() > 0) {
- buf.append("::");
- }
-
- String name = getText(object);
- if (name == null) {
- name = String.format("<%s>", object.eClass().getName());
- }
- buf.append(name);
- }
-}
+/***************************************************************************** + * Copyright (c) 2011, 2016 CEA LIST, Christian W. Damus, and others. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 474467 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.ui.emf.providers; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.papyrus.emf.facet.custom.metamodel.v0_2_0.internal.treeproxy.TreeElement; +import org.eclipse.papyrus.emf.facet.custom.ui.internal.DecoratingCustomizedLabelProvider; +import org.eclipse.papyrus.emf.facet.custom.ui.internal.ResolvingCustomizedLabelProvider; +import org.eclipse.papyrus.infra.emf.utils.EMFHelper; +import org.eclipse.papyrus.infra.services.labelprovider.service.IDetailLabelProvider; +import org.eclipse.papyrus.infra.services.labelprovider.service.IQualifierLabelProvider; +import org.eclipse.papyrus.infra.ui.internal.emf.Activator; +import org.eclipse.swt.graphics.Image; + +/** + * This class handles labels for EMF Objects + * The class can handle the following cases : + * - An EObject (Which can be resolved with {@link EMFHelper#getEObject(Object)}) + * - A IStructuredSelection containing EObject(s) + * + * @author Camille Letavernier + */ +public class EMFLabelProvider extends ResolvingCustomizedLabelProvider implements IDetailLabelProvider, IQualifierLabelProvider { + + protected ILabelProvider baseEMFLabelProvider; + + /** + * Creates a new EMFObjectLabelProvider. + */ + public EMFLabelProvider() { + this(new StandardEMFLabelProvider()); + } + + EMFLabelProvider(ILabelProvider baseEMFLabelProvider) { + // Note: CustomizableModelLabelProvider doesn't use the CustomizationManager. + // It relies on the content provider's CustomizationManager + super(new DecoratingCustomizedLabelProvider(Activator.getDefault().getCustomizationManager())); + this.baseEMFLabelProvider = baseEMFLabelProvider; + } + + @Override + public void dispose() { + baseEMFLabelProvider.dispose(); + + super.dispose(); + } + + /** + * {@inheritDoc} + */ + @Override + public String getText(Object element) { + if (element == null) { + return ""; //$NON-NLS-1$ + } + + if (element instanceof TreeElement) { + return super.getText(element); + } + + EObject eObject = EMFHelper.getEObject(element); + if (eObject != null) { + return getText(eObject); + } + + if (element instanceof IStructuredSelection) { + return getText((IStructuredSelection) element); + } + + return element.toString(); + } + + protected String getText(EObject element) { + return baseEMFLabelProvider.getText(element); + } + + protected String getText(IStructuredSelection selection) { + if (selection.isEmpty()) { + return ""; //$NON-NLS-1$ + } + + if (selection.size() == 1) { + return getText(selection.getFirstElement()); + } else { + final List<?> selectionAsList = selection.toList(); + String str = ""; + for (int i = 0; i < selectionAsList.size(); i++) { + final String txt = getText(selectionAsList.get(i)); + if (txt != null) { + str += txt; + } + if (i < selectionAsList.size() - 1) { + str += ", "; + } + } + return str; + } + } + + /** + * {@inheritDoc} + */ + @Override + public Image getImage(Object element) { + if (element instanceof TreeElement) { + return super.getImage(element); + } + + EObject eObject = EMFHelper.getEObject(element); + if (eObject != null) { + return getImage(eObject); + } + + if (element instanceof IStructuredSelection) { + return getImage((IStructuredSelection) element); + } + + return null; + } + + protected Image getImage(EObject eObject) { + return baseEMFLabelProvider.getImage(eObject); + } + + protected Image getImage(IStructuredSelection selection) { + if (selection.isEmpty()) { + return null; + } else if (selection.size() == 1) { + return getImage(selection.getFirstElement()); + } + + final List<?> selectionAsList = selection.toList(); + final Set<EObject> selectedEObject = new HashSet<EObject>(); + boolean isEObjectSelection = true; + for (final Object current : selectionAsList) { + final EObject obj = EMFHelper.getEObject(current); + if (obj != null) { + selectedEObject.add(obj); + } else { + isEObjectSelection = false; + } + } + + if (isEObjectSelection) {// all selected elements are EObject + if (selectedEObject.size() == 1 || hasCommonImage(selectedEObject)) { + return getImage(selectedEObject.toArray()[0]); + } else { + final EClass common = org.eclipse.papyrus.emf.facet.util.emf.core.internal.EMFUtils.computeLeastCommonSupertype(getEClasses(selectedEObject)); + if (!common.isAbstract()) { + // FIXME : the label provider service should manage this case + final Object instance = common.getEPackage().getEFactoryInstance().create(common); + return getNonCommonIcon(instance); + } + } + } else if (selectedEObject.size() == 0) { + // the multiple selection contains any EObject + } else { + // the selection contains EObject and others elements + } + return null; + } + + /** + * + * @param objects + * a collection of objects + * @return + * <code>true</code> if the image found for each object is the same <code>false</code> of if the collection is empty or the image returned + * for each object is not the same + */ + protected boolean hasCommonImage(final Collection<?> objects) { + if (!objects.isEmpty()) { + final Image lastImage = getImage(objects.toArray()[0]); + for (final Object current : objects) { + if (lastImage != getImage(current)) { + return false; + } + } + } else { + return false; + } + return true; + } + + /** + * + * @param commonEClass + * the eClass + * @return + * the icon to use for this eclass + */ + protected Image getNonCommonIcon(final Object commonObject) { + return getImage(commonObject); + } + + /** + * + * @param objects + * a collection of eobject + * @return + * the set of eclasses for the parameter objects + */ + private Set<EClass> getEClasses(final Collection<EObject> objects) { + final Set<EClass> eclasses = new HashSet<EClass>(); + for (final EObject current : objects) { + eclasses.add(current.eClass()); + } + return eclasses; + } + + @Override + public String getDetail(Object object) { + object = EMFHelper.getEObject(object); + return getText(object) + " - " + getQualifiedClassName(object); //$NON-NLS-1$ + } + + /** + * Returns the qualified Class name of the given EObject, or an + * empty String if the object is not an EObject + * + * @param object + * @return The qualified name of this object's class, or an empty + * String if the object is not an EObject + */ + protected String getQualifiedClassName(Object object) { + if (object instanceof EObject) { + EObject eObject = (EObject) object; + EClass eClass = eObject.eClass(); + return EMFHelper.getQualifiedName(eClass, "::"); //$NON-NLS-1$ + } + return ""; //$NON-NLS-1$ + } + + + + @Override + public String getQualifierText(Object element) { + String result = null; + + EObject parent = getParentObject(element); + if (parent != null) { + result = getQualifiedText(parent); + } + + return result; + } + + private EObject getParentObject(Object element) { + EObject result = null; + + if (element != null) { + EObject eObject = EMFHelper.getEObject(element); + if (eObject != null) { + result = getParent(eObject); + } + } + + return result; + } + + @Override + public Image getQualifierImage(Object element) { + Image result = null; + + EObject parent = getParentObject(element); + if (parent != null) { + result = getImage(parent); + } + + return result; + } + + protected EObject getParent(EObject object) { + return object.eContainer(); + } + + protected String getQualifiedText(EObject object) { + StringBuilder result = new StringBuilder(); + + appendQualifiedText(object, result); + + return result.toString(); + } + + protected void appendQualifiedText(EObject object, StringBuilder buf) { + EObject parent = getParent(object); + if (parent != null) { + appendQualifiedText(parent, buf); + } + + if (buf.length() > 0) { + buf.append("::"); + } + + String name = getText(object); + if (name == null) { + name = String.format("<%s>", object.eClass().getName()); + } + buf.append(name); + } + + @Override + public void addListener(ILabelProviderListener listener) { + super.addListener(listener); + baseEMFLabelProvider.addListener(listener); + + // If we're adding a listener to it, presumably we want its + // notifications, so enable them + if (baseEMFLabelProvider.getClass() == StandardEMFLabelProvider.class) { + // Replace it with a fowarding provider + baseEMFLabelProvider.dispose(); + baseEMFLabelProvider = new ForwardingEMFLabelProvider(); + baseEMFLabelProvider.addListener(listener); + } else if (baseEMFLabelProvider instanceof AdapterFactoryLabelProvider) { + // Trust that it will notify if enabled + ((AdapterFactoryLabelProvider) baseEMFLabelProvider).setFireLabelUpdateNotifications(true); + } + } + + @Override + public void removeListener(ILabelProviderListener listener) { + baseEMFLabelProvider.removeListener(listener); + super.removeListener(listener); + } +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/ForwardingEMFLabelProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/ForwardingEMFLabelProvider.java new file mode 100644 index 00000000000..a998f1a1097 --- /dev/null +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/ForwardingEMFLabelProvider.java @@ -0,0 +1,82 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus and others. + * + * 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.ui.emf.providers; + +import java.util.Map; +import java.util.concurrent.ConcurrentMap; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.edit.provider.IChangeNotifier; +import org.eclipse.emf.edit.provider.IItemLabelProvider; +import org.eclipse.emf.edit.provider.INotifyChangedListener; + +import com.google.common.collect.MapMaker; + +/** + * A specialized {@link StandardEMFLabelProvider} that forwards change notifications + * from the label-providers to which it delegates. By default, it + * {@linkplain #isFireLabelUpdateNotifications() fires label update notifications} + * because that is the presumed purpose of using this class in the first place. + */ +public class ForwardingEMFLabelProvider extends StandardEMFLabelProvider { + + // Need to track this because EMF's change notifiers don't prevent multiple attachment + // of the same listener + private final ConcurrentMap<IChangeNotifier, INotifyChangedListener> forwards = new MapMaker().weakKeys().weakValues().makeMap(); + + private INotifyChangedListener forwardingListener; + + public ForwardingEMFLabelProvider() { + super(); + + // I am used in contexts where JFace label provider events are needed + setFireLabelUpdateNotifications(true); + } + + @Override + public void dispose() { + try { + for (Map.Entry<IChangeNotifier, INotifyChangedListener> next : forwards.entrySet()) { + next.getKey().removeListener(next.getValue()); + } + forwards.clear(); + } finally { + super.dispose(); + } + } + + @Override + IItemLabelProvider adapt(AdapterFactory adapterFactory, EObject object) { + IItemLabelProvider result = super.adapt(adapterFactory, object); + + if (result instanceof IChangeNotifier) { + // Hook it up for forwarding + IChangeNotifier notifier = (IChangeNotifier) result; + if (forwards.putIfAbsent(notifier, getForwardingListener()) == null) { + notifier.addListener(getForwardingListener()); + } + } + + return result; + } + + private INotifyChangedListener getForwardingListener() { + if (forwardingListener == null) { + forwardingListener = notification -> notifyChanged(notification); + } + return forwardingListener; + } + +} diff --git a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/StandardEMFLabelProvider.java b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/StandardEMFLabelProvider.java index d659ec48007..62b12fa7200 100644 --- a/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/StandardEMFLabelProvider.java +++ b/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf/src/org/eclipse/papyrus/infra/ui/emf/providers/StandardEMFLabelProvider.java @@ -1,5 +1,6 @@ /******************************************************************************* - * Copyright (c) 2008 Obeo. + * Copyright (c) 2008, 2016 Obeo, CEA LIST, Christian W. Damus, and others. + * * 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 @@ -9,6 +10,8 @@ * Obeo - initial API and implementation * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Added support for enum literals * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Implementation of IDetailLabelProvider + * Christian W. Damus - bug 474467 + * *******************************************************************************/ package org.eclipse.papyrus.infra.ui.emf.providers; @@ -42,9 +45,6 @@ import org.eclipse.swt.graphics.Image; */ public class StandardEMFLabelProvider extends AdapterFactoryLabelProvider implements IDetailLabelProvider { - /** item provider class */ - private static final Class<?> IItemLabelProviderClass = IItemLabelProvider.class; - /** list of adapter factories, identified by their Ids */ private static Map<String, AdapterFactory> factories = new HashMap<String, AdapterFactory>(); @@ -154,12 +154,16 @@ public class StandardEMFLabelProvider extends AdapterFactoryLabelProvider implem if (eObject != null) { AdapterFactory adapterFactory = getEditFactory(eObject); if (adapterFactory != null) { - return (IItemLabelProvider) adapterFactory.adapt(eObject, IItemLabelProviderClass); + itemLabelProvider = adapt(adapterFactory, eObject); } } return itemLabelProvider; } + IItemLabelProvider adapt(AdapterFactory adapterFactory, EObject object) { + return (IItemLabelProvider) adapterFactory.adapt(object, IItemLabelProvider.class); + } + /** * Gets the edit factory. * @@ -205,6 +209,7 @@ public class StandardEMFLabelProvider extends AdapterFactoryLabelProvider implem return factory; } + @Override public String getDetail(Object object) { object = EMFHelper.getEObject(object); return getText(object) + " - " + getQualifiedClassName(object); //$NON-NLS-1$ @@ -226,5 +231,4 @@ public class StandardEMFLabelProvider extends AdapterFactoryLabelProvider implem } return ""; //$NON-NLS-1$ } - } diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/GmfEditorFactory.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/GmfEditorFactory.java index 15ebfc9c20b..7092088acc3 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/GmfEditorFactory.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/GmfEditorFactory.java @@ -1,6 +1,5 @@ /***************************************************************************** - * Copyright (c) 2008, 2014 LIFL, CEA LIST, and others. - * + * Copyright (c) 2008, 2016 LIFL, CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,6 +10,7 @@ * Cedric Dumoulin Cedric.dumoulin@lifl.fr - Initial API and implementation * Christian W. Damus (CEA) - service hook for integrating tools into graphical editor (CDO) * Christian W. Damus (CEA) - bug 392301 + * Christian W. Damus - bug 474467 * *****************************************************************************/ package org.eclipse.papyrus.infra.gmfdiag.common; @@ -19,19 +19,19 @@ import java.lang.reflect.Constructor; import org.eclipse.gef.ui.parts.GraphicalEditor; import org.eclipse.gmf.runtime.notation.Diagram; -import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.papyrus.infra.core.editor.BackboneException; +import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.AbstractPageModel; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IEditorModel; import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel; import org.eclipse.papyrus.infra.core.services.ServiceException; import org.eclipse.papyrus.infra.core.services.ServicesRegistry; -import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForEObject; +import org.eclipse.papyrus.infra.core.utils.ServiceUtils; import org.eclipse.papyrus.infra.gmfdiag.common.messages.Messages; -import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramUtils; +import org.eclipse.papyrus.infra.gmfdiag.common.providers.NotationLabelProvider; import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService; import org.eclipse.papyrus.infra.ui.extension.diagrameditor.AbstractEditorFactory; import org.eclipse.papyrus.infra.ui.multidiagram.actionbarcontributor.ActionBarContributorRegistry; -import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.part.EditorActionBarContributor; @@ -83,17 +83,14 @@ public class GmfEditorFactory extends AbstractEditorFactory { } - /** - * - * @see org.eclipse.papyrus.infra.ui.extension.diagrameditor.IPluggableEditorFactory#createIPageModel(java.lang.Object) - * @param pageIdentifier - * @return - * - */ @Override public IPageModel createIPageModel(Object pageIdentifier) { + ServicesRegistry services = getServiceRegistry(); + ILabelProvider labels = ServiceUtils.getInstance().tryService(services, LabelProviderService.class) + .map(lps -> lps.getLabelProvider(pageIdentifier)) + .orElseGet(NotationLabelProvider::new); - return new GMFEditorModel((Diagram) pageIdentifier, getServiceRegistry()); + return new GMFEditorModel((Diagram) pageIdentifier, services, labels); } /** @@ -102,7 +99,7 @@ public class GmfEditorFactory extends AbstractEditorFactory { * @author dumoulin * */ - class GMFEditorModel implements IEditorModel { + class GMFEditorModel extends AbstractPageModel implements IEditorModel { /** * The Diagram object describing the diagram. @@ -114,13 +111,13 @@ public class GmfEditorFactory extends AbstractEditorFactory { */ private ServicesRegistry servicesRegistry; - private Image tabIcon; - /** * * Constructor. */ - public GMFEditorModel(Diagram pageIdentifier, ServicesRegistry servicesRegistry) { + public GMFEditorModel(Diagram pageIdentifier, ServicesRegistry servicesRegistry, ILabelProvider labels) { + super(labels); + diagram = pageIdentifier; this.servicesRegistry = servicesRegistry; } @@ -204,51 +201,6 @@ public class GmfEditorFactory extends AbstractEditorFactory { public Object getRawModel() { return diagram; } - - /** - * Get the icon to be shown by Tabs - * - * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel#getTabIcon() - * @return - * - */ - @Override - public Image getTabIcon() { - if (tabIcon == null) { - ImageDescriptor imageDescriptor = DiagramUtils.getPrototype(diagram).getIconDescriptor(); - if (imageDescriptor != null) { - tabIcon = imageDescriptor.createImage(); - } - } - - return tabIcon; - } - - /** - * Get the title of the Diagram. - * - * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel#getTabTitle() - * @return - * - */ - @Override - public String getTabTitle() { - try { - LabelProviderService service = ServiceUtilsForEObject.getInstance().getService(LabelProviderService.class, diagram); - return service.getLabelProvider().getText(diagram); - } catch (ServiceException e) { - Activator.log.error(e); - } - return diagram.getName(); - } - - @Override - public void dispose() { - if (tabIcon != null) { - tabIcon.dispose(); - tabIcon = null; - } - } } } diff --git a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/NotationLabelProvider.java b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/NotationLabelProvider.java index 8a33dd14ea1..7dc1bc51caa 100644 --- a/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/NotationLabelProvider.java +++ b/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/NotationLabelProvider.java @@ -1,92 +1,69 @@ -/*****************************************************************************
- * Copyright (c) 2012 CEA LIST.
- *
- * 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:
- * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation
- *****************************************************************************/
-package org.eclipse.papyrus.infra.gmfdiag.common.providers;
-
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.gef.EditPart;
-import org.eclipse.gmf.runtime.diagram.ui.editparts.ResizableCompartmentEditPart;
-import org.eclipse.gmf.runtime.diagram.ui.services.editpart.EditPartService;
-import org.eclipse.gmf.runtime.notation.BasicCompartment;
-import org.eclipse.gmf.runtime.notation.DecorationNode;
-import org.eclipse.gmf.runtime.notation.Diagram;
-import org.eclipse.gmf.runtime.notation.View;
-import org.eclipse.papyrus.infra.gmfdiag.common.Activator;
-import org.eclipse.papyrus.infra.gmfdiag.common.types.NotationTypesMap;
-import org.eclipse.papyrus.infra.gmfdiag.common.utils.DiagramUtils;
-import org.eclipse.papyrus.infra.ui.emf.providers.EMFLabelProvider;
-import org.eclipse.papyrus.infra.viewpoints.policy.ViewPrototype;
-import org.eclipse.swt.graphics.Image;
-
-/**
- * A Label Provider for GMF Notation model
- */
-public class NotationLabelProvider extends EMFLabelProvider {
-
- /** icon for a compartment */
- public static final String ICON_COMPARTMENT = "/icons/none_comp_vis.gif"; //$NON-NLS-1$
-
- @Override
- public void dispose() {
- super.dispose();
- }
-
- @Override
- protected Image getImage(EObject element) {
- if (element instanceof Diagram) {
- ViewPrototype proto = DiagramUtils.getPrototype((Diagram) element);
- if (proto == null) {
- return null;
- }
- return proto.getIcon();
- }
-
- // if the element is a compartment
- if (element instanceof BasicCompartment || element instanceof DecorationNode) {
- return org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage(Activator.ID, ICON_COMPARTMENT);
- }
-
- return super.getImage(element);
- }
-
- /**
- *
- * @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
- *
- * @param element
- * @return
- * <ul>
- * <li>if element is a {@link NamedElement}, we return its name</li>
- * <li>else if element is a {@link Element}, we return its type + a index</li>
- * <li>else return Messages#EditorLabelProvider_No_name</li>
- * </ul>
- */
- @Override
- protected String getText(EObject element) {
- if (element instanceof Diagram) {
- return ((Diagram) element).getName();
- }
-
- if (element instanceof View) { // maybe it is a view of a compartment
- String humanType = NotationTypesMap.instance.getHumanReadableType((View) element);
- if (humanType != null) {
- return humanType;
- }
-
- EditPart dummyEP = EditPartService.getInstance().createGraphicEditPart((View) element);
- if (dummyEP instanceof ResizableCompartmentEditPart) {
- return ((ResizableCompartmentEditPart) dummyEP).getCompartmentName();
- }
- }
-
- return super.getText(element);
- }
-}
+/***************************************************************************** + * Copyright (c) 2012, 2016 CEA LIST, Christian W. Damus, and others. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 474467 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.gmfdiag.common.providers; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gef.EditPart; +import org.eclipse.gmf.runtime.diagram.ui.editparts.ResizableCompartmentEditPart; +import org.eclipse.gmf.runtime.diagram.ui.services.editpart.EditPartService; +import org.eclipse.gmf.runtime.notation.BasicCompartment; +import org.eclipse.gmf.runtime.notation.DecorationNode; +import org.eclipse.gmf.runtime.notation.Diagram; +import org.eclipse.gmf.runtime.notation.View; +import org.eclipse.papyrus.infra.gmfdiag.common.Activator; +import org.eclipse.papyrus.infra.gmfdiag.common.types.NotationTypesMap; +import org.eclipse.papyrus.infra.viewpoints.policy.ViewPrototypeLabelProvider; +import org.eclipse.swt.graphics.Image; + +/** + * A Label Provider for GMF Notation model + */ +public class NotationLabelProvider extends ViewPrototypeLabelProvider { + + /** icon for a compartment */ + public static final String ICON_COMPARTMENT = "/icons/none_comp_vis.gif"; //$NON-NLS-1$ + + @Override + protected Image getImage(EObject element) { + // if the element is a compartment + if (element instanceof BasicCompartment || element instanceof DecorationNode) { + return org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage(Activator.ID, ICON_COMPARTMENT); + } + + return super.getImage(element); + } + + @Override + protected String getText(EObject element) { + String result = null; + + if (element instanceof Diagram) { + result = super.getText(element); + } else if (element instanceof View) { // maybe it is a view of a compartment + String humanType = NotationTypesMap.instance.getHumanReadableType((View) element); + if (humanType != null) { + result = humanType; + } else { + EditPart dummyEP = EditPartService.getInstance().createGraphicEditPart((View) element); + if (dummyEP instanceof ResizableCompartmentEditPart) { + result = ((ResizableCompartmentEditPart) dummyEP).getCompartmentName(); + } + } + } else { + result = super.getText(element); + } + + return result; + } +} diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/.classpath b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/.classpath index 8a8f1668cdc..eca7bdba8f0 100644 --- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/.classpath +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/.classpath @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/.settings/org.eclipse.jdt.core.prefs b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/.settings/org.eclipse.jdt.core.prefs index 94d61f00da6..b3aa6d60f94 100644 --- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/.settings/org.eclipse.jdt.core.prefs +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/.settings/org.eclipse.jdt.core.prefs @@ -1,10 +1,10 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/META-INF/MANIFEST.MF b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/META-INF/MANIFEST.MF index 6f08492aac3..2f19d31ecec 100644 --- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/META-INF/MANIFEST.MF +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/META-INF/MANIFEST.MF @@ -23,4 +23,4 @@ Bundle-Name: %Bundle-Name Bundle-Activator: org.eclipse.papyrus.infra.nattable.common.Activator Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.papyrus.infra.nattable.common;singleton:=true -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/factory/NattableEditorFactory.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/factory/NattableEditorFactory.java index adeab806353..f6fb244db5b 100644 --- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/factory/NattableEditorFactory.java +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.common/src/org/eclipse/papyrus/infra/nattable/common/factory/NattableEditorFactory.java @@ -1,6 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2011, 2014 LIFL, CEA LIST, and others.
- *
+ * Copyright (c) 2011, 2016 LIFL, CEA LIST, Christian W. Damus, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -11,23 +10,28 @@ * Cedric Dumoulin (LIFL) cedric.dumoulin@lifl.fr - Initial API and implementation
* Vincent Lorenzo (CEA-LIST) vincent.lorenzo@cea.fr
* Christian W. Damus (CEA) - bug 392301
+ * Christian W. Damus - bug 474467
*
*****************************************************************************/
package org.eclipse.papyrus.infra.nattable.common.factory;
import java.lang.reflect.Constructor;
+import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.papyrus.infra.core.editor.BackboneException;
+import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.AbstractPageModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IEditorModel;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
+import org.eclipse.papyrus.infra.core.utils.ServiceUtils;
import org.eclipse.papyrus.infra.nattable.Activator;
import org.eclipse.papyrus.infra.nattable.common.editor.NatTableEditor;
import org.eclipse.papyrus.infra.nattable.model.nattable.Table;
+import org.eclipse.papyrus.infra.nattable.provider.TableLabelProvider;
+import org.eclipse.papyrus.infra.services.labelprovider.service.LabelProviderService;
import org.eclipse.papyrus.infra.ui.extension.diagrameditor.AbstractEditorFactory;
import org.eclipse.papyrus.infra.ui.multidiagram.actionbarcontributor.ActionBarContributorRegistry;
-import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorActionBarContributor;
@@ -64,7 +68,12 @@ public class NattableEditorFactory extends AbstractEditorFactory { */
@Override
public IPageModel createIPageModel(Object pageIdentifier) {
- return new NattableEditorModel(pageIdentifier, getServiceRegistry());
+ ServicesRegistry services = getServiceRegistry();
+ ILabelProvider labels = ServiceUtils.getInstance().tryService(services, LabelProviderService.class)
+ .map(lps -> lps.getLabelProvider(pageIdentifier))
+ .orElseGet(TableLabelProvider::new);
+
+ return new NattableEditorModel(pageIdentifier, services, labels);
}
/**
@@ -84,7 +93,7 @@ public class NattableEditorFactory extends AbstractEditorFactory { * @author cedric dumoulin
*
*/
- class NattableEditorModel implements IEditorModel {
+ class NattableEditorModel extends AbstractPageModel implements IEditorModel {
/**
@@ -106,7 +115,9 @@ public class NattableEditorFactory extends AbstractEditorFactory { *
* Constructor.
*/
- public NattableEditorModel(Object pageIdentifier, ServicesRegistry servicesRegistry) {
+ public NattableEditorModel(Object pageIdentifier, ServicesRegistry servicesRegistry, ILabelProvider labels) {
+ super(labels);
+
this.rawModel = (Table) pageIdentifier;
this.servicesRegistry = servicesRegistry;
}
@@ -186,34 +197,5 @@ public class NattableEditorFactory extends AbstractEditorFactory { public Object getRawModel() {
return this.rawModel;
}
-
- /**
- * Get the icon to be shown by Tabs
- *
- * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel#getTabIcon()
- * @return
- *
- */
- @Override
- public Image getTabIcon() {
- return org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage(this.rawModel.getTableConfiguration().getIconPath());
- }
-
- /**
- * Get the title of the Diagram.
- *
- * @see org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageModel#getTabTitle()
- * @return
- *
- */
- @Override
- public String getTabTitle() {
- return this.rawModel.getName();
- }
-
- @Override
- public void dispose() {
- // Pass. The tab icon is a plugin-shared image
- }
}
}
diff --git a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/provider/TableLabelProvider.java b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/provider/TableLabelProvider.java index 794a90418a7..f5383eecc89 100644 --- a/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/provider/TableLabelProvider.java +++ b/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable/src/org/eclipse/papyrus/infra/nattable/provider/TableLabelProvider.java @@ -1,5 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
+ * Copyright (c) 2013, 2016 CEA LIST, Christian W. Damus, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -8,17 +8,16 @@ *
* Contributors:
* Juan Cadavid (CEA LIST) juan.cadavid@cea.fr - Initial API and implementation
+ * Christian W. Damus - bug 474467
+ *
*****************************************************************************/
package org.eclipse.papyrus.infra.nattable.provider;
-import java.util.Collection;
-
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;
import org.eclipse.papyrus.infra.nattable.model.nattable.Table;
import org.eclipse.papyrus.infra.services.labelprovider.service.IFilteredLabelProvider;
-import org.eclipse.papyrus.infra.ui.emf.providers.EMFLabelProvider;
-import org.eclipse.papyrus.infra.widgets.Activator;
+import org.eclipse.papyrus.infra.viewpoints.policy.ViewPrototypeLabelProvider;
import org.eclipse.swt.graphics.Image;
/**
@@ -26,74 +25,16 @@ import org.eclipse.swt.graphics.Image; * This labelprovider provides icon and text for tables to display them in treeviewer AND in the property view
*
*/
-public class TableLabelProvider extends EMFLabelProvider implements IFilteredLabelProvider {
+public class TableLabelProvider extends ViewPrototypeLabelProvider implements IFilteredLabelProvider {
- /**
- *
- * @see org.eclipse.papyrus.infra.ui.emf.providers.EMFLabelProvider#getText(java.lang.Object)
- *
- * @param table
- * @return
- */
- @Override
- public String getText(Object table) {
- if (table instanceof IStructuredSelection) {
- return super.getText((IStructuredSelection) table);
- }
-
- Object el = EMFHelper.getEObject(table);
-
- if (el instanceof Table) {
- return ((Table) el).getName();
- }
- return ""; //$NON-NLS-1$
- }
-
- /**
- *
- * @see org.eclipse.papyrus.infra.ui.emf.providers.EMFLabelProvider#getImage(java.lang.Object)
- *
- * @param table
- * @return
- */
- @Override
- public Image getImage(Object table) {
- if (table instanceof IStructuredSelection) {
- return getImage(((IStructuredSelection) table));
- }
-
- table = EMFHelper.getEObject(table);
-
- if (table instanceof Table) {
- final String iconPath = getIcon((Table) table);
- if (iconPath != null) {
- return Activator.getDefault().getImage(iconPath);
- }
- }
- return null;
- }
-
- protected String getIcon(Table table) {
- if (table == null || table.getTableConfiguration() == null || table.getTableConfiguration().getIconPath() == null) {
- return null;
- }
- return table.getTableConfiguration().getIconPath();
- }
-
- /**
- *
- * @see org.eclipse.papyrus.infra.services.labelprovider.service.IFilteredLabelProvider#accept(java.lang.Object)
- *
- * @param object
- * @return
- */
@Override
public boolean accept(Object object) {
if (object instanceof IStructuredSelection) {
return accept((IStructuredSelection) object);
}
- return EMFHelper.getEObject(object) instanceof Table;
+ boolean result = EMFHelper.getEObject(object) instanceof Table;
+ return result;
}
/**
@@ -101,7 +42,7 @@ public class TableLabelProvider extends EMFLabelProvider implements IFilteredLab * @param selection
* a selection
* @return
- * <code>true</code> if all elements in the selection are accepted
+ * <code>true</code> if all elements in the selection are accepted
*/
protected boolean accept(final IStructuredSelection selection) {
for (final Object current : selection.toList()) {
@@ -112,43 +53,6 @@ public class TableLabelProvider extends EMFLabelProvider implements IFilteredLab return true;
}
- /**
- *
- * @see org.eclipse.papyrus.infra.ui.emf.providers.EMFLabelProvider#hasCommonImage(java.util.Collection)
- *
- * @param objects
- * @return
- * <code>true</code> if all selected table have the same icon
- */
- @Override
- protected boolean hasCommonImage(Collection<?> objects) {
- String iconPath = null;
- for (Object current : objects) {
- if (!(current instanceof Table)) {
- return false;
- }
-
- String icon = getIcon((Table) current);
- if (icon == null && iconPath != null) {
- return false;
- }
-
- if (iconPath == null) {
- iconPath = icon;
- } else if (!iconPath.equals(icon)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- *
- * @see org.eclipse.papyrus.infra.ui.emf.providers.EMFLabelProvider#getNonCommonIcon(java.lang.Object)
- *
- * @param commonObject
- * @return
- */
@Override
protected Image getNonCommonIcon(final Object commonObject) {
return org.eclipse.papyrus.infra.widgets.Activator.getDefault().getImage(org.eclipse.papyrus.infra.nattable.Activator.PLUGIN_ID, "/icons/table.gif");
diff --git a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/.classpath b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/.classpath index ed2585fb3f4..f0c55498599 100755 --- a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/.classpath +++ b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/.classpath @@ -1,8 +1,8 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="src-gen"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="src-gen"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/.settings/org.eclipse.jdt.core.prefs b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/.settings/org.eclipse.jdt.core.prefs index 4759947300a..62a08f4494d 100755 --- a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/.settings/org.eclipse.jdt.core.prefs +++ b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/.settings/org.eclipse.jdt.core.prefs @@ -1,10 +1,10 @@ eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
-org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/META-INF/MANIFEST.MF b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/META-INF/MANIFEST.MF index 91d463d9a96..f1bbf28c833 100755 --- a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/META-INF/MANIFEST.MF +++ b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/META-INF/MANIFEST.MF @@ -15,7 +15,8 @@ Require-Bundle: org.eclipse.ui;bundle-version="[3.107.0,4.0.0)";visibility:=reex org.eclipse.papyrus.infra.viewpoints.iso42010;bundle-version="[1.2.0,2.0.0)";visibility:=reexport, org.eclipse.papyrus.infra.viewpoints.configuration;bundle-version="[1.2.0,2.0.0)";visibility:=reexport, org.eclipse.papyrus.infra.constraints;bundle-version="[2.0.0,3.0.0)";visibility:=reexport, - org.eclipse.papyrus.infra.widgets;bundle-version="[2.0.0,3.0.0)" + org.eclipse.papyrus.infra.widgets;bundle-version="[2.0.0,3.0.0)", + org.eclipse.papyrus.infra.ui.emf;bundle-version="[1.2.0,2.0.0)" Bundle-Vendor: %providerName Bundle-ActivationPolicy: lazy Bundle-ClassPath: . @@ -25,4 +26,4 @@ Bundle-Name: %pluginName Bundle-ManifestVersion: 2 Bundle-Activator: org.eclipse.papyrus.infra.viewpoints.policy.Activator Bundle-SymbolicName: org.eclipse.papyrus.infra.viewpoints.policy;singleton:=true -Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/UnavailableViewPrototype.java b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/UnavailableViewPrototype.java index 663897e863a..9689ea5ad15 100755 --- a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/UnavailableViewPrototype.java +++ b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/UnavailableViewPrototype.java @@ -1,6 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
- *
+ * Copyright (c) 2013, 2016 CEA LIST, Christian W. Damus, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -9,6 +8,7 @@ *
* Contributors:
* Laurent Wouters laurent.wouters@cea.fr - Initial API and implementation
+ * Christian W. Damus - bug 474467
*
*****************************************************************************/
package org.eclipse.papyrus.infra.viewpoints.policy;
@@ -49,6 +49,11 @@ public class UnavailableViewPrototype extends ViewPrototype { return true;
}
+ @Override
+ public boolean isUnavailable() {
+ return true;
+ }
+
/**
* @see org.eclipse.papyrus.infra.viewpoints.policy.ViewPrototype#getImplementation()
*/
diff --git a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/ViewPrototype.java b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/ViewPrototype.java index 7b4ea6c23ad..e0b95afe2e4 100755 --- a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/ViewPrototype.java +++ b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/ViewPrototype.java @@ -1,6 +1,5 @@ /***************************************************************************** - * Copyright (c) 2013 CEA LIST. - * + * Copyright (c) 2013, 2016 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -9,6 +8,7 @@ * * Contributors: * Laurent Wouters laurent.wouters@cea.fr - Initial API and implementation + * Christian W. Damus - bug 474467 * *****************************************************************************/ package org.eclipse.papyrus.infra.viewpoints.policy; @@ -158,7 +158,7 @@ public abstract class ViewPrototype { * * @param view * The view for which a prototype is expected - * @return The view's prototype + * @return The view's prototype, never {@code null} but possibly {@link #isUnavailable() unavailable} */ public static ViewPrototype get(EObject view) { for (IViewTypeHelper helper : HELPERS) { @@ -227,6 +227,17 @@ public abstract class ViewPrototype { } /** + * Queries whether the prototype is unavailable, effectively a <em>Null Object</em>. + * + * @return whether the prototype is a non-view prototype + * + * @since 1.2 + */ + public boolean isUnavailable() { + return false; + } + + /** * Gets the ID of the implementation of this prototype * * @return The implementation ID @@ -419,6 +430,7 @@ public abstract class ViewPrototype { /** * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ + @Override public int compare(ViewPrototype proto1, ViewPrototype proto2) { Integer p1 = getPriority(proto1); Integer p2 = getPriority(proto2); diff --git a/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/ViewPrototypeLabelProvider.java b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/ViewPrototypeLabelProvider.java new file mode 100644 index 00000000000..5e71ff35851 --- /dev/null +++ b/plugins/infra/viewpoints/org.eclipse.papyrus.infra.viewpoints.policy/src/org/eclipse/papyrus/infra/viewpoints/policy/ViewPrototypeLabelProvider.java @@ -0,0 +1,95 @@ +/***************************************************************************** + * Copyright (c) 2012, 2016 CEA LIST, Christian W. Damus, and others. + * + * 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: + * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation + * Christian W. Damus - bug 474467 + * + *****************************************************************************/ +package org.eclipse.papyrus.infra.viewpoints.policy; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil; +import org.eclipse.osgi.util.NLS; +import org.eclipse.papyrus.infra.ui.emf.providers.DependentEMFLabelProvider; +import org.eclipse.swt.graphics.Image; + +/** + * A Label Provider for viewpoint-based notations. + * + * @since 1.2 + */ +public class ViewPrototypeLabelProvider extends DependentEMFLabelProvider { + + @Override + protected Image getImage(EObject element) { + Image result; + + ViewPrototype proto = ViewPrototype.get(element); + if (proto != null) { + // This is shared by the Widgets plug-in activator, so don't + // dispose it + result = proto.getIcon(); + } else { + result = super.getImage(element); + } + + return result; + } + + @Override + protected String getText(EObject element) { + // Hit the delegate to ensure that the item provider adapter is attached + // for notifications + String result = super.getText(element); + + ViewPrototype proto = ViewPrototype.get(element); + if (!proto.isUnavailable()) { + EObject context = proto.getRootOf(element); + result = getName(element); + + if ((result != null) && !result.isEmpty()) { + if (context != null) { + // In case we were deriving a label from it + unsubscribe(context, element); + } + } else { + if (context != null) { + String contextLabel = getText(context); + result = NLS.bind("({0} of {1})", proto.getLabel(), contextLabel); + + // Update when the context's label changes + subscribe(context, element); + } else { + result = NLS.bind("({1})", proto.getLabel()); + } + + if ((result == null) || result.isEmpty()) { + result = "(unnamed)"; + } + } + } // else just keep the super result + + return result; + } + + /** + * Attempts to infer the name of an {@code object} by looking for a string-valued + * attribute named "name". + * + * @param object + * an object + * + * @return a best-effort name for the {@code object} + * + * @see EMFCoreUtil#getName(EObject) + */ + protected String getName(EObject object) { + return EMFCoreUtil.getName(object); + } +} diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/basic/unnamed_diagram.di b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/basic/unnamed_diagram.di new file mode 100644 index 00000000000..6973c8a48a6 --- /dev/null +++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/basic/unnamed_diagram.di @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="ASCII"?> +<di:SashWindowsMngr xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.eclipse.org/papyrus/0.7.0/sashdi"> + <sashModel currentSelection="//@sashModel/@windows.0/@children.0"> + <windows> + <children xsi:type="di:TabFolder"> + <children> + <emfPageIdentifier href="unnamed_diagram.notation#_1xkSQHqQEeK9jI2Tc6HWsA"/> + </children> + </children> + </windows> + </sashModel> +</di:SashWindowsMngr> diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/basic/unnamed_diagram.notation b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/basic/unnamed_diagram.notation new file mode 100644 index 00000000000..d8bec030baf --- /dev/null +++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/basic/unnamed_diagram.notation @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_1xkSQHqQEeK9jI2Tc6HWsA" type="PapyrusUMLClassDiagram" measurementUnit="Pixel"> + <children xmi:type="notation:Shape" xmi:id="_2WT-EHqQEeK9jI2Tc6HWsA" type="2008"> + <children xmi:type="notation:DecorationNode" xmi:id="_2WdvEHqQEeK9jI2Tc6HWsA" type="5029"/> + <children xmi:type="notation:BasicCompartment" xmi:id="_2WdvEXqQEeK9jI2Tc6HWsA" type="7017"> + <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_2WdvIHqQEeK9jI2Tc6HWsA" source="PapyrusCSSForceValue"> + <details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_2WdvIXqQEeK9jI2Tc6HWsA" key="showTitle" value="true"/> + </eAnnotations> + <styles xmi:type="notation:TitleStyle" xmi:id="_2WdvEnqQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:SortingStyle" xmi:id="_2WdvE3qQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:FilteringStyle" xmi:id="_2WdvFHqQEeK9jI2Tc6HWsA"/> + <layoutConstraint xmi:type="notation:Bounds" xmi:id="_2WdvFXqQEeK9jI2Tc6HWsA"/> + </children> + <children xmi:type="notation:BasicCompartment" xmi:id="_2WdvFnqQEeK9jI2Tc6HWsA" type="7018"> + <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_2WdvInqQEeK9jI2Tc6HWsA" source="PapyrusCSSForceValue"> + <details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_2WdvI3qQEeK9jI2Tc6HWsA" key="showTitle" value="true"/> + </eAnnotations> + <styles xmi:type="notation:TitleStyle" xmi:id="_2WdvF3qQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:SortingStyle" xmi:id="_2WdvGHqQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:FilteringStyle" xmi:id="_2WdvGXqQEeK9jI2Tc6HWsA"/> + <layoutConstraint xmi:type="notation:Bounds" xmi:id="_2WdvGnqQEeK9jI2Tc6HWsA"/> + </children> + <children xmi:type="notation:BasicCompartment" xmi:id="_2WdvG3qQEeK9jI2Tc6HWsA" type="7019"> + <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_2WdvJHqQEeK9jI2Tc6HWsA" source="PapyrusCSSForceValue"> + <details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_2WdvJXqQEeK9jI2Tc6HWsA" key="showTitle" value="true"/> + </eAnnotations> + <styles xmi:type="notation:TitleStyle" xmi:id="_2WdvHHqQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:SortingStyle" xmi:id="_2WdvHXqQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:FilteringStyle" xmi:id="_2WdvHnqQEeK9jI2Tc6HWsA"/> + <layoutConstraint xmi:type="notation:Bounds" xmi:id="_2WdvH3qQEeK9jI2Tc6HWsA"/> + </children> + <element xmi:type="uml:Class" href="unnamed_diagram.uml#_2O35UHqQEeK9jI2Tc6HWsA"/> + <layoutConstraint xmi:type="notation:Bounds" xmi:id="_2WT-EXqQEeK9jI2Tc6HWsA" x="290" y="270"/> + </children> + <children xmi:type="notation:Shape" xmi:id="_3N8wsHqQEeK9jI2Tc6HWsA" type="2008"> + <children xmi:type="notation:DecorationNode" xmi:id="_3N8wsnqQEeK9jI2Tc6HWsA" type="5029"/> + <children xmi:type="notation:BasicCompartment" xmi:id="_3N8ws3qQEeK9jI2Tc6HWsA" type="7017"> + <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_3N8wwnqQEeK9jI2Tc6HWsA" source="PapyrusCSSForceValue"> + <details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_3N8ww3qQEeK9jI2Tc6HWsA" key="showTitle" value="true"/> + </eAnnotations> + <styles xmi:type="notation:TitleStyle" xmi:id="_3N8wtHqQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:SortingStyle" xmi:id="_3N8wtXqQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:FilteringStyle" xmi:id="_3N8wtnqQEeK9jI2Tc6HWsA"/> + <layoutConstraint xmi:type="notation:Bounds" xmi:id="_3N8wt3qQEeK9jI2Tc6HWsA"/> + </children> + <children xmi:type="notation:BasicCompartment" xmi:id="_3N8wuHqQEeK9jI2Tc6HWsA" type="7018"> + <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_3N8wxHqQEeK9jI2Tc6HWsA" source="PapyrusCSSForceValue"> + <details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_3N8wxXqQEeK9jI2Tc6HWsA" key="showTitle" value="true"/> + </eAnnotations> + <styles xmi:type="notation:TitleStyle" xmi:id="_3N8wuXqQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:SortingStyle" xmi:id="_3N8wunqQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:FilteringStyle" xmi:id="_3N8wu3qQEeK9jI2Tc6HWsA"/> + <layoutConstraint xmi:type="notation:Bounds" xmi:id="_3N8wvHqQEeK9jI2Tc6HWsA"/> + </children> + <children xmi:type="notation:BasicCompartment" xmi:id="_3N8wvXqQEeK9jI2Tc6HWsA" type="7019"> + <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_3N8wxnqQEeK9jI2Tc6HWsA" source="PapyrusCSSForceValue"> + <details xmi:type="ecore:EStringToStringMapEntry" xmi:id="_3N8wx3qQEeK9jI2Tc6HWsA" key="showTitle" value="true"/> + </eAnnotations> + <styles xmi:type="notation:TitleStyle" xmi:id="_3N8wvnqQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:SortingStyle" xmi:id="_3N8wv3qQEeK9jI2Tc6HWsA"/> + <styles xmi:type="notation:FilteringStyle" xmi:id="_3N8wwHqQEeK9jI2Tc6HWsA"/> + <layoutConstraint xmi:type="notation:Bounds" xmi:id="_3N8wwXqQEeK9jI2Tc6HWsA"/> + </children> + <element xmi:type="uml:Class" href="unnamed_diagram.uml#_3Np1wHqQEeK9jI2Tc6HWsA"/> + <layoutConstraint xmi:type="notation:Bounds" xmi:id="_3N8wsXqQEeK9jI2Tc6HWsA" x="840" y="270"/> + </children> + <styles xmi:type="notation:DiagramStyle" xmi:id="_1xkSQXqQEeK9jI2Tc6HWsA"/> + <element xmi:type="uml:Model" href="unnamed_diagram.uml#_1w91UHqQEeK9jI2Tc6HWsA"/> + <edges xmi:type="notation:Connector" xmi:id="_4hkUsHqQEeK9jI2Tc6HWsA" type="4001" source="_2WT-EHqQEeK9jI2Tc6HWsA" target="_3N8wsHqQEeK9jI2Tc6HWsA"> + <children xmi:type="notation:DecorationNode" xmi:id="_4hkUs3qQEeK9jI2Tc6HWsA" type="6001"> + <layoutConstraint xmi:type="notation:Location" xmi:id="_4hkUtHqQEeK9jI2Tc6HWsA" y="-20"/> + </children> + <children xmi:type="notation:DecorationNode" xmi:id="_4hkUtXqQEeK9jI2Tc6HWsA" type="6002"> + <layoutConstraint xmi:type="notation:Location" xmi:id="_4hkUtnqQEeK9jI2Tc6HWsA" y="20"/> + </children> + <children xmi:type="notation:DecorationNode" xmi:id="_4hkUt3qQEeK9jI2Tc6HWsA" type="6003"> + <layoutConstraint xmi:type="notation:Location" xmi:id="_4hkUuHqQEeK9jI2Tc6HWsA" y="-20"/> + </children> + <children xmi:type="notation:DecorationNode" xmi:id="_4hkUuXqQEeK9jI2Tc6HWsA" type="6005"> + <layoutConstraint xmi:type="notation:Location" xmi:id="_4hkUunqQEeK9jI2Tc6HWsA" y="20"/> + </children> + <children xmi:type="notation:DecorationNode" xmi:id="_4hkUu3qQEeK9jI2Tc6HWsA" type="6033"> + <layoutConstraint xmi:type="notation:Location" xmi:id="_4hkUvHqQEeK9jI2Tc6HWsA" y="20"/> + </children> + <children xmi:type="notation:DecorationNode" xmi:id="_4hkUvXqQEeK9jI2Tc6HWsA" type="6034"> + <layoutConstraint xmi:type="notation:Location" xmi:id="_4hkUvnqQEeK9jI2Tc6HWsA" y="-20"/> + </children> + <styles xmi:type="notation:FontStyle" xmi:id="_4hkUsXqQEeK9jI2Tc6HWsA"/> + <element xmi:type="uml:Association" href="unnamed_diagram.uml#_4hHowHqQEeK9jI2Tc6HWsA"/> + <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_4hkUsnqQEeK9jI2Tc6HWsA" points="[77, -1, -567, -9]$[645, -42, 1, -50]"/> + <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_4nEfwHqQEeK9jI2Tc6HWsA" id="(0.23,0.45)"/> + </edges> +</notation:Diagram> diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/basic/unnamed_diagram.uml b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/basic/unnamed_diagram.uml new file mode 100644 index 00000000000..cac8a57cf98 --- /dev/null +++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/basic/unnamed_diagram.uml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<uml:Model xmi:version="20110701" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_1w91UHqQEeK9jI2Tc6HWsA" name="model2"> + <packagedElement xmi:type="uml:Class" xmi:id="_2O35UHqQEeK9jI2Tc6HWsA" name="Class1"> + <ownedAttribute xmi:id="_4g93wHqQEeK9jI2Tc6HWsA" name="class2" type="_3Np1wHqQEeK9jI2Tc6HWsA" association="_4hHowHqQEeK9jI2Tc6HWsA"> + <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_4g93wXqQEeK9jI2Tc6HWsA" value="1"/> + <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_4g93wnqQEeK9jI2Tc6HWsA" value="1"/> + </ownedAttribute> + </packagedElement> + <packagedElement xmi:type="uml:Class" xmi:id="_3Np1wHqQEeK9jI2Tc6HWsA" name="Class2"/> + <packagedElement xmi:type="uml:Association" xmi:id="_4hHowHqQEeK9jI2Tc6HWsA" name="class1_class2_1" memberEnd="_4hHowXqQEeK9jI2Tc6HWsA _4g93wHqQEeK9jI2Tc6HWsA"> + <ownedEnd xmi:id="_4hHowXqQEeK9jI2Tc6HWsA" name="class1" type="_2O35UHqQEeK9jI2Tc6HWsA" association="_4hHowHqQEeK9jI2Tc6HWsA"> + <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_4hHownqQEeK9jI2Tc6HWsA" value="1"/> + <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_4hHow3qQEeK9jI2Tc6HWsA" value="1"/> + </ownedEnd> + </packagedElement> +</uml:Model> diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.notation b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.notation index ed846af8855..16e458be63e 100644 --- a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.notation +++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment.notation @@ -193,7 +193,7 @@ <nattable:Table xmi:id="_HvMBoPrfEeOjArr2x5XJOA" name="classes" currentRowAxisProvider="_HvMosfrfEeOjArr2x5XJOA" currentColumnAxisProvider="_HvMosPrfEeOjArr2x5XJOA"> <context xmi:type="uml:Model" href="employment.uml#_6iAasPJDEeOWJr1T78jdJA"/> <owner xmi:type="uml:Model" href="employment.uml#_6iAasPJDEeOWJr1T78jdJA"/> - <prototype xmi:type="configuration:PapyrusSyncTable" href="platform:/plugin/org.eclipse.papyrus.infra.viewpoints.policy/builtin/default.configuration#_7wNb2NxhEeOqHvRyiN87hA"/> + <prototype xmi:type="configuration:PapyrusSyncTable" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/genericTable.configuration#_Uz8agHDuEeWh-MssWmCB_A"/> <tableConfiguration xmi:type="nattableconfiguration:TableConfiguration" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#/"/> <columnAxisProvidersHistory xmi:type="nattableaxisprovider:SlaveObjectAxisProvider" xmi:id="_HvMosPrfEeOjArr2x5XJOA" description="This axis provider provides available columns according to the rows of the table (features of the object displayed on the other axis)" name="UML Feature axis provider"> <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kkPrfEeOjArr2x5XJOA"> diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment_sashes.notation b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment_sashes.notation index 1908737dee0..a80718a7ca7 100644 --- a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment_sashes.notation +++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/model/reload/employment_sashes.notation @@ -193,7 +193,7 @@ <nattable:Table xmi:id="_HvMBoPrfEeOjArr2x5XJOA" name="classes_table" currentRowAxisProvider="_HvMosfrfEeOjArr2x5XJOA" currentColumnAxisProvider="_HvMosPrfEeOjArr2x5XJOA"> <context xmi:type="uml:Model" href="employment_sashes.uml#_6iAasPJDEeOWJr1T78jdJA"/> <owner xmi:type="uml:Model" href="employment_sashes.uml#_6iAasPJDEeOWJr1T78jdJA"/> - <prototype xmi:type="configuration:PapyrusSyncTable" href="platform:/plugin/org.eclipse.papyrus.infra.viewpoints.policy/builtin/default.configuration#_7wNb2NxhEeOqHvRyiN87hA"/> + <prototype xmi:type="configuration:PapyrusSyncTable" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/genericTable.configuration#_Uz8agHDuEeWh-MssWmCB_A"/> <tableConfiguration xmi:type="nattableconfiguration:TableConfiguration" href="platform:/plugin/org.eclipse.papyrus.uml.nattable.generic.config/configs/generic.nattableconfiguration#/"/> <columnAxisProvidersHistory xmi:type="nattableaxisprovider:SlaveObjectAxisProvider" xmi:id="_HvMosPrfEeOjArr2x5XJOA" description="This axis provider provides available columns according to the rows of the table (features of the object displayed on the other axis)" name="UML Feature axis provider"> <axis xmi:type="nattableaxis:EStructuralFeatureAxis" xmi:id="_I58kkPrfEeOjArr2x5XJOA"> diff --git a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/tests/EditorMemoryLeakTest.java b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/tests/EditorMemoryLeakTest.java index f358bcb5ce5..899a2bf8cf6 100644 --- a/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/tests/EditorMemoryLeakTest.java +++ b/tests/junit/plugins/core/org.eclipse.papyrus.editor.integration.tests/src/org/eclipse/papyrus/editor/integration/tests/tests/EditorMemoryLeakTest.java @@ -8,7 +8,7 @@ * * Contributors: * Christian W. Damus (CEA) - Initial API and implementation - * Christian W. Damus - bug 485214 + * Christian W. Damus - bugs 485214, 474467 * */ package org.eclipse.papyrus.editor.integration.tests.tests; @@ -186,4 +186,17 @@ public class EditorMemoryLeakTest extends AbstractPapyrusTest { memory.add(editor.getModel().getAppliedProfile("j2ee")); } + /** + * Verify that the attachment of listeners to the UML's shared item providers doesn't + * cause any leaks (all is properly cleaned up when unloading the editor). + */ + @Test + @SoftReferenceSensitive + @PluginResource("model/basic/unnamed_diagram.di") + public void testCleanUpListenersOnItemProviders() { + memory.add(editor.getModelSet()); + + DiagramEditor diagramEditor = (DiagramEditor) editor.getEditor().getActiveEditor(); + memory.add(diagramEditor.getDiagramEditPart()); + } } diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/.classpath b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/.classpath index 64c5e31b7a2..eca7bdba8f0 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/.classpath +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/.classpath @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="src" path="src"/> <classpathentry kind="output" path="bin"/> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/.settings/org.eclipse.jdt.core.prefs b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/.settings/org.eclipse.jdt.core.prefs index c585cc455ae..b3aa6d60f94 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/.settings/org.eclipse.jdt.core.prefs +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/.settings/org.eclipse.jdt.core.prefs @@ -1,10 +1,10 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/META-INF/MANIFEST.MF b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/META-INF/MANIFEST.MF index 7c2dcfc3436..4b8de23889d 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/META-INF/MANIFEST.MF +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/META-INF/MANIFEST.MF @@ -16,4 +16,4 @@ Bundle-Name: %pluginName Bundle-Localization: fragment Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.papyrus.infra.ui.emf.tests -Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/org.eclipse.papyrus.infra.ui.emf.tests.launch b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/org.eclipse.papyrus.infra.ui.emf.tests.launch index 5aa09b0fa3f..c98b2e8ae6c 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/org.eclipse.papyrus.infra.ui.emf.tests.launch +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/org.eclipse.papyrus.infra.ui.emf.tests.launch @@ -25,7 +25,7 @@ <stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/> <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> <stringAttribute key="org.eclipse.jdt.launching.JAVA_COMMAND" value="java"/> -<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> +<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.papyrus.infra.ui.emf.tests.AllTests"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.papyrus.infra.ui.emf.tests"/> diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/providers/tests/DependentEMFLabelProviderTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/providers/tests/DependentEMFLabelProviderTest.java new file mode 100644 index 00000000000..943414b4d24 --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/providers/tests/DependentEMFLabelProviderTest.java @@ -0,0 +1,128 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus and others. + * + * 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.ui.emf.providers.tests; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.papyrus.infra.ui.emf.providers.DependentEMFLabelProvider; +import org.eclipse.papyrus.junit.utils.rules.HouseKeeper; +import org.eclipse.uml2.uml.Package; +import org.eclipse.uml2.uml.UMLFactory; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +/** + * Tests for the {@link DependentEMFLabelProvider} class. + */ +public class DependentEMFLabelProviderTest { + + @Rule + public final HouseKeeper houseKeeper = new HouseKeeper(); + + private ILabelProvider fixture; + + private Package imported; + private Package importing; + + @Test + public void getText() { + assertThat(fixture.getText(imported), is("<Package> foo (imported by <Package> bar)")); + } + + @Test + public void notificationsOnDependentWhenItChanges() { + boolean[] gotEvent = { false }; + ILabelProviderListener listener = event -> gotEvent[0] = gotEvent[0] || (event.getElement() == imported); + fixture.addListener(listener); + + fixture.getText(imported); // Access it once to hook up the item adapters + gotEvent[0] = false; + + // Change the name of the package, itself + imported.setName("quux"); + + assertThat("Label provider did not notify", gotEvent[0], is(true)); + } + + @Test + public void notificationsOnDependentWhenDependencyChanges() { + boolean[] gotEvent = { false }; + ILabelProviderListener listener = event -> gotEvent[0] = gotEvent[0] || (event.getElement() == imported); + fixture.addListener(listener); + + fixture.getText(imported); // Access it once to hook up the item adapters + gotEvent[0] = false; + + // Change the name of the package that the label of our dependent package depends on + importing.setName("quux"); + + assertThat("Label provider did not notify", gotEvent[0], is(true)); + } + + // + // Test framework + // + + @Before + public void createFixture() { + fixture = houseKeeper.cleanUpLater(new ImportedPackageLabelProvider()); + + imported = UMLFactory.eINSTANCE.createPackage(); + imported.setName("foo"); + + importing = UMLFactory.eINSTANCE.createPackage(); + importing.setName("bar"); + + importing.createPackageImport(imported); + } + + // For testing purposes, a label provider for packages that decorates the label + // with the label of one package that imports it (if any) + private class ImportedPackageLabelProvider extends DependentEMFLabelProvider { + @Override + protected String getText(EObject element) { + // Default + String result = super.getText(element); + + if (element instanceof Package) { + Package package_ = (Package) element; + Package importer = getImportingPackage(package_); + if (importer != null) { + // Listen for changes in the dependency to notify on the dependent + subscribe(importer, package_); + + result = String.format("%s (imported by %s)", result, getText(importer)); + } + } + + return result; + } + + private Package getImportingPackage(Package package_) { + Package result = null; + + // Cheat! + if (importing.getPackageImport(package_) != null) { + result = importing; + } + + return result; + } + } +} diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/providers/tests/EMFLabelProviderTest.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/providers/tests/EMFLabelProviderTest.java new file mode 100644 index 00000000000..e2b5c4b6568 --- /dev/null +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/providers/tests/EMFLabelProviderTest.java @@ -0,0 +1,72 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus and others. + * + * 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.ui.emf.providers.tests; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.papyrus.infra.ui.emf.providers.EMFLabelProvider; +import org.eclipse.papyrus.junit.utils.rules.HouseKeeper; +import org.eclipse.uml2.uml.Package; +import org.eclipse.uml2.uml.UMLFactory; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +/** + * Tests for the {@link EMFLabelProvider} class. + */ +public class EMFLabelProviderTest { + + @Rule + public final HouseKeeper houseKeeper = new HouseKeeper(); + + private ILabelProvider fixture; + + private Package package_; + + @Test + public void getText() { + assertThat(fixture.getText(package_), is("<Package> foo")); + } + + @Test + public void labelProviderChangeNotifications() { + boolean[] gotEvent = { false }; + ILabelProviderListener listener = event -> gotEvent[0] = gotEvent[0] || (event.getElement() == package_); + fixture.addListener(listener); + + fixture.getText(package_); // Access it once to hook up the item adapters + gotEvent[0] = false; + + package_.setName("bar"); + + assertThat("Label provider did not notify", gotEvent[0], is(true)); + } + + // + // Test framework + // + + @Before + public void createFixture() { + fixture = houseKeeper.cleanUpLater(new EMFLabelProvider()); + + package_ = UMLFactory.eINSTANCE.createPackage(); + package_.setName("foo"); + } + +} diff --git a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/tests/AllTests.java b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/tests/AllTests.java index 77fc856002d..ef86a5c8845 100644 --- a/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/tests/AllTests.java +++ b/tests/junit/plugins/infra/emf/org.eclipse.papyrus.infra.ui.emf.tests/src/org/eclipse/papyrus/infra/ui/emf/tests/AllTests.java @@ -8,11 +8,13 @@ * * Contributors: * Christian W. Damus (CEA) - Initial API and implementation - * Christian W. Damus - bug 485220 + * Christian W. Damus - bugs 485220, 474467 * *****************************************************************************/ package org.eclipse.papyrus.infra.ui.emf.tests; +import org.eclipse.papyrus.infra.ui.emf.providers.tests.DependentEMFLabelProviderTest; +import org.eclipse.papyrus.infra.ui.emf.providers.tests.EMFLabelProviderTest; import org.eclipse.papyrus.infra.ui.internal.emf.readonly.handlers.ReferencedModelReadOnlyHandlerTest; import org.eclipse.papyrus.junit.framework.classification.ClassificationSuite; import org.junit.runner.RunWith; @@ -25,6 +27,8 @@ import org.junit.runners.Suite.SuiteClasses; @RunWith(ClassificationSuite.class) @SuiteClasses({ ReferencedModelReadOnlyHandlerTest.class, + EMFLabelProviderTest.class, + DependentEMFLabelProviderTest.class, }) public class AllTests { diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/.classpath b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/.classpath index 64c5e31b7a2..eca7bdba8f0 100644 --- a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/.classpath +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/.classpath @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="src" path="src"/> <classpathentry kind="output" path="bin"/> diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/.settings/org.eclipse.jdt.core.prefs b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/.settings/org.eclipse.jdt.core.prefs index c585cc455ae..b3aa6d60f94 100644 --- a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/.settings/org.eclipse.jdt.core.prefs +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/.settings/org.eclipse.jdt.core.prefs @@ -1,10 +1,10 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/META-INF/MANIFEST.MF b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/META-INF/MANIFEST.MF index 653969f63d4..07f3c77fe7c 100644 --- a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/META-INF/MANIFEST.MF +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/META-INF/MANIFEST.MF @@ -16,4 +16,4 @@ Bundle-Name: %pluginName Bundle-Localization: fragment Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.papyrus.infra.gmfdiag.common.tests;singleton:=true -Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/tests/NotationLabelProviderTest.java b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/tests/NotationLabelProviderTest.java new file mode 100644 index 00000000000..eabb73cef8d --- /dev/null +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/providers/tests/NotationLabelProviderTest.java @@ -0,0 +1,110 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus and others. + * + * 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.gmfdiag.common.providers.tests; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assume.assumeThat; + +import org.eclipse.gmf.runtime.notation.Diagram; +import org.eclipse.gmf.runtime.notation.NotationFactory; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.papyrus.infra.gmfdiag.common.providers.NotationLabelProvider; +import org.eclipse.papyrus.junit.utils.rules.HouseKeeper; +import org.eclipse.uml2.uml.Package; +import org.eclipse.uml2.uml.UMLFactory; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +/** + * Tests for the {@link NotationLabelProvider} class. + */ +public class NotationLabelProviderTest { + + @Rule + public final HouseKeeper houseKeeper = new HouseKeeper(); + + private ILabelProvider fixture; + + private Package package_; + private Diagram diagram; + + @Test + public void getText_namedDiagram() { + assertThat(fixture.getText(diagram), is("classes")); + } + + @Test + public void getText_unnamedDiagram() { + diagram.setName(null); + assertThat(fixture.getText(diagram), is("(Class Diagram of <Package> foo)")); + } + + @Test + public void getText_unnamedDiagramChangeContextName() { + diagram.setName(null); + assumeThat(fixture.getText(diagram), is("(Class Diagram of <Package> foo)")); + package_.setName("bar"); + assumeThat(fixture.getText(diagram), is("(Class Diagram of <Package> bar)")); + } + + @Test + public void getText_namedDiagramNotifications() { + boolean[] gotEvent = { false }; + ILabelProviderListener listener = event -> gotEvent[0] = gotEvent[0] || (event.getElement() == diagram); + fixture.addListener(listener); + + fixture.getText(diagram); // Access it once to hook up the item adapters + gotEvent[0] = false; + + diagram.setName("new name"); + + assertThat("Label provider did not notify", gotEvent[0], is(true)); + } + + @Test + public void getText_unnamedDiagramNotifications() { + diagram.setName(null); + + boolean[] gotEvent = { false }; + ILabelProviderListener listener = event -> gotEvent[0] = gotEvent[0] || (event.getElement() == diagram); + fixture.addListener(listener); + + fixture.getText(diagram); // Access it once to hook up the item adapters + gotEvent[0] = false; + + package_.setName("bar"); + + assertThat("Label provider did not notify", gotEvent[0], is(true)); + } + + // + // Test framework + // + + @Before + public void createFixture() { + fixture = houseKeeper.cleanUpLater(new NotationLabelProvider()); + + package_ = UMLFactory.eINSTANCE.createPackage(); + package_.setName("foo"); + diagram = NotationFactory.eINSTANCE.createDiagram(); + diagram.setName("classes"); + diagram.setType("PapyrusUMLClassDiagram"); + diagram.setElement(package_); + } + +} diff --git a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/tests/AllTests.java b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/tests/AllTests.java index 5412b830459..19729d7cdc0 100644 --- a/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/tests/AllTests.java +++ b/tests/junit/plugins/infra/gmfdiag/org.eclipse.papyrus.infra.gmfdiag.common.tests/src/org/eclipse/papyrus/infra/gmfdiag/common/tests/AllTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015 CEA LIST, Christian W. Damus, and others. + * Copyright (c) 2014, 2016 CEA LIST, Christian W. Damus, and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,14 +8,15 @@ * * Contributors: * Christian W. Damus (CEA) - initial API and implementation - * Christian W. Damus - bug 465416 + * Christian W. Damus - bugs 465416, 474467 */ package org.eclipse.papyrus.infra.gmfdiag.common.tests; +import org.eclipse.papyrus.infra.gmfdiag.common.providers.tests.NotationLabelProviderTest; import org.eclipse.papyrus.infra.gmfdiag.common.sync.tests.SyncTests; import org.eclipse.papyrus.infra.gmfdiag.common.utils.GMFUnsafeTest; -import org.junit.runner.RunWith; import org.eclipse.papyrus.junit.framework.classification.ClassificationSuite; +import org.junit.runner.RunWith; import org.junit.runners.Suite.SuiteClasses; @@ -34,7 +35,8 @@ import org.junit.runners.Suite.SuiteClasses; ExpansionDropElements.class, AssistantUsage.class, GMFUnsafeTest.class, - SyncTests.class + SyncTests.class, + NotationLabelProviderTest.class, }) public class AllTests { diff --git a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/.classpath b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/.classpath index 8a8f1668cdc..eca7bdba8f0 100644 --- a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/.classpath +++ b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/.classpath @@ -1,7 +1,7 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/.settings/org.eclipse.jdt.core.prefs b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/.settings/org.eclipse.jdt.core.prefs index 410244d65a6..62a08f4494d 100644 --- a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/.settings/org.eclipse.jdt.core.prefs +++ b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/.settings/org.eclipse.jdt.core.prefs @@ -1,10 +1,10 @@ eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
+org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/META-INF/MANIFEST.MF b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/META-INF/MANIFEST.MF index 5f91651d71d..6fbc5644dbf 100644 --- a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/META-INF/MANIFEST.MF +++ b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/META-INF/MANIFEST.MF @@ -24,4 +24,4 @@ Bundle-Activator: org.eclipse.papyrus.infra.nattable.tests.Activator Bundle-ManifestVersion: 2 Bundle-Description: T%Bundle-Description Bundle-SymbolicName: org.eclipse.papyrus.infra.nattable.tests -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/NattableCommonTests.launch b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/NattableCommonTests.launch index 9732ed6f825..4ea733b1fe6 100644 --- a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/NattableCommonTests.launch +++ b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/NattableCommonTests.launch @@ -1,47 +1,48 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
-<booleanAttribute key="append.args" value="true"/>
-<booleanAttribute key="askclear" value="false"/>
-<booleanAttribute key="automaticAdd" value="true"/>
-<booleanAttribute key="automaticValidate" value="false"/>
-<stringAttribute key="bootstrap" value=""/>
-<stringAttribute key="checked" value="[NONE]"/>
-<listAttribute key="classFilters">
-<listEntry value="ClassFilter(include, org.eclipse.papyrus.infra.emf.*)"/>
-<listEntry value="ClassFilter(include, org.eclipse.papyrus.uml.tools.*)"/>
-<listEntry value="ClassFilter(include, *.tests.*)"/>
-</listAttribute>
-<booleanAttribute key="clearConfig" value="true"/>
-<booleanAttribute key="clearws" value="true"/>
-<booleanAttribute key="clearwslog" value="false"/>
-<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
-<booleanAttribute key="default" value="true"/>
-<booleanAttribute key="includeOptional" value="true"/>
-<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.papyrus.infra.nattable.tests/src/org/eclipse/papyrus/infra/nattable/tests/tests/AllTests.java"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="1"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.papyrus.infra.nattable.tests.tests.AllTests"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.papyrus.infra.nattable.tests"/>
-<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dosgi.requiredJavaVersion=1.5 -Xms120m -Xmx512m -XX:PermSize=256M -XX:MaxPermSize=512M"/>
-<stringAttribute key="pde.version" value="3.3"/>
-<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
-<booleanAttribute key="run_in_ui_thread" value="true"/>
-<booleanAttribute key="show_selected_only" value="false"/>
-<stringAttribute key="templateConfig" value="${target_home}\configuration\config.ini"/>
-<booleanAttribute key="tracing" value="false"/>
-<booleanAttribute key="useCustomFeatures" value="false"/>
-<booleanAttribute key="useDefaultConfig" value="true"/>
-<booleanAttribute key="useDefaultConfigArea" value="false"/>
-<booleanAttribute key="useProduct" value="true"/>
-</launchConfiguration>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig"> +<booleanAttribute key="append.args" value="true"/> +<booleanAttribute key="askclear" value="false"/> +<booleanAttribute key="automaticAdd" value="true"/> +<booleanAttribute key="automaticValidate" value="false"/> +<stringAttribute key="bootstrap" value=""/> +<stringAttribute key="checked" value="[NONE]"/> +<listAttribute key="classFilters"> +<listEntry value="ClassFilter(include, org.eclipse.papyrus.infra.emf.*)"/> +<listEntry value="ClassFilter(include, org.eclipse.papyrus.uml.tools.*)"/> +<listEntry value="ClassFilter(include, *.tests.*)"/> +</listAttribute> +<booleanAttribute key="clearConfig" value="true"/> +<booleanAttribute key="clearws" value="true"/> +<booleanAttribute key="clearwslog" value="false"/> +<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/> +<booleanAttribute key="default" value="true"/> +<booleanAttribute key="includeOptional" value="true"/> +<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.papyrus.infra.nattable.tests/src/org/eclipse/papyrus/infra/nattable/tests/tests/AllTests.java"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="1"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/> +<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/> +<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.papyrus.infra.nattable.tests.tests.AllTests"/> +<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.papyrus.infra.nattable.tests"/> +<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/> +<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dosgi.requiredJavaVersion=1.5 -Xms120m -Xmx512m -XX:PermSize=256M -XX:MaxPermSize=512M"/> +<stringAttribute key="pde.version" value="3.3"/> +<stringAttribute key="product" value="org.eclipse.sdk.ide"/> +<booleanAttribute key="run_in_ui_thread" value="true"/> +<booleanAttribute key="show_selected_only" value="false"/> +<stringAttribute key="templateConfig" value="${target_home}\configuration\config.ini"/> +<booleanAttribute key="tracing" value="false"/> +<booleanAttribute key="useCustomFeatures" value="false"/> +<booleanAttribute key="useDefaultConfig" value="true"/> +<booleanAttribute key="useDefaultConfigArea" value="false"/> +<booleanAttribute key="useProduct" value="true"/> +</launchConfiguration> diff --git a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/src/org/eclipse/papyrus/infra/nattable/tests/tests/AllTests.java b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/src/org/eclipse/papyrus/infra/nattable/tests/tests/AllTests.java index b5bb9741308..8445ce59ab9 100644 --- a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/src/org/eclipse/papyrus/infra/nattable/tests/tests/AllTests.java +++ b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/src/org/eclipse/papyrus/infra/nattable/tests/tests/AllTests.java @@ -1,6 +1,5 @@ /*****************************************************************************
- * Copyright (c) 2014 CEA LIST.
- *
+ * Copyright (c) 2014, 2016 CEA LIST, Christian W. Damus, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -9,17 +8,22 @@ *
* Contributors:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
+ * Christian W. Damus - bug 474467
*
*****************************************************************************/
package org.eclipse.papyrus.infra.nattable.tests.tests;
-import org.junit.runner.RunWith;
import org.eclipse.papyrus.junit.framework.classification.ClassificationSuite;
+import org.junit.runner.RunWith;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(ClassificationSuite.class)
-@SuiteClasses({ TableSelectionProviderTest.class , PasteTreeUtils_Tests.class})
+@SuiteClasses({
+ TableSelectionProviderTest.class,
+ PasteTreeUtils_Tests.class,
+ TableLabelProviderTest.class,
+})
public class AllTests {
// JUnit 4 test suite
}
diff --git a/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/src/org/eclipse/papyrus/infra/nattable/tests/tests/TableLabelProviderTest.java b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/src/org/eclipse/papyrus/infra/nattable/tests/tests/TableLabelProviderTest.java new file mode 100644 index 00000000000..384b2586738 --- /dev/null +++ b/tests/junit/plugins/infra/nattable/org.eclipse.papyrus.infra.nattable.tests/src/org/eclipse/papyrus/infra/nattable/tests/tests/TableLabelProviderTest.java @@ -0,0 +1,127 @@ +/***************************************************************************** + * Copyright (c) 2016 Christian W. Damus and others. + * + * 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: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.nattable.tests.tests; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assume.assumeThat; + +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.papyrus.infra.nattable.model.nattable.NattableFactory; +import org.eclipse.papyrus.infra.nattable.model.nattable.Table; +import org.eclipse.papyrus.infra.nattable.provider.TableLabelProvider; +import org.eclipse.papyrus.infra.viewpoints.configuration.ConfigurationFactory; +import org.eclipse.papyrus.infra.viewpoints.configuration.PapyrusTable; +import org.eclipse.papyrus.junit.utils.rules.HouseKeeper; +import org.eclipse.uml2.uml.Package; +import org.eclipse.uml2.uml.UMLFactory; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +/** + * Tests for the {@link TableLabelProvider} class. + */ +public class TableLabelProviderTest { + + @Rule + public final HouseKeeper houseKeeper = new HouseKeeper(); + + private ILabelProvider fixture; + + private Package package_; + private PapyrusTable proto; + private Table table; + + @Test + public void getText_namedTable() { + assertThat(fixture.getText(table), is("classes")); + } + + @Test + public void getText_unnamedTable() { + table.setName(null); + assertThat(fixture.getText(table), is("(Test Table of <Package> foo)")); + } + + @Test + public void getText_unnamedTableChangeContextName() { + table.setName(null); + assumeThat(fixture.getText(table), is("(Test Table of <Package> foo)")); + package_.setName("bar"); + assumeThat(fixture.getText(table), is("(Test Table of <Package> bar)")); + } + + @Test + public void getText_namedTableNotifications() { + boolean[] gotEvent = { false }; + ILabelProviderListener listener = event -> gotEvent[0] = gotEvent[0] || (event.getElement() == table); + fixture.addListener(listener); + + fixture.getText(table); // Access it once to hook up the item adapters + gotEvent[0] = false; + + table.setName("new name"); + + assertThat("Label provider did not notify", gotEvent[0], is(true)); + } + + @Test + public void getText_unnamedTableNotifications() { + table.setName(null); + + boolean[] gotEvent = { false }; + ILabelProviderListener listener = event -> gotEvent[0] = gotEvent[0] || (event.getElement() == table); + fixture.addListener(listener); + + fixture.getText(table); // Access it once to hook up the item adapters + gotEvent[0] = false; + + package_.setName("bar"); + + assertThat("Label provider did not notify", gotEvent[0], is(true)); + } + + @Test + public void getText_selectionOfMultipleTables() { + StructuredSelection selection = new StructuredSelection(new Object[] { table, table }); + + assertThat(fixture.getText(selection), is("classes, classes")); + } + + // + // Test framework + // + + @Before + public void createFixture() { + fixture = houseKeeper.cleanUpLater(new TableLabelProvider()); + + package_ = UMLFactory.eINSTANCE.createPackage(); + package_.setName("foo"); + + proto = ConfigurationFactory.eINSTANCE.createPapyrusTable(); + proto.setName("Test Table"); + proto.setImplementationID("org.eclipse.papyrus.infra.nattable.tests.TestTable"); + proto.setConfiguration("TestTable"); + + table = NattableFactory.eINSTANCE.createTable(); + table.setName("classes"); + table.setPrototype(proto); + table.setContext(package_); + } + +} |