Bug 197787 - [Viewers] wrong cell editor activated after table refresh
Summary: [Viewers] wrong cell editor activated after table refresh
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.3   Edit
Hardware: PC Windows XP
: P3 normal with 1 vote (vote)
Target Milestone: 3.4 M7   Edit
Assignee: Thomas Schindl CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-07-25 09:13 EDT by sibylle.duerr CLA
Modified: 2008-04-30 09:39 EDT (History)
4 users (show)

See Also:
tom.schindl: review? (bokowski)


Attachments
snippet to demonstrate the bug (14.53 KB, application/octet-stream)
2007-07-25 09:16 EDT, sibylle.duerr CLA
no flags Details
and here's fix (2.02 KB, patch)
2007-07-25 09:56 EDT, Thomas Schindl CLA
no flags Details | Diff
now a real fix (3.29 KB, patch)
2007-07-25 11:38 EDT, Thomas Schindl CLA
no flags Details | Diff
Too much things commented (3.26 KB, patch)
2007-07-25 11:40 EDT, Thomas Schindl CLA
no flags Details | Diff
Example for the reflection approach (14.60 KB, text/plain)
2007-07-26 10:47 EDT, Thomas Schindl CLA
no flags Details
Patch (2.05 KB, patch)
2007-08-21 13:55 EDT, Thomas Schindl CLA
no flags Details | Diff
mylyn/context/zip (928 bytes, application/octet-stream)
2007-08-21 13:55 EDT, Thomas Schindl CLA
no flags Details
apply to HEAD (2.58 KB, patch)
2008-02-20 12:53 EST, Thomas Schindl CLA
no flags Details | Diff
Test snippet (11.64 KB, text/x-java)
2008-04-11 06:12 EDT, Thomas Schindl CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description sibylle.duerr CLA 2007-07-25 09:13:29 EDT
Build ID: I20070625-1500

Steps To Reproduce:
to demonstrate the problem I have modified Snippet040TableViewerSorting. for example click on "Tod" and enter the editor. change the name to "zebra" and press enter. the items are rearranged due to a table.refresh() (not really necessary at this point but makes it easier to demonstrate the problem). now press enter again and see the strange behavior (the wrong editor (at the previous item position) is activated with the "correct" content).

The modified Snippet:
package org.eclipse.swt.snippets;

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.IStructuredContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TableViewerEditor;
import org.eclipse.jface.viewers.TableViewerFocusCellManager;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerRow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
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.TableItem;

import com.swtdesigner.SWTResourceManager;

/**
 * Example usage of ViewerComparator in tables to allow sorting
 * 
 * @author Tom Schindl <tom.schindl@bestsolution.at>
 * 
 */
public class Snippet040TableViewerSorting {

	private class MyContentProvider implements IStructuredContentProvider {

		public Object[] getElements(Object inputElement) {
			return (Person[]) inputElement;
		}

		public void dispose() {
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}

	}

	public class Person {
		public String givenname;
		public String surname;
		public String email;

		public Person(String givenname, String surname, String email) {
			this.givenname = givenname;
			this.surname = surname;
			this.email = email;
		}

	}

	protected abstract class AbstractEditingSupport extends EditingSupport {
		private TextCellEditor editor;

		public AbstractEditingSupport(TableViewer viewer) {
			super(viewer);
			this.editor = new TextCellEditor(viewer.getTable());
		}

		protected boolean canEdit(Object element) {
			return true;
		}

		protected CellEditor getCellEditor(Object element) {
			return editor;
		}

		protected void setValue(Object element, Object value) {
			doSetValue(element, value);
			getViewer().update(element, null);
			
			TableViewer tableViewer = (TableViewer) getViewer();
			
			TableItem item = tableViewer.getTable().getItem(tableViewer.getTable().getSelectionIndex());
			Object obj = item.getData();
			
			// refresh table
			tableViewer.refresh();			
			
			// search for the item that has the object from the
			// previously selected item
			TableItem itemtoselect = null;
			TableItem[] items = tableViewer.getTable().getItems();
			for (TableItem it : items) {
				if (it.getData().equals(obj)) {
					itemtoselect = it;
				}
			}
			// select this item
			tableViewer.getTable().setSelection(itemtoselect);
		}

		protected abstract void doSetValue(Object element, Object value);
	}

	public Snippet040TableViewerSorting(Shell shell) {
		TableViewer v = new TableViewer(shell, SWT.BORDER | SWT.FULL_SELECTION);
		v.setContentProvider(new MyContentProvider());
		
		final TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(v, new EditableFocusCellHighlighter(v));
		ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(v) {
			protected boolean isEditorActivationEvent(
					ColumnViewerEditorActivationEvent event) {
				if ( event.sourceEvent instanceof KeyEvent && event.keyCode > 31 && event.keyCode < 127) {
					((KeyEvent)event.sourceEvent).doit=false;
				}
				
				return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
						|| event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
						|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode > 31 && event.keyCode < 127)
						|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR)
						|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == 16777296)
						|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.F2)
						|| event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
			}
		};

		TableViewerEditor.create(v, focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
				| ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
				| ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
		

		TableViewerColumn column = new TableViewerColumn(v, SWT.NONE);
		column.getColumn().setWidth(200);
		column.getColumn().setText("Givenname");
		column.getColumn().setMoveable(true);
		column.setLabelProvider(new ColumnLabelProvider() {

			public String getText(Object element) {
				return ((Person) element).givenname;
			}
		});

		column.setEditingSupport(new AbstractEditingSupport(v) {

			protected Object getValue(Object element) {
				return ((Person) element).givenname;
			}

			protected void doSetValue(Object element, Object value) {
				((Person) element).givenname = value.toString();
			}

		});
		
		ColumnViewerSorter cSorter = new ColumnViewerSorter(v,column) {

			protected int doCompare(Viewer viewer, Object e1, Object e2) {
				Person p1 = (Person) e1;
				Person p2 = (Person) e2;
				return p1.givenname.compareToIgnoreCase(p2.givenname);
			}
			
		};

		column = new TableViewerColumn(v, SWT.NONE);
		column.getColumn().setWidth(200);
		column.getColumn().setText("Surname");
		column.getColumn().setMoveable(true);
		column.setLabelProvider(new ColumnLabelProvider() {

			public String getText(Object element) {
				return ((Person) element).surname;
			}

		});

		column.setEditingSupport(new AbstractEditingSupport(v) {

			protected Object getValue(Object element) {
				return ((Person) element).surname;
			}

			protected void doSetValue(Object element, Object value) {
				((Person) element).surname = value.toString();
			}

		});
		
		new ColumnViewerSorter(v,column) {

			protected int doCompare(Viewer viewer, Object e1, Object e2) {
				Person p1 = (Person) e1;
				Person p2 = (Person) e2;
				return p1.surname.compareToIgnoreCase(p2.surname);
			}
			
		};

		column = new TableViewerColumn(v, SWT.NONE);
		column.getColumn().setWidth(200);
		column.getColumn().setText("E-Mail");
		column.getColumn().setMoveable(true);
		column.setLabelProvider(new ColumnLabelProvider() {

			public String getText(Object element) {
				return ((Person) element).email;
			}

		});

		column.setEditingSupport(new AbstractEditingSupport(v) {

			protected Object getValue(Object element) {
				return ((Person) element).email;
			}

			protected void doSetValue(Object element, Object value) {
				((Person) element).email = value.toString();
			}

		});
		
		new ColumnViewerSorter(v,column) {

			protected int doCompare(Viewer viewer, Object e1, Object e2) {
				Person p1 = (Person) e1;
				Person p2 = (Person) e2;
				return p1.email.compareToIgnoreCase(p2.email);
			}
			
		};

		Person[] model = createModel();
		v.setInput(model);
		v.getTable().setLinesVisible(true);
		v.getTable().setHeaderVisible(true);
		cSorter.setSorter(cSorter, ColumnViewerSorter.ASC);
	}

	private Person[] createModel() {
		Person[] elements = new Person[4];
		elements[0] = new Person("Tom", "Schindl",
				"tom.schindl@bestsolution.at");
		elements[1] = new Person("Boris", "Bokowski",
				"Boris_Bokowski@ca.ibm.com");
		elements[2] = new Person("Tod", "Creasey", "Tod_Creasey@ca.ibm.com");
		elements[3] = new Person("Wayne", "Beaton", "wayne@eclipse.org");

		return elements;
	}

	private static abstract class ColumnViewerSorter extends ViewerComparator {
		public static final int ASC = 1;
		
		public static final int NONE = 0;
		
		public static final int DESC = -1;
		
		private int direction = 0;
		
		private TableViewerColumn column;
		
		private ColumnViewer viewer;
		
		public ColumnViewerSorter(ColumnViewer viewer, TableViewerColumn column) {
			this.column = column;
			this.viewer = viewer;
			this.column.getColumn().addSelectionListener(new SelectionAdapter() {

				public void widgetSelected(SelectionEvent e) {
					if( ColumnViewerSorter.this.viewer.getComparator() != null ) {
						if( ColumnViewerSorter.this.viewer.getComparator() == ColumnViewerSorter.this ) {
							int tdirection = ColumnViewerSorter.this.direction;
							
							if( tdirection == ASC ) {
								setSorter(ColumnViewerSorter.this, DESC);
							} else if( tdirection == DESC ) {
								setSorter(ColumnViewerSorter.this, NONE);
							}
						} else {
							setSorter(ColumnViewerSorter.this, ASC);
						}
					} else {
						setSorter(ColumnViewerSorter.this, ASC);
					}
				}
			});
		}
		
		public void setSorter(ColumnViewerSorter sorter, int direction) {
			if( direction == NONE ) {
				column.getColumn().getParent().setSortColumn(null);
				column.getColumn().getParent().setSortDirection(SWT.NONE);
				viewer.setComparator(null);
			} else {
				column.getColumn().getParent().setSortColumn(column.getColumn());
				sorter.direction = direction;
				
				if( direction == ASC ) {
					column.getColumn().getParent().setSortDirection(SWT.DOWN);
				} else {
					column.getColumn().getParent().setSortDirection(SWT.UP);
				}
				
				if( viewer.getComparator() == sorter ) {
					viewer.refresh();
				} else {
					viewer.setComparator(sorter);
				}
				
			}
		}

		public int compare(Viewer viewer, Object e1, Object e2) {
			return direction * doCompare(viewer, e1, e2);
		}
		
		protected abstract int doCompare(Viewer viewer, Object e1, Object e2);
	}
	
	private class EditableFocusCellHighlighter extends FocusCellHighlighter {
		private ViewerCell oldCell;

		/**
		 * @param viewer
		 *            the viewer
		 */
		public EditableFocusCellHighlighter(ColumnViewer viewer) {
			super(viewer);
			hookListener(viewer);
		}

		private void markFocusedCell(Event event, ViewerCell cell) {
			GC gc = event.gc;

			gc.setBackground(SWTResourceManager.getColor(255, 255, 255));
			gc.setForeground(SWTResourceManager.getColor(0, 0, 0));
			gc.setLineWidth(4);
			int currentCol = event.index;
			Rectangle rect = ((TableItem)event.item).getBounds(currentCol);
			gc.drawRectangle(rect);

			event.detail &= ~SWT.FOCUSED;
			event.detail &= SWT.FocusOut;
			event.detail &= ~SWT.SELECTED;
		}

		private void removeSelectionInformation(Event event, ViewerCell cell) {

		}

		private void hookListener(final ColumnViewer viewer) {

			Listener listener = new Listener() {

				public void handleEvent(Event event) {
					if ((event.detail & SWT.SELECTED) > 0) {
						ViewerCell focusCell = getFocusCell();
						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 (focusCell == null || !cell.equals(focusCell)) {
							removeSelectionInformation(event, cell);
						} else {
							markFocusedCell(event, cell);
						}
					}
				}

			};
			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;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.viewers.FocusCellHighlighter#focusCellChanged(org.eclipse.jface.viewers.ViewerCell)
		 */
		protected void focusCellChanged(ViewerCell cell) {
			super.focusCellChanged(cell);

			// Redraw new area
			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;
				// 1 is a fix for Linux-GTK
				cell.getControl().redraw(x, rect.y-1, width, rect.height+1, 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;
				// 1 is a fix for Linux-GTK
				oldCell.getControl().redraw(x, rect.y-1, width, rect.height+1, true);
			}

			this.oldCell = cell;
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Display display = new Display();

		Shell shell = new Shell(display);
		shell.setLayout(new FillLayout());
		new Snippet040TableViewerSorting(shell);
		shell.open();

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}

		display.dispose();

	}

}
Comment 1 sibylle.duerr CLA 2007-07-25 09:16:58 EDT
Created attachment 74555 [details]
snippet to demonstrate the bug

the snippet copy-pasted above here also as an attachment.
Comment 2 Thomas Schindl CLA 2007-07-25 09:52:40 EDT
moving to UI and assign to me
Comment 3 Thomas Schindl CLA 2007-07-25 09:56:24 EDT
Created attachment 74561 [details]
and here's fix

the problem is that we are not updating the focus cell appropiately when the selection is changed using StrucutureViewer#setSelection(). Please note that Control#setSelection() can never work because this won't give us the required events.
Comment 4 Thomas Schindl CLA 2007-07-25 10:07:36 EDT
If you need a workaround you can call: tableViewer.editElement(element, 0) after having refresh() the viewer this is the only method I can think of currently fixing the problem. This way you can even keep the editor in editing mode if you put this into a asyncExec call:

protected void setValue(final Object element, Object value) {
    doSetValue(element, value);
    getViewer().update(element, null);

    final TableViewer tableViewer = (TableViewer) getViewer();
    tableViewer.refresh();
    
    Display.getCurrent().asyncExec(new Runnable() {
        public void run() {
	    tableViewer.editElement(element, 0);
	}
    });
}

Another thing which might not be a bad idea is that you do the refresh() not in the setValue-method but add a ColumnViewerEditorActivationListener listener to your ColumnViewerEditor and do the refresh there. You might not need a async-call then.
Comment 5 Thomas Schindl CLA 2007-07-25 10:49:02 EDT
Comment on attachment 74561 [details]
and here's fix

not appropriate need to redesign :-(
Comment 6 Thomas Schindl CLA 2007-07-25 11:38:58 EDT
Created attachment 74580 [details]
now a real fix

The problem when we want to fix this SWTFocusCellManager is that we are not informed about selection changes (at the SWT-Level) which occur when we are resorting. Boris is this a 3.3.1 candidate?
Comment 7 Thomas Schindl CLA 2007-07-25 11:40:47 EDT
Created attachment 74581 [details]
Too much things commented
Comment 8 sibylle.duerr CLA 2007-07-26 04:32:41 EDT
As a workaround for me, I changed the isEditorActivationEvent(ColumnViewerEditorActivationEvent) a bit:

		ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(v) {
			protected boolean isEditorActivationEvent(
					ColumnViewerEditorActivationEvent event) {
				if ( event.sourceEvent instanceof KeyEvent && event.keyCode > 31 && event.keyCode < 127) {
					((KeyEvent)event.sourceEvent).doit=false;
				}
				
				if ((event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR)
						|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == 16777296)
						|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.F2)
						|| (event.sourceEvent instanceof KeyEvent && event.keyCode > 31 && event.keyCode < 127)
						|| (event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL))
				{
					int index = ((ViewerCell)event.getSource()).getColumnIndex();
					v.editElement(((ViewerCell)event.getSource()).getElement(), index);
				}
				
				return event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
						|| event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
			}
		};

The only problem I have with this is the activation of the editor now does not get the KeyPressed Event so I don't know in my own implementation of the CellEditor what key is pressed. I needed this to get the character of the KeyEvent and put it in the editor as well. But I don't see how to solve this at the moment.
Comment 9 Thomas Schindl CLA 2007-07-26 04:48:21 EDT
Why not using the code i showed you. This way the ViewerCell is updated correctly the draw back is that your editor is activated for a short time but you can solve this by setting the editor edit mode to false for a short time probably. 

I admit it is not ideal because when ever you update a selection using (viewer#setSelection()) you have to append a call to viewer#editElement(). I hope we can fix this for 3.3.1 although I can't promise it.
Comment 10 sibylle.duerr CLA 2007-07-26 05:26:31 EDT
(In reply to comment #9)
> Why not using the code i showed you. This way the ViewerCell is updated
> correctly the draw back is that your editor is activated for a short time but
> you can solve this by setting the editor edit mode to false for a short time
> probably. 
With your code from above the editor is always active. That's why I was looking for an other solution. Can you tell me how to set the edit mode to false for a short time? I don't see how to do this at the moment. 
 
> I admit it is not ideal because when ever you update a selection using
> (viewer#setSelection()) you have to append a call to viewer#editElement(). I
> hope we can fix this for 3.3.1 although I can't promise it.
With my solution I don't have to call viewer#editElement() all the time. But it has other drawbacks. And we can't wait till 3.3.1 or later.
Comment 11 Thomas Schindl CLA 2007-07-26 05:45:53 EDT
Hm. Setting the editor none editable is not possible because then the update is not happening! The only work-around currently is:

-------------8<-------------
protected void saveCellEditorValue(CellEditor cellEditor, ViewerCell cell) {
    super.saveCellEditorValue(cellEditor, cell);

    TableViewer tableViewer = (TableViewer) getViewer();
    tableViewer.refresh();
    tableViewer.editElement(cell.getElement(), cell.getColumnIndex());
}
-------------8<-------------

You are relying on internals here that the editor is not activated and this might break in a future version! So once we fixed the problem I would advice you to remove this workaround or somehow wrap it in an IF-Clause.
Comment 12 sibylle.duerr CLA 2007-07-26 06:23:13 EDT
Thanks for your help, but I think this does not really help. It does not solve the same problem when re-sorting the table. And with my own CellEditor (TableCellEditor) that is the same as TextCellEditor but has an activate(ColumnViewerEditorActivationEvent) (and does not set text.selectAll() in doSetFocus()) this ends in an endless loop.

    // TableCellEditor#activate(ColumnViewerEditorActivationEvent)
    public void activate(ColumnViewerEditorActivationEvent event) {
    	if (event.keyCode > 31 && event.keyCode < 127) {
	    	text.setText(event.character+text.getText());
	    	text.setSelection(1);
    	}
    }
Comment 13 Thomas Schindl CLA 2007-07-26 07:06:26 EDT
Another possibility is that you Subclass TableViewerFocusCellManager and do what the fix does. To access som of the methods you of course need Reflection but this should work and the performance hit is not too big because the methods you need reflection for are part of the last if block.
Comment 14 Thomas Schindl CLA 2007-07-26 09:18:18 EDT
One more note on this I still have the feeling that we have to provide a ListenerAPI for Viewers where they can inform interested parties about:
- refresh
- resort
- filter
- ....

And we definately need an API to set the selected cell from the out-side just like StructuredSelection for rows. This is somehow related to bug #151377.
Comment 15 sibylle.duerr CLA 2007-07-26 10:10:49 EDT
(In reply to comment #13)
> Another possibility is that you Subclass TableViewerFocusCellManager and do
> what the fix does. To access som of the methods you of course need Reflection
> but this should work and the performance hit is not too big because the methods
> you need reflection for are part of the last if block.
> 

sounds good. I like to do this, but I don't know much about reflection. So I don't really see how to do this. Can you help me again?
Comment 16 Thomas Schindl CLA 2007-07-26 10:47:01 EDT
Created attachment 74695 [details]
Example for the reflection approach

!!!!!!!!! ATTENTION !!!!!!!!!
I haven't put too much thought into the algorithm to find methods you should query them in a loop and find the right one. This also relies on implementation details (method names which are not API) and might break in future versions.
!!!!!!!!! ATTENTION !!!!!!!!!
Comment 17 Thomas Schindl CLA 2007-08-21 13:55:02 EDT
Created attachment 76566 [details]
Patch

without commented parts
Comment 18 Thomas Schindl CLA 2007-08-21 13:55:04 EDT
Created attachment 76567 [details]
mylyn/context/zip
Comment 19 Thomas Schindl CLA 2007-12-12 14:43:06 EST
missed the M4 cut
Comment 20 Thomas Schindl CLA 2008-01-30 12:44:28 EST
This is also ready for review. It fixes the problem but we should really think about some listener-API for structural Viewer-changes (refresh/filter/sort)
Comment 21 Thomas Schindl CLA 2008-02-20 12:53:48 EST
Created attachment 90220 [details]
apply to HEAD
Comment 22 Pavel Sklenak CLA 2008-02-23 07:33:04 EST
Thanks for idea shown here (attachment 74695 [details]). I have problem with loosing focused cell after setInput (my way how to do refresh with ILazyContentProvider). I can restore selection, but whole line is selected instead of cell.
So I added following code fixing my problem:

public ViewerCell getFocusCell() {
			ViewerCell cell = super.getFocusCell();
			Table t = viewer.getTable();
....

	if(cell == null && t.getSelection().length > 0) {
             //choose cell from selection
        }
Comment 23 Thomas Schindl CLA 2008-03-27 03:16:52 EDT
maybe we could and internal methods people could call using reflection because API freeze is gone, I'm sorry we missed this for M6
Comment 24 Thomas Schindl CLA 2008-04-11 06:12:07 EDT
Created attachment 95656 [details]
Test snippet
Comment 25 Thomas Schindl CLA 2008-04-11 06:12:29 EDT
Boris?
Comment 26 Boris Bokowski CLA 2008-04-25 11:15:41 EDT
+1
Comment 27 Thomas Schindl CLA 2008-04-27 16:26:19 EDT
released to CVS-HEAD >= 20080427
Comment 28 Thomas Schindl CLA 2008-04-27 16:29:30 EDT
There's still a problem which is common to all viewers who get resorted because the focus indicator is not fixed but entering bugs is not possible ATM
Comment 29 Thomas Schindl CLA 2008-04-30 09:37:12 EDT
Filed new bug 229613 for the Focus-Indicator problem 
Comment 30 Thomas Schindl CLA 2008-04-30 09:39:07 EDT
verified in I20080430 by running the attached snippet