Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Langer2017-11-22 12:57:08 +0000
committerLaurent Goubet2018-05-01 12:16:11 +0000
commit9122ab6c947ea30f940458ae041402faa7d6a187 (patch)
treefeb53fd13a8243fc762d706e68a427be3342ac44
parent1fd9e80ab75d560769cf2f49a954b91a2b62fe7e (diff)
downloadorg.eclipse.emf.compare-9122ab6c947ea30f940458ae041402faa7d6a187.tar.gz
org.eclipse.emf.compare-9122ab6c947ea30f940458ae041402faa7d6a187.tar.xz
org.eclipse.emf.compare-9122ab6c947ea30f940458ae041402faa7d6a187.zip
[527567] Generalize the table and tree merge viewer framework
This is in preparation for the property merge viewer support. Add context menu support to AbstractStructuredMergeViewer. Most of the implementation is generic so that subclasses need only override createAction(MergeMode, Diff). Provide AbstractTableOrTreeItemWrapper.isExpandable() so that the content provider doesn't need to be used to determine if a tree item has a +/- icon or not. Improve the implementation of AbstractTableOrTreeMergeViewer. Do a better job painting the items correctly in handlePaintItemEvent (so that the selection highlight box of a tree item doesn't look left shifted as it does without these changes). Avoid ever painting focus highlighting; it doesn't look nice in the table viewer, especially when we paint out own diff boxes. Avoid using the expensive content provider to determine the +/- icon. Avoid drawing the connecting line on top of the hover information. Compute bounds in a way that works well for an arbitrary number of columns with arbitrary missing or present icons and text for each column. ImproveTreeMergeViewer to provide createTreeViewer(Composite) so we can control the style and even implementation of tree viewer's tree used by a subclass. Generalize MergeAction.getSelectedDifferences(IStructuredSelection) so that a selection that is directly diffs will work correctly and use that in PapyrusTreeContentMergeViewer.createMergeViewer(Composite, MergeViewerSide), TableContentMergeViewer.createMergeViewer(Composite, MergeViewerSide), and TreeContentMergeViewer.createMergeViewer(Composite, MergeViewerSide) Factor out AbstractTreeContentMergeViewer from TreeContentMergeViewer so that we can reuse all this stuff in the Properties merge viewer. The logic in EMFCompareContentMergeViewer.commandStackChanged(EventObject) misses the case that the transactional command stack wraps the command in a compound command. Bug: 527567 Change-Id: I08a41a47838aa30c6857142145489bb64c472652 Signed-off-by: Philip Langer <planger@eclipsesource.com>
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/EMFCompareContentMergeViewer.java16
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java16
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/AbstractTreeContentMergeViewer.java286
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java231
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java6
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractStructuredMergeViewer.java103
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeItemWrapper.java22
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeMergeViewer.java86
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/TreeMergeViewer.java17
9 files changed, 538 insertions, 245 deletions
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/EMFCompareContentMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/EMFCompareContentMergeViewer.java
index 05f1824f2..351f2eda0 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/EMFCompareContentMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/EMFCompareContentMergeViewer.java
@@ -9,7 +9,7 @@
* Obeo - initial API and implementation
* Michael Borkowski - bug 462863
* Stefan Dirix - bug 473985
- * Philip Langer - bug 516645, 521948
+ * Philip Langer - bug 516645, 521948, 527567
* Martin Fleck - bug 514079
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer;
@@ -32,6 +32,7 @@ import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.command.CommandStackListener;
+import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.command.ICompareCommandStack;
@@ -413,7 +414,9 @@ public abstract class EMFCompareContentMergeViewer extends ContentMergeViewer im
}
final Command mostRecentCommand = ((CommandStack)event.getSource()).getMostRecentCommand();
- if (mostRecentCommand instanceof ICompareCopyCommand) {
+ if (mostRecentCommand instanceof ICompareCopyCommand
+ || mostRecentCommand instanceof CompoundCommand && ((CompoundCommand)mostRecentCommand)
+ .getCommandList().get(0) instanceof ICompareCopyCommand) {
SWTUtil.safeRefresh(this, true, false);
} else if (mostRecentCommand != null) {
// Model has changed, but not by EMFCompare. Typical case is update from properties view.
@@ -550,6 +553,15 @@ public abstract class EMFCompareContentMergeViewer extends ContentMergeViewer im
fRight.getControl().setBounds(x + width1 + centerWidth, y, width2, height);
}
+ /**
+ * Creates the merge viewer for the given parent and the given side.
+ *
+ * @param parent
+ * composite in which to create the merge viewer.
+ * @param side
+ * the side of the new viewer.
+ * @return a new merge viewer.
+ */
protected abstract IMergeViewer createMergeViewer(Composite parent, MergeViewerSide side);
@Override
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java
index 3efaedf6c..703866cb0 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/table/TableContentMergeViewer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2016 Obeo and others.
+ * Copyright (c) 2012, 2017 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
@@ -8,6 +8,7 @@
* Contributors:
* Obeo - initial API and implementation
* Martin Fleck - bug 483798
+ * Philip Langer - bug 527567
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.table;
@@ -26,6 +27,8 @@ import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.adapterfactory.context.IContextTester;
import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration;
import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer;
+import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeAction;
+import org.eclipse.emf.compare.internal.merge.MergeMode;
import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin;
import org.eclipse.emf.compare.rcp.ui.contentmergeviewer.accessor.ICompareAccessor;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.AbstractMergeViewer;
@@ -40,11 +43,13 @@ import org.eclipse.emf.edit.provider.IItemFontProvider;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
+import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.MouseEvent;
@@ -164,7 +169,14 @@ public class TableContentMergeViewer extends EMFCompareContentMergeViewer {
*/
@Override
protected AbstractMergeViewer createMergeViewer(Composite parent, final MergeViewerSide side) {
- TableMergeViewer ret = new TableMergeViewer(parent, side, this, getCompareConfiguration());
+ TableMergeViewer ret = new TableMergeViewer(parent, side, this, getCompareConfiguration()) {
+ @Override
+ protected IAction createAction(MergeMode mode, Diff diff) {
+ return new MergeAction(getCompareConfiguration(),
+ EMFCompareRCPPlugin.getDefault().getMergerRegistry(), mode, null,
+ new StructuredSelection(diff));
+ }
+ };
ret.getStructuredViewer().getTable().getVerticalBar().setVisible(false);
ret.setContentProvider(new ArrayContentProvider() {
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/AbstractTreeContentMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/AbstractTreeContentMergeViewer.java
new file mode 100644
index 000000000..dbd600efd
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/AbstractTreeContentMergeViewer.java
@@ -0,0 +1,286 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2017 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
+ * Stefan Dirix - bugs 487595, 510442
+ * Martin Fleck - bug 483798
+ * Philip Langer - bug 527567
+ *******************************************************************************/
+package org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.tree;
+
+import static com.google.common.base.Predicates.equalTo;
+import static com.google.common.collect.Lists.newArrayList;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+import java.util.List;
+import java.util.ResourceBundle;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration;
+import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer;
+import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.TreeMergeViewer;
+import org.eclipse.emf.compare.rcp.ui.internal.util.MergeViewerUtil;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseWheelListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+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.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+
+/**
+ * Specialized {@link org.eclipse.compare.contentmergeviewer.ContentMergeViewer} that uses
+ * {@link org.eclipse.jface.viewers.TreeViewer} to display left, right and ancestor {@link EObject}.
+ *
+ * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>
+ */
+public abstract class AbstractTreeContentMergeViewer extends EMFCompareContentMergeViewer {
+
+ private double[] fBasicCenterCurve;
+
+ /**
+ * Creates a new {@link AbstractTreeContentMergeViewer} by calling the super constructor with the given
+ * parameters.
+ * <p>
+ * It calls {@link #buildControl(Composite)} as stated in its javadoc.
+ * <p>
+ * It sets a {@link TreeContentMergeViewerContentProvider specific}
+ * {@link #setContentProvider(org.eclipse.jface.viewers.IContentProvider) content provider} to properly
+ * display ancestor, left and right parts.
+ *
+ * @param style
+ * the style indicator for the parent
+ * @param bundle
+ * the {@link ResourceBundle} for localization
+ * @param parent
+ * the parent composite to build the UI in
+ * @param config
+ * the {@link CompareConfiguration}
+ */
+ public AbstractTreeContentMergeViewer(int style, ResourceBundle bundle, EMFCompareConfiguration config) {
+ super(style, bundle, config);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#getAncestorMergeViewer()
+ */
+ // see createMergeViewer() to see it is safe
+ @Override
+ protected TreeMergeViewer getAncestorMergeViewer() {
+ return (TreeMergeViewer)super.getAncestorMergeViewer();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#getLeftMergeViewer()
+ */
+ // see createMergeViewer() to see it is safe
+ @Override
+ protected TreeMergeViewer getLeftMergeViewer() {
+ return (TreeMergeViewer)super.getLeftMergeViewer();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#getRightMergeViewer()
+ */
+ // see createMergeViewer() to see it is safe
+ @Override
+ protected TreeMergeViewer getRightMergeViewer() {
+ return (TreeMergeViewer)super.getRightMergeViewer();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#getContents(boolean)
+ */
+ @Override
+ protected byte[] getContents(boolean left) {
+ return null;
+ }
+
+ /**
+ * Adds all required listeners to the given {@link TreeMergeViewer}.
+ *
+ * @param treeMergeViewer
+ * the {@link TreeMergeViewer}.
+ */
+ protected void hookListeners(TreeMergeViewer treeMergeViewer) {
+
+ treeMergeViewer.getStructuredViewer().getTree().getVerticalBar().addListener(SWT.Selection,
+ new Listener() {
+ public void handleEvent(Event event) {
+ redrawCenterControl();
+ }
+ });
+
+ treeMergeViewer.getStructuredViewer().getTree().addMouseWheelListener(new MouseWheelListener() {
+ public void mouseScrolled(MouseEvent e) {
+ redrawCenterControl();
+ }
+ });
+ treeMergeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ redrawCenterControl();
+ }
+ });
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#paintCenter(org.eclipse.swt.widgets.Canvas,
+ * org.eclipse.swt.graphics.GC)
+ */
+ @Override
+ protected void paintCenter(GC g) {
+ TreeMergeViewer leftMergeViewer = getLeftMergeViewer();
+ TreeMergeViewer rightMergeViewer = getRightMergeViewer();
+
+ Tree leftTree = leftMergeViewer.getStructuredViewer().getTree();
+ Tree rightTree = rightMergeViewer.getStructuredViewer().getTree();
+
+ Rectangle leftClientArea = leftTree.getClientArea();
+ Rectangle rightClientArea = rightTree.getClientArea();
+
+ final List<TreeItem> leftItems = getExpandedTreeItems(leftTree);
+ final List<TreeItem> rightItems = getExpandedTreeItems(rightTree);
+
+ final ImmutableSet<TreeItem> selection = ImmutableSet.copyOf(leftTree.getSelection());
+
+ for (TreeItem leftItem : leftItems) {
+ final boolean selected = Iterables.any(selection, equalTo(leftItem));
+ IMergeViewerItem leftData = (IMergeViewerItem)leftItem.getData();
+ final Diff leftDiff = leftData.getDiff();
+ if (leftDiff != null) {
+ if (!MergeViewerUtil.isMarkAsMerged(leftDiff, leftData, getCompareConfiguration())) {
+ TreeItem rightItem = findRightTreeItemFromLeftDiff(rightItems, leftDiff, leftData);
+
+ if (rightItem != null) {
+ final Color strokeColor = getCompareColor().getStrokeColor(leftDiff, isThreeWay(),
+ false, selected);
+ g.setForeground(strokeColor);
+ drawCenterLine(g, leftClientArea, rightClientArea, leftItem, rightItem);
+ }
+ }
+ }
+ }
+ }
+
+ private List<TreeItem> getExpandedTreeItems(Tree tree) {
+ return getExpandedTreeItems(tree.getItems());
+ }
+
+ /**
+ * @param items
+ * @return
+ */
+ private List<TreeItem> getExpandedTreeItems(TreeItem[] items) {
+ List<TreeItem> ret = newArrayList();
+ for (TreeItem item : items) {
+ ret.add(item);
+ if (!item.getExpanded()) {
+ continue;
+ }
+ ret.addAll(getExpandedTreeItems(item.getItems()));
+ }
+ return ret;
+ }
+
+ private void drawCenterLine(GC g, Rectangle leftClientArea, Rectangle rightClientArea, TreeItem leftItem,
+ TreeItem rightItem) {
+ Control control = getCenterControl();
+ Point from = new Point(0, 0);
+ Point to = new Point(0, 0);
+
+ Rectangle leftBounds = leftItem.getBounds();
+ Rectangle rightBounds = rightItem.getBounds();
+
+ from.y = leftBounds.y + (leftBounds.height / 2) - leftClientArea.y;
+ if ("gtk".equals(SWT.getPlatform())) { //$NON-NLS-1$
+ from.y -= 1;
+ } else if ("win32".equals(SWT.getPlatform())) { //$NON-NLS-1$
+ from.y += 1;
+ }
+
+ to.x = control.getBounds().width;
+ to.y = rightBounds.y + (rightBounds.height / 2) - rightClientArea.y;
+ if ("gtk".equals(SWT.getPlatform())) { //$NON-NLS-1$
+ to.y -= 1;
+ } else if ("win32".equals(SWT.getPlatform())) { //$NON-NLS-1$
+ to.y += 1;
+ }
+
+ int[] points = getCenterCurvePoints(from, to);
+ for (int i = 1; i < points.length; i++) {
+ g.drawLine(from.x + i - 1, points[i - 1], i, points[i]);
+ }
+ }
+
+ private TreeItem findRightTreeItemFromLeftDiff(List<TreeItem> rightItems, Diff leftDiff,
+ IMergeViewerItem leftData) {
+ TreeItem ret = null;
+ for (TreeItem rightItem : rightItems) {
+ IMergeViewerItem rightData = (IMergeViewerItem)rightItem.getData();
+ final Diff rightDiff = rightData.getDiff();
+ if (leftDiff == rightDiff) {
+ return rightItem;
+ } else if (rightData.getAncestor() == leftData.getAncestor()
+ && rightData.getRight() == leftData.getRight()
+ && rightData.getLeft() == leftData.getLeft()) {
+ ret = rightItem;
+ }
+ }
+ return ret;
+ }
+
+ private int[] getCenterCurvePoints(Point from, Point to) {
+ int startx = from.x;
+ int starty = from.y;
+ int endx = to.x;
+ int endy = to.y;
+ if (fBasicCenterCurve == null) {
+ buildBaseCenterCurve(endx - startx);
+ }
+ double height = endy - starty;
+ height = height / 2;
+ int width = endx - startx;
+ int[] points = new int[width];
+ for (int i = 0; i < width; i++) {
+ points[i] = (int)(-height * fBasicCenterCurve[i] + height + starty);
+ }
+ return points;
+ }
+
+ private void buildBaseCenterCurve(int w) {
+ double width = w;
+ fBasicCenterCurve = new double[getCenterWidth()];
+ for (int i = 0; i < getCenterWidth(); i++) {
+ double r = i / width;
+ fBasicCenterCurve[i] = Math.cos(Math.PI * r);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java
index 3b3da6edb..39095e0f7 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/tree/TreeContentMergeViewer.java
@@ -9,18 +9,16 @@
* Obeo - initial API and implementation
* Stefan Dirix - bugs 487595, 510442
* Martin Fleck - bug 483798
+ * Philip Langer - bug 527567
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.tree;
import static com.google.common.base.Predicates.and;
-import static com.google.common.base.Predicates.equalTo;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Lists.newArrayList;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import java.util.List;
@@ -36,16 +34,16 @@ import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.adapterfactory.context.IContextTester;
import org.eclipse.emf.compare.ide.ui.internal.configuration.EMFCompareConfiguration;
-import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer;
import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.tree.provider.DelegatingTreeMergeViewerItemContentProvider;
import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.tree.provider.MergeViewerItemProviderConfiguration;
import org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.tree.provider.TreeContentMergeViewerItemLabelProvider;
+import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.MergeAction;
+import org.eclipse.emf.compare.internal.merge.MergeMode;
import org.eclipse.emf.compare.match.impl.NotLoadedFragmentMatch;
import org.eclipse.emf.compare.rcp.EMFCompareRCPPlugin;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.AbstractMergeViewer;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.TreeMergeViewer;
import org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.impl.MergeViewerItem;
-import org.eclipse.emf.compare.rcp.ui.internal.util.MergeViewerUtil;
import org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide;
import org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem;
import org.eclipse.emf.compare.rcp.ui.mergeviewer.item.provider.IMergeViewerItemProviderConfiguration;
@@ -55,26 +53,17 @@ import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
+import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseWheelListener;
-import org.eclipse.swt.graphics.Color;
-import org.eclipse.swt.graphics.GC;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
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.Tree;
-import org.eclipse.swt.widgets.TreeItem;
/**
* Specialized {@link org.eclipse.compare.contentmergeviewer.ContentMergeViewer} that uses
@@ -82,7 +71,7 @@ import org.eclipse.swt.widgets.TreeItem;
*
* @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>
*/
-public class TreeContentMergeViewer extends EMFCompareContentMergeViewer {
+public class TreeContentMergeViewer extends AbstractTreeContentMergeViewer {
/**
* Bundle name of the property file containing all displayed strings.
@@ -98,8 +87,6 @@ public class TreeContentMergeViewer extends EMFCompareContentMergeViewer {
private AtomicBoolean fSyncExpandedState;
- private double[] fBasicCenterCurve;
-
/** The unmirrored content provider of this merge viewer. */
protected TreeContentMergeViewerContentProvider fContentProvider;
@@ -187,55 +174,19 @@ public class TreeContentMergeViewer extends EMFCompareContentMergeViewer {
/**
* {@inheritDoc}
*
- * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#getAncestorMergeViewer()
- */
- // see createMergeViewer() to see it is safe
- @Override
- protected TreeMergeViewer getAncestorMergeViewer() {
- return (TreeMergeViewer)super.getAncestorMergeViewer();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#getLeftMergeViewer()
- */
- // see createMergeViewer() to see it is safe
- @Override
- protected TreeMergeViewer getLeftMergeViewer() {
- return (TreeMergeViewer)super.getLeftMergeViewer();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#getRightMergeViewer()
- */
- // see createMergeViewer() to see it is safe
- @Override
- protected TreeMergeViewer getRightMergeViewer() {
- return (TreeMergeViewer)super.getRightMergeViewer();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.compare.contentmergeviewer.ContentMergeViewer#getContents(boolean)
- */
- @Override
- protected byte[] getContents(boolean left) {
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
* @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#createMergeViewer(org.eclipse.swt.widgets.Composite)
*/
@Override
protected AbstractMergeViewer createMergeViewer(final Composite parent, final MergeViewerSide side) {
final TreeMergeViewer mergeTreeViewer = new TreeMergeViewer(parent, side, this,
- getCompareConfiguration());
+ getCompareConfiguration()) {
+ @Override
+ protected IAction createAction(MergeMode mode, Diff diff) {
+ return new MergeAction(getCompareConfiguration(),
+ EMFCompareRCPPlugin.getDefault().getMergerRegistry(), mode, null,
+ new StructuredSelection(diff));
+ }
+ };
final IContentProvider contentProvider = createMergeViewerContentProvider(side);
mergeTreeViewer.setContentProvider(contentProvider);
final AdapterFactoryLabelProvider labelProvider = new TreeContentMergeViewerItemLabelProvider(
@@ -277,164 +228,14 @@ public class TreeContentMergeViewer extends EMFCompareContentMergeViewer {
* @param treeMergeViewer
* the {@link TreeMergeViewer}.
*/
+ @Override
protected void hookListeners(TreeMergeViewer treeMergeViewer) {
treeMergeViewer.getStructuredViewer().getTree().addListener(SWT.Collapse,
new ExpandCollapseListener(treeMergeViewer, false));
treeMergeViewer.getStructuredViewer().getTree().addListener(SWT.Expand,
new ExpandCollapseListener(treeMergeViewer, true));
- treeMergeViewer.getStructuredViewer().getTree().getVerticalBar().addListener(SWT.Selection,
- new Listener() {
- public void handleEvent(Event event) {
- redrawCenterControl();
- }
- });
-
- treeMergeViewer.getStructuredViewer().getTree().addMouseWheelListener(new MouseWheelListener() {
- public void mouseScrolled(MouseEvent e) {
- redrawCenterControl();
- }
- });
- treeMergeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
- public void selectionChanged(SelectionChangedEvent event) {
- redrawCenterControl();
- }
- });
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer.EMFCompareContentMergeViewer#paintCenter(org.eclipse.swt.widgets.Canvas,
- * org.eclipse.swt.graphics.GC)
- */
- @Override
- protected void paintCenter(GC g) {
- TreeMergeViewer leftMergeViewer = getLeftMergeViewer();
- TreeMergeViewer rightMergeViewer = getRightMergeViewer();
-
- Tree leftTree = leftMergeViewer.getStructuredViewer().getTree();
- Tree rightTree = rightMergeViewer.getStructuredViewer().getTree();
-
- Rectangle leftClientArea = leftTree.getClientArea();
- Rectangle rightClientArea = rightTree.getClientArea();
-
- final List<TreeItem> leftItems = getExpandedTreeItems(leftTree);
- final List<TreeItem> rightItems = getExpandedTreeItems(rightTree);
-
- final ImmutableSet<TreeItem> selection = ImmutableSet.copyOf(leftTree.getSelection());
-
- for (TreeItem leftItem : leftItems) {
- final boolean selected = Iterables.any(selection, equalTo(leftItem));
- IMergeViewerItem leftData = (IMergeViewerItem)leftItem.getData();
- final Diff leftDiff = leftData.getDiff();
- if (leftDiff != null) {
- if (!MergeViewerUtil.isMarkAsMerged(leftDiff, leftData, getCompareConfiguration())) {
- TreeItem rightItem = findRightTreeItemFromLeftDiff(rightItems, leftDiff, leftData);
-
- if (rightItem != null) {
- final Color strokeColor = getCompareColor().getStrokeColor(leftDiff, isThreeWay(),
- false, selected);
- g.setForeground(strokeColor);
- drawCenterLine(g, leftClientArea, rightClientArea, leftItem, rightItem);
- }
- }
- }
- }
- }
-
- private List<TreeItem> getExpandedTreeItems(Tree tree) {
- return getExpandedTreeItems(tree.getItems());
- }
-
- /**
- * @param items
- * @return
- */
- private List<TreeItem> getExpandedTreeItems(TreeItem[] items) {
- List<TreeItem> ret = newArrayList();
- for (TreeItem item : items) {
- ret.add(item);
- if (!item.getExpanded()) {
- continue;
- }
- ret.addAll(getExpandedTreeItems(item.getItems()));
- }
- return ret;
- }
-
- private void drawCenterLine(GC g, Rectangle leftClientArea, Rectangle rightClientArea, TreeItem leftItem,
- TreeItem rightItem) {
- Control control = getCenterControl();
- Point from = new Point(0, 0);
- Point to = new Point(0, 0);
-
- Rectangle leftBounds = leftItem.getBounds();
- Rectangle rightBounds = rightItem.getBounds();
-
- from.y = leftBounds.y + (leftBounds.height / 2) - leftClientArea.y;
- if ("gtk".equals(SWT.getPlatform())) { //$NON-NLS-1$
- from.y -= 1;
- } else if ("win32".equals(SWT.getPlatform())) { //$NON-NLS-1$
- from.y += 1;
- }
-
- to.x = control.getBounds().width;
- to.y = rightBounds.y + (rightBounds.height / 2) - rightClientArea.y;
- if ("gtk".equals(SWT.getPlatform())) { //$NON-NLS-1$
- to.y -= 1;
- } else if ("win32".equals(SWT.getPlatform())) { //$NON-NLS-1$
- to.y += 1;
- }
-
- int[] points = getCenterCurvePoints(from, to);
- for (int i = 1; i < points.length; i++) {
- g.drawLine(from.x + i - 1, points[i - 1], i, points[i]);
- }
- }
-
- private TreeItem findRightTreeItemFromLeftDiff(List<TreeItem> rightItems, Diff leftDiff,
- IMergeViewerItem leftData) {
- TreeItem ret = null;
- for (TreeItem rightItem : rightItems) {
- IMergeViewerItem rightData = (IMergeViewerItem)rightItem.getData();
- final Diff rightDiff = rightData.getDiff();
- if (leftDiff == rightDiff) {
- return rightItem;
- } else if (rightData.getAncestor() == leftData.getAncestor()
- && rightData.getRight() == leftData.getRight()
- && rightData.getLeft() == leftData.getLeft()) {
- ret = rightItem;
- }
- }
- return ret;
- }
-
- private int[] getCenterCurvePoints(Point from, Point to) {
- int startx = from.x;
- int starty = from.y;
- int endx = to.x;
- int endy = to.y;
- if (fBasicCenterCurve == null) {
- buildBaseCenterCurve(endx - startx);
- }
- double height = endy - starty;
- height = height / 2;
- int width = endx - startx;
- int[] points = new int[width];
- for (int i = 0; i < width; i++) {
- points[i] = (int)(-height * fBasicCenterCurve[i] + height + starty);
- }
- return points;
- }
-
- private void buildBaseCenterCurve(int w) {
- double width = w;
- fBasicCenterCurve = new double[getCenterWidth()];
- for (int i = 0; i < getCenterWidth(); i++) {
- double r = i / width;
- fBasicCenterCurve[i] = Math.cos(Math.PI * r);
- }
+ super.hookListeners(treeMergeViewer);
}
/**
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java
index 7dd6c1c69..32b44fe1d 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java
@@ -9,13 +9,14 @@
* Obeo - initial API and implementation
* Michael Borkowski - bug 462237
* Martin Fleck - bug 483798
- * Philip Langer - bug 521948
+ * Philip Langer - bugs 521948, 527567
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
import static com.google.common.collect.Iterables.addAll;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.isEmpty;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static org.eclipse.emf.compare.DifferenceSource.LEFT;
@@ -590,6 +591,9 @@ public class MergeAction extends BaseSelectionListenerAction {
Iterable<TreeNode> selectedTreeNode = filter(selectedNotifiers, TreeNode.class);
Iterable<EObject> selectedEObjects = transform(selectedTreeNode, IDifferenceGroup.TREE_NODE_DATA);
Iterable<Diff> diffs = filter(selectedEObjects, Diff.class);
+ if (isEmpty(diffs)) {
+ diffs = filter(selectedObjects, Diff.class);
+ }
return getSelectedDifferences(diffs);
}
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractStructuredMergeViewer.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractStructuredMergeViewer.java
index 205b83310..2c5912f09 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractStructuredMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractStructuredMergeViewer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2014 Obeo.
+ * Copyright (c) 2012, 2017 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
@@ -7,19 +7,31 @@
*
* Contributors:
* Obeo - initial API and implementation
+ * Philip Langer - bug 527567
*******************************************************************************/
package org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl;
+import java.util.EnumSet;
+
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.internal.merge.MergeMode;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration;
+import org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
/**
* A specific {@link AbstractMergeViewer} for the EMF Compare Editor.
@@ -54,6 +66,7 @@ public abstract class AbstractStructuredMergeViewer extends AbstractMergeViewer
fForwardingSelectionListener = new ForwardingViewerSelectionListener();
getStructuredViewer().addSelectionChangedListener(fForwardingSelectionListener);
+ createContextMenu();
}
/**
@@ -82,6 +95,94 @@ public abstract class AbstractStructuredMergeViewer extends AbstractMergeViewer
return fControl;
}
+ /**
+ * Creates the context menu for the {@link #getStructuredViewer() structured viewer} adding a
+ * {@link IMenuListener menu listener} that calls {@link #fillContextMenu(IMenuManager)}.
+ */
+ protected void createContextMenu() {
+ MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ menuMgr.setRemoveAllWhenShown(true);
+ menuMgr.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager manager) {
+ fillContextMenu(manager);
+ }
+ });
+ Control control = getStructuredViewer().getControl();
+ Menu menu = menuMgr.createContextMenu(control);
+ control.setMenu(menu);
+ }
+
+ /**
+ * Fills the context menu for the {@link #getStructuredViewer() structured viewer. By default, this
+ * determines the merge mode from the {@link #getCompareConfiguration() compare configuration}, and uses
+ * the {@link #getDiff() diff} of the {@link #getSelection() selection} to
+ * {@link #createAction(MergeMode, Diff) create actions}. The default implementation of
+ * {@code createAction} returns {@code null}, in which case no action is {@link IMenuManager#add(IAction)
+ * added} to the menu manager.
+ *
+ * @param manager
+ * the menu manager of the {@link #createContextMenu() context menu}.
+ * @see #getDiff()
+ * @see #createAction(MergeMode, Diff)
+ */
+ protected void fillContextMenu(IMenuManager manager) {
+ IEMFCompareConfiguration configuration = getCompareConfiguration();
+ boolean leftEditable = configuration.isLeftEditable();
+ boolean rightEditable = configuration.isRightEditable();
+ if (rightEditable || leftEditable) {
+ Diff diff = getDiff();
+ if (diff != null) {
+ final EnumSet<MergeMode> modes;
+ if (rightEditable && leftEditable) {
+ modes = EnumSet.of(MergeMode.RIGHT_TO_LEFT, MergeMode.LEFT_TO_RIGHT);
+ } else {
+ modes = EnumSet.of(MergeMode.ACCEPT, MergeMode.REJECT);
+ }
+ for (MergeMode mode : modes) {
+ IAction action = createAction(mode, diff);
+ if (action != null) {
+ manager.add(action);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the {@link IMergeViewerItem#getDiff() diff} associated with the one {@link IMergeViewerItem} in
+ * the viewer's {@link #getSelection() selection}.
+ *
+ * @return the diff associated with the one {@code IMergeViewerItem} in the viewer's selection.
+ */
+ protected Diff getDiff() {
+ ISelection selection = getSelection();
+ if (!selection.isEmpty() && selection instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection)selection;
+ if (structuredSelection.size() == 1) {
+ Object firstElement = structuredSelection.getFirstElement();
+ if (firstElement instanceof IMergeViewerItem) {
+ IMergeViewerItem mergeViewerItem = (IMergeViewerItem)firstElement;
+ return mergeViewerItem.getDiff();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates the action for merging the given diff via the specified mode. By default this returns
+ * {@code null}.
+ *
+ * @param mode
+ * the merge mode.
+ * @param diff
+ * the diff to be merged.
+ * @return a new action for merging the given diff via the specified mode.
+ */
+ protected IAction createAction(MergeMode mode, Diff diff) {
+ return null;
+ }
+
@Override
protected void handleDispose(DisposeEvent event) {
getStructuredViewer().removeSelectionChangedListener(fForwardingSelectionListener);
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeItemWrapper.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeItemWrapper.java
index c8362e5c7..d58d6d199 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeItemWrapper.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeItemWrapper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2014 Obeo.
+ * Copyright (c) 2012, 2017 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
@@ -7,6 +7,7 @@
*
* Contributors:
* Obeo - initial API and implementation
+ * Philip Langer - bug 527567
*******************************************************************************/
package org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl;
@@ -135,6 +136,15 @@ public abstract class AbstractTableOrTreeItemWrapper {
public abstract int getParentItemHeight();
/**
+ * Returns whether the receiver can be expanded to show children.
+ *
+ * @return whether the receiver can be expanded to show children.
+ */
+ public boolean isExpandable() {
+ return false;
+ }
+
+ /**
* Returns the data associated to the Item.
*
* @return the data associated to the Item.
@@ -239,6 +249,16 @@ public abstract class AbstractTableOrTreeItemWrapper {
/**
* {@inheritDoc}
*
+ * @see org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.AbstractTableOrTreeItemWrapper#isExpandable()
+ */
+ @Override
+ public boolean isExpandable() {
+ return fItem.getItemCount() > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.AbstractTableOrTreeItemWrapper#getTextBounds(int)
*/
@Override
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeMergeViewer.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeMergeViewer.java
index eacd19ffb..efbeb30e2 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/AbstractTableOrTreeMergeViewer.java
@@ -7,7 +7,11 @@
*
* Contributors:
* Obeo - initial API and implementation
+<<<<<<< master
* Philip Langer - bug 527858
+=======
+ * Philip Langer - bug 527567
+>>>>>>> dde9ebc [527567] Generalize the table and tree merge viewer framework
*******************************************************************************/
package org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl;
@@ -23,7 +27,6 @@ import org.eclipse.emf.compare.rcp.ui.internal.util.MergeViewerUtil;
import org.eclipse.emf.compare.rcp.ui.mergeviewer.ICompareColor;
import org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem;
import org.eclipse.jface.viewers.IElementComparer;
-import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.graphics.Color;
@@ -119,16 +122,17 @@ public abstract class AbstractTableOrTreeMergeViewer extends AbstractStructuredM
Image image = itemWrapper.getImage(event.index);
/* center column 1 vertically */
+ int cellGap = TEXT_GAP;
+ if (event.index == 0) {
+ cellGap = 0;
+ }
Point size = event.gc.textExtent(text);
int yOffset = Math.max(0, (event.height - size.y) / 2);
- int xOffset = event.x;
if (image != null) {
int imageYOffset = Math.max(0, (event.height - image.getBounds().height) / 2);
- event.gc.drawImage(image, event.x + IMAGE_GAP, event.y + imageYOffset);
- xOffset += IMAGE_GAP + image.getBounds().width;
+ event.gc.drawImage(image, event.x + cellGap, event.y + imageYOffset);
}
- event.gc.drawText(text, xOffset + TEXT_GAP, event.y + yOffset, true);
- event.width += 2;
+ event.gc.drawText(text, itemWrapper.getTextBounds(event.index).x + cellGap, event.y + yOffset, true);
}
/**
@@ -159,6 +163,10 @@ public abstract class AbstractTableOrTreeMergeViewer extends AbstractStructuredM
}
}
}
+
+ // Avoid drawing the ugly focus box on tables.
+ // It looks especially bad for our own painted items.
+ event.detail &= ~SWT.FOCUSED;
}
/**
@@ -225,17 +233,11 @@ public abstract class AbstractTableOrTreeMergeViewer extends AbstractStructuredM
GC g) {
AbstractTableOrTreeItemWrapper parent = itemWrapper.getParentItem();
final int xOffset;
- if (getContentProvider() instanceof ITreeContentProvider) {
- final boolean hasChildren = ((ITreeContentProvider)getContentProvider())
- .hasChildren(itemWrapper.getData());
- if (hasChildren) {
- if (parent != null) {
- xOffset = parent.getImageBounds(0).x;
- } else {
- xOffset = 0;
- }
+ if (itemWrapper.isExpandable()) {
+ if (parent != null) {
+ xOffset = parent.getImageBounds(0).x;
} else {
- xOffset = boxBounds.x;
+ xOffset = 0;
}
} else {
xOffset = boxBounds.x;
@@ -267,7 +269,11 @@ public abstract class AbstractTableOrTreeMergeViewer extends AbstractStructuredM
from.y = itemBounds.y + (itemBounds.height / 2);
Point to = new Point(0, from.y);
to.x = clientArea.x + clientArea.width;
- g.drawLine(from.x, from.y, to.x, to.y);
+ // We expect the to.x to be to the right so we need this guard because otherwise the line may be drawn
+ // on top of the hover information when the box is clipped.
+ if (from.x < to.x) {
+ g.drawLine(from.x, from.y, to.x, to.y);
+ }
}
/**
@@ -327,16 +333,55 @@ public abstract class AbstractTableOrTreeMergeViewer extends AbstractStructuredM
Scrollable tree = itemWrapper.getParent();
Rectangle treeBounds = tree.getClientArea();
Rectangle itemBounds = itemWrapper.getBounds();
- Rectangle imageBounds = itemWrapper.getImageBounds(0);
+
+ // Compute the left and right points of all columns based on images and text being present so that the
+ // box only bounds what's visibly present.
+ int columnCount = itemWrapper.getParentColumnCount();
+ int limit = Math.max(1, columnCount);
+ int left = -1;
+ int right = -1;
+ for (int i = 0; i < limit; ++i) {
+ Image image = itemWrapper.getImage(i);
+ if (image != null) {
+ Rectangle imageBounds = itemWrapper.getImageBounds(i);
+ if (left == -1) {
+ left = imageBounds.x - TEXT_GAP;
+ if (i > 0) {
+ left += TEXT_GAP;
+ }
+ }
+ right = imageBounds.x + imageBounds.width + TEXT_GAP;
+ if (i > 0) {
+ right += TEXT_GAP;
+ }
+ }
+
+ String text = itemWrapper.getText(i);
+ if (!text.isEmpty()) {
+ Rectangle textBounds = itemWrapper.getTextBounds(i);
+ if (left == -1) {
+ left = textBounds.x - TEXT_GAP;
+ if (i > 0) {
+ left += TEXT_GAP;
+ }
+ }
+ int textWidth = event.gc.textExtent(text).x;
+ right = textBounds.x + textWidth + TEXT_GAP;
+ if (i > 0) {
+ right += TEXT_GAP;
+ }
+ }
+ }
Rectangle fill = new Rectangle(0, 0, 0, 0);
- fill.x = itemBounds.x - imageBounds.width;
+ fill.x = left;
fill.y = itemBounds.y;
if (!"cocoa".equals(SWT.getPlatform())) { //$NON-NLS-1$
fill.y += 1;
}
// +x to add the icon and the expand "+" if we are in a tree
- fill.width = itemBounds.width + imageBounds.width + DELTA_IMAGE_GAP;
+ // fill.width = itemBounds.width + imageBounds.width + DELTA_IMAGE_GAP;
+ fill.width = right - left;
fill.height = itemBounds.height - 1;
if (!"cocoa".equals(SWT.getPlatform())) { //$NON-NLS-1$
fill.height -= 3;
@@ -345,7 +390,6 @@ public abstract class AbstractTableOrTreeMergeViewer extends AbstractStructuredM
final GC g = event.gc;
// If you wish to paint the selection beyond the end of last column, you must change the clipping
// region.
- int columnCount = itemWrapper.getParentColumnCount();
if (event.index == columnCount - 1 || columnCount == 0) {
int width = treeBounds.x + treeBounds.width - event.x;
if (width > 0) {
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/TreeMergeViewer.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/TreeMergeViewer.java
index 5ccdc5b44..8319b9a16 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/TreeMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/impl/TreeMergeViewer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2014 Obeo.
+ * Copyright (c) 2012, 2017 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
@@ -7,6 +7,7 @@
*
* Contributors:
* Obeo - initial API and implementation
+ * Philip Langer - bug 527567
*******************************************************************************/
package org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl;
@@ -74,12 +75,23 @@ public class TreeMergeViewer extends AbstractTableOrTreeMergeViewer {
layout.marginHeight = 0;
composite.setLayout(layout);
- fTreeViewer = new TreeViewer(composite);
+ fTreeViewer = createTreeViewer(composite);
fTreeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
return composite;
}
/**
+ * Creates a new tree viewer.
+ *
+ * @param parent
+ * the parent of the new tree viewer.
+ * @return a new tree viewer.
+ */
+ protected TreeViewer createTreeViewer(Composite parent) {
+ return new TreeViewer(parent);
+ }
+
+ /**
* {@inheritDoc}
*
* @see org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.impl.ide.ui.internal.contentmergeviewer.AbstractMergeViewer#getStructuredViewer()
@@ -101,6 +113,7 @@ public class TreeMergeViewer extends AbstractTableOrTreeMergeViewer {
getStructuredViewer().setExpandedState(elementOrTreePath, expanded);
}
+ @Override
protected void hookDispose() {
fInput = null;
fTreeViewer = null;

Back to the top