305152: Improvements to the displayed comparison results

Allow selection of set operations from UI

Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=305152

Change-Id: I802b9ffd9131141fc49ecb6e3f61f2bcc63e8878
diff --git a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/snapshot/inspections/CompareTablesQuery.java b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/snapshot/inspections/CompareTablesQuery.java
index 8173cf7..16231ae 100644
--- a/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/snapshot/inspections/CompareTablesQuery.java
+++ b/plugins/org.eclipse.mat.api/src/org/eclipse/mat/internal/snapshot/inspections/CompareTablesQuery.java
@@ -152,7 +152,8 @@
         INTERSECTION,

         UNION,

         SYMMETRIC_DIFFERENCE,

-        DIFFERENCE

+        DIFFERENCE,

+        REVERSE_DIFFERENCE

     }

 

     public IResult execute(IProgressListener listener) throws Exception

@@ -1302,6 +1303,7 @@
                         if (setOp == Operation.UNION && op != 1) continue;

                         if (setOp == Operation.SYMMETRIC_DIFFERENCE && op != 2) continue;

                         if (setOp == Operation.DIFFERENCE && op != 3) continue;

+                        if (setOp == Operation.REVERSE_DIFFERENCE && op != 4) continue;

                         final int op1 = op;

                         // intersection, union, symmetric difference, difference, difference

                         String title1;

@@ -2259,6 +2261,29 @@
             updateColumns();

         }

 

+        public Operation getOperation()

+        {

+            return setOp;

+        }

+

+        public void setOperation(Operation op)

+        {

+            if (op != Operation.NONE)

+            {

+                // Don't allow an operation if there are not enough local tables

+                int samec = 0;

+                for (boolean same : CompareTablesQuery.this.sameSnapshot)

+                {

+                    if (same)

+                        ++samec;

+                }

+                if (samec < 2)

+                    op = Operation.NONE;

+            }

+            this.setOp = op;

+            updateColumns();

+        }

+

         private void addPositiveIndicator(Format formatter)

         {

             if (formatter instanceof DecimalFormat)

diff --git a/plugins/org.eclipse.mat.ui/icons/set_differenceA.gif b/plugins/org.eclipse.mat.ui/icons/set_differenceA.gif
new file mode 100644
index 0000000..4f7f7dc
--- /dev/null
+++ b/plugins/org.eclipse.mat.ui/icons/set_differenceA.gif
Binary files differ
diff --git a/plugins/org.eclipse.mat.ui/icons/set_differenceB.gif b/plugins/org.eclipse.mat.ui/icons/set_differenceB.gif
new file mode 100644
index 0000000..a31bd31
--- /dev/null
+++ b/plugins/org.eclipse.mat.ui/icons/set_differenceB.gif
Binary files differ
diff --git a/plugins/org.eclipse.mat.ui/icons/set_intersection.gif b/plugins/org.eclipse.mat.ui/icons/set_intersection.gif
new file mode 100644
index 0000000..1734558
--- /dev/null
+++ b/plugins/org.eclipse.mat.ui/icons/set_intersection.gif
Binary files differ
diff --git a/plugins/org.eclipse.mat.ui/icons/set_symmetric_difference.gif b/plugins/org.eclipse.mat.ui/icons/set_symmetric_difference.gif
new file mode 100644
index 0000000..cef6b0b
--- /dev/null
+++ b/plugins/org.eclipse.mat.ui/icons/set_symmetric_difference.gif
Binary files differ
diff --git a/plugins/org.eclipse.mat.ui/icons/set_union.gif b/plugins/org.eclipse.mat.ui/icons/set_union.gif
new file mode 100644
index 0000000..182954a
--- /dev/null
+++ b/plugins/org.eclipse.mat.ui/icons/set_union.gif
Binary files differ
diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/MemoryAnalyserPlugin.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/MemoryAnalyserPlugin.java
index c3fe9c5..4edd4d0 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/MemoryAnalyserPlugin.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/MemoryAnalyserPlugin.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2015 SAP AG, IBM Corporation and others.
+ * Copyright (c) 2008, 2020 SAP AG, IBM Corporation 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
@@ -57,8 +57,8 @@
         String PLUS = PREFIX + "plus.gif"; //$NON-NLS-1$
         String EXPERT_SYSTEM = PREFIX + "expert.gif"; //$NON-NLS-1$
 
-        String REFRESH = PREFIX + "refresh.gif"; //$NON-NLS-1$       
-        String THREAD = PREFIX + "thread.gif"; //$NON-NLS-1$       
+        String REFRESH = PREFIX + "refresh.gif"; //$NON-NLS-1$
+        String THREAD = PREFIX + "thread.gif"; //$NON-NLS-1$
 
         String RETAINED_SET = PREFIX + "retainedSet.gif"; //$NON-NLS-1$
         String PACKAGE = PREFIX + "package.gif"; //$NON-NLS-1$
@@ -100,14 +100,14 @@
         String INFO = PREFIX + "info.gif"; //$NON-NLS-1$
         String HELP = PREFIX + "help.png"; //$NON-NLS-1$
 
-        String FIND = PREFIX + "find.gif"; //$NON-NLS-1$  
+        String FIND = PREFIX + "find.gif"; //$NON-NLS-1$
         String EXECUTE_QUERY = PREFIX + "execute_query.gif"; //$NON-NLS-1$
-        String SHOW_AS_HISTOGRAM = PREFIX + "as_histogram.gif"; //$NON-NLS-1$  
-        String EXPLORE = PREFIX + "explore.gif"; //$NON-NLS-1$  
+        String SHOW_AS_HISTOGRAM = PREFIX + "as_histogram.gif"; //$NON-NLS-1$
+        String EXPLORE = PREFIX + "explore.gif"; //$NON-NLS-1$
 
-        String SHOW_PANE = PREFIX + "show_pane.gif"; //$NON-NLS-1$  
-        String CLOSE_PANE = PREFIX + "close_pane.gif"; //$NON-NLS-1$  
-        String CLOSE_BRANCH = PREFIX + "close_branch.gif"; //$NON-NLS-1$  
+        String SHOW_PANE = PREFIX + "show_pane.gif"; //$NON-NLS-1$
+        String CLOSE_PANE = PREFIX + "close_pane.gif"; //$NON-NLS-1$
+        String CLOSE_BRANCH = PREFIX + "close_branch.gif"; //$NON-NLS-1$
 
         String PINNED = PREFIX + "pinned.gif"; //$NON-NLS-1$
 
@@ -116,6 +116,11 @@
         String REMOVE = PREFIX + "remove.gif"; //$NON-NLS-1$
         String REMOVE_ALL = PREFIX + "removeall.gif"; //$NON-NLS-1$
         String SELECT_COLUMN = PREFIX + "select_table.gif"; //$NON-NLS-1$
+        String SET_DIFFERENCE_A = PREFIX + "set_differenceA.gif"; //$NON-NLS-1$
+        String SET_DIFFERENCE_B = PREFIX + "set_differenceB.gif"; //$NON-NLS-1$
+        String SET_INTERSECTION = PREFIX + "set_intersection.gif"; //$NON-NLS-1$
+        String SET_SYMMETRIC_DIFFERENCE = PREFIX + "set_symmetric_difference.gif"; //$NON-NLS-1$
+        String SET_UNION = PREFIX + "set_union.gif"; //$NON-NLS-1$
     }
 
     private static MemoryAnalyserPlugin plugin;
diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/Messages.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/Messages.java
index 8115399..517aba1 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/Messages.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/Messages.java
@@ -52,12 +52,20 @@
 	public static String CompareBasketView_ResultsToBeComparedColumnHeader;

     public static String CompareTablesPane_AbsoluteValues;

     public static String CompareTablesPane_ChooseDiffOptionTooltip;

+    public static String CompareTablesPane_ChooseOperation;

     public static String CompareTablesPane_DifferenceToBaseTable;

     public static String CompareTablesPane_DifferenceToPrecedingTable;

     public static String CompareTablesPane_PercentageDifferenceToBaseTable;

     public static String CompareTablesPane_PercentageDifferenceToPrecedingTable;

     public static String CompareTablesPane_SelectDisplayedColumnsTooltip;

-	public static String Copy_ErrorInExport;

+	public static String CompareTablesPane_Setop_All;

+    public static String CompareTablesPane_Setop_Difference;

+    public static String CompareTablesPane_Setop_Intersection;

+    public static String CompareTablesPane_Setop_None;

+    public static String CompareTablesPane_Setop_ReverseDifference;

+    public static String CompareTablesPane_Setop_SymmetricDifference;

+    public static String CompareTablesPane_Setop_Union;

+    public static String Copy_ErrorInExport;

     public static String CopyActions_CopyingToClipboard;

     public static String CopyOQL_Copying;

     public static String CopyOQL_TooBig;

diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/icon_labels.properties b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/icon_labels.properties
index 77a6034..f6ce086 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/icon_labels.properties
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/icon_labels.properties
@@ -33,6 +33,7 @@
 IconLabel-decorations-gc_root=gc root 

 IconLabel-decorations-in=in 

 IconLabel-decorations-out=out 

+IconLabel-delta_histogram=delta histogram 

 IconLabel-dominator_tree=dominator tree 

 IconLabel-duplicate_classes=duplicate classes 

 IconLabel-execute_query=execute query 

diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/messages.properties b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/messages.properties
index f703d11..a4cb3e0 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/messages.properties
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/messages.properties
@@ -74,11 +74,19 @@
 CompareBasketView_ResultsToBeComparedColumnHeader=Results to be compared

 CompareTablesPane_AbsoluteValues=Absolute Values

 CompareTablesPane_ChooseDiffOptionTooltip=Choose difference option ...

+CompareTablesPane_ChooseOperation=Choose set operation ...

 CompareTablesPane_DifferenceToBaseTable=Difference from Base Table

 CompareTablesPane_DifferenceToPrecedingTable=Difference from Preceding Table

 CompareTablesPane_PercentageDifferenceToBaseTable=Percentage Difference from Base Table

 CompareTablesPane_PercentageDifferenceToPrecedingTable=Percentage Difference from Preceding Table

 CompareTablesPane_SelectDisplayedColumnsTooltip=Select displayed columns...

+CompareTablesPane_Setop_All=All

+CompareTablesPane_Setop_Difference=Difference

+CompareTablesPane_Setop_Intersection=Intersection

+CompareTablesPane_Setop_None=None

+CompareTablesPane_Setop_ReverseDifference=Reverse Difference

+CompareTablesPane_Setop_SymmetricDifference=Symmetric Difference

+CompareTablesPane_Setop_Union=Union

 Copy_ErrorInExport=Error in export to .txt: data type not supported for export.

 CopyActions_CopyingToClipboard=Copying to clipboard

 CopyOQL_Copying=Copying OQL to clipboard

diff --git a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/CompareTablesPane.java b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/CompareTablesPane.java
index 9687f1d..1715709 100644
--- a/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/CompareTablesPane.java
+++ b/plugins/org.eclipse.mat.ui/src/org/eclipse/mat/ui/snapshot/panes/CompareTablesPane.java
@@ -1,5 +1,5 @@
 /*******************************************************************************

- * Copyright (c) 2010, 2011 SAP AG and IBM Corporation.

+ * Copyright (c) 2010, 2020 SAP AG and IBM Corporation.

  * 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:

  *    SAP AG - initial API and implementation

+ *    Andrew Johnson (IBM Corporation) - set operations

  *******************************************************************************/

 package org.eclipse.mat.ui.snapshot.panes;

 

@@ -21,6 +22,7 @@
 import org.eclipse.jface.action.Separator;

 import org.eclipse.mat.internal.snapshot.inspections.CompareTablesQuery.ComparedColumn;

 import org.eclipse.mat.internal.snapshot.inspections.CompareTablesQuery.Mode;

+import org.eclipse.mat.internal.snapshot.inspections.CompareTablesQuery.Operation;

 import org.eclipse.mat.internal.snapshot.inspections.CompareTablesQuery.TableComparisonResult;

 import org.eclipse.mat.query.IResult;

 import org.eclipse.mat.query.registry.QueryResult;

@@ -34,227 +36,413 @@
 public class CompareTablesPane extends QueryResultPane

 {

 

-	public enum DiffOption

-	{

+    public enum DiffOption

+    {

         ABSOLUTE(Messages.CompareTablesPane_AbsoluteValues), DIFF_TO_BASE(

                         Messages.CompareTablesPane_DifferenceToBaseTable), DIFF_RATIO_TO_BASE(

-                        Messages.CompareTablesPane_PercentageDifferenceToBaseTable), DIFF_TO_PREV(

-                        Messages.CompareTablesPane_DifferenceToPrecedingTable), DIFF_RATIO_TO_PREV(

-                        Messages.CompareTablesPane_PercentageDifferenceToPrecedingTable);

+                                        Messages.CompareTablesPane_PercentageDifferenceToBaseTable), DIFF_TO_PREV(

+                                                        Messages.CompareTablesPane_DifferenceToPrecedingTable), DIFF_RATIO_TO_PREV(

+                                                                        Messages.CompareTablesPane_PercentageDifferenceToPrecedingTable);

 

-		String label;

+        String label;

 

-		private DiffOption(String label)

-		{

-			this.label = label;

-		}

+        private DiffOption(String label)

+        {

+            this.label = label;

+        }

 

-		public String toString()

-		{

-			return label;

-		}

-	}

+        public String toString()

+        {

+            return label;

+        }

+    }

 

-	private DiffOption diffOption;

+    private DiffOption diffOption;

 

-	@Override

-	public void initWithArgument(Object argument)

-	{

-		super.initWithArgument(argument);

 

-		IResult subject = ((QueryResult) argument).getSubject();

-		if (subject instanceof TableComparisonResult)

-		{

-			Mode mode = ((TableComparisonResult) subject).getMode();

-			switch (mode)

-			{

-			case ABSOLUTE:

-				diffOption = DiffOption.ABSOLUTE;

-				break;

-			case DIFF_TO_FIRST:

-				diffOption = DiffOption.DIFF_TO_BASE;

-				break;

-			case DIFF_TO_PREVIOUS:

-				diffOption = DiffOption.DIFF_TO_PREV;

-				break;

-            case DIFF_RATIO_TO_FIRST:

-                diffOption = DiffOption.DIFF_RATIO_TO_BASE;

-                break;

-            case DIFF_RATIO_TO_PREVIOUS:

-                diffOption = DiffOption.DIFF_RATIO_TO_PREV;

-                break;				

+    public enum SetopOption

+    {

+        NONE(Messages.CompareTablesPane_Setop_None),

+        ALL(Messages.CompareTablesPane_Setop_All),

+        INTERSECTION(Messages.CompareTablesPane_Setop_Intersection),

+        UNION(Messages.CompareTablesPane_Setop_Union),

+        SYMMETRIC_DIFFERENCE(Messages.CompareTablesPane_Setop_SymmetricDifference),

+        DIFFERENCE(Messages.CompareTablesPane_Setop_Difference),

+        REVERSE_DIFFERENCE(Messages.CompareTablesPane_Setop_ReverseDifference);

 

-			default:

-				break;

-			}

-		}

-	}

+        String label;

 

-	@Override

-	public void contributeToToolBar(IToolBarManager manager)

-	{

-		addDiffOptions(manager);

+        private SetopOption(String label)

+        {

+            this.label = label;

+        }

 

-		addSelectColumns(manager);

+        public String toString()

+        {

+            return label;

+        }

+    }

 

-		manager.add(new Separator());

-		super.contributeToToolBar(manager);

+    private SetopOption setopOption;

 

-	}

+    @Override

+    public void initWithArgument(Object argument)

+    {

+        super.initWithArgument(argument);

 

-	private void addSelectColumns(IToolBarManager manager)

-	{

-		final IResult result = viewer.getQueryResult().getSubject();

-		if (result instanceof TableComparisonResult)

-		{

-			Action selectColumnsAction = new EasyToolBarDropDown(Messages.CompareTablesPane_SelectDisplayedColumnsTooltip, //

-					MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.SELECT_COLUMN), this) {

+        IResult subject = ((QueryResult) argument).getSubject();

+        if (subject instanceof TableComparisonResult)

+        {

+            Mode mode = ((TableComparisonResult) subject).getMode();

+            switch (mode)

+            {

+                case ABSOLUTE:

+                    diffOption = DiffOption.ABSOLUTE;

+                    break;

+                case DIFF_TO_FIRST:

+                    diffOption = DiffOption.DIFF_TO_BASE;

+                    break;

+                case DIFF_TO_PREVIOUS:

+                    diffOption = DiffOption.DIFF_TO_PREV;

+                    break;

+                case DIFF_RATIO_TO_FIRST:

+                    diffOption = DiffOption.DIFF_RATIO_TO_BASE;

+                    break;

+                case DIFF_RATIO_TO_PREVIOUS:

+                    diffOption = DiffOption.DIFF_RATIO_TO_PREV;

+                    break;

+                default:

+                    break;

+            }

 

-				@Override

-				public void contribute(PopupMenu menu)

-				{

-					List<ComparedColumn> columns = ((TableComparisonResult) result).getComparedColumns();

-					for (ComparedColumn comparedColumn : columns)

-					{

-						menu.add(new SelectColumnAction(comparedColumn));

-					}

+            Operation op = ((TableComparisonResult) subject).getOperation();

+            switch (op)

+            {

+                case NONE:

+                    setopOption = SetopOption.NONE;

+                    break;

+                case ALL:

+                    setopOption = SetopOption.ALL;

+                    break;

+                case INTERSECTION:

+                    setopOption = SetopOption.INTERSECTION;

+                    break;

+                case UNION:

+                    setopOption = SetopOption.UNION;

+                    break;

+                case SYMMETRIC_DIFFERENCE:

+                    setopOption = SetopOption.SYMMETRIC_DIFFERENCE;

+                    break;

+                case DIFFERENCE:

+                    setopOption = SetopOption.DIFFERENCE;

+                    break;

+                case REVERSE_DIFFERENCE:

+                    setopOption = SetopOption.REVERSE_DIFFERENCE;

+                    break;

+                default:

+                    break;

+            }

+        }

+    }

 

-				}

-			};

-			

-			manager.add(selectColumnsAction);

-		}

+    @Override

+    public void contributeToToolBar(IToolBarManager manager)

+    {

+        addDiffOptions(manager);

 

-	}

+        addSetopOptions(manager);

 

-	private void addDiffOptions(IToolBarManager manager)

-	{

-		Action diffOptionAction = new EasyToolBarDropDown(Messages.CompareTablesPane_ChooseDiffOptionTooltip, //

-				MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.GROUPING), this) {

-			@Override

-			public void contribute(PopupMenu menu)

-			{

-				for (DiffOption opt : DiffOption.values())

-				{

-					Action action = new DiffOptionAction(opt);

-					action.setEnabled(opt != diffOption);

-					action.setChecked(opt == diffOption);

-					menu.add(action);

-				}

-			}

-		};

+        addSelectColumns(manager);

 

-		manager.add(diffOptionAction);

-	}

+        manager.add(new Separator());

+        super.contributeToToolBar(manager);

 

-	private class DiffOptionAction extends Action

-	{

-		private DiffOption diffOption;

+    }

 

-		private DiffOptionAction(DiffOption diffOption)

-		{

-			super(diffOption.toString(), AS_CHECK_BOX);

-			this.diffOption = diffOption;

-		}

+    private void addSelectColumns(IToolBarManager manager)

+    {

+        final IResult result = viewer.getQueryResult().getSubject();

+        if (result instanceof TableComparisonResult)

+        {

+            Action selectColumnsAction = new EasyToolBarDropDown(Messages.CompareTablesPane_SelectDisplayedColumnsTooltip, //

+                            MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.SELECT_COLUMN), this) {

 

-		@Override

-		public void run()

-		{

-			// do not run the same action twice - selection was not changed

-			if (!isChecked()) return;

+                @Override

+                public void contribute(PopupMenu menu)

+                {

+                    List<ComparedColumn> columns = ((TableComparisonResult) result).getComparedColumns();

+                    for (ComparedColumn comparedColumn : columns)

+                    {

+                        menu.add(new SelectColumnAction(comparedColumn));

+                    }

 

-			Mode mode = Mode.ABSOLUTE;

-			switch (diffOption)

-			{

-			case DIFF_TO_PREV:

-				mode = Mode.DIFF_TO_PREVIOUS;

+                }

+            };

 

-				break;

-			case DIFF_TO_BASE:

-				mode = Mode.DIFF_TO_FIRST;

+            manager.add(selectColumnsAction);

+        }

 

-				break;

-				

-            case DIFF_RATIO_TO_PREV:

-                mode = Mode.DIFF_RATIO_TO_PREVIOUS;

+    }

 

-                break;

-            case DIFF_RATIO_TO_BASE:

-                mode = Mode.DIFF_RATIO_TO_FIRST;

+    private void addDiffOptions(IToolBarManager manager)

+    {

+        Action diffOptionAction = new EasyToolBarDropDown(Messages.CompareTablesPane_ChooseDiffOptionTooltip, //

+                        MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.GROUPING), this) {

+            @Override

+            public void contribute(PopupMenu menu)

+            {

+                for (DiffOption opt : DiffOption.values())

+                {

+                    Action action = new DiffOptionAction(opt);

+                    action.setEnabled(opt != diffOption);

+                    action.setChecked(opt == diffOption);

+                    menu.add(action);

+                }

+            }

+        };

 

-                break;				

+        manager.add(diffOptionAction);

+    }

 

-			default:

-				break;

-			}

+    private void addSetopOptions(IToolBarManager manager)

+    {

+        final IResult result = viewer.getQueryResult().getSubject();

+        // Test whether set operations make sense

+        if (result instanceof TableComparisonResult)

+        {

+            TableComparisonResult tcr = (TableComparisonResult)result;

+            Operation op1 = tcr.getOperation();

+            if (op1 == Operation.NONE)

+            {

+                // Try setting the operation

+                Operation op2 = Operation.ALL;

+                tcr.setOperation(op2);

+                Operation op3 = tcr.getOperation();

+                // Restore

+                tcr.setOperation(op1);

+                // If we can't change the mode, don't give the option to change

+                if (op3 != op2)

+                    return;

+            }

+        }

+        Action setopOptionAction = new EasyToolBarDropDown(Messages.CompareTablesPane_ChooseOperation, //

+                        MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.SET_SYMMETRIC_DIFFERENCE), this)

+        {

+            @Override

+            public void contribute(PopupMenu menu)

+            {

+                for (SetopOption opt : SetopOption.values())

+                {

+                    Action action = new SetopOptionAction(opt);

+                    action.setEnabled(opt != setopOption);

+                    action.setChecked(opt == setopOption);

+                    switch (opt)

+                    {

+                        case UNION:

+                            action.setImageDescriptor(MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.SET_UNION));

+                            break;

+                        case INTERSECTION:

+                            action.setImageDescriptor(MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.SET_INTERSECTION));

+                            break;

+                        case SYMMETRIC_DIFFERENCE:

+                            action.setImageDescriptor(MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.SET_SYMMETRIC_DIFFERENCE));

+                            break;

+                        case DIFFERENCE:

+                            action.setImageDescriptor(MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.SET_DIFFERENCE_A));

+                            break;

+                        case REVERSE_DIFFERENCE:

+                            action.setImageDescriptor(MemoryAnalyserPlugin.getImageDescriptor(MemoryAnalyserPlugin.ISharedImages.SET_DIFFERENCE_B));

+                            break;

+                        case NONE:

+                        case ALL:

+                            break;

+                    }

+                    menu.add(action);

+                }

+            }

+        };

 

-			IResult result = viewer.getQueryResult().getSubject();

-			if (result instanceof TableComparisonResult)

-			{

-				((TableComparisonResult) result).setMode(mode);

-			}

+        manager.add(setopOptionAction);

+    }

 

-			final QueryResult queryResult = new QueryResult(null, "compare", result); //$NON-NLS-1$

+    private class DiffOptionAction extends Action

+    {

+        private DiffOption diffOption;

 

-			new Job(getText()) {

-				protected IStatus run(IProgressMonitor monitor)

-				{

+        private DiffOptionAction(DiffOption diffOption)

+        {

+            super(diffOption.toString(), AS_CHECK_BOX);

+            this.diffOption = diffOption;

+        }

 

-					top.getDisplay().asyncExec(new Runnable() {

-						public void run()

-						{

-							CompareTablesPane.this.diffOption = diffOption;

-							deactivateViewer();

-							RefinedResultViewer v = createViewer(queryResult);

-							activateViewer(v);

-						}

-					});

-					return Status.OK_STATUS;

-				}

-			}.schedule();

-		}

-	}

+        @Override

+        public void run()

+        {

+            // do not run the same action twice - selection was not changed

+            if (!isChecked()) return;

 

-	private class SelectColumnAction extends Action

-	{

-		ComparedColumn column;

+            Mode mode = Mode.ABSOLUTE;

+            switch (diffOption)

+            {

+                case DIFF_TO_PREV:

+                    mode = Mode.DIFF_TO_PREVIOUS;

 

-		public SelectColumnAction(ComparedColumn column)

-		{

-			super(column.getDescription().getLabel(), AS_CHECK_BOX);

-			this.column = column;

-			setChecked(column.isDisplayed());

-		}

+                    break;

+                case DIFF_TO_BASE:

+                    mode = Mode.DIFF_TO_FIRST;

 

-		@Override

-		public void run()

-		{

-			column.setDisplayed(!column.isDisplayed());

-			

-			IResult result = viewer.getQueryResult().getSubject();

-			if (result instanceof TableComparisonResult)

-			{

-				((TableComparisonResult) result).updateColumns();

-			}

+                    break;

 

-			final QueryResult queryResult = new QueryResult(null, "compare", result); //$NON-NLS-1$

+                case DIFF_RATIO_TO_PREV:

+                    mode = Mode.DIFF_RATIO_TO_PREVIOUS;

 

-			new Job(getText()) {

-				protected IStatus run(IProgressMonitor monitor)

-				{

+                    break;

+                case DIFF_RATIO_TO_BASE:

+                    mode = Mode.DIFF_RATIO_TO_FIRST;

 

-					top.getDisplay().asyncExec(new Runnable() {

-						public void run()

-						{

-							deactivateViewer();

-							RefinedResultViewer v = createViewer(queryResult);

-							activateViewer(v);

-						}

-					});

-					return Status.OK_STATUS;

-				}

-			}.schedule();

-		}

-	}

+                    break;

 

+                default:

+                    break;

+            }

+

+            IResult result = viewer.getQueryResult().getSubject();

+            if (result instanceof TableComparisonResult)

+            {

+                ((TableComparisonResult) result).setMode(mode);

+            }

+

+            final QueryResult queryResult = new QueryResult(null, "compare", result); //$NON-NLS-1$

+

+            new Job(getText()) {

+                protected IStatus run(IProgressMonitor monitor)

+                {

+

+                    top.getDisplay().asyncExec(new Runnable() {

+                        public void run()

+                        {

+                            CompareTablesPane.this.diffOption = diffOption;

+                            deactivateViewer();

+                            RefinedResultViewer v = createViewer(queryResult);

+                            activateViewer(v);

+                        }

+                    });

+                    return Status.OK_STATUS;

+                }

+            }.schedule();

+        }

+    }

+

+    private class SelectColumnAction extends Action

+    {

+        ComparedColumn column;

+

+        public SelectColumnAction(ComparedColumn column)

+        {

+            super(column.getDescription().getLabel(), AS_CHECK_BOX);

+            this.column = column;

+            setChecked(column.isDisplayed());

+        }

+

+        @Override

+        public void run()

+        {

+            column.setDisplayed(!column.isDisplayed());

+

+            IResult result = viewer.getQueryResult().getSubject();

+            if (result instanceof TableComparisonResult)

+            {

+                ((TableComparisonResult) result).updateColumns();

+            }

+

+            final QueryResult queryResult = new QueryResult(null, "compare", result); //$NON-NLS-1$

+

+            new Job(getText()) {

+                protected IStatus run(IProgressMonitor monitor)

+                {

+

+                    top.getDisplay().asyncExec(new Runnable() {

+                        public void run()

+                        {

+                            deactivateViewer();

+                            RefinedResultViewer v = createViewer(queryResult);

+                            activateViewer(v);

+                        }

+                    });

+                    return Status.OK_STATUS;

+                }

+            }.schedule();

+        }

+    }

+

+    private class SetopOptionAction extends Action

+    {

+        private SetopOption setopOption;

+

+        private SetopOptionAction(SetopOption setopOption)

+        {

+            super(setopOption.toString(), AS_CHECK_BOX);

+            this.setopOption = setopOption;

+        }

+

+        @Override

+        public void run()

+        {

+            // do not run the same action twice - selection was not changed

+            if (!isChecked())

+                return;

+

+            Operation op = Operation.NONE;

+            switch (setopOption)

+            {

+                case ALL:

+                    op = Operation.ALL;

+                    break;

+                case INTERSECTION:

+                    op = Operation.INTERSECTION;

+                    break;

+                case UNION:

+                    op = Operation.UNION;

+                    break;

+                case SYMMETRIC_DIFFERENCE:

+                    op = Operation.SYMMETRIC_DIFFERENCE;

+                    break;

+                case DIFFERENCE:

+                    op = Operation.DIFFERENCE;

+                    break;

+                case REVERSE_DIFFERENCE:

+                    op = Operation.REVERSE_DIFFERENCE;

+                    break;

+                default:

+                    break;

+            }

+

+            IResult result = viewer.getQueryResult().getSubject();

+            if (result instanceof TableComparisonResult)

+            {

+                ((TableComparisonResult) result).setOperation(op);

+            }

+

+            final QueryResult queryResult = new QueryResult(null,  viewer.getQueryResult().getCommand(), result);

+

+            new Job(getText())

+            {

+                protected IStatus run(IProgressMonitor monitor)

+                {

+

+                    top.getDisplay().asyncExec(new Runnable()

+                    {

+                        public void run()

+                        {

+                            CompareTablesPane.this.setopOption = setopOption;

+                            deactivateViewer();

+                            RefinedResultViewer v = createViewer(queryResult);

+                            activateViewer(v);

+                        }

+                    });

+                    return Status.OK_STATUS;

+                }

+            }.schedule();

+        }

+    }

 }