Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 167325 | Differences between
and this patch

Collapse All | Expand All

(-)Eclipse (+222 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 Tom Schindl and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     Tom Schindl - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.jface.snippets.viewers;
13
14
import java.util.ArrayList;
15
16
import org.eclipse.jface.resource.FontRegistry;
17
import org.eclipse.jface.viewers.CellEditor;
18
import org.eclipse.jface.viewers.EditingSupport;
19
import org.eclipse.jface.viewers.ICellModifier;
20
import org.eclipse.jface.viewers.ITableLabelProvider;
21
import org.eclipse.jface.viewers.ITreeContentProvider;
22
import org.eclipse.jface.viewers.LabelProvider;
23
import org.eclipse.jface.viewers.TextCellEditor;
24
import org.eclipse.jface.viewers.TreeViewer;
25
import org.eclipse.jface.viewers.Viewer;
26
import org.eclipse.swt.SWT;
27
import org.eclipse.swt.graphics.Image;
28
import org.eclipse.swt.layout.FillLayout;
29
import org.eclipse.swt.widgets.Display;
30
import org.eclipse.swt.widgets.Shell;
31
import org.eclipse.swt.widgets.TreeColumn;
32
import org.eclipse.swt.widgets.TreeItem;
33
34
/**
35
 * A simple TreeViewer to demonstrate usage
36
 * 
37
 * @author Tom Schindl <tom.schindl@bestsolution.at>
38
 * 
39
 */
40
public class Snippet026TreeViewerTabEditing {
41
	private class MyContentProvider implements ITreeContentProvider {
42
43
		/*
44
		 * (non-Javadoc)
45
		 * 
46
		 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
47
		 */
48
		public Object[] getElements(Object inputElement) {
49
			return ((MyModel) inputElement).child.toArray();
50
		}
51
52
		/*
53
		 * (non-Javadoc)
54
		 * 
55
		 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
56
		 */
57
		public void dispose() {
58
59
		}
60
61
		/*
62
		 * (non-Javadoc)
63
		 * 
64
		 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
65
		 *      java.lang.Object, java.lang.Object)
66
		 */
67
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
68
69
		}
70
71
		/*
72
		 * (non-Javadoc)
73
		 * 
74
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
75
		 */
76
		public Object[] getChildren(Object parentElement) {
77
			return getElements(parentElement);
78
		}
79
80
		/*
81
		 * (non-Javadoc)
82
		 * 
83
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
84
		 */
85
		public Object getParent(Object element) {
86
			if (element == null) {
87
				return null;
88
			}
89
90
			return ((MyModel) element).parent;
91
		}
92
93
		/*
94
		 * (non-Javadoc)
95
		 * 
96
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
97
		 */
98
		public boolean hasChildren(Object element) {
99
			return ((MyModel) element).child.size() > 0;
100
		}
101
102
	}
103
104
	public class MyModel {
105
		public MyModel parent;
106
107
		public ArrayList child = new ArrayList();
108
109
		public int counter;
110
111
		public MyModel(int counter, MyModel parent) {
112
			this.parent = parent;
113
			this.counter = counter;
114
		}
115
116
		public String toString() {
117
			String rv = "Item ";
118
			if (parent != null) {
119
				rv = parent.toString() + ".";
120
			}
121
122
			rv += counter;
123
124
			return rv;
125
		}
126
	}
127
128
	public class MyLabelProvider extends LabelProvider implements
129
			ITableLabelProvider {
130
		FontRegistry registry = new FontRegistry();
131
132
		public Image getColumnImage(Object element, int columnIndex) {
133
			return null;
134
		}
135
136
		public String getColumnText(Object element, int columnIndex) {
137
			return "Column " + columnIndex + " => " + element.toString();
138
		}
139
	}
140
141
	public Snippet026TreeViewerTabEditing(Shell shell) {
142
		final TreeViewer v = new TreeViewer(shell,SWT.BORDER|SWT.FULL_SELECTION);
143
		
144
		TreeColumn column = new TreeColumn(v.getTree(),SWT.NONE);
145
		column.setWidth(200);
146
		column.setText("Column 1");
147
		
148
		column = new TreeColumn(v.getTree(),SWT.NONE);
149
		column.setWidth(200);
150
		column.setText("Column 2");
151
		
152
		v.setLabelProvider(new MyLabelProvider());
153
		v.setContentProvider(new MyContentProvider());
154
		v.setCellModifier(new ICellModifier() {
155
156
			/* (non-Javadoc)
157
			 * @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object, java.lang.String)
158
			 */
159
			public boolean canModify(Object element, String property) {
160
				return true;
161
			}
162
163
			/* (non-Javadoc)
164
			 * @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object, java.lang.String)
165
			 */
166
			public Object getValue(Object element, String property) {
167
				return ((MyModel)element).counter + "";
168
			}
169
170
			/* (non-Javadoc)
171
			 * @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object, java.lang.String, java.lang.Object)
172
			 */
173
			public void modify(Object element, String property, Object value) {
174
				TreeItem item = (TreeItem)element;
175
				((MyModel)item.getData()).counter = Integer.parseInt(value.toString());
176
				v.update(item.getData(), null);
177
			}
178
			
179
		});
180
		
181
		v.setColumnProperties(new String[] { "column1", "column2" });
182
		v.setCellEditors(new CellEditor[] { new TextCellEditor(v.getTree()), new TextCellEditor(v.getTree()) });
183
		v.setTabEditingStyle(EditingSupport.TABING_HORIZONTAL|EditingSupport.TABING_MOVE_TO_ROW_NEIGHBOR|EditingSupport.TABING_VERTICAL);
184
		
185
		v.setInput(createModel());
186
	}
187
188
	private MyModel createModel() {
189
190
		MyModel root = new MyModel(0, null);
191
		root.counter = 0;
192
193
		MyModel tmp;
194
		MyModel subItem;
195
		for (int i = 1; i < 10; i++) {
196
			tmp = new MyModel(i, root);
197
			root.child.add(tmp);
198
			for (int j = 1; j < i; j++) {
199
				subItem = new MyModel(j, tmp);
200
				subItem.child.add(new MyModel(j*100,subItem));
201
				tmp.child.add(subItem);
202
			}
203
		}
204
205
		return root;
206
	}
207
208
	public static void main(String[] args) {
209
		Display display = new Display();
210
		Shell shell = new Shell(display);
211
		shell.setLayout(new FillLayout());
212
		new Snippet026TreeViewerTabEditing(shell);
213
		shell.open();
214
215
		while (!shell.isDisposed()) {
216
			if (!display.readAndDispatch())
217
				display.sleep();
218
		}
219
220
		display.dispose();
221
	}
222
}
(-)src/org/eclipse/jface/viewers/TableViewerRow.java (+35 lines)
Lines 146-149 Link Here
146
		return item.getParent();
146
		return item.getParent();
147
	}
147
	}
148
148
149
	public ViewerRow getNeighbor(int direction, boolean sameLevel) {
150
		if( direction == ViewerRow.ABOVE ) {
151
			return getRowAbove(sameLevel);
152
		} else if( direction == ViewerRow.BELOW ) {
153
			return getRowBelow(sameLevel);
154
		} else {
155
			throw new IllegalArgumentException("The given direction argument is not known!"); //$NON-NLS-1$
156
		}
157
	}
158
159
	
160
	private ViewerRow getRowAbove(boolean sameLevel) {
161
		int index = item.getParent().indexOf(item) - 1;
162
		
163
		if( index >= 0 ) {
164
			return (ViewerRow)item.getParent().getItem(index).getData(ViewerRow.ROWPART_KEY); 
165
		}
166
		
167
		return null;
168
	}
169
170
	private ViewerRow getRowBelow(boolean sameLevel) {
171
		int index = item.getParent().indexOf(item) + 1;
172
		
173
		if( index < item.getParent().getItemCount() ) {
174
			TableItem tmp = item.getParent().getItem(index);
175
			//TODO NULL can happen in case of VIRTUAL => How do we deal with that
176
			if( tmp != null ) {
177
				return (ViewerRow)tmp.getData(ViewerRow.ROWPART_KEY);
178
			}
179
		}
180
		
181
		return null;
182
	}
183
149
}
184
}
(-)src/org/eclipse/jface/viewers/EditingSupport.java (-23 / +4 lines)
Lines 16-23 Link Here
16
import org.eclipse.core.runtime.Assert;
16
import org.eclipse.core.runtime.Assert;
17
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.events.TraverseEvent;
18
import org.eclipse.swt.events.TraverseEvent;
19
import org.eclipse.swt.graphics.Point;
20
import org.eclipse.swt.graphics.Rectangle;
21
19
22
/**
20
/**
23
 * EditingSupport is the abstract superclass of the support for cell editing.
21
 * EditingSupport is the abstract superclass of the support for cell editing.
Lines 184-192 Link Here
184
		ViewerRow newRow = null;
182
		ViewerRow newRow = null;
185
183
186
		if (above) {
184
		if (above) {
187
			newRow = getRowAbove(row, viewer);
185
			newRow = row.getNeighbor(ViewerRow.ABOVE, false);
188
		} else {
186
		} else {
189
			newRow = getRowBelow(row, viewer);
187
			newRow = row.getNeighbor(ViewerRow.BELOW,false);
190
		}
188
		}
191
189
192
		if (newRow != null) {
190
		if (newRow != null) {
Lines 228-234 Link Here
228
							startIndex);
226
							startIndex);
229
				}
227
				}
230
			} else if ((getTabingStyle() & TABING_MOVE_TO_ROW_NEIGHBOR) == TABING_MOVE_TO_ROW_NEIGHBOR) {
228
			} else if ((getTabingStyle() & TABING_MOVE_TO_ROW_NEIGHBOR) == TABING_MOVE_TO_ROW_NEIGHBOR) {
231
				ViewerRow rowAbove = getRowAbove(row, viewer);
229
				ViewerRow rowAbove = row.getNeighbor(ViewerRow.ABOVE,false);
232
				if (rowAbove != null) {
230
				if (rowAbove != null) {
233
					rv = searchPreviousCell(rowAbove, viewer, rowAbove
231
					rv = searchPreviousCell(rowAbove, viewer, rowAbove
234
							.getColumnCount(), startIndex);
232
							.getColumnCount(), startIndex);
Lines 261-267 Link Here
261
					rv = searchNextCell(row, viewer, -1, startIndex);
259
					rv = searchNextCell(row, viewer, -1, startIndex);
262
				}
260
				}
263
			} else if ((getTabingStyle() & TABING_MOVE_TO_ROW_NEIGHBOR) == TABING_MOVE_TO_ROW_NEIGHBOR) {
261
			} else if ((getTabingStyle() & TABING_MOVE_TO_ROW_NEIGHBOR) == TABING_MOVE_TO_ROW_NEIGHBOR) {
264
				ViewerRow rowBelow = getRowBelow(row, viewer);
262
				ViewerRow rowBelow = row.getNeighbor(ViewerRow.BELOW,false);
265
				if (rowBelow != null) {
263
				if (rowBelow != null) {
266
					rv = searchNextCell(rowBelow, viewer, -1, startIndex);
264
					rv = searchNextCell(rowBelow, viewer, -1, startIndex);
267
				}
265
				}
Lines 270-292 Link Here
270
268
271
		return rv;
269
		return rv;
272
	}
270
	}
273
274
	private ViewerRow getRowAbove(ViewerRow row, ColumnViewer viewer) {
275
		// TODO maybe there's a better solution maybe we should provide an
276
		// API in ViewerColumn
277
		// to find row above/below itself?
278
		Rectangle r = row.getBounds();
279
		return viewer.getViewerRow(new Point(r.x, r.y - 2));
280
	}
281
282
	private ViewerRow getRowBelow(ViewerRow row, ColumnViewer viewer) {
283
		// TODO maybe there's a better solution maybe we should provide an
284
		// API in ViewerColumn
285
		// to find row above/below itself?
286
		Rectangle r = row.getBounds();
287
		return viewer.getViewerRow(new Point(r.x,
288
				r.y + r.height + 2));
289
	}
290
	
271
	
291
	/**
272
	/**
292
	 * @return the viewer this editing support works for
273
	 * @return the viewer this editing support works for
(-)src/org/eclipse/jface/viewers/TreeViewerRow.java (+151 lines)
Lines 18-23 Link Here
18
import org.eclipse.swt.graphics.Rectangle;
18
import org.eclipse.swt.graphics.Rectangle;
19
import org.eclipse.swt.widgets.Control;
19
import org.eclipse.swt.widgets.Control;
20
import org.eclipse.swt.widgets.Item;
20
import org.eclipse.swt.widgets.Item;
21
import org.eclipse.swt.widgets.Tree;
21
import org.eclipse.swt.widgets.TreeItem;
22
import org.eclipse.swt.widgets.TreeItem;
22
23
23
/**
24
/**
Lines 144-147 Link Here
144
	public Control getControl() {
145
	public Control getControl() {
145
		return item.getParent();
146
		return item.getParent();
146
	}
147
	}
148
149
	
150
	public ViewerRow getNeighbor(int direction, boolean sameLevel) {
151
		if( direction == ViewerRow.ABOVE ) {
152
			return getRowAbove(sameLevel);
153
		} else if( direction == ViewerRow.BELOW ) {
154
			return getRowBelow(sameLevel);
155
		} else {
156
			throw new IllegalArgumentException("The given direction argument is not known!"); //$NON-NLS-1$
157
		}
158
	}
159
	
160
	private ViewerRow getRowBelow(boolean sameLevel) {
161
		Tree tree = item.getParent();
162
		
163
		// This means we have top-level item
164
		if( item.getParentItem() == null ) {
165
			if( sameLevel || ! item.getExpanded() ) {
166
				int index = tree.indexOf(item) + 1;
167
				
168
				if( index < tree.getItemCount() ) {
169
					return (ViewerRow)tree.getItem(index).getData(ViewerRow.ROWPART_KEY);
170
				}
171
			} else if( item.getExpanded() && item.getItemCount() > 0 ) {
172
				return (ViewerRow)item.getItem(0).getData(ViewerRow.ROWPART_KEY);
173
			}
174
		} else {
175
			if( sameLevel || ! item.getExpanded() ) {
176
				TreeItem parentItem = item.getParentItem();
177
				
178
				int nextIndex = parentItem.indexOf(item) + 1;
179
				int totalIndex = parentItem.getItemCount();
180
				
181
				TreeItem itemAfter;
182
				
183
				// This would mean that it was the last item
184
				if( nextIndex == totalIndex ) {
185
					itemAfter = findNextItem( parentItem );
186
				} else {
187
					itemAfter = parentItem.getItem(nextIndex);
188
				}
189
				
190
				if( itemAfter != null ) {
191
					return (ViewerRow) itemAfter.getData(ViewerRow.ROWPART_KEY);
192
				}
193
				
194
			} else if( item.getExpanded() && item.getItemCount() > 0 ) {
195
				return (ViewerRow)item.getItem(0).getData(ViewerRow.ROWPART_KEY);
196
			}
197
		}
198
199
		return null;
200
	}
201
	
202
	private ViewerRow getRowAbove(boolean sameLevel) {
203
		Tree tree = item.getParent();
204
		
205
		// This means we have top-level item
206
		if( item.getParentItem() == null ) {
207
			int index = tree.indexOf(item) - 1;
208
			TreeItem nextTopItem = null;
209
			
210
			if( index >= 0 ) {
211
				nextTopItem = tree.getItem(index);
212
			}
213
			
214
			if( nextTopItem != null ) {
215
				if( sameLevel ) {
216
					return (ViewerRow)nextTopItem.getData(ViewerRow.ROWPART_KEY);
217
				}
218
				
219
				return (ViewerRow) findLastVisibleItem(nextTopItem).getData(ViewerRow.ROWPART_KEY);
220
			}
221
		} else {
222
			TreeItem parentItem = item.getParentItem();
223
			int previousIndex = parentItem.indexOf(item) - 1;
224
			
225
			TreeItem itemBefore;
226
			if( previousIndex >= 0 ) {
227
				if( sameLevel ) {
228
					itemBefore = parentItem.getItem(previousIndex);
229
				} else {
230
					itemBefore = findLowestLeave(parentItem.getItem(previousIndex));
231
				}
232
			} else {
233
				itemBefore = parentItem;
234
			}
235
			
236
			if( itemBefore != null ) {
237
				return (ViewerRow) itemBefore.getData(ViewerRow.ROWPART_KEY);
238
			}
239
		}
240
		
241
		return null;
242
	}
243
244
	private TreeItem findLastVisibleItem(TreeItem parentItem) {
245
		TreeItem rv = parentItem;
246
		
247
		if( rv.getExpanded() && rv.getItemCount() > 0 ) {
248
			rv = findLastVisibleItem(rv.getItem(rv.getItemCount()-1));
249
		}
250
		
251
		return rv;
252
	}
253
	
254
	private TreeItem findLowestLeave(TreeItem item) {
255
		TreeItem rv = item;
256
		
257
		if( rv.getExpanded() && rv.getItemCount() > 0 ) {
258
			rv = findLowestLeave(rv.getItem(rv.getItemCount()-1));
259
		}
260
		
261
		return rv;
262
	}
263
	
264
	private TreeItem findNextItem(TreeItem item) {
265
		TreeItem rv = null;
266
		Tree tree = item.getParent();
267
		TreeItem parentItem = item.getParentItem();
268
		
269
		int nextIndex;
270
		int totalItems;
271
		
272
		if( parentItem == null ) {
273
			nextIndex = tree.indexOf(item) + 1;
274
			totalItems = tree.getItemCount();
275
		} else {
276
			nextIndex = parentItem.indexOf(item) + 1;
277
			totalItems = parentItem.getItemCount();
278
		}
279
		
280
		// This is once more the last item in the tree
281
		// Search on
282
		if( nextIndex == totalItems ) {
283
			if( item.getParentItem() != null ) {
284
				rv = findNextItem(item.getParentItem());
285
			}
286
		} else {
287
			if( parentItem == null ) {
288
				rv = tree.getItem(nextIndex);
289
			} else {
290
				rv = parentItem.getItem(nextIndex);
291
			}
292
		}
293
		
294
		return rv;
295
	}
296
	
297
	
147
}
298
}
(-)src/org/eclipse/jface/viewers/ViewerRow.java (-3 / +25 lines)
Lines 39-44 Link Here
39
	public static final String ROWPART_KEY = Policy.JFACE + ".ROWPART"; //$NON-NLS-1$
39
	public static final String ROWPART_KEY = Policy.JFACE + ".ROWPART"; //$NON-NLS-1$
40
40
41
	/**
41
	/**
42
	 * the cell above the current one
43
	 */
44
	public static final int ABOVE = 1;
45
46
	/**
47
	 * the cell below the current one;
48
	 */
49
	public static final int BELOW = 2;
50
51
	/**
42
	 * Create a new instance of the receiver.
52
	 * Create a new instance of the receiver.
43
	 * 
53
	 * 
44
	 * @param item
54
	 * @param item
Lines 176-187 Link Here
176
	 */
186
	 */
177
	public int getColumnIndex(Point point) {
187
	public int getColumnIndex(Point point) {
178
		int count = getColumnCount();
188
		int count = getColumnCount();
179
		
189
180
		// If there are no columns the column-index is 0
190
		// If there are no columns the column-index is 0
181
		if( count == 0 ) {
191
		if (count == 0) {
182
			return 0;
192
			return 0;
183
		}
193
		}
184
		
194
185
		for (int i = 0; i < count; i++) {
195
		for (int i = 0; i < count; i++) {
186
			if (getBounds(i).contains(point)) {
196
			if (getBounds(i).contains(point)) {
187
				return i;
197
				return i;
Lines 212-215 Link Here
212
	 */
222
	 */
213
	public abstract Control getControl();
223
	public abstract Control getControl();
214
224
225
	/**
226
	 * Get the neighbor of the row
227
	 * 
228
	 * @param direction
229
	 *            the direction {@link #BELOW} or {@link #ABOVE}
230
	 * 
231
	 * @param sameLevel
232
	 *            search at the samelevel
233
	 * @return the row above or <code>null</code>
234
	 */
235
	public abstract ViewerRow getNeighbor(int direction, boolean sameLevel);
236
215
}
237
}
(-)src/org/eclipse/jface/viewers/ViewerCell.java (+62 lines)
Lines 34-39 Link Here
34
	private ViewerRow row;
34
	private ViewerRow row;
35
35
36
	/**
36
	/**
37
	 * The direction pointing to the row above the current cell
38
	 */
39
	public int ABOVE = 1;
40
41
	/**
42
	 * The direction pointing to the row below the current cell
43
	 */
44
	public int BELOW = 1 << 1;
45
46
	/**
47
	 * The direction pointing to the left of the current cell
48
	 */
49
	public int LEFT = 1 << 2;
50
51
	/**
52
	 * The direction pointing to the right of the current cell
53
	 */
54
	public int RIGHT = 1 << 3;
55
56
	/**
37
	 * Create a new instance of the receiver on the row.
57
	 * Create a new instance of the receiver on the row.
38
	 * 
58
	 * 
39
	 * @param row
59
	 * @param row
Lines 177-180 Link Here
177
	public Control getControl() {
197
	public Control getControl() {
178
		return row.getControl();
198
		return row.getControl();
179
	}
199
	}
200
201
	/**
202
	 * This method provides access to all cells who are neighbors of the
203
	 * current-cell by passing the appropriate coordinadate constant. You can
204
	 * even access cell e.g. to the upper-left of the current cell by passing a
205
	 * bitmask like {@link #ABOVE} | {@link #LEFT}
206
	 * 
207
	 * @param directionMask
208
	 *            the direction mask used to identify the requested cell
209
	 * @param sameLevel
210
	 *            should we stay at the samelevel (this only has an effect for
211
	 *            viewers organized as trees)
212
	 * @return the cell or <code>null</code>
213
	 */
214
	public ViewerCell getNeighbor(int directionMask, boolean sameLevel) {
215
		ViewerRow row;
216
		int columnIndex;
217
218
		if ((directionMask & ABOVE) == ABOVE) {
219
			row = this.row.getNeighbor(ViewerRow.ABOVE, sameLevel);
220
		} else if ((directionMask & BELOW) == BELOW) {
221
			row = this.row.getNeighbor(ViewerRow.BELOW, sameLevel);
222
		} else {
223
			row = this.row;
224
		}
225
226
		if (row != null) {
227
			if ((directionMask & LEFT) == LEFT) {
228
				columnIndex = getColumnIndex() - 1;
229
			} else if ((directionMask & RIGHT) == RIGHT) {
230
				columnIndex = getColumnIndex() + 1;
231
			} else {
232
				columnIndex = getColumnIndex();
233
			}
234
235
			if (columnIndex >= 0 && columnIndex < row.getColumnCount()) {
236
				return row.getCell(columnIndex);
237
			}
238
		}
239
240
		return null;
241
	}
180
}
242
}

Return to bug 167325