Bug 566936: example for the bug. Selection of cells leads to jumping.

Change-Id: If370a8792f9542d91eaa28b5d98a7297b3d72227
Signed-off-by: Denis Ungemach <denis.ungemach@sap.com>
diff --git a/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/Bug566936TreeViewerTest.java b/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/Bug566936TreeViewerTest.java
new file mode 100644
index 0000000..56f631c
--- /dev/null
+++ b/tests/org.eclipse.jface.tests/src/org/eclipse/jface/tests/viewers/Bug566936TreeViewerTest.java
@@ -0,0 +1,312 @@
+package org.eclipse.jface.tests.viewers;

+

+import java.util.ArrayList;

+import java.util.List;

+

+import org.eclipse.core.runtime.Assert;

+import org.eclipse.jface.viewers.CellEditor;

+import org.eclipse.jface.viewers.ColumnLabelProvider;

+import org.eclipse.jface.viewers.ColumnViewer;

+import org.eclipse.jface.viewers.ColumnViewerEditor;

+import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;

+import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;

+import org.eclipse.jface.viewers.EditingSupport;

+import org.eclipse.jface.viewers.FocusCellHighlighter;

+import org.eclipse.jface.viewers.ITreeContentProvider;

+import org.eclipse.jface.viewers.StructuredSelection;

+import org.eclipse.jface.viewers.TextCellEditor;

+import org.eclipse.jface.viewers.TreeViewer;

+import org.eclipse.jface.viewers.TreeViewerColumn;

+import org.eclipse.jface.viewers.TreeViewerEditor;

+import org.eclipse.jface.viewers.TreeViewerFocusCellManager;

+import org.eclipse.jface.viewers.ViewerCell;

+import org.eclipse.jface.viewers.ViewerRow;

+import org.eclipse.swt.SWT;

+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.layout.FillLayout;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.swt.widgets.Display;

+import org.eclipse.swt.widgets.Event;

+import org.eclipse.swt.widgets.Listener;

+import org.eclipse.swt.widgets.Shell;

+import org.eclipse.swt.widgets.Tree;

+

+/**

+ * Example for https://bugs.eclipse.org/bugs/show_bug.cgi?id=566936

+ *

+ */

+public class Bug566936TreeViewerTest {

+

+	public static boolean flag = true;

+

+	private class MyModel {

+		public int counter;

+

+		public MyModel(int counter) {

+			this.counter = counter;

+		}

+

+		@Override

+		public String toString() {

+			return "Item " + this.counter;

+		}

+	}

+

+	private class MyEditingSupport extends EditingSupport {

+

+		private String property;

+

+		public MyEditingSupport(ColumnViewer viewer, String property) {

+			super(viewer);

+			this.property = property;

+		}

+

+		@Override

+		protected CellEditor getCellEditor(Object element) {

+			return new TextCellEditor((Composite) getViewer().getControl());

+		}

+

+		@Override

+		protected boolean canEdit(Object element) {

+			return true;

+		}

+

+		@Override

+		protected Object getValue(Object element) {

+			return "Column " + property + " => " + element;

+		}

+

+		@Override

+		protected void setValue(Object element, Object value) {

+

+		}

+

+	}

+

+	private class MyColumnLabelProvider extends ColumnLabelProvider implements ITreeContentProvider {

+

+		public MyColumnLabelProvider(Tree tree, int columnIndex) {

+			super();

+			this.tree = tree;

+			this.columnIndex = columnIndex;

+		}

+

+		private int columnIndex;

+		private Tree tree;

+

+		@Override

+		public String getText(Object element) {

+			return "Column " + tree.getColumnOrder()[columnIndex] + " => " + element;

+		}

+

+		@SuppressWarnings("rawtypes")

+		@Override

+		public Object[] getElements(Object inputElement) {

+			if (inputElement instanceof List) {

+				return ((List) inputElement).toArray();

+			}

+			return new Object[0];

+		}

+

+		@Override

+		public Object[] getChildren(Object parentElement) {

+			return new Object[0];

+		}

+

+		@Override

+		public Object getParent(Object element) {

+			return new Object[0];

+		}

+

+		@Override

+		public boolean hasChildren(Object element) {

+			return true;

+		}

+	}

+

+	public Bug566936TreeViewerTest(Shell shell) {

+		final TreeViewer v = new TreeViewer(shell, SWT.BORDER | SWT.FULL_SELECTION);

+		v.setContentProvider(new MyColumnLabelProvider(v.getTree(), 0));

+

+		TreeViewerFocusCellManager focusCellManager = new TreeViewerFocusCellManager(v,

+				new MyFocusBorderCellHighlighter(v)) {

+

+			@Override

+			public ViewerCell getFocusCell() {

+				ViewerCell cell = super.getFocusCell();

+

+				if (cell != null) {

+					return cell;

+				}

+

+				return v.getCell(new Point(5, 5));

+

+			}

+

+		};

+		ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(v) {

+			@Override

+			protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {

+				return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL

+						|| event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION

+						|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR)

+						|| event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;

+			}

+		};

+

+		int feature = ColumnViewerEditor.TABBING_HORIZONTAL | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR

+				| ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION;

+

+		TreeViewerEditor.create(v, focusCellManager, actSupport, feature);

+

+		String[] columLabels = { "Column 1", "Column 2", "Column 3", "Col 4", "Col 5", "Col 6", "Col 7", "Col 8",

+				"Col 9", "Col 10", "Col 11", "Col 12" };

+		int property = 0;

+		for (String label : columLabels) {

+			createColumnFor(v, label, property++);

+		}

+

+		List<MyModel> model = createModel();

+

+		v.setInput(model);

+		v.setSelection(new StructuredSelection(model.get(0)));

+		v.getTree().setLinesVisible(true);

+		v.getTree().setHeaderVisible(true);

+		v.getTree().setFocus();

+	}

+

+	private void createColumnFor(TreeViewer v, String label, int columnIndex) {

+

+		TreeViewerColumn viewerColumn = new TreeViewerColumn(v, SWT.NONE, columnIndex);

+		viewerColumn.getColumn().setWidth(300);

+		viewerColumn.getColumn().setMoveable(true);

+		viewerColumn.getColumn().setText(label);

+		viewerColumn.getColumn().setResizable(true);

+

+		viewerColumn.setEditingSupport(new MyEditingSupport(v, columnIndex + ""));

+		viewerColumn.setLabelProvider(new MyColumnLabelProvider(v.getTree(), columnIndex));

+	}

+

+	private List<MyModel> createModel() {

+		List<MyModel> elements = new ArrayList<>();

+

+		for (int i = 0; i < 10; i++) {

+			elements.add(new MyModel(i));

+		}

+		return elements;

+	}

+

+	/**

+	 * @param args

+	 */

+	public static void main(String[] args) {

+		Display display = new Display();

+

+		Shell shell = new Shell(display);

+		shell.setLayout(new FillLayout());

+		new Bug566936TreeViewerTest(shell);

+		shell.open();

+

+		while (!shell.isDisposed()) {

+			if (!display.readAndDispatch()) {

+				display.sleep();

+			}

+		}

+		display.dispose();

+	}

+

+}

+

+class MyFocusBorderCellHighlighter extends FocusCellHighlighter {

+

+	/**

+	 * @param viewer the viewer

+	 */

+	public MyFocusBorderCellHighlighter(ColumnViewer viewer) {

+		super(viewer);

+		hookListener(viewer);

+	}

+

+	private static void markFocusedCell(Event event) {

+		GC gc = event.gc;

+

+		Rectangle rect = event.getBounds();

+		gc.drawFocus(rect.x, rect.y, rect.width, rect.height);

+

+		event.detail &= ~SWT.SELECTED;

+	}

+

+	private static void removeSelectionInformation(ViewerCell cell) {

+

+		if (cell != null) {

+			Rectangle rect = cell.getBounds();

+			int x = cell.getColumnIndex() == 0 ? 0 : rect.x;

+			int width = cell.getColumnIndex() == 0 ? rect.x + rect.width : rect.width;

+			cell.getControl().redraw(x, rect.y, width, rect.height, true);

+		}

+

+	}

+

+	private void hookListener(final ColumnViewer viewer) {

+

+		Listener listener = event -> {

+			if ((event.detail & SWT.SELECTED) > 0) {

+				ViewerCell focusCell = getFocusCell();

+				if (focusCell == null) {

+					return;

+				}

+				ViewerRow row = focusCell.getViewerRow();

+

+				Assert.isNotNull(row, "Internal structure invalid. Item without associated row is not possible."); //$NON-NLS-1$

+

+				ViewerCell cell = row.getCell(event.index);

+

+				if (!cell.equals(focusCell)) {

+					removeSelectionInformation(cell);

+				} else {

+					markFocusedCell(event);

+				}

+			}

+		};

+		viewer.getControl().addListener(SWT.EraseItem, listener);

+	}

+

+	/**

+	 * @param cell the cell which is colored

+	 * @return the color

+	 */

+	protected Color getSelectedCellBackgroundColor(ViewerCell cell) {

+		return null;

+	}

+

+	/**

+	 * @param cell the cell which is colored

+	 * @return the color

+	 */

+	protected Color getSelectedCellForegroundColor(ViewerCell cell) {

+		return null;

+	}

+

+	@Override

+	protected void focusCellChanged(ViewerCell newCell, ViewerCell oldCell) {

+

+		// Redraw new area

+		if (newCell != null) {

+			Rectangle rect = newCell.getBounds();

+			int x = newCell.getColumnIndex() == 0 ? 0 : rect.x;

+			int width = newCell.getColumnIndex() == 0 ? rect.x + rect.width : rect.width;

+			newCell.getControl().redraw(x, rect.y, width, rect.height, true);

+		}

+

+		if (oldCell != null) {

+			Rectangle rect = oldCell.getBounds();

+			int x = oldCell.getColumnIndex() == 0 ? 0 : rect.x;

+			int width = oldCell.getColumnIndex() == 0 ? rect.x + rect.width : rect.width;

+			oldCell.getControl().redraw(x, rect.y, width, rect.height, true);

+		}

+

+	}

+}
\ No newline at end of file