| /******************************************************************************* |
| * Copyright (c) 2013, 2020 Obeo 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: |
| * Obeo - initial API and implementation |
| * Christian W. Damus - bug 525473 |
| *******************************************************************************/ |
| package org.eclipse.emf.compare.diagram.ide.ui.internal.contentmergeviewer.diagram; |
| |
| import org.eclipse.draw2d.ColorConstants; |
| import org.eclipse.draw2d.FigureCanvas; |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.Viewport; |
| import org.eclipse.draw2d.geometry.Dimension; |
| import org.eclipse.draw2d.geometry.Point; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.emf.compare.diagram.ide.ui.internal.AbstractGraphicalMergeViewer; |
| import org.eclipse.emf.compare.diagram.ide.ui.internal.accessor.IDiagramDiffAccessor; |
| import org.eclipse.emf.compare.diagram.ide.ui.internal.accessor.IDiagramNodeAccessor; |
| import org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.transaction.TransactionalEditingDomain; |
| import org.eclipse.gef.EditDomain; |
| import org.eclipse.gef.EditPart; |
| import org.eclipse.gef.EditPartViewer; |
| import org.eclipse.gef.MouseWheelHandler; |
| import org.eclipse.gef.MouseWheelZoomHandler; |
| import org.eclipse.gef.RootEditPart; |
| import org.eclipse.gef.SelectionManager; |
| import org.eclipse.gef.ui.parts.DomainEventDispatcher; |
| import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart; |
| import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack; |
| import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain; |
| import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer; |
| import org.eclipse.gmf.runtime.diagram.ui.services.editpart.EditPartService; |
| import org.eclipse.gmf.runtime.notation.Diagram; |
| import org.eclipse.gmf.runtime.notation.View; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| |
| /** |
| * The graphical viewer on each side of the compare viewer. |
| * |
| * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a> |
| */ |
| public class DiagramMergeViewer extends AbstractGraphicalMergeViewer { |
| |
| /** |
| * Selection manager to forbid manual selections on graphical objects. |
| * |
| * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a> |
| */ |
| protected class NonEditingManager extends SelectionManager { |
| |
| @Override |
| public void appendSelection(EditPart editpart) { |
| // needed to disable manual selection on every objects. |
| } |
| } |
| |
| /** |
| * Event dispatcher to forbid external mouse actions on diagrams. |
| * |
| * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a> |
| */ |
| protected class NonEditingEventDispatcher extends DomainEventDispatcher { |
| |
| /** |
| * Constructor. |
| * |
| * @param d |
| * The edit domain. |
| * @param v |
| * The edit part viewer. |
| */ |
| public NonEditingEventDispatcher(EditDomain d, EditPartViewer v) { |
| super(d, v); |
| } |
| |
| @Override |
| public void dispatchMousePressed(MouseEvent me) { |
| // needed not to get a change of the cursor releasing from a connector. |
| } |
| |
| @Override |
| public void dispatchMouseReleased(MouseEvent me) { |
| // needed not to get a change of the cursor releasing from a connector. |
| } |
| |
| @Override |
| public void dispatchMouseDoubleClicked(MouseEvent me) { |
| // needed not to get a change of the cursor double-clicking on a connector. |
| } |
| |
| @Override |
| public void dispatchMouseHover(MouseEvent me) { |
| // needed not to get a change of the cursor hovering a connector. |
| } |
| |
| @Override |
| public void dispatchMouseMoved(MouseEvent me) { |
| // needed not to get a change of the cursor hovering a connector. |
| } |
| |
| } |
| |
| /** the zoom factor of displayed diagrams. */ |
| private static final double ZOOM_FACTOR = 1; |
| |
| /** The graphical viewer. */ |
| private DiagramGraphicalViewerForCompare fGraphicalViewer; |
| |
| /** the current diagram used. */ |
| private Diagram currentDiag; |
| |
| /** The diagram edit domain. */ |
| private DiagramEditDomain editDomain; |
| |
| /** |
| * Constructor. |
| * |
| * @param parent |
| * The parent composite. |
| * @param side |
| * The side having to be managed by this viewer. |
| * @param compareConfiguration |
| * the compare configuration. |
| */ |
| DiagramMergeViewer(Composite parent, MergeViewerSide side, |
| IEMFCompareConfiguration compareConfiguration) { |
| super(parent, side, compareConfiguration); |
| ((FigureCanvas)fGraphicalViewer.getControl()).getLightweightSystem() |
| .setEventDispatcher(new NonEditingEventDispatcher(editDomain, fGraphicalViewer)); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.AbstractMergeViewer#createControl(org.eclipse.swt.widgets.Composite) |
| */ |
| @Override |
| public Control createControl(Composite parent) { |
| editDomain = new DiagramEditDomain(null); |
| editDomain.setCommandStack(new DiagramCommandStack(editDomain)); |
| createDiagramGraphicalViewer(parent); |
| return fGraphicalViewer.getControl(); |
| } |
| |
| /** |
| * It creates and initialize the graphical viewer. |
| * |
| * @param composite |
| * The composite. |
| */ |
| private void createDiagramGraphicalViewer(Composite composite) { |
| fGraphicalViewer = new DiagramGraphicalViewerForCompare(); |
| fGraphicalViewer.createControl(composite); |
| fGraphicalViewer.setEditDomain(editDomain); |
| fGraphicalViewer.setEditPartFactory(EditPartService.getInstance()); |
| fGraphicalViewer.getControl().setBackground(ColorConstants.listBackground); |
| fGraphicalViewer.setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.CTRL), |
| MouseWheelZoomHandler.SINGLETON); |
| |
| fGraphicalViewer.setSelectionManager(new NonEditingManager()); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.emf.compare.diagram.ide.ui.internal.AbstractGraphicalMergeViewer#getGraphicalViewer() |
| */ |
| @Override |
| public DiagramGraphicalViewerForCompare getGraphicalViewer() { |
| return fGraphicalViewer; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.emf.compare.diagram.ide.ui.AbstractEditPartMergeViewer#setInput(java.lang.Object) |
| */ |
| @Override |
| public void setInput(final Object input) { |
| if (input instanceof IDiagramNodeAccessor) { |
| Diagram diagram = ((IDiagramNodeAccessor)input).getOwnedDiagram(); |
| if (diagram != null) { |
| TransactionalEditingDomain domain = getEditingDomain(diagram); |
| if (domain != null && currentDiag != diagram) { |
| RootEditPart oldRoot = fGraphicalViewer.getRootEditPart(); |
| if (oldRoot != null) { |
| oldRoot.deactivate(); |
| fGraphicalViewer.getEditPartRegistry().clear(); |
| fGraphicalViewer.getVisualPartMap().clear(); |
| } |
| |
| DiagramRootEditPart rootEditPart = new DiagramRootEditPart(diagram.getMeasurementUnit()); |
| // rootEditPart.getZoomManager().setZoomAnimationStyle(ZoomManager.ANIMATE_NEVER); |
| // rootEditPart.getZoomManager().setZoom(ZOOM_FACTOR); |
| fGraphicalViewer.setRootEditPart(rootEditPart); |
| fGraphicalViewer.setContents(diagram); |
| } |
| View view = ((IDiagramNodeAccessor)input).getOwnedView(); |
| EditPart editPart = getEditPart(view); |
| fGraphicalViewer.deselectAll(); |
| // Selection only on matches. |
| if (!(input instanceof IDiagramDiffAccessor) && editPart != null) { |
| setSelection(editPart); |
| } |
| } else { |
| fGraphicalViewer.setContents((EditPart)null); |
| } |
| currentDiag = diagram; |
| } |
| } |
| |
| /** |
| * Set the selection of the first selectable object from the given edit part. |
| * |
| * @param editPart |
| * The edit part. |
| */ |
| private void setSelection(EditPart editPart) { |
| EditPart ep = editPart; |
| while (ep != null && !ep.isSelectable()) { |
| ep = ep.getParent(); |
| } |
| |
| if (ep != null) { |
| setSelection(new StructuredSelection(ep)); |
| fGraphicalViewer.reveal(ep); |
| } |
| } |
| |
| /** |
| * It creates/retrieves an editing domain for this diagram. |
| * |
| * @param diagram |
| * The diagram. |
| * @return The editing domain for this diagram. |
| */ |
| private TransactionalEditingDomain getEditingDomain(Diagram diagram) { |
| final TransactionalEditingDomain domain; |
| ResourceSet resourceSet = null; |
| if (diagram != null) { |
| Resource resource = diagram.eResource(); |
| if (resource != null) { |
| resourceSet = resource.getResourceSet(); |
| } |
| } |
| if (resourceSet != null) { |
| TransactionalEditingDomain existingDomain = TransactionalEditingDomain.Factory.INSTANCE |
| .getEditingDomain(resourceSet); |
| if (existingDomain == null) { |
| domain = TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain(resourceSet); |
| } else { |
| domain = existingDomain; |
| } |
| } else { |
| domain = null; |
| } |
| return domain; |
| } |
| |
| /** |
| * Return the editpart from the given view. |
| * |
| * @param view |
| * The view. |
| * @return The editpart. |
| */ |
| public EditPart getEditPart(final EObject view) { |
| return (EditPart)fGraphicalViewer.getEditPartRegistry().get(view); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.jface.viewers.Viewer#refresh() |
| */ |
| @Override |
| public void refresh() { |
| |
| } |
| |
| /** |
| * {@link DiagramGraphicalViewer} which enables to make a reveal on a given figure, without editpart. |
| * |
| * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a> |
| */ |
| public class DiagramGraphicalViewerForCompare extends DiagramGraphicalViewer { |
| |
| /** |
| * It reveals the given figure. It is a partial copy of |
| * {@link DiagramGraphicalViewer#reveal(EditPart)}.<br> |
| * FIXME: Find a better solution to make the reveal. |
| * |
| * @param figure |
| * The figure. |
| */ |
| public void reveal(IFigure figure) { |
| IFigure target = figure; |
| Viewport port = getFigureCanvas().getViewport(); |
| Rectangle exposeRegion = target.getBounds().getCopy(); |
| target = target.getParent(); |
| while (target != null && target != port) { |
| target.translateToParent(exposeRegion); |
| target = target.getParent(); |
| } |
| exposeRegion.expand(5, 5); |
| |
| Dimension viewportSize = port.getClientArea().getSize(); |
| |
| Point topLeft = exposeRegion.getTopLeft(); |
| Point bottomRight = exposeRegion.getBottomRight().translate(viewportSize.getNegated()); |
| Point finalLocation = new Point(); |
| if (viewportSize.width < exposeRegion.width) { |
| finalLocation.x = Math.min(bottomRight.x, Math.max(topLeft.x, port.getViewLocation().x)); |
| } else { |
| finalLocation.x = Math.min(topLeft.x, Math.max(bottomRight.x, port.getViewLocation().x)); |
| } |
| |
| if (viewportSize.height < exposeRegion.height) { |
| finalLocation.y = Math.min(bottomRight.y, Math.max(topLeft.y, port.getViewLocation().y)); |
| } else { |
| finalLocation.y = Math.min(topLeft.y, Math.max(bottomRight.y, port.getViewLocation().y)); |
| } |
| |
| getFigureCanvas().scrollSmoothTo(finalLocation.x, finalLocation.y); |
| |
| } |
| |
| @Override |
| protected DomainEventDispatcher getEventDispatcher() { |
| return new NonEditingEventDispatcher(editDomain, this); |
| } |
| |
| } |
| |
| } |