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 144260 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/jface/tests/databinding/scenarios/TableScenarios.java (-36 / +110 lines)
Lines 16-27 Link Here
16
import org.eclipse.jface.examples.databinding.model.SampleData;
16
import org.eclipse.jface.examples.databinding.model.SampleData;
17
import org.eclipse.jface.internal.databinding.provisional.description.Property;
17
import org.eclipse.jface.internal.databinding.provisional.description.Property;
18
import org.eclipse.jface.internal.databinding.provisional.description.TableModelDescription;
18
import org.eclipse.jface.internal.databinding.provisional.description.TableModelDescription;
19
import org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerEditorManager;
19
import org.eclipse.jface.viewers.ITableLabelProvider;
20
import org.eclipse.jface.viewers.ITableLabelProvider;
21
import org.eclipse.jface.viewers.StructuredSelection;
20
import org.eclipse.jface.viewers.TableViewer;
22
import org.eclipse.jface.viewers.TableViewer;
23
import org.eclipse.jface.viewers.TextCellEditor;
21
import org.eclipse.swt.SWT;
24
import org.eclipse.swt.SWT;
22
import org.eclipse.swt.graphics.Image;
25
import org.eclipse.swt.graphics.Image;
23
import org.eclipse.swt.layout.FillLayout;
26
import org.eclipse.swt.layout.FillLayout;
27
import org.eclipse.swt.widgets.Event;
24
import org.eclipse.swt.widgets.TableColumn;
28
import org.eclipse.swt.widgets.TableColumn;
29
import org.eclipse.swt.widgets.Text;
25
30
26
/**
31
/**
27
 * To run the tests in this class, right-click and select "Run As JUnit Plug-in
32
 * To run the tests in this class, right-click and select "Run As JUnit Plug-in
Lines 112-117 Link Here
112
		}
117
		}
113
	}
118
	}
114
119
120
	public void testEditColumnWithTextCellEditor() throws Exception {
121
		TableModelDescription description = new TableModelDescription(
122
				new Property(catalog, "accounts", Account.class, Boolean.TRUE),
123
				new String[] { "firstName", "lastName" });
124
125
		getDbc().bind(tableViewer, description, null);
126
127
		TableViewerEditorManager manager = new TableViewerEditorManager(
128
				tableViewer, description, getDbc());
129
		TextCellEditor editor = new TextCellEditor();
130
		manager.bind(editor, "firstName", String.class, null);
131
132
		Account account = catalog.getAccounts()[0];
133
		String originalValue = account.getFirstName();
134
135
		tableViewer.editElement(account, 0);
136
		assertEquals(account,
137
				((StructuredSelection) tableViewer.getSelection())
138
						.getFirstElement());
139
140
		String newValue = editor.getValue().toString() + ","
141
				+ editor.getValue().toString();
142
		editor.setValue(newValue);
143
144
		// Value shouldn't yet change
145
		assertEquals(originalValue, account.getFirstName());
146
147
		getShell().open();
148
149
		// Apply value
150
		Text text = (Text) editor.getControl();
151
		Event event = new Event();
152
		event.detail = SWT.TRAVERSE_RETURN;
153
		text.notifyListeners(SWT.Traverse, event);
154
		tableViewer.getTable().setFocus();
155
156
		assertEquals(newValue, account.getFirstName());
157
	}
158
159
	public void testCancelEditOfTextCellEditor() throws Exception {
160
		TableModelDescription description = new TableModelDescription(
161
				new Property(catalog, "accounts", Account.class, Boolean.TRUE),
162
				new String[] { "firstName", "lastName" });
163
164
		getDbc().bind(tableViewer, description, null);
165
166
		TableViewerEditorManager manager = new TableViewerEditorManager(
167
				tableViewer, description, getDbc());
168
		TextCellEditor editor = new TextCellEditor();
169
		manager.bind(editor, "firstName", String.class, null);
170
171
		Account account = catalog.getAccounts()[0];
172
		String originalValue = account.getFirstName();
173
174
		tableViewer.editElement(account, 0);
175
		assertEquals(account,
176
				((StructuredSelection) tableViewer.getSelection())
177
						.getFirstElement());
178
179
		String newValue = editor.getValue().toString() + ","
180
				+ editor.getValue().toString();
181
		editor.setValue(newValue);
182
183
		// Value shouldn't yet change
184
		assertEquals(originalValue, account.getFirstName());
185
186
		// Aborts the edit
187
		tableViewer.getTable().setFocus();
188
189
		assertEquals(originalValue, account.getFirstName());
190
	}
191
115
	public void testScenario02() throws SecurityException, IllegalArgumentException {
192
	public void testScenario02() throws SecurityException, IllegalArgumentException {
116
		// Show that a TableViewer with three columns can be used to update
193
		// Show that a TableViewer with three columns can be used to update
117
		// columns
194
		// columns
Lines 135-141 Link Here
135
//		// Check whether the model has changed
212
//		// Check whether the model has changed
136
//		assertEquals("Bill",account.getFirstName());
213
//		assertEquals("Bill",account.getFirstName());
137
	}
214
	}
138
	
215
139
	public void testScenario04() {
216
	public void testScenario04() {
140
//		// Show that when an item is added to a collection the table gets an extra item
217
//		// Show that when an item is added to a collection the table gets an extra item
141
//		Account[] accounts = catalog.getAccounts();	
218
//		Account[] accounts = catalog.getAccounts();	
Lines 212-218 Link Here
212
//		assertEquals(tableViewer.getTable().getItemCount(),numberOfAccounts);
289
//		assertEquals(tableViewer.getTable().getItemCount(),numberOfAccounts);
213
//		
290
//		
214
	}
291
	}
215
		
292
216
	public void testScenario03() {
293
	public void testScenario03() {
217
//		// Show that converters work for table columns
294
//		// Show that converters work for table columns
218
//		Account[] accounts = catalog.getAccounts();
295
//		Account[] accounts = catalog.getAccounts();
Lines 247-253 Link Here
247
//					.convertModelToTarget(account.getState())), col_state);
324
//					.convertModelToTarget(account.getState())), col_state);
248
//		}
325
//		}
249
	}
326
	}
250
	
327
251
	public void testScenario05() {
328
	public void testScenario05() {
252
//		// Show that when the model changes then the UI refreshes to reflect this
329
//		// Show that when the model changes then the UI refreshes to reflect this
253
//
330
//
Lines 281-287 Link Here
281
//		assertEquals(lastName,account.getLastName());
358
//		assertEquals(lastName,account.getLastName());
282
//		
359
//		
283
	}
360
	}
284
	
361
285
	public void testScenario06(){
362
	public void testScenario06(){
286
//		// Check that explicit type means that defaulting of converters works
363
//		// Check that explicit type means that defaulting of converters works
287
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(
364
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(
Lines 301-307 Link Here
301
//		assertEquals(transporation.getPrice(),123.45,0);
378
//		assertEquals(transporation.getPrice(),123.45,0);
302
		
379
		
303
	}
380
	}
304
	
381
305
	public void testScenario07(){
382
	public void testScenario07(){
306
//		// Verify that even when a column's property type is not set, that it is worked out lazily from the target type 
383
//		// Verify that even when a column's property type is not set, that it is worked out lazily from the target type 
307
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(
384
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(
Lines 322-328 Link Here
322
//		assertEquals(transporation.getPrice(),123.45,0);
399
//		assertEquals(transporation.getPrice(),123.45,0);
323
//		
400
//		
324
	}
401
	}
325
	
402
326
	public void testScenario08_00(){
403
	public void testScenario08_00(){
327
//		// Verify that binding to a Collection property (rather than an array) works when specifying data type
404
//		// Verify that binding to a Collection property (rather than an array) works when specifying data type
328
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(
405
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(
Lines 347-353 Link Here
347
//		assertEquals("Cricket11Players",firstSignon.getPassword());
424
//		assertEquals("Cricket11Players",firstSignon.getPassword());
348
//		
425
//		
349
	}
426
	}
350
	
427
351
	public void testScenario08_01(){
428
	public void testScenario08_01(){
352
//		// Verify that binding to a Collection property (rather than an array) works without specifying data type
429
//		// Verify that binding to a Collection property (rather than an array) works without specifying data type
353
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(
430
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(
Lines 372-378 Link Here
372
//		assertEquals("Cricket11Players",firstSignon.getPassword());
449
//		assertEquals("Cricket11Players",firstSignon.getPassword());
373
//		
450
//		
374
	}
451
	}
375
	
452
376
	public void testScenario09(){
453
	public void testScenario09(){
377
//		// Verify that nested properties work.  Catalog has adventures.  Adventure has defaultLodging.  Loding has name.
454
//		// Verify that nested properties work.  Catalog has adventures.  Adventure has defaultLodging.  Loding has name.
378
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(tableViewer);
455
//		TableViewerDescription tableViewerDescription = new TableViewerDescription(tableViewer);
Lines 381-412 Link Here
381
//		getDbc().bind(tableViewerDescription,new Property(category, "adventures"),null);
458
//		getDbc().bind(tableViewerDescription,new Property(category, "adventures"),null);
382
//		
459
//		
383
	}
460
	}
384
/**	
385
	public void testScenario10(){
386
		// Verify that for TIME_EARLY updating occurs on a per key basic for a TextCellEditor
387
		// Show that converters work for table columns
388
		Account[] accounts = catalog.getAccounts();
389
		Account firstAccount = accounts[0];
390
		SampleData.getSWTObservableFactory().setUpdateTime(DataBindingContext.TIME_EARLY);
391
		TableViewerDescription tableViewerDescription = new TableViewerDescription(tableViewer);
392
		tableViewerDescription.addEditableColumn("lastName");
393
		tableViewerDescription.addColumn("lastName");
394
		getDbc().bind(tableViewerDescription,new Property(catalog, "accounts"), null);
395
		
396
		// Verify that the first account is shown in the first row with the last name correctly
397
		assertEquals(tableViewer.getTable().getItem(0).getData(),firstAccount);
398
		assertEquals(tableViewer.getTable().getItem(0).getText(0),firstAccount.getLastName());
399
		assertEquals(tableViewer.getTable().getItem(0).getText(1),firstAccount.getLastName());
400
		// Create a cell editor over the first column
401
		tableViewer.editElement(firstAccount, 0);
402
		// Set the text property of the cell editor which is now active over the "firstName" column
403
		CellEditor[] cellEditors = tableViewer.getCellEditors();
404
		TextCellEditor lastNameCellEditor = (TextCellEditor) cellEditors[0];
405
		((Text)lastNameCellEditor.getControl()).setText("E");
406
		// Verify that the key press goes to the model
407
		assertEquals(firstAccount.getLastName(),"E");
408
		
409
	}
410
 **/	
411
}
412
461
462
	/**
463
	 * public void testScenario10(){ // Verify that for TIME_EARLY updating
464
	 * occurs on a per key basic for a TextCellEditor // Show that converters
465
	 * work for table columns Account[] accounts = catalog.getAccounts();
466
	 * Account firstAccount = accounts[0];
467
	 * SampleData.getSWTObservableFactory().setUpdateTime(DataBindingContext.TIME_EARLY);
468
	 * TableViewerDescription tableViewerDescription = new
469
	 * TableViewerDescription(tableViewer);
470
	 * tableViewerDescription.addEditableColumn("lastName");
471
	 * tableViewerDescription.addColumn("lastName");
472
	 * getDbc().bind(tableViewerDescription,new Property(catalog, "accounts"),
473
	 * null); // Verify that the first account is shown in the first row with
474
	 * the last name correctly
475
	 * assertEquals(tableViewer.getTable().getItem(0).getData(),firstAccount);
476
	 * assertEquals(tableViewer.getTable().getItem(0).getText(0),firstAccount.getLastName());
477
	 * assertEquals(tableViewer.getTable().getItem(0).getText(1),firstAccount.getLastName()); //
478
	 * Create a cell editor over the first column
479
	 * tableViewer.editElement(firstAccount, 0); // Set the text property of the
480
	 * cell editor which is now active over the "firstName" column CellEditor[]
481
	 * cellEditors = tableViewer.getCellEditors(); TextCellEditor
482
	 * lastNameCellEditor = (TextCellEditor) cellEditors[0];
483
	 * ((Text)lastNameCellEditor.getControl()).setText("E"); // Verify that the
484
	 * key press goes to the model assertEquals(firstAccount.getLastName(),"E"); }
485
	 */
486
}
(-)src/org/eclipse/jface/tests/internal/databinding/viewers/ViewersObservableFactoryTests.java (+54 lines)
Added Link Here
1
package org.eclipse.jface.tests.internal.databinding.viewers;
2
3
import junit.framework.TestCase;
4
5
import org.eclipse.jface.internal.databinding.internal.swt.TextObservableValue;
6
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
7
import org.eclipse.jface.internal.databinding.provisional.viewers.ViewersObservableFactory;
8
import org.eclipse.jface.viewers.TableViewer;
9
import org.eclipse.jface.viewers.TextCellEditor;
10
import org.eclipse.swt.SWT;
11
import org.eclipse.swt.widgets.Shell;
12
13
/**
14
 * @since 3.2
15
 *
16
 */
17
public class ViewersObservableFactoryTests extends TestCase {
18
	private ViewersObservableFactory factory;
19
	private TableViewer viewer;
20
	
21
	/* (non-Javadoc)
22
	 * @see junit.framework.TestCase#setUp()
23
	 */
24
	protected void setUp() throws Exception {
25
		super.setUp();
26
		
27
		factory = new ViewersObservableFactory();
28
		
29
		Shell shell = new Shell();
30
		viewer = new TableViewer(shell, SWT.NONE);
31
	}
32
	
33
	public void testCreateTextCellEditorObservable() throws Exception {
34
		TextCellEditor editor = new TextCellEditor(viewer.getTable());
35
		IObservable observable = factory.createObservable(editor);
36
		assertNotNull(observable);
37
		assertTrue(observable instanceof TextObservableValue);
38
	}
39
	
40
	/**
41
	 * TextCellEditor must have been constructed with a parent.
42
	 * 
43
	 * @throws Exception
44
	 */
45
	public void testCreateTextCellEditorObservableWithoutViewerException() throws Exception {
46
		try {
47
			TextCellEditor editor = new TextCellEditor();
48
			factory.createObservable(editor);
49
			fail("Exception should have been thrown.");
50
		} catch (IllegalArgumentException e) {
51
			assertTrue(true);
52
		}
53
	}
54
}
(-)src/org/eclipse/jface/tests/internal/databinding/viewers/TableViewerEditorManagerTests.java (+152 lines)
Added Link Here
1
package org.eclipse.jface.tests.internal.databinding.viewers;
2
3
import junit.framework.TestCase;
4
5
import org.eclipse.jface.examples.databinding.model.SampleData;
6
import org.eclipse.jface.internal.databinding.internal.ValueBinding;
7
import org.eclipse.jface.internal.databinding.provisional.Binding;
8
import org.eclipse.jface.internal.databinding.provisional.DataBindingContext;
9
import org.eclipse.jface.internal.databinding.provisional.description.Property;
10
import org.eclipse.jface.internal.databinding.provisional.description.TableModelDescription;
11
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
12
import org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerEditorManager;
13
import org.eclipse.jface.viewers.CellEditor;
14
import org.eclipse.jface.viewers.TableViewer;
15
import org.eclipse.jface.viewers.TextCellEditor;
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.widgets.Shell;
18
19
/**
20
 * @since 3.2
21
 */
22
public class TableViewerEditorManagerTests extends TestCase {
23
	private TableViewer viewer;
24
25
	private DataBindingContext context;
26
27
	private TableModelDescription description;
28
	private TableViewerEditorManager manager;
29
30
	protected void setUp() throws Exception {
31
		Shell shell = new Shell();
32
33
		viewer = new TableViewer(shell, SWT.NONE);
34
		context = SampleData.getDatabindingContext(shell);
35
		description = new TableModelDescription(new Property(null, null),
36
				new String[] { "firstName", "middleName", "lastName" });
37
		manager = new TableViewerEditorManager(viewer, description, context);
38
	}
39
40
	public void testConstruction() throws Exception {
41
		assertEquals(viewer, manager.getTableViewer());
42
		assertEquals(description, manager.getTableModelDescription());
43
		assertEquals(context, manager.getDataBindingContext());
44
	}
45
46
	public void testConstructionExceptions() throws Exception {
47
		try {
48
			manager = new TableViewerEditorManager(null, description, context);
49
			fail("Exception should have been thrown.");
50
		} catch (NullPointerException e) {
51
			assertTrue(true);
52
		}
53
54
		try {
55
			manager = new TableViewerEditorManager(viewer, null, context);
56
			fail("Exception should have been thrown.");
57
		} catch (NullPointerException e) {
58
			assertTrue(true);
59
		}
60
61
		try {
62
			manager = new TableViewerEditorManager(viewer, description, null);
63
			fail("Exception should have been thrown.");
64
		} catch (NullPointerException e) {
65
			assertTrue(true);
66
		}
67
	}
68
69
	public void testCellModifierCreation() throws Exception {
70
		assertNotNull(viewer.getCellModifier());
71
	}
72
73
	public void testCellEditorArrayCreation() throws Exception {
74
		CellEditor[] editors = viewer.getCellEditors();
75
		assertNotNull(editors);
76
		assertEquals(description.getColumnIDs().length, editors.length);
77
	}
78
79
	public void testSetColumnProperties() throws Exception {
80
		Object[] properties = viewer.getColumnProperties();
81
		Object[] columnIDs = description.getColumnIDs();
82
		assertNotNull(properties);
83
		assertEquals(columnIDs.length, properties.length);
84
85
		for (int i = 0; i < properties.length; i++) {
86
			assertEquals(columnIDs[i], properties[i]);
87
		}
88
	}
89
90
	public void testBindEditor() throws Exception {
91
		Binding binding = manager.bind(new TextCellEditor(), "firstName", String.class,
92
				null);
93
		assertNotNull(binding);
94
		assertTrue(binding instanceof ValueBinding);
95
	}
96
	
97
	public void testSetEditorOnViewer() throws Exception {
98
		CellEditor editor = new TextCellEditor();
99
		manager.bind(editor, "firstName", String.class, null);
100
		assertEquals(editor, viewer.getCellEditors()[0]);
101
	}
102
103
	public void testBindEditorNullPointerExceptions() throws Exception {
104
		try {
105
			manager.bind(null, "firstName", String.class, null);
106
			fail("Exception should have been thrown.");
107
		} catch (NullPointerException e) {
108
			assertTrue(true);
109
		}
110
		
111
		try {
112
			manager.bind(new TextCellEditor(viewer.getTable()), null, String.class, null);
113
			fail("Exception should have been thrown.");
114
		} catch (NullPointerException e) {
115
			assertTrue(true);
116
		}
117
		
118
		try {
119
			manager.bind(new TextCellEditor(viewer.getTable()), "firstName", null, null);
120
			fail("Exception should have been thrown.");
121
		} catch (NullPointerException e) {
122
			assertTrue(true);
123
		}
124
	}
125
	
126
	public void testCreateControlIfNullWhenBound() throws Exception {
127
		TextCellEditor editor = new TextCellEditor();
128
		assertNull(editor.getControl());
129
		manager.bind(editor, "firstName", String.class, null);
130
		assertNotNull(editor.getControl());
131
	}
132
	
133
	public void testIAEIfColumnIDNotFound() throws Exception {
134
		try {
135
			manager.bind(new TextCellEditor(viewer.getTable()), "invalid column ID", String.class, null);
136
			fail("Exception should have been thrown.");
137
		} catch (IllegalArgumentException e) {
138
			assertTrue(true);
139
		}
140
	}
141
	
142
	public void testReuseSelectionAcrossBindings() throws Exception {
143
		manager.bind(new TextCellEditor(),	"firstName", String.class, null);
144
		IObservable selection1 = manager.getSelectionObservable();
145
		assertNotNull(selection1);
146
		
147
		manager.bind(new TextCellEditor(), "lastName", String.class, null);
148
		IObservable selection2 = manager.getSelectionObservable();
149
		assertNotNull(selection2);
150
		assertSame(selection1, selection2);
151
	}
152
}
(-)src/org/eclipse/jface/tests/databinding/swt/TextObservableValueTests.java (+132 lines)
Added Link Here
1
package org.eclipse.jface.tests.databinding.swt;
2
3
import junit.framework.TestCase;
4
5
import org.eclipse.jface.internal.databinding.internal.swt.TextObservableValue;
6
import org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue;
7
import org.eclipse.jface.internal.databinding.provisional.observable.value.IValueChangeListener;
8
import org.eclipse.jface.internal.databinding.provisional.observable.value.ValueDiff;
9
import org.eclipse.swt.SWT;
10
import org.eclipse.swt.widgets.Event;
11
import org.eclipse.swt.widgets.Shell;
12
import org.eclipse.swt.widgets.Text;
13
14
/**
15
 * Tests for TextObservableValue.
16
 * 
17
 * @since 3.2
18
 */
19
public class TextObservableValueTests extends TestCase {
20
	private Shell shell;
21
22
	private Text text;
23
24
	protected void setUp() throws Exception {
25
		super.setUp();
26
27
		shell = new Shell();
28
		text = new Text(shell, SWT.NONE);
29
	}
30
31
	/**
32
	 * Asserts that if the a <code>null</code> Text is passed TextObservableValue throws a NPE.
33
	 */
34
	public void testConstructor() {
35
		try {
36
			new TextObservableValue(null, SWT.NONE);
37
			fail();
38
		} catch (NullPointerException e) {
39
			assertTrue(true);
40
		}
41
	}
42
	
43
	/**
44
	 * Asserts that only valid SWT event types are accepted on construction of TextObservableValue.
45
	 */
46
	public void testConstructorUpdateEventTypes() {
47
		try {
48
			new TextObservableValue(text, SWT.NONE);
49
			new TextObservableValue(text, SWT.FocusOut);
50
			new TextObservableValue(text, SWT.Modify);
51
			assertTrue(true);
52
		} catch (IllegalArgumentException e) {
53
			fail();
54
		}
55
		
56
		try {
57
			new TextObservableValue(text, SWT.Verify);
58
			fail();
59
		} catch (IllegalArgumentException e) {
60
			assertTrue(true);
61
		}
62
	}
63
	
64
	public void testFireValueChangeEventsOnFocusOut() {
65
		TextObservableValue observable = new TextObservableValue(text,
66
				SWT.FocusOut);
67
		ValueChangeCounter counter = new ValueChangeCounter();
68
		observable.addValueChangeListener(counter);
69
70
		text.setText("value");
71
		assertEquals(0, counter.count);
72
		text.notifyListeners(SWT.FocusOut, null);
73
		assertEquals(1, counter.count);
74
	}
75
76
	public void testFireValueChangeEventsOnModify() {
77
		TextObservableValue observable = new TextObservableValue(text,
78
				SWT.Modify);
79
		ValueChangeCounter counter = new ValueChangeCounter();
80
		observable.addValueChangeListener(counter);
81
82
		text.setText("value");
83
		assertEquals(1, counter.count);
84
	}
85
86
	public void testSuppressFireValueChangeEvents() {
87
		TextObservableValue observable = new TextObservableValue(text, SWT.NONE);
88
		ValueChangeCounter counter = new ValueChangeCounter();
89
		observable.addValueChangeListener(counter);
90
91
		text.setText("value");
92
		assertEquals(0, counter.count);
93
		text.notifyListeners(SWT.Modify, null);
94
		assertEquals(0, counter.count);
95
		text.notifyListeners(SWT.FocusOut, null);
96
		assertEquals(0, counter.count);
97
	}
98
99
	public void testFireChangeEventsOnTraversal() {
100
		TextObservableValue observable = TextObservableValue.asTraversalObservable(text, SWT.TRAVERSE_RETURN | SWT.TRAVERSE_TAB_NEXT);
101
		
102
		ValueChangeCounter counter = new ValueChangeCounter();
103
		observable.addValueChangeListener(counter);
104
		
105
		text.setText("value");
106
		assertEquals(0, counter.count);
107
		text.notifyListeners(SWT.Modify, null);
108
		assertEquals(0, counter.count);
109
		text.notifyListeners(SWT.FocusOut, null);
110
		assertEquals(0, counter.count);
111
		
112
		Event event = new Event();
113
		event.detail = SWT.TRAVERSE_RETURN;
114
		
115
		text.notifyListeners(SWT.Traverse, event);
116
		assertEquals(1, counter.count);
117
		
118
		event = new Event();
119
		event.detail = SWT.TRAVERSE_TAB_NEXT;
120
		
121
		text.notifyListeners(SWT.Traverse, event);
122
		assertEquals(2, counter.count);
123
	}
124
125
	private class ValueChangeCounter implements IValueChangeListener {
126
		private int count;
127
128
		public void handleValueChange(IObservableValue source, ValueDiff diff) {
129
			count++;
130
		}
131
	}
132
}
(-)src/org/eclipse/jface/internal/databinding/internal/swt/TextObservableValue.java (-45 / +213 lines)
Lines 11-20 Link Here
11
package org.eclipse.jface.internal.databinding.internal.swt;
11
package org.eclipse.jface.internal.databinding.internal.swt;
12
12
13
import org.eclipse.jface.internal.databinding.provisional.observable.Diffs;
13
import org.eclipse.jface.internal.databinding.provisional.observable.Diffs;
14
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
14
import org.eclipse.jface.internal.databinding.provisional.observable.value.AbstractVetoableValue;
15
import org.eclipse.jface.internal.databinding.provisional.observable.value.AbstractVetoableValue;
15
import org.eclipse.swt.SWT;
16
import org.eclipse.swt.SWT;
16
import org.eclipse.swt.events.KeyEvent;
17
import org.eclipse.swt.events.KeyEvent;
17
import org.eclipse.swt.events.KeyListener;
18
import org.eclipse.swt.events.KeyListener;
19
import org.eclipse.swt.events.TraverseEvent;
20
import org.eclipse.swt.events.TraverseListener;
18
import org.eclipse.swt.events.VerifyEvent;
21
import org.eclipse.swt.events.VerifyEvent;
19
import org.eclipse.swt.events.VerifyListener;
22
import org.eclipse.swt.events.VerifyListener;
20
import org.eclipse.swt.widgets.Event;
23
import org.eclipse.swt.widgets.Event;
Lines 22-83 Link Here
22
import org.eclipse.swt.widgets.Text;
25
import org.eclipse.swt.widgets.Text;
23
26
24
/**
27
/**
25
 * @since 1.0
28
 * {@link IObservable} implementation that manages the binding of a model
29
 * property to a {@link Text} widget. The time at which communication of the
30
 * value change event is specified by the consumer on construction.
31
 * 
32
 * <dl>
33
 * <dt>Events:</dt>
34
 * <dd> If the update event type (specified on construction) is
35
 * <code>SWT.Modify</code> a value change event will be fired on every key
36
 * stroke. If the update event type is <code>SWT.FocusOut</code> a value
37
 * change event will be fired on focus out. When in either mode if the user is
38
 * entering text and presses [Escape] the value will be reverted back to the
39
 * previous, unedited, model value. Regardless of the update event type a value
40
 * changing event will fire on verify.</dd>
41
 * </dl>
42
 * 
43
 * <p>
44
 * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
45
 * part of a work in progress. There is no guarantee that this API will remain
46
 * unchanged during the 3.2 release cycle. Please do not use this API without
47
 * consulting with the Platform/UI team.
48
 * </p>
26
 * 
49
 * 
50
 * @since 1.0
27
 */
51
 */
28
public class TextObservableValue extends AbstractVetoableValue {
52
public class TextObservableValue extends AbstractVetoableValue {
29
53
	/**
54
	 * {@link Text} widget that this is being observed.
55
	 */
30
	private final Text text;
56
	private final Text text;
31
57
58
	/**
59
	 * Flag to track when the model is updating the widget. When
60
	 * <code>true</code> the handlers for the SWT events should not process
61
	 * the event as this would cause an infinite loop.
62
	 */
32
	private boolean updating = false;
63
	private boolean updating = false;
33
64
34
	private int updatePolicy;
65
	/**
66
	 * SWT event that on firing this observable will fire change events in an
67
	 * attempt to update the model.
68
	 */
69
	private final int updateEventType;
70
71
	/**
72
	 * Valid types for the {@link #updateEventType}.
73
	 */
74
	private static final int[] validUpdateEventTypes = new int[] { SWT.Modify,
75
			SWT.FocusOut, SWT.NONE };
35
76
77
	/**
78
	 * Previous value from the model. It is maintained so that when entering
79
	 * text if the consumer were to press [Escape] the value can be reverted
80
	 * back to the last known model value.
81
	 */
36
	private String bufferedValue;
82
	private String bufferedValue;
37
83
38
	private Listener updateListener = new Listener() {
84
	private Listener updateListener;
39
		public void handleEvent(Event event) {
85
40
			if (!updating) {
86
	private VerifyListener verifyListener;
41
				String oldValue = bufferedValue;
87
42
				String newValue = text.getText();
88
	private KeyListener keyListener;
43
89
44
				// If we are updating on focus lost then when we fire the change
90
	private TraverseListener traverseListener;
45
				// event change the buffered value
91
46
				if (updatePolicy == SWT.FocusOut) {
92
	/**
47
					bufferedValue = text.getText();
93
	 * Private constructor for constructing a new instance.
94
	 * 
95
	 * @param text
96
	 * @param updateEventType
97
	 *            -1 if not specified
98
	 * @param traversalDetail
99
	 *            -1 if not specified
100
	 * @throws IllegalArgumentException if both <code>updateEventType</code> and <code>traverseEventType</code> == -1.
101
	 * @throws IllegalArgumentException if <code>updateEventType</code> is unsupported
102
	 */
103
	private TextObservableValue(final Text text, final int updateEventType,
104
			final int traversalDetail) {
105
		if (text == null) {
106
			throw new NullPointerException("Parameter " + text + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
107
		}
108
109
		if (updateEventType == -1 && traversalDetail == -1) {
110
			throw new IllegalArgumentException(
111
					"Update event type or traversal event must be set."); //$NON-NLS-1$
112
		}
113
		
114
		if (updateEventType > -1) {
115
			boolean eventValid = false;
116
			for (int i = 0; !eventValid && i < validUpdateEventTypes.length; i++) {
117
				eventValid = (updateEventType == validUpdateEventTypes[i]);
118
			}
119
			if (!eventValid) {
120
				throw new IllegalArgumentException(
121
						"UpdateEventType [" + updateEventType + "] is unsupported."); //$NON-NLS-1$//$NON-NLS-2$
122
			}
123
			
124
			setupLifecycleHandling(text, updateEventType);
125
		}
126
127
		if (traversalDetail > -1) {
128
			setupTraverseHandling(text, traversalDetail);
129
		}
130
131
		this.text = text;
132
		this.updateEventType = updateEventType;
133
134
		keyListener = new KeyListener() {
135
			public void keyPressed(KeyEvent e) {
136
				if (e.character == SWT.ESC && bufferedValue != null) {
137
					// Revert the value in the text field to the model value
138
					text.setText(bufferedValue);
139
				}
140
			}
141
142
			public void keyReleased(KeyEvent e) {
143
			}
144
		};
145
		text.addKeyListener(keyListener);
146
	}
147
148
	/**
149
	 * Performs setup for firing value change events on traversal.
150
	 * 
151
	 * @param text
152
	 * @param traverseEventTypes
153
	 */
154
	private void setupTraverseHandling(final Text text,
155
			final int traverseEventTypes) {
156
		traverseListener = new TraverseListener() {
157
			public void keyTraversed(TraverseEvent e) {
158
				if ((e.detail & traverseEventTypes) != 0) {
159
					String oldValue = bufferedValue;
160
					String newValue = text.getText();
161
48
					if (!newValue.equals(oldValue)) {
162
					if (!newValue.equals(oldValue)) {
49
						fireValueChange(Diffs.createValueDiff(oldValue,
163
						fireValueChange(Diffs.createValueDiff(oldValue,
50
								newValue));
164
								newValue));
51
					}
165
					}
52
				} else {
53
					fireValueChange(Diffs.createValueDiff(oldValue, text
54
							.getText()));
55
				}
166
				}
56
			}
167
			}
57
		}
168
		};
58
	};
169
		text.addTraverseListener(traverseListener);
59
170
	}
60
	private VerifyListener verifyListener;
61
62
	private KeyListener keyListener;
63
171
64
	/**
172
	/**
173
	 * Performs validation and setup for listeners of lifecycle events like
174
	 * modify and focus out.
175
	 * 
65
	 * @param text
176
	 * @param text
66
	 * @param updatePolicy
177
	 * @param event
178
	 * @param updateListener
67
	 */
179
	 */
68
	public TextObservableValue(final Text text, int updatePolicy) {
180
	private void setupLifecycleHandling(final Text text, int event) {
69
		this.text = text;
181
		if (event != SWT.None) {
70
		this.updatePolicy = updatePolicy;
182
			updateListener = new Listener() {
71
		if (updatePolicy != SWT.None) {
183
				public void handleEvent(Event event) {
72
			text.addListener(updatePolicy, updateListener);
184
					if (!updating) {
185
						String oldValue = bufferedValue;
186
						String newValue = text.getText();
187
188
						// If we are updating on focus lost then when we fire
189
						// the change
190
						// event change the buffered value
191
						if (updateEventType == SWT.FocusOut) {
192
							bufferedValue = text.getText();
193
							if (!newValue.equals(oldValue)) {
194
								fireValueChange(Diffs.createValueDiff(oldValue,
195
										newValue));
196
							}
197
						} else {
198
							fireValueChange(Diffs.createValueDiff(oldValue,
199
									text.getText()));
200
						}
201
					}
202
				}
203
			};
204
			text.addListener(event, updateListener);
73
		}
205
		}
74
		// If the update policy is TIME_EARLY then the model is notified of
206
		// If the update policy is SWT.Modify then the model is notified of
75
		// changed on key stroke by key stroke
207
		// changed on key stroke by key stroke
76
		// When escape is pressed we need to rollback to the previous value
208
		// When escape is pressed we need to rollback to the previous value
77
		// which is done with a key listener, however
209
		// which is done with a key listener, however
78
		// the bufferedValue (the last remembered change value) must be changed
210
		// the bufferedValue (the last remembered change value) must be changed
79
		// on focus lost
211
		// on focus lost
80
		if (updatePolicy == SWT.Modify) {
212
		if (event == SWT.Modify) {
81
			text.addListener(SWT.FocusOut, new Listener() {
213
			text.addListener(SWT.FocusOut, new Listener() {
82
				public void handleEvent(Event event) {
214
				public void handleEvent(Event event) {
83
					if (!updating) {
215
					if (!updating) {
Lines 101-120 Link Here
101
			}
233
			}
102
		};
234
		};
103
		text.addVerifyListener(verifyListener);
235
		text.addVerifyListener(verifyListener);
104
		keyListener = new KeyListener() {
236
	}
105
			public void keyPressed(KeyEvent e) {
106
				if (e.character == SWT.ESC && bufferedValue != null) {
107
					// Revert the value in the text field to the model value
108
					text.setText(bufferedValue);
109
				}
110
			}
111
237
112
			public void keyReleased(KeyEvent e) {
238
	/**
113
			}
239
	 * Constructs a new instance bound to <code>text</code> and configured to
114
		};
240
	 * fire change events at the time of the <code>updateEventType</code>.
115
		text.addKeyListener(keyListener);
241
	 * 
242
	 * @param text
243
	 * @param updateEventType
244
	 *            SWT event constant as to what SWT event to update the model in
245
	 *            response to. Appropriate values are: <code>SWT.Modify</code>,
246
	 *            <code>SWT.FocusOut</code>, <code>SWT.NONE</code>.
247
	 * @throws IllegalArgumentException
248
	 *             if <code>updateEventType</code> is an incorrect type.
249
	 */
250
	public TextObservableValue(final Text text, final int updateEventType) {
251
		this(text, updateEventType, -1);
116
	}
252
	}
117
253
254
	/**
255
	 * Sets the bound {@link Text Text's} text to the passed <code>value</code>.
256
	 * 
257
	 * @param value
258
	 *            new value, String expected
259
	 * @see org.eclipse.jface.internal.databinding.provisional.observable.value.AbstractVetoableValue#doSetValue(java.lang.Object)
260
	 * @throws ClassCastException
261
	 *             if the value is anything other than a String
262
	 */
118
	public void doSetValue(final Object value) {
263
	public void doSetValue(final Object value) {
119
		try {
264
		try {
120
			updating = true;
265
			updating = true;
Lines 135-146 Link Here
135
280
136
	public void dispose() {
281
	public void dispose() {
137
		if (!text.isDisposed()) {
282
		if (!text.isDisposed()) {
138
			text.removeKeyListener(keyListener);
283
			if (keyListener != null) {
139
			if (updatePolicy != SWT.None) {
284
				text.removeKeyListener(keyListener);
140
				text.removeListener(updatePolicy, updateListener);
285
			}
286
			if (updateListener != null) {
287
				text.removeListener(updateEventType, updateListener);
288
			}
289
290
			if (verifyListener != null) {
291
				text.removeVerifyListener(verifyListener);
292
			}
293
294
			if (traverseListener != null) {
295
				text.removeTraverseListener(traverseListener);
141
			}
296
			}
142
			text.removeVerifyListener(verifyListener);
143
		}
297
		}
144
		super.dispose();
298
		super.dispose();
145
	}
299
	}
300
301
	/**
302
	 * Constructs a TextObservableValue whose update policy is defined for
303
	 * traversal events rather than lifecycle events like Modify and FocusOut.
304
	 * 
305
	 * @param text
306
	 * @param details
307
	 *            traversal detail values or'd "|" together
308
	 * @return TextObservableValue
309
	 */
310
	public static TextObservableValue asTraversalObservable(Text text,
311
			int details) {
312
		return new TextObservableValue(text, -1, details);
313
	}
146
}
314
}
(-)src/org/eclipse/jface/internal/databinding/provisional/viewers/ViewersObservableFactory.java (+21 lines)
Lines 10-15 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jface.internal.databinding.provisional.viewers;
11
package org.eclipse.jface.internal.databinding.provisional.viewers;
12
12
13
import org.eclipse.jface.internal.databinding.internal.swt.TextObservableValue;
13
import org.eclipse.jface.internal.databinding.internal.viewers.AbstractListViewerObservableCollectionWithLabels;
14
import org.eclipse.jface.internal.databinding.internal.viewers.AbstractListViewerObservableCollectionWithLabels;
14
import org.eclipse.jface.internal.databinding.internal.viewers.StructuredViewerObservableValue;
15
import org.eclipse.jface.internal.databinding.internal.viewers.StructuredViewerObservableValue;
15
import org.eclipse.jface.internal.databinding.internal.viewers.TableViewerObservableCollectionWithLabels;
16
import org.eclipse.jface.internal.databinding.internal.viewers.TableViewerObservableCollectionWithLabels;
Lines 17-24 Link Here
17
import org.eclipse.jface.internal.databinding.provisional.factories.IObservableFactory;
18
import org.eclipse.jface.internal.databinding.provisional.factories.IObservableFactory;
18
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
19
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
19
import org.eclipse.jface.viewers.AbstractListViewer;
20
import org.eclipse.jface.viewers.AbstractListViewer;
21
import org.eclipse.jface.viewers.CellEditor;
20
import org.eclipse.jface.viewers.StructuredViewer;
22
import org.eclipse.jface.viewers.StructuredViewer;
21
import org.eclipse.jface.viewers.TableViewer;
23
import org.eclipse.jface.viewers.TableViewer;
24
import org.eclipse.jface.viewers.TextCellEditor;
25
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.widgets.Text;
22
27
23
/**
28
/**
24
 * A factory that supports binding to JFace viewers. This factory supports the
29
 * A factory that supports binding to JFace viewers. This factory supports the
Lines 36-41 Link Here
36
 * ViewersProperties.CONTENT</li>
41
 * ViewersProperties.CONTENT</li>
37
 * </ul>
42
 * </ul>
38
 * </li>
43
 * </li>
44
 * <li>TextCellEditor</li>
39
 * </ul>
45
 * </ul>
40
 * TODO complete the list
46
 * TODO complete the list
41
 * 
47
 * 
Lines 85-91 Link Here
85
		} else if (description instanceof TableViewer) {
91
		} else if (description instanceof TableViewer) {
86
			return new TableViewerObservableCollectionWithLabels(
92
			return new TableViewerObservableCollectionWithLabels(
87
					(TableViewer) description);
93
					(TableViewer) description);
94
95
		} else if (description instanceof CellEditor) {
96
			CellEditor editor = (CellEditor) description;
97
98
			if (editor.getControl() == null) {
99
				throw new IllegalArgumentException(
100
						"The CellEditor's control has not been constructed. The editor must have a control to bind.  Use the editor contructor that accepts a parent."); //$NON-NLS-1$
101
			}
102
103
			if (description instanceof TextCellEditor) {
104
				return TextObservableValue.asTraversalObservable(
105
						(Text) editor.getControl(), SWT.TRAVERSE_RETURN
106
								| SWT.TRAVERSE_TAB_NEXT);
107
			}
88
		}
108
		}
109
89
		return null;
110
		return null;
90
	}
111
	}
91
}
112
}
(-)src/org/eclipse/jface/internal/databinding/provisional/viewers/TableViewerEditorManager.java (+254 lines)
Added Link Here
1
package org.eclipse.jface.internal.databinding.provisional.viewers;
2
3
import org.eclipse.jface.internal.databinding.provisional.BindSpec;
4
import org.eclipse.jface.internal.databinding.provisional.Binding;
5
import org.eclipse.jface.internal.databinding.provisional.DataBindingContext;
6
import org.eclipse.jface.internal.databinding.provisional.description.Property;
7
import org.eclipse.jface.internal.databinding.provisional.description.TableModelDescription;
8
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
9
import org.eclipse.jface.util.Assert;
10
import org.eclipse.jface.viewers.CellEditor;
11
import org.eclipse.jface.viewers.ICellModifier;
12
import org.eclipse.jface.viewers.TableViewer;
13
14
/**
15
 * Manages the process of binding editors to a <code>TableViewer</code>. When
16
 * using the manager manipulation of the cell modifier, column properties, or
17
 * editors on the viewer is forbidden.
18
 * 
19
 * @since 3.3
20
 */
21
public class TableViewerEditorManager {
22
	/**
23
	 * TableViewer whose editors are being managed.
24
	 */
25
	private final TableViewer tableViewer;
26
27
	/**
28
	 * Describes the model of the viewer, used to determine columns to edit.
29
	 */
30
	private final TableModelDescription tableModelDescription;
31
32
	/**
33
	 * Used to create observables for cell editors and to bind editors to the
34
	 * model.
35
	 */
36
	private final DataBindingContext dataBindingContext;
37
38
	/**
39
	 * IObservable that provides the ability to observe selection of the
40
	 * TableViewer. All editors observe the same instance.
41
	 */
42
	private IObservable selectionObservable;
43
44
	/**
45
	 * Constructs a new instance.
46
	 * 
47
	 * @param tableViewer
48
	 *            viewer to associate editors with
49
	 * @param tableModelDescription
50
	 *            description of the model to apply to editing
51
	 * @param dataBindingContext
52
	 *            context to use when binding
53
	 */
54
	public TableViewerEditorManager(TableViewer tableViewer,
55
			TableModelDescription tableModelDescription,
56
			DataBindingContext dataBindingContext) {
57
		if (tableViewer == null) {
58
			throw new NullPointerException(
59
					"Parameter " + tableViewer + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
60
		}
61
		if (tableModelDescription == null) {
62
			throw new NullPointerException(
63
					"Parameter " + tableModelDescription + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
64
		}
65
		if (dataBindingContext == null) {
66
			throw new NullPointerException(
67
					"Parameter " + dataBindingContext + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
68
		}
69
70
		this.tableViewer = tableViewer;
71
		this.tableModelDescription = tableModelDescription;
72
		this.dataBindingContext = dataBindingContext;
73
74
		tableViewer.setCellModifier(new CellModifier(tableViewer));
75
76
		Object[] columnIDs = tableModelDescription.getColumnIDs();
77
		int columnCount = (columnIDs != null) ? columnIDs.length : 0;
78
79
		tableViewer.setCellEditors(new CellEditor[columnCount]);
80
81
		String[] properties = new String[columnCount];
82
		tableViewer.setColumnProperties(properties);
83
84
		for (int i = 0; i < columnCount; i++) {
85
			properties[i] = columnIDs[i].toString();
86
		}
87
	}
88
89
	/**
90
	 * @return Returns the dataBindingContext.
91
	 */
92
	public DataBindingContext getDataBindingContext() {
93
		return dataBindingContext;
94
	}
95
96
	/**
97
	 * @return Returns the tableModelDescription.
98
	 */
99
	public TableModelDescription getTableModelDescription() {
100
		return tableModelDescription;
101
	}
102
103
	/**
104
	 * @return Returns the tableViewer.
105
	 */
106
	public TableViewer getTableViewer() {
107
		return tableViewer;
108
	}
109
110
	/**
111
	 * ICellModifier implementation that mostly ignores it's duty of being the
112
	 * translator between an editor on the value being edited. The binding
113
	 * framework takes place of the ICellModifier but editing can't occur in
114
	 * viewers without an ICellModifier.
115
	 * 
116
	 * @since 3.3
117
	 */
118
	private static class CellModifier implements ICellModifier {
119
		private final TableViewer viewer;
120
121
		private CellModifier(TableViewer viewer) {
122
			this.viewer = viewer;
123
		}
124
125
		/**
126
		 * Returns the editor for the property.
127
		 * 
128
		 * @param property
129
		 * @return editor, <code>null</code> if not found
130
		 */
131
		private CellEditor getEditor(String property) {
132
			Assert.isNotNull(property);
133
134
			CellEditor editor = null;
135
			Object[] properties = viewer.getColumnProperties();
136
			for (int i = 0; i < properties.length; i++) {
137
				if (property.equals(properties[i])) {
138
					editor = viewer.getCellEditors()[i];
139
					break;
140
				}
141
			}
142
			return editor;
143
		}
144
145
		/*
146
		 * (non-Javadoc)
147
		 * 
148
		 * @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object,
149
		 *      java.lang.String)
150
		 */
151
		public boolean canModify(Object element, String property) {
152
			return getEditor(property) != null;
153
		}
154
155
		/*
156
		 * (non-Javadoc)
157
		 * 
158
		 * @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object,
159
		 *      java.lang.String)
160
		 */
161
		public Object getValue(Object element, String property) {
162
			/*
163
			 * this is a workaround. if we return null the CellEditor will throw
164
			 * an exception. the binding framework will set the appropriate
165
			 * value after this method is invoked.
166
			 */
167
			CellEditor editor = getEditor(property);
168
169
			Assert.isTrue(editor != null);
170
171
			return editor.getValue();
172
		}
173
174
		/*
175
		 * (non-Javadoc)
176
		 * 
177
		 * @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object,
178
		 *      java.lang.String, java.lang.Object)
179
		 */
180
		public void modify(Object element, String property, Object value) {
181
			// modifies are handled by the binding framework
182
		}
183
	}
184
185
	/**
186
	 * Assigns an editor to the viewer.
187
	 * 
188
	 * @param cellEditor
189
	 * @param columnID
190
	 *            value that corresponds to the column specified in the
191
	 *            TableModelDescription
192
	 * @param columnIDType
193
	 *            type of the attribute to bind the editor to
194
	 * @param bindSpec
195
	 *            spec that contains validators, converters, etc. to employ when
196
	 *            updating the observables, can be <code>null</code>.
197
	 * @return binding
198
	 * @throws IllegalArgumentException
199
	 *             if the columnID is not found in the TableModelDescription's
200
	 *             columnIDs.
201
	 */
202
	public Binding bind(CellEditor cellEditor, Object columnID,
203
			Class columnIDType, BindSpec bindSpec) {
204
		if (cellEditor == null) {
205
			throw new NullPointerException(
206
					"Parameter " + cellEditor + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
207
		}
208
		if (columnID == null) {
209
			throw new NullPointerException(
210
					"Parameter " + columnID + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
211
		}
212
		if (columnIDType == null) {
213
			throw new NullPointerException(
214
					"Parameter " + columnIDType + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
215
		}
216
217
		int columnIndex = -1;
218
		Object[] columnIDs = tableModelDescription.getColumnIDs();
219
		for (int i = 0; columnIndex == -1 && i < columnIDs.length; i++) {
220
			if (columnID.equals(columnIDs[i])) {
221
				columnIndex = i;
222
			}
223
		}
224
225
		if (columnIndex == -1) {
226
			throw new IllegalArgumentException(
227
					"Column with ID [" + columnID + "] not found in TableModelDescription."); //$NON-NLS-1$//$NON-NLS-2$
228
		}
229
230
		tableViewer.getCellEditors()[columnIndex] = cellEditor;
231
232
		if (selectionObservable == null) {
233
			selectionObservable = dataBindingContext
234
					.createObservable(new Property(tableViewer,
235
							ViewersProperties.SINGLE_SELECTION));
236
			Assert.isNotNull(selectionObservable);
237
		}
238
239
		if (cellEditor.getControl() == null) {
240
			cellEditor.create(tableViewer.getTable());
241
		}
242
243
		return dataBindingContext.bind(cellEditor, new Property(
244
				selectionObservable, columnID, columnIDType, Boolean.FALSE),
245
				bindSpec);
246
	}
247
248
	/**
249
	 * @return Returns the viewerSelectionObservable.
250
	 */
251
	public IObservable getSelectionObservable() {
252
		return selectionObservable;
253
	}
254
}

Return to bug 144260