View | Details | Raw Unified | Return to bug 144260 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/jface/tests/internal/databinding/provisional/viewers/ViewersObservableFactoryTest.java (-2 / +25 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2006 Brad Reynolds.
2
 * Copyright (c) 2006 Brad Reynolds and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 18-34 Link Here
18
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
18
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
19
import org.eclipse.jface.internal.databinding.provisional.viewers.ViewersObservableFactory;
19
import org.eclipse.jface.internal.databinding.provisional.viewers.ViewersObservableFactory;
20
import org.eclipse.jface.internal.databinding.provisional.viewers.ViewersProperties;
20
import org.eclipse.jface.internal.databinding.provisional.viewers.ViewersProperties;
21
import org.eclipse.jface.viewers.CheckboxCellEditor;
21
import org.eclipse.jface.viewers.ISelection;
22
import org.eclipse.jface.viewers.ISelection;
22
import org.eclipse.jface.viewers.ISelectionChangedListener;
23
import org.eclipse.jface.viewers.ISelectionChangedListener;
23
import org.eclipse.jface.viewers.ISelectionProvider;
24
import org.eclipse.jface.viewers.ISelectionProvider;
24
import org.eclipse.jface.viewers.ListViewer;
25
import org.eclipse.jface.viewers.ListViewer;
25
import org.eclipse.jface.viewers.TableViewer;
26
import org.eclipse.jface.viewers.TableViewer;
27
import org.eclipse.jface.viewers.TextCellEditor;
26
import org.eclipse.swt.widgets.Shell;
28
import org.eclipse.swt.widgets.Shell;
27
29
28
/**
30
/**
29
 * Tests for ViewerObservableFactory.
31
 * Tests for ViewerObservableFactory.
30
 * 
32
 * 
31
 * @since 1.1
33
 * @since 3.2
32
 */
34
 */
33
public class ViewersObservableFactoryTest extends TestCase {
35
public class ViewersObservableFactoryTest extends TestCase {
34
	private Shell shell;
36
	private Shell shell;
Lines 72-77 Link Here
72
		assertTrue(observable instanceof SelectionProviderSingleSelectionObservableValue);
74
		assertTrue(observable instanceof SelectionProviderSingleSelectionObservableValue);
73
	}
75
	}
74
	
76
	
77
	public void testGetObservableForTextCellEditor() throws Exception {
78
		TextCellEditor editor = new TextCellEditor(shell);
79
		IObservable observable = factory.createObservable(editor);
80
		assertNotNull(observable);
81
	}
82
	
83
	public void testThrowsIAEIfTextCellEditorControlIsNotCreated() throws Exception {
84
		TextCellEditor editor = new TextCellEditor();
85
		try {
86
			factory.createObservable(editor);
87
			fail("exception should have been thrown");
88
		} catch (IllegalArgumentException e) {
89
		}
90
	}
91
	
92
	public void testGetObservableForCheckboxCellEditor() throws Exception {
93
		CheckboxCellEditor editor = new CheckboxCellEditor();
94
		IObservable observable = factory.createObservable(editor);
95
		assertNotNull(observable);
96
	}
97
	
75
	/**
98
	/**
76
	 * Empty stub to satisfy the requirement that we have a type of ISelectionProvider that is not a viewer.
99
	 * Empty stub to satisfy the requirement that we have a type of ISelectionProvider that is not a viewer.
77
	 */
100
	 */
(-)src/org/eclipse/jface/tests/databinding/BindingTestSuite.java (+7 lines)
Lines 8-13 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 137877
10
 *     Brad Reynolds - bug 137877
11
 *     Brad Reynolds - bug 144260
11
 *******************************************************************************/
12
 *******************************************************************************/
12
package org.eclipse.jface.tests.databinding;
13
package org.eclipse.jface.tests.databinding;
13
14
Lines 32-37 Link Here
32
import org.eclipse.jface.tests.internal.databinding.internal.viewers.SVOCWLTest;
33
import org.eclipse.jface.tests.internal.databinding.internal.viewers.SVOCWLTest;
33
import org.eclipse.jface.tests.internal.databinding.internal.viewers.SelectionProviderSingleSelectionObservableValueTest;
34
import org.eclipse.jface.tests.internal.databinding.internal.viewers.SelectionProviderSingleSelectionObservableValueTest;
34
import org.eclipse.jface.tests.internal.databinding.provisional.observable.AbstractObservableTest;
35
import org.eclipse.jface.tests.internal.databinding.provisional.observable.AbstractObservableTest;
36
import org.eclipse.jface.tests.internal.databinding.provisional.viewers.BooleanCellEditorObservableValueTest;
37
import org.eclipse.jface.tests.internal.databinding.provisional.viewers.TableViewerBindingFactoryTest;
38
import org.eclipse.jface.tests.internal.databinding.provisional.viewers.TableViewerEditorManagerTest;
35
import org.eclipse.jface.tests.internal.databinding.provisional.viewers.ViewersObservableFactoryTest;
39
import org.eclipse.jface.tests.internal.databinding.provisional.viewers.ViewersObservableFactoryTest;
36
40
37
public class BindingTestSuite extends TestSuite {
41
public class BindingTestSuite extends TestSuite {
Lines 72-77 Link Here
72
		addTestSuite(AbstractObservableTest.class);
76
		addTestSuite(AbstractObservableTest.class);
73
		addTestSuite(MocksTest.class);
77
		addTestSuite(MocksTest.class);
74
		addTestSuite(PersonTests.class);
78
		addTestSuite(PersonTests.class);
79
		addTestSuite(BooleanCellEditorObservableValueTest.class);
80
		addTestSuite(TableViewerBindingFactoryTest.class);
81
		addTestSuite(TableViewerEditorManagerTest.class);
75
	}
82
	}
76
83
77
	/**
84
	/**
(-)src/org/eclipse/jface/tests/internal/databinding/provisional/viewers/TableViewerEditorManagerTest.java (+282 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 Brad Reynolds 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
 *     Brad Reynolds - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.tests.internal.databinding.provisional.viewers;
13
14
import junit.framework.TestCase;
15
16
import org.eclipse.jface.examples.databinding.model.Adventure;
17
import org.eclipse.jface.examples.databinding.model.Catalog;
18
import org.eclipse.jface.examples.databinding.model.Category;
19
import org.eclipse.jface.examples.databinding.model.Lodging;
20
import org.eclipse.jface.examples.databinding.model.SampleData;
21
import org.eclipse.jface.internal.databinding.provisional.Binding;
22
import org.eclipse.jface.internal.databinding.provisional.DataBindingContext;
23
import org.eclipse.jface.internal.databinding.provisional.description.Property;
24
import org.eclipse.jface.internal.databinding.provisional.description.TableModelDescription;
25
import org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerEditorManager;
26
import org.eclipse.jface.viewers.CellEditor;
27
import org.eclipse.jface.viewers.CheckboxCellEditor;
28
import org.eclipse.jface.viewers.ICellModifier;
29
import org.eclipse.jface.viewers.TableViewer;
30
import org.eclipse.jface.viewers.TextCellEditor;
31
import org.eclipse.swt.SWT;
32
import org.eclipse.swt.layout.RowLayout;
33
import org.eclipse.swt.widgets.Shell;
34
35
/**
36
 * @since 3.2
37
 */
38
public class TableViewerEditorManagerTest extends TestCase {
39
	private Shell shell;
40
41
	private TableViewer viewer;
42
43
	private DataBindingContext context;
44
45
	private TableModelDescription description;
46
47
	private TableViewerEditorManager manager;
48
49
	private Catalog model;
50
51
	protected void setUp() throws Exception {
52
		shell = new Shell();
53
		shell.setLayout(new RowLayout());
54
55
		viewer = new TableViewer(shell, SWT.NONE);
56
		context = SampleData.getDatabindingContext(shell);
57
		model = SampleData.CATALOG_2005;
58
59
		description = new TableModelDescription(new Property(model,
60
				"lodgings", Lodging.class, Boolean.TRUE),
61
				new String[] { "name", "description" });
62
63
		context.bind(viewer, description, null);
64
65
		manager = new TableViewerEditorManager(viewer, description.getColumnIDs(), context);
66
	}
67
68
	/*
69
	 * (non-Javadoc)
70
	 * 
71
	 * @see junit.framework.TestCase#tearDown()
72
	 */
73
	protected void tearDown() throws Exception {
74
		if (shell != null && !shell.isDisposed()) {
75
			shell.dispose();
76
			shell = null;
77
		}
78
	}
79
80
	public void testCreateControlIfItDoesntExist() throws Exception {
81
		TextCellEditor editor = new TextCellEditor();
82
83
		manager.setEditor(editor, "name", String.class, null);
84
		assertNotNull(viewer.getCellEditors()[0]);
85
	}
86
87
	public void testSetupViewerForEditing() throws Exception {
88
		assertNotNull(viewer.getCellModifier());
89
90
		assertNotNull(viewer.getColumnProperties());
91
		assertEquals(2, viewer.getColumnProperties().length);
92
		assertNotNull(viewer.getColumnProperties()[0]);
93
		assertEquals("name", viewer.getColumnProperties()[0]);
94
		
95
		assertNotNull(viewer.getCellEditors());
96
		assertEquals(2, viewer.getCellEditors().length);
97
		assertNull(viewer.getCellEditors()[0]);
98
		
99
		TextCellEditor editor = new TextCellEditor();
100
		manager.setEditor(editor, "name", String.class, null);
101
		
102
		assertEquals(editor, viewer.getCellEditors()[0]);
103
	}
104
105
	public void testSetValueInTextCellEditorOnEdit() throws Exception {
106
		TextCellEditor editor = new TextCellEditor();
107
		manager.setEditor(editor, "name", String.class, null);
108
109
		viewer.editElement(model.getLodgings()[0], 0);
110
111
		Lodging lodging = model.getLodgings()[0];
112
		assertEquals(lodging.getName(), editor.getValue());
113
	}
114
115
	public void testUpdateModelFromTextCellEditorAfterEdit() throws Exception {
116
		TextCellEditor editor = new TextCellEditor();
117
		manager.setEditor(editor, "name", String.class, null);
118
		
119
		Lodging lodging = model.getLodgings()[0];
120
		viewer.editElement(lodging, 0);
121
		
122
		assertTrue(editor.isActivated());
123
		
124
		String newValue = lodging.getName() + " new";
125
		editor.setValue(newValue);
126
		
127
		editor.getControl().notifyListeners(SWT.FocusOut, null);
128
		
129
		assertFalse(editor.isActivated());
130
		assertEquals(newValue, lodging.getName());
131
	}
132
133
	public void testToggleCheckboxCellEditorValueOnEdit() throws Exception {
134
		Category model = SampleData.WINTER_CATEGORY;
135
		description = new TableModelDescription(new Property(model,
136
				"adventures", Adventure.class, Boolean.TRUE),
137
				new String[] { "petsAllowed" });
138
139
		context.bind(viewer, description, null);
140
141
		manager = new TableViewerEditorManager(viewer, description.getColumnIDs(), context);
142
143
		CheckboxCellEditor editor = new CheckboxCellEditor();
144
		manager.setEditor(editor, "petsAllowed", boolean.class, null);
145
146
		Adventure adventure = model.getAdventures()[0];
147
		boolean old = adventure.isPetsAllowed();
148
		
149
		viewer.editElement(adventure, 0);
150
		
151
		assertEquals(!old, adventure.isPetsAllowed());
152
	}
153
	
154
	public void testRemoveEditor() throws Exception {
155
		TextCellEditor editor = new TextCellEditor();
156
		Binding binding = manager.setEditor(editor, "name", String.class, null);
157
		assertNotNull(binding);
158
		assertFalse(binding.isDisposed());
159
		
160
		ICellModifier cellModifier = viewer.getCellModifier();
161
		Lodging lodging = model.getLodgings()[0];
162
		assertTrue(cellModifier.canModify(lodging, "name"));
163
		
164
		manager.setEditor(null, "name", String.class, null);
165
		
166
		assertTrue(binding.isDisposed());
167
		assertFalse(cellModifier.canModify(lodging, "name"));
168
	}
169
	
170
	public void testSetEditorForExistingEditableColumn() throws Exception {
171
		TextCellEditor firstEditor = new TextCellEditor();
172
		Binding firstBinding = manager.setEditor(firstEditor, "name", String.class, null);
173
		assertFalse(firstBinding.isDisposed());
174
		
175
		TextCellEditor secondEditor = new TextCellEditor();
176
		Binding secondBinding = manager.setEditor(secondEditor, "name", String.class, null);
177
		assertTrue(firstBinding.isDisposed());
178
		assertFalse(secondBinding.isDisposed());
179
		
180
		ICellModifier cellModifier = viewer.getCellModifier();
181
		Lodging lodging = model.getLodgings()[0];
182
		assertTrue(cellModifier.canModify(lodging, "name"));
183
	}
184
	
185
	public void testSetEditorForInvalidColumnID() throws Exception {
186
		try {
187
			TextCellEditor editor = new TextCellEditor();
188
			manager.setEditor(editor, "bogus ID", String.class, null);
189
			fail("exception should have been thrown");
190
		} catch (IllegalArgumentException e) {
191
		}
192
	}
193
194
	public void testSetNullColumnID() throws Exception {
195
		try {
196
			TextCellEditor editor = new TextCellEditor();
197
			manager.setEditor(editor, null, String.class, null);
198
		} catch (IllegalArgumentException e) {
199
		}
200
	}
201
	
202
	public void testSetNullPropertyType() throws Exception {
203
		try {
204
			TextCellEditor editor = new TextCellEditor();
205
			manager.setEditor(editor, "name", null, null);
206
		} catch (IllegalArgumentException e) {
207
		}
208
	}
209
	
210
	public void testCellModifierOnlyAllowsEditingForColumnsWithAnEditor() throws Exception {
211
		ICellModifier modifier = viewer.getCellModifier();
212
		Lodging lodging = model.getLodgings()[0];
213
		
214
		TextCellEditor editor = new TextCellEditor();
215
		manager.setEditor(editor, "name", String.class, null);
216
		
217
		assertTrue(modifier.canModify(lodging, "name"));
218
		assertFalse(modifier.canModify(lodging, "description"));
219
	}
220
	
221
	public void testConstructWithNullTableViewer() throws Exception {
222
		try {
223
			manager = new TableViewerEditorManager(null, description.getColumnIDs(), context);
224
			fail("exception should have been thrown");
225
		} catch (IllegalArgumentException e) {
226
		}
227
	}
228
	
229
	public void testConstructWithNullTableModelDescription() throws Exception {
230
		try {
231
			manager = new TableViewerEditorManager(viewer, null, context);
232
			fail("exception should have been thrown");
233
		} catch (IllegalArgumentException e) {
234
		}
235
	}
236
	
237
	public void testConstructWithNullDataBindingContext() throws Exception {
238
		try {
239
			manager = new TableViewerEditorManager(viewer, description.getColumnIDs(), null);
240
			fail("exception should have been thrown");
241
		} catch (IllegalArgumentException e) {
242
		}
243
	}
244
	
245
	public void testGetEditor() throws Exception {
246
		assertNull(manager.getEditor("name"));
247
		
248
		TextCellEditor editor = new TextCellEditor();
249
		manager.setEditor(editor, "name", String.class, null);
250
		
251
		CellEditor nameEditor = manager.getEditor("name");
252
		assertNotNull(nameEditor);
253
		assertEquals(editor, nameEditor);
254
	}
255
	
256
	public void testGetInvalidEditor() throws Exception {
257
		try {
258
			manager.getEditor("column ID that does not exist");
259
			fail("exception should have been thrown");			
260
		} catch (IllegalArgumentException e) {
261
		}
262
	}
263
	
264
	public void testGetBinding() throws Exception {
265
		assertNull(manager.getBinding("name"));
266
		
267
		TextCellEditor editor = new TextCellEditor();
268
		Binding binding = manager.setEditor(editor, "name", String.class, null);
269
		
270
		Binding nameBinding = manager.getBinding("name");
271
		assertNotNull(nameBinding);
272
		assertEquals(binding, nameBinding);
273
	}
274
	
275
	public void testGetInvalidBinding() throws Exception {
276
		try {
277
			manager.getBinding("column ID that does not exist");
278
			fail("exception should have been thrown");
279
		} catch (IllegalArgumentException e) {
280
		}
281
	}
282
}
(-)src/org/eclipse/jface/tests/internal/databinding/provisional/viewers/TableViewerBindingFactoryTest.java (+224 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 Brad Reynolds 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
 *     Brad Reynolds - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.tests.internal.databinding.provisional.viewers;
13
14
import junit.framework.TestCase;
15
16
import org.eclipse.jface.examples.databinding.model.Catalog;
17
import org.eclipse.jface.examples.databinding.model.Lodging;
18
import org.eclipse.jface.examples.databinding.model.SampleData;
19
import org.eclipse.jface.internal.databinding.provisional.Binding;
20
import org.eclipse.jface.internal.databinding.provisional.DataBindingContext;
21
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
22
import org.eclipse.jface.internal.databinding.provisional.observable.list.WritableList;
23
import org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue;
24
import org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerBindingFactory;
25
import org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerBindingRecord;
26
import org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerEditorManager;
27
import org.eclipse.jface.internal.databinding.provisional.viewers.ViewersProperties;
28
import org.eclipse.jface.viewers.TableViewer;
29
import org.eclipse.jface.viewers.TextCellEditor;
30
import org.eclipse.swt.SWT;
31
import org.eclipse.swt.layout.RowLayout;
32
import org.eclipse.swt.widgets.Shell;
33
import org.eclipse.swt.widgets.Table;
34
import org.eclipse.swt.widgets.TableColumn;
35
import org.eclipse.swt.widgets.TableItem;
36
37
/**
38
 * @since 3.2
39
 */
40
public class TableViewerBindingFactoryTest extends TestCase {
41
	private Shell shell;
42
43
	private TableViewer viewer;
44
45
	private DataBindingContext context;
46
47
	private Catalog model;
48
	
49
	private TableViewerBindingFactory factory;
50
	
51
	/* (non-Javadoc)
52
	 * @see junit.framework.TestCase#setUp()
53
	 */
54
	protected void setUp() throws Exception {
55
		shell = new Shell();
56
		shell.setLayout(new RowLayout());
57
58
		viewer = new TableViewer(shell, SWT.NONE);
59
		context = SampleData.getDatabindingContext(shell);
60
		model = SampleData.CATALOG_2005;
61
		factory = new TableViewerBindingFactory();
62
	}
63
	
64
	/* (non-Javadoc)
65
	 * @see junit.framework.TestCase#tearDown()
66
	 */
67
	protected void tearDown() throws Exception {
68
		if (shell != null && !shell.isDisposed()) {
69
			shell.dispose();
70
			shell = null;
71
		}
72
	}
73
	
74
	public void testAddAndGetFactoryColumnIDs() throws Exception {
75
		Object[] columnIDs = factory.getColumnIDs();
76
		assertNotNull(columnIDs);
77
		assertEquals(0, columnIDs.length);
78
		
79
		factory.addColumn("name");
80
		columnIDs = factory.getColumnIDs();
81
		assertNotNull(columnIDs);
82
		assertEquals(1, columnIDs.length);
83
		assertEquals("name", columnIDs[0]);
84
		
85
		factory.addColumn("description");
86
		columnIDs = factory.getColumnIDs();
87
		assertEquals(2, columnIDs.length);
88
		assertEquals("name", columnIDs[0]);
89
		assertEquals("description", columnIDs[1]);
90
		
91
		assertEquals("name", factory.getColumnID(0));
92
		assertEquals("description", factory.getColumnID(1));
93
	}
94
	
95
	public void testBindingRecordValues() throws Exception {
96
		factory.addColumn("name");
97
		factory.addColumn("description");
98
99
		TableViewerBindingRecord record = factory.bind(viewer, model, "lodgings", Lodging.class, context, null);
100
		Object[] columnIDs = record.getColumnIDs();
101
		assertNotNull(columnIDs);
102
		assertEquals(2, columnIDs.length);
103
		assertEquals("name", columnIDs[0]);
104
		assertEquals("description", columnIDs[1]);
105
		
106
		assertNotNull(record.getBinding());
107
	}
108
	
109
	public void testBindProperty() throws Exception {
110
		Table table = viewer.getTable();
111
		for (int i = 0; i < 2; i++) {
112
			new TableColumn(table, SWT.NONE);
113
		}
114
				
115
		factory.addColumn("name");
116
		factory.addColumn("description");
117
		
118
		TableViewerBindingRecord tvb = factory.bind(viewer, model, "lodgings", Lodging.class, context, null);
119
		Binding binding = tvb.getBinding();
120
		assertNotNull(binding);
121
		
122
		//Assert the binding worked
123
		TableItem item = table.getItem(0);
124
		Lodging lodging = model.getLodgings()[0];
125
		assertEquals(lodging, item.getData());
126
		assertEquals(lodging.getName(), item.getText(0));
127
		assertEquals(lodging.getDescription(), item.getText(1));		
128
	}
129
	
130
	public void testAddEditableColumn() throws Exception {
131
		TextCellEditor nameEditor = new TextCellEditor();
132
		
133
		factory.addEditableColumn("name", nameEditor, String.class, null);
134
		factory.addColumn("description");
135
		
136
		TableViewerBindingRecord tvb = factory.bind(viewer, model, "lodgings", Lodging.class, context, null);
137
		TableViewerEditorManager editorManager = tvb.getTableViewerEditorManager();
138
		assertNotNull(editorManager);
139
		assertEquals(nameEditor, editorManager.getEditor("name"));
140
		
141
		assertNull(editorManager.getEditor("description"));
142
	}
143
	
144
	public void testAddEditableColumnWithNullEditor() throws Exception {
145
		try {
146
			factory.addEditableColumn("name", null, String.class, null);
147
			fail("exception should have been thrown");
148
		} catch (IllegalArgumentException e) {
149
		}		
150
	}
151
	
152
	public void testAddEditableColumnWithNullPropertyType() throws Exception {
153
		try {
154
			factory.addEditableColumn("name", new TextCellEditor(), null, null);
155
			fail("exception should have been thrown");
156
		} catch (IllegalArgumentException e) {
157
		}
158
	}
159
	
160
	public void testBindObservableList() throws Exception {
161
		WritableList list = new WritableList(Lodging.class);
162
		Lodging lodging = new Lodging();
163
		lodging.setName("lodging name");
164
		list.add(lodging);
165
		
166
		factory.addColumn("name");
167
		
168
		TableViewerBindingRecord tvb = factory.bind(viewer, list, context, null);
169
		assertNotNull(tvb.getBinding());
170
		
171
		//Assert the binding worked
172
		Table table = viewer.getTable();
173
		TableItem item = table.getItem(0);
174
		assertEquals(lodging, item.getData());
175
		assertEquals(lodging.getName(), item.getText(0));
176
	}
177
	
178
	public void testAddNullColumnID() throws Exception {
179
		try {
180
			factory.addColumn(null);
181
			fail("exception should have been thrown");
182
		} catch (IllegalArgumentException e) {
183
		}
184
	}
185
	
186
	public void testGetContentObservable() throws Exception {
187
		Table table = viewer.getTable();
188
		for (int i = 0; i < 2; i++) {
189
			new TableColumn(table, SWT.NONE);
190
		}
191
		
192
		factory.addColumn("name");
193
		factory.addColumn("description");
194
		
195
		TableViewerBindingRecord tvb = factory.bind(viewer, model, "lodgings", Lodging.class, context, null);
196
		
197
		IObservable observable = tvb.getObservable(ViewersProperties.CONTENT);
198
		assertNotNull(observable);
199
	}
200
	
201
	public void testGetSelectionObservableValue() throws Exception {
202
		Table table = viewer.getTable();
203
		for (int i = 0; i < 2; i++) {
204
			new TableColumn(table, SWT.NONE);
205
		}
206
				
207
		factory.addColumn("name");
208
		factory.addColumn("description");
209
		
210
		TableViewerBindingRecord record = factory.bind(viewer, model, "lodgings", Lodging.class, context, null);
211
		
212
		IObservableValue selectionObservable = record.getSelection();
213
		assertNotNull(selectionObservable);
214
		
215
		//assert that only one selection observable is created
216
		assertSame(selectionObservable, record.getSelection());
217
		
218
		table.setSelection(0);
219
		assertEquals(model.getLodgings()[0], selectionObservable.getValue());
220
		
221
		table.setSelection(1);
222
		assertEquals(model.getLodgings()[1], selectionObservable.getValue());
223
	}
224
}
(-)src/org/eclipse/jface/tests/internal/databinding/provisional/viewers/BooleanCellEditorObservableValueTest.java (+162 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 Brad Reynolds 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
 *     Brad Reynolds - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.tests.internal.databinding.provisional.viewers;
13
14
import junit.framework.TestCase;
15
16
import org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue;
17
import org.eclipse.jface.internal.databinding.provisional.observable.value.IValueChangeListener;
18
import org.eclipse.jface.internal.databinding.provisional.observable.value.ValueDiff;
19
import org.eclipse.jface.internal.databinding.provisional.viewers.BooleanCellEditorObservableValue;
20
import org.eclipse.jface.viewers.CheckboxCellEditor;
21
22
/**
23
 * @since 3.2
24
 */
25
public class BooleanCellEditorObservableValueTest extends TestCase {
26
	private BooleanCellEditorObservableValue observable;
27
28
	private MyCheckboxCellEditor cellEditor;
29
30
	protected void setUp() throws Exception {
31
		cellEditor = new MyCheckboxCellEditor();
32
		cellEditor.setValue(Boolean.FALSE);
33
		observable = new BooleanCellEditorObservableValue(cellEditor);
34
	}
35
36
	private class MyCheckboxCellEditor extends CheckboxCellEditor {
37
		protected void setValueValid(boolean valid) {
38
			// TODO Auto-generated method stub
39
			super.setValueValid(valid);
40
		}
41
	}
42
43
	public void testConstructionIllegalArgumentExceptions() throws Exception {
44
		try {
45
			new BooleanCellEditorObservableValue(null);
46
			fail("Exception should have been thrown.");
47
		} catch (IllegalArgumentException e) {
48
		}
49
	}
50
51
	public void testGetValueType() throws Exception {
52
		assertEquals(Boolean.class, observable.getValueType());
53
	}
54
55
	public void testGetValue() throws Exception {
56
		cellEditor.setValue(Boolean.TRUE);
57
		assertEquals(Boolean.TRUE, observable.getValue());
58
		cellEditor.setValue(Boolean.FALSE);
59
		assertEquals(Boolean.FALSE, observable.getValue());
60
	}
61
62
	public void testSetFalseWhenCellEditorValueIsNull() throws Exception {
63
		cellEditor.setValueValid(false);
64
		assertNull(cellEditor.getValue());
65
		observable.setValue(Boolean.FALSE);
66
		Boolean editorValue = (Boolean) cellEditor.getValue();
67
		assertNotNull(editorValue);
68
		assertEquals(Boolean.FALSE, editorValue);
69
	}
70
71
	public void testObservableSetValueSame() throws Exception {
72
		ValueChangeCounter listener = new ValueChangeCounter();
73
		observable.addValueChangeListener(listener);
74
		assertEquals(0, listener.count);
75
		assertEquals(Boolean.FALSE, observable.getValue());
76
		assertEquals(Boolean.FALSE, cellEditor.getValue());
77
78
		observable.setValue(Boolean.FALSE);
79
80
		assertEquals(0, listener.count);
81
		assertEquals(Boolean.FALSE, observable.getValue());
82
		assertEquals(Boolean.FALSE, cellEditor.getValue());
83
	}
84
85
	public void testObservableSetValueDifferent() throws Exception {
86
		ValueChangeCounter listener = new ValueChangeCounter();
87
		observable.addValueChangeListener(listener);
88
		assertEquals(0, listener.count);
89
		assertEquals(Boolean.FALSE, observable.getValue());
90
		assertEquals(Boolean.FALSE, cellEditor.getValue());
91
92
		observable.setValue(Boolean.TRUE);
93
94
		assertEquals(1, listener.count);
95
		assertEquals(Boolean.TRUE, observable.getValue());
96
		assertEquals(Boolean.TRUE, cellEditor.getValue());
97
98
		assertEquals(observable, listener.source);
99
		assertEquals(Boolean.FALSE, listener.diff.getOldValue());
100
		assertEquals(Boolean.TRUE, listener.diff.getNewValue());
101
	}
102
103
	public void testCellEditorChangeValue() throws Exception {
104
		ValueChangeCounter listener = new ValueChangeCounter();
105
		observable.addValueChangeListener(listener);
106
		assertEquals(0, listener.count);
107
		assertEquals(Boolean.FALSE, observable.getValue());
108
		assertEquals(Boolean.FALSE, cellEditor.getValue());
109
110
		cellEditor.activate();
111
112
		assertEquals(1, listener.count);
113
		assertEquals(Boolean.TRUE, observable.getValue());
114
		assertEquals(Boolean.TRUE, cellEditor.getValue());
115
116
		assertEquals(observable, listener.source);
117
		assertEquals(Boolean.FALSE, listener.diff.getOldValue());
118
		assertEquals(Boolean.TRUE, listener.diff.getNewValue());
119
	}
120
121
	public void testCellEditorSetValueDifferent() throws Exception {
122
		ValueChangeCounter listener = new ValueChangeCounter();
123
		observable.addValueChangeListener(listener);
124
		assertEquals(0, listener.count);
125
		assertEquals(Boolean.FALSE, observable.getValue());
126
		assertEquals(Boolean.FALSE, cellEditor.getValue());
127
128
		cellEditor.setValue(Boolean.TRUE);
129
130
		assertEquals(0, listener.count);
131
		assertEquals(Boolean.TRUE, observable.getValue());
132
		assertEquals(Boolean.TRUE, cellEditor.getValue());
133
	}
134
135
	public void testSetObservableNullValue() throws Exception {
136
		ValueChangeCounter listener = new ValueChangeCounter();
137
		observable.addValueChangeListener(listener);
138
		assertEquals(0, listener.count);
139
		assertEquals(Boolean.FALSE, observable.getValue());
140
		assertEquals(Boolean.FALSE, cellEditor.getValue());
141
142
		observable.setValue(null);
143
144
		assertEquals(0, listener.count);
145
		assertEquals(Boolean.FALSE, observable.getValue());
146
		assertEquals(Boolean.FALSE, cellEditor.getValue());
147
	}
148
149
	private class ValueChangeCounter implements IValueChangeListener {
150
		private int count;
151
152
		private IObservableValue source;
153
154
		private ValueDiff diff;
155
156
		public void handleValueChange(IObservableValue source, ValueDiff diff) {
157
			count++;
158
			this.source = source;
159
			this.diff = diff;
160
		}
161
	}
162
}
(-)src/org/eclipse/jface/internal/databinding/provisional/viewers/ViewersObservableFactory.java (-2 / +29 lines)
Lines 8-33 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *     Brad Reynolds - bug 137877
10
 *     Brad Reynolds - bug 137877
11
 *     Brad Reynolds - bug 144260
11
 *******************************************************************************/
12
 *******************************************************************************/
12
13
13
package org.eclipse.jface.internal.databinding.provisional.viewers;
14
package org.eclipse.jface.internal.databinding.provisional.viewers;
14
15
16
import org.eclipse.jface.internal.databinding.internal.swt.TextObservableValue;
15
import org.eclipse.jface.internal.databinding.internal.viewers.AbstractListViewerObservableCollectionWithLabels;
17
import org.eclipse.jface.internal.databinding.internal.viewers.AbstractListViewerObservableCollectionWithLabels;
16
import org.eclipse.jface.internal.databinding.internal.viewers.SelectionProviderSingleSelectionObservableValue;
18
import org.eclipse.jface.internal.databinding.internal.viewers.SelectionProviderSingleSelectionObservableValue;
17
import org.eclipse.jface.internal.databinding.internal.viewers.TableViewerObservableCollectionWithLabels;
19
import org.eclipse.jface.internal.databinding.internal.viewers.TableViewerObservableCollectionWithLabels;
18
import org.eclipse.jface.internal.databinding.provisional.description.Property;
20
import org.eclipse.jface.internal.databinding.provisional.description.Property;
21
import org.eclipse.jface.internal.databinding.provisional.description.TableModelDescription;
19
import org.eclipse.jface.internal.databinding.provisional.factories.IObservableFactory;
22
import org.eclipse.jface.internal.databinding.provisional.factories.IObservableFactory;
20
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
23
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
21
import org.eclipse.jface.viewers.AbstractListViewer;
24
import org.eclipse.jface.viewers.AbstractListViewer;
25
import org.eclipse.jface.viewers.CellEditor;
26
import org.eclipse.jface.viewers.CheckboxCellEditor;
22
import org.eclipse.jface.viewers.ISelectionProvider;
27
import org.eclipse.jface.viewers.ISelectionProvider;
23
import org.eclipse.jface.viewers.TableViewer;
28
import org.eclipse.jface.viewers.TableViewer;
29
import org.eclipse.jface.viewers.TextCellEditor;
30
import org.eclipse.swt.SWT;
31
import org.eclipse.swt.widgets.Text;
24
32
25
/**
33
/**
26
 * A factory that supports binding to JFace viewers. This factory supports the
34
 * A factory that supports binding to JFace viewers. This factory supports the
27
 * following description objects:
35
 * following description objects:
28
 * <ul>
36
 * <ul>
29
 * <li>{@link AbstractListViewer} - denotes the viewer's collection of elements</li>
37
 * <li>{@link AbstractListViewer} - denotes the viewer's collection of elements</li>
30
 * <li>{@link TableViewerDescription} - TODO describe</li>
38
 * <li>{@link TableModelDescription} - TODO describe</li>
31
 * <li>org.eclipse.jface.databinding.PropertyDescription - depending on the
39
 * <li>org.eclipse.jface.databinding.PropertyDescription - depending on the
32
 * property description's object and property ID:
40
 * property description's object and property ID:
33
 * <ul>
41
 * <ul>
Lines 37-42 Link Here
37
 * {@link ViewersProperties#CONTENT}</li>
45
 * {@link ViewersProperties#CONTENT}</li>
38
 * <li>object instanceof AbstractListViewer, property ID is
46
 * <li>object instanceof AbstractListViewer, property ID is
39
 * {@link ViewersProperties#CONTENT}</li>
47
 * {@link ViewersProperties#CONTENT}</li>
48
 * <li>object instanceof <code>TextCellEditor</code></li>
49
 * <li>object instanceof <code>CheckboxCellEditor</code></li>
40
 * </ul>
50
 * </ul>
41
 * </li>
51
 * </li>
42
 * </ul>
52
 * </ul>
Lines 54-60 Link Here
54
	}
64
	}
55
65
56
	/**
66
	/**
57
	 * @param updateTime.
67
	 * @param updateTime
58
	 *            Update policy of DataBindingContext.TIME_EARLY or TIME_LATE.
68
	 *            Update policy of DataBindingContext.TIME_EARLY or TIME_LATE.
59
	 *            This is only a hint that some editable viewers may support
69
	 *            This is only a hint that some editable viewers may support
60
	 */
70
	 */
Lines 84-90 Link Here
84
		} else if (description instanceof TableViewer) {
94
		} else if (description instanceof TableViewer) {
85
			return new TableViewerObservableCollectionWithLabels(
95
			return new TableViewerObservableCollectionWithLabels(
86
					(TableViewer) description);
96
					(TableViewer) description);
97
		} else if (description instanceof CellEditor) {
98
			if (description instanceof TextCellEditor) {
99
				TextCellEditor editor = (TextCellEditor) description;
100
101
				if (editor.getControl() == null) {
102
					throw new IllegalArgumentException(
103
							"The TextCellEditor control must be created before creating the observable."); //$NON-NLS-1$
104
				}
105
106
				//Updating of the model will need to be done manually, hence the SWT.NONE.
107
				return new TextObservableValue((Text) editor.getControl(),
108
						SWT.NONE);
109
			} else if (description instanceof CheckboxCellEditor) {
110
				return new BooleanCellEditorObservableValue(
111
						(CheckboxCellEditor) description);
112
			}
87
		}
113
		}
114
88
		return null;
115
		return null;
89
	}
116
	}
90
}
117
}
(-)src/org/eclipse/jface/internal/databinding/provisional/viewers/TableViewerBindingFactory.java (+351 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 Brad Reynolds 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
 *     Brad Reynolds - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.provisional.viewers;
13
14
import java.util.ArrayList;
15
import java.util.HashMap;
16
import java.util.Iterator;
17
import java.util.LinkedList;
18
import java.util.List;
19
import java.util.Map;
20
21
import org.eclipse.jface.internal.databinding.provisional.BindSpec;
22
import org.eclipse.jface.internal.databinding.provisional.Binding;
23
import org.eclipse.jface.internal.databinding.provisional.DataBindingContext;
24
import org.eclipse.jface.internal.databinding.provisional.description.Property;
25
import org.eclipse.jface.internal.databinding.provisional.description.TableModelDescription;
26
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
27
import org.eclipse.jface.internal.databinding.provisional.observable.list.IObservableList;
28
import org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue;
29
import org.eclipse.jface.viewers.CellEditor;
30
import org.eclipse.jface.viewers.TableViewer;
31
import org.eclipse.swt.events.DisposeEvent;
32
import org.eclipse.swt.events.DisposeListener;
33
34
/**
35
 * Builds a binding for a <code>TableViewer</code>.
36
 * 
37
 * @since 3.2
38
 */
39
public class TableViewerBindingFactory {
40
	/**
41
	 * Empty array to represent no column IDs.
42
	 */
43
	private static final Object[] NO_COLUMN_IDS = new Object[0];
44
45
	/**
46
	 * Maintains the order of columns.
47
	 */
48
	private List columnIDs;
49
50
	/**
51
	 * Maintains columnData instances keyed by column ID.
52
	 */
53
	private Map columnDatas;
54
55
	/**
56
	 * Constructs a new instance.
57
	 */
58
	public TableViewerBindingFactory() {
59
	}
60
61
	/**
62
	 * Adds a column to the binding.
63
	 * 
64
	 * @param columnID
65
	 */
66
	public void addColumn(Object columnID) {
67
		addColumn(columnID, null, null, null);
68
	}
69
70
	/**
71
	 * Adds a column that is to be edited with the provided editor data.
72
	 * 
73
	 * @param columnID
74
	 * @param cellEditor
75
	 * @param propertyType
76
	 * @param bindSpec
77
	 */
78
	private void addColumn(Object columnID, CellEditor cellEditor,
79
			Class propertyType, BindSpec bindSpec) {
80
		if (columnID == null) {
81
			throw new IllegalArgumentException(
82
					"Parameter " + columnID + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
83
		}
84
85
		if (columnDatas == null) {
86
			columnIDs = new ArrayList();
87
			columnDatas = new HashMap();
88
		}
89
90
		columnIDs.add(columnID);
91
		columnDatas.put(columnID, new ColumnData(cellEditor, propertyType,
92
				bindSpec));
93
	}
94
95
	/**
96
	 * Adds a column that is to be edited using the editor data.
97
	 * 
98
	 * @param columnID
99
	 * @param cellEditor
100
	 * @param propertyType
101
	 * @param bindSpec
102
	 *            can be <code>null</code>
103
	 */
104
	public void addEditableColumn(Object columnID, CellEditor cellEditor,
105
			Class propertyType, BindSpec bindSpec) {
106
		if (columnID == null) {
107
			throw new IllegalArgumentException(
108
					"Parameter " + columnID + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
109
		}
110
		if (cellEditor == null) {
111
			throw new IllegalArgumentException(
112
					"Parameter " + cellEditor + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
113
		}
114
		if (propertyType == null) {
115
			throw new IllegalArgumentException(
116
					"Parameter " + propertyType + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
117
		}
118
119
		addColumn(columnID, cellEditor, propertyType, bindSpec);
120
	}
121
122
	/**
123
	 * Returns the columnID for the column index.
124
	 * 
125
	 * @param columnIndex
126
	 * @return column ID
127
	 */
128
	public Object getColumnID(int columnIndex) {
129
		if (columnIDs == null || columnIndex >= columnIDs.size()
130
				|| columnIndex < 0) {
131
			throw new IllegalArgumentException(
132
					"Parameter columnIndex [" + columnIndex + "] is out of bounds."); //$NON-NLS-1$//$NON-NLS-2$
133
		}
134
135
		return columnIDs.get(columnIndex);
136
	}
137
138
	/**
139
	 * @return Number of columns added to the factory.
140
	 */
141
	public int getColumnCount() {
142
		return (columnDatas != null) ? columnDatas.size() : 0;
143
	}
144
145
	/**
146
	 * Binds a viewer to the provided <code>propertyName</code> of the
147
	 * <code>model</code> which contains objects of the provided
148
	 * <code>propertyType</code>.
149
	 * 
150
	 * @param viewer
151
	 * @param model
152
	 * @param propertyName
153
	 * @param propertyType
154
	 * @param context
155
	 * @param bindSpec
156
	 * @return binding manager
157
	 */
158
	public TableViewerBindingRecord bind(TableViewer viewer, Object model,
159
			String propertyName, Class propertyType,
160
			DataBindingContext context, BindSpec bindSpec) {
161
		TableModelDescription description = new TableModelDescription(
162
				new Property(model, propertyName, propertyType, Boolean.TRUE),
163
				getColumnIDs());
164
		return bind(viewer, description, context, bindSpec);
165
	}
166
167
	/**
168
	 * Binds a viewer to the provided <code>observableList</code>.
169
	 * 
170
	 * @param viewer
171
	 * @param observableList
172
	 * @param context
173
	 * @param bindSpec
174
	 * 
175
	 * @return binding manager
176
	 */
177
	public TableViewerBindingRecord bind(TableViewer viewer,
178
			IObservableList observableList, DataBindingContext context,
179
			BindSpec bindSpec) {
180
		TableModelDescription description = new TableModelDescription(
181
				observableList, getColumnIDs());
182
183
		return bind(viewer, description, context, bindSpec);
184
	}
185
186
	private TableViewerBindingRecord bind(TableViewer viewer,
187
			TableModelDescription description, DataBindingContext context,
188
			BindSpec bindSpec) {
189
		// Perform the binding.
190
		Binding binding = context.bind(viewer, description, bindSpec);
191
192
		// Setup editing.
193
		TableViewerEditorManager editorManager = new TableViewerEditorManager(
194
				viewer, description.getColumnIDs(), context);
195
		if (columnDatas != null) {
196
			for (Iterator it = columnIDs.iterator(); it.hasNext();) {
197
				Object columnID = it.next();
198
				ColumnData data = (ColumnData) columnDatas.get(columnID);
199
				if (data.editor != null) {
200
					editorManager.setEditor(data.editor, columnID,
201
							data.propertyType, data.bindSpec);
202
				}
203
			}
204
		}
205
206
		return new TableViewerBindingRecordImpl(viewer, context, binding,
207
				editorManager, description.getColumnIDs());
208
	}
209
210
	/**
211
	 * @return columnIDs, empty array if none
212
	 */
213
	public Object[] getColumnIDs() {
214
		Object[] result = NO_COLUMN_IDS;
215
216
		if (columnIDs != null) {
217
			result = columnIDs.toArray();
218
		}
219
		return result;
220
	}
221
222
	/**
223
	 * Manages relationship between columnID and the editor data.
224
	 * 
225
	 * @since 3.2
226
	 */
227
	private static class ColumnData {
228
		private final CellEditor editor;
229
230
		private final Class propertyType;
231
232
		private final BindSpec bindSpec;
233
234
		/**
235
		 * Constructs a new instance.
236
		 * 
237
		 * @param editor
238
		 * @param propertyType
239
		 * @param bindSpec
240
		 */
241
		public ColumnData(CellEditor editor, Class propertyType,
242
				BindSpec bindSpec) {
243
			this.editor = editor;
244
			this.propertyType = propertyType;
245
			this.bindSpec = bindSpec;
246
		}
247
	}
248
249
	/**
250
	 * Implementation of TableViewerBindingRecord to use internally.
251
	 * 
252
	 * @since 3.2
253
	 */
254
	private static class TableViewerBindingRecordImpl extends
255
			TableViewerBindingRecord {
256
		private final TableViewer viewer;
257
258
		private final DataBindingContext context;
259
260
		private final Binding binding;
261
262
		private final TableViewerEditorManager manager;
263
264
		private final Object[] columnIDs;
265
266
		private IObservableValue selection;
267
268
		private LinkedList observables;
269
270
		TableViewerBindingRecordImpl(TableViewer viewer,
271
				DataBindingContext context, Binding binding,
272
				TableViewerEditorManager manager, Object[] columnIDs) {
273
			this.viewer = viewer;
274
			this.context = context;
275
			this.binding = binding;
276
			this.manager = manager;
277
			this.columnIDs = columnIDs;
278
279
			viewer.getTable().addDisposeListener(new DisposeListener() {
280
				public void widgetDisposed(DisposeEvent e) {
281
					if (observables != null) {
282
						for (Iterator it = observables.iterator(); it.hasNext();) {
283
							((IObservable) it.next()).dispose();
284
						}
285
286
						observables.clear();
287
					}
288
				}
289
			});
290
		}
291
292
		/*
293
		 * (non-Javadoc)
294
		 * 
295
		 * @see org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerBindingRecord#getBinding()
296
		 */
297
		public Binding getBinding() {
298
			return binding;
299
		}
300
301
		/*
302
		 * (non-Javadoc)
303
		 * 
304
		 * @see org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerBindingRecord#getColumnIDs()
305
		 */
306
		public Object[] getColumnIDs() {
307
			return columnIDs;
308
		}
309
310
		/*
311
		 * (non-Javadoc)
312
		 * 
313
		 * @see org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerBindingRecord#getObservable(int)
314
		 */
315
		public IObservable getObservable(String viewersProperty) {
316
			IObservable observable = context.createObservable(new Property(
317
					viewer, viewersProperty));
318
			if (observables == null) {
319
				observables = new LinkedList();
320
			}
321
322
			observables.add(observable);
323
324
			return observable;
325
		}
326
327
		/*
328
		 * (non-Javadoc)
329
		 * 
330
		 * @see org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerBindingRecord#getSelection()
331
		 */
332
		public IObservableValue getSelection() {
333
			IObservableValue result = this.selection;
334
335
			if (result == null) {
336
				this.selection = result = (IObservableValue) getObservable(ViewersProperties.SINGLE_SELECTION);
337
			}
338
339
			return result;
340
		}
341
342
		/*
343
		 * (non-Javadoc)
344
		 * 
345
		 * @see org.eclipse.jface.internal.databinding.provisional.viewers.TableViewerBindingRecord#getTableViewerEditorManager()
346
		 */
347
		public TableViewerEditorManager getTableViewerEditorManager() {
348
			return manager;
349
		}
350
	}
351
}
(-)src/org/eclipse/jface/internal/databinding/provisional/viewers/TableViewerBindingRecord.java (+49 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 Brad Reynolds 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
 *     Brad Reynolds - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.provisional.viewers;
13
14
import org.eclipse.jface.internal.databinding.provisional.Binding;
15
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
16
import org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue;
17
18
/**
19
 * Maintains the artifacts of the binding of a TableViewer.
20
 * 
21
 * @since 3.2
22
 */
23
public abstract class TableViewerBindingRecord {
24
	/**
25
	 * @return column IDs provided when the viewer was bound
26
	 */
27
	public abstract Object[] getColumnIDs();
28
	
29
	/**
30
	 * @return binding for the viewer
31
	 */
32
	public abstract Binding getBinding();
33
	
34
	/**
35
	 * @return manager that provides access to the editing capabilities of the binding
36
	 */
37
	public abstract TableViewerEditorManager getTableViewerEditorManager();
38
	
39
	/**
40
	 * @param viewersProperty
41
	 * @return observable for the provided {@link ViewersProperties viewer property}
42
	 */
43
	public abstract IObservable getObservable(String viewersProperty);
44
	
45
	/**
46
	 * @return observable value for the selection of the table viewer
47
	 */
48
	public abstract IObservableValue getSelection();
49
}
(-)src/org/eclipse/jface/internal/databinding/provisional/viewers/TableViewerEditorManager.java (+320 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 Brad Reynolds 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
 *     Brad Reynolds - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.provisional.viewers;
13
14
import org.eclipse.jface.internal.databinding.provisional.BindSpec;
15
import org.eclipse.jface.internal.databinding.provisional.Binding;
16
import org.eclipse.jface.internal.databinding.provisional.DataBindingContext;
17
import org.eclipse.jface.internal.databinding.provisional.description.Property;
18
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
19
import org.eclipse.jface.internal.databinding.provisional.observable.value.AbstractObservableValue;
20
import org.eclipse.jface.internal.databinding.provisional.observable.value.ValueDiff;
21
import org.eclipse.jface.util.Assert;
22
import org.eclipse.jface.viewers.CellEditor;
23
import org.eclipse.jface.viewers.ICellModifier;
24
import org.eclipse.jface.viewers.TableViewer;
25
import org.eclipse.swt.widgets.Item;
26
27
/**
28
 * Manages the editing of a bound <code>TableViewer</code>.
29
 * <p>
30
 * The <code>CellEditor</code> must not propagate changes to the model on its
31
 * own. This is facilitated by this manager and if the editor was to propagate
32
 * changes on its own the behavior is undefined.
33
 * </p>
34
 * 
35
 * @since 3.2
36
 */
37
public class TableViewerEditorManager {
38
	private final Object[] columnIDs;
39
40
	/**
41
	 * Viewer to associate editors with.
42
	 */
43
	private final TableViewer viewer;
44
45
	/**
46
	 * Bindings that have been created for editors.
47
	 */
48
	private Binding[] bindings;
49
50
	/**
51
	 * DBC to use for creating editor bindings.
52
	 */
53
	private final DataBindingContext context;
54
55
	/**
56
	 * Observable that represents the element being edited. This is set in
57
	 * CellModifer getValue as this is the only place that we have access to
58
	 * this.
59
	 */
60
	private EditableElement editableElement;
61
62
	/**
63
	 * Constructs a new instance.
64
	 * 
65
	 * @param viewer
66
	 * @param columnIDs
67
	 * @param context
68
	 */
69
	public TableViewerEditorManager(TableViewer viewer, Object[] columnIDs,
70
			DataBindingContext context) {
71
		if (viewer == null) {
72
			throw new IllegalArgumentException(
73
					"Parameter " + viewer + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
74
		}
75
		if (columnIDs == null) {
76
			throw new IllegalArgumentException(
77
					"Parameter " + columnIDs + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
78
		}
79
		if (context == null) {
80
			throw new IllegalArgumentException(
81
					"Parameter " + context + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
82
		}
83
84
		this.viewer = viewer;
85
		this.context = context;
86
		this.columnIDs = columnIDs;
87
88
		int columnCount = (columnIDs != null) ? columnIDs.length : 0;
89
90
		viewer.setCellEditors(new CellEditor[columnCount]);
91
92
		String[] properties = new String[columnCount];
93
		viewer.setColumnProperties(properties);
94
95
		for (int i = 0; i < columnCount; i++) {
96
			properties[i] = columnIDs[i].toString();
97
		}
98
99
		editableElement = new EditableElement();
100
		bindings = new Binding[columnCount];
101
102
		viewer.setCellModifier(new CellModifier());
103
	}
104
	
105
	/**
106
	 * Returns the binding for the columnID.
107
	 * 
108
	 * @param columnID 
109
	 * @return binding, <code>null</code> if a binding doesn't exist because there is no editor.
110
	 */
111
	public Binding getBinding(Object columnID) {
112
		int columnIndex = getValidColumnIndex(columnID);
113
114
		return bindings[columnIndex];
115
	}
116
117
	/**
118
	 * Retuns the editor for the columnID.
119
	 * 
120
	 * @param columnID 
121
	 * @return editor, <code>null</code> if an editor was not set
122
	 */
123
	public CellEditor getEditor(Object columnID) {
124
		int columnIndex = getValidColumnIndex(columnID);
125
126
		return viewer.getCellEditors()[columnIndex];
127
	}
128
	
129
	/**
130
	 * Sets a <code>editor</code> as the editor for the provided
131
	 * <code>columnID</code>.
132
	 * 
133
	 * @param editor
134
	 *            if <code>null</code> removes the current editor
135
	 * @param columnID
136
	 * @param propertyType
137
	 *            type of the attribute to be edited
138
	 * @param bindSpec
139
	 *            can be <code>null</code>
140
	 * @return binding for the editor
141
	 */
142
	public Binding setEditor(CellEditor editor, Object columnID,
143
			Class propertyType, BindSpec bindSpec) {
144
		if (columnID == null) {
145
			throw new IllegalArgumentException(
146
					"Parameter " + columnID + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
147
		}
148
		if (propertyType == null) {
149
			throw new IllegalArgumentException(
150
					"Parameter " + propertyType + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
151
		}
152
153
		int columnIndex = getValidColumnIndex(columnID);
154
		viewer.getCellEditors()[columnIndex] = editor;
155
		Binding existingBinding = bindings[columnIndex];
156
157
		if (existingBinding != null) {
158
			// Remove the existing editor.
159
			existingBinding.dispose();
160
			bindings[columnIndex] = null;
161
		}
162
163
		Binding result = null;
164
165
		if (editor != null) {
166
			if (editor.getControl() == null) {
167
				editor.create(viewer.getTable());
168
			}
169
170
			IObservable observable = context.createObservable(new Property(
171
					editableElement, columnID, propertyType, Boolean.FALSE));
172
173
			result = context.bind(editor, observable, bindSpec);
174
			bindings[columnIndex] = result;
175
		}
176
177
		return result;
178
	}
179
180
	/**
181
	 * Returns the index for the column ID.
182
	 * 
183
	 * @param columnID
184
	 * @return column index, -1 if not found
185
	 */
186
	private int getColumnIndex(Object columnID) {
187
		int columnIndex = -1;
188
		for (int i = 0; columnIndex == -1 && i < columnIDs.length; i++) {
189
			if (columnID.equals(columnIDs[i])) {
190
				columnIndex = i;
191
			}
192
		}
193
194
		return columnIndex;
195
	}
196
197
	/**
198
	 * Returns the column index of the provided <code>columnID</code>.
199
	 * 
200
	 * @param columnID
201
	 * @return index
202
	 * @throws IllegalArgumentException
203
	 *             if columnID is invalid.
204
	 */
205
	private int getValidColumnIndex(Object columnID) {
206
		int index = getColumnIndex(columnID);
207
208
		if (index <= -1) {
209
			throw new IllegalArgumentException(
210
					"ColumnID [" + columnID + "] is an invalid columnID."); //$NON-NLS-1$//$NON-NLS-2$
211
		}
212
213
		return index;
214
	}
215
216
	/**
217
	 * Observable for the element being edited.
218
	 * 
219
	 * @since 3.2
220
	 */
221
	private static class EditableElement extends AbstractObservableValue {
222
		private Object element;
223
224
		/*
225
		 * (non-Javadoc)
226
		 * 
227
		 * @see org.eclipse.jface.internal.databinding.provisional.observable.value.AbstractObservableValue#setValue(java.lang.Object)
228
		 */
229
		public void setValue(Object value) {
230
			final Object old = element;
231
			element = value;
232
			fireValueChange(new ValueDiff() {
233
				public Object getNewValue() {
234
					return element;
235
				}
236
237
				public Object getOldValue() {
238
					return old;
239
				}
240
			});
241
		}
242
243
		/*
244
		 * (non-Javadoc)
245
		 * 
246
		 * @see org.eclipse.jface.internal.databinding.provisional.observable.value.AbstractObservableValue#doGetValue()
247
		 */
248
		protected Object doGetValue() {
249
			return element;
250
		}
251
252
		/*
253
		 * (non-Javadoc)
254
		 * 
255
		 * @see org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue#getValueType()
256
		 */
257
		public Object getValueType() {
258
			return Object.class;
259
		}
260
	}
261
262
	/**
263
	 * <code>ICellModifier</code> implementation to be used in data binding
264
	 * that when requested retrieves the values from the model and sets the
265
	 * value in the model. The observables should not automatically update the
266
	 * model, the cell modifier handles this.
267
	 * 
268
	 * @since 3.2
269
	 */
270
	private class CellModifier implements ICellModifier {
271
		public boolean canModify(Object element, String property) {
272
			int columnIndex = getColumnIndex(property);
273
			Assert.isTrue(columnIndex > -1);
274
275
			return bindings[columnIndex] != null;
276
		}
277
278
		/*
279
		 * (non-Javadoc)
280
		 * 
281
		 * @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object,
282
		 *      java.lang.String)
283
		 */
284
		public Object getValue(Object element, String property) {
285
			if (editableElement.getValue() != element) {
286
				editableElement.setValue(element);
287
			}
288
289
			Binding binding = getBinding(property);
290
			Assert.isNotNull(binding);
291
			binding.updateTargetFromModel();
292
293
			/*
294
			 * Something has to be returned so just pass the value of the
295
			 * editor, it's the correct value at this point. This will end up
296
			 * setting the value twice but the observable shouldn't fire 2
297
			 * change events as the value didn't change on the second set.
298
			 */
299
			return getEditor(property).getValue();
300
		}
301
302
		/*
303
		 * (non-Javadoc)
304
		 * 
305
		 * @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object,
306
		 *      java.lang.String, java.lang.Object)
307
		 */
308
		public void modify(Object element, String property, Object value) {
309
			element = ((Item) element).getData();
310
			Assert.isTrue(editableElement.getValue().equals(element));
311
312
			Binding binding = getBinding(property);
313
			Assert.isNotNull(binding);
314
			binding.updateModelFromTarget();
315
316
			editableElement.setValue(null);
317
		}
318
	}
319
320
}
(-)src/org/eclipse/jface/internal/databinding/provisional/viewers/BooleanCellEditorObservableValue.java (+113 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 Brad Reynolds 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
 *     Brad Reynolds - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.internal.databinding.provisional.viewers;
13
14
import org.eclipse.jface.internal.databinding.provisional.observable.Diffs;
15
import org.eclipse.jface.internal.databinding.provisional.observable.IObservable;
16
import org.eclipse.jface.internal.databinding.provisional.observable.value.AbstractObservableValue;
17
import org.eclipse.jface.viewers.CellEditor;
18
import org.eclipse.jface.viewers.ICellEditorListener;
19
20
/**
21
 * {@link IObservable} implementation for a <code>CellEditor</code> that has
22
 * no control and its value is of type boolean.
23
 * 
24
 * @since 3.2
25
 */
26
public class BooleanCellEditorObservableValue extends AbstractObservableValue {
27
	private final CellEditor editor;
28
29
	private CellEditorListener listener;
30
31
	/**
32
	 * Constructs a new instance.
33
	 * 
34
	 * @param cellEditor
35
	 */
36
	public BooleanCellEditorObservableValue(final CellEditor cellEditor) {
37
		if (cellEditor == null) {
38
			throw new IllegalArgumentException(
39
					"Parameter " + cellEditor + " was null."); //$NON-NLS-1$ //$NON-NLS-2$
40
		}
41
42
		this.editor = cellEditor;
43
44
		listener = new CellEditorListener(this);
45
		editor.addListener(listener);
46
	}
47
48
	public void dispose() {
49
		super.dispose();
50
51
		if (listener != null) {
52
			editor.removeListener(listener);
53
			listener = null;
54
		}
55
	}
56
57
	/**
58
	 * @see org.eclipse.jface.internal.databinding.provisional.observable.value.AbstractObservableValue#doGetValue()
59
	 */
60
	protected Object doGetValue() {
61
		return editor.getValue();
62
	}
63
64
	/**
65
	 * @see org.eclipse.jface.internal.databinding.provisional.observable.value.IObservableValue#getValueType()
66
	 */
67
	public Object getValueType() {
68
		return Boolean.class;
69
	}
70
71
	/**
72
	 * @see org.eclipse.jface.internal.databinding.provisional.observable.value.AbstractObservableValue#setValue(java.lang.Object)
73
	 */
74
	public void setValue(Object value) {
75
		Boolean oldValue = (Boolean) editor.getValue();
76
		Boolean newValue = (value == null) ? Boolean.FALSE : (Boolean) value;
77
		
78
		if (!newValue.equals(oldValue)) {
79
			editor.setValue(newValue); // does not fire an event
80
			fireValueChange(Diffs.createValueDiff(oldValue, newValue));
81
		}
82
	}
83
84
	private static class CellEditorListener implements ICellEditorListener {
85
		private final BooleanCellEditorObservableValue observable;
86
87
		private CellEditorListener(BooleanCellEditorObservableValue observable) {
88
			this.observable = observable;
89
		}
90
91
		public void applyEditorValue() {
92
			/*
93
			 * When applyEditorValue() is invoked the value has changed. Because
94
			 * of the nature of a boolean we know the old is the opposite of the
95
			 * current value.
96
			 */
97
			boolean value = ((Boolean) observable.editor.getValue())
98
					.booleanValue();
99
100
			observable.fireValueChange(Diffs.createValueDiff(Boolean
101
					.valueOf(!value), Boolean.valueOf(value)));
102
		}
103
104
		public void cancelEditor() {
105
			// not needed
106
		}
107
108
		public void editorValueChanged(boolean oldValidState,
109
				boolean newValidState) {
110
			// not needed
111
		}
112
	}
113
}

Return to bug 144260